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