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