From owner-svn-src-all@FreeBSD.ORG Thu Jun 24 20:45:19 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 803201065673; Thu, 24 Jun 2010 20:45:19 +0000 (UTC) (envelope-from imp@bsdimp.com) Received: from harmony.bsdimp.com (bsdimp.com [199.45.160.85]) by mx1.freebsd.org (Postfix) with ESMTP id 0D4E28FC0C; Thu, 24 Jun 2010 20:45:18 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by harmony.bsdimp.com (8.14.3/8.14.1) with ESMTP id o5OKfg64013430; Thu, 24 Jun 2010 14:41:42 -0600 (MDT) (envelope-from imp@bsdimp.com) Date: Thu, 24 Jun 2010 14:41:53 -0600 (MDT) Message-Id: <20100624.144153.705015198875273131.imp@bsdimp.com> To: nwhitehorn@freebsd.org From: "M. Warner Losh" In-Reply-To: <20100624151959.6b00bfdd@anacreon.physics.wisc.edu> References: <201006241753.o5OHrPnU058288@svn.freebsd.org> <20100624151959.6b00bfdd@anacreon.physics.wisc.edu> X-Mailer: Mew version 6.3 on Emacs 22.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Thu_Jun_24_14_41_53_2010_185)--" Content-Transfer-Encoding: 7bit Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r209511 - head X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Jun 2010 20:45:19 -0000 ----Next_Part(Thu_Jun_24_14_41_53_2010_185)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit In message: <20100624151959.6b00bfdd@anacreon.physics.wisc.edu> Nathan Whitehorn writes: : On Thu, 24 Jun 2010 17:53:25 +0000 (UTC) : Warner Losh 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(Thu_Jun_24_14_41_53_2010_185)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename=PP 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 #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -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); +} ----Next_Part(Thu_Jun_24_14_41_53_2010_185)----