aboutsummaryrefslogtreecommitdiffstats
path: root/sbin/geom/misc
diff options
context:
space:
mode:
authorAndrey V. Elsukov <ae@FreeBSD.org>2010-06-21 08:24:50 +0000
committerAndrey V. Elsukov <ae@FreeBSD.org>2010-06-21 08:24:50 +0000
commit79d89bb0aba0ca54d28e7a881f0b78bed7d65c7b (patch)
tree9dd1dea00f2542fb485d8c429ca1f7be1c43fd76 /sbin/geom/misc
parent875b8844bec77f4cf470344741bd05524f0d41a9 (diff)
downloadsrc-79d89bb0aba0ca54d28e7a881f0b78bed7d65c7b.tar.gz
src-79d89bb0aba0ca54d28e7a881f0b78bed7d65c7b.zip
Remove G_TYPE_ASCLBA type and replace it with G_TYPE_STRING in gpart.
Move code that converts params from humanized numbers to sectors count to subr.c and adjust comment. Add post-processing for "size" and "start offset" params in gpart, now they are properly converted to sectors count with known sector size that can be greater that 512 bytes. Also replace "unsigned long long" type to "off_t" for unify code since it used for medium size in libgeom(3) and DIOCGMEDIASIZE ioctl. PR: bin/146277 Reviewed by: marcel (previous version) Approved by: kib (mentor) MFC after: 1 month
Notes
Notes: svn path=/head/; revision=209388
Diffstat (limited to 'sbin/geom/misc')
-rw-r--r--sbin/geom/misc/subr.c90
-rw-r--r--sbin/geom/misc/subr.h1
2 files changed, 91 insertions, 0 deletions
diff --git a/sbin/geom/misc/subr.c b/sbin/geom/misc/subr.c
index e71ec7489b0c..7a4786fc87f2 100644
--- a/sbin/geom/misc/subr.c
+++ b/sbin/geom/misc/subr.c
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
+#include <limits.h>
+#include <inttypes.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
@@ -107,6 +109,94 @@ bitcount32(uint32_t x)
return (x);
}
+/*
+ * The size of a sector is context specific (i.e. determined by the
+ * media). 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. We should map the byte-oriented value into a sector-oriented
+ * value when we already know the sector size in bytes. At this time
+ * we can use g_parse_lba() function. It converts user specified
+ * value into sectors with following conditions:
+ * o Sectors size taken as argument from caller.
+ * 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.
+ *
+ */
+int
+g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors)
+{
+ off_t number, mult, unit;
+ char *s;
+
+ assert(lbastr != NULL);
+ assert(sectorsize > 0);
+ assert(sectors != NULL);
+
+ number = (off_t)strtoimax(lbastr, &s, 0);
+ if (s == lbastr)
+ return (EINVAL);
+
+ mult = 1;
+ unit = sectorsize;
+ 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 = sectorsize; /* sector */
+ break;
+ case 'b': case 'B':
+ unit = 1; /* bytes */
+ break;
+ default:
+ return (EINVAL);
+ }
+ s++;
+ if (*s != '\0')
+ return (EINVAL);
+done:
+ if (mult * unit < mult || number * mult * unit < number)
+ return (ERANGE);
+ number *= mult * unit;
+ if (number % sectorsize)
+ return (EINVAL);
+ number /= sectorsize;
+ *sectors = number;
+ return (0);
+}
+
off_t
g_get_mediasize(const char *name)
{
diff --git a/sbin/geom/misc/subr.h b/sbin/geom/misc/subr.h
index c3242a3bdc9b..2b43bdb60129 100644
--- a/sbin/geom/misc/subr.h
+++ b/sbin/geom/misc/subr.h
@@ -32,6 +32,7 @@
unsigned g_lcm(unsigned a, unsigned b);
uint32_t bitcount32(uint32_t x);
+int g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors);
off_t g_get_mediasize(const char *name);
unsigned g_get_sectorsize(const char *name);