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