some code cleanup in preparation for a cleaner client/server split
[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
35 struct map_struct *map_file(int fd,OFF_T len)
36 {
37   struct map_struct *ret;
38   ret = (struct map_struct *)malloc(sizeof(*ret));
39   if (!ret) out_of_memory("map_file");
40
41   ret->map = NULL;
42   ret->fd = fd;
43   ret->size = len;
44   ret->p = NULL;
45   ret->p_size = 0;
46   ret->p_offset = 0;
47   ret->p_len = 0;
48
49 #ifdef HAVE_MMAP
50   if (len < MAX_MAP_SIZE) {
51           ret->map = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
52           if (ret->map == (char *)-1) {
53                   ret->map = NULL;
54           }
55   }
56 #endif
57   return ret;
58 }
59
60
61 char *map_ptr(struct map_struct *map,OFF_T offset,int len)
62 {
63   int nread = -2;
64
65   if (map->map)
66     return map->map+offset;
67
68   if (len == 0) 
69     return NULL;
70
71   if (len > (map->size-offset))
72       len = map->size-offset;
73
74   if (offset >= map->p_offset && 
75       offset+len <= map->p_offset+map->p_len) {
76     return (map->p + (offset - map->p_offset));
77   }
78
79   len = MAX(len,CHUNK_SIZE);
80   if (len > (map->size-offset))
81       len = map->size-offset;
82
83   if (len > map->p_size) {
84     if (map->p) free(map->p);
85     map->p = (char *)malloc(len);
86     if (!map->p) out_of_memory("map_ptr");
87     map->p_size = len;
88   }
89
90   if (do_lseek(map->fd,offset,SEEK_SET) != offset ||
91       (nread=read(map->fd,map->p,len)) != len) {
92           fprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
93                   (int)offset, len, nread, errno);
94           exit_cleanup(1);
95   }
96
97   map->p_offset = offset;
98   map->p_len = len;
99
100   return map->p; 
101 }
102
103
104 void unmap_file(struct map_struct *map)
105 {
106 #ifdef HAVE_MMAP
107   if (map->map)
108     munmap(map->map,map->size);
109 #endif
110   if (map->p) free(map->p);
111   free(map);
112 }
113
114
115 /* this is taken from CVS */
116 int piped_child(char **command,int *f_in,int *f_out)
117 {
118   int pid;
119   int to_child_pipe[2];
120   int from_child_pipe[2];
121
122   if (pipe(to_child_pipe) < 0 ||
123       pipe(from_child_pipe) < 0) {
124     fprintf(FERROR,"pipe: %s\n",strerror(errno));
125     exit_cleanup(1);
126   }
127
128
129   pid = do_fork();
130   if (pid < 0) {
131     fprintf(FERROR,"fork: %s\n",strerror(errno));
132     exit_cleanup(1);
133   }
134
135   if (pid == 0)
136     {
137       extern int orig_umask;
138       if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
139           close(to_child_pipe[1]) < 0 ||
140           close(from_child_pipe[0]) < 0 ||
141           dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
142         fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
143         exit_cleanup(1);
144       }
145       if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
146       if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
147       umask(orig_umask);
148       execvp(command[0], command);
149       fprintf(FERROR,"Failed to exec %s : %s\n",
150               command[0],strerror(errno));
151       exit_cleanup(1);
152     }
153
154   if (close(from_child_pipe[1]) < 0 ||
155       close(to_child_pipe[0]) < 0) {
156     fprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
157     exit_cleanup(1);
158   }
159
160   *f_in = from_child_pipe[0];
161   *f_out = to_child_pipe[1];
162   
163   return pid;
164 }
165
166 int local_child(int argc, char **argv,int *f_in,int *f_out)
167 {
168         int pid;
169         int to_child_pipe[2];
170         int from_child_pipe[2];
171
172         if (pipe(to_child_pipe) < 0 ||
173             pipe(from_child_pipe) < 0) {
174                 fprintf(FERROR,"pipe: %s\n",strerror(errno));
175                 exit_cleanup(1);
176         }
177
178
179         pid = do_fork();
180         if (pid < 0) {
181                 fprintf(FERROR,"fork: %s\n",strerror(errno));
182                 exit_cleanup(1);
183         }
184
185         if (pid == 0) {
186                 extern int am_sender;
187                 extern int am_server;
188
189                 am_sender = !am_sender;
190                 am_server = 1;          
191
192                 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
193                     close(to_child_pipe[1]) < 0 ||
194                     close(from_child_pipe[0]) < 0 ||
195                     dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
196                         fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
197                         exit_cleanup(1);
198                 }
199                 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
200                 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
201                 start_server(argc, argv);
202         }
203
204         if (close(from_child_pipe[1]) < 0 ||
205             close(to_child_pipe[0]) < 0) {
206                 fprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
207                 exit_cleanup(1);
208         }
209
210         *f_in = from_child_pipe[0];
211         *f_out = to_child_pipe[1];
212   
213         return pid;
214 }
215
216
217
218 void out_of_memory(char *str)
219 {
220   fprintf(FERROR,"ERROR: out of memory in %s\n",str);
221   exit_cleanup(1);
222 }
223
224 void overflow(char *str)
225 {
226   fprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
227   exit_cleanup(1);
228 }
229
230
231
232 int set_modtime(char *fname,time_t modtime)
233 {
234         extern int dry_run;
235         if (dry_run) return 0;
236         {
237 #ifdef HAVE_UTIMBUF
238                 struct utimbuf tbuf;  
239                 tbuf.actime = time(NULL);
240                 tbuf.modtime = modtime;
241                 return utime(fname,&tbuf);
242 #elif defined(HAVE_UTIME)
243                 time_t t[2];
244                 t[0] = time(NULL);
245                 t[1] = modtime;
246                 return utime(fname,t);
247 #else
248                 struct timeval t[2];
249                 t[0].tv_sec = time(NULL);
250                 t[0].tv_usec = 0;
251                 t[1].tv_sec = modtime;
252                 t[1].tv_usec = 0;
253                 return utimes(fname,t);
254 #endif
255         }
256 }
257
258
259
260 /****************************************************************************
261 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
262 else
263 if SYSV use O_NDELAY
264 if BSD use FNDELAY
265 ****************************************************************************/
266 int set_blocking(int fd, int set)
267 {
268   int val;
269 #ifdef O_NONBLOCK
270 #define FLAG_TO_SET O_NONBLOCK
271 #else
272 #ifdef SYSV
273 #define FLAG_TO_SET O_NDELAY
274 #else /* BSD */
275 #define FLAG_TO_SET FNDELAY
276 #endif
277 #endif
278
279   if((val = fcntl(fd, F_GETFL, 0)) == -1)
280         return -1;
281   if(set) /* Turn blocking on - ie. clear nonblock flag */
282         val &= ~FLAG_TO_SET;
283   else
284     val |= FLAG_TO_SET;
285   return fcntl( fd, F_SETFL, val);
286 #undef FLAG_TO_SET
287 }
288
289 /****************************************************************************
290 create any necessary directories in fname. Unfortunately we don't know
291 what perms to give the directory when this is called so we need to rely
292 on the umask
293 ****************************************************************************/
294 int create_directory_path(char *fname)
295 {
296         extern int orig_umask;
297         char *p;
298
299         while (*fname == '/') fname++;
300         while (strncmp(fname,"./",2)==0) fname += 2;
301
302         p = fname;
303         while ((p=strchr(p,'/'))) {
304                 *p = 0;
305                 do_mkdir(fname,0777 & ~orig_umask); 
306                 *p = '/';
307                 p++;
308         }
309         return 0;
310 }
311
312
313 /* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
314    Return LEN upon success, write's (negative) error code otherwise.  
315
316    derived from GNU C's cccp.c.
317 */
318 int full_write(int desc, char *ptr, int len)
319 {
320         int total_written;
321         
322         total_written = 0;
323         while (len > 0) {
324                 int written = write (desc, ptr, len);
325                 if (written < 0)  {
326 #ifdef EINTR
327                         if (errno == EINTR)
328                                 continue;
329 #endif
330                         return written;
331                 }
332                 total_written += written;
333                 ptr += written;
334                 len -= written;
335         }
336         return total_written;
337 }
338
339 /* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
340    Return the actual number of bytes read, zero for EOF, or negative
341    for an error.  
342
343    derived from GNU C's cccp.c. */
344 int safe_read(int desc, char *ptr, int len)
345 {
346         int n_chars;
347  
348         if (len <= 0)
349                 return len;
350  
351 #ifdef EINTR
352         do {
353                 n_chars = read(desc, ptr, len);
354         } while (n_chars < 0 && errno == EINTR);
355 #else
356         n_chars = read(desc, ptr, len);
357 #endif
358  
359         return n_chars;
360 }
361
362
363 /* copy a file - this is used in conjunction with the --temp-dir option */
364 int copy_file(char *source, char *dest, mode_t mode)
365 {
366         int ifd;
367         int ofd;
368         char buf[1024 * 8];
369         int len;   /* Number of bytes read into `buf'. */
370
371         ifd = open(source, O_RDONLY);
372         if (ifd == -1) {
373                 fprintf(FERROR,"open %s: %s\n",
374                         source,strerror(errno));
375                 return -1;
376         }
377
378         if (do_unlink(dest) && errno != ENOENT) {
379                 fprintf(FERROR,"unlink %s: %s\n",
380                         dest,strerror(errno));
381                 return -1;
382         }
383
384         ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
385         if (ofd < 0) {
386                 fprintf(FERROR,"open %s: %s\n",
387                         dest,strerror(errno));
388                 close(ifd);
389                 return -1;
390         }
391
392         while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
393                 if (full_write(ofd, buf, len) < 0) {
394                         fprintf(FERROR,"write %s: %s\n",
395                                 dest,strerror(errno));
396                         close(ifd);
397                         close(ofd);
398                         return -1;
399                 }
400         }
401
402         close(ifd);
403         close(ofd);
404
405         if (len < 0) {
406                 fprintf(FERROR,"read %s: %s\n",
407                         source,strerror(errno));
408                 return -1;
409         }
410
411         return 0;
412 }
413
414 /* sleep for a while via select */
415 void u_sleep(int usec)
416 {
417         struct timeval tv;
418
419         tv.tv_sec = 0;
420         tv.tv_usec = usec;
421         select(0, NULL, NULL, NULL, &tv);
422 }
423
424
425 static pid_t all_pids[10];
426 static int num_pids;
427
428 /* fork and record the pid of the child */
429 pid_t do_fork(void)
430 {
431         pid_t newpid = fork();
432         
433         if (newpid) {
434                 all_pids[num_pids++] = newpid;
435         }
436         return newpid;
437 }
438
439 /* kill all children */
440 void kill_all(int sig)
441 {
442         int i;
443         for (i=0;i<num_pids;i++) {
444                 if (all_pids[i] != getpid())
445                         kill(all_pids[i], sig);
446         }
447 }