standard input on server may be nonblocking
[rsync/rsync.git] / util.c
1 /* 
2    Copyright (C) Andrew Tridgell 1996
3    Copyright (C) Paul Mackerras 1996
4    
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 /*
21   Utilities used in rsync 
22
23   tridge, June 1996
24   */
25 #include "rsync.h"
26
27 int num_waiting(int fd)
28 {
29   int len=0;
30   ioctl(fd,FIONREAD,&len);
31   return(len);
32 }
33
34 static int map_fd = -1;
35 static off_t map_size = 0;
36 static char *p = NULL;
37 static int p_size = 0;
38 static int p_offset = 0;
39 static int p_len = 0;
40
41
42 char *map_file(int fd,off_t len)
43 {
44   char *ret = NULL;
45 #ifdef HAVE_MMAP
46   if (len < MAX_MAP_SIZE)
47     ret = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
48 #endif
49   map_fd = fd;
50   map_size = len; 
51   return ret;
52 }
53
54 char *map_ptr(char *buf,off_t offset,int len)
55 {
56   if (buf)
57     return buf+offset;
58
59   if (len == 0) 
60     return NULL;
61
62   len = MIN(len,map_size-offset);
63
64   if (offset >= p_offset && 
65       offset+len <= p_offset+p_len) {
66     return (p + (offset - p_offset));
67   }
68
69   len = MAX(len,WRITE_BLOCK_SIZE);
70   len = MIN(len,map_size - offset);  
71
72   if (len > p_size) {
73     if (p) free(p);
74     p = (char *)malloc(len);
75     if (!p) out_of_memory("map_ptr");
76     p_size = len;
77   }
78
79   if (lseek(map_fd,offset,SEEK_SET) != offset ||
80       read(map_fd,p,len) != len) {
81     fprintf(stderr,"EOF in map_ptr!\n");
82     exit(1);
83   }
84
85   p_offset = offset;
86   p_len = len;
87
88   return p; 
89 }
90
91
92 void unmap_file(char *buf,off_t len)
93 {
94   if (len > 0 && buf)
95     munmap(buf,len);
96   map_fd = -1;
97   map_size = 0;
98   p_len = 0;
99 }
100
101
102 /* this is taken from CVS */
103 int piped_child(char **command,int *f_in,int *f_out)
104 {
105   int pid;
106   int to_child_pipe[2];
107   int from_child_pipe[2];
108
109   if (pipe(to_child_pipe) < 0 ||
110       pipe(from_child_pipe) < 0) {
111     fprintf(stderr,"pipe: %s\n",strerror(errno));
112     exit(1);
113   }
114
115
116   pid = fork();
117   if (pid < 0) {
118     fprintf(stderr,"fork: %s\n",strerror(errno));
119     exit(1);
120   }
121
122   if (pid == 0)
123     {
124       if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
125           close(to_child_pipe[1]) < 0 ||
126           close(from_child_pipe[0]) < 0 ||
127           dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
128         fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno));
129         exit(1);
130       }
131       execvp(command[0], command);
132       fprintf(stderr,"Failed to exec %s : %s\n",
133               command[0],strerror(errno));
134       exit(1);
135     }
136
137   if (close(from_child_pipe[1]) < 0 ||
138       close(to_child_pipe[0]) < 0) {
139     fprintf(stderr,"Failed to close : %s\n",strerror(errno));   
140     exit(1);
141   }
142
143   *f_in = from_child_pipe[0];
144   *f_out = to_child_pipe[1];
145   
146   return pid;
147 }
148
149
150 void out_of_memory(char *str)
151 {
152   fprintf(stderr,"out of memory in %s\n",str);
153   exit(1);
154 }
155
156
157 #ifndef HAVE_STRDUP
158  char *strdup(char *s)
159 {
160   int l = strlen(s) + 1;
161   char *ret = (char *)malloc(l);
162   if (ret)
163     strcpy(ret,s);
164   return ret;
165 }
166 #endif
167
168
169 int set_modtime(char *fname,time_t modtime)
170 {
171 #ifdef HAVE_UTIME_H
172   struct utimbuf tbuf;  
173   tbuf.actime = time(NULL);
174   tbuf.modtime = modtime;
175   return utime(fname,&tbuf);
176 #elif defined(HAVE_UTIME)
177   time_t t[2];
178   t[0] = time(NULL);
179   t[1] = modtime;
180   return utime(fname,t);
181 #else
182   struct timeval t[2];
183   t[0].tv_sec = time(NULL);
184   t[0].tv_usec = 0;
185   t[1].tv_sec = modtime;
186   t[1].tv_usec = 0;
187   return utimes(fname,t);
188 #endif
189 }
190
191
192
193 /****************************************************************************
194 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
195 else
196 if SYSV use O_NDELAY
197 if BSD use FNDELAY
198 ****************************************************************************/
199 int set_blocking(int fd, int set)
200 {
201   int val;
202 #ifdef O_NONBLOCK
203 #define FLAG_TO_SET O_NONBLOCK
204 #else
205 #ifdef SYSV
206 #define FLAG_TO_SET O_NDELAY
207 #else /* BSD */
208 #define FLAG_TO_SET FNDELAY
209 #endif
210 #endif
211
212   if((val = fcntl(fd, F_GETFL, 0)) == -1)
213         return -1;
214   if(set) /* Turn blocking on - ie. clear nonblock flag */
215         val &= ~FLAG_TO_SET;
216   else
217     val |= FLAG_TO_SET;
218   return fcntl( fd, F_SETFL, val);
219 #undef FLAG_TO_SET
220 }