svn commit: r209511 - head

M. Warner Losh imp at bsdimp.com
Thu Jun 24 20:45:19 UTC 2010


In message: <20100624151959.6b00bfdd at anacreon.physics.wisc.edu>
            Nathan Whitehorn <nwhitehorn at freebsd.org> writes:
: On Thu, 24 Jun 2010 17:53:25 +0000 (UTC)
: Warner Losh <imp at FreeBSD.org> wrote:
: 
: > Author: imp
: > Date: Thu Jun 24 17:53:25 2010
: > New Revision: 209511
: > URL: http://svn.freebsd.org/changeset/base/209511
: > 
: > Log:
: >   Merge from tbemd:
: >   
: >   use MACHINE_CPUARCH instead of MACHINE_CPU since the sources for the
: >   CSU is based on MACHINE_CPUARCH
: >   
: >   Reviewed by:	arch@ (twice)
: 
: This is not always true. For example, on powerpc64, the ABI is
: different enough between powerpc and powerpc64, which share a CPUARCH,
: that the csu code shares very little. I can work around this with
: Makefile or preprocessor hacks, of course, but would be it be possible
: here instead to check for MACHINE_ARCH before falling back to
: MACHINE_CPUARCH?

Does this patch do what you are asking?

Warner
-------------- next part --------------
Index: mtree.h
===================================================================
--- mtree.h	(revision 205300)
+++ mtree.h	(working copy)
@@ -48,6 +48,11 @@
 	char	*sha1digest;			/* SHA-1 digest */
 	char	*sha256digest;			/* SHA-256 digest */
 	char	*rmd160digest;			/* RIPEMD160 digest */
+	char	*sha384digest;			/* SHA384 digest */
+	char	*sha512digest;			/* SHA512 digest */
+	char	*tags;				/* tags, comma delimited,
+						 * also with leading and
+						 * trailing commas */
 	char	*slink;				/* symbolic link reference */
 	uid_t	st_uid;				/* uid */
 	gid_t	st_gid;				/* gid */
Index: spec.c
===================================================================
--- spec.c	(revision 205300)
+++ spec.c	(working copy)
@@ -37,12 +37,14 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <assert.h>
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <fts.h>
 #include <grp.h>
 #include <pwd.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <vis.h>
@@ -51,19 +53,261 @@
 
 int lineno;				/* Current spec line number. */
 
-static void	 set(char *, NODE *);
-static void	 unset(char *, NODE *);
+static void	addchild(NODE *, NODE *);
+static	void	replacenode(NODE *, NODE *);
+static void	set(char *, NODE *);
+static void	unset(char *, NODE *);
+static	int	nodecmp(const NODE *, const NODE *);
 
+#define REPLACEPTR(x,v)	do { if ((x)) free((x)); (x) = (v); } while (0)
+
+#define mtree_Sflag 0		/* kludge */
+
+static u_int
+nodetoino(u_int type)
+{
+
+	switch (type) {
+	case F_BLOCK:
+		return S_IFBLK;
+	case F_CHAR:
+		return S_IFCHR;
+	case F_DIR:
+		return S_IFDIR;
+	case F_FIFO:
+		return S_IFIFO;
+	case F_FILE:
+		return S_IFREG;
+	case F_LINK:
+		return S_IFLNK;
+#ifdef S_IFSOCK
+	case F_SOCK:
+		return S_IFSOCK;
+#endif
+	default:
+		printf("unknown type %d", type);
+		abort();
+	}
+	/* NOTREACHED */
+}
+
+static const char *
+nodetype(u_int type)
+{
+
+	return (inotype(nodetoino(type)));
+}
+
+static void
+mtree_err(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vwarnx(fmt, ap);
+	va_end(ap);
+#if 0
+	if (mtree_lineno)
+		warnx("failed at line %lu of the specification",
+		    (u_long) mtree_lineno);
+#endif
+	exit(1);
+	/* NOTREACHED */
+}
+
+static void
+replacenode(NODE *cur, NODE *new)
+{
+
+#define REPLACE(x)	cur->x = new->x
+#define REPLACESTR(x)	REPLACEPTR(cur->x,new->x)
+
+	if (cur->type != new->type) {
+#if 0
+		if (mtree_Mflag) {
+				/*
+				 * merge entries with different types; we
+				 * don't want children retained in this case.
+				 */
+			REPLACE(type);
+			free_nodes(cur->child);
+			cur->child = NULL;
+		} else {
+#endif
+			mtree_err(
+			    "existing entry for `%s', type `%s'"
+			    " does not match type `%s'",
+			    cur->name, nodetype(cur->type),
+			    nodetype(new->type));
+#if 0
+		}
+#endif
+	}
+
+	REPLACE(st_size);
+	REPLACE(st_mtimespec);
+	REPLACESTR(slink);
+	if (cur->slink != NULL) {
+		if ((cur->slink = strdup(new->slink)) == NULL)
+			mtree_err("memory allocation error");
+		if (strunvis(cur->slink, new->slink) == -1)
+			mtree_err("strunvis failed on `%s'", new->slink);
+		free(new->slink);
+	}
+	REPLACE(st_uid);
+	REPLACE(st_gid);
+	REPLACE(st_mode);
+//	REPLACE(st_rdev);
+	REPLACE(st_flags);
+	REPLACE(st_nlink);
+	REPLACE(cksum);
+	REPLACESTR(md5digest);
+	REPLACESTR(rmd160digest);
+	REPLACESTR(sha1digest);
+	REPLACESTR(sha256digest);
+	REPLACESTR(sha384digest);
+	REPLACESTR(sha512digest);
+	REPLACESTR(tags);
+//	REPLACE(lineno);
+	REPLACE(flags);
+	free(new);
+}
+
+/*
+ * addchild --
+ *	Add the centry node as a child of the pathparent node.	If
+ *	centry is a duplicate, call replacenode().  If centry is not
+ *	a duplicate, insert it into the linked list referenced by
+ *	pathparent->child.  Keep the list sorted if Sflag is set.
+ */
+static void
+addchild(NODE *pathparent, NODE *centry)
+{
+	NODE *samename;      /* node with the same name as centry */
+	NODE *replacepos;    /* if non-NULL, centry should replace this node */
+	NODE *insertpos;     /* if non-NULL, centry should be inserted
+			      * after this node */
+	NODE *cur;           /* for stepping through the list */
+	NODE *last;          /* the last node in the list */
+	int cmp;
+
+	samename = NULL;
+	replacepos = NULL;
+	insertpos = NULL;
+	last = NULL;
+	cur = pathparent->child;
+	if (cur == NULL) {
+		/* centry is pathparent's first and only child node so far */
+		pathparent->child = centry;
+		return;
+	}
+
+	/*
+	 * pathparent already has at least one other child, so add the
+	 * centry node to the list.
+	 *
+	 * We first scan through the list looking for an existing node
+	 * with the same name (setting samename), and also looking
+	 * for the correct position to replace or insert the new node
+	 * (setting replacepos and/or insertpos).
+	 */
+	for (; cur != NULL; last = cur, cur = cur->next) {
+		if (strcmp(centry->name, cur->name) == 0) {
+			samename = cur;
+		}
+		if (mtree_Sflag) {
+			cmp = nodecmp(centry, cur);
+			if (cmp == 0) {
+				replacepos = cur;
+			} else if (cmp > 0) {
+				insertpos = cur;
+			}
+		}
+	}
+	if (! mtree_Sflag) {
+		if (samename != NULL) {
+			/* replace node with same name */
+			replacepos = samename;
+		} else {
+			/* add new node at end of list */
+			insertpos = last;
+		}
+	}
+
+	if (samename != NULL) {
+		/*
+		 * We found a node with the same name above.  Call
+		 * replacenode(), which will either exit with an error,
+		 * or replace the information in the samename node and
+		 * free the information in the centry node.
+		 */
+		replacenode(samename, centry);
+		if (samename == replacepos) {
+			/* The just-replaced node was in the correct position */
+			return;
+		}
+		if (samename == insertpos || samename->prev == insertpos) {
+			/*
+			 * We thought the new node should be just before
+			 * or just after the replaced node, but that would
+			 * be equivalent to just retaining the replaced node.
+			 */
+			return;
+		}
+
+		/*
+		 * The just-replaced node is in the wrong position in
+		 * the list.  This can happen if sort order depends on
+		 * criteria other than the node name.
+		 *
+		 * Make centry point to the just-replaced node.	 Unlink
+		 * the just-replaced node from the list, and allow it to
+		 * be insterted in the correct position later.
+		 */
+		centry = samename;
+		if (centry->prev)
+			centry->prev->next = centry->next;
+		else {
+			/* centry->next is the new head of the list */
+			pathparent->child = centry->next;
+			assert(centry->next != NULL);
+		}
+		if (centry->next)
+			centry->next->prev = centry->prev;
+		centry->prev = NULL;
+		centry->next = NULL;
+	}
+
+	if (insertpos == NULL) {
+		/* insert centry at the beginning of the list */
+		pathparent->child->prev = centry;
+		centry->next = pathparent->child;
+		centry->prev = NULL;
+		pathparent->child = centry;
+	} else {
+		/* insert centry into the list just after insertpos */
+		centry->next = insertpos->next;
+		insertpos->next = centry;
+		centry->prev = insertpos;
+		if (centry->next)
+			centry->next->prev = centry;
+	}
+	return;
+}
+
 NODE *
 mtree_readspec(FILE *fi)
 {
-	NODE *centry, *last;
-	char *p;
+	NODE *centry, *last, *pathparent, *cur;
+	char *p, *e, *next;
 	NODE ginfo, *root;
 	int c_cur, c_next;
-	char buf[2048];
+	char buf[2048], *tname;
+	size_t tnamelen;
 
 	centry = last = root = NULL;
+	tname = NULL;
+	tnamelen = 0;
 	bzero(&ginfo, sizeof(ginfo));
 	c_cur = c_next = 0;
 	for (lineno = 1; fgets(buf, sizeof(buf), fi);
@@ -100,29 +344,30 @@
 			continue;
 		}
 
+#if 1
 		/* Grab file name, "$", "set", or "unset". */
+		next = buf;
+		while ((p = strsep(&next, " \t")) != NULL && *p == '\0')
+			continue;
+		if (p == NULL)
+			mtree_err("missing field");
+#else
+		/* Grab file name, "$", "set", or "unset". */
 		if ((p = strtok(p, "\n\t ")) == NULL)
 			errx(1, "line %d: missing field", lineno);
+#endif
 
-		if (p[0] == '/')
-			switch(p[1]) {
-			case 's':
-				if (strcmp(p + 1, "set"))
-					break;
-				set(NULL, &ginfo);
-				continue;
-			case 'u':
-				if (strcmp(p + 1, "unset"))
-					break;
-				unset(NULL, &ginfo);
-				continue;
-			}
+		if (p[0] == '/') {
+			if (strcmp(p + 1, "set") == 0)
+				set(next, &ginfo);
+			else if (strcmp(p + 1, "unset") == 0)
+				unset(next, &ginfo);
+			else
+				mtree_err("invalid specification `%s'", p);
+			continue;
+		}
 
-		if (index(p, '/'))
-			errx(1, "line %d: slash character in file name",
-			lineno);
-
-		if (!strcmp(p, "..")) {
+		if (strcmp(p, "..") == 0) {
 			/* Don't go up, if haven't gone down. */
 			if (!root)
 				goto noparent;
@@ -137,6 +382,33 @@
 noparent:		errx(1, "line %d: no parent node", lineno);
 		}
 
+		/* XXX investigate the NetBSD strvis extentions */
+
+		pathparent = NULL;
+		if (strchr(p, '/') != NULL) {
+			cur = root;
+			for (; (e = strchr(p, '/')) != NULL; p = e+1) {
+				if (p == e)
+					continue;	/* handle // */
+				*e = '\0';
+				if (strcmp(p, ".") != 0) {
+					while (cur &&
+					    strcmp(cur->name, p) != 0) {
+						cur = cur->next;
+					}
+				}
+				if (cur == NULL || cur->type != F_DIR) {
+					mtree_err("%s: %s", tname,
+					"missing directory in specification");
+				}
+				*e = '/';
+				pathparent = cur;
+				cur = cur->child;
+			}
+			if (*p == '\0')
+				mtree_err("%s: empty leaf element", tname);
+		}
+
 		if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
 			errx(1, "calloc");
 		*centry = ginfo;
@@ -147,16 +419,45 @@
 			errx(1, "filename %s is ill-encoded", p);
 		set(NULL, centry);
 
-		if (!root) {
+		if (root == NULL) {
+				/*
+				 * empty tree
+				 */
+			if (strcmp(centry->name, ".") != 0 ||
+			    centry->type != F_DIR)
+				mtree_err(
+				    "root node must be the directory `.'");
 			last = root = centry;
 			root->parent = root;
+		} else if (pathparent != NULL) {
+				/*
+				 * full path entry; add or replace
+				 */
+			centry->parent = pathparent;
+			addchild(pathparent, centry);
+			last = centry;
+		} else if (strcmp(centry->name, ".") == 0) {
+				/*
+				 * duplicate "." entry; always replace
+				 */
+			replacenode(root, centry);
 		} else if (last->type == F_DIR && !(last->flags & F_DONE)) {
+				/*
+				 * new relative child in current dir;
+				 * add or replace
+				 */
 			centry->parent = last;
-			last = last->child = centry;
+			addchild(last, centry);
+			last = centry;
 		} else {
+				/*
+				 * new relative child in parent dir
+				 * (after encountering ".." entry);
+				 * add or replace
+				 */
 			centry->parent = last->parent;
-			centry->prev = last;
-			last = last->next = centry;
+			addchild(last->parent, centry);
+			last = centry;
 		}
 	}
 	return (root);
@@ -321,3 +622,23 @@
 	while ((p = strtok(t, "\n\t ")))
 		ip->flags &= ~parsekey(p, NULL);
 }
+/*
+ * nodecmp --
+ *	used as a comparison function by addchild() to control the order
+ *	in which entries appear within a list of sibling nodes.	 We make
+ *	directories sort after non-directories, but otherwise sort in
+ *	strcmp() order.
+ *
+ * Keep this in sync with dcmp() in create.c.
+ */
+static int
+nodecmp(const NODE *a, const NODE *b)
+{
+
+	if ((a->type & F_DIR) != 0) {
+		if ((b->type & F_DIR) == 0)
+			return 1;
+	} else if ((b->type & F_DIR) != 0)
+		return -1;
+	return strcmp(a->name, b->name);
+}


More information about the svn-src-head mailing list