X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;ds=sidebyside;f=parse.c;h=7dc5fcc869ff05b21accb95257bb4fa473d188f3;hb=77787c82d755cc8ab8fda82531dd648cfd127d8d;hp=8e29fabf8e64e87129d900fea6300a9b80a5daa7;hpb=5ec10eaad3b09875b91e19a20bbdfa06f2117562;p=fio.git diff --git a/parse.c b/parse.c index 8e29fabf..7dc5fcc8 100644 --- a/parse.c +++ b/parse.c @@ -8,10 +8,13 @@ #include #include #include +#include #include "parse.h" #include "debug.h" +static struct fio_option *fio_options; + static int vp_cmp(const void *p1, const void *p2) { const struct value_pair *vp1 = p1; @@ -109,13 +112,18 @@ static unsigned long get_mult_bytes(char c) */ int str_to_decimal(const char *str, long long *val, int kilo) { - int len; + int len, base; len = strlen(str); if (!len) return 1; - *val = strtoll(str, NULL, 10); + if (strstr(str, "0x") || strstr(str, "0X")) + base = 16; + else + base = 10; + + *val = strtoll(str, NULL, base); if (*val == LONG_MAX && errno == ERANGE) return 1; @@ -149,7 +157,7 @@ void strip_blank_front(char **p) void strip_blank_end(char *p) { - char *s; + char *start = p, *s; s = strchr(p, ';'); if (s) @@ -161,7 +169,7 @@ void strip_blank_end(char *p) p = s; s = p + strlen(p); - while ((isspace(*s) || iscntrl(*s)) && (s > p)) + while ((isspace(*s) || iscntrl(*s)) && (s > start)) s--; *(s + 1) = '\0'; @@ -233,7 +241,7 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name, o->type, ptr); - if (!ptr && o->type != FIO_OPT_STR_SET) { + if (!ptr && o->type != FIO_OPT_STR_SET && o->type != FIO_OPT_STR) { fprintf(stderr, "Option %s requires an argument\n", o->name); return 1; } @@ -269,6 +277,7 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, } case FIO_OPT_STR_VAL_TIME: is_time = 1; + case FIO_OPT_INT: case FIO_OPT_STR_VAL: case FIO_OPT_STR_VAL_INT: { fio_opt_str_val_fn *fn = o->cb; @@ -295,7 +304,8 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, if (fn) ret = fn(data, &ull); else { - if (o->type == FIO_OPT_STR_VAL_INT) { + if (o->type == FIO_OPT_STR_VAL_INT || + o->type == FIO_OPT_INT) { if (first) val_store(ilp, ull, o->off1, data); if (!more && o->off2) @@ -365,7 +375,6 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, break; } - case FIO_OPT_INT: case FIO_OPT_BOOL: { fio_opt_int_fn *fn = o->cb; @@ -410,6 +419,9 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, } break; } + case FIO_OPT_DEPRECATED: + fprintf(stdout, "Option %s is deprecated\n", o->name); + break; default: fprintf(stderr, "Bad option type %u\n", o->type); ret = 1; @@ -456,6 +468,58 @@ static int handle_option(struct fio_option *o, const char *ptr, void *data) return r1 && r2; } +static struct fio_option *get_option(const char *opt, + struct fio_option *options, char **post) +{ + struct fio_option *o; + char *ret; + + ret = strchr(opt, '='); + if (ret) { + *post = ret; + *ret = '\0'; + ret = (char *) opt; + (*post)++; + strip_blank_end(ret); + o = find_option(options, ret); + } else { + o = find_option(options, opt); + *post = NULL; + } + + return o; +} + +static int opt_cmp(const void *p1, const void *p2) +{ + struct fio_option *o1, *o2; + char *s1, *s2, *foo; + int prio1, prio2; + + s1 = strdup(*((char **) p1)); + s2 = strdup(*((char **) p2)); + + o1 = get_option(s1, fio_options, &foo); + o2 = get_option(s2, fio_options, &foo); + + prio1 = prio2 = 0; + if (o1) + prio1 = o1->prio; + if (o2) + prio2 = o2->prio; + + free(s1); + free(s2); + return prio2 - prio1; +} + +void sort_options(char **opts, struct fio_option *options, int num_opts) +{ + fio_options = options; + qsort(opts, num_opts, sizeof(char *), opt_cmp); + fio_options = NULL; +} + int parse_cmd_option(const char *opt, const char *val, struct fio_option *options, void *data) { @@ -463,7 +527,7 @@ int parse_cmd_option(const char *opt, const char *val, o = find_option(options, opt); if (!o) { - fprintf(stderr, "Bad option %s\n", opt); + fprintf(stderr, "Bad option <%s>\n", opt); return 1; } @@ -474,28 +538,65 @@ int parse_cmd_option(const char *opt, const char *val, return 1; } +/* + * Return a copy of the input string with substrings of the form ${VARNAME} + * substituted with the value of the environment variable VARNAME. The + * substitution always occurs, even if VARNAME is empty or the corresponding + * environment variable undefined. + */ +static char *option_dup_subs(const char *opt) +{ + char out[OPT_LEN_MAX+1]; + char in[OPT_LEN_MAX+1]; + char *outptr = out; + char *inptr = in; + char *ch1, *ch2, *env; + ssize_t nchr = OPT_LEN_MAX; + size_t envlen; + + in[OPT_LEN_MAX] = '\0'; + strncpy(in, opt, OPT_LEN_MAX); + + while (*inptr && nchr > 0) { + if (inptr[0] == '$' && inptr[1] == '{') { + ch2 = strchr(inptr, '}'); + if (ch2 && inptr+1 < ch2) { + ch1 = inptr+2; + inptr = ch2+1; + *ch2 = '\0'; + + env = getenv(ch1); + if (env) { + envlen = strlen(env); + if (envlen <= nchr) { + memcpy(outptr, env, envlen); + outptr += envlen; + nchr -= envlen; + } + } + + continue; + } + } + + *outptr++ = *inptr++; + --nchr; + } + + *outptr = '\0'; + return strdup(out); +} + int parse_option(const char *opt, struct fio_option *options, void *data) { struct fio_option *o; - char *pre, *post; - char *tmp; - - tmp = strdup(opt); - - pre = strchr(tmp, '='); - if (pre) { - post = pre; - *pre = '\0'; - pre = tmp; - post++; - o = find_option(options, pre); - } else { - o = find_option(options, tmp); - post = NULL; - } + char *post, *tmp; + tmp = option_dup_subs(opt); + + o = get_option(tmp, options, &post); if (!o) { - fprintf(stderr, "Bad option %s\n", tmp); + fprintf(stderr, "Bad option <%s>\n", tmp); free(tmp); return 1; } @@ -644,6 +745,9 @@ int show_cmd_help(struct fio_option *options, const char *name) for (o = &options[0]; o->name; o++) { int match = 0; + if (o->type == FIO_OPT_DEPRECATED) + continue; + if (name) { if (!strcmp(name, o->name) || (o->alias && !strcmp(name, o->alias))) @@ -715,6 +819,8 @@ void options_init(struct fio_option *options) dprint(FD_PARSE, "init options\n"); for (o = &options[0]; o->name; o++) { + if (o->type == FIO_OPT_DEPRECATED) + continue; if (o->type == FIO_OPT_BOOL) { o->minval = 0; o->maxval = 1;