btrfs-progs: move number and range parsing helpers to parse-utils.c
Some of the parsers in cmds/balance.c are generic enough for the common part. Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
af56460de8
commit
6b93a7336c
116
cmds/balance.c
116
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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue