2 * QMP commands related to the monitor (common to sysemu and tools)
4 * Copyright (c) 2003-2004 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "qemu/osdep.h"
27 #include "monitor-internal.h"
28 #include "qemu-version.h"
29 #include "qapi/compat-policy.h"
30 #include "qapi/error.h"
31 #include "qapi/qapi-commands-control.h"
32 #include "qapi/qapi-commands-introspect.h"
33 #include "qapi/qapi-emit-events.h"
34 #include "qapi/qapi-introspect.h"
35 #include "qapi/qapi-visit-introspect.h"
36 #include "qapi/qobject-input-visitor.h"
39 * Accept QMP capabilities in @list for @mon.
40 * On success, set mon->qmp.capab[], and return true.
41 * On error, set @errp, and return false.
43 static bool qmp_caps_accept(MonitorQMP
*mon
, QMPCapabilityList
*list
,
46 GString
*unavailable
= NULL
;
47 bool capab
[QMP_CAPABILITY__MAX
];
49 memset(capab
, 0, sizeof(capab
));
51 for (; list
; list
= list
->next
) {
52 if (!mon
->capab_offered
[list
->value
]) {
54 unavailable
= g_string_new(QMPCapability_str(list
->value
));
56 g_string_append_printf(unavailable
, ", %s",
57 QMPCapability_str(list
->value
));
60 capab
[list
->value
] = true;
64 error_setg(errp
, "Capability %s not available", unavailable
->str
);
65 g_string_free(unavailable
, true);
69 memcpy(mon
->capab
, capab
, sizeof(capab
));
73 void qmp_qmp_capabilities(bool has_enable
, QMPCapabilityList
*enable
,
76 Monitor
*cur_mon
= monitor_cur();
79 assert(monitor_is_qmp(cur_mon
));
80 mon
= container_of(cur_mon
, MonitorQMP
, common
);
82 if (mon
->commands
== &qmp_commands
) {
83 error_set(errp
, ERROR_CLASS_COMMAND_NOT_FOUND
,
84 "Capabilities negotiation is already complete, command "
89 if (!qmp_caps_accept(mon
, enable
, errp
)) {
93 mon
->commands
= &qmp_commands
;
96 VersionInfo
*qmp_query_version(Error
**errp
)
98 VersionInfo
*info
= g_new0(VersionInfo
, 1);
100 info
->qemu
= g_new0(VersionTriple
, 1);
101 info
->qemu
->major
= QEMU_VERSION_MAJOR
;
102 info
->qemu
->minor
= QEMU_VERSION_MINOR
;
103 info
->qemu
->micro
= QEMU_VERSION_MICRO
;
104 info
->package
= g_strdup(QEMU_PKGVERSION
);
109 static void query_commands_cb(const QmpCommand
*cmd
, void *opaque
)
112 CommandInfoList
**list
= opaque
;
118 info
= g_malloc0(sizeof(*info
));
119 info
->name
= g_strdup(cmd
->name
);
120 QAPI_LIST_PREPEND(*list
, info
);
123 CommandInfoList
*qmp_query_commands(Error
**errp
)
125 CommandInfoList
*list
= NULL
;
126 Monitor
*cur_mon
= monitor_cur();
129 assert(monitor_is_qmp(cur_mon
));
130 mon
= container_of(cur_mon
, MonitorQMP
, common
);
132 qmp_for_each_command(mon
->commands
, query_commands_cb
, &list
);
137 static void *split_off_generic_list(void *list
,
138 bool (*splitp
)(void *elt
),
141 GenericList
*keep
= NULL
, **keep_tailp
= &keep
;
142 GenericList
*split
= NULL
, **split_tailp
= &split
;
145 for (tail
= list
; tail
; tail
= tail
->next
) {
148 split_tailp
= &tail
->next
;
151 keep_tailp
= &tail
->next
;
155 *keep_tailp
= *split_tailp
= NULL
;
160 static bool is_in(const char *s
, strList
*list
)
164 for (tail
= list
; tail
; tail
= tail
->next
) {
165 if (!strcmp(tail
->value
, s
)) {
172 static bool is_entity_deprecated(void *link
)
174 return is_in("deprecated", ((SchemaInfoList
*)link
)->value
->features
);
177 static bool is_member_deprecated(void *link
)
179 return is_in("deprecated",
180 ((SchemaInfoObjectMemberList
*)link
)->value
->features
);
183 static SchemaInfoList
*zap_deprecated(SchemaInfoList
*schema
)
186 SchemaInfoList
*tail
;
189 schema
= split_off_generic_list(schema
, is_entity_deprecated
, &to_zap
);
190 qapi_free_SchemaInfoList(to_zap
);
192 for (tail
= schema
; tail
; tail
= tail
->next
) {
194 if (ent
->meta_type
== SCHEMA_META_TYPE_OBJECT
) {
195 ent
->u
.object
.members
196 = split_off_generic_list(ent
->u
.object
.members
,
197 is_member_deprecated
, &to_zap
);
198 qapi_free_SchemaInfoObjectMemberList(to_zap
);
205 SchemaInfoList
*qmp_query_qmp_schema(Error
**errp
)
207 QObject
*obj
= qobject_from_qlit(&qmp_schema_qlit
);
208 Visitor
*v
= qobject_input_visitor_new(obj
);
209 SchemaInfoList
*schema
= NULL
;
211 /* test_visitor_in_qmp_introspect() ensures this can't fail */
212 visit_type_SchemaInfoList(v
, NULL
, &schema
, &error_abort
);
218 if (compat_policy
.deprecated_output
== COMPAT_POLICY_OUTPUT_HIDE
) {
219 return zap_deprecated(schema
);