Date: Wed, 15 Mar 2017 13:34:52 +0000 (UTC) From: Ed Maste <emaste@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315304 - head/usr.sbin/makefs Message-ID: <201703151334.v2FDYqY8057248@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: emaste Date: Wed Mar 15 13:34:51 2017 New Revision: 315304 URL: https://svnweb.freebsd.org/changeset/base/315304 Log: makefs: sync option parsing with NetBSD - add support for parsing different types; not just int - homogenize option parsing - fix single letter parsing - remove duplicated code NetBSD revisions: cd9660.c 1.36 1.37 1.38 1.41 1.42 1.43 ffs.c 1.50 1.51 1.52 1.53 1.56 1.57 makefs.c 1.36 1.37 1.38 1.39 1.40 1.42 1.43 1.44 1.46 makefs.h 1.28 1.29 1.31 1.32 Obtained from: NetBSD Sponsored by: The FreeBSD Foundation Modified: head/usr.sbin/makefs/cd9660.c head/usr.sbin/makefs/cd9660.h head/usr.sbin/makefs/ffs.c head/usr.sbin/makefs/makefs.c head/usr.sbin/makefs/makefs.h Modified: head/usr.sbin/makefs/cd9660.c ============================================================================== --- head/usr.sbin/makefs/cd9660.c Wed Mar 15 11:16:26 2017 (r315303) +++ head/usr.sbin/makefs/cd9660.c Wed Mar 15 13:34:51 2017 (r315304) @@ -256,7 +256,70 @@ cd9660_prep_opts(fsinfo_t *fsopts) if ((diskStructure = calloc(1, sizeof(*diskStructure))) == NULL) err(EXIT_FAILURE, "%s: calloc", __func__); +#define OPT_STR(letter, name, desc) \ + { letter, name, NULL, OPT_STRBUF, 0, 0, desc } + +#define OPT_NUM(letter, name, field, min, max, desc) \ + { letter, name, &diskStructure->field, \ + sizeof(diskStructure->field) == 8 ? OPT_INT64 : \ + (sizeof(diskStructure->field) == 4 ? OPT_INT32 : \ + (sizeof(diskStructure->field) == 2 ? OPT_INT16 : OPT_INT8)), \ + min, max, desc } + +#define OPT_BOOL(letter, name, field, desc) \ + OPT_NUM(letter, name, field, 0, 1, desc) + + const option_t cd9660_options[] = { + OPT_NUM('l', "isolevel", isoLevel, + 1, 2, "ISO Level"), + OPT_NUM('v', "verbose", verbose_level, + 0, 2, "Turns on verbose output"), + + OPT_BOOL('h', "help", displayHelp, + "Show help message"), + OPT_BOOL('S', "follow-symlinks", follow_sym_links, + "Resolve symlinks in pathnames"), + OPT_BOOL('R', "rockridge", rock_ridge_enabled, + "Enable Rock-Ridge extensions"), + OPT_BOOL('C', "chrp-boot", chrp_boot, + "Enable CHRP boot"), + OPT_BOOL('K', "keep-bad-images", keep_bad_images, + "Keep bad images"), + OPT_BOOL('D', "allow-deep-trees", allow_deep_trees, + "Allow trees more than 8 levels"), + OPT_BOOL('a', "allow-max-name", allow_max_name, + "Allow 37 char filenames (unimplemented)"), + OPT_BOOL('i', "allow-illegal-chars", allow_illegal_chars, + "Allow illegal characters in filenames"), + OPT_BOOL('d', "allow-multidot", allow_multidot, + "Allow multiple periods in filenames"), + OPT_BOOL('o', "omit-trailing-period", omit_trailing_period, + "Omit trailing periods in filenames"), + OPT_BOOL('\0', "allow-lowercase", allow_lowercase, + "Allow lowercase characters in filenames"), + OPT_BOOL('\0', "archimedes", archimedes_enabled, + "Enable Archimedes structure"), + OPT_BOOL('\0', "no-trailing-padding", include_padding_areas, + "Include padding areas"), + + OPT_STR('A', "applicationid", "Application Identifier"), + OPT_STR('P', "publisher", "Publisher Identifier"), + OPT_STR('p', "preparer", "Preparer Identifier"), + OPT_STR('L', "label", "Disk Label"), + OPT_STR('V', "volumeid", "Volume Set Identifier"), + OPT_STR('B', "bootimage", "Boot image parameter"), + OPT_STR('G', "generic-bootimage", "Generic boot image param"), + OPT_STR('\0', "bootimagedir", "Boot image directory"), + OPT_STR('\0', "no-emul-boot", "No boot emulation"), + OPT_STR('\0', "no-boot", "No boot support"), + OPT_STR('\0', "hard-disk-boot", "Boot from hard disk"), + OPT_STR('\0', "boot-load-segment", "Boot load segment"), + + { .name = NULL } + }; + fsopts->fs_specific = diskStructure; + fsopts->fs_options = copy_opts(cd9660_options); cd9660_set_defaults(diskStructure); } @@ -265,6 +328,7 @@ void cd9660_cleanup_opts(fsinfo_t *fsopts) { free(fsopts->fs_specific); + free(fsopts->fs_options); } static int @@ -301,144 +365,106 @@ cd9660_arguments_set_string(const char * int cd9660_parse_opts(const char *option, fsinfo_t *fsopts) { - char *var, *val; - int rv; + int rv, i; iso9660_disk *diskStructure = fsopts->fs_specific; - - /* Set up allowed options - integer options ONLY */ - option_t cd9660_options[] = { - { "l", &diskStructure->isoLevel, 1, 2, "ISO Level" }, - { "isolevel", &diskStructure->isoLevel, 1, 2, "ISO Level" }, - { "verbose", &diskStructure->verbose_level, 0, 2, - "Turns on verbose output" }, - { "v", &diskStructure->verbose_level, 0 , 2, - "Turns on verbose output"}, - { .name = NULL } - }; - - /* - * Todo : finish implementing this, and make a function that - * parses them - */ - /* - string_option_t cd9660_string_options[] = { - { "L", "Label", &diskStructure.primaryDescriptor.volume_id, 1, 32, "Disk Label", ISO_STRING_FILTER_DCHARS }, - { NULL } - } - */ + option_t *cd9660_options = fsopts->fs_options; + char buf[1024]; + const char *name, *desc; assert(option != NULL); if (debug & DEBUG_FS_PARSE_OPTS) printf("cd9660_parse_opts: got `%s'\n", option); - if ((var = strdup(option)) == NULL) - err(1, "allocating memory for copy of option string"); - rv = 1; - - val = strchr(var, '='); - if (val != NULL) - *val++ = '\0'; - - /* First handle options with no parameters */ - if (strcmp(var, "h") == 0) { - diskStructure->displayHelp = 1; - rv = 1; - } else if (CD9660_IS_COMMAND_ARG_DUAL(var, "S", "follow-symlinks")) { - /* this is not handled yet */ - diskStructure->follow_sym_links = 1; - rv = 1; - } else if (CD9660_IS_COMMAND_ARG_DUAL(var, "L", "label")) { - rv = cd9660_arguments_set_string(val, "Disk Label", 32, 'd', - diskStructure->primaryDescriptor.volume_id); - } else if (CD9660_IS_COMMAND_ARG_DUAL(var, "A", "applicationid")) { - rv = cd9660_arguments_set_string(val, "Application Identifier", 128, 'a', - diskStructure->primaryDescriptor.application_id); - } else if(CD9660_IS_COMMAND_ARG_DUAL(var, "P", "publisher")) { - rv = cd9660_arguments_set_string(val, "Publisher Identifier", - 128, 'a', diskStructure->primaryDescriptor.publisher_id); - } else if (CD9660_IS_COMMAND_ARG_DUAL(var, "p", "preparer")) { - rv = cd9660_arguments_set_string(val, "Preparer Identifier", - 128, 'a', diskStructure->primaryDescriptor.preparer_id); - } else if (CD9660_IS_COMMAND_ARG_DUAL(var, "V", "volumeid")) { - rv = cd9660_arguments_set_string(val, "Volume Set Identifier", - 128, 'a', diskStructure->primaryDescriptor.volume_set_id); - /* Boot options */ - } else if (CD9660_IS_COMMAND_ARG_DUAL(var, "B", "bootimage")) { - if (val == NULL) - warnx("error: The Boot Image parameter requires a valid boot information string"); - else - rv = cd9660_add_boot_disk(diskStructure, val); - } else if (CD9660_IS_COMMAND_ARG(var, "bootimagedir")) { - /* - * XXXfvdl this is unused. - */ - if (val == NULL) - errx(1, "error: The Boot Image Directory parameter" - " requires a directory name\n"); - else { - if ((diskStructure->boot_image_directory = - malloc(strlen(val) + 1)) == NULL) { - CD9660_MEM_ALLOC_ERROR("cd9660_parse_opts"); - exit(1); - } + i = set_option(cd9660_options, option, buf, sizeof(buf)); + if (i == -1) + return 0; - /* BIG TODO: Add the max length function here */ - cd9660_arguments_set_string(val, "Boot Image Directory", - 12 , 'd', diskStructure->boot_image_directory); - } - } else if (CD9660_IS_COMMAND_ARG_DUAL(var, "G", "generic-bootimage")) { - if (val == NULL) - warnx("error: The Boot Image parameter requires a valid boot information string"); - else - rv = cd9660_add_generic_bootimage(diskStructure, val); - } else if (CD9660_IS_COMMAND_ARG(var, "no-trailing-padding")) - diskStructure->include_padding_areas = 0; - /* RRIP */ - else if (CD9660_IS_COMMAND_ARG_DUAL(var, "R", "rockridge")) - diskStructure->rock_ridge_enabled = 1; - else if (CD9660_IS_COMMAND_ARG_DUAL(var, "A", "archimedes")) - diskStructure->archimedes_enabled = 1; - else if (CD9660_IS_COMMAND_ARG(var, "chrp-boot")) - diskStructure->chrp_boot = 1; - else if (CD9660_IS_COMMAND_ARG_DUAL(var, "K", "keep-bad-images")) - diskStructure->keep_bad_images = 1; - else if (CD9660_IS_COMMAND_ARG(var, "allow-deep-trees")) - diskStructure->allow_deep_trees = 1; - else if (CD9660_IS_COMMAND_ARG(var, "allow-max-name")) - diskStructure->allow_max_name = 1; - else if (CD9660_IS_COMMAND_ARG(var, "allow-illegal-chars")) - diskStructure->allow_illegal_chars = 1; - else if (CD9660_IS_COMMAND_ARG(var, "allow-lowercase")) - diskStructure->allow_lowercase = 1; - else if (CD9660_IS_COMMAND_ARG(var,"allow-multidot")) - diskStructure->allow_multidot = 1; - else if (CD9660_IS_COMMAND_ARG(var, "omit-trailing-period")) - diskStructure->omit_trailing_period = 1; - else if (CD9660_IS_COMMAND_ARG(var, "no-emul-boot") || - CD9660_IS_COMMAND_ARG(var, "no-boot") || - CD9660_IS_COMMAND_ARG(var, "hard-disk-boot")) { - cd9660_eltorito_add_boot_option(diskStructure, var, 0); - - /* End of flag variables */ - } else if (CD9660_IS_COMMAND_ARG(var, "boot-load-segment")) { - if (val == NULL) { - warnx("Option `%s' doesn't contain a value", var); + if (cd9660_options[i].name == NULL) + abort(); + + name = cd9660_options[i].name; + desc = cd9660_options[i].desc; + switch (cd9660_options[i].letter) { + case 'h': + case 'S': + rv = 0; /* this is not handled yet */ + break; + case 'L': + rv = cd9660_arguments_set_string(buf, desc, 32, 'd', + diskStructure->primaryDescriptor.volume_id); + break; + case 'A': + rv = cd9660_arguments_set_string(buf, desc, 128, 'a', + diskStructure->primaryDescriptor.application_id); + break; + case 'P': + rv = cd9660_arguments_set_string(buf, desc, 128, 'a', + diskStructure->primaryDescriptor.publisher_id); + break; + case 'p': + rv = cd9660_arguments_set_string(buf, desc, 128, 'a', + diskStructure->primaryDescriptor.preparer_id); + break; + case 'V': + rv = cd9660_arguments_set_string(buf, desc, 128, 'a', + diskStructure->primaryDescriptor.volume_set_id); + break; + /* Boot options */ + case 'B': + if (buf[0] == '\0') { + warnx("The Boot Image parameter requires a valid boot" + "information string"); rv = 0; - } else { - cd9660_eltorito_add_boot_option(diskStructure, var, - val); - } - } else { - if (val == NULL) { - warnx("Option `%s' doesn't contain a value", var); + } else + rv = cd9660_add_boot_disk(diskStructure, buf); + break; + case 'G': + if (buf[0] == '\0') { + warnx("The Generic Boot Image parameter requires a" + " valid boot information string"); rv = 0; } else - rv = set_option(cd9660_options, var, val); + rv = cd9660_add_generic_bootimage(diskStructure, buf); + break; + default: + if (strcmp(name, "bootimagedir") == 0) { + /* + * XXXfvdl this is unused. + */ + if (buf[0] == '\0') { + warnx("The Boot Image Directory parameter" + " requires a directory name\n"); + rv = 0; + } else { + diskStructure->boot_image_directory = + malloc(strlen(buf) + 1); + if (diskStructure->boot_image_directory == NULL) + err(1, "malloc"); + /* BIG TODO: Add the max length function here */ + rv = cd9660_arguments_set_string(buf, desc, 12, + 'd', diskStructure->boot_image_directory); + } + } else if (strcmp(name, "no-emul-boot") == 0 || + strcmp(name, "no-boot") == 0 || + strcmp(name, "hard-disk-boot") == 0) { + /* RRIP */ + cd9660_eltorito_add_boot_option(diskStructure, name, 0); + rv = 1; + } else if (strcmp(name, "boot-load-segment") == 0) { + if (buf[0] == '\0') { + warnx("Option `%s' doesn't contain a value", + name); + rv = 0; + } else { + cd9660_eltorito_add_boot_option(diskStructure, + name, buf); + rv = 1; + } + } else + rv = 1; } - - free(var); - return (rv); + return rv; } /* Modified: head/usr.sbin/makefs/cd9660.h ============================================================================== --- head/usr.sbin/makefs/cd9660.h Wed Mar 15 11:16:26 2017 (r315303) +++ head/usr.sbin/makefs/cd9660.h Wed Mar 15 13:34:51 2017 (r315304) @@ -120,12 +120,6 @@ typedef struct { #define CD9660_MEM_ALLOC_ERROR(_F) \ err(EXIT_FAILURE, "%s, %s l. %d", _F, __FILE__, __LINE__) -#define CD9660_IS_COMMAND_ARG_DUAL(var,short,long)\ - (strcmp((var),(short)) == 0) || (strcmp((var),(long))==0) - -#define CD9660_IS_COMMAND_ARG(var,arg)\ - (strcmp((var),(arg)) == 0) - #define CD9660_TYPE_FILE 0x01 #define CD9660_TYPE_DIR 0x02 #define CD9660_TYPE_DOT 0x04 Modified: head/usr.sbin/makefs/ffs.c ============================================================================== --- head/usr.sbin/makefs/ffs.c Wed Mar 15 11:16:26 2017 (r315303) +++ head/usr.sbin/makefs/ffs.c Wed Mar 15 13:34:51 2017 (r315304) @@ -144,7 +144,6 @@ static void *ffs_build_dinode2(struct u int sectorsize; /* XXX: for buf.c::getblk() */ - /* publicly visible functions */ void @@ -155,7 +154,33 @@ ffs_prep_opts(fsinfo_t *fsopts) if ((ffs_opts = calloc(1, sizeof(ffs_opt_t))) == NULL) err(1, "Allocating memory for ffs_options"); - fsopts->fs_specific = ffs_opts; + const option_t ffs_options[] = { + { 'b', "bsize", &ffs_opts->bsize, OPT_INT32, + 1, INT_MAX, "block size" }, + { 'f', "fsize", &ffs_opts->fsize, OPT_INT32, + 1, INT_MAX, "fragment size" }, + { 'd', "density", &ffs_opts->density, OPT_INT32, + 1, INT_MAX, "bytes per inode" }, + { 'm', "minfree", &ffs_opts->minfree, OPT_INT32, + 0, 99, "minfree" }, + { 'M', "maxbpg", &ffs_opts->maxbpg, OPT_INT32, + 1, INT_MAX, "max blocks per file in a cg" }, + { 'a', "avgfilesize", &ffs_opts->avgfilesize, OPT_INT32, + 1, INT_MAX, "expected average file size" }, + { 'n', "avgfpdir", &ffs_opts->avgfpdir, OPT_INT32, + 1, INT_MAX, "expected # of files per directory" }, + { 'x', "extent", &ffs_opts->maxbsize, OPT_INT32, + 1, INT_MAX, "maximum # extent size" }, + { 'g', "maxbpcg", &ffs_opts->maxblkspercg, OPT_INT32, + 1, INT_MAX, "max # of blocks per group" }, + { 'v', "version", &ffs_opts->version, OPT_INT32, + 1, 2, "UFS version" }, + { 'o', "optimization", NULL, OPT_STRBUF, + 0, 0, "Optimization (time|space)" }, + { 'l', "label", ffs_opts->label, OPT_STRARRAY, + 1, sizeof(ffs_opts->label), "UFS label" }, + { .name = NULL } + }; ffs_opts->bsize= -1; ffs_opts->fsize= -1; @@ -168,45 +193,25 @@ ffs_prep_opts(fsinfo_t *fsopts) ffs_opts->avgfilesize= -1; ffs_opts->avgfpdir= -1; ffs_opts->version = 1; + + fsopts->fs_specific = ffs_opts; + fsopts->fs_options = copy_opts(ffs_options); } void ffs_cleanup_opts(fsinfo_t *fsopts) { - if (fsopts->fs_specific) - free(fsopts->fs_specific); + free(fsopts->fs_specific); + free(fsopts->fs_options); } int ffs_parse_opts(const char *option, fsinfo_t *fsopts) { ffs_opt_t *ffs_opts = fsopts->fs_specific; + option_t *ffs_options = fsopts->fs_options; + char buf[1024]; - option_t ffs_options[] = { - { "bsize", &ffs_opts->bsize, 1, INT_MAX, - "block size" }, - { "fsize", &ffs_opts->fsize, 1, INT_MAX, - "fragment size" }, - { "density", &ffs_opts->density, 1, INT_MAX, - "bytes per inode" }, - { "minfree", &ffs_opts->minfree, 0, 99, - "minfree" }, - { "maxbpg", &ffs_opts->maxbpg, 1, INT_MAX, - "max blocks per file in a cg" }, - { "avgfilesize", &ffs_opts->avgfilesize,1, INT_MAX, - "expected average file size" }, - { "avgfpdir", &ffs_opts->avgfpdir, 1, INT_MAX, - "expected # of files per directory" }, - { "extent", &ffs_opts->maxbsize, 1, INT_MAX, - "maximum # extent size" }, - { "maxbpcg", &ffs_opts->maxblkspercg,1, INT_MAX, - "max # of blocks per group" }, - { "version", &ffs_opts->version, 1, 2, - "UFS version" }, - { .name = NULL } - }; - - char *var, *val; int rv; assert(option != NULL); @@ -216,36 +221,28 @@ ffs_parse_opts(const char *option, fsinf if (debug & DEBUG_FS_PARSE_OPTS) printf("ffs_parse_opts: got `%s'\n", option); - if ((var = strdup(option)) == NULL) - err(1, "Allocating memory for copy of option string"); - rv = 0; - - if ((val = strchr(var, '=')) == NULL) { - warnx("Option `%s' doesn't contain a value", var); - goto leave_ffs_parse_opts; - } - *val++ = '\0'; - - if (strcmp(var, "optimization") == 0) { - if (strcmp(val, "time") == 0) { + rv = set_option(ffs_options, option, buf, sizeof(buf)); + if (rv == -1) + return 0; + + if (ffs_options[rv].name == NULL) + abort(); + + switch (ffs_options[rv].letter) { + case 'o': + if (strcmp(buf, "time") == 0) { ffs_opts->optimization = FS_OPTTIME; - } else if (strcmp(val, "space") == 0) { + } else if (strcmp(buf, "space") == 0) { ffs_opts->optimization = FS_OPTSPACE; } else { - warnx("Invalid optimization `%s'", val); - goto leave_ffs_parse_opts; + warnx("Invalid optimization `%s'", buf); + return 0; } - rv = 1; - } else if (strcmp(var, "label") == 0) { - strlcpy(ffs_opts->label, val, sizeof(ffs_opts->label)); - rv = 1; - } else - rv = set_option(ffs_options, var, val); - - leave_ffs_parse_opts: - if (var) - free(var); - return (rv); + break; + default: + break; + } + return 1; } Modified: head/usr.sbin/makefs/makefs.c ============================================================================== --- head/usr.sbin/makefs/makefs.c Wed Mar 15 11:16:26 2017 (r315303) +++ head/usr.sbin/makefs/makefs.c Wed Mar 15 13:34:51 2017 (r315304) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <time.h> #include <unistd.h> +#include <stdbool.h> #include "makefs.h" #include "mtree.h" @@ -82,7 +83,7 @@ struct stat stampst; static fstype_t *get_fstype(const char *); static int get_tstamp(const char *, struct stat *); -static void usage(void); +static void usage(fstype_t *, fsinfo_t *); int main(int, char *[]); int @@ -141,7 +142,7 @@ main(int argc, char *argv[]) #endif } else { warnx("Invalid endian `%s'.", optarg); - usage(); + usage(fstype, &fsoptions); } break; @@ -210,7 +211,7 @@ main(int argc, char *argv[]) if (*p == '\0') errx(1, "Empty option"); if (! fstype->parse_options(p, &fsoptions)) - usage(); + usage(fstype, &fsoptions); } break; } @@ -263,7 +264,7 @@ main(int argc, char *argv[]) case '?': default: - usage(); + usage(fstype, &fsoptions); /* NOTREACHED */ } @@ -278,7 +279,7 @@ main(int argc, char *argv[]) argv += optind; if (argc < 2) - usage(); + usage(fstype, &fsoptions); /* -x must be accompanied by -F */ if (fsoptions.onlyspec != 0 && specfile == NULL) @@ -344,21 +345,84 @@ main(int argc, char *argv[]) /* NOTREACHED */ } +int +set_option(const option_t *options, const char *option, char *buf, size_t len) +{ + char *var, *val; + int retval; + + assert(option != NULL); + + if ((var = strdup(option)) == NULL) { + err(EXIT_FAILURE, "Allocating memory for copy of option string"); + } + + for (val = var; *val; val++) + if (*val == '=') { + *val++ = '\0'; + break; + } + retval = set_option_var(options, var, val, buf, len); + free(var); + return retval; +} int -set_option(option_t *options, const char *var, const char *val) +set_option_var(const option_t *options, const char *var, const char *val, + char *buf, size_t len) { - int i; + char *s; + size_t i; + +#define NUM(type) \ + if (!*val) { \ + *(type *)options[i].value = 1; \ + break; \ + } \ + *(type *)options[i].value = (type)strsuftoll(options[i].desc, val, \ + options[i].minimum, options[i].maximum); break for (i = 0; options[i].name != NULL; i++) { - if (strcmp(options[i].name, var) != 0) + if (var[1] == '\0') { + if (options[i].letter != var[0]) + continue; + } else if (strcmp(options[i].name, var) != 0) continue; - *options[i].value = (int)strsuftoll(options[i].desc, val, - options[i].minimum, options[i].maximum); - return (1); + switch (options[i].type) { + case OPT_BOOL: + *(bool *)options[i].value = 1; + break; + case OPT_STRARRAY: + strlcpy((void *)options[i].value, val, (size_t) + options[i].maximum); + break; + case OPT_STRPTR: + if ((s = strdup(val)) == NULL) + err(1, NULL); + *(char **)options[i].value = s; + break; + case OPT_STRBUF: + if (buf == NULL) + abort(); + strlcpy(buf, val, len); + break; + case OPT_INT64: + NUM(uint64_t); + case OPT_INT32: + NUM(uint32_t); + case OPT_INT16: + NUM(uint16_t); + case OPT_INT8: + NUM(uint8_t); + default: + warnx("Unknown type %d in option %s", options[i].type, + val); + return 0; + } + return i; } warnx("Unknown option `%s'", var); - return (0); + return -1; } @@ -373,6 +437,20 @@ get_fstype(const char *type) return (NULL); } +option_t * +copy_opts(const option_t *o) +{ + size_t i; + void *rv; + + for (i = 0; o[i].name; i++) + continue; + i++; + if ((rv = calloc(i, sizeof(*o))) == NULL) + err(1, "calloc"); + return memcpy(rv, o, i * sizeof(*o)); +} + static int get_tstamp(const char *b, struct stat *st) { @@ -400,17 +478,29 @@ get_tstamp(const char *b, struct stat *s } static void -usage(void) +usage(fstype_t *fstype, fsinfo_t *fsoptions) { const char *prog; prog = getprogname(); fprintf(stderr, -"usage: %s [-xZ] [-B endian] [-b free-blocks] [-d debug-mask]\n" +"Usage: %s [-xZ] [-B endian] [-b free-blocks] [-d debug-mask]\n" "\t[-F mtree-specfile] [-f free-files] [-M minimum-size] [-m maximum-size]\n" "\t[-N userdb-dir] [-o fs-options] [-R roundup-size] [-S sector-size]\n" "\t[-s image-size] [-T <timestamp/file>] [-t fs-type]\n" "\timage-file directory | manifest [extra-directory ...]\n", prog); + + if (fstype) { + size_t i; + option_t *o = fsoptions->fs_options; + + fprintf(stderr, "\n%s specific options:\n", fstype->type); + for (i = 0; o[i].name != NULL; i++) + fprintf(stderr, "\t%c%c%20.20s\t%s\n", + o[i].letter ? o[i].letter : ' ', + o[i].letter ? ',' : ' ', + o[i].name, o[i].desc); + } exit(1); } Modified: head/usr.sbin/makefs/makefs.h ============================================================================== --- head/usr.sbin/makefs/makefs.h Wed Mar 15 11:16:26 2017 (r315303) +++ head/usr.sbin/makefs/makefs.h Wed Mar 15 13:34:51 2017 (r315304) @@ -104,11 +104,37 @@ typedef struct _fsnode { #define FSNODE_F_OPTIONAL 0x02 /* fsnode is optional */ /* + * option_t - contains option name, description, pointer to location to store + * result, and range checks for the result. Used to simplify fs specific + * option setting + */ +typedef enum { + OPT_STRARRAY, + OPT_STRPTR, + OPT_STRBUF, + OPT_BOOL, + OPT_INT8, + OPT_INT16, + OPT_INT32, + OPT_INT64 +} opttype_t; + +typedef struct { + char letter; /* option letter NUL for none */ + const char *name; /* option name */ + void *value; /* where to stuff the value */ + opttype_t type; /* type of entry */ + long long minimum; /* minimum for value */ + long long maximum; /* maximum for value */ + const char *desc; /* option description */ +} option_t; + +/* * fsinfo_t - contains various settings and parameters pertaining to * the image, including current settings, global options, and fs * specific options */ -typedef struct { +typedef struct makefs_fsinfo { /* current settings */ off_t size; /* total size */ off_t inodes; /* number of inodes */ @@ -124,8 +150,8 @@ typedef struct { off_t minsize; /* minimum size image should be */ off_t maxsize; /* maximum size image can be */ off_t freefiles; /* free file entries to leave */ - int freefilepc; /* free file % */ off_t freeblocks; /* free blocks to leave */ + int freefilepc; /* free file % */ int freeblockpc; /* free block % */ int needswap; /* non-zero if byte swapping needed */ int sectorsize; /* sector size */ @@ -133,30 +159,20 @@ typedef struct { off_t roundup; /* round image size up to this value */ void *fs_specific; /* File system specific additions. */ + option_t *fs_options; /* File system specific options */ } fsinfo_t; -/* - * option_t - contains option name, description, pointer to location to store - * result, and range checks for the result. Used to simplify fs specific - * option setting - */ -typedef struct { - const char *name; /* option name */ - int *value; /* where to stuff the value */ - int minimum; /* minimum for value */ - int maximum; /* maximum for value */ - const char *desc; /* option description */ -} option_t; - - void apply_specfile(const char *, const char *, fsnode *, int); void dump_fsnodes(fsnode *); const char * inode_type(mode_t); fsnode * read_mtree(const char *, fsnode *); -int set_option(option_t *, const char *, const char *); +int set_option(const option_t *, const char *, char *, size_t); +int set_option_var(const option_t *, const char *, const char *, + char *, size_t); fsnode * walk_dir(const char *, const char *, fsnode *, fsnode *); void free_fsnodes(fsnode *); +option_t * copy_opts(const option_t *); #define DECLARE_FUN(fs) \ void fs ## _prep_opts(fsinfo_t *); \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703151334.v2FDYqY8057248>