mirror of https://github.com/xemu-project/xemu.git
vl: plumb keyval-based options into -readconfig
Let -readconfig support parsing command line options into QDict or QemuOpts. This will be used to add back support for objects in -readconfig. Cc: Markus Armbruster <armbru@redhat.com> Cc: qemu-stable@nongnu.org Reviewed-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-Id: <20210524105752.3318299-3-pbonzini@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
3770141139
commit
c0d4aa82f8
|
@ -20,8 +20,6 @@ void qdict_join(QDict *dest, QDict *src, bool overwrite);
|
||||||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
||||||
void qdict_array_split(QDict *src, QList **dst);
|
void qdict_array_split(QDict *src, QList **dst);
|
||||||
int qdict_array_entries(QDict *src, const char *subqdict);
|
int qdict_array_entries(QDict *src, const char *subqdict);
|
||||||
QObject *qdict_crumple(const QDict *src, Error **errp);
|
|
||||||
void qdict_flatten(QDict *qdict);
|
|
||||||
|
|
||||||
typedef struct QDictRenames {
|
typedef struct QDictRenames {
|
||||||
const char *from;
|
const char *from;
|
||||||
|
|
|
@ -64,4 +64,7 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key);
|
||||||
|
|
||||||
QDict *qdict_clone_shallow(const QDict *src);
|
QDict *qdict_clone_shallow(const QDict *src);
|
||||||
|
|
||||||
|
QObject *qdict_crumple(const QDict *src, Error **errp);
|
||||||
|
void qdict_flatten(QDict *qdict);
|
||||||
|
|
||||||
#endif /* QDICT_H */
|
#endif /* QDICT_H */
|
||||||
|
|
83
softmmu/vl.c
83
softmmu/vl.c
|
@ -121,6 +121,7 @@
|
||||||
#include "qapi/qapi-commands-misc.h"
|
#include "qapi/qapi-commands-misc.h"
|
||||||
#include "qapi/qapi-visit-qom.h"
|
#include "qapi/qapi-visit-qom.h"
|
||||||
#include "qapi/qapi-commands-ui.h"
|
#include "qapi/qapi-commands-ui.h"
|
||||||
|
#include "qapi/qmp/qdict.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
#include "sysemu/iothread.h"
|
#include "sysemu/iothread.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
|
@ -2127,13 +2128,53 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return whether configuration group @group is stored in QemuOpts, or
|
||||||
|
* recorded as one or more QDicts by qemu_record_config_group.
|
||||||
|
*/
|
||||||
|
static bool is_qemuopts_group(const char *group)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_record_config_group(const char *group, QDict *dict,
|
||||||
|
bool from_json, Error **errp)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse non-QemuOpts config file groups, pass the rest to
|
||||||
|
* qemu_config_do_parse.
|
||||||
|
*/
|
||||||
|
static void qemu_parse_config_group(const char *group, QDict *qdict,
|
||||||
|
void *opaque, Error **errp)
|
||||||
|
{
|
||||||
|
QObject *crumpled;
|
||||||
|
if (is_qemuopts_group(group)) {
|
||||||
|
qemu_config_do_parse(group, qdict, opaque, errp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
crumpled = qdict_crumple(qdict, errp);
|
||||||
|
if (!crumpled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (qobject_type(crumpled) != QTYPE_QDICT) {
|
||||||
|
assert(qobject_type(crumpled) == QTYPE_QLIST);
|
||||||
|
error_setg(errp, "Lists cannot be at top level of a configuration section");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qemu_record_config_group(group, qobject_to(QDict, crumpled), false, errp);
|
||||||
|
}
|
||||||
|
|
||||||
static void qemu_read_default_config_file(Error **errp)
|
static void qemu_read_default_config_file(Error **errp)
|
||||||
{
|
{
|
||||||
ERRP_GUARD();
|
ERRP_GUARD();
|
||||||
int ret;
|
int ret;
|
||||||
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
|
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
|
||||||
|
|
||||||
ret = qemu_read_config_file(file, qemu_config_do_parse, errp);
|
ret = qemu_read_config_file(file, qemu_parse_config_group, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ret == -ENOENT) {
|
if (ret == -ENOENT) {
|
||||||
error_free(*errp);
|
error_free(*errp);
|
||||||
|
@ -2142,9 +2183,8 @@ static void qemu_read_default_config_file(Error **errp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemu_set_option(const char *str)
|
static void qemu_set_option(const char *str, Error **errp)
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
|
||||||
char group[64], id[64], arg[64];
|
char group[64], id[64], arg[64];
|
||||||
QemuOptsList *list;
|
QemuOptsList *list;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
|
@ -2152,27 +2192,23 @@ static int qemu_set_option(const char *str)
|
||||||
|
|
||||||
rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
|
rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
|
||||||
if (rc < 3 || str[offset] != '=') {
|
if (rc < 3 || str[offset] != '=') {
|
||||||
error_report("can't parse: \"%s\"", str);
|
error_setg(errp, "can't parse: \"%s\"", str);
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list = qemu_find_opts(group);
|
if (!is_qemuopts_group(group)) {
|
||||||
if (list == NULL) {
|
error_setg(errp, "-set is not supported with %s", group);
|
||||||
return -1;
|
} else {
|
||||||
|
list = qemu_find_opts_err(group, errp);
|
||||||
|
if (list) {
|
||||||
|
opts = qemu_opts_find(list, id);
|
||||||
|
if (!opts) {
|
||||||
|
error_setg(errp, "there is no %s \"%s\" defined", group, id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qemu_opt_set(opts, arg, str + offset + 1, errp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = qemu_opts_find(list, id);
|
|
||||||
if (!opts) {
|
|
||||||
error_report("there is no %s \"%s\" defined",
|
|
||||||
list->name, id);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) {
|
|
||||||
error_report_err(local_err);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void user_register_global_props(void)
|
static void user_register_global_props(void)
|
||||||
|
@ -2766,8 +2802,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_set:
|
case QEMU_OPTION_set:
|
||||||
if (qemu_set_option(optarg) != 0)
|
qemu_set_option(optarg, &error_fatal);
|
||||||
exit(1);
|
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_global:
|
case QEMU_OPTION_global:
|
||||||
if (qemu_global_option(optarg) != 0)
|
if (qemu_global_option(optarg) != 0)
|
||||||
|
@ -3399,7 +3434,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
qemu_plugin_opt_parse(optarg, &plugin_list);
|
qemu_plugin_opt_parse(optarg, &plugin_list);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_readconfig:
|
case QEMU_OPTION_readconfig:
|
||||||
qemu_read_config_file(optarg, qemu_config_do_parse, &error_fatal);
|
qemu_read_config_file(optarg, qemu_parse_config_group, &error_fatal);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_spice:
|
case QEMU_OPTION_spice:
|
||||||
olist = qemu_find_opts_err("spice", NULL);
|
olist = qemu_find_opts_err("spice", NULL);
|
||||||
|
|
Loading…
Reference in New Issue