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