Merging upstream version 2.10.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
736f2f7c80
commit
37275c4af3
530 changed files with 12276 additions and 4877 deletions
324
util/argconfig.c
324
util/argconfig.c
|
@ -30,6 +30,7 @@
|
|||
*/
|
||||
|
||||
#include "argconfig.h"
|
||||
#include "cleanup.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
@ -43,10 +44,12 @@
|
|||
#include <stdbool.h>
|
||||
#include <locale.h>
|
||||
|
||||
static const char *append_usage_str = "";
|
||||
static bool is_null_or_empty(const char *s)
|
||||
{
|
||||
return !s || !*s;
|
||||
}
|
||||
|
||||
static int argconfig_parse_val(struct argconfig_commandline_options *s, struct option *option,
|
||||
int index);
|
||||
static const char *append_usage_str = "";
|
||||
|
||||
void argconfig_append_usage(const char *str)
|
||||
{
|
||||
|
@ -134,7 +137,7 @@ void argconfig_print_help(const char *program_desc,
|
|||
return;
|
||||
|
||||
fprintf(stderr, "\n\033[1mOptions:\033[0m\n");
|
||||
for (; s && s->option; s++)
|
||||
for (; s->option; s++)
|
||||
show_option(s);
|
||||
}
|
||||
|
||||
|
@ -144,23 +147,9 @@ static int argconfig_error(char *type, const char *opt, const char *arg)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int argconfig_parse_byte(const char *opt, const char *str, unsigned char *val)
|
||||
static int argconfig_parse_type(struct argconfig_commandline_options *s)
|
||||
{
|
||||
char *endptr;
|
||||
unsigned long tmp = strtoul(str, &endptr, 0);
|
||||
|
||||
if (errno || tmp >= 1 << 8 || str == endptr)
|
||||
return argconfig_error("byte", opt, str);
|
||||
|
||||
*val = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int argconfig_parse_type(struct argconfig_commandline_options *s, struct option *option,
|
||||
int index)
|
||||
{
|
||||
void *value = (void *)(char *)s->default_value;
|
||||
void *value = s->default_value;
|
||||
char *endptr;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -168,87 +157,67 @@ static int argconfig_parse_type(struct argconfig_commandline_options *s, struct
|
|||
|
||||
switch (s->config_type) {
|
||||
case CFG_STRING:
|
||||
*((char **)value) = optarg;
|
||||
break;
|
||||
case CFG_SIZE:
|
||||
*((size_t *)value) = strtol(optarg, &endptr, 0);
|
||||
if (errno || optarg == endptr)
|
||||
ret = argconfig_error("integer", option[index].name, optarg);
|
||||
*(char **)value = optarg;
|
||||
break;
|
||||
case CFG_INT:
|
||||
*((int *)value) = strtol(optarg, &endptr, 0);
|
||||
*(int *)value = strtol(optarg, &endptr, 0);
|
||||
if (errno || optarg == endptr)
|
||||
ret = argconfig_error("integer", option[index].name, optarg);
|
||||
ret = argconfig_error("integer", s->option, optarg);
|
||||
break;
|
||||
case CFG_BYTE:
|
||||
ret = argconfig_parse_byte(option[index].name, optarg, (uint8_t *)value);
|
||||
case CFG_BYTE: {
|
||||
unsigned long tmp = strtoul(optarg, &endptr, 0);
|
||||
|
||||
if (errno || tmp >= 1 << 8 || optarg == endptr)
|
||||
ret = argconfig_error("byte", s->option, optarg);
|
||||
else
|
||||
*(uint8_t *)value = tmp;
|
||||
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);
|
||||
ret = argconfig_error("short", s->option, optarg);
|
||||
else
|
||||
*((uint16_t *)value) = tmp;
|
||||
*(uint16_t *)value = tmp;
|
||||
break;
|
||||
}
|
||||
case CFG_POSITIVE: {
|
||||
uint32_t tmp = strtoul(optarg, &endptr, 0);
|
||||
|
||||
if (errno || optarg == endptr)
|
||||
ret = argconfig_error("word", option[index].name, optarg);
|
||||
ret = argconfig_error("word", s->option, optarg);
|
||||
else
|
||||
*((uint32_t *)value) = tmp;
|
||||
*(uint32_t *)value = tmp;
|
||||
break;
|
||||
}
|
||||
case CFG_INCREMENT:
|
||||
*((int *)value) += 1;
|
||||
*(int *)value += 1;
|
||||
break;
|
||||
case CFG_LONG:
|
||||
*((unsigned long *)value) = strtoul(optarg, &endptr, 0);
|
||||
*(unsigned long *)value = strtoul(optarg, &endptr, 0);
|
||||
if (errno || optarg == endptr)
|
||||
ret = argconfig_error("long integer", option[index].name, optarg);
|
||||
ret = argconfig_error("long integer", s->option, optarg);
|
||||
break;
|
||||
case CFG_LONG_SUFFIX:
|
||||
ret = suffix_binary_parse(optarg, &endptr, (uint64_t *)value);
|
||||
if (ret)
|
||||
argconfig_error("long suffixed integer", option[index].name, optarg);
|
||||
argconfig_error("long suffixed integer", s->option, optarg);
|
||||
break;
|
||||
case CFG_DOUBLE:
|
||||
*((double *)value) = strtod(optarg, &endptr);
|
||||
*(double *)value = strtod(optarg, &endptr);
|
||||
if (errno || optarg == endptr)
|
||||
ret = argconfig_error("float", option[index].name, optarg);
|
||||
ret = argconfig_error("float", s->option, optarg);
|
||||
break;
|
||||
case CFG_FLAG:
|
||||
*((bool *)value) = true;
|
||||
break;
|
||||
default:
|
||||
*(bool *)value = true;
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
static void argconfig_set_opt_val(enum argconfig_types type, union argconfig_val *opt_val, void *val)
|
||||
{
|
||||
switch (type) {
|
||||
case CFG_FLAG:
|
||||
|
@ -281,30 +250,39 @@ static int argconfig_set_opt_val(enum argconfig_types type, union argconfig_val
|
|||
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)
|
||||
static struct argconfig_opt_val *
|
||||
argconfig_match_val(struct argconfig_opt_val *v, const char *str)
|
||||
{
|
||||
const char *str = optarg;
|
||||
void *val = s->default_value;
|
||||
int len = strlen(optarg);
|
||||
struct argconfig_opt_val *v;
|
||||
int val_len;
|
||||
size_t len = strlen(str);
|
||||
struct argconfig_opt_val *match = NULL;
|
||||
|
||||
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))
|
||||
for (; v->str; v++) {
|
||||
if (strncasecmp(str, v->str, len))
|
||||
continue;
|
||||
return argconfig_set_opt_val(v->type, &v->val, val);
|
||||
|
||||
if (match)
|
||||
return NULL; /* multiple matches; input is ambiguous */
|
||||
|
||||
match = v;
|
||||
}
|
||||
|
||||
return argconfig_parse_type(s, option, index);
|
||||
return match;
|
||||
}
|
||||
|
||||
static int argconfig_parse_val(struct argconfig_commandline_options *s)
|
||||
{
|
||||
struct argconfig_opt_val *v = s->opt_val;
|
||||
|
||||
if (v)
|
||||
v = argconfig_match_val(v, optarg);
|
||||
if (!v)
|
||||
return argconfig_parse_type(s);
|
||||
|
||||
argconfig_set_opt_val(v->type, &v->val, s->default_value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool argconfig_check_human_readable(struct argconfig_commandline_options *s)
|
||||
|
@ -320,8 +298,8 @@ static bool argconfig_check_human_readable(struct argconfig_commandline_options
|
|||
int argconfig_parse(int argc, char *argv[], const char *program_desc,
|
||||
struct argconfig_commandline_options *options)
|
||||
{
|
||||
char *short_opts;
|
||||
struct option *long_opts;
|
||||
_cleanup_free_ char *short_opts = NULL;
|
||||
_cleanup_free_ struct option *long_opts = NULL;
|
||||
struct argconfig_commandline_options *s;
|
||||
int c, option_index = 0, short_index = 0, options_count = 0;
|
||||
int ret = 0;
|
||||
|
@ -330,16 +308,15 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc,
|
|||
for (s = options; s->option; s++)
|
||||
options_count++;
|
||||
|
||||
long_opts = calloc(1, sizeof(struct option) * (options_count + 3));
|
||||
short_opts = calloc(1, sizeof(*short_opts) * (options_count * 3 + 5));
|
||||
long_opts = calloc(options_count + 2, sizeof(struct option));
|
||||
short_opts = calloc(options_count * 3 + 3, sizeof(*short_opts));
|
||||
|
||||
if (!long_opts || !short_opts) {
|
||||
fprintf(stderr, "failed to allocate memory for opts: %s\n", strerror(errno));
|
||||
ret = -errno;
|
||||
goto out;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
for (s = options; s->option && option_index < options_count; s++) {
|
||||
for (s = options; s->option; s++) {
|
||||
if (s->short_option) {
|
||||
short_opts[short_index++] = s->short_option;
|
||||
if (s->argument_type == required_argument ||
|
||||
|
@ -348,7 +325,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc,
|
|||
if (s->argument_type == optional_argument)
|
||||
short_opts[short_index++] = ':';
|
||||
}
|
||||
if (s->option && strlen(s->option)) {
|
||||
if (!is_null_or_empty(s->option)) {
|
||||
long_opts[option_index].name = s->option;
|
||||
long_opts[option_index].has_arg = s->argument_type;
|
||||
}
|
||||
|
@ -384,10 +361,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc,
|
|||
if (!s->default_value)
|
||||
continue;
|
||||
|
||||
if (s->opt_val)
|
||||
ret = argconfig_parse_val(s, long_opts, option_index);
|
||||
else
|
||||
ret = argconfig_parse_type(s, long_opts, option_index);
|
||||
ret = argconfig_parse_val(s);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
@ -395,139 +369,12 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc,
|
|||
if (!argconfig_check_human_readable(options))
|
||||
setlocale(LC_ALL, "C");
|
||||
|
||||
out:
|
||||
free(short_opts);
|
||||
free(long_opts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int argconfig_parse_comma_sep_array(char *string, int *val, unsigned int max_length)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long v;
|
||||
char *tmp;
|
||||
char *p;
|
||||
|
||||
if (!string || !strlen(string))
|
||||
return 0;
|
||||
|
||||
tmp = strtok(string, ",");
|
||||
if (!tmp)
|
||||
return 0;
|
||||
|
||||
v = strtoul(tmp, &p, 0);
|
||||
if (*p != 0)
|
||||
return -1;
|
||||
if (v > UINT_MAX) {
|
||||
fprintf(stderr, "%s out of range\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
val[ret] = v;
|
||||
|
||||
ret++;
|
||||
while (1) {
|
||||
tmp = strtok(NULL, ",");
|
||||
|
||||
if (tmp == NULL)
|
||||
return ret;
|
||||
|
||||
if (ret >= max_length)
|
||||
return -1;
|
||||
|
||||
v = strtoul(tmp, &p, 0);
|
||||
if (*p != 0)
|
||||
return -1;
|
||||
if (v > UINT_MAX) {
|
||||
fprintf(stderr, "%s out of range\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
val[ret] = v;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
int argconfig_parse_comma_sep_array_short(char *string, unsigned short *val,
|
||||
unsigned int max_length)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long v;
|
||||
char *tmp;
|
||||
char *p;
|
||||
|
||||
if (!string || !strlen(string))
|
||||
return 0;
|
||||
|
||||
tmp = strtok(string, ",");
|
||||
if (!tmp)
|
||||
return 0;
|
||||
|
||||
v = strtoul(tmp, &p, 0);
|
||||
if (*p != 0)
|
||||
return -1;
|
||||
if (v > UINT16_MAX) {
|
||||
fprintf(stderr, "%s out of range\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
val[ret] = v;
|
||||
ret++;
|
||||
|
||||
while (1) {
|
||||
tmp = strtok(NULL, ",");
|
||||
if (tmp == NULL)
|
||||
return ret;
|
||||
|
||||
if (ret >= max_length)
|
||||
return -1;
|
||||
|
||||
v = strtoul(tmp, &p, 0);
|
||||
if (*p != 0)
|
||||
return -1;
|
||||
if (v > UINT16_MAX) {
|
||||
fprintf(stderr, "%s out of range\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
val[ret] = v;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
int argconfig_parse_comma_sep_array_long(char *string, unsigned long long *val,
|
||||
unsigned int max_length)
|
||||
{
|
||||
int ret = 0;
|
||||
char *tmp;
|
||||
char *p;
|
||||
|
||||
if (!string || !strlen(string))
|
||||
return 0;
|
||||
|
||||
tmp = strtok(string, ",");
|
||||
if (tmp == NULL)
|
||||
return 0;
|
||||
|
||||
val[ret] = strtoll(tmp, &p, 0);
|
||||
if (*p != 0)
|
||||
return -1;
|
||||
ret++;
|
||||
while (1) {
|
||||
tmp = strtok(NULL, ",");
|
||||
|
||||
if (tmp == NULL)
|
||||
return ret;
|
||||
|
||||
if (ret >= max_length)
|
||||
return -1;
|
||||
|
||||
val[ret] = strtoll(tmp, &p, 0);
|
||||
if (*p != 0)
|
||||
return -1;
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(size) \
|
||||
int argconfig_parse_comma_sep_array_u##size(char *string, \
|
||||
__u##size *val, \
|
||||
#define DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(name, ret_t, ret_max) \
|
||||
int argconfig_parse_comma_sep_array ## name(char *string, \
|
||||
ret_t *val, \
|
||||
unsigned int max_length) \
|
||||
{ \
|
||||
int ret = 0; \
|
||||
|
@ -535,44 +382,39 @@ int argconfig_parse_comma_sep_array_u##size(char *string, \
|
|||
char *tmp; \
|
||||
char *p; \
|
||||
\
|
||||
if (!string || !strlen(string)) \
|
||||
if (is_null_or_empty(string)) \
|
||||
return 0; \
|
||||
\
|
||||
tmp = strtok(string, ","); \
|
||||
if (!tmp) \
|
||||
return 0; \
|
||||
\
|
||||
v = strtoumax(tmp, &p, 0); \
|
||||
if (*p != 0) \
|
||||
return -1; \
|
||||
if (v > UINT##size##_MAX) { \
|
||||
fprintf(stderr, "%s out of range\n", tmp); \
|
||||
return -1; \
|
||||
} \
|
||||
val[ret] = v; \
|
||||
\
|
||||
ret++; \
|
||||
while (1) { \
|
||||
tmp = strtok(NULL, ","); \
|
||||
\
|
||||
if (tmp == NULL) \
|
||||
return ret; \
|
||||
\
|
||||
while (tmp) { \
|
||||
if (ret >= max_length) \
|
||||
return -1; \
|
||||
\
|
||||
v = strtoumax(tmp, &p, 0); \
|
||||
if (*p != 0) \
|
||||
return -1; \
|
||||
if (v > UINT##size##_MAX) { \
|
||||
if (v > ret_max) { \
|
||||
fprintf(stderr, "%s out of range\n", tmp); \
|
||||
return -1; \
|
||||
} \
|
||||
val[ret] = v; \
|
||||
ret++; \
|
||||
\
|
||||
tmp = strtok(NULL, ","); \
|
||||
} \
|
||||
\
|
||||
return ret; \
|
||||
}
|
||||
|
||||
DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(, int, UINT_MAX)
|
||||
DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(_short, unsigned short, UINT16_MAX)
|
||||
DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(_long, unsigned long long, ULLONG_MAX)
|
||||
|
||||
#define DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(size) \
|
||||
DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_FUNC(_u ## size, __u ## size, \
|
||||
UINT ## size ## _MAX)
|
||||
|
||||
DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(16);
|
||||
DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(32);
|
||||
DEFINE_ARGCONFIG_PARSE_COMMA_SEP_ARRAY_UINT_FUNC(64);
|
||||
|
|
|
@ -47,7 +47,6 @@ enum argconfig_types {
|
|||
CFG_FLAG,
|
||||
CFG_STRING,
|
||||
CFG_INT,
|
||||
CFG_SIZE,
|
||||
CFG_LONG,
|
||||
CFG_LONG_SUFFIX,
|
||||
CFG_DOUBLE,
|
||||
|
@ -181,7 +180,6 @@ int argconfig_parse_comma_sep_array_u32(char *string, __u32 *val,
|
|||
unsigned int max_length);
|
||||
int argconfig_parse_comma_sep_array_u64(char *string, __u64 *val,
|
||||
unsigned int max_length);
|
||||
int argconfig_parse_byte(const char *opt, const char *str, unsigned char *val);
|
||||
|
||||
void print_word_wrapped(const char *s, int indent, int start, FILE *stream);
|
||||
bool argconfig_parse_seen(struct argconfig_commandline_options *options,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
@ -42,7 +43,7 @@ static const char base64_table[65] =
|
|||
int base64_encode(const unsigned char *src, int srclen, char *dst)
|
||||
{
|
||||
int i, bits = 0;
|
||||
u_int32_t ac = 0;
|
||||
uint32_t ac = 0;
|
||||
char *cp = dst;
|
||||
|
||||
for (i = 0; i < srclen; i++) {
|
||||
|
@ -77,7 +78,7 @@ int base64_encode(const unsigned char *src, int srclen, char *dst)
|
|||
*/
|
||||
int base64_decode(const char *src, int srclen, unsigned char *dst)
|
||||
{
|
||||
u_int32_t ac = 0;
|
||||
uint32_t ac = 0;
|
||||
int i, bits = 0;
|
||||
unsigned char *bp = dst;
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <libnvme.h>
|
||||
|
||||
#include "util/mem.h"
|
||||
|
||||
#define __cleanup__(fn) __attribute__((cleanup(fn)))
|
||||
|
@ -21,17 +23,36 @@ DECLARE_CLEANUP_FUNC(name, type) \
|
|||
|
||||
static inline void freep(void *p)
|
||||
{
|
||||
free(*(void**) p);
|
||||
free(*(void **)p);
|
||||
}
|
||||
#define _cleanup_free_ __cleanup__(freep)
|
||||
|
||||
#define _cleanup_huge_ __cleanup__(nvme_free_huge)
|
||||
|
||||
static inline void close_file(int *f)
|
||||
static inline void cleanup_fd(int *fd)
|
||||
{
|
||||
if (*f > STDERR_FILENO)
|
||||
close(*f);
|
||||
if (*fd > STDERR_FILENO)
|
||||
close(*fd);
|
||||
}
|
||||
#define _cleanup_file_ __cleanup__(close_file)
|
||||
#define _cleanup_fd_ __cleanup__(cleanup_fd)
|
||||
|
||||
#endif
|
||||
static inline void cleanup_nvme_root(nvme_root_t *r)
|
||||
{
|
||||
nvme_free_tree(*r);
|
||||
}
|
||||
#define _cleanup_nvme_root_ __cleanup__(cleanup_nvme_root)
|
||||
|
||||
static inline DEFINE_CLEANUP_FUNC(cleanup_nvme_ctrl, nvme_ctrl_t, nvme_free_ctrl)
|
||||
#define _cleanup_nvme_ctrl_ __cleanup__(cleanup_nvme_ctrl)
|
||||
|
||||
static inline void free_uri(struct nvme_fabrics_uri **uri)
|
||||
{
|
||||
if (*uri)
|
||||
nvme_free_uri(*uri);
|
||||
}
|
||||
#define _cleanup_uri_ __cleanup__(free_uri)
|
||||
|
||||
static inline DEFINE_CLEANUP_FUNC(cleanup_file, FILE *, fclose)
|
||||
#define _cleanup_file_ __cleanup__(cleanup_file)
|
||||
|
||||
#endif /* __CLEANUP_H */
|
||||
|
|
|
@ -56,6 +56,8 @@ uint64_t util_json_object_get_uint64(struct json_object *obj);
|
|||
|
||||
struct json_object;
|
||||
|
||||
#define json_object_add_value_string(o, k, v)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -92,15 +92,14 @@ int nvme_submit_passthru(int fd, unsigned long ioctl_cmd,
|
|||
struct timeval end;
|
||||
int err;
|
||||
|
||||
if (log_level >= LOG_INFO)
|
||||
if (log_level >= LOG_DEBUG)
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
err = ioctl(fd, ioctl_cmd, cmd);
|
||||
|
||||
if (log_level >= LOG_INFO) {
|
||||
if (log_level >= LOG_DEBUG) {
|
||||
gettimeofday(&end, NULL);
|
||||
if (log_level >= LOG_DEBUG)
|
||||
nvme_show_command(cmd, err);
|
||||
nvme_show_command(cmd, err);
|
||||
nvme_show_latency(start, end);
|
||||
}
|
||||
|
||||
|
@ -118,16 +117,15 @@ int nvme_submit_passthru64(int fd, unsigned long ioctl_cmd,
|
|||
struct timeval end;
|
||||
int err;
|
||||
|
||||
if (log_level >= LOG_INFO)
|
||||
if (log_level >= LOG_DEBUG)
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
|
||||
err = ioctl(fd, ioctl_cmd, cmd);
|
||||
|
||||
if (log_level >= LOG_INFO) {
|
||||
if (log_level >= LOG_DEBUG) {
|
||||
gettimeofday(&end, NULL);
|
||||
if (log_level >= LOG_DEBUG)
|
||||
nvme_show_command64(cmd, err);
|
||||
nvme_show_command64(cmd, err);
|
||||
nvme_show_latency(start, end);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ sources += [
|
|||
'util/mem.c',
|
||||
'util/suffix.c',
|
||||
'util/types.c',
|
||||
'util/utils.c'
|
||||
]
|
||||
|
||||
if json_c_dep.found()
|
||||
|
|
10
util/types.h
10
util/types.h
|
@ -16,6 +16,16 @@ static inline long kelvin_to_celsius(long t)
|
|||
return t + ABSOLUTE_ZERO_CELSIUS;
|
||||
}
|
||||
|
||||
static inline long celsius_to_fahrenheit(long t)
|
||||
{
|
||||
return t * 9 / 5 + 32;
|
||||
}
|
||||
|
||||
static inline long kelvin_to_fahrenheit(long t)
|
||||
{
|
||||
return celsius_to_fahrenheit(kelvin_to_celsius(t));
|
||||
}
|
||||
|
||||
/* uint128_t is not always available, define our own. */
|
||||
union nvme_uint128 {
|
||||
__u8 bytes[16];
|
||||
|
|
305
util/utils.c
Normal file
305
util/utils.c
Normal file
|
@ -0,0 +1,305 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) Micron, Inc 2024.
|
||||
*
|
||||
* @file: micron-utils.h
|
||||
* @brief: This module contains all the utilities needed for other modules.
|
||||
* @author: Chaithanya Shoba <ashoba@micron.com>
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
#include "types.h"
|
||||
#include "json.h"
|
||||
|
||||
int hex_to_int(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return 10 + (c - 'A');
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return 10 + (c - 'a');
|
||||
else
|
||||
return -1; // Invalid character
|
||||
}
|
||||
|
||||
char *hex_to_ascii(const char *hex)
|
||||
{
|
||||
int hex_length = strlen(hex);
|
||||
|
||||
char *text = NULL;
|
||||
|
||||
if (hex_length > 0) {
|
||||
int symbol_count;
|
||||
int odd_hex_count = hex_length % 2 == 1;
|
||||
|
||||
if (odd_hex_count)
|
||||
symbol_count = (hex_length / 2) + 1;
|
||||
else
|
||||
symbol_count = hex_length / 2;
|
||||
|
||||
text = (char *)malloc(symbol_count + 1); // Allocate memory for the result
|
||||
|
||||
int last_index = hex_length - 1;
|
||||
|
||||
for (int i = last_index; i >= 0; --i) {
|
||||
if ((last_index - i) % 2 != 0) {
|
||||
int dec = 16 * hex_to_int(hex[i]) + hex_to_int(hex[i + 1]);
|
||||
|
||||
if (odd_hex_count)
|
||||
text[i / 2 + 1] = dec;
|
||||
else
|
||||
text[i / 2] = dec;
|
||||
} else if (i == 0) {
|
||||
int dec = hex_to_int(hex[0]);
|
||||
|
||||
text[0] = dec;
|
||||
}
|
||||
}
|
||||
|
||||
text[symbol_count] = '\0'; // Terminate the string
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
unsigned char *read_binary_file(char *data_dir_path, const char *bin_path,
|
||||
long *buffer_size, int retry_count)
|
||||
{
|
||||
char *file_path = NULL;
|
||||
FILE *bin_file = NULL;
|
||||
size_t n_data = 0;
|
||||
unsigned char *buffer = NULL;
|
||||
|
||||
/* set path */
|
||||
if (data_dir_path == NULL) {
|
||||
file_path = (char *)bin_path;
|
||||
} else {
|
||||
/* +2 for the / and null terminator */
|
||||
file_path = (char *) calloc(1, strlen(data_dir_path) + strlen(bin_path) + 2);
|
||||
if (!file_path)
|
||||
return NULL;
|
||||
|
||||
if (strlen(bin_path) != 0)
|
||||
sprintf(file_path, "%s/%s", data_dir_path, bin_path);
|
||||
else
|
||||
sprintf(file_path, "%s", data_dir_path);
|
||||
}
|
||||
|
||||
/* open file */
|
||||
for (int i = 0; i < retry_count; i++) {
|
||||
bin_file = fopen(file_path, "rb");
|
||||
if (bin_file != NULL)
|
||||
break;
|
||||
sleep((unsigned int)(retry_count > 1));
|
||||
}
|
||||
|
||||
if (!bin_file) {
|
||||
nvme_show_error("\nFailed to open %s", file_path);
|
||||
if (file_path != bin_path)
|
||||
free(file_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get size */
|
||||
fseek(bin_file, 0, SEEK_END);
|
||||
*buffer_size = ftell(bin_file);
|
||||
fseek(bin_file, 0, SEEK_SET);
|
||||
if (*buffer_size <= 0) {
|
||||
fclose(bin_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* allocate buffer */
|
||||
buffer = (unsigned char *)malloc(*buffer_size);
|
||||
if (!buffer) {
|
||||
nvme_show_result("\nFailed to allocate %ld bytes!", *buffer_size);
|
||||
fclose(bin_file);
|
||||
return NULL;
|
||||
}
|
||||
memset(buffer, 0, *buffer_size);
|
||||
|
||||
/* Read data */
|
||||
n_data = fread(buffer, 1, *buffer_size, bin_file);
|
||||
|
||||
/* Close file */
|
||||
fclose(bin_file);
|
||||
|
||||
/* Validate we read data */
|
||||
if (n_data != (size_t)*buffer_size) {
|
||||
nvme_show_result("\nFailed to read %ld bytes from %s", *buffer_size, file_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (file_path != bin_path)
|
||||
free(file_path);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void print_formatted_var_size_str(const char *msg, const __u8 *pdata, size_t data_size, FILE *fp)
|
||||
{
|
||||
char description_str[256] = "";
|
||||
char temp_buffer[3] = { 0 };
|
||||
|
||||
for (size_t i = 0; i < data_size; ++i) {
|
||||
sprintf(temp_buffer, "%02X", pdata[i]);
|
||||
strcat(description_str, temp_buffer);
|
||||
}
|
||||
|
||||
if (fp)
|
||||
fprintf(fp, "%s: %s\n", msg, description_str);
|
||||
else
|
||||
printf("%s: %s\n", msg, description_str);
|
||||
}
|
||||
|
||||
void process_field_size_16(int offset, char *sfield, __u8 *buf, char *datastr)
|
||||
{
|
||||
__u64 lval_lo, lval_hi;
|
||||
|
||||
if (strstr(sfield, "GUID")) {
|
||||
sprintf(datastr, "0x%"PRIx64"%"PRIx64"",
|
||||
le64_to_cpu(*(__u64 *)(&buf[offset + 8])),
|
||||
le64_to_cpu(*(__u64 *)(&buf[offset])));
|
||||
} else {
|
||||
lval_lo = *((__u64 *)(&buf[offset]));
|
||||
lval_hi = *((__u64 *)(&buf[offset + 8]));
|
||||
|
||||
if (lval_hi)
|
||||
sprintf(datastr, "0x%"PRIx64"%016"PRIx64"",
|
||||
le64_to_cpu(lval_hi), le64_to_cpu(lval_lo));
|
||||
else
|
||||
sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo));
|
||||
}
|
||||
}
|
||||
|
||||
void process_field_size_8(int offset, char *sfield, __u8 *buf, char *datastr)
|
||||
{
|
||||
__u64 lval_lo;
|
||||
|
||||
if (strstr(sfield, "Boot SSD Spec Version")) {
|
||||
sprintf(datastr, "%x.%x.%x.%x",
|
||||
le16_to_cpu(*((__u16 *)(&buf[300]))),
|
||||
le16_to_cpu(*((__u16 *)(&buf[302]))),
|
||||
le16_to_cpu(*((__u16 *)(&buf[304]))),
|
||||
le16_to_cpu(*((__u16 *)(&buf[306]))));
|
||||
} else if (strstr(sfield, "Firmware Revision")) {
|
||||
char buffer[30] = {'\0'};
|
||||
|
||||
lval_lo = *((__u64 *)(&buf[offset]));
|
||||
|
||||
sprintf(buffer, "%"PRIx64, __builtin_bswap64(lval_lo));
|
||||
sprintf(datastr, "%s", hex_to_ascii(buffer));
|
||||
} else if (strstr(sfield, "Timestamp")) {
|
||||
char ts_buf[128];
|
||||
|
||||
lval_lo = *((__u64 *)(&buf[offset]));
|
||||
|
||||
convert_ts(le64_to_cpu(lval_lo), ts_buf);
|
||||
sprintf(datastr, "%s", ts_buf);
|
||||
} else {
|
||||
lval_lo = *((__u64 *)(&buf[offset]));
|
||||
|
||||
sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo));
|
||||
}
|
||||
}
|
||||
|
||||
void process_field_size_7(int offset, char *sfield, __u8 *buf, char *datastr)
|
||||
{
|
||||
__u8 lval[8] = { 0 };
|
||||
__u64 lval_lo;
|
||||
|
||||
/* 7 bytes will be in little-endian format, with last byte as MSB */
|
||||
memcpy(&lval[0], &buf[offset], 7);
|
||||
memcpy((void *)&lval_lo, lval, 8);
|
||||
sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo));
|
||||
}
|
||||
|
||||
void process_field_size_6(int offset, char *sfield, __u8 *buf, char *datastr)
|
||||
{
|
||||
__u32 ival;
|
||||
__u16 sval;
|
||||
__u64 lval_lo;
|
||||
|
||||
if (strstr(sfield, "DSSD Spec Version")) {
|
||||
sprintf(datastr, "%x.%x.%x.%x", buf[103],
|
||||
le16_to_cpu(*((__u16 *)(&buf[101]))),
|
||||
le16_to_cpu(*((__u16 *)(&buf[99]))), buf[98]);
|
||||
} else {
|
||||
ival = *((__u32 *)(&buf[offset]));
|
||||
sval = *((__u16 *)(&buf[offset + 4]));
|
||||
lval_lo = (((__u64)sval << 32) | ival);
|
||||
|
||||
sprintf(datastr, "0x%"PRIx64"", le64_to_cpu(lval_lo));
|
||||
}
|
||||
}
|
||||
|
||||
void process_field_size_default(int offset, char *sfield, __u8 *buf, int size, char *datastr)
|
||||
{
|
||||
__u8 cval;
|
||||
char description_str[256] = "0x";
|
||||
char temp_buffer[3] = { 0 };
|
||||
|
||||
for (unsigned char i = 0; i < (unsigned char)size; i++) {
|
||||
cval = (buf[offset + i]);
|
||||
|
||||
sprintf(temp_buffer, "%02X", cval);
|
||||
strcat(description_str, temp_buffer);
|
||||
}
|
||||
sprintf(datastr, "%s", description_str);
|
||||
}
|
||||
|
||||
void generic_structure_parser(__u8 *buf, struct request_data *req_data, int field_count,
|
||||
struct json_object *stats, __u8 spec, FILE *fp)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
for (int field = 0; field < field_count; field++) {
|
||||
char datastr[1024] = { 0 };
|
||||
char *sfield = req_data[field].field;
|
||||
int size = !spec ? req_data[field].size : req_data[field].size2;
|
||||
|
||||
if (!size || sfield == NULL)
|
||||
continue;
|
||||
|
||||
switch (size) {
|
||||
case FIELD_SIZE_16:
|
||||
process_field_size_16(offset, sfield, buf, datastr);
|
||||
break;
|
||||
case FIELD_SIZE_8:
|
||||
process_field_size_8(offset, sfield, buf, datastr);
|
||||
break;
|
||||
case FIELD_SIZE_7:
|
||||
process_field_size_7(offset, sfield, buf, datastr);
|
||||
break;
|
||||
case FIELD_SIZE_6:
|
||||
process_field_size_6(offset, sfield, buf, datastr);
|
||||
break;
|
||||
case FIELD_SIZE_4:
|
||||
sprintf(datastr, "0x%x", le32_to_cpu(*((__u32 *)(&buf[offset]))));
|
||||
break;
|
||||
case FIELD_SIZE_3:
|
||||
sprintf(datastr, "0x%02X%02X%02X",
|
||||
buf[offset + 0], buf[offset + 1], buf[offset + 2]);
|
||||
break;
|
||||
case FIELD_SIZE_2:
|
||||
sprintf(datastr, "0x%04x", le16_to_cpu(*((__u16 *)(&buf[offset]))));
|
||||
break;
|
||||
case FIELD_SIZE_1:
|
||||
sprintf(datastr, "0x%02x", buf[offset]);
|
||||
break;
|
||||
default:
|
||||
process_field_size_default(offset, sfield, buf, size, datastr);
|
||||
break;
|
||||
}
|
||||
offset += size;
|
||||
/* do not print reserved values */
|
||||
if (strstr(sfield, "Reserved"))
|
||||
continue;
|
||||
if (stats)
|
||||
json_object_add_value_string(stats, sfield, datastr);
|
||||
else if (fp)
|
||||
fprintf(fp, "%-40s : %-4s\n", sfield, datastr);
|
||||
else
|
||||
printf("%-40s : %-4s\n", sfield, datastr);
|
||||
}
|
||||
}
|
150
util/utils.h
Normal file
150
util/utils.h
Normal file
|
@ -0,0 +1,150 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) Micron, Inc 2024.
|
||||
*
|
||||
* @file: utils.h
|
||||
* @brief: This module contains all the utilities needed for other modules.
|
||||
* @author: Chaithanya Shoba <ashoba@micron.com>
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
/*Request data format*/
|
||||
struct __packed request_data {
|
||||
char *field;
|
||||
int size;
|
||||
int size2;
|
||||
};
|
||||
|
||||
enum field_size {
|
||||
FIELD_SIZE_16 = 16,
|
||||
FIELD_SIZE_8 = 8,
|
||||
FIELD_SIZE_7 = 7,
|
||||
FIELD_SIZE_6 = 6,
|
||||
FIELD_SIZE_4 = 4,
|
||||
FIELD_SIZE_3 = 3,
|
||||
FIELD_SIZE_2 = 2,
|
||||
FIELD_SIZE_1 = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief converts a single hexadecimal character to its integer value.
|
||||
*
|
||||
* @param hex_char, input hex char
|
||||
* @param ts_buf, output time string
|
||||
*
|
||||
* @return integer value of hexadecimal
|
||||
*/
|
||||
int hex_to_int(char c);
|
||||
|
||||
/**
|
||||
* @brief convert time_t format time to a human readable string
|
||||
*
|
||||
* @param hex_string, input hex string pointer
|
||||
* @param ascii_buffer, output ascii buffer pointer
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
char *hex_to_ascii(const char *hex);
|
||||
|
||||
/**
|
||||
* @brief convert time_t format time to a human readable string
|
||||
*
|
||||
* @param data_dir_path, input data directory path pointer
|
||||
* @param bin_path, input binary file path pointer
|
||||
* @param buffer_size, input buffer size pointer
|
||||
* @param retry_count, input retry count
|
||||
*
|
||||
* @return pointer to binary data buffer
|
||||
*/
|
||||
unsigned char *read_binary_file(char *data_dir_path, const char *bin_path, long *buffer_size,
|
||||
int retry_count);
|
||||
|
||||
/**
|
||||
* @brief prints generic structure parser
|
||||
*
|
||||
* @param buf, input raw log data
|
||||
* @param log_page, input format of the data
|
||||
* @param field_count, intput log field count
|
||||
* @param stats, input json object to add fields
|
||||
* @param spec, input ocp spec index
|
||||
* @param fp, input file pointer
|
||||
*
|
||||
* @return 0 success
|
||||
*/
|
||||
void generic_structure_parser(__u8 *buf, struct request_data *req_data, int field_count,
|
||||
struct json_object *stats, __u8 spec, FILE *fp);
|
||||
|
||||
/**
|
||||
* @brief prints raw data to the buffer
|
||||
*
|
||||
* @param msg, intput buffer to write data
|
||||
* @param pdata, input raw data
|
||||
* @param data_size, input size of the data
|
||||
* @param fp, input file pointer
|
||||
*
|
||||
* @return 0 success
|
||||
*/
|
||||
void print_formatted_var_size_str(const char *msg, const __u8 *pdata, size_t data_size, FILE *fp);
|
||||
|
||||
/**
|
||||
* @brief prints raw data to the buffer
|
||||
*
|
||||
* @param offset, intput offset of the param
|
||||
* @param sfield, intput field
|
||||
* @param buf, input raw data
|
||||
* @param datastr, output data buffer
|
||||
*
|
||||
* @return 0 success
|
||||
*/
|
||||
void process_field_size_16(int offset, char *sfield, __u8 *buf, char *datastr);
|
||||
|
||||
/**
|
||||
* @brief prints raw data to the buffer
|
||||
*
|
||||
* @param offset, intput offset of the param
|
||||
* @param sfield, intput field
|
||||
* @param buf, input raw data
|
||||
* @param datastr, output data buffer
|
||||
*
|
||||
* @return 0 success
|
||||
*/
|
||||
void process_field_size_8(int offset, char *sfield, __u8 *buf, char *datastr);
|
||||
|
||||
/**
|
||||
* @brief prints raw data to the buffer
|
||||
*
|
||||
* @param offset, intput offset of the param
|
||||
* @param sfield, intput field
|
||||
* @param buf, input raw data
|
||||
* @param datastr, output data buffer
|
||||
*
|
||||
* @return 0 success
|
||||
*/
|
||||
void process_field_size_7(int offset, char *sfield, __u8 *buf, char *datastr);
|
||||
|
||||
/**
|
||||
* @brief prints raw data to the buffer
|
||||
*
|
||||
* @param offset, intput offset of the param
|
||||
* @param sfield, intput field
|
||||
* @param buf, input raw data
|
||||
* @param datastr, output data buffer
|
||||
*
|
||||
* @return 0 success
|
||||
*/
|
||||
void process_field_size_6(int offset, char *sfield, __u8 *buf, char *datastr);
|
||||
|
||||
/**
|
||||
* @brief prints raw data to the buffer
|
||||
*
|
||||
* @param offset, intput offset of the param
|
||||
* @param sfield, intput field
|
||||
* @param buf, input raw data
|
||||
* @param size, input data size
|
||||
* @param datastr, output data buffer
|
||||
*
|
||||
* @return 0 success
|
||||
*/
|
||||
void process_field_size_default(int offset, char *sfield, __u8 *buf, int size, char *datastr);
|
Loading…
Add table
Add a link
Reference in a new issue