aboutsummaryrefslogtreecommitdiff
path: root/util/qemu-option.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/qemu-option.c')
-rw-r--r--util/qemu-option.c255
1 files changed, 132 insertions, 123 deletions
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 0ebfd97a98..b9f93a7f8b 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -96,7 +96,7 @@ const char *get_opt_value(const char *p, char **value)
return offset;
}
-static void parse_option_bool(const char *name, const char *value, bool *ret,
+static bool parse_option_bool(const char *name, const char *value, bool *ret,
Error **errp)
{
if (!strcmp(value, "on")) {
@@ -106,10 +106,12 @@ static void parse_option_bool(const char *name, const char *value, bool *ret,
} else {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
name, "'on' or 'off'");
+ return false;
}
+ return true;
}
-static void parse_option_number(const char *name, const char *value,
+static bool parse_option_number(const char *name, const char *value,
uint64_t *ret, Error **errp)
{
uint64_t number;
@@ -119,13 +121,14 @@ static void parse_option_number(const char *name, const char *value,
if (err == -ERANGE) {
error_setg(errp, "Value '%s' is too large for parameter '%s'",
value, name);
- return;
+ return false;
}
if (err) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
- return;
+ return false;
}
*ret = number;
+ return true;
}
static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
@@ -142,7 +145,14 @@ static const QemuOptDesc *find_desc_by_name(const QemuOptDesc *desc,
return NULL;
}
-void parse_option_size(const char *name, const char *value,
+static const char *find_default_by_name(QemuOpts *opts, const char *name)
+{
+ const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
+
+ return desc ? desc->def_value_str : NULL;
+}
+
+bool parse_option_size(const char *name, const char *value,
uint64_t *ret, Error **errp)
{
uint64_t size;
@@ -152,7 +162,7 @@ void parse_option_size(const char *name, const char *value,
if (err == -ERANGE) {
error_setg(errp, "Value '%s' is out of range for parameter '%s'",
value, name);
- return;
+ return false;
}
if (err) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
@@ -160,9 +170,10 @@ void parse_option_size(const char *name, const char *value,
error_append_hint(errp, "Optional suffix k, M, G, T, P or E means"
" kilo-, mega-, giga-, tera-, peta-\n"
"and exabytes, respectively.\n");
- return;
+ return false;
}
*ret = size;
+ return true;
}
static const char *opt_type_to_string(enum QemuOptType type)
@@ -277,12 +288,10 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
opt = qemu_opt_find(opts, name);
if (!opt) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- return desc->def_value_str;
- }
+ return find_default_by_name(opts, name);
}
- return opt ? opt->str : NULL;
+
+ return opt->str;
}
void qemu_opt_iter_init(QemuOptsIter *iter, QemuOpts *opts, const char *name)
@@ -311,8 +320,7 @@ const char *qemu_opt_iter_next(QemuOptsIter *iter)
char *qemu_opt_get_del(QemuOpts *opts, const char *name)
{
QemuOpt *opt;
- const QemuOptDesc *desc;
- char *str = NULL;
+ char *str;
if (opts == NULL) {
return NULL;
@@ -320,11 +328,7 @@ char *qemu_opt_get_del(QemuOpts *opts, const char *name)
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;
+ return g_strdup(find_default_by_name(opts, name));
}
str = opt->str;
opt->str = NULL;
@@ -348,6 +352,7 @@ static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
bool defval, bool del)
{
QemuOpt *opt;
+ const char *def_val;
bool ret = defval;
if (opts == NULL) {
@@ -356,9 +361,9 @@ static bool qemu_opt_get_bool_helper(QemuOpts *opts, const char *name,
opt = qemu_opt_find(opts, name);
if (opt == NULL) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- parse_option_bool(name, desc->def_value_str, &ret, &error_abort);
+ def_val = find_default_by_name(opts, name);
+ if (def_val) {
+ parse_option_bool(name, def_val, &ret, &error_abort);
}
return ret;
}
@@ -384,6 +389,7 @@ static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
uint64_t defval, bool del)
{
QemuOpt *opt;
+ const char *def_val;
uint64_t ret = defval;
if (opts == NULL) {
@@ -392,9 +398,9 @@ static uint64_t qemu_opt_get_number_helper(QemuOpts *opts, const char *name,
opt = qemu_opt_find(opts, name);
if (opt == NULL) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- parse_option_number(name, desc->def_value_str, &ret, &error_abort);
+ def_val = find_default_by_name(opts, name);
+ if (def_val) {
+ parse_option_number(name, def_val, &ret, &error_abort);
}
return ret;
}
@@ -421,6 +427,7 @@ static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
uint64_t defval, bool del)
{
QemuOpt *opt;
+ const char *def_val;
uint64_t ret = defval;
if (opts == NULL) {
@@ -429,9 +436,9 @@ static uint64_t qemu_opt_get_size_helper(QemuOpts *opts, const char *name,
opt = qemu_opt_find(opts, name);
if (opt == NULL) {
- const QemuOptDesc *desc = find_desc_by_name(opts->list->desc, name);
- if (desc && desc->def_value_str) {
- parse_option_size(name, desc->def_value_str, &ret, &error_abort);
+ def_val = find_default_by_name(opts, name);
+ if (def_val) {
+ parse_option_size(name, def_val, &ret, &error_abort);
}
return ret;
}
@@ -454,24 +461,24 @@ uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
return qemu_opt_get_size_helper(opts, name, defval, true);
}
-static void qemu_opt_parse(QemuOpt *opt, Error **errp)
+static bool qemu_opt_parse(QemuOpt *opt, Error **errp)
{
if (opt->desc == NULL)
- return;
+ return true;
switch (opt->desc->type) {
case QEMU_OPT_STRING:
/* nothing */
- return;
+ return true;
case QEMU_OPT_BOOL:
- parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
- break;
+ return parse_option_bool(opt->name, opt->str, &opt->value.boolean,
+ errp);
case QEMU_OPT_NUMBER:
- parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
- break;
+ return parse_option_number(opt->name, opt->str, &opt->value.uint,
+ errp);
case QEMU_OPT_SIZE:
- parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
- break;
+ return parse_option_size(opt->name, opt->str, &opt->value.uint,
+ errp);
default:
abort();
}
@@ -496,86 +503,99 @@ int qemu_opt_unset(QemuOpts *opts, const char *name)
}
}
-static void opt_set(QemuOpts *opts, const char *name, char *value,
- bool prepend, bool *help_wanted, Error **errp)
+static QemuOpt *opt_create(QemuOpts *opts, const char *name, char *value,
+ bool prepend)
{
- QemuOpt *opt;
- const QemuOptDesc *desc;
- Error *local_err = NULL;
+ QemuOpt *opt = g_malloc0(sizeof(*opt));
- desc = find_desc_by_name(opts->list->desc, name);
- if (!desc && !opts_accepts_any(opts)) {
- g_free(value);
- error_setg(errp, QERR_INVALID_PARAMETER, name);
- if (help_wanted && is_help_option(name)) {
- *help_wanted = true;
- }
- return;
- }
-
- opt = g_malloc0(sizeof(*opt));
opt->name = g_strdup(name);
+ opt->str = value;
opt->opts = opts;
if (prepend) {
QTAILQ_INSERT_HEAD(&opts->head, opt, next);
} else {
QTAILQ_INSERT_TAIL(&opts->head, opt, next);
}
+
+ return opt;
+}
+
+static bool opt_validate(QemuOpt *opt, bool *help_wanted,
+ Error **errp)
+{
+ const QemuOptDesc *desc;
+
+ desc = find_desc_by_name(opt->opts->list->desc, opt->name);
+ if (!desc && !opts_accepts_any(opt->opts)) {
+ error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
+ if (help_wanted && is_help_option(opt->name)) {
+ *help_wanted = true;
+ }
+ return false;
+ }
+
opt->desc = desc;
- opt->str = value;
- qemu_opt_parse(opt, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- qemu_opt_del(opt);
+ if (!qemu_opt_parse(opt, errp)) {
+ return false;
}
+
+ return true;
}
-void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
+bool qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
Error **errp)
{
- opt_set(opts, name, g_strdup(value), false, NULL, errp);
+ QemuOpt *opt = opt_create(opts, name, g_strdup(value), false);
+
+ if (!opt_validate(opt, NULL, errp)) {
+ qemu_opt_del(opt);
+ return false;
+ }
+ return true;
}
-void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
+bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
Error **errp)
{
QemuOpt *opt;
- const QemuOptDesc *desc = opts->list->desc;
+ const QemuOptDesc *desc;
- opt = g_malloc0(sizeof(*opt));
- opt->desc = find_desc_by_name(desc, name);
- if (!opt->desc && !opts_accepts_any(opts)) {
+ desc = find_desc_by_name(opts->list->desc, name);
+ if (!desc && !opts_accepts_any(opts)) {
error_setg(errp, QERR_INVALID_PARAMETER, name);
- g_free(opt);
- return;
+ return false;
}
+ opt = g_malloc0(sizeof(*opt));
opt->name = g_strdup(name);
opt->opts = opts;
+ opt->desc = desc;
opt->value.boolean = !!val;
opt->str = g_strdup(val ? "on" : "off");
QTAILQ_INSERT_TAIL(&opts->head, opt, next);
+ return true;
}
-void qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
+bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
Error **errp)
{
QemuOpt *opt;
- const QemuOptDesc *desc = opts->list->desc;
+ const QemuOptDesc *desc;
- opt = g_malloc0(sizeof(*opt));
- opt->desc = find_desc_by_name(desc, name);
- if (!opt->desc && !opts_accepts_any(opts)) {
+ desc = find_desc_by_name(opts->list->desc, name);
+ if (!desc && !opts_accepts_any(opts)) {
error_setg(errp, QERR_INVALID_PARAMETER, name);
- g_free(opt);
- return;
+ return false;
}
+ opt = g_malloc0(sizeof(*opt));
opt->name = g_strdup(name);
opt->opts = opts;
+ opt->desc = desc;
opt->value.uint = val;
opt->str = g_strdup_printf("%" PRId64, val);
QTAILQ_INSERT_TAIL(&opts->head, opt, next);
+ return true;
}
/**
@@ -666,18 +686,16 @@ void qemu_opts_loc_restore(QemuOpts *opts)
loc_restore(&opts->loc);
}
-void qemu_opts_set(QemuOptsList *list, const char *id,
+bool qemu_opts_set(QemuOptsList *list, const char *id,
const char *name, const char *value, Error **errp)
{
QemuOpts *opts;
- Error *local_err = NULL;
- opts = qemu_opts_create(list, id, 1, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
+ opts = qemu_opts_create(list, id, 1, errp);
+ if (!opts) {
+ return false;
}
- qemu_opt_set(opts, name, value, errp);
+ return qemu_opt_set(opts, name, value, errp);
}
const char *qemu_opts_id(QemuOpts *opts)
@@ -803,13 +821,13 @@ static const char *get_opt_name_value(const char *params,
return p;
}
-static void opts_do_parse(QemuOpts *opts, const char *params,
+static bool opts_do_parse(QemuOpts *opts, const char *params,
const char *firstname, bool prepend,
bool *help_wanted, Error **errp)
{
- Error *local_err = NULL;
char *option, *value;
const char *p;
+ QemuOpt *opt;
for (p = params; *p;) {
p = get_opt_name_value(p, firstname, &option, &value);
@@ -821,13 +839,15 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
continue;
}
- opt_set(opts, option, value, prepend, help_wanted, &local_err);
+ opt = opt_create(opts, option, value, prepend);
g_free(option);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
+ if (!opt_validate(opt, help_wanted, errp)) {
+ qemu_opt_del(opt);
+ return false;
}
}
+
+ return true;
}
static char *opts_parse_id(const char *params)
@@ -873,10 +893,10 @@ bool has_help_option(const char *params)
* 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,
+bool qemu_opts_do_parse(QemuOpts *opts, const char *params,
const char *firstname, Error **errp)
{
- opts_do_parse(opts, params, firstname, false, NULL, errp);
+ return opts_do_parse(opts, params, firstname, false, NULL, errp);
}
static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
@@ -886,7 +906,6 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
const char *firstname;
char *id = opts_parse_id(params);
QemuOpts *opts;
- Error *local_err = NULL;
assert(!permit_abbrev || list->implied_opt_name);
firstname = permit_abbrev ? list->implied_opt_name : NULL;
@@ -899,16 +918,14 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
* (if unlikely) future misuse:
*/
assert(!defaults || list->merge_lists);
- opts = qemu_opts_create(list, id, !defaults, &local_err);
+ opts = qemu_opts_create(list, id, !defaults, errp);
g_free(id);
if (opts == NULL) {
- error_propagate(errp, local_err);
return NULL;
}
- opts_do_parse(opts, params, firstname, defaults, help_wanted, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ if (!opts_do_parse(opts, params, firstname, defaults, help_wanted,
+ errp)) {
qemu_opts_del(opts);
return NULL;
}
@@ -965,17 +982,18 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
assert(opts);
}
-static void qemu_opts_from_qdict_entry(QemuOpts *opts,
+static bool qemu_opts_from_qdict_entry(QemuOpts *opts,
const QDictEntry *entry,
Error **errp)
{
const char *key = qdict_entry_key(entry);
QObject *obj = qdict_entry_value(entry);
- char buf[32], *tmp = NULL;
+ char buf[32];
+ g_autofree char *tmp = NULL;
const char *value;
if (!strcmp(key, "id")) {
- return;
+ return true;
}
switch (qobject_type(obj)) {
@@ -992,11 +1010,10 @@ static void qemu_opts_from_qdict_entry(QemuOpts *opts,
value = buf;
break;
default:
- return;
+ return true;
}
- qemu_opt_set(opts, key, value, errp);
- g_free(tmp);
+ return qemu_opt_set(opts, key, value, errp);
}
/*
@@ -1008,14 +1025,11 @@ static void qemu_opts_from_qdict_entry(QemuOpts *opts,
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
Error **errp)
{
- Error *local_err = NULL;
QemuOpts *opts;
const QDictEntry *entry;
- opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1, errp);
+ if (!opts) {
return NULL;
}
@@ -1024,9 +1038,7 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
for (entry = qdict_first(qdict);
entry;
entry = qdict_next(qdict, entry)) {
- qemu_opts_from_qdict_entry(opts, entry, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ if (!qemu_opts_from_qdict_entry(opts, entry, errp)) {
qemu_opts_del(opts);
return NULL;
}
@@ -1040,28 +1052,26 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
* 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)
+bool 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;
-
next = qdict_next(qdict, entry);
if (find_desc_by_name(opts->list->desc, entry->key)) {
- qemu_opts_from_qdict_entry(opts, entry, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
+ if (!qemu_opts_from_qdict_entry(opts, entry, errp)) {
+ return false;
}
qdict_del(qdict, entry->key);
}
entry = next;
}
+
+ return true;
}
/*
@@ -1121,10 +1131,9 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
/* Validate parsed opts against descriptions where no
* descriptions were provided in the QemuOptsList.
*/
-void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
+bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
{
QemuOpt *opt;
- Error *local_err = NULL;
assert(opts_accepts_any(opts));
@@ -1132,15 +1141,15 @@ void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
opt->desc = find_desc_by_name(desc, opt->name);
if (!opt->desc) {
error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
- return;
+ return false;
}
- qemu_opt_parse(opt, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
+ if (!qemu_opt_parse(opt, errp)) {
+ return false;
}
}
+
+ return true;
}
/**