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