From 8f8d94b8c932fc61e80573b5cf8cc73302fcfd3d Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Wed, 17 Jan 2024 14:40:39 +1030 Subject: [PATCH] btrfs-progs: use parse_u64() to implement arg_strtou64() 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 Signed-off-by: David Sterba --- common/parse-utils.c | 19 ++++++++++++++++++- common/string-utils.c | 26 ++++++++++---------------- common/string-utils.h | 2 ++ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/common/parse-utils.c b/common/parse-utils.c index 3d9a6d63..bc913c23 100644 --- a/common/parse-utils.c +++ b/common/parse-utils.c @@ -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 a negative value). + * Return -ERANGE if the value is too large for u64. + */ int parse_u64(const char *str, u64 *result) { char *endptr; u64 val; + /* + * Although strtoull accepts a negative number and converts it u64, we + * don't really want to utilize this as the helper is meant for u64 only. + */ + 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; diff --git a/common/string-utils.c b/common/string-utils.c index e338afa7..ba5cc55a 100644 --- a/common/string-utils.c +++ b/common/string-utils.c @@ -20,6 +20,7 @@ #include #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; } diff --git a/common/string-utils.h b/common/string-utils.h index ade8fcd1..a7ac8f5c 100644 --- a/common/string-utils.h +++ b/common/string-utils.h @@ -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);