qemu/util/qemu-option.c
<<
>>
Prefs
   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 "qemu/osdep.h"
  27
  28#include "qapi/error.h"
  29#include "qemu/error-report.h"
  30#include "qapi/qmp/qbool.h"
  31#include "qapi/qmp/qdict.h"
  32#include "qapi/qmp/qnum.h"
  33#include "qapi/qmp/qstring.h"
  34#include "qapi/qmp/qerror.h"
  35#include "qemu/option_int.h"
  36#include "qemu/cutils.h"
  37#include "qemu/id.h"
  38#include "qemu/help_option.h"
  39
  40/*
  41 * Extracts the name of an option from the parameter string (p points at the
  42 * first byte of the option name)
  43 *
  44 * The option name is delimited by delim (usually , or =) or the string end
  45 * and is copied into option. The caller is responsible for free'ing option
  46 * when no longer required.
  47 *
  48 * The return value is the position of the delimiter/zero byte after the option
  49 * name in p.
  50 */
  51static const char *get_opt_name(const char *p, char **option, char delim)
  52{
  53    char *offset = strchr(p, delim);
  54
  55    if (offset) {
  56        *option = g_strndup(p, offset - p);
  57        return offset;
  58    } else {
  59        *option = g_strdup(p);
  60        return p + strlen(p);
  61    }
  62}
  63
  64/*
  65 * Extracts the value of an option from the parameter string p (p points at the
  66 * first byte of the option value)
  67 *
  68 * This function is comparable to get_opt_name with the difference that the
  69 * delimiter is fixed to be comma which starts a new option. To specify an
  70 * option value that contains commas, double each comma.
  71 */
  72const char *get_opt_value(const char *p, char **value)
  73{
  74    size_t capacity = 0, length;
  75    const char *offset;
  76
  77    *value = NULL;
  78    while (1) {
  79        offset = qemu_strchrnul(p, ',');
  80        length = offset - p;
  81        if (*offset != '\0' && *(offset + 1) == ',') {
  82            length++;
  83        }
  84        *value = g_renew(char, *value, capacity + length + 1);
  85        strncpy(*value + capacity, p, length);
  86        (*value)[capacity + length] = '\0';
  87        capacity += length;
  88        if (*offset == '\0' ||
  89            *(offset + 1) != ',') {
  90            break;
  91        }
  92
  93        p += (offset - p) + 2;
  94    }
  95
  96    return offset;
  97}
  98
  99static bool parse_option_bool(const char *name, const char *value, bool *ret,
 100                              Error **errp)
 101{
 102    if (!strcmp(value, "on")) {
 103        *ret = 1;
 104    } else if (!strcmp(value, "off")) {
 105        *ret = 0;
 106    } else {
 107        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
 108                   name, "'on' or 'off'");
 109        return false;
 110    }
 111    return true;
 112}
 113
 114static bool parse_option_number(const char *name, const char *value,
 115                                uint64_t *ret, Error **errp)
 116{
 117    uint64_t number;
 118    int err;
 119
 120    err = qemu_strtou64(value, NULL, 0, &number);
 121    if (err == -ERANGE) {
 122        error_setg(errp, "Value '%s' is too large for parameter '%s'",
 123                   value, name);
 124        return false;
 125    }
 126    if (err) {
 127        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
 128        return false;
 129    }
 130    *ret = number;
 131    return true;
 132}
 133
 134static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
 135                                            const char *name)
 136{
 137    int i;
 138
 139    for (i = 0; desc[i].name != NULL; i++) {
 140        if (strcmp(desc[i].name, name) == 0) {
 141            return &desc[i];
 142        }
 143    }
 144
 145    return NULL;
 146}
 147
 148static const char *find_default_by_name(QemuOpts *opts, const char *name)
 149{
 150    const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
 151
 152    return desc ? desc->def_value_str : NULL;
 153}
 154
 155bool parse_option_size(const char *name, const char *value,
 156                       uint64_t *ret, Error **errp)
 157{
 158    uint64_t size;
 159    int err;
 160
 161    err = qemu_strtosz(value, NULL, &size);
 162    if (err == -ERANGE) {
 163        error_setg(errp, "Value '%s' is out of range for parameter '%s'",
 164                   value, name);
 165        return false;
 166    }
 167    if (err) {
 168        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
 169                   "a non-negative number below 2^64");
 170        error_append_hint(errp, "Optional suffix k, M, G, T, P or E means"
 171                          " kilo-, mega-, giga-, tera-, peta-\n"
 172                          "and exabytes, respectively.\n");
 173        return false;
 174    }
 175    *ret = size;
 176    return true;
 177}
 178
 179static const char *opt_type_to_string(enum QemuOptType type)
 180{
 181    switch (type) {
 182    case QEMU_OPT_STRING:
 183        return "str";
 184    case QEMU_OPT_BOOL:
 185        return "bool (on/off)";
 186    case QEMU_OPT_NUMBER:
 187        return "num";
 188    case QEMU_OPT_SIZE:
 189        return "size";
 190    }
 191
 192    g_assert_not_reached();
 193}
 194
 195/**
 196 * Print the list of options available in the given list.  If
 197 * @print_caption is true, a caption (including the list name, if it
 198 * exists) is printed.  The options itself will be indented, so
 199 * @print_caption should only be set to false if the caller prints its
 200 * own custom caption (so that the indentation makes sense).
 201 */
 202void qemu_opts_print_help(QemuOptsList *list, bool print_caption)
 203{
 204    QemuOptDesc *desc;
 205    int i;
 206    GPtrArray *array = g_ptr_array_new();
 207
 208    assert(list);
 209    desc = list->desc;
 210    while (desc && desc->name) {
 211        GString *str = g_string_new(NULL);
 212        g_string_append_printf(str, "  %s=<%s>", desc->name,
 213                               opt_type_to_string(desc->type));
 214        if (desc->help) {
 215            if (str->len < 24) {
 216                g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
 217            }
 218            g_string_append_printf(str, " - %s", desc->help);
 219        }
 220        g_ptr_array_add(array, g_string_free(str, false));
 221        desc++;
 222    }
 223
 224    g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
 225    if (print_caption && array->len > 0) {
 226        if (list->name) {
 227            printf("%s options:\n", list->name);
 228        } else {
 229            printf("Options:\n");
 230        }
 231    } else if (array->len == 0) {
 232        if (list->name) {
 233            printf("There are no options for %s.\n", list->name);
 234        } else {
 235            printf("No options available.\n");
 236        }
 237    }
 238    for (i = 0; i < array->len; i++) {
 239        printf("%s\n", (char *)array->pdata[i]);
 240    }
 241    g_ptr_array_set_free_func(array, g_free);
 242    g_ptr_array_free(array, true);
 243
 244}
 245/* ------------------------------------------------------------------ */
 246
 247QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
 248{
 249    QemuOpt *opt;
 250
 251    QTAILQ_FOREACH_REVERSE(opt, &opts->head, next) {
 252        if (strcmp(opt->name, name) != 0)
 253            continue;
 254        return opt;
 255    }
 256    return NULL;
 257}
 258
 259static void qemu_opt_del(QemuOpt *opt)
 260{
 261    QTAILQ_REMOVE(&opt->opts->head, opt, next);
 262    g_free(opt->name);
 263    g_free(opt->str);
 264    g_free(opt);
 265}
 266
 267/* qemu_opt_set allows many settings for the same option.
 268 * This function deletes all settings for an option.
 269 */
 270static void qemu_opt_del_all(QemuOpts *opts, const char *name)
 271{
 272    QemuOpt *opt, *next_opt;
 273
 274    QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next_opt) {
 275        if (!strcmp(opt->name, name)) {
 276            qemu_opt_del(opt);
 277        }
 278    }
 279}
 280
 281const char *qemu_opt_get(QemuOpts *opts, const char *name)
 282{
 283    QemuOpt *opt;
 284
 285    if (opts == NULL) {
 286        return NULL;
 287    }
 288
 289    opt = qemu_opt_find(opts, name);
 290    if (!opt) {
 291        return find_default_by_name(opts, name);
 292    }
 293
 294    return opt->str;
 295}
 296
 297void qemu_opt_iter_init(QemuOptsIter *iter, QemuOpts *opts, const char *name)
 298{
 299    iter->opts = opts;
 300    iter->opt = QTAILQ_FIRST(&opts->head);
 301    iter->name = name;
 302}
 303
 304const char *qemu_opt_iter_next(QemuOptsIter *iter)
 305{
 306    QemuOpt *ret = iter->opt;
 307    if (iter->name) {
 308        while (ret && !g_str_equal(iter->name, ret->name)) {
 309            ret = QTAILQ_NEXT(ret, next);
 310        }
 311    }
 312    iter->opt = ret ? QTAILQ_NEXT(ret, next) : NULL;
 313    return ret ? ret->str : NULL;
 314}
 315
 316/* Get a known option (or its default) and remove it from the list
 317 * all in one action. Return a malloced string of the option value.
 318 * Result must be freed by caller with g_free().
 319 */
 320char *qemu_opt_get_del(QemuOpts *opts, const char *name)
 321{
 322    QemuOpt *opt;
 323    char *str;
 324
 325    if (opts == NULL) {
 326        return NULL;
 327    }
 328
 329    opt = qemu_opt_find(opts, name);
 330    if (!opt) {
 331        return g_strdup(find_default_by_name(opts, name));
 332    }
 333    str = opt->str;
 334    opt->str = NULL;
 335    qemu_opt_del_all(opts, name);
 336    return str;
 337}
 338
 339bool qemu_opt_has_help_opt(QemuOpts *opts)
 340{
 341    QemuOpt *opt;
 342
 343    QTAILQ_FOREACH_REVERSE(opt, &opts->head, next) {
 344        if (is_help_option(opt->name)) {
 345            return true;
 346        }
 347    }
 348    return false;
 349}
 350
 351static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
 352                                     bool defval, bool del)
 353{
 354    QemuOpt *opt;
 355    const char *def_val;
 356    bool ret = defval;
 357
 358    if (opts == NULL) {
 359        return ret;
 360    }
 361
 362    opt = qemu_opt_find(opts, name);
 363    if (opt == NULL) {
 364        def_val = find_default_by_name(opts, name);
 365        if (def_val) {
 366            parse_option_bool(name, def_val, &ret, &error_abort);
 367        }
 368        return ret;
 369    }
 370    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
 371    ret = opt->value.boolean;
 372    if (del) {
 373        qemu_opt_del_all(opts, name);
 374    }
 375    return ret;
 376}
 377
 378bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
 379{
 380    return qemu_opt_get_bool_helper(opts, name, defval, false);
 381}
 382
 383bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
 384{
 385    return qemu_opt_get_bool_helper(opts, name, defval, true);
 386}
 387
 388static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
 389                                           uint64_t defval, bool del)
 390{
 391    QemuOpt *opt;
 392    const char *def_val;
 393    uint64_t ret = defval;
 394
 395    if (opts == NULL) {
 396        return ret;
 397    }
 398
 399    opt = qemu_opt_find(opts, name);
 400    if (opt == NULL) {
 401        def_val = find_default_by_name(opts, name);
 402        if (def_val) {
 403            parse_option_number(name, def_val, &ret, &error_abort);
 404        }
 405        return ret;
 406    }
 407    assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
 408    ret = opt->value.uint;
 409    if (del) {
 410        qemu_opt_del_all(opts, name);
 411    }
 412    return ret;
 413}
 414
 415uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
 416{
 417    return qemu_opt_get_number_helper(opts, name, defval, false);
 418}
 419
 420uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
 421                                 uint64_t defval)
 422{
 423    return qemu_opt_get_number_helper(opts, name, defval, true);
 424}
 425
 426static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
 427                                         uint64_t defval, bool del)
 428{
 429    QemuOpt *opt;
 430    const char *def_val;
 431    uint64_t ret = defval;
 432
 433    if (opts == NULL) {
 434        return ret;
 435    }
 436
 437    opt = qemu_opt_find(opts, name);
 438    if (opt == NULL) {
 439        def_val = find_default_by_name(opts, name);
 440        if (def_val) {
 441            parse_option_size(name, def_val, &ret, &error_abort);
 442        }
 443        return ret;
 444    }
 445    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
 446    ret = opt->value.uint;
 447    if (del) {
 448        qemu_opt_del_all(opts, name);
 449    }
 450    return ret;
 451}
 452
 453uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
 454{
 455    return qemu_opt_get_size_helper(opts, name, defval, false);
 456}
 457
 458uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
 459                               uint64_t defval)
 460{
 461    return qemu_opt_get_size_helper(opts, name, defval, true);
 462}
 463
 464static bool qemu_opt_parse(QemuOpt *opt, Error **errp)
 465{
 466    if (opt->desc == NULL)
 467        return true;
 468
 469    switch (opt->desc->type) {
 470    case QEMU_OPT_STRING:
 471        /* nothing */
 472        return true;
 473    case QEMU_OPT_BOOL:
 474        return parse_option_bool(opt->name, opt->str, &opt->value.boolean,
 475                                 errp);
 476    case QEMU_OPT_NUMBER:
 477        return parse_option_number(opt->name, opt->str, &opt->value.uint,
 478                                   errp);
 479    case QEMU_OPT_SIZE:
 480        return parse_option_size(opt->name, opt->str, &opt->value.uint,
 481                                 errp);
 482    default:
 483        abort();
 484    }
 485}
 486
 487static bool opts_accepts_any(const QemuOpts *opts)
 488{
 489    return opts->list->desc[0].name == NULL;
 490}
 491
 492int qemu_opt_unset(QemuOpts *opts, const char *name)
 493{
 494    QemuOpt *opt = qemu_opt_find(opts, name);
 495
 496    assert(opts_accepts_any(opts));
 497
 498    if (opt == NULL) {
 499        return -1;
 500    } else {
 501        qemu_opt_del(opt);
 502        return 0;
 503    }
 504}
 505
 506static QemuOpt *opt_create(QemuOpts *opts, const char *name, char *value,
 507                           bool prepend)
 508{
 509    QemuOpt *opt = g_malloc0(sizeof(*opt));
 510
 511    opt->name = g_strdup(name);
 512    opt->str = value;
 513    opt->opts = opts;
 514    if (prepend) {
 515        QTAILQ_INSERT_HEAD(&opts->head, opt, next);
 516    } else {
 517        QTAILQ_INSERT_TAIL(&opts->head, opt, next);
 518    }
 519
 520    return opt;
 521}
 522
 523static bool opt_validate(QemuOpt *opt, bool *help_wanted,
 524                         Error **errp)
 525{
 526    const QemuOptDesc *desc;
 527
 528    desc = find_desc_by_name(opt->opts->list->desc, opt->name);
 529    if (!desc && !opts_accepts_any(opt->opts)) {
 530        error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
 531        if (help_wanted && is_help_option(opt->name)) {
 532            *help_wanted = true;
 533        }
 534        return false;
 535    }
 536
 537    opt->desc = desc;
 538    if (!qemu_opt_parse(opt, errp)) {
 539        return false;
 540    }
 541
 542    return true;
 543}
 544
 545bool qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
 546                  Error **errp)
 547{
 548    QemuOpt *opt = opt_create(opts, name, g_strdup(value), false);
 549
 550    if (!opt_validate(opt, NULL, errp)) {
 551        qemu_opt_del(opt);
 552        return false;
 553    }
 554    return true;
 555}
 556
 557bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
 558                       Error **errp)
 559{
 560    QemuOpt *opt;
 561    const QemuOptDesc *desc;
 562
 563    desc = find_desc_by_name(opts->list->desc, name);
 564    if (!desc && !opts_accepts_any(opts)) {
 565        error_setg(errp, QERR_INVALID_PARAMETER, name);
 566        return false;
 567    }
 568
 569    opt = g_malloc0(sizeof(*opt));
 570    opt->name = g_strdup(name);
 571    opt->opts = opts;
 572    opt->desc = desc;
 573    opt->value.boolean = !!val;
 574    opt->str = g_strdup(val ? "on" : "off");
 575    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
 576    return true;
 577}
 578
 579bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
 580                         Error **errp)
 581{
 582    QemuOpt *opt;
 583    const QemuOptDesc *desc;
 584
 585    desc = find_desc_by_name(opts->list->desc, name);
 586    if (!desc && !opts_accepts_any(opts)) {
 587        error_setg(errp, QERR_INVALID_PARAMETER, name);
 588        return false;
 589    }
 590
 591    opt = g_malloc0(sizeof(*opt));
 592    opt->name = g_strdup(name);
 593    opt->opts = opts;
 594    opt->desc = desc;
 595    opt->value.uint = val;
 596    opt->str = g_strdup_printf("%" PRId64, val);
 597    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
 598    return true;
 599}
 600
 601/**
 602 * For each member of @opts, call @func(@opaque, name, value, @errp).
 603 * @func() may store an Error through @errp, but must return non-zero then.
 604 * When @func() returns non-zero, break the loop and return that value.
 605 * Return zero when the loop completes.
 606 */
 607int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
 608                     Error **errp)
 609{
 610    QemuOpt *opt;
 611    int rc;
 612
 613    QTAILQ_FOREACH(opt, &opts->head, next) {
 614        rc = func(opaque, opt->name, opt->str, errp);
 615        if (rc) {
 616            return rc;
 617        }
 618        assert(!errp || !*errp);
 619    }
 620    return 0;
 621}
 622
 623QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
 624{
 625    QemuOpts *opts;
 626
 627    QTAILQ_FOREACH(opts, &list->head, next) {
 628        if (!opts->id && !id) {
 629            return opts;
 630        }
 631        if (opts->id && id && !strcmp(opts->id, id)) {
 632            return opts;
 633        }
 634    }
 635    return NULL;
 636}
 637
 638QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
 639                           int fail_if_exists, Error **errp)
 640{
 641    QemuOpts *opts = NULL;
 642
 643    if (id) {
 644        if (!id_wellformed(id)) {
 645            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
 646                       "an identifier");
 647            error_append_hint(errp, "Identifiers consist of letters, digits, "
 648                              "'-', '.', '_', starting with a letter.\n");
 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
 675void 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
 684void qemu_opts_loc_restore(QemuOpts *opts)
 685{
 686    loc_restore(&opts->loc);
 687}
 688
 689bool qemu_opts_set(QemuOptsList *list, const char *id,
 690                   const char *name, const char *value, Error **errp)
 691{
 692    QemuOpts *opts;
 693
 694    opts = qemu_opts_create(list, id, 1, errp);
 695    if (!opts) {
 696        return false;
 697    }
 698    return qemu_opt_set(opts, name, value, errp);
 699}
 700
 701const char *qemu_opts_id(QemuOpts *opts)
 702{
 703    return opts->id;
 704}
 705
 706/* The id string will be g_free()d by qemu_opts_del */
 707void qemu_opts_set_id(QemuOpts *opts, char *id)
 708{
 709    opts->id = id;
 710}
 711
 712void qemu_opts_del(QemuOpts *opts)
 713{
 714    QemuOpt *opt;
 715
 716    if (opts == NULL) {
 717        return;
 718    }
 719
 720    for (;;) {
 721        opt = QTAILQ_FIRST(&opts->head);
 722        if (opt == NULL)
 723            break;
 724        qemu_opt_del(opt);
 725    }
 726    QTAILQ_REMOVE(&opts->list->head, opts, next);
 727    g_free(opts->id);
 728    g_free(opts);
 729}
 730
 731/* print value, escaping any commas in value */
 732static void escaped_print(const char *value)
 733{
 734    const char *ptr;
 735
 736    for (ptr = value; *ptr; ++ptr) {
 737        if (*ptr == ',') {
 738            putchar(',');
 739        }
 740        putchar(*ptr);
 741    }
 742}
 743
 744void qemu_opts_print(QemuOpts *opts, const char *separator)
 745{
 746    QemuOpt *opt;
 747    QemuOptDesc *desc = opts->list->desc;
 748    const char *sep = "";
 749
 750    if (opts->id) {
 751        printf("id=%s", opts->id); /* passed id_wellformed -> no commas */
 752        sep = separator;
 753    }
 754
 755    if (desc[0].name == NULL) {
 756        QTAILQ_FOREACH(opt, &opts->head, next) {
 757            printf("%s%s=", sep, opt->name);
 758            escaped_print(opt->str);
 759            sep = separator;
 760        }
 761        return;
 762    }
 763    for (; desc && desc->name; desc++) {
 764        const char *value;
 765        opt = qemu_opt_find(opts, desc->name);
 766
 767        value = opt ? opt->str : desc->def_value_str;
 768        if (!value) {
 769            continue;
 770        }
 771        if (desc->type == QEMU_OPT_STRING) {
 772            printf("%s%s=", sep, desc->name);
 773            escaped_print(value);
 774        } else if ((desc->type == QEMU_OPT_SIZE ||
 775                    desc->type == QEMU_OPT_NUMBER) && opt) {
 776            printf("%s%s=%" PRId64, sep, desc->name, opt->value.uint);
 777        } else {
 778            printf("%s%s=%s", sep, desc->name, value);
 779        }
 780        sep = separator;
 781    }
 782}
 783
 784static const char *get_opt_name_value(const char *params,
 785                                      const char *firstname,
 786                                      char **name, char **value)
 787{
 788    const char *p, *pe, *pc;
 789
 790    pe = strchr(params, '=');
 791    pc = strchr(params, ',');
 792
 793    if (!pe || (pc && pc < pe)) {
 794        /* found "foo,more" */
 795        if (firstname) {
 796            /* implicitly named first option */
 797            *name = g_strdup(firstname);
 798            p = get_opt_value(params, value);
 799        } else {
 800            /* option without value, must be a flag */
 801            p = get_opt_name(params, name, ',');
 802            if (strncmp(*name, "no", 2) == 0) {
 803                memmove(*name, *name + 2, strlen(*name + 2) + 1);
 804                *value = g_strdup("off");
 805            } else {
 806                *value = g_strdup("on");
 807            }
 808        }
 809    } else {
 810        /* found "foo=bar,more" */
 811        p = get_opt_name(params, name, '=');
 812        assert(*p == '=');
 813        p++;
 814        p = get_opt_value(p, value);
 815    }
 816
 817    assert(!*p || *p == ',');
 818    if (*p == ',') {
 819        p++;
 820    }
 821    return p;
 822}
 823
 824static bool opts_do_parse(QemuOpts *opts, const char *params,
 825                          const char *firstname, bool prepend,
 826                          bool *help_wanted, Error **errp)
 827{
 828    char *option, *value;
 829    const char *p;
 830    QemuOpt *opt;
 831
 832    for (p = params; *p;) {
 833        p = get_opt_name_value(p, firstname, &option, &value);
 834        firstname = NULL;
 835
 836        if (!strcmp(option, "id")) {
 837            g_free(option);
 838            g_free(value);
 839            continue;
 840        }
 841
 842        opt = opt_create(opts, option, value, prepend);
 843        g_free(option);
 844        if (!opt_validate(opt, help_wanted, errp)) {
 845            qemu_opt_del(opt);
 846            return false;
 847        }
 848    }
 849
 850    return true;
 851}
 852
 853static char *opts_parse_id(const char *params)
 854{
 855    const char *p;
 856    char *name, *value;
 857
 858    for (p = params; *p;) {
 859        p = get_opt_name_value(p, NULL, &name, &value);
 860        if (!strcmp(name, "id")) {
 861            g_free(name);
 862            return value;
 863        }
 864        g_free(name);
 865        g_free(value);
 866    }
 867
 868    return NULL;
 869}
 870
 871bool has_help_option(const char *params)
 872{
 873    const char *p;
 874    char *name, *value;
 875    bool ret;
 876
 877    for (p = params; *p;) {
 878        p = get_opt_name_value(p, NULL, &name, &value);
 879        ret = is_help_option(name);
 880        g_free(name);
 881        g_free(value);
 882        if (ret) {
 883            return true;
 884        }
 885    }
 886
 887    return false;
 888}
 889
 890/**
 891 * Store options parsed from @params into @opts.
 892 * If @firstname is non-null, the first key=value in @params may omit
 893 * key=, and is treated as if key was @firstname.
 894 * On error, store an error object through @errp if non-null.
 895 */
 896bool qemu_opts_do_parse(QemuOpts *opts, const char *params,
 897                       const char *firstname, Error **errp)
 898{
 899    return opts_do_parse(opts, params, firstname, false, NULL, errp);
 900}
 901
 902static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
 903                            bool permit_abbrev, bool defaults,
 904                            bool *help_wanted, Error **errp)
 905{
 906    const char *firstname;
 907    char *id = opts_parse_id(params);
 908    QemuOpts *opts;
 909
 910    assert(!permit_abbrev || list->implied_opt_name);
 911    firstname = permit_abbrev ? list->implied_opt_name : NULL;
 912
 913    /*
 914     * This code doesn't work for defaults && !list->merge_lists: when
 915     * params has no id=, and list has an element with !opts->id, it
 916     * appends a new element instead of returning the existing opts.
 917     * However, we got no use for this case.  Guard against possible
 918     * (if unlikely) future misuse:
 919     */
 920    assert(!defaults || list->merge_lists);
 921    opts = qemu_opts_create(list, id, !defaults, errp);
 922    g_free(id);
 923    if (opts == NULL) {
 924        return NULL;
 925    }
 926
 927    if (!opts_do_parse(opts, params, firstname, defaults, help_wanted,
 928                       errp)) {
 929        qemu_opts_del(opts);
 930        return NULL;
 931    }
 932
 933    return opts;
 934}
 935
 936/**
 937 * Create a QemuOpts in @list and with options parsed from @params.
 938 * If @permit_abbrev, the first key=value in @params may omit key=,
 939 * and is treated as if key was @list->implied_opt_name.
 940 * On error, store an error object through @errp if non-null.
 941 * Return the new QemuOpts on success, null pointer on error.
 942 */
 943QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
 944                          bool permit_abbrev, Error **errp)
 945{
 946    return opts_parse(list, params, permit_abbrev, false, NULL, errp);
 947}
 948
 949/**
 950 * Create a QemuOpts in @list and with options parsed from @params.
 951 * If @permit_abbrev, the first key=value in @params may omit key=,
 952 * and is treated as if key was @list->implied_opt_name.
 953 * Report errors with error_report_err().  This is inappropriate in
 954 * QMP context.  Do not use this function there!
 955 * Return the new QemuOpts on success, null pointer on error.
 956 */
 957QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
 958                                  bool permit_abbrev)
 959{
 960    Error *err = NULL;
 961    QemuOpts *opts;
 962    bool help_wanted = false;
 963
 964    opts = opts_parse(list, params, permit_abbrev, false, &help_wanted, &err);
 965    if (err) {
 966        if (help_wanted) {
 967            qemu_opts_print_help(list, true);
 968            error_free(err);
 969        } else {
 970            error_report_err(err);
 971        }
 972    }
 973    return opts;
 974}
 975
 976void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
 977                            int permit_abbrev)
 978{
 979    QemuOpts *opts;
 980
 981    opts = opts_parse(list, params, permit_abbrev, true, NULL, NULL);
 982    assert(opts);
 983}
 984
 985static bool qemu_opts_from_qdict_entry(QemuOpts *opts,
 986                                       const QDictEntry *entry,
 987                                       Error **errp)
 988{
 989    const char *key = qdict_entry_key(entry);
 990    QObject *obj = qdict_entry_value(entry);
 991    char buf[32];
 992    g_autofree char *tmp = NULL;
 993    const char *value;
 994
 995    if (!strcmp(key, "id")) {
 996        return true;
 997    }
 998
 999    switch (qobject_type(obj)) {
1000    case QTYPE_QSTRING:
1001        value = qstring_get_str(qobject_to(QString, obj));
1002        break;
1003    case QTYPE_QNUM:
1004        tmp = qnum_to_string(qobject_to(QNum, obj));
1005        value = tmp;
1006        break;
1007    case QTYPE_QBOOL:
1008        pstrcpy(buf, sizeof(buf),
1009                qbool_get_bool(qobject_to(QBool, obj)) ? "on" : "off");
1010        value = buf;
1011        break;
1012    default:
1013        return true;
1014    }
1015
1016    return qemu_opt_set(opts, key, value, errp);
1017}
1018
1019/*
1020 * Create QemuOpts from a QDict.
1021 * Use value of key "id" as ID if it exists and is a QString.  Only
1022 * QStrings, QNums and QBools are copied.  Entries with other types
1023 * are silently ignored.
1024 */
1025QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
1026                               Error **errp)
1027{
1028    QemuOpts *opts;
1029    const QDictEntry *entry;
1030
1031    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, errp);
1032    if (!opts) {
1033        return NULL;
1034    }
1035
1036    assert(opts != NULL);
1037
1038    for (entry = qdict_first(qdict);
1039         entry;
1040         entry = qdict_next(qdict, entry)) {
1041        if (!qemu_opts_from_qdict_entry(opts, entry, errp)) {
1042            qemu_opts_del(opts);
1043            return NULL;
1044        }
1045    }
1046
1047    return opts;
1048}
1049
1050/*
1051 * Adds all QDict entries to the QemuOpts that can be added and removes them
1052 * from the QDict. When this function returns, the QDict contains only those
1053 * entries that couldn't be added to the QemuOpts.
1054 */
1055bool qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
1056{
1057    const QDictEntry *entry, *next;
1058
1059    entry = qdict_first(qdict);
1060
1061    while (entry != NULL) {
1062        next = qdict_next(qdict, entry);
1063
1064        if (find_desc_by_name(opts->list->desc, entry->key)) {
1065            if (!qemu_opts_from_qdict_entry(opts, entry, errp)) {
1066                return false;
1067            }
1068            qdict_del(qdict, entry->key);
1069        }
1070
1071        entry = next;
1072    }
1073
1074    return true;
1075}
1076
1077/*
1078 * Convert from QemuOpts to QDict. The QDict values are of type QString.
1079 *
1080 * If @list is given, only add those options to the QDict that are contained in
1081 * the list. If @del is true, any options added to the QDict are removed from
1082 * the QemuOpts, otherwise they remain there.
1083 *
1084 * If two options in @opts have the same name, they are processed in order
1085 * so that the last one wins (consistent with the reverse iteration in
1086 * qemu_opt_find()), but all of them are deleted if @del is true.
1087 *
1088 * TODO We'll want to use types appropriate for opt->desc->type, but
1089 * this is enough for now.
1090 */
1091QDict *qemu_opts_to_qdict_filtered(QemuOpts *opts, QDict *qdict,
1092                                   QemuOptsList *list, bool del)
1093{
1094    QemuOpt *opt, *next;
1095
1096    if (!qdict) {
1097        qdict = qdict_new();
1098    }
1099    if (opts->id) {
1100        qdict_put_str(qdict, "id", opts->id);
1101    }
1102    QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next) {
1103        if (list) {
1104            QemuOptDesc *desc;
1105            bool found = false;
1106            for (desc = list->desc; desc->name; desc++) {
1107                if (!strcmp(desc->name, opt->name)) {
1108                    found = true;
1109                    break;
1110                }
1111            }
1112            if (!found) {
1113                continue;
1114            }
1115        }
1116        qdict_put_str(qdict, opt->name, opt->str);
1117        if (del) {
1118            qemu_opt_del(opt);
1119        }
1120    }
1121    return qdict;
1122}
1123
1124/* Copy all options in a QemuOpts to the given QDict. See
1125 * qemu_opts_to_qdict_filtered() for details. */
1126QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
1127{
1128    return qemu_opts_to_qdict_filtered(opts, qdict, NULL, false);
1129}
1130
1131/* Validate parsed opts against descriptions where no
1132 * descriptions were provided in the QemuOptsList.
1133 */
1134bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
1135{
1136    QemuOpt *opt;
1137
1138    assert(opts_accepts_any(opts));
1139
1140    QTAILQ_FOREACH(opt, &opts->head, next) {
1141        opt->desc = find_desc_by_name(desc, opt->name);
1142        if (!opt->desc) {
1143            error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
1144            return false;
1145        }
1146
1147        if (!qemu_opt_parse(opt, errp)) {
1148            return false;
1149        }
1150    }
1151
1152    return true;
1153}
1154
1155/**
1156 * For each member of @list, call @func(@opaque, member, @errp).
1157 * Call it with the current location temporarily set to the member's.
1158 * @func() may store an Error through @errp, but must return non-zero then.
1159 * When @func() returns non-zero, break the loop and return that value.
1160 * Return zero when the loop completes.
1161 */
1162int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
1163                      void *opaque, Error **errp)
1164{
1165    Location loc;
1166    QemuOpts *opts;
1167    int rc = 0;
1168
1169    loc_push_none(&loc);
1170    QTAILQ_FOREACH(opts, &list->head, next) {
1171        loc_restore(&opts->loc);
1172        rc = func(opaque, opts, errp);
1173        if (rc) {
1174            break;
1175        }
1176        assert(!errp || !*errp);
1177    }
1178    loc_pop(&loc);
1179    return rc;
1180}
1181
1182static size_t count_opts_list(QemuOptsList *list)
1183{
1184    QemuOptDesc *desc = NULL;
1185    size_t num_opts = 0;
1186
1187    if (!list) {
1188        return 0;
1189    }
1190
1191    desc = list->desc;
1192    while (desc && desc->name) {
1193        num_opts++;
1194        desc++;
1195    }
1196
1197    return num_opts;
1198}
1199
1200void qemu_opts_free(QemuOptsList *list)
1201{
1202    g_free(list);
1203}
1204
1205/* Realloc dst option list and append options from an option list (list)
1206 * to it. dst could be NULL or a malloced list.
1207 * The lifetime of dst must be shorter than the input list because the
1208 * QemuOptDesc->name, ->help, and ->def_value_str strings are shared.
1209 */
1210QemuOptsList *qemu_opts_append(QemuOptsList *dst,
1211                               QemuOptsList *list)
1212{
1213    size_t num_opts, num_dst_opts;
1214    QemuOptDesc *desc;
1215    bool need_init = false;
1216    bool need_head_update;
1217
1218    if (!list) {
1219        return dst;
1220    }
1221
1222    /* If dst is NULL, after realloc, some area of dst should be initialized
1223     * before adding options to it.
1224     */
1225    if (!dst) {
1226        need_init = true;
1227        need_head_update = true;
1228    } else {
1229        /* Moreover, even if dst is not NULL, the realloc may move it to a
1230         * different address in which case we may get a stale tail pointer
1231         * in dst->head. */
1232        need_head_update = QTAILQ_EMPTY(&dst->head);
1233    }
1234
1235    num_opts = count_opts_list(dst);
1236    num_dst_opts = num_opts;
1237    num_opts += count_opts_list(list);
1238    dst = g_realloc(dst, sizeof(QemuOptsList) +
1239                    (num_opts + 1) * sizeof(QemuOptDesc));
1240    if (need_init) {
1241        dst->name = NULL;
1242        dst->implied_opt_name = NULL;
1243        dst->merge_lists = false;
1244    }
1245    if (need_head_update) {
1246        QTAILQ_INIT(&dst->head);
1247    }
1248    dst->desc[num_dst_opts].name = NULL;
1249
1250    /* append list->desc to dst->desc */
1251    if (list) {
1252        desc = list->desc;
1253        while (desc && desc->name) {
1254            if (find_desc_by_name(dst->desc, desc->name) == NULL) {
1255                dst->desc[num_dst_opts++] = *desc;
1256                dst->desc[num_dst_opts].name = NULL;
1257            }
1258            desc++;
1259        }
1260    }
1261
1262    return dst;
1263}
1264