- Improved option_error() to make sure that the user sees the error 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 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) {
710 depth++;
711 while (*reldir) {
712 if (*reldir++ == '/') {
713 depth++;
714 }
715 }
716 }
44e2e578
DD
717 start = p;
718 sanp = p;
b5f9e67d
DD
719 while (*p == '/') {
720 /* remove leading slashes */
721 p++;
722 }
1b8e662a 723 while (*p != '\0') {
b5f9e67d 724 /* this loop iterates once per filename component in p.
44e2e578 725 * both p (and sanp if the original had a slash) should
b5f9e67d
DD
726 * always be left pointing after a slash
727 */
c284f34a 728 if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
b5f9e67d
DD
729 /* skip "." component */
730 while (*++p == '/') {
731 /* skip following slashes */
732 ;
733 }
cb13abfe
DD
734 continue;
735 }
736 allowdotdot = 0;
c284f34a 737 if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
cb13abfe 738 /* ".." component followed by slash or end */
c284f34a 739 if (depth > 0 && sanp == start) {
cb13abfe
DD
740 /* allow depth levels of .. at the beginning */
741 --depth;
742 allowdotdot = 1;
743 } else {
744 p += 2;
745 if (*p == '/')
746 p++;
747 if (sanp != start) {
748 /* back up sanp one level */
749 --sanp; /* now pointing at slash */
c284f34a 750 while (sanp > start && sanp[-1] != '/') {
cb13abfe
DD
751 /* skip back up to slash */
752 sanp--;
753 }
b5f9e67d 754 }
cb13abfe 755 continue;
1b8e662a 756 }
cb13abfe
DD
757 }
758 while (1) {
759 /* copy one component through next slash */
760 *sanp++ = *p++;
42509417 761 if (*p == '\0' || p[-1] == '/') {
cb13abfe
DD
762 while (*p == '/') {
763 /* skip multiple slashes */
764 p++;
b5f9e67d 765 }
cb13abfe 766 break;
1b8e662a
DD
767 }
768 }
cb13abfe
DD
769 if (allowdotdot) {
770 /* move the virtual beginning to leave the .. alone */
771 start = sanp;
772 }
1b8e662a 773 }
c284f34a 774 if (sanp == start && !allowdotdot) {
b5f9e67d 775 /* ended up with nothing, so put in "." component */
79452d46
DD
776 /*
777 * note that the !allowdotdot doesn't prevent this from
778 * happening in all allowed ".." situations, but I didn't
779 * think it was worth putting in an extra variable to ensure
780 * it since an extra "." won't hurt in those situations.
781 */
44e2e578 782 *sanp++ = '.';
b5f9e67d 783 }
44e2e578 784 *sanp = '\0';
1b8e662a
DD
785}
786
14b61c63
WD
787/* Works much like sanitize_path(), with these differences: (1) a new buffer
788 * is allocated for the sanitized path rather than modifying it in-place; (2)
789 * a leading slash gets transformed into the rootdir value (which can be empty
790 * or NULL if you just want the slash to get dropped); (3) no "reldir" can be
791 * specified. */
792char *alloc_sanitize_path(const char *path, const char *rootdir)
793{
794 char *buf;
795 int rlen, plen = strlen(path);
796
b05b3c9b 797 if (*path == '/' && rootdir) {
14b61c63 798 rlen = strlen(rootdir);
b05b3c9b
WD
799 if (rlen == 1)
800 path++;
801 } else
14b61c63
WD
802 rlen = 0;
803 if (!(buf = new_array(char, rlen + plen + 1)))
804 out_of_memory("alloc_sanitize_path");
805 if (rlen)
806 memcpy(buf, rootdir, rlen);
807 memcpy(buf + rlen, path, plen + 1);
808
b05b3c9b 809 if (rlen > 1)
14b61c63
WD
810 rlen++;
811 sanitize_path(buf + rlen, NULL);
b05b3c9b
WD
812 if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
813 if (rlen > 1)
814 rlen--;
815 buf[rlen] = '\0';
816 }
14b61c63
WD
817
818 return buf;
819}
5243c216 820
4791825d 821char curr_dir[MAXPATHLEN];
4af8fe4e 822unsigned int curr_dir_len;
5243c216 823
4e5db0ad 824/**
a16d8f2b
WD
825 * Like chdir(), but it keeps track of the current directory (in the
826 * global "curr_dir"), and ensures that the path size doesn't overflow.
827 * Also cleans the path using the clean_fname() function.
4e5db0ad 828 **/
4af8fe4e 829int push_dir(char *dir)
5243c216 830{
5243c216 831 static int initialised;
4af8fe4e 832 unsigned int len;
5243c216
AT
833
834 if (!initialised) {
835 initialised = 1;
5cb37436 836 getcwd(curr_dir, sizeof curr_dir - 1);
4af8fe4e 837 curr_dir_len = strlen(curr_dir);
5243c216
AT
838 }
839
4af8fe4e
WD
840 if (!dir) /* this call was probably just to initialize */
841 return 0;
c226b7c2 842
4af8fe4e
WD
843 len = strlen(dir);
844 if (len == 1 && *dir == '.')
845 return 1;
5243c216 846
4af8fe4e
WD
847 if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir)
848 return 0;
849
850 if (chdir(dir))
851 return 0;
5243c216
AT
852
853 if (*dir == '/') {
4af8fe4e
WD
854 memcpy(curr_dir, dir, len + 1);
855 curr_dir_len = len;
856 } else {
857 curr_dir[curr_dir_len++] = '/';
858 memcpy(curr_dir + curr_dir_len, dir, len + 1);
859 curr_dir_len += len;
5243c216
AT
860 }
861
862 clean_fname(curr_dir);
863
4af8fe4e 864 return 1;
5243c216
AT
865}
866
a16d8f2b
WD
867/**
868 * Reverse a push_dir() call. You must pass in an absolute path
869 * that was copied from a prior value of "curr_dir".
870 **/
5243c216
AT
871int pop_dir(char *dir)
872{
4af8fe4e
WD
873 if (chdir(dir))
874 return 0;
5243c216 875
4af8fe4e
WD
876 curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
877 if (curr_dir_len >= sizeof curr_dir)
878 curr_dir_len = sizeof curr_dir - 1;
5243c216 879
4af8fe4e 880 return 1;
5243c216 881}
aa9b77a5 882
eb61be19
WD
883/**
884 * Return a quoted string with the full pathname of the indicated filename.
885 * The string " (in MODNAME)" may also be appended. The returned pointer
886 * remains valid until the next time full_fname() is called.
887 **/
888char *full_fname(char *fn)
889{
eb61be19
WD
890 static char *result = NULL;
891 char *m1, *m2, *m3;
892 char *p1, *p2;
893
894 if (result)
895 free(result);
896
897 if (*fn == '/')
898 p1 = p2 = "";
899 else {
900 p1 = curr_dir;
901 p2 = "/";
902 }
903 if (module_id >= 0) {
904 m1 = " (in ";
905 m2 = lp_name(module_id);
906 m3 = ")";
907 if (*p1) {
908 if (!lp_use_chroot(module_id)) {
909 char *p = lp_path(module_id);
910 if (*p != '/' || p[1])
911 p1 += strlen(p);
912 }
913 if (!*p1)
914 p2++;
915 else
916 p1++;
917 }
918 else
919 fn++;
920 } else
921 m1 = m2 = m3 = "";
922
923 asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3);
924
925 return result;
926}
927
ac13ad10 928/** We need to supply our own strcmp function for file list comparisons
aa9b77a5
AT
929 to ensure that signed/unsigned usage is consistent between machines. */
930int u_strcmp(const char *cs1, const char *cs2)
931{
5a788ade
AT
932 const uchar *s1 = (const uchar *)cs1;
933 const uchar *s2 = (const uchar *)cs2;
aa9b77a5
AT
934
935 while (*s1 && *s2 && (*s1 == *s2)) {
936 s1++; s2++;
937 }
5cb37436 938
aa9b77a5
AT
939 return (int)*s1 - (int)*s2;
940}
eb86d661 941
4b957c22 942
ac13ad10
MP
943
944/**
945 * Determine if a symlink points outside the current directory tree.
036e70b0
MP
946 * This is considered "unsafe" because e.g. when mirroring somebody
947 * else's machine it might allow them to establish a symlink to
948 * /etc/passwd, and then read it through a web server.
949 *
4e5db0ad
MP
950 * Null symlinks and absolute symlinks are always unsafe.
951 *
952 * Basically here we are concerned with symlinks whose target contains
953 * "..", because this might cause us to walk back up out of the
954 * transferred directory. We are not allowed to go back up and
955 * reenter.
956 *
036e70b0
MP
957 * @param dest Target of the symlink in question.
958 *
25d34a5c 959 * @param src Top source directory currently applicable. Basically this
036e70b0 960 * is the first parameter to rsync in a simple invocation, but it's
25d34a5c 961 * modified by flist.c in slightly complex ways.
036e70b0
MP
962 *
963 * @retval True if unsafe
964 * @retval False is unsafe
4e5db0ad
MP
965 *
966 * @sa t_unsafe.c
ac13ad10 967 **/
7afa3a4a 968int unsafe_symlink(const char *dest, const char *src)
4b957c22 969{
7afa3a4a 970 const char *name, *slash;
4b957c22
AT
971 int depth = 0;
972
973 /* all absolute and null symlinks are unsafe */
7afa3a4a 974 if (!dest || !*dest || *dest == '/') return 1;
4b957c22
AT
975
976 /* find out what our safety margin is */
7afa3a4a
WD
977 for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
978 if (strncmp(name, "../", 3) == 0) {
c284f34a 979 depth = 0;
7afa3a4a 980 } else if (strncmp(name, "./", 2) == 0) {
4b957c22
AT
981 /* nothing */
982 } else {
983 depth++;
984 }
985 }
7afa3a4a
WD
986 if (strcmp(name, "..") == 0)
987 depth = 0;
4b957c22 988
7afa3a4a
WD
989 for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
990 if (strncmp(name, "../", 3) == 0) {
991 /* if at any point we go outside the current directory
992 then stop - it is unsafe */
993 if (--depth < 0)
994 return 1;
995 } else if (strncmp(name, "./", 2) == 0) {
4b957c22
AT
996 /* nothing */
997 } else {
998 depth++;
999 }
4b957c22 1000 }
7afa3a4a
WD
1001 if (strcmp(name, "..") == 0)
1002 depth--;
4b957c22 1003
4b957c22
AT
1004 return (depth < 0);
1005}
375a4556 1006
f7632fc6 1007
ac13ad10 1008/**
b4235b31
MP
1009 * Return the date and time as a string
1010 **/
f7632fc6
AT
1011char *timestring(time_t t)
1012{
1013 static char TimeBuf[200];
1014 struct tm *tm = localtime(&t);
1015
1016#ifdef HAVE_STRFTIME
5cb37436 1017 strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
f7632fc6 1018#else
5cb37436 1019 strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);
f7632fc6
AT
1020#endif
1021
1022 if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
1023 TimeBuf[strlen(TimeBuf)-1] = 0;
1024 }
1025
1026 return(TimeBuf);
1027}
1028
9ec16c83 1029
e1bd49d6
MP
1030/**
1031 * Sleep for a specified number of milliseconds.
1032 *
1033 * Always returns TRUE. (In the future it might return FALSE if
1034 * interrupted.)
1035 **/
1036int msleep(int t)
9ec16c83 1037{
c284f34a
WD
1038 int tdiff = 0;
1039 struct timeval tval, t1, t2;
9ec16c83
AT
1040
1041 gettimeofday(&t1, NULL);
1042 gettimeofday(&t2, NULL);
5cb37436 1043
9ec16c83
AT
1044 while (tdiff < t) {
1045 tval.tv_sec = (t-tdiff)/1000;
1046 tval.tv_usec = 1000*((t-tdiff)%1000);
5cb37436 1047
9ec16c83
AT
1048 errno = 0;
1049 select(0,NULL,NULL, NULL, &tval);
1050
1051 gettimeofday(&t2, NULL);
5cb37436 1052 tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
9ec16c83
AT
1053 (t2.tv_usec - t1.tv_usec)/1000;
1054 }
e1bd49d6
MP
1055
1056 return True;
9ec16c83
AT
1057}
1058
1059
ac13ad10
MP
1060/**
1061 * Determine if two file modification times are equivalent (either
1062 * exact or in the modification timestamp window established by
1063 * --modify-window).
1064 *
1065 * @retval 0 if the times should be treated as the same
1066 *
1067 * @retval +1 if the first is later
1068 *
1069 * @retval -1 if the 2nd is later
1070 **/
5b56cc19
AT
1071int cmp_modtime(time_t file1, time_t file2)
1072{
5b56cc19 1073 if (file2 > file1) {
bc6ebcd2
WD
1074 if (file2 - file1 <= modify_window)
1075 return 0;
5b56cc19
AT
1076 return -1;
1077 }
bc6ebcd2
WD
1078 if (file1 - file2 <= modify_window)
1079 return 0;
5b56cc19
AT
1080 return 1;
1081}
1082
1083
1084#ifdef __INSURE__XX
0f8f98c8
AT
1085#include <dlfcn.h>
1086
ac13ad10
MP
1087/**
1088 This routine is a trick to immediately catch errors when debugging
1089 with insure. A xterm with a gdb is popped up when insure catches
1090 a error. It is Linux specific.
1091**/
0f8f98c8
AT
1092int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
1093{
1094 static int (*fn)();
1095 int ret;
8950ac03 1096 char *cmd;
0f8f98c8 1097
5cb37436 1098 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
1099 getpid(), getpid(), getpid());
1100
1101 if (!fn) {
1102 static void *h;
1103 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
1104 fn = dlsym(h, "_Insure_trap_error");
1105 }
1106
1107 ret = fn(a1, a2, a3, a4, a5, a6);
1108
1109 system(cmd);
1110
8950ac03
AT
1111 free(cmd);
1112
0f8f98c8
AT
1113 return ret;
1114}
1115#endif
58cadc86
WD
1116
1117
1118#define MALLOC_MAX 0x40000000
1119
1120void *_new_array(unsigned int size, unsigned long num)
1121{
1122 if (num >= MALLOC_MAX/size)
1123 return NULL;
1124 return malloc(size * num);
1125}
1126
1127void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
1128{
1129 if (num >= MALLOC_MAX/size)
1130 return NULL;
1131 /* No realloc should need this, but just in case... */
1132 if (!ptr)
1133 return malloc(size * num);
1134 return realloc(ptr, size * num);
1135}