static void qnull_visit_test(void) { QObject *obj; Visitor *v; QNull *null; /* * Most tests of interactions between QObject and visitors are in * test-qmp-*-visitor; but these tests live here because they * depend on layering violations to check qnull_ refcnt. */ g_assert(qnull_.base.refcnt == 1); obj = QOBJECT(qnull()); v = qobject_input_visitor_new(obj); qobject_decref(obj); visit_type_null(v, NULL, &null, &error_abort); g_assert(obj == QOBJECT(&qnull_)); QDECREF(null); visit_free(v); null = NULL; v = qobject_output_visitor_new(&obj); visit_type_null(v, NULL, &null, &error_abort); visit_complete(v, &obj); g_assert(obj == QOBJECT(&qnull_)); QDECREF(null); qobject_decref(obj); visit_free(v); g_assert(qnull_.base.refcnt == 1); }
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) { Visitor *v; QDict *pdict; Object *obj; const char *id = qemu_opts_id(opts); char *type = qemu_opt_get_del(opts, "qom-type"); if (!type) { error_setg(errp, QERR_MISSING_PARAMETER, "qom-type"); return NULL; } if (!id) { error_setg(errp, QERR_MISSING_PARAMETER, "id"); qemu_opt_set(opts, "qom-type", type, &error_abort); g_free(type); return NULL; } qemu_opts_set_id(opts, NULL); pdict = qemu_opts_to_qdict(opts, NULL); v = opts_visitor_new(opts); obj = user_creatable_add_type(type, id, pdict, v, errp); visit_free(v); qemu_opts_set_id(opts, (char *) id); qemu_opt_set(opts, "qom-type", type, &error_abort); g_free(type); qobject_unref(pdict); return obj; }
/* test generated deallocation on an object whose construction was prematurely * terminated due to an error */ static void test_dealloc_partial(void) { static const char text[] = "don't leak me"; UserDefTwo *ud2 = NULL; Error *err = NULL; /* create partial object */ { QDict *ud2_dict; Visitor *v; ud2_dict = qdict_new(); qdict_put_str(ud2_dict, "string0", text); v = qobject_input_visitor_new(QOBJECT(ud2_dict)); visit_type_UserDefTwo(v, NULL, &ud2, &err); visit_free(v); qobject_unref(ud2_dict); } /* verify that visit_type_XXX() cleans up properly on error */ error_free_or_abort(&err); assert(!ud2); /* Manually create a partial object, leaving ud2->dict1 at NULL */ ud2 = g_new0(UserDefTwo, 1); ud2->string0 = g_strdup(text); /* tear down partial object */ qapi_free_UserDefTwo(ud2); }
static InetSocketAddress *ssh_config(BDRVSSHState *s, QDict *options, Error **errp) { InetSocketAddress *inet = NULL; QDict *addr = NULL; QObject *crumpled_addr = NULL; Visitor *iv = NULL; Error *local_error = NULL; qdict_extract_subqdict(options, &addr, "server."); if (!qdict_size(addr)) { error_setg(errp, "SSH server address missing"); goto out; } crumpled_addr = qdict_crumple(addr, errp); if (!crumpled_addr) { goto out; } iv = qobject_input_visitor_new(crumpled_addr, true); visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); if (local_error) { error_propagate(errp, local_error); goto out; } out: QDECREF(addr); qobject_decref(crumpled_addr); visit_free(iv); return inet; }
static void visitor_output_teardown(TestOutputVisitorData *data, const void *unused) { visit_free(data->ov); data->ov = NULL; qobject_decref(data->obj); data->obj = NULL; }
static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp) { Visitor *v = qapi_dealloc_visitor_new(); visit(v, &native_in, errp); visit_free(v); }
void object_property_set_qobject(Object *obj, QObject *value, const char *name, Error **errp) { Visitor *v; /* TODO: Should we reject, rather than ignore, excess input? */ v = qobject_input_visitor_new(value, false); object_property_set(obj, v, name, errp); visit_free(v); }
static void visitor_input_teardown(TestInputVisitorData *data, const void *unused) { qobject_decref(data->obj); data->obj = NULL; if (data->qiv) { visit_free(data->qiv); data->qiv = NULL; } }
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp) { Visitor *v; QDict *pdict; Object *obj = NULL; v = opts_visitor_new(opts); pdict = qemu_opts_to_qdict(opts, NULL); obj = user_creatable_add(pdict, v, errp); visit_free(v); QDECREF(pdict); return obj; }
void *qapi_clone(const void *src, void (*visit_type)(Visitor *, const char *, void **, Error **)) { Visitor *v; void *dst = (void *) src; /* Cast away const */ if (!src) { return NULL; } v = qapi_clone_visitor_new(); visit_type(v, NULL, &dst, &error_abort); visit_free(v); return dst; }
QObject *object_property_get_qobject(Object *obj, const char *name, Error **errp) { QObject *ret = NULL; Error *local_err = NULL; Visitor *v; v = qobject_output_visitor_new(&ret); object_property_get(obj, v, name, &local_err); if (!local_err) { visit_complete(v, &ret); } error_propagate(errp, local_err); visit_free(v); return ret; }
static QCryptoBlockCreateOptions * block_crypto_create_opts_init(QCryptoBlockFormat format, QemuOpts *opts, Error **errp) { Visitor *v; QCryptoBlockCreateOptions *ret = NULL; Error *local_err = NULL; ret = g_new0(QCryptoBlockCreateOptions, 1); ret->format = format; v = opts_visitor_new(opts); visit_start_struct(v, NULL, NULL, 0, &local_err); if (local_err) { goto out; } switch (format) { case Q_CRYPTO_BLOCK_FORMAT_LUKS: visit_type_QCryptoBlockCreateOptionsLUKS_members( v, &ret->u.luks, &local_err); break; default: error_setg(&local_err, "Unsupported block format %d", format); break; } if (!local_err) { visit_check_struct(v, &local_err); } visit_end_struct(v, NULL); out: if (local_err) { error_propagate(errp, local_err); qapi_free_QCryptoBlockCreateOptions(ret); ret = NULL; } visit_free(v); return ret; }
static QAuthZ * qauthz_list_file_load(QAuthZListFile *fauthz, Error **errp) { GError *err = NULL; gchar *content = NULL; gsize len; QObject *obj = NULL; QDict *pdict; Visitor *v = NULL; QAuthZ *ret = NULL; trace_qauthz_list_file_load(fauthz, fauthz->filename); if (!g_file_get_contents(fauthz->filename, &content, &len, &err)) { error_setg(errp, "Unable to read '%s': %s", fauthz->filename, err->message); goto cleanup; } obj = qobject_from_json(content, errp); if (!obj) { goto cleanup; } pdict = qobject_to(QDict, obj); if (!pdict) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "obj", "dict"); goto cleanup; } v = qobject_input_visitor_new(obj); ret = (QAuthZ *)user_creatable_add_type(TYPE_QAUTHZ_LIST, NULL, pdict, v, errp); cleanup: visit_free(v); qobject_unref(obj); if (err) { g_error_free(err); } g_free(content); return ret; }
static InetSocketAddress *ssh_config(QDict *options, Error **errp) { InetSocketAddress *inet = NULL; QDict *addr = NULL; QObject *crumpled_addr = NULL; Visitor *iv = NULL; Error *local_error = NULL; qdict_extract_subqdict(options, &addr, "server."); if (!qdict_size(addr)) { error_setg(errp, "SSH server address missing"); goto out; } crumpled_addr = qdict_crumple(addr, errp); if (!crumpled_addr) { goto out; } /* * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive. * .to doesn't matter, it's ignored anyway. * That's because when @options come from -blockdev or * blockdev_add, members are typed according to the QAPI schema, * but when they come from -drive, they're all QString. The * visitor expects the former. */ iv = qobject_input_visitor_new(crumpled_addr); visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); if (local_error) { error_propagate(errp, local_error); goto out; } out: QDECREF(addr); qobject_decref(crumpled_addr); visit_free(iv); return inet; }
static int qemu_rbd_convert_options(QDict *options, BlockdevOptionsRbd **opts, Error **errp) { Visitor *v; Error *local_err = NULL; /* Convert the remaining options into a QAPI object */ v = qobject_input_visitor_new_flat_confused(options, errp); if (!v) { return -EINVAL; } visit_type_BlockdevOptionsRbd(v, NULL, opts, &local_err); visit_free(v); if (local_err) { error_propagate(errp, local_err); return -EINVAL; } return 0; }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; BlockdevOptionsRbd *opts = NULL; Visitor *v; QObject *crumpled = NULL; const QDictEntry *e; Error *local_err = NULL; const char *filename; char *keypairs, *secretid; int r; /* If we are given a filename, parse the filename, with precedence given to * filename encoded options */ filename = qdict_get_try_str(options, "filename"); if (filename) { warn_report("'filename' option specified. " "This is an unsupported option, and may be deprecated " "in the future"); qemu_rbd_parse_filename(filename, options, &local_err); qdict_del(options, "filename"); if (local_err) { error_propagate(errp, local_err); return -EINVAL; } } keypairs = g_strdup(qdict_get_try_str(options, "=keyvalue-pairs")); if (keypairs) { qdict_del(options, "=keyvalue-pairs"); } secretid = g_strdup(qdict_get_try_str(options, "password-secret")); if (secretid) { qdict_del(options, "password-secret"); } /* Convert the remaining options into a QAPI object */ crumpled = qdict_crumple(options, errp); if (crumpled == NULL) { r = -EINVAL; goto out; } v = qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsRbd(v, NULL, &opts, &local_err); visit_free(v); qobject_unref(crumpled); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto out; } /* Remove the processed options from the QDict (the visitor processes * _all_ options in the QDict) */ while ((e = qdict_first(options))) { qdict_del(options, e->key); } r = qemu_rbd_connect(&s->cluster, &s->io_ctx, opts, !(flags & BDRV_O_NOCACHE), keypairs, secretid, errp); if (r < 0) { goto out; } s->snap = g_strdup(opts->snapshot); s->image_name = g_strdup(opts->image); /* rbd_open is always r/w */ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap); if (r < 0) { error_setg_errno(errp, -r, "error reading header from %s", s->image_name); goto failed_open; } /* If we are using an rbd snapshot, we must be r/o, otherwise * leave as-is */ if (s->snap != NULL) { if (!bdrv_is_read_only(bs)) { error_report("Opening rbd snapshots without an explicit " "read-only=on option is deprecated. Future versions " "will refuse to open the image instead of " "automatically marking the image read-only."); r = bdrv_set_read_only(bs, true, &local_err); if (r < 0) { error_propagate(errp, local_err); goto failed_open; } } } r = 0; goto out; failed_open: rados_ioctx_destroy(s->io_ctx); g_free(s->snap); g_free(s->image_name); rados_shutdown(s->cluster); out: qapi_free_BlockdevOptionsRbd(opts); g_free(keypairs); g_free(secretid); return r; }
void acpi_table_add(const QemuOpts *opts, Error **errp) { AcpiTableOptions *hdrs = NULL; Error *err = NULL; char **pathnames = NULL; char **cur; size_t bloblen = 0; char unsigned *blob = NULL; { Visitor *v; v = opts_visitor_new(opts); visit_type_AcpiTableOptions(v, NULL, &hdrs, &err); visit_free(v); } if (err) { goto out; } if (hdrs->has_file == hdrs->has_data) { error_setg(&err, "'-acpitable' requires one of 'data' or 'file'"); goto out; } pathnames = g_strsplit(hdrs->has_file ? hdrs->file : hdrs->data, ":", 0); if (pathnames == NULL || pathnames[0] == NULL) { error_setg(&err, "'-acpitable' requires at least one pathname"); goto out; } /* now read in the data files, reallocating buffer as needed */ for (cur = pathnames; *cur; ++cur) { int fd = open(*cur, O_RDONLY | O_BINARY); if (fd < 0) { error_setg(&err, "can't open file %s: %s", *cur, strerror(errno)); goto out; } for (;;) { char unsigned data[8192]; ssize_t r; r = read(fd, data, sizeof data); if (r == 0) { break; } else if (r > 0) { blob = g_realloc(blob, bloblen + r); memcpy(blob + bloblen, data, r); bloblen += r; } else if (errno != EINTR) { error_setg(&err, "can't read file %s: %s", *cur, strerror(errno)); close(fd); goto out; } } close(fd); } acpi_table_install(blob, bloblen, hdrs->has_file, hdrs, &err); out: g_free(blob); g_strfreev(pathnames); qapi_free_AcpiTableOptions(hdrs); error_propagate(errp, err); }
static void cpu_model_from_info(S390CPUModel *model, const CpuModelInfo *info, Error **errp) { const QDict *qdict = NULL; const QDictEntry *e; Visitor *visitor; ObjectClass *oc; S390CPU *cpu; Object *obj; if (info->props) { qdict = qobject_to_qdict(info->props); if (!qdict) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); return; } } oc = cpu_class_by_name(TYPE_S390_CPU, info->name); if (!oc) { error_setg(errp, "The CPU definition \'%s\' is unknown.", info->name); return; } if (S390_CPU_CLASS(oc)->kvm_required && !kvm_enabled()) { error_setg(errp, "The CPU definition '%s' requires KVM", info->name); return; } obj = object_new(object_class_get_name(oc)); cpu = S390_CPU(obj); if (!cpu->model) { error_setg(errp, "Details about the host CPU model are not available, " "it cannot be used."); object_unref(obj); return; } if (qdict) { visitor = qobject_input_visitor_new(info->props); visit_start_struct(visitor, NULL, NULL, 0, errp); if (*errp) { object_unref(obj); return; } for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { object_property_set(obj, visitor, e->key, errp); if (*errp) { break; } } if (!*errp) { visit_check_struct(visitor, errp); } visit_end_struct(visitor, NULL); visit_free(visitor); if (*errp) { object_unref(obj); return; } } /* copy the model and throw the cpu away */ memcpy(model, cpu->model, sizeof(*model)); object_unref(obj); }