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