Merge remote-tracking branch 'qmp/for-anthony' into staging

This commit is contained in:
Anthony Liguori
2011-07-22 09:23:53 -05:00
40 changed files with 4842 additions and 31 deletions
+41 -4
View File
@@ -106,6 +106,8 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
QEMU_CFLAGS+=$(CURL_CFLAGS)
QEMU_CFLAGS+=$(GLIB_CFLAGS)
ui/cocoa.o: ui/cocoa.m
ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
@@ -138,7 +140,7 @@ endif
######################################################################
qemu-img.o: qemu-img-cmds.h
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o: $(GENERATED_HEADERS)
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
@@ -160,19 +162,54 @@ check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o error.o qerror.o qemu-error.o $(CHECK_PROG_DEPS)
$(qapi-obj-y): $(GENERATED_HEADERS)
qapi-dir := qapi-generated
test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
$(qapi-dir)/test-qapi-types.c: $(qapi-dir)/test-qapi-types.h
$(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
$(qapi-dir)/test-qapi-visit.c: $(qapi-dir)/test-qapi-visit.h
$(qapi-dir)/test-qapi-visit.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
$(qapi-dir)/test-qmp-commands.h: $(qapi-dir)/test-qmp-marshal.c
$(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
$(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h
$(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h
$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o
qemu-ga.o: $(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c) $(qapi-obj-y)
qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f qemu-options.def
rm -f *.o *.d *.a *.lo $(TOOLS) TAGS cscope.* *.pod *~ */*~
rm -f *.o *.d *.a *.lo $(TOOLS) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -Rf .libs
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d
rm -f qemu-img-cmds.h
rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
rm -f trace-dtrace.h trace-dtrace.h-timestamp
rm -rf $(qapi-dir)
$(MAKE) -C tests clean
for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
@@ -361,4 +398,4 @@ tarbin:
$(mandir)/man8/qemu-nbd.8
# Include automatically generated dependency files
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d)
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d qga/*.d)
+8
View File
@@ -373,7 +373,15 @@ endif
libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
######################################################################
# qapi
qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
qapi-nested-y += qmp-registry.o qmp-dispatch.o
qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
vl.o: QEMU_CFLAGS+=$(GLIB_CFLAGS)
+1
View File
@@ -204,6 +204,7 @@ QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
QEMU_CFLAGS += $(GLIB_CFLAGS)
# xen support
obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
+2 -2
View File
@@ -568,7 +568,7 @@ void do_commit(Monitor *mon, const QDict *qdict)
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *device = qdict_get_str(qdict, "device");
const char *filename = qdict_get_try_str(qdict, "snapshot_file");
const char *filename = qdict_get_try_str(qdict, "snapshot-file");
const char *format = qdict_get_try_str(qdict, "format");
BlockDriverState *bs;
BlockDriver *drv, *old_drv, *proto_drv;
@@ -577,7 +577,7 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
char old_filename[1024];
if (!filename) {
qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
qerror_report(QERR_MISSING_PARAMETER, "snapshot-file");
ret = -1;
goto out;
}
+34
View File
@@ -0,0 +1,34 @@
/* public domain */
#ifndef COMPILER_H
#define COMPILER_H
#include "config-host.h"
#define QEMU_NORETURN __attribute__ ((__noreturn__))
#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define QEMU_WARN_UNUSED_RESULT
#endif
#define QEMU_BUILD_BUG_ON(x) \
typedef char qemu_build_bug_on__##__LINE__[(x)?-1:1];
#if defined __GNUC__
# if (__GNUC__ < 4) || \
defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)
/* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
# define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2)))
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
# else
/* Use gnu_printf when supported (qemu uses standard format strings). */
# define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
# endif
#else
#define GCC_ATTR /**/
#define GCC_FMT_ATTR(n, m)
#endif
#endif /* COMPILER_H */
Vendored
+16
View File
@@ -1809,6 +1809,18 @@ EOF
fi
fi
##########################################
# glib support probe
if $pkg_config --modversion gthread-2.0 gio-2.0 > /dev/null 2>&1 ; then
glib_cflags=`$pkg_config --cflags gthread-2.0 gio-2.0 2>/dev/null`
glib_libs=`$pkg_config --libs gthread-2.0 gio-2.0 2>/dev/null`
libs_softmmu="$glib_libs $libs_softmmu"
libs_tools="$glib_libs $libs_tools"
else
echo "glib-2.0 required to compile QEMU"
exit 1
fi
##########################################
# pthread probe
PTHREADLIBS_LIST="-lpthread -lpthreadGC2"
@@ -2543,6 +2555,7 @@ if test "$softmmu" = yes ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
tools="qemu-nbd\$(EXESUF) $tools"
tools="qemu-ga\$(EXESUF) $tools"
if [ "$check_utests" = "yes" ]; then
tools="check-qint check-qstring check-qdict check-qlist $tools"
tools="check-qfloat check-qjson $tools"
@@ -2873,6 +2886,7 @@ if test "$bluez" = "yes" ; then
echo "CONFIG_BLUEZ=y" >> $config_host_mak
echo "BLUEZ_CFLAGS=$bluez_cflags" >> $config_host_mak
fi
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
if test "$xen" = "yes" ; then
echo "CONFIG_XEN_BACKEND=y" >> $config_host_mak
echo "CONFIG_XEN_CTRL_INTERFACE_VERSION=$xen_ctrl_version" >> $config_host_mak
@@ -3501,6 +3515,8 @@ DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
DIRS="$DIRS pc-bios/spapr-rtas"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS fsdev ui"
DIRS="$DIRS qapi"
DIRS="$DIRS qga"
FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
+316
View File
@@ -0,0 +1,316 @@
= How to use the QAPI code generator =
* Note: as of this writing, QMP does not use QAPI. Eventually QMP
commands will be converted to use QAPI internally. The following
information describes QMP/QAPI as it will exist after the
conversion.
QAPI is a native C API within QEMU which provides management-level
functionality to internal/external users. For external
users/processes, this interface is made available by a JSON-based
QEMU Monitor protocol that is provided by the QMP server.
To map QMP-defined interfaces to the native C QAPI implementations,
a JSON-based schema is used to define types and function
signatures, and a set of scripts is used to generate types/signatures,
and marshaling/dispatch code. The QEMU Guest Agent also uses these
scripts, paired with a seperate schema, to generate
marshaling/dispatch code for the guest agent server running in the
guest.
This document will describe how the schemas, scripts, and resulting
code is used.
== QMP/Guest agent schema ==
This file defines the types, commands, and events used by QMP. It should
fully describe the interface used by QMP.
This file is designed to be loosely based on JSON although it's technically
executable Python. While dictionaries are used, they are parsed as
OrderedDicts so that ordering is preserved.
There are two basic syntaxes used, type definitions and command definitions.
The first syntax defines a type and is represented by a dictionary. There are
two kinds of types that are supported: complex user-defined types, and enums.
A complex type is a dictionary containing a single key who's value is a
dictionary. This corresponds to a struct in C or an Object in JSON. An
example of a complex type is:
{ 'type': 'MyType',
'data' { 'member1': 'str', 'member2': 'int', '*member3': 'str } }
The use of '*' as a prefix to the name means the member is optional. Optional
members should always be added to the end of the dictionary to preserve
backwards compatibility.
An enumeration type is a dictionary containing a single key who's value is a
list of strings. An example enumeration is:
{ 'enum': 'MyEnum', 'data': [ 'value1', 'value2', 'value3' ] }
Generally speaking, complex types and enums should always use CamelCase for
the type names.
Commands are defined by using a list containing three members. The first
member is the command name, the second member is a dictionary containing
arguments, and the third member is the return type.
An example command is:
{ 'command': 'my-command',
'data': { 'arg1': 'str', '*arg2': 'str' },
'returns': 'str' ]
Command names should be all lower case with words separated by a hyphen.
== Code generation ==
Schemas are fed into 3 scripts to generate all the code/files that, paired
with the core QAPI libraries, comprise everything required to take JSON
commands read in by a QMP/guest agent server, unmarshal the arguments into
the underlying C types, call into the corresponding C function, and map the
response back to a QMP/guest agent response to be returned to the user.
As an example, we'll use the following schema, which describes a single
complex user-defined type (which will produce a C struct, along with a list
node structure that can be used to chain together a list of such types in
case we want to accept/return a list of this type with a command), and a
command which takes that type as a parameter and returns the same type:
mdroth@illuin:~/w/qemu2.git$ cat example-schema.json
{ 'type': 'UserDefOne',
'data': { 'integer': 'int', 'string': 'str' } }
{ 'command': 'my-command',
'data': {'arg1': 'UserDefOne'},
'returns': 'UserDefOne' }
mdroth@illuin:~/w/qemu2.git$
=== scripts/qapi-types.py ===
Used to generate the C types defined by a schema. The following files are
created:
$(prefix)qapi-types.h - C types corresponding to types defined in
the schema you pass in
$(prefix)qapi-types.c - Cleanup functions for the above C types
The $(prefix) is an optional parameter used as a namespace to keep the
generated code from one schema/code-generation separated from others so code
can be generated/used from multiple schemas without clobbering previously
created code.
Example:
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
--output-dir="qapi-generated" --prefix="example-" < example-schema.json
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
#include "qapi/qapi-dealloc-visitor.h"
#include "example-qapi-types.h"
#include "example-qapi-visit.h"
void qapi_free_UserDefOne(UserDefOne * obj)
{
QapiDeallocVisitor *md;
Visitor *v;
if (!obj) {
return;
}
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &obj, NULL, NULL);
qapi_dealloc_visitor_cleanup(md);
}
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
#define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
#include "qapi/qapi-types-core.h"
typedef struct UserDefOne UserDefOne;
typedef struct UserDefOneList
{
UserDefOne *value;
struct UserDefOneList *next;
} UserDefOneList;
struct UserDefOne
{
int64_t integer;
char * string;
};
void qapi_free_UserDefOne(UserDefOne * obj);
#endif
=== scripts/qapi-visit.py ===
Used to generate the visitor functions used to walk through and convert
a QObject (as provided by QMP) to a native C data structure and
vice-versa, as well as the visitor function used to dealloc a complex
schema-defined C type.
The following files are generated:
$(prefix)qapi-visit.c: visitor function for a particular C type, used
to automagically convert QObjects into the
corresponding C type and vice-versa, as well
as for deallocating memory for an existing C
type
$(prefix)qapi-visit.h: declarations for previously mentioned visitor
functions
Example:
mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
--output-dir="qapi-generated" --prefix="example-" < example-schema.json
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#include "example-qapi-visit.h"
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
{
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
visit_end_struct(m, errp);
}
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
{
GenericList *i;
visit_start_list(m, name, errp);
for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) {
UserDefOneList *native_i = (UserDefOneList *)i;
visit_type_UserDefOne(m, &native_i->value, NULL, errp);
}
visit_end_list(m, errp);
}
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
#define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
#include "qapi/qapi-visit-core.h"
#include "example-qapi-types.h"
void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);
#endif
mdroth@illuin:~/w/qemu2.git$
=== scripts/qapi-commands.py ===
Used to generate the marshaling/dispatch functions for the commands defined
in the schema. The following files are generated:
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
QMP command defined in the schema. Functions
generated by qapi-visit.py are used to
convert QObjects recieved from the wire into
function parameters, and uses the same
visitor functions to convert native C return
values to QObjects from transmission back
over the wire.
$(prefix)qmp-commands.h: Function prototypes for the QMP commands
specified in the schema.
Example:
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#include "qemu-objects.h"
#include "qapi/qmp-core.h"
#include "qapi/qapi-visit-core.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi/qapi-dealloc-visitor.h"
#include "example-qapi-types.h"
#include "example-qapi-visit.h"
#include "example-qmp-commands.h"
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
{
QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
QmpOutputVisitor *mo = qmp_output_visitor_new();
Visitor *v;
v = qmp_output_get_visitor(mo);
visit_type_UserDefOne(v, &ret_in, "unused", errp);
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &ret_in, "unused", errp);
qapi_dealloc_visitor_cleanup(md);
*ret_out = qmp_output_get_qobject(mo);
}
static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
{
UserDefOne * retval = NULL;
QmpInputVisitor *mi;
QapiDeallocVisitor *md;
Visitor *v;
UserDefOne * arg1 = NULL;
mi = qmp_input_visitor_new(QOBJECT(args));
v = qmp_input_get_visitor(mi);
visit_type_UserDefOne(v, &arg1, "arg1", errp);
if (error_is_set(errp)) {
goto out;
}
retval = qmp_my_command(arg1, errp);
qmp_marshal_output_my_command(retval, ret, errp);
out:
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &arg1, "arg1", errp);
qapi_dealloc_visitor_cleanup(md);
return;
}
static void qmp_init_marshal(void)
{
qmp_register_command("my-command", qmp_marshal_input_my_command);
}
qapi_init(qmp_init_marshal);
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
#ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
#define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
#include "example-qapi-types.h"
#include "error.h"
UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);
#endif
mdroth@illuin:~/w/qemu2.git$
+1
View File
@@ -12,6 +12,7 @@
#ifndef ERROR_H
#define ERROR_H
#include "compiler.h"
#include <stdbool.h>
/**
+1 -1
View File
@@ -840,7 +840,7 @@ ETEXI
{
.name = "snapshot_blkdev",
.args_type = "device:B,snapshot_file:s?,format:s?",
.args_type = "device:B,snapshot-file:s?,format:s?",
.params = "device [new-image-file] [format]",
.help = "initiates a live snapshot\n\t\t\t"
"of device. If a new image file is specified, the\n\t\t\t"
+2
View File
@@ -24,12 +24,14 @@ typedef enum {
MODULE_INIT_BLOCK,
MODULE_INIT_DEVICE,
MODULE_INIT_MACHINE,
MODULE_INIT_QAPI,
MODULE_INIT_MAX
} module_init_type;
#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
#define device_init(function) module_init(function, MODULE_INIT_DEVICE)
#define machine_init(function) module_init(function, MODULE_INIT_MACHINE)
#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
void register_module_init(void (*fn)(void), module_init_type type);
+217
View File
@@ -0,0 +1,217 @@
# *-*- Mode: Python -*-*
##
# @guest-sync:
#
# Echo back a unique integer value
#
# This is used by clients talking to the guest agent over the
# wire to ensure the stream is in sync and doesn't contain stale
# data from previous client. All guest agent responses should be
# ignored until the provided unique integer value is returned,
# and it is up to the client to handle stale whole or
# partially-delivered JSON text in such a way that this response
# can be obtained.
#
# Such clients should also preceed this command
# with a 0xFF byte to make such the guest agent flushes any
# partially read JSON data from a previous session.
#
# @id: randomly generated 64-bit integer
#
# Returns: The unique integer id passed in by the client
#
# Since: 0.15.0
##
{ 'command': 'guest-sync'
'data': { 'id': 'int' },
'returns': 'int' }
##
# @guest-ping:
#
# Ping the guest agent, a non-error return implies success
#
# Since: 0.15.0
##
{ 'command': 'guest-ping' }
##
# @guest-info:
#
# Get some information about the guest agent.
#
# Since: 0.15.0
##
{ 'type': 'GuestAgentInfo', 'data': {'version': 'str'} }
{ 'command': 'guest-info',
'returns': 'GuestAgentInfo' }
##
# @guest-shutdown:
#
# Initiate guest-activated shutdown. Note: this is an asynchronous
# shutdown request, with no guaruntee of successful shutdown. Errors
# will be logged to guest's syslog.
#
# @mode: #optional "halt", "powerdown" (default), or "reboot"
#
# Returns: Nothing on success
#
# Since: 0.15.0
##
{ 'command': 'guest-shutdown', 'data': { '*mode': 'str' } }
##
# @guest-file-open:
#
# Open a file in the guest and retrieve a file handle for it
#
# @filepath: Full path to the file in the guest to open.
#
# @mode: #optional open mode, as per fopen(), "r" is the default.
#
# Returns: Guest file handle on success.
#
# Since: 0.15.0
##
{ 'command': 'guest-file-open',
'data': { 'path': 'str', '*mode': 'str' },
'returns': 'int' }
##
# @guest-file-close:
#
# Close an open file in the guest
#
# @handle: filehandle returned by guest-file-open
#
# Returns: Nothing on success.
#
# Since: 0.15.0
##
{ 'command': 'guest-file-close',
'data': { 'handle': 'int' } }
##
# @guest-file-read:
#
# Read from an open file in the guest. Data will be base64-encoded
#
# @handle: filehandle returned by guest-file-open
#
# @count: #optional maximum number of bytes to read (default is 4KB)
#
# Returns: GuestFileRead on success. Note: count is number of bytes read
# *before* base64 encoding bytes read.
#
# Since: 0.15.0
##
{ 'type': 'GuestFileRead',
'data': { 'count': 'int', 'buf-b64': 'str', 'eof': 'bool' } }
{ 'command': 'guest-file-read',
'data': { 'handle': 'int', '*count': 'int' },
'returns': 'GuestFileRead' }
##
# @guest-file-write:
#
# Write to an open file in the guest.
#
# @handle: filehandle returned by guest-file-open
#
# @buf-b64: base64-encoded string representing data to be written
#
# @count: #optional bytes to write (actual bytes, after base64-decode),
# default is all content in buf-b64 buffer after base64 decoding
#
# Returns: GuestFileWrite on success. Note: count is the number of bytes
# base64-decoded bytes written
#
# Since: 0.15.0
##
{ 'type': 'GuestFileWrite',
'data': { 'count': 'int', 'eof': 'bool' } }
{ 'command': 'guest-file-write',
'data': { 'handle': 'int', 'buf-b64': 'str', '*count': 'int' },
'returns': 'GuestFileWrite' }
##
# @guest-file-seek:
#
# Seek to a position in the file, as with fseek(), and return the
# current file position afterward. Also encapsulates ftell()'s
# functionality, just Set offset=0, whence=SEEK_CUR.
#
# @handle: filehandle returned by guest-file-open
#
# @offset: bytes to skip over in the file stream
#
# @whence: SEEK_SET, SEEK_CUR, or SEEK_END, as with fseek()
#
# Returns: GuestFileSeek on success.
#
# Since: 0.15.0
##
{ 'type': 'GuestFileSeek',
'data': { 'position': 'int', 'eof': 'bool' } }
{ 'command': 'guest-file-seek',
'data': { 'handle': 'int', 'offset': 'int', 'whence': 'int' },
'returns': 'GuestFileSeek' }
##
# @guest-file-flush:
#
# Write file changes bufferred in userspace to disk/kernel buffers
#
# @handle: filehandle returned by guest-file-open
#
# Returns: Nothing on success.
#
# Since: 0.15.0
##
{ 'command': 'guest-file-flush',
'data': { 'handle': 'int' } }
##
# @guest-fsfreeze-status:
#
# Get guest fsfreeze state. error state indicates failure to thaw 1 or more
# previously frozen filesystems, or failure to open a previously cached
# filesytem (filesystem unmounted/directory changes, etc).
#
# Returns: GuestFsfreezeStatus ("thawed", "frozen", etc., as defined below)
#
# Since: 0.15.0
##
{ 'enum': 'GuestFsfreezeStatus',
'data': [ 'thawed', 'frozen', 'error' ] }
{ 'command': 'guest-fsfreeze-status',
'returns': 'GuestFsfreezeStatus' }
##
# @guest-fsfreeze-freeze:
#
# Sync and freeze all non-network guest filesystems
#
# Returns: Number of file systems frozen on success
#
# Since: 0.15.0
##
{ 'command': 'guest-fsfreeze-freeze',
'returns': 'int' }
##
# @guest-fsfreeze-thaw:
#
# Unfreeze frozen guest fileystems
#
# Returns: Number of file systems thawed
# If error, -1 (unknown error) or -errno
#
# Since: 0.15.0
##
{ 'command': 'guest-fsfreeze-thaw',
'returns': 'int' }
+22
View File
@@ -0,0 +1,22 @@
# *-*- Mode: Python -*-*
# for testing enums
{ 'enum': 'EnumOne',
'data': [ 'value1', 'value2', 'value3' ] }
{ 'type': 'NestedEnumsOne',
'data': { 'enum1': 'EnumOne', '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
# for testing nested structs
{ 'type': 'UserDefOne',
'data': { 'integer': 'int', 'string': 'str' } }
{ 'type': 'UserDefTwo',
'data': { 'string': 'str',
'dict': { 'string': 'str',
'dict': { 'userdef': 'UserDefOne', 'string': 'str' },
'*dict2': { 'userdef': 'UserDefOne', 'string': 'str' } } } }
# testing commands
{ 'command': 'user_def_cmd', 'data': {} }
{ 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} }
{ 'command': 'user_def_cmd2', 'data': {'ud1a': 'UserDefOne', 'ud1b': 'UserDefOne'}, 'returns': 'UserDefTwo' }
+147
View File
@@ -0,0 +1,147 @@
/*
* Dealloc Visitor
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Michael Roth <mdroth@linux.vnet.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qapi-dealloc-visitor.h"
#include "qemu-queue.h"
#include "qemu-common.h"
#include "qemu-objects.h"
typedef struct StackEntry
{
void *value;
QTAILQ_ENTRY(StackEntry) node;
} StackEntry;
struct QapiDeallocVisitor
{
Visitor visitor;
QTAILQ_HEAD(, StackEntry) stack;
};
static QapiDeallocVisitor *to_qov(Visitor *v)
{
return container_of(v, QapiDeallocVisitor, visitor);
}
static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value)
{
StackEntry *e = qemu_mallocz(sizeof(*e));
e->value = value;
QTAILQ_INSERT_HEAD(&qov->stack, e, node);
}
static void *qapi_dealloc_pop(QapiDeallocVisitor *qov)
{
StackEntry *e = QTAILQ_FIRST(&qov->stack);
QObject *value;
QTAILQ_REMOVE(&qov->stack, e, node);
value = e->value;
qemu_free(e);
return value;
}
static void qapi_dealloc_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t unused,
Error **errp)
{
QapiDeallocVisitor *qov = to_qov(v);
qapi_dealloc_push(qov, obj);
}
static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
{
QapiDeallocVisitor *qov = to_qov(v);
void **obj = qapi_dealloc_pop(qov);
if (obj) {
qemu_free(*obj);
}
}
static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
{
}
static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **list,
Error **errp)
{
GenericList *retval = *list;
qemu_free(retval->value);
*list = retval->next;
return retval;
}
static void qapi_dealloc_end_list(Visitor *v, Error **errp)
{
}
static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
Error **errp)
{
if (obj) {
qemu_free(*obj);
}
}
static void qapi_dealloc_type_int(Visitor *v, int64_t *obj, const char *name,
Error **errp)
{
}
static void qapi_dealloc_type_bool(Visitor *v, bool *obj, const char *name,
Error **errp)
{
}
static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name,
Error **errp)
{
}
static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name,
Error **errp)
{
}
Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
{
return &v->visitor;
}
void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *v)
{
qemu_free(v);
}
QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
{
QapiDeallocVisitor *v;
v = qemu_mallocz(sizeof(*v));
v->visitor.start_struct = qapi_dealloc_start_struct;
v->visitor.end_struct = qapi_dealloc_end_struct;
v->visitor.start_list = qapi_dealloc_start_list;
v->visitor.next_list = qapi_dealloc_next_list;
v->visitor.end_list = qapi_dealloc_end_list;
v->visitor.type_enum = qapi_dealloc_type_enum;
v->visitor.type_int = qapi_dealloc_type_int;
v->visitor.type_bool = qapi_dealloc_type_bool;
v->visitor.type_str = qapi_dealloc_type_str;
v->visitor.type_number = qapi_dealloc_type_number;
QTAILQ_INIT(&v->stack);
return v;
}
+26
View File
@@ -0,0 +1,26 @@
/*
* Dealloc Visitor
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Michael Roth <mdroth@linux.vnet.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef QAPI_DEALLOC_VISITOR_H
#define QAPI_DEALLOC_VISITOR_H
#include "qapi-visit-core.h"
typedef struct QapiDeallocVisitor QapiDeallocVisitor;
QapiDeallocVisitor *qapi_dealloc_visitor_new(void);
void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *d);
Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v);
#endif
+20
View File
@@ -0,0 +1,20 @@
/*
* Core Definitions for QAPI-generated Types
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef QAPI_TYPES_CORE_H
#define QAPI_TYPES_CORE_H
#include "qemu-common.h"
#include "error.h"
#endif
+118
View File
@@ -0,0 +1,118 @@
/*
* Core Definitions for QAPI Visitor Classes
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qapi/qapi-visit-core.h"
void visit_start_handle(Visitor *v, void **obj, const char *kind,
const char *name, Error **errp)
{
if (!error_is_set(errp) && v->start_handle) {
v->start_handle(v, obj, kind, name, errp);
}
}
void visit_end_handle(Visitor *v, Error **errp)
{
if (!error_is_set(errp) && v->end_handle) {
v->end_handle(v, errp);
}
}
void visit_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp)
{
if (!error_is_set(errp)) {
v->start_struct(v, obj, kind, name, size, errp);
}
}
void visit_end_struct(Visitor *v, Error **errp)
{
if (!error_is_set(errp)) {
v->end_struct(v, errp);
}
}
void visit_start_list(Visitor *v, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
v->start_list(v, name, errp);
}
}
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp)
{
if (!error_is_set(errp)) {
return v->next_list(v, list, errp);
}
return 0;
}
void visit_end_list(Visitor *v, Error **errp)
{
if (!error_is_set(errp)) {
v->end_list(v, errp);
}
}
void visit_start_optional(Visitor *v, bool *present, const char *name,
Error **errp)
{
if (!error_is_set(errp) && v->start_optional) {
v->start_optional(v, present, name, errp);
}
}
void visit_end_optional(Visitor *v, Error **errp)
{
if (!error_is_set(errp) && v->end_optional) {
v->end_optional(v, errp);
}
}
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
v->type_enum(v, obj, strings, kind, name, errp);
}
}
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
v->type_int(v, obj, name, errp);
}
}
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
v->type_bool(v, obj, name, errp);
}
}
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
v->type_str(v, obj, name, errp);
}
}
void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
{
if (!error_is_set(errp)) {
v->type_number(v, obj, name, errp);
}
}
+76
View File
@@ -0,0 +1,76 @@
/*
* Core Definitions for QAPI Visitor Classes
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef QAPI_VISITOR_CORE_H
#define QAPI_VISITOR_CORE_H
#include "qapi/qapi-types-core.h"
#include <stdlib.h>
typedef struct GenericList
{
void *value;
struct GenericList *next;
} GenericList;
typedef struct Visitor Visitor;
struct Visitor
{
/* Must be set */
void (*start_struct)(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp);
void (*end_struct)(Visitor *v, Error **errp);
void (*start_list)(Visitor *v, const char *name, Error **errp);
GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
void (*end_list)(Visitor *v, Error **errp);
void (*type_enum)(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name, Error **errp);
void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp);
void (*type_number)(Visitor *v, double *obj, const char *name,
Error **errp);
/* May be NULL */
void (*start_optional)(Visitor *v, bool *present, const char *name,
Error **errp);
void (*end_optional)(Visitor *v, Error **errp);
void (*start_handle)(Visitor *v, void **obj, const char *kind,
const char *name, Error **errp);
void (*end_handle)(Visitor *v, Error **errp);
};
void visit_start_handle(Visitor *v, void **obj, const char *kind,
const char *name, Error **errp);
void visit_end_handle(Visitor *v, Error **errp);
void visit_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp);
void visit_end_struct(Visitor *v, Error **errp);
void visit_start_list(Visitor *v, const char *name, Error **errp);
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
void visit_end_list(Visitor *v, Error **errp);
void visit_start_optional(Visitor *v, bool *present, const char *name,
Error **errp);
void visit_end_optional(Visitor *v, Error **errp);
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name, Error **errp);
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
#endif
+41
View File
@@ -0,0 +1,41 @@
/*
* Core Definitions for QAPI/QMP Dispatch
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef QMP_CORE_H
#define QMP_CORE_H
#include "qobject.h"
#include "qdict.h"
#include "error.h"
typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
typedef enum QmpCommandType
{
QCT_NORMAL,
} QmpCommandType;
typedef struct QmpCommand
{
const char *name;
QmpCommandType type;
QmpCommandFunc *fn;
QTAILQ_ENTRY(QmpCommand) node;
} QmpCommand;
void qmp_register_command(const char *name, QmpCommandFunc *fn);
QmpCommand *qmp_find_command(const char *name);
QObject *qmp_dispatch(QObject *request);
#endif
+124
View File
@@ -0,0 +1,124 @@
/*
* Core Definitions for QAPI/QMP Dispatch
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qemu-objects.h"
#include "qapi/qmp-core.h"
#include "json-parser.h"
#include "error.h"
#include "error_int.h"
#include "qerror.h"
static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
{
const QDictEntry *ent;
const char *arg_name;
const QObject *arg_obj;
bool has_exec_key = false;
QDict *dict = NULL;
if (qobject_type(request) != QTYPE_QDICT) {
error_set(errp, QERR_QMP_BAD_INPUT_OBJECT,
"request is not a dictionary");
return NULL;
}
dict = qobject_to_qdict(request);
for (ent = qdict_first(dict); ent;
ent = qdict_next(dict, ent)) {
arg_name = qdict_entry_key(ent);
arg_obj = qdict_entry_value(ent);
if (!strcmp(arg_name, "execute")) {
if (qobject_type(arg_obj) != QTYPE_QSTRING) {
error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
"string");
return NULL;
}
has_exec_key = true;
} else if (strcmp(arg_name, "arguments")) {
error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
return NULL;
}
}
if (!has_exec_key) {
error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
return NULL;
}
return dict;
}
static QObject *do_qmp_dispatch(QObject *request, Error **errp)
{
const char *command;
QDict *args, *dict;
QmpCommand *cmd;
QObject *ret = NULL;
dict = qmp_dispatch_check_obj(request, errp);
if (!dict || error_is_set(errp)) {
return NULL;
}
command = qdict_get_str(dict, "execute");
cmd = qmp_find_command(command);
if (cmd == NULL) {
error_set(errp, QERR_COMMAND_NOT_FOUND, command);
return NULL;
}
if (!qdict_haskey(dict, "arguments")) {
args = qdict_new();
} else {
args = qdict_get_qdict(dict, "arguments");
QINCREF(args);
}
switch (cmd->type) {
case QCT_NORMAL:
cmd->fn(args, &ret, errp);
if (!error_is_set(errp) && ret == NULL) {
ret = QOBJECT(qdict_new());
}
break;
}
QDECREF(args);
return ret;
}
QObject *qmp_dispatch(QObject *request)
{
Error *err = NULL;
QObject *ret;
QDict *rsp;
ret = do_qmp_dispatch(request, &err);
rsp = qdict_new();
if (err) {
qdict_put_obj(rsp, "error", error_get_qobject(err));
error_free(err);
} else if (ret) {
qdict_put_obj(rsp, "return", ret);
} else {
QDECREF(rsp);
return NULL;
}
return QOBJECT(rsp);
}
+301
View File
@@ -0,0 +1,301 @@
/*
* Input Visitor
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qmp-input-visitor.h"
#include "qemu-queue.h"
#include "qemu-common.h"
#include "qemu-objects.h"
#include "qerror.h"
#define QIV_STACK_SIZE 1024
typedef struct StackObject
{
const QObject *obj;
const QListEntry *entry;
} StackObject;
struct QmpInputVisitor
{
Visitor visitor;
QObject *obj;
StackObject stack[QIV_STACK_SIZE];
int nb_stack;
};
static QmpInputVisitor *to_qiv(Visitor *v)
{
return container_of(v, QmpInputVisitor, visitor);
}
static const QObject *qmp_input_get_object(QmpInputVisitor *qiv,
const char *name)
{
const QObject *qobj;
if (qiv->nb_stack == 0) {
qobj = qiv->obj;
} else {
qobj = qiv->stack[qiv->nb_stack - 1].obj;
}
if (name && qobject_type(qobj) == QTYPE_QDICT) {
return qdict_get(qobject_to_qdict(qobj), name);
} else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) {
return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
}
return qobj;
}
static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp)
{
qiv->stack[qiv->nb_stack].obj = obj;
if (qobject_type(obj) == QTYPE_QLIST) {
qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj));
}
qiv->nb_stack++;
if (qiv->nb_stack >= QIV_STACK_SIZE) {
error_set(errp, QERR_BUFFER_OVERRUN);
return;
}
}
static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
{
qiv->nb_stack--;
if (qiv->nb_stack < 0) {
error_set(errp, QERR_BUFFER_OVERRUN);
return;
}
}
static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
const char *name, size_t size, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
const QObject *qobj = qmp_input_get_object(qiv, name);
if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"QDict");
return;
}
qmp_input_push(qiv, qobj, errp);
if (error_is_set(errp)) {
return;
}
if (obj) {
*obj = qemu_mallocz(size);
}
}
static void qmp_input_end_struct(Visitor *v, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
qmp_input_pop(qiv, errp);
}
static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
const QObject *qobj = qmp_input_get_object(qiv, name);
if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"list");
return;
}
qmp_input_push(qiv, qobj, errp);
}
static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
GenericList *entry;
StackObject *so = &qiv->stack[qiv->nb_stack - 1];
if (so->entry == NULL) {
return NULL;
}
entry = qemu_mallocz(sizeof(*entry));
if (*list) {
so->entry = qlist_next(so->entry);
if (so->entry == NULL) {
qemu_free(entry);
return NULL;
}
(*list)->next = entry;
}
*list = entry;
return entry;
}
static void qmp_input_end_list(Visitor *v, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
qmp_input_pop(qiv, errp);
}
static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
const QObject *qobj = qmp_input_get_object(qiv, name);
if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"integer");
return;
}
*obj = qint_get_int(qobject_to_qint(qobj));
}
static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
const QObject *qobj = qmp_input_get_object(qiv, name);
if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"boolean");
return;
}
*obj = qbool_get_int(qobject_to_qbool(qobj));
}
static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
const QObject *qobj = qmp_input_get_object(qiv, name);
if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"string");
return;
}
*obj = qemu_strdup(qstring_get_str(qobject_to_qstring(qobj)));
}
static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
const QObject *qobj = qmp_input_get_object(qiv, name);
if (!qobj || qobject_type(qobj) != QTYPE_QFLOAT) {
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"double");
return;
}
*obj = qfloat_get_double(qobject_to_qfloat(qobj));
}
static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[],
const char *kind, const char *name,
Error **errp)
{
int64_t value = 0;
char *enum_str;
assert(strings);
qmp_input_type_str(v, &enum_str, name, errp);
if (error_is_set(errp)) {
return;
}
while (strings[value] != NULL) {
if (strcmp(strings[value], enum_str) == 0) {
break;
}
value++;
}
if (strings[value] == NULL) {
error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
return;
}
*obj = value;
}
static void qmp_input_start_optional(Visitor *v, bool *present,
const char *name, Error **errp)
{
QmpInputVisitor *qiv = to_qiv(v);
const QObject *qobj = qmp_input_get_object(qiv, name);
if (!qobj) {
*present = false;
return;
}
*present = true;
}
static void qmp_input_end_optional(Visitor *v, Error **errp)
{
}
Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
{
return &v->visitor;
}
void qmp_input_visitor_cleanup(QmpInputVisitor *v)
{
qobject_decref(v->obj);
qemu_free(v);
}
QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
{
QmpInputVisitor *v;
v = qemu_mallocz(sizeof(*v));
v->visitor.start_struct = qmp_input_start_struct;
v->visitor.end_struct = qmp_input_end_struct;
v->visitor.start_list = qmp_input_start_list;
v->visitor.next_list = qmp_input_next_list;
v->visitor.end_list = qmp_input_end_list;
v->visitor.type_enum = qmp_input_type_enum;
v->visitor.type_int = qmp_input_type_int;
v->visitor.type_bool = qmp_input_type_bool;
v->visitor.type_str = qmp_input_type_str;
v->visitor.type_number = qmp_input_type_number;
v->visitor.start_optional = qmp_input_start_optional;
v->visitor.end_optional = qmp_input_end_optional;
v->obj = obj;
qobject_incref(v->obj);
return v;
}

Some files were not shown because too many files have changed in this diff Show More