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; 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 visit_check_struct(v, &local_err); 67 if (local_err) { 68 goto out_visit; 69 } 70 71 obj = user_creatable_add_type(type, id, pdict, v, &local_err); 72 73 out_visit: 74 visit_end_struct(v, NULL); 75 76 out: 77 QDECREF(pdict); 78 g_free(id); 79 g_free(type); 80 if (local_err) { 81 error_propagate(errp, local_err); 82 object_unref(obj); 83 return NULL; 84 } 85 return obj; 86 } 87 88 89 Object *user_creatable_add_type(const char *type, const char *id, 90 const QDict *qdict, 91 Visitor *v, Error **errp) 92 { 93 Object *obj; 94 ObjectClass *klass; 95 const QDictEntry *e; 96 Error *local_err = NULL; 97 98 klass = object_class_by_name(type); 99 if (!klass) { 100 error_setg(errp, "invalid object type: %s", type); 101 return NULL; 102 } 103 104 if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { 105 error_setg(errp, "object type '%s' isn't supported by object-add", 106 type); 107 return NULL; 108 } 109 110 if (object_class_is_abstract(klass)) { 111 error_setg(errp, "object type '%s' is abstract", type); 112 return NULL; 113 } 114 115 assert(qdict); 116 obj = object_new(type); 117 visit_start_struct(v, NULL, NULL, 0, &local_err); 118 if (local_err) { 119 goto out; 120 } 121 for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { 122 object_property_set(obj, v, e->key, &local_err); 123 if (local_err) { 124 break; 125 } 126 } 127 if (!local_err) { 128 visit_check_struct(v, &local_err); 129 } 130 visit_end_struct(v, NULL); 131 if (local_err) { 132 goto out; 133 } 134 135 object_property_add_child(object_get_objects_root(), 136 id, obj, &local_err); 137 if (local_err) { 138 goto out; 139 } 140 141 user_creatable_complete(obj, &local_err); 142 if (local_err) { 143 object_property_del(object_get_objects_root(), 144 id, &error_abort); 145 goto out; 146 } 147 out: 148 if (local_err) { 149 error_propagate(errp, local_err); 150 object_unref(obj); 151 return NULL; 152 } 153 return obj; 154 } 155 156 157 Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) 158 { 159 Visitor *v; 160 QDict *pdict; 161 Object *obj = NULL; 162 163 v = opts_visitor_new(opts); 164 pdict = qemu_opts_to_qdict(opts, NULL); 165 166 obj = user_creatable_add(pdict, v, errp); 167 visit_free(v); 168 QDECREF(pdict); 169 return obj; 170 } 171 172 173 int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp) 174 { 175 bool (*type_predicate)(const char *) = opaque; 176 Object *obj = NULL; 177 Error *err = NULL; 178 const char *type; 179 180 type = qemu_opt_get(opts, "qom-type"); 181 if (type && type_predicate && 182 !type_predicate(type)) { 183 return 0; 184 } 185 186 obj = user_creatable_add_opts(opts, &err); 187 if (!obj) { 188 error_report_err(err); 189 return -1; 190 } 191 object_unref(obj); 192 return 0; 193 } 194 195 196 void user_creatable_del(const char *id, Error **errp) 197 { 198 Object *container; 199 Object *obj; 200 201 container = object_get_objects_root(); 202 obj = object_resolve_path_component(container, id); 203 if (!obj) { 204 error_setg(errp, "object '%s' not found", id); 205 return; 206 } 207 208 if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { 209 error_setg(errp, "object '%s' is in use, can not be deleted", id); 210 return; 211 } 212 object_unparent(obj); 213 } 214 215 static void register_types(void) 216 { 217 static const TypeInfo uc_interface_info = { 218 .name = TYPE_USER_CREATABLE, 219 .parent = TYPE_INTERFACE, 220 .class_size = sizeof(UserCreatableClass), 221 }; 222 223 type_register_static(&uc_interface_info); 224 } 225 226 type_init(register_types) 227