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