Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Dec 2025 01:11:19 +0000
From:      Jose Luis Duran <jlduran@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: a3b349e43987 - stable/13 - Import latest mtree from NetBSD
Message-ID:  <6945f7b7.35924.1cf63169@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/13 has been updated by jlduran:

URL: https://cgit.FreeBSD.org/src/commit/?id=a3b349e439870eeb4f58c74b990f721d86a75e1d

commit a3b349e439870eeb4f58c74b990f721d86a75e1d
Author:     Jose Luis Duran <jlduran@FreeBSD.org>
AuthorDate: 2025-12-13 14:28:16 +0000
Commit:     Jose Luis Duran <jlduran@FreeBSD.org>
CommitDate: 2025-12-20 01:08:28 +0000

    Import latest mtree from NetBSD
    
    Merge commit 'f600477feb4ae61a75f61949eb600caff4aeea8c'
    
    MFC after:      1 week
    Discussed with: brooks
    
    (cherry picked from commit 49b6dda4d71175ad615718401573be5fd024822b)
---
 contrib/mtree/compare.c  |  39 ++++++++-----
 contrib/mtree/crc.c      |  20 +++----
 contrib/mtree/create.c   | 144 ++++++++++++++++++++---------------------------
 contrib/mtree/extern.h   |  13 ++++-
 contrib/mtree/misc.c     |  10 ++--
 contrib/mtree/mtree.8    | 139 +++++++++++++++++++++++++++++++++++----------
 contrib/mtree/mtree.c    |   8 +--
 contrib/mtree/spec.c     |  44 ++++++++++++---
 contrib/mtree/specspec.c |   4 +-
 contrib/mtree/verify.c   |  17 ++++--
 10 files changed, 271 insertions(+), 167 deletions(-)

diff --git a/contrib/mtree/compare.c b/contrib/mtree/compare.c
index e3639ceea08f..c4e5bfcac1d7 100644
--- a/contrib/mtree/compare.c
+++ b/contrib/mtree/compare.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $	*/
+/*	$NetBSD: compare.c,v 1.61 2024/12/05 17:17:43 christos Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993
@@ -38,7 +38,7 @@
 #if 0
 static char sccsid[] = "@(#)compare.c	8.1 (Berkeley) 6/6/93";
 #else
-__RCSID("$NetBSD: compare.c,v 1.58 2013/11/21 18:39:50 christos Exp $");
+__RCSID("$NetBSD: compare.c,v 1.61 2024/12/05 17:17:43 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -135,8 +135,9 @@ do {									\
 int
 compare(NODE *s, FTSENT *p)
 {
-	u_int32_t len, val, flags;
+	uint32_t len, val, flags;
 	int fd, label;
+	bool was_unlinked;
 	const char *cp, *tab;
 #if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2)
 	char *digestbuf;
@@ -144,6 +145,7 @@ compare(NODE *s, FTSENT *p)
 
 	tab = NULL;
 	label = 0;
+	was_unlinked = false;
 	switch(s->type) {
 	case F_BLOCK:
 		if (!S_ISBLK(p->fts_statp->st_mode))
@@ -210,47 +212,53 @@ typeerr:		LABEL;
 			      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) )
+			      p->fts_statp->st_gid) == -1) ) {
 				printf(", not modified: %s%s\n",
 				    strerror(errno),
 				    flavor == F_FREEBSD9 ? "" : ")");
-			 else
+			} else {
 				printf(", modified%s\n",
 				    flavor == F_FREEBSD9 ? "" : ")");
+				was_unlinked = true;
+			}
 		} 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) {
+	if (s->flags & (F_UID | F_UNAME) &&
+	    (was_unlinked || s->st_uid != p->fts_statp->st_uid)) {
 		LABEL;
 		printf(flavor == F_FREEBSD9 ?
 		    "%suser expected %lu found %lu" : "%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))
+			if (lchown(p->fts_accpath, s->st_uid, (gid_t)-1))
 				printf(", not modified: %s%s\n",
 				    strerror(errno),
 				    flavor == F_FREEBSD9 ? "" : ")");
 			else
-				printf(", modified%s\n",
+				printf(", modified%s%s\n",
+				    was_unlinked ? " by unlink" : "",
 				    flavor == F_FREEBSD9 ? "" : ")");
 		} else
 			printf(")\n");
 		tab = "\t";
 	}
-	if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
+	if (s->flags & (F_GID | F_GNAME) &&
+	    (was_unlinked || s->st_gid != p->fts_statp->st_gid)) {
 		LABEL;
 		printf(flavor == F_FREEBSD9 ?
 		    "%sgid expected %lu found %lu" : "%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))
+			if (lchown(p->fts_accpath, (uid_t)-1, s->st_gid))
 				printf(", not modified: %s%s\n",
 				    strerror(errno),
 				    flavor == F_FREEBSD9 ? "" : ")");
 			else
-				printf(", modified%s\n",
+				printf(", modified%s%s\n",
+				    was_unlinked ? " by unlink" : "",
 				    flavor == F_FREEBSD9 ? "" : ")");
 		}
 		else
@@ -258,8 +266,8 @@ typeerr:		LABEL;
 		tab = "\t";
 	}
 	if (s->flags & F_MODE &&
-	    s->st_mode != (p->fts_statp->st_mode & MBITS)) {
-		if (lflag) {
+	    (was_unlinked || s->st_mode != (p->fts_statp->st_mode & MBITS))) {
+		if (lflag && !was_unlinked) {
 			mode_t tmode, mode;
 
 			tmode = s->st_mode;
@@ -287,7 +295,8 @@ typeerr:		LABEL;
 				    strerror(errno),
 				    flavor == F_FREEBSD9 ? "" : ")");
 			else
-				printf(", modified%s\n",
+				printf(", modified%s%s\n",
+				    was_unlinked ? " by unlink" : "",
 				    flavor == F_FREEBSD9 ? "" : ")");
 		}
 		else
@@ -567,7 +576,7 @@ const char *
 rlink(const char *name)
 {
 	static char lbuf[MAXPATHLEN];
-	int len;
+	ssize_t len;
 
 	if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
 		mtree_err("%s: %s", name, strerror(errno));
diff --git a/contrib/mtree/crc.c b/contrib/mtree/crc.c
index 4eac66e5b995..69b30b206439 100644
--- a/contrib/mtree/crc.c
+++ b/contrib/mtree/crc.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $	*/
+/*	$NetBSD: crc.c,v 1.11 2024/12/05 17:17:43 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -41,7 +41,7 @@
 #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 $");
+__RCSID("$NetBSD: crc.c,v 1.11 2024/12/05 17:17:43 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -53,7 +53,7 @@ __RCSID("$NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $");
 
 #include "extern.h"
 
-static const u_int32_t crctab[] = {
+static const uint32_t crctab[] = {
 	0x0,
 	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
 	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
@@ -114,15 +114,15 @@ static const u_int32_t crctab[] = {
  * 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. */
+uint32_t crc_total = ~0u;		/* The crc over a number of files. */
 
 int
-crc(int fd, u_int32_t *cval, u_int32_t *clen)
+crc(int fd, uint32_t *cval, uint32_t *clen)
 {
 	u_char *p;
-	int nr;
-	u_int32_t thecrc, len;
-	u_int32_t crctot;
+	ssize_t nr;
+	uint32_t thecrc, len;
+	uint32_t crctot;
 	u_char buf[16 * 1024];
 
 #define	COMPUTE(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
@@ -132,12 +132,12 @@ crc(int fd, u_int32_t *cval, u_int32_t *clen)
 		crctot = ~crc_total;
 	while ((nr = read(fd, buf, sizeof(buf))) > 0)
 		if (sflag) {
-			for (len += nr, p = buf; nr--; ++p) {
+			for (len += (uint32_t)nr, p = buf; nr--; ++p) {
 				COMPUTE(thecrc, *p);
 				COMPUTE(crctot, *p);
 			}
 		} else {
-			for (len += nr, p = buf; nr--; ++p)
+			for (len += (uint32_t)nr, p = buf; nr--; ++p)
 				COMPUTE(thecrc, *p);
 		}
 	if (nr < 0)
diff --git a/contrib/mtree/create.c b/contrib/mtree/create.c
index 7a09a1cc3951..e23004851f39 100644
--- a/contrib/mtree/create.c
+++ b/contrib/mtree/create.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: create.c,v 1.73 2014/04/24 17:22:41 christos Exp $	*/
+/*	$NetBSD: create.c,v 1.79 2024/12/05 17:17:43 christos Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993
@@ -38,7 +38,7 @@
 #if 0
 static char sccsid[] = "@(#)create.c	8.1 (Berkeley) 6/6/93";
 #else
-__RCSID("$NetBSD: create.c,v 1.73 2014/04/24 17:22:41 christos Exp $");
+__RCSID("$NetBSD: create.c,v 1.79 2024/12/05 17:17:43 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -84,13 +84,6 @@ 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(FILE *, int, int *, const char *, ...)
     __printflike(4, 5);
 static int	statd(FILE *, FTS *, FTSENT *, uid_t *, gid_t *, mode_t *,
@@ -180,15 +173,59 @@ cwalk(FILE *fp)
 		mtree_err("%s checksum: %u", fullpath, crc_total);
 }
 
+static void
+dosum(FILE *fp, int indent, FTSENT *p, int *offset, int flag,
+    char * (*func)(const char *, char *), const char *key)
+{
+	char *digestbuf;
+
+	if ((keys & flag) == 0)
+		return;
+
+	digestbuf = (*func)(p->fts_accpath, NULL);
+	if (digestbuf != NULL) {
+		output(fp, indent, offset, "%s=%s", key, digestbuf);
+		free(digestbuf);
+		return;
+	}
+
+	if (qflag) {
+		warn("%s: %s failed", p->fts_path, key);
+		return;
+	}
+
+	mtree_err("%s: %s failed: %s", p->fts_path, key, strerror(errno));
+}
+
+static char *
+crcFile(const char *fname, char *dummy __unused)
+{
+	char *ptr;
+	uint32_t val, len;
+	int fd, e;
+
+	if ((fd = open(fname, O_RDONLY)) == -1)
+		goto out;
+
+	e = crc(fd, &val, &len);
+	close(fd);
+	if (e)
+		goto out;
+
+	if (asprintf(&ptr, "%u", val) < 0)
+		goto out;
+
+	return ptr;
+out:
+	mtree_err("%s: %s", fname, strerror(errno));
+	return NULL;
+}
+
 static void
 statf(FILE *fp, int indent, FTSENT *p)
 {
-	u_int32_t len, val;
-	int fd, offset;
+	int offset;
 	const char *name = NULL;
-#if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2)
-	char *digestbuf;
-#endif
 
 	offset = fprintf(fp, "%*s%s%s", indent, "",
 	    S_ISDIR(p->fts_statp->st_mode) ? "" : "    ", vispath(p->fts_name));
@@ -241,65 +278,25 @@ statf(FILE *fp, int indent, FTSENT *p)
 		output(fp, indent, &offset, "time=%jd.%09ld",
 		    (intmax_t)p->fts_statp->st_mtime, (long)0);
 #endif
-	if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) {
-		if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 ||
-		    crc(fd, &val, &len))
-			mtree_err("%s: %s", p->fts_accpath, strerror(errno));
-		close(fd);
-		output(fp, indent, &offset, "cksum=%lu", (long)val);
-	}
+	if (S_ISREG(p->fts_statp->st_mode))  {
+		dosum(fp, indent, p, &offset, F_CKSUM, crcFile, "cksum");
 #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(fp, indent, &offset, "%s=%s", MD5KEY, digestbuf);
-		free(digestbuf);
-	}
+		dosum(fp, indent, p, &offset, F_MD5, MD5File, MD5KEY);
 #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(fp, indent, &offset, "%s=%s", RMD160KEY, digestbuf);
-		free(digestbuf);
-	}
+		dosum(fp, indent, p, &offset, F_RMD160, RMD160File, RMD160KEY);
 #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(fp, indent, &offset, "%s=%s", SHA1KEY, digestbuf);
-		free(digestbuf);
-	}
+		dosum(fp, indent, p, &offset, F_SHA1, SHA1File, SHA1KEY);
 #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(fp, indent, &offset, "%s=%s", SHA256KEY, digestbuf);
-		free(digestbuf);
-	}
+		dosum(fp, indent, p, &offset, F_SHA256, SHA256_File, SHA256KEY);
 #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(fp, indent, &offset, "%s=%s", SHA384KEY, digestbuf);
-		free(digestbuf);
-	}
+		dosum(fp, indent, p, &offset, F_SHA384, SHA384_File, SHA384KEY);
 #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(fp, indent, &offset, "%s=%s", SHA512KEY, digestbuf);
-		free(digestbuf);
-	}
+		dosum(fp, indent, p, &offset, F_SHA512, SHA512_File, SHA512KEY);
 #endif	/* ! NO_SHA2 */
+	}
 	if (keys & F_SLINK &&
 	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
 		output(fp, indent, &offset, "link=%s",
@@ -440,27 +437,6 @@ statd(FILE *fp, FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode,
 	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(FILE *fp, int indent, int *offset, const char *fmt, ...)
 {
diff --git a/contrib/mtree/extern.h b/contrib/mtree/extern.h
index 091cf8f84460..7b58dd4a4d20 100644
--- a/contrib/mtree/extern.h
+++ b/contrib/mtree/extern.h
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.39 2014/04/24 17:22:41 christos Exp $	*/
+/*	$NetBSD: extern.h,v 1.41 2024/12/05 17:17:43 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -49,6 +49,12 @@
 #include <netdb.h>
 #endif
 
+#if defined(__FreeBSD__) && !defined(HAVE_NBTOOL_CONFIG_H)
+#define    FTS_CONST const
+#else
+#define    FTS_CONST
+#endif
+
 #ifndef MAXHOSTNAMELEN
 #define MAXHOSTNAMELEN 256
 #endif
@@ -62,8 +68,9 @@ enum flavor {
 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 *);
+int	 crc(int, uint32_t *, uint32_t *);
 void	 cwalk(FILE *);
+int	dcmp(const FTSENT *FTS_CONST *, const FTSENT *FTS_CONST *);
 void	 dump_nodes(FILE *, const char *, NODE *, int);
 void	 init_excludes(void);
 int	 matchtags(NODE *);
@@ -83,7 +90,7 @@ extern int	bflag, dflag, eflag, iflag, jflag, lflag, mflag,
 extern int	mtree_Mflag, mtree_Sflag, mtree_Wflag;
 extern size_t	mtree_lineno;
 extern enum flavor	flavor;
-extern u_int32_t crc_total;
+extern uint32_t crc_total;
 extern int	ftsoptions, keys;
 extern char	fullpath[];
 extern slist_t	includetags, excludetags;
diff --git a/contrib/mtree/misc.c b/contrib/mtree/misc.c
index b99f1ce1f708..b5bd9f4e06c6 100644
--- a/contrib/mtree/misc.c
+++ b/contrib/mtree/misc.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 christos Exp $	*/
+/*	$NetBSD: misc.c,v 1.35 2024/12/05 17:17:43 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 christos Exp $");
+__RCSID("$NetBSD: misc.c,v 1.35 2024/12/05 17:17:43 christos Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -111,7 +111,7 @@ slist_t	excludetags, includetags;
 int	keys = KEYDEFAULT;
 
 
-int keycompare(const void *, const void *);
+static int keycompare(const void *, const void *);
 
 u_int
 parsekey(const char *name, int *needvaluep)
@@ -153,7 +153,7 @@ parsetype(const char *name)
 	return (k->val);
 }
 
-int
+static int
 keycompare(const void *a, const void *b)
 {
 
@@ -198,7 +198,7 @@ void
 parsetags(slist_t *list, char *args)
 {
 	char	*p, *e;
-	int	len;
+	size_t	len;
 
 	if (args == NULL) {
 		addtag(list, NULL);
diff --git a/contrib/mtree/mtree.8 b/contrib/mtree/mtree.8
index 53bb21f711bf..99e3199de943 100644
--- a/contrib/mtree/mtree.8
+++ b/contrib/mtree/mtree.8
@@ -1,4 +1,4 @@
-.\"	$NetBSD: mtree.8,v 1.69 2013/02/03 19:16:06 christos Exp $
+.\"	$NetBSD: mtree.8,v 1.78 2023/12/02 13:26:09 christos Exp $
 .\"
 .\" Copyright (c) 1989, 1990, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -56,7 +56,7 @@
 .\"
 .\"     @(#)mtree.8	8.2 (Berkeley) 12/11/93
 .\"
-.Dd February 3, 2013
+.Dd December 2, 2023
 .Dt MTREE 8
 .Os
 .Sh NAME
@@ -93,9 +93,11 @@ 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
+.Bl -tag -width Fl
+.
 .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.
@@ -105,8 +107,7 @@ from the file given by
 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 \&./ )
+.Pq beginning with Ql \&./
 is always printed as the first field;
 .Fl K ,
 .Fl k ,
@@ -120,19 +121,25 @@ 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 )
+the current working directory
+.Po or the directory provided by
+.Fl p Ar path
+.Pc
 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
@@ -141,9 +148,11 @@ 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
@@ -151,22 +160,23 @@ utility.
 The
 .Ar flavor
 can be one of
-.Sy mtree ,
-.Sy freebsd9 ,
+.Cm mtree ,
+.Cm freebsd9 ,
 or
-.Sy netbsd6 .
+.Cm netbsd6 .
 The default is
-.Sy mtree .
+.Cm mtree .
 The
-.Sy freebsd9
+.Cm freebsd9
 and
-.Sy netbsd6
-flavors attempt to preserve output compatiblity and command line option
+.Cm netbsd6
+flavors attempt to preserve output compatibility 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  ,
@@ -178,10 +188,18 @@ 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.
+having
+.Dq in first spec only ,
+.Dq in second spec only ,
+and
+.Dq different
+columns, prefixed by zero, one and two
+.Tn TAB
+characters respectively.
+Each entry in the
+.Dq different
+column occupies two lines, one from each specification.
+.
 .It Fl I Ar tags
 Add the comma separated tags to the
 .Dq inclusion
@@ -191,14 +209,22 @@ Non-directories with tags which are in the inclusion list are printed with
 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.
+If specified, set the
+.Ql schg
+and/or
+.Ql 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
+This does not affect either the
+.Ql /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
@@ -207,26 +233,31 @@ 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.
+.Ar 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 .
+.Fl R Cm type .
+.
 .It Fl L
 Follow all symbolic links in the file hierarchy.
+.
 .It Fl l
 Do
 .Dq loose
@@ -235,7 +266,7 @@ 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
+checks apply only to read, write and execute permissions \(em 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.
@@ -244,17 +275,25 @@ This option may not be set at the same time as the
 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).
+If the
+.Ql schg
+and/or
+.Ql sappnd
+flags are specified, reset these flags.
+Note that this is only possible with securelevel less than 1
+.Po
+i.e., in single user mode or while the system is running in insecure mode
+.Pc .
 See
 .Xr init 8
 for information on security levels.
+.
 .It Fl n
 Do not emit pathname comments when creating a specification.
 Normally
@@ -262,6 +301,7 @@ 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
@@ -274,31 +314,42 @@ rather than using the results from the system's
 and
 .Xr getgrnam 3
 (and related) library calls.
+.
 .It Fl O Ar onlypaths
 Only include files included in this list of pathnames.
+.
 .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.
+Repeating the flag more than once will attempt to reset all the
+file flags via
+.Xr lchflags 2
+before attempting to remove the file in case the file was immutable.
+.
 .It Fl S
 When reading a specification into an internal data structure,
 sort the entries.
@@ -320,19 +371,23 @@ 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,
@@ -350,6 +405,7 @@ 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
@@ -358,6 +414,7 @@ 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
@@ -370,11 +427,14 @@ the starting directory); otherwise,
 it will be matched against basenames only.
 Comments are permitted in
 the
-.Ar exclude-list
+.Ar exclude-file
 file.
+.
 .It Fl x
 Don't descend below mount points in the file hierarchy.
+.
 .El
+.
 .Pp
 Specifications are mostly composed of
 .Dq keywords ,
@@ -384,7 +444,8 @@ 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
+.
+.Bl -tag -width Sy
 .It Sy cksum
 The checksum of the file using the default algorithm specified by
 the
@@ -420,6 +481,7 @@ format.)
 .It Ar number
 Opaque number (as stored on the file system).
 .El
+.
 .Pp
 The following values for
 .Ar format
@@ -614,9 +676,24 @@ they match.
 .Nm
 uses
 .Xr strsvis 3
-(in VIS_CSTYLE format) to encode path names containing
+(in
+.Dv VIS_OCTAL
+format) to encode path names containing
 non-printable characters.
 Whitespace characters are encoded as
+.Ql \e040
+(space),
+.Ql \e011
+(tab), and
+.Ql \e012
+(new line).
+When flavor
+.Sy netbsd6
+is selected,
+.Xr strsvis 3
+(in
+.Dv VIS_CSTYLE
+format) is used and whitespace characters are encoded as
 .Ql \es
 (space),
 .Ql \et
@@ -678,7 +755,7 @@ The
 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
+.Bl -tag -width Pa -compact
 .It Pa /etc/mtree
 system specification directory
 .El
diff --git a/contrib/mtree/mtree.c b/contrib/mtree/mtree.c
index 8b4cb9494d53..28f09fa32210 100644
--- a/contrib/mtree/mtree.c
+++ b/contrib/mtree/mtree.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $	*/
+/*	$NetBSD: mtree.c,v 1.51 2024/12/05 17:17:15 christos Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1990, 1993
@@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\
 #if 0
 static char sccsid[] = "@(#)mtree.c	8.1 (Berkeley) 6/6/93";
 #else
-__RCSID("$NetBSD: mtree.c,v 1.49 2014/04/24 17:22:41 christos Exp $");
+__RCSID("$NetBSD: mtree.c,v 1.51 2024/12/05 17:17:15 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -195,7 +195,7 @@ main(int argc, char **argv)
 			qflag = 1;
 			break;
 		case 'r':
-			rflag = 1;
+			rflag++;
 			break;
 		case 'R':
 			while ((p = strsep(&optarg, " \t,")) != NULL)
@@ -204,7 +204,7 @@ main(int argc, char **argv)
 			break;
 		case 's':
 			sflag = 1;
-			crc_total = ~strtol(optarg, &p, 0);
+			crc_total = (uint32_t)~strtol(optarg, &p, 0);
 			if (*p)
 				mtree_err("illegal seed value -- %s", optarg);
 			break;
diff --git a/contrib/mtree/spec.c b/contrib/mtree/spec.c
index 6fbe6f534560..25bface34bd0 100644
--- a/contrib/mtree/spec.c
+++ b/contrib/mtree/spec.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: spec.c,v 1.89 2014/04/24 17:22:41 christos Exp $	*/
+/*	$NetBSD: spec.c,v 1.92 2024/12/05 17:17:43 christos Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993
@@ -67,7 +67,7 @@
 #if 0
 static char sccsid[] = "@(#)spec.c	8.2 (Berkeley) 4/28/95";
 #else
-__RCSID("$NetBSD: spec.c,v 1.89 2014/04/24 17:22:41 christos Exp $");
+__RCSID("$NetBSD: spec.c,v 1.92 2024/12/05 17:17:43 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -224,10 +224,14 @@ noparent:		mtree_err("no parent node");
 			 */
 			if (strcmp(centry->name, ".") == 0 && centry->type == 0)
 				centry->type = F_DIR;
-			if (strcmp(centry->name, ".") != 0 ||
-			    centry->type != F_DIR)
+			if (strcmp(centry->name, ".") != 0)
 				mtree_err(
-				    "root node must be the directory `.'");
+				    "root node must be the directory `.',"
+				    " found `%s'", centry->name);
+			if (centry->type != F_DIR)
+				mtree_err(
+				    "root node must type %#x != %#x",
+				    F_DIR, centry->type);
 			last = root = centry;
 			root->parent = root;
 		} else if (pathparent != NULL) {
@@ -539,7 +543,8 @@ replacenode(NODE *cur, NODE *new)
 static void
 set(char *t, NODE *ip)
 {
*** 120 LINES SKIPPED ***


help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6945f7b7.35924.1cf63169>