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