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