qemu-option.c 30.2 KB
Newer Older
K
Kevin Wolf 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Commandline option parsing functions
 *
 * Copyright (c) 2003-2008 Fabrice Bellard
 * Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

P
Peter Maydell 已提交
26
#include "qemu/osdep.h"
K
Kevin Wolf 已提交
27

28
#include "qapi/error.h"
K
Kevin Wolf 已提交
29
#include "qemu-common.h"
30
#include "qemu/error-report.h"
31 32
#include "qapi/qmp/types.h"
#include "qapi/qmp/qerror.h"
33
#include "qemu/option_int.h"
34 35 36
#include "qemu/cutils.h"
#include "qemu/id.h"
#include "qemu/help_option.h"
K
Kevin Wolf 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

/*
 * Extracts the name of an option from the parameter string (p points at the
 * first byte of the option name)
 *
 * The option name is delimited by delim (usually , or =) or the string end
 * and is copied into buf. If the option name is longer than buf_size, it is
 * truncated. buf is always zero terminated.
 *
 * The return value is the position of the delimiter/zero byte after the option
 * name in p.
 */
const char *get_opt_name(char *buf, int buf_size, const char *p, char delim)
{
    char *q;

    q = buf;
    while (*p != '\0' && *p != delim) {
        if (q && (q - buf) < buf_size - 1)
            *q++ = *p;
        p++;
    }
    if (q)
        *q = '\0';

    return p;
}

/*
 * Extracts the value of an option from the parameter string p (p points at the
 * first byte of the option value)
 *
 * This function is comparable to get_opt_name with the difference that the
 * delimiter is fixed to be comma which starts a new option. To specify an
 * option value that contains commas, double each comma.
 */
const char *get_opt_value(char *buf, int buf_size, const char *p)
{
    char *q;

    q = buf;
    while (*p != '\0') {
        if (*p == ',') {
            if (*(p + 1) != ',')
                break;
            p++;
        }
        if (q && (q - buf) < buf_size - 1)
            *q++ = *p;
        p++;
    }
    if (q)
        *q = '\0';

    return p;
}

94 95
static void parse_option_bool(const char *name, const char *value, bool *ret,
                              Error **errp)
96
{
97
    if (!strcmp(value, "on")) {
98
        *ret = 1;
99 100 101 102 103
    } else if (!strcmp(value, "off")) {
        *ret = 0;
    } else {
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                   name, "'on' or 'off'");
104 105 106
    }
}

107 108
static void parse_option_number(const char *name, const char *value,
                                uint64_t *ret, Error **errp)
109 110
{
    uint64_t number;
111
    int err;
112

113 114 115 116 117 118 119
    err = qemu_strtou64(value, NULL, 0, &number);
    if (err == -ERANGE) {
        error_setg(errp, "Value '%s' is too large for parameter '%s'",
                   value, name);
        return;
    }
    if (err) {
120
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
121
        return;
122
    }
123
    *ret = number;
124 125
}

126 127 128 129 130 131 132 133 134 135 136 137 138 139
static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
                                            const char *name)
{
    int i;

    for (i = 0; desc[i].name != NULL; i++) {
        if (strcmp(desc[i].name, name) == 0) {
            return &desc[i];
        }
    }

    return NULL;
}

140 141
void parse_option_size(const char *name, const char *value,
                       uint64_t *ret, Error **errp)
142
{
143 144
    uint64_t size;
    int err;
145

146 147
    err = qemu_strtosz(value, NULL, &size);
    if (err == -ERANGE) {
148
        error_setg(errp, "Value '%s' is out of range for parameter '%s'",
149
                   value, name);
150 151
        return;
    }
152 153 154 155 156 157
    if (err) {
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
                   "a non-negative number below 2^64");
        error_append_hint(errp, "Optional suffix k, M, G, T, P or E means"
                          " kilo-, mega-, giga-, tera-, peta-\n"
                          "and exabytes, respectively.\n");
158
        return;
159
    }
160
    *ret = size;
161 162
}

163 164 165
bool has_help_option(const char *param)
{
    size_t buflen = strlen(param) + 1;
166
    char *buf = g_malloc(buflen);
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
    const char *p = param;
    bool result = false;

    while (*p) {
        p = get_opt_value(buf, buflen, p);
        if (*p) {
            p++;
        }

        if (is_help_option(buf)) {
            result = true;
            goto out;
        }
    }

out:
183
    g_free(buf);
184 185 186 187 188 189
    return result;
}

bool is_valid_option_list(const char *param)
{
    size_t buflen = strlen(param) + 1;
190
    char *buf = g_malloc(buflen);
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
    const char *p = param;
    bool result = true;

    while (*p) {
        p = get_opt_value(buf, buflen, p);
        if (*p && !*++p) {
            result = false;
            goto out;
        }

        if (!*buf || *buf == ',') {
            result = false;
            goto out;
        }
    }

out:
208
    g_free(buf);
209 210 211
    return result;
}

212 213 214 215 216 217 218 219 220 221 222 223 224
void qemu_opts_print_help(QemuOptsList *list)
{
    QemuOptDesc *desc;

    assert(list);
    desc = list->desc;
    printf("Supported options:\n");
    while (desc && desc->name) {
        printf("%-16s %s\n", desc->name,
               desc->help ? desc->help : "No description available");
        desc++;
    }
}
225 226
/* ------------------------------------------------------------------ */

C
Chunyan Liu 已提交
227
QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name)
228 229 230
{
    QemuOpt *opt;

M
Mark McLoughlin 已提交
231
    QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
232 233 234 235 236 237 238
        if (strcmp(opt->name, name) != 0)
            continue;
        return opt;
    }
    return NULL;
}

239 240 241 242 243 244 245 246
static void qemu_opt_del(QemuOpt *opt)
{
    QTAILQ_REMOVE(&opt->opts->head, opt, next);
    g_free(opt->name);
    g_free(opt->str);
    g_free(opt);
}

247 248 249 250 251 252 253 254 255 256 257 258 259 260
/* qemu_opt_set allows many settings for the same option.
 * This function deletes all settings for an option.
 */
static void qemu_opt_del_all(QemuOpts *opts, const char *name)
{
    QemuOpt *opt, *next_opt;

    QTAILQ_FOREACH_SAFE(opt, &opts->head, next, next_opt) {
        if (!strcmp(opt->name, name)) {
            qemu_opt_del(opt);
        }
    }
}

261 262
const char *qemu_opt_get(QemuOpts *opts, const char *name)
{
263 264 265 266 267
    QemuOpt *opt;

    if (opts == NULL) {
        return NULL;
    }
268

269
    opt = qemu_opt_find(opts, name);
270 271 272 273 274 275
    if (!opt) {
        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
        if (desc && desc->def_value_str) {
            return desc->def_value_str;
        }
    }
276 277 278
    return opt ? opt->str : NULL;
}

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
void qemu_opt_iter_init(QemuOptsIter *iter, QemuOpts *opts, const char *name)
{
    iter->opts = opts;
    iter->opt = QTAILQ_FIRST(&opts->head);
    iter->name = name;
}

const char *qemu_opt_iter_next(QemuOptsIter *iter)
{
    QemuOpt *ret = iter->opt;
    if (iter->name) {
        while (ret && !g_str_equal(iter->name, ret->name)) {
            ret = QTAILQ_NEXT(ret, next);
        }
    }
    iter->opt = ret ? QTAILQ_NEXT(ret, next) : NULL;
    return ret ? ret->str : NULL;
}

298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
/* Get a known option (or its default) and remove it from the list
 * all in one action. Return a malloced string of the option value.
 * Result must be freed by caller with g_free().
 */
char *qemu_opt_get_del(QemuOpts *opts, const char *name)
{
    QemuOpt *opt;
    const QemuOptDesc *desc;
    char *str = NULL;

    if (opts == NULL) {
        return NULL;
    }

    opt = qemu_opt_find(opts, name);
    if (!opt) {
        desc = find_desc_by_name(opts->list->desc, name);
        if (desc && desc->def_value_str) {
            str = g_strdup(desc->def_value_str);
        }
        return str;
    }
    str = opt->str;
    opt->str = NULL;
    qemu_opt_del_all(opts, name);
    return str;
}

326 327 328 329 330 331 332 333 334 335 336 337
bool qemu_opt_has_help_opt(QemuOpts *opts)
{
    QemuOpt *opt;

    QTAILQ_FOREACH_REVERSE(opt, &opts->head, QemuOptHead, next) {
        if (is_help_option(opt->name)) {
            return true;
        }
    }
    return false;
}

338 339
static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
                                     bool defval, bool del)
340
{
341
    QemuOpt *opt;
342
    bool ret = defval;
343

344 345 346 347 348
    if (opts == NULL) {
        return ret;
    }

    opt = qemu_opt_find(opts, name);
349 350 351
    if (opt == NULL) {
        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
        if (desc && desc->def_value_str) {
352
            parse_option_bool(name, desc->def_value_str, &ret, &error_abort);
353
        }
354
        return ret;
355
    }
356
    assert(opt->desc && opt->desc->type == QEMU_OPT_BOOL);
357 358 359 360 361
    ret = opt->value.boolean;
    if (del) {
        qemu_opt_del_all(opts, name);
    }
    return ret;
362 363
}

364 365 366 367 368 369 370 371 372 373 374 375
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
{
    return qemu_opt_get_bool_helper(opts, name, defval, false);
}

bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval)
{
    return qemu_opt_get_bool_helper(opts, name, defval, true);
}

static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
                                           uint64_t defval, bool del)
376
{
377
    QemuOpt *opt;
378
    uint64_t ret = defval;
379

380 381 382 383 384
    if (opts == NULL) {
        return ret;
    }

    opt = qemu_opt_find(opts, name);
385 386 387
    if (opt == NULL) {
        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
        if (desc && desc->def_value_str) {
388
            parse_option_number(name, desc->def_value_str, &ret, &error_abort);
389
        }
390
        return ret;
391
    }
392
    assert(opt->desc && opt->desc->type == QEMU_OPT_NUMBER);
393 394 395 396 397
    ret = opt->value.uint;
    if (del) {
        qemu_opt_del_all(opts, name);
    }
    return ret;
398 399
}

400 401 402 403 404 405 406 407 408 409 410 411 412
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval)
{
    return qemu_opt_get_number_helper(opts, name, defval, false);
}

uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
                                 uint64_t defval)
{
    return qemu_opt_get_number_helper(opts, name, defval, true);
}

static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
                                         uint64_t defval, bool del)
413
{
414
    QemuOpt *opt;
415
    uint64_t ret = defval;
416

417 418 419 420 421
    if (opts == NULL) {
        return ret;
    }

    opt = qemu_opt_find(opts, name);
422 423 424
    if (opt == NULL) {
        const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
        if (desc && desc->def_value_str) {
425
            parse_option_size(name, desc->def_value_str, &ret, &error_abort);
426
        }
427
        return ret;
428
    }
429
    assert(opt->desc && opt->desc->type == QEMU_OPT_SIZE);
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
    ret = opt->value.uint;
    if (del) {
        qemu_opt_del_all(opts, name);
    }
    return ret;
}

uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
{
    return qemu_opt_get_size_helper(opts, name, defval, false);
}

uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
                               uint64_t defval)
{
    return qemu_opt_get_size_helper(opts, name, defval, true);
446 447
}

448
static void qemu_opt_parse(QemuOpt *opt, Error **errp)
449 450
{
    if (opt->desc == NULL)
451
        return;
452

453 454 455
    switch (opt->desc->type) {
    case QEMU_OPT_STRING:
        /* nothing */
456
        return;
457
    case QEMU_OPT_BOOL:
458
        parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
459
        break;
460
    case QEMU_OPT_NUMBER:
461
        parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
462
        break;
463
    case QEMU_OPT_SIZE:
464
        parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
465
        break;
466 467 468 469 470
    default:
        abort();
    }
}

471 472 473 474 475
static bool opts_accepts_any(const QemuOpts *opts)
{
    return opts->list->desc[0].name == NULL;
}

K
Kevin Wolf 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489
int qemu_opt_unset(QemuOpts *opts, const char *name)
{
    QemuOpt *opt = qemu_opt_find(opts, name);

    assert(opts_accepts_any(opts));

    if (opt == NULL) {
        return -1;
    } else {
        qemu_opt_del(opt);
        return 0;
    }
}

490 491 492 493 494 495 496 497 498
static void opt_set(QemuOpts *opts, const char *name, const char *value,
                    bool prepend, Error **errp)
{
    QemuOpt *opt;
    const QemuOptDesc *desc;
    Error *local_err = NULL;

    desc = find_desc_by_name(opts->list->desc, name);
    if (!desc && !opts_accepts_any(opts)) {
499
        error_setg(errp, QERR_INVALID_PARAMETER, name);
500
        return;
501
    }
M
Mark McLoughlin 已提交
502

503 504
    opt = g_malloc0(sizeof(*opt));
    opt->name = g_strdup(name);
M
Mark McLoughlin 已提交
505
    opt->opts = opts;
506 507 508 509 510
    if (prepend) {
        QTAILQ_INSERT_HEAD(&opts->head, opt, next);
    } else {
        QTAILQ_INSERT_TAIL(&opts->head, opt, next);
    }
511
    opt->desc = desc;
512
    opt->str = g_strdup(value);
513
    assert(opt->str);
514
    qemu_opt_parse(opt, &local_err);
515
    if (local_err) {
516
        error_propagate(errp, local_err);
517 518 519 520
        qemu_opt_del(opt);
    }
}

521 522
void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
                  Error **errp)
523 524 525 526
{
    opt_set(opts, name, value, false, errp);
}

527 528
void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
                       Error **errp)
529 530 531 532
{
    QemuOpt *opt;
    const QemuOptDesc *desc = opts->list->desc;

533 534 535
    opt = g_malloc0(sizeof(*opt));
    opt->desc = find_desc_by_name(desc, name);
    if (!opt->desc && !opts_accepts_any(opts)) {
536
        error_setg(errp, QERR_INVALID_PARAMETER, name);
537
        g_free(opt);
538
        return;
539 540 541 542 543
    }

    opt->name = g_strdup(name);
    opt->opts = opts;
    opt->value.boolean = !!val;
544 545
    opt->str = g_strdup(val ? "on" : "off");
    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
546 547
}

548 549
void qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
                         Error **errp)
550 551 552 553 554 555 556
{
    QemuOpt *opt;
    const QemuOptDesc *desc = opts->list->desc;

    opt = g_malloc0(sizeof(*opt));
    opt->desc = find_desc_by_name(desc, name);
    if (!opt->desc && !opts_accepts_any(opts)) {
557
        error_setg(errp, QERR_INVALID_PARAMETER, name);
558
        g_free(opt);
559
        return;
560 561 562 563 564 565 566 567 568
    }

    opt->name = g_strdup(name);
    opt->opts = opts;
    opt->value.uint = val;
    opt->str = g_strdup_printf("%" PRId64, val);
    QTAILQ_INSERT_TAIL(&opts->head, opt, next);
}

569
/**
570 571
 * For each member of @opts, call @func(@opaque, name, value, @errp).
 * @func() may store an Error through @errp, but must return non-zero then.
572 573 574
 * When @func() returns non-zero, break the loop and return that value.
 * Return zero when the loop completes.
 */
575 576
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                     Error **errp)
G
Gerd Hoffmann 已提交
577 578
{
    QemuOpt *opt;
579
    int rc;
G
Gerd Hoffmann 已提交
580

B
Blue Swirl 已提交
581
    QTAILQ_FOREACH(opt, &opts->head, next) {
582
        rc = func(opaque, opt->name, opt->str, errp);
583 584 585
        if (rc) {
            return rc;
        }
586
        assert(!errp || !*errp);
G
Gerd Hoffmann 已提交
587
    }
588
    return 0;
G
Gerd Hoffmann 已提交
589 590
}

591 592 593 594
QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
{
    QemuOpts *opts;

B
Blue Swirl 已提交
595
    QTAILQ_FOREACH(opts, &list->head, next) {
596 597
        if (!opts->id && !id) {
            return opts;
598
        }
599 600
        if (opts->id && id && !strcmp(opts->id, id)) {
            return opts;
601 602 603 604 605
        }
    }
    return NULL;
}

606 607
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
                           int fail_if_exists, Error **errp)
608 609 610 611
{
    QemuOpts *opts = NULL;

    if (id) {
612
        if (!id_wellformed(id)) {
613 614
            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id",
                       "an identifier");
615
            error_append_hint(errp, "Identifiers consist of letters, digits, "
616
                              "'-', '.', '_', starting with a letter.\n");
617 618
            return NULL;
        }
619 620
        opts = qemu_opts_find(list, id);
        if (opts != NULL) {
621
            if (fail_if_exists && !list->merge_lists) {
622
                error_setg(errp, "Duplicate ID '%s' for %s", id, list->name);
623 624 625 626 627
                return NULL;
            } else {
                return opts;
            }
        }
628 629 630 631 632
    } else if (list->merge_lists) {
        opts = qemu_opts_find(list, NULL);
        if (opts) {
            return opts;
        }
633
    }
634
    opts = g_malloc0(sizeof(*opts));
635
    opts->id = g_strdup(id);
636
    opts->list = list;
637
    loc_save(&opts->loc);
B
Blue Swirl 已提交
638 639
    QTAILQ_INIT(&opts->head);
    QTAILQ_INSERT_TAIL(&list->head, opts, next);
640 641 642
    return opts;
}

643 644 645 646 647 648 649 650 651
void qemu_opts_reset(QemuOptsList *list)
{
    QemuOpts *opts, *next_opts;

    QTAILQ_FOREACH_SAFE(opts, &list->head, next, next_opts) {
        qemu_opts_del(opts);
    }
}

652 653 654 655 656
void qemu_opts_loc_restore(QemuOpts *opts)
{
    loc_restore(&opts->loc);
}

657 658
void qemu_opts_set(QemuOptsList *list, const char *id,
                   const char *name, const char *value, Error **errp)
659 660
{
    QemuOpts *opts;
661
    Error *local_err = NULL;
662

663
    opts = qemu_opts_create(list, id, 1, &local_err);
664
    if (local_err) {
665 666
        error_propagate(errp, local_err);
        return;
667
    }
668
    qemu_opt_set(opts, name, value, errp);
669 670
}

G
Gerd Hoffmann 已提交
671 672 673 674 675
const char *qemu_opts_id(QemuOpts *opts)
{
    return opts->id;
}

676 677 678 679 680 681
/* The id string will be g_free()d by qemu_opts_del */
void qemu_opts_set_id(QemuOpts *opts, char *id)
{
    opts->id = id;
}

682 683 684 685
void qemu_opts_del(QemuOpts *opts)
{
    QemuOpt *opt;

686 687 688 689
    if (opts == NULL) {
        return;
    }

690
    for (;;) {
B
Blue Swirl 已提交
691
        opt = QTAILQ_FIRST(&opts->head);
692 693 694 695
        if (opt == NULL)
            break;
        qemu_opt_del(opt);
    }
B
Blue Swirl 已提交
696
    QTAILQ_REMOVE(&opts->list->head, opts, next);
697 698
    g_free(opts->id);
    g_free(opts);
699 700
}

701 702 703 704 705 706 707 708 709 710 711 712 713 714
/* print value, escaping any commas in value */
static void escaped_print(const char *value)
{
    const char *ptr;

    for (ptr = value; *ptr; ++ptr) {
        if (*ptr == ',') {
            putchar(',');
        }
        putchar(*ptr);
    }
}

void qemu_opts_print(QemuOpts *opts, const char *separator)
715 716
{
    QemuOpt *opt;
717
    QemuOptDesc *desc = opts->list->desc;
718 719 720 721 722 723
    const char *sep = "";

    if (opts->id) {
        printf("id=%s", opts->id); /* passed id_wellformed -> no commas */
        sep = separator;
    }
724

725 726
    if (desc[0].name == NULL) {
        QTAILQ_FOREACH(opt, &opts->head, next) {
727 728 729
            printf("%s%s=", sep, opt->name);
            escaped_print(opt->str);
            sep = separator;
730 731 732 733 734
        }
        return;
    }
    for (; desc && desc->name; desc++) {
        const char *value;
735
        opt = qemu_opt_find(opts, desc->name);
736 737 738 739 740 741

        value = opt ? opt->str : desc->def_value_str;
        if (!value) {
            continue;
        }
        if (desc->type == QEMU_OPT_STRING) {
742 743
            printf("%s%s=", sep, desc->name);
            escaped_print(value);
744 745
        } else if ((desc->type == QEMU_OPT_SIZE ||
                    desc->type == QEMU_OPT_NUMBER) && opt) {
746
            printf("%s%s=%" PRId64, sep, desc->name, opt->value.uint);
747
        } else {
748
            printf("%s%s=%s", sep, desc->name, value);
749
        }
750
        sep = separator;
751 752 753
    }
}

754 755
static void opts_do_parse(QemuOpts *opts, const char *params,
                          const char *firstname, bool prepend, Error **errp)
756
{
757
    char option[128], value[1024];
758
    const char *p,*pe,*pc;
759
    Error *local_err = NULL;
760

761
    for (p = params; *p != '\0'; p++) {
762 763 764 765 766 767 768 769 770 771 772
        pe = strchr(p, '=');
        pc = strchr(p, ',');
        if (!pe || (pc && pc < pe)) {
            /* found "foo,more" */
            if (p == params && firstname) {
                /* implicitly named first option */
                pstrcpy(option, sizeof(option), firstname);
                p = get_opt_value(value, sizeof(value), p);
            } else {
                /* option without value, probably a flag */
                p = get_opt_name(option, sizeof(option), p, ',');
773
                if (strncmp(option, "no", 2) == 0) {
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
                    memmove(option, option+2, strlen(option+2)+1);
                    pstrcpy(value, sizeof(value), "off");
                } else {
                    pstrcpy(value, sizeof(value), "on");
                }
            }
        } else {
            /* found "foo=bar,more" */
            p = get_opt_name(option, sizeof(option), p, '=');
            if (*p != '=') {
                break;
            }
            p++;
            p = get_opt_value(value, sizeof(value), p);
        }
        if (strcmp(option, "id") != 0) {
            /* store and parse */
791
            opt_set(opts, option, value, prepend, &local_err);
792
            if (local_err) {
793 794
                error_propagate(errp, local_err);
                return;
795 796 797 798 799 800
            }
        }
        if (*p != ',') {
            break;
        }
    }
801 802
}

803 804 805 806 807 808 809 810
/**
 * Store options parsed from @params into @opts.
 * If @firstname is non-null, the first key=value in @params may omit
 * key=, and is treated as if key was @firstname.
 * On error, store an error object through @errp if non-null.
 */
void qemu_opts_do_parse(QemuOpts *opts, const char *params,
                       const char *firstname, Error **errp)
811
{
812
    opts_do_parse(opts, params, firstname, false, errp);
813 814 815
}

static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
816
                            bool permit_abbrev, bool defaults, Error **errp)
817
{
818
    const char *firstname;
819
    char value[1024], *id = NULL;
820 821
    const char *p;
    QemuOpts *opts;
822
    Error *local_err = NULL;
823

824 825 826
    assert(!permit_abbrev || list->implied_opt_name);
    firstname = permit_abbrev ? list->implied_opt_name : NULL;

827 828
    if (strncmp(params, "id=", 3) == 0) {
        get_opt_value(value, sizeof(value), params+3);
J
Jan Kiszka 已提交
829
        id = value;
830 831
    } else if ((p = strstr(params, ",id=")) != NULL) {
        get_opt_value(value, sizeof(value), p+4);
J
Jan Kiszka 已提交
832
        id = value;
833
    }
834 835 836 837 838 839 840 841 842

    /*
     * This code doesn't work for defaults && !list->merge_lists: when
     * params has no id=, and list has an element with !opts->id, it
     * appends a new element instead of returning the existing opts.
     * However, we got no use for this case.  Guard against possible
     * (if unlikely) future misuse:
     */
    assert(!defaults || list->merge_lists);
843
    opts = qemu_opts_create(list, id, !defaults, &local_err);
844
    if (opts == NULL) {
845
        error_propagate(errp, local_err);
846
        return NULL;
847
    }
848

849 850
    opts_do_parse(opts, params, firstname, defaults, &local_err);
    if (local_err) {
851
        error_propagate(errp, local_err);
852 853 854 855
        qemu_opts_del(opts);
        return NULL;
    }

856 857 858
    return opts;
}

859 860 861 862
/**
 * Create a QemuOpts in @list and with options parsed from @params.
 * If @permit_abbrev, the first key=value in @params may omit key=,
 * and is treated as if key was @list->implied_opt_name.
863
 * On error, store an error object through @errp if non-null.
864 865
 * Return the new QemuOpts on success, null pointer on error.
 */
866
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
                          bool permit_abbrev, Error **errp)
{
    return opts_parse(list, params, permit_abbrev, false, errp);
}

/**
 * Create a QemuOpts in @list and with options parsed from @params.
 * If @permit_abbrev, the first key=value in @params may omit key=,
 * and is treated as if key was @list->implied_opt_name.
 * Report errors with error_report_err().  This is inappropriate in
 * QMP context.  Do not use this function there!
 * Return the new QemuOpts on success, null pointer on error.
 */
QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
                                  bool permit_abbrev)
882
{
883 884 885 886
    Error *err = NULL;
    QemuOpts *opts;

    opts = opts_parse(list, params, permit_abbrev, false, &err);
887 888
    if (err) {
        error_report_err(err);
889 890
    }
    return opts;
891 892 893 894 895 896 897
}

void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
                            int permit_abbrev)
{
    QemuOpts *opts;

898
    opts = opts_parse(list, params, permit_abbrev, true, NULL);
899 900 901
    assert(opts);
}

902 903 904 905 906
typedef struct OptsFromQDictState {
    QemuOpts *opts;
    Error **errp;
} OptsFromQDictState;

907 908
static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
{
909
    OptsFromQDictState *state = opaque;
910
    char buf[32], *tmp = NULL;
911 912
    const char *value;

913
    if (!strcmp(key, "id") || *state->errp) {
914 915 916 917 918 919 920
        return;
    }

    switch (qobject_type(obj)) {
    case QTYPE_QSTRING:
        value = qstring_get_str(qobject_to_qstring(obj));
        break;
921 922 923
    case QTYPE_QNUM:
        tmp = qnum_to_string(qobject_to_qnum(obj));
        value = tmp;
924 925
        break;
    case QTYPE_QBOOL:
B
Blue Swirl 已提交
926
        pstrcpy(buf, sizeof(buf),
E
Eric Blake 已提交
927
                qbool_get_bool(qobject_to_qbool(obj)) ? "on" : "off");
928 929 930 931 932
        value = buf;
        break;
    default:
        return;
    }
933

934
    qemu_opt_set(state->opts, key, value, state->errp);
935
    g_free(tmp);
936 937 938 939
}

/*
 * Create QemuOpts from a QDict.
940 941 942
 * Use value of key "id" as ID if it exists and is a QString.  Only
 * QStrings, QNums and QBools are copied.  Entries with other types
 * are silently ignored.
943
 */
944 945
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
                               Error **errp)
946
{
947
    OptsFromQDictState state;
948
    Error *local_err = NULL;
949
    QemuOpts *opts;
950

951 952
    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
                            &local_err);
953
    if (local_err) {
954
        error_propagate(errp, local_err);
955
        return NULL;
956
    }
957

958
    assert(opts != NULL);
959 960 961 962

    state.errp = &local_err;
    state.opts = opts;
    qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
963
    if (local_err) {
964 965 966 967 968
        error_propagate(errp, local_err);
        qemu_opts_del(opts);
        return NULL;
    }

969 970 971
    return opts;
}

972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993
/*
 * Adds all QDict entries to the QemuOpts that can be added and removes them
 * from the QDict. When this function returns, the QDict contains only those
 * entries that couldn't be added to the QemuOpts.
 */
void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
{
    const QDictEntry *entry, *next;

    entry = qdict_first(qdict);

    while (entry != NULL) {
        Error *local_err = NULL;
        OptsFromQDictState state = {
            .errp = &local_err,
            .opts = opts,
        };

        next = qdict_next(qdict, entry);

        if (find_desc_by_name(opts->list->desc, entry->key)) {
            qemu_opts_from_qdict_1(entry->key, entry->value, &state);
994
            if (local_err) {
995 996 997 998 999 1000 1001 1002 1003 1004 1005
                error_propagate(errp, local_err);
                return;
            } else {
                qdict_del(qdict, entry->key);
            }
        }

        entry = next;
    }
}

1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
/*
 * Convert from QemuOpts to QDict.
 * The QDict values are of type QString.
 * TODO We'll want to use types appropriate for opt->desc->type, but
 * this is enough for now.
 */
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
{
    QemuOpt *opt;

    if (!qdict) {
        qdict = qdict_new();
    }
    if (opts->id) {
1020
        qdict_put_str(qdict, "id", opts->id);
1021 1022
    }
    QTAILQ_FOREACH(opt, &opts->head, next) {
1023
        qdict_put_str(qdict, opt->name, opt->str);
1024 1025 1026 1027
    }
    return qdict;
}

1028 1029 1030
/* Validate parsed opts against descriptions where no
 * descriptions were provided in the QemuOptsList.
 */
1031
void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
1032 1033
{
    QemuOpt *opt;
1034
    Error *local_err = NULL;
1035

1036
    assert(opts_accepts_any(opts));
1037 1038

    QTAILQ_FOREACH(opt, &opts->head, next) {
1039 1040
        opt->desc = find_desc_by_name(desc, opt->name);
        if (!opt->desc) {
1041
            error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
1042
            return;
1043 1044
        }

1045
        qemu_opt_parse(opt, &local_err);
1046
        if (local_err) {
1047 1048
            error_propagate(errp, local_err);
            return;
1049 1050 1051 1052
        }
    }
}

1053
/**
1054
 * For each member of @list, call @func(@opaque, member, @errp).
1055
 * Call it with the current location temporarily set to the member's.
1056
 * @func() may store an Error through @errp, but must return non-zero then.
1057 1058 1059 1060
 * When @func() returns non-zero, break the loop and return that value.
 * Return zero when the loop completes.
 */
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func,
1061
                      void *opaque, Error **errp)
1062
{
1063
    Location loc;
1064
    QemuOpts *opts;
1065
    int rc = 0;
1066

1067
    loc_push_none(&loc);
B
Blue Swirl 已提交
1068
    QTAILQ_FOREACH(opts, &list->head, next) {
1069
        loc_restore(&opts->loc);
1070
        rc = func(opaque, opts, errp);
1071
        if (rc) {
1072
            break;
1073
        }
1074
        assert(!errp || !*errp);
1075
    }
1076
    loc_pop(&loc);
1077
    return rc;
1078
}
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101

static size_t count_opts_list(QemuOptsList *list)
{
    QemuOptDesc *desc = NULL;
    size_t num_opts = 0;

    if (!list) {
        return 0;
    }

    desc = list->desc;
    while (desc && desc->name) {
        num_opts++;
        desc++;
    }

    return num_opts;
}

void qemu_opts_free(QemuOptsList *list)
{
    g_free(list);
}
1102

C
Chunyan Liu 已提交
1103 1104
/* Realloc dst option list and append options from an option list (list)
 * to it. dst could be NULL or a malloced list.
1105 1106
 * The lifetime of dst must be shorter than the input list because the
 * QemuOptDesc->name, ->help, and ->def_value_str strings are shared.
1107 1108
 */
QemuOptsList *qemu_opts_append(QemuOptsList *dst,
C
Chunyan Liu 已提交
1109
                               QemuOptsList *list)
1110 1111 1112 1113
{
    size_t num_opts, num_dst_opts;
    QemuOptDesc *desc;
    bool need_init = false;
1114
    bool need_head_update;
1115

C
Chunyan Liu 已提交
1116
    if (!list) {
1117 1118 1119 1120 1121 1122 1123 1124
        return dst;
    }

    /* If dst is NULL, after realloc, some area of dst should be initialized
     * before adding options to it.
     */
    if (!dst) {
        need_init = true;
1125 1126 1127 1128 1129 1130
        need_head_update = true;
    } else {
        /* Moreover, even if dst is not NULL, the realloc may move it to a
         * different address in which case we may get a stale tail pointer
         * in dst->head. */
        need_head_update = QTAILQ_EMPTY(&dst->head);
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
    }

    num_opts = count_opts_list(dst);
    num_dst_opts = num_opts;
    num_opts += count_opts_list(list);
    dst = g_realloc(dst, sizeof(QemuOptsList) +
                    (num_opts + 1) * sizeof(QemuOptDesc));
    if (need_init) {
        dst->name = NULL;
        dst->implied_opt_name = NULL;
        dst->merge_lists = false;
    }
1143 1144 1145
    if (need_head_update) {
        QTAILQ_INIT(&dst->head);
    }
1146 1147 1148 1149 1150 1151 1152
    dst->desc[num_dst_opts].name = NULL;

    /* append list->desc to dst->desc */
    if (list) {
        desc = list->desc;
        while (desc && desc->name) {
            if (find_desc_by_name(dst->desc, desc->name) == NULL) {
1153
                dst->desc[num_dst_opts++] = *desc;
1154 1155 1156 1157 1158 1159 1160 1161
                dst->desc[num_dst_opts].name = NULL;
            }
            desc++;
        }
    }

    return dst;
}