From owner-freebsd-hackers@FreeBSD.ORG Wed Aug 14 18:41:46 2013 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id E19D485F; Wed, 14 Aug 2013 18:41:46 +0000 (UTC) (envelope-from eric@vangyzen.net) Received: from aussmtpmrkpc120.us.dell.com (aussmtpmrkpc120.us.dell.com [143.166.82.159]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 6F1952DEB; Wed, 14 Aug 2013 18:41:45 +0000 (UTC) X-Loopcount0: from 64.238.244.148 X-IronPort-AV: E=Sophos;i="4.89,878,1367989200"; d="scan'208";a="39998222" Message-ID: <520BCF67.2070109@vangyzen.net> Date: Wed, 14 Aug 2013 13:41:43 -0500 From: Eric van Gyzen User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:17.0) Gecko/20130702 Thunderbird/17.0.7 MIME-Version: 1.0 To: freebsd-hackers@freebsd.org, Brooks Davis , marcel@FreeBSD.org Subject: [PATCH] Add flag to makefs to require specfile entries to exist Content-Type: multipart/mixed; boundary="------------040609050209020303070807" X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Aug 2013 18:41:47 -0000 --------------040609050209020303070807 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit 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 --------------040609050209020303070807 Content-Type: text/plain; charset="ISO-8859-1"; name="makefs-X-head.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="makefs-X-head.patch" commit 4f90b5ed516eab57c951162cfdc29d0da0ae7495 Author: Eric van Gyzen 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); } } } --------------040609050209020303070807--