2a49b63c1065c30bde38bd664f6bd622f859f04b
[fio.git] / parse.c
1 /*
2  * This file contains the ini and command liner parser main.
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <ctype.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <limits.h>
11 #include <stdlib.h>
12
13 #include "parse.h"
14 #include "debug.h"
15
16 static struct fio_option *fio_options;
17
18 static int vp_cmp(const void *p1, const void *p2)
19 {
20         const struct value_pair *vp1 = p1;
21         const struct value_pair *vp2 = p2;
22
23         return strlen(vp2->ival) - strlen(vp1->ival);
24 }
25
26 static void posval_sort(struct fio_option *o, struct value_pair *vpmap)
27 {
28         const struct value_pair *vp;
29         int entries;
30
31         memset(vpmap, 0, PARSE_MAX_VP * sizeof(struct value_pair));
32
33         for (entries = 0; entries < PARSE_MAX_VP; entries++) {
34                 vp = &o->posval[entries];
35                 if (!vp->ival || vp->ival[0] == '\0')
36                         break;
37
38                 memcpy(&vpmap[entries], vp, sizeof(*vp));
39         }
40
41         qsort(vpmap, entries, sizeof(struct value_pair), vp_cmp);
42 }
43
44 static void show_option_range(struct fio_option *o, FILE *out)
45 {
46         if (!o->minval && !o->maxval)
47                 return;
48
49         fprintf(out, "%20s: min=%d", "range", o->minval);
50         if (o->maxval)
51                 fprintf(out, ", max=%d", o->maxval);
52         fprintf(out, "\n");
53 }
54
55 static void show_option_values(struct fio_option *o)
56 {
57         int i = 0;
58
59         do {
60                 const struct value_pair *vp = &o->posval[i];
61
62                 if (!vp->ival)
63                         break;
64
65                 printf("%20s: %-10s", i == 0 ? "valid values" : "", vp->ival);
66                 if (vp->help)
67                         printf(" %s", vp->help);
68                 printf("\n");
69                 i++;
70         } while (i < PARSE_MAX_VP);
71
72         if (i)
73                 printf("\n");
74 }
75
76 static void show_option_help(struct fio_option *o, FILE *out)
77 {
78         const char *typehelp[] = {
79                 "string (opt=bla)",
80                 "string with possible k/m/g postfix (opt=4k)",
81                 "string with time postfix (opt=10s)",
82                 "string (opt=bla)",
83                 "string with dual range (opt=1k-4k,4k-8k)",
84                 "integer value (opt=100)",
85                 "boolean value (opt=1)",
86                 "no argument (opt)",
87         };
88
89         if (o->alias)
90                 fprintf(out, "%20s: %s\n", "alias", o->alias);
91
92         fprintf(out, "%20s: %s\n", "type", typehelp[o->type]);
93         fprintf(out, "%20s: %s\n", "default", o->def ? o->def : "no default");
94         show_option_range(o, stdout);
95         show_option_values(o);
96 }
97
98 static unsigned long get_mult_time(char c)
99 {
100         switch (c) {
101         case 'm':
102         case 'M':
103                 return 60;
104         case 'h':
105         case 'H':
106                 return 60 * 60;
107         case 'd':
108         case 'D':
109                 return 24 * 60 * 60;
110         default:
111                 return 1;
112         }
113 }
114
115 static unsigned long long get_mult_bytes(char c)
116 {
117         switch (c) {
118         case 'k':
119         case 'K':
120                 return 1024;
121         case 'm':
122         case 'M':
123                 return 1024 * 1024;
124         case 'g':
125         case 'G':
126                 return 1024 * 1024 * 1024;
127         case 't':
128         case 'T':
129                 return 1024 * 1024 * 1024 * 1024UL;
130         case 'p':
131         case 'P':
132                 return 1024 * 1024 * 1024 * 1024ULL * 1024ULL;
133         default:
134                 return 1;
135         }
136 }
137
138 /*
139  * convert string into decimal value, noting any size suffix
140  */
141 int str_to_decimal(const char *str, long long *val, int kilo)
142 {
143         int len, base;
144
145         len = strlen(str);
146         if (!len)
147                 return 1;
148
149         if (strstr(str, "0x") || strstr(str, "0X"))
150                 base = 16;
151         else
152                 base = 10;
153
154         *val = strtoll(str, NULL, base);
155         if (*val == LONG_MAX && errno == ERANGE)
156                 return 1;
157
158         if (kilo)
159                 *val *= get_mult_bytes(str[len - 1]);
160         else
161                 *val *= get_mult_time(str[len - 1]);
162
163         return 0;
164 }
165
166 static int check_str_bytes(const char *p, long long *val)
167 {
168         return str_to_decimal(p, val, 1);
169 }
170
171 static int check_str_time(const char *p, long long *val)
172 {
173         return str_to_decimal(p, val, 0);
174 }
175
176 void strip_blank_front(char **p)
177 {
178         char *s = *p;
179
180         while (isspace(*s))
181                 s++;
182
183         *p = s;
184 }
185
186 void strip_blank_end(char *p)
187 {
188         char *start = p, *s;
189
190         s = strchr(p, ';');
191         if (s)
192                 *s = '\0';
193         s = strchr(p, '#');
194         if (s)
195                 *s = '\0';
196         if (s)
197                 p = s;
198
199         s = p + strlen(p);
200         while ((isspace(*s) || iscntrl(*s)) && (s > start))
201                 s--;
202
203         *(s + 1) = '\0';
204 }
205
206 static int check_range_bytes(const char *str, long *val)
207 {
208         char suffix;
209
210         if (!strlen(str))
211                 return 1;
212
213         if (sscanf(str, "%lu%c", val, &suffix) == 2) {
214                 *val *= get_mult_bytes(suffix);
215                 return 0;
216         }
217
218         if (sscanf(str, "%lu", val) == 1)
219                 return 0;
220
221         return 1;
222 }
223
224 static int check_int(const char *p, int *val)
225 {
226         if (!strlen(p))
227                 return 1;
228         if (strstr(p, "0x") || strstr(p, "0X")) {
229                 if (sscanf(p, "%x", val) == 1)
230                         return 0;
231         } else {
232                 if (sscanf(p, "%u", val) == 1)
233                         return 0;
234         }
235
236         return 1;
237 }
238
239 static struct fio_option *find_option(struct fio_option *options,
240                                       const char *opt)
241 {
242         struct fio_option *o;
243
244         for (o = &options[0]; o->name; o++) {
245                 if (!strcmp(o->name, opt))
246                         return o;
247                 else if (o->alias && !strcmp(o->alias, opt))
248                         return o;
249         }
250
251         return NULL;
252 }
253
254 #define val_store(ptr, val, off, data)                  \
255         do {                                            \
256                 ptr = td_var((data), (off));            \
257                 *ptr = (val);                           \
258         } while (0)
259
260 static int __handle_option(struct fio_option *o, const char *ptr, void *data,
261                            int first, int more)
262 {
263         int il, *ilp;
264         long long ull, *ullp;
265         long ul1, ul2;
266         char **cp;
267         int ret = 0, is_time = 0;
268
269         dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name,
270                                                         o->type, ptr);
271
272         if (!ptr && o->type != FIO_OPT_STR_SET && o->type != FIO_OPT_STR) {
273                 fprintf(stderr, "Option %s requires an argument\n", o->name);
274                 return 1;
275         }
276
277         switch (o->type) {
278         case FIO_OPT_STR: {
279                 fio_opt_str_fn *fn = o->cb;
280                 const struct value_pair *vp;
281                 struct value_pair posval[PARSE_MAX_VP];
282                 int i;
283
284                 posval_sort(o, posval);
285
286                 for (i = 0; i < PARSE_MAX_VP; i++) {
287                         vp = &posval[i];
288                         if (!vp->ival || vp->ival[0] == '\0')
289                                 break;
290                         ret = 1;
291                         if (!strncmp(vp->ival, ptr, strlen(vp->ival))) {
292                                 ret = 0;
293                                 if (!o->off1)
294                                         break;
295                                 val_store(ilp, vp->oval, o->off1, data);
296                                 break;
297                         }
298                 }
299
300                 if (ret)
301                         show_option_values(o);
302                 else if (fn)
303                         ret = fn(data, ptr);
304                 break;
305         }
306         case FIO_OPT_STR_VAL_TIME:
307                 is_time = 1;
308         case FIO_OPT_INT:
309         case FIO_OPT_STR_VAL: {
310                 fio_opt_str_val_fn *fn = o->cb;
311
312                 if (is_time)
313                         ret = check_str_time(ptr, &ull);
314                 else
315                         ret = check_str_bytes(ptr, &ull);
316
317                 if (ret)
318                         break;
319
320                 if (o->maxval && ull > o->maxval) {
321                         fprintf(stderr, "max value out of range: %lld"
322                                         " (%d max)\n", ull, o->maxval);
323                         return 1;
324                 }
325                 if (o->minval && ull < o->minval) {
326                         fprintf(stderr, "min value out of range: %lld"
327                                         " (%d min)\n", ull, o->minval);
328                         return 1;
329                 }
330
331                 if (fn)
332                         ret = fn(data, &ull);
333                 else {
334                         if (o->type == FIO_OPT_INT) {
335                                 if (first)
336                                         val_store(ilp, ull, o->off1, data);
337                                 if (!more && o->off2)
338                                         val_store(ilp, ull, o->off2, data);
339                         } else {
340                                 if (first)
341                                         val_store(ullp, ull, o->off1, data);
342                                 if (!more && o->off2)
343                                         val_store(ullp, ull, o->off2, data);
344                         }
345                 }
346                 break;
347         }
348         case FIO_OPT_STR_STORE: {
349                 fio_opt_str_fn *fn = o->cb;
350
351                 cp = td_var(data, o->off1);
352                 *cp = strdup(ptr);
353                 if (fn) {
354                         ret = fn(data, ptr);
355                         if (ret) {
356                                 free(*cp);
357                                 *cp = NULL;
358                         }
359                 }
360                 break;
361         }
362         case FIO_OPT_RANGE: {
363                 char tmp[128];
364                 char *p1, *p2;
365
366                 strncpy(tmp, ptr, sizeof(tmp) - 1);
367
368                 p1 = strchr(tmp, '-');
369                 if (!p1) {
370                         p1 = strchr(tmp, ':');
371                         if (!p1) {
372                                 ret = 1;
373                                 break;
374                         }
375                 }
376
377                 p2 = p1 + 1;
378                 *p1 = '\0';
379                 p1 = tmp;
380
381                 ret = 1;
382                 if (!check_range_bytes(p1, &ul1) &&
383                     !check_range_bytes(p2, &ul2)) {
384                         ret = 0;
385                         if (ul1 > ul2) {
386                                 unsigned long foo = ul1;
387
388                                 ul1 = ul2;
389                                 ul2 = foo;
390                         }
391
392                         if (first) {
393                                 val_store(ilp, ul1, o->off1, data);
394                                 val_store(ilp, ul2, o->off2, data);
395                         }
396                         if (o->off3 && o->off4) {
397                                 val_store(ilp, ul1, o->off3, data);
398                                 val_store(ilp, ul2, o->off4, data);
399                         }
400                 }
401
402                 break;
403         }
404         case FIO_OPT_BOOL: {
405                 fio_opt_int_fn *fn = o->cb;
406
407                 ret = check_int(ptr, &il);
408                 if (ret)
409                         break;
410
411                 if (o->maxval && il > (int) o->maxval) {
412                         fprintf(stderr, "max value out of range: %d (%d max)\n",
413                                                                 il, o->maxval);
414                         return 1;
415                 }
416                 if (o->minval && il < o->minval) {
417                         fprintf(stderr, "min value out of range: %d (%d min)\n",
418                                                                 il, o->minval);
419                         return 1;
420                 }
421
422                 if (o->neg)
423                         il = !il;
424
425                 if (fn)
426                         ret = fn(data, &il);
427                 else {
428                         if (first)
429                                 val_store(ilp, il, o->off1, data);
430                         if (!more && o->off2)
431                                 val_store(ilp, il, o->off2, data);
432                 }
433                 break;
434         }
435         case FIO_OPT_STR_SET: {
436                 fio_opt_str_set_fn *fn = o->cb;
437
438                 if (fn)
439                         ret = fn(data);
440                 else {
441                         if (first)
442                                 val_store(ilp, 1, o->off1, data);
443                         if (!more && o->off2)
444                                 val_store(ilp, 1, o->off2, data);
445                 }
446                 break;
447         }
448         case FIO_OPT_DEPRECATED:
449                 fprintf(stdout, "Option %s is deprecated\n", o->name);
450                 break;
451         default:
452                 fprintf(stderr, "Bad option type %u\n", o->type);
453                 ret = 1;
454         }
455
456         if (ret)
457                 return ret;
458
459         if (o->verify) {
460                 ret = o->verify(o, data);
461                 if (ret) {
462                         fprintf(stderr,"Correct format for offending option\n");
463                         fprintf(stderr, "%20s: %s\n", o->name, o->help);
464                         show_option_help(o, stderr);
465                 }
466         }
467
468         return ret;
469 }
470
471 static int handle_option(struct fio_option *o, const char *__ptr, void *data)
472 {
473         char *ptr, *ptr2 = NULL;
474         int r1, r2;
475
476         dprint(FD_PARSE, "handle_option=%s, ptr=%s\n", o->name, __ptr);
477
478         ptr = NULL;
479         if (__ptr)
480                 ptr = strdup(__ptr);
481
482         /*
483          * See if we have a second set of parameters, hidden after a comma.
484          * Do this before parsing the first round, to check if we should
485          * copy set 1 options to set 2.
486          */
487         if (ptr &&
488             (o->type != FIO_OPT_STR_STORE) &&
489             (o->type != FIO_OPT_STR)) {
490                 ptr2 = strchr(ptr, ',');
491                 if (ptr2 && *(ptr2 + 1) == '\0')
492                         *ptr2 = '\0';
493                 if (!ptr2)
494                         ptr2 = strchr(ptr, ':');
495                 if (!ptr2)
496                         ptr2 = strchr(ptr, '-');
497         }
498
499         /*
500          * Don't return early if parsing the first option fails - if
501          * we are doing multiple arguments, we can allow the first one
502          * being empty.
503          */
504         r1 = __handle_option(o, ptr, data, 1, !!ptr2);
505
506         if (!ptr2) {
507                 if (ptr)
508                         free(ptr);
509                 return r1;
510         }
511
512         ptr2++;
513         r2 = __handle_option(o, ptr2, data, 0, 0);
514
515         if (ptr)
516                 free(ptr);
517         return r1 && r2;
518 }
519
520 static struct fio_option *get_option(const char *opt,
521                                      struct fio_option *options, char **post)
522 {
523         struct fio_option *o;
524         char *ret;
525
526         ret = strchr(opt, '=');
527         if (ret) {
528                 *post = ret;
529                 *ret = '\0';
530                 ret = (char *) opt;
531                 (*post)++;
532                 strip_blank_end(ret);
533                 o = find_option(options, ret);
534         } else {
535                 o = find_option(options, opt);
536                 *post = NULL;
537         }
538
539         return o;
540 }
541
542 static int opt_cmp(const void *p1, const void *p2)
543 {
544         struct fio_option *o1, *o2;
545         char *s1, *s2, *foo;
546         int prio1, prio2;
547
548         s1 = strdup(*((char **) p1));
549         s2 = strdup(*((char **) p2));
550
551         o1 = get_option(s1, fio_options, &foo);
552         o2 = get_option(s2, fio_options, &foo);
553         
554         prio1 = prio2 = 0;
555         if (o1)
556                 prio1 = o1->prio;
557         if (o2)
558                 prio2 = o2->prio;
559
560         free(s1);
561         free(s2);
562         return prio2 - prio1;
563 }
564
565 void sort_options(char **opts, struct fio_option *options, int num_opts)
566 {
567         fio_options = options;
568         qsort(opts, num_opts, sizeof(char *), opt_cmp);
569         fio_options = NULL;
570 }
571
572 int parse_cmd_option(const char *opt, const char *val,
573                      struct fio_option *options, void *data)
574 {
575         struct fio_option *o;
576
577         o = find_option(options, opt);
578         if (!o) {
579                 fprintf(stderr, "Bad option <%s>\n", opt);
580                 return 1;
581         }
582
583         if (!handle_option(o, val, data))
584                 return 0;
585
586         fprintf(stderr, "fio: failed parsing %s=%s\n", opt, val);
587         return 1;
588 }
589
590 /*
591  * Return a copy of the input string with substrings of the form ${VARNAME}
592  * substituted with the value of the environment variable VARNAME.  The
593  * substitution always occurs, even if VARNAME is empty or the corresponding
594  * environment variable undefined.
595  */
596 static char *option_dup_subs(const char *opt)
597 {
598         char out[OPT_LEN_MAX+1];
599         char in[OPT_LEN_MAX+1];
600         char *outptr = out;
601         char *inptr = in;
602         char *ch1, *ch2, *env;
603         ssize_t nchr = OPT_LEN_MAX;
604         size_t envlen;
605
606         in[OPT_LEN_MAX] = '\0';
607         strncpy(in, opt, OPT_LEN_MAX);
608
609         while (*inptr && nchr > 0) {
610                 if (inptr[0] == '$' && inptr[1] == '{') {
611                         ch2 = strchr(inptr, '}');
612                         if (ch2 && inptr+1 < ch2) {
613                                 ch1 = inptr+2;
614                                 inptr = ch2+1;
615                                 *ch2 = '\0';
616
617                                 env = getenv(ch1);
618                                 if (env) {
619                                         envlen = strlen(env);
620                                         if (envlen <= nchr) {
621                                                 memcpy(outptr, env, envlen);
622                                                 outptr += envlen;
623                                                 nchr -= envlen;
624                                         }
625                                 }
626
627                                 continue;
628                         }
629                 }
630
631                 *outptr++ = *inptr++;
632                 --nchr;
633         }
634
635         *outptr = '\0';
636         return strdup(out);
637 }
638
639 int parse_option(const char *opt, struct fio_option *options, void *data)
640 {
641         struct fio_option *o;
642         char *post, *tmp;
643
644         tmp = option_dup_subs(opt);
645
646         o = get_option(tmp, options, &post);
647         if (!o) {
648                 fprintf(stderr, "Bad option <%s>\n", tmp);
649                 free(tmp);
650                 return 1;
651         }
652
653         if (!handle_option(o, post, data)) {
654                 free(tmp);
655                 return 0;
656         }
657
658         fprintf(stderr, "fio: failed parsing %s\n", opt);
659         free(tmp);
660         return 1;
661 }
662
663 /*
664  * Option match, levenshtein distance. Handy for not quite remembering what
665  * the option name is.
666  */
667 static int string_distance(const char *s1, const char *s2)
668 {
669         unsigned int s1_len = strlen(s1);
670         unsigned int s2_len = strlen(s2);
671         unsigned int *p, *q, *r;
672         unsigned int i, j;
673
674         p = malloc(sizeof(unsigned int) * (s2_len + 1));
675         q = malloc(sizeof(unsigned int) * (s2_len + 1));
676
677         p[0] = 0;
678         for (i = 1; i <= s2_len; i++)
679                 p[i] = p[i - 1] + 1;
680
681         for (i = 1; i <= s1_len; i++) {
682                 q[0] = p[0] + 1;
683                 for (j = 1; j <= s2_len; j++) {
684                         unsigned int sub = p[j - 1];
685
686                         if (s1[i - 1] != s2[j - 1])
687                                 sub++;
688
689                         q[j] = min(p[j] + 1, min(q[j - 1] + 1, sub));
690                 }
691                 r = p;
692                 p = q;
693                 q = r;
694         }
695
696         i = p[s2_len];
697         free(p);
698         free(q);
699         return i;
700 }
701
702 static struct fio_option *find_child(struct fio_option *options,
703                                      struct fio_option *o)
704 {
705         struct fio_option *__o;
706
707         for (__o = options + 1; __o->name; __o++)
708                 if (__o->parent && !strcmp(__o->parent, o->name))
709                         return __o;
710
711         return NULL;
712 }
713
714 static void __print_option(struct fio_option *o, struct fio_option *org,
715                            int level)
716 {
717         char name[256], *p;
718         int depth;
719
720         if (!o)
721                 return;
722         if (!org)
723                 org = o;
724
725         p = name;
726         depth = level;
727         while (depth--)
728                 p += sprintf(p, "%s", "  ");
729
730         sprintf(p, "%s", o->name);
731
732         printf("%-24s: %s\n", name, o->help);
733 }
734
735 static void print_option(struct fio_option *o)
736 {
737         struct fio_option *parent;
738         struct fio_option *__o;
739         unsigned int printed;
740         unsigned int level;
741
742         __print_option(o, NULL, 0);
743         parent = o;
744         level = 0;
745         do {
746                 level++;
747                 printed = 0;
748
749                 while ((__o = find_child(o, parent)) != NULL) {
750                         __print_option(__o, o, level);
751                         o = __o;
752                         printed++;
753                 }
754
755                 parent = o;
756         } while (printed);
757 }
758
759 int show_cmd_help(struct fio_option *options, const char *name)
760 {
761         struct fio_option *o, *closest;
762         unsigned int best_dist;
763         int found = 0;
764         int show_all = 0;
765
766         if (!name || !strcmp(name, "all"))
767                 show_all = 1;
768
769         closest = NULL;
770         best_dist = -1;
771         for (o = &options[0]; o->name; o++) {
772                 int match = 0;
773
774                 if (o->type == FIO_OPT_DEPRECATED)
775                         continue;
776
777                 if (name) {
778                         if (!strcmp(name, o->name) ||
779                             (o->alias && !strcmp(name, o->alias)))
780                                 match = 1;
781                         else {
782                                 unsigned int dist;
783
784                                 dist = string_distance(name, o->name);
785                                 if (dist < best_dist) {
786                                         best_dist = dist;
787                                         closest = o;
788                                 }
789                         }
790                 }
791
792                 if (show_all || match) {
793                         found = 1;
794                         if (match)
795                                 printf("%24s: %s\n", o->name, o->help);
796                         if (show_all) {
797                                 if (!o->parent)
798                                         print_option(o);
799                                 continue;
800                         }
801                 }
802
803                 if (!match)
804                         continue;
805
806                 show_option_help(o, stdout);
807         }
808
809         if (found)
810                 return 0;
811
812         printf("No such command: %s", name);
813         if (closest) {
814                 printf(" - showing closest match\n");
815                 printf("%20s: %s\n", closest->name, closest->help);
816                 show_option_help(closest, stdout);
817         } else
818                 printf("\n");
819
820         return 1;
821 }
822
823 /*
824  * Handle parsing of default parameters.
825  */
826 void fill_default_options(void *data, struct fio_option *options)
827 {
828         struct fio_option *o;
829
830         dprint(FD_PARSE, "filling default options\n");
831
832         for (o = &options[0]; o->name; o++)
833                 if (o->def)
834                         handle_option(o, o->def, data);
835 }
836
837 /*
838  * Sanitize the options structure. For now it just sets min/max for bool
839  * values and whether both callback and offsets are given.
840  */
841 void options_init(struct fio_option *options)
842 {
843         struct fio_option *o;
844
845         dprint(FD_PARSE, "init options\n");
846
847         for (o = &options[0]; o->name; o++) {
848                 if (o->type == FIO_OPT_DEPRECATED)
849                         continue;
850                 if (o->type == FIO_OPT_BOOL) {
851                         o->minval = 0;
852                         o->maxval = 1;
853                 }
854                 if (o->type == FIO_OPT_STR_SET && o->def) {
855                         fprintf(stderr, "Option %s: string set option with"
856                                         " default will always be true\n",
857                                                 o->name);
858                 }
859                 if (!o->cb && !o->off1) {
860                         fprintf(stderr, "Option %s: neither cb nor offset"
861                                         " given\n", o->name);
862                 }
863                 if (o->type == FIO_OPT_STR || o->type == FIO_OPT_STR_STORE)
864                         continue;
865                 if (o->cb && (o->off1 || o->off2 || o->off3 || o->off4)) {
866                         fprintf(stderr, "Option %s: both cb and offset given\n",
867                                                                  o->name);
868                 }
869         }
870 }