From owner-svn-src-all@FreeBSD.ORG Mon Sep 13 13:59:28 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AAC8A1065672; Mon, 13 Sep 2010 13:59:28 +0000 (UTC) (envelope-from pjd@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 98A3D8FC15; Mon, 13 Sep 2010 13:59:28 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o8DDxS5M004701; Mon, 13 Sep 2010 13:59:28 GMT (envelope-from pjd@svn.freebsd.org) Received: (from pjd@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o8DDxSLm004698; Mon, 13 Sep 2010 13:59:28 GMT (envelope-from pjd@svn.freebsd.org) Message-Id: <201009131359.o8DDxSLm004698@svn.freebsd.org> From: Pawel Jakub Dawidek Date: Mon, 13 Sep 2010 13:59:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212555 - head/sbin/geom/core X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Sep 2010 13:59:28 -0000 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 }