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