Index: vendor/NetBSD/mtree/dist/create.c =================================================================== --- vendor/NetBSD/mtree/dist/create.c (revision 273788) +++ vendor/NetBSD/mtree/dist/create.c (revision 273789) @@ -1,472 +1,476 @@ -/* $NetBSD: create.c,v 1.72 2013/10/17 17:22:59 christos Exp $ */ +/* $NetBSD: create.c,v 1.73 2014/04/24 17:22:41 christos Exp $ */ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif #include #if defined(__RCSID) && !defined(lint) #if 0 static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: create.c,v 1.72 2013/10/17 17:22:59 christos Exp $"); +__RCSID("$NetBSD: create.c,v 1.73 2014/04/24 17:22:41 christos Exp $"); #endif #endif /* not lint */ #include #include #if ! HAVE_NBTOOL_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #ifndef NO_MD5 #include #endif #ifndef NO_RMD160 #include #endif #ifndef NO_SHA1 #include #endif #ifndef NO_SHA2 #include #endif #include "extern.h" #define INDENTNAMELEN 15 #define MAXLINELEN 80 static gid_t gid; static uid_t uid; static mode_t mode; static u_long flags; #ifdef __FreeBSD__ #define FTS_CONST const #else #define FTS_CONST #endif static int dcmp(const FTSENT *FTS_CONST *, const FTSENT *FTS_CONST *); -static void output(int, int *, const char *, ...) - __attribute__((__format__(__printf__, 3, 4))); -static int statd(FTS *, FTSENT *, uid_t *, gid_t *, mode_t *, u_long *); -static void statf(int, FTSENT *); +static void output(FILE *, int, int *, const char *, ...) + __printflike(4, 5); +static int statd(FILE *, FTS *, FTSENT *, uid_t *, gid_t *, mode_t *, + u_long *); +static void statf(FILE *, int, FTSENT *); void -cwalk(void) +cwalk(FILE *fp) { FTS *t; FTSENT *p; time_t clocktime; char host[MAXHOSTNAMELEN + 1]; const char *user; char *argv[2]; char dot[] = "."; int indent = 0; argv[0] = dot; argv[1] = NULL; time(&clocktime); gethostname(host, sizeof(host)); host[sizeof(host) - 1] = '\0'; if ((user = getlogin()) == NULL) { struct passwd *pw; user = (pw = getpwuid(getuid())) == NULL ? pw->pw_name : ""; } if (!nflag) - printf( + fprintf(fp, "#\t user: %s\n#\tmachine: %s\n#\t tree: %s\n" "#\t date: %s", user, host, fullpath, ctime(&clocktime)); if ((t = fts_open(argv, ftsoptions, dcmp)) == NULL) mtree_err("fts_open: %s", strerror(errno)); while ((p = fts_read(t)) != NULL) { if (jflag) indent = p->fts_level * 4; if (check_excludes(p->fts_name, p->fts_path)) { fts_set(t, p, FTS_SKIP); continue; } if (!find_only(p->fts_path)) { fts_set(t, p, FTS_SKIP); continue; } switch(p->fts_info) { case FTS_D: if (!bflag) - printf("\n"); + fprintf(fp, "\n"); if (!nflag) - printf("# %s\n", p->fts_path); - statd(t, p, &uid, &gid, &mode, &flags); - statf(indent, p); + fprintf(fp, "# %s\n", p->fts_path); + statd(fp, t, p, &uid, &gid, &mode, &flags); + statf(fp, indent, p); break; case FTS_DP: if (p->fts_level > 0) if (!nflag) - printf("%*s# %s\n", indent, "", + fprintf(fp, "%*s# %s\n", indent, "", p->fts_path); if (p->fts_level > 0 || flavor == F_FREEBSD9) { - printf("%*s..\n", indent, ""); + fprintf(fp, "%*s..\n", indent, ""); if (!bflag) - printf("\n"); + fprintf(fp, "\n"); } break; case FTS_DNR: case FTS_ERR: case FTS_NS: mtree_err("%s: %s", p->fts_path, strerror(p->fts_errno)); break; default: if (!dflag) - statf(indent, p); + statf(fp, indent, p); break; } } fts_close(t); if (sflag && keys & F_CKSUM) mtree_err("%s checksum: %u", fullpath, crc_total); } static void -statf(int indent, FTSENT *p) +statf(FILE *fp, int indent, FTSENT *p) { u_int32_t len, val; int fd, offset; const char *name = NULL; #if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2) char *digestbuf; #endif - offset = printf("%*s%s%s", indent, "", + offset = fprintf(fp, "%*s%s%s", indent, "", S_ISDIR(p->fts_statp->st_mode) ? "" : " ", vispath(p->fts_name)); if (offset > (INDENTNAMELEN + indent)) offset = MAXLINELEN; else - offset += printf("%*s", (INDENTNAMELEN + indent) - offset, ""); + offset += fprintf(fp, "%*s", + (INDENTNAMELEN + indent) - offset, ""); if (!S_ISREG(p->fts_statp->st_mode) && (flavor == F_NETBSD6 || !dflag)) - output(indent, &offset, "type=%s", + output(fp, indent, &offset, "type=%s", inotype(p->fts_statp->st_mode)); if (keys & (F_UID | F_UNAME) && p->fts_statp->st_uid != uid) { if (keys & F_UNAME && (name = user_from_uid(p->fts_statp->st_uid, 1)) != NULL) - output(indent, &offset, "uname=%s", name); + output(fp, indent, &offset, "uname=%s", name); if (keys & F_UID || (keys & F_UNAME && name == NULL)) - output(indent, &offset, "uid=%u", p->fts_statp->st_uid); + output(fp, indent, &offset, "uid=%u", + p->fts_statp->st_uid); } if (keys & (F_GID | F_GNAME) && p->fts_statp->st_gid != gid) { if (keys & F_GNAME && (name = group_from_gid(p->fts_statp->st_gid, 1)) != NULL) - output(indent, &offset, "gname=%s", name); + output(fp, indent, &offset, "gname=%s", name); if (keys & F_GID || (keys & F_GNAME && name == NULL)) - output(indent, &offset, "gid=%u", p->fts_statp->st_gid); + output(fp, indent, &offset, "gid=%u", + p->fts_statp->st_gid); } if (keys & F_MODE && (p->fts_statp->st_mode & MBITS) != mode) - output(indent, &offset, "mode=%#o", + output(fp, indent, &offset, "mode=%#o", p->fts_statp->st_mode & MBITS); if (keys & F_DEV && (S_ISBLK(p->fts_statp->st_mode) || S_ISCHR(p->fts_statp->st_mode))) - output(indent, &offset, "device=%#jx", + output(fp, indent, &offset, "device=%#jx", (uintmax_t)p->fts_statp->st_rdev); if (keys & F_NLINK && p->fts_statp->st_nlink != 1) - output(indent, &offset, "nlink=%u", p->fts_statp->st_nlink); + output(fp, indent, &offset, "nlink=%u", p->fts_statp->st_nlink); if (keys & F_SIZE && (flavor == F_FREEBSD9 || S_ISREG(p->fts_statp->st_mode))) - output(indent, &offset, "size=%ju", + output(fp, indent, &offset, "size=%ju", (uintmax_t)p->fts_statp->st_size); if (keys & F_TIME) #if defined(BSD4_4) && !defined(HAVE_NBTOOL_CONFIG_H) - output(indent, &offset, "time=%jd.%09ld", + output(fp, indent, &offset, "time=%jd.%09ld", (intmax_t)p->fts_statp->st_mtimespec.tv_sec, p->fts_statp->st_mtimespec.tv_nsec); #else - output(indent, &offset, "time=%jd.%09ld", + output(fp, indent, &offset, "time=%jd.%09ld", (intmax_t)p->fts_statp->st_mtime, (long)0); #endif if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) { if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 || crc(fd, &val, &len)) mtree_err("%s: %s", p->fts_accpath, strerror(errno)); close(fd); - output(indent, &offset, "cksum=%lu", (long)val); + output(fp, indent, &offset, "cksum=%lu", (long)val); } #ifndef NO_MD5 if (keys & F_MD5 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL) mtree_err("%s: MD5File failed: %s", p->fts_accpath, strerror(errno)); - output(indent, &offset, "%s=%s", MD5KEY, digestbuf); + output(fp, indent, &offset, "%s=%s", MD5KEY, digestbuf); free(digestbuf); } #endif /* ! NO_MD5 */ #ifndef NO_RMD160 if (keys & F_RMD160 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL) mtree_err("%s: RMD160File failed: %s", p->fts_accpath, strerror(errno)); - output(indent, &offset, "%s=%s", RMD160KEY, digestbuf); + output(fp, indent, &offset, "%s=%s", RMD160KEY, digestbuf); free(digestbuf); } #endif /* ! NO_RMD160 */ #ifndef NO_SHA1 if (keys & F_SHA1 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL) mtree_err("%s: SHA1File failed: %s", p->fts_accpath, strerror(errno)); - output(indent, &offset, "%s=%s", SHA1KEY, digestbuf); + output(fp, indent, &offset, "%s=%s", SHA1KEY, digestbuf); free(digestbuf); } #endif /* ! NO_SHA1 */ #ifndef NO_SHA2 if (keys & F_SHA256 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL) mtree_err("%s: SHA256_File failed: %s", p->fts_accpath, strerror(errno)); - output(indent, &offset, "%s=%s", SHA256KEY, digestbuf); + output(fp, indent, &offset, "%s=%s", SHA256KEY, digestbuf); free(digestbuf); } #ifdef SHA384_BLOCK_LENGTH if (keys & F_SHA384 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL) mtree_err("%s: SHA384_File failed: %s", p->fts_accpath, strerror(errno)); - output(indent, &offset, "%s=%s", SHA384KEY, digestbuf); + output(fp, indent, &offset, "%s=%s", SHA384KEY, digestbuf); free(digestbuf); } #endif if (keys & F_SHA512 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL) mtree_err("%s: SHA512_File failed: %s", p->fts_accpath, strerror(errno)); - output(indent, &offset, "%s=%s", SHA512KEY, digestbuf); + output(fp, indent, &offset, "%s=%s", SHA512KEY, digestbuf); free(digestbuf); } #endif /* ! NO_SHA2 */ if (keys & F_SLINK && (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) - output(indent, &offset, "link=%s", + output(fp, indent, &offset, "link=%s", vispath(rlink(p->fts_accpath))); #if HAVE_STRUCT_STAT_ST_FLAGS if (keys & F_FLAGS && p->fts_statp->st_flags != flags) { char *str = flags_to_string(p->fts_statp->st_flags, "none"); - output(indent, &offset, "flags=%s", str); + output(fp, indent, &offset, "flags=%s", str); free(str); } #endif putchar('\n'); } /* XXX * FLAGS2INDEX will fail once the user and system settable bits need more * than one byte, respectively. */ #define FLAGS2INDEX(x) (((x >> 8) & 0x0000ff00) | (x & 0x000000ff)) #define MTREE_MAXGID 5000 #define MTREE_MAXUID 5000 #define MTREE_MAXMODE (MBITS + 1) #if HAVE_STRUCT_STAT_ST_FLAGS #define MTREE_MAXFLAGS (FLAGS2INDEX(CH_MASK) + 1) /* 1808 */ #else #define MTREE_MAXFLAGS 1 #endif #define MTREE_MAXS 16 static int -statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, - u_long *pflags) +statd(FILE *fp, FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, + u_long *pflags) { FTSENT *p; gid_t sgid; uid_t suid; mode_t smode; u_long sflags = 0; const char *name = NULL; gid_t savegid; uid_t saveuid; mode_t savemode; u_long saveflags; u_short maxgid, maxuid, maxmode, maxflags; u_short g[MTREE_MAXGID], u[MTREE_MAXUID], m[MTREE_MAXMODE], f[MTREE_MAXFLAGS]; static int first = 1; savegid = *pgid; saveuid = *puid; savemode = *pmode; saveflags = *pflags; if ((p = fts_children(t, 0)) == NULL) { if (errno) mtree_err("%s: %s", RP(parent), strerror(errno)); return (1); } memset(g, 0, sizeof(g)); memset(u, 0, sizeof(u)); memset(m, 0, sizeof(m)); memset(f, 0, sizeof(f)); maxuid = maxgid = maxmode = maxflags = 0; for (; p; p = p->fts_link) { if (flavor == F_NETBSD6 || !dflag || (dflag && S_ISDIR(p->fts_statp->st_mode))) { smode = p->fts_statp->st_mode & MBITS; if (smode < MTREE_MAXMODE && ++m[smode] > maxmode) { savemode = smode; maxmode = m[smode]; } sgid = p->fts_statp->st_gid; if (sgid < MTREE_MAXGID && ++g[sgid] > maxgid) { savegid = sgid; maxgid = g[sgid]; } suid = p->fts_statp->st_uid; if (suid < MTREE_MAXUID && ++u[suid] > maxuid) { saveuid = suid; maxuid = u[suid]; } #if HAVE_STRUCT_STAT_ST_FLAGS sflags = FLAGS2INDEX(p->fts_statp->st_flags); if (sflags < MTREE_MAXFLAGS && ++f[sflags] > maxflags) { saveflags = p->fts_statp->st_flags; maxflags = f[sflags]; } #endif } } /* * If the /set record is the same as the last one we do not need to * output a new one. So first we check to see if anything changed. * Note that we always output a /set record for the first directory. */ if (((keys & (F_UNAME | F_UID)) && (*puid != saveuid)) || ((keys & (F_GNAME | F_GID)) && (*pgid != savegid)) || ((keys & F_MODE) && (*pmode != savemode)) || ((keys & F_FLAGS) && (*pflags != saveflags)) || first) { first = 0; if (flavor != F_NETBSD6 && dflag) - printf("/set type=dir"); + fprintf(fp, "/set type=dir"); else - printf("/set type=file"); + fprintf(fp, "/set type=file"); if (keys & (F_UID | F_UNAME)) { if (keys & F_UNAME && (name = user_from_uid(saveuid, 1)) != NULL) - printf(" uname=%s", name); + fprintf(fp, " uname=%s", name); if (keys & F_UID || (keys & F_UNAME && name == NULL)) - printf(" uid=%lu", (u_long)saveuid); + fprintf(fp, " uid=%lu", (u_long)saveuid); } if (keys & (F_GID | F_GNAME)) { if (keys & F_GNAME && (name = group_from_gid(savegid, 1)) != NULL) - printf(" gname=%s", name); + fprintf(fp, " gname=%s", name); if (keys & F_GID || (keys & F_GNAME && name == NULL)) - printf(" gid=%lu", (u_long)savegid); + fprintf(fp, " gid=%lu", (u_long)savegid); } if (keys & F_MODE) - printf(" mode=%#lo", (u_long)savemode); + fprintf(fp, " mode=%#lo", (u_long)savemode); if (keys & F_NLINK) - printf(" nlink=1"); + fprintf(fp, " nlink=1"); if (keys & F_FLAGS) { char *str = flags_to_string(saveflags, "none"); - printf(" flags=%s", str); + fprintf(fp, " flags=%s", str); free(str); } - printf("\n"); + fprintf(fp, "\n"); *puid = saveuid; *pgid = savegid; *pmode = savemode; *pflags = saveflags; } return (0); } /* * dcmp -- * used as a comparison function passed to fts_open() to control * the order in which fts_read() returns results. We make * directories sort after non-directories, but otherwise sort in * strcmp() order. * * Keep this in sync with nodecmp() in spec.c. */ static int dcmp(const FTSENT *FTS_CONST *a, const FTSENT *FTS_CONST *b) { if (S_ISDIR((*a)->fts_statp->st_mode)) { if (!S_ISDIR((*b)->fts_statp->st_mode)) return (1); } else if (S_ISDIR((*b)->fts_statp->st_mode)) return (-1); return (strcmp((*a)->fts_name, (*b)->fts_name)); } void -output(int indent, int *offset, const char *fmt, ...) +output(FILE *fp, int indent, int *offset, const char *fmt, ...) { va_list ap; char buf[1024]; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (*offset + strlen(buf) > MAXLINELEN - 3) { - printf(" \\\n%*s", INDENTNAMELEN + indent, ""); + fprintf(fp, " \\\n%*s", INDENTNAMELEN + indent, ""); *offset = INDENTNAMELEN + indent; } - *offset += printf(" %s", buf) + 1; + *offset += fprintf(fp, " %s", buf) + 1; } Index: vendor/NetBSD/mtree/dist/extern.h =================================================================== --- vendor/NetBSD/mtree/dist/extern.h (revision 273788) +++ vendor/NetBSD/mtree/dist/extern.h (revision 273789) @@ -1,90 +1,90 @@ -/* $NetBSD: extern.h,v 1.38 2013/02/03 19:15:17 christos Exp $ */ +/* $NetBSD: extern.h,v 1.39 2014/04/24 17:22:41 christos Exp $ */ /*- * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)extern.h 8.1 (Berkeley) 6/6/93 */ #include "mtree.h" #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #else #define HAVE_STRUCT_STAT_ST_FLAGS 1 #endif #include #include #include #include #if HAVE_NETDB_H /* For MAXHOSTNAMELEN on some platforms. */ #include #endif #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif enum flavor { F_MTREE, F_FREEBSD9, F_NETBSD6 }; void addtag(slist_t *, char *); int check_excludes(const char *, const char *); int compare(NODE *, FTSENT *); int crc(int, u_int32_t *, u_int32_t *); -void cwalk(void); -void dump_nodes(const char *, NODE *, int); +void cwalk(FILE *); +void dump_nodes(FILE *, const char *, NODE *, int); void init_excludes(void); int matchtags(NODE *); __dead __printflike(1,2) void mtree_err(const char *, ...); const char *nodetype(u_int); u_int parsekey(const char *, int *); void parsetags(slist_t *, char *); u_int parsetype(const char *); void read_excludes_file(const char *); const char *rlink(const char *); int verify(FILE *); void load_only(const char *fname); bool find_only(const char *path); extern int bflag, dflag, eflag, iflag, jflag, lflag, mflag, nflag, qflag, rflag, sflag, tflag, uflag; extern int mtree_Mflag, mtree_Sflag, mtree_Wflag; extern size_t mtree_lineno; extern enum flavor flavor; extern u_int32_t crc_total; extern int ftsoptions, keys; extern char fullpath[]; extern slist_t includetags, excludetags; Index: vendor/NetBSD/mtree/dist/getid.c =================================================================== --- vendor/NetBSD/mtree/dist/getid.c (revision 273788) +++ vendor/NetBSD/mtree/dist/getid.c (revision 273789) @@ -1,437 +1,446 @@ -/* $NetBSD: getid.c,v 1.8 2013/10/16 17:27:42 christos Exp $ */ +/* $NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 christos Exp $ */ /* from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */ /* from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */ /* * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Luke Mewburn of Wasabi Systems. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif #include -__RCSID("$NetBSD: getid.c,v 1.8 2013/10/16 17:27:42 christos Exp $"); +__RCSID("$NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 christos Exp $"); #include #include #include #include #include #include #include #include #include #include "extern.h" static struct group * gi_getgrnam(const char *); static struct group * gi_getgrgid(gid_t); static int gi_setgroupent(int); static void gi_endgrent(void); static int grstart(void); static int grscan(int, gid_t, const char *); static int grmatchline(int, gid_t, const char *); static struct passwd * gi_getpwnam(const char *); static struct passwd * gi_getpwuid(uid_t); static int gi_setpassent(int); static void gi_endpwent(void); static int pwstart(void); static int pwscan(int, uid_t, const char *); static int pwmatchline(int, uid_t, const char *); #define MAXGRP 200 #define MAXLINELENGTH 1024 static FILE *_gr_fp; static struct group _gr_group; static int _gr_stayopen; static int _gr_filesdone; static FILE *_pw_fp; static struct passwd _pw_passwd; /* password structure */ static int _pw_stayopen; /* keep fd's open */ static int _pw_filesdone; static char grfile[MAXPATHLEN]; static char pwfile[MAXPATHLEN]; static char *members[MAXGRP]; static char grline[MAXLINELENGTH]; static char pwline[MAXLINELENGTH]; int setup_getid(const char *dir) { if (dir == NULL) return (0); /* close existing databases */ gi_endgrent(); gi_endpwent(); /* build paths to new databases */ snprintf(grfile, sizeof(grfile), "%s/group", dir); snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir); /* try to open new databases */ if (!grstart() || !pwstart()) return (0); /* switch pwcache(3) lookup functions */ if (pwcache_groupdb(gi_setgroupent, gi_endgrent, gi_getgrnam, gi_getgrgid) == -1 || pwcache_userdb(gi_setpassent, gi_endpwent, gi_getpwnam, gi_getpwuid) == -1) return (0); return (1); } /* * group lookup functions */ static struct group * gi_getgrnam(const char *name) { int rval; if (!grstart()) return NULL; rval = grscan(1, 0, name); if (!_gr_stayopen) endgrent(); return (rval) ? &_gr_group : NULL; } static struct group * gi_getgrgid(gid_t gid) { int rval; if (!grstart()) return NULL; rval = grscan(1, gid, NULL); if (!_gr_stayopen) endgrent(); return (rval) ? &_gr_group : NULL; } static int gi_setgroupent(int stayopen) { if (!grstart()) return 0; _gr_stayopen = stayopen; return 1; } static void gi_endgrent(void) { _gr_filesdone = 0; if (_gr_fp) { (void)fclose(_gr_fp); _gr_fp = NULL; } } static int grstart(void) { _gr_filesdone = 0; if (_gr_fp) { rewind(_gr_fp); return 1; } if (grfile[0] == '\0') /* sanity check */ return 0; - return (_gr_fp = fopen(grfile, "r")) ? 1 : 0; + + _gr_fp = fopen(grfile, "r"); + if (_gr_fp != NULL) + return 1; + warn("Can't open `%s'", grfile); + return 0; } static int grscan(int search, gid_t gid, const char *name) { if (_gr_filesdone) return 0; for (;;) { if (!fgets(grline, sizeof(grline), _gr_fp)) { if (!search) _gr_filesdone = 1; return 0; } /* skip lines that are too big */ if (!strchr(grline, '\n')) { int ch; while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) ; continue; } /* skip comments */ - if (pwline[0] == '#') + if (grline[0] == '#') continue; if (grmatchline(search, gid, name)) return 1; } /* NOTREACHED */ } static int grmatchline(int search, gid_t gid, const char *name) { unsigned long id; char **m; char *cp, *bp, *ep; /* name may be NULL if search is nonzero */ bp = grline; memset(&_gr_group, 0, sizeof(_gr_group)); _gr_group.gr_name = strsep(&bp, ":\n"); if (search && name && strcmp(_gr_group.gr_name, name)) return 0; _gr_group.gr_passwd = strsep(&bp, ":\n"); if (!(cp = strsep(&bp, ":\n"))) return 0; id = strtoul(cp, &ep, 10); if (id > GID_MAX || *ep != '\0') return 0; _gr_group.gr_gid = (gid_t)id; if (search && name == NULL && _gr_group.gr_gid != gid) return 0; cp = NULL; if (bp == NULL) return 0; for (_gr_group.gr_mem = m = members;; bp++) { if (m == &members[MAXGRP - 1]) break; if (*bp == ',') { if (cp) { *bp = '\0'; *m++ = cp; cp = NULL; } } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { if (cp) { *bp = '\0'; *m++ = cp; } break; } else if (cp == NULL) cp = bp; } *m = NULL; return 1; } /* * user lookup functions */ static struct passwd * gi_getpwnam(const char *name) { int rval; if (!pwstart()) return NULL; rval = pwscan(1, 0, name); if (!_pw_stayopen) endpwent(); return (rval) ? &_pw_passwd : NULL; } static struct passwd * gi_getpwuid(uid_t uid) { int rval; if (!pwstart()) return NULL; rval = pwscan(1, uid, NULL); if (!_pw_stayopen) endpwent(); return (rval) ? &_pw_passwd : NULL; } static int gi_setpassent(int stayopen) { if (!pwstart()) return 0; _pw_stayopen = stayopen; return 1; } static void gi_endpwent(void) { _pw_filesdone = 0; if (_pw_fp) { (void)fclose(_pw_fp); _pw_fp = NULL; } } static int pwstart(void) { _pw_filesdone = 0; if (_pw_fp) { rewind(_pw_fp); return 1; } if (pwfile[0] == '\0') /* sanity check */ return 0; - return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0; + _pw_fp = fopen(pwfile, "r"); + if (_pw_fp != NULL) + return 1; + warn("Can't open `%s'", pwfile); + return 0; } static int pwscan(int search, uid_t uid, const char *name) { if (_pw_filesdone) return 0; for (;;) { if (!fgets(pwline, sizeof(pwline), _pw_fp)) { if (!search) _pw_filesdone = 1; return 0; } /* skip lines that are too big */ if (!strchr(pwline, '\n')) { int ch; while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) ; continue; } /* skip comments */ if (pwline[0] == '#') continue; if (pwmatchline(search, uid, name)) return 1; } /* NOTREACHED */ } static int pwmatchline(int search, uid_t uid, const char *name) { unsigned long id; char *cp, *bp, *ep; /* name may be NULL if search is nonzero */ bp = pwline; memset(&_pw_passwd, 0, sizeof(_pw_passwd)); _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */ if (search && name && strcmp(_pw_passwd.pw_name, name)) return 0; _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */ if (!(cp = strsep(&bp, ":\n"))) /* uid */ return 0; id = strtoul(cp, &ep, 10); if (id > UID_MAX || *ep != '\0') return 0; _pw_passwd.pw_uid = (uid_t)id; if (search && name == NULL && _pw_passwd.pw_uid != uid) return 0; if (!(cp = strsep(&bp, ":\n"))) /* gid */ return 0; id = strtoul(cp, &ep, 10); if (id > GID_MAX || *ep != '\0') return 0; _pw_passwd.pw_gid = (gid_t)id; if (!(ep = strsep(&bp, ":"))) /* class */ return 0; if (!(ep = strsep(&bp, ":"))) /* change */ return 0; if (!(ep = strsep(&bp, ":"))) /* expire */ return 0; if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */ return 0; if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */ return 0; if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */ return 0; if (strchr(bp, ':') != NULL) return 0; return 1; } Index: vendor/NetBSD/mtree/dist/mtree.c =================================================================== --- vendor/NetBSD/mtree/dist/mtree.c (revision 273788) +++ vendor/NetBSD/mtree/dist/mtree.c (revision 273789) @@ -1,332 +1,332 @@ -/* $NetBSD: mtree.c,v 1.48 2013/04/08 17:39:11 christos Exp $ */ +/* $NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $ */ /*- * Copyright (c) 1989, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif #include #if defined(__COPYRIGHT) && !defined(lint) __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\ The Regents of the University of California. All rights reserved."); #endif /* not lint */ #if defined(__RCSID) && !defined(lint) #if 0 static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: mtree.c,v 1.48 2013/04/08 17:39:11 christos Exp $"); +__RCSID("$NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $"); #endif #endif /* not lint */ #include #include #include #include #include #include #include #include "extern.h" int ftsoptions = FTS_PHYSICAL; int bflag, dflag, eflag, iflag, jflag, lflag, mflag, nflag, qflag, rflag, sflag, tflag, uflag; char fullpath[MAXPATHLEN]; static struct { enum flavor flavor; const char name[9]; } flavors[] = { {F_MTREE, "mtree"}, {F_FREEBSD9, "freebsd9"}, {F_NETBSD6, "netbsd6"}, }; __dead static void usage(void); int main(int argc, char **argv) { int ch, status; unsigned int i; int cflag, Cflag, Dflag, Uflag, wflag; char *dir, *p; FILE *spec1, *spec2; setprogname(argv[0]); cflag = Cflag = Dflag = Uflag = wflag = 0; dir = NULL; init_excludes(); spec1 = stdin; spec2 = NULL; while ((ch = getopt(argc, argv, "bcCdDeE:f:F:I:ijk:K:lLmMnN:O:p:PqrR:s:StuUwWxX:")) != -1) { switch((char)ch) { case 'b': bflag = 1; break; case 'c': cflag = 1; break; case 'C': Cflag = 1; break; case 'd': dflag = 1; break; case 'D': Dflag = 1; break; case 'E': parsetags(&excludetags, optarg); break; case 'e': eflag = 1; break; case 'f': if (spec1 == stdin) { spec1 = fopen(optarg, "r"); if (spec1 == NULL) mtree_err("%s: %s", optarg, strerror(errno)); } else if (spec2 == NULL) { spec2 = fopen(optarg, "r"); if (spec2 == NULL) mtree_err("%s: %s", optarg, strerror(errno)); } else usage(); break; case 'F': for (i = 0; i < __arraycount(flavors); i++) if (strcmp(optarg, flavors[i].name) == 0) { flavor = flavors[i].flavor; break; } if (i == __arraycount(flavors)) usage(); break; case 'i': iflag = 1; break; case 'I': parsetags(&includetags, optarg); break; case 'j': jflag = 1; break; case 'k': keys = F_TYPE; while ((p = strsep(&optarg, " \t,")) != NULL) if (*p != '\0') keys |= parsekey(p, NULL); break; case 'K': while ((p = strsep(&optarg, " \t,")) != NULL) if (*p != '\0') keys |= parsekey(p, NULL); break; case 'l': lflag = 1; break; case 'L': ftsoptions &= ~FTS_PHYSICAL; ftsoptions |= FTS_LOGICAL; break; case 'm': mflag = 1; break; case 'M': mtree_Mflag = 1; break; case 'n': nflag = 1; break; case 'N': if (! setup_getid(optarg)) mtree_err( "Unable to use user and group databases in `%s'", optarg); break; case 'O': load_only(optarg); break; case 'p': dir = optarg; break; case 'P': ftsoptions &= ~FTS_LOGICAL; ftsoptions |= FTS_PHYSICAL; break; case 'q': qflag = 1; break; case 'r': rflag = 1; break; case 'R': while ((p = strsep(&optarg, " \t,")) != NULL) if (*p != '\0') keys &= ~parsekey(p, NULL); break; case 's': sflag = 1; crc_total = ~strtol(optarg, &p, 0); if (*p) mtree_err("illegal seed value -- %s", optarg); break; case 'S': mtree_Sflag = 1; break; case 't': tflag = 1; break; case 'u': uflag = 1; break; case 'U': Uflag = uflag = 1; break; case 'w': wflag = 1; break; case 'W': mtree_Wflag = 1; break; case 'x': ftsoptions |= FTS_XDEV; break; case 'X': read_excludes_file(optarg); break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc) usage(); switch (flavor) { case F_FREEBSD9: if (cflag && iflag) { warnx("-c and -i passed, replacing -i with -j for " "FreeBSD compatibility"); iflag = 0; jflag = 1; } if (dflag && !bflag) { warnx("Adding -b to -d for FreeBSD compatibility"); bflag = 1; } if (uflag && !iflag) { warnx("Adding -i to -%c for FreeBSD compatibility", Uflag ? 'U' : 'u'); iflag = 1; } if (uflag && !tflag) { warnx("Adding -t to -%c for FreeBSD compatibility", Uflag ? 'U' : 'u'); tflag = 1; } if (wflag) warnx("The -w flag is a no-op"); break; default: if (wflag) usage(); } if (spec2 && (cflag || Cflag || Dflag)) mtree_err("Double -f, -c, -C and -D flags are mutually " "exclusive"); if (dir && spec2) mtree_err("Double -f and -p flags are mutually exclusive"); if (dir && chdir(dir)) mtree_err("%s: %s", dir, strerror(errno)); if ((cflag || sflag) && !getcwd(fullpath, sizeof(fullpath))) mtree_err("%s", strerror(errno)); if ((cflag && Cflag) || (cflag && Dflag) || (Cflag && Dflag)) mtree_err("-c, -C and -D flags are mutually exclusive"); if (iflag && mflag) mtree_err("-i and -m flags are mutually exclusive"); if (lflag && uflag) mtree_err("-l and -u flags are mutually exclusive"); if (cflag) { - cwalk(); + cwalk(stdout); exit(0); } if (Cflag || Dflag) { - dump_nodes("", spec(spec1), Dflag); + dump_nodes(stdout, "", spec(spec1), Dflag); exit(0); } if (spec2 != NULL) status = mtree_specspec(spec1, spec2); else status = verify(spec1); if (Uflag && (status == MISMATCHEXIT)) status = 0; exit(status); } static void usage(void) { unsigned int i; fprintf(stderr, "usage: %s [-bCcDdejLlMnPqrStUuWx] [-i|-m] [-E tags]\n" "\t\t[-f spec] [-f spec]\n" "\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n" "\t\t[-R keywords] [-s seed] [-X exclude-file]\n" "\t\t[-F flavor]\n", getprogname()); fprintf(stderr, "\nflavors:"); for (i = 0; i < __arraycount(flavors); i++) fprintf(stderr, " %s", flavors[i].name); fprintf(stderr, "\n"); exit(1); } Index: vendor/NetBSD/mtree/dist/spec.c =================================================================== --- vendor/NetBSD/mtree/dist/spec.c (revision 273788) +++ vendor/NetBSD/mtree/dist/spec.c (revision 273789) @@ -1,847 +1,852 @@ -/* $NetBSD: spec.c,v 1.88 2013/10/17 17:22:59 christos Exp $ */ +/* $NetBSD: spec.c,v 1.89 2014/04/24 17:22:41 christos Exp $ */ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 2001-2004 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Luke Mewburn of Wasabi Systems. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #endif #include #if defined(__RCSID) && !defined(lint) #if 0 static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: spec.c,v 1.88 2013/10/17 17:22:59 christos Exp $"); +__RCSID("$NetBSD: spec.c,v 1.89 2014/04/24 17:22:41 christos Exp $"); #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" #include "pack_dev.h" size_t mtree_lineno; /* Current spec line number */ int mtree_Mflag; /* Merge duplicate entries */ int mtree_Wflag; /* Don't "whack" permissions */ int mtree_Sflag; /* Sort entries */ static dev_t parsedev(char *); static void replacenode(NODE *, NODE *); static void set(char *, NODE *); static void unset(char *, NODE *); static void addchild(NODE *, NODE *); static int nodecmp(const NODE *, const NODE *); -static int appendfield(int, const char *, ...) __printflike(2, 3); +static int appendfield(FILE *, int, const char *, ...) __printflike(3, 4); #define REPLACEPTR(x,v) do { if ((x)) free((x)); (x) = (v); } while (0) NODE * spec(FILE *fp) { NODE *centry, *last, *pathparent, *cur; char *p, *e, *next; NODE ginfo, *root; char *buf, *tname, *ntname; size_t tnamelen, plen; root = NULL; centry = last = NULL; tname = NULL; tnamelen = 0; memset(&ginfo, 0, sizeof(ginfo)); for (mtree_lineno = 0; (buf = fparseln(fp, NULL, &mtree_lineno, NULL, FPARSELN_UNESCCOMM)); free(buf)) { /* Skip leading whitespace. */ for (p = buf; *p && isspace((unsigned char)*p); ++p) continue; /* If nothing but whitespace, continue. */ if (!*p) continue; #ifdef DEBUG fprintf(stderr, "line %lu: {%s}\n", (u_long)mtree_lineno, p); #endif /* Grab file name, "$", "set", or "unset". */ next = buf; while ((p = strsep(&next, " \t")) != NULL && *p == '\0') continue; if (p == NULL) mtree_err("missing field"); 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 (strcmp(p, "..") == 0) { /* Don't go up, if haven't gone down. */ if (root == NULL) goto noparent; if (last->type != F_DIR || last->flags & F_DONE) { if (last == root) goto noparent; last = last->parent; } last->flags |= F_DONE; continue; noparent: mtree_err("no parent node"); } plen = strlen(p) + 1; if (plen > tnamelen) { if ((ntname = realloc(tname, plen)) == NULL) mtree_err("realloc: %s", strerror(errno)); tname = ntname; tnamelen = plen; } if (strunvis(tname, p) == -1) mtree_err("strunvis failed on `%s'", p); p = tname; 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) mtree_err("%s", strerror(errno)); *centry = ginfo; centry->lineno = mtree_lineno; strcpy(centry->name, p); #define MAGIC "?*[" if (strpbrk(p, MAGIC)) centry->flags |= F_MAGIC; set(next, centry); if (root == NULL) { /* * empty tree */ /* * Allow a bare "." root node by forcing it to * type=dir for compatibility with FreeBSD. */ if (strcmp(centry->name, ".") == 0 && centry->type == 0) centry->type = F_DIR; 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; addchild(last, centry); last = centry; } else { /* * new relative child in parent dir * (after encountering ".." entry); * add or replace */ centry->parent = last->parent; addchild(last->parent, centry); last = centry; } } return (root); } void free_nodes(NODE *root) { NODE *cur, *next; if (root == NULL) return; next = NULL; for (cur = root; cur != NULL; cur = next) { next = cur->next; free_nodes(cur->child); REPLACEPTR(cur->slink, NULL); REPLACEPTR(cur->md5digest, NULL); REPLACEPTR(cur->rmd160digest, NULL); REPLACEPTR(cur->sha1digest, NULL); REPLACEPTR(cur->sha256digest, NULL); REPLACEPTR(cur->sha384digest, NULL); REPLACEPTR(cur->sha512digest, NULL); REPLACEPTR(cur->tags, NULL); REPLACEPTR(cur, NULL); } } /* * appendfield -- - * Like printf(), but output a space either before or after + * Like fprintf(), but output a space either before or after * the regular output, according to the pathlast flag. */ static int -appendfield(int pathlast, const char *fmt, ...) +appendfield(FILE *fp, int pathlast, const char *fmt, ...) { va_list ap; int result; va_start(ap, fmt); if (!pathlast) - printf(" "); + fprintf(fp, " "); result = vprintf(fmt, ap); if (pathlast) - printf(" "); + fprintf(fp, " "); va_end(ap); return result; } /* * dump_nodes -- * dump the NODEs from `cur', based in the directory `dir'. * if pathlast is none zero, print the path last, otherwise print * it first. */ void -dump_nodes(const char *dir, NODE *root, int pathlast) +dump_nodes(FILE *fp, const char *dir, NODE *root, int pathlast) { NODE *cur; char path[MAXPATHLEN]; const char *name; char *str; char *p, *q; for (cur = root; cur != NULL; cur = cur->next) { if (cur->type != F_DIR && !matchtags(cur)) continue; if (snprintf(path, sizeof(path), "%s%s%s", dir, *dir ? "/" : "", cur->name) >= (int)sizeof(path)) mtree_err("Pathname too long."); if (!pathlast) - printf("%s", vispath(path)); + fprintf(fp, "%s", vispath(path)); #define MATCHFLAG(f) ((keys & (f)) && (cur->flags & (f))) if (MATCHFLAG(F_TYPE)) - appendfield(pathlast, "type=%s", nodetype(cur->type)); + appendfield(fp, pathlast, "type=%s", + nodetype(cur->type)); if (MATCHFLAG(F_UID | F_UNAME)) { if (keys & F_UNAME && (name = user_from_uid(cur->st_uid, 1)) != NULL) - appendfield(pathlast, "uname=%s", name); + appendfield(fp, pathlast, "uname=%s", name); else - appendfield(pathlast, "uid=%u", cur->st_uid); + appendfield(fp, pathlast, "uid=%u", + cur->st_uid); } if (MATCHFLAG(F_GID | F_GNAME)) { if (keys & F_GNAME && (name = group_from_gid(cur->st_gid, 1)) != NULL) - appendfield(pathlast, "gname=%s", name); + appendfield(fp, pathlast, "gname=%s", name); else - appendfield(pathlast, "gid=%u", cur->st_gid); + appendfield(fp, pathlast, "gid=%u", + cur->st_gid); } if (MATCHFLAG(F_MODE)) - appendfield(pathlast, "mode=%#o", cur->st_mode); + appendfield(fp, pathlast, "mode=%#o", cur->st_mode); if (MATCHFLAG(F_DEV) && (cur->type == F_BLOCK || cur->type == F_CHAR)) - appendfield(pathlast, "device=%#jx", + appendfield(fp, pathlast, "device=%#jx", (uintmax_t)cur->st_rdev); if (MATCHFLAG(F_NLINK)) - appendfield(pathlast, "nlink=%d", cur->st_nlink); + appendfield(fp, pathlast, "nlink=%d", cur->st_nlink); if (MATCHFLAG(F_SLINK)) - appendfield(pathlast, "link=%s", vispath(cur->slink)); + appendfield(fp, pathlast, "link=%s", + vispath(cur->slink)); if (MATCHFLAG(F_SIZE)) - appendfield(pathlast, "size=%ju", + appendfield(fp, pathlast, "size=%ju", (uintmax_t)cur->st_size); if (MATCHFLAG(F_TIME)) - appendfield(pathlast, "time=%jd.%09ld", + appendfield(fp, pathlast, "time=%jd.%09ld", (intmax_t)cur->st_mtimespec.tv_sec, cur->st_mtimespec.tv_nsec); if (MATCHFLAG(F_CKSUM)) - appendfield(pathlast, "cksum=%lu", cur->cksum); + appendfield(fp, pathlast, "cksum=%lu", cur->cksum); if (MATCHFLAG(F_MD5)) - appendfield(pathlast, "%s=%s", MD5KEY, cur->md5digest); + appendfield(fp, pathlast, "%s=%s", MD5KEY, + cur->md5digest); if (MATCHFLAG(F_RMD160)) - appendfield(pathlast, "%s=%s", RMD160KEY, + appendfield(fp, pathlast, "%s=%s", RMD160KEY, cur->rmd160digest); if (MATCHFLAG(F_SHA1)) - appendfield(pathlast, "%s=%s", SHA1KEY, + appendfield(fp, pathlast, "%s=%s", SHA1KEY, cur->sha1digest); if (MATCHFLAG(F_SHA256)) - appendfield(pathlast, "%s=%s", SHA256KEY, + appendfield(fp, pathlast, "%s=%s", SHA256KEY, cur->sha256digest); if (MATCHFLAG(F_SHA384)) - appendfield(pathlast, "%s=%s", SHA384KEY, + appendfield(fp, pathlast, "%s=%s", SHA384KEY, cur->sha384digest); if (MATCHFLAG(F_SHA512)) - appendfield(pathlast, "%s=%s", SHA512KEY, + appendfield(fp, pathlast, "%s=%s", SHA512KEY, cur->sha512digest); if (MATCHFLAG(F_FLAGS)) { str = flags_to_string(cur->st_flags, "none"); - appendfield(pathlast, "flags=%s", str); + appendfield(fp, pathlast, "flags=%s", str); free(str); } if (MATCHFLAG(F_IGN)) - appendfield(pathlast, "ignore"); + appendfield(fp, pathlast, "ignore"); if (MATCHFLAG(F_OPT)) - appendfield(pathlast, "optional"); + appendfield(fp, pathlast, "optional"); if (MATCHFLAG(F_TAGS)) { /* don't output leading or trailing commas */ p = cur->tags; while (*p == ',') p++; q = p + strlen(p); while(q > p && q[-1] == ',') q--; - appendfield(pathlast, "tags=%.*s", (int)(q - p), p); + appendfield(fp, pathlast, "tags=%.*s", (int)(q - p), p); } puts(pathlast ? vispath(path) : ""); if (cur->child) - dump_nodes(path, cur->child, pathlast); + dump_nodes(fp, path, cur->child, pathlast); } } /* * vispath -- * strsvis(3) encodes path, which must not be longer than MAXPATHLEN * characters long, and returns a pointer to a static buffer containing * the result. */ char * vispath(const char *path) { static const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' }; static const char extra_glob[] = { ' ', '\t', '\n', '\\', '#', '*', '?', '[', '\0' }; static char pathbuf[4*MAXPATHLEN + 1]; if (flavor == F_NETBSD6) strsvis(pathbuf, path, VIS_CSTYLE, extra); else strsvis(pathbuf, path, VIS_OCTAL, extra_glob); return pathbuf; } static dev_t parsedev(char *arg) { #define MAX_PACK_ARGS 3 u_long numbers[MAX_PACK_ARGS]; char *p, *ep, *dev; int argc; pack_t *pack; dev_t result; const char *error = NULL; if ((dev = strchr(arg, ',')) != NULL) { *dev++='\0'; if ((pack = pack_find(arg)) == NULL) mtree_err("unknown format `%s'", arg); argc = 0; while ((p = strsep(&dev, ",")) != NULL) { if (*p == '\0') mtree_err("missing number"); numbers[argc++] = strtoul(p, &ep, 0); if (*ep != '\0') mtree_err("invalid number `%s'", p); if (argc > MAX_PACK_ARGS) mtree_err("too many arguments"); } if (argc < 2) mtree_err("not enough arguments"); result = (*pack)(argc, numbers, &error); if (error != NULL) mtree_err("%s", error); } else { result = (dev_t)strtoul(arg, &ep, 0); if (*ep != '\0') mtree_err("invalid device `%s'", arg); } return (result); } 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 (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 { mtree_err( "existing entry for `%s', type `%s'" " does not match type `%s'", cur->name, nodetype(cur->type), nodetype(new->type)); } } 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); } static void set(char *t, NODE *ip) { int type, value, len; gid_t gid; uid_t uid; char *kw, *val, *md, *ep; void *m; while ((kw = strsep(&t, "= \t")) != NULL) { if (*kw == '\0') continue; if (strcmp(kw, "all") == 0) mtree_err("invalid keyword `all'"); ip->flags |= type = parsekey(kw, &value); if (!value) /* Just set flag bit (F_IGN and F_OPT) */ continue; while ((val = strsep(&t, " \t")) != NULL && *val == '\0') continue; if (val == NULL) mtree_err("missing value"); switch (type) { case F_CKSUM: ip->cksum = strtoul(val, &ep, 10); if (*ep) mtree_err("invalid checksum `%s'", val); break; case F_DEV: ip->st_rdev = parsedev(val); break; case F_FLAGS: if (strcmp("none", val) == 0) ip->st_flags = 0; else if (string_to_flags(&val, &ip->st_flags, NULL) != 0) mtree_err("invalid flag `%s'", val); break; case F_GID: ip->st_gid = (gid_t)strtoul(val, &ep, 10); if (*ep) mtree_err("invalid gid `%s'", val); break; case F_GNAME: if (mtree_Wflag) /* don't parse if whacking */ break; if (gid_from_group(val, &gid) == -1) mtree_err("unknown group `%s'", val); ip->st_gid = gid; break; case F_MD5: if (val[0]=='0' && val[1]=='x') md=&val[2]; else md=val; if ((ip->md5digest = strdup(md)) == NULL) mtree_err("memory allocation error"); break; case F_MODE: if ((m = setmode(val)) == NULL) mtree_err("cannot set file mode `%s' (%s)", val, strerror(errno)); ip->st_mode = getmode(m, 0); free(m); break; case F_NLINK: ip->st_nlink = (nlink_t)strtoul(val, &ep, 10); if (*ep) mtree_err("invalid link count `%s'", val); break; case F_RMD160: if (val[0]=='0' && val[1]=='x') md=&val[2]; else md=val; if ((ip->rmd160digest = strdup(md)) == NULL) mtree_err("memory allocation error"); break; case F_SHA1: if (val[0]=='0' && val[1]=='x') md=&val[2]; else md=val; if ((ip->sha1digest = strdup(md)) == NULL) mtree_err("memory allocation error"); break; case F_SIZE: ip->st_size = (off_t)strtoll(val, &ep, 10); if (*ep) mtree_err("invalid size `%s'", val); break; case F_SLINK: if ((ip->slink = strdup(val)) == NULL) mtree_err("memory allocation error"); if (strunvis(ip->slink, val) == -1) mtree_err("strunvis failed on `%s'", val); break; case F_TAGS: len = strlen(val) + 3; /* "," + str + ",\0" */ if ((ip->tags = malloc(len)) == NULL) mtree_err("memory allocation error"); snprintf(ip->tags, len, ",%s,", val); break; case F_TIME: ip->st_mtimespec.tv_sec = (time_t)strtoll(val, &ep, 10); if (*ep != '.') mtree_err("invalid time `%s'", val); val = ep + 1; ip->st_mtimespec.tv_nsec = strtol(val, &ep, 10); if (*ep) mtree_err("invalid time `%s'", val); break; case F_TYPE: ip->type = parsetype(val); break; case F_UID: ip->st_uid = (uid_t)strtoul(val, &ep, 10); if (*ep) mtree_err("invalid uid `%s'", val); break; case F_UNAME: if (mtree_Wflag) /* don't parse if whacking */ break; if (uid_from_user(val, &uid) == -1) mtree_err("unknown user `%s'", val); ip->st_uid = uid; break; case F_SHA256: if (val[0]=='0' && val[1]=='x') md=&val[2]; else md=val; if ((ip->sha256digest = strdup(md)) == NULL) mtree_err("memory allocation error"); break; case F_SHA384: if (val[0]=='0' && val[1]=='x') md=&val[2]; else md=val; if ((ip->sha384digest = strdup(md)) == NULL) mtree_err("memory allocation error"); break; case F_SHA512: if (val[0]=='0' && val[1]=='x') md=&val[2]; else md=val; if ((ip->sha512digest = strdup(md)) == NULL) mtree_err("memory allocation error"); break; default: mtree_err( "set(): unsupported key type 0x%x (INTERNAL ERROR)", type); /* NOTREACHED */ } } } static void unset(char *t, NODE *ip) { char *p; while ((p = strsep(&t, " \t")) != NULL) { if (*p == '\0') continue; ip->flags &= ~parsekey(p, NULL); } } /* * 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; } /* * 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); }