diff --git a/cmds/balance.c b/cmds/balance.c index 31d79e95..073a85f7 100644 --- a/cmds/balance.c +++ b/cmds/balance.c @@ -74,122 +74,6 @@ static int parse_profiles(char *profiles, u64 *flags) return 0; } -static int parse_u64(const char *str, u64 *result) -{ - char *endptr; - u64 val; - - val = strtoull(str, &endptr, 10); - if (*endptr) - return 1; - - *result = val; - return 0; -} - -/* - * Parse range that's missing some part that can be implicit: - * a..b - exact range, a can be equal to b - * a.. - implicitly unbounded maximum (end == (u64)-1) - * ..b - implicitly starting at 0 - * a - invalid; unclear semantics, use parse_u64 instead - * - * Returned values are u64, value validation and interpretation should be done - * by the caller. - */ -static int parse_range(const char *range, u64 *start, u64 *end) -{ - char *dots; - char *endptr; - const char *rest; - int skipped = 0; - - dots = strstr(range, ".."); - if (!dots) - return 1; - - rest = dots + 2; - - if (!*rest) { - *end = (u64)-1; - skipped++; - } else { - *end = strtoull(rest, &endptr, 10); - if (*endptr) - return 1; - } - if (dots == range) { - *start = 0; - skipped++; - } else { - *start = strtoull(range, &endptr, 10); - if (*endptr != 0 && *endptr != '.') - return 1; - } - - if (*start > *end) { - error("range %llu..%llu doesn't make sense", - (unsigned long long)*start, - (unsigned long long)*end); - return 1; - } - - if (skipped <= 1) - return 0; - - return 1; -} - -/* - * Parse range and check if start < end - */ -static int parse_range_strict(const char *range, u64 *start, u64 *end) -{ - if (parse_range(range, start, end) == 0) { - if (*start >= *end) { - error("range %llu..%llu not allowed", - (unsigned long long)*start, - (unsigned long long)*end); - return 1; - } - return 0; - } - - return 1; -} - -/* - * Convert 64bit range to 32bit with boundary checks - */ -static int range_to_u32(u64 start, u64 end, u32 *start32, u32 *end32) -{ - if (start > (u32)-1) - return 1; - - if (end != (u64)-1 && end > (u32)-1) - return 1; - - *start32 = (u32)start; - *end32 = (u32)end; - - return 0; -} - -__attribute__ ((unused)) -static int parse_range_u32(const char *range, u32 *start, u32 *end) -{ - u64 tmp_start; - u64 tmp_end; - - if (parse_range(range, &tmp_start, &tmp_end)) - return 1; - - if (range_to_u32(tmp_start, tmp_end, start, end)) - return 1; - - return 0; -} - __attribute__ ((unused)) static void print_range(u64 start, u64 end) { diff --git a/common/parse-utils.c b/common/parse-utils.c index 12e13b48..adefd006 100644 --- a/common/parse-utils.c +++ b/common/parse-utils.c @@ -20,6 +20,122 @@ #include "common/parse-utils.h" #include "common/messages.h" +int parse_u64(const char *str, u64 *result) +{ + char *endptr; + u64 val; + + val = strtoull(str, &endptr, 10); + if (*endptr) + return 1; + + *result = val; + return 0; +} + +/* + * Parse range that's missing some part that can be implicit: + * a..b - exact range, a can be equal to b + * a.. - implicitly unbounded maximum (end == (u64)-1) + * ..b - implicitly starting at 0 + * a - invalid; unclear semantics, use parse_u64 instead + * + * Returned values are u64, value validation and interpretation should be done + * by the caller. + */ +int parse_range(const char *range, u64 *start, u64 *end) +{ + char *dots; + char *endptr; + const char *rest; + int skipped = 0; + + dots = strstr(range, ".."); + if (!dots) + return 1; + + rest = dots + 2; + + if (!*rest) { + *end = (u64)-1; + skipped++; + } else { + *end = strtoull(rest, &endptr, 10); + if (*endptr) + return 1; + } + if (dots == range) { + *start = 0; + skipped++; + } else { + *start = strtoull(range, &endptr, 10); + if (*endptr != 0 && *endptr != '.') + return 1; + } + + if (*start > *end) { + error("range %llu..%llu doesn't make sense", + (unsigned long long)*start, + (unsigned long long)*end); + return 1; + } + + if (skipped <= 1) + return 0; + + return 1; +} + +/* + * Convert 64bit range to 32bit with boundary checks + */ +static int range_to_u32(u64 start, u64 end, u32 *start32, u32 *end32) +{ + if (start > (u32)-1) + return 1; + + if (end != (u64)-1 && end > (u32)-1) + return 1; + + *start32 = (u32)start; + *end32 = (u32)end; + + return 0; +} + +int parse_range_u32(const char *range, u32 *start, u32 *end) +{ + u64 tmp_start; + u64 tmp_end; + + if (parse_range(range, &tmp_start, &tmp_end)) + return 1; + + if (range_to_u32(tmp_start, tmp_end, start, end)) + return 1; + + return 0; +} + + +/* + * Parse range and check if start < end + */ +int parse_range_strict(const char *range, u64 *start, u64 *end) +{ + if (parse_range(range, start, end) == 0) { + if (*start >= *end) { + error("range %llu..%llu not allowed", + (unsigned long long)*start, + (unsigned long long)*end); + return 1; + } + return 0; + } + + return 1; +} + u64 parse_size_from_string(const char *s) { char c; diff --git a/common/parse-utils.h b/common/parse-utils.h index 8133d64e..0eecebf2 100644 --- a/common/parse-utils.h +++ b/common/parse-utils.h @@ -23,6 +23,10 @@ u64 parse_size_from_string(const char *s); enum btrfs_csum_type parse_csum_type(const char *s); +int parse_u64(const char *str, u64 *result); +int parse_range_u32(const char *range, u32 *start, u32 *end); +int parse_range(const char *range, u64 *start, u64 *end); +int parse_range_strict(const char *range, u64 *start, u64 *end); int fls64(u64 x); #endif