btrfs-progs: split parsing helpers from utils.c

There are various parsing helpers scattered everywhere, unify them to
one file and start with helpers already in utils.c.

Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2021-09-03 22:29:06 +02:00
parent d15b7b0d58
commit af56460de8
9 changed files with 161 additions and 108 deletions

View File

@ -173,7 +173,8 @@ libbtrfs_objects = common/send-stream.o common/send-utils.o kernel-lib/rbtree.o
common/device-scan.o common/path-utils.o \
common/utils.o libbtrfsutil/subvolume.o libbtrfsutil/stubs.o \
crypto/hash.o crypto/xxhash.o $(CRYPTO_OBJECTS) \
common/open-utils.o common/units.o common/device-utils.o
common/open-utils.o common/units.o common/device-utils.o \
common/parse-utils.o
libbtrfs_headers = common/send-stream.h common/send-utils.h send.h kernel-lib/rbtree.h btrfs-list.h \
crypto/crc32c.h kernel-lib/list.h kerncompat.h \
kernel-lib/radix-tree.h kernel-lib/sizes.h kernel-lib/raid56.h \

View File

@ -46,6 +46,7 @@
#include "common/device-scan.h"
#include "common/device-utils.h"
#include "common/open-utils.h"
#include "common/parse-utils.h"
/*
* for btrfs fi show, we maintain a hash of fsids we've already printed.

View File

@ -30,6 +30,7 @@
#include "common/utils.h"
#include "common/help.h"
#include "common/units.h"
#include "common/parse-utils.h"
static const char * const qgroup_cmd_group_usage[] = {
"btrfs qgroup <command> [options] <path>",

127
common/parse-utils.c Normal file
View File

@ -0,0 +1,127 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#include "kerncompat.h"
#include <limits.h>
#include <ctype.h>
#include "common/parse-utils.h"
#include "common/messages.h"
u64 parse_size_from_string(const char *s)
{
char c;
char *endptr;
u64 mult = 1;
u64 ret;
if (!s) {
error("size value is empty");
exit(1);
}
if (s[0] == '-') {
error("size value '%s' is less equal than 0", s);
exit(1);
}
ret = strtoull(s, &endptr, 10);
if (endptr == s) {
error("size value '%s' is invalid", s);
exit(1);
}
if (endptr[0] && endptr[1]) {
error("illegal suffix contains character '%c' in wrong position",
endptr[1]);
exit(1);
}
/*
* strtoll returns LLONG_MAX when overflow, if this happens,
* need to call strtoull to get the real size
*/
if (errno == ERANGE && ret == ULLONG_MAX) {
error("size value '%s' is too large for u64", s);
exit(1);
}
if (endptr[0]) {
c = tolower(endptr[0]);
switch (c) {
case 'e':
mult *= 1024;
/* fallthrough */
case 'p':
mult *= 1024;
/* fallthrough */
case 't':
mult *= 1024;
/* fallthrough */
case 'g':
mult *= 1024;
/* fallthrough */
case 'm':
mult *= 1024;
/* fallthrough */
case 'k':
mult *= 1024;
/* fallthrough */
case 'b':
break;
default:
error("unknown size descriptor '%c'", c);
exit(1);
}
}
/* Check whether ret * mult overflow */
if (fls64(ret) + fls64(mult) - 1 > 64) {
error("size value '%s' is too large for u64", s);
exit(1);
}
ret *= mult;
return ret;
}
enum btrfs_csum_type parse_csum_type(const char *s)
{
if (strcasecmp(s, "crc32c") == 0) {
return BTRFS_CSUM_TYPE_CRC32;
} else if (strcasecmp(s, "xxhash64") == 0 ||
strcasecmp(s, "xxhash") == 0) {
return BTRFS_CSUM_TYPE_XXHASH;
} else if (strcasecmp(s, "sha256") == 0) {
return BTRFS_CSUM_TYPE_SHA256;
} else if (strcasecmp(s, "blake2b") == 0 ||
strcasecmp(s, "blake2") == 0) {
return BTRFS_CSUM_TYPE_BLAKE2;
} else {
error("unknown csum type %s", s);
exit(1);
}
/* not reached */
return 0;
}
/*
* Find last set bit in a 64-bit word. Returns 0 if value is 0 or the position
* of the last set bit if value is nonzero. The last (most significant) bit is
* at position 64.
*/
int fls64(u64 x)
{
int i;
for (i = 0; i < 64; i++)
if (x << i & (1ULL << 63))
return 64 - i;
return 64 - i;
}

28
common/parse-utils.h Normal file
View File

@ -0,0 +1,28 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#ifndef __PARSE_UTILS_H__
#define __PARSE_UTILS_H__
#include "kerncompat.h"
#include "kernel-shared/ctree.h"
u64 parse_size_from_string(const char *s);
enum btrfs_csum_type parse_csum_type(const char *s);
int fls64(u64 x);
#endif

View File

@ -227,90 +227,6 @@ int set_label(const char *btrfs_dev, const char *label)
return ret;
}
/*
* A not-so-good version fls64. No fascinating optimization since
* no one except parse_size_from_string uses it
*/
static int fls64(u64 x)
{
int i;
for (i = 0; i <64; i++)
if (x << i & (1ULL << 63))
return 64 - i;
return 64 - i;
}
u64 parse_size_from_string(const char *s)
{
char c;
char *endptr;
u64 mult = 1;
u64 ret;
if (!s) {
error("size value is empty");
exit(1);
}
if (s[0] == '-') {
error("size value '%s' is less equal than 0", s);
exit(1);
}
ret = strtoull(s, &endptr, 10);
if (endptr == s) {
error("size value '%s' is invalid", s);
exit(1);
}
if (endptr[0] && endptr[1]) {
error("illegal suffix contains character '%c' in wrong position",
endptr[1]);
exit(1);
}
/*
* strtoll returns LLONG_MAX when overflow, if this happens,
* need to call strtoull to get the real size
*/
if (errno == ERANGE && ret == ULLONG_MAX) {
error("size value '%s' is too large for u64", s);
exit(1);
}
if (endptr[0]) {
c = tolower(endptr[0]);
switch (c) {
case 'e':
mult *= 1024;
/* fallthrough */
case 'p':
mult *= 1024;
/* fallthrough */
case 't':
mult *= 1024;
/* fallthrough */
case 'g':
mult *= 1024;
/* fallthrough */
case 'm':
mult *= 1024;
/* fallthrough */
case 'k':
mult *= 1024;
/* fallthrough */
case 'b':
break;
default:
error("unknown size descriptor '%c'", c);
exit(1);
}
}
/* Check whether ret * mult overflow */
if (fls64(ret) + fls64(mult) - 1 > 64) {
error("size value '%s' is too large for u64", s);
exit(1);
}
ret *= mult;
return ret;
}
u64 parse_qgroupid(const char *p)
{
char *s = strchr(p, '/');
@ -365,26 +281,6 @@ err:
exit(-1);
}
enum btrfs_csum_type parse_csum_type(const char *s)
{
if (strcasecmp(s, "crc32c") == 0) {
return BTRFS_CSUM_TYPE_CRC32;
} else if (strcasecmp(s, "xxhash64") == 0 ||
strcasecmp(s, "xxhash") == 0) {
return BTRFS_CSUM_TYPE_XXHASH;
} else if (strcasecmp(s, "sha256") == 0) {
return BTRFS_CSUM_TYPE_SHA256;
} else if (strcasecmp(s, "blake2b") == 0 ||
strcasecmp(s, "blake2") == 0) {
return BTRFS_CSUM_TYPE_BLAKE2;
} else {
error("unknown csum type %s", s);
exit(1);
}
/* not reached */
return 0;
}
void btrfs_format_csum(u16 csum_type, const u8 *data, char *output)
{
int i;

View File

@ -42,12 +42,9 @@ enum exclusive_operation {
BTRFS_EXCLOP_UNKNOWN = -1,
};
enum btrfs_csum_type parse_csum_type(const char *s);
/* 2 for "0x", 2 for each byte, plus nul */
#define BTRFS_CSUM_STRING_LEN (2 + 2 * BTRFS_CSUM_SIZE + 1)
void btrfs_format_csum(u16 csum_type, const u8 *data, char *output);
u64 parse_size_from_string(const char *s);
u64 parse_qgroupid(const char *p);
u64 arg_strtou64(const char *str);
int get_fs_info(const char *path, struct btrfs_ioctl_fs_info_args *fi_args,

View File

@ -100,6 +100,7 @@
#include "common/task-utils.h"
#include "common/path-utils.h"
#include "common/help.h"
#include "common/parse-utils.h"
#include "mkfs/common.h"
#include "convert/common.h"
#include "convert/source-fs.h"

View File

@ -44,6 +44,7 @@
#include "kernel-lib/list_sort.h"
#include "common/help.h"
#include "common/rbtree-utils.h"
#include "common/parse-utils.h"
#include "mkfs/common.h"
#include "mkfs/rootdir.h"
#include "common/fsfeatures.h"