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 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, 645 int fail_if_exists, Error **errp) 646 { 647 QemuOpts *opts = NULL; 648 649 if (id) { 650 if (!id_wellformed(id)) { 651 error_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier"); 652 #if 0 /* conversion from qerror_report() to error_set() broke this: */ 653 error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n"); 654 #endif 655 return NULL; 656 } 657 opts = qemu_opts_find(list, id); 658 if (opts != NULL) { 659 if (fail_if_exists && !list->merge_lists) { 660 error_setg(errp, "Duplicate ID '%s' for %s", id, list->name); 661 return NULL; 662 } else { 663 return opts; 664 } 665 } 666 } else if (list->merge_lists) { 667 opts = qemu_opts_find(list, NULL); 668 if (opts) { 669 return opts; 670 } 671 } 672 opts = g_malloc0(sizeof(*opts)); 673 opts->id = g_strdup(id); 674 opts->list = list; 675 loc_save(&opts->loc); 676 QTAILQ_INIT(&opts->head); 677 QTAILQ_INSERT_TAIL(&list->head, opts, next); 678 return opts; 679 } 680 681 void qemu_opts_reset(QemuOptsList *list) 682 { 683 QemuOpts *opts, *next_opts; 684 685 QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) { 686 qemu_opts_del(opts); 687 } 688 } 689 690 void qemu_opts_loc_restore(QemuOpts *opts) 691 { 692 loc_restore(&opts->loc); 693 } 694 695 int qemu_opts_set(QemuOptsList *list, const char *id, 696 const char *name, const char *value) 697 { 698 QemuOpts *opts; 699 Error *local_err = NULL; 700 701 opts = qemu_opts_create(list, id, 1, &local_err); 702 if (local_err) { 703 qerror_report_err(local_err); 704 error_free(local_err); 705 return -1; 706 } 707 return qemu_opt_set(opts, name, value); 708 } 709 710 const char *qemu_opts_id(QemuOpts *opts) 711 { 712 return opts->id; 713 } 714 715 /* The id string will be g_free()d by qemu_opts_del */ 716 void qemu_opts_set_id(QemuOpts *opts, char *id) 717 { 718 opts->id = id; 719 } 720 721 void qemu_opts_del(QemuOpts *opts) 722 { 723 QemuOpt *opt; 724 725 if (opts == NULL) { 726 return; 727 } 728 729 for (;;) { 730 opt = QTAILQ_FIRST(&opts->head); 731 if (opt == NULL) 732 break; 733 qemu_opt_del(opt); 734 } 735 QTAILQ_REMOVE(&opts->list->head, opts, next); 736 g_free(opts->id); 737 g_free(opts); 738 } 739 740 void qemu_opts_print(QemuOpts *opts) 741 { 742 QemuOpt *opt; 743 QemuOptDesc *desc = opts->list->desc; 744 745 if (desc[0].name == NULL) { 746 QTAILQ_FOREACH(opt, &opts->head, next) { 747 printf("%s=\"%s\" ", opt->name, opt->str); 748 } 749 return; 750 } 751 for (; desc && desc->name; desc++) { 752 const char *value; 753 QemuOpt *opt = qemu_opt_find(opts, desc->name); 754 755 value = opt ? opt->str : desc->def_value_str; 756 if (!value) { 757 continue; 758 } 759 if (desc->type == QEMU_OPT_STRING) { 760 printf("%s='%s' ", desc->name, value); 761 } else if ((desc->type == QEMU_OPT_SIZE || 762 desc->type == QEMU_OPT_NUMBER) && opt) { 763 printf("%s=%" PRId64 " ", desc->name, opt->value.uint); 764 } else { 765 printf("%s=%s ", desc->name, value); 766 } 767 } 768 } 769 770 static int opts_do_parse(QemuOpts *opts, const char *params, 771 const char *firstname, bool prepend) 772 { 773 char option[128], value[1024]; 774 const char *p,*pe,*pc; 775 Error *local_err = NULL; 776 777 for (p = params; *p != '\0'; p++) { 778 pe = strchr(p, '='); 779 pc = strchr(p, ','); 780 if (!pe || (pc && pc < pe)) { 781 /* found "foo,more" */ 782 if (p == params && firstname) { 783 /* implicitly named first option */ 784 pstrcpy(option, sizeof(option), firstname); 785 p = get_opt_value(value, sizeof(value), p); 786 } else { 787 /* option without value, probably a flag */ 788 p = get_opt_name(option, sizeof(option), p, ','); 789 if (strncmp(option, "no", 2) == 0) { 790 memmove(option, option+2, strlen(option+2)+1); 791 pstrcpy(value, sizeof(value), "off"); 792 } else { 793 pstrcpy(value, sizeof(value), "on"); 794 } 795 } 796 } else { 797 /* found "foo=bar,more" */ 798 p = get_opt_name(option, sizeof(option), p, '='); 799 if (*p != '=') { 800 break; 801 } 802 p++; 803 p = get_opt_value(value, sizeof(value), p); 804 } 805 if (strcmp(option, "id") != 0) { 806 /* store and parse */ 807 opt_set(opts, option, value, prepend, &local_err); 808 if (local_err) { 809 qerror_report_err(local_err); 810 error_free(local_err); 811 return -1; 812 } 813 } 814 if (*p != ',') { 815 break; 816 } 817 } 818 return 0; 819 } 820 821 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname) 822 { 823 return opts_do_parse(opts, params, firstname, false); 824 } 825 826 static QemuOpts *opts_parse(QemuOptsList *list, const char *params, 827 int permit_abbrev, bool defaults) 828 { 829 const char *firstname; 830 char value[1024], *id = NULL; 831 const char *p; 832 QemuOpts *opts; 833 Error *local_err = NULL; 834 835 assert(!permit_abbrev || list->implied_opt_name); 836 firstname = permit_abbrev ? list->implied_opt_name : NULL; 837 838 if (strncmp(params, "id=", 3) == 0) { 839 get_opt_value(value, sizeof(value), params+3); 840 id = value; 841 } else if ((p = strstr(params, ",id=")) != NULL) { 842 get_opt_value(value, sizeof(value), p+4); 843 id = value; 844 } 845 846 /* 847 * This code doesn't work for defaults && !list->merge_lists: when 848 * params has no id=, and list has an element with !opts->id, it 849 * appends a new element instead of returning the existing opts. 850 * However, we got no use for this case. Guard against possible 851 * (if unlikely) future misuse: 852 */ 853 assert(!defaults || list->merge_lists); 854 opts = qemu_opts_create(list, id, !defaults, &local_err); 855 if (opts == NULL) { 856 if (local_err) { 857 qerror_report_err(local_err); 858 error_free(local_err); 859 } 860 return NULL; 861 } 862 863 if (opts_do_parse(opts, params, firstname, defaults) != 0) { 864 qemu_opts_del(opts); 865 return NULL; 866 } 867 868 return opts; 869 } 870 871 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, 872 int permit_abbrev) 873 { 874 return opts_parse(list, params, permit_abbrev, false); 875 } 876 877 void qemu_opts_set_defaults(QemuOptsList *list, const char *params, 878 int permit_abbrev) 879 { 880 QemuOpts *opts; 881 882 opts = opts_parse(list, params, permit_abbrev, true); 883 assert(opts); 884 } 885 886 typedef struct OptsFromQDictState { 887 QemuOpts *opts; 888 Error **errp; 889 } OptsFromQDictState; 890 891 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque) 892 { 893 OptsFromQDictState *state = opaque; 894 char buf[32]; 895 const char *value; 896 int n; 897 898 if (!strcmp(key, "id") || *state->errp) { 899 return; 900 } 901 902 switch (qobject_type(obj)) { 903 case QTYPE_QSTRING: 904 value = qstring_get_str(qobject_to_qstring(obj)); 905 break; 906 case QTYPE_QINT: 907 n = snprintf(buf, sizeof(buf), "%" PRId64, 908 qint_get_int(qobject_to_qint(obj))); 909 assert(n < sizeof(buf)); 910 value = buf; 911 break; 912 case QTYPE_QFLOAT: 913 n = snprintf(buf, sizeof(buf), "%.17g", 914 qfloat_get_double(qobject_to_qfloat(obj))); 915 assert(n < sizeof(buf)); 916 value = buf; 917 break; 918 case QTYPE_QBOOL: 919 pstrcpy(buf, sizeof(buf), 920 qbool_get_int(qobject_to_qbool(obj)) ? "on" : "off"); 921 value = buf; 922 break; 923 default: 924 return; 925 } 926 927 qemu_opt_set_err(state->opts, key, value, state->errp); 928 } 929 930 /* 931 * Create QemuOpts from a QDict. 932 * Use value of key "id" as ID if it exists and is a QString. 933 * Only QStrings, QInts, QFloats and QBools are copied. Entries with 934 * other types are silently ignored. 935 */ 936 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict, 937 Error **errp) 938 { 939 OptsFromQDictState state; 940 Error *local_err = NULL; 941 QemuOpts *opts; 942 943 opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, 944 &local_err); 945 if (local_err) { 946 error_propagate(errp, local_err); 947 return NULL; 948 } 949 950 assert(opts != NULL); 951 952 state.errp = &local_err; 953 state.opts = opts; 954 qdict_iter(qdict, qemu_opts_from_qdict_1, &state); 955 if (local_err) { 956 error_propagate(errp, local_err); 957 qemu_opts_del(opts); 958 return NULL; 959 } 960 961 return opts; 962 } 963 964 /* 965 * Adds all QDict entries to the QemuOpts that can be added and removes them 966 * from the QDict. When this function returns, the QDict contains only those 967 * entries that couldn't be added to the QemuOpts. 968 */ 969 void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp) 970 { 971 const QDictEntry *entry, *next; 972 973 entry = qdict_first(qdict); 974 975 while (entry != NULL) { 976 Error *local_err = NULL; 977 OptsFromQDictState state = { 978 .errp = &local_err, 979 .opts = opts, 980 }; 981 982 next = qdict_next(qdict, entry); 983 984 if (find_desc_by_name(opts->list->desc, entry->key)) { 985 qemu_opts_from_qdict_1(entry->key, entry->value, &state); 986 if (local_err) { 987 error_propagate(errp, local_err); 988 return; 989 } else { 990 qdict_del(qdict, entry->key); 991 } 992 } 993 994 entry = next; 995 } 996 } 997 998 /* 999 * Convert from QemuOpts to QDict. 1000 * The QDict values are of type QString. 1001 * TODO We'll want to use types appropriate for opt->desc->type, but 1002 * this is enough for now. 1003 */ 1004 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict) 1005 { 1006 QemuOpt *opt; 1007 QObject *val; 1008 1009 if (!qdict) { 1010 qdict = qdict_new(); 1011 } 1012 if (opts->id) { 1013 qdict_put(qdict, "id", qstring_from_str(opts->id)); 1014 } 1015 QTAILQ_FOREACH(opt, &opts->head, next) { 1016 val = QOBJECT(qstring_from_str(opt->str)); 1017 qdict_put_obj(qdict, opt->name, val); 1018 } 1019 return qdict; 1020 } 1021 1022 /* Validate parsed opts against descriptions where no 1023 * descriptions were provided in the QemuOptsList. 1024 */ 1025 void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp) 1026 { 1027 QemuOpt *opt; 1028 Error *local_err = NULL; 1029 1030 assert(opts_accepts_any(opts)); 1031 1032 QTAILQ_FOREACH(opt, &opts->head, next) { 1033 opt->desc = find_desc_by_name(desc, opt->name); 1034 if (!opt->desc) { 1035 error_set(errp, QERR_INVALID_PARAMETER, opt->name); 1036 return; 1037 } 1038 1039 qemu_opt_parse(opt, &local_err); 1040 if (local_err) { 1041 error_propagate(errp, local_err); 1042 return; 1043 } 1044 } 1045 } 1046 1047 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque, 1048 int abort_on_failure) 1049 { 1050 Location loc; 1051 QemuOpts *opts; 1052 int rc = 0; 1053 1054 loc_push_none(&loc); 1055 QTAILQ_FOREACH(opts, &list->head, next) { 1056 loc_restore(&opts->loc); 1057 rc |= func(opts, opaque); 1058 if (abort_on_failure && rc != 0) 1059 break; 1060 } 1061 loc_pop(&loc); 1062 return rc; 1063 } 1064 1065 static size_t count_opts_list(QemuOptsList *list) 1066 { 1067 QemuOptDesc *desc = NULL; 1068 size_t num_opts = 0; 1069 1070 if (!list) { 1071 return 0; 1072 } 1073 1074 desc = list->desc; 1075 while (desc && desc->name) { 1076 num_opts++; 1077 desc++; 1078 } 1079 1080 return num_opts; 1081 } 1082 1083 void qemu_opts_free(QemuOptsList *list) 1084 { 1085 g_free(list); 1086 } 1087 1088 /* Realloc dst option list and append options from an option list (list) 1089 * to it. dst could be NULL or a malloced list. 1090 * The lifetime of dst must be shorter than the input list because the 1091 * QemuOptDesc->name, ->help, and ->def_value_str strings are shared. 1092 */ 1093 QemuOptsList *qemu_opts_append(QemuOptsList *dst, 1094 QemuOptsList *list) 1095 { 1096 size_t num_opts, num_dst_opts; 1097 QemuOptDesc *desc; 1098 bool need_init = false; 1099 bool need_head_update; 1100 1101 if (!list) { 1102 return dst; 1103 } 1104 1105 /* If dst is NULL, after realloc, some area of dst should be initialized 1106 * before adding options to it. 1107 */ 1108 if (!dst) { 1109 need_init = true; 1110 need_head_update = true; 1111 } else { 1112 /* Moreover, even if dst is not NULL, the realloc may move it to a 1113 * different address in which case we may get a stale tail pointer 1114 * in dst->head. */ 1115 need_head_update = QTAILQ_EMPTY(&dst->head); 1116 } 1117 1118 num_opts = count_opts_list(dst); 1119 num_dst_opts = num_opts; 1120 num_opts += count_opts_list(list); 1121 dst = g_realloc(dst, sizeof(QemuOptsList) + 1122 (num_opts + 1) * sizeof(QemuOptDesc)); 1123 if (need_init) { 1124 dst->name = NULL; 1125 dst->implied_opt_name = NULL; 1126 dst->merge_lists = false; 1127 } 1128 if (need_head_update) { 1129 QTAILQ_INIT(&dst->head); 1130 } 1131 dst->desc[num_dst_opts].name = NULL; 1132 1133 /* append list->desc to dst->desc */ 1134 if (list) { 1135 desc = list->desc; 1136 while (desc && desc->name) { 1137 if (find_desc_by_name(dst->desc, desc->name) == NULL) { 1138 dst->desc[num_dst_opts++] = *desc; 1139 dst->desc[num_dst_opts].name = NULL; 1140 } 1141 desc++; 1142 } 1143 } 1144 1145 return dst; 1146 } 1147