mirror of https://gitee.com/openkylin/qemu.git
qemu-option: Add qemu_config_parse_qdict()
This function basically parses command-line options given as a QDict replacing a config file. For instance, the QDict {"section.opt1": 42, "section.opt2": 23} corresponds to the config file: [section] opt1 = 42 opt2 = 23 It is possible to specify multiple sections and also multiple sections of the same type. On the command line, this looks like the following: inject-error.0.event=reftable_load,\ inject-error.1.event=l2_load,\ set-state.event=l1_update This would correspond to the following config file: [inject-error "inject-error.0"] event = reftable_load [inject-error "inject-error.1"] event = l2_load [set-state] event = l1_update Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
9f23fc0c23
commit
adf5c449e5
|
@ -4,6 +4,7 @@
|
|||
#include <stdio.h>
|
||||
#include "qemu/option.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
|
||||
QemuOptsList *qemu_find_opts(const char *group);
|
||||
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
|
||||
|
@ -18,6 +19,11 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname);
|
|||
|
||||
int qemu_read_config_file(const char *filename);
|
||||
|
||||
/* Parse QDict options as a replacement for a config file (allowing multiple
|
||||
enumerated (0..(n-1)) configuration "sections") */
|
||||
void qemu_config_parse_qdict(QDict *options, QemuOptsList **lists,
|
||||
Error **errp);
|
||||
|
||||
/* Read default QEMU config files
|
||||
*/
|
||||
int qemu_read_default_config_files(bool userconfig);
|
||||
|
|
|
@ -356,3 +356,103 @@ 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 (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
qemu_opts_absorb_qdict(subopts, subqdict, &local_err);
|
||||
if (error_is_set(&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;
|
||||
|
||||
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 (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
qemu_opts_absorb_qdict(subopts, section, &local_err);
|
||||
if (error_is_set(&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 (error_is_set(&local_err)) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue