diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libutil/expand_number.3 | 6 | ||||
-rw-r--r-- | lib/libutil/expand_number.c | 47 |
2 files changed, 27 insertions, 26 deletions
diff --git a/lib/libutil/expand_number.3 b/lib/libutil/expand_number.3 index 23e488d..f78223b 100644 --- a/lib/libutil/expand_number.3 +++ b/lib/libutil/expand_number.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 16, 2007 +.Dd August 15, 2010 .Dt EXPAND_NUMBER 3 .Os .Sh NAME @@ -37,14 +37,14 @@ .In libutil.h .Ft int .Fo expand_number -.Fa "const char *buf" "int64_t *num" +.Fa "const char *buf" "uint64_t *num" .Fc .Sh DESCRIPTION The .Fn expand_number function unformats the .Fa buf -string and stores a signed 64-bit quantity at address pointed out by the +string and stores a unsigned 64-bit quantity at address pointed out by the .Fa num argument. .Pp diff --git a/lib/libutil/expand_number.c b/lib/libutil/expand_number.c index 30a292e..5d55884 100644 --- a/lib/libutil/expand_number.c +++ b/lib/libutil/expand_number.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #include <stdint.h> /* - * Convert an expression of the following forms to a int64_t. + * Convert an expression of the following forms to a uint64_t. * 1) A positive decimal number. * 2) A positive decimal number followed by a 'b' or 'B' (mult by 1). * 3) A positive decimal number followed by a 'k' or 'K' (mult by 1 << 10). @@ -50,6 +50,7 @@ int expand_number(const char *buf, uint64_t *num) { uint64_t number; + unsigned shift; char *endptr; number = strtoumax(buf, &endptr, 0); @@ -60,41 +61,41 @@ expand_number(const char *buf, uint64_t *num) return (-1); } - if (*endptr == '\0') { - /* No unit. */ - *num = number; - return (0); - } - -#define SHIFT(n, b) \ - do { if (((n << b) >> b) != n) goto overflow; n <<= b; } while (0) - switch (tolower((unsigned char)*endptr)) { case 'e': - SHIFT(number, 10); + shift = 60; + break; case 'p': - SHIFT(number, 10); + shift = 50; + break; case 't': - SHIFT(number, 10); + shift = 40; + break; case 'g': - SHIFT(number, 10); + shift = 30; + break; case 'm': - SHIFT(number, 10); + shift = 20; + break; case 'k': - SHIFT(number, 10); - case 'b': + shift = 10; break; + case 'b': + case '\0': /* No unit. */ + *num = number; + return (0); default: /* Unrecognized unit. */ errno = EINVAL; return (-1); } - *num = number; - return (0); + if ((number << shift) >> shift != number) { + /* Overflow */ + errno = ERANGE; + return (-1); + } -overflow: - /* Overflow */ - errno = ERANGE; - return (-1); + *num = number << shift; + return (0); } |