const char *backing_file, const char *backing_format,
int flags)
{
- if (drv->bdrv_create2)
- return drv->bdrv_create2(filename, size_in_sectors, backing_file,
- backing_format, flags);
- if (drv->bdrv_create)
- return drv->bdrv_create(filename, size_in_sectors, backing_file,
- flags);
- return -ENOTSUP;
+ QEMUOptionParameter *options;
+
+ options = parse_option_parameters("", drv->create_options, NULL);
+
+ // Process flags
+ if (flags & ~(BLOCK_FLAG_ENCRYPT | BLOCK_FLAG_COMPAT6 | BLOCK_FLAG_COMPRESS)) {
+ return -ENOTSUP;
+ }
+
+ if (flags & BLOCK_FLAG_ENCRYPT) {
+ set_option_parameter_int(options, BLOCK_OPT_ENCRYPT, 1);
+ }
+ if (flags & BLOCK_FLAG_COMPAT6) {
+ set_option_parameter_int(options, BLOCK_OPT_COMPAT6, 1);
+ }
+
+ // Add size to options
+ set_option_parameter_int(options, BLOCK_OPT_SIZE, size_in_sectors * 512);
+
+ // Backing files
+ if ((backing_file != NULL && set_option_parameter(options,
+ BLOCK_OPT_BACKING_FILE, backing_file))
+ || (backing_format != NULL && set_option_parameter(options,
+ BLOCK_OPT_BACKING_FMT, backing_format)))
+ {
+ return -ENOTSUP;
+ }
+
+ return bdrv_create(drv, filename, options);
}
-int bdrv_create(BlockDriver *drv,
- const char *filename, int64_t size_in_sectors,
- const char *backing_file, int flags)
+int bdrv_create(BlockDriver *drv, const char* filename,
+ QEMUOptionParameter *options)
{
if (!drv->bdrv_create)
return -ENOTSUP;
- return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
+
+ return drv->bdrv_create(filename, options);
}
#ifdef _WIN32
#include "qemu-aio.h"
#include "qemu-common.h"
+#include "qemu-option.h"
/* block.c */
typedef struct BlockDriver BlockDriver;
void bdrv_init(void);
BlockDriver *bdrv_find_format(const char *format_name);
-int bdrv_create(BlockDriver *drv,
- const char *filename, int64_t size_in_sectors,
- const char *backing_file, int flags);
+int bdrv_create(BlockDriver *drv, const char* filename,
+ QEMUOptionParameter *options);
int bdrv_create2(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, const char *backing_format,
close(s->fd);
}
-static int cow_create(const char *filename, int64_t image_sectors,
- const char *image_filename, int flags)
+static int cow_create(const char *filename, QEMUOptionParameter *options)
{
int fd, cow_fd;
struct cow_header_v2 cow_header;
struct stat st;
-
- if (flags)
- return -ENOTSUP;
+ int64_t image_sectors = 0;
+ const char *image_filename = NULL;
+
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ image_sectors = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ image_filename = options->value.s;
+ }
+ options++;
+ }
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
fsync(s->fd);
}
+static QEMUOptionParameter cow_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { NULL }
+};
+
static BlockDriver bdrv_cow = {
.format_name = "cow",
.instance_size = sizeof(BDRVCowState),
.bdrv_create = cow_create,
.bdrv_flush = cow_flush,
.bdrv_is_allocated = cow_is_allocated,
+
+ .create_options = cow_create_options,
};
static void bdrv_cow_init(void)
bdrv_delete(s->hd);
}
-static int qcow_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int qcow_create(const char *filename, QEMUOptionParameter *options)
{
int fd, header_size, backing_filename_len, l1_size, i, shift;
QCowHeader header;
uint64_t tmp;
+ int64_t total_size = 0;
+ const char *backing_file = NULL;
+ int flags = 0;
+
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ backing_file = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
+ flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (fd < 0)
return 0;
}
+
+static QEMUOptionParameter qcow_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { BLOCK_OPT_ENCRYPT, OPT_FLAG },
+ { NULL }
+};
+
static BlockDriver bdrv_qcow = {
.format_name = "qcow",
.instance_size = sizeof(BDRVQcowState),
.aiocb_size = sizeof(QCowAIOCB),
.bdrv_write_compressed = qcow_write_compressed,
.bdrv_get_info = qcow_get_info,
+
+ .create_options = qcow_create_options,
};
static void bdrv_qcow_init(void)
return 0;
}
-static int qcow_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
-{
- return qcow_create2(filename, total_size, backing_file, NULL, flags);
+static int qcow_create(const char *filename, QEMUOptionParameter *options)
+{
+ const char *backing_file = NULL;
+ const char *backing_fmt = NULL;
+ uint64_t sectors = 0;
+ int flags = 0;
+
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ sectors = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ backing_file = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FMT)) {
+ backing_fmt = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_ENCRYPT)) {
+ flags |= options->value.n ? BLOCK_FLAG_ENCRYPT : 0;
+ }
+ options++;
+ }
+
+ return qcow_create2(filename, sectors, backing_file, backing_fmt, flags);
}
static int qcow_make_empty(BlockDriverState *bs)
return ret;
}
+static QEMUOptionParameter qcow_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { BLOCK_OPT_BACKING_FMT, OPT_STRING },
+ { BLOCK_OPT_ENCRYPT, OPT_FLAG },
+ { NULL }
+};
+
static BlockDriver bdrv_qcow2 = {
.format_name = "qcow2",
.instance_size = sizeof(BDRVQcowState),
.bdrv_put_buffer = qcow_put_buffer,
.bdrv_get_buffer = qcow_get_buffer,
- .bdrv_create2 = qcow_create2,
+ .create_options = qcow_create_options,
.bdrv_check = qcow_check,
};
}
#endif
-static int raw_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int raw_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
+ int64_t total_size = 0;
- if (flags || backing_file)
- return -ENOTSUP;
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
fsync(s->fd);
}
+
+static QEMUOptionParameter raw_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { NULL }
+};
+
static BlockDriver bdrv_raw = {
.format_name = "raw",
.instance_size = sizeof(BDRVRawState),
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
+
+ .create_options = raw_create_options,
};
/***********************************************/
#endif /* !linux && !FreeBSD */
#if defined(__linux__) || defined(__FreeBSD__)
-static int hdev_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int hdev_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
int ret = 0;
struct stat stat_buf;
+ int64_t total_size = 0;
- if (flags || backing_file)
- return -ENOTSUP;
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, "size")) {
+ total_size = options->value.n / 512;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_BINARY);
if (fd < 0)
#else /* !(linux || freebsd) */
-static int hdev_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int hdev_create(const char *filename, QEMUOptionParameter *options)
{
return -ENOTSUP;
}
return l.QuadPart;
}
-static int raw_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int raw_create(const char *filename, QEMUOptionParameter *options)
{
int fd;
+ int64_t total_size = 0;
- if (flags || backing_file)
- return -ENOTSUP;
+ /* Read out options */
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ }
+ options++;
+ }
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
return 0;
}
+static QEMUOptionParameter raw_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { NULL }
+};
+
static BlockDriver bdrv_raw = {
.format_name = "raw",
.instance_size = sizeof(BDRVRawState),
.bdrv_write = raw_write,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
+
+ .create_options = raw_create_options,
};
/***********************************************/
return 0;
}
-static int vmdk_create(const char *filename, int64_t total_size,
- const char *backing_file, int flags)
+static int vmdk_create(const char *filename, QEMUOptionParameter *options)
{
int fd, i;
VMDK4Header header;
"ddb.adapterType = \"ide\"\n";
char desc[1024];
const char *real_filename, *temp_str;
+ int64_t total_size = 0;
+ const char *backing_file = NULL;
+ int flags = 0;
+
+ // Read out options
+ while (options && options->name) {
+ if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
+ total_size = options->value.n / 512;
+ } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
+ backing_file = options->value.s;
+ } else if (!strcmp(options->name, BLOCK_OPT_COMPAT6)) {
+ flags |= options->value.n ? BLOCK_FLAG_COMPAT6: 0;
+ }
+ options++;
+ }
/* XXX: add support for backing file */
if (backing_file) {
bdrv_flush(s->hd);
}
+
+static QEMUOptionParameter vmdk_create_options[] = {
+ { BLOCK_OPT_SIZE, OPT_SIZE },
+ { BLOCK_OPT_BACKING_FILE, OPT_STRING },
+ { BLOCK_OPT_COMPAT6, OPT_FLAG },
+ { NULL }
+};
+
static BlockDriver bdrv_vmdk = {
.format_name = "vmdk",
.instance_size = sizeof(BDRVVmdkState),
.bdrv_create = vmdk_create,
.bdrv_flush = vmdk_flush,
.bdrv_is_allocated = vmdk_is_allocated,
+
+ .create_options = vmdk_create_options,
};
static void bdrv_vmdk_init(void)
return 0;
}
-static int vpc_create(const char *filename, int64_t total_sectors,
- const char *backing_file, int flags)
+static int vpc_create(const char *filename, QEMUOptionParameter *options)
{
uint8_t buf[1024];
struct vhd_footer* footer = (struct vhd_footer*) buf;
uint8_t heads;
uint8_t secs_per_cyl;
size_t block_size, num_bat_entries;
+ int64_t total_sectors = 0;
- if (backing_file != NULL)
- return -ENOTSUP;
+ // Read out options
+ while (options && options->name) {
+ if (!strcmp(options->name, "size")) {
+ total_sectors = options->value.n / 512;
+ }
+ options++;
+ }
+ // Create the file
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
if (fd < 0)
return -EIO;
bdrv_delete(s->hd);
}
+static QEMUOptionParameter vpc_create_options[] = {
+ { "size", OPT_SIZE },
+ { NULL }
+};
+
static BlockDriver bdrv_vpc = {
.format_name = "vpc",
.instance_size = sizeof(BDRVVPCState),
.bdrv_write = vpc_write,
.bdrv_close = vpc_close,
.bdrv_create = vpc_create,
+
+ .create_options = vpc_create_options,
};
static void bdrv_vpc_init(void)
s->qcow_filename = qemu_malloc(1024);
get_tmp_filename(s->qcow_filename, 1024);
- if (bdrv_create(bdrv_find_format("qcow"),
- s->qcow_filename, s->sector_count, "fat:", 0) < 0)
+ if (bdrv_create2(bdrv_find_format("qcow"),
+ s->qcow_filename, s->sector_count, "fat:", NULL, 0) < 0)
return -1;
s->qcow = bdrv_new("");
if (s->qcow == NULL || bdrv_open(s->qcow, s->qcow_filename, 0) < 0)
#define BLOCK_INT_H
#include "block.h"
+#include "qemu-option.h"
#define BLOCK_FLAG_ENCRYPT 1
#define BLOCK_FLAG_COMPRESS 2
#define BLOCK_FLAG_COMPAT6 4
+#define BLOCK_OPT_SIZE "size"
+#define BLOCK_OPT_ENCRYPT "encryption"
+#define BLOCK_OPT_COMPAT6 "compat6"
+#define BLOCK_OPT_BACKING_FILE "backing_file"
+#define BLOCK_OPT_BACKING_FMT "backing_fmt"
+
typedef struct AIOPool {
void (*cancel)(BlockDriverAIOCB *acb);
int aiocb_size;
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
void (*bdrv_close)(BlockDriverState *bs);
- int (*bdrv_create)(const char *filename, int64_t total_sectors,
- const char *backing_file, int flags);
+ int (*bdrv_create)(const char *filename, QEMUOptionParameter *options);
void (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
AIOPool aio_pool;
- /* new create with backing file format */
- int (*bdrv_create2)(const char *filename, int64_t total_sectors,
- const char *backing_file, const char *backing_format,
- int flags);
+ /* List of options for creating images, terminated by name == NULL */
+ QEMUOptionParameter *create_options;
+
/* Returns number of errors in image, -errno for internal errors */
int (*bdrv_check)(BlockDriverState* bs);
if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
error("Compression and encryption not supported at the same time");
- ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
+ ret = bdrv_create2(drv, out_filename, total_sectors, out_baseimg, NULL, flags);
if (ret < 0) {
if (ret == -ENOTSUP) {
error("Formatting not supported for file format '%s'", out_fmt);