static int block_crypto_create_generic(QCryptoBlockFormat format, const char *filename, QemuOpts *opts, Error **errp) { int ret = -EINVAL; QCryptoBlockCreateOptions *create_opts = NULL; QCryptoBlock *crypto = NULL; struct BlockCryptoCreateData data = { .size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE), .opts = opts, .filename = filename, }; create_opts = block_crypto_create_opts_init(format, opts, errp); if (!create_opts) { return -1; } crypto = qcrypto_block_create(create_opts, block_crypto_init_func, block_crypto_write_func, &data, errp); if (!crypto) { ret = -EIO; goto cleanup; } ret = 0; cleanup: qcrypto_block_free(crypto); blk_unref(data.blk); qapi_free_QCryptoBlockCreateOptions(create_opts); return ret; } static int block_crypto_truncate(BlockDriverState *bs, int64_t offset, Error **errp) { BlockCrypto *crypto = bs->opaque; size_t payload_offset = qcrypto_block_get_payload_offset(crypto->block); offset += payload_offset; return bdrv_truncate(bs->file, offset, errp); }
static QCryptoBlockCreateOptions * block_crypto_create_opts_init(QCryptoBlockFormat format, QemuOpts *opts, Error **errp) { OptsVisitor *ov; QCryptoBlockCreateOptions *ret = NULL; Error *local_err = NULL; ret = g_new0(QCryptoBlockCreateOptions, 1); ret->format = format; ov = opts_visitor_new(opts); visit_start_struct(opts_get_visitor(ov), NULL, NULL, 0, &local_err); if (local_err) { goto out; } switch (format) { case Q_CRYPTO_BLOCK_FORMAT_LUKS: visit_type_QCryptoBlockCreateOptionsLUKS_members( opts_get_visitor(ov), &ret->u.luks, &local_err); break; default: error_setg(&local_err, "Unsupported block format %d", format); break; } if (!local_err) { visit_check_struct(opts_get_visitor(ov), &local_err); } visit_end_struct(opts_get_visitor(ov)); out: if (local_err) { error_propagate(errp, local_err); qapi_free_QCryptoBlockCreateOptions(ret); ret = NULL; } opts_visitor_cleanup(ov); return ret; }