cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

qemu-option.c (33126B)


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