[PATCH] Add flag to makefs to require specfile entries to exist

Eric van Gyzen eric at vangyzen.net
Wed Aug 14 18:41:47 UTC 2013


The attached patch adds a -X flag to makefs:

    If a regular file listed in the specfile does not exist in the file
    system, and the entry is not marked optional, abort creation of the
    image.  Without this flag, the image would contain a zero-length
    file in this case.

This is very handy when the specfile is the absolute authority for the
contents of the image.  It fails early and loudly, instead of causing
late and sometimes obscure run-time errors.

I checked NetBSD-current; the -X flag is available there.

Would someone like to commit it for me?

Eric
-------------- next part --------------
commit 4f90b5ed516eab57c951162cfdc29d0da0ae7495
Author: Eric van Gyzen <eric at vangyzen.net>
Date:   Wed Aug 14 13:25:55 2013 -0500

    Add a -X flag to makefs
    
    If a regular file listed in the specfile does not exist in the file
    system, and the entry is not marked optional, abort creation of the
    image.  Without this flag, the image would contain a zero-length
    file in this case.

    Obtained from:  Dell, Inc.

diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8
index 4d81e45..776933d 100644
--- a/usr.sbin/makefs/makefs.8
+++ b/usr.sbin/makefs/makefs.8
@@ -43,7 +43,7 @@
 .Nd create a file system image from a directory tree or a mtree manifest
 .Sh SYNOPSIS
 .Nm
-.Op Fl Dpx
+.Op Fl DpXx
 .Op Fl B Ar byte-order
 .Op Fl b Ar free-blocks
 .Op Fl d Ar debug-mask
@@ -155,7 +155,10 @@ isn't provided, the current time will be used.
 If
 .Sy flags
 isn't provided, the current file flags will be used.
-Missing regular file entries will be created as zero-length files.
+Missing regular file entries will be created as zero-length files
+unless
+.Fl X
+is specified.
 .It Fl f Ar free-files
 Ensure that a minimum of
 .Ar free-files
@@ -211,6 +214,12 @@ BSD fast file system (default).
 .It Sy cd9660
 ISO 9660 file system.
 .El
+.It Fl X
+If a regular file listed in the specfile does not exist in the file system,
+and the entry is not marked
+.Sy optional ,
+abort creation of the image.  Without this flag, the image would contain
+a zero-length file in this case.
 .It Fl x
 Exclude file system nodes not explicitly listed in the specfile.
 .El
diff --git a/usr.sbin/makefs/makefs.c b/usr.sbin/makefs/makefs.c
index 03ff1ac..32f3469 100644
--- a/usr.sbin/makefs/makefs.c
+++ b/usr.sbin/makefs/makefs.c
@@ -113,7 +113,7 @@ main(int argc, char *argv[])
 	start_time.tv_sec = start.tv_sec;
 	start_time.tv_nsec = start.tv_usec * 1000;
 
-	while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:ps:S:t:x")) != -1) {
+	while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:ps:S:t:Xx")) != -1) {
 		switch (ch) {
 
 		case 'B':
@@ -229,6 +229,10 @@ main(int argc, char *argv[])
 			fstype->prepare_options(&fsoptions);
 			break;
 
+		case 'X':
+			fsoptions.specrequired = 1;
+			break;
+
 		case 'x':
 			fsoptions.onlyspec = 1;
 			break;
@@ -252,6 +256,10 @@ main(int argc, char *argv[])
 	if (argc < 2)
 		usage();
 
+	/* -X must be accompanied by -F */
+	if (fsoptions.specrequired != 0 && specfile == NULL)
+		errx(1, "-X requires -F mtree-specfile.");
+
 	/* -x must be accompanied by -F */
 	if (fsoptions.onlyspec != 0 && specfile == NULL)
 		errx(1, "-x requires -F mtree-specfile.");
@@ -295,7 +303,8 @@ main(int argc, char *argv[])
 
 	if (specfile) {		/* apply a specfile */
 		TIMER_START(start);
-		apply_specfile(specfile, subtree, root, fsoptions.onlyspec);
+		apply_specfile(specfile, subtree, root, fsoptions.onlyspec,
+			fsoptions.specrequired);
 		TIMER_RESULTS(start, "apply_specfile");
 	}
 
@@ -354,7 +363,7 @@ usage(void)
 	fprintf(stderr,
 "usage: %s [-t fs-type] [-o fs-options] [-d debug-mask] [-B endian]\n"
 "\t[-S sector-size] [-M minimum-size] [-m maximum-size] [-s image-size]\n"
-"\t[-b free-blocks] [-f free-files] [-F mtree-specfile] [-px]\n"
+"\t[-b free-blocks] [-f free-files] [-F mtree-specfile [-X] [-x]] [-p]\n"
 "\t[-N userdb-dir] image-file directory | manifest [extra-directory ...]\n",
 	    prog);
 	exit(1);
diff --git a/usr.sbin/makefs/makefs.h b/usr.sbin/makefs/makefs.h
index 5ab0444..ebb5e8c 100644
--- a/usr.sbin/makefs/makefs.h
+++ b/usr.sbin/makefs/makefs.h
@@ -118,6 +118,7 @@ typedef struct {
 	int	fd;		/* file descriptor of image */
 	void	*superblock;	/* superblock */
 	int	onlyspec;	/* only add entries in specfile */
+	int	specrequired;	/* entries in specfile are required to exist */
 
 
 		/* global options */
@@ -149,7 +150,7 @@ typedef struct {
 } option_t;
 
 
-void		apply_specfile(const char *, const char *, fsnode *, int);
+void		apply_specfile(const char *, const char *, fsnode *, int, int);
 void		dump_fsnodes(fsnode *);
 const char *	inode_type(mode_t);
 fsnode *	read_mtree(const char *, fsnode *);
diff --git a/usr.sbin/makefs/walk.c b/usr.sbin/makefs/walk.c
index 2fc964a..d071692 100644
--- a/usr.sbin/makefs/walk.c
+++ b/usr.sbin/makefs/walk.c
@@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
 #include "mtree.h"
 #include "extern.h"
 
-static	void	 apply_specdir(const char *, NODE *, fsnode *, int);
+static	void	 apply_specdir(const char *, NODE *, fsnode *, int, int);
 static	void	 apply_specentry(const char *, NODE *, fsnode *);
 static	fsnode	*create_fsnode(const char *, const char *, const char *,
 			       struct stat *);
@@ -285,10 +285,11 @@ free_fsnodes(fsnode *node)
  *	read in the mtree(8) specfile, and apply it to the tree
  *	at dir,parent. parameters in parent on equivalent types
  *	will be changed to those found in specfile, and missing
- *	entries will be added.
+ *	entries will be added if specrequired is false.
  */
 void
-apply_specfile(const char *specfile, const char *dir, fsnode *parent, int speconly)
+apply_specfile(const char *specfile, const char *dir, fsnode *parent,
+    int speconly, int specrequired)
 {
 	struct timeval	 start;
 	FILE	*fp;
@@ -316,12 +317,13 @@ apply_specfile(const char *specfile, const char *dir, fsnode *parent, int specon
 	assert(root->type == F_DIR);
 
 				/* merge in the changes */
-	apply_specdir(dir, root, parent, speconly);
+	apply_specdir(dir, root, parent, speconly, specrequired);
 
 }
 
 static void
-apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly)
+apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly,
+    int specrequired)
 {
 	char	 path[MAXPATHLEN + 1];
 	NODE	*curnode;
@@ -388,13 +390,22 @@ apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly)
 		if (curfsnode == NULL) {	/* need new entry */
 			struct stat	stbuf;
 
-					    /*
-					     * don't add optional spec entries
-					     * that lack an existing fs entry
-					     */
-			if ((curnode->flags & F_OPT) &&
-			    lstat(path, &stbuf) == -1)
+			if (lstat(path, &stbuf) == -1) {
+					/*
+					 * don't add optional spec entries
+					 * that lack an existing fs entry
+					 */
+				if (curnode->flags & F_OPT)
 					continue;
+					/*
+					 * When specrequired is true, abort
+					 * if a non-optional regular file
+					 * lacks an existing fs entry.
+					 */
+				if (specrequired && curnode->type == F_FILE)
+					err(1, "`%s', required by specfile",
+					    path);
+			}
 
 					/* check that enough info is provided */
 #define NODETEST(t, m)							\
@@ -451,7 +462,8 @@ apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly)
 			if (curfsnode->type != S_IFDIR)
 				errx(1, "`%s' is not a directory", path);
 			assert (curfsnode->child != NULL);
-			apply_specdir(path, curnode, curfsnode->child, speconly);
+			apply_specdir(path, curnode, curfsnode->child, speconly,
+			    specrequired);
 		}
 	}
 }


More information about the freebsd-hackers mailing list