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-all
mailing list