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