CLI help improvements
PULLv2: - fix uninitialized "seentype" variable in qom-test -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbt1jlAAoJENro4Ql1lpzl2dkQAIF4atepjSd2wjOaTVZFjN3A TM42MdaeoRu78srdsd3lOIJiy931BdD82WD+Az5EYjZ9/wLgzBtwZgWFSYD8LRQi g8xDioZQKjAUNQ7ERPOksxsHXpP3ulBagLsZWWxfY81loXfYdsscMuZc/T3cpHoV 6wwf2CpdKcl5qq63DDeYpwuv9+6uemND1EKHoppXtAmGPhX7pqPYZ1+h9Cqriwu9 X5FwlbpZUgig1QjmLZBmp8Akwi66c/NOXUv8BPMR7moQkTdyNfY5Vznvl9fIHEKw UxraDsecGXspUABE3gfbnHkGLC5dYK9uoQpBJ56zcFy0O3hUrvAxjwZRltd8hC8q iEJp0mvTb4FphOm0Ez0dtlDr594OjZF13FOy0b1TLCkqhz672Irb591o2uIKVavT ZHwTT3jRC4nOhz9qoV5MkDMNQcEoVVtu+k/wLloQvghLb4l5bbetuG68jBzw8xGt /5q6p2AUwkwFwAbu122M/8dDKnME+J4cABqkw4FIG6iCD+lmIiccgLcDSGj9/PFD eW0Gc6D+XHl4HLswiaAClXQRFUNaE1YwtL2JWk7ugzX0klDjW1Zye3b90w+rs+YN w6IaubJZJ0Pv/Q9HrajdZ/BKbdsS5rYFbJTdjW/JtRGi6nn+g+/5En3cHmLc5hP7 lbR3Tdl3hXNIGn33/EO1 =7blB -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/elmarco/tags/option-pull-request' into staging CLI help improvements PULLv2: - fix uninitialized "seentype" variable in qom-test # gpg: Signature made Fri 05 Oct 2018 13:28:21 BST # gpg: using RSA key DAE8E10975969CE5 # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" # Primary key fingerprint: 87A9 BD93 3F87 C606 D276 F62D DAE8 E109 7596 9CE5 * remotes/elmarco/tags/option-pull-request: vl: list user creatable properties when 'help' is argument hostmem: add some properties description vl: handle -object help tests/qom-proplist: check class properties iterator tests/qom-proplist: check properties are not listed multiple times tests/qom-proplist: check duplicate "bv" property registration failed qom/object: register 'type' property as class property qom/object: fix iterating properties over a class qemu-option: improve qemu_opts_print_help() output qemu-option: add help fallback to print the list of options cutils: add qemu_pstrcmp0() qdev-monitor: print help to stdout Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
df51a00519
@ -145,16 +145,25 @@ memfd_backend_class_init(ObjectClass *oc, void *data)
|
||||
memfd_backend_get_hugetlb,
|
||||
memfd_backend_set_hugetlb,
|
||||
&error_abort);
|
||||
object_class_property_set_description(oc, "hugetlb",
|
||||
"Use huge pages",
|
||||
&error_abort);
|
||||
object_class_property_add(oc, "hugetlbsize", "int",
|
||||
memfd_backend_get_hugetlbsize,
|
||||
memfd_backend_set_hugetlbsize,
|
||||
NULL, NULL, &error_abort);
|
||||
object_class_property_set_description(oc, "hugetlbsize",
|
||||
"Huge pages size (ex: 2M, 1G)",
|
||||
&error_abort);
|
||||
}
|
||||
if (qemu_memfd_check(MFD_ALLOW_SEALING)) {
|
||||
object_class_property_add_bool(oc, "seal",
|
||||
memfd_backend_get_seal,
|
||||
memfd_backend_set_seal,
|
||||
&error_abort);
|
||||
object_class_property_set_description(oc, "seal",
|
||||
"Seal growing & shrinking",
|
||||
&error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,27 +397,41 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
|
||||
object_class_property_add_bool(oc, "merge",
|
||||
host_memory_backend_get_merge,
|
||||
host_memory_backend_set_merge, &error_abort);
|
||||
object_class_property_set_description(oc, "merge",
|
||||
"Mark memory as mergeable", &error_abort);
|
||||
object_class_property_add_bool(oc, "dump",
|
||||
host_memory_backend_get_dump,
|
||||
host_memory_backend_set_dump, &error_abort);
|
||||
object_class_property_set_description(oc, "dump",
|
||||
"Set to 'off' to exclude from core dump", &error_abort);
|
||||
object_class_property_add_bool(oc, "prealloc",
|
||||
host_memory_backend_get_prealloc,
|
||||
host_memory_backend_set_prealloc, &error_abort);
|
||||
object_class_property_set_description(oc, "prealloc",
|
||||
"Preallocate memory", &error_abort);
|
||||
object_class_property_add(oc, "size", "int",
|
||||
host_memory_backend_get_size,
|
||||
host_memory_backend_set_size,
|
||||
NULL, NULL, &error_abort);
|
||||
object_class_property_set_description(oc, "size",
|
||||
"Size of the memory region (ex: 500M)", &error_abort);
|
||||
object_class_property_add(oc, "host-nodes", "int",
|
||||
host_memory_backend_get_host_nodes,
|
||||
host_memory_backend_set_host_nodes,
|
||||
NULL, NULL, &error_abort);
|
||||
object_class_property_set_description(oc, "host-nodes",
|
||||
"Binds memory to the list of NUMA host nodes", &error_abort);
|
||||
object_class_property_add_enum(oc, "policy", "HostMemPolicy",
|
||||
&HostMemPolicy_lookup,
|
||||
host_memory_backend_get_policy,
|
||||
host_memory_backend_set_policy, &error_abort);
|
||||
object_class_property_set_description(oc, "policy",
|
||||
"Set the NUMA policy", &error_abort);
|
||||
object_class_property_add_bool(oc, "share",
|
||||
host_memory_backend_get_share, host_memory_backend_set_share,
|
||||
&error_abort);
|
||||
object_class_property_set_description(oc, "share",
|
||||
"Mark the memory as private to QEMU or shared", &error_abort);
|
||||
}
|
||||
|
||||
static const TypeInfo host_memory_backend_info = {
|
||||
|
@ -47,4 +47,7 @@ int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd);
|
||||
void monitor_fdset_dup_fd_remove(int dup_fd);
|
||||
int monitor_fdset_dup_fd_find(int dup_fd);
|
||||
|
||||
void monitor_vfprintf(FILE *stream,
|
||||
const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0);
|
||||
|
||||
#endif /* MONITOR_H */
|
||||
|
@ -169,4 +169,16 @@ bool test_buffer_is_zero_next_accel(void);
|
||||
int uleb128_encode_small(uint8_t *out, uint32_t n);
|
||||
int uleb128_decode_small(const uint8_t *in, uint32_t *n);
|
||||
|
||||
/**
|
||||
* qemu_pstrcmp0:
|
||||
* @str1: a non-NULL pointer to a C string (*str1 can be NULL)
|
||||
* @str2: a non-NULL pointer to a C string (*str2 can be NULL)
|
||||
*
|
||||
* Compares *str1 and *str2 with g_strcmp0().
|
||||
*
|
||||
* Returns: an integer less than, equal to, or greater than zero, if
|
||||
* *str1 is <, == or > than *str2.
|
||||
*/
|
||||
int qemu_pstrcmp0(const char **str1, const char **str2);
|
||||
|
||||
#endif
|
||||
|
20
monitor.c
20
monitor.c
@ -4492,6 +4492,20 @@ static void monitor_readline_flush(void *opaque)
|
||||
monitor_flush(opaque);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print to current monitor if we have one, else to stream.
|
||||
* TODO should return int, so callers can calculate width, but that
|
||||
* requires surgery to monitor_vprintf(). Left for another day.
|
||||
*/
|
||||
void monitor_vfprintf(FILE *stream, const char *fmt, va_list ap)
|
||||
{
|
||||
if (cur_mon && !monitor_cur_is_qmp()) {
|
||||
monitor_vprintf(cur_mon, fmt, ap);
|
||||
} else {
|
||||
vfprintf(stream, fmt, ap);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print to current monitor if we have one, else to stderr.
|
||||
* TODO should return int, so callers can calculate width, but that
|
||||
@ -4499,11 +4513,7 @@ static void monitor_readline_flush(void *opaque)
|
||||
*/
|
||||
void error_vprintf(const char *fmt, va_list ap)
|
||||
{
|
||||
if (cur_mon && !monitor_cur_is_qmp()) {
|
||||
monitor_vprintf(cur_mon, fmt, ap);
|
||||
} else {
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
monitor_vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
|
||||
void error_vprintf_unless_qmp(const char *fmt, va_list ap)
|
||||
|
@ -104,22 +104,31 @@ static bool qdev_class_has_alias(DeviceClass *dc)
|
||||
return (qdev_class_get_alias(dc) != NULL);
|
||||
}
|
||||
|
||||
static void out_printf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
monitor_vfprintf(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void qdev_print_devinfo(DeviceClass *dc)
|
||||
{
|
||||
error_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc)));
|
||||
out_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc)));
|
||||
if (dc->bus_type) {
|
||||
error_printf(", bus %s", dc->bus_type);
|
||||
out_printf(", bus %s", dc->bus_type);
|
||||
}
|
||||
if (qdev_class_has_alias(dc)) {
|
||||
error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
|
||||
out_printf(", alias \"%s\"", qdev_class_get_alias(dc));
|
||||
}
|
||||
if (dc->desc) {
|
||||
error_printf(", desc \"%s\"", dc->desc);
|
||||
out_printf(", desc \"%s\"", dc->desc);
|
||||
}
|
||||
if (!dc->user_creatable) {
|
||||
error_printf(", no-user");
|
||||
out_printf(", no-user");
|
||||
}
|
||||
error_printf("\n");
|
||||
out_printf("\n");
|
||||
}
|
||||
|
||||
static void qdev_print_devinfos(bool show_no_user)
|
||||
@ -155,8 +164,7 @@ static void qdev_print_devinfos(bool show_no_user)
|
||||
continue;
|
||||
}
|
||||
if (!cat_printed) {
|
||||
error_printf("%s%s devices:\n", i ? "\n" : "",
|
||||
cat_name[i]);
|
||||
out_printf("%s%s devices:\n", i ? "\n" : "", cat_name[i]);
|
||||
cat_printed = true;
|
||||
}
|
||||
qdev_print_devinfo(dc);
|
||||
@ -278,13 +286,11 @@ int qdev_device_help(QemuOpts *opts)
|
||||
}
|
||||
|
||||
for (prop = prop_list; prop; prop = prop->next) {
|
||||
error_printf("%s.%s=%s", driver,
|
||||
prop->value->name,
|
||||
prop->value->type);
|
||||
out_printf("%s.%s=%s", driver, prop->value->name, prop->value->type);
|
||||
if (prop->value->has_description) {
|
||||
error_printf(" (%s)\n", prop->value->description);
|
||||
out_printf(" (%s)\n", prop->value->description);
|
||||
} else {
|
||||
error_printf("\n");
|
||||
out_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1115,7 +1115,7 @@ void object_class_property_iter_init(ObjectPropertyIterator *iter,
|
||||
ObjectClass *klass)
|
||||
{
|
||||
g_hash_table_iter_init(&iter->iter, klass->properties);
|
||||
iter->nextclass = klass;
|
||||
iter->nextclass = object_class_get_parent(klass);
|
||||
}
|
||||
|
||||
ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
|
||||
@ -2430,9 +2430,10 @@ void object_class_property_set_description(ObjectClass *klass,
|
||||
op->description = g_strdup(description);
|
||||
}
|
||||
|
||||
static void object_instance_init(Object *obj)
|
||||
static void object_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
|
||||
object_class_property_add_str(klass, "type", qdev_get_type,
|
||||
NULL, &error_abort);
|
||||
}
|
||||
|
||||
static void register_types(void)
|
||||
@ -2446,7 +2447,7 @@ static void register_types(void)
|
||||
static TypeInfo object_info = {
|
||||
.name = TYPE_OBJECT,
|
||||
.instance_size = sizeof(Object),
|
||||
.instance_init = object_instance_init,
|
||||
.class_init = object_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
|
@ -141,14 +141,14 @@ Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
|
||||
|
||||
int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
|
||||
{
|
||||
bool (*type_predicate)(const char *) = opaque;
|
||||
bool (*type_opt_predicate)(const char *, QemuOpts *) = opaque;
|
||||
Object *obj = NULL;
|
||||
Error *err = NULL;
|
||||
const char *type;
|
||||
|
||||
type = qemu_opt_get(opts, "qom-type");
|
||||
if (type && type_predicate &&
|
||||
!type_predicate(type)) {
|
||||
if (type && type_opt_predicate &&
|
||||
!type_opt_predicate(type, opts)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -125,10 +125,13 @@ static char *dummy_get_sv(Object *obj,
|
||||
|
||||
static void dummy_init(Object *obj)
|
||||
{
|
||||
Error *err = NULL;
|
||||
|
||||
object_property_add_bool(obj, "bv",
|
||||
dummy_get_bv,
|
||||
dummy_set_bv,
|
||||
NULL);
|
||||
&err);
|
||||
error_free_or_abort(&err);
|
||||
}
|
||||
|
||||
|
||||
@ -517,6 +520,32 @@ static void test_dummy_getenum(void)
|
||||
}
|
||||
|
||||
|
||||
static void test_dummy_prop_iterator(ObjectPropertyIterator *iter)
|
||||
{
|
||||
bool seenbv = false, seensv = false, seenav = false, seentype = false;
|
||||
ObjectProperty *prop;
|
||||
|
||||
while ((prop = object_property_iter_next(iter))) {
|
||||
if (!seenbv && g_str_equal(prop->name, "bv")) {
|
||||
seenbv = true;
|
||||
} else if (!seensv && g_str_equal(prop->name, "sv")) {
|
||||
seensv = true;
|
||||
} else if (!seenav && g_str_equal(prop->name, "av")) {
|
||||
seenav = true;
|
||||
} else if (!seentype && g_str_equal(prop->name, "type")) {
|
||||
/* This prop comes from the base Object class */
|
||||
seentype = true;
|
||||
} else {
|
||||
g_printerr("Found prop '%s'\n", prop->name);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
g_assert(seenbv);
|
||||
g_assert(seenav);
|
||||
g_assert(seensv);
|
||||
g_assert(seentype);
|
||||
}
|
||||
|
||||
static void test_dummy_iterator(void)
|
||||
{
|
||||
Object *parent = object_get_objects_root();
|
||||
@ -529,35 +558,21 @@ static void test_dummy_iterator(void)
|
||||
"sv", "Hiss hiss hiss",
|
||||
"av", "platypus",
|
||||
NULL));
|
||||
|
||||
ObjectProperty *prop;
|
||||
ObjectPropertyIterator iter;
|
||||
bool seenbv = false, seensv = false, seenav = false, seentype;
|
||||
|
||||
object_property_iter_init(&iter, OBJECT(dobj));
|
||||
while ((prop = object_property_iter_next(&iter))) {
|
||||
if (g_str_equal(prop->name, "bv")) {
|
||||
seenbv = true;
|
||||
} else if (g_str_equal(prop->name, "sv")) {
|
||||
seensv = true;
|
||||
} else if (g_str_equal(prop->name, "av")) {
|
||||
seenav = true;
|
||||
} else if (g_str_equal(prop->name, "type")) {
|
||||
/* This prop comes from the base Object class */
|
||||
seentype = true;
|
||||
} else {
|
||||
g_printerr("Found prop '%s'\n", prop->name);
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
g_assert(seenbv);
|
||||
g_assert(seenav);
|
||||
g_assert(seensv);
|
||||
g_assert(seentype);
|
||||
|
||||
test_dummy_prop_iterator(&iter);
|
||||
object_unparent(OBJECT(dobj));
|
||||
}
|
||||
|
||||
static void test_dummy_class_iterator(void)
|
||||
{
|
||||
ObjectPropertyIterator iter;
|
||||
ObjectClass *klass = object_class_by_name(TYPE_DUMMY);
|
||||
|
||||
object_class_property_iter_init(&iter, klass);
|
||||
test_dummy_prop_iterator(&iter);
|
||||
}
|
||||
|
||||
static void test_dummy_delchild(void)
|
||||
{
|
||||
@ -629,6 +644,7 @@ int main(int argc, char **argv)
|
||||
g_test_add_func("/qom/proplist/badenum", test_dummy_badenum);
|
||||
g_test_add_func("/qom/proplist/getenum", test_dummy_getenum);
|
||||
g_test_add_func("/qom/proplist/iterator", test_dummy_iterator);
|
||||
g_test_add_func("/qom/proplist/class_iterator", test_dummy_class_iterator);
|
||||
g_test_add_func("/qom/proplist/delchild", test_dummy_delchild);
|
||||
g_test_add_func("/qom/resolve/partial", test_qom_partial_path);
|
||||
|
||||
|
@ -769,3 +769,8 @@ char *size_to_str(uint64_t val)
|
||||
|
||||
return g_strdup_printf("%0.3g %sB", (double)val / div, suffixes[i]);
|
||||
}
|
||||
|
||||
int qemu_pstrcmp0(const char **str1, const char **str2)
|
||||
{
|
||||
return g_strcmp0(*str1, *str2);
|
||||
}
|
||||
|
@ -208,17 +208,51 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *opt_type_to_string(enum QemuOptType type)
|
||||
{
|
||||
switch (type) {
|
||||
case QEMU_OPT_STRING:
|
||||
return "str";
|
||||
case QEMU_OPT_BOOL:
|
||||
return "bool (on/off)";
|
||||
case QEMU_OPT_NUMBER:
|
||||
return "num";
|
||||
case QEMU_OPT_SIZE:
|
||||
return "size";
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void qemu_opts_print_help(QemuOptsList *list)
|
||||
{
|
||||
QemuOptDesc *desc;
|
||||
int i;
|
||||
GPtrArray *array = g_ptr_array_new();
|
||||
|
||||
assert(list);
|
||||
desc = list->desc;
|
||||
while (desc && desc->name) {
|
||||
printf("%-16s %s\n", desc->name,
|
||||
desc->help ? desc->help : "No description available");
|
||||
GString *str = g_string_new(NULL);
|
||||
if (list->name) {
|
||||
g_string_append_printf(str, "%s.", list->name);
|
||||
}
|
||||
g_string_append_printf(str, "%s=%s", desc->name,
|
||||
opt_type_to_string(desc->type));
|
||||
if (desc->help) {
|
||||
g_string_append_printf(str, " - %s", desc->help);
|
||||
}
|
||||
g_ptr_array_add(array, g_string_free(str, false));
|
||||
desc++;
|
||||
}
|
||||
|
||||
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
|
||||
for (i = 0; i < array->len; i++) {
|
||||
printf("%s\n", (char *)array->pdata[i]);
|
||||
}
|
||||
g_ptr_array_set_free_func(array, g_free);
|
||||
g_ptr_array_free(array, true);
|
||||
|
||||
}
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
@ -486,7 +520,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name)
|
||||
}
|
||||
|
||||
static void opt_set(QemuOpts *opts, const char *name, char *value,
|
||||
bool prepend, Error **errp)
|
||||
bool prepend, bool *invalidp, Error **errp)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
const QemuOptDesc *desc;
|
||||
@ -496,6 +530,9 @@ static void opt_set(QemuOpts *opts, const char *name, char *value,
|
||||
if (!desc && !opts_accepts_any(opts)) {
|
||||
g_free(value);
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
||||
if (invalidp) {
|
||||
*invalidp = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -519,7 +556,7 @@ static void opt_set(QemuOpts *opts, const char *name, char *value,
|
||||
void qemu_opt_set(QemuOpts *opts, const char *name, const char *value,
|
||||
Error **errp)
|
||||
{
|
||||
opt_set(opts, name, g_strdup(value), false, errp);
|
||||
opt_set(opts, name, g_strdup(value), false, NULL, errp);
|
||||
}
|
||||
|
||||
void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
|
||||
@ -750,7 +787,8 @@ void qemu_opts_print(QemuOpts *opts, const char *separator)
|
||||
}
|
||||
|
||||
static void opts_do_parse(QemuOpts *opts, const char *params,
|
||||
const char *firstname, bool prepend, Error **errp)
|
||||
const char *firstname, bool prepend,
|
||||
bool *invalidp, Error **errp)
|
||||
{
|
||||
char *option = NULL;
|
||||
char *value = NULL;
|
||||
@ -785,7 +823,7 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
|
||||
}
|
||||
if (strcmp(option, "id") != 0) {
|
||||
/* store and parse */
|
||||
opt_set(opts, option, value, prepend, &local_err);
|
||||
opt_set(opts, option, value, prepend, invalidp, &local_err);
|
||||
value = NULL;
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
@ -814,11 +852,12 @@ static void opts_do_parse(QemuOpts *opts, const char *params,
|
||||
void qemu_opts_do_parse(QemuOpts *opts, const char *params,
|
||||
const char *firstname, Error **errp)
|
||||
{
|
||||
opts_do_parse(opts, params, firstname, false, errp);
|
||||
opts_do_parse(opts, params, firstname, false, NULL, errp);
|
||||
}
|
||||
|
||||
static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
|
||||
bool permit_abbrev, bool defaults, Error **errp)
|
||||
bool permit_abbrev, bool defaults,
|
||||
bool *invalidp, Error **errp)
|
||||
{
|
||||
const char *firstname;
|
||||
char *id = NULL;
|
||||
@ -850,7 +889,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opts_do_parse(opts, params, firstname, defaults, &local_err);
|
||||
opts_do_parse(opts, params, firstname, defaults, invalidp, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
qemu_opts_del(opts);
|
||||
@ -870,7 +909,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
|
||||
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params,
|
||||
bool permit_abbrev, Error **errp)
|
||||
{
|
||||
return opts_parse(list, params, permit_abbrev, false, errp);
|
||||
return opts_parse(list, params, permit_abbrev, false, NULL, errp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -886,10 +925,16 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
|
||||
{
|
||||
Error *err = NULL;
|
||||
QemuOpts *opts;
|
||||
bool invalidp = false;
|
||||
|
||||
opts = opts_parse(list, params, permit_abbrev, false, &err);
|
||||
opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
|
||||
if (err) {
|
||||
error_report_err(err);
|
||||
if (invalidp && has_help_option(params)) {
|
||||
qemu_opts_print_help(list);
|
||||
error_free(err);
|
||||
} else {
|
||||
error_report_err(err);
|
||||
}
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
@ -899,7 +944,7 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
|
||||
{
|
||||
QemuOpts *opts;
|
||||
|
||||
opts = opts_parse(list, params, permit_abbrev, true, NULL);
|
||||
opts = opts_parse(list, params, permit_abbrev, true, NULL, NULL);
|
||||
assert(opts);
|
||||
}
|
||||
|
||||
|
53
vl.c
53
vl.c
@ -2696,8 +2696,55 @@ static int machine_set_property(void *opaque,
|
||||
* cannot be created here, as it depends on the chardev
|
||||
* already existing.
|
||||
*/
|
||||
static bool object_create_initial(const char *type)
|
||||
static bool object_create_initial(const char *type, QemuOpts *opts)
|
||||
{
|
||||
ObjectClass *klass;
|
||||
|
||||
if (is_help_option(type)) {
|
||||
GSList *l, *list;
|
||||
|
||||
printf("List of user creatable objects:\n");
|
||||
list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
|
||||
for (l = list; l != NULL; l = l->next) {
|
||||
ObjectClass *oc = OBJECT_CLASS(l->data);
|
||||
printf("%s\n", object_class_get_name(oc));
|
||||
}
|
||||
g_slist_free(list);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
klass = object_class_by_name(type);
|
||||
if (klass && qemu_opt_has_help_opt(opts)) {
|
||||
ObjectPropertyIterator iter;
|
||||
ObjectProperty *prop;
|
||||
GPtrArray *array = g_ptr_array_new();
|
||||
int i;
|
||||
|
||||
object_class_property_iter_init(&iter, klass);
|
||||
while ((prop = object_property_iter_next(&iter))) {
|
||||
GString *str;
|
||||
|
||||
if (!prop->set) {
|
||||
continue;
|
||||
}
|
||||
|
||||
str = g_string_new(NULL);
|
||||
g_string_append_printf(str, "%s.%s=%s", type,
|
||||
prop->name, prop->type);
|
||||
if (prop->description) {
|
||||
g_string_append_printf(str, " - %s", prop->description);
|
||||
}
|
||||
g_ptr_array_add(array, g_string_free(str, false));
|
||||
}
|
||||
g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
|
||||
for (i = 0; i < array->len; i++) {
|
||||
printf("%s\n", (char *)array->pdata[i]);
|
||||
}
|
||||
g_ptr_array_set_free_func(array, g_free);
|
||||
g_ptr_array_free(array, true);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (g_str_equal(type, "rng-egd") ||
|
||||
g_str_has_prefix(type, "pr-manager-")) {
|
||||
return false;
|
||||
@ -2744,9 +2791,9 @@ static bool object_create_initial(const char *type)
|
||||
* The remainder of object creation happens after the
|
||||
* creation of chardev, fsdev, net clients and device data types.
|
||||
*/
|
||||
static bool object_create_delayed(const char *type)
|
||||
static bool object_create_delayed(const char *type, QemuOpts *opts)
|
||||
{
|
||||
return !object_create_initial(type);
|
||||
return !object_create_initial(type, opts);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user