aboutsummaryrefslogtreecommitdiff
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.c49
1 files changed, 44 insertions, 5 deletions
diff --git a/lib/libutil/expand_number.c b/lib/libutil/expand_number.c
index f4c19d7867a3..a3313ba39d98 100644
--- a/lib/libutil/expand_number.c
+++ b/lib/libutil/expand_number.c
@@ -37,13 +37,12 @@
#include <stdbool.h>
#include <stdint.h>
-int
-expand_number(const char *buf, int64_t *num)
+static int
+expand_impl(const char *buf, uint64_t *num, bool *neg)
{
char *endptr;
uintmax_t number;
unsigned int shift;
- bool neg;
int serrno;
/*
@@ -52,10 +51,10 @@ expand_number(const char *buf, int64_t *num)
while (isspace((unsigned char)*buf))
buf++;
if (*buf == '-') {
- neg = true;
+ *neg = true;
buf++;
} else {
- neg = false;
+ *neg = false;
if (*buf == '+')
buf++;
}
@@ -127,6 +126,22 @@ expand_number(const char *buf, int64_t *num)
}
number <<= shift;
+ *num = number;
+ return (0);
+}
+
+int
+(expand_number)(const char *buf, int64_t *num)
+{
+ uint64_t number;
+ bool neg;
+
+ /*
+ * Parse the number.
+ */
+ if (expand_impl(buf, &number, &neg) != 0)
+ return (-1);
+
/*
* Apply the sign and check for overflow.
*/
@@ -146,3 +161,27 @@ expand_number(const char *buf, int64_t *num)
return (0);
}
+
+int
+expand_unsigned(const char *buf, uint64_t *num)
+{
+ uint64_t number;
+ bool neg;
+
+ /*
+ * Parse the number.
+ */
+ if (expand_impl(buf, &number, &neg) != 0)
+ return (-1);
+
+ /*
+ * Negative numbers are out of range.
+ */
+ if (neg && number > 0) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ *num = number;
+ return (0);
+}