svn commit: r212555 - head/sbin/geom/core

Pawel Jakub Dawidek pjd at FreeBSD.org
Mon Sep 13 13:59:28 UTC 2010


Author: pjd
Date: Mon Sep 13 13:59:28 2010
New Revision: 212555
URL: http://svn.freebsd.org/changeset/base/212555

Log:
  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.

Modified:
  head/sbin/geom/core/geom.c
  head/sbin/geom/core/geom.h

Modified: head/sbin/geom/core/geom.c
==============================================================================
--- head/sbin/geom/core/geom.c	Mon Sep 13 13:48:18 2010	(r212554)
+++ head/sbin/geom/core/geom.c	Mon Sep 13 13:59:28 2010	(r212555)
@@ -234,9 +234,31 @@ find_option(struct g_command *cmd, char 
 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 
 				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, s
 		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, s
 		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();
 		}

Modified: head/sbin/geom/core/geom.h
==============================================================================
--- head/sbin/geom/core/geom.h	Mon Sep 13 13:48:18 2010	(r212554)
+++ head/sbin/geom/core/geom.h	Mon Sep 13 13:59:28 2010	(r212555)
@@ -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 }


More information about the svn-src-all mailing list