From 01c4d3d32c5044d3d17055c2d94d40fee9d130e1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 1 Jul 2023 00:38:48 +0200 Subject: Adding upstream version 2.5. Signed-off-by: Daniel Baumann --- util/argconfig.c | 264 +++++++++++++++++++++++-------------------------------- util/argconfig.h | 130 +++++++++++++++++---------- util/base64.c | 28 +++--- util/crc32.c | 173 ++++++++++++++++++------------------ util/suffix.c | 50 ++++++++--- util/types.c | 57 +++++++++++- util/types.h | 23 +++++ 7 files changed, 411 insertions(+), 314 deletions(-) (limited to 'util') diff --git a/util/argconfig.c b/util/argconfig.c index 3eb885f..effeea2 100644 --- a/util/argconfig.c +++ b/util/argconfig.c @@ -42,18 +42,11 @@ #include #include -#if __has_attribute(__fallthrough__) -#define fallthrough __attribute__((__fallthrough__)) -#else -#define fallthrough do {} while (0) -#endif - -static argconfig_help_func *help_funcs[MAX_HELP_FUNC] = { NULL }; - -static char END_DEFAULT[] = "__end_default__"; - static const char *append_usage_str = ""; +static int argconfig_parse_val(struct argconfig_commandline_options *s, struct option *option, + int index); + void argconfig_append_usage(const char *str) { append_usage_str = str; @@ -168,11 +161,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct { void *value = (void *)(char *)s->default_value; char *endptr; - const char *fopts = NULL; - FILE *f; int ret = 0; - char **opts = ((char **)value); - int remaining_space = CFG_MAX_SUBOPTS - 2; switch (s->config_type) { case CFG_STRING: @@ -190,6 +179,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct break; case CFG_BOOL: { int tmp = strtol(optarg, &endptr, 0); + if (errno || tmp < 0 || tmp > 1 || optarg == endptr) ret = argconfig_error("0 or 1", option[index].name, optarg); else @@ -201,6 +191,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct break; case CFG_SHORT: { unsigned long tmp = strtoul(optarg, &endptr, 0); + if (errno || tmp >= 1 << 16 || optarg == endptr) ret = argconfig_error("short", option[index].name, optarg); else @@ -209,6 +200,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct } case CFG_POSITIVE: { uint32_t tmp = strtoul(optarg, &endptr, 0); + if (errno || optarg == endptr) ret = argconfig_error("word", option[index].name, optarg); else @@ -224,7 +216,7 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct ret = argconfig_error("long integer", option[index].name, optarg); break; case CFG_LONG_SUFFIX: - ret = suffix_binary_parse(optarg, &endptr, (uint64_t*)value); + ret = suffix_binary_parse(optarg, &endptr, (uint64_t *)value); if (ret) argconfig_error("long suffixed integer", option[index].name, optarg); break; @@ -233,48 +225,6 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct if (errno || optarg == endptr) ret = argconfig_error("float", option[index].name, optarg); break; - case CFG_SUBOPTS: - *opts = END_DEFAULT; - opts += 2; - ret = argconfig_parse_subopt_string(optarg, opts, remaining_space); - if (ret) { - if (ret == 2) - fprintf(stderr, "Error Parsing Sub-Options: Too many options!\n"); - else - fprintf(stderr, "Error Parsing Sub-Options\n"); - ret = -EINVAL; - } - break; - case CFG_FILE_A: - fopts = "a"; - fallthrough; - case CFG_FILE_R: - if (!fopts) - fopts = "r"; - fallthrough; - case CFG_FILE_W: - if (!fopts) - fopts = "w"; - fallthrough; - case CFG_FILE_AP: - if (!fopts) - fopts = "a+"; - fallthrough; - case CFG_FILE_RP: - if (!fopts) - fopts = "r+"; - fallthrough; - case CFG_FILE_WP: - if (!fopts) - fopts = "w+"; - f = fopen(optarg, fopts); - if (!f) { - fprintf(stderr, "Unable to open %s file: %s\n", s->option, optarg); - ret = -EINVAL; - } else { - *((FILE **)value) = f; - } - break; case CFG_FLAG: *((bool *)value) = true; break; @@ -285,9 +235,87 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct return ret; } +static int argconfig_get_val_len(struct argconfig_opt_val *opt_val, const char *str) +{ + struct argconfig_opt_val *v; + int len; + int match; + + for (len = 1; len <= strlen(str); len++) { + match = 0; + for (v = opt_val; v && v->str; v++) { + if (!strncasecmp(str, v->str, len)) + match++; + } + if (match == 1) + break; + } + + return len; +} + +static int argconfig_set_opt_val(enum argconfig_types type, union argconfig_val *opt_val, void *val) +{ + switch (type) { + case CFG_FLAG: + *(bool *)val = opt_val->bool_val; + break; + case CFG_LONG_SUFFIX: + *(uint64_t *)val = opt_val->long_suffix; + break; + case CFG_POSITIVE: + *(uint32_t *)val = opt_val->positive; + break; + case CFG_INT: + *(int *)val = opt_val->int_val; + break; + case CFG_LONG: + *(unsigned long *)val = opt_val->long_val; + break; + case CFG_DOUBLE: + *(double *)val = opt_val->double_val; + break; + case CFG_BYTE: + *(uint8_t *)val = opt_val->byte; + break; + case CFG_SHORT: + *(uint16_t *)val = opt_val->short_val; + break; + case CFG_INCREMENT: + *(int *)val = opt_val->increment; + break; + case CFG_STRING: + *(char **)val = opt_val->string; + break; + default: + break; + } + + return 0; +} + +static int argconfig_parse_val(struct argconfig_commandline_options *s, struct option *option, + int index) +{ + const char *str = optarg; + void *val = s->default_value; + int len = strlen(optarg); + struct argconfig_opt_val *v; + int val_len; + + for (v = s->opt_val; v && v->str; v++) { + val_len = argconfig_get_val_len(s->opt_val, v->str); + if (strncasecmp(str, v->str, len > val_len ? len : val_len)) + continue; + return argconfig_set_opt_val(v->type, &v->val, val); + } + + return argconfig_parse_type(s, option, index); +} + bool argconfig_output_format_json(bool set) { - static bool output_format_json = false; + static bool output_format_json; if (set) output_format_json = true; @@ -295,6 +323,18 @@ bool argconfig_output_format_json(bool set) return output_format_json; } +static bool argconfig_check_output_format_json(struct argconfig_commandline_options *s) +{ + for (; s && s->option; s++) { + if (strcmp(s->option, "output-format") || s->config_type != CFG_STRING) + continue; + if (!strcmp(*(char **)s->default_value, "json")) + return true; + } + + return false; +} + int argconfig_parse(int argc, char *argv[], const char *program_desc, struct argconfig_commandline_options *options) { @@ -368,94 +408,24 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc, if (!s->default_value) continue; - ret = argconfig_parse_type(s, long_opts,option_index); + if (s->opt_val) + ret = argconfig_parse_val(s, long_opts, option_index); + else + ret = argconfig_parse_type(s, long_opts, option_index); if (ret) break; } + + if (argconfig_check_output_format_json(options)) + argconfig_output_format_json(true); + out: free(short_opts); free(long_opts); return ret; } -int argconfig_parse_subopt_string(char *string, char **options, - size_t max_options) -{ - char **o = options; - char *tmp; - size_t toklen; - - if (!string || !strlen(string)) { - *(o++) = NULL; - *(o++) = NULL; - return 0; - } - - tmp = calloc(strlen(string) + 2, 1); - if (!tmp) - return 1; - strcpy(tmp, string); - - toklen = strcspn(tmp, "="); - - if (!toklen) { - free(tmp); - return 1; - } - - *(o++) = tmp; - tmp[toklen] = 0; - tmp += toklen + 1; - - while (1) { - if (*tmp == '"' || *tmp == '\'' || *tmp == '[' || *tmp == '(' || - *tmp == '{') { - - tmp++; - toklen = strcspn(tmp, "\"'])}"); - - if (!toklen) - return 1; - - *(o++) = tmp; - tmp[toklen] = 0; - tmp += toklen + 1; - - toklen = strcspn(tmp, ";:,"); - tmp[toklen] = 0; - tmp += toklen + 1; - } else { - toklen = strcspn(tmp, ";:,"); - - if (!toklen) - return 1; - - *(o++) = tmp; - tmp[toklen] = 0; - tmp += toklen + 1; - } - - toklen = strcspn(tmp, "="); - - if (!toklen) - break; - - *(o++) = tmp; - tmp[toklen] = 0; - tmp += toklen + 1; - - if ((o - options) > (max_options - 2)) - return 2; - } - - *(o++) = NULL; - *(o++) = NULL; - - return 0; -} - -int argconfig_parse_comma_sep_array(char *string, int *val, - unsigned max_length) +int argconfig_parse_comma_sep_array(char *string, int *val, unsigned int max_length) { int ret = 0; unsigned long v; @@ -501,7 +471,7 @@ int argconfig_parse_comma_sep_array(char *string, int *val, } int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val, - unsigned max_length) + unsigned int max_length) { int ret = 0; unsigned long v; @@ -545,9 +515,8 @@ int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val, } } -int argconfig_parse_comma_sep_array_long(char *string, - unsigned long long *val, - unsigned max_length) +int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val, + unsigned int max_length) { int ret = 0; char *tmp; @@ -580,19 +549,6 @@ int argconfig_parse_comma_sep_array_long(char *string, } } -void argconfig_register_help_func(argconfig_help_func * f) -{ - int i; - for (i = 0; i < MAX_HELP_FUNC; i++) { - if (help_funcs[i] == NULL) { - help_funcs[i] = f; - if (i < MAX_HELP_FUNC - 1) - help_funcs[i + 1] = NULL; - break; - } - } -} - bool argconfig_parse_seen(struct argconfig_commandline_options *s, const char *option) { diff --git a/util/argconfig.h b/util/argconfig.h index 81eaaf4..eaf8375 100644 --- a/util/argconfig.h +++ b/util/argconfig.h @@ -39,6 +39,7 @@ #include #include #include +#include enum argconfig_types { CFG_FLAG, @@ -53,13 +54,6 @@ enum argconfig_types { CFG_SHORT, CFG_POSITIVE, CFG_INCREMENT, - CFG_SUBOPTS, - CFG_FILE_A, - CFG_FILE_W, - CFG_FILE_R, - CFG_FILE_AP, - CFG_FILE_WP, - CFG_FILE_RP, }; #define OPT_ARGS(n) \ @@ -67,40 +61,96 @@ enum argconfig_types { #define OPT_END() { NULL } -#define OPT_FLAG(l, s, v, d) \ - {l, s, NULL, CFG_FLAG, v, no_argument, d} +#define OPT_FLAG(l, s, v, d, ...) \ + {l, s, NULL, CFG_FLAG, v, no_argument, d, false, __VA_ARGS__} -#define OPT_SUFFIX(l, s, v, d) \ - {l, s, "IONUM", CFG_LONG_SUFFIX, v, required_argument, d} +#define OPT_SUFFIX(l, s, v, d, ...) \ + {l, s, "IONUM", CFG_LONG_SUFFIX, v, required_argument, d, false, __VA_ARGS__} -#define OPT_UINT(l, s, v, d) \ - {l, s, "NUM", CFG_POSITIVE, v, required_argument, d} +#define OPT_UINT(l, s, v, d, ...) \ + {l, s, "NUM", CFG_POSITIVE, v, required_argument, d, false, __VA_ARGS__} -#define OPT_INT(l, s, v, d) \ - {l, s, "NUM", CFG_INT, v, required_argument, d} +#define OPT_INT(l, s, v, d, ...) \ + {l, s, "NUM", CFG_INT, v, required_argument, d, false, __VA_ARGS__} -#define OPT_LONG(l, s, v, d) \ - {l, s, "NUM", CFG_LONG, v, required_argument, d} +#define OPT_LONG(l, s, v, d, ...) \ + {l, s, "NUM", CFG_LONG, v, required_argument, d, false, __VA_ARGS__} -#define OPT_DOUBLE(l, s, v, d) \ - {l, s, "NUM", CFG_DOUBLE, v, required_argument, d} +#define OPT_DOUBLE(l, s, v, d, ...) \ + {l, s, "NUM", CFG_DOUBLE, v, required_argument, d, false, __VA_ARGS__} -#define OPT_BYTE(l, s, v, d) \ - {l, s, "NUM", CFG_BYTE, v, required_argument, d} +#define OPT_BYTE(l, s, v, d, ...) \ + {l, s, "NUM", CFG_BYTE, v, required_argument, d, false, __VA_ARGS__} -#define OPT_SHRT(l, s, v, d) \ - {l, s, "NUM", CFG_SHORT, v, required_argument, d} +#define OPT_SHRT(l, s, v, d, ...) \ + {l, s, "NUM", CFG_SHORT, v, required_argument, d, false, __VA_ARGS__} -#define OPT_INCR(l, s, v, d) \ - {l, s, "NUM", CFG_INCREMENT, v, no_argument, d} +#define OPT_INCR(l, s, v, d, ...) \ + {l, s, "NUM", CFG_INCREMENT, v, no_argument, d, false, __VA_ARGS__} -#define OPT_STRING(l, s, m, v, d) \ - {l, s, m, CFG_STRING, v, required_argument, d} +#define OPT_STRING(l, s, m, v, d, ...) \ + {l, s, m, CFG_STRING, v, required_argument, d, false, __VA_ARGS__} -#define OPT_FMT(l, s, v, d) OPT_STRING(l, s, "FMT", v, d) -#define OPT_FILE(l, s, v, d) OPT_STRING(l, s, "FILE", v, d) -#define OPT_LIST(l, s, v, d) OPT_STRING(l, s, "LIST", v, d) -#define OPT_STR(l, s, v, d) OPT_STRING(l, s, "STRING", v, d) +#define OPT_FMT(l, s, v, d, ...) OPT_STRING(l, s, "FMT", v, d, __VA_ARGS__) +#define OPT_FILE(l, s, v, d, ...) OPT_STRING(l, s, "FILE", v, d, __VA_ARGS__) +#define OPT_LIST(l, s, v, d, ...) OPT_STRING(l, s, "LIST", v, d, __VA_ARGS__) +#define OPT_STR(l, s, v, d, ...) OPT_STRING(l, s, "STRING", v, d, __VA_ARGS__) + +#define OPT_VALS(n) \ + struct argconfig_opt_val n[] + +#define VAL_END() { NULL } + +#define VAL_FLAG(s, l, v) \ + {s, CFG_FLAG, .val.flag = v} + +#define VAL_LONG_SUFFIX(s, v) \ + {s, CFG_LONG_SUFFIX, .val.long_suffix = v} + +#define VAL_UINT(s, v) \ + {s, CFG_POSITIVE, v} + +#define VAL_INT(s, v) \ + {s, CFG_INT, .val.int_val = v} + +#define VAL_LONG(s, v) \ + {s, CFG_LONG, .val.long_val = v} + +#define VAL_DOUBLE(s, v) \ + {s, CFG_DOUBLE, .val.double_val = v} + +#define VAL_BYTE(s, v) \ + {s, CFG_BYTE, .val.byte = v} + +#define VAL_SHRT(s, v) \ + {s, CFG_SHORT, .val.short_val = v} + +#define VAL_INCR(s, v) \ + {s, CFG_INCREMENT, .val.increment = v} + +#define VAL_STRING(s, m, v) \ + {s, CFG_STRING, .val.string = v} + +union argconfig_val { + char *string; + size_t size; + int int_val; + int bool_val; + uint8_t byte; + uint16_t short_val; + uint32_t positive; + int increment; + unsigned long long_val; + uint64_t long_suffix; + double double_val; + bool flag; +}; + +struct argconfig_opt_val { + const char *str; + enum argconfig_types type; + union argconfig_val val; +}; struct argconfig_commandline_options { const char *option; @@ -111,28 +161,20 @@ struct argconfig_commandline_options { int argument_type; const char *help; bool seen; + struct argconfig_opt_val *opt_val; }; -#define CFG_MAX_SUBOPTS 500 -#define MAX_HELP_FUNC 20 - -typedef void argconfig_help_func(); void argconfig_append_usage(const char *str); void argconfig_print_help(const char *program_desc, struct argconfig_commandline_options *options); int argconfig_parse(int argc, char *argv[], const char *program_desc, struct argconfig_commandline_options *options); -int argconfig_parse_subopt_string(char *string, char **options, - size_t max_options); -int argconfig_parse_comma_sep_array(char *string, int *ret, - unsigned max_length); +int argconfig_parse_comma_sep_array(char *string, int *ret, unsigned int max_length); int argconfig_parse_comma_sep_array_short(char *string, unsigned short *ret, - unsigned max_length); -int argconfig_parse_comma_sep_array_long(char *string, - unsigned long long *ret, - unsigned max_length); + unsigned int max_length); +int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *ret, + unsigned int 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, FILE *stream); bool argconfig_parse_seen(struct argconfig_commandline_options *options, diff --git a/util/base64.c b/util/base64.c index 07f975c..7f47cda 100644 --- a/util/base64.c +++ b/util/base64.c @@ -81,24 +81,24 @@ int base64_decode(const char *src, int srclen, unsigned char *dst) int i, bits = 0; unsigned char *bp = dst; - for (i = 0; i < srclen; i++) { - const char *p = strchr(base64_table, src[i]); + for (i = 0; i < srclen; i++) { + const char *p = strchr(base64_table, src[i]); - if (src[i] == '=') { - ac = (ac << 6); + if (src[i] == '=') { + ac = (ac << 6); bits += 6; if (bits >= 8) bits -= 8; - continue; - } - if (p == NULL || src[i] == 0) - return -EINVAL; - ac = (ac << 6) | (p - base64_table); - bits += 6; - if (bits >= 8) { - bits -= 8; - *bp++ = (unsigned char)(ac >> bits); - } + continue; + } + if (!p || !src[i]) + return -EINVAL; + ac = (ac << 6) | (p - base64_table); + bits += 6; + if (bits >= 8) { + bits -= 8; + *bp++ = (unsigned char)(ac >> bits); + } } if (ac && ((1 << bits) - 1)) return -EAGAIN; diff --git a/util/crc32.c b/util/crc32.c index cc2d8f2..bb5f129 100644 --- a/util/crc32.c +++ b/util/crc32.c @@ -1,99 +1,100 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/* Copyright (C) 2002 Red Hat, Inc. - This file is part of elfutils. - - This file is free software; you can redistribute it and/or modify - it under the terms of either - - * the GNU Lesser General Public License as published by the Free - Software Foundation; either version 3 of the License, or (at - your option) any later version - - or - - * the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at - your option) any later version - - or both in parallel, as here. - - elfutils 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 copies of the GNU General Public License and - the GNU Lesser General Public License along with this program. If - not, see . */ +/* + * Copyright (C) 2002 Red Hat, Inc. + * This file is part of elfutils. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * * the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version + * + * or + * + * * the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at + * your option) any later version + * + * or both in parallel, as here. + * + * elfutils 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 copies of the GNU General Public License and + * the GNU Lesser General Public License along with this program. If + * not, see . + */ /* https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/crc32.c;hb=575198c29a427392823cc8f2400579a23d06a875 */ #include "crc32.h" /* Table computed with Mark Adler's makecrc.c utility. */ -static const uint32_t crc32_table[256] = -{ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d +static const uint32_t crc32_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d }; -uint32_t crc32 (uint32_t crc, unsigned char *buf, size_t len) +uint32_t crc32(uint32_t crc, unsigned char *buf, size_t len) { - unsigned char *end; + unsigned char *end; - crc = ~crc; - for (end = buf + len; buf < end; ++buf) - crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); - return ~crc; + crc = ~crc; + for (end = buf + len; buf < end; ++buf) + crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); + return ~crc; } diff --git a/util/suffix.c b/util/suffix.c index 8ed080d..f010f3b 100644 --- a/util/suffix.c +++ b/util/suffix.c @@ -40,6 +40,7 @@ #include #include #include +#include static struct si_suffix { long double magnitude; @@ -68,11 +69,26 @@ const char *suffix_si_get(double *value) return suffix; } +static bool suffix_si_check(const char val) +{ + int i; + struct si_suffix *s; + + for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) { + s = &si_suffixes[i]; + + if (val == *s->suffix) + return true; + } + + return false; +} + int suffix_si_parse(const char *str, char **endptr, uint64_t *val) { - unsigned long long num, frac; + unsigned long long num, frac = 0; char *sep, *tmp; - int frac_len, len, i; + int frac_len = 0, len, i; num = strtoull(str, endptr, 0); if (str == *endptr || @@ -93,23 +109,31 @@ int suffix_si_parse(const char *str, char **endptr, uint64_t *val) len = 0; for (i = 0; i < len; i++) { + if (suffix_si_check((*endptr)[i])) + break; if (((*endptr)[i] == '\0') || (*endptr)[i] != sep[i]) return -EINVAL; } - *endptr += len; - tmp = *endptr; - /* extract the digits after decimal point */ - frac = strtoull(tmp, endptr, 0); - if (tmp == *endptr || - ((frac == ULLONG_MAX) && errno == ERANGE)) - return -EINVAL; + if (suffix_si_check((*endptr)[i])) { + if ((*endptr)[i + 1] != '\0') + return -EINVAL; + } else { + *endptr += len; + tmp = *endptr; + + /* extract the digits after decimal point */ + frac = strtoull(tmp, endptr, 0); + if (tmp == *endptr || + ((frac == ULLONG_MAX) && errno == ERANGE)) + return -EINVAL; - /* test that we have max one character as suffix */ - if ((*endptr)[0] != '\0' && (*endptr)[1] != '\0') - return -EINVAL; + /* test that we have max one character as suffix */ + if ((*endptr)[0] != '\0' && (*endptr)[1] != '\0') + return -EINVAL; - frac_len = *endptr - tmp; + frac_len = *endptr - tmp; + } for (i = 0; i < ARRAY_SIZE(si_suffixes); i++) { struct si_suffix *s = &si_suffixes[i]; diff --git a/util/types.c b/util/types.c index daef298..044391d 100644 --- a/util/types.c +++ b/util/types.c @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -14,6 +15,7 @@ nvme_uint128_t le128_to_cpu(__u8 *data) { nvme_uint128_t u; nvme_uint128_t tmp; + memcpy(tmp.bytes, data, 16); u.words[0] = le32_to_cpu(tmp.words[3]); u.words[1] = le32_to_cpu(tmp.words[2]); @@ -24,8 +26,8 @@ nvme_uint128_t le128_to_cpu(__u8 *data) long double int128_to_double(__u8 *data) { - int i; long double result = 0; + int i; for (i = 0; i < 16; i++) { result *= 256; @@ -48,8 +50,8 @@ uint64_t int48_to_long(__u8 *data) static long double uint128_t_to_double(nvme_uint128_t data) { - int i; long double result = 0; + int i; for (i = 0; i < sizeof(data.words) / sizeof(*data.words); i++) { result *= 4294967296; @@ -117,8 +119,8 @@ char *uint128_t_to_l10n_string(nvme_uint128_t val) 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; + static char str[40]; const char *suffix = suffix_si_get_ld(&bytes); int n = snprintf(str, sizeof(str), "%.2Lf %sB", bytes, suffix); @@ -150,3 +152,52 @@ const char *util_fw_to_string(char *c) ret[i] = '\0'; return ret; } + +int convert_ts(time_t time, char *ts_buf) +{ + struct tm time_info; + time_t time_human, time_ms; + char buf[80]; + + time_human = time / 1000; + time_ms = time % 1000; + + gmtime_r((const time_t *)&time_human, &time_info); + + strftime(buf, sizeof(buf), "%Y-%m-%dD|%H:%M:%S", &time_info); + sprintf(ts_buf, "%s:%03ld", buf, time_ms); + + return 0; +} + +void util_spinner(const char *disp_name, float percent) +{ + static const char dash[51] = {[0 ... 49] = '=', '\0'}; + static const char space[51] = {[0 ... 49] = ' ', '\0'}; + static const char spin[] = {'-', '\\', '|', '/' }; + static int progress; + static int i; + const char *dn = disp_name ? disp_name : ""; + + if (percent < 0) + percent = 0; + else if (percent > 1) + percent = 1; + + progress = (int)(percent * 100.0); + if (progress < 2) + printf("\r%s [%c%.*s] %3d%%", dn, + spin[i % 4], 49, + space, progress); + else if (progress < 100) + printf("\r%s [%.*s%c%.*s] %3d%%", dn, + progress / 2 - 1, dash, + spin[i % 4], 50 - progress / 2, + space, progress); + else + printf("\r%s [%.*s] %3d%%\n", dn, + 50, dash, 100); + i++; + + fflush(stdout); +} diff --git a/util/types.h b/util/types.h index f7fe9fc..595958b 100644 --- a/util/types.h +++ b/util/types.h @@ -34,4 +34,27 @@ 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); +/** + * @brief convert time_t format time to a human readable string + * + * @param time, input time_t time + * @param ts_buf, output time string + * @Note, time string format is "Y-M-D|H:M:S:MS" + * + * @return 0 success + */ +int convert_ts(time_t time, char *ts_buf); + +/** + * @brief print once a progress of spinner to stdout + * the output will be looks like if disp_name is "LogDump" and percent is 0.5 + * LogDump [========================- ] 50% + + * + * @param disp_name, const string displayed before spiner + * @param percent [0, 1.0] about the progress + * + */ +void util_spinner(const char *disp_name, float percent); + #endif /* _MISC_H */ -- cgit v1.2.3