One more attempt to get HP-UX's cc to build popt successfully.
[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 (!*s) s = ".";
503 s = argv[*argc] = strdup(s);
504 exclude_server_path(s);
505 (*argc)++;
506#else
507 extern int sanitize_paths;
508 glob_t globbuf;
509 int i;
510
511 if (!*s) s = ".";
512
513 s = argv[*argc] = strdup(s);
514 if (sanitize_paths) {
515 sanitize_path(s, NULL);
516 }
517
518 memset(&globbuf, 0, sizeof globbuf);
519 if (!exclude_server_path(s))
520 glob(s, 0, NULL, &globbuf);
521 if (globbuf.gl_pathc == 0) {
522 (*argc)++;
523 globfree(&globbuf);
524 return;
525 }
526 for (i = 0; i < maxargs - *argc && i < (int)globbuf.gl_pathc; i++) {
527 if (i == 0)
528 free(s);
529 argv[*argc + i] = strdup(globbuf.gl_pathv[i]);
530 if (!argv[*argc + i])
531 out_of_memory("glob_expand");
532 }
533 globfree(&globbuf);
534 *argc += i;
535#endif
536}
537
538/* This routine is only used in daemon mode. */
539void glob_expand(char *base1, char **argv, int *argc, int maxargs)
540{
541 char *s = argv[*argc];
542 char *p, *q;
543 char *base = base1;
544 int base_len = strlen(base);
545
546 if (!s || !*s) return;
547
548 if (strncmp(s, base, base_len) == 0)
549 s += base_len;
550
551 s = strdup(s);
552 if (!s) out_of_memory("glob_expand");
553
554 if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
555 base_len++;
556
557 q = s;
558 while ((p = strstr(q,base)) != NULL && *argc < maxargs) {
559 /* split it at this point */
560 *p = 0;
561 glob_expand_one(q, argv, argc, maxargs);
562 q = p + base_len;
563 }
564
565 if (*q && *argc < maxargs)
566 glob_expand_one(q, argv, argc, maxargs);
567
568 free(s);
569 free(base);
570}
571
572/**
573 * Convert a string to lower case
574 **/
575void strlower(char *s)
576{
577 while (*s) {
578 if (isupper(* (unsigned char *) s))
579 *s = tolower(* (unsigned char *) s);
580 s++;
581 }
582}
583
584/* Join strings p1 & p2 into "dest" with a guaranteed '/' between them. (If
585 * p1 ends with a '/', no extra '/' is inserted.) Returns the length of both
586 * strings + 1 (if '/' was inserted), regardless of whether the null-terminated
587 * string fits into destsize. */
588size_t pathjoin(char *dest, size_t destsize, const char *p1, const char *p2)
589{
590 size_t len = strlcpy(dest, p1, destsize);
591 if (len < destsize - 1) {
592 if (!len || dest[len-1] != '/')
593 dest[len++] = '/';
594 if (len < destsize - 1)
595 len += strlcpy(dest + len, p2, destsize - len);
596 else {
597 dest[len] = '\0';
598 len += strlen(p2);
599 }
600 }
601 else
602 len += strlen(p2) + 1; /* Assume we'd insert a '/'. */
603 return len;
604}
605
606/* Join any number of strings together, putting them in "dest". The return
607 * value is the length of all the strings, regardless of whether the null-
608 * terminated whole fits in destsize. Your list of string pointers must end
609 * with a NULL to indicate the end of the list. */
610size_t stringjoin(char *dest, size_t destsize, ...)
611{
612 va_list ap;
613 size_t len, ret = 0;
614 const char *src;
615
616 va_start(ap, destsize);
617 while (1) {
618 if (!(src = va_arg(ap, const char *)))
619 break;
620 len = strlen(src);
621 ret += len;
622 if (destsize > 1) {
623 if (len >= destsize)
624 len = destsize - 1;
625 memcpy(dest, src, len);
626 destsize -= len;
627 dest += len;
628 }
629 }
630 *dest = '\0';
631 va_end(ap);
632
633 return ret;
634}
635
636void clean_fname(char *name)
637{
638 char *p;
639 int l;
640 int modified = 1;
641
642 if (!name) return;
643
644 while (modified) {
645 modified = 0;
646
647 if ((p = strstr(name,"/./")) != NULL) {
648 modified = 1;
649 while (*p) {
650 p[0] = p[2];
651 p++;
652 }
653 }
654
655 if ((p = strstr(name,"//")) != NULL) {
656 modified = 1;
657 while (*p) {
658 p[0] = p[1];
659 p++;
660 }
661 }
662
663 if (strncmp(p = name, "./", 2) == 0) {
664 modified = 1;
665 do {
666 p[0] = p[2];
667 } while (*p++);
668 }
669
670 l = strlen(p = name);
671 if (l > 1 && p[l-1] == '/') {
672 modified = 1;
673 p[l-1] = 0;
674 }
675 }
676}
677
678/**
679 * Make path appear as if a chroot had occurred:
680 *
681 * @li 1. remove leading "/" (or replace with "." if at end)
682 *
683 * @li 2. remove leading ".." components (except those allowed by @p reldir)
684 *
685 * @li 3. delete any other "<dir>/.." (recursively)
686 *
687 * Can only shrink paths, so sanitizes in place.
688 *
689 * While we're at it, remove double slashes and "." components like
690 * clean_fname() does, but DON'T remove a trailing slash because that
691 * is sometimes significant on command line arguments.
692 *
693 * If @p reldir is non-null, it is a sanitized directory that the path will be
694 * relative to, so allow as many ".." at the beginning of the path as
695 * there are components in reldir. This is used for symbolic link targets.
696 * If reldir is non-null and the path began with "/", to be completely like
697 * a chroot we should add in depth levels of ".." at the beginning of the
698 * path, but that would blow the assumption that the path doesn't grow and
699 * it is not likely to end up being a valid symlink anyway, so just do
700 * the normal removal of the leading "/" instead.
701 *
702 * Contributed by Dave Dykstra <dwd@bell-labs.com>
703 */
704void sanitize_path(char *p, char *reldir)
705{
706 char *start, *sanp;
707 int depth = 0;
708 int allowdotdot = 0;
709
710 if (reldir) {
711 depth++;
712 while (*reldir) {
713 if (*reldir++ == '/') {
714 depth++;
715 }
716 }
717 }
718 start = p;
719 sanp = p;
720 while (*p == '/') {
721 /* remove leading slashes */
722 p++;
723 }
724 while (*p != '\0') {
725 /* this loop iterates once per filename component in p.
726 * both p (and sanp if the original had a slash) should
727 * always be left pointing after a slash
728 */
729 if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
730 /* skip "." component */
731 while (*++p == '/') {
732 /* skip following slashes */
733 ;
734 }
735 continue;
736 }
737 allowdotdot = 0;
738 if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
739 /* ".." component followed by slash or end */
740 if (depth > 0 && sanp == start) {
741 /* allow depth levels of .. at the beginning */
742 --depth;
743 allowdotdot = 1;
744 } else {
745 p += 2;
746 if (*p == '/')
747 p++;
748 if (sanp != start) {
749 /* back up sanp one level */
750 --sanp; /* now pointing at slash */
751 while (sanp > start && sanp[-1] != '/') {
752 /* skip back up to slash */
753 sanp--;
754 }
755 }
756 continue;
757 }
758 }
759 while (1) {
760 /* copy one component through next slash */
761 *sanp++ = *p++;
762 if (*p == '\0' || p[-1] == '/') {
763 while (*p == '/') {
764 /* skip multiple slashes */
765 p++;
766 }
767 break;
768 }
769 }
770 if (allowdotdot) {
771 /* move the virtual beginning to leave the .. alone */
772 start = sanp;
773 }
774 }
775 if (sanp == start && !allowdotdot) {
776 /* ended up with nothing, so put in "." component */
777 /*
778 * note that the !allowdotdot doesn't prevent this from
779 * happening in all allowed ".." situations, but I didn't
780 * think it was worth putting in an extra variable to ensure
781 * it since an extra "." won't hurt in those situations.
782 */
783 *sanp++ = '.';
784 }
785 *sanp = '\0';
786}
787
788/* Works much like sanitize_path(), with these differences: (1) a new buffer
789 * is allocated for the sanitized path rather than modifying it in-place; (2)
790 * a leading slash gets transformed into the rootdir value (which can be empty
791 * or NULL if you just want the slash to get dropped); (3) no "reldir" can be
792 * specified. */
793char *alloc_sanitize_path(const char *path, const char *rootdir)
794{
795 char *buf;
796 int rlen, plen = strlen(path);
797
798 if (*path == '/' && rootdir) {
799 rlen = strlen(rootdir);
800 if (rlen == 1)
801 path++;
802 } else
803 rlen = 0;
804 if (!(buf = new_array(char, rlen + plen + 1)))
805 out_of_memory("alloc_sanitize_path");
806 if (rlen)
807 memcpy(buf, rootdir, rlen);
808 memcpy(buf + rlen, path, plen + 1);
809
810 if (rlen > 1)
811 rlen++;
812 sanitize_path(buf + rlen, NULL);
813 if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
814 if (rlen > 1)
815 rlen--;
816 buf[rlen] = '\0';
817 }
818
819 return buf;
820}
821
822char curr_dir[MAXPATHLEN];
823unsigned int curr_dir_len;
824
825/**
826 * Like chdir(), but it keeps track of the current directory (in the
827 * global "curr_dir"), and ensures that the path size doesn't overflow.
828 * Also cleans the path using the clean_fname() function.
829 **/
830int push_dir(char *dir)
831{
832 static int initialised;
833 unsigned int len;
834
835 if (!initialised) {
836 initialised = 1;
837 getcwd(curr_dir, sizeof curr_dir - 1);
838 curr_dir_len = strlen(curr_dir);
839 }
840
841 if (!dir) /* this call was probably just to initialize */
842 return 0;
843
844 len = strlen(dir);
845 if (len == 1 && *dir == '.')
846 return 1;
847
848 if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir)
849 return 0;
850
851 if (chdir(dir))
852 return 0;
853
854 if (*dir == '/') {
855 memcpy(curr_dir, dir, len + 1);
856 curr_dir_len = len;
857 } else {
858 curr_dir[curr_dir_len++] = '/';
859 memcpy(curr_dir + curr_dir_len, dir, len + 1);
860 curr_dir_len += len;
861 }
862
863 clean_fname(curr_dir);
864
865 return 1;
866}
867
868/**
869 * Reverse a push_dir() call. You must pass in an absolute path
870 * that was copied from a prior value of "curr_dir".
871 **/
872int pop_dir(char *dir)
873{
874 if (chdir(dir))
875 return 0;
876
877 curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
878 if (curr_dir_len >= sizeof curr_dir)
879 curr_dir_len = sizeof curr_dir - 1;
880
881 return 1;
882}
883
884/**
885 * Return a quoted string with the full pathname of the indicated filename.
886 * The string " (in MODNAME)" may also be appended. The returned pointer
887 * remains valid until the next time full_fname() is called.
888 **/
889char *full_fname(char *fn)
890{
891 extern int module_id;
892 static char *result = NULL;
893 char *m1, *m2, *m3;
894 char *p1, *p2;
895
896 if (result)
897 free(result);
898
899 if (*fn == '/')
900 p1 = p2 = "";
901 else {
902 p1 = curr_dir;
903 p2 = "/";
904 }
905 if (module_id >= 0) {
906 m1 = " (in ";
907 m2 = lp_name(module_id);
908 m3 = ")";
909 if (*p1) {
910 if (!lp_use_chroot(module_id)) {
911 char *p = lp_path(module_id);
912 if (*p != '/' || p[1])
913 p1 += strlen(p);
914 }
915 if (!*p1)
916 p2++;
917 else
918 p1++;
919 }
920 else
921 fn++;
922 } else
923 m1 = m2 = m3 = "";
924
925 asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3);
926
927 return result;
928}
929
930/** We need to supply our own strcmp function for file list comparisons
931 to ensure that signed/unsigned usage is consistent between machines. */
932int u_strcmp(const char *cs1, const char *cs2)
933{
934 const uchar *s1 = (const uchar *)cs1;
935 const uchar *s2 = (const uchar *)cs2;
936
937 while (*s1 && *s2 && (*s1 == *s2)) {
938 s1++; s2++;
939 }
940
941 return (int)*s1 - (int)*s2;
942}
943
944
945
946/**
947 * Determine if a symlink points outside the current directory tree.
948 * This is considered "unsafe" because e.g. when mirroring somebody
949 * else's machine it might allow them to establish a symlink to
950 * /etc/passwd, and then read it through a web server.
951 *
952 * Null symlinks and absolute symlinks are always unsafe.
953 *
954 * Basically here we are concerned with symlinks whose target contains
955 * "..", because this might cause us to walk back up out of the
956 * transferred directory. We are not allowed to go back up and
957 * reenter.
958 *
959 * @param dest Target of the symlink in question.
960 *
961 * @param src Top source directory currently applicable. Basically this
962 * is the first parameter to rsync in a simple invocation, but it's
963 * modified by flist.c in slightly complex ways.
964 *
965 * @retval True if unsafe
966 * @retval False is unsafe
967 *
968 * @sa t_unsafe.c
969 **/
970int unsafe_symlink(const char *dest, const char *src)
971{
972 const char *name, *slash;
973 int depth = 0;
974
975 /* all absolute and null symlinks are unsafe */
976 if (!dest || !*dest || *dest == '/') return 1;
977
978 /* find out what our safety margin is */
979 for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
980 if (strncmp(name, "../", 3) == 0) {
981 depth = 0;
982 } else if (strncmp(name, "./", 2) == 0) {
983 /* nothing */
984 } else {
985 depth++;
986 }
987 }
988 if (strcmp(name, "..") == 0)
989 depth = 0;
990
991 for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
992 if (strncmp(name, "../", 3) == 0) {
993 /* if at any point we go outside the current directory
994 then stop - it is unsafe */
995 if (--depth < 0)
996 return 1;
997 } else if (strncmp(name, "./", 2) == 0) {
998 /* nothing */
999 } else {
1000 depth++;
1001 }
1002 }
1003 if (strcmp(name, "..") == 0)
1004 depth--;
1005
1006 return (depth < 0);
1007}
1008
1009
1010/**
1011 * Return the date and time as a string
1012 **/
1013char *timestring(time_t t)
1014{
1015 static char TimeBuf[200];
1016 struct tm *tm = localtime(&t);
1017
1018#ifdef HAVE_STRFTIME
1019 strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
1020#else
1021 strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);
1022#endif
1023
1024 if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
1025 TimeBuf[strlen(TimeBuf)-1] = 0;
1026 }
1027
1028 return(TimeBuf);
1029}
1030
1031
1032/**
1033 * Sleep for a specified number of milliseconds.
1034 *
1035 * Always returns TRUE. (In the future it might return FALSE if
1036 * interrupted.)
1037 **/
1038int msleep(int t)
1039{
1040 int tdiff = 0;
1041 struct timeval tval, t1, t2;
1042
1043 gettimeofday(&t1, NULL);
1044 gettimeofday(&t2, NULL);
1045
1046 while (tdiff < t) {
1047 tval.tv_sec = (t-tdiff)/1000;
1048 tval.tv_usec = 1000*((t-tdiff)%1000);
1049
1050 errno = 0;
1051 select(0,NULL,NULL, NULL, &tval);
1052
1053 gettimeofday(&t2, NULL);
1054 tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
1055 (t2.tv_usec - t1.tv_usec)/1000;
1056 }
1057
1058 return True;
1059}
1060
1061
1062/**
1063 * Determine if two file modification times are equivalent (either
1064 * exact or in the modification timestamp window established by
1065 * --modify-window).
1066 *
1067 * @retval 0 if the times should be treated as the same
1068 *
1069 * @retval +1 if the first is later
1070 *
1071 * @retval -1 if the 2nd is later
1072 **/
1073int cmp_modtime(time_t file1, time_t file2)
1074{
1075 extern int modify_window;
1076
1077 if (file2 > file1) {
1078 if (file2 - file1 <= modify_window) return 0;
1079 return -1;
1080 }
1081 if (file1 - file2 <= modify_window) return 0;
1082 return 1;
1083}
1084
1085
1086#ifdef __INSURE__XX
1087#include <dlfcn.h>
1088
1089/**
1090 This routine is a trick to immediately catch errors when debugging
1091 with insure. A xterm with a gdb is popped up when insure catches
1092 a error. It is Linux specific.
1093**/
1094int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
1095{
1096 static int (*fn)();
1097 int ret;
1098 char *cmd;
1099
1100 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'",
1101 getpid(), getpid(), getpid());
1102
1103 if (!fn) {
1104 static void *h;
1105 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
1106 fn = dlsym(h, "_Insure_trap_error");
1107 }
1108
1109 ret = fn(a1, a2, a3, a4, a5, a6);
1110
1111 system(cmd);
1112
1113 free(cmd);
1114
1115 return ret;
1116}
1117#endif
1118
1119
1120#define MALLOC_MAX 0x40000000
1121
1122void *_new_array(unsigned int size, unsigned long num)
1123{
1124 if (num >= MALLOC_MAX/size)
1125 return NULL;
1126 return malloc(size * num);
1127}
1128
1129void *_realloc_array(void *ptr, unsigned int size, unsigned long num)
1130{
1131 if (num >= MALLOC_MAX/size)
1132 return NULL;
1133 /* No realloc should need this, but just in case... */
1134 if (!ptr)
1135 return malloc(size * num);
1136 return realloc(ptr, size * num);
1137}