Module Name:    othersrc
Committed By:   agc
Date:           Tue Jun 21 04:21:25 UTC 2011

Modified Files:
        othersrc/external/bsd/mat/dist: frontends.c main.c mat.1 mat.c mat.h
            matpax.1
        othersrc/external/bsd/mat/mat: Makefile

Log Message:
Add a separate "audit" comment to the tar and pax frontends for mat, which
compare each component of the archive with its entry in the file system.
Sizes, all digests, oweners, group owners, mtimes and symbolic link targets
are all compared.

Add a test for the new audit command:

        cd d && env LD_LIBRARY_PATH=${LIBMATDIR} ../${PROG} avvf 
../archive2.mat > archive2.audit
        cd d && env LD_LIBRARY_PATH=${LIBMATDIR} ../${PROG} tvvf 
../archive2.mat > archive2.list
        -diff d/archive2.list d/archive2.audit

(from the testing target in the mat Makefile).

Update the matpax(1) manual page, per wiz, to describe the pax arguments,
rather than the tar arguments.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 othersrc/external/bsd/mat/dist/frontends.c
cvs rdiff -u -r1.2 -r1.3 othersrc/external/bsd/mat/dist/main.c \
    othersrc/external/bsd/mat/dist/mat.h \
    othersrc/external/bsd/mat/dist/matpax.1
cvs rdiff -u -r1.4 -r1.5 othersrc/external/bsd/mat/dist/mat.1
cvs rdiff -u -r1.1.1.1 -r1.2 othersrc/external/bsd/mat/dist/mat.c
cvs rdiff -u -r1.2 -r1.3 othersrc/external/bsd/mat/mat/Makefile

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: othersrc/external/bsd/mat/dist/frontends.c
diff -u othersrc/external/bsd/mat/dist/frontends.c:1.1 othersrc/external/bsd/mat/dist/frontends.c:1.2
--- othersrc/external/bsd/mat/dist/frontends.c:1.1	Mon Jun 20 14:58:53 2011
+++ othersrc/external/bsd/mat/dist/frontends.c	Tue Jun 21 04:21:24 2011
@@ -66,7 +66,8 @@
 reading(const char *action)
 {
 	return (strcmp(action, "verify") == 0 ||
-		strcmp(action, "list")  == 0 ||
+		strcmp(action, "audit") == 0 ||
+		strcmp(action, "list") == 0 ||
 		strcmp(action, "extract") == 0);
 }
 
@@ -137,7 +138,7 @@
 		(void) snprintf(newarg, sizeof(newarg), "-%s", argv[1]);
 		argv[1] = newarg;
 	}
-	while ((i = getopt(argc, argv, "C:T:Vcf:ptvx")) != -1) {
+	while ((i = getopt(argc, argv, "C:T:Vacf:ptvx")) != -1) {
 		switch(i) {
 		case 'C':
 			dir = optarg;
@@ -148,6 +149,9 @@
 		case 'V':
 			action = "verify";
 			break;
+		case 'a':
+			action = "audit";
+			break;
 		case 'c':
 			action = "create";
 			break;
@@ -200,6 +204,8 @@
 			ok = mat_verify(&mat);
 		} else if (strcmp(action, "extract") == 0) {
 			ok = mat_extract(&mat, NULL);
+		} else if (strcmp(action, "audit") == 0) {
+			ok = mat_audit(&mat, NULL, stdout);
 		} else {
 			(void) fprintf(stderr, "unknown action specified (%s)\n", action);
 			return 0;
@@ -218,6 +224,10 @@
 				if (!mat_list(&mat, argv[i], stdout)) {
 					ok = 0;
 				}
+			} else if (strcmp(action, "audit") == 0) {
+				if (!mat_audit(&mat, argv[i], stdout)) {
+					ok = 0;
+				}
 			}
 		}
 	}
@@ -276,11 +286,17 @@
 	ok = 1;
 	action = "list";
 	deltemp = 0;
-	while ((i = getopt(argc, argv, "Vaf:ilrvw")) != -1) {
+	while ((i = getopt(argc, argv, "C:Vaf:lrwv")) != -1) {
 		switch(i) {
+		case 'C':
+			dir = optarg;
+			break;
 		case 'V':
 			action = "verify";
 			break;
+		case 'a':
+			action = "audit";
+			break;
 		case 'f':
 			archive = optarg;
 			break;
@@ -293,6 +309,9 @@
 		case 'w':
 			action = "create";
 			break;
+		case 'v':
+			mat.verbose += 1;
+			break;
 		default:
 			(void) fprintf(stderr, "Unknown flag \"%c\"\n", i);
 		}
@@ -371,4 +390,3 @@
 	va_end(args);
 	return mat_pax(argc, argv);
 }
-

Index: othersrc/external/bsd/mat/dist/main.c
diff -u othersrc/external/bsd/mat/dist/main.c:1.2 othersrc/external/bsd/mat/dist/main.c:1.3
--- othersrc/external/bsd/mat/dist/main.c:1.2	Mon Jun 20 14:58:53 2011
+++ othersrc/external/bsd/mat/dist/main.c	Tue Jun 21 04:21:24 2011
@@ -37,14 +37,14 @@
 } map_t;
 
 static map_t	mappings[] = {
-	{ "tar",	mat_tar	},
-	{ "mtar",	mat_tar	},
-	{ "mattar",	mat_tar	},
-	{ "mat",	mat_tar	},
-	{ "pax",	mat_pax	},
-	{ "mpax",	mat_pax	},
-	{ "matpax",	mat_pax	},
-	{ NULL,		NULL	}
+	{ "tar",	mat_tar		},
+	{ "mtar",	mat_tar		},
+	{ "mattar",	mat_tar		},
+	{ "mat",	mat_tar		},
+	{ "pax",	mat_pax		},
+	{ "mpax",	mat_pax		},
+	{ "matpax",	mat_pax		},
+	{ NULL,		NULL		}
 };
 
 int
Index: othersrc/external/bsd/mat/dist/mat.h
diff -u othersrc/external/bsd/mat/dist/mat.h:1.2 othersrc/external/bsd/mat/dist/mat.h:1.3
--- othersrc/external/bsd/mat/dist/mat.h:1.2	Mon Jun 20 14:58:53 2011
+++ othersrc/external/bsd/mat/dist/mat.h	Tue Jun 21 04:21:24 2011
@@ -99,6 +99,7 @@
 int mat_list(mat_t */*mat*/, const char */*pat*/, FILE */*fp*/);
 int mat_verify(mat_t */*mat*/);
 int mat_extract(mat_t */*mat*/, const char */*pat*/);
+int mat_audit(mat_t */*mat*/, const char */*pat*/, FILE */*fp*/);
 
 int mat_tar(int /*argc*/, char **/*argv*/);
 int mat_vtar(char */*arg*/, ...);
Index: othersrc/external/bsd/mat/dist/matpax.1
diff -u othersrc/external/bsd/mat/dist/matpax.1:1.2 othersrc/external/bsd/mat/dist/matpax.1:1.3
--- othersrc/external/bsd/mat/dist/matpax.1:1.2	Mon Jun 20 15:15:25 2011
+++ othersrc/external/bsd/mat/dist/matpax.1	Tue Jun 21 04:21:24 2011
@@ -1,4 +1,4 @@
-.\" $NetBSD: matpax.1,v 1.2 2011/06/20 15:15:25 wiz Exp $
+.\" $NetBSD: matpax.1,v 1.3 2011/06/21 04:21:24 agc Exp $
 .\"
 .\" Copyright (c) 2011 Alistair Crooks <[email protected]>
 .\" All rights reserved.
@@ -23,7 +23,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd June 19, 2011
+.Dd June 20, 2011
 .Dt MATPAX 1
 .Os
 .Sh NAME
@@ -31,10 +31,9 @@
 .Nd minimalist archive tool program with pax frontend
 .Sh SYNOPSIS
 .Nm
-.Op Fl cptVvx
+.Op Fl Valrw
 .Op Fl C Ar directory
 .Op Fl f Ar archive
-.Op Fl T Ar template
 .Op Ar file ...
 .Sh DESCRIPTION
 The
@@ -56,8 +55,19 @@
 perform an initial
 .Xr chdir 2
 into the specified directory before attempting to resolve any filenames.
-.It Fl c
-create the archive
+.It Fl a
+Perform an
+.Dq audit
+pass where all of the components of the named archive are compared
+to the entries in the file system, and the file system entries are
+displayed in the same format as the
+.Dq list
+function of
+.Nm
+so that tools such as
+.Xr diff 1
+can be used to compare packages and installed file system entries to
+see if anything has been changed.
 .It Fl f Ar archive
 Use the
 .Xr libmat 3
@@ -69,39 +79,24 @@
 or will be read from
 .Dv stdin
 depending on the action specified.
-.It Fl p
-when extracting the components of the archive,
-preserve the file owner and group information,
-as well as the file modes.
-Setuid and setgid bits are only preserved
-if the program is run with an effective
-uid of 0.
-.It Fl T Ar template
-takes the names of the entries to be included in the archive
-from the template file provided.
-This template file is expected to be in the
-.Dv METALOG
-format, as generated during the
-.Nx
-.Dv build.sh
-phase.
-.It Fl t
-list the contents of the archive on stdout.
+.It Fl l
+list the archive
+.It Fl r
+extract the named components from the archive.
+.It Fl w
+create the archive from the named components.
 .It Fl V
 verify the archive does not contain dangerous
 entries which could compromise a machine if the archive
 is extracted or listed.
-.It Fl v
-perform operations in a verbose manner.
-This option can be repeated to provide higher
 levels of verbosity.
 For instance, when listing entries,
 a verbosity level of 2 will also show
 the
 .Xr SHA256 3
 digests associated with the archive component.
-.It Fl x
-extract the contents of the archive.
+.It Fl v
+increase the verbosity level by one unit.
 .El
 .Pp
 .Nm
@@ -126,8 +121,10 @@
 .Bd -literal
 .Ed
 .Sh SEE ALSO
+.Xr mat 1 ,
 .Xr pax 1 ,
 .Xr tar 1 ,
+.Xr chdir 2 ,
 .Xr libmat 3 ,
 .Xr sha2 3
 .Sh HISTORY

Index: othersrc/external/bsd/mat/dist/mat.1
diff -u othersrc/external/bsd/mat/dist/mat.1:1.4 othersrc/external/bsd/mat/dist/mat.1:1.5
--- othersrc/external/bsd/mat/dist/mat.1:1.4	Mon Jun 20 15:09:18 2011
+++ othersrc/external/bsd/mat/dist/mat.1	Tue Jun 21 04:21:24 2011
@@ -1,4 +1,4 @@
-.\" $NetBSD: mat.1,v 1.4 2011/06/20 15:09:18 wiz Exp $
+.\" $NetBSD: mat.1,v 1.5 2011/06/21 04:21:24 agc Exp $
 .\"
 .\" Copyright (c) 2011 Alistair Crooks <[email protected]>
 .\" All rights reserved.
@@ -23,7 +23,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd June 19, 2011
+.Dd June 20, 2011
 .Dt MATTAR 1
 .Os
 .Sh NAME
@@ -31,7 +31,7 @@
 .Nd minimalist archive tool program
 .Sh SYNOPSIS
 .Nm
-.Op Fl cptVvx
+.Op Fl acptVvx
 .Op Fl C Ar directory
 .Op Fl f Ar archive
 .Op Fl T Ar template
@@ -57,6 +57,20 @@
 .Xr chdir 2
 into the specified directory before attempting to resolve any filenames.
 .It Fl c
+audit the contents of the archive against the installed versions of the file system.
+The output is the same as would be output using the
+.Fl t
+option, except that for all components of the archive,
+all digests, symbolic link targets, file system
+owners and group owners, sizes, and mtimes are all read from the file system
+rather than the archive.
+This output can then be compared to that from the
+.Fl t
+option using programs such as
+.Xr diff 1
+to see if anything has been modified since the archive contents
+were extracted.
+.It Fl c
 create the archive
 .It Fl f Ar archive
 Use the

Index: othersrc/external/bsd/mat/dist/mat.c
diff -u othersrc/external/bsd/mat/dist/mat.c:1.1.1.1 othersrc/external/bsd/mat/dist/mat.c:1.2
--- othersrc/external/bsd/mat/dist/mat.c:1.1.1.1	Sat Jun 18 04:53:13 2011
+++ othersrc/external/bsd/mat/dist/mat.c	Tue Jun 21 04:21:24 2011
@@ -234,6 +234,40 @@
 	SHA256_Final(dig, &sha256);
 }
 
+/* calculate a combo digest */
+static int
+digest_file(uint8_t *dig, const char *f)
+{
+	struct stat	 st;
+	SHA256_CTX	 sha256;
+	ssize_t		 cc;
+	size_t		 size;
+	uint8_t		*mapped;
+	FILE		*fp;
+	char		 buf[BUFSIZ * 10];
+
+	if ((fp = fopen(f, "r")) == NULL) {
+		return 0;
+	}
+	SHA256_Init(&sha256);
+	(void) fstat(fileno(fp), &st);
+	size = (size_t)st.st_size;
+	mapped = mmap(NULL, size, PROT_READ, MAP_FILE, fileno(fp), 0);
+	if (mapped == MAP_FAILED) {
+		SHA256_Update(&sha256, mapped, size);
+	} else {
+		while ((cc = read(fileno(fp), buf, sizeof(buf))) > 0) {
+			SHA256_Update(&sha256, (const uint8_t *)buf, (size_t)cc);
+		}
+	}
+	SHA256_Final(dig, &sha256);
+	if (mapped != MAP_FAILED) {
+		munmap(mapped, size);
+	}
+	(void) fclose(fp);
+	return 1;
+}
+
 /* make intermediate dirs */
 static int
 intermediates(const char *path)
@@ -897,3 +931,130 @@
 	(void) fclose(mat->fp);
 	return 1;
 }
+
+/* list the contents of the archive on the file system */
+int
+mat_audit(mat_t *mat, const char *pat, FILE *fp)
+{
+	struct stat	 st;
+	uint64_t	 off;
+	unsigned	 i;
+	matent_t	 fsent;
+	matent_t	 ent;
+	uint8_t		*contents;
+	uint8_t		*name;
+	uint8_t		*s;
+	time_t		 t;
+	char		 buf[MAT_PATH_MAX * 2];
+	char		 mbuf[12];
+	char		*tim;
+	char		 date[16];
+	int		 list;
+	int		 cc;
+	int		 ok;
+
+	if (!mat_verify(mat)) {
+		return 0;
+	}
+	for (ok = 1, off = sizeof(matheader_t), s = mat->mapped; off < mat->size ; ) {
+		(void) memset(&ent, 0x0, sizeof(ent));
+		(void) memset(&fsent, 0x0, sizeof(fsent));
+		readmeta(&s[off], &ent);
+		/* skip over meta info */
+		off += sizeof(ent.meta);
+		/* next is name */
+		name = &s[off];
+		off += ent.meta.namelen;
+		list = (pat == NULL) ? 1 : (fnmatch(pat, (char *)name, FNM_PATHNAME) == 0);
+		if (list) {
+			if (lstat((const char *)name, &st) < 0) {
+				(void) fprintf(stderr, "can't lstat '%s'\n", name);
+				list = 0;
+			} else {
+				fillmeta(&fsent, (const char *)name, &st, NULL, NULL);
+			}
+		}
+		contents = NULL;
+		switch(ent.meta.type) {
+		case 'f':
+			digest_file(fsent.digest, (const char *)name);
+			off += ent.meta.size;
+			off += sizeof(ent.digest);
+			break;
+		case 'h':
+			contents = &s[off];
+			off += ent.meta.linklen;
+			digest_file(fsent.digest, (const char *)name);
+			off += sizeof(ent.digest);
+			break;
+		case 'l':
+			contents = &s[off];
+			if ((cc = (int)readlink((const char *)name, buf, sizeof(buf))) < 0) {
+				(void) fprintf(stderr, "bad readlink for '%s'\n", name);
+				ok = 0;
+			}
+			buf[cc] = 0x0;
+			digest_update(fsent.digest, (uint8_t *)buf, ent.meta.linklen);
+			off += ent.meta.linklen;
+			(void) memcpy(ent.digest, &s[off], sizeof(ent.digest));
+			off += sizeof(ent.digest);
+			break;
+		case 'b':
+		case 'c':
+		case 'd':
+			break;
+		default:
+			(void) fprintf(stderr, "unrecognised type '%c' '%.*s'\n",
+				ent.meta.type, (int)ent.meta.namelen, name);
+			break;
+		}
+		cc = 0;
+		if (mat->verbose > 0) {
+			mbuf[0] = ((st.st_mode & S_IFMT) == S_IFREG) ? '-' :
+					((st.st_mode & S_IFMT) == S_IFLNK) ? 'l':
+					((st.st_mode & S_IFMT) == S_IFDIR) ? 'd':
+					((st.st_mode & S_IFMT) == S_IFBLK) ? 'b':
+					((st.st_mode & S_IFMT) == S_IFCHR) ? 'c': '?';
+			mbuf[1] = (st.st_mode & 0400) ? 'r' : '-';
+			mbuf[2] = (st.st_mode & 0200) ? 'w' : '-';
+			mbuf[3] = (st.st_mode & 04000) ? 's' : (st.st_mode & 0100) ? 'x' : '-';
+			mbuf[4] = (st.st_mode & 0040) ? 'r' : '-';
+			mbuf[5] = (st.st_mode & 0020) ? 'w' : '-';
+			mbuf[6] = (st.st_mode & 02000) ? 's' : (st.st_mode & 0010) ? 'x' : '-';
+			mbuf[7] = (st.st_mode & 0004) ? 'r' : '-';
+			mbuf[8] = (st.st_mode & 0002) ? 'w' : '-';
+			mbuf[9] = (st.st_mode & 01000) ? 't' : (st.st_mode & 0001) ? 'x' : '-';
+			mbuf[10] = 0x0;
+			t = st.st_mtime;
+			tim = ctime(&t);
+			t = time(NULL);
+			if (t - st.st_mtime >= MONTHS(6)) {
+				(void) snprintf(date, sizeof(date), "%.7s %.4s", &tim[4], &tim[20]);
+			} else {
+				(void) snprintf(date, sizeof(date), "%.12s", &tim[4]);
+			}
+			find_name("user", st.st_uid, fsent.meta.user, sizeof(fsent.meta.user));
+			find_name("group", st.st_gid, fsent.meta.group, sizeof(fsent.meta.group));
+			cc += snprintf(&buf[cc], sizeof(buf) - cc, "%s %2d %s  %s %6" PRIu64 " %s ",
+				mbuf, st.st_nlink, fsent.meta.user, fsent.meta.group, st.st_size, date);
+			if (mat->verbose > 1) {
+				for (i = 0 ; i < sizeof(fsent.digest) ; i++) {
+					cc += snprintf(&buf[cc], sizeof(buf) - cc, "%02x", fsent.digest[i]);
+				}
+				buf[cc++] = ' ';
+			}
+		}
+		cc += snprintf(&buf[cc], sizeof(buf) - cc, "%s", name);
+		if (mat->verbose > 0 && ent.meta.type == 'l') {
+			cc += snprintf(&buf[cc], sizeof(buf) - cc, " -> %s", contents);
+		}
+		if (mat->verbose > 0 && ent.meta.type == 'h') {
+			cc += snprintf(&buf[cc], sizeof(buf) - cc, " == %s", contents);
+		}
+		cc += snprintf(&buf[cc], sizeof(buf) - cc, "\n");
+		if (list && fp) {
+			(void) fprintf(fp, "%s", buf);
+		}
+	}
+	return ok;
+}

Index: othersrc/external/bsd/mat/mat/Makefile
diff -u othersrc/external/bsd/mat/mat/Makefile:1.2 othersrc/external/bsd/mat/mat/Makefile:1.3
--- othersrc/external/bsd/mat/mat/Makefile:1.2	Mon Jun 20 14:58:54 2011
+++ othersrc/external/bsd/mat/mat/Makefile	Tue Jun 21 04:21:25 2011
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.2 2011/06/20 14:58:54 agc Exp $
+#	$NetBSD: Makefile,v 1.3 2011/06/21 04:21:25 agc Exp $
 
 .include <bsd.own.mk>
 
@@ -58,3 +58,7 @@
 	rm -rf b && mkdir b
 	cd b && env LD_LIBRARY_PATH=${LIBMATDIR} ../${PROG} xvf ../a.mat
 	cd b && env LD_LIBRARY_PATH=${LIBMATDIR} ../${PROG} xvf ../archive2.mat m
+	cd d && env LD_LIBRARY_PATH=${LIBMATDIR} ../${PROG} avvf ../archive2.mat > archive2.audit
+	cd d && env LD_LIBRARY_PATH=${LIBMATDIR} ../${PROG} tvvf ../archive2.mat > archive2.list
+	-diff d/archive2.list d/archive2.audit
+	env LD_LIBRARY_PATH=${LIBMATDIR} ./${PROG} avvf a.mat

Reply via email to