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