* Make "make install-strip" works properly, and "make install"
[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
6dd41b67 87static void print_child_argv(char **cmd)
5ad0e46f 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
4cf64834 481/** Fork and record the pid of the child. **/
3ba62a83
AT
482pid_t do_fork(void)
483{
484 pid_t newpid = fork();
485
4cf64834 486 if (newpid != 0 && newpid != -1) {
3ba62a83
AT
487 all_pids[num_pids++] = newpid;
488 }
489 return newpid;
490}
491
4cf64834
MP
492/**
493 * Kill all children.
494 *
495 * @todo It would be kind of nice to make sure that they are actually
496 * all our children before we kill them, because their pids may have
497 * been recycled by some other process. Perhaps when we wait for a
498 * child, we should remove it from this array. Alternatively we could
499 * perhaps use process groups, but I think that would not work on
500 * ancient Unix versions that don't support them.
501 **/
3ba62a83
AT
502void kill_all(int sig)
503{
504 int i;
4cf64834
MP
505
506 for (i = 0; i < num_pids; i++) {
507 /* Let's just be a little careful where we
508 * point that gun, hey? See kill(2) for the
509 * magic caused by negative values. */
510 pid_t p = all_pids[i];
511
512 if (p == getpid())
513 continue;
514 if (p <= 0)
515 continue;
516
517 kill(p, sig);
3ba62a83
AT
518 }
519}
9486289c 520
4cf64834 521
8ef4ffd6
AT
522/* turn a user name into a uid */
523int name_to_uid(char *name, uid_t *uid)
524{
525 struct passwd *pass;
526 if (!name || !*name) return 0;
527 pass = getpwnam(name);
528 if (pass) {
529 *uid = pass->pw_uid;
530 return 1;
531 }
532 return 0;
533}
534
535/* turn a group name into a gid */
536int name_to_gid(char *name, gid_t *gid)
537{
538 struct group *grp;
539 if (!name || !*name) return 0;
540 grp = getgrnam(name);
541 if (grp) {
542 *gid = grp->gr_gid;
543 return 1;
544 }
545 return 0;
546}
547
ff8b29b8 548
31593dd6
AT
549/* lock a byte range in a open file */
550int lock_range(int fd, int offset, int len)
0c515f17 551{
31593dd6 552 struct flock lock;
0c515f17 553
31593dd6
AT
554 lock.l_type = F_WRLCK;
555 lock.l_whence = SEEK_SET;
556 lock.l_start = offset;
557 lock.l_len = len;
558 lock.l_pid = 0;
559
560 return fcntl(fd,F_SETLK,&lock) == 0;
0c515f17 561}
874895d5
AT
562
563
cb13abfe 564static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
874895d5 565{
932be9aa 566#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
e42c9458 567 if (!*s) s = ".";
087bf010 568 argv[*argc] = strdup(s);
874895d5
AT
569 (*argc)++;
570 return;
571#else
cb13abfe 572 extern int sanitize_paths;
874895d5
AT
573 glob_t globbuf;
574 int i;
575
e42c9458
AT
576 if (!*s) s = ".";
577
cb13abfe
DD
578 argv[*argc] = strdup(s);
579 if (sanitize_paths) {
580 sanitize_path(argv[*argc], NULL);
581 }
087bf010 582
874895d5
AT
583 memset(&globbuf, 0, sizeof(globbuf));
584 glob(argv[*argc], 0, NULL, &globbuf);
585 if (globbuf.gl_pathc == 0) {
586 (*argc)++;
587 globfree(&globbuf);
588 return;
589 }
a261989c 590 for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
874895d5
AT
591 if (i == 0) free(argv[*argc]);
592 argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
593 if (!argv[(*argc) + i]) out_of_memory("glob_expand");
594 }
595 globfree(&globbuf);
596 (*argc) += i;
597#endif
598}
5a96ee05 599
cb13abfe 600void glob_expand(char *base1, char **argv, int *argc, int maxargs)
087bf010
AT
601{
602 char *s = argv[*argc];
603 char *p, *q;
ba5e128d 604 char *base = base1;
087bf010
AT
605
606 if (!s || !*s) return;
607
e42c9458
AT
608 if (strncmp(s, base, strlen(base)) == 0) {
609 s += strlen(base);
610 }
611
087bf010
AT
612 s = strdup(s);
613 if (!s) out_of_memory("glob_expand");
614
8950ac03 615 if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
ba5e128d 616
087bf010
AT
617 q = s;
618 while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
ba5e128d
AT
619 /* split it at this point */
620 *p = 0;
cb13abfe 621 glob_expand_one(q, argv, argc, maxargs);
ba5e128d 622 q = p+strlen(base);
087bf010
AT
623 }
624
cb13abfe 625 if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
087bf010
AT
626
627 free(s);
ba5e128d 628 free(base);
087bf010 629}
5a96ee05
AT
630
631/*******************************************************************
632 convert a string to lower case
633********************************************************************/
634void strlower(char *s)
635{
636 while (*s) {
637 if (isupper(*s)) *s = tolower(*s);
638 s++;
639 }
640}
e42c9458 641
fe8c0a98
AT
642void *Realloc(void *p, int size)
643{
644 if (!p) return (void *)malloc(size);
645 return (void *)realloc(p, size);
646}
5243c216
AT
647
648
649void clean_fname(char *name)
650{
651 char *p;
652 int l;
653 int modified = 1;
654
655 if (!name) return;
656
657 while (modified) {
658 modified = 0;
659
660 if ((p=strstr(name,"/./"))) {
661 modified = 1;
662 while (*p) {
663 p[0] = p[2];
664 p++;
665 }
666 }
667
668 if ((p=strstr(name,"//"))) {
669 modified = 1;
670 while (*p) {
671 p[0] = p[1];
672 p++;
673 }
674 }
675
676 if (strncmp(p=name,"./",2) == 0) {
677 modified = 1;
678 do {
679 p[0] = p[2];
680 } while (*p++);
681 }
682
683 l = strlen(p=name);
684 if (l > 1 && p[l-1] == '/') {
685 modified = 1;
686 p[l-1] = 0;
687 }
688 }
689}
690
1b8e662a
DD
691/*
692 * Make path appear as if a chroot had occurred:
1b8e662a 693 * 1. remove leading "/" (or replace with "." if at end)
cb13abfe 694 * 2. remove leading ".." components (except those allowed by "reldir")
1b8e662a 695 * 3. delete any other "<dir>/.." (recursively)
79452d46 696 * Can only shrink paths, so sanitizes in place.
b5f9e67d
DD
697 * While we're at it, remove double slashes and "." components like
698 * clean_fname does(), but DON'T remove a trailing slash because that
699 * is sometimes significant on command line arguments.
79452d46
DD
700 * If "reldir" is non-null, it is a sanitized directory that the path will be
701 * relative to, so allow as many ".." at the beginning of the path as
702 * there are components in reldir. This is used for symbolic link targets.
703 * If reldir is non-null and the path began with "/", to be completely like
704 * a chroot we should add in depth levels of ".." at the beginning of the
705 * path, but that would blow the assumption that the path doesn't grow and
706 * it is not likely to end up being a valid symlink anyway, so just do
707 * the normal removal of the leading "/" instead.
1b8e662a
DD
708 * Contributed by Dave Dykstra <dwd@bell-labs.com>
709 */
710
cb13abfe 711void sanitize_path(char *p, char *reldir)
1b8e662a 712{
44e2e578 713 char *start, *sanp;
cb13abfe
DD
714 int depth = 0;
715 int allowdotdot = 0;
716
717 if (reldir) {
718 depth++;
719 while (*reldir) {
720 if (*reldir++ == '/') {
721 depth++;
722 }
723 }
724 }
44e2e578
DD
725 start = p;
726 sanp = p;
b5f9e67d
DD
727 while (*p == '/') {
728 /* remove leading slashes */
729 p++;
730 }
1b8e662a 731 while (*p != '\0') {
b5f9e67d 732 /* this loop iterates once per filename component in p.
44e2e578 733 * both p (and sanp if the original had a slash) should
b5f9e67d
DD
734 * always be left pointing after a slash
735 */
736 if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
737 /* skip "." component */
738 while (*++p == '/') {
739 /* skip following slashes */
740 ;
741 }
cb13abfe
DD
742 continue;
743 }
744 allowdotdot = 0;
745 if ((*p == '.') && (*(p+1) == '.') &&
1b8e662a 746 ((*(p+2) == '/') || (*(p+2) == '\0'))) {
cb13abfe
DD
747 /* ".." component followed by slash or end */
748 if ((depth > 0) && (sanp == start)) {
749 /* allow depth levels of .. at the beginning */
750 --depth;
751 allowdotdot = 1;
752 } else {
753 p += 2;
754 if (*p == '/')
755 p++;
756 if (sanp != start) {
757 /* back up sanp one level */
758 --sanp; /* now pointing at slash */
759 while ((sanp > start) && (*(sanp - 1) != '/')) {
760 /* skip back up to slash */
761 sanp--;
762 }
b5f9e67d 763 }
cb13abfe 764 continue;
1b8e662a 765 }
cb13abfe
DD
766 }
767 while (1) {
768 /* copy one component through next slash */
769 *sanp++ = *p++;
770 if ((*p == '\0') || (*(p-1) == '/')) {
771 while (*p == '/') {
772 /* skip multiple slashes */
773 p++;
b5f9e67d 774 }
cb13abfe 775 break;
1b8e662a
DD
776 }
777 }
cb13abfe
DD
778 if (allowdotdot) {
779 /* move the virtual beginning to leave the .. alone */
780 start = sanp;
781 }
1b8e662a 782 }
cb13abfe 783 if ((sanp == start) && !allowdotdot) {
b5f9e67d 784 /* ended up with nothing, so put in "." component */
79452d46
DD
785 /*
786 * note that the !allowdotdot doesn't prevent this from
787 * happening in all allowed ".." situations, but I didn't
788 * think it was worth putting in an extra variable to ensure
789 * it since an extra "." won't hurt in those situations.
790 */
44e2e578 791 *sanp++ = '.';
b5f9e67d 792 }
44e2e578 793 *sanp = '\0';
1b8e662a
DD
794}
795
5243c216
AT
796
797static char curr_dir[MAXPATHLEN];
798
799/* like chdir() but can be reversed with pop_dir() if save is set. It
800 is also much faster as it remembers where we have been */
801char *push_dir(char *dir, int save)
802{
803 char *ret = curr_dir;
804 static int initialised;
805
806 if (!initialised) {
807 initialised = 1;
808 getcwd(curr_dir, sizeof(curr_dir)-1);
809 }
810
c226b7c2
DD
811 if (!dir) return NULL; /* this call was probably just to initialize */
812
5243c216
AT
813 if (chdir(dir)) return NULL;
814
815 if (save) {
816 ret = strdup(curr_dir);
817 }
818
819 if (*dir == '/') {
37f9805d 820 strlcpy(curr_dir, dir, sizeof(curr_dir));
5243c216 821 } else {
37f9805d
AT
822 strlcat(curr_dir,"/", sizeof(curr_dir));
823 strlcat(curr_dir,dir, sizeof(curr_dir));
5243c216
AT
824 }
825
826 clean_fname(curr_dir);
827
828 return ret;
829}
830
831/* reverse a push_dir call */
832int pop_dir(char *dir)
833{
834 int ret;
835
836 ret = chdir(dir);
837 if (ret) {
838 free(dir);
839 return ret;
840 }
841
37f9805d 842 strlcpy(curr_dir, dir, sizeof(curr_dir));
5243c216
AT
843
844 free(dir);
845
846 return 0;
847}
aa9b77a5
AT
848
849/* we need to supply our own strcmp function for file list comparisons
850 to ensure that signed/unsigned usage is consistent between machines. */
851int u_strcmp(const char *cs1, const char *cs2)
852{
5a788ade
AT
853 const uchar *s1 = (const uchar *)cs1;
854 const uchar *s2 = (const uchar *)cs2;
aa9b77a5
AT
855
856 while (*s1 && *s2 && (*s1 == *s2)) {
857 s1++; s2++;
858 }
859
860 return (int)*s1 - (int)*s2;
861}
eb86d661 862
47f1218d
MP
863static OFF_T last_ofs;
864static struct timeval print_time;
865static struct timeval start_time;
866static OFF_T start_ofs;
867
868static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
869{
870 return (t2->tv_sec - t1->tv_sec) * 1000
871 + (t2->tv_usec - t1->tv_usec) / 1000;
872}
873
874
875/**
6066594b
MP
876 * @param ofs Current position in file
877 * @param size Total size of file
47f1218d
MP
878 * @param is_last True if this is the last time progress will be
879 * printed for this file, so we should output a newline. (Not
880 * necessarily the same as all bytes being received.)
881 **/
882static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
883 int is_last)
884{
62791bdf 885 int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
47f1218d 886 unsigned long diff = msdiff(&start_time, now);
f9c3005b 887 double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
a9b31409 888 const char *units;
c579310a
MP
889 /* If we've finished transferring this file, show the time taken;
890 * otherwise show expected time to complete. That's kind of
891 * inconsistent, but people can probably cope. Hopefully we'll
892 * get more consistent and complete progress reporting soon. --
893 * mbp */
894 double remain = is_last
895 ? (double) diff / 1000.0
896 : rate ? (double) (size-ofs) / rate / 1000.0 : 0.0;
7007bdda 897 int remain_h, remain_m, remain_s;
47f1218d 898
47f1218d
MP
899 if (rate > 1024*1024) {
900 rate /= 1024.0 * 1024.0;
901 units = "GB/s";
902 } else if (rate > 1024) {
903 rate /= 1024.0;
904 units = "MB/s";
905 } else {
906 units = "kB/s";
907 }
62791bdf 908
7007bdda
MP
909 remain_s = (int) remain % 60;
910 remain_m = (int) (remain / 60.0) % 60;
911 remain_h = (int) (remain / 3600.0);
47f1218d 912
7007bdda 913 rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
47f1218d 914 (double) ofs, pct, rate, units,
7007bdda 915 remain_h, remain_m, remain_s,
47f1218d
MP
916 is_last ? "\n" : "\r");
917}
eb86d661 918
166aa723 919void end_progress(OFF_T size)
eb86d661
AT
920{
921 extern int do_progress, am_server;
922
923 if (do_progress && !am_server) {
47f1218d
MP
924 struct timeval now;
925 gettimeofday(&now, NULL);
926 rprint_progress(size, size, &now, True);
927 }
928 last_ofs = 0;
929 start_ofs = 0;
930 print_time.tv_sec = print_time.tv_usec = 0;
931 start_time.tv_sec = start_time.tv_usec = 0;
eb86d661
AT
932}
933
934void show_progress(OFF_T ofs, OFF_T size)
935{
936 extern int do_progress, am_server;
47f1218d
MP
937 struct timeval now;
938
939 gettimeofday(&now, NULL);
940
941 if (!start_time.tv_sec && !start_time.tv_usec) {
942 start_time.tv_sec = now.tv_sec;
943 start_time.tv_usec = now.tv_usec;
944 start_ofs = ofs;
945 }
946
947 if (do_progress
948 && !am_server
949 && ofs > last_ofs + 1000
950 && msdiff(&print_time, &now) > 250) {
951 rprint_progress(ofs, size, &now, False);
952 last_ofs = ofs;
953 print_time.tv_sec = now.tv_sec;
954 print_time.tv_usec = now.tv_usec;
eb86d661
AT
955 }
956}
4b957c22
AT
957
958/* determine if a symlink points outside the current directory tree */
959int unsafe_symlink(char *dest, char *src)
960{
961 char *tok;
962 int depth = 0;
963
964 /* all absolute and null symlinks are unsafe */
965 if (!dest || !(*dest) || (*dest == '/')) return 1;
966
967 src = strdup(src);
968 if (!src) out_of_memory("unsafe_symlink");
969
970 /* find out what our safety margin is */
971 for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
972 if (strcmp(tok,"..") == 0) {
973 depth=0;
974 } else if (strcmp(tok,".") == 0) {
975 /* nothing */
976 } else {
977 depth++;
978 }
979 }
980 free(src);
981
982 /* drop by one to account for the filename portion */
983 depth--;
984
985 dest = strdup(dest);
986 if (!dest) out_of_memory("unsafe_symlink");
987
988 for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
989 if (strcmp(tok,"..") == 0) {
990 depth--;
991 } else if (strcmp(tok,".") == 0) {
992 /* nothing */
993 } else {
994 depth++;
995 }
996 /* if at any point we go outside the current directory then
997 stop - it is unsafe */
998 if (depth < 0) break;
999 }
1000
1001 free(dest);
1002 return (depth < 0);
1003}
375a4556 1004
f7632fc6
AT
1005
1006/****************************************************************************
1007 return the date and time as a string
1008****************************************************************************/
1009char *timestring(time_t t)
1010{
1011 static char TimeBuf[200];
1012 struct tm *tm = localtime(&t);
1013
1014#ifdef HAVE_STRFTIME
1015 strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
1016#else
37f9805d 1017 strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
f7632fc6
AT
1018#endif
1019
1020 if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
1021 TimeBuf[strlen(TimeBuf)-1] = 0;
1022 }
1023
1024 return(TimeBuf);
1025}
1026
9ec16c83 1027
e1bd49d6
MP
1028/**
1029 * Sleep for a specified number of milliseconds.
1030 *
1031 * Always returns TRUE. (In the future it might return FALSE if
1032 * interrupted.)
1033 **/
1034int msleep(int t)
9ec16c83
AT
1035{
1036 int tdiff=0;
1037 struct timeval tval,t1,t2;
1038
1039 gettimeofday(&t1, NULL);
1040 gettimeofday(&t2, NULL);
1041
1042 while (tdiff < t) {
1043 tval.tv_sec = (t-tdiff)/1000;
1044 tval.tv_usec = 1000*((t-tdiff)%1000);
1045
1046 errno = 0;
1047 select(0,NULL,NULL, NULL, &tval);
1048
1049 gettimeofday(&t2, NULL);
1050 tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
1051 (t2.tv_usec - t1.tv_usec)/1000;
1052 }
e1bd49d6
MP
1053
1054 return True;
9ec16c83
AT
1055}
1056
1057
5b56cc19
AT
1058/*******************************************************************
1059 Determine if two file modification times are equivalent (either exact
1060 or in the modification timestamp window established by --modify-window)
1061 Returns 0 if the times should be treated as the same, 1 if the
1062 first is later and -1 if the 2nd is later
1063 *******************************************************************/
1064int cmp_modtime(time_t file1, time_t file2)
1065{
5b56cc19
AT
1066 extern int modify_window;
1067
1068 if (file2 > file1) {
1069 if (file2 - file1 <= modify_window) return 0;
1070 return -1;
1071 }
1072 if (file1 - file2 <= modify_window) return 0;
1073 return 1;
1074}
1075
1076
1077#ifdef __INSURE__XX
0f8f98c8
AT
1078#include <dlfcn.h>
1079
1080/*******************************************************************
1081This routine is a trick to immediately catch errors when debugging
1082with insure. A xterm with a gdb is popped up when insure catches
1083a error. It is Linux specific.
1084********************************************************************/
1085int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
1086{
1087 static int (*fn)();
1088 int ret;
8950ac03 1089 char *cmd;
0f8f98c8 1090
8950ac03 1091 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
1092 getpid(), getpid(), getpid());
1093
1094 if (!fn) {
1095 static void *h;
1096 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
1097 fn = dlsym(h, "_Insure_trap_error");
1098 }
1099
1100 ret = fn(a1, a2, a3, a4, a5, a6);
1101
1102 system(cmd);
1103
8950ac03
AT
1104 free(cmd);
1105
0f8f98c8
AT
1106 return ret;
1107}
1108#endif