1 /* 2 * Commandline option parsing functions 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * Copyright (c) 2009 Kevin Wolf <kwolf@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-report.h" 31 #include "qapi/qmp/types.h" 32 #include "qapi/error.h" 33 #include "qapi/qmp/qerror.h" 34 #include "qemu/option_int.h" 35 36 /* 37 * Extracts the name of an option from the parameter string (p points at the 38 * first byte of the option name) 39 * 40 * The option name is delimited by delim (usually , or =) or the string end 41 * and is copied into buf. If the option name is longer than buf_size, it is 42 * truncated. buf is always zero terminated. 43 * 44 * The return value is the position of the delimiter/zero byte after the option 45 * name in p. 46 */ 47 const char *get_opt_name(char *buf, int buf_size, const char *p, char delim) 48 { 49 char *q; 50 51 q = buf; 52 while (*p != '\0' && *p != delim) { 53 if (q && (q - buf) < buf_size - 1) 54 *q++ = *p; 55 p++; 56 } 57 if (q) 58 *q = '\0'; 59 60 return p; 61 } 62 63 /* 64 * Extracts the value of an option from the parameter string p (p points at the 65 * first byte of the option value) 66 * 67 * This function is comparable to get_opt_name with the difference that the 68 * delimiter is fixed to be comma which starts a new option. To specify an 69 * option value that contains commas, double each comma. 70 */ 71 const char *get_opt_value(char *buf, int buf_size, const char *p) 72 { 73 char *q; 74 75 q = buf; 76 while (*p != '\0') { 77 if (*p == ',') { 78 if (*(p + 1) != ',') 79 break; 80 p++; 81 } 82 if (q && (q - buf) < buf_size - 1) 83 *q++ = *p; 84 p++; 85 } 86 if (q) 87 *q = '\0'; 88 89 return p; 90 } 91 92 int get_next_param_value(char *buf, int buf_size, 93 const char *tag, const char **pstr) 94 { 95 const char *p; 96 char option[128]; 97 98 p = *pstr; 99 for(;;) { 100 p = get_opt_name(option, sizeof(option), p, '='); 101 if (*p != '=') 102 break; 103 p++; 104 if (!strcmp(tag, option)) { 105 *pstr = get_opt_value(buf, buf_size, p); 106 if (**pstr == ',') { 107 (*pstr)++; 108 } 109 return strlen(buf); 110 } else { 111 p = get_opt_value(NULL, 0, p); 112 } 113 if (*p != ',') 114 break; 115 p++; 116 } 117 return 0; 118 } 119 120 int get_param_value(char *buf, int buf_size, 121 const char *tag, const char *str) 122 { 123 return get_next_param_value(buf, buf_size, tag, &str); 124 } 125 126 static void parse_option_bool(const char *name, const char *value, bool *ret, 127 Error **errp) 128 { 129 if (value != NULL) { 130 if (!strcmp(value, "on")) { 131 *ret = 1; 132 } else if (!strcmp(value, "off")) { 133 *ret = 0; 134 } else { 135 error_set(errp,QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'"); 136 } 137 } else { 138 *ret = 1; 139 } 140 } 141 142 static void parse_option_number(const char *name, const char *value, 143 uint64_t *ret, Error **errp) 144 { 145 char *postfix; 146 uint64_t number; 147 148 if (value != NULL) { 149 number = strtoull(value, &postfix, 0); 150 if (*postfix != '\0') { 151 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number"); 152 return; 153 } 154 *ret = number; 155 } else { 156 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number"); 157 } 158 } 159 160 static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc, 161 const char *name) 162 { 163 int i; 164 165 for (i = 0; desc[i].name != NULL; i++) { 166 if (strcmp(desc[i].name, name) == 0) { 167 return &desc[i]; 168 } 169 } 170 171 return NULL; 172 } 173 174 void parse_option_size(const char *name, const char *value, 175 uint64_t *ret, Error **errp) 176 { 177 char *postfix; 178 double sizef; 179 180 if (value != NULL) { 181 sizef = strtod(value, &postfix); 182 switch (*postfix) { 183 case 'T': 184 sizef *= 1024; 185 /* fall through */ 186 case 'G': 187 sizef *= 1024; 188 /* fall through */ 189 case 'M': 190 sizef *= 1024; 191 /* fall through */ 192 case 'K': 193 case 'k': 194 sizef *= 1024; 195 /* fall through */ 196 case 'b': 197 case '\0': 198 *ret = (uint64_t) sizef; 199 break; 200 default: 201 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size"); 202 #if 0 /* conversion from qerror_report() to error_set() broke this: */ 203 error_printf_unless_qmp("You may use k, M, G or T suffixes for " 204 "kilobytes, megabytes, gigabytes and terabytes.\n"); 205 #endif 206 return; 207 } 208 } else { 209 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size"); 210 } 211 } 212 213 bool has_help_option(const char *param) 214 { 215 size_t buflen = strlen(param) + 1; 216 char *buf = g_malloc0(buflen); 217 const char *p = param; 218 bool result = false; 219 220 while (*p) { 221 p = get_opt_value(buf, buflen, p); 222 if (*p) { 223 p++; 224 } 225 226 if (is_help_option(buf)) { 227 result = true; 228 goto out; 229 } 230 } 231 232 out: 233 free(buf); 234 return result; 235 } 236 237 bool is_valid_option_list(const char *param) 238 { 239 size_t buflen = strlen(param) + 1; 240 char *buf = g_malloc0(buflen); 241 const char *p = param; 242 bool result = true; 243 244 while (*p) { 245 p = get_opt_value(buf, buflen, p); 246 if (*p && !*++p) { 247 result = false; 248 goto out; 249 } 250 251 if (!*buf || *buf == ',') { 252 result = false; 253 goto out; 254 } 255 } 256 257 out: 258 free(buf); 259 return result; 260 } 261 262 void qemu_opts_print_help(QemuOptsList *list) 263 { 264 QemuOptDesc *desc; 265 266 assert(list); 267 desc = list->desc; 268 printf("Supported options:\n"); 269 while (desc && desc->name) { 270 printf("%-16s %s\n", desc->name, 271 desc->help ? desc->help : "No description available"); 272 desc++; 273 } 274 } 275 /* ------------------------------------------------------------------ */ 276 277 QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name) 278 { 279 QemuOpt *opt; 280 281 QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) { 282 if (strcmp(opt->name, name) != 0) 283 continue; 284 return opt; 285 } 286 return NULL; 287 } 288 289 static void qemu_opt_del(QemuOpt *opt) 290 { 291 QTAILQ_REMOVE(&opt->opts->head, opt, next); 292 g_free(opt->name); 293 g_free(opt->str); 294 g_free(opt); 295 } 296 297 /* qemu_opt_set allows many settings for the same option. 298 * This function deletes all settings for an option. 299 */ 300 static void qemu_opt_del_all(QemuOpts *opts, const char *name) 301 { 302 QemuOpt *opt, *next_opt; 303 304 QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next_opt) { 305 if (!strcmp(opt->name, name)) { 306 qemu_opt_del(opt); 307 } 308 } 309 } 310 311 const char *qemu_opt_get(QemuOpts *opts, const char *name) 312 { 313 QemuOpt *opt; 314 315 if (opts == NULL) { 316 return NULL; 317 } 318 319 opt = qemu_opt_find(opts, name); 320 if (!opt) { 321 const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); 322 if (desc && desc->def_value_str) { 323 return desc->def_value_str; 324 } 325 } 326 return opt ? opt->str : NULL; 327 } 328 329 /* Get a known option (or its default) and remove it from the list 330 * all in one action. Return a malloced string of the option value. 331 * Result must be freed by caller with g_free(). 332 */ 333 char *qemu_opt_get_del(QemuOpts *opts, const char *name) 334 { 335 QemuOpt *opt; 336 const QemuOptDesc *desc; 337 char *str = NULL; 338 339 if (opts == NULL) { 340 return NULL; 341 } 342 343 opt = qemu_opt_find(opts, name); 344 if (!opt) { 345 desc = find_desc_by_name(opts->list->desc, name); 346 if (desc && desc->def_value_str) { 347 str = g_strdup(desc->def_value_str); 348 } 349 return str; 350 } 351 str = opt->str; 352 opt->str = NULL; 353 qemu_opt_del_all(opts, name); 354 return str; 355 } 356 357 bool qemu_opt_has_help_opt(QemuOpts *opts) 358 { 359 QemuOpt *opt; 360 361 QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) { 362 if (is_help_option(opt->name)) { 363 return true; 364 } 365 } 366 return false; 367 } 368 369 static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name, 370 bool defval, bool del) 371 { 372 QemuOpt *opt; 373 bool ret = defval; 374 375 if (opts == NULL) { 376 return ret; 377 } 378 379 opt = qemu_opt_find(opts, name); 380 if (opt == NULL) { 381 const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); 382 if (desc && desc->def_value_str) { 383 parse_option_bool(name, desc->def_value_str, &ret, &error_abort); 384 } 385 return ret; 386 } 387 assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL); 388 ret = opt->value.boolean; 389 if (del) { 390 qemu_opt_del_all(opts, name); 391 } 392 return ret; 393 } 394 395 bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval) 396 { 397 return qemu_opt_get_bool_helper(opts, name, defval, false); 398 } 399 400 bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval) 401 { 402 return qemu_opt_get_bool_helper(opts, name, defval, true); 403 } 404 405 static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name, 406 uint64_t defval, bool del) 407 { 408 QemuOpt *opt; 409 uint64_t ret = defval; 410 411 if (opts == NULL) { 412 return ret; 413 } 414 415 opt = qemu_opt_find(opts, name); 416 if (opt == NULL) { 417 const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); 418 if (desc && desc->def_value_str) { 419 parse_option_number(name, desc->def_value_str, &ret, &error_abort); 420 } 421 return ret; 422 } 423 assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER); 424 ret = opt->value.uint; 425 if (del) { 426 qemu_opt_del_all(opts, name); 427 } 428 return ret; 429 } 430 431 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval) 432 { 433 return qemu_opt_get_number_helper(opts, name, defval, false); 434 } 435 436 uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name, 437 uint64_t defval) 438 { 439 return qemu_opt_get_number_helper(opts, name, defval, true); 440 } 441 442 static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name, 443 uint64_t defval, bool del) 444 { 445 QemuOpt *opt; 446 uint64_t ret = defval; 447 448 if (opts == NULL) { 449 return ret; 450 } 451 452 opt = qemu_opt_find(opts, name); 453 if (opt == NULL) { 454 const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name); 455 if (desc && desc->def_value_str) { 456 parse_option_size(name, desc->def_value_str, &ret, &error_abort); 457 } 458 return ret; 459 } 460 assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE); 461 ret = opt->value.uint; 462 if (del) { 463 qemu_opt_del_all(opts, name); 464 } 465 return ret; 466 } 467 468 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval) 469 { 470 return qemu_opt_get_size_helper(opts, name, defval, false); 471 } 472 473 uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name, 474 uint64_t defval) 475 { 476 return qemu_opt_get_size_helper(opts, name, defval, true); 477 } 478 479 static void qemu_opt_parse(QemuOpt *opt, Error **errp) 480 { 481 if (opt->desc == NULL) 482 return; 483 484 switch (opt->desc->type) { 485 case QEMU_OPT_STRING: 486 /* nothing */ 487 return; 488 case QEMU_OPT_BOOL: 489 parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp); 490 break; 491 case QEMU_OPT_NUMBER: 492 parse_option_number(opt->name, opt->str, &opt->value.uint, errp); 493 break; 494 case QEMU_OPT_SIZE: 495 parse_option_size(opt->name, opt->str, &opt->value.uint, errp); 496 break; 497 default: 498 abort(); 499 } 500 } 501 502 static bool opts_accepts_any(const QemuOpts *opts) 503 { 504 return opts->list->desc[0].name == NULL; 505 } 506 507 int qemu_opt_unset(QemuOpts *opts, const char *name) 508 { 509 QemuOpt *opt = qemu_opt_find(opts, name); 510 511 assert(opts_accepts_any(opts)); 512 513 if (opt == NULL) { 514 return -1; 515 } else { 516 qemu_opt_del(opt); 517 return 0; 518 } 519 } 520 521 static void opt_set(QemuOpts *opts, const char *name, const char *value, 522 bool prepend, Error **errp) 523 { 524 QemuOpt *opt; 525 const QemuOptDesc *desc; 526 Error *local_err = NULL; 527 528 desc = find_desc_by_name(opts->list->desc, name); 529 if (!desc && !opts_accepts_any(opts)) { 530 error_set(errp, QERR_INVALID_PARAMETER, name); 531 return; 532 } 533 534 opt = g_malloc0(sizeof(*opt)); 535 opt->name = g_strdup(name); 536 opt->opts = opts; 537 if (prepend) { 538 QTAILQ_INSERT_HEAD(&opts->head, opt, next); 539 } else { 540 QTAILQ_INSERT_TAIL(&opts->head, opt, next); 541 } 542 opt->desc = desc; 543 opt->str = g_strdup(value); 544 qemu_opt_parse(opt, &local_err); 545 if (local_err) { 546 error_propagate(errp, local_err); 547 qemu_opt_del(opt); 548 } 549 } 550 551 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value) 552 { 553 Error *local_err = NULL; 554 555 opt_set(opts, name, value, false, &local_err); 556 if (local_err) { 557 qerror_report_err(local_err); 558 error_free(local_err); 559 return -1; 560 } 561 562 return 0; 563 } 564 565 void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value, 566 Error **errp) 567 { 568 opt_set(opts, name, value, false, errp); 569 } 570 571 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val) 572 { 573 QemuOpt *opt; 574 const QemuOptDesc *desc = opts->list->desc; 575 576 opt = g_malloc0(sizeof(*opt)); 577 opt->desc = find_desc_by_name(desc, name); 578 if (!opt->desc && !opts_accepts_any(opts)) { 579 qerror_report(QERR_INVALID_PARAMETER, name); 580 g_free(opt); 581 return -1; 582 } 583 584 opt->name = g_strdup(name); 585 opt->opts = opts; 586 opt->value.boolean = !!val; 587 opt->str = g_strdup(val ? "on" : "off"); 588 QTAILQ_INSERT_TAIL(&opts->head, opt, next); 589 590 return 0; 591 } 592 593 int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val) 594 { 595 QemuOpt *opt; 596 const QemuOptDesc *desc = opts->list->desc; 597 598 opt = g_malloc0(sizeof(*opt)); 599 opt->desc = find_desc_by_name(desc, name); 600 if (!opt->desc && !opts_accepts_any(opts)) { 601 qerror_report(QERR_INVALID_PARAMETER, name); 602 g_free(opt); 603 return -1; 604 } 605 606 opt->name = g_strdup(name); 607 opt->opts = opts; 608 opt->value.uint = val; 609 opt->str = g_strdup_printf("%" PRId64, val); 610 QTAILQ_INSERT_TAIL(&opts->head, opt, next); 611 612 return 0; 613 } 614 615 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque, 616 int abort_on_failure) 617 { 618 QemuOpt *opt; 619 int rc = 0; 620 621 QTAILQ_FOREACH(opt, &opts->head, next) { 622 rc = func(opt->name, opt->str, opaque); 623 if (abort_on_failure && rc != 0) 624 break; 625 } 626 return rc; 627 } 628 629 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id) 630 { 631 QemuOpts *opts; 632 633 QTAILQ_FOREACH(opts, &list->head, next) { 634 if (!opts->id && !id) { 635 return opts; 636 } 637 if (opts->id && id && !strcmp(opts->id, id)) { 638 return opts; 639 } 640 } 641 return NULL; 642 } 643 644 static int id_wellformed(const char *id) 645 { 646 int i; 647 648 if (!qemu_isalpha(id[0])) { 649 return 0; 650 } 651 for (i = 1; id[i]; i++) { 652 if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) { 653 return 0; 654 } 655 } 656 return 1; 657 } 658 659 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, 660 int fail_if_exists, Error **errp) 661 { 662 QemuOpts *opts = NULL; 663 664 if (id) { 665 if (!id_wellformed(id)) { 666 error_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier"); 667 #if 0 /* conversion from qerror_report() to error_set() broke this: */ 668 error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n"); 669 #endif 670 return NULL; 671 } 672 opts = qemu_opts_find(list, id); 673 if (opts != NULL) { 674 if (fail_if_exists && !list->merge_lists) { 675 error_setg(errp, "Duplicate ID '%s' for %s", id, list->name); 676 return NULL; 677 } else { 678 return opts; 679 } 680 } 681 } else if (list->merge_lists) { 682 opts = qemu_opts_find(list, NULL); 683 if (opts) { 684 return opts; 685 } 686 } 687 opts = g_malloc0(sizeof(*opts)); 688 opts->id = g_strdup(id); 689 opts->list = list; 690 loc_save(&opts->loc); 691 QTAILQ_INIT(&opts->head); 692 QTAILQ_INSERT_TAIL(&list->head, opts, next); 693 return opts; 694 } 695 696 void qemu_opts_reset(QemuOptsList *list) 697 { 698 QemuOpts *opts, *next_opts; 699 700 QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) { 701 qemu_opts_del(opts); 702 } 703 } 704 705 void qemu_opts_loc_restore(QemuOpts *opts) 706 { 707 loc_restore(&opts->loc); 708 } 709 710 int qemu_opts_set(QemuOptsList *list, const char *id, 711 const char *name, const char *value) 712 { 713 QemuOpts *opts; 714 Error *local_err = NULL; 715 716 opts = qemu_opts_create(list, id, 1, &local_err); 717 if (local_err) { 718 qerror_report_err(local_err); 719 error_free(local_err); 720 return -1; 721 } 722 return qemu_opt_set(opts, name, value); 723 } 724 725 const char *qemu_opts_id(QemuOpts *opts) 726 { 727 return opts->id; 728 } 729 730 /* The id string will be g_free()d by qemu_opts_del */ 731 void qemu_opts_set_id(QemuOpts *opts, char *id) 732 { 733 opts->id = id; 734 } 735 736 void qemu_opts_del(QemuOpts *opts) 737 { 738 QemuOpt *opt; 739 740 if (opts == NULL) { 741 return; 742 } 743 744 for (;;) { 745 opt = QTAILQ_FIRST(&opts->head); 746 if (opt == NULL) 747 break; 748 qemu_opt_del(opt); 749 } 750 QTAILQ_REMOVE(&opts->list->head, opts, next); 751 g_free(opts->id); 752 g_free(opts); 753 } 754 755 void qemu_opts_print(QemuOpts *opts) 756 { 757 QemuOpt *opt; 758 QemuOptDesc *desc = opts->list->desc; 759 760 if (desc[0].name == NULL) { 761 QTAILQ_FOREACH(opt, &opts->head, next) { 762 printf("%s=\"%s\" ", opt->name, opt->str); 763 } 764 return; 765 } 766 for (; desc && desc->name; desc++) { 767 const char *value; 768 QemuOpt *opt = qemu_opt_find(opts, desc->name); 769 770 value = opt ? opt->str : desc->def_value_str; 771 if (!value) { 772 continue; 773 } 774 if (desc->type == QEMU_OPT_STRING) { 775 printf("%s='%s' ", desc->name, value); 776 } else if ((desc->type == QEMU_OPT_SIZE || 777 desc->type == QEMU_OPT_NUMBER) && opt) { 778 printf("%s=%" PRId64 " ", desc->name, opt->value.uint); 779 } else { 780 printf("%s=%s ", desc->name, value); 781 } 782 } 783 } 784 785 static int opts_do_parse(QemuOpts *opts, const char *params, 786 const char *firstname, bool prepend) 787 { 788 char option[128], value[1024]; 789 const char *p,*pe,*pc; 790 Error *local_err = NULL; 791 792 for (p = params; *p != '\0'; p++) { 793 pe = strchr(p, '='); 794 pc = strchr(p, ','); 795 if (!pe || (pc && pc < pe)) { 796 /* found "foo,more" */ 797 if (p == params && firstname) { 798 /* implicitly named first option */ 799 pstrcpy(option, sizeof(option), firstname); 800 p = get_opt_value(value, sizeof(value), p); 801 } else { 802 /* option without value, probably a flag */ 803 p = get_opt_name(option, sizeof(option), p, ','); 804 if (strncmp(option, "no", 2) == 0) { 805 memmove(option, option+2, strlen(option+2)+1); 806 pstrcpy(value, sizeof(value), "off"); 807 } else { 808 pstrcpy(value, sizeof(value), "on"); 809 } 810 } 811 } else { 812 /* found "foo=bar,more" */ 813 p = get_opt_name(option, sizeof(option), p, '='); 814 if (*p != '=') { 815 break; 816 } 817 p++; 818 p = get_opt_value(value, sizeof(value), p); 819 } 820 if (strcmp(option, "id") != 0) { 821 /* store and parse */ 822 opt_set(opts, option, value, prepend, &local_err); 823 if (local_err) { 824 qerror_report_err(local_err); 825 error_free(local_err); 826 return -1; 827 } 828 } 829 if (*p != ',') { 830 break; 831 } 832 } 833 return 0; 834 } 835 836 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname) 837 { 838 return opts_do_parse(opts, params, firstname, false); 839 } 840 841 static QemuOpts *opts_parse(QemuOptsList *list, const char *params, 842 int permit_abbrev, bool defaults) 843 { 844 const char *firstname; 845 char value[1024], *id = NULL; 846 const char *p; 847 QemuOpts *opts; 848 Error *local_err = NULL; 849 850 assert(!permit_abbrev || list->implied_opt_name); 851 firstname = permit_abbrev ? list->implied_opt_name : NULL; 852 853 if (strncmp(params, "id=", 3) == 0) { 854 get_opt_value(value, sizeof(value), params+3); 855 id = value; 856 } else if ((p = strstr(params, ",id=")) != NULL) { 857 get_opt_value(value, sizeof(value), p+4); 858 id = value; 859 } 860 861 /* 862 * This code doesn't work for defaults && !list->merge_lists: when 863 * params has no id=, and list has an element with !opts->id, it 864 * appends a new element instead of returning the existing opts. 865 * However, we got no use for this case. Guard against possible 866 * (if unlikely) future misuse: 867 */ 868 assert(!defaults || list->merge_lists); 869 opts = qemu_opts_create(list, id, !defaults, &local_err); 870 if (opts == NULL) { 871 if (local_err) { 872 qerror_report_err(local_err); 873 error_free(local_err); 874 } 875 return NULL; 876 } 877 878 if (opts_do_parse(opts, params, firstname, defaults) != 0) { 879 qemu_opts_del(opts); 880 return NULL; 881 } 882 883 return opts; 884 } 885 886 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, 887 int permit_abbrev) 888 { 889 return opts_parse(list, params, permit_abbrev, false); 890 } 891 892 void qemu_opts_set_defaults(QemuOptsList *list, const char *params, 893 int permit_abbrev) 894 { 895 QemuOpts *opts; 896 897 opts = opts_parse(list, params, permit_abbrev, true); 898 assert(opts); 899 } 900 901 typedef struct OptsFromQDictState { 902 QemuOpts *opts; 903 Error **errp; 904 } OptsFromQDictState; 905 906 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque) 907 { 908 OptsFromQDictState *state = opaque; 909 char buf[32]; 910 const char *value; 911 int n; 912 913 if (!strcmp(key, "id") || *state->errp) { 914 return; 915 } 916 917 switch (qobject_type(obj)) { 918 case QTYPE_QSTRING: 919 value = qstring_get_str(qobject_to_qstring(obj)); 920 break; 921 case QTYPE_QINT: 922 n = snprintf(buf, sizeof(buf), "%" PRId64, 923 qint_get_int(qobject_to_qint(obj))); 924 assert(n < sizeof(buf)); 925 value = buf; 926 break; 927 case QTYPE_QFLOAT: 928 n = snprintf(buf, sizeof(buf), "%.17g", 929 qfloat_get_double(qobject_to_qfloat(obj))); 930 assert(n < sizeof(buf)); 931 value = buf; 932 break; 933 case QTYPE_QBOOL: 934 pstrcpy(buf, sizeof(buf), 935 qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off"); 936 value = buf; 937 break; 938 default: 939 return; 940 } 941 942 qemu_opt_set_err(state->opts, key, value, state->errp); 943 } 944 945 /* 946 * Create QemuOpts from a QDict. 947 * Use value of key "id" as ID if it exists and is a QString. 948 * Only QStrings, QInts, QFloats and QBools are copied. Entries with 949 * other types are silently ignored. 950 */ 951 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, 952 Error **errp) 953 { 954 OptsFromQDictState state; 955 Error *local_err = NULL; 956 QemuOpts *opts; 957 958 opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, 959 &local_err); 960 if (local_err) { 961 error_propagate(errp, local_err); 962 return NULL; 963 } 964 965 assert(opts != NULL); 966 967 state.errp = &local_err; 968 state.opts = opts; 969 qdict_iter(qdict, qemu_opts_from_qdict_1, &state); 970 if (local_err) { 971 error_propagate(errp, local_err); 972 qemu_opts_del(opts); 973 return NULL; 974 } 975 976 return opts; 977 } 978 979 /* 980 * Adds all QDict entries to the QemuOpts that can be added and removes them 981 * from the QDict. When this function returns, the QDict contains only those 982 * entries that couldn't be added to the QemuOpts. 983 */ 984 void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp) 985 { 986 const QDictEntry *entry, *next; 987 988 entry = qdict_first(qdict); 989 990 while (entry != NULL) { 991 Error *local_err = NULL; 992 OptsFromQDictState state = { 993 .errp = &local_err, 994 .opts = opts, 995 }; 996 997 next = qdict_next(qdict, entry); 998 999 if (find_desc_by_name(opts->list->desc, entry->key)) { 1000 qemu_opts_from_qdict_1(entry->key, entry->value, &state); 1001 if (local_err) { 1002 error_propagate(errp, local_err); 1003 return; 1004 } else { 1005 qdict_del(qdict, entry->key); 1006 } 1007 } 1008 1009 entry = next; 1010 } 1011 } 1012 1013 /* 1014 * Convert from QemuOpts to QDict. 1015 * The QDict values are of type QString. 1016 * TODO We'll want to use types appropriate for opt->desc->type, but 1017 * this is enough for now. 1018 */ 1019 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict) 1020 { 1021 QemuOpt *opt; 1022 QObject *val; 1023 1024 if (!qdict) { 1025 qdict = qdict_new(); 1026 } 1027 if (opts->id) { 1028 qdict_put(qdict, "id", qstring_from_str(opts->id)); 1029 } 1030 QTAILQ_FOREACH(opt, &opts->head, next) { 1031 val = QOBJECT(qstring_from_str(opt->str)); 1032 qdict_put_obj(qdict, opt->name, val); 1033 } 1034 return qdict; 1035 } 1036 1037 /* Validate parsed opts against descriptions where no 1038 * descriptions were provided in the QemuOptsList. 1039 */ 1040 void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) 1041 { 1042 QemuOpt *opt; 1043 Error *local_err = NULL; 1044 1045 assert(opts_accepts_any(opts)); 1046 1047 QTAILQ_FOREACH(opt, &opts->head, next) { 1048 opt->desc = find_desc_by_name(desc, opt->name); 1049 if (!opt->desc) { 1050 error_set(errp, QERR_INVALID_PARAMETER, opt->name); 1051 return; 1052 } 1053 1054 qemu_opt_parse(opt, &local_err); 1055 if (local_err) { 1056 error_propagate(errp, local_err); 1057 return; 1058 } 1059 } 1060 } 1061 1062 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque, 1063 int abort_on_failure) 1064 { 1065 Location loc; 1066 QemuOpts *opts; 1067 int rc = 0; 1068 1069 loc_push_none(&loc); 1070 QTAILQ_FOREACH(opts, &list->head, next) { 1071 loc_restore(&opts->loc); 1072 rc |= func(opts, opaque); 1073 if (abort_on_failure && rc != 0) 1074 break; 1075 } 1076 loc_pop(&loc); 1077 return rc; 1078 } 1079 1080 static size_t count_opts_list(QemuOptsList *list) 1081 { 1082 QemuOptDesc *desc = NULL; 1083 size_t num_opts = 0; 1084 1085 if (!list) { 1086 return 0; 1087 } 1088 1089 desc = list->desc; 1090 while (desc && desc->name) { 1091 num_opts++; 1092 desc++; 1093 } 1094 1095 return num_opts; 1096 } 1097 1098 void qemu_opts_free(QemuOptsList *list) 1099 { 1100 g_free(list); 1101 } 1102 1103 /* Realloc dst option list and append options from an option list (list) 1104 * to it. dst could be NULL or a malloced list. 1105 * The lifetime of dst must be shorter than the input list because the 1106 * QemuOptDesc->name, ->help, and ->def_value_str strings are shared. 1107 */ 1108 QemuOptsList *qemu_opts_append(QemuOptsList *dst, 1109 QemuOptsList *list) 1110 { 1111 size_t num_opts, num_dst_opts; 1112 QemuOptDesc *desc; 1113 bool need_init = false; 1114 bool need_head_update; 1115 1116 if (!list) { 1117 return dst; 1118 } 1119 1120 /* If dst is NULL, after realloc, some area of dst should be initialized 1121 * before adding options to it. 1122 */ 1123 if (!dst) { 1124 need_init = true; 1125 need_head_update = true; 1126 } else { 1127 /* Moreover, even if dst is not NULL, the realloc may move it to a 1128 * different address in which case we may get a stale tail pointer 1129 * in dst->head. */ 1130 need_head_update = QTAILQ_EMPTY(&dst->head); 1131 } 1132 1133 num_opts = count_opts_list(dst); 1134 num_dst_opts = num_opts; 1135 num_opts += count_opts_list(list); 1136 dst = g_realloc(dst, sizeof(QemuOptsList) + 1137 (num_opts + 1) * sizeof(QemuOptDesc)); 1138 if (need_init) { 1139 dst->name = NULL; 1140 dst->implied_opt_name = NULL; 1141 dst->merge_lists = false; 1142 } 1143 if (need_head_update) { 1144 QTAILQ_INIT(&dst->head); 1145 } 1146 dst->desc[num_dst_opts].name = NULL; 1147 1148 /* append list->desc to dst->desc */ 1149 if (list) { 1150 desc = list->desc; 1151 while (desc && desc->name) { 1152 if (find_desc_by_name(dst->desc, desc->name) == NULL) { 1153 dst->desc[num_dst_opts++] = *desc; 1154 dst->desc[num_dst_opts].name = NULL; 1155 } 1156 desc++; 1157 } 1158 } 1159 1160 return dst; 1161 } 1162