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