summaryrefslogtreecommitdiffstats
path: root/lib/libutil/expand_number.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutil/expand_number.c')
-rw-r--r--lib/libutil/expand_number.c47
1 files changed, 24 insertions, 23 deletions
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);
}
OpenPOWER on IntegriCloud