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;
|
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))
|
__attribute__ ((unused))
|
||||||
static void print_range(u64 start, u64 end)
|
static void print_range(u64 start, u64 end)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,122 @@
|
||||||
#include "common/parse-utils.h"
|
#include "common/parse-utils.h"
|
||||||
#include "common/messages.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)
|
u64 parse_size_from_string(const char *s)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
u64 parse_size_from_string(const char *s);
|
u64 parse_size_from_string(const char *s);
|
||||||
enum btrfs_csum_type parse_csum_type(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);
|
int fls64(u64 x);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue