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