--- old/usr/src/cmd/filesync/eval.c	2017-05-26 19:16:42.712981755 -0400
+++ /dev/null	2017-05-26 19:16:42.000000000 -0400
@@ -1,997 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 1995-2003 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * module:
- *	eval.c
- *
- * purpose:
- *	routines to ascertain the current status of all of the files
- *	described by a set of rules.  Some of the routines that update
- *	file status information are also called later (during reconcilation)
- *	to reflect the changes that have been made to files.
- *
- * contents:
- *	evaluate	top level - evaluate one side of one base
- *	add_file_arg	(static) add a file to the list of files to evaluate
- *	eval_file	(static) stat a specific file, recurse on directories
- *	walker		(static) node visitor for recursive descent
- *	note_info	update a file_info structure from a stat structure
- *	do_update	(static) update one file_info structure from another
- *	update_info	update the baseline file_info from the prevailng side
- *	fakedata	(static) make it look like one side hasn't changed
- *	check_inum	(static) sanity check to detect wrong-dir errors
- *	add_glob	(static) expand a wildcard in an include rule
- *	add_run		(static) run a program to generate an include list
- *
- * notes:
- *	pay careful attention to the use of the LISTED and EVALUATE
- *	flags in each file description structure.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <string.h>
-#include <glob.h>
-#include <ftw.h>
-#include <sys/mkdev.h>
-#include <errno.h>
-
-#include "filesync.h"
-#include "database.h"
-#include "messages.h"
-#include "debug.h"
-
-/*
- * routines:
- */
-static errmask_t eval_file(struct base *, struct file *);
-static errmask_t add_file_arg(struct base *, char *);
-static int walker(const char *, const struct stat *, int, struct FTW *);
-static errmask_t add_glob(struct base *, char *);
-static errmask_t add_run(struct base *, char *);
-static void check_inum(struct file *, int);
-static void fakedata(struct file *, int);
-
-/*
- * globals
- */
-static bool_t usingsrc;	/* this pass is on the source side		*/
-static int walk_errs;	/* errors found in tree walk			*/
-static struct file *cur_dir;	/* base directory for this pass		*/
-static struct base *cur_base;	/* base pointer for this pass		*/
-
-/*
- * routine:
- *	evaluate
- *
- * purpose:
- *	to build up a baseline description for all of the files
- *	under one side of one base pair (as specified by the rules
- *	for that base pair).
- *
- * parameters:
- *	pointer to the base to be evaluated
- *	source/destination indication
- *	are we restricted to new rules
- *
- * returns:
- *	error mask
- *
- * notes:
- *	we evaluate source and destination separately, and
- *	reinterpret the include rules on each side (since there
- *	may be wild cards and programs that must be evaluated
- *	in a specific directory context).  Similarly the ignore
- *	rules must be interpreted anew for each base.
- */
-errmask_t
-evaluate(struct base *bp, side_t srcdst, bool_t newrules)
-{	errmask_t errs = 0;
-	char *dir;
-	struct rule *rp;
-	struct file *fp;
-
-	/* see if this base is still relevant		*/
-	if ((bp->b_flags & F_LISTED) == 0)
-		return (0);
-
-	/* figure out what this pass is all about	*/
-	usingsrc = (srcdst == OPT_SRC);
-
-	/*
-	 * the ignore engine maintains considerable per-base-directory
-	 * state, and so must be reset at the start of a new tree.
-	 */
-	ignore_reset();
-
-	/* all evaluation must happen from the appropriate directory */
-	dir = usingsrc ? bp->b_src_name : bp->b_dst_name;
-	if (chdir(dir) < 0) {
-		fprintf(stderr, gettext(ERR_chdir), dir);
-
-		/*
-		 * if we have -n -o we are actually willing to
-		 * pretend that nothing has changed on the missing
-		 * side.  This is actually useful on a disconnected
-		 * notebook to ask what has been changed so far.
-		 */
-		if (opt_onesided == (usingsrc ? OPT_DST : OPT_SRC)) {
-			for (fp = bp->b_files; fp; fp = fp->f_next)
-				fakedata(fp, srcdst);
-
-			if (opt_debug & DBG_EVAL)
-				fprintf(stderr, "EVAL: FAKE DATA %s dir=%s\n",
-					usingsrc ? "SRC" : "DST", dir);
-			return (0);
-		} else
-			return (ERR_NOBASE);
-	}
-
-	if (opt_debug & DBG_EVAL)
-		fprintf(stderr, "EVAL: base=%d, %s dir=%s\n",
-			bp->b_ident, usingsrc ? "SRC" : "DST", dir);
-
-	/* assemble the include list			*/
-	for (rp = bp->b_includes; rp; rp = rp->r_next) {
-
-		/* see if we are skipping old rules	*/
-		if (newrules && ((rp->r_flags & R_NEW) == 0))
-			continue;
-
-		if (rp->r_flags & R_PROGRAM)
-			errs |= add_run(bp, rp->r_file);
-		else if (rp->r_flags & R_WILD)
-			errs |= add_glob(bp, rp->r_file);
-		else
-			errs |= add_file_arg(bp, rp->r_file);
-	}
-
-	/* assemble the base-specific exclude list		*/
-	for (rp = bp->b_excludes; rp; rp = rp->r_next)
-		if (rp->r_flags & R_PROGRAM)
-			ignore_pgm(rp->r_file);
-		else if (rp->r_flags & R_WILD)
-			ignore_expr(rp->r_file);
-		else
-			ignore_file(rp->r_file);
-
-	/* add in the global excludes				*/
-	for (rp = omnibase.b_excludes; rp; rp = rp->r_next)
-		if (rp->r_flags & R_WILD)
-			ignore_expr(rp->r_file);
-		else
-			ignore_file(rp->r_file);
-
-	/*
-	 * because of restriction lists and new-rules, the baseline
-	 * may contain many more files than we are actually supposed
-	 * to look at during the impending evaluation/analysis phases
-	 *
-	 * when LIST arguments are encountered within a rule, we turn
-	 * on the LISTED flag for the associated files.  We only evaluate
-	 * files that have the LISTED flag.  We turn the LISTED flag off
-	 * after evaluating them because just because a file was enumerated
-	 * in the source doesn't mean that will necessarily be enumerated
-	 * in the destination.
-	 */
-	for (fp = bp->b_files; fp; fp = fp->f_next)
-		if (fp->f_flags & F_LISTED) {
-			errs |= eval_file(bp, fp);
-			fp->f_flags &= ~F_LISTED;
-		}
-
-	/* note that this base has been evaluated	*/
-	bp->b_flags |= F_EVALUATE;
-
-	return (errs);
-}
-
-/*
- * routine:
- *	add_file_arg
- *
- * purpose:
- *	to create file node(s) under a specified base for an explictly
- *	included file.
- *
- * parameters:
- *	pointer to associated base
- *	name of the file
- *
- * returns:
- *	error mask
- *
- * notes:
- *	the trick is that an include LIST argument need not be a file
- *	in the base directory, but may be a path passing through
- *	several intermediate directories.  If this is the case we
- *	need to ensure that all of those directories are added to
- *	the tree SPARSELY since it is not intended that they be
- *	expanded during the course of evaluation.
- *
- *	we ignore arguments that end in .. because they have the
- *	potential to walk out of the base tree, because it can
- *	result in different names for a single file, and because
- *	should never be necessary to specify files that way.
- */
-static errmask_t
-add_file_arg(struct base *bp, char *path)
-{	int i;
-	errmask_t errs = 0;
-	struct file *dp = 0;
-	struct file *fp;
-	char *s, *p;
-	char name[ MAX_NAME ];
-
-	/*
-	 * see if someone is trying to feed us a ..
-	 */
-	if (strcmp(path, "..") == 0 || prefix(path, "../") ||
-	    suffix(path, "/..") || contains(path, "/../")) {
-		fprintf(stderr, gettext(WARN_ignore), path);
-		return (ERR_MISSING);
-	}
-
-	/*
-	 * strip off any trailing "/." or "/"
-	 *	since noone will miss these, it is safe to actually
-	 *	take them off the name.  When we fall out of this
-	 *	loop, s will point where the null belongs.  We don't
-	 *	actually null the end of string yet because we want
-	 *	to leave it pristine for error messages.
-	 */
-	for (s = path; *s; s++);
-	while (s > path) {
-		if (s[-1] == '/') {
-			s--;
-			continue;
-		}
-		if (s[-1] == '.' && s > &path[1] && s[-2] == '/') {
-			s -= 2;
-			continue;
-		}
-		break;
-	}
-
-	/*
-	 * skip over leading "/" and "./" (but not over a lone ".")
-	 */
-	for (p = path; p < s; ) {
-		if (*p == '/') {
-			p++;
-			continue;
-		}
-		if (*p == '.' && s > &p[1] && p[1] == '/') {
-			p += 2;
-			continue;
-		}
-		break;
-	}
-
-	/*
-	 * if there is nothing left, we're miffed, but done
-	 */
-	if (p >= s) {
-		fprintf(stderr, gettext(WARN_ignore), path);
-		return (ERR_MISSING);
-	} else {
-		/*
-		 * this is actually storing a null into the argument,
-		 * but it is OK to do this because the stuff we are
-		 * truncating really is garbage that noone will ever
-		 * want to see.
-		 */
-		*s = 0;
-		path = p;
-	}
-
-	/*
-	 * see if there are any restrictions that would force
-	 * us to ignore this argument
-	 */
-	if (check_restr(bp, path) == 0)
-		return (0);
-
-	while (*path) {
-		/* lex off the next name component	*/
-		for (i = 0; path[i] && path[i] != '/'; i++)
-			name[i] = path[i];
-		name[i] = 0;
-
-		/* add it into the database		*/
-		fp = (dp == 0)  ? add_file_to_base(bp, name)
-				: add_file_to_dir(dp, name);
-
-		/* see if this was an intermediate directory	*/
-		if (path[i] == '/') {
-			fp->f_flags |= F_LISTED | F_SPARSE;
-			path += i+1;
-		} else {
-			fp->f_flags |= F_LISTED;
-			path += i;
-		}
-
-		dp = fp;
-	}
-
-	return (errs);
-}
-
-/*
- * routine:
- *	eval_file
- *
- * purpose:
- *	to evaluate one named file under a particular directory
- *
- * parameters:
- *	pointer to base structure
- *	pointer to file structure
- *
- * returns:
- *	error mask
- *	filled in evaluations in the baseline
- *
- * note:
- *	due to new rules and other restrictions we may not be expected
- *	to evaluate the entire tree.  We should only be called on files
- *	that are LISTed, and we should only invoke ourselves recursively
- *	on such files.
- */
-static errmask_t
-eval_file(struct base *bp, struct file *fp)
-{	errmask_t errs = 0;
-	int rc;
-	char *name;
-	struct file *cp;
-	struct stat statb;
-
-	if (opt_debug & DBG_EVAL)
-		fprintf(stderr, "EVAL: FILE, flags=%s, name=%s\n",
-			showflags(fileflags, fp->f_flags), fp->f_name);
-
-	/* stat the file and fill in the file structure information	*/
-	name = get_name(fp);
-
-#ifdef 	DBG_ERRORS
-	/* see if we should simulated a stat error on this file	*/
-	if (opt_errors && (errno = dbg_chk_error(name, usingsrc ? 's' : 'S')))
-		rc = -1;
-	else
-#endif
-	rc = lstat(name, &statb);
-
-	if (rc < 0) {
-		if (opt_debug & DBG_EVAL)
-			fprintf(stderr, "EVAL: FAIL lstat, errno=%d\n", errno);
-		switch (errno) {
-		    case EACCES:
-			fp->f_flags |= F_STAT_ERROR;
-			return (ERR_PERM);
-		    case EOVERFLOW:
-			fp->f_flags |= F_STAT_ERROR;
-			return (ERR_UNRESOLVED);
-		    default:
-			return (ERR_MISSING);
-		}
-	}
-
-	/* record the information we've just gained			*/
-	note_info(fp, &statb, usingsrc ? OPT_SRC : OPT_DST);
-
-	/*
-	 * checking for ACLs is expensive, so we only do it if we
-	 * have been asked to, or if we have reason to believe that
-	 * the file has an ACL
-	 */
-	if (opt_acls || fp->f_info[OPT_BASE].f_numacls)
-		(void) get_acls(name,
-				&fp->f_info[usingsrc ? OPT_SRC : OPT_DST]);
-
-
-	/* note that this file has been evaluated			*/
-	fp->f_flags |= F_EVALUATE;
-
-	/* if it is not a directory, a simple stat will suffice	*/
-	if ((statb.st_mode & S_IFMT) != S_IFDIR)
-		return (0);
-
-	/*
-	 * as a sanity check, we look for changes in the I-node
-	 * numbers associated with LISTed directories ... on the
-	 * assumption that these are high-enough up on the tree
-	 * that they aren't likely to change, and so a change
-	 * might indicate trouble.
-	 */
-	if (fp->f_flags & F_LISTED)
-		check_inum(fp, usingsrc);
-
-	/*
-	 * sparse directories are on the path between a base and
-	 * a listed directory.  As such, we don't walk these
-	 * directories.  Rather, we just enumerate the LISTed
-	 * files.
-	 */
-	if (fp->f_flags & F_SPARSE) {
-		push_name(fp->f_name);
-
-		/* this directory isn't supposed to be fully walked	*/
-		for (cp = fp->f_files; cp; cp = cp->f_next)
-			if (cp->f_flags & F_LISTED) {
-				errs |= eval_file(bp, cp);
-				cp->f_flags &= ~F_LISTED;
-			}
-		pop_name();
-	} else {
-		/* fully walk the tree beneath this directory		*/
-		walk_errs = 0;
-		cur_base = bp;
-		cur_dir = fp;
-		nftw(get_name(fp), &walker, MAX_DEPTH, FTW_PHYS|FTW_MOUNT);
-		errs |= walk_errs;
-	}
-
-	return (errs);
-}
-
-/*
- * routine:
- *	walker
- *
- * purpose:
- *	node visitor for recursive directory enumeration
- *
- * parameters:
- *	name of file
- *	pointer to stat buffer for file
- *	file type
- *	FTW structure (base name offset, walk-depth)
- *
- * returns:
- *	0 	continue
- *	-1	stop
- *
- * notes:
- *	Ignoring files is easy, but ignoring directories is harder.
- *	Ideally we would just decline to walk the trees beneath
- *	ignored directories, but ftw doesn't allow the walker to
- *	tell it to "don't enter this directory, but continue".
- *
- *	Instead, we have to set a global to tell us to ignore
- *	everything under that tree.  The variable ignore_level
- *	is set to a level, below which, everything should be
- *	ignored.  Once the enumeration rises above that level
- *	again, we clear it.
- */
-static int
-walker(const char *name, const struct stat *sp, int type,
-		struct FTW *ftwx)
-{	const char *path;
-	struct file *fp;
-	int level;
-	int which;
-	bool_t restr;
-	static struct file *dirstack[ MAX_DEPTH + 1 ];
-	static int ignore_level = 0;
-
-	path = &name[ftwx->base];
-	level = ftwx->level;
-	which = usingsrc ? OPT_SRC : OPT_DST;
-
-	/*
-	 * see if we are ignoring all files in this sub-tree
-	 */
-	if (ignore_level > 0 && level >= ignore_level) {
-		if (opt_debug & DBG_EVAL)
-			fprintf(stderr, "EVAL: SKIP file=%s\n", name);
-		return (0);
-	} else
-		ignore_level = 0;	/* we're through ignoring	*/
-
-#ifdef 	DBG_ERRORS
-	/* see if we should simulated a stat error on this file	*/
-	if (opt_errors && dbg_chk_error(name, usingsrc ? 'n' : 'N'))
-		type = FTW_NS;
-#endif
-
-	switch (type) {
-	case FTW_F:	/* file 		*/
-	case FTW_SL:	/* symbolic link	*/
-		/*
-		 * filter out files of inappropriate types
-		 */
-		switch (sp->st_mode & S_IFMT) {
-			default:	/* anything else we ignore	*/
-				return (0);
-
-			case S_IFCHR:
-			case S_IFBLK:
-			case S_IFREG:
-			case S_IFLNK:
-				if (opt_debug & DBG_EVAL)
-					fprintf(stderr,
-						"EVAL: WALK lvl=%d, file=%s\n",
-						level, path);
-
-				/* see if we were told to ignore this one */
-				if (ignore_check(path))
-					return (0);
-
-				fp = add_file_to_dir(dirstack[level-1], path);
-				note_info(fp, sp, which);
-
-				/* note that this file has been evaluated */
-				fp->f_flags |= F_EVALUATE;
-
-				/* see if we should check ACLs		*/
-				if ((sp->st_mode & S_IFMT) == S_IFLNK)
-					return (0);
-
-				if (fp->f_info[OPT_BASE].f_numacls || opt_acls)
-					(void) get_acls(name,
-							&fp->f_info[which]);
-
-				return (0);
-		}
-
-	case FTW_D:	/* enter directory 		*/
-		if (opt_debug & DBG_EVAL)
-			fprintf(stderr, "EVAL: WALK lvl=%d, dir=%s\n",
-				level, name);
-
-		/*
-		 * if we have been told to ignore this directory, we should
-		 * ignore all files under it.  Similarly, if we are outside
-		 * of our restrictions, we should ignore the entire subtree
-		 */
-		restr = check_restr(cur_base, name);
-		if (restr == FALSE || ignore_check(path)) {
-			ignore_level = level + 1;
-			return (0);
-		}
-
-		fp = (level == 0) ?  cur_dir :
-		    add_file_to_dir(dirstack[level-1], path);
-
-		note_info(fp, sp, which);
-
-		/* see if we should be checking ACLs	*/
-		if (opt_acls || fp->f_info[OPT_BASE].f_numacls)
-			(void) get_acls(name, &fp->f_info[which]);
-
-		/* note that this file has been evaluated */
-		fp->f_flags |= F_EVALUATE;
-
-		/* note the parent of the children to come	*/
-		dirstack[ level ] = fp;
-
-		/*
-		 * PROBLEM: given the information that nftw provides us with,
-		 *	    how do we know that we have confirmed the fact
-		 *	    that a file no longer exists.  Or to rephrase
-		 *	    this in filesync terms, how do we know when to
-		 *	    set the EVALUATE flag for a file we didn't find.
-		 *
-		 * if we are going to fully scan this directory (we
-		 * are completely within our restrictions) then we
-		 * will be confirming the non-existance of files that
-		 * used to be here.  Thus any file that was in the
-		 * base line under this directory should be considered
-		 * to have been evaluated (whether we found it or not).
-		 *
-		 * if, however, we are only willing to scan selected
-		 * files (due to restrictions), or the file was not
-		 * in the baseline, then we should not assume that this
-		 * pass will evaluate it.
-		 */
-		if (restr == TRUE)
-			for (fp = fp->f_files; fp; fp = fp->f_next) {
-				if ((fp->f_flags & F_IN_BASELINE) == 0)
-					continue;
-				fp->f_flags |= F_EVALUATE;
-			}
-
-		return (0);
-
-	case FTW_DP:	/* end of directory	*/
-		dirstack[ level ] = 0;
-		break;
-
-	case FTW_DNR:	/* unreadable directory	*/
-		walk_errs |= ERR_PERM;
-		/* FALLTHROUGH	*/
-	case FTW_NS:	/* unstatable file	*/
-		if (opt_debug & DBG_EVAL)
-			fprintf(stderr, "EVAL: walker can't stat/read %s\n",
-				name);
-		fp = (level == 0) ?  cur_dir :
-			add_file_to_dir(dirstack[level-1], path);
-		fp->f_flags |= F_STAT_ERROR;
-		walk_errs |= ERR_UNRESOLVED;
-		break;
-	}
-
-	return (0);
-}
-
-/*
- * routine:
- *	note_info
- *
- * purpose:
- * 	to record information about a file in its file node
- *
- * parameters
- *	file node pointer
- *	stat buffer
- *	which file info structure to fill in (0-2)
- *
- * returns
- *	void
- */
-void
-note_info(struct file *fp, const struct stat *sp, side_t which)
-{	struct fileinfo *ip;
-	static int flags[3] = { F_IN_BASELINE, F_IN_SOURCE, F_IN_DEST };
-
-	ip = &fp->f_info[ which ];
-
-	ip->f_ino	= sp->st_ino;
-	ip->f_d_maj	= major(sp->st_dev);
-	ip->f_d_min	= minor(sp->st_dev);
-	ip->f_type	= sp->st_mode & S_IFMT;
-	ip->f_size	= sp->st_size;
-	ip->f_mode	= sp->st_mode & S_IAMB;
-	ip->f_uid	= sp->st_uid;
-	ip->f_gid	= sp->st_gid;
-	ip->f_modtime	= sp->st_mtim.tv_sec;
-	ip->f_modns	= sp->st_mtim.tv_nsec;
-	ip->f_nlink	= sp->st_nlink;
-	ip->f_rd_maj	= major(sp->st_rdev);
-	ip->f_rd_min	= minor(sp->st_rdev);
-
-	/* indicate where this file has been found	*/
-	fp->f_flags |= flags[which];
-
-	if (opt_debug & DBG_STAT)
-		fprintf(stderr,
-			"STAT: list=%d, file=%s, mod=%08lx.%08lx, nacl=%d\n",
-			which, fp->f_name, ip->f_modtime, ip->f_modns,
-			ip->f_numacls);
-}
-
-/*
- * routine:
- *	do_update
- *
- * purpose:
- * 	to copy information from one side into the baseline in order
- *	to reflect the effects of recent reconciliation actions
- *
- * parameters
- *	fileinfo structure to be updated
- *	fileinfo structure to be updated from
- *
- * returns
- *	void
- *
- * note:
- *	we play fast and loose with the copying of acl chains
- *	here, but noone is going to free or reuse any of this
- * 	memory anyway.  None the less, I do feel embarassed.
- */
-static void
-do_update(struct fileinfo *np, struct fileinfo *ip)
-{
-	/* get most of the fields from the designated "right" copy */
-	np->f_type	= ip->f_type;
-	np->f_size	= ip->f_size;
-	np->f_mode	= ip->f_mode;
-	np->f_uid	= ip->f_uid;
-	np->f_gid	= ip->f_gid;
-	np->f_rd_maj	= ip->f_rd_maj;
-	np->f_rd_min	= ip->f_rd_min;
-
-	/* see if facls have to be propagated	*/
-	np->f_numacls = ip->f_numacls;
-	np->f_acls = ip->f_acls;
-}
-
-/*
- * routine:
- *	update_info
- *
- * purpose:
- * 	to update the baseline to reflect recent reconcliations
- *
- * parameters
- *	file node pointer
- *	which file info structure to trust (1/2)
- *
- * returns
- *	void
- *
- * note:
- *	after we update this I-node we run down the entire
- *	change list looking for links and update them too.
- *	This is to ensure that when subsequent links get
- *	reconciled, they are already found to be up-to-date.
- */
-void
-update_info(struct file *fp, side_t which)
-{
-	/* first update the specified fileinfo structure	*/
-	do_update(&fp->f_info[ OPT_BASE ], &fp->f_info[ which ]);
-
-	if (opt_debug & DBG_STAT)
-		fprintf(stderr,
-			"STAT: UPDATE from=%d, file=%s, mod=%08lx.%08lx\n",
-			which, fp->f_name, fp->f_info[ which ].f_modtime,
-			fp->f_info[ which ].f_modns);
-}
-
-/*
- * routine:
- *	fakedata
- *
- * purpose:
- *	to populate a tree we cannot analyze with information from the baseline
- *
- * parameters:
- *	file to be faked
- *	which side to fake
- *
- * notes:
- *	We would never use this for real reconciliation, but it is useful
- *	if a disconnected notebook user wants to find out what has been
- *	changed so far.  We only do this if we are notouch and oneway.
- */
-static void
-fakedata(struct file *fp, int which)
-{	struct file *lp;
-
-	/* pretend we actually found the file			*/
-	fp->f_flags |= (which == OPT_SRC) ? F_IN_SOURCE : F_IN_DEST;
-
-	/* update the specified side from the baseline		*/
-	do_update(&fp->f_info[ which ], &fp->f_info[ OPT_BASE ]);
-	fp->f_info[which].f_nlink = (which == OPT_SRC) ? fp->f_s_nlink :
-							fp->f_d_nlink;
-	fp->f_info[which].f_modtime = (which == OPT_SRC) ? fp->f_s_modtime :
-							fp->f_d_modtime;
-
-	for (lp = fp->f_files; lp; lp = lp->f_next)
-		fakedata(lp, which);
-}
-
-/*
- * routine:
- *	check_inum
- *
- * purpose:
- *	sanity check inode #s on directories that are unlikely to change
- *
- * parameters:
- *	pointer to file node
- *	are we using the source
- *
- * note:
- *	the purpose of this sanity check is to catch a case where we
- *	have somehow been pointed at a directory that is not the one
- *	we expected to be reconciling against.  It could happen if a
- *	variable wasn't properly set, or if we were in a new domain
- *	where an old path no longer worked.  This could result in
- *	bazillions of inappropriate propagations and deletions.
- */
-void
-check_inum(struct file *fp, int src)
-{	struct fileinfo *ip;
-
-	/*
-	 * we validate the inode number and the major device numbers ... minor
-	 * device numbers for NFS devices are arbitrary
-	 */
-	if (src) {
-		ip = &fp->f_info[ OPT_SRC ];
-		if (ip->f_ino == fp->f_s_inum && ip->f_d_maj == fp->f_s_maj)
-			return;
-
-		/* if file was newly created/deleted, this isn't warnable */
-		if (fp->f_s_inum == 0 || ip->f_ino == 0)
-			return;
-
-		if (opt_verbose)
-			fprintf(stdout, V_change, fp->f_name, TXT_src,
-				fp->f_s_maj, fp->f_s_min, fp->f_s_inum,
-				ip->f_d_maj, ip->f_d_min, ip->f_ino);
-	} else {
-		ip = &fp->f_info[ OPT_DST ];
-		if (ip->f_ino == fp->f_d_inum && ip->f_d_maj == fp->f_d_maj)
-			return;
-
-		/* if file was newly created/deleted, this isn't warnable */
-		if (fp->f_d_inum == 0 || ip->f_ino == 0)
-			return;
-
-		if (opt_verbose)
-			fprintf(stdout, V_change, fp->f_name, TXT_dst,
-				fp->f_d_maj, fp->f_d_min, fp->f_d_inum,
-				ip->f_d_maj, ip->f_d_min, ip->f_ino);
-	}
-
-	/* note that something has changed	*/
-	inum_changes++;
-}
-
-/*
- * routine:
- *	add_glob
- *
- * purpose:
- *	to evaluate a wild-carded expression into names, and add them
- *	to the evaluation list.
- *
- * parameters:
- *	base
- *	expression
- *
- * returns:
- * 	error mask
- *
- * notes:
- *	we don't want to allow any patterns to expand to a . because
- *	that could result in re-evaluation of a tree under a different
- *	name.  The real thing we are worried about here is ".*" which
- *	is meant to pick up . files, but shouldn't pick up . and ..
- */
-static errmask_t
-add_glob(struct base *bp, char *expr)
-{	int i;
-	errmask_t errs = 0;
-#ifndef BROKEN_GLOB
-	glob_t gt;
-	char *s;
-
-	/* expand the regular expression	*/
-	i = glob(expr, GLOB_NOSORT, 0, &gt);
-	if (i == GLOB_NOMATCH)
-		return (ERR_MISSING);
-	if (i) {
-		/* this shouldn't happen, so it's cryptic message time	*/
-		fprintf(stderr, "EVAL: add_glob globfail expr=%s, ret=%d\n",
-				expr, i);
-		return (ERR_OTHER);
-	}
-
-	for (i = 0; i < gt.gl_pathc; i++) {
-		/* make sure we don't let anything expand to a . */
-		s = basename(gt.gl_pathv[i]);
-		if (strcmp(s, ".") == 0) {
-			fprintf(stderr, gettext(WARN_ignore), gt.gl_pathv[i]);
-			errs |= ERR_MISSING;
-			continue;
-		}
-
-		errs |= add_file_arg(bp, gt.gl_pathv[i]);
-	}
-
-	globfree(&gt);
-#else
-	/*
-	 * in 2.4 the glob function was completely broken.  The
-	 * easiest way to get around this problem is to just ask
-	 * the shell to do the work for us.  This is much slower
-	 * but produces virtually identical results.  Given that
-	 * the 2.4 version is internal use only, I probably won't
-	 * worry about the performance difference (less than 2
-	 * seconds for a typical filesync command, and no hit
-	 * at all if they don't use regular expressions in
-	 * their LIST rules).
-	 */
-	char cmdbuf[MAX_LINE];
-
-	sprintf(cmdbuf, "ls -d %s 2> /dev/null", expr);
-	errs |= add_run(bp, cmdbuf);
-#endif
-
-	return (errs);
-}
-
-
-/*
- * routine:
- *	add_run
- *
- * purpose:
- *	to run a command and capture the names it outputs in the
- *	evaluation list.
- *
- * parameters
- *	base
- *	command
- *
- * returns:
- *	error mask
- */
-static errmask_t
-add_run(struct base *bp, char *cmd)
-{	char *s, *p;
-	FILE *fp;
-	char inbuf[ MAX_LINE ];
-	errmask_t errs = 0;
-	int added = 0;
-
-	if (opt_debug & DBG_EVAL)
-		fprintf(stderr, "EVAL: RUN %s\n", cmd);
-
-	/* run the command and collect its ouput	*/
-	fp = popen(cmd, "r");
-	if (fp == NULL) {
-		fprintf(stderr, gettext(ERR_badrun), cmd);
-		return (ERR_OTHER);
-	}
-
-	while (fgets(inbuf, sizeof (inbuf), fp) != 0) {
-		/* strip off any trailing newline	*/
-		for (s = inbuf; *s && *s != '\n'; s++);
-		*s = 0;
-
-		/* skip any leading white space		*/
-		for (s = inbuf; *s == ' ' || *s == '\t'; s++);
-
-		/* make sure we don't let anything expand to a . */
-		p = basename(s);
-		if (strcmp(p, ".") == 0) {
-			fprintf(stderr, gettext(WARN_ignore), s);
-			errs |= ERR_MISSING;
-			continue;
-		}
-
-		/* add this file to the list		*/
-		if (*s) {
-			errs |= add_file_arg(bp, s);
-			added++;
-		}
-	}
-
-	pclose(fp);
-
-#ifdef	BROKEN_GLOB
-	/*
-	 * if we are being used to simulate libc glob, and we didn't
-	 * return anything, we should probably assume that the regex
-	 * was unable to match anything
-	 */
-	if (added == 0)
-		errs |= ERR_MISSING;
-#endif
-	return (errs);
-}
