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 9 void 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 26 bool 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 39 Object *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 82 out: 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 95 Object *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 } 143 out: 144 if (local_err) { 145 error_propagate(errp, local_err); 146 object_unref(obj); 147 return NULL; 148 } 149 return obj; 150 } 151 152 153 Object *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 169 int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp) 170 { 171 bool (*type_predicate)(const char *) = opaque; 172 Object *obj = NULL; 173 const char *type; 174 175 type = qemu_opt_get(opts, "qom-type"); 176 if (type && type_predicate && 177 !type_predicate(type)) { 178 return 0; 179 } 180 181 obj = user_creatable_add_opts(opts, errp); 182 if (!obj) { 183 return -1; 184 } 185 object_unref(obj); 186 return 0; 187 } 188 189 190 void user_creatable_del(const char *id, Error **errp) 191 { 192 Object *container; 193 Object *obj; 194 195 container = object_get_objects_root(); 196 obj = object_resolve_path_component(container, id); 197 if (!obj) { 198 error_setg(errp, "object '%s' not found", id); 199 return; 200 } 201 202 if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { 203 error_setg(errp, "object '%s' is in use, can not be deleted", id); 204 return; 205 } 206 object_unparent(obj); 207 } 208 209 static void register_types(void) 210 { 211 static const TypeInfo uc_interface_info = { 212 .name = TYPE_USER_CREATABLE, 213 .parent = TYPE_INTERFACE, 214 .class_size = sizeof(UserCreatableClass), 215 }; 216 217 type_register_static(&uc_interface_info); 218 } 219 220 type_init(register_types) 221