From d2082ee94267e4ca59b187c5e37dac03c1d65187 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 31 Jan 2023 05:13:03 +0100 Subject: Merging upstream version 2.3. Signed-off-by: Daniel Baumann --- util/argconfig.c | 50 +++++++++++++++++++++++++++++++------------------- util/argconfig.h | 7 +++---- util/suffix.c | 49 ++++++++++++++++++++++++++++++++++++++++++------- util/suffix.h | 3 +++ util/types.c | 43 +++++++++++++++++++++++++++++++++++++++++-- util/types.h | 1 + 6 files changed, 121 insertions(+), 32 deletions(-) (limited to 'util') diff --git a/util/argconfig.c b/util/argconfig.c index 2c328ff..231a704 100644 --- a/util/argconfig.c +++ b/util/argconfig.c @@ -53,7 +53,7 @@ void argconfig_append_usage(const char *str) append_usage_str = str; } -void print_word_wrapped(const char *s, int indent, int start) +void print_word_wrapped(const char *s, int indent, int start, FILE *stream) { const int width = 76; const char *c, *t; @@ -61,7 +61,7 @@ void print_word_wrapped(const char *s, int indent, int start) int last_line = indent; while (start < indent) { - putc(' ', stderr); + putc(' ', stream); start++; } @@ -78,14 +78,14 @@ void print_word_wrapped(const char *s, int indent, int start) int i; new_line: last_line = (int) (c-s) + start; - putc('\n', stderr); + putc('\n', stream); for (i = 0; i < indent; i++) - putc(' ', stderr); + putc(' ', stream); start = indent; continue; } } - putc(*c, stderr); + putc(*c, stream); } } @@ -115,8 +115,8 @@ static void show_option(const struct argconfig_commandline_options *option) fprintf(stderr, "%s", buffer); if (option->help) { - print_word_wrapped("--- ", 40, b - buffer); - print_word_wrapped(option->help, 44, 44); + print_word_wrapped("--- ", 40, b - buffer, stderr); + print_word_wrapped(option->help, 44, 44, stderr); } fprintf(stderr, "\n"); } @@ -126,20 +126,37 @@ void argconfig_print_help(const char *program_desc, { const struct argconfig_commandline_options *s; - printf("\033[1mUsage: %s\033[0m\n\n", - append_usage_str); + fprintf(stderr, "\033[1mUsage: %s\033[0m\n\n", + append_usage_str); - print_word_wrapped(program_desc, 0, 0); - printf("\n"); + print_word_wrapped(program_desc, 0, 0, stderr); + fprintf(stderr, "\n"); if (!options || !options->option) return; - printf("\n\033[1mOptions:\033[0m\n"); + fprintf(stderr, "\n\033[1mOptions:\033[0m\n"); for (s = options; (s != NULL) && (s->option != NULL); s++) show_option(s); } +int argconfig_parse_byte(const char *opt, const char *str, unsigned char *val) +{ + char *endptr; + unsigned long tmp = strtoul(str, &endptr, 0); + + if (errno || tmp >= 1 << 8 || str == endptr) { + fprintf(stderr, + "Expected byte argument for '%s' but got '%s'!\n", opt, + str); + return -EINVAL; + } + + *val = tmp; + + return 0; +} + int argconfig_parse(int argc, char *argv[], const char *program_desc, const struct argconfig_commandline_options *options) { @@ -244,14 +261,9 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, } *((int *)value_addr) = tmp; } else if (s->config_type == CFG_BYTE) { - unsigned long tmp = strtoul(optarg, &endptr, 0); - if (errno || tmp >= (1 << 8) || optarg == endptr) { - fprintf(stderr, - "Expected byte argument for '%s' but got '%s'!\n", - long_opts[option_index].name, optarg); + if (argconfig_parse_byte(long_opts[option_index].name, + optarg, (uint8_t *)value_addr)) goto out; - } - *((uint8_t *) value_addr) = tmp; } else if (s->config_type == CFG_SHORT) { unsigned long tmp = strtoul(optarg, &endptr, 0); if (errno || tmp >= (1 << 16) || optarg == endptr) { diff --git a/util/argconfig.h b/util/argconfig.h index b66706a..6ef3b6a 100644 --- a/util/argconfig.h +++ b/util/argconfig.h @@ -37,6 +37,7 @@ #include #include #include +#include enum argconfig_types { CFG_FLAG, @@ -71,9 +72,6 @@ enum argconfig_types { #define OPT_SUFFIX(l, s, v, d) \ {l, s, "IONUM", CFG_LONG_SUFFIX, v, required_argument, d} -#define OPT_LONG(l, s, v, d) \ - {l, s, "NUM", CFG_LONG, v, required_argument, d} - #define OPT_UINT(l, s, v, d) \ {l, s, "NUM", CFG_POSITIVE, v, required_argument, d} @@ -131,7 +129,8 @@ int argconfig_parse_comma_sep_array_short(char *string, unsigned short *ret, int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *ret, unsigned max_length); +int argconfig_parse_byte(const char *opt, const char *str, unsigned char *val); void argconfig_register_help_func(argconfig_help_func * f); -void print_word_wrapped(const char *s, int indent, int start); +void print_word_wrapped(const char *s, int indent, int start, FILE *stream); #endif diff --git a/util/suffix.c b/util/suffix.c index 6cd4f0b..4106958 100644 --- a/util/suffix.c +++ b/util/suffix.c @@ -38,24 +38,59 @@ #include static struct si_suffix { - double magnitude; + long double magnitude; const char *suffix; } si_suffixes[] = { + {1e30, "Q"}, + {1e27, "R"}, + {1e24, "Y"}, + {1e21, "Z"}, + {1e18, "E"}, {1e15, "P"}, {1e12, "T"}, {1e9, "G"}, {1e6, "M"}, {1e3, "k"}, {1e0, ""}, - {1e-3, "m"}, - {1e-6, "u"}, - {1e-9, "n"}, - {1e-12, "p"}, - {1e-15, "f"}, {0} }; const char *suffix_si_get(double *value) +{ + long double value_ld = *value; + const char *suffix = suffix_si_get_ld(&value_ld); + + *value = value_ld; + + return suffix; +} + +uint64_t suffix_si_parse(const char *value, bool *suffixed) +{ + char *suffix; + double ret; + struct si_suffix *s; + + errno = 0; + ret = strtod(value, &suffix); + if (errno) + return 0; + + for (s = si_suffixes; s->magnitude != 0; s++) { + if (suffix[0] == s->suffix[0]) { + if (suffixed && suffix[0] != '\0') + *suffixed = true; + return ret *= s->magnitude; + } + } + + if (suffix[0] != '\0') + errno = EINVAL; + + return (uint64_t)ret; +} + +const char *suffix_si_get_ld(long double *value) { struct si_suffix *s; @@ -114,7 +149,7 @@ uint64_t suffix_binary_parse(const char *value) { char *suffix; errno = 0; - uint64_t ret = strtoll(value, &suffix, 0); + uint64_t ret = strtoull(value, &suffix, 0); if (errno) return 0; diff --git a/util/suffix.h b/util/suffix.h index 4f8e041..b367ce4 100644 --- a/util/suffix.h +++ b/util/suffix.h @@ -33,8 +33,11 @@ #ifndef __ARGCONFIG_SUFFIX_H__ #include +#include const char *suffix_si_get(double *value); +uint64_t suffix_si_parse(const char *value, bool *suffixed); +const char *suffix_si_get_ld(long double *value); const char *suffix_binary_get(long long *value); const char *suffix_dbinary_get(double *value); uint64_t suffix_binary_parse(const char *value); diff --git a/util/types.c b/util/types.c index 06bb8d4..18ced77 100644 --- a/util/types.c +++ b/util/types.c @@ -3,10 +3,12 @@ #include #include #include +#include #include #include "types.h" +#include "util/suffix.h" nvme_uint128_t le128_to_cpu(__u8 *data) { @@ -46,14 +48,22 @@ uint64_t int48_to_long(__u8 *data) char *uint128_t_to_string(nvme_uint128_t val) { - static char str[40]; - int idx = 40; + static char str[60]; + int idx = 60; __u64 div, rem; + char *sep = localeconv()->thousands_sep; + int len = sep ? strlen(sep) : 0; + int i; /* terminate at the end, and build up from the ones */ str[--idx] = '\0'; do { + if (len && !((sizeof(str) - idx) % (3 + len))) { + for (i = 0; i < len; i++) + str[--idx] = sep[i]; + } + rem = val.words[0]; div = rem / 10; @@ -78,6 +88,35 @@ char *uint128_t_to_string(nvme_uint128_t val) return str + idx; } +static long double uint128_t_to_double(nvme_uint128_t data) +{ + int i; + long double result = 0; + + for (i = 0; i < sizeof(data.words) / sizeof(*data.words); i++) { + result *= 4294967296; + result += data.words[i]; + } + + return result; +} + +char *uint128_t_to_si_string(nvme_uint128_t val, __u32 bytes_per_unit) +{ + static char str[40]; + long double bytes = uint128_t_to_double(val) * bytes_per_unit; + const char *suffix = suffix_si_get_ld(&bytes); + int n = snprintf(str, sizeof(str), "%.2Lf %sB", bytes, suffix); + + if (n <= 0) + return ""; + + if (n >= sizeof(str)) + str[sizeof(str) - 1] = '\0'; + + return str; +} + const char *util_uuid_to_string(unsigned char uuid[NVME_UUID_LEN]) { static char uuid_str[NVME_UUID_LEN_STRING]; diff --git a/util/types.h b/util/types.h index 6d45108..2e88717 100644 --- a/util/types.h +++ b/util/types.h @@ -29,6 +29,7 @@ long double int128_to_double(__u8 *data); uint64_t int48_to_long(__u8 *data); char *uint128_t_to_string(nvme_uint128_t val); +char *uint128_t_to_si_string(nvme_uint128_t val, __u32 bytes_per_unit); const char *util_uuid_to_string(unsigned char uuid[NVME_UUID_LEN]); const char *util_fw_to_string(char *c); -- cgit v1.2.3