qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qemu-option.c (33144B)


      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  */
     50 static 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  */
     64 const 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 
     91 static 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 
    111 static 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 
    125 static 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 
    132 bool 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 
    156 static 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  */
    179 void 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 
    224 QemuOpt *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 
    236 static 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  */
    247 static 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 
    258 const 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 
    274 void 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 
    281 const 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  */
    297 char *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 
    316 bool 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 
    328 static 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 
    355 bool 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 
    360 bool 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 
    365 static 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 
    392 uint64_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 
    397 uint64_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 
    403 static 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 
    430 uint64_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 
    435 uint64_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 
    441 static 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 
    463 static bool opts_accepts_any(const QemuOptsList *list)
    464 {
    465     return list->desc[0].name == NULL;
    466 }
    467 
    468 int 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 
    482 static 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 
    494 static 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 
    513 bool 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 
    525 bool 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 
    548 bool 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  */
    577 int 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 
    593 QemuOpts *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 
    608 QemuOpts *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 
    646 void 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 
    655 void qemu_opts_loc_restore(QemuOpts *opts)
    656 {
    657     loc_restore(&opts->loc);
    658 }
    659 
    660 const 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 */
    666 void qemu_opts_set_id(QemuOpts *opts, char *id)
    667 {
    668     opts->id = id;
    669 }
    670 
    671 void 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 */
    691 static 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 
    703 void 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 
    743 static 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 
    799 static 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 
    833 static 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 
    851 bool 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  */
    875 bool 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 
    881 static 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  */
    914 QemuOpts *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  */
    928 QemuOpts *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 
    949 static 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  */
    989 QemuOpts *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  */
   1017 bool 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  */
   1054 QDict *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. */
   1089 QDict *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  */
   1097 bool 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  */
   1125 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
   1126                       void *opaque, Error **errp)
   1127 {
   1128     Location loc;
   1129     QemuOpts *opts, *next;
   1130     int rc = 0;
   1131 
   1132     loc_push_none(&loc);
   1133     QTAILQ_FOREACH_SAFE(opts, &list->head, next, 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 
   1145 static 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 
   1163 void 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  */
   1173 QemuOptsList *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 }