@@ -31,14 +31,31 @@
#include "common/messages.h"
#include "common/utils.h"
+/*
+ * Parse a string to u64.
+ *
+ * Return 0 if there is a valid numeric string and result would be stored in
+ * @result.
+ * Return -EINVAL if the string is not valid (no numeric string at all, or
+ * has any tailing characters, or minus value).
+ * Return -ERANGE if the value is too larger for u64.
+ */
int parse_u64(const char *str, u64 *result)
{
char *endptr;
u64 val;
+ /*
+ * Although strtoull accepts minus number and convert it u64,
+ * we don't really want to utilize this behavior.
+ */
+ if (str[0] == '-')
+ return -EINVAL;
val = strtoull(str, &endptr, 10);
if (*endptr)
- return 1;
+ return -EINVAL;
+ if (val == ULLONG_MAX && errno == ERANGE)
+ return -ERANGE;
*result = val;
return 0;
@@ -20,6 +20,7 @@
#include <limits.h>
#include "common/string-utils.h"
#include "common/messages.h"
+#include "common/parse-utils.h"
int string_is_numerical(const char *str)
{
@@ -50,25 +51,18 @@ int string_has_prefix(const char *str, const char *prefix)
u64 arg_strtou64(const char *str)
{
u64 value;
- char *ptr_parse_end = NULL;
+ int ret;
- value = strtoull(str, &ptr_parse_end, 0);
- if (ptr_parse_end && *ptr_parse_end != '\0') {
- error("%s is not a valid numeric value", str);
- exit(1);
- }
-
- /*
- * if we pass a negative number to strtoull, it will return an
- * unexpected number to us, so let's do the check ourselves.
- */
- if (str[0] == '-') {
- error("%s: negative value is invalid", str);
- exit(1);
- }
- if (value == ULLONG_MAX) {
+ ret = parse_u64(str, &value);
+ if (ret == -ERANGE) {
error("%s is too large", str);
exit(1);
+ } else if (ret == -EINVAL) {
+ if (str[0] == '-')
+ error("%s: negative value is invalid", str);
+ else
+ error("%s is not a valid numeric value", str);
+ exit(1);
}
return value;
}
@@ -17,6 +17,8 @@
#ifndef __BTRFS_STRING_UTILS_H__
#define __BTRFS_STRING_UTILS_H__
+#include "kerncompat.h"
+
int string_is_numerical(const char *str);
int string_has_prefix(const char *str, const char *prefix);
u64 arg_strtou64(const char *str);
Both functions are just doing the same thing, the only difference is only in error handling, as parse_u64() requires callers to handle it, meanwhile arg_strtou64() would call exit(1). This patch would convert arg_strtou64() to utilize parse_u64(), and use the return value to output different error messages. This also means the return value of parse_u64() would be more than just 0 or 1, but -EINVAL for invalid string (including no numeric string at all, has any tailing characters, or minus value), and -ERANGE for overflow. The existing callers are only checking if the return value is 0, thus not really affected. Signed-off-by: Qu Wenruo <wqu@suse.com> --- common/parse-utils.c | 19 ++++++++++++++++++- common/string-utils.c | 26 ++++++++++---------------- common/string-utils.h | 2 ++ 3 files changed, 30 insertions(+), 17 deletions(-)