master
c 220 lines 5.78 KB
Raw
1 /*
2 * HMP commands related to QOM
3 *
4 * This work is licensed under the terms of the GNU GPL, version 2 or
5 * later. See the COPYING file in the top-level directory.
6 */
7
8 #include "qemu/osdep.h"
9 #include "hw/core/qdev.h"
10 #include "monitor/hmp.h"
11 #include "monitor/hmp-completion.h"
12 #include "monitor/monitor.h"
13 #include "qapi/error.h"
14 #include "qapi/qapi-commands-qom.h"
15 #include "qobject/qdict.h"
16 #include "qobject/qjson.h"
17 #include "qemu/readline.h"
18 #include "qom/object.h"
19 #include "qom/object_interfaces.h"
20
21 void hmp_qom_list(MonitorHMP *hmp, const QDict *qdict)
22 {
23 const char *path = qdict_get_try_str(qdict, "path");
24 ObjectPropertyInfoList *list;
25 Error *err = NULL;
26
27 if (path == NULL) {
28 monitor_hmp_printf(hmp, "/\n");
29 return;
30 }
31
32 list = qmp_qom_list(path, &err);
33 if (err == NULL) {
34 ObjectPropertyInfoList *start = list;
35 while (list != NULL) {
36 ObjectPropertyInfo *value = list->value;
37
38 monitor_hmp_printf(hmp, "%s (%s)\n",
39 value->name, value->type);
40 list = list->next;
41 }
42 qapi_free_ObjectPropertyInfoList(start);
43 }
44 hmp_handle_error(hmp, err);
45 }
46
47 void hmp_qom_set(MonitorHMP *hmp, const QDict *qdict)
48 {
49 const bool json = qdict_get_try_bool(qdict, "json", false);
50 const char *path = qdict_get_str(qdict, "path");
51 const char *property = qdict_get_str(qdict, "property");
52 const char *value = qdict_get_str(qdict, "value");
53 Error *err = NULL;
54
55 if (!json) {
56 Object *obj = object_resolve_path(path, NULL);
57
58 if (!obj) {
59 error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND,
60 "Device '%s' not found", path);
61 } else {
62 object_property_parse(obj, property, value, &err);
63 }
64 } else {
65 QObject *obj = qobject_from_json(value, &err);
66
67 if (!err) {
68 qmp_qom_set(path, property, obj, &err);
69 }
70 }
71
72 hmp_handle_error(hmp, err);
73 }
74
75 void hmp_qom_get(MonitorHMP *hmp, const QDict *qdict)
76 {
77 const char *path = qdict_get_str(qdict, "path");
78 const char *property = qdict_get_str(qdict, "property");
79 Error *err = NULL;
80 QObject *obj = qmp_qom_get(path, property, &err);
81
82 if (err == NULL) {
83 GString *str = qobject_to_json_pretty(obj, true);
84 monitor_hmp_printf(hmp, "%s\n", str->str);
85 g_string_free(str, true);
86 }
87
88 qobject_unref(obj);
89 hmp_handle_error(hmp, err);
90 }
91
92 typedef struct QOMCompositionState {
93 Monitor *mon;
94 int indent;
95 } QOMCompositionState;
96
97 static void print_qom_composition(MonitorHMP *hmp, Object *obj, int indent);
98
99 static int qom_composition_compare(const void *a, const void *b)
100 {
101 return g_strcmp0(object_get_canonical_path_component(*(Object **)a),
102 object_get_canonical_path_component(*(Object **)b));
103 }
104
105 static int insert_qom_composition_child(Object *obj, void *opaque)
106 {
107 g_array_append_val(opaque, obj);
108 return 0;
109 }
110
111 static void print_qom_composition(MonitorHMP *hmp, Object *obj, int indent)
112 {
113 GArray *children = g_array_new(false, false, sizeof(Object *));
114 const char *name;
115 int i;
116
117 if (obj == object_get_root()) {
118 name = "";
119 } else {
120 name = object_get_canonical_path_component(obj);
121 }
122 monitor_hmp_printf(hmp, "%*s/%s (%s)\n", indent, "", name,
123 object_get_typename(obj));
124
125 object_child_foreach(obj, insert_qom_composition_child, children);
126 g_array_sort(children, qom_composition_compare);
127
128 for (i = 0; i < children->len; i++) {
129 print_qom_composition(hmp, g_array_index(children, Object *, i),
130 indent + 2);
131 }
132 g_array_free(children, TRUE);
133 }
134
135 void hmp_info_qom_tree(MonitorHMP *hmp, const QDict *dict)
136 {
137 const char *path = qdict_get_try_str(dict, "path");
138 Object *obj;
139 bool ambiguous = false;
140
141 if (path) {
142 obj = object_resolve_path(path, &ambiguous);
143 if (!obj) {
144 monitor_hmp_printf(hmp, "Path '%s' could not be resolved.\n", path);
145 return;
146 }
147 if (ambiguous) {
148 monitor_hmp_printf(hmp, "Warning: Path '%s' is ambiguous.\n", path);
149 return;
150 }
151 } else {
152 obj = qdev_get_machine();
153 }
154 print_qom_composition(hmp, obj, 0);
155 }
156
157 void hmp_object_add(MonitorHMP *hmp, const QDict *qdict)
158 {
159 const char *options = qdict_get_str(qdict, "object");
160 Error *err = NULL;
161
162 user_creatable_add_from_str(options, &err);
163 hmp_handle_error(hmp, err);
164 }
165
166 void hmp_object_del(MonitorHMP *hmp, const QDict *qdict)
167 {
168 const char *id = qdict_get_str(qdict, "id");
169 Error *err = NULL;
170
171 user_creatable_del(id, &err);
172 hmp_handle_error(hmp, err);
173 }
174
175 void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
176 {
177 GSList *list, *elt;
178 size_t len;
179
180 if (nb_args != 2) {
181 return;
182 }
183
184 len = strlen(str);
185 readline_set_completion_index(rs, len);
186 list = elt = object_class_get_list(TYPE_USER_CREATABLE, false);
187 while (elt) {
188 const char *name;
189
190 name = object_class_get_name(OBJECT_CLASS(elt->data));
191 if (strcmp(name, TYPE_USER_CREATABLE)) {
192 readline_add_completion_of(rs, str, name);
193 }
194 elt = elt->next;
195 }
196 g_slist_free(list);
197 }
198
199 void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
200 {
201 ObjectPropertyInfoList *list, *start;
202 size_t len;
203
204 if (nb_args != 2) {
205 return;
206 }
207 len = strlen(str);
208 readline_set_completion_index(rs, len);
209
210 start = list = qmp_qom_list("/objects", NULL);
211 while (list) {
212 ObjectPropertyInfo *info = list->value;
213
214 if (!strncmp(info->type, "child<", 5)) {
215 readline_add_completion_of(rs, str, info->name);
216 }
217 list = list->next;
218 }
219 qapi_free_ObjectPropertyInfoList(start);
220 }