svn commit: r193648 - in head/sbin/geom: class/part core

Marcel Moolenaar marcel at FreeBSD.org
Sun Jun 7 20:12:15 UTC 2009


Author: marcel
Date: Sun Jun  7 20:12:14 2009
New Revision: 193648
URL: http://svn.freebsd.org/changeset/base/193648

Log:
  Allow humanized numbers for LBAs, as well as partition indices for
  gpart(8). LBAs in particular are ugly. The ganularity is a sector,
  but users expect byte granularity when specifying the size or offset
  with a SI unit. Handle LBAs specially to deal with this.

Modified:
  head/sbin/geom/class/part/geom_part.c
  head/sbin/geom/core/geom.c
  head/sbin/geom/core/geom.h

Modified: head/sbin/geom/class/part/geom_part.c
==============================================================================
--- head/sbin/geom/class/part/geom_part.c	Sun Jun  7 20:02:32 2009	(r193647)
+++ head/sbin/geom/class/part/geom_part.c	Sun Jun  7 20:12:14 2009	(r193648)
@@ -68,10 +68,10 @@ static void gpart_show(struct gctl_req *
 
 struct g_command PUBSYM(class_commands)[] = {
 	{ "add", 0, gpart_issue, {
-		{ 'b', "start", NULL, G_TYPE_STRING },
-		{ 's', "size", NULL, G_TYPE_STRING },
+		{ 'b', "start", NULL, G_TYPE_ASCLBA },
+		{ 's', "size", NULL, G_TYPE_ASCLBA },
 		{ 't', "type", NULL, G_TYPE_STRING },
-		{ 'i', index_param, optional, G_TYPE_STRING },
+		{ 'i', index_param, optional, G_TYPE_ASCNUM },
 		{ 'l', "label", optional, G_TYPE_STRING },
 		{ 'f', "flags", flags, G_TYPE_STRING },
 		G_OPT_SENTINEL },
@@ -80,7 +80,7 @@ struct g_command PUBSYM(class_commands)[
 	{ "bootcode", 0, gpart_bootcode, {
 		{ 'b', bootcode_param, optional, G_TYPE_STRING },
 		{ 'p', partcode_param, optional, G_TYPE_STRING },
-		{ 'i', index_param, optional, G_TYPE_STRING },
+		{ 'i', index_param, optional, G_TYPE_ASCNUM },
 		{ 'f', "flags", flags, G_TYPE_STRING },
 		G_OPT_SENTINEL },
 	  "geom", NULL
@@ -88,13 +88,13 @@ struct g_command PUBSYM(class_commands)[
 	{ "commit", 0, gpart_issue, G_NULL_OPTS, "geom", NULL },
 	{ "create", 0, gpart_issue, {
 		{ 's', "scheme", NULL, G_TYPE_STRING },
-		{ 'n', "entries", optional, G_TYPE_STRING },
+		{ 'n', "entries", optional, G_TYPE_ASCNUM },
 		{ 'f', "flags", flags, G_TYPE_STRING },
 		G_OPT_SENTINEL },
 	  "provider", NULL
 	},
 	{ "delete", 0, gpart_issue, {
-		{ 'i', index_param, NULL, G_TYPE_STRING },
+		{ 'i', index_param, NULL, G_TYPE_ASCNUM },
 		{ 'f', "flags", flags, G_TYPE_STRING },
 		G_OPT_SENTINEL },
 	  "geom", NULL
@@ -104,7 +104,7 @@ struct g_command PUBSYM(class_commands)[
 		G_OPT_SENTINEL },
 	  "geom", NULL },
 	{ "modify", 0, gpart_issue, {
-		{ 'i', index_param, NULL, G_TYPE_STRING },
+		{ 'i', index_param, NULL, G_TYPE_ASCNUM },
 		{ 'l', "label", optional, G_TYPE_STRING },
 		{ 't', "type", optional, G_TYPE_STRING },
 		{ 'f', "flags", flags, G_TYPE_STRING },
@@ -113,7 +113,7 @@ struct g_command PUBSYM(class_commands)[
 	},
 	{ "set", 0, gpart_issue, {
 		{ 'a', "attrib", NULL, G_TYPE_STRING },
-		{ 'i', index_param, NULL, G_TYPE_STRING },
+		{ 'i', index_param, NULL, G_TYPE_ASCNUM },
 		{ 'f', "flags", flags, G_TYPE_STRING },
 		G_OPT_SENTINEL },
 	  "geom", NULL
@@ -127,7 +127,7 @@ struct g_command PUBSYM(class_commands)[
 	{ "undo", 0, gpart_issue, G_NULL_OPTS, "geom", NULL },
 	{ "unset", 0, gpart_issue, {
 		{ 'a', "attrib", NULL, G_TYPE_STRING },
-		{ 'i', index_param, NULL, G_TYPE_STRING },
+		{ 'i', index_param, NULL, G_TYPE_ASCNUM },
 		{ 'f', "flags", flags, G_TYPE_STRING },
 		G_OPT_SENTINEL },
 	  "geom", NULL

Modified: head/sbin/geom/core/geom.c
==============================================================================
--- head/sbin/geom/core/geom.c	Sun Jun  7 20:02:32 2009	(r193647)
+++ head/sbin/geom/core/geom.c	Sun Jun  7 20:12:14 2009	(r193648)
@@ -226,20 +226,117 @@ find_option(struct g_command *cmd, char 
 static void
 set_option(struct gctl_req *req, struct g_option *opt, const char *val)
 {
+	char *s;
+	intmax_t number;
 
-	if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
-		intmax_t number;
-
+	if (G_OPT_TYPE(opt) == G_TYPE_NUMBER ||
+	    G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
 		if (expand_number(val, &number) == -1) {
 			err(EXIT_FAILURE, "Invalid value for '%c' argument.",
 			    opt->go_char);
 		}
-		opt->go_val = malloc(sizeof(intmax_t));
+		if (G_OPT_TYPE(opt) == G_TYPE_NUMBER)
+			opt->go_val = malloc(sizeof(intmax_t));
+		else {
+			asprintf(&s, "%jd", number);
+			opt->go_val = s;
+		}
 		if (opt->go_val == NULL)
 			errx(EXIT_FAILURE, "No memory.");
-		*(intmax_t *)opt->go_val = number;
+		if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
+			*(intmax_t *)opt->go_val = number;
+			gctl_ro_param(req, opt->go_name, sizeof(intmax_t),
+			    opt->go_val);
+		} else
+			gctl_ro_param(req, opt->go_name, -1, opt->go_val);
+	} else if (G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
+		/*
+		 * LBAs are ugly. The argument is a sector. The size of a
+		 * sector is context specific (i.e. determined by the media),
+		 * which we don't know here. But when users enter a value
+		 * with a SI unit, they really mean the byte-size or byte-
+		 * offset and not the size or offset in sectors.
+		 * So how can we map the byte-oriented value into a sector-
+		 * oriented value if we don't know the sector size in bytes?
+		 * The approach taken here is:
+		 * o  Sectors are 512 bytes in size. Mostly the case anyway.
+		 * o  When no SI unit is specified the value is in sectors.
+		 * o  With an SI unit the value is in bytes.
+		 * o  The 'b' suffix forces byte interpretation and the 's'
+		 *    suffix forces sector interpretation.
+		 *
+		 * Thus:
+		 * o  2 and 2s mean 2 sectors, and 2b means 2 bytes.
+		 * o  4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors.
+		 *
+		 * "This seemed like a good idea at the time"
+		 */
+		intmax_t mult, unit;
 
-		gctl_ro_param(req, opt->go_name, sizeof(intmax_t), opt->go_val);
+		number = strtoimax(val, &s, 0);
+		if (s == val)
+			errc(EXIT_FAILURE, EINVAL, "argument '%c'",
+			    opt->go_char);
+		mult = 1;
+		unit = 512;	/* sector */
+		if (*s == '\0')
+			goto done;
+		switch (*s) {
+		case 'e': case 'E':
+			mult *= 1024;
+			/*FALLTHROUGH*/
+		case 'p': case 'P':
+			mult *= 1024;
+			/*FALLTHROUGH*/
+		case 't': case 'T':
+			mult *= 1024;
+			/*FALLTHROUGH*/
+		case 'g': case 'G':
+			mult *= 1024;
+			/*FALLTHROUGH*/
+		case 'm': case 'M':
+			mult *= 1024;
+			/*FALLTHROUGH*/
+		case 'k': case 'K':
+			mult *= 1024;
+			break;
+		default:
+			goto sfx;
+		}
+		unit = 1;	/* bytes */
+		s++;
+		if (*s == '\0')
+			goto done;
+sfx:
+		switch (*s) {
+		case 's': case 'S':
+			unit = 512;	/* sector */
+			break;
+		case 'b': case 'B':
+			unit = 1;	/* bytes */
+			break;
+		default:
+			errc(EXIT_FAILURE, EINVAL, "argument '%c': suffix '%c'",
+			    opt->go_char, *s);
+		}
+		s++;
+		if (*s != '\0')
+			errx(EXIT_FAILURE, "argument '%c': junk at end (%s)",
+			    opt->go_char, s);
+done:
+		if (mult * unit < mult || number * mult * unit < number)
+			errc(EXIT_FAILURE, ERANGE, "argument '%c'",
+			    opt->go_char);
+		number *= mult * unit;
+		if (number % 512)
+			errx(EXIT_FAILURE, "argument '%c': "
+			    "not a valid block address", opt->go_char);
+		number /= 512;
+		asprintf(&s, "%jd", number);
+		if (s == NULL)
+			err(EXIT_FAILURE, NULL);
+		opt->go_val = s;
+		gctl_ro_param(req, opt->go_name, -1, s);
 	} else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
 		gctl_ro_param(req, opt->go_name, -1, val);
 	} else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
@@ -247,9 +344,7 @@ set_option(struct gctl_req *req, struct 
 		if (opt->go_val == NULL)
 			errx(EXIT_FAILURE, "No memory.");
 		*(int *)opt->go_val = *val - '0';
-
-		gctl_ro_param(req, opt->go_name, sizeof(int),
-		    opt->go_val);
+		gctl_ro_param(req, opt->go_name, sizeof(int), opt->go_val);
 	} else {
 		assert(!"Invalid type");
 	}
@@ -333,7 +428,9 @@ parse_arguments(struct g_command *cmd, s
 				if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
 					gctl_ro_param(req, opt->go_name,
 					    sizeof(intmax_t), opt->go_val);
-				} else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
+				} else if (G_OPT_TYPE(opt) == G_TYPE_STRING ||
+				    G_OPT_TYPE(opt) == G_TYPE_ASCNUM ||
+				    G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
 					if (cmd->gc_argname == NULL ||
 					    opt->go_val == NULL ||
 					    *(char *)opt->go_val != '\0')

Modified: head/sbin/geom/core/geom.h
==============================================================================
--- head/sbin/geom/core/geom.h	Sun Jun  7 20:02:32 2009	(r193647)
+++ head/sbin/geom/core/geom.h	Sun Jun  7 20:12:14 2009	(r193648)
@@ -28,7 +28,7 @@
 
 #ifndef _GEOM_H_
 #define	_GEOM_H_
-#define	G_LIB_VERSION	3
+#define	G_LIB_VERSION	4
 
 #define	G_FLAG_NONE	0x0000
 #define	G_FLAG_VERBOSE	0x0001
@@ -38,7 +38,9 @@
 #define	G_TYPE_BOOL	0x01
 #define	G_TYPE_STRING	0x02
 #define	G_TYPE_NUMBER	0x03
-#define	G_TYPE_MASK	0x03
+#define	G_TYPE_ASCNUM	0x04
+#define	G_TYPE_ASCLBA	0x05
+#define	G_TYPE_MASK	0x0f
 #define	G_TYPE_DONE	0x10
 
 #define	G_OPT_MAX	16


More information about the svn-src-head mailing list