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-introspect.h"
34 #include "qapi/qapi-visit-introspect.h"
35 #include "qapi/qobject-input-visitor.h"
38 * Accept QMP capabilities in @list for @mon.
39 * On success, set mon->qmp.capab[], and return true.
40 * On error, set @errp, and return false.
42 static bool qmp_caps_accept(MonitorQMP
*mon
, QMPCapabilityList
*list
,
45 GString
*unavailable
= NULL
;
46 bool capab
[QMP_CAPABILITY__MAX
];
48 memset(capab
, 0, sizeof(capab
));
50 for (; list
; list
= list
->next
) {
51 if (!mon
->capab_offered
[list
->value
]) {
53 unavailable
= g_string_new(QMPCapability_str(list
->value
));
55 g_string_append_printf(unavailable
, ", %s",
56 QMPCapability_str(list
->value
));
59 capab
[list
->value
] = true;
63 error_setg(errp
, "Capability %s not available", unavailable
->str
);
64 g_string_free(unavailable
, true);
68 memcpy(mon
->capab
, capab
, sizeof(capab
));
72 void qmp_qmp_capabilities(bool has_enable
, QMPCapabilityList
*enable
,
75 Monitor
*cur_mon
= monitor_cur();
78 assert(monitor_is_qmp(cur_mon
));
79 mon
= container_of(cur_mon
, MonitorQMP
, common
);
81 if (mon
->commands
== &qmp_commands
) {
82 error_set(errp
, ERROR_CLASS_COMMAND_NOT_FOUND
,
83 "Capabilities negotiation is already complete, command "
88 if (!qmp_caps_accept(mon
, enable
, errp
)) {
92 mon
->commands
= &qmp_commands
;
95 VersionInfo
*qmp_query_version(Error
**errp
)
97 VersionInfo
*info
= g_new0(VersionInfo
, 1);
99 info
->qemu
= g_new0(VersionTriple
, 1);
100 info
->qemu
->major
= QEMU_VERSION_MAJOR
;
101 info
->qemu
->minor
= QEMU_VERSION_MINOR
;
102 info
->qemu
->micro
= QEMU_VERSION_MICRO
;
103 info
->package
= g_strdup(QEMU_PKGVERSION
);
108 static void query_commands_cb(const QmpCommand
*cmd
, void *opaque
)
111 CommandInfoList
**list
= opaque
;
117 info
= g_malloc0(sizeof(*info
));
118 info
->name
= g_strdup(cmd
->name
);
119 QAPI_LIST_PREPEND(*list
, info
);
122 CommandInfoList
*qmp_query_commands(Error
**errp
)
124 CommandInfoList
*list
= NULL
;
125 Monitor
*cur_mon
= monitor_cur();
128 assert(monitor_is_qmp(cur_mon
));
129 mon
= container_of(cur_mon
, MonitorQMP
, common
);
131 qmp_for_each_command(mon
->commands
, query_commands_cb
, &list
);
136 static void *split_off_generic_list(void *list
,
137 bool (*splitp
)(void *elt
),
140 GenericList
*keep
= NULL
, **keep_tailp
= &keep
;
141 GenericList
*split
= NULL
, **split_tailp
= &split
;
144 for (tail
= list
; tail
; tail
= tail
->next
) {
147 split_tailp
= &tail
->next
;
150 keep_tailp
= &tail
->next
;
154 *keep_tailp
= *split_tailp
= NULL
;
159 static bool is_in(const char *s
, strList
*list
)
163 for (tail
= list
; tail
; tail
= tail
->next
) {
164 if (!strcmp(tail
->value
, s
)) {
171 static bool is_entity_deprecated(void *link
)
173 return is_in("deprecated", ((SchemaInfoList
*)link
)->value
->features
);
176 static bool is_member_deprecated(void *link
)
178 return is_in("deprecated",
179 ((SchemaInfoObjectMemberList
*)link
)->value
->features
);
182 static SchemaInfoList
*zap_deprecated(SchemaInfoList
*schema
)
185 SchemaInfoList
*tail
;
188 schema
= split_off_generic_list(schema
, is_entity_deprecated
, &to_zap
);
189 qapi_free_SchemaInfoList(to_zap
);
191 for (tail
= schema
; tail
; tail
= tail
->next
) {
193 if (ent
->meta_type
== SCHEMA_META_TYPE_OBJECT
) {
194 ent
->u
.object
.members
195 = split_off_generic_list(ent
->u
.object
.members
,
196 is_member_deprecated
, &to_zap
);
197 qapi_free_SchemaInfoObjectMemberList(to_zap
);
204 SchemaInfoList
*qmp_query_qmp_schema(Error
**errp
)
206 QObject
*obj
= qobject_from_qlit(&qmp_schema_qlit
);
207 Visitor
*v
= qobject_input_visitor_new(obj
);
208 SchemaInfoList
*schema
= NULL
;
210 /* test_visitor_in_qmp_introspect() ensures this can't fail */
211 visit_type_SchemaInfoList(v
, NULL
, &schema
, &error_abort
);
217 if (compat_policy
.deprecated_output
== COMPAT_POLICY_OUTPUT_HIDE
) {
218 return zap_deprecated(schema
);