diff options
author | Andrey V. Elsukov <ae@FreeBSD.org> | 2010-06-21 08:24:50 +0000 |
---|---|---|
committer | Andrey V. Elsukov <ae@FreeBSD.org> | 2010-06-21 08:24:50 +0000 |
commit | 79d89bb0aba0ca54d28e7a881f0b78bed7d65c7b (patch) | |
tree | 9dd1dea00f2542fb485d8c429ca1f7be1c43fd76 /sbin/geom/misc | |
parent | 875b8844bec77f4cf470344741bd05524f0d41a9 (diff) | |
download | src-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.c | 90 | ||||
-rw-r--r-- | sbin/geom/misc/subr.h | 1 |
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); |