qemu/qom/object_interfaces.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2
   3#include "qemu/cutils.h"
   4#include "qapi/error.h"
   5#include "qapi/qmp/qdict.h"
   6#include "qapi/qmp/qerror.h"
   7#include "qom/object_interfaces.h"
   8#include "qemu/help_option.h"
   9#include "qemu/module.h"
  10#include "qemu/option.h"
  11#include "qapi/opts-visitor.h"
  12#include "qemu/config-file.h"
  13
  14void user_creatable_complete(UserCreatable *uc, Error **errp)
  15{
  16    UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
  17
  18    if (ucc->complete) {
  19        ucc->complete(uc, errp);
  20    }
  21}
  22
  23bool user_creatable_can_be_deleted(UserCreatable *uc)
  24{
  25
  26    UserCreatableClass *ucc = USER_CREATABLE_GET_CLASS(uc);
  27
  28    if (ucc->can_be_deleted) {
  29        return ucc->can_be_deleted(uc);
  30    } else {
  31        return true;
  32    }
  33}
  34
  35Object *user_creatable_add_type(const char *type, const char *id,
  36                                const QDict *qdict,
  37                                Visitor *v, Error **errp)
  38{
  39    Object *obj;
  40    ObjectClass *klass;
  41    const QDictEntry *e;
  42    Error *local_err = NULL;
  43
  44    klass = object_class_by_name(type);
  45    if (!klass) {
  46        error_setg(errp, "invalid object type: %s", type);
  47        return NULL;
  48    }
  49
  50    if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) {
  51        error_setg(errp, "object type '%s' isn't supported by object-add",
  52                   type);
  53        return NULL;
  54    }
  55
  56    if (object_class_is_abstract(klass)) {
  57        error_setg(errp, "object type '%s' is abstract", type);
  58        return NULL;
  59    }
  60
  61    assert(qdict);
  62    obj = object_new(type);
  63    visit_start_struct(v, NULL, NULL, 0, &local_err);
  64    if (local_err) {
  65        goto out;
  66    }
  67    for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
  68        object_property_set(obj, v, e->key, &local_err);
  69        if (local_err) {
  70            break;
  71        }
  72    }
  73    if (!local_err) {
  74        visit_check_struct(v, &local_err);
  75    }
  76    visit_end_struct(v, NULL);
  77    if (local_err) {
  78        goto out;
  79    }
  80
  81    if (id != NULL) {
  82        object_property_add_child(object_get_objects_root(),
  83                                  id, obj, &local_err);
  84        if (local_err) {
  85            goto out;
  86        }
  87    }
  88
  89    user_creatable_complete(USER_CREATABLE(obj), &local_err);
  90    if (local_err) {
  91        if (id != NULL) {
  92            object_property_del(object_get_objects_root(),
  93                                id, &error_abort);
  94        }
  95        goto out;
  96    }
  97out:
  98    if (local_err) {
  99        error_propagate(errp, local_err);
 100        object_unref(obj);
 101        return NULL;
 102    }
 103    return obj;
 104}
 105
 106
 107Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
 108{
 109    Visitor *v;
 110    QDict *pdict;
 111    Object *obj;
 112    const char *id = qemu_opts_id(opts);
 113    char *type = qemu_opt_get_del(opts, "qom-type");
 114
 115    if (!type) {
 116        error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
 117        return NULL;
 118    }
 119    if (!id) {
 120        error_setg(errp, QERR_MISSING_PARAMETER, "id");
 121        qemu_opt_set(opts, "qom-type", type, &error_abort);
 122        g_free(type);
 123        return NULL;
 124    }
 125
 126    qemu_opts_set_id(opts, NULL);
 127    pdict = qemu_opts_to_qdict(opts, NULL);
 128
 129    v = opts_visitor_new(opts);
 130    obj = user_creatable_add_type(type, id, pdict, v, errp);
 131    visit_free(v);
 132
 133    qemu_opts_set_id(opts, (char *) id);
 134    qemu_opt_set(opts, "qom-type", type, &error_abort);
 135    g_free(type);
 136    qobject_unref(pdict);
 137    return obj;
 138}
 139
 140
 141int user_creatable_add_opts_foreach(void *opaque, QemuOpts *opts, Error **errp)
 142{
 143    bool (*type_opt_predicate)(const char *, QemuOpts *) = opaque;
 144    Object *obj = NULL;
 145    const char *type;
 146
 147    type = qemu_opt_get(opts, "qom-type");
 148    if (type && type_opt_predicate &&
 149        !type_opt_predicate(type, opts)) {
 150        return 0;
 151    }
 152
 153    obj = user_creatable_add_opts(opts, errp);
 154    if (!obj) {
 155        return -1;
 156    }
 157    object_unref(obj);
 158    return 0;
 159}
 160
 161bool user_creatable_print_help(const char *type, QemuOpts *opts)
 162{
 163    ObjectClass *klass;
 164
 165    if (is_help_option(type)) {
 166        GSList *l, *list;
 167
 168        printf("List of user creatable objects:\n");
 169        list = object_class_get_list_sorted(TYPE_USER_CREATABLE, false);
 170        for (l = list; l != NULL; l = l->next) {
 171            ObjectClass *oc = OBJECT_CLASS(l->data);
 172            printf("  %s\n", object_class_get_name(oc));
 173        }
 174        g_slist_free(list);
 175        return true;
 176    }
 177
 178    klass = object_class_by_name(type);
 179    if (klass && qemu_opt_has_help_opt(opts)) {
 180        ObjectPropertyIterator iter;
 181        ObjectProperty *prop;
 182        GPtrArray *array = g_ptr_array_new();
 183        int i;
 184
 185        object_class_property_iter_init(&iter, klass);
 186        while ((prop = object_property_iter_next(&iter))) {
 187            GString *str;
 188
 189            if (!prop->set) {
 190                continue;
 191            }
 192
 193            str = g_string_new(NULL);
 194            g_string_append_printf(str, "  %s=<%s>", prop->name, prop->type);
 195            if (prop->description) {
 196                if (str->len < 24) {
 197                    g_string_append_printf(str, "%*s", 24 - (int)str->len, "");
 198                }
 199                g_string_append_printf(str, " - %s", prop->description);
 200            }
 201            g_ptr_array_add(array, g_string_free(str, false));
 202        }
 203        g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
 204        if (array->len > 0) {
 205            printf("%s options:\n", type);
 206        } else {
 207            printf("There are no options for %s.\n", type);
 208        }
 209        for (i = 0; i < array->len; i++) {
 210            printf("%s\n", (char *)array->pdata[i]);
 211        }
 212        g_ptr_array_set_free_func(array, g_free);
 213        g_ptr_array_free(array, true);
 214        return true;
 215    }
 216
 217    return false;
 218}
 219
 220void user_creatable_del(const char *id, Error **errp)
 221{
 222    Object *container;
 223    Object *obj;
 224
 225    container = object_get_objects_root();
 226    obj = object_resolve_path_component(container, id);
 227    if (!obj) {
 228        error_setg(errp, "object '%s' not found", id);
 229        return;
 230    }
 231
 232    if (!user_creatable_can_be_deleted(USER_CREATABLE(obj))) {
 233        error_setg(errp, "object '%s' is in use, can not be deleted", id);
 234        return;
 235    }
 236
 237    /*
 238     * if object was defined on the command-line, remove its corresponding
 239     * option group entry
 240     */
 241    qemu_opts_del(qemu_opts_find(qemu_find_opts_err("object", &error_abort),
 242                                 id));
 243
 244    object_unparent(obj);
 245}
 246
 247void user_creatable_cleanup(void)
 248{
 249    object_unparent(object_get_objects_root());
 250}
 251
 252static void register_types(void)
 253{
 254    static const TypeInfo uc_interface_info = {
 255        .name          = TYPE_USER_CREATABLE,
 256        .parent        = TYPE_INTERFACE,
 257        .class_size = sizeof(UserCreatableClass),
 258    };
 259
 260    type_register_static(&uc_interface_info);
 261}
 262
 263type_init(register_types)
 264