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