[Midnightbsd-cvs] src [8625] vendor/NetBSD/mtree: add mtree from netbsd

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Sep 25 14:03:03 EDT 2016


Revision: 8625
          http://svnweb.midnightbsd.org/src/?rev=8625
Author:   laffer1
Date:     2016-09-25 14:03:03 -0400 (Sun, 25 Sep 2016)
Log Message:
-----------
add mtree from netbsd

Added Paths:
-----------
    vendor/NetBSD/mtree/
    vendor/NetBSD/mtree/dist/
    vendor/NetBSD/mtree/dist/Makefile
    vendor/NetBSD/mtree/dist/compare.c
    vendor/NetBSD/mtree/dist/crc.c
    vendor/NetBSD/mtree/dist/create.c
    vendor/NetBSD/mtree/dist/excludes.c
    vendor/NetBSD/mtree/dist/extern.h
    vendor/NetBSD/mtree/dist/getid.c
    vendor/NetBSD/mtree/dist/misc.c
    vendor/NetBSD/mtree/dist/mtree.8
    vendor/NetBSD/mtree/dist/mtree.c
    vendor/NetBSD/mtree/dist/mtree.h
    vendor/NetBSD/mtree/dist/spec.c
    vendor/NetBSD/mtree/dist/specspec.c
    vendor/NetBSD/mtree/dist/verify.c

Added: vendor/NetBSD/mtree/dist/Makefile
===================================================================
--- vendor/NetBSD/mtree/dist/Makefile	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/Makefile	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,20 @@
+#	$NetBSD: Makefile,v 1.33 2012/10/05 01:26:56 christos Exp $
+#	from: @(#)Makefile	8.2 (Berkeley) 4/27/95
+
+.include <bsd.own.mk>
+
+PROG=	mtree
+#CPPFLAGS+=-DDEBUG
+CPPFLAGS+= -DMTREE
+MAN=	mtree.8
+SRCS=	compare.c crc.c create.c excludes.c misc.c mtree.c spec.c specspec.c \
+	verify.c getid.c pack_dev.c
+.if (${HOSTPROG:U} == "")
+DPADD+= ${LIBUTIL}
+LDADD+= -lutil
+.endif
+
+CPPFLAGS+=	-I${NETBSDSRCDIR}/sbin/mknod
+.PATH:		${NETBSDSRCDIR}/sbin/mknod
+
+.include <bsd.prog.mk>

Added: vendor/NetBSD/mtree/dist/compare.c
===================================================================
--- vendor/NetBSD/mtree/dist/compare.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/compare.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,528 @@
+/*	$NetBSD: compare.c,v 1.55 2012/10/05 00:59:35 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 <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)compare.c	8.1 (Berkeley) 6/6/93";
+#else
+__RCSID("$NetBSD: compare.c,v 1.55 2012/10/05 00:59:35 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifndef NO_MD5
+#include <md5.h>
+#endif
+#ifndef NO_RMD160
+#include <rmd160.h>
+#endif
+#ifndef NO_SHA1
+#include <sha1.h>
+#endif
+#ifndef NO_SHA2
+#include <sha2.h>
+#endif
+
+#include "extern.h"
+
+#define	INDENTNAMELEN	8
+#define MARK								\
+do {									\
+	len = printf("%s: ", RP(p));					\
+	if (len > INDENTNAMELEN) {					\
+		tab = "\t";						\
+		printf("\n");						\
+	} else {							\
+		tab = "";						\
+		printf("%*s", INDENTNAMELEN - (int)len, "");		\
+	}								\
+} while (0)
+#define	LABEL if (!label++) MARK
+
+#if HAVE_STRUCT_STAT_ST_FLAGS
+
+
+#define CHANGEFLAGS							\
+	if (flags != p->fts_statp->st_flags) {				\
+		char *sf;						\
+		if (!label) {						\
+			MARK;						\
+			sf = flags_to_string(p->fts_statp->st_flags, "none"); \
+			printf("%sflags (\"%s\"", tab, sf);		\
+			free(sf);					\
+		}							\
+		if (lchflags(p->fts_accpath, flags)) {			\
+			label++;					\
+			printf(", not modified: %s)\n",			\
+			    strerror(errno));				\
+		} else {						\
+			sf = flags_to_string(flags, "none");		\
+			printf(", modified to \"%s\")\n", sf);		\
+			free(sf);					\
+		}							\
+	}
+
+/* SETFLAGS:
+ * given pflags, additionally set those flags specified in s->st_flags and
+ * selected by mask (the other flags are left unchanged).
+ */
+#define SETFLAGS(pflags, mask)						\
+do {									\
+	flags = (s->st_flags & (mask)) | (pflags);			\
+	CHANGEFLAGS;							\
+} while (0)
+
+/* CLEARFLAGS:
+ * given pflags, reset the flags specified in s->st_flags and selected by mask
+ * (the other flags are left unchanged).
+ */
+#define CLEARFLAGS(pflags, mask)					\
+do {									\
+	flags = (~(s->st_flags & (mask)) & CH_MASK) & (pflags);		\
+	CHANGEFLAGS;							\
+} while (0)
+#endif	/* HAVE_STRUCT_STAT_ST_FLAGS */
+
+int
+compare(NODE *s, FTSENT *p)
+{
+	u_int32_t len, val, flags;
+	int fd, label;
+	const char *cp, *tab;
+#if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2)
+	char *digestbuf;
+#endif
+
+	tab = NULL;
+	label = 0;
+	switch(s->type) {
+	case F_BLOCK:
+		if (!S_ISBLK(p->fts_statp->st_mode))
+			goto typeerr;
+		break;
+	case F_CHAR:
+		if (!S_ISCHR(p->fts_statp->st_mode))
+			goto typeerr;
+		break;
+	case F_DIR:
+		if (!S_ISDIR(p->fts_statp->st_mode))
+			goto typeerr;
+		break;
+	case F_FIFO:
+		if (!S_ISFIFO(p->fts_statp->st_mode))
+			goto typeerr;
+		break;
+	case F_FILE:
+		if (!S_ISREG(p->fts_statp->st_mode))
+			goto typeerr;
+		break;
+	case F_LINK:
+		if (!S_ISLNK(p->fts_statp->st_mode))
+			goto typeerr;
+		break;
+#ifdef S_ISSOCK
+	case F_SOCK:
+		if (!S_ISSOCK(p->fts_statp->st_mode))
+			goto typeerr;
+		break;
+#endif
+typeerr:		LABEL;
+		printf("\ttype (%s, %s)\n",
+		    nodetype(s->type), inotype(p->fts_statp->st_mode));
+		return (label);
+	}
+	if (mtree_Wflag)
+		goto afterpermwhack;
+#if HAVE_STRUCT_STAT_ST_FLAGS
+	if (iflag && !uflag) {
+		if (s->flags & F_FLAGS)
+		    SETFLAGS(p->fts_statp->st_flags, SP_FLGS);
+		return (label);
+        }
+	if (mflag && !uflag) {
+		if (s->flags & F_FLAGS)
+		    CLEARFLAGS(p->fts_statp->st_flags, SP_FLGS);
+		return (label);
+        }
+#endif
+	if (s->flags & F_DEV &&
+	    (s->type == F_BLOCK || s->type == F_CHAR) &&
+	    s->st_rdev != p->fts_statp->st_rdev) {
+		LABEL;
+		printf("%sdevice (%#llx, %#llx",
+		    tab, (long long)s->st_rdev,
+		    (long long)p->fts_statp->st_rdev);
+		if (uflag) {
+			if ((unlink(p->fts_accpath) == -1) ||
+			    (mknod(p->fts_accpath,
+			      s->st_mode | nodetoino(s->type),
+			      s->st_rdev) == -1) ||
+			    (lchown(p->fts_accpath, p->fts_statp->st_uid,
+			      p->fts_statp->st_gid) == -1) )
+				printf(", not modified: %s)\n",
+				    strerror(errno));
+			 else
+				printf(", modified)\n");
+		} else
+			printf(")\n");
+		tab = "\t";
+	}
+	/* Set the uid/gid first, then set the mode. */
+	if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
+		LABEL;
+		printf("%suser (%lu, %lu",
+		    tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
+		if (uflag) {
+			if (lchown(p->fts_accpath, s->st_uid, -1))
+				printf(", not modified: %s)\n",
+				    strerror(errno));
+			else
+				printf(", modified)\n");
+		} else
+			printf(")\n");
+		tab = "\t";
+	}
+	if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
+		LABEL;
+		printf("%sgid (%lu, %lu",
+		    tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
+		if (uflag) {
+			if (lchown(p->fts_accpath, -1, s->st_gid))
+				printf(", not modified: %s)\n",
+				    strerror(errno));
+			else
+				printf(", modified)\n");
+		}
+		else
+			printf(")\n");
+		tab = "\t";
+	}
+	if (s->flags & F_MODE &&
+	    s->st_mode != (p->fts_statp->st_mode & MBITS)) {
+		if (lflag) {
+			mode_t tmode, mode;
+
+			tmode = s->st_mode;
+			mode = p->fts_statp->st_mode & MBITS;
+			/*
+			 * if none of the suid/sgid/etc bits are set,
+			 * then if the mode is a subset of the target,
+			 * skip.
+			 */
+			if (!((tmode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) ||
+			    (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO))))
+				if ((mode | tmode) == tmode)
+					goto skip;
+		}
+
+		LABEL;
+		printf("%spermissions (%#lo, %#lo",
+		    tab, (u_long)s->st_mode,
+		    (u_long)p->fts_statp->st_mode & MBITS);
+		if (uflag) {
+			if (lchmod(p->fts_accpath, s->st_mode))
+				printf(", not modified: %s)\n",
+				    strerror(errno));
+			else
+				printf(", modified)\n");
+		}
+		else
+			printf(")\n");
+		tab = "\t";
+	skip:	;
+	}
+	if (s->flags & F_NLINK && s->type != F_DIR &&
+	    s->st_nlink != p->fts_statp->st_nlink) {
+		LABEL;
+		printf("%slink count (%lu, %lu)\n",
+		    tab, (u_long)s->st_nlink, (u_long)p->fts_statp->st_nlink);
+		tab = "\t";
+	}
+	if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) {
+		LABEL;
+		printf("%ssize (%lld, %lld)\n",
+		    tab, (long long)s->st_size,
+		    (long long)p->fts_statp->st_size);
+		tab = "\t";
+	}
+	/*
+	 * XXX
+	 * Since utimes(2) only takes a timeval, there's no point in
+	 * comparing the low bits of the timespec nanosecond field.  This
+	 * will only result in mismatches that we can never fix.
+	 *
+	 * Doesn't display microsecond differences.
+	 */
+	if (s->flags & F_TIME) {
+		struct timeval tv[2];
+		struct stat *ps = p->fts_statp;
+		time_t smtime = s->st_mtimespec.tv_sec;
+
+#if defined(BSD4_4) && !defined(HAVE_NBTOOL_CONFIG_H)
+		time_t pmtime = ps->st_mtimespec.tv_sec;
+
+		TIMESPEC_TO_TIMEVAL(&tv[0], &s->st_mtimespec);
+		TIMESPEC_TO_TIMEVAL(&tv[1], &ps->st_mtimespec);
+#else
+		time_t pmtime = (time_t)ps->st_mtime;
+
+		tv[0].tv_sec = smtime;
+		tv[0].tv_usec = 0;
+		tv[1].tv_sec = pmtime;
+		tv[1].tv_usec = 0;
+#endif
+
+		if (tv[0].tv_sec != tv[1].tv_sec ||
+		    tv[0].tv_usec != tv[1].tv_usec) {
+			LABEL;
+			printf("%smodification time (%.24s, ",
+			    tab, ctime(&smtime));
+			printf("%.24s", ctime(&pmtime));
+			if (tflag) {
+				tv[1] = tv[0];
+				if (utimes(p->fts_accpath, tv))
+					printf(", not modified: %s)\n",
+					    strerror(errno));
+				else
+					printf(", modified)\n");
+			} else
+				printf(")\n");
+			tab = "\t";
+		}
+	}
+#if HAVE_STRUCT_STAT_ST_FLAGS
+	/*
+	 * XXX
+	 * since lchflags(2) will reset file times, the utimes() above
+	 * may have been useless!  oh well, we'd rather have correct
+	 * flags, rather than times?
+	 */
+        if ((s->flags & F_FLAGS) && ((s->st_flags != p->fts_statp->st_flags)
+	    || mflag || iflag)) {
+		if (s->st_flags != p->fts_statp->st_flags) {
+			char *f_s;
+			LABEL;
+			f_s = flags_to_string(s->st_flags, "none");
+			printf("%sflags (\"%s\" is not ", tab, f_s);
+			free(f_s);
+			f_s = flags_to_string(p->fts_statp->st_flags, "none");
+			printf("\"%s\"", f_s);
+			free(f_s);
+		}
+		if (uflag) {
+			if (iflag)
+				SETFLAGS(0, CH_MASK);
+			else if (mflag)
+				CLEARFLAGS(0, SP_FLGS);
+			else
+				SETFLAGS(0, (~SP_FLGS & CH_MASK));
+		} else
+			printf(")\n");
+		tab = "\t";
+	}
+#endif	/* HAVE_STRUCT_STAT_ST_FLAGS */
+
+	/*
+	 * from this point, no more permission checking or whacking
+	 * occurs, only checking of stuff like checksums and symlinks.
+	 */
+ afterpermwhack:
+	if (s->flags & F_CKSUM) {
+		if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
+			LABEL;
+			printf("%scksum: %s: %s\n",
+			    tab, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else if (crc(fd, &val, &len)) {
+			close(fd);
+			LABEL;
+			printf("%scksum: %s: %s\n",
+			    tab, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else {
+			close(fd);
+			if (s->cksum != val) {
+				LABEL;
+				printf("%scksum (%lu, %lu)\n",
+				    tab, s->cksum, (unsigned long)val);
+			}
+			tab = "\t";
+		}
+	}
+#ifndef NO_MD5
+	if (s->flags & F_MD5) {
+		if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL) {
+			LABEL;
+			printf("%s%s: %s: %s\n",
+			    tab, MD5KEY, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else {
+			if (strcmp(s->md5digest, digestbuf)) {
+				LABEL;
+				printf("%s%s (0x%s, 0x%s)\n",
+				    tab, MD5KEY, s->md5digest, digestbuf);
+			}
+			tab = "\t";
+			free(digestbuf);
+		}
+	}
+#endif	/* ! NO_MD5 */
+#ifndef NO_RMD160
+	if (s->flags & F_RMD160) {
+		if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL) {
+			LABEL;
+			printf("%s%s: %s: %s\n",
+			    tab, RMD160KEY, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else {
+			if (strcmp(s->rmd160digest, digestbuf)) {
+				LABEL;
+				printf("%s%s (0x%s, 0x%s)\n",
+				    tab, RMD160KEY, s->rmd160digest, digestbuf);
+			}
+			tab = "\t";
+			free(digestbuf);
+		}
+	}
+#endif	/* ! NO_RMD160 */
+#ifndef NO_SHA1
+	if (s->flags & F_SHA1) {
+		if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL) {
+			LABEL;
+			printf("%s%s: %s: %s\n",
+			    tab, SHA1KEY, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else {
+			if (strcmp(s->sha1digest, digestbuf)) {
+				LABEL;
+				printf("%s%s (0x%s, 0x%s)\n",
+				    tab, SHA1KEY, s->sha1digest, digestbuf);
+			}
+			tab = "\t";
+			free(digestbuf);
+		}
+	}
+#endif	/* ! NO_SHA1 */
+#ifndef NO_SHA2
+	if (s->flags & F_SHA256) {
+		if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL) {
+			LABEL;
+			printf("%s%s: %s: %s\n",
+			    tab, SHA256KEY, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else {
+			if (strcmp(s->sha256digest, digestbuf)) {
+				LABEL;
+				printf("%s%s (0x%s, 0x%s)\n",
+				    tab, SHA256KEY, s->sha256digest, digestbuf);
+			}
+			tab = "\t";
+			free(digestbuf);
+		}
+	}
+#ifdef SHA384_BLOCK_LENGTH
+	if (s->flags & F_SHA384) {
+		if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL) {
+			LABEL;
+			printf("%s%s: %s: %s\n",
+			    tab, SHA384KEY, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else {
+			if (strcmp(s->sha384digest, digestbuf)) {
+				LABEL;
+				printf("%s%s (0x%s, 0x%s)\n",
+				    tab, SHA384KEY, s->sha384digest, digestbuf);
+			}
+			tab = "\t";
+			free(digestbuf);
+		}
+	}
+#endif
+	if (s->flags & F_SHA512) {
+		if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL) {
+			LABEL;
+			printf("%s%s: %s: %s\n",
+			    tab, SHA512KEY, p->fts_accpath, strerror(errno));
+			tab = "\t";
+		} else {
+			if (strcmp(s->sha512digest, digestbuf)) {
+				LABEL;
+				printf("%s%s (0x%s, 0x%s)\n",
+				    tab, SHA512KEY, s->sha512digest, digestbuf);
+			}
+			tab = "\t";
+			free(digestbuf);
+		}
+	}
+#endif	/* ! NO_SHA2 */
+	if (s->flags & F_SLINK &&
+	    strcmp(cp = rlink(p->fts_accpath), s->slink)) {
+		LABEL;
+		printf("%slink ref (%s, %s", tab, cp, s->slink);
+		if (uflag) {
+			if ((unlink(p->fts_accpath) == -1) ||
+			    (symlink(s->slink, p->fts_accpath) == -1) )
+				printf(", not modified: %s)\n",
+				    strerror(errno));
+			else
+				printf(", modified)\n");
+		} else
+			printf(")\n");
+	}
+	return (label);
+}
+
+const char *
+rlink(const char *name)
+{
+	static char lbuf[MAXPATHLEN];
+	int len;
+
+	if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
+		mtree_err("%s: %s", name, strerror(errno));
+	lbuf[len] = '\0';
+	return (lbuf);
+}

Added: vendor/NetBSD/mtree/dist/crc.c
===================================================================
--- vendor/NetBSD/mtree/dist/crc.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/crc.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,163 @@
+/*	$NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $	*/
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * 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 <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)crc.c	8.1 (Berkeley) 6/17/93";
+#else
+__RCSID("$NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static const u_int32_t crctab[] = {
+	0x0,
+	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
+	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
+	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
+	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
+	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
+	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
+	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
+	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
+	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
+	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
+	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
+	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
+	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
+	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
+	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
+	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
+	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
+	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
+	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
+	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
+	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
+	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
+	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
+	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
+	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
+	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
+	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
+	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
+	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
+	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+/*
+ * Compute a POSIX 1003.2 checksum.  This routine has been broken out so that
+ * other programs can use it.  It takes a file descriptor to read from and
+ * locations to store the crc and the number of bytes read.  It returns 0 on
+ * success and 1 on failure.  Errno is set on failure.
+ */
+u_int32_t crc_total = ~0;		/* The crc over a number of files. */
+
+int
+crc(int fd, u_int32_t *cval, u_int32_t *clen)
+{
+	u_char *p;
+	int nr;
+	u_int32_t thecrc, len;
+	u_int32_t crctot;
+	u_char buf[16 * 1024];
+
+#define	COMPUTE(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
+
+	thecrc = len = crctot = 0;
+	if (sflag)
+		crctot = ~crc_total;
+	while ((nr = read(fd, buf, sizeof(buf))) > 0)
+		if (sflag) {
+			for (len += nr, p = buf; nr--; ++p) {
+				COMPUTE(thecrc, *p);
+				COMPUTE(crctot, *p);
+			}
+		} else {
+			for (len += nr, p = buf; nr--; ++p)
+				COMPUTE(thecrc, *p);
+		}
+	if (nr < 0)
+		return 1;
+
+	*clen = len;
+
+	/* Include the length of the file. */
+	if (sflag) {
+		for (; len != 0; len >>= 8) {
+			COMPUTE(thecrc, len & 0xff);
+			COMPUTE(crctot, len & 0xff);
+		}
+	} else {
+		for (; len != 0; len >>= 8)
+			COMPUTE(thecrc, len & 0xff);
+	}
+
+	*cval = ~thecrc;
+	if (sflag)
+		crc_total = ~crctot;
+	return 0;
+}

Added: vendor/NetBSD/mtree/dist/create.c
===================================================================
--- vendor/NetBSD/mtree/dist/create.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/create.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,467 @@
+/*	$NetBSD: create.c,v 1.68 2012/12/20 16:43:16 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 <sys/cdefs.h>
+#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.68 2012/12/20 16:43:16 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#if ! HAVE_NBTOOL_CONFIG_H
+#include <dirent.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifndef NO_MD5
+#include <md5.h>
+#endif
+#ifndef NO_RMD160
+#include <rmd160.h>
+#endif
+#ifndef NO_SHA1
+#include <sha1.h>
+#endif
+#ifndef NO_SHA2
+#include <sha2.h>
+#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 *);
+
+void
+cwalk(void)
+{
+	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 :
+		    "<unknown>";
+	}
+
+	if (!nflag)
+		printf(
+	    	    "#\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;
+		}
+		switch(p->fts_info) {
+		case FTS_D:
+			if (!bflag)
+				printf("\n");
+			if (!nflag)
+				printf("# %s\n", p->fts_path);
+			statd(t, p, &uid, &gid, &mode, &flags);
+			statf(indent, p);
+			break;
+		case FTS_DP:
+			if (p->fts_level > 0)
+				if (!nflag)
+					printf("%*s# %s\n", indent, "",
+					    p->fts_path);
+			if (p->fts_level > 0 || flavor == F_FREEBSD9) {
+				printf("%*s..\n", indent, "");
+				if (!bflag)
+					printf("\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);
+			break;
+
+		}
+	}
+	fts_close(t);
+	if (sflag && keys & F_CKSUM)
+		mtree_err("%s checksum: %u", fullpath, crc_total);
+}
+
+static void
+statf(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, "",
+	    S_ISDIR(p->fts_statp->st_mode) ? "" : "    ", vispath(p->fts_name));
+
+	if (offset > (INDENTNAMELEN + indent))
+		offset = MAXLINELEN;
+	else
+		offset += printf("%*s", (INDENTNAMELEN + indent) - offset, "");
+
+	if (!S_ISREG(p->fts_statp->st_mode) && (flavor == F_NETBSD6 || !dflag))
+		output(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);
+		if (keys & F_UID || (keys & F_UNAME && name == NULL))
+			output(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);
+		if (keys & F_GID || (keys & F_GNAME && name == NULL))
+			output(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",
+		    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=%#llx",
+		    (long long)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);
+	if (keys & F_SIZE &&
+	    (flavor != F_NETBSD6 || S_ISREG(p->fts_statp->st_mode)))
+		output(indent, &offset, "size=%lld",
+		    (long long)p->fts_statp->st_size);
+	if (keys & F_TIME)
+#if defined(BSD4_4) && !defined(HAVE_NBTOOL_CONFIG_H)
+		output(indent, &offset, "time=%ld.%09ld",
+		    (long)p->fts_statp->st_mtimespec.tv_sec,
+		    p->fts_statp->st_mtimespec.tv_nsec);
+#else
+		output(indent, &offset, "time=%ld.%09ld",
+		    (long)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);
+	}
+#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);
+		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);
+		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);
+		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);
+		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);
+		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);
+		free(digestbuf);
+	}
+#endif	/* ! NO_SHA2 */
+	if (keys & F_SLINK &&
+	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
+		output(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);
+		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)
+{
+	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");
+		else
+			printf("/set type=file");
+		if (keys & (F_UID | F_UNAME)) {
+			if (keys & F_UNAME &&
+			    (name = user_from_uid(saveuid, 1)) != NULL)
+				printf(" uname=%s", name);
+			if (keys & F_UID || (keys & F_UNAME && name == NULL))
+				printf(" 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);
+			if (keys & F_GID || (keys & F_GNAME && name == NULL))
+				printf(" gid=%lu", (u_long)savegid);
+		}
+		if (keys & F_MODE)
+			printf(" mode=%#lo", (u_long)savemode);
+		if (keys & F_NLINK)
+			printf(" nlink=1");
+		if (keys & F_FLAGS) {
+			char *str = flags_to_string(saveflags, "none");
+			printf(" flags=%s", str);
+			free(str);
+		}
+		printf("\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, ...)
+{
+	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, "");
+		*offset = INDENTNAMELEN + indent;
+	}
+	*offset += printf(" %s", buf) + 1;
+}

Added: vendor/NetBSD/mtree/dist/excludes.c
===================================================================
--- vendor/NetBSD/mtree/dist/excludes.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/excludes.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,121 @@
+/*	$NetBSD: excludes.c,v 1.13 2004/06/20 22:20:18 jmc Exp $	*/
+
+/*
+ * Copyright 2000 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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 <sys/cdefs.h>
+
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: excludes.c,v 1.13 2004/06/20 22:20:18 jmc Exp $");
+#endif
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <fnmatch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <util.h>
+
+#include "extern.h"
+
+
+/*
+ * We're assuming that there won't be a whole lot of excludes,
+ * so it's OK to use a stupid algorithm.
+ */
+struct exclude {
+	LIST_ENTRY(exclude) link;
+	const char *glob;
+	int pathname;
+};
+static LIST_HEAD(, exclude) excludes;
+
+
+void
+init_excludes(void)
+{
+
+	LIST_INIT(&excludes);
+}
+
+void
+read_excludes_file(const char *name)
+{
+	FILE *fp;
+	char *line;
+	struct exclude *e;
+
+	fp = fopen(name, "r");
+	if (fp == 0)
+		err(1, "%s", name);
+
+	while ((line = fparseln(fp, NULL, NULL, NULL,
+	    FPARSELN_UNESCCOMM | FPARSELN_UNESCCONT | FPARSELN_UNESCESC))
+	    != NULL) {
+		if (line[0] == '\0')
+			continue;
+
+		if ((e = malloc(sizeof *e)) == NULL)
+			mtree_err("memory allocation error");
+
+		e->glob = line;
+		if (strchr(e->glob, '/') != NULL)
+			e->pathname = 1;
+		else
+			e->pathname = 0;
+		LIST_INSERT_HEAD(&excludes, e, link);
+	}
+	fclose(fp);
+}
+
+int
+check_excludes(const char *fname, const char *path)
+{
+	struct exclude *e;
+
+	/* fnmatch(3) has a funny return value convention... */
+#define MATCH(g, n) (fnmatch((g), (n), FNM_PATHNAME) == 0)
+
+	e = LIST_FIRST(&excludes);
+	while (e) {
+		if ((e->pathname && MATCH(e->glob, path))
+		    || MATCH(e->glob, fname)) {
+			return (1);
+		}
+		e = LIST_NEXT(e, link);
+	}
+	return (0);
+}

Added: vendor/NetBSD/mtree/dist/extern.h
===================================================================
--- vendor/NetBSD/mtree/dist/extern.h	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/extern.h	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,87 @@
+/*	$NetBSD: extern.h,v 1.37 2012/12/20 16:43:16 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 <err.h> 
+#include <fts.h>
+#include <util.h>
+
+#if HAVE_NETDB_H
+/* For MAXHOSTNAMELEN on some platforms. */
+#include <netdb.h>
+#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	 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 *);
+
+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;
+

Added: vendor/NetBSD/mtree/dist/getid.c
===================================================================
--- vendor/NetBSD/mtree/dist/getid.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/getid.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,431 @@
+/*	$NetBSD: getid.c,v 1.7 2008/04/28 20:24:17 martin 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 <sys/cdefs.h>
+__RCSID("$NetBSD: getid.c,v 1.7 2008/04/28 20:24:17 martin Exp $");
+
+#include <sys/param.h>
+
+#include <grp.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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;
+}
+
+
+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;
+		}
+		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;
+}
+
+
+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;
+		}
+		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;
+}
+

Added: vendor/NetBSD/mtree/dist/misc.c
===================================================================
--- vendor/NetBSD/mtree/dist/misc.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/misc.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,312 @@
+/*	$NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 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.
+ *
+ *	@(#)misc.c	8.1 (Berkeley) 6/6/93
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+__RCSID("$NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 christos Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "extern.h"
+
+enum flavor	flavor = F_MTREE;
+
+typedef struct _key {
+	const char	*name;		/* key name */
+	u_int		val;		/* value */
+
+#define	NEEDVALUE	0x01
+	u_int		flags;
+} KEY;
+
+/* NB: the following tables must be sorted lexically. */
+static KEY keylist[] = {
+	{"cksum",	F_CKSUM,	NEEDVALUE},
+	{"device",	F_DEV,		NEEDVALUE},
+	{"flags",	F_FLAGS,	NEEDVALUE},
+	{"gid",		F_GID,		NEEDVALUE},
+	{"gname",	F_GNAME,	NEEDVALUE},
+	{"ignore",	F_IGN,		0},
+	{"link",	F_SLINK,	NEEDVALUE},
+	{"md5",		F_MD5,		NEEDVALUE},
+	{"md5digest",	F_MD5,		NEEDVALUE},
+	{"mode",	F_MODE,		NEEDVALUE},
+	{"nlink",	F_NLINK,	NEEDVALUE},
+	{"nochange",	F_NOCHANGE,	0},
+	{"optional",	F_OPT,		0},
+	{"ripemd160digest", F_RMD160,	NEEDVALUE},
+	{"rmd160",	F_RMD160,	NEEDVALUE},
+	{"rmd160digest",F_RMD160,	NEEDVALUE},
+	{"sha1",	F_SHA1,		NEEDVALUE},
+	{"sha1digest",	F_SHA1,		NEEDVALUE},
+	{"sha256",	F_SHA256,	NEEDVALUE},
+	{"sha256digest",F_SHA256,	NEEDVALUE},
+	{"sha384",	F_SHA384,	NEEDVALUE},
+	{"sha384digest",F_SHA384,	NEEDVALUE},
+	{"sha512",	F_SHA512,	NEEDVALUE},
+	{"sha512digest",F_SHA512,	NEEDVALUE},
+	{"size",	F_SIZE,		NEEDVALUE},
+	{"tags",	F_TAGS,		NEEDVALUE},
+	{"time",	F_TIME,		NEEDVALUE},
+	{"type",	F_TYPE,		NEEDVALUE},
+	{"uid",		F_UID,		NEEDVALUE},
+	{"uname",	F_UNAME,	NEEDVALUE}
+};
+
+static KEY typelist[] = {
+	{"block",	F_BLOCK,	0},
+	{"char",	F_CHAR,		0},
+	{"dir",		F_DIR,		0},
+#ifdef S_IFDOOR
+	{"door",	F_DOOR,		0},
+#endif
+	{"fifo",	F_FIFO,		0},
+	{"file",	F_FILE,		0},
+	{"link",	F_LINK,		0},
+	{"socket",	F_SOCK,		0},
+};
+
+slist_t	excludetags, includetags;
+int	keys = KEYDEFAULT;
+
+
+int keycompare(const void *, const void *);
+
+u_int
+parsekey(const char *name, int *needvaluep)
+{
+	static int allbits;
+	KEY *k, tmp;
+
+	if (allbits == 0) {
+		size_t i;
+
+		for (i = 0; i < sizeof(keylist) / sizeof(KEY); i++)
+			allbits |= keylist[i].val;
+	}
+	tmp.name = name;
+	if (strcmp(name, "all") == 0)
+		return (allbits);
+	k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY),
+	    sizeof(KEY), keycompare);
+	if (k == NULL)
+		mtree_err("unknown keyword `%s'", name);
+
+	if (needvaluep)
+		*needvaluep = k->flags & NEEDVALUE ? 1 : 0;
+
+	return (k->val);
+}
+
+u_int
+parsetype(const char *name)
+{
+	KEY *k, tmp;
+
+	tmp.name = name;
+	k = (KEY *)bsearch(&tmp, typelist, sizeof(typelist) / sizeof(KEY),
+	    sizeof(KEY), keycompare);
+	if (k == NULL)
+		mtree_err("unknown file type `%s'", name);
+
+	return (k->val);
+}
+
+int
+keycompare(const void *a, const void *b)
+{
+
+	return (strcmp(((const KEY *)a)->name, ((const KEY *)b)->name));
+}
+
+void
+mtree_err(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vwarnx(fmt, ap);
+	va_end(ap);
+	if (mtree_lineno)
+		warnx("failed at line %lu of the specification",
+		    (u_long) mtree_lineno);
+	exit(1);
+	/* NOTREACHED */
+}
+
+void
+addtag(slist_t *list, char *elem)
+{
+
+#define	TAG_CHUNK 20
+
+	if ((list->count % TAG_CHUNK) == 0) {
+		char **new;
+
+		new = (char **)realloc(list->list, (list->count + TAG_CHUNK)
+		    * sizeof(char *));
+		if (new == NULL)
+			mtree_err("memory allocation error");
+		list->list = new;
+	}
+	list->list[list->count] = elem;
+	list->count++;
+}
+
+void
+parsetags(slist_t *list, char *args)
+{
+	char	*p, *e;
+	int	len;
+
+	if (args == NULL) {
+		addtag(list, NULL);
+		return;
+	}
+	while ((p = strsep(&args, ",")) != NULL) {
+		if (*p == '\0')
+			continue;
+		len = strlen(p) + 3;	/* "," + p + ",\0" */
+		if ((e = malloc(len)) == NULL)
+			mtree_err("memory allocation error");
+		snprintf(e, len, ",%s,", p);
+		addtag(list, e);
+	}
+}
+
+/*
+ * matchtags
+ *	returns 0 if there's a match from the exclude list in the node's tags,
+ *	or there's an include list and no match.
+ *	return 1 otherwise.
+ */
+int
+matchtags(NODE *node)
+{
+	int	i;
+
+	if (node->tags) {
+		for (i = 0; i < excludetags.count; i++)
+			if (strstr(node->tags, excludetags.list[i]))
+				break;
+		if (i < excludetags.count)
+			return (0);
+
+		for (i = 0; i < includetags.count; i++)
+			if (strstr(node->tags, includetags.list[i]))
+				break;
+		if (i > 0 && i == includetags.count)
+			return (0);
+	} else if (includetags.count > 0) {
+		return (0);
+	}
+	return (1);
+}
+
+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 */
+}
+
+const char *
+nodetype(u_int type)
+{
+
+	return (inotype(nodetoino(type)));
+}
+
+
+const char *
+inotype(u_int type)
+{
+
+	switch (type & S_IFMT) {
+	case S_IFBLK:
+		return ("block");
+	case S_IFCHR:
+		return ("char");
+	case S_IFDIR:
+		return ("dir");
+	case S_IFIFO:
+		return ("fifo");
+	case S_IFREG:
+		return ("file");
+	case S_IFLNK:
+		return ("link");
+#ifdef S_IFSOCK
+	case S_IFSOCK:
+		return ("socket");
+#endif
+#ifdef S_IFDOOR
+	case S_IFDOOR:
+		return ("door");
+#endif
+	default:
+		return ("unknown");
+	}
+	/* NOTREACHED */
+}

Added: vendor/NetBSD/mtree/dist/mtree.8
===================================================================
--- vendor/NetBSD/mtree/dist/mtree.8	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/mtree.8	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,805 @@
+.\"	$NetBSD: mtree.8,v 1.67 2012/12/20 20:31:01 wiz 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.
+.\"
+.\" 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.
+.\"
+.\"     @(#)mtree.8	8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 20, 2012
+.Dt MTREE 8
+.Os
+.Sh NAME
+.Nm mtree
+.Nd map a directory hierarchy
+.Sh SYNOPSIS
+.Nm
+.Op Fl bCcDdejLlMnPqrStUuWx
+.Op Fl i | Fl m
+.Op Fl E Ar tags
+.Op Fl F Ar flavor
+.Op Fl f Ar spec
+.Op Fl I Ar tags
+.Op Fl K Ar keywords
+.Op Fl k Ar keywords
+.Op Fl N Ar dbdir
+.Op Fl p Ar path
+.Op Fl R Ar keywords
+.Op Fl s Ar seed
+.Op Fl X Ar exclude-file
+.Sh DESCRIPTION
+The
+.Nm
+utility compares a file hierarchy against a specification,
+creates a specification for a file hierarchy, or modifies
+a specification.
+.Pp
+The default action, if not overridden by command line options,
+is to compare the file hierarchy rooted in the current directory
+against a specification read from the standard input.
+Messages are written to the standard output for any files whose
+characteristics do not match the specification, or which are
+missing from either the file hierarchy or the specification.
+.Pp
+The options are as follows:
+.Bl -tag -width Xxxexcludexfilexx
+.It Fl b
+Suppress blank lines before entering and after exiting directories.
+.It Fl C
+Convert a specification into
+a format that's easier to parse with various tools.
+The input specification is read from standard input or
+from the file given by
+.Fl f Ar spec .
+In the output, each file or directory is represented using a single line
+(which might be very long).
+The full path name
+(beginning with
+.Dq \&./ )
+is always printed as the first field;
+.Fl K ,
+.Fl k ,
+and
+.Fl R
+can be used to control which other keywords are printed;
+.Fl E
+and
+.Fl I
+can be used to control which files are printed;
+and the
+.Fl S
+option can be used to sort the output.
+.It Fl c
+Print a specification for the file hierarchy originating at
+the current working directory (or the directory provided by
+.Fl p Ar path )
+to the standard output.
+The output is in a style using relative path names.
+.It Fl D
+As per
+.Fl C ,
+except that the path name is always printed as the last field instead of
+the first.
+.It Fl d
+Ignore everything except directory type files.
+.It Fl E Ar tags
+Add the comma separated tags to the
+.Dq exclusion
+list.
+Non-directories with tags which are in the exclusion list are not printed with
+.Fl C
+and
+.Fl D .
+.It Fl e
+Don't complain about files that are in the file hierarchy, but not in the
+specification.
+.It Fl F Ar flavor
+Set the compatibility flavor of the
+.Nm
+utility.
+The
+.Ar flavor
+can be one of
+.Sy mtree ,
+.Sy freebsd9 ,
+or
+.Sy netbsd6 .
+The default is
+.Sy mtree .
+The
+.Sy freebsd9
+and
+.Sy netbsd6
+flavors attempt to preserve output compatiblity and command line option
+backward compatibility with
+.Fx 9.0
+and
+.Nx 6.0
+respectively.
+.It Fl f Ar spec
+Read the specification from
+.Ar file  ,
+instead of from the standard input.
+.Pp
+If this option is specified twice, the two specifications are compared
+to each other rather than to the file hierarchy.
+The specifications will be sorted like output generated using
+.Fl c .
+The output format in this case is somewhat reminiscent of
+.Xr comm 1 ,
+having "in first spec only", "in second spec only", and "different"
+columns, prefixed by zero, one and two TAB characters respectively.
+Each entry in the "different" column occupies two lines, one from each
+specification.
+.It Fl I Ar tags
+Add the comma separated tags to the
+.Dq inclusion
+list.
+Non-directories with tags which are in the inclusion list are printed with
+.Fl C
+and
+.Fl D .
+If no inclusion list is provided, the default is to display all files.
+.It Fl i
+If specified, set the schg and/or sappnd flags.
+.It Fl j
+Indent the output 4 spaces each time a directory level is descended when
+creating a specification with the
+.Fl c
+option.
+This does not affect either the /set statements or the comment before each
+directory.
+It does however affect the comment before the close of each directory.
+This is the equivalent of the
+.Fl i
+option in the
+.Fx
+version of
+.Nm .
+.It Fl K Ar keywords
+Add the specified (whitespace or comma separated) keywords to the current
+set of keywords.
+If
+.Ql all
+is specified, add all of the other keywords.
+.It Fl k Ar keywords
+Use the
+.Sy type
+keyword plus the specified (whitespace or comma separated)
+keywords instead of the current set of keywords.
+If
+.Ql all
+is specified, use all of the other keywords.
+If the
+.Sy type
+keyword is not desired, suppress it with
+.Fl R Ar type .
+.It Fl L
+Follow all symbolic links in the file hierarchy.
+.It Fl l
+Do
+.Dq loose
+permissions checks, in which more stringent permissions
+will match less stringent ones.
+For example, a file marked mode 0444
+will pass a check for mode 0644.
+.Dq Loose
+checks apply only to read, write and execute permissions -- in
+particular, if other bits like the sticky bit or suid/sgid bits are
+set either in the specification or the file, exact checking will be
+performed.
+This option may not be set at the same time as the
+.Fl U
+or
+.Fl u
+option.
+.It Fl M
+Permit merging of specification entries with different types,
+with the last entry taking precedence.
+.It Fl m
+If the schg and/or sappnd flags are specified, reset these flags.
+Note that this is only possible with securelevel less than 1 (i.e.,
+in single user mode or while the system is running in insecure
+mode).
+See
+.Xr init 8
+for information on security levels.
+.It Fl n
+Do not emit pathname comments when creating a specification.
+Normally
+a comment is emitted before each directory and before the close of that
+directory when using the
+.Fl c
+option.
+.It Fl N Ar dbdir
+Use the user database text file
+.Pa master.passwd
+and group database text file
+.Pa group
+from
+.Ar dbdir ,
+rather than using the results from the system's
+.Xr getpwnam 3
+and
+.Xr getgrnam 3
+(and related) library calls.
+.It Fl P
+Don't follow symbolic links in the file hierarchy, instead consider
+the symbolic link itself in any comparisons.
+This is the default.
+.It Fl p Ar path
+Use the file hierarchy rooted in
+.Ar path  ,
+instead of the current directory.
+.It Fl q
+Quiet mode.
+Do not complain when a
+.Dq missing
+directory cannot be created because it already exists.
+This occurs when the directory is a symbolic link.
+.It Fl R Ar keywords
+Remove the specified (whitespace or comma separated) keywords from the current
+set of keywords.
+If
+.Ql all
+is specified, remove all of the other keywords.
+.It Fl r
+Remove any files in the file hierarchy that are not described in the
+specification.
+.It Fl S
+When reading a specification into an internal data structure,
+sort the entries.
+Sorting will affect the order of the output produced by the
+.Fl C
+or
+.Fl D
+options, and will also affect the order in which
+missing entries are created or reported when a directory tree is checked
+against a specification.
+.Pp
+The sort order is the same as that used by the
+.Fl c
+option, which is that entries within the same directory are
+sorted in the order used by
+.Xr strcmp 3 ,
+except that entries for subdirectories sort after other entries.
+By default, if the
+.Fl S
+option is not used, entries within the same directory are collected
+together (separated from entries for other directories), but not sorted.
+.It Fl s Ar seed
+Display a single checksum to the standard error output that represents all
+of the files for which the keyword
+.Sy cksum
+was specified.
+The checksum is seeded with the specified value.
+.It Fl t
+Modify the modified time of existing files, the device type of devices, and
+symbolic link targets, to match the specification.
+.It Fl U
+Same as
+.Fl u
+except that a mismatch is not considered to be an error if it was corrected.
+.It Fl u
+Modify the owner, group, permissions, and flags of existing files,
+the device type of devices, and symbolic link targets,
+to match the specification.
+Create any missing directories, devices or symbolic links.
+User, group, and permissions must all be specified for missing directories
+to be created.
+Note that unless the
+.Fl i
+option is given, the schg and sappnd flags will not be set, even if
+specified.
+If
+.Fl m
+is given, these flags will be reset.
+Exit with a status of 0 on success,
+2 if the file hierarchy did not match the specification, and
+1 if any other error occurred.
+.It Fl W
+Don't attempt to set various file attributes such as the
+ownership, mode, flags, or time
+when creating new directories or changing existing entries.
+This option will be most useful when used in conjunction with
+.Fl U
+or
+.Fl u .
+.It Fl X Ar exclude-file
+The specified file contains
+.Xr fnmatch 3
+patterns matching files to be excluded from
+the specification, one to a line.
+If the pattern contains a
+.Ql \&/
+character, it will be matched against entire pathnames (relative to
+the starting directory); otherwise,
+it will be matched against basenames only.
+Comments are permitted in
+the
+.Ar exclude-list
+file.
+.It Fl x
+Don't descend below mount points in the file hierarchy.
+.El
+.Pp
+Specifications are mostly composed of
+.Dq keywords ,
+i.e. strings that
+that specify values relating to files.
+No keywords have default values, and if a keyword has no value set, no
+checks based on it are performed.
+.Pp
+Currently supported keywords are as follows:
+.Bl -tag -width sha384digestxx
+.It Sy cksum
+The checksum of the file using the default algorithm specified by
+the
+.Xr cksum 1
+utility.
+.It Sy device
+The device number to use for
+.Sy block
+or
+.Sy char
+file types.
+The argument must be one of the following forms:
+.Bl -tag -width 4n
+.It Ar format , Ns Ar major , Ns Ar minor
+A device with
+.Ar major
+and
+.Ar minor
+fields, for an operating system specified with
+.Ar format .
+See below for valid formats.
+.It Ar format , Ns Ar major , Ns Ar unit , Ns Ar subunit
+A device with
+.Ar major ,
+.Ar unit ,
+and
+.Ar subunit
+fields, for an operating system specified with
+.Ar format .
+(Currently this is only supported by the
+.Sy bsdos
+format.)
+.It Ar number
+Opaque number (as stored on the file system).
+.El
+.Pp
+The following values for
+.Ar format
+are recognized:
+.Sy native ,
+.Sy 386bsd ,
+.Sy 4bsd ,
+.Sy bsdos ,
+.Sy freebsd ,
+.Sy hpux ,
+.Sy isc ,
+.Sy linux ,
+.Sy netbsd ,
+.Sy osf1 ,
+.Sy sco ,
+.Sy solaris ,
+.Sy sunos ,
+.Sy svr3 ,
+.Sy svr4 ,
+and
+.Sy ultrix .
+.Pp
+See
+.Xr mknod 8
+for more details.
+.It Sy flags
+The file flags as a symbolic name.
+See
+.Xr chflags 1
+for information on these names.
+If no flags are to be set the string
+.Ql none
+may be used to override the current default.
+Note that the schg and sappnd flags are treated specially (see the
+.Fl i
+and
+.Fl m
+options).
+.It Sy ignore
+Ignore any file hierarchy below this file.
+.It Sy gid
+The file group as a numeric value.
+.It Sy gname
+The file group as a symbolic name.
+.It Sy link
+The file the symbolic link is expected to reference.
+.It Sy md5
+The
+.Tn MD5
+cryptographic message digest of the file.
+.It Sy md5digest
+Synonym for
+.Sy md5 .
+.It Sy mode
+The current file's permissions as a numeric (octal) or symbolic
+value.
+.It Sy nlink
+The number of hard links the file is expected to have.
+.It Sy nochange
+Make sure this file or directory exists but otherwise ignore all attributes.
+.It Sy optional
+The file is optional; don't complain about the file if it's
+not in the file hierarchy.
+.It Sy ripemd160digest
+Synonym for
+.Sy rmd160 .
+.It Sy rmd160
+The
+.Tn RMD-160
+cryptographic message digest of the file.
+.It Sy rmd160digest
+Synonym for
+.Sy rmd160 .
+.It Sy sha1
+The
+.Tn SHA-1
+cryptographic message digest of the file.
+.It Sy sha1digest
+Synonym for
+.Sy sha1 .
+.It Sy sha256
+The 256-bits
+.Tn SHA-2
+cryptographic message digest of the file.
+.It Sy sha256digest
+Synonym for
+.Sy sha256 .
+.It Sy sha384
+The 384-bits
+.Tn SHA-2
+cryptographic message digest of the file.
+.It Sy sha384digest
+Synonym for
+.Sy sha384 .
+.It Sy sha512
+The 512-bits
+.Tn SHA-2
+cryptographic message digest of the file.
+.It Sy sha512digest
+Synonym for
+.Sy sha512 .
+.It Sy size
+The size, in bytes, of the file.
+.It Sy tags
+Comma delimited tags to be matched with
+.Fl E
+and
+.Fl I .
+These may be specified without leading or trailing commas, but will be
+stored internally with them.
+.It Sy time
+The last modification time of the file,
+in second and nanoseconds.
+The value should include a period character and exactly nine digits after
+the period.
+.It Sy type
+The type of the file; may be set to any one of the following:
+.Pp
+.Bl -tag -width Sy -compact
+.It Sy block
+block special device
+.It Sy char
+character special device
+.It Sy dir
+directory
+.It Sy fifo
+fifo
+.It Sy file
+regular file
+.It Sy link
+symbolic link
+.It Sy socket
+socket
+.El
+.It Sy uid
+The file owner as a numeric value.
+.It Sy uname
+The file owner as a symbolic name.
+.El
+.Pp
+The default set of keywords are
+.Sy flags ,
+.Sy gid ,
+.Sy link ,
+.Sy mode ,
+.Sy nlink ,
+.Sy size ,
+.Sy time ,
+.Sy type ,
+and
+.Sy uid .
+.Pp
+There are four types of lines in a specification:
+.Bl -enum
+.It
+Set global values for a keyword.
+This consists of the string
+.Ql /set
+followed by whitespace, followed by sets of keyword/value
+pairs, separated by whitespace.
+Keyword/value pairs consist of a keyword, followed by an equals sign
+.Pq Ql = ,
+followed by a value, without whitespace characters.
+Once a keyword has been set, its value remains unchanged until either
+reset or unset.
+.It
+Unset global values for a keyword.
+This consists of the string
+.Ql /unset ,
+followed by whitespace, followed by one or more keywords,
+separated by whitespace.
+If
+.Ql all
+is specified, unset all of the keywords.
+.It
+A file specification, consisting of a path name, followed by whitespace,
+followed by zero or more whitespace separated keyword/value pairs.
+.Pp
+The path name may be preceded by whitespace characters.
+The path name may contain any of the standard path name matching
+characters
+.Po
+.Ql \&[ ,
+.Ql \&] ,
+.Ql \&?
+or
+.Ql *
+.Pc ,
+in which case files
+in the hierarchy will be associated with the first pattern that
+they match.
+.Nm
+uses
+.Xr strsvis 3
+(in VIS_CSTYLE format) to encode path names containing
+non-printable characters.
+Whitespace characters are encoded as
+.Ql \es
+(space),
+.Ql \et
+(tab), and
+.Ql \en
+(new line).
+.Ql #
+characters in path names are escaped by a preceding backslash
+.Ql \e
+to distinguish them from comments.
+.Pp
+Each of the keyword/value pairs consist of a keyword, followed by an
+equals sign
+.Pq Ql = ,
+followed by the keyword's value, without
+whitespace characters.
+These values override, without changing, the global value of the
+corresponding keyword.
+.Pp
+The first path name entry listed must be a directory named
+.Ql \&. ,
+as this ensures that intermixing full and relative path names will
+work consistently and correctly.
+Multiple entries for a directory named
+.Ql \&.
+are permitted; the settings for the last such entry override those
+of the existing entry.
+.Pp
+A path name that contains a slash
+.Pq Ql /
+that is not the first character will be treated as a full path
+(relative to the root of the tree).
+All parent directories referenced in the path name must exist.
+The current directory path used by relative path names will be updated
+appropriately.
+Multiple entries for the same full path are permitted if the types
+are the same (unless
+.Fl M
+is given, in which case the types may differ);
+in this case the settings for the last entry take precedence.
+.Pp
+A path name that does not contain a slash will be treated as a relative path.
+Specifying a directory will cause subsequent files to be searched
+for in that directory hierarchy.
+.It
+A line containing only the string
+.Ql \&..
+which causes the current directory path (used by relative paths)
+to ascend one level.
+.El
+.Pp
+Empty lines and lines whose first non-whitespace character is a hash
+mark
+.Pq Ql #
+are ignored.
+.Pp
+The
+.Nm
+utility exits with a status of 0 on success, 1 if any error occurred,
+and 2 if the file hierarchy did not match the specification.
+.Sh FILES
+.Bl -tag -width /etc/mtree -compact
+.It Pa /etc/mtree
+system specification directory
+.El
+.Sh EXAMPLES
+To detect system binaries that have been
+.Dq trojan horsed ,
+it is recommended that
+.Nm
+be run on the file systems, and a copy of the results stored on a different
+machine, or, at least, in encrypted form.
+The seed for the
+.Fl s
+option should not be an obvious value and the final checksum should not be
+stored on-line under any circumstances!
+Then, periodically,
+.Nm
+should be run against the on-line specifications and the final checksum
+compared with the previous value.
+While it is possible for the bad guys to change the on-line specifications
+to conform to their modified binaries, it shouldn't be possible for them
+to make it produce the same final checksum value.
+If the final checksum value changes, the off-line copies of the specification
+can be used to detect which of the binaries have actually been modified.
+.Pp
+The
+.Fl d
+option can be used in combination with
+.Fl U
+or
+.Fl u
+to create directory hierarchies for, for example, distributions.
+.Sh COMPATIBILITY
+The compatibility shims provided by the
+.Fl F
+option are incomplete by design.
+Known limitations are described below.
+.Pp
+The
+.Sy freebsd9
+flavor retains the default handling of lookup failures for the
+.Sy uname
+and
+.Sy group
+keywords by replacing them with appropriate
+.Sy uid
+and
+.Sy gid
+keywords rather than failing and reporting an error.
+The related
+.Fl w
+flag is a no-op rather than causing a warning to be printed and no
+keyword to be emitted.
+The latter behavior is not emulated as it is potentially dangerous in
+the face of /set statements.
+.Pp
+The
+.Sy netbsd6
+flavor does not replicate the historical bug that reported time as
+seconds.nanoseconds without zero padding nanosecond values less than
+100000000.
+.Sh SEE ALSO
+.Xr chflags 1 ,
+.Xr chgrp 1 ,
+.Xr chmod 1 ,
+.Xr cksum 1 ,
+.Xr stat 2 ,
+.Xr fnmatch 3 ,
+.Xr fts 3 ,
+.Xr strsvis 3 ,
+.Xr chown 8 ,
+.Xr mknod 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.3 Reno .
+The
+.Sy optional
+keyword appeared in
+.Nx 1.2 .
+The
+.Fl U
+option appeared in
+.Nx 1.3 .
+The
+.Sy flags
+and
+.Sy md5
+keywords, and
+.Fl i
+and
+.Fl m
+options
+appeared in
+.Nx 1.4 .
+The
+.Sy device ,
+.Sy rmd160 ,
+.Sy sha1 ,
+.Sy tags ,
+and
+.Sy all
+keywords,
+.Fl D ,
+.Fl E ,
+.Fl I ,
+.Fl L ,
+.Fl l ,
+.Fl N ,
+.Fl P ,
+.Fl R ,
+.Fl W ,
+and
+.Fl X
+options, and support for full paths appeared in
+.Nx 1.6 .
+The
+.Sy sha256 ,
+.Sy sha384 ,
+and
+.Sy sha512
+keywords appeared in
+.Nx 3.0 .
+The
+.Fl S
+option appeared in
+.Nx 6.0 .

Added: vendor/NetBSD/mtree/dist/mtree.c
===================================================================
--- vendor/NetBSD/mtree/dist/mtree.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/mtree.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,327 @@
+/*	$NetBSD: mtree.c,v 1.46 2012/12/20 19:09:25 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 <sys/cdefs.h>
+#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.46 2012/12/20 19:09:25 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+int	ftsoptions = FTS_PHYSICAL;
+int	bflag, cflag, Cflag, dflag, Dflag, eflag, iflag, jflag, lflag, mflag,
+    	nflag, qflag, rflag, sflag, tflag, uflag, Uflag, wflag;
+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;
+	char	*dir, *p;
+	FILE	*spec1, *spec2;
+
+	setprogname(argv[0]);
+
+	dir = NULL;
+	init_excludes();
+	spec1 = stdin;
+	spec2 = NULL;
+
+	while ((ch = getopt(argc, argv,
+	    "bcCdDeE:f:F:I:ijk:K:lLmMnN: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 '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();
+		exit(0);
+	}
+	if (Cflag || Dflag) {
+		dump_nodes("", 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);
+}

Added: vendor/NetBSD/mtree/dist/mtree.h
===================================================================
--- vendor/NetBSD/mtree/dist/mtree.h	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/mtree.h	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,158 @@
+/*	$NetBSD: mtree.h,v 1.31 2012/10/05 09:17:29 wiz Exp $	*/
+
+/*-
+ * Copyright (c) 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.
+ *
+ *	@(#)mtree.h	8.1 (Berkeley) 6/6/93
+ */
+
+#ifndef _MTREE_H_
+#define	_MTREE_H_
+
+#define	KEYDEFAULT	(F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | \
+			F_TIME | F_TYPE | F_UID | F_FLAGS)
+
+#define	MISMATCHEXIT	2
+
+typedef struct _node {
+	struct _node	*parent, *child;	/* up, down */
+	struct _node	*prev, *next;		/* left, right */
+	off_t	st_size;			/* size */
+	struct timespec	st_mtimespec;		/* last modification time */
+	char	*slink;				/* symbolic link reference */
+	uid_t	st_uid;				/* uid */
+	gid_t	st_gid;				/* gid */
+#define	MBITS	(S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
+	mode_t	st_mode;			/* mode */
+	dev_t	st_rdev;			/* device type */
+	u_long	st_flags;			/* flags */
+	nlink_t	st_nlink;			/* link count */
+	u_long	cksum;				/* check sum */
+	char	*md5digest;			/* MD5 digest */
+	char	*rmd160digest;			/* RMD-160 digest */
+	char	*sha1digest;			/* SHA1 digest */
+	char	*sha256digest;			/* SHA256 digest */
+	char	*sha384digest;			/* SHA384 digest */
+	char	*sha512digest;			/* SHA512 digest */
+	char	*tags;				/* tags, comma delimited,
+						 * also with leading and
+						 * trailing commas */
+	size_t	lineno;				/* line # entry came from */
+
+#define	F_CKSUM		0x00000001		/* cksum(1) check sum */
+#define	F_DEV		0x00000002		/* device type */
+#define	F_DONE		0x00000004		/* directory done */
+#define	F_FLAGS		0x00000008		/* file flags */
+#define	F_GID		0x00000010		/* gid */
+#define	F_GNAME		0x00000020		/* group name */
+#define	F_IGN		0x00000040		/* ignore */
+#define	F_MAGIC		0x00000080		/* name has magic chars */
+#define	F_MD5		0x00000100		/* MD5 digest */
+#define	F_MODE		0x00000200		/* mode */
+#define	F_NLINK		0x00000400		/* number of links */
+#define	F_OPT		0x00000800		/* existence optional */
+#define	F_RMD160	0x00001000		/* RMD-160 digest */
+#define	F_SHA1		0x00002000		/* SHA1 digest */
+#define	F_SIZE		0x00004000		/* size */
+#define	F_SLINK		0x00008000		/* symbolic link */
+#define	F_TAGS		0x00010000		/* tags */
+#define	F_TIME		0x00020000		/* modification time */
+#define	F_TYPE		0x00040000		/* file type */
+#define	F_UID		0x00080000		/* uid */
+#define	F_UNAME		0x00100000		/* user name */
+#define	F_VISIT		0x00200000		/* file visited */
+#define	F_NOCHANGE	0x00400000		/* check existence, but not */
+						/* other properties */
+#define	F_SHA256	0x00800000		/* SHA256 digest */
+#define	F_SHA384	0x01000000		/* SHA384 digest */
+#define	F_SHA512	0x02000000		/* SHA512 digest */
+
+	int	flags;				/* items set */
+
+#define	F_BLOCK	0x001				/* block special */
+#define	F_CHAR	0x002				/* char special */
+#define	F_DIR	0x004				/* directory */
+#define	F_FIFO	0x008				/* fifo */
+#define	F_FILE	0x010				/* regular file */
+#define	F_LINK	0x020				/* symbolic link */
+#define	F_SOCK	0x040				/* socket */
+#define	F_DOOR	0x080				/* door */
+	int	type;				/* file type */
+
+	char	name[1];			/* file name (must be last) */
+} NODE;
+
+
+typedef struct {
+	char  **list;
+	int	count;
+} slist_t;
+
+
+/*
+ * prototypes for functions published to other programs which want to use
+ * the specfile parser but don't want to pull in all of "extern.h"
+ */
+const char	*inotype(u_int);
+u_int		 nodetoino(u_int);
+int		 setup_getid(const char *);
+NODE		*spec(FILE *);
+int		 mtree_specspec(FILE *, FILE *);
+void		 free_nodes(NODE *);
+char		*vispath(const char *);
+
+#ifdef __FreeBSD__
+#define KEY_DIGEST "digest"
+#else
+#define KEY_DIGEST
+#endif
+
+#define	MD5KEY		"md5"		KEY_DIGEST
+#ifdef __FreeBSD__
+#define	RMD160KEY	"ripemd160"	KEY_DIGEST
+#else
+#define	RMD160KEY	"rmd160"	KEY_DIGEST
+#endif
+#define	SHA1KEY		"sha1"		KEY_DIGEST
+#define	SHA256KEY	"sha256"	KEY_DIGEST
+#define	SHA384KEY	"sha384"
+#define	SHA512KEY	"sha512"
+
+#define	RP(p)	\
+	((p)->fts_path[0] == '.' && (p)->fts_path[1] == '/' ? \
+	    (p)->fts_path + 2 : (p)->fts_path)
+
+#define	UF_MASK ((UF_NODUMP | UF_IMMUTABLE |   \
+                  UF_APPEND | UF_OPAQUE)       \
+                    & UF_SETTABLE)              /* user settable flags */
+#define	SF_MASK ((SF_ARCHIVED | SF_IMMUTABLE | \
+                  SF_APPEND) & SF_SETTABLE)     /* root settable flags */
+#define	CH_MASK  (UF_MASK | SF_MASK)            /* all settable flags */
+#define	SP_FLGS  (SF_IMMUTABLE | SF_APPEND)     /* special flags */
+
+#endif /* _MTREE_H_ */

Added: vendor/NetBSD/mtree/dist/spec.c
===================================================================
--- vendor/NetBSD/mtree/dist/spec.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/spec.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,838 @@
+/*	$NetBSD: spec.c,v 1.85 2012/12/20 16:43:16 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 <sys/cdefs.h>
+#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.85 2012/12/20 16:43:16 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <vis.h>
+#include <util.h>
+
+#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);
+
+#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
+				 */
+			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
+ *	the regular output, according to the pathlast flag.
+ */
+static int
+appendfield(int pathlast, const char *fmt, ...)
+{
+	va_list ap;
+	int result;
+
+	va_start(ap, fmt);
+	if (!pathlast)
+		printf(" ");
+	result = vprintf(fmt, ap);
+	if (pathlast)
+		printf(" ");
+	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)
+{
+	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));
+
+#define MATCHFLAG(f)	((keys & (f)) && (cur->flags & (f)))
+		if (MATCHFLAG(F_TYPE))
+			appendfield(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);
+			else
+				appendfield(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);
+			else
+				appendfield(pathlast, "gid=%u", cur->st_gid);
+		}
+		if (MATCHFLAG(F_MODE))
+			appendfield(pathlast, "mode=%#o", cur->st_mode);
+		if (MATCHFLAG(F_DEV) &&
+		    (cur->type == F_BLOCK || cur->type == F_CHAR))
+			appendfield(pathlast, "device=%#llx", (long long)cur->st_rdev);
+		if (MATCHFLAG(F_NLINK))
+			appendfield(pathlast, "nlink=%d", cur->st_nlink);
+		if (MATCHFLAG(F_SLINK))
+			appendfield(pathlast, "link=%s", vispath(cur->slink));
+		if (MATCHFLAG(F_SIZE))
+			appendfield(pathlast, "size=%lld", (long long)cur->st_size);
+		if (MATCHFLAG(F_TIME))
+			appendfield(pathlast, "time=%lld.%09ld",
+			    (long long)cur->st_mtimespec.tv_sec,
+			    cur->st_mtimespec.tv_nsec);
+		if (MATCHFLAG(F_CKSUM))
+			appendfield(pathlast, "cksum=%lu", cur->cksum);
+		if (MATCHFLAG(F_MD5))
+			appendfield(pathlast, "%s=%s", MD5KEY, cur->md5digest);
+		if (MATCHFLAG(F_RMD160))
+			appendfield(pathlast, "%s=%s", RMD160KEY,
+			    cur->rmd160digest);
+		if (MATCHFLAG(F_SHA1))
+			appendfield(pathlast, "%s=%s", SHA1KEY,
+			    cur->sha1digest);
+		if (MATCHFLAG(F_SHA256))
+			appendfield(pathlast, "%s=%s", SHA256KEY,
+			    cur->sha256digest);
+		if (MATCHFLAG(F_SHA384))
+			appendfield(pathlast, "%s=%s", SHA384KEY,
+			    cur->sha384digest);
+		if (MATCHFLAG(F_SHA512))
+			appendfield(pathlast, "%s=%s", SHA512KEY,
+			    cur->sha512digest);
+		if (MATCHFLAG(F_FLAGS)) {
+			str = flags_to_string(cur->st_flags, "none");
+			appendfield(pathlast, "flags=%s", str);
+			free(str);
+		}
+		if (MATCHFLAG(F_IGN))
+			appendfield(pathlast, "ignore");
+		if (MATCHFLAG(F_OPT))
+			appendfield(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);
+		}
+		puts(pathlast ? vispath(path) : "");
+
+		if (cur->child)
+			dump_nodes(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);
+}

Added: vendor/NetBSD/mtree/dist/specspec.c
===================================================================
--- vendor/NetBSD/mtree/dist/specspec.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/specspec.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,273 @@
+/*	$NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2003 Poul-Henning Kamp
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
+__RCSID("$NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $");
+
+#include <err.h>
+#include <grp.h>
+#include <pwd.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "mtree.h"
+#include "extern.h"
+
+#define FF(a, b, c, d) \
+	(((a)->flags & (c)) && ((b)->flags & (c)) && ((a)->d) != ((b)->d))
+#define FS(a, b, c, d) \
+	(((a)->flags & (c)) && ((b)->flags & (c)) && strcmp((a)->d,(b)->d))
+#define FM(a, b, c, d) \
+	(((a)->flags & (c)) && ((b)->flags & (c)) && memcmp(&(a)->d,&(b)->d, sizeof (a)->d))
+
+static void
+shownode(NODE *n, int f, char const *path)
+{
+	struct group *gr;
+	struct passwd *pw;
+
+	printf("%s%s %s", path, n->name, inotype(nodetoino(n->type)));
+	if (f & F_CKSUM)
+		printf(" cksum=%lu", n->cksum);
+	if (f & F_GID)
+		printf(" gid=%d", n->st_gid);
+	if (f & F_GNAME) {
+		gr = getgrgid(n->st_gid);
+		if (gr == NULL)
+			printf(" gid=%d", n->st_gid);
+		else
+			printf(" gname=%s", gr->gr_name);
+	}
+	if (f & F_MODE)
+		printf(" mode=%o", n->st_mode);
+	if (f & F_NLINK)
+		printf(" nlink=%d", n->st_nlink);
+	if (f & F_SIZE)
+		printf(" size=%jd", (intmax_t)n->st_size);
+	if (f & F_UID)
+		printf(" uid=%d", n->st_uid);
+	if (f & F_UNAME) {
+		pw = getpwuid(n->st_uid);
+		if (pw == NULL)
+			printf(" uid=%d", n->st_uid);
+		else
+			printf(" uname=%s", pw->pw_name);
+	}
+	if (f & F_MD5)
+		printf(" %s=%s", MD5KEY, n->md5digest);
+	if (f & F_SHA1)
+		printf(" %s=%s", SHA1KEY, n->sha1digest);
+	if (f & F_RMD160)
+		printf(" %s=%s", RMD160KEY, n->rmd160digest);
+	if (f & F_SHA256)
+		printf(" %s=%s", SHA256KEY, n->sha256digest);
+	if (f & F_SHA384)
+		printf(" %s=%s", SHA384KEY, n->sha384digest);
+	if (f & F_SHA512)
+		printf(" %s=%s", SHA512KEY, n->sha512digest);
+	if (f & F_FLAGS)
+		printf(" flags=%s", flags_to_string(n->st_flags, "none"));
+	printf("\n");
+}
+
+static int
+mismatch(NODE *n1, NODE *n2, int differ, char const *path)
+{
+
+	if (n2 == NULL) {
+		shownode(n1, differ, path);
+		return (1);
+	}
+	if (n1 == NULL) {
+		printf("\t");
+		shownode(n2, differ, path);
+		return (1);
+	}
+	if (!(differ & keys))
+		return(0);
+	printf("\t\t");
+	shownode(n1, differ, path);
+	printf("\t\t");
+	shownode(n2, differ, path);
+	return (1);
+}
+
+static int
+compare_nodes(NODE *n1, NODE *n2, char const *path)
+{
+	int differs;
+	
+	if (n1 != NULL && n1->type == F_LINK)
+		n1->flags &= ~F_MODE;
+	if (n2 != NULL && n2->type == F_LINK)
+		n2->flags &= ~F_MODE;
+	differs = 0;
+	if (n1 == NULL && n2 != NULL) {
+		differs = n2->flags;
+		mismatch(n1, n2, differs, path);
+		return (1);
+	}
+	if (n1 != NULL && n2 == NULL) {
+		differs = n1->flags;
+		mismatch(n1, n2, differs, path);
+		return (1);
+	}
+	if (n1->type != n2->type) {
+		differs = 0;
+		mismatch(n1, n2, differs, path);
+		return (1);
+	}
+	if (FF(n1, n2, F_CKSUM, cksum))
+		differs |= F_CKSUM;
+	if (FF(n1, n2, F_GID, st_gid))
+		differs |= F_GID;
+	if (FF(n1, n2, F_GNAME, st_gid))
+		differs |= F_GNAME;
+	if (FF(n1, n2, F_MODE, st_mode))
+		differs |= F_MODE;
+	if (FF(n1, n2, F_NLINK, st_nlink))
+		differs |= F_NLINK;
+	if (FF(n1, n2, F_SIZE, st_size))
+		differs |= F_SIZE;
+	if (FS(n1, n2, F_SLINK, slink))
+		differs |= F_SLINK;
+	if (FM(n1, n2, F_TIME, st_mtimespec))
+		differs |= F_TIME;
+	if (FF(n1, n2, F_UID, st_uid))
+		differs |= F_UID;
+	if (FF(n1, n2, F_UNAME, st_uid))
+		differs |= F_UNAME;
+	if (FS(n1, n2, F_MD5, md5digest))
+		differs |= F_MD5;
+	if (FS(n1, n2, F_SHA1, sha1digest))
+		differs |= F_SHA1;
+	if (FS(n1, n2, F_RMD160, rmd160digest))
+		differs |= F_RMD160;
+	if (FS(n1, n2, F_SHA256, sha256digest))
+		differs |= F_SHA256;
+	if (FS(n1, n2, F_SHA384, sha384digest))
+		differs |= F_SHA384;
+	if (FS(n1, n2, F_SHA512, sha512digest))
+		differs |= F_SHA512;
+	if (FF(n1, n2, F_FLAGS, st_flags))
+		differs |= F_FLAGS;
+	if (differs) {
+		mismatch(n1, n2, differs, path);
+		return (1);
+	}
+	return (0);	
+}
+static int
+walk_in_the_forest(NODE *t1, NODE *t2, char const *path)
+{
+	int r, i;
+	NODE *c1, *c2, *n1, *n2;
+	char *np;
+
+	r = 0;
+
+	if (t1 != NULL)
+		c1 = t1->child;
+	else
+		c1 = NULL;
+	if (t2 != NULL)
+		c2 = t2->child;
+	else
+		c2 = NULL;
+	while (c1 != NULL || c2 != NULL) {
+		n1 = n2 = NULL;
+		if (c1 != NULL)
+			n1 = c1->next;
+		if (c2 != NULL)
+			n2 = c2->next;
+		if (c1 != NULL && c2 != NULL) {
+			if (c1->type != F_DIR && c2->type == F_DIR) {
+				n2 = c2;
+				c2 = NULL;
+			} else if (c1->type == F_DIR && c2->type != F_DIR) {
+				n1 = c1;
+				c1 = NULL;
+			} else {
+				i = strcmp(c1->name, c2->name);
+				if (i > 0) {
+					n1 = c1;
+					c1 = NULL;
+				} else if (i < 0) {
+					n2 = c2;
+					c2 = NULL;
+				}
+			}
+		}
+		if (c1 == NULL && c2->type == F_DIR) {
+			asprintf(&np, "%s%s/", path, c2->name);
+			i = walk_in_the_forest(c1, c2, np);
+			free(np);
+			i += compare_nodes(c1, c2, path);
+		} else if (c2 == NULL && c1->type == F_DIR) {
+			asprintf(&np, "%s%s/", path, c1->name);
+			i = walk_in_the_forest(c1, c2, np);
+			free(np);
+			i += compare_nodes(c1, c2, path);
+		} else if (c1 == NULL || c2 == NULL) {
+			i = compare_nodes(c1, c2, path);
+		} else if (c1->type == F_DIR && c2->type == F_DIR) {
+			asprintf(&np, "%s%s/", path, c1->name);
+			i = walk_in_the_forest(c1, c2, np);
+			free(np);
+			i += compare_nodes(c1, c2, path);
+		} else {
+			i = compare_nodes(c1, c2, path);
+		}
+		r += i;
+		c1 = n1;
+		c2 = n2;
+	}
+	return (r);	
+}
+
+int
+mtree_specspec(FILE *fi, FILE *fj)
+{
+	int rval;
+	NODE *root1, *root2;
+
+	root1 = spec(fi);
+	root2 = spec(fj);
+	rval = walk_in_the_forest(root1, root2, "");
+	rval += compare_nodes(root1, root2, "");
+	if (rval > 0)
+		return (MISMATCHEXIT);
+	return (0);
+}

Added: vendor/NetBSD/mtree/dist/verify.c
===================================================================
--- vendor/NetBSD/mtree/dist/verify.c	                        (rev 0)
+++ vendor/NetBSD/mtree/dist/verify.c	2016-09-25 18:03:03 UTC (rev 8625)
@@ -0,0 +1,303 @@
+/*	$NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $	*/
+
+/*-
+ * Copyright (c) 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 <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)verify.c	8.1 (Berkeley) 6/6/93";
+#else
+__RCSID("$NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#if ! HAVE_NBTOOL_CONFIG_H
+#include <dirent.h>
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static NODE *root;
+static char path[MAXPATHLEN];
+
+static void	miss(NODE *, char *);
+static int	vwalk(void);
+
+int
+verify(FILE *fi)
+{
+	int rval;
+
+	root = spec(fi);
+	rval = vwalk();
+	miss(root, path);
+	return (rval);
+}
+
+static int
+vwalk(void)
+{
+	FTS *t;
+	FTSENT *p;
+	NODE *ep, *level;
+	int specdepth, rval;
+	char *argv[2];
+	char  dot[] = ".";
+	argv[0] = dot;
+	argv[1] = NULL;
+
+	if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
+		mtree_err("fts_open: %s", strerror(errno));
+	level = root;
+	specdepth = rval = 0;
+	while ((p = fts_read(t)) != NULL) {
+		if (check_excludes(p->fts_name, p->fts_path)) {
+			fts_set(t, p, FTS_SKIP);
+			continue;
+		}
+		switch(p->fts_info) {
+		case FTS_D:
+		case FTS_SL:
+			break;
+		case FTS_DP:
+			if (specdepth > p->fts_level) {
+				for (level = level->parent; level->prev;
+				    level = level->prev)
+					continue;
+				--specdepth;
+			}
+			continue;
+		case FTS_DNR:
+		case FTS_ERR:
+		case FTS_NS:
+			warnx("%s: %s", RP(p), strerror(p->fts_errno));
+			continue;
+		default:
+			if (dflag)
+				continue;
+		}
+
+		if (specdepth != p->fts_level)
+			goto extra;
+		for (ep = level; ep; ep = ep->next)
+			if ((ep->flags & F_MAGIC &&
+			    !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) ||
+			    !strcmp(ep->name, p->fts_name)) {
+				ep->flags |= F_VISIT;
+				if ((ep->flags & F_NOCHANGE) == 0 &&
+				    compare(ep, p))
+					rval = MISMATCHEXIT;
+				if (!(ep->flags & F_IGN) &&
+				    ep->type == F_DIR &&
+				    p->fts_info == FTS_D) {
+					if (ep->child) {
+						level = ep->child;
+						++specdepth;
+					}
+				} else
+					fts_set(t, p, FTS_SKIP);
+				break;
+			}
+
+		if (ep)
+			continue;
+ extra:
+		if (!eflag && !(dflag && p->fts_info == FTS_SL)) {
+			printf("extra: %s", RP(p));
+			if (rflag) {
+				if ((S_ISDIR(p->fts_statp->st_mode)
+				    ? rmdir : unlink)(p->fts_accpath)) {
+					printf(", not removed: %s",
+					    strerror(errno));
+				} else
+					printf(", removed");
+			}
+			putchar('\n');
+		}
+		fts_set(t, p, FTS_SKIP);
+	}
+	fts_close(t);
+	if (sflag)
+		warnx("%s checksum: %u", fullpath, crc_total);
+	return (rval);
+}
+
+static void
+miss(NODE *p, char *tail)
+{
+	int create;
+	char *tp;
+	const char *type;
+	u_int32_t flags;
+
+	for (; p; p = p->next) {
+		if (p->flags & F_OPT && !(p->flags & F_VISIT))
+			continue;
+		if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
+			continue;
+		strcpy(tail, p->name);
+		if (!(p->flags & F_VISIT)) {
+			/* Don't print missing message if file exists as a 
+			   symbolic link and the -q flag is set. */
+			struct stat statbuf;
+
+			if (qflag && stat(path, &statbuf) == 0 &&
+			    S_ISDIR(statbuf.st_mode))
+				p->flags |= F_VISIT;
+			else
+				(void)printf("%s missing", path);
+		}
+		switch (p->type) {
+		case F_BLOCK:
+		case F_CHAR:
+			type = "device";
+			break;
+		case F_DIR:
+			type = "directory";
+			break;
+		case F_LINK:
+			type = "symlink";
+			break;
+		default:
+			putchar('\n');
+			continue;
+		}
+
+		create = 0;
+		if (!(p->flags & F_VISIT) && uflag) {
+			if (mtree_Wflag || p->type == F_LINK)
+				goto createit;
+			if (!(p->flags & (F_UID | F_UNAME)))
+			    printf(
+				" (%s not created: user not specified)", type);
+			else if (!(p->flags & (F_GID | F_GNAME)))
+			    printf(
+				" (%s not created: group not specified)", type);
+			else if (!(p->flags & F_MODE))
+			    printf(
+				" (%s not created: mode not specified)", type);
+			else
+ createit:
+			switch (p->type) {
+			case F_BLOCK:
+			case F_CHAR:
+				if (mtree_Wflag)
+					continue;
+				if (!(p->flags & F_DEV))
+					printf(
+				    " (%s not created: device not specified)",
+					    type);
+				else if (mknod(path,
+				    p->st_mode | nodetoino(p->type),
+				    p->st_rdev) == -1)
+					printf(" (%s not created: %s)\n",
+					    type, strerror(errno));
+				else
+					create = 1;
+				break;
+			case F_LINK:
+				if (!(p->flags & F_SLINK))
+					printf(
+				    " (%s not created: link not specified)\n",
+					    type);
+				else if (symlink(p->slink, path))
+					printf(
+					    " (%s not created: %s)\n",
+					    type, strerror(errno));
+				else
+					create = 1;
+				break;
+			case F_DIR:
+				if (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO))
+					printf(" (not created: %s)",
+					    strerror(errno));
+				else
+					create = 1;
+				break;
+			default:
+				mtree_err("can't create create %s",
+				    nodetype(p->type));
+			}
+		}
+		if (create)
+			printf(" (created)");
+		if (p->type == F_DIR) {
+			if (!(p->flags & F_VISIT))
+				putchar('\n');
+			for (tp = tail; *tp; ++tp)
+				continue;
+			*tp = '/';
+			miss(p->child, tp + 1);
+			*tp = '\0';
+		} else
+			putchar('\n');
+
+		if (!create || mtree_Wflag)
+			continue;
+		if ((p->flags & (F_UID | F_UNAME)) &&
+		    (p->flags & (F_GID | F_GNAME)) &&
+		    (lchown(path, p->st_uid, p->st_gid))) {
+			printf("%s: user/group/mode not modified: %s\n",
+			    path, strerror(errno));
+			printf("%s: warning: file mode %snot set\n", path,
+			    (p->flags & F_FLAGS) ? "and file flags " : "");
+			continue;
+		}
+		if (p->flags & F_MODE) {
+			if (lchmod(path, p->st_mode))
+				printf("%s: permissions not set: %s\n",
+				    path, strerror(errno));
+		}
+#if HAVE_STRUCT_STAT_ST_FLAGS
+		if ((p->flags & F_FLAGS) && p->st_flags) {
+			if (iflag)
+				flags = p->st_flags;
+			else
+				flags = p->st_flags & ~SP_FLGS;
+			if (lchflags(path, flags))
+				printf("%s: file flags not set: %s\n",
+				    path, strerror(errno));
+		}
+#endif	/* HAVE_STRUCT_STAT_ST_FLAGS */
+	}
+}



More information about the Midnightbsd-cvs mailing list