X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/968854c8a106243eae7a68394ce1cb85dc138837..8287fea321882b01d30cd7bfc85d1a043935d525:/util/qemu-config.c diff --git a/util/qemu-config.c b/util/qemu-config.c index 04da942a25..ba375c0148 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -20,7 +20,7 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group, break; } if (lists[i] == NULL) { - error_set(errp, QERR_INVALID_OPTION_GROUP, group); + error_setg(errp, "There is no option group '%s'", group); } return lists[i]; } @@ -31,7 +31,7 @@ QemuOptsList *qemu_find_opts(const char *group) Error *local_err = NULL; ret = find_list(vm_config_groups, group, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); } @@ -39,6 +39,20 @@ QemuOptsList *qemu_find_opts(const char *group) return ret; } +QemuOpts *qemu_find_opts_singleton(const char *group) +{ + QemuOptsList *list; + QemuOpts *opts; + + list = qemu_find_opts(group); + assert(list); + opts = qemu_opts_find(list, NULL); + if (!opts) { + opts = qemu_opts_create(list, NULL, 0, &error_abort); + } + return opts; +} + static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc) { CommandLineParameterInfoList *param_list = NULL, *entry; @@ -68,6 +82,10 @@ static CommandLineParameterInfoList *query_option_descs(const QemuOptDesc *desc) info->has_help = true; info->help = g_strdup(desc[i].help); } + if (desc[i].def_value_str) { + info->has_q_default = true; + info->q_default = g_strdup(desc[i].def_value_str); + } entry = g_malloc0(sizeof(*entry)); entry->value = info; @@ -295,7 +313,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { /* group with id */ list = find_list(lists, group, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); goto out; @@ -306,12 +324,12 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) if (sscanf(line, "[%63[^]]]", group) == 1) { /* group without id */ list = find_list(lists, group, &local_err); - if (error_is_set(&local_err)) { + if (local_err) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); goto out; } - opts = qemu_opts_create_nofail(list); + opts = qemu_opts_create(list, NULL, 0, &error_abort); continue; } if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { @@ -356,3 +374,109 @@ int qemu_read_config_file(const char *filename) return -EINVAL; } } + +static void config_parse_qdict_section(QDict *options, QemuOptsList *opts, + Error **errp) +{ + QemuOpts *subopts; + QDict *subqdict; + QList *list = NULL; + Error *local_err = NULL; + size_t orig_size, enum_size; + char *prefix; + + prefix = g_strdup_printf("%s.", opts->name); + qdict_extract_subqdict(options, &subqdict, prefix); + g_free(prefix); + orig_size = qdict_size(subqdict); + if (!orig_size) { + goto out; + } + + subopts = qemu_opts_create(opts, NULL, 0, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto out; + } + + qemu_opts_absorb_qdict(subopts, subqdict, &local_err); + if (local_err) { + error_propagate(errp, local_err); + goto out; + } + + enum_size = qdict_size(subqdict); + if (enum_size < orig_size && enum_size) { + error_setg(errp, "Unknown option '%s' for [%s]", + qdict_first(subqdict)->key, opts->name); + goto out; + } + + if (enum_size) { + /* Multiple, enumerated sections */ + QListEntry *list_entry; + unsigned i = 0; + + /* Not required anymore */ + qemu_opts_del(subopts); + + qdict_array_split(subqdict, &list); + if (qdict_size(subqdict)) { + error_setg(errp, "Unused option '%s' for [%s]", + qdict_first(subqdict)->key, opts->name); + goto out; + } + + QLIST_FOREACH_ENTRY(list, list_entry) { + QDict *section = qobject_to_qdict(qlist_entry_obj(list_entry)); + char *opt_name; + + if (!section) { + error_setg(errp, "[%s] section (index %u) does not consist of " + "keys", opts->name, i); + goto out; + } + + opt_name = g_strdup_printf("%s.%u", opts->name, i++); + subopts = qemu_opts_create(opts, opt_name, 1, &local_err); + g_free(opt_name); + if (local_err) { + error_propagate(errp, local_err); + goto out; + } + + qemu_opts_absorb_qdict(subopts, section, &local_err); + if (local_err) { + error_propagate(errp, local_err); + qemu_opts_del(subopts); + goto out; + } + + if (qdict_size(section)) { + error_setg(errp, "[%s] section doesn't support the option '%s'", + opts->name, qdict_first(section)->key); + qemu_opts_del(subopts); + goto out; + } + } + } + +out: + QDECREF(subqdict); + QDECREF(list); +} + +void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists, + Error **errp) +{ + int i; + Error *local_err = NULL; + + for (i = 0; lists[i]; i++) { + config_parse_qdict_section(options, lists[i], &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + } +}