summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block.c141
-rw-r--r--block.h4
-rw-r--r--qemu-img.c108
3 files changed, 147 insertions, 106 deletions
diff --git a/block.c b/block.c
index b4aaf41640..a48b30c249 100644
--- a/block.c
+++ b/block.c
@@ -2758,3 +2758,144 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs)
{
return bs->dirty_count;
}
+
+int bdrv_img_create(const char *filename, const char *fmt,
+ const char *base_filename, const char *base_fmt,
+ char *options, uint64_t img_size, int flags)
+{
+ QEMUOptionParameter *param = NULL, *create_options = NULL;
+ QEMUOptionParameter *backing_fmt;
+ BlockDriverState *bs = NULL;
+ BlockDriver *drv, *proto_drv;
+ int ret = 0;
+
+ /* Find driver and parse its options */
+ drv = bdrv_find_format(fmt);
+ if (!drv) {
+ error_report("Unknown file format '%s'", fmt);
+ ret = -1;
+ goto out;
+ }
+
+ proto_drv = bdrv_find_protocol(filename);
+ if (!proto_drv) {
+ error_report("Unknown protocol '%s'", filename);
+ ret = -1;
+ goto out;
+ }
+
+ create_options = append_option_parameters(create_options,
+ drv->create_options);
+ create_options = append_option_parameters(create_options,
+ proto_drv->create_options);
+
+ /* Create parameter list with default values */
+ param = parse_option_parameters("", create_options, param);
+
+ set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
+
+ /* Parse -o options */
+ if (options) {
+ param = parse_option_parameters(options, create_options, param);
+ if (param == NULL) {
+ error_report("Invalid options for file format '%s'.", fmt);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ if (base_filename) {
+ if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE,
+ base_filename)) {
+ error_report("Backing file not supported for file format '%s'",
+ fmt);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ if (base_fmt) {
+ if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+ error_report("Backing file format not supported for file "
+ "format '%s'", fmt);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
+ if (backing_fmt && backing_fmt->value.s) {
+ if (!bdrv_find_format(backing_fmt->value.s)) {
+ error_report("Unknown backing file format '%s'",
+ backing_fmt->value.s);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ // The size for the image must always be specified, with one exception:
+ // If we are using a backing file, we can obtain the size from there
+ if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
+ QEMUOptionParameter *backing_file =
+ get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
+
+ if (backing_file && backing_file->value.s) {
+ uint64_t size;
+ const char *fmt = NULL;
+ char buf[32];
+
+ if (backing_fmt && backing_fmt->value.s) {
+ fmt = backing_fmt->value.s;
+ }
+
+ bs = bdrv_new("");
+
+ ret = bdrv_open(bs, backing_file->value.s, flags, drv);
+ if (ret < 0) {
+ error_report("Could not open '%s'", filename);
+ ret = -1;
+ goto out;
+ }
+ bdrv_get_geometry(bs, &size);
+ size *= 512;
+
+ snprintf(buf, sizeof(buf), "%" PRId64, size);
+ set_option_parameter(param, BLOCK_OPT_SIZE, buf);
+ } else {
+ error_report("Image creation needs a size parameter");
+ ret = -1;
+ goto out;
+ }
+ }
+
+ printf("Formatting '%s', fmt=%s ", filename, fmt);
+ print_option_parameters(param);
+ puts("");
+
+ ret = bdrv_create(drv, filename, param);
+
+ if (ret < 0) {
+ if (ret == -ENOTSUP) {
+ error_report("Formatting or formatting option not supported for "
+ "file format '%s'", fmt);
+ } else if (ret == -EFBIG) {
+ error_report("The image size is too large for file format '%s'",
+ fmt);
+ } else {
+ error_report("%s: error while creating %s: %s", filename, fmt,
+ strerror(-ret));
+ }
+ }
+
+out:
+ free_option_parameters(create_options);
+ free_option_parameters(param);
+
+ if (bs) {
+ bdrv_delete(bs);
+ }
+ if (ret) {
+ return 1;
+ }
+ return 0;
+}
diff --git a/block.h b/block.h
index 78ecfac343..b812172735 100644
--- a/block.h
+++ b/block.h
@@ -227,6 +227,10 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
int64_t pos, int size);
+int bdrv_img_create(const char *filename, const char *fmt,
+ const char *base_filename, const char *base_fmt,
+ char *options, uint64_t img_size, int flags);
+
#define BDRV_SECTORS_PER_DIRTY_CHUNK 2048
void bdrv_set_dirty_tracking(BlockDriverState *bs, int enable);
diff --git a/qemu-img.c b/qemu-img.c
index f576cfb0d5..0ff179f00b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -288,9 +288,6 @@ static int img_create(int argc, char **argv)
const char *base_fmt = NULL;
const char *filename;
const char *base_filename = NULL;
- BlockDriver *drv, *proto_drv;
- QEMUOptionParameter *param = NULL, *create_options = NULL;
- QEMUOptionParameter *backing_fmt = NULL;
char *options = NULL;
for(;;) {
@@ -351,110 +348,9 @@ static int img_create(int argc, char **argv)
goto out;
}
- /* Find driver and parse its options */
- drv = bdrv_find_format(fmt);
- if (!drv) {
- error("Unknown file format '%s'", fmt);
- ret = -1;
- goto out;
- }
-
- proto_drv = bdrv_find_protocol(filename);
- if (!proto_drv) {
- error("Unknown protocol '%s'", filename);
- ret = -1;
- goto out;
- }
-
- create_options = append_option_parameters(create_options,
- drv->create_options);
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
-
- /* Create parameter list with default values */
- param = parse_option_parameters("", create_options, param);
-
- set_option_parameter_int(param, BLOCK_OPT_SIZE, img_size);
-
- /* Parse -o options */
- if (options) {
- param = parse_option_parameters(options, create_options, param);
- if (param == NULL) {
- error("Invalid options for file format '%s'.", fmt);
- ret = -1;
- goto out;
- }
- }
-
- /* Add old-style options to parameters */
- ret = add_old_style_options(fmt, param, base_filename, base_fmt);
- if (ret < 0) {
- goto out;
- }
-
- backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
- if (backing_fmt && backing_fmt->value.s) {
- if (!bdrv_find_format(backing_fmt->value.s)) {
- error("Unknown backing file format '%s'",
- backing_fmt->value.s);
- ret = -1;
- goto out;
- }
- }
-
- // The size for the image must always be specified, with one exception:
- // If we are using a backing file, we can obtain the size from there
- if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
-
- QEMUOptionParameter *backing_file =
- get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
-
- if (backing_file && backing_file->value.s) {
- BlockDriverState *bs;
- uint64_t size;
- const char *fmt = NULL;
- char buf[32];
-
- if (backing_fmt && backing_fmt->value.s) {
- fmt = backing_fmt->value.s;
- }
-
- bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS);
- if (!bs) {
- ret = -1;
- goto out;
- }
- bdrv_get_geometry(bs, &size);
- size *= 512;
- bdrv_delete(bs);
-
- snprintf(buf, sizeof(buf), "%" PRId64, size);
- set_option_parameter(param, BLOCK_OPT_SIZE, buf);
- } else {
- error("Image creation needs a size parameter");
- ret = -1;
- goto out;
- }
- }
-
- printf("Formatting '%s', fmt=%s ", filename, fmt);
- print_option_parameters(param);
- puts("");
-
- ret = bdrv_create(drv, filename, param);
-
- if (ret < 0) {
- if (ret == -ENOTSUP) {
- error("Formatting or formatting option not supported for file format '%s'", fmt);
- } else if (ret == -EFBIG) {
- error("The image size is too large for file format '%s'", fmt);
- } else {
- error("%s: error while creating %s: %s", filename, fmt, strerror(-ret));
- }
- }
+ ret = bdrv_img_create(filename, fmt, base_filename, base_fmt,
+ options, img_size, BDRV_O_FLAGS);
out:
- free_option_parameters(create_options);
- free_option_parameters(param);
if (ret) {
return 1;
}