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
This commit is contained in:
parent
ce9f323727
commit
776c68249b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315304
@ -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 *val, const char *fieldtitle, int length,
|
||||
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;
|
||||
i = set_option(cd9660_options, option, buf, sizeof(buf));
|
||||
if (i == -1)
|
||||
return 0;
|
||||
|
||||
val = strchr(var, '=');
|
||||
if (val != NULL)
|
||||
*val++ = '\0';
|
||||
if (cd9660_options[i].name == NULL)
|
||||
abort();
|
||||
|
||||
/* 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);
|
||||
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 */
|
||||
} 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
rv = 0;
|
||||
} else {
|
||||
cd9660_eltorito_add_boot_option(diskStructure, var,
|
||||
val);
|
||||
}
|
||||
} else {
|
||||
if (val == NULL) {
|
||||
warnx("Option `%s' doesn't contain a value", var);
|
||||
case 'B':
|
||||
if (buf[0] == '\0') {
|
||||
warnx("The Boot Image parameter requires a valid boot"
|
||||
"information string");
|
||||
rv = 0;
|
||||
} else
|
||||
rv = set_option(cd9660_options, var, val);
|
||||
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 = 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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -144,7 +144,6 @@ static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *,
|
||||
|
||||
|
||||
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, fsinfo_t *fsopts)
|
||||
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;
|
||||
rv = set_option(ffs_options, option, buf, sizeof(buf));
|
||||
if (rv == -1)
|
||||
return 0;
|
||||
|
||||
if ((val = strchr(var, '=')) == NULL) {
|
||||
warnx("Option `%s' doesn't contain a value", var);
|
||||
goto leave_ffs_parse_opts;
|
||||
}
|
||||
*val++ = '\0';
|
||||
if (ffs_options[rv].name == NULL)
|
||||
abort();
|
||||
|
||||
if (strcmp(var, "optimization") == 0) {
|
||||
if (strcmp(val, "time") == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 *st)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -103,12 +103,38 @@ typedef struct _fsnode {
|
||||
#define FSNODE_F_HASSPEC 0x01 /* fsnode has a spec entry */
|
||||
#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 *); \
|
||||
|
Loading…
Reference in New Issue
Block a user