xref: /qemu/qom/object_interfaces.c (revision 8d86ada2)
1 #include "qemu/osdep.h"
2 #include "qom/object_interfaces.h"
3 #include "qemu/module.h"
4 #include "qapi-visit.h"
5 #include "qapi/qmp-output-visitor.h"
6 #include "qapi/opts-visitor.h"
7 
8 void user_creatable_complete(Object *obj, Error **errp)
9 {
10 
11     UserCreatableClass *ucc;
12     UserCreatable *uc =
13         (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
14 
15     if (!uc) {
16         return;
17     }
18 
19     ucc = USER_CREATABLE_GET_CLASS(uc);
20     if (ucc->complete) {
21         ucc->complete(uc, errp);
22     }
23 }
24 
25 bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp)
26 {
27 
28     UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
29 
30     if (ucc->can_be_deleted) {
31         return ucc->can_be_deleted(uc, errp);
32     } else {
33         return true;
34     }
35 }
36 
37 
38 Object *user_creatable_add(const QDict *qdict,
39                            Visitor *v, Error **errp)
40 {
41     char *type = NULL;
42     char *id = NULL;
43     Object *obj = NULL;
44     Error *local_err = NULL, *end_err = NULL;
45     QDict *pdict;
46 
47     pdict = qdict_clone_shallow(qdict);
48 
49     visit_start_struct(v, NULL, NULL, 0, &local_err);
50     if (local_err) {
51         goto out;
52     }
53 
54     qdict_del(pdict, "qom-type");
55     visit_type_str(v, "qom-type", &type, &local_err);
56     if (local_err) {
57         goto out_visit;
58     }
59 
60     qdict_del(pdict, "id");
61     visit_type_str(v, "id", &id, &local_err);
62     if (local_err) {
63         goto out_visit;
64     }
65 
66     obj = user_creatable_add_type(type, id, pdict, v, &local_err);
67     if (local_err) {
68         goto out_visit;
69     }
70 
71  out_visit:
72     visit_end_struct(v, &end_err);
73     if (end_err) {
74         error_propagate(&local_err, end_err);
75         if (obj) {
76             user_creatable_del(id, NULL);
77         }
78         goto out;
79     }
80 
81 out:
82     QDECREF(pdict);
83     g_free(id);
84     g_free(type);
85     if (local_err) {
86         error_propagate(errp, local_err);
87         object_unref(obj);
88         return NULL;
89     }
90     return obj;
91 }
92 
93 
94 Object *user_creatable_add_type(const char *type, const char *id,
95                                 const QDict *qdict,
96                                 Visitor *v, Error **errp)
97 {
98     Object *obj;
99     ObjectClass *klass;
100     const QDictEntry *e;
101     Error *local_err = NULL;
102 
103     klass = object_class_by_name(type);
104     if (!klass) {
105         error_setg(errp, "invalid object type: %s", type);
106         return NULL;
107     }
108 
109     if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
110         error_setg(errp, "object type '%s' isn't supported by object-add",
111                    type);
112         return NULL;
113     }
114 
115     if (object_class_is_abstract(klass)) {
116         error_setg(errp, "object type '%s' is abstract", type);
117         return NULL;
118     }
119 
120     obj = object_new(type);
121     if (qdict) {
122         for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
123             object_property_set(obj, v, e->key, &local_err);
124             if (local_err) {
125                 goto out;
126             }
127         }
128     }
129 
130     object_property_add_child(object_get_objects_root(),
131                               id, obj, &local_err);
132     if (local_err) {
133         goto out;
134     }
135 
136     user_creatable_complete(obj, &local_err);
137     if (local_err) {
138         object_property_del(object_get_objects_root(),
139                             id, &error_abort);
140         goto out;
141     }
142 out:
143     if (local_err) {
144         error_propagate(errp, local_err);
145         object_unref(obj);
146         return NULL;
147     }
148     return obj;
149 }
150 
151 
152 Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
153 {
154     OptsVisitor *ov;
155     QDict *pdict;
156     Object *obj = NULL;
157 
158     ov = opts_visitor_new(opts);
159     pdict = qemu_opts_to_qdict(opts, NULL);
160 
161     obj = user_creatable_add(pdict, opts_get_visitor(ov), errp);
162     opts_visitor_cleanup(ov);
163     QDECREF(pdict);
164     return obj;
165 }
166 
167 
168 int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
169 {
170     bool (*type_predicate)(const char *) = opaque;
171     Object *obj = NULL;
172     const char *type;
173 
174     type = qemu_opt_get(opts, "qom-type");
175     if (type && type_predicate &&
176         !type_predicate(type)) {
177         return 0;
178     }
179 
180     obj = user_creatable_add_opts(opts, errp);
181     if (!obj) {
182         return -1;
183     }
184     object_unref(obj);
185     return 0;
186 }
187 
188 
189 void user_creatable_del(const char *id, Error **errp)
190 {
191     Object *container;
192     Object *obj;
193 
194     container = object_get_objects_root();
195     obj = object_resolve_path_component(container, id);
196     if (!obj) {
197         error_setg(errp, "object '%s' not found", id);
198         return;
199     }
200 
201     if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) {
202         error_setg(errp, "object '%s' is in use, can not be deleted", id);
203         return;
204     }
205     object_unparent(obj);
206 }
207 
208 static void register_types(void)
209 {
210     static const TypeInfo uc_interface_info = {
211         .name          = TYPE_USER_CREATABLE,
212         .parent        = TYPE_INTERFACE,
213         .class_size = sizeof(UserCreatableClass),
214     };
215 
216     type_register_static(&uc_interface_info);
217 }
218 
219 type_init(register_types)
220