preparing for release of 2.0.9
[rsync/rsync.git] / util.c
CommitLineData
c627d613
AT
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
720b47f2 27int num_waiting(int fd)
94481d91
AT
28{
29 int len=0;
94481d91 30 ioctl(fd,FIONREAD,&len);
94481d91
AT
31 return(len);
32}
33
d9bea2dd 34
bcacc18b 35struct map_struct *map_file(int fd,OFF_T len)
c627d613 36{
c6e7fcb4
AT
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
d9bea2dd 49#ifdef HAVE_MMAP
94c9ef1f
AT
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 }
d9bea2dd 56#endif
c627d613
AT
57 return ret;
58}
59
0b910560 60
bcacc18b 61char *map_ptr(struct map_struct *map,OFF_T offset,int len)
d9bea2dd 62{
3e607d23
AT
63 int nread;
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 map->p_offset = offset;
91 map->p_len = len;
92
93 if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
94 rprintf(FERROR,"lseek failed in map_ptr\n");
95 exit_cleanup(1);
96 }
97
98 if ((nread=read(map->fd,map->p,len)) != len) {
99 if (nread < 0) nread = 0;
100 /* the best we can do is zero the buffer - the file
101 has changed mid transfer! */
102 memset(map->p+nread, 0, len - nread);
103 }
104
105 return map->p;
d9bea2dd
AT
106}
107
108
c6e7fcb4 109void unmap_file(struct map_struct *map)
c627d613 110{
7bec6a5c 111#ifdef HAVE_MMAP
c6e7fcb4
AT
112 if (map->map)
113 munmap(map->map,map->size);
7bec6a5c 114#endif
c6e7fcb4
AT
115 if (map->p) free(map->p);
116 free(map);
c627d613
AT
117}
118
119
c627d613
AT
120/* this is taken from CVS */
121int piped_child(char **command,int *f_in,int *f_out)
122{
123 int pid;
124 int to_child_pipe[2];
125 int from_child_pipe[2];
126
127 if (pipe(to_child_pipe) < 0 ||
128 pipe(from_child_pipe) < 0) {
9486289c 129 rprintf(FERROR,"pipe: %s\n",strerror(errno));
34ccb63e 130 exit_cleanup(1);
c627d613
AT
131 }
132
133
3ba62a83 134 pid = do_fork();
c627d613 135 if (pid < 0) {
9486289c 136 rprintf(FERROR,"fork: %s\n",strerror(errno));
34ccb63e 137 exit_cleanup(1);
c627d613
AT
138 }
139
140 if (pid == 0)
141 {
6574b4f7 142 extern int orig_umask;
c627d613
AT
143 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
144 close(to_child_pipe[1]) < 0 ||
145 close(from_child_pipe[0]) < 0 ||
146 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
9486289c 147 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
34ccb63e 148 exit_cleanup(1);
c627d613 149 }
773f2bd4
AT
150 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
151 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
6574b4f7 152 umask(orig_umask);
c627d613 153 execvp(command[0], command);
9486289c 154 rprintf(FERROR,"Failed to exec %s : %s\n",
c627d613 155 command[0],strerror(errno));
34ccb63e 156 exit_cleanup(1);
c627d613
AT
157 }
158
159 if (close(from_child_pipe[1]) < 0 ||
160 close(to_child_pipe[0]) < 0) {
9486289c 161 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
34ccb63e 162 exit_cleanup(1);
c627d613
AT
163 }
164
165 *f_in = from_child_pipe[0];
166 *f_out = to_child_pipe[1];
167
168 return pid;
169}
170
366345fe
AT
171int local_child(int argc, char **argv,int *f_in,int *f_out)
172{
173 int pid;
174 int to_child_pipe[2];
175 int from_child_pipe[2];
176
177 if (pipe(to_child_pipe) < 0 ||
178 pipe(from_child_pipe) < 0) {
9486289c 179 rprintf(FERROR,"pipe: %s\n",strerror(errno));
366345fe
AT
180 exit_cleanup(1);
181 }
182
183
184 pid = do_fork();
185 if (pid < 0) {
9486289c 186 rprintf(FERROR,"fork: %s\n",strerror(errno));
366345fe
AT
187 exit_cleanup(1);
188 }
189
190 if (pid == 0) {
191 extern int am_sender;
192 extern int am_server;
193
194 am_sender = !am_sender;
195 am_server = 1;
196
197 if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
198 close(to_child_pipe[1]) < 0 ||
199 close(from_child_pipe[0]) < 0 ||
200 dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
9486289c 201 rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
366345fe
AT
202 exit_cleanup(1);
203 }
204 if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
205 if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
9486289c 206 start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
366345fe
AT
207 }
208
209 if (close(from_child_pipe[1]) < 0 ||
210 close(to_child_pipe[0]) < 0) {
9486289c 211 rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
366345fe
AT
212 exit_cleanup(1);
213 }
214
215 *f_in = from_child_pipe[0];
216 *f_out = to_child_pipe[1];
217
218 return pid;
219}
220
221
c627d613
AT
222
223void out_of_memory(char *str)
224{
9486289c 225 rprintf(FERROR,"ERROR: out of memory in %s\n",str);
575f2fca
AT
226 exit_cleanup(1);
227}
228
229void overflow(char *str)
230{
9486289c 231 rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
34ccb63e 232 exit_cleanup(1);
c627d613
AT
233}
234
235
c627d613
AT
236
237int set_modtime(char *fname,time_t modtime)
238{
31e12522
AT
239 extern int dry_run;
240 if (dry_run) return 0;
241 {
1e9f155a 242#ifdef HAVE_UTIMBUF
31e12522
AT
243 struct utimbuf tbuf;
244 tbuf.actime = time(NULL);
245 tbuf.modtime = modtime;
246 return utime(fname,&tbuf);
c627d613 247#elif defined(HAVE_UTIME)
31e12522
AT
248 time_t t[2];
249 t[0] = time(NULL);
250 t[1] = modtime;
251 return utime(fname,t);
c627d613 252#else
31e12522
AT
253 struct timeval t[2];
254 t[0].tv_sec = time(NULL);
255 t[0].tv_usec = 0;
256 t[1].tv_sec = modtime;
257 t[1].tv_usec = 0;
258 return utimes(fname,t);
c627d613 259#endif
31e12522 260 }
c627d613 261}
94481d91 262
720b47f2
AT
263
264
265/****************************************************************************
266Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
267else
268if SYSV use O_NDELAY
269if BSD use FNDELAY
270****************************************************************************/
271int set_blocking(int fd, int set)
272{
273 int val;
274#ifdef O_NONBLOCK
275#define FLAG_TO_SET O_NONBLOCK
276#else
277#ifdef SYSV
278#define FLAG_TO_SET O_NDELAY
279#else /* BSD */
280#define FLAG_TO_SET FNDELAY
281#endif
282#endif
283
284 if((val = fcntl(fd, F_GETFL, 0)) == -1)
285 return -1;
286 if(set) /* Turn blocking on - ie. clear nonblock flag */
287 val &= ~FLAG_TO_SET;
288 else
289 val |= FLAG_TO_SET;
290 return fcntl( fd, F_SETFL, val);
291#undef FLAG_TO_SET
292}
6574b4f7
AT
293
294/****************************************************************************
295create any necessary directories in fname. Unfortunately we don't know
296what perms to give the directory when this is called so we need to rely
297on the umask
298****************************************************************************/
299int create_directory_path(char *fname)
300{
301 extern int orig_umask;
302 char *p;
303
304 while (*fname == '/') fname++;
305 while (strncmp(fname,"./",2)==0) fname += 2;
306
307 p = fname;
308 while ((p=strchr(p,'/'))) {
309 *p = 0;
1b2d733a 310 do_mkdir(fname,0777 & ~orig_umask);
6574b4f7
AT
311 *p = '/';
312 p++;
313 }
314 return 0;
315}
950ab32d
AT
316
317
318/* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted.
319 Return LEN upon success, write's (negative) error code otherwise.
320
321 derived from GNU C's cccp.c.
322*/
323int full_write(int desc, char *ptr, int len)
324{
325 int total_written;
326
327 total_written = 0;
328 while (len > 0) {
329 int written = write (desc, ptr, len);
330 if (written < 0) {
331#ifdef EINTR
332 if (errno == EINTR)
333 continue;
334#endif
335 return written;
336 }
337 total_written += written;
338 ptr += written;
339 len -= written;
340 }
341 return total_written;
342}
343
344/* Read LEN bytes at PTR from descriptor DESC, retrying if interrupted.
345 Return the actual number of bytes read, zero for EOF, or negative
346 for an error.
347
348 derived from GNU C's cccp.c. */
349int safe_read(int desc, char *ptr, int len)
350{
351 int n_chars;
352
353 if (len <= 0)
354 return len;
355
356#ifdef EINTR
357 do {
358 n_chars = read(desc, ptr, len);
359 } while (n_chars < 0 && errno == EINTR);
360#else
361 n_chars = read(desc, ptr, len);
362#endif
363
364 return n_chars;
365}
366
367
368/* copy a file - this is used in conjunction with the --temp-dir option */
369int copy_file(char *source, char *dest, mode_t mode)
370{
371 int ifd;
372 int ofd;
373 char buf[1024 * 8];
374 int len; /* Number of bytes read into `buf'. */
375
376 ifd = open(source, O_RDONLY);
377 if (ifd == -1) {
9486289c 378 rprintf(FERROR,"open %s: %s\n",
950ab32d
AT
379 source,strerror(errno));
380 return -1;
381 }
382
31e12522 383 if (do_unlink(dest) && errno != ENOENT) {
9486289c 384 rprintf(FERROR,"unlink %s: %s\n",
950ab32d
AT
385 dest,strerror(errno));
386 return -1;
387 }
388
31e12522 389 ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
950ab32d 390 if (ofd < 0) {
9486289c 391 rprintf(FERROR,"open %s: %s\n",
950ab32d
AT
392 dest,strerror(errno));
393 close(ifd);
394 return -1;
395 }
396
397 while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
398 if (full_write(ofd, buf, len) < 0) {
9486289c 399 rprintf(FERROR,"write %s: %s\n",
950ab32d
AT
400 dest,strerror(errno));
401 close(ifd);
402 close(ofd);
403 return -1;
404 }
405 }
406
407 close(ifd);
408 close(ofd);
409
410 if (len < 0) {
9486289c 411 rprintf(FERROR,"read %s: %s\n",
950ab32d
AT
412 source,strerror(errno));
413 return -1;
414 }
415
416 return 0;
417}
feaa89c4
AT
418
419/* sleep for a while via select */
420void u_sleep(int usec)
421{
422 struct timeval tv;
423
424 tv.tv_sec = 0;
425 tv.tv_usec = usec;
426 select(0, NULL, NULL, NULL, &tv);
427}
3ba62a83
AT
428
429
430static pid_t all_pids[10];
431static int num_pids;
432
433/* fork and record the pid of the child */
434pid_t do_fork(void)
435{
436 pid_t newpid = fork();
437
438 if (newpid) {
439 all_pids[num_pids++] = newpid;
440 }
441 return newpid;
442}
443
444/* kill all children */
445void kill_all(int sig)
446{
447 int i;
448 for (i=0;i<num_pids;i++) {
449 if (all_pids[i] != getpid())
450 kill(all_pids[i], sig);
451 }
452}
9486289c 453
7a6421fa
AT
454/* like strncpy but does not 0 fill the buffer and always null
455 terminates (thus it can use maxlen+1 space in d) */
456void strlcpy(char *d, char *s, int maxlen)
457{
458 int len = strlen(s);
459 if (len > maxlen) len = maxlen;
460 memcpy(d, s, len);
461 d[len] = 0;
462}
8ef4ffd6 463
e42c9458
AT
464/* like strncat but does not 0 fill the buffer and always null
465 terminates (thus it can use maxlen+1 space in d) */
466void strlcat(char *d, char *s, int maxlen)
467{
468 int len1 = strlen(d);
469 int len2 = strlen(s);
470 if (len1+len2 > maxlen) {
471 len2 = maxlen-len1;
472 }
473 if (len2 > 0) {
474 memcpy(d+len1, s, len2);
475 d[len1+len2] = 0;
476 }
477}
478
8ef4ffd6
AT
479/* turn a user name into a uid */
480int name_to_uid(char *name, uid_t *uid)
481{
482 struct passwd *pass;
483 if (!name || !*name) return 0;
484 pass = getpwnam(name);
485 if (pass) {
486 *uid = pass->pw_uid;
487 return 1;
488 }
489 return 0;
490}
491
492/* turn a group name into a gid */
493int name_to_gid(char *name, gid_t *gid)
494{
495 struct group *grp;
496 if (!name || !*name) return 0;
497 grp = getgrnam(name);
498 if (grp) {
499 *gid = grp->gr_gid;
500 return 1;
501 }
502 return 0;
503}
504
ff8b29b8 505
0c515f17
AT
506/****************************************************************************
507check if a process exists.
508****************************************************************************/
509int process_exists(int pid)
510{
511 return(kill(pid,0) == 0 || errno != ESRCH);
512}
513
31593dd6
AT
514/* lock a byte range in a open file */
515int lock_range(int fd, int offset, int len)
0c515f17 516{
31593dd6 517 struct flock lock;
0c515f17 518
31593dd6
AT
519 lock.l_type = F_WRLCK;
520 lock.l_whence = SEEK_SET;
521 lock.l_start = offset;
522 lock.l_len = len;
523 lock.l_pid = 0;
524
525 return fcntl(fd,F_SETLK,&lock) == 0;
0c515f17 526}
874895d5
AT
527
528
087bf010 529static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
874895d5
AT
530{
531#ifndef HAVE_GLOB
e42c9458 532 if (!*s) s = ".";
087bf010 533 argv[*argc] = strdup(s);
874895d5
AT
534 (*argc)++;
535 return;
536#else
537 glob_t globbuf;
538 int i;
539
e42c9458
AT
540 if (!*s) s = ".";
541
087bf010
AT
542 argv[*argc] = strdup(s);
543
874895d5
AT
544 memset(&globbuf, 0, sizeof(globbuf));
545 glob(argv[*argc], 0, NULL, &globbuf);
546 if (globbuf.gl_pathc == 0) {
547 (*argc)++;
548 globfree(&globbuf);
549 return;
550 }
551 for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
552 if (i == 0) free(argv[*argc]);
553 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
554 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
555 }
556 globfree(&globbuf);
557 (*argc) += i;
558#endif
559}
5a96ee05 560
087bf010
AT
561void glob_expand(char *base, char **argv, int *argc, int maxargs)
562{
563 char *s = argv[*argc];
564 char *p, *q;
565
566 if (!s || !*s) return;
567
e42c9458
AT
568 if (strncmp(s, base, strlen(base)) == 0) {
569 s += strlen(base);
570 }
571
087bf010
AT
572 s = strdup(s);
573 if (!s) out_of_memory("glob_expand");
574
575 q = s;
576 while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
577 if (p != q && *(p-1) == ' ' && p[strlen(base)] == '/') {
578 /* split it at this point */
579 *(p-1) = 0;
580 glob_expand_one(q, argv, argc, maxargs);
e42c9458 581 q = p+strlen(base)+1;
087bf010
AT
582 } else {
583 q++;
584 }
585 }
586
587 if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
588
589 free(s);
590}
5a96ee05
AT
591
592/*******************************************************************
593 convert a string to lower case
594********************************************************************/
595void strlower(char *s)
596{
597 while (*s) {
598 if (isupper(*s)) *s = tolower(*s);
599 s++;
600 }
601}
e42c9458
AT
602
603/* this is like vsnprintf but the 'n' limit does not include
604 the terminating null. So if you have a 1024 byte buffer then
605 pass 1023 for n */
606int vslprintf(char *str, int n, const char *format, va_list ap)
607{
608#ifdef HAVE_VSNPRINTF
609 int ret = vsnprintf(str, n, format, ap);
610 if (ret > n || ret < 0) {
611 str[n] = 0;
612 return -1;
613 }
614 str[ret] = 0;
615 return ret;
616#else
617 static char *buf;
618 static int len=MAXPATHLEN*8;
619 int ret;
620
621 /* this code is NOT a proper vsnprintf() implementation. It
622 relies on the fact that all calls to slprintf() in rsync
623 pass strings which have already been checked to be less
624 than MAXPATHLEN in length and never more than 2 strings are
625 concatenated. This means the above buffer is absolutely
626 ample and can never be overflowed.
627
628 In the future we would like to replace this with a proper
629 vsnprintf() implementation but right now we need a solution
630 that is secure and portable. This is it. */
631
632 if (!buf) {
633 buf = malloc(len);
634 if (!buf) {
635 /* can't call debug or we would recurse */
8d9dc9f9 636 exit_cleanup(1);
e42c9458
AT
637 }
638 }
639
f72399f8
AT
640 vsprintf(buf, format, ap);
641 ret = strlen(buf);
642 if (ret > n) {
643 /* yikes! */
8d9dc9f9 644 exit_cleanup(1);
e42c9458 645 }
f72399f8 646 buf[ret] = 0;
e42c9458 647
f72399f8 648 memcpy(str, buf, ret+1);
e42c9458
AT
649
650 return ret;
651#endif
652}
653
654
655/* like snprintf but always null terminates */
656int slprintf(char *str, int n, char *format, ...)
657{
658 va_list ap;
659 int ret;
660
661 va_start(ap, format);
662 ret = vslprintf(str,n,format,ap);
663 va_end(ap);
664 return ret;
665}
8d9dc9f9 666