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