File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / util.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    1: /*
    2:  * Utility routines used in rsync.
    3:  *
    4:  * Copyright (C) 1996-2000 Andrew Tridgell
    5:  * Copyright (C) 1996 Paul Mackerras
    6:  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
    7:  * Copyright (C) 2003-2020 Wayne Davison
    8:  *
    9:  * This program is free software; you can redistribute it and/or modify
   10:  * it under the terms of the GNU General Public License as published by
   11:  * the Free Software Foundation; either version 3 of the License, or
   12:  * (at your option) any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,
   15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:  * GNU General Public License for more details.
   18:  *
   19:  * You should have received a copy of the GNU General Public License along
   20:  * with this program; if not, visit the http://fsf.org website.
   21:  */
   22: 
   23: #include "rsync.h"
   24: #include "ifuncs.h"
   25: #include "itypes.h"
   26: #include "inums.h"
   27: 
   28: extern int dry_run;
   29: extern int module_id;
   30: extern int do_fsync;
   31: extern int protect_args;
   32: extern int modify_window;
   33: extern int relative_paths;
   34: extern int preserve_times;
   35: extern int preserve_xattrs;
   36: extern int preallocate_files;
   37: extern int force_change;
   38: extern char *module_dir;
   39: extern unsigned int module_dirlen;
   40: extern char *partial_dir;
   41: extern filter_rule_list daemon_filter_list;
   42: 
   43: int sanitize_paths = 0;
   44: 
   45: char curr_dir[MAXPATHLEN];
   46: unsigned int curr_dir_len;
   47: int curr_dir_depth; /* This is only set for a sanitizing daemon. */
   48: 
   49: /* Set a fd into nonblocking mode. */
   50: void set_nonblocking(int fd)
   51: {
   52: 	int val;
   53: 
   54: 	if ((val = fcntl(fd, F_GETFL)) == -1)
   55: 		return;
   56: 	if (!(val & NONBLOCK_FLAG)) {
   57: 		val |= NONBLOCK_FLAG;
   58: 		fcntl(fd, F_SETFL, val);
   59: 	}
   60: }
   61: 
   62: /* Set a fd into blocking mode. */
   63: void set_blocking(int fd)
   64: {
   65: 	int val;
   66: 
   67: 	if ((val = fcntl(fd, F_GETFL)) == -1)
   68: 		return;
   69: 	if (val & NONBLOCK_FLAG) {
   70: 		val &= ~NONBLOCK_FLAG;
   71: 		fcntl(fd, F_SETFL, val);
   72: 	}
   73: }
   74: 
   75: /**
   76:  * Create a file descriptor pair - like pipe() but use socketpair if
   77:  * possible (because of blocking issues on pipes).
   78:  *
   79:  * Always set non-blocking.
   80:  */
   81: int fd_pair(int fd[2])
   82: {
   83: 	int ret;
   84: 
   85: #ifdef HAVE_SOCKETPAIR
   86: 	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
   87: #else
   88: 	ret = pipe(fd);
   89: #endif
   90: 
   91: 	if (ret == 0) {
   92: 		set_nonblocking(fd[0]);
   93: 		set_nonblocking(fd[1]);
   94: 	}
   95: 
   96: 	return ret;
   97: }
   98: 
   99: void print_child_argv(const char *prefix, char **cmd)
  100: {
  101: 	int cnt = 0;
  102: 	rprintf(FCLIENT, "%s ", prefix);
  103: 	for (; *cmd; cmd++) {
  104: 		/* Look for characters that ought to be quoted.  This
  105: 		* is not a great quoting algorithm, but it's
  106: 		* sufficient for a log message. */
  107: 		if (strspn(*cmd, "abcdefghijklmnopqrstuvwxyz"
  108: 			   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  109: 			   "0123456789"
  110: 			   ",.-_=+@/") != strlen(*cmd)) {
  111: 			rprintf(FCLIENT, "\"%s\" ", *cmd);
  112: 		} else {
  113: 			rprintf(FCLIENT, "%s ", *cmd);
  114: 		}
  115: 		cnt++;
  116: 	}
  117: 	rprintf(FCLIENT, " (%d args)\n", cnt);
  118: }
  119: 
  120: #ifdef SUPPORT_FORCE_CHANGE
  121: static int try_a_force_change(const char *fname, STRUCT_STAT *stp)
  122: {
  123: 	uint32 fileflags = ST_FLAGS(*stp);
  124: 	if (fileflags == NO_FFLAGS) {
  125: 		STRUCT_STAT st;
  126: 		if (x_lstat(fname, &st, NULL) == 0)
  127: 			fileflags = st.st_flags;
  128: 	}
  129: 	if (fileflags != NO_FFLAGS && make_mutable(fname, stp->st_mode, fileflags, force_change) > 0) {
  130: 		int ret, save_force_change = force_change;
  131: 
  132: 		force_change = 0; /* Make certain we can't come back here. */
  133: 		ret = set_times(fname, stp);
  134: 		force_change = save_force_change;
  135: 
  136: 		undo_make_mutable(fname, fileflags);
  137: 
  138: 		return ret;
  139: 	}
  140: 
  141: 	errno = EPERM;
  142: 
  143: 	return -1;
  144: }
  145: #endif
  146: 
  147: /* This returns 0 for success, 1 for a symlink if symlink time-setting
  148:  * is not possible, or -1 for any other error. */
  149: int set_times(const char *fname, STRUCT_STAT *stp)
  150: {
  151: 	static int switch_step = 0;
  152: 
  153: 	if (DEBUG_GTE(TIME, 1)) {
  154: 		rprintf(FINFO,
  155: 			"set modtime, atime of %s to (%ld) %s, (%ld) %s\n",
  156: 			fname, (long)stp->st_mtime,
  157: 			timestring(stp->st_mtime), (long)stp->st_atime, timestring(stp->st_atime));
  158: 	}
  159: 
  160: 	switch (switch_step) {
  161: #ifdef HAVE_SETATTRLIST
  162: #include "case_N.h"
  163: 		if (do_setattrlist_times(fname, stp) == 0)
  164: 			break;
  165: 		if (errno != ENOSYS)
  166: 			return -1;
  167: 		switch_step++;
  168: #endif
  169: 
  170: #ifdef HAVE_UTIMENSAT
  171: #include "case_N.h"
  172: 		if (do_utimensat(fname, stp) == 0)
  173: 			break;
  174: #ifdef SUPPORT_FORCE_CHANGE
  175: 		if (force_change && errno == EPERM && try_a_force_change(fname, stp) == 0)
  176: 			break;
  177: #endif
  178: 		if (errno != ENOSYS)
  179: 			return -1;
  180: 		switch_step++;
  181: #endif
  182: 
  183: #ifdef HAVE_LUTIMES
  184: #include "case_N.h"
  185: 		if (do_lutimes(fname, stp) == 0)
  186: 			break;
  187: #ifdef SUPPORT_FORCE_CHANGE
  188: 		if (force_change && errno == EPERM && try_a_force_change(fname, stp) == 0)
  189: 			break;
  190: #endif
  191: 		if (errno != ENOSYS)
  192: 			return -1;
  193: 		switch_step++;
  194: #endif
  195: 
  196: #include "case_N.h"
  197: 		switch_step++;
  198: 		if (preserve_times & PRESERVE_LINK_TIMES) {
  199: 			preserve_times &= ~PRESERVE_LINK_TIMES;
  200: 			if (S_ISLNK(stp->st_mode))
  201: 				return 1;
  202: 		}
  203: 
  204: #include "case_N.h"
  205: #ifdef HAVE_UTIMES
  206: 		if (do_utimes(fname, stp) == 0)
  207: 			break;
  208: #else
  209: 		if (do_utime(fname, stp) == 0)
  210: 			break;
  211: #endif
  212: #ifdef SUPPORT_FORCE_CHANGE
  213: 		if (force_change && errno == EPERM && try_a_force_change(fname, stp) == 0)
  214: 			break;
  215: #endif
  216: 
  217: 		return -1;
  218: 	}
  219: 
  220: 	return 0;
  221: }
  222: 
  223: /* Create any necessary directories in fname.  Any missing directories are
  224:  * created with default permissions.  Returns < 0 on error, or the number
  225:  * of directories created. */
  226: int make_path(char *fname, mode_t mode, int flags)
  227: {
  228: 	char *end, *p;
  229: 	int ret = 0;
  230: 
  231: 	if (flags & MKP_SKIP_SLASH) {
  232: 		while (*fname == '/')
  233: 			fname++;
  234: 	}
  235: 
  236: 	while (*fname == '.' && fname[1] == '/')
  237: 		fname += 2;
  238: 
  239: 	if (flags & MKP_DROP_NAME) {
  240: 		end = strrchr(fname, '/');
  241: 		if (!end || end == fname)
  242: 			return 0;
  243: 		*end = '\0';
  244: 	} else
  245: 		end = fname + strlen(fname);
  246: 
  247: 	/* Try to find an existing dir, starting from the deepest dir. */
  248: 	for (p = end; ; ) {
  249: 		if (dry_run) {
  250: 			STRUCT_STAT st;
  251: 			if (do_stat(fname, &st) == 0) {
  252: 				if (S_ISDIR(st.st_mode))
  253: 					errno = EEXIST;
  254: 				else
  255: 					errno = ENOTDIR;
  256: 			}
  257: 		} else if (do_mkdir(fname, mode) == 0) {
  258: 			ret++;
  259: 			break;
  260: 		}
  261: 
  262: 		if (errno != ENOENT) {
  263: 			STRUCT_STAT st;
  264: 			if (errno != EEXIST || (do_stat(fname, &st) == 0 && !S_ISDIR(st.st_mode)))
  265: 				ret = -ret - 1;
  266: 			break;
  267: 		}
  268: 		while (1) {
  269: 			if (p == fname) {
  270: 				/* We got a relative path that doesn't exist, so assume that '.'
  271: 				 * is there and just break out and create the whole thing. */
  272: 				p = NULL;
  273: 				goto double_break;
  274: 			}
  275: 			if (*--p == '/') {
  276: 				if (p == fname) {
  277: 					/* We reached the "/" dir, which we assume is there. */
  278: 					goto double_break;
  279: 				}
  280: 				*p = '\0';
  281: 				break;
  282: 			}
  283: 		}
  284: 	}
  285:   double_break:
  286: 
  287: 	/* Make all the dirs that we didn't find on the way here. */
  288: 	while (p != end) {
  289: 		if (p)
  290: 			*p = '/';
  291: 		else
  292: 			p = fname;
  293: 		p += strlen(p);
  294: 		if (ret < 0) /* Skip mkdir on error, but keep restoring the path. */
  295: 			continue;
  296: 		if (do_mkdir(fname, mode) < 0)
  297: 			ret = -ret - 1;
  298: 		else
  299: 			ret++;
  300: 	}
  301: 
  302: 	if (flags & MKP_DROP_NAME)
  303: 		*end = '/';
  304: 
  305: 	return ret;
  306: }
  307: 
  308: /**
  309:  * Write @p len bytes at @p ptr to descriptor @p desc, retrying if
  310:  * interrupted.
  311:  *
  312:  * @retval len upon success
  313:  *
  314:  * @retval <0 write's (negative) error code
  315:  *
  316:  * Derived from GNU C's cccp.c.
  317:  */
  318: int full_write(int desc, const char *ptr, size_t len)
  319: {
  320: 	int total_written;
  321: 
  322: 	total_written = 0;
  323: 	while (len > 0) {
  324: 		int written = write(desc, ptr, len);
  325: 		if (written < 0)  {
  326: 			if (errno == EINTR)
  327: 				continue;
  328: 			return written;
  329: 		}
  330: 		total_written += written;
  331: 		ptr += written;
  332: 		len -= written;
  333: 	}
  334: 	return total_written;
  335: }
  336: 
  337: /**
  338:  * Read @p len bytes at @p ptr from descriptor @p desc, retrying if
  339:  * interrupted.
  340:  *
  341:  * @retval >0 the actual number of bytes read
  342:  *
  343:  * @retval 0 for EOF
  344:  *
  345:  * @retval <0 for an error.
  346:  *
  347:  * Derived from GNU C's cccp.c. */
  348: static int safe_read(int desc, char *ptr, size_t len)
  349: {
  350: 	int n_chars;
  351: 
  352: 	if (len == 0)
  353: 		return len;
  354: 
  355: 	do {
  356: 		n_chars = read(desc, ptr, len);
  357: 	} while (n_chars < 0 && errno == EINTR);
  358: 
  359: 	return n_chars;
  360: }
  361: 
  362: /* Copy a file.  If ofd < 0, copy_file unlinks and opens the "dest" file.
  363:  * Otherwise, it just writes to and closes the provided file descriptor.
  364:  * In either case, if --xattrs are being preserved, the dest file will
  365:  * have its xattrs set from the source file.
  366:  *
  367:  * This is used in conjunction with the --temp-dir, --backup, and
  368:  * --copy-dest options. */
  369: int copy_file(const char *source, const char *dest, int ofd, mode_t mode)
  370: {
  371: 	int ifd;
  372: 	char buf[1024 * 8];
  373: 	int len;   /* Number of bytes read into `buf'. */
  374: 	OFF_T prealloc_len = 0, offset = 0;
  375: 
  376: 	if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
  377: 		int save_errno = errno;
  378: 		rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
  379: 		errno = save_errno;
  380: 		return -1;
  381: 	}
  382: 
  383: 	if (ofd < 0) {
  384: 		if (robust_unlink(dest) && errno != ENOENT) {
  385: 			int save_errno = errno;
  386: 			rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
  387: 			close(ifd);
  388: 			errno = save_errno;
  389: 			return -1;
  390: 		}
  391: 
  392: #ifdef SUPPORT_XATTRS
  393: 		if (preserve_xattrs)
  394: 			mode |= S_IWUSR;
  395: #endif
  396: 		mode &= INITACCESSPERMS;
  397: 		if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
  398: 			int save_errno = errno;
  399: 			rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
  400: 			close(ifd);
  401: 			errno = save_errno;
  402: 			return -1;
  403: 		}
  404: 	}
  405: 
  406: #ifdef SUPPORT_PREALLOCATION
  407: 	if (preallocate_files) {
  408: 		STRUCT_STAT srcst;
  409: 
  410: 		/* Try to preallocate enough space for file's eventual length.  Can
  411: 		 * reduce fragmentation on filesystems like ext4, xfs, and NTFS. */
  412: 		if (do_fstat(ifd, &srcst) < 0)
  413: 			rsyserr(FWARNING, errno, "fstat %s", full_fname(source));
  414: 		else if (srcst.st_size > 0) {
  415: 			prealloc_len = do_fallocate(ofd, 0, srcst.st_size);
  416: 			if (prealloc_len < 0)
  417: 				rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(dest));
  418: 		}
  419: 	}
  420: #endif
  421: 
  422: 	while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
  423: 		if (full_write(ofd, buf, len) < 0) {
  424: 			int save_errno = errno;
  425: 			rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
  426: 			close(ifd);
  427: 			close(ofd);
  428: 			errno = save_errno;
  429: 			return -1;
  430: 		}
  431: 		offset += len;
  432: 	}
  433: 
  434: 	if (len < 0) {
  435: 		int save_errno = errno;
  436: 		rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
  437: 		close(ifd);
  438: 		close(ofd);
  439: 		errno = save_errno;
  440: 		return -1;
  441: 	}
  442: 
  443: 	if (close(ifd) < 0) {
  444: 		rsyserr(FWARNING, errno, "close failed on %s",
  445: 			full_fname(source));
  446: 	}
  447: 
  448: 	/* Source file might have shrunk since we fstatted it.
  449: 	 * Cut off any extra preallocated zeros from dest file. */
  450: 	if (offset < prealloc_len && do_ftruncate(ofd, offset) < 0) {
  451: 		/* If we fail to truncate, the dest file may be wrong, so we
  452: 		 * must trigger the "partial transfer" error. */
  453: 		rsyserr(FERROR_XFER, errno, "ftruncate %s", full_fname(dest));
  454: 	}
  455: 
  456: 	if (do_fsync && fsync(ofd) < 0) {
  457: 		rsyserr(FERROR, errno, "fsync failed on %s",
  458: 			full_fname(dest));
  459: 		close(ofd);
  460: 		return -1;
  461: 	}
  462: 
  463: 	if (close(ofd) < 0) {
  464: 		int save_errno = errno;
  465: 		rsyserr(FERROR_XFER, errno, "close failed on %s",
  466: 			full_fname(dest));
  467: 		errno = save_errno;
  468: 		return -1;
  469: 	}
  470: 
  471: #ifdef SUPPORT_XATTRS
  472: 	if (preserve_xattrs)
  473: 		copy_xattrs(source, dest);
  474: #endif
  475: 
  476: 	return 0;
  477: }
  478: 
  479: /* MAX_RENAMES should be 10**MAX_RENAMES_DIGITS */
  480: #define MAX_RENAMES_DIGITS 3
  481: #define MAX_RENAMES 1000
  482: 
  483: /**
  484:  * Robust unlink: some OS'es (HPUX) refuse to unlink busy files, so
  485:  * rename to <path>/.rsyncNNN instead.
  486:  *
  487:  * Note that successive rsync runs will shuffle the filenames around a
  488:  * bit as long as the file is still busy; this is because this function
  489:  * does not know if the unlink call is due to a new file coming in, or
  490:  * --delete trying to remove old .rsyncNNN files, hence it renames it
  491:  * each time.
  492:  **/
  493: int robust_unlink(const char *fname)
  494: {
  495: #ifndef ETXTBSY
  496: 	return do_unlink(fname);
  497: #else
  498: 	static int counter = 1;
  499: 	int rc, pos, start;
  500: 	char path[MAXPATHLEN];
  501: 
  502: 	rc = do_unlink(fname);
  503: 	if (rc == 0 || errno != ETXTBSY)
  504: 		return rc;
  505: 
  506: 	if ((pos = strlcpy(path, fname, MAXPATHLEN)) >= MAXPATHLEN)
  507: 		pos = MAXPATHLEN - 1;
  508: 
  509: 	while (pos > 0 && path[pos-1] != '/')
  510: 		pos--;
  511: 	pos += strlcpy(path+pos, ".rsync", MAXPATHLEN-pos);
  512: 
  513: 	if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) {
  514: 		errno = ETXTBSY;
  515: 		return -1;
  516: 	}
  517: 
  518: 	/* start where the last one left off to reduce chance of clashes */
  519: 	start = counter;
  520: 	do {
  521: 		snprintf(&path[pos], MAX_RENAMES_DIGITS+1, "%03d", counter);
  522: 		if (++counter >= MAX_RENAMES)
  523: 			counter = 1;
  524: 	} while ((rc = access(path, 0)) == 0 && counter != start);
  525: 
  526: 	if (INFO_GTE(MISC, 1)) {
  527: 		rprintf(FWARNING, "renaming %s to %s because of text busy\n",
  528: 			fname, path);
  529: 	}
  530: 
  531: 	/* maybe we should return rename()'s exit status? Nah. */
  532: 	if (do_rename(fname, path) != 0) {
  533: 		errno = ETXTBSY;
  534: 		return -1;
  535: 	}
  536: 	return 0;
  537: #endif
  538: }
  539: 
  540: /* Returns 0 on successful rename, 1 if we successfully copied the file
  541:  * across filesystems, -2 if copy_file() failed, and -1 on other errors.
  542:  * If partialptr is not NULL and we need to do a copy, copy the file into
  543:  * the active partial-dir instead of over the destination file. */
  544: int robust_rename(const char *from, const char *to, const char *partialptr,
  545: 		  int mode)
  546: {
  547: 	int tries = 4;
  548: 
  549: 	/* A resumed in-place partial-dir transfer might call us with from and
  550: 	 * to pointing to the same buf if the transfer failed yet again. */
  551: 	if (from == to)
  552: 		return 0;
  553: 
  554: 	while (tries--) {
  555: 		if (do_rename(from, to) == 0)
  556: 			return 0;
  557: 
  558: 		switch (errno) {
  559: #ifdef ETXTBSY
  560: 		case ETXTBSY:
  561: 			if (robust_unlink(to) != 0) {
  562: 				errno = ETXTBSY;
  563: 				return -1;
  564: 			}
  565: 			errno = ETXTBSY;
  566: 			break;
  567: #endif
  568: 		case EXDEV:
  569: 			if (partialptr) {
  570: 				if (!handle_partial_dir(partialptr,PDIR_CREATE))
  571: 					return -2;
  572: 				to = partialptr;
  573: 			}
  574: 			if (copy_file(from, to, -1, mode) != 0)
  575: 				return -2;
  576: 			do_unlink(from);
  577: 			return 1;
  578: 		default:
  579: 			return -1;
  580: 		}
  581: 	}
  582: 	return -1;
  583: }
  584: 
  585: static pid_t all_pids[10];
  586: static int num_pids;
  587: 
  588: /** Fork and record the pid of the child. **/
  589: pid_t do_fork(void)
  590: {
  591: 	pid_t newpid = fork();
  592: 
  593: 	if (newpid != 0  &&  newpid != -1) {
  594: 		all_pids[num_pids++] = newpid;
  595: 	}
  596: 	return newpid;
  597: }
  598: 
  599: /**
  600:  * Kill all children.
  601:  *
  602:  * @todo It would be kind of nice to make sure that they are actually
  603:  * all our children before we kill them, because their pids may have
  604:  * been recycled by some other process.  Perhaps when we wait for a
  605:  * child, we should remove it from this array.  Alternatively we could
  606:  * perhaps use process groups, but I think that would not work on
  607:  * ancient Unix versions that don't support them.
  608:  **/
  609: void kill_all(int sig)
  610: {
  611: 	int i;
  612: 
  613: 	for (i = 0; i < num_pids; i++) {
  614: 		/* Let's just be a little careful where we
  615: 		 * point that gun, hey?  See kill(2) for the
  616: 		 * magic caused by negative values. */
  617: 		pid_t p = all_pids[i];
  618: 
  619: 		if (p == getpid())
  620: 			continue;
  621: 		if (p <= 0)
  622: 			continue;
  623: 
  624: 		kill(p, sig);
  625: 	}
  626: }
  627: 
  628: /** Lock a byte range in a open file */
  629: int lock_range(int fd, int offset, int len)
  630: {
  631: 	struct flock lock;
  632: 
  633: 	lock.l_type = F_WRLCK;
  634: 	lock.l_whence = SEEK_SET;
  635: 	lock.l_start = offset;
  636: 	lock.l_len = len;
  637: 	lock.l_pid = 0;
  638: 
  639: 	return fcntl(fd,F_SETLK,&lock) == 0;
  640: }
  641: 
  642: #define ENSURE_MEMSPACE(buf, type, sz, req) \
  643: 	do { if ((req) > sz) buf = realloc_array(buf, type, sz = MAX(sz * 2, req)); } while(0)
  644: 
  645: static inline void call_glob_match(const char *name, int len, int from_glob,
  646: 				   char *arg, int abpos, int fbpos);
  647: 
  648: static struct glob_data {
  649: 	char *arg_buf, *filt_buf, **argv;
  650: 	int absize, fbsize, maxargs, argc;
  651: } glob;
  652: 
  653: static void glob_match(char *arg, int abpos, int fbpos)
  654: {
  655: 	int len;
  656: 	char *slash;
  657: 
  658: 	while (*arg == '.' && arg[1] == '/') {
  659: 		if (fbpos < 0) {
  660: 			ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, glob.absize);
  661: 			memcpy(glob.filt_buf, glob.arg_buf, abpos + 1);
  662: 			fbpos = abpos;
  663: 		}
  664: 		ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + 3);
  665: 		glob.arg_buf[abpos++] = *arg++;
  666: 		glob.arg_buf[abpos++] = *arg++;
  667: 		glob.arg_buf[abpos] = '\0';
  668: 	}
  669: 	if ((slash = strchr(arg, '/')) != NULL) {
  670: 		*slash = '\0';
  671: 		len = slash - arg;
  672: 	} else
  673: 		len = strlen(arg);
  674: 	if (strpbrk(arg, "*?[")) {
  675: 		struct dirent *di;
  676: 		DIR *d;
  677: 
  678: 		if (!(d = opendir(abpos ? glob.arg_buf : ".")))
  679: 			return;
  680: 		while ((di = readdir(d)) != NULL) {
  681: 			char *dname = d_name(di);
  682: 			if (dname[0] == '.' && (dname[1] == '\0'
  683: 			  || (dname[1] == '.' && dname[2] == '\0')))
  684: 				continue;
  685: 			if (!wildmatch(arg, dname))
  686: 				continue;
  687: 			call_glob_match(dname, strlen(dname), 1,
  688: 					slash ? arg + len + 1 : NULL,
  689: 					abpos, fbpos);
  690: 		}
  691: 		closedir(d);
  692: 	} else {
  693: 		call_glob_match(arg, len, 0,
  694: 				slash ? arg + len + 1 : NULL,
  695: 				abpos, fbpos);
  696: 	}
  697: 	if (slash)
  698: 		*slash = '/';
  699: }
  700: 
  701: static inline void call_glob_match(const char *name, int len, int from_glob,
  702: 				   char *arg, int abpos, int fbpos)
  703: {
  704: 	char *use_buf;
  705: 
  706: 	ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, abpos + len + 2);
  707: 	memcpy(glob.arg_buf + abpos, name, len);
  708: 	abpos += len;
  709: 	glob.arg_buf[abpos] = '\0';
  710: 
  711: 	if (fbpos >= 0) {
  712: 		ENSURE_MEMSPACE(glob.filt_buf, char, glob.fbsize, fbpos + len + 2);
  713: 		memcpy(glob.filt_buf + fbpos, name, len);
  714: 		fbpos += len;
  715: 		glob.filt_buf[fbpos] = '\0';
  716: 		use_buf = glob.filt_buf;
  717: 	} else
  718: 		use_buf = glob.arg_buf;
  719: 
  720: 	if (from_glob || (arg && len)) {
  721: 		STRUCT_STAT st;
  722: 		int is_dir;
  723: 
  724: 		if (do_stat(glob.arg_buf, &st) != 0)
  725: 			return;
  726: 		is_dir = S_ISDIR(st.st_mode) != 0;
  727: 		if (arg && !is_dir)
  728: 			return;
  729: 
  730: 		if (daemon_filter_list.head
  731: 		 && check_filter(&daemon_filter_list, FLOG, use_buf, is_dir) < 0)
  732: 			return;
  733: 	}
  734: 
  735: 	if (arg) {
  736: 		glob.arg_buf[abpos++] = '/';
  737: 		glob.arg_buf[abpos] = '\0';
  738: 		if (fbpos >= 0) {
  739: 			glob.filt_buf[fbpos++] = '/';
  740: 			glob.filt_buf[fbpos] = '\0';
  741: 		}
  742: 		glob_match(arg, abpos, fbpos);
  743: 	} else {
  744: 		ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
  745: 		glob.argv[glob.argc++] = strdup(glob.arg_buf);
  746: 	}
  747: }
  748: 
  749: /* This routine performs wild-card expansion of the pathname in "arg".  Any
  750:  * daemon-excluded files/dirs will not be matched by the wildcards.  Returns 0
  751:  * if a wild-card string is the only returned item (due to matching nothing). */
  752: int glob_expand(const char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
  753: {
  754: 	int ret, save_argc;
  755: 	char *s;
  756: 
  757: 	if (!arg) {
  758: 		if (glob.filt_buf)
  759: 			free(glob.filt_buf);
  760: 		free(glob.arg_buf);
  761: 		memset(&glob, 0, sizeof glob);
  762: 		return -1;
  763: 	}
  764: 
  765: 	if (sanitize_paths)
  766: 		s = sanitize_path(NULL, arg, "", 0, SP_KEEP_DOT_DIRS);
  767: 	else {
  768: 		s = strdup(arg);
  769: 		clean_fname(s, CFN_KEEP_DOT_DIRS | CFN_KEEP_TRAILING_SLASH | CFN_COLLAPSE_DOT_DOT_DIRS);
  770: 	}
  771: 
  772: 	ENSURE_MEMSPACE(glob.arg_buf, char, glob.absize, MAXPATHLEN);
  773: 	*glob.arg_buf = '\0';
  774: 
  775: 	glob.argc = save_argc = *argc_p;
  776: 	glob.argv = *argv_p;
  777: 	glob.maxargs = *maxargs_p;
  778: 
  779: 	ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, 100);
  780: 
  781: 	glob_match(s, 0, -1);
  782: 
  783: 	/* The arg didn't match anything, so add the failed arg to the list. */
  784: 	if (glob.argc == save_argc) {
  785: 		ENSURE_MEMSPACE(glob.argv, char *, glob.maxargs, glob.argc + 1);
  786: 		glob.argv[glob.argc++] = s;
  787: 		ret = 0;
  788: 	} else {
  789: 		free(s);
  790: 		ret = 1;
  791: 	}
  792: 
  793: 	*maxargs_p = glob.maxargs;
  794: 	*argv_p = glob.argv;
  795: 	*argc_p = glob.argc;
  796: 
  797: 	return ret;
  798: }
  799: 
  800: /* This routine is only used in daemon mode. */
  801: void glob_expand_module(char *base1, char *arg, char ***argv_p, int *argc_p, int *maxargs_p)
  802: {
  803: 	char *p, *s;
  804: 	char *base = base1;
  805: 	int base_len = strlen(base);
  806: 
  807: 	if (!arg || !*arg)
  808: 		return;
  809: 
  810: 	if (strncmp(arg, base, base_len) == 0)
  811: 		arg += base_len;
  812: 
  813: 	if (protect_args) {
  814: 		glob_expand(arg, argv_p, argc_p, maxargs_p);
  815: 		return;
  816: 	}
  817: 
  818: 	arg = strdup(arg);
  819: 
  820: 	if (asprintf(&base," %s/", base1) < 0)
  821: 		out_of_memory("glob_expand_module");
  822: 	base_len++;
  823: 
  824: 	for (s = arg; *s; s = p + base_len) {
  825: 		if ((p = strstr(s, base)) != NULL)
  826: 			*p = '\0'; /* split it at this point */
  827: 		glob_expand(s, argv_p, argc_p, maxargs_p);
  828: 		if (!p)
  829: 			break;
  830: 	}
  831: 
  832: 	free(arg);
  833: 	free(base);
  834: }
  835: 
  836: /**
  837:  * Convert a string to lower case
  838:  **/
  839: void strlower(char *s)
  840: {
  841: 	while (*s) {
  842: 		if (isUpper(s))
  843: 			*s = toLower(s);
  844: 		s++;
  845: 	}
  846: }
  847: 
  848: /**
  849:  * Split a string into tokens based (usually) on whitespace & commas.  If the
  850:  * string starts with a comma (after skipping any leading whitespace), then
  851:  * splitting is done only on commas. No empty tokens are ever returned. */
  852: char *conf_strtok(char *str)
  853: {
  854: 	static int commas_only = 0;
  855: 
  856: 	if (str) {
  857: 		while (isSpace(str)) str++;
  858: 		if (*str == ',') {
  859: 			commas_only = 1;
  860: 			str++;
  861: 		} else
  862: 			commas_only = 0;
  863: 	}
  864: 
  865: 	while (commas_only) {
  866: 		char *end, *tok = strtok(str, ",");
  867: 		if (!tok)
  868: 			return NULL;
  869: 		/* Trim just leading and trailing whitespace. */
  870: 		while (isSpace(tok))
  871: 			tok++;
  872: 		end = tok + strlen(tok);
  873: 		while (end > tok && isSpace(end-1))
  874: 			*--end = '\0';
  875: 		if (*tok)
  876: 			return tok;
  877: 		str = NULL;
  878: 	}
  879: 
  880: 	return strtok(str, " ,\t\r\n");
  881: }
  882: 
  883: /* Join strings p1 & p2 into "dest" with a guaranteed '/' between them.  (If
  884:  * p1 ends with a '/', no extra '/' is inserted.)  Returns the length of both
  885:  * strings + 1 (if '/' was inserted), regardless of whether the null-terminated
  886:  * string fits into destsize. */
  887: size_t pathjoin(char *dest, size_t destsize, const char *p1, const char *p2)
  888: {
  889: 	size_t len = strlcpy(dest, p1, destsize);
  890: 	if (len < destsize - 1) {
  891: 		if (!len || dest[len-1] != '/')
  892: 			dest[len++] = '/';
  893: 		if (len < destsize - 1)
  894: 			len += strlcpy(dest + len, p2, destsize - len);
  895: 		else {
  896: 			dest[len] = '\0';
  897: 			len += strlen(p2);
  898: 		}
  899: 	}
  900: 	else
  901: 		len += strlen(p2) + 1; /* Assume we'd insert a '/'. */
  902: 	return len;
  903: }
  904: 
  905: /* Join any number of strings together, putting them in "dest".  The return
  906:  * value is the length of all the strings, regardless of whether the null-
  907:  * terminated whole fits in destsize.  Your list of string pointers must end
  908:  * with a NULL to indicate the end of the list. */
  909: size_t stringjoin(char *dest, size_t destsize, ...)
  910: {
  911: 	va_list ap;
  912: 	size_t len, ret = 0;
  913: 	const char *src;
  914: 
  915: 	va_start(ap, destsize);
  916: 	while (1) {
  917: 		if (!(src = va_arg(ap, const char *)))
  918: 			break;
  919: 		len = strlen(src);
  920: 		ret += len;
  921: 		if (destsize > 1) {
  922: 			if (len >= destsize)
  923: 				len = destsize - 1;
  924: 			memcpy(dest, src, len);
  925: 			destsize -= len;
  926: 			dest += len;
  927: 		}
  928: 	}
  929: 	*dest = '\0';
  930: 	va_end(ap);
  931: 
  932: 	return ret;
  933: }
  934: 
  935: /* Append formatted text at *dest_ptr up to a maximum of sz (like snprintf).
  936:  * On success, advance *dest_ptr and return True; on overflow, return False. */
  937: BOOL snappendf(char **dest_ptr, size_t sz, const char *format, ...)
  938: {
  939: 	va_list ap;
  940: 	size_t len;
  941: 
  942: 	va_start(ap, format);
  943: 	len = vsnprintf(*dest_ptr, sz, format, ap);
  944: 	va_end(ap);
  945: 
  946: 	if (len >= sz)
  947: 		return False;
  948: 	else {
  949: 		*dest_ptr += len;
  950: 		return True;
  951: 	}
  952: }
  953: 
  954: int count_dir_elements(const char *p)
  955: {
  956: 	int cnt = 0, new_component = 1;
  957: 	while (*p) {
  958: 		if (*p++ == '/')
  959: 			new_component = (*p != '.' || (p[1] != '/' && p[1] != '\0'));
  960: 		else if (new_component) {
  961: 			new_component = 0;
  962: 			cnt++;
  963: 		}
  964: 	}
  965: 	return cnt;
  966: }
  967: 
  968: /* Turns multiple adjacent slashes into a single slash (possible exception:
  969:  * the preserving of two leading slashes at the start), drops all leading or
  970:  * interior "." elements unless CFN_KEEP_DOT_DIRS is flagged.  Will also drop
  971:  * a trailing '.' after a '/' if CFN_DROP_TRAILING_DOT_DIR is flagged, removes
  972:  * a trailing slash (perhaps after removing the aforementioned dot) unless
  973:  * CFN_KEEP_TRAILING_SLASH is flagged, and will also collapse ".." elements
  974:  * (except at the start) if CFN_COLLAPSE_DOT_DOT_DIRS is flagged.  If the
  975:  * resulting name would be empty, returns ".". */
  976: int clean_fname(char *name, int flags)
  977: {
  978: 	char *limit = name - 1, *t = name, *f = name;
  979: 	int anchored;
  980: 
  981: 	if (!name)
  982: 		return 0;
  983: 
  984: #define DOT_IS_DOT_DOT_DIR(bp) (bp[1] == '.' && (bp[2] == '/' || !bp[2]))
  985: 
  986: 	if ((anchored = *f == '/') != 0) {
  987: 		*t++ = *f++;
  988: #ifdef __CYGWIN__
  989: 		/* If there are exactly 2 slashes at the start, preserve
  990: 		 * them.  Would break daemon excludes unless the paths are
  991: 		 * really treated differently, so used this sparingly. */
  992: 		if (*f == '/' && f[1] != '/')
  993: 			*t++ = *f++;
  994: #endif
  995: 	} else if (flags & CFN_KEEP_DOT_DIRS && *f == '.' && f[1] == '/') {
  996: 		*t++ = *f++;
  997: 		*t++ = *f++;
  998: 	} else if (flags & CFN_REFUSE_DOT_DOT_DIRS && *f == '.' && DOT_IS_DOT_DOT_DIR(f))
  999: 		return -1;
 1000: 	while (*f) {
 1001: 		/* discard extra slashes */
 1002: 		if (*f == '/') {
 1003: 			f++;
 1004: 			continue;
 1005: 		}
 1006: 		if (*f == '.') {
 1007: 			/* discard interior "." dirs */
 1008: 			if (f[1] == '/' && !(flags & CFN_KEEP_DOT_DIRS)) {
 1009: 				f += 2;
 1010: 				continue;
 1011: 			}
 1012: 			if (f[1] == '\0' && flags & CFN_DROP_TRAILING_DOT_DIR)
 1013: 				break;
 1014: 			/* collapse ".." dirs */
 1015: 			if (flags & (CFN_COLLAPSE_DOT_DOT_DIRS|CFN_REFUSE_DOT_DOT_DIRS) && DOT_IS_DOT_DOT_DIR(f)) {
 1016: 				char *s = t - 1;
 1017: 				if (flags & CFN_REFUSE_DOT_DOT_DIRS)
 1018: 					return -1;
 1019: 				if (s == name && anchored) {
 1020: 					f += 2;
 1021: 					continue;
 1022: 				}
 1023: 				while (s > limit && *--s != '/') {}
 1024: 				if (s != t - 1 && (s < name || *s == '/')) {
 1025: 					t = s + 1;
 1026: 					f += 2;
 1027: 					continue;
 1028: 				}
 1029: 				limit = t + 2;
 1030: 			}
 1031: 		}
 1032: 		while (*f && (*t++ = *f++) != '/') {}
 1033: 	}
 1034: 
 1035: 	if (t > name+anchored && t[-1] == '/' && !(flags & CFN_KEEP_TRAILING_SLASH))
 1036: 		t--;
 1037: 	if (t == name)
 1038: 		*t++ = '.';
 1039: 	*t = '\0';
 1040: 
 1041: #undef DOT_IS_DOT_DOT_DIR
 1042: 
 1043: 	return t - name;
 1044: }
 1045: 
 1046: /* Make path appear as if a chroot had occurred.  This handles a leading
 1047:  * "/" (either removing it or expanding it) and any leading or embedded
 1048:  * ".." components that attempt to escape past the module's top dir.
 1049:  *
 1050:  * If dest is NULL, a buffer is allocated to hold the result.  It is legal
 1051:  * to call with the dest and the path (p) pointing to the same buffer, but
 1052:  * rootdir will be ignored to avoid expansion of the string.
 1053:  *
 1054:  * The rootdir string contains a value to use in place of a leading slash.
 1055:  * Specify NULL to get the default of "module_dir".
 1056:  *
 1057:  * The depth var is a count of how many '..'s to allow at the start of the
 1058:  * path.
 1059:  *
 1060:  * We also clean the path in a manner similar to clean_fname() but with a
 1061:  * few differences:
 1062:  *
 1063:  * Turns multiple adjacent slashes into a single slash, gets rid of "." dir
 1064:  * elements (INCLUDING a trailing dot dir), PRESERVES a trailing slash, and
 1065:  * ALWAYS collapses ".." elements (except for those at the start of the
 1066:  * string up to "depth" deep).  If the resulting name would be empty,
 1067:  * change it into a ".". */
 1068: char *sanitize_path(char *dest, const char *p, const char *rootdir, int depth, int flags)
 1069: {
 1070: 	char *start, *sanp;
 1071: 	int rlen = 0, drop_dot_dirs = !relative_paths || !(flags & SP_KEEP_DOT_DIRS);
 1072: 
 1073: 	if (dest != p) {
 1074: 		int plen = strlen(p); /* the path len INCLUDING any separating slash */
 1075: 		if (*p == '/') {
 1076: 			if (!rootdir)
 1077: 				rootdir = module_dir;
 1078: 			rlen = strlen(rootdir);
 1079: 			depth = 0;
 1080: 			p++;
 1081: 		}
 1082: 		if (!dest)
 1083: 			dest = new_array(char, MAX(rlen + plen + 1, 2));
 1084: 		else if (rlen + plen + 1 >= MAXPATHLEN)
 1085: 			return NULL;
 1086: 		if (rlen) { /* only true if p previously started with a slash */
 1087: 			memcpy(dest, rootdir, rlen);
 1088: 			if (rlen > 1) /* a rootdir of len 1 is "/", so this avoids a 2nd slash */
 1089: 				dest[rlen++] = '/';
 1090: 		}
 1091: 	}
 1092: 
 1093: 	if (drop_dot_dirs) {
 1094: 		while (*p == '.' && p[1] == '/')
 1095: 			p += 2;
 1096: 	}
 1097: 
 1098: 	start = sanp = dest + rlen;
 1099: 	/* This loop iterates once per filename component in p, pointing at
 1100: 	 * the start of the name (past any prior slash) for each iteration. */
 1101: 	while (*p) {
 1102: 		/* discard leading or extra slashes */
 1103: 		if (*p == '/') {
 1104: 			p++;
 1105: 			continue;
 1106: 		}
 1107: 		if (drop_dot_dirs) {
 1108: 			if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
 1109: 				/* skip "." component */
 1110: 				p++;
 1111: 				continue;
 1112: 			}
 1113: 		}
 1114: 		if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
 1115: 			/* ".." component followed by slash or end */
 1116: 			if (depth <= 0 || sanp != start) {
 1117: 				p += 2;
 1118: 				if (sanp != start) {
 1119: 					/* back up sanp one level */
 1120: 					--sanp; /* now pointing at slash */
 1121: 					while (sanp > start && sanp[-1] != '/')
 1122: 						sanp--;
 1123: 				}
 1124: 				continue;
 1125: 			}
 1126: 			/* allow depth levels of .. at the beginning */
 1127: 			depth--;
 1128: 			/* move the virtual beginning to leave the .. alone */
 1129: 			start = sanp + 3;
 1130: 		}
 1131: 		/* copy one component through next slash */
 1132: 		while (*p && (*sanp++ = *p++) != '/') {}
 1133: 	}
 1134: 	if (sanp == dest) {
 1135: 		/* ended up with nothing, so put in "." component */
 1136: 		*sanp++ = '.';
 1137: 	}
 1138: 	*sanp = '\0';
 1139: 
 1140: 	return dest;
 1141: }
 1142: 
 1143: /* Like chdir(), but it keeps track of the current directory (in the
 1144:  * global "curr_dir"), and ensures that the path size doesn't overflow.
 1145:  * Also cleans the path using the clean_fname() function. */
 1146: int change_dir(const char *dir, int set_path_only)
 1147: {
 1148: 	static int initialised, skipped_chdir;
 1149: 	unsigned int len;
 1150: 
 1151: 	if (!initialised) {
 1152: 		initialised = 1;
 1153: 		if (getcwd(curr_dir, sizeof curr_dir - 1) == NULL) {
 1154: 			rsyserr(FERROR, errno, "getcwd()");
 1155: 			exit_cleanup(RERR_FILESELECT);
 1156: 		}
 1157: 		curr_dir_len = strlen(curr_dir);
 1158: 	}
 1159: 
 1160: 	if (!dir)	/* this call was probably just to initialize */
 1161: 		return 0;
 1162: 
 1163: 	len = strlen(dir);
 1164: 	if (len == 1 && *dir == '.' && (!skipped_chdir || set_path_only))
 1165: 		return 1;
 1166: 
 1167: 	if (*dir == '/') {
 1168: 		if (len >= sizeof curr_dir) {
 1169: 			errno = ENAMETOOLONG;
 1170: 			return 0;
 1171: 		}
 1172: 		if (!set_path_only && chdir(dir))
 1173: 			return 0;
 1174: 		skipped_chdir = set_path_only;
 1175: 		memcpy(curr_dir, dir, len + 1);
 1176: 	} else {
 1177: 		unsigned int save_dir_len = curr_dir_len;
 1178: 		if (curr_dir_len + 1 + len >= sizeof curr_dir) {
 1179: 			errno = ENAMETOOLONG;
 1180: 			return 0;
 1181: 		}
 1182: 		if (!(curr_dir_len && curr_dir[curr_dir_len-1] == '/'))
 1183: 			curr_dir[curr_dir_len++] = '/';
 1184: 		memcpy(curr_dir + curr_dir_len, dir, len + 1);
 1185: 
 1186: 		if (!set_path_only && chdir(curr_dir)) {
 1187: 			curr_dir_len = save_dir_len;
 1188: 			curr_dir[curr_dir_len] = '\0';
 1189: 			return 0;
 1190: 		}
 1191: 		skipped_chdir = set_path_only;
 1192: 	}
 1193: 
 1194: 	curr_dir_len = clean_fname(curr_dir, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
 1195: 	if (sanitize_paths) {
 1196: 		if (module_dirlen > curr_dir_len)
 1197: 			module_dirlen = curr_dir_len;
 1198: 		curr_dir_depth = count_dir_elements(curr_dir + module_dirlen);
 1199: 	}
 1200: 
 1201: 	if (DEBUG_GTE(CHDIR, 1) && !set_path_only)
 1202: 		rprintf(FINFO, "[%s] change_dir(%s)\n", who_am_i(), curr_dir);
 1203: 
 1204: 	return 1;
 1205: }
 1206: 
 1207: /* This will make a relative path absolute and clean it up via clean_fname().
 1208:  * Returns the string, which might be newly allocated, or NULL on error. */
 1209: char *normalize_path(char *path, BOOL force_newbuf, unsigned int *len_ptr)
 1210: {
 1211: 	unsigned int len;
 1212: 
 1213: 	if (*path != '/') { /* Make path absolute. */
 1214: 		int len = strlen(path);
 1215: 		if (curr_dir_len + 1 + len >= sizeof curr_dir)
 1216: 			return NULL;
 1217: 		curr_dir[curr_dir_len] = '/';
 1218: 		memcpy(curr_dir + curr_dir_len + 1, path, len + 1);
 1219: 		path = strdup(curr_dir);
 1220: 		curr_dir[curr_dir_len] = '\0';
 1221: 	} else if (force_newbuf)
 1222: 		path = strdup(path);
 1223: 
 1224: 	len = clean_fname(path, CFN_COLLAPSE_DOT_DOT_DIRS | CFN_DROP_TRAILING_DOT_DIR);
 1225: 
 1226: 	if (len_ptr)
 1227: 		*len_ptr = len;
 1228: 
 1229: 	return path;
 1230: }
 1231: 
 1232: /* We need to supply our own strcmp function for file list comparisons
 1233:  * to ensure that signed/unsigned usage is consistent between machines. */
 1234: int u_strcmp(const char *p1, const char *p2)
 1235: {
 1236:         for ( ; *p1; p1++, p2++) {
 1237: 		if (*p1 != *p2)
 1238: 			break;
 1239: 	}
 1240: 
 1241: 	return (int)*(uchar*)p1 - (int)*(uchar*)p2;
 1242: }
 1243: 
 1244: /* We need a memcmp function compares unsigned-byte values. */
 1245: int u_memcmp(const void *p1, const void *p2, size_t len)
 1246: {
 1247: 	const uchar *u1 = p1;
 1248: 	const uchar *u2 = p2;
 1249: 
 1250: 	while (len--) {
 1251: 		if (*u1 != *u2)
 1252: 			return (int)*u1 - (int)*u2;
 1253: 	}
 1254: 
 1255: 	return 0;
 1256: }
 1257: 
 1258: /**
 1259:  * Return a quoted string with the full pathname of the indicated filename.
 1260:  * The string " (in MODNAME)" may also be appended.  The returned pointer
 1261:  * remains valid until the next time full_fname() is called.
 1262:  **/
 1263: char *full_fname(const char *fn)
 1264: {
 1265: 	static char *result = NULL;
 1266: 	char *m1, *m2, *m3;
 1267: 	char *p1, *p2;
 1268: 
 1269: 	if (result)
 1270: 		free(result);
 1271: 
 1272: 	if (*fn == '/')
 1273: 		p1 = p2 = "";
 1274: 	else {
 1275: 		p1 = curr_dir + module_dirlen;
 1276: 		for (p2 = p1; *p2 == '/'; p2++) {}
 1277: 		if (*p2)
 1278: 			p2 = "/";
 1279: 	}
 1280: 	if (module_id >= 0) {
 1281: 		m1 = " (in ";
 1282: 		m2 = lp_name(module_id);
 1283: 		m3 = ")";
 1284: 	} else
 1285: 		m1 = m2 = m3 = "";
 1286: 
 1287: 	if (asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3) < 0)
 1288: 		out_of_memory("full_fname");
 1289: 
 1290: 	return result;
 1291: }
 1292: 
 1293: static char partial_fname[MAXPATHLEN];
 1294: 
 1295: char *partial_dir_fname(const char *fname)
 1296: {
 1297: 	char *t = partial_fname;
 1298: 	int sz = sizeof partial_fname;
 1299: 	const char *fn;
 1300: 
 1301: 	if ((fn = strrchr(fname, '/')) != NULL) {
 1302: 		fn++;
 1303: 		if (*partial_dir != '/') {
 1304: 			int len = fn - fname;
 1305: 			strncpy(t, fname, len); /* safe */
 1306: 			t += len;
 1307: 			sz -= len;
 1308: 		}
 1309: 	} else
 1310: 		fn = fname;
 1311: 	if ((int)pathjoin(t, sz, partial_dir, fn) >= sz)
 1312: 		return NULL;
 1313: 	if (daemon_filter_list.head) {
 1314: 		t = strrchr(partial_fname, '/');
 1315: 		*t = '\0';
 1316: 		if (check_filter(&daemon_filter_list, FLOG, partial_fname, 1) < 0)
 1317: 			return NULL;
 1318: 		*t = '/';
 1319: 		if (check_filter(&daemon_filter_list, FLOG, partial_fname, 0) < 0)
 1320: 			return NULL;
 1321: 	}
 1322: 
 1323: 	return partial_fname;
 1324: }
 1325: 
 1326: /* If no --partial-dir option was specified, we don't need to do anything
 1327:  * (the partial-dir is essentially '.'), so just return success. */
 1328: int handle_partial_dir(const char *fname, int create)
 1329: {
 1330: 	char *fn, *dir;
 1331: 
 1332: 	if (fname != partial_fname)
 1333: 		return 1;
 1334: 	if (!create && *partial_dir == '/')
 1335: 		return 1;
 1336: 	if (!(fn = strrchr(partial_fname, '/')))
 1337: 		return 1;
 1338: 
 1339: 	*fn = '\0';
 1340: 	dir = partial_fname;
 1341: 	if (create) {
 1342: 		STRUCT_STAT st;
 1343: 		int statret = do_lstat(dir, &st);
 1344: 		if (statret == 0 && !S_ISDIR(st.st_mode)) {
 1345: 			if (do_unlink(dir) < 0) {
 1346: 				*fn = '/';
 1347: 				return 0;
 1348: 			}
 1349: 			statret = -1;
 1350: 		}
 1351: 		if (statret < 0 && make_path(dir, 0700, 0) < 0) {
 1352: 			*fn = '/';
 1353: 			return 0;
 1354: 		}
 1355: 	} else
 1356: 		do_rmdir(dir);
 1357: 	*fn = '/';
 1358: 
 1359: 	return 1;
 1360: }
 1361: 
 1362: /* Determine if a symlink points outside the current directory tree.
 1363:  * This is considered "unsafe" because e.g. when mirroring somebody
 1364:  * else's machine it might allow them to establish a symlink to
 1365:  * /etc/passwd, and then read it through a web server.
 1366:  *
 1367:  * Returns 1 if unsafe, 0 if safe.
 1368:  *
 1369:  * Null symlinks and absolute symlinks are always unsafe.
 1370:  *
 1371:  * Basically here we are concerned with symlinks whose target contains
 1372:  * "..", because this might cause us to walk back up out of the
 1373:  * transferred directory.  We are not allowed to go back up and
 1374:  * reenter.
 1375:  *
 1376:  * "dest" is the target of the symlink in question.
 1377:  *
 1378:  * "src" is the top source directory currently applicable at the level
 1379:  * of the referenced symlink.  This is usually the symlink's full path
 1380:  * (including its name), as referenced from the root of the transfer. */
 1381: int unsafe_symlink(const char *dest, const char *src)
 1382: {
 1383: 	const char *name, *slash;
 1384: 	int depth = 0;
 1385: 
 1386: 	/* all absolute and null symlinks are unsafe */
 1387: 	if (!dest || !*dest || *dest == '/')
 1388: 		return 1;
 1389: 
 1390: 	/* find out what our safety margin is */
 1391: 	for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
 1392: 		/* ".." segment starts the count over.  "." segment is ignored. */
 1393: 		if (*name == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))) {
 1394: 			if (name[1] == '.')
 1395: 				depth = 0;
 1396: 		} else
 1397: 			depth++;
 1398: 		while (slash[1] == '/') slash++; /* just in case src isn't clean */
 1399: 	}
 1400: 	if (*name == '.' && name[1] == '.' && name[2] == '\0')
 1401: 		depth = 0;
 1402: 
 1403: 	for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {
 1404: 		if (*name == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))) {
 1405: 			if (name[1] == '.') {
 1406: 				/* if at any point we go outside the current directory
 1407: 				   then stop - it is unsafe */
 1408: 				if (--depth < 0)
 1409: 					return 1;
 1410: 			}
 1411: 		} else
 1412: 			depth++;
 1413: 		while (slash[1] == '/') slash++;
 1414: 	}
 1415: 	if (*name == '.' && name[1] == '.' && name[2] == '\0')
 1416: 		depth--;
 1417: 
 1418: 	return depth < 0;
 1419: }
 1420: 
 1421: /* Return the date and time as a string.  Some callers tweak returned buf. */
 1422: char *timestring(time_t t)
 1423: {
 1424: 	static int ndx = 0;
 1425: 	static char buffers[4][20]; /* We support 4 simultaneous timestring results. */
 1426: 	char *TimeBuf = buffers[ndx = (ndx + 1) % 4];
 1427: 	struct tm *tm = localtime(&t);
 1428: 	int len = snprintf(TimeBuf, sizeof buffers[0], "%4d/%02d/%02d %02d:%02d:%02d",
 1429: 		 (int)tm->tm_year + 1900, (int)tm->tm_mon + 1, (int)tm->tm_mday,
 1430: 		 (int)tm->tm_hour, (int)tm->tm_min, (int)tm->tm_sec);
 1431: 	assert(len > 0); /* Silence gcc warning */
 1432: 
 1433: 	return TimeBuf;
 1434: }
 1435: 
 1436: /* Determine if two time_t values are equivalent (either exact, or in
 1437:  * the modification timestamp window established by --modify-window).
 1438:  * Returns 1 if the times the "same", or 0 if they are different. */
 1439: int same_time(time_t f1_sec, unsigned long f1_nsec, time_t f2_sec, unsigned long f2_nsec)
 1440: {
 1441: 	if (modify_window == 0)
 1442: 		return f1_sec == f2_sec;
 1443: 	if (modify_window < 0)
 1444: 		return f1_sec == f2_sec && f1_nsec == f2_nsec;
 1445: 	/* The nano seconds doesn't figure into these checks -- time windows don't care about that. */
 1446: 	if (f2_sec > f1_sec)
 1447: 		return f2_sec - f1_sec <= modify_window;
 1448: 	return f1_sec - f2_sec <= modify_window;
 1449: }
 1450: 
 1451: #ifdef __INSURE__XX
 1452: #include <dlfcn.h>
 1453: 
 1454: /**
 1455:    This routine is a trick to immediately catch errors when debugging
 1456:    with insure. A xterm with a gdb is popped up when insure catches
 1457:    a error. It is Linux specific.
 1458: **/
 1459: int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
 1460: {
 1461: 	static int (*fn)();
 1462: 	int ret, pid_int = getpid();
 1463: 	char *cmd;
 1464: 
 1465: 	if (asprintf(&cmd,
 1466: 	    "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; "
 1467: 	    "gdb /proc/%d/exe %d'", pid_int, pid_int, pid_int) < 0)
 1468: 		return -1;
 1469: 
 1470: 	if (!fn) {
 1471: 		static void *h;
 1472: 		h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
 1473: 		fn = dlsym(h, "_Insure_trap_error");
 1474: 	}
 1475: 
 1476: 	ret = fn(a1, a2, a3, a4, a5, a6);
 1477: 
 1478: 	system(cmd);
 1479: 
 1480: 	free(cmd);
 1481: 
 1482: 	return ret;
 1483: }
 1484: #endif
 1485: 
 1486: /* Take a filename and filename length and return the most significant
 1487:  * filename suffix we can find.  This ignores suffixes such as "~",
 1488:  * ".bak", ".orig", ".~1~", etc. */
 1489: const char *find_filename_suffix(const char *fn, int fn_len, int *len_ptr)
 1490: {
 1491: 	const char *suf, *s;
 1492: 	BOOL had_tilde;
 1493: 	int s_len;
 1494: 
 1495: 	/* One or more dots at the start aren't a suffix. */
 1496: 	while (fn_len && *fn == '.') fn++, fn_len--;
 1497: 
 1498: 	/* Ignore the ~ in a "foo~" filename. */
 1499: 	if (fn_len > 1 && fn[fn_len-1] == '~')
 1500: 		fn_len--, had_tilde = True;
 1501: 	else
 1502: 		had_tilde = False;
 1503: 
 1504: 	/* Assume we don't find an suffix. */
 1505: 	suf = "";
 1506: 	*len_ptr = 0;
 1507: 
 1508: 	/* Find the last significant suffix. */
 1509: 	for (s = fn + fn_len; fn_len > 1; ) {
 1510: 		while (*--s != '.' && s != fn) {}
 1511: 		if (s == fn)
 1512: 			break;
 1513: 		s_len = fn_len - (s - fn);
 1514: 		fn_len = s - fn;
 1515: 		if (s_len == 4) {
 1516: 			if (strcmp(s+1, "bak") == 0
 1517: 			 || strcmp(s+1, "old") == 0)
 1518: 				continue;
 1519: 		} else if (s_len == 5) {
 1520: 			if (strcmp(s+1, "orig") == 0)
 1521: 				continue;
 1522: 		} else if (s_len > 2 && had_tilde && s[1] == '~' && isDigit(s + 2))
 1523: 			continue;
 1524: 		*len_ptr = s_len;
 1525: 		suf = s;
 1526: 		if (s_len == 1)
 1527: 			break;
 1528: 		/* Determine if the suffix is all digits. */
 1529: 		for (s++, s_len--; s_len > 0; s++, s_len--) {
 1530: 			if (!isDigit(s))
 1531: 				return suf;
 1532: 		}
 1533: 		/* An all-digit suffix may not be that significant. */
 1534: 		s = suf;
 1535: 	}
 1536: 
 1537: 	return suf;
 1538: }
 1539: 
 1540: /* This is an implementation of the Levenshtein distance algorithm.  It
 1541:  * was implemented to avoid needing a two-dimensional matrix (to save
 1542:  * memory).  It was also tweaked to try to factor in the ASCII distance
 1543:  * between changed characters as a minor distance quantity.  The normal
 1544:  * Levenshtein units of distance (each signifying a single change between
 1545:  * the two strings) are defined as a "UNIT". */
 1546: 
 1547: #define UNIT (1 << 16)
 1548: 
 1549: uint32 fuzzy_distance(const char *s1, unsigned len1, const char *s2, unsigned len2)
 1550: {
 1551: 	uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc;
 1552: 	int32 cost;
 1553: 	unsigned i1, i2;
 1554: 
 1555: 	if (!len1 || !len2) {
 1556: 		if (!len1) {
 1557: 			s1 = s2;
 1558: 			len1 = len2;
 1559: 		}
 1560: 		for (i1 = 0, cost = 0; i1 < len1; i1++)
 1561: 			cost += s1[i1];
 1562: 		return (int32)len1 * UNIT + cost;
 1563: 	}
 1564: 
 1565: 	for (i2 = 0; i2 < len2; i2++)
 1566: 		a[i2] = (i2+1) * UNIT;
 1567: 
 1568: 	for (i1 = 0; i1 < len1; i1++) {
 1569: 		diag = i1 * UNIT;
 1570: 		above = (i1+1) * UNIT;
 1571: 		for (i2 = 0; i2 < len2; i2++) {
 1572: 			left = a[i2];
 1573: 			if ((cost = *((uchar*)s1+i1) - *((uchar*)s2+i2)) != 0) {
 1574: 				if (cost < 0)
 1575: 					cost = UNIT - cost;
 1576: 				else
 1577: 					cost = UNIT + cost;
 1578: 			}
 1579: 			diag_inc = diag + cost;
 1580: 			left_inc = left + UNIT + *((uchar*)s1+i1);
 1581: 			above_inc = above + UNIT + *((uchar*)s2+i2);
 1582: 			a[i2] = above = left < above
 1583: 			      ? (left_inc < diag_inc ? left_inc : diag_inc)
 1584: 			      : (above_inc < diag_inc ? above_inc : diag_inc);
 1585: 			diag = left;
 1586: 		}
 1587: 	}
 1588: 
 1589: 	return a[len2-1];
 1590: }
 1591: 
 1592: #define BB_SLOT_SIZE     (16*1024)          /* Desired size in bytes */
 1593: #define BB_PER_SLOT_BITS (BB_SLOT_SIZE * 8) /* Number of bits per slot */
 1594: #define BB_PER_SLOT_INTS (BB_SLOT_SIZE / 4) /* Number of int32s per slot */
 1595: 
 1596: struct bitbag {
 1597: 	uint32 **bits;
 1598: 	int slot_cnt;
 1599: };
 1600: 
 1601: struct bitbag *bitbag_create(int max_ndx)
 1602: {
 1603: 	struct bitbag *bb = new(struct bitbag);
 1604: 	bb->slot_cnt = (max_ndx + BB_PER_SLOT_BITS - 1) / BB_PER_SLOT_BITS;
 1605: 
 1606: 	bb->bits = new_array0(uint32*, bb->slot_cnt);
 1607: 
 1608: 	return bb;
 1609: }
 1610: 
 1611: void bitbag_set_bit(struct bitbag *bb, int ndx)
 1612: {
 1613: 	int slot = ndx / BB_PER_SLOT_BITS;
 1614: 	ndx %= BB_PER_SLOT_BITS;
 1615: 
 1616: 	if (!bb->bits[slot])
 1617: 		bb->bits[slot] = new_array0(uint32, BB_PER_SLOT_INTS);
 1618: 
 1619: 	bb->bits[slot][ndx/32] |= 1u << (ndx % 32);
 1620: }
 1621: 
 1622: #if 0 /* not needed yet */
 1623: void bitbag_clear_bit(struct bitbag *bb, int ndx)
 1624: {
 1625: 	int slot = ndx / BB_PER_SLOT_BITS;
 1626: 	ndx %= BB_PER_SLOT_BITS;
 1627: 
 1628: 	if (!bb->bits[slot])
 1629: 		return;
 1630: 
 1631: 	bb->bits[slot][ndx/32] &= ~(1u << (ndx % 32));
 1632: }
 1633: 
 1634: int bitbag_check_bit(struct bitbag *bb, int ndx)
 1635: {
 1636: 	int slot = ndx / BB_PER_SLOT_BITS;
 1637: 	ndx %= BB_PER_SLOT_BITS;
 1638: 
 1639: 	if (!bb->bits[slot])
 1640: 		return 0;
 1641: 
 1642: 	return bb->bits[slot][ndx/32] & (1u << (ndx % 32)) ? 1 : 0;
 1643: }
 1644: #endif
 1645: 
 1646: /* Call this with -1 to start checking from 0.  Returns -1 at the end. */
 1647: int bitbag_next_bit(struct bitbag *bb, int after)
 1648: {
 1649: 	uint32 bits, mask;
 1650: 	int i, ndx = after + 1;
 1651: 	int slot = ndx / BB_PER_SLOT_BITS;
 1652: 	ndx %= BB_PER_SLOT_BITS;
 1653: 
 1654: 	mask = (1u << (ndx % 32)) - 1;
 1655: 	for (i = ndx / 32; slot < bb->slot_cnt; slot++, i = mask = 0) {
 1656: 		if (!bb->bits[slot])
 1657: 			continue;
 1658: 		for ( ; i < BB_PER_SLOT_INTS; i++, mask = 0) {
 1659: 			if (!(bits = bb->bits[slot][i] & ~mask))
 1660: 				continue;
 1661: 			/* The xor magic figures out the lowest enabled bit in
 1662: 			 * bits, and the switch quickly computes log2(bit). */
 1663: 			switch (bits ^ (bits & (bits-1))) {
 1664: #define LOG2(n) case 1u << n: return slot*BB_PER_SLOT_BITS + i*32 + n
 1665: 			    LOG2(0);  LOG2(1);  LOG2(2);  LOG2(3);
 1666: 			    LOG2(4);  LOG2(5);  LOG2(6);  LOG2(7);
 1667: 			    LOG2(8);  LOG2(9);  LOG2(10); LOG2(11);
 1668: 			    LOG2(12); LOG2(13); LOG2(14); LOG2(15);
 1669: 			    LOG2(16); LOG2(17); LOG2(18); LOG2(19);
 1670: 			    LOG2(20); LOG2(21); LOG2(22); LOG2(23);
 1671: 			    LOG2(24); LOG2(25); LOG2(26); LOG2(27);
 1672: 			    LOG2(28); LOG2(29); LOG2(30); LOG2(31);
 1673: 			}
 1674: 			return -1; /* impossible... */
 1675: 		}
 1676: 	}
 1677: 
 1678: 	return -1;
 1679: }
 1680: 
 1681: void flist_ndx_push(flist_ndx_list *lp, int ndx)
 1682: {
 1683: 	struct flist_ndx_item *item;
 1684: 
 1685: 	item = new(struct flist_ndx_item);
 1686: 	item->next = NULL;
 1687: 	item->ndx = ndx;
 1688: 	if (lp->tail)
 1689: 		lp->tail->next = item;
 1690: 	else
 1691: 		lp->head = item;
 1692: 	lp->tail = item;
 1693: }
 1694: 
 1695: int flist_ndx_pop(flist_ndx_list *lp)
 1696: {
 1697: 	struct flist_ndx_item *next;
 1698: 	int ndx;
 1699: 
 1700: 	if (!lp->head)
 1701: 		return -1;
 1702: 
 1703: 	ndx = lp->head->ndx;
 1704: 	next = lp->head->next;
 1705: 	free(lp->head);
 1706: 	lp->head = next;
 1707: 	if (!next)
 1708: 		lp->tail = NULL;
 1709: 
 1710: 	return ndx;
 1711: }
 1712: 
 1713: /* Make sure there is room for one more item in the item list.  If there
 1714:  * is not, expand the list as indicated by the value of "incr":
 1715:  *  - if incr < 0 then increase the malloced size by -1 * incr
 1716:  *  - if incr >= 0 then either make the malloced size equal to "incr"
 1717:  *    or (if that's not large enough) double the malloced size
 1718:  * After the size check, the list's count is incremented by 1 and a pointer
 1719:  * to the "new" list item is returned.
 1720:  */
 1721: void *expand_item_list(item_list *lp, size_t item_size, const char *desc, int incr)
 1722: {
 1723: 	/* First time through, 0 <= 0, so list is expanded. */
 1724: 	if (lp->malloced <= lp->count) {
 1725: 		void *new_ptr;
 1726: 		size_t expand_size;
 1727: 		if (incr < 0)
 1728: 			expand_size = -incr; /* increase slowly */
 1729: 		else if (lp->malloced < (size_t)incr)
 1730: 			expand_size = incr - lp->malloced;
 1731: 		else if (lp->malloced)
 1732: 			expand_size = lp->malloced; /* double in size */
 1733: 		else
 1734: 			expand_size = 1;
 1735: 		if (SIZE_MAX/item_size - expand_size < lp->malloced)
 1736: 			overflow_exit("expand_item_list");
 1737: 		expand_size += lp->malloced;
 1738: 		new_ptr = realloc_buf(lp->items, expand_size * item_size);
 1739: 		if (DEBUG_GTE(FLIST, 3)) {
 1740: 			rprintf(FINFO, "[%s] expand %s to %s bytes, did%s move\n",
 1741: 				who_am_i(), desc, big_num(expand_size * item_size),
 1742: 				new_ptr == lp->items ? " not" : "");
 1743: 		}
 1744: 
 1745: 		lp->items = new_ptr;
 1746: 		lp->malloced = expand_size;
 1747: 	}
 1748: 	return (char*)lp->items + (lp->count++ * item_size);
 1749: }
 1750: 
 1751: /* This zeroing of memory won't be optimized away by the compiler. */
 1752: void force_memzero(void *buf, size_t len)
 1753: {
 1754: 	volatile uchar *z = buf;
 1755: 	while (len-- > 0)
 1756: 		*z++ = '\0';
 1757: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>