improved max connections code. Now use fcntl instead of flock.
[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           rprintf(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     rprintf(FERROR,"pipe: %s\n",strerror(errno));
125     exit_cleanup(1);
126   }
127
128
129   pid = do_fork();
130   if (pid < 0) {
131     rprintf(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         rprintf(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       rprintf(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     rprintf(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                 rprintf(FERROR,"pipe: %s\n",strerror(errno));
175                 exit_cleanup(1);
176         }
177
178
179         pid = do_fork();
180         if (pid < 0) {
181                 rprintf(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                         rprintf(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(STDIN_FILENO, STDOUT_FILENO, argc, argv);
202         }
203
204         if (close(from_child_pipe[1]) < 0 ||
205             close(to_child_pipe[0]) < 0) {
206                 rprintf(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   rprintf(FERROR,"ERROR: out of memory in %s\n",str);
221   exit_cleanup(1);
222 }
223
224 void overflow(char *str)
225 {
226   rprintf(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                 rprintf(FERROR,"open %s: %s\n",
374                         source,strerror(errno));
375                 return -1;
376         }
377
378         if (do_unlink(dest) && errno != ENOENT) {
379                 rprintf(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                 rprintf(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                         rprintf(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                 rprintf(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 }
448
449 /* like strncpy but does not 0 fill the buffer and always null 
450    terminates (thus it can use maxlen+1 space in d) */
451 void strlcpy(char *d, char *s, int maxlen)
452 {
453         int len = strlen(s);
454         if (len > maxlen) len = maxlen;
455         memcpy(d, s, len);
456         d[len] = 0;
457 }
458
459 /* turn a user name into a uid */
460 int name_to_uid(char *name, uid_t *uid)
461 {
462         struct passwd *pass;
463         if (!name || !*name) return 0;
464         pass = getpwnam(name);
465         if (pass) {
466                 *uid = pass->pw_uid;
467                 return 1;
468         }
469         return 0;
470 }
471
472 /* turn a group name into a gid */
473 int name_to_gid(char *name, gid_t *gid)
474 {
475         struct group *grp;
476         if (!name || !*name) return 0;
477         grp = getgrnam(name);
478         if (grp) {
479                 *gid = grp->gr_gid;
480                 return 1;
481         }
482         return 0;
483 }
484
485
486 /****************************************************************************
487 check if a process exists. 
488 ****************************************************************************/
489 int process_exists(int pid)
490 {
491         return(kill(pid,0) == 0 || errno != ESRCH);
492 }
493
494 /* lock a byte range in a open file */
495 int lock_range(int fd, int offset, int len)
496 {
497         struct flock lock;
498
499         lock.l_type = F_WRLCK;
500         lock.l_whence = SEEK_SET;
501         lock.l_start = offset;
502         lock.l_len = len;
503         lock.l_pid = 0;
504         
505         return fcntl(fd,F_SETLK,&lock) == 0;
506 }