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