In message: <20100624151959.6b00b...@anacreon.physics.wisc.edu>
            Nathan Whitehorn <nwhiteh...@freebsd.org> writes:
: On Thu, 24 Jun 2010 17:53:25 +0000 (UTC)
: Warner Losh <i...@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
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);
+}
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to