1 /* 2 * Commandline option parsing functions 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * Copyright (c) 2009 Kevin Wolf <kwolf (at) redhat.com> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include <stdio.h> 27 #include <string.h> 28 29 #include "qemu-common.h" 30 #include "qemu-error.h" 31 #include "qemu-objects.h" 32 #include "qemu-option.h" 33 #include "qerror.h" 34 35 /* 36 * Extracts the name of an option from the parameter string (p points at the 37 * first byte of the option name) 38 * 39 * The option name is delimited by delim (usually , or =) or the string end 40 * and is copied into buf. If the option name is longer than buf_size, it is 41 * truncated. buf is always zero terminated. 42 * 43 * The return value is the position of the delimiter/zero byte after the option 44 * name in p. 45 */ 46 const char *get_opt_name(char *buf, int buf_size, const char *p, char delim) 47 { 48 char *q; 49 50 q = buf; 51 while (*p != '\0' && *p != delim) { 52 if (q && (q - buf) < buf_size - 1) 53 *q++ = *p; 54 p++; 55 } 56 if (q) 57 *q = '\0'; 58 59 return p; 60 } 61 62 /* 63 * Extracts the value of an option from the parameter string p (p points at the 64 * first byte of the option value) 65 * 66 * This function is comparable to get_opt_name with the difference that the 67 * delimiter is fixed to be comma which starts a new option. To specify an 68 * option value that contains commas, double each comma. 69 */ 70 const char *get_opt_value(char *buf, int buf_size, const char *p) 71 { 72 char *q; 73 74 q = buf; 75 while (*p != '\0') { 76 if (*p == ',') { 77 if (*(p + 1) != ',') 78 break; 79 p++; 80 } 81 if (q && (q - buf) < buf_size - 1) 82 *q++ = *p; 83 p++; 84 } 85 if (q) 86 *q = '\0'; 87 88 return p; 89 } 90 91 int get_next_param_value(char *buf, int buf_size, 92 const char *tag, const char **pstr) 93 { 94 const char *p; 95 char option[128]; 96 97 p = *pstr; 98 for(;;) { 99 p = get_opt_name(option, sizeof(option), p, '='); 100 if (*p != '=') 101 break; 102 p++; 103 if (!strcmp(tag, option)) { 104 *pstr = get_opt_value(buf, buf_size, p); 105 if (**pstr == ',') { 106 (*pstr)++; 107 } 108 return strlen(buf); 109 } else { 110 p = get_opt_value(NULL, 0, p); 111 } 112 if (*p != ',') 113 break; 114 p++; 115 } 116 return 0; 117 } 118 119 int get_param_value(char *buf, int buf_size, 120 const char *tag, const char *str) 121 { 122 return get_next_param_value(buf, buf_size, tag, &str); 123 } 124 125 int check_params(char *buf, int buf_size, 126 const char * const *params, const char *str) 127 { 128 const char *p; 129 int i; 130 131 p = str; 132 while (*p != '\0') { 133 p = get_opt_name(buf, buf_size, p, '='); 134 if (*p != '=') { 135 return -1; 136 } 137 p++; 138 for (i = 0; params[i] != NULL; i++) { 139 if (!strcmp(params[i], buf)) { 140 break; 141 } 142 } 143 if (params[i] == NULL) { 144 return -1; 145 } 146 p = get_opt_value(NULL, 0, p); 147 if (*p != ',') { 148 break; 149 } 150 p++; 151 } 152 return 0; 153 } 154 155 /* 156 * Searches an option list for an option with the given name 157 */ 158 QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list, 159 const char *name) 160 { 161 while (list && list->name) { 162 if (!strcmp(list->name, name)) { 163 return list; 164 } 165 list++; 166 } 167 168 return NULL; 169 } 170 171 static int parse_option_bool(const char *name, const char *value, int *ret) 172 { 173 if (value != NULL) { 174 if (!strcmp(value, "on")) { 175 *ret = 1; 176 } else if (!strcmp(value, "off")) { 177 *ret = 0; 178 } else { 179 qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'"); 180 return -1; 181 } 182 } else { 183 *ret = 1; 184 } 185 return 0; 186 } 187 188 static int parse_option_number(const char *name, const char *value, uint64_t *ret) 189 { 190 char *postfix; 191 uint64_t number; 192 193 if (value != NULL) { 194 number = strtoull(value, &postfix, 0); 195 if (*postfix != '\0') { 196 qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number"); 197 return -1; 198 } 199 *ret = number; 200 } else { 201 qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number"); 202 return -1; 203 } 204 return 0; 205 } 206 207 static int parse_option_size(const char *name, const char *value, uint64_t *ret) 208 { 209 char *postfix; 210 double sizef; 211 212 if (value != NULL) { 213 sizef = strtod(value, &postfix); 214 switch (*postfix) { 215 case 'T': 216 sizef *= 1024; 217 case 'G': 218 sizef *= 1024; 219 case 'M': 220 sizef *= 1024; 221 case 'K': 222 case 'k': 223 sizef *= 1024; 224 case 'b': 225 case '\0': 226 *ret = (uint64_t) sizef; 227 break; 228 default: 229 qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size"); 230 error_printf_unless_qmp("You may use k, M, G or T suffixes for " 231 "kilobytes, megabytes, gigabytes and terabytes.\n"); 232 return -1; 233 } 234 } else { 235 qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size"); 236 return -1; 237 } 238 return 0; 239 } 240 241 /* 242 * Sets the value of a parameter in a given option list. The parsing of the 243 * value depends on the type of option: 244 * 245 * OPT_FLAG (uses value.n): 246 * If no value is given, the flag is set to 1. 247 * Otherwise the value must be "on" (set to 1) or "off" (set to 0) 248 * 249 * OPT_STRING (uses value.s): 250 * value is strdup()ed and assigned as option value 251 * 252 * OPT_SIZE (uses value.n): 253 * The value is converted to an integer. Suffixes for kilobytes etc. are 254 * allowed (powers of 1024). 255 * 256 * Returns 0 on succes, -1 in error cases 257 */ 258 int set_option_parameter(QEMUOptionParameter *list, const char *name, 259 const char *value) 260 { 261 int flag; 262 263 // Find a matching parameter 264 list = get_option_parameter(list, name); 265 if (list == NULL) { 266 fprintf(stderr, "Unknown option '%s'\n", name); 267 return -1; 268 } 269 270 // Process parameter 271 switch (list->type) { 272 case OPT_FLAG: 273 if (parse_option_bool(name, value, &flag) == -1) 274 return -1; 275 list->value.n = flag; 276 break; 277 278 case OPT_STRING: 279 if (value != NULL) { 280 list->value.s = qemu_strdup(value); 281 } else { 282 fprintf(stderr, "Option '%s' needs a parameter\n", name); 283 return -1; 284 } 285 break; 286 287 case OPT_SIZE: 288 if (parse_option_size(name, value, &list->value.n) == -1) 289 return -1; 290 break; 291 292 default: 293 fprintf(stderr, "Bug: Option '%s' has an unknown type\n", name); 294 return -1; 295 } 296 297 return 0; 298 } 299 300 /* 301 * Sets the given parameter to an integer instead of a string. 302 * This function cannot be used to set string options. 303 * 304 * Returns 0 on success, -1 in error cases 305 */ 306 int set_option_parameter_int(QEMUOptionParameter *list, const char *name, 307 uint64_t value) 308 { 309 // Find a matching parameter 310 list = get_option_parameter(list, name); 311 if (list == NULL) { 312 fprintf(stderr, "Unknown option '%s'\n", name); 313 return -1; 314 } 315 316 // Process parameter 317 switch (list->type) { 318 case OPT_FLAG: 319 case OPT_NUMBER: 320 case OPT_SIZE: 321 list->value.n = value; 322 break; 323 324 default: 325 return -1; 326 } 327 328 return 0; 329 } 330 331 /* 332 * Frees a option list. If it contains strings, the strings are freed as well. 333 */ 334 void free_option_parameters(QEMUOptionParameter *list) 335 { 336 QEMUOptionParameter *cur = list; 337 338 while (cur && cur->name) { 339 if (cur->type == OPT_STRING) { 340 qemu_free(cur->value.s); 341 } 342 cur++; 343 } 344 345 qemu_free(list); 346 } 347 348 /* 349 * Count valid options in list 350 */ 351 static size_t count_option_parameters(QEMUOptionParameter *list) 352 { 353 size_t num_options = 0; 354 355 while (list && list->name) { 356 num_options++; 357 list++; 358 } 359 360 return num_options; 361 } 362 363 /* 364 * Append an option list (list) to an option list (dest). 365 * 366 * If dest is NULL, a new copy of list is created. 367 * 368 * Returns a pointer to the first element of dest (or the newly allocated copy) 369 */ 370 QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest, 371 QEMUOptionParameter *list) 372 { 373 size_t num_options, num_dest_options; 374 375 num_options = count_option_parameters(dest); 376 num_dest_options = num_options; 377 378 num_options += count_option_parameters(list); 379 380 dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter)); 381 dest[num_dest_options].name = NULL; 382 383 while (list && list->name) { 384 if (get_option_parameter(dest, list->name) == NULL) { 385 dest[num_dest_options++] = *list; 386 dest[num_dest_options].name = NULL; 387 } 388 list++; 389 } 390 391 return dest; 392 } 393 394 /* 395 * Parses a parameter string (param) into an option list (dest). 396 * 397 * list is the template option list. If dest is NULL, a new copy of list is 398 * created. If list is NULL, this function fails. 399 * 400 * A parameter string consists of one or more parameters, separated by commas. 401 * Each parameter consists of its name and possibly of a value. In the latter 402 * case, the value is delimited by an = character. To specify a value which 403 * contains commas, double each comma so it won't be recognized as the end of 404 * the parameter. 405 * 406 * For more details of the parsing see above. 407 * 408 * Returns a pointer to the first element of dest (or the newly allocated copy) 409 * or NULL in error cases 410 */ 411 QEMUOptionParameter *parse_option_parameters(const char *param, 412 QEMUOptionParameter *list, QEMUOptionParameter *dest) 413 { 414 QEMUOptionParameter *allocated = NULL; 415 char name[256]; 416 char value[256]; 417 char *param_delim, *value_delim; 418 char next_delim; 419 420 if (list == NULL) { 421 return NULL; 422 } 423 424 if (dest == NULL) { 425 dest = allocated = append_option_parameters(NULL, list); 426 } 427 428 while (*param) { 429 430 // Find parameter name and value in the string 431 param_delim = strchr(param, ','); 432 value_delim = strchr(param, '='); 433 434 if (value_delim && (value_delim < param_delim || !param_delim)) { 435 next_delim = '='; 436 } else { 437 next_delim = ','; 438 value_delim = NULL; 439 } 440 441 param = get_opt_name(name, sizeof(name), param, next_delim); 442 if (value_delim) { 443 param = get_opt_value(value, sizeof(value), param + 1); 444 } 445 if (*param != '\0') { 446 param++; 447 } 448 449 // Set the parameter 450 if (set_option_parameter(dest, name, value_delim ? value : NULL)) { 451 goto fail; 452 } 453 } 454 455 return dest; 456 457 fail: 458 // Only free the list if it was newly allocated 459 free_option_parameters(allocated); 460 return NULL; 461 } 462 463 /* 464 * Prints all options of a list that have a value to stdout 465 */ 466 void print_option_parameters(QEMUOptionParameter *list) 467 { 468 while (list && list->name) { 469 switch (list->type) { 470 case OPT_STRING: 471 if (list->value.s != NULL) { 472 printf("%s='%s' ", list->name, list->value.s); 473 } 474 break; 475 case OPT_FLAG: 476 printf("%s=%s ", list->name, list->value.n ? "on" : "off"); 477 break; 478 case OPT_SIZE: 479 case OPT_NUMBER: 480 printf("%s=%" PRId64 " ", list->name, list->value.n); 481 break; 482 default: 483 printf("%s=(unkown type) ", list->name); 484 break; 485 } 486 list++; 487 } 488 } 489 490 /* 491 * Prints an overview of all available options 492 */ 493 void print_option_help(QEMUOptionParameter *list) 494 { 495 printf("Supported options:\n"); 496 while (list && list->name) { 497 printf("%-16s %s\n", list->name, 498 list->help ? list->help : "No description available"); 499 list++; 500 } 501 } 502 503 /* ------------------------------------------------------------------ */ 504 505 struct QemuOpt { 506 const char *name; 507 const char *str; 508 509 const QemuOptDesc *desc; 510 union { 511 int boolean; 512 uint64_t uint; 513 } value; 514 515 QemuOpts *opts; 516 QTAILQ_ENTRY(QemuOpt) next; 517 }; 518 519 struct QemuOpts { 520 char *id; 521 QemuOptsList *list; 522 Location loc; 523 QTAILQ_HEAD(QemuOptHead, QemuOpt) head; 524 QTAILQ_ENTRY(QemuOpts) next; 525 }; 526 527 static QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name) 528 { 529 QemuOpt *opt; 530 531 QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) { 532 if (strcmp(opt->name, name) != 0) 533 continue; 534 return opt; 535 } 536 return NULL; 537 } 538 539 const char *qemu_opt_get(QemuOpts *opts, const char *name) 540 { 541 QemuOpt *opt = qemu_opt_find(opts, name); 542 return opt ? opt->str : NULL; 543 } 544 545 int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval) 546 { 547 QemuOpt *opt = qemu_opt_find(opts, name); 548 549 if (opt == NULL) 550 return defval; 551 assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL); 552 return opt->value.boolean; 553 } 554 555 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval) 556 { 557 QemuOpt *opt = qemu_opt_find(opts, name); 558 559 if (opt == NULL) 560 return defval; 561 assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER); 562 return opt->value.uint; 563 } 564 565 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval) 566 { 567 QemuOpt *opt = qemu_opt_find(opts, name); 568 569 if (opt == NULL) 570 return defval; 571 assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE); 572 return opt->value.uint; 573 } 574 575 static int qemu_opt_parse(QemuOpt *opt) 576 { 577 if (opt->desc == NULL) 578 return 0; 579 switch (opt->desc->type) { 580 case QEMU_OPT_STRING: 581 /* nothing */ 582 return 0; 583 case QEMU_OPT_BOOL: 584 return parse_option_bool(opt->name, opt->str, &opt->value.boolean); 585 case QEMU_OPT_NUMBER: 586 return parse_option_number(opt->name, opt->str, &opt->value.uint); 587 case QEMU_OPT_SIZE: 588 return parse_option_size(opt->name, opt->str, &opt->value.uint); 589 default: 590 abort(); 591 } 592 } 593 594 static void qemu_opt_del(QemuOpt *opt) 595 { 596 QTAILQ_REMOVE(&opt->opts->head, opt, next); 597 qemu_free((/* !const */ char*)opt->name); 598 qemu_free((/* !const */ char*)opt->str); 599 qemu_free(opt); 600 } 601 602 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value) 603 { 604 QemuOpt *opt; 605 const QemuOptDesc *desc = opts->list->desc; 606 int i; 607 608 for (i = 0; desc[i].name != NULL; i++) { 609 if (strcmp(desc[i].name, name) == 0) { 610 break; 611 } 612 } 613 if (desc[i].name == NULL) { 614 if (i == 0) { 615 /* empty list -> allow any */; 616 } else { 617 qerror_report(QERR_INVALID_PARAMETER, name); 618 return -1; 619 } 620 } 621 622 opt = qemu_mallocz(sizeof(*opt)); 623 opt->name = qemu_strdup(name); 624 opt->opts = opts; 625 QTAILQ_INSERT_TAIL(&opts->head, opt, next); 626 if (desc[i].name != NULL) { 627 opt->desc = desc+i; 628 } 629 if (value) { 630 opt->str = qemu_strdup(value); 631 } 632 if (qemu_opt_parse(opt) < 0) { 633 qemu_opt_del(opt); 634 return -1; 635 } 636 return 0; 637 } 638 639 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque, 640 int abort_on_failure) 641 { 642 QemuOpt *opt; 643 int rc = 0; 644 645 QTAILQ_FOREACH(opt, &opts->head, next) { 646 rc = func(opt->name, opt->str, opaque); 647 if (abort_on_failure && rc != 0) 648 break; 649 } 650 return rc; 651 } 652 653 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id) 654 { 655 QemuOpts *opts; 656 657 QTAILQ_FOREACH(opts, &list->head, next) { 658 if (!opts->id) { 659 continue; 660 } 661 if (strcmp(opts->id, id) != 0) { 662 continue; 663 } 664 return opts; 665 } 666 return NULL; 667 } 668 669 static int id_wellformed(const char *id) 670 { 671 int i; 672 673 if (!qemu_isalpha(id[0])) { 674 return 0; 675 } 676 for (i = 1; id[i]; i++) { 677 if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) { 678 return 0; 679 } 680 } 681 return 1; 682 } 683 684 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists) 685 { 686 QemuOpts *opts = NULL; 687 688 if (id) { 689 if (!id_wellformed(id)) { 690 qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier"); 691 error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n"); 692 return NULL; 693 } 694 opts = qemu_opts_find(list, id); 695 if (opts != NULL) { 696 if (fail_if_exists) { 697 qerror_report(QERR_DUPLICATE_ID, id, list->name); 698 return NULL; 699 } else { 700 return opts; 701 } 702 } 703 } 704 opts = qemu_mallocz(sizeof(*opts)); 705 if (id) { 706 opts->id = qemu_strdup(id); 707 } 708 opts->list = list; 709 loc_save(&opts->loc); 710 QTAILQ_INIT(&opts->head); 711 QTAILQ_INSERT_TAIL(&list->head, opts, next); 712 return opts; 713 } 714 715 void qemu_opts_reset(QemuOptsList *list) 716 { 717 QemuOpts *opts, *next_opts; 718 719 QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) { 720 qemu_opts_del(opts); 721 } 722 } 723 724 void qemu_opts_loc_restore(QemuOpts *opts) 725 { 726 loc_restore(&opts->loc); 727 } 728 729 int qemu_opts_set(QemuOptsList *list, const char *id, 730 const char *name, const char *value) 731 { 732 QemuOpts *opts; 733 734 opts = qemu_opts_create(list, id, 1); 735 if (opts == NULL) { 736 return -1; 737 } 738 return qemu_opt_set(opts, name, value); 739 } 740 741 const char *qemu_opts_id(QemuOpts *opts) 742 { 743 return opts->id; 744 } 745 746 void qemu_opts_del(QemuOpts *opts) 747 { 748 QemuOpt *opt; 749 750 for (;;) { 751 opt = QTAILQ_FIRST(&opts->head); 752 if (opt == NULL) 753 break; 754 qemu_opt_del(opt); 755 } 756 QTAILQ_REMOVE(&opts->list->head, opts, next); 757 qemu_free(opts->id); 758 qemu_free(opts); 759 } 760 761 int qemu_opts_print(QemuOpts *opts, void *dummy) 762 { 763 QemuOpt *opt; 764 765 fprintf(stderr, "%s: %s:", opts->list->name, 766 opts->id ? opts->id : "<noid>"); 767 QTAILQ_FOREACH(opt, &opts->head, next) { 768 fprintf(stderr, " %s=\"%s\"", opt->name, opt->str); 769 } 770 fprintf(stderr, "\n"); 771 return 0; 772 } 773 774 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname) 775 { 776 char option[128], value[1024]; 777 const char *p,*pe,*pc; 778 779 for (p = params; *p != '\0'; p++) { 780 pe = strchr(p, '='); 781 pc = strchr(p, ','); 782 if (!pe || (pc && pc < pe)) { 783 /* found "foo,more" */ 784 if (p == params && firstname) { 785 /* implicitly named first option */ 786 pstrcpy(option, sizeof(option), firstname); 787 p = get_opt_value(value, sizeof(value), p); 788 } else { 789 /* option without value, probably a flag */ 790 p = get_opt_name(option, sizeof(option), p, ','); 791 if (strncmp(option, "no", 2) == 0) { 792 memmove(option, option+2, strlen(option+2)+1); 793 pstrcpy(value, sizeof(value), "off"); 794 } else { 795 pstrcpy(value, sizeof(value), "on"); 796 } 797 } 798 } else { 799 /* found "foo=bar,more" */ 800 p = get_opt_name(option, sizeof(option), p, '='); 801 if (*p != '=') { 802 break; 803 } 804 p++; 805 p = get_opt_value(value, sizeof(value), p); 806 } 807 if (strcmp(option, "id") != 0) { 808 /* store and parse */ 809 if (qemu_opt_set(opts, option, value) == -1) { 810 return -1; 811 } 812 } 813 if (*p != ',') { 814 break; 815 } 816 } 817 return 0; 818 } 819 820 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, 821 int permit_abbrev) 822 { 823 const char *firstname; 824 char value[1024], *id = NULL; 825 const char *p; 826 QemuOpts *opts; 827 828 assert(!permit_abbrev || list->implied_opt_name); 829 firstname = permit_abbrev ? list->implied_opt_name : NULL; 830 831 if (strncmp(params, "id=", 3) == 0) { 832 get_opt_value(value, sizeof(value), params+3); 833 id = value; 834 } else if ((p = strstr(params, ",id=")) != NULL) { 835 get_opt_value(value, sizeof(value), p+4); 836 id = value; 837 } 838 opts = qemu_opts_create(list, id, 1); 839 if (opts == NULL) 840 return NULL; 841 842 if (qemu_opts_do_parse(opts, params, firstname) != 0) { 843 qemu_opts_del(opts); 844 return NULL; 845 } 846 847 return opts; 848 } 849 850 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque) 851 { 852 char buf[32]; 853 const char *value; 854 int n; 855 856 if (!strcmp(key, "id")) { 857 return; 858 } 859 860 switch (qobject_type(obj)) { 861 case QTYPE_QSTRING: 862 value = qstring_get_str(qobject_to_qstring(obj)); 863 break; 864 case QTYPE_QINT: 865 n = snprintf(buf, sizeof(buf), "%" PRId64, 866 qint_get_int(qobject_to_qint(obj))); 867 assert(n < sizeof(buf)); 868 value = buf; 869 break; 870 case QTYPE_QFLOAT: 871 n = snprintf(buf, sizeof(buf), "%.17g", 872 qfloat_get_double(qobject_to_qfloat(obj))); 873 assert(n < sizeof(buf)); 874 value = buf; 875 break; 876 case QTYPE_QBOOL: 877 pstrcpy(buf, sizeof(buf), 878 qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off"); 879 value = buf; 880 break; 881 default: 882 return; 883 } 884 qemu_opt_set(opaque, key, value); 885 } 886 887 /* 888 * Create QemuOpts from a QDict. 889 * Use value of key "id" as ID if it exists and is a QString. 890 * Only QStrings, QInts, QFloats and QBools are copied. Entries with 891 * other types are silently ignored. 892 */ 893 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict) 894 { 895 QemuOpts *opts; 896 897 opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1); 898 if (opts == NULL) 899 return NULL; 900 901 qdict_iter(qdict, qemu_opts_from_qdict_1, opts); 902 return opts; 903 } 904 905 /* 906 * Convert from QemuOpts to QDict. 907 * The QDict values are of type QString. 908 * TODO We'll want to use types appropriate for opt->desc->type, but 909 * this is enough for now. 910 */ 911 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict) 912 { 913 QemuOpt *opt; 914 QObject *val; 915 916 if (!qdict) { 917 qdict = qdict_new(); 918 } 919 if (opts->id) { 920 qdict_put(qdict, "id", qstring_from_str(opts->id)); 921 } 922 QTAILQ_FOREACH(opt, &opts->head, next) { 923 val = QOBJECT(qstring_from_str(opt->str)); 924 qdict_put_obj(qdict, opt->name, val); 925 } 926 return qdict; 927 } 928 929 /* Validate parsed opts against descriptions where no 930 * descriptions were provided in the QemuOptsList. 931 */ 932 int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc) 933 { 934 QemuOpt *opt; 935 936 assert(opts->list->desc[0].name == NULL); 937 938 QTAILQ_FOREACH(opt, &opts->head, next) { 939 int i; 940 941 for (i = 0; desc[i].name != NULL; i++) { 942 if (strcmp(desc[i].name, opt->name) == 0) { 943 break; 944 } 945 } 946 if (desc[i].name == NULL) { 947 qerror_report(QERR_INVALID_PARAMETER, opt->name); 948 return -1; 949 } 950 951 opt->desc = &desc[i]; 952 953 if (qemu_opt_parse(opt) < 0) { 954 return -1; 955 } 956 } 957 958 return 0; 959 } 960 961 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque, 962 int abort_on_failure) 963 { 964 Location loc; 965 QemuOpts *opts; 966 int rc = 0; 967 968 loc_push_none(&loc); 969 QTAILQ_FOREACH(opts, &list->head, next) { 970 loc_restore(&opts->loc); 971 rc |= func(opts, opaque); 972 if (abort_on_failure && rc != 0) 973 break; 974 } 975 loc_pop(&loc); 976 return rc; 977 } 978