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