Removed some excessive parens.
[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",
b5bd5542 137 fname, (long)modtime,
404e813c
MP
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;
b5bd5542
WD
442 if (!name || !*name)
443 return 0;
8ef4ffd6
AT
444 pass = getpwnam(name);
445 if (pass) {
446 *uid = pass->pw_uid;
447 return 1;
448 }
449 return 0;
450}
451
ac13ad10 452/** Turn a group name into a gid */
8ef4ffd6
AT
453int name_to_gid(char *name, gid_t *gid)
454{
455 struct group *grp;
b5bd5542
WD
456 if (!name || !*name)
457 return 0;
8ef4ffd6
AT
458 grp = getgrnam(name);
459 if (grp) {
460 *gid = grp->gr_gid;
461 return 1;
462 }
463 return 0;
464}
465
ff8b29b8 466
ac13ad10 467/** Lock a byte range in a open file */
31593dd6 468int lock_range(int fd, int offset, int len)
0c515f17 469{
31593dd6 470 struct flock lock;
0c515f17 471
31593dd6
AT
472 lock.l_type = F_WRLCK;
473 lock.l_whence = SEEK_SET;
474 lock.l_start = offset;
475 lock.l_len = len;
476 lock.l_pid = 0;
5cb37436 477
31593dd6 478 return fcntl(fd,F_SETLK,&lock) == 0;
0c515f17 479}
874895d5 480
4791825d
WD
481static int exclude_server_path(char *arg)
482{
483 char *s;
4791825d 484
bf6dcd17 485 if (server_exclude_list.head) {
4791825d
WD
486 for (s = arg; (s = strchr(s, '/')) != NULL; ) {
487 *s = '\0';
9fdb334e 488 if (check_exclude(&server_exclude_list, arg, 1) < 0) {
4791825d
WD
489 /* We must leave arg truncated! */
490 return 1;
491 }
492 *s++ = '/';
493 }
494 }
495 return 0;
496}
874895d5 497
b5bd5542 498static void glob_expand_one(char *s, char **argv, int *argc_ptr, int maxargs)
874895d5 499{
b5bd5542 500 int argc = *argc_ptr;
932be9aa 501#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
b5bd5542 502 if (maxargs <= argc)
4135d091
WD
503 return;
504 if (!*s)
505 s = ".";
b5bd5542 506 s = argv[argc++] = strdup(s);
4791825d 507 exclude_server_path(s);
874895d5
AT
508#else
509 glob_t globbuf;
510 int i;
511
b5bd5542
WD
512 if (maxargs <= argc)
513 return;
4135d091
WD
514 if (!*s)
515 s = ".";
e42c9458 516
b5bd5542 517 s = strdup(s);
4135d091 518 if (sanitize_paths)
4791825d 519 sanitize_path(s, NULL);
087bf010 520
5cb37436 521 memset(&globbuf, 0, sizeof globbuf);
4791825d
WD
522 if (!exclude_server_path(s))
523 glob(s, 0, NULL, &globbuf);
b5bd5542
WD
524 if (globbuf.gl_pathc == 0)
525 argv[argc++] = s;
526 else {
527 int j = globbuf.gl_pathc;
528 if (j > maxargs - argc)
529 j = maxargs - argc;
530 free(s);
531 for (i = 0; i < j; i++) {
532 if (!(argv[argc++] = strdup(globbuf.gl_pathv[i])))
533 out_of_memory("glob_expand_one");
534 }
874895d5
AT
535 }
536 globfree(&globbuf);
874895d5 537#endif
b5bd5542 538 *argc_ptr = argc;
874895d5 539}
5a96ee05 540
4791825d 541/* This routine is only used in daemon mode. */
b5bd5542 542void glob_expand(char *base1, char **argv, int *argc_ptr, int maxargs)
087bf010 543{
b5bd5542 544 char *s = argv[*argc_ptr];
087bf010 545 char *p, *q;
ba5e128d 546 char *base = base1;
4791825d 547 int base_len = strlen(base);
087bf010 548
b5bd5542
WD
549 if (!s || !*s)
550 return;
087bf010 551
4791825d
WD
552 if (strncmp(s, base, base_len) == 0)
553 s += base_len;
e42c9458 554
b5bd5542
WD
555 if (!(s = strdup(s)))
556 out_of_memory("glob_expand");
087bf010 557
b5bd5542
WD
558 if (asprintf(&base," %s/", base1) <= 0)
559 out_of_memory("glob_expand");
4791825d 560 base_len++;
ba5e128d 561
b5bd5542
WD
562 for (q = s; *q; q = p + base_len) {
563 if ((p = strstr(q, base)) != NULL)
564 *p = '\0'; /* split it at this point */
565 glob_expand_one(q, argv, argc_ptr, maxargs);
566 if (!p)
567 break;
087bf010
AT
568 }
569
087bf010 570 free(s);
ba5e128d 571 free(base);
087bf010 572}
5a96ee05 573
ac13ad10
MP
574/**
575 * Convert a string to lower case
576 **/
5a96ee05
AT
577void strlower(char *s)
578{
579 while (*s) {
b5bd5542
WD
580 if (isupper(*(unsigned char *)s))
581 *s = tolower(*(unsigned char *)s);
5a96ee05
AT
582 s++;
583 }
584}
e42c9458 585
368ad70e
WD
586/* Join strings p1 & p2 into "dest" with a guaranteed '/' between them. (If
587 * p1 ends with a '/', no extra '/' is inserted.) Returns the length of both
a8f7e4b8
WD
588 * strings + 1 (if '/' was inserted), regardless of whether the null-terminated
589 * string fits into destsize. */
368ad70e
WD
590size_t pathjoin(char *dest, size_t destsize, const char *p1, const char *p2)
591{
592 size_t len = strlcpy(dest, p1, destsize);
593 if (len < destsize - 1) {
594 if (!len || dest[len-1] != '/')
595 dest[len++] = '/';
596 if (len < destsize - 1)
597 len += strlcpy(dest + len, p2, destsize - len);
598 else {
599 dest[len] = '\0';
600 len += strlen(p2);
601 }
602 }
603 else
604 len += strlen(p2) + 1; /* Assume we'd insert a '/'. */
605 return len;
606}
607
608/* Join any number of strings together, putting them in "dest". The return
a8f7e4b8
WD
609 * value is the length of all the strings, regardless of whether the null-
610 * terminated whole fits in destsize. Your list of string pointers must end
611 * with a NULL to indicate the end of the list. */
368ad70e
WD
612size_t stringjoin(char *dest, size_t destsize, ...)
613{
5cb37436 614 va_list ap;
368ad70e
WD
615 size_t len, ret = 0;
616 const char *src;
617
618 va_start(ap, destsize);
619 while (1) {
620 if (!(src = va_arg(ap, const char *)))
621 break;
622 len = strlen(src);
623 ret += len;
624 if (destsize > 1) {
625 if (len >= destsize)
626 len = destsize - 1;
627 memcpy(dest, src, len);
628 destsize -= len;
629 dest += len;
630 }
631 }
632 *dest = '\0';
633 va_end(ap);
634
635 return ret;
636}
637
5243c216
AT
638void clean_fname(char *name)
639{
640 char *p;
641 int l;
642 int modified = 1;
643
b5bd5542
WD
644 if (!name)
645 return;
5243c216
AT
646
647 while (modified) {
648 modified = 0;
649
c284f34a 650 if ((p = strstr(name,"/./")) != NULL) {
5243c216
AT
651 modified = 1;
652 while (*p) {
653 p[0] = p[2];
654 p++;
655 }
656 }
657
c284f34a 658 if ((p = strstr(name,"//")) != NULL) {
5243c216
AT
659 modified = 1;
660 while (*p) {
661 p[0] = p[1];
662 p++;
663 }
664 }
665
c284f34a 666 if (strncmp(p = name, "./", 2) == 0) {
5243c216
AT
667 modified = 1;
668 do {
669 p[0] = p[2];
670 } while (*p++);
671 }
672
c284f34a 673 l = strlen(p = name);
5243c216
AT
674 if (l > 1 && p[l-1] == '/') {
675 modified = 1;
676 p[l-1] = 0;
677 }
678 }
679}
680
ac13ad10 681/**
1b8e662a 682 * Make path appear as if a chroot had occurred:
ac13ad10 683 *
b4235b31
MP
684 * @li 1. remove leading "/" (or replace with "." if at end)
685 *
686 * @li 2. remove leading ".." components (except those allowed by @p reldir)
687 *
688 * @li 3. delete any other "<dir>/.." (recursively)
ac13ad10 689 *
79452d46 690 * Can only shrink paths, so sanitizes in place.
ac13ad10 691 *
b5f9e67d 692 * While we're at it, remove double slashes and "." components like
b4235b31 693 * clean_fname() does, but DON'T remove a trailing slash because that
b5f9e67d 694 * is sometimes significant on command line arguments.
ac13ad10 695 *
b4235b31 696 * If @p reldir is non-null, it is a sanitized directory that the path will be
79452d46
DD
697 * relative to, so allow as many ".." at the beginning of the path as
698 * there are components in reldir. This is used for symbolic link targets.
699 * If reldir is non-null and the path began with "/", to be completely like
700 * a chroot we should add in depth levels of ".." at the beginning of the
701 * path, but that would blow the assumption that the path doesn't grow and
702 * it is not likely to end up being a valid symlink anyway, so just do
703 * the normal removal of the leading "/" instead.
ac13ad10 704 *
1b8e662a
DD
705 * Contributed by Dave Dykstra <dwd@bell-labs.com>
706 */
cb13abfe 707void sanitize_path(char *p, char *reldir)
1b8e662a 708{
44e2e578 709 char *start, *sanp;
cb13abfe
DD
710 int depth = 0;
711 int allowdotdot = 0;
712
713 if (reldir) {
f9e5a0cd 714 int new_component = 1;
cb13abfe 715 while (*reldir) {
f9e5a0cd
WD
716 if (*reldir++ == '/')
717 new_component = 1;
718 else if (new_component) {
719 new_component = 0;
cb13abfe
DD
720 depth++;
721 }
722 }
723 }
44e2e578
DD
724 start = p;
725 sanp = p;
b5f9e67d
DD
726 while (*p == '/') {
727 /* remove leading slashes */
728 p++;
729 }
1b8e662a 730 while (*p != '\0') {
b5f9e67d 731 /* this loop iterates once per filename component in p.
44e2e578 732 * both p (and sanp if the original had a slash) should
b5f9e67d
DD
733 * always be left pointing after a slash
734 */
c284f34a 735 if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
b5f9e67d
DD
736 /* skip "." component */
737 while (*++p == '/') {
738 /* skip following slashes */
739 ;
740 }
cb13abfe
DD
741 continue;
742 }
743 allowdotdot = 0;
c284f34a 744 if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
cb13abfe 745 /* ".." component followed by slash or end */
c284f34a 746 if (depth > 0 && sanp == start) {
cb13abfe
DD
747 /* allow depth levels of .. at the beginning */
748 --depth;
749 allowdotdot = 1;
750 } else {
751 p += 2;
752 if (*p == '/')
753 p++;
754 if (sanp != start) {
755 /* back up sanp one level */
756 --sanp; /* now pointing at slash */
c284f34a 757 while (sanp > start && sanp[-1] != '/') {
cb13abfe
DD
758 /* skip back up to slash */
759 sanp--;
760 }
b5f9e67d 761 }
cb13abfe 762 continue;
1b8e662a 763 }
cb13abfe
DD
764 }
765 while (1) {
766 /* copy one component through next slash */
767 *sanp++ = *p++;
42509417 768 if (*p == '\0' || p[-1] == '/') {
cb13abfe
DD
769 while (*p == '/') {
770 /* skip multiple slashes */
771 p++;
b5f9e67d 772 }
cb13abfe 773 break;
1b8e662a
DD
774 }
775 }
cb13abfe
DD
776 if (allowdotdot) {
777 /* move the virtual beginning to leave the .. alone */
778 start = sanp;
779 }
1b8e662a 780 }
c284f34a 781 if (sanp == start && !allowdotdot) {
b5f9e67d 782 /* ended up with nothing, so put in "." component */
79452d46
DD
783 /*
784 * note that the !allowdotdot doesn't prevent this from
785 * happening in all allowed ".." situations, but I didn't
786 * think it was worth putting in an extra variable to ensure
787 * it since an extra "." won't hurt in those situations.
788 */
44e2e578 789 *sanp++ = '.';
b5f9e67d 790 }
44e2e578 791 *sanp = '\0';
1b8e662a
DD
792}
793
14b61c63
WD
794/* Works much like sanitize_path(), with these differences: (1) a new buffer
795 * is allocated for the sanitized path rather than modifying it in-place; (2)
796 * a leading slash gets transformed into the rootdir value (which can be empty
797 * or NULL if you just want the slash to get dropped); (3) no "reldir" can be
798 * specified. */
799char *alloc_sanitize_path(const char *path, const char *rootdir)
800{
801 char *buf;
802 int rlen, plen = strlen(path);
803
b05b3c9b 804 if (*path == '/' && rootdir) {
14b61c63 805 rlen = strlen(rootdir);
b05b3c9b
WD
806 if (rlen == 1)
807 path++;
808 } else
14b61c63
WD
809 rlen = 0;
810 if (!(buf = new_array(char, rlen + plen + 1)))
811 out_of_memory("alloc_sanitize_path");
812 if (rlen)
813 memcpy(buf, rootdir, rlen);
814 memcpy(buf + rlen, path, plen + 1);
815
b05b3c9b 816 if (rlen > 1)
14b61c63
WD
817 rlen++;
818 sanitize_path(buf + rlen, NULL);
b05b3c9b
WD
819 if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
820 if (rlen > 1)
821 rlen--;
822 buf[rlen] = '\0';
823 }
14b61c63
WD
824
825 return buf;
826}
5243c216 827
4791825d 828char curr_dir[MAXPATHLEN];
4af8fe4e 829unsigned int curr_dir_len;
5243c216 830
4e5db0ad 831/**
a16d8f2b
WD
832 * Like chdir(), but it keeps track of the current directory (in the
833 * global "curr_dir"), and ensures that the path size doesn't overflow.
834 * Also cleans the path using the clean_fname() function.
4e5db0ad 835 **/
4af8fe4e 836int push_dir(char *dir)
5243c216 837{
5243c216 838 static int initialised;
4af8fe4e 839 unsigned int len;
5243c216
AT
840
841 if (!initialised) {
842 initialised = 1;
5cb37436 843 getcwd(curr_dir, sizeof curr_dir - 1);
4af8fe4e 844 curr_dir_len = strlen(curr_dir);
5243c216
AT
845 }
846
4af8fe4e
WD
847 if (!dir) /* this call was probably just to initialize */
848 return 0;
c226b7c2 849
4af8fe4e
WD
850 len = strlen(dir);
851 if (len == 1 && *dir == '.')
852 return 1;
5243c216 853
4af8fe4e
WD
854 if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir)
855 return 0;
856
857 if (chdir(dir))
858 return 0;
5243c216
AT
859
860 if (*dir == '/') {
4af8fe4e
WD
861 memcpy(curr_dir, dir, len + 1);
862 curr_dir_len = len;
863 } else {
864 curr_dir[curr_dir_len++] = '/';
865 memcpy(curr_dir + curr_dir_len, dir, len + 1);
866 curr_dir_len += len;
5243c216
AT
867 }
868
869 clean_fname(curr_dir);
870
4af8fe4e 871 return 1;
5243c216
AT
872}
873
a16d8f2b
WD
874/**
875 * Reverse a push_dir() call. You must pass in an absolute path
876 * that was copied from a prior value of "curr_dir".
877 **/
5243c216
AT
878int pop_dir(char *dir)
879{
4af8fe4e
WD
880 if (chdir(dir))
881 return 0;
5243c216 882
4af8fe4e
WD
883 curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
884 if (curr_dir_len >= sizeof curr_dir)
885 curr_dir_len = sizeof curr_dir - 1;
5243c216 886
4af8fe4e 887 return 1;
5243c216 888}
aa9b77a5 889
eb61be19
WD
890/**
891 * Return a quoted string with the full pathname of the indicated filename.
892 * The string " (in MODNAME)" may also be appended. The returned pointer
893 * remains valid until the next time full_fname() is called.
894 **/
9a5ade18 895char *full_fname(const char *fn)
eb61be19 896{
eb61be19
WD
897 static char *result = NULL;
898 char *m1, *m2, *m3;
899 char *p1, *p2;
900
901 if (result)
902 free(result);
903
904 if (*fn == '/')
905 p1 = p2 = "";
906 else {
907 p1 = curr_dir;
908 p2 = "/";
909 }
910 if (module_id >= 0) {
911 m1 = " (in ";
912 m2 = lp_name(module_id);
913 m3 = ")";
914 if (*p1) {
915 if (!lp_use_chroot(module_id)) {
916 char *p = lp_path(module_id);
917 if (*p != '/' || p[1])
918 p1 += strlen(p);
919 }
920 if (!*p1)
921 p2++;
922 else
923 p1++;
924 }
925 else
926 fn++;
927 } else
928 m1 = m2 = m3 = "";
929
930 asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3);
931
932 return result;
933}
934
ac13ad10 935/** We need to supply our own strcmp function for file list comparisons
aa9b77a5
AT
936 to ensure that signed/unsigned usage is consistent between machines. */
937int u_strcmp(const char *cs1, const char *cs2)
938{
5a788ade
AT
939 const uchar *s1 = (const uchar *)cs1;
940 const uchar *s2 = (const uchar *)cs2;
aa9b77a5
AT
941
942 while (*s1 && *s2 && (*s1 == *s2)) {
943 s1++; s2++;
944 }
5cb37436 945
aa9b77a5
AT
946 return (int)*s1 - (int)*s2;
947}
eb86d661 948
4b957c22 949
ac13ad10
MP
950
951/**
952 * Determine if a symlink points outside the current directory tree.
036e70b0
MP
953 * This is considered "unsafe" because e.g. when mirroring somebody
954 * else's machine it might allow them to establish a symlink to
955 * /etc/passwd, and then read it through a web server.
956 *
4e5db0ad
MP
957 * Null symlinks and absolute symlinks are always unsafe.
958 *
959 * Basically here we are concerned with symlinks whose target contains
960 * "..", because this might cause us to walk back up out of the
961 * transferred directory. We are not allowed to go back up and
962 * reenter.
963 *
036e70b0
MP
964 * @param dest Target of the symlink in question.
965 *
25d34a5c 966 * @param src Top source directory currently applicable. Basically this
036e70b0 967 * is the first parameter to rsync in a simple invocation, but it's
25d34a5c 968 * modified by flist.c in slightly complex ways.
036e70b0
MP
969 *
970 * @retval True if unsafe
971 * @retval False is unsafe
4e5db0ad
MP
972 *
973 * @sa t_unsafe.c
ac13ad10 974 **/
7afa3a4a 975int unsafe_symlink(const char *dest, const char *src)
4b957c22 976{
7afa3a4a 977 const char *name, *slash;
4b957c22
AT
978 int depth = 0;
979
980 /* all absolute and null symlinks are unsafe */
b5bd5542
WD
981 if (!dest || !*dest || *dest == '/')
982 return 1;
4b957c22
AT
983
984 /* find out what our safety margin is */
7afa3a4a
WD
985 for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
986 if (strncmp(name, "../", 3) == 0) {
c284f34a 987 depth = 0;
7afa3a4a 988 } else if (strncmp(name, "./", 2) == 0) {
4b957c22
AT
989 /* nothing */
990 } else {
991 depth++;
992 }
993 }
7afa3a4a
WD
994 if (strcmp(name, "..") == 0)
995 depth = 0;
4b957c22 996
7afa3a4a
WD
997 for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
998 if (strncmp(name, "../", 3) == 0) {
999 /* if at any point we go outside the current directory
1000 then stop - it is unsafe */
1001 if (--depth < 0)
1002 return 1;
1003 } else if (strncmp(name, "./", 2) == 0) {
4b957c22
AT
1004 /* nothing */
1005 } else {
1006 depth++;
1007 }
4b957c22 1008 }
7afa3a4a
WD
1009 if (strcmp(name, "..") == 0)
1010 depth--;
4b957c22 1011
4b957c22
AT
1012 return (depth < 0);
1013}
375a4556 1014
f7632fc6 1015
ac13ad10 1016/**
b4235b31
MP
1017 * Return the date and time as a string
1018 **/
f7632fc6
AT
1019char *timestring(time_t t)
1020{
1021 static char TimeBuf[200];
1022 struct tm *tm = localtime(&t);
1023
1024#ifdef HAVE_STRFTIME
5cb37436 1025 strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
f7632fc6 1026#else
5cb37436 1027 strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);
f7632fc6
AT
1028#endif
1029
1030 if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
1031 TimeBuf[strlen(TimeBuf)-1] = 0;
1032 }
1033
1034 return(TimeBuf);
1035}
1036
9ec16c83 1037
e1bd49d6
MP
1038/**
1039 * Sleep for a specified number of milliseconds.
1040 *
1041 * Always returns TRUE. (In the future it might return FALSE if
1042 * interrupted.)
1043 **/
1044int msleep(int t)
9ec16c83 1045{
c284f34a
WD
1046 int tdiff = 0;
1047 struct timeval tval, t1, t2;
9ec16c83
AT
1048
1049 gettimeofday(&t1, NULL);
5cb37436 1050
9ec16c83
AT
1051 while (tdiff < t) {
1052 tval.tv_sec = (t-tdiff)/1000;
1053 tval.tv_usec = 1000*((t-tdiff)%1000);
5cb37436 1054
9ec16c83
AT
1055 errno = 0;
1056 select(0,NULL,NULL, NULL, &tval);
1057
1058 gettimeofday(&t2, NULL);
5cb37436 1059 tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
9ec16c83
AT
1060 (t2.tv_usec - t1.tv_usec)/1000;
1061 }
e1bd49d6
MP
1062
1063 return True;
9ec16c83
AT
1064}
1065
1066
ac13ad10
MP
1067/**
1068 * Determine if two file modification times are equivalent (either
1069 * exact or in the modification timestamp window established by
1070 * --modify-window).
1071 *
1072 * @retval 0 if the times should be treated as the same
1073 *
1074 * @retval +1 if the first is later
1075 *
1076 * @retval -1 if the 2nd is later
1077 **/
5b56cc19
AT
1078int cmp_modtime(time_t file1, time_t file2)
1079{
5b56cc19 1080 if (file2 > file1) {
bc6ebcd2
WD
1081 if (file2 - file1 <= modify_window)
1082 return 0;
5b56cc19
AT
1083 return -1;
1084 }
bc6ebcd2
WD
1085 if (file1 - file2 <= modify_window)
1086 return 0;
5b56cc19
AT
1087 return 1;
1088}
1089
1090
1091#ifdef __INSURE__XX
0f8f98c8
AT
1092#include <dlfcn.h>
1093
ac13ad10
MP
1094/**
1095 This routine is a trick to immediately catch errors when debugging
1096 with insure. A xterm with a gdb is popped up when insure catches
1097 a error. It is Linux specific.
1098**/
0f8f98c8
AT
1099int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
1100{
1101 static int (*fn)();
1102 int ret;
8950ac03 1103 char *cmd;
0f8f98c8 1104
5cb37436 1105 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
1106 getpid(), getpid(), getpid());
1107
1108 if (!fn) {
1109 static void *h;
1110 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
1111 fn = dlsym(h, "_Insure_trap_error");
1112 }
1113
1114 ret = fn(a1, a2, a3, a4, a5, a6);
1115
1116 system(cmd);
1117
8950ac03
AT
1118 free(cmd);
1119
0f8f98c8
AT
1120 return ret;
1121}
1122#endif
58cadc86
WD
1123
1124
1125#define MALLOC_MAX 0x40000000
1126
1127void *_new_array(unsigned int size, unsigned long num)
1128{
1129 if (num >= MALLOC_MAX/size)
1130 return NULL;
1131 return malloc(size * num);
1132}
1133
1134void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
1135{
1136 if (num >= MALLOC_MAX/size)
1137 return NULL;
1138 /* No realloc should need this, but just in case... */
1139 if (!ptr)
1140 return malloc(size * num);
1141 return realloc(ptr, size * num);
1142}