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/opts-visitor.h" 7 #include "qemu/config-file.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) 27 { 28 29 UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc); 30 31 if (ucc->can_be_deleted) { 32 return ucc->can_be_deleted(uc); 33 } else { 34 return true; 35 } 36 } 37 38 Object *user_creatable_add_type(const char *type, const char *id, 39 const QDict *qdict, 40 Visitor *v, Error **errp) 41 { 42 Object *obj; 43 ObjectClass *klass; 44 const QDictEntry *e; 45 Error *local_err = NULL; 46 47 klass = object_class_by_name(type); 48 if (!klass) { 49 error_setg(errp, "invalid object type: %s", type); 50 return NULL; 51 } 52 53 if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { 54 error_setg(errp, "object type '%s' isn't supported by object-add", 55 type); 56 return NULL; 57 } 58 59 if (object_class_is_abstract(klass)) { 60 error_setg(errp, "object type '%s' is abstract", type); 61 return NULL; 62 } 63 64 assert(qdict); 65 obj = object_new(type); 66 if (object_property_find(obj, "id", NULL)) { 67 object_property_set_str(obj, id, "id", &local_err); 68 if (local_err) { 69 goto out; 70 } 71 } 72 visit_start_struct(v, NULL, NULL, 0, &local_err); 73 if (local_err) { 74 goto out; 75 } 76 for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { 77 object_property_set(obj, v, e->key, &local_err); 78 if (local_err) { 79 break; 80 } 81 } 82 if (!local_err) { 83 visit_check_struct(v, &local_err); 84 } 85 visit_end_struct(v, NULL); 86 if (local_err) { 87 goto out; 88 } 89 90 object_property_add_child(object_get_objects_root(), 91 id, obj, &local_err); 92 if (local_err) { 93 goto out; 94 } 95 96 user_creatable_complete(obj, &local_err); 97 if (local_err) { 98 object_property_del(object_get_objects_root(), 99 id, &error_abort); 100 goto out; 101 } 102 out: 103 if (local_err) { 104 error_propagate(errp, local_err); 105 object_unref(obj); 106 return NULL; 107 } 108 return obj; 109 } 110 111 112 Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) 113 { 114 Visitor *v; 115 QDict *pdict; 116 Object *obj; 117 const char *id = qemu_opts_id(opts); 118 char *type = qemu_opt_get_del(opts, "qom-type"); 119 120 if (!type) { 121 error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); 122 return NULL; 123 } 124 if (!id) { 125 error_setg(errp, QERR_MISSING_PARAMETER, "id"); 126 qemu_opt_set(opts, "qom-type", type, &error_abort); 127 g_free(type); 128 return NULL; 129 } 130 131 qemu_opts_set_id(opts, NULL); 132 pdict = qemu_opts_to_qdict(opts, NULL); 133 134 v = opts_visitor_new(opts); 135 obj = user_creatable_add_type(type, id, pdict, v, errp); 136 visit_free(v); 137 138 qemu_opts_set_id(opts, (char *) id); 139 qemu_opt_set(opts, "qom-type", type, &error_abort); 140 g_free(type); 141 QDECREF(pdict); 142 return obj; 143 } 144 145 146 int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp) 147 { 148 bool (*type_predicate)(const char *) = opaque; 149 Object *obj = NULL; 150 Error *err = NULL; 151 const char *type; 152 153 type = qemu_opt_get(opts, "qom-type"); 154 if (type && type_predicate && 155 !type_predicate(type)) { 156 return 0; 157 } 158 159 obj = user_creatable_add_opts(opts, &err); 160 if (!obj) { 161 error_report_err(err); 162 return -1; 163 } 164 object_unref(obj); 165 return 0; 166 } 167 168 169 void user_creatable_del(const char *id, Error **errp) 170 { 171 Object *container; 172 Object *obj; 173 174 container = object_get_objects_root(); 175 obj = object_resolve_path_component(container, id); 176 if (!obj) { 177 error_setg(errp, "object '%s' not found", id); 178 return; 179 } 180 181 if (!user_creatable_can_be_deleted(USER_CREATABLE(obj))) { 182 error_setg(errp, "object '%s' is in use, can not be deleted", id); 183 return; 184 } 185 186 /* 187 * if object was defined on the command-line, remove its corresponding 188 * option group entry 189 */ 190 qemu_opts_del(qemu_opts_find(qemu_find_opts_err("object", &error_abort), 191 id)); 192 193 object_unparent(obj); 194 } 195 196 void user_creatable_cleanup(void) 197 { 198 object_unparent(object_get_objects_root()); 199 } 200 201 static void register_types(void) 202 { 203 static const TypeInfo uc_interface_info = { 204 .name = TYPE_USER_CREATABLE, 205 .parent = TYPE_INTERFACE, 206 .class_size = sizeof(UserCreatableClass), 207 }; 208 209 type_register_static(&uc_interface_info); 210 } 211 212 type_init(register_types) 213