summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-01-31 04:13:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-01-31 04:13:03 +0000
commitd2082ee94267e4ca59b187c5e37dac03c1d65187 (patch)
treecd93a882e0726a7df500fedf2263263984406b36 /util
parentReleasing debian version 2.2.1-4. (diff)
downloadnvme-cli-d2082ee94267e4ca59b187c5e37dac03c1d65187.tar.xz
nvme-cli-d2082ee94267e4ca59b187c5e37dac03c1d65187.zip
Merging upstream version 2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--util/argconfig.c50
-rw-r--r--util/argconfig.h7
-rw-r--r--util/suffix.c49
-rw-r--r--util/suffix.h3
-rw-r--r--util/types.c43
-rw-r--r--util/types.h1
6 files changed, 121 insertions, 32 deletions
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 <string.h>
#include <getopt.h>
#include <stdarg.h>
+#include <stdio.h>
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,25 +38,60 @@
#include <math.h>
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;
for (s = si_suffixes; s->magnitude != 0; 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 <inttypes.h>
+#include <stdbool.h>
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 <inttypes.h>
#include <stdio.h>
#include <string.h>
+#include <locale.h>
#include <ccan/endian/endian.h>
#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);