summaryrefslogtreecommitdiffstats
path: root/sbin/geom/core
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2010-09-13 13:59:28 +0000
committerpjd <pjd@FreeBSD.org>2010-09-13 13:59:28 +0000
commitec902e91d572923f633e4ae16f50a57385f50a27 (patch)
tree905b6532fa37aa9fb4912c18fa459cd73971d77b /sbin/geom/core
parent3d8ce965d3cc7199c39bd29a375291b4276bab53 (diff)
downloadFreeBSD-src-ec902e91d572923f633e4ae16f50a57385f50a27.zip
FreeBSD-src-ec902e91d572923f633e4ae16f50a57385f50a27.tar.gz
Add G_TYPE_MULTI flag, which when set for the given option, will
allow the option to be specified multiple times. This will help to implement things like passing multiple keyfiles to geli(8) instead of cat(1)ing them all into stdin and reading from there using one '-k -' option.
Diffstat (limited to 'sbin/geom/core')
-rw-r--r--sbin/geom/core/geom.c40
-rw-r--r--sbin/geom/core/geom.h6
2 files changed, 40 insertions, 6 deletions
diff --git a/sbin/geom/core/geom.c b/sbin/geom/core/geom.c
index 4a3dcd4..39731e9 100644
--- a/sbin/geom/core/geom.c
+++ b/sbin/geom/core/geom.c
@@ -234,9 +234,31 @@ find_option(struct g_command *cmd, char ch)
static void
set_option(struct gctl_req *req, struct g_option *opt, const char *val)
{
+ const char *optname;
uint64_t number;
void *ptr;
+ if (G_OPT_ISMULTI(opt)) {
+ size_t optnamesize;
+
+ if (G_OPT_NUM(opt) == UCHAR_MAX)
+ errx(EXIT_FAILURE, "Too many -%c options.", opt->go_char);
+
+ /*
+ * Base option name length plus 3 bytes for option number
+ * (max. 255 options) plus 1 byte for terminating '\0'.
+ */
+ optnamesize = strlen(opt->go_name) + 3 + 1;
+ ptr = malloc(optnamesize);
+ if (ptr == NULL)
+ errx(EXIT_FAILURE, "No memory.");
+ snprintf(ptr, optnamesize, "%s%u", opt->go_name, G_OPT_NUM(opt));
+ G_OPT_NUMINC(opt);
+ optname = ptr;
+ } else {
+ optname = opt->go_name;
+ }
+
if (G_OPT_TYPE(opt) == G_TYPE_NUMBER ||
G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
if (expand_number(val, &number) == -1) {
@@ -249,27 +271,30 @@ set_option(struct gctl_req *req, struct g_option *opt, const char *val)
errx(EXIT_FAILURE, "No memory.");
*(intmax_t *)ptr = number;
opt->go_val = ptr;
- gctl_ro_param(req, opt->go_name, sizeof(intmax_t),
+ gctl_ro_param(req, optname, sizeof(intmax_t),
opt->go_val);
} else {
asprintf((void *)(&ptr), "%jd", number);
if (ptr == NULL)
errx(EXIT_FAILURE, "No memory.");
opt->go_val = ptr;
- gctl_ro_param(req, opt->go_name, -1, opt->go_val);
+ gctl_ro_param(req, optname, -1, opt->go_val);
}
} else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
- gctl_ro_param(req, opt->go_name, -1, val);
+ gctl_ro_param(req, optname, -1, val);
} else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
ptr = malloc(sizeof(int));
if (ptr == NULL)
errx(EXIT_FAILURE, "No memory.");
*(int *)ptr = *val - '0';
opt->go_val = ptr;
- gctl_ro_param(req, opt->go_name, sizeof(int), opt->go_val);
+ gctl_ro_param(req, optname, sizeof(int), opt->go_val);
} else {
assert(!"Invalid type");
}
+
+ if (G_OPT_ISMULTI(opt))
+ free(__DECONST(char *, optname));
}
/*
@@ -294,7 +319,10 @@ parse_arguments(struct g_command *cmd, struct gctl_req *req, int *argc,
if (opt->go_name == NULL)
break;
assert(G_OPT_TYPE(opt) != 0);
- assert((opt->go_type & ~G_TYPE_MASK) == 0);
+ assert((opt->go_type & ~(G_TYPE_MASK | G_TYPE_MULTI)) == 0);
+ /* Multiple bool arguments makes no sense. */
+ assert(G_OPT_TYPE(opt) != G_TYPE_BOOL ||
+ (opt->go_type & G_TYPE_MULTI) == 0);
strlcatf(opts, sizeof(opts), "%c", opt->go_char);
if (G_OPT_TYPE(opt) != G_TYPE_BOOL)
strlcat(opts, ":", sizeof(opts));
@@ -314,7 +342,7 @@ parse_arguments(struct g_command *cmd, struct gctl_req *req, int *argc,
opt = find_option(cmd, ch);
if (opt == NULL)
usage();
- if (G_OPT_ISDONE(opt)) {
+ if (!G_OPT_ISMULTI(opt) && G_OPT_ISDONE(opt)) {
warnx("Option '%c' specified twice.", opt->go_char);
usage();
}
diff --git a/sbin/geom/core/geom.h b/sbin/geom/core/geom.h
index 92c97a3..c88005e 100644
--- a/sbin/geom/core/geom.h
+++ b/sbin/geom/core/geom.h
@@ -41,11 +41,17 @@
#define G_TYPE_ASCNUM 0x04
#define G_TYPE_MASK 0x0f
#define G_TYPE_DONE 0x10
+#define G_TYPE_MULTI 0x20
+#define G_TYPE_NUMMASK 0xff00
+#define G_TYPE_NUMSHIFT 8
#define G_OPT_MAX 16
#define G_OPT_DONE(opt) do { (opt)->go_type |= G_TYPE_DONE; } while (0)
#define G_OPT_ISDONE(opt) ((opt)->go_type & G_TYPE_DONE)
+#define G_OPT_ISMULTI(opt) ((opt)->go_type & G_TYPE_MULTI)
#define G_OPT_TYPE(opt) ((opt)->go_type & G_TYPE_MASK)
+#define G_OPT_NUM(opt) (((opt)->go_type & G_TYPE_NUMMASK) >> G_TYPE_NUMSHIFT)
+#define G_OPT_NUMINC(opt) ((opt)->go_type += (1 << G_TYPE_NUMSHIFT))
#define G_OPT_SENTINEL { '\0', NULL, NULL, G_TYPE_NONE }
#define G_NULL_OPTS { G_OPT_SENTINEL }
OpenPOWER on IntegriCloud