Changed the non-globbing version of glob_expand_one() so that it
[rsync/rsync.git] / util.c
1 /*  -*- c-file-style: "linux" -*-
2  *
3  * Copyright (C) 1996-2000 by Andrew Tridgell
4  * Copyright (C) Paul Mackerras 1996
5  * Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 /**
23  * @file
24  *
25  * Utilities used in rsync
26  **/
27
28 #include "rsync.h"
29
30 extern int verbose;
31 extern struct exclude_list_struct server_exclude_list;
32
33 int sanitize_paths = 0;
34
35
36
37 /**
38  * Set a fd into nonblocking mode
39  **/
40 void set_nonblocking(int fd)
41 {
42         int val;
43
44         if ((val = fcntl(fd, F_GETFL, 0)) == -1)
45                 return;
46         if (!(val & NONBLOCK_FLAG)) {
47                 val |= NONBLOCK_FLAG;
48                 fcntl(fd, F_SETFL, val);
49         }
50 }
51
52 /**
53  * Set a fd into blocking mode
54  **/
55 void set_blocking(int fd)
56 {
57         int val;
58
59         if ((val = fcntl(fd, F_GETFL, 0)) == -1)
60                 return;
61         if (val & NONBLOCK_FLAG) {
62                 val &= ~NONBLOCK_FLAG;
63                 fcntl(fd, F_SETFL, val);
64         }
65 }
66
67
68 /**
69  * Create a file descriptor pair - like pipe() but use socketpair if
70  * possible (because of blocking issues on pipes).
71  *
72  * Always set non-blocking.
73  */
74 int fd_pair(int fd[2])
75 {
76         int ret;
77
78 #if HAVE_SOCKETPAIR
79         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
80 #else
81         ret = pipe(fd);
82 #endif
83
84         if (ret == 0) {
85                 set_nonblocking(fd[0]);
86                 set_nonblocking(fd[1]);
87         }
88
89         return ret;
90 }
91
92
93 void print_child_argv(char **cmd)
94 {
95         rprintf(FINFO, "opening connection using ");
96         for (; *cmd; cmd++) {
97                 /* Look for characters that ought to be quoted.  This
98                 * is not a great quoting algorithm, but it's
99                 * sufficient for a log message. */
100                 if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz"
101                            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
102                            "0123456789"
103                            ",.-_=+@/") != strlen(*cmd)) {
104                         rprintf(FINFO, "\"%s\" ", *cmd);
105                 } else {
106                         rprintf(FINFO, "%s ", *cmd);
107                 }
108         }
109         rprintf(FINFO, "\n");
110 }
111
112
113 void out_of_memory(char *str)
114 {
115         rprintf(FERROR, "ERROR: out of memory in %s\n", str);
116         exit_cleanup(RERR_MALLOC);
117 }
118
119 void overflow(char *str)
120 {
121         rprintf(FERROR, "ERROR: buffer overflow in %s\n", str);
122         exit_cleanup(RERR_MALLOC);
123 }
124
125
126
127 int set_modtime(char *fname, time_t modtime)
128 {
129         extern int dry_run;
130         if (dry_run)
131                 return 0;
132
133         if (verbose > 2) {
134                 rprintf(FINFO, "set modtime of %s to (%ld) %s",
135                         fname, (long) modtime,
136                         asctime(localtime(&modtime)));
137         }
138
139         {
140 #ifdef HAVE_UTIMBUF
141                 struct utimbuf tbuf;
142                 tbuf.actime = time(NULL);
143                 tbuf.modtime = modtime;
144                 return utime(fname,&tbuf);
145 #elif defined(HAVE_UTIME)
146                 time_t t[2];
147                 t[0] = time(NULL);
148                 t[1] = modtime;
149                 return utime(fname,t);
150 #else
151                 struct timeval t[2];
152                 t[0].tv_sec = time(NULL);
153                 t[0].tv_usec = 0;
154                 t[1].tv_sec = modtime;
155                 t[1].tv_usec = 0;
156                 return utimes(fname,t);
157 #endif
158         }
159 }
160
161
162 /**
163    Create any necessary directories in fname. Unfortunately we don't know
164    what perms to give the directory when this is called so we need to rely
165    on the umask
166 **/
167 int create_directory_path(char *fname, int base_umask)
168 {
169         char *p;
170
171         while (*fname == '/')
172                 fname++;
173         while (strncmp(fname, "./", 2) == 0)
174                 fname += 2;
175
176         p = fname;
177         while ((p = strchr(p,'/')) != NULL) {
178                 *p = 0;
179                 do_mkdir(fname, 0777 & ~base_umask);
180                 *p = '/';
181                 p++;
182         }
183         return 0;
184 }
185
186
187 /**
188  * Write @p len bytes at @p ptr to descriptor @p desc, retrying if
189  * interrupted.
190  *
191  * @retval len upon success
192  *
193  * @retval <0 write's (negative) error code
194  *
195  * Derived from GNU C's cccp.c.
196  */
197 static int full_write(int desc, char *ptr, size_t len)
198 {
199         int total_written;
200
201         total_written = 0;
202         while (len > 0) {
203                 int written = write(desc, ptr, len);
204                 if (written < 0)  {
205                         if (errno == EINTR)
206                                 continue;
207                         return written;
208                 }
209                 total_written += written;
210                 ptr += written;
211                 len -= written;
212         }
213         return total_written;
214 }
215
216
217 /**
218  * Read @p len bytes at @p ptr from descriptor @p desc, retrying if
219  * interrupted.
220  *
221  * @retval >0 the actual number of bytes read
222  *
223  * @retval 0 for EOF
224  *
225  * @retval <0 for an error.
226  *
227  * Derived from GNU C's cccp.c. */
228 static int safe_read(int desc, char *ptr, size_t len)
229 {
230         int n_chars;
231
232         if (len == 0)
233                 return len;
234
235         do {
236                 n_chars = read(desc, ptr, len);
237         } while (n_chars < 0 && errno == EINTR);
238
239         return n_chars;
240 }
241
242
243 /** Copy a file.
244  *
245  * This is used in conjunction with the --temp-dir option */
246 int copy_file(char *source, char *dest, mode_t mode)
247 {
248         int ifd;
249         int ofd;
250         char buf[1024 * 8];
251         int len;   /* Number of bytes read into `buf'. */
252
253         ifd = do_open(source, O_RDONLY, 0);
254         if (ifd == -1) {
255                 rprintf(FERROR,"open %s: %s\n",
256                         full_fname(source), strerror(errno));
257                 return -1;
258         }
259
260         if (robust_unlink(dest) && errno != ENOENT) {
261                 rprintf(FERROR,"unlink %s: %s\n",
262                         full_fname(dest), strerror(errno));
263                 return -1;
264         }
265
266         ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
267         if (ofd == -1) {
268                 rprintf(FERROR,"open %s: %s\n",
269                         full_fname(dest), strerror(errno));
270                 close(ifd);
271                 return -1;
272         }
273
274         while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
275                 if (full_write(ofd, buf, len) < 0) {
276                         rprintf(FERROR,"write %s: %s\n",
277                                 full_fname(dest), strerror(errno));
278                         close(ifd);
279                         close(ofd);
280                         return -1;
281                 }
282         }
283
284         if (len < 0) {
285                 rprintf(FERROR, "read %s: %s\n",
286                         full_fname(source), strerror(errno));
287                 close(ifd);
288                 close(ofd);
289                 return -1;
290         }
291
292         if (close(ifd) < 0) {
293                 rprintf(FINFO, "close failed on %s: %s\n",
294                         full_fname(source), strerror(errno));
295         }
296
297         if (close(ofd) < 0) {
298                 rprintf(FERROR, "close failed on %s: %s\n",
299                         full_fname(dest), strerror(errno));
300                 return -1;
301         }
302
303         return 0;
304 }
305
306 /* MAX_RENAMES should be 10**MAX_RENAMES_DIGITS */
307 #define MAX_RENAMES_DIGITS 3
308 #define MAX_RENAMES 1000
309
310 /**
311  * Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so
312  * rename to <path>/.rsyncNNN instead.
313  *
314  * Note that successive rsync runs will shuffle the filenames around a
315  * bit as long as the file is still busy; this is because this function
316  * does not know if the unlink call is due to a new file coming in, or
317  * --delete trying to remove old .rsyncNNN files, hence it renames it
318  * each time.
319  **/
320 int robust_unlink(char *fname)
321 {
322 #ifndef ETXTBSY
323         return do_unlink(fname);
324 #else
325         static int counter = 1;
326         int rc, pos, start;
327         char path[MAXPATHLEN];
328
329         rc = do_unlink(fname);
330         if (rc == 0 || errno != ETXTBSY)
331                 return rc;
332
333         if ((pos = strlcpy(path, fname, MAXPATHLEN)) >= MAXPATHLEN)
334                 pos = MAXPATHLEN - 1;
335
336         while (pos > 0 && path[pos-1] != '/')
337                 pos--;
338         pos += strlcpy(path+pos, ".rsync", MAXPATHLEN-pos);
339
340         if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) {
341                 errno = ETXTBSY;
342                 return -1;
343         }
344
345         /* start where the last one left off to reduce chance of clashes */
346         start = counter;
347         do {
348                 sprintf(&path[pos], "%03d", counter);
349                 if (++counter >= MAX_RENAMES)
350                         counter = 1;
351         } while ((rc = access(path, 0)) == 0 && counter != start);
352
353         if (verbose > 0) {
354                 rprintf(FINFO,"renaming %s to %s because of text busy\n",
355                         fname, path);
356         }
357
358         /* maybe we should return rename()'s exit status? Nah. */
359         if (do_rename(fname, path) != 0) {
360                 errno = ETXTBSY;
361                 return -1;
362         }
363         return 0;
364 #endif
365 }
366
367 /* Returns 0 on success, -1 on most errors, and -2 if we got an error
368  * trying to copy the file across file systems. */
369 int robust_rename(char *from, char *to, int mode)
370 {
371         int tries = 4;
372
373         while (tries--) {
374                 if (do_rename(from, to) == 0)
375                         return 0;
376
377                 switch (errno) {
378 #ifdef ETXTBSY
379                 case ETXTBSY:
380                         if (robust_unlink(to) != 0)
381                                 return -1;
382                         break;
383 #endif
384                 case EXDEV:
385                         if (copy_file(from, to, mode) != 0)
386                                 return -2;
387                         do_unlink(from);
388                         return 0;
389                 default:
390                         return -1;
391                 }
392         }
393         return -1;
394 }
395
396
397 static pid_t all_pids[10];
398 static int num_pids;
399
400 /** Fork and record the pid of the child. **/
401 pid_t do_fork(void)
402 {
403         pid_t newpid = fork();
404
405         if (newpid != 0  &&  newpid != -1) {
406                 all_pids[num_pids++] = newpid;
407         }
408         return newpid;
409 }
410
411 /**
412  * Kill all children.
413  *
414  * @todo It would be kind of nice to make sure that they are actually
415  * all our children before we kill them, because their pids may have
416  * been recycled by some other process.  Perhaps when we wait for a
417  * child, we should remove it from this array.  Alternatively we could
418  * perhaps use process groups, but I think that would not work on
419  * ancient Unix versions that don't support them.
420  **/
421 void kill_all(int sig)
422 {
423         int i;
424
425         for (i = 0; i < num_pids; i++) {
426                 /* Let's just be a little careful where we
427                  * point that gun, hey?  See kill(2) for the
428                  * magic caused by negative values. */
429                 pid_t p = all_pids[i];
430
431                 if (p == getpid())
432                         continue;
433                 if (p <= 0)
434                         continue;
435
436                 kill(p, sig);
437         }
438 }
439
440
441 /** Turn a user name into a uid */
442 int name_to_uid(char *name, uid_t *uid)
443 {
444         struct passwd *pass;
445         if (!name || !*name) return 0;
446         pass = getpwnam(name);
447         if (pass) {
448                 *uid = pass->pw_uid;
449                 return 1;
450         }
451         return 0;
452 }
453
454 /** Turn a group name into a gid */
455 int name_to_gid(char *name, gid_t *gid)
456 {
457         struct group *grp;
458         if (!name || !*name) return 0;
459         grp = getgrnam(name);
460         if (grp) {
461                 *gid = grp->gr_gid;
462                 return 1;
463         }
464         return 0;
465 }
466
467
468 /** Lock a byte range in a open file */
469 int lock_range(int fd, int offset, int len)
470 {
471         struct flock lock;
472
473         lock.l_type = F_WRLCK;
474         lock.l_whence = SEEK_SET;
475         lock.l_start = offset;
476         lock.l_len = len;
477         lock.l_pid = 0;
478
479         return fcntl(fd,F_SETLK,&lock) == 0;
480 }
481
482 static int exclude_server_path(char *arg)
483 {
484         char *s;
485
486         if (server_exclude_list.head) {
487                 for (s = arg; (s = strchr(s, '/')) != NULL; ) {
488                         *s = '\0';
489                         if (check_exclude(&server_exclude_list, arg, 1) < 0) {
490                                 /* We must leave arg truncated! */
491                                 return 1;
492                         }
493                         *s++ = '/';
494                 }
495         }
496         return 0;
497 }
498
499 static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
500 {
501 #if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
502         if (maxargs <= *argc)
503                 return;
504         if (!*s)
505                 s = ".";
506         s = argv[*argc] = strdup(s);
507         exclude_server_path(s);
508         (*argc)++;
509 #else
510         extern int sanitize_paths;
511         glob_t globbuf;
512         int i;
513
514         if (!*s)
515                 s = ".";
516
517         s = argv[*argc] = strdup(s);
518         if (sanitize_paths)
519                 sanitize_path(s, NULL);
520
521         memset(&globbuf, 0, sizeof globbuf);
522         if (!exclude_server_path(s))
523                 glob(s, 0, NULL, &globbuf);
524         if (globbuf.gl_pathc == 0) {
525                 (*argc)++;
526                 globfree(&globbuf);
527                 return;
528         }
529         for (i = 0; i < maxargs - *argc && i < (int)globbuf.gl_pathc; i++) {
530                 if (i == 0)
531                         free(s);
532                 argv[*argc + i] = strdup(globbuf.gl_pathv[i]);
533                 if (!argv[*argc + i])
534                         out_of_memory("glob_expand");
535         }
536         globfree(&globbuf);
537         *argc += i;
538 #endif
539 }
540
541 /* This routine is only used in daemon mode. */
542 void glob_expand(char *base1, char **argv, int *argc, int maxargs)
543 {
544         char *s = argv[*argc];
545         char *p, *q;
546         char *base = base1;
547         int base_len = strlen(base);
548
549         if (!s || !*s) return;
550
551         if (strncmp(s, base, base_len) == 0)
552                 s += base_len;
553
554         s = strdup(s);
555         if (!s) out_of_memory("glob_expand");
556
557         if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
558         base_len++;
559
560         q = s;
561         while ((p = strstr(q,base)) != NULL && *argc < maxargs) {
562                 /* split it at this point */
563                 *p = 0;
564                 glob_expand_one(q, argv, argc, maxargs);
565                 q = p + base_len;
566         }
567
568         if (*q && *argc < maxargs)
569                 glob_expand_one(q, argv, argc, maxargs);
570
571         free(s);
572         free(base);
573 }
574
575 /**
576  * Convert a string to lower case
577  **/
578 void strlower(char *s)
579 {
580         while (*s) {
581                 if (isupper(* (unsigned char *) s))
582                         *s = tolower(* (unsigned char *) s);
583                 s++;
584         }
585 }
586
587 /* Join strings p1 & p2 into "dest" with a guaranteed '/' between them.  (If
588  * p1 ends with a '/', no extra '/' is inserted.)  Returns the length of both
589  * strings + 1 (if '/' was inserted), regardless of whether the null-terminated
590  * string fits into destsize. */
591 size_t pathjoin(char *dest, size_t destsize, const char *p1, const char *p2)
592 {
593         size_t len = strlcpy(dest, p1, destsize);
594         if (len < destsize - 1) {
595                 if (!len || dest[len-1] != '/')
596                         dest[len++] = '/';
597                 if (len < destsize - 1)
598                         len += strlcpy(dest + len, p2, destsize - len);
599                 else {
600                         dest[len] = '\0';
601                         len += strlen(p2);
602                 }
603         }
604         else
605                 len += strlen(p2) + 1; /* Assume we'd insert a '/'. */
606         return len;
607 }
608
609 /* Join any number of strings together, putting them in "dest".  The return
610  * value is the length of all the strings, regardless of whether the null-
611  * terminated whole fits in destsize.  Your list of string pointers must end
612  * with a NULL to indicate the end of the list. */
613 size_t stringjoin(char *dest, size_t destsize, ...)
614 {
615         va_list ap;
616         size_t len, ret = 0;
617         const char *src;
618
619         va_start(ap, destsize);
620         while (1) {
621                 if (!(src = va_arg(ap, const char *)))
622                         break;
623                 len = strlen(src);
624                 ret += len;
625                 if (destsize > 1) {
626                         if (len >= destsize)
627                                 len = destsize - 1;
628                         memcpy(dest, src, len);
629                         destsize -= len;
630                         dest += len;
631                 }
632         }
633         *dest = '\0';
634         va_end(ap);
635
636         return ret;
637 }
638
639 void clean_fname(char *name)
640 {
641         char *p;
642         int l;
643         int modified = 1;
644
645         if (!name) return;
646
647         while (modified) {
648                 modified = 0;
649
650                 if ((p = strstr(name,"/./")) != NULL) {
651                         modified = 1;
652                         while (*p) {
653                                 p[0] = p[2];
654                                 p++;
655                         }
656                 }
657
658                 if ((p = strstr(name,"//")) != NULL) {
659                         modified = 1;
660                         while (*p) {
661                                 p[0] = p[1];
662                                 p++;
663                         }
664                 }
665
666                 if (strncmp(p = name, "./", 2) == 0) {
667                         modified = 1;
668                         do {
669                                 p[0] = p[2];
670                         } while (*p++);
671                 }
672
673                 l = strlen(p = name);
674                 if (l > 1 && p[l-1] == '/') {
675                         modified = 1;
676                         p[l-1] = 0;
677                 }
678         }
679 }
680
681 /**
682  * Make path appear as if a chroot had occurred:
683  *
684  * @li 1. remove leading "/" (or replace with "." if at end)
685  *
686  * @li 2. remove leading ".." components (except those allowed by @p reldir)
687  *
688  * @li 3. delete any other "<dir>/.." (recursively)
689  *
690  * Can only shrink paths, so sanitizes in place.
691  *
692  * While we're at it, remove double slashes and "." components like
693  *   clean_fname() does, but DON'T remove a trailing slash because that
694  *   is sometimes significant on command line arguments.
695  *
696  * If @p reldir is non-null, it is a sanitized directory that the path will be
697  *    relative to, so allow as many ".." at the beginning of the path as
698  *    there are components in reldir.  This is used for symbolic link targets.
699  *    If reldir is non-null and the path began with "/", to be completely like
700  *    a chroot we should add in depth levels of ".." at the beginning of the
701  *    path, but that would blow the assumption that the path doesn't grow and
702  *    it is not likely to end up being a valid symlink anyway, so just do
703  *    the normal removal of the leading "/" instead.
704  *
705  * Contributed by Dave Dykstra <dwd@bell-labs.com>
706  */
707 void sanitize_path(char *p, char *reldir)
708 {
709         char *start, *sanp;
710         int depth = 0;
711         int allowdotdot = 0;
712
713         if (reldir) {
714                 depth++;
715                 while (*reldir) {
716                         if (*reldir++ == '/') {
717                                 depth++;
718                         }
719                 }
720         }
721         start = p;
722         sanp = p;
723         while (*p == '/') {
724                 /* remove leading slashes */
725                 p++;
726         }
727         while (*p != '\0') {
728                 /* this loop iterates once per filename component in p.
729                  * both p (and sanp if the original had a slash) should
730                  * always be left pointing after a slash
731                  */
732                 if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
733                         /* skip "." component */
734                         while (*++p == '/') {
735                                 /* skip following slashes */
736                                 ;
737                         }
738                         continue;
739                 }
740                 allowdotdot = 0;
741                 if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
742                         /* ".." component followed by slash or end */
743                         if (depth > 0 && sanp == start) {
744                                 /* allow depth levels of .. at the beginning */
745                                 --depth;
746                                 allowdotdot = 1;
747                         } else {
748                                 p += 2;
749                                 if (*p == '/')
750                                         p++;
751                                 if (sanp != start) {
752                                         /* back up sanp one level */
753                                         --sanp; /* now pointing at slash */
754                                         while (sanp > start && sanp[-1] != '/') {
755                                                 /* skip back up to slash */
756                                                 sanp--;
757                                         }
758                                 }
759                                 continue;
760                         }
761                 }
762                 while (1) {
763                         /* copy one component through next slash */
764                         *sanp++ = *p++;
765                         if (*p == '\0' || p[-1] == '/') {
766                                 while (*p == '/') {
767                                         /* skip multiple slashes */
768                                         p++;
769                                 }
770                                 break;
771                         }
772                 }
773                 if (allowdotdot) {
774                         /* move the virtual beginning to leave the .. alone */
775                         start = sanp;
776                 }
777         }
778         if (sanp == start && !allowdotdot) {
779                 /* ended up with nothing, so put in "." component */
780                 /*
781                  * note that the !allowdotdot doesn't prevent this from
782                  *  happening in all allowed ".." situations, but I didn't
783                  *  think it was worth putting in an extra variable to ensure
784                  *  it since an extra "." won't hurt in those situations.
785                  */
786                 *sanp++ = '.';
787         }
788         *sanp = '\0';
789 }
790
791 /* Works much like sanitize_path(), with these differences:  (1) a new buffer
792  * is allocated for the sanitized path rather than modifying it in-place; (2)
793  * a leading slash gets transformed into the rootdir value (which can be empty
794  * or NULL if you just want the slash to get dropped); (3) no "reldir" can be
795  * specified. */
796 char *alloc_sanitize_path(const char *path, const char *rootdir)
797 {
798         char *buf;
799         int rlen, plen = strlen(path);
800
801         if (*path == '/' && rootdir) {
802                 rlen = strlen(rootdir);
803                 if (rlen == 1)
804                         path++;
805         } else
806                 rlen = 0;
807         if (!(buf = new_array(char, rlen + plen + 1)))
808                 out_of_memory("alloc_sanitize_path");
809         if (rlen)
810                 memcpy(buf, rootdir, rlen);
811         memcpy(buf + rlen, path, plen + 1);
812
813         if (rlen > 1)
814                 rlen++;
815         sanitize_path(buf + rlen, NULL);
816         if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
817                 if (rlen > 1)
818                         rlen--;
819                 buf[rlen] = '\0';
820         }
821
822         return buf;
823 }
824
825 char curr_dir[MAXPATHLEN];
826 unsigned int curr_dir_len;
827
828 /**
829  * Like chdir(), but it keeps track of the current directory (in the
830  * global "curr_dir"), and ensures that the path size doesn't overflow.
831  * Also cleans the path using the clean_fname() function.
832  **/
833 int push_dir(char *dir)
834 {
835         static int initialised;
836         unsigned int len;
837
838         if (!initialised) {
839                 initialised = 1;
840                 getcwd(curr_dir, sizeof curr_dir - 1);
841                 curr_dir_len = strlen(curr_dir);
842         }
843
844         if (!dir)       /* this call was probably just to initialize */
845                 return 0;
846
847         len = strlen(dir);
848         if (len == 1 && *dir == '.')
849                 return 1;
850
851         if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir)
852                 return 0;
853
854         if (chdir(dir))
855                 return 0;
856
857         if (*dir == '/') {
858                 memcpy(curr_dir, dir, len + 1);
859                 curr_dir_len = len;
860         } else {
861                 curr_dir[curr_dir_len++] = '/';
862                 memcpy(curr_dir + curr_dir_len, dir, len + 1);
863                 curr_dir_len += len;
864         }
865
866         clean_fname(curr_dir);
867
868         return 1;
869 }
870
871 /**
872  * Reverse a push_dir() call.  You must pass in an absolute path
873  * that was copied from a prior value of "curr_dir".
874  **/
875 int pop_dir(char *dir)
876 {
877         if (chdir(dir))
878                 return 0;
879
880         curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
881         if (curr_dir_len >= sizeof curr_dir)
882                 curr_dir_len = sizeof curr_dir - 1;
883
884         return 1;
885 }
886
887 /**
888  * Return a quoted string with the full pathname of the indicated filename.
889  * The string " (in MODNAME)" may also be appended.  The returned pointer
890  * remains valid until the next time full_fname() is called.
891  **/
892 char *full_fname(char *fn)
893 {
894         extern int module_id;
895         static char *result = NULL;
896         char *m1, *m2, *m3;
897         char *p1, *p2;
898
899         if (result)
900                 free(result);
901
902         if (*fn == '/')
903                 p1 = p2 = "";
904         else {
905                 p1 = curr_dir;
906                 p2 = "/";
907         }
908         if (module_id >= 0) {
909                 m1 = " (in ";
910                 m2 = lp_name(module_id);
911                 m3 = ")";
912                 if (*p1) {
913                         if (!lp_use_chroot(module_id)) {
914                                 char *p = lp_path(module_id);
915                                 if (*p != '/' || p[1])
916                                         p1 += strlen(p);
917                         }
918                         if (!*p1)
919                                 p2++;
920                         else
921                                 p1++;
922                 }
923                 else
924                         fn++;
925         } else
926                 m1 = m2 = m3 = "";
927
928         asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3);
929
930         return result;
931 }
932
933 /** We need to supply our own strcmp function for file list comparisons
934    to ensure that signed/unsigned usage is consistent between machines. */
935 int u_strcmp(const char *cs1, const char *cs2)
936 {
937         const uchar *s1 = (const uchar *)cs1;
938         const uchar *s2 = (const uchar *)cs2;
939
940         while (*s1 && *s2 && (*s1 == *s2)) {
941                 s1++; s2++;
942         }
943
944         return (int)*s1 - (int)*s2;
945 }
946
947
948
949 /**
950  * Determine if a symlink points outside the current directory tree.
951  * This is considered "unsafe" because e.g. when mirroring somebody
952  * else's machine it might allow them to establish a symlink to
953  * /etc/passwd, and then read it through a web server.
954  *
955  * Null symlinks and absolute symlinks are always unsafe.
956  *
957  * Basically here we are concerned with symlinks whose target contains
958  * "..", because this might cause us to walk back up out of the
959  * transferred directory.  We are not allowed to go back up and
960  * reenter.
961  *
962  * @param dest Target of the symlink in question.
963  *
964  * @param src Top source directory currently applicable.  Basically this
965  * is the first parameter to rsync in a simple invocation, but it's
966  * modified by flist.c in slightly complex ways.
967  *
968  * @retval True if unsafe
969  * @retval False is unsafe
970  *
971  * @sa t_unsafe.c
972  **/
973 int unsafe_symlink(const char *dest, const char *src)
974 {
975         const char *name, *slash;
976         int depth = 0;
977
978         /* all absolute and null symlinks are unsafe */
979         if (!dest || !*dest || *dest == '/') return 1;
980
981         /* find out what our safety margin is */
982         for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
983                 if (strncmp(name, "../", 3) == 0) {
984                         depth = 0;
985                 } else if (strncmp(name, "./", 2) == 0) {
986                         /* nothing */
987                 } else {
988                         depth++;
989                 }
990         }
991         if (strcmp(name, "..") == 0)
992                 depth = 0;
993
994         for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
995                 if (strncmp(name, "../", 3) == 0) {
996                         /* if at any point we go outside the current directory
997                            then stop - it is unsafe */
998                         if (--depth < 0)
999                                 return 1;
1000                 } else if (strncmp(name, "./", 2) == 0) {
1001                         /* nothing */
1002                 } else {
1003                         depth++;
1004                 }
1005         }
1006         if (strcmp(name, "..") == 0)
1007                 depth--;
1008
1009         return (depth < 0);
1010 }
1011
1012
1013 /**
1014  * Return the date and time as a string
1015  **/
1016 char *timestring(time_t t)
1017 {
1018         static char TimeBuf[200];
1019         struct tm *tm = localtime(&t);
1020
1021 #ifdef HAVE_STRFTIME
1022         strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
1023 #else
1024         strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);
1025 #endif
1026
1027         if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
1028                 TimeBuf[strlen(TimeBuf)-1] = 0;
1029         }
1030
1031         return(TimeBuf);
1032 }
1033
1034
1035 /**
1036  * Sleep for a specified number of milliseconds.
1037  *
1038  * Always returns TRUE.  (In the future it might return FALSE if
1039  * interrupted.)
1040  **/
1041 int msleep(int t)
1042 {
1043         int tdiff = 0;
1044         struct timeval tval, t1, t2;
1045
1046         gettimeofday(&t1, NULL);
1047         gettimeofday(&t2, NULL);
1048
1049         while (tdiff < t) {
1050                 tval.tv_sec = (t-tdiff)/1000;
1051                 tval.tv_usec = 1000*((t-tdiff)%1000);
1052
1053                 errno = 0;
1054                 select(0,NULL,NULL, NULL, &tval);
1055
1056                 gettimeofday(&t2, NULL);
1057                 tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
1058                         (t2.tv_usec - t1.tv_usec)/1000;
1059         }
1060
1061         return True;
1062 }
1063
1064
1065 /**
1066  * Determine if two file modification times are equivalent (either
1067  * exact or in the modification timestamp window established by
1068  * --modify-window).
1069  *
1070  * @retval 0 if the times should be treated as the same
1071  *
1072  * @retval +1 if the first is later
1073  *
1074  * @retval -1 if the 2nd is later
1075  **/
1076 int cmp_modtime(time_t file1, time_t file2)
1077 {
1078         extern int modify_window;
1079
1080         if (file2 > file1) {
1081                 if (file2 - file1 <= modify_window) return 0;
1082                 return -1;
1083         }
1084         if (file1 - file2 <= modify_window) return 0;
1085         return 1;
1086 }
1087
1088
1089 #ifdef __INSURE__XX
1090 #include <dlfcn.h>
1091
1092 /**
1093    This routine is a trick to immediately catch errors when debugging
1094    with insure. A xterm with a gdb is popped up when insure catches
1095    a error. It is Linux specific.
1096 **/
1097 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
1098 {
1099         static int (*fn)();
1100         int ret;
1101         char *cmd;
1102
1103         asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
1104                 getpid(), getpid(), getpid());
1105
1106         if (!fn) {
1107                 static void *h;
1108                 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
1109                 fn = dlsym(h, "_Insure_trap_error");
1110         }
1111
1112         ret = fn(a1, a2, a3, a4, a5, a6);
1113
1114         system(cmd);
1115
1116         free(cmd);
1117
1118         return ret;
1119 }
1120 #endif
1121
1122
1123 #define MALLOC_MAX 0x40000000
1124
1125 void *_new_array(unsigned int size, unsigned long num)
1126 {
1127         if (num >= MALLOC_MAX/size)
1128                 return NULL;
1129         return malloc(size * num);
1130 }
1131
1132 void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
1133 {
1134         if (num >= MALLOC_MAX/size)
1135                 return NULL;
1136         /* No realloc should need this, but just in case... */
1137         if (!ptr)
1138                 return malloc(size * num);
1139         return realloc(ptr, size * num);
1140 }