#include "block/qapi.h"
#include <getopt.h>
+#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
+ ", Copyright (c) 2004-2008 Fabrice Bellard\n"
+
typedef struct img_cmd_t {
const char *name;
int (*handler)(int argc, char **argv);
printf(" %s", name);
}
+static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
+{
+ va_list ap;
+
+ error_printf("qemu-img: ");
+
+ va_start(ap, fmt);
+ error_vprintf(fmt, ap);
+ va_end(ap);
+
+ error_printf("\nTry 'qemu-img --help' for more information\n");
+ exit(EXIT_FAILURE);
+}
+
/* Please keep in synch with qemu-img.texi */
-static void help(void)
+static void QEMU_NORETURN help(void)
{
const char *help_msg =
- "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
+ QEMU_IMG_VERSION
"usage: qemu-img command [command options]\n"
"QEMU disk image utility\n"
"\n"
" 'cache' is the cache mode used to write the output disk image, the valid\n"
" options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
" 'directsync' and 'unsafe' (default for convert)\n"
+ " 'src_cache' in contrast is the cache mode used to read input disk images\n"
" 'size' is the disk image size in bytes. Optional suffixes\n"
" 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
" 'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P) are\n"
printf("%s\nSupported formats:", help_msg);
bdrv_iterate_format(format_print, NULL);
printf("\n");
- exit(1);
+ exit(EXIT_SUCCESS);
}
static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
static int read_password(char *buf, int buf_size)
{
int c, i;
+
printf("Password: ");
fflush(stdout);
i = 0;
for(;;) {
c = getchar();
- if (c == '\n')
+ if (c < 0) {
+ buf[i] = '\0';
+ return -1;
+ } else if (c == '\n') {
break;
- if (i < (buf_size - 1))
+ } else if (i < (buf_size - 1)) {
buf[i++] = c;
+ }
}
buf[i] = '\0';
return 0;
if (errno == EAGAIN || errno == EINTR) {
continue;
} else {
- ret = -1;
break;
}
} else if (ret == 0) {
static int print_block_option_help(const char *filename, const char *fmt)
{
BlockDriver *drv, *proto_drv;
- QEMUOptionParameter *create_options = NULL;
+ QemuOptsList *create_opts = NULL;
/* Find driver and parse its options */
drv = bdrv_find_format(fmt);
return 1;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
-
+ create_opts = qemu_opts_append(create_opts, drv->create_opts);
if (filename) {
proto_drv = bdrv_find_protocol(filename, true);
if (!proto_drv) {
error_report("Unknown protocol '%s'", filename);
+ qemu_opts_free(create_opts);
return 1;
}
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
}
- print_option_help(create_options);
- free_option_parameters(create_options);
+ qemu_opts_print_help(create_opts);
+ qemu_opts_free(create_opts);
return 0;
}
-static BlockDriverState *bdrv_new_open(const char *filename,
+static BlockDriverState *bdrv_new_open(const char *id,
+ const char *filename,
const char *fmt,
int flags,
bool require_io,
Error *local_err = NULL;
int ret;
- bs = bdrv_new("image");
+ bs = bdrv_new(id, &error_abort);
if (fmt) {
drv = bdrv_find_format(fmt);
return NULL;
}
-static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
+static int add_old_style_options(const char *fmt, QemuOpts *opts,
const char *base_filename,
const char *base_fmt)
{
if (base_filename) {
- if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
error_report("Backing file not supported for file format '%s'",
fmt);
return -1;
}
}
if (base_fmt) {
- if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
error_report("Backing file format not supported for file "
"format '%s'", fmt);
return -1;
}
if (optind >= argc) {
- help();
+ error_exit("Expecting image file name");
}
optind++;
img_size = (uint64_t)sval;
}
if (optind != argc) {
- help();
+ error_exit("Unexpected argument: %s", argv[optind]);
}
bdrv_img_create(filename, fmt, base_filename, base_fmt,
static void dump_json_image_check(ImageCheck *check, bool quiet)
{
- Error *errp = NULL;
+ Error *local_err = NULL;
QString *str;
QmpOutputVisitor *ov = qmp_output_visitor_new();
QObject *obj;
visit_type_ImageCheck(qmp_output_get_visitor(ov),
- &check, NULL, &errp);
+ &check, NULL, &local_err);
obj = qmp_output_get_qobject(ov);
str = qobject_to_json_pretty(obj);
assert(str != NULL);
/*
* Checks an image for consistency. Exit codes:
*
- * 0 - Check completed, image is good
- * 1 - Check not completed because of internal errors
- * 2 - Check completed, image is corrupted
- * 3 - Check completed, image has leaked clusters, but is good otherwise
+ * 0 - Check completed, image is good
+ * 1 - Check not completed because of internal errors
+ * 2 - Check completed, image is corrupted
+ * 3 - Check completed, image has leaked clusters, but is good otherwise
+ * 63 - Checks are not supported by the image format
*/
static int img_check(int argc, char **argv)
{
int c, ret;
OutputFormat output_format = OFORMAT_HUMAN;
- const char *filename, *fmt, *output;
+ const char *filename, *fmt, *output, *cache;
BlockDriverState *bs;
int fix = 0;
int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
fmt = NULL;
output = NULL;
+ cache = BDRV_DEFAULT_CACHE;
for(;;) {
int option_index = 0;
static const struct option long_options[] = {
{"output", required_argument, 0, OPTION_OUTPUT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "f:hr:q",
+ c = getopt_long(argc, argv, "hf:r:T:q",
long_options, &option_index);
if (c == -1) {
break;
} else if (!strcmp(optarg, "all")) {
fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
} else {
- help();
+ error_exit("Unknown option value for -r "
+ "(expecting 'leaks' or 'all'): %s", optarg);
}
break;
case OPTION_OUTPUT:
output = optarg;
break;
+ case 'T':
+ cache = optarg;
+ break;
case 'q':
quiet = true;
break;
}
}
if (optind != argc - 1) {
- help();
+ error_exit("Expecting one image file name");
}
filename = argv[optind++];
return 1;
}
- bs = bdrv_new_open(filename, fmt, flags, true, quiet);
+ ret = bdrv_parse_cache_flags(cache, &flags);
+ if (ret < 0) {
+ error_report("Invalid source cache option: %s", cache);
+ return 1;
+ }
+
+ bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
if (!bs) {
return 1;
}
ret = collect_image_check(bs, check, filename, fmt, fix);
if (ret == -ENOTSUP) {
- if (output_format == OFORMAT_HUMAN) {
- error_report("This image format does not support checks");
- }
+ error_report("This image format does not support checks");
ret = 63;
goto fail;
}
}
}
if (optind != argc - 1) {
- help();
+ error_exit("Expecting one image file name");
}
filename = argv[optind++];
ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
- return -1;
+ return 1;
}
- bs = bdrv_new_open(filename, fmt, flags, true, quiet);
+ bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
if (!bs) {
return 1;
}
*/
static int img_compare(int argc, char **argv)
{
- const char *fmt1 = NULL, *fmt2 = NULL, *filename1, *filename2;
+ const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
BlockDriverState *bs1, *bs2;
int64_t total_sectors1, total_sectors2;
uint8_t *buf1 = NULL, *buf2 = NULL;
int allocated1, allocated2;
int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
bool progress = false, quiet = false, strict = false;
+ int flags;
int64_t total_sectors;
int64_t sector_num = 0;
int64_t nb_sectors;
int c, pnum;
- uint64_t bs_sectors;
uint64_t progress_base;
+ cache = BDRV_DEFAULT_CACHE;
for (;;) {
- c = getopt(argc, argv, "hpf:F:sq");
+ c = getopt(argc, argv, "hf:F:T:pqs");
if (c == -1) {
break;
}
case 'F':
fmt2 = optarg;
break;
+ case 'T':
+ cache = optarg;
+ break;
case 'p':
progress = true;
break;
if (optind != argc - 2) {
- help();
+ error_exit("Expecting two image file names");
}
filename1 = argv[optind++];
filename2 = argv[optind++];
/* Initialize before goto out */
qemu_progress_init(progress, 2.0);
- bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
+ flags = BDRV_O_FLAGS;
+ ret = bdrv_parse_cache_flags(cache, &flags);
+ if (ret < 0) {
+ error_report("Invalid source cache option: %s", cache);
+ ret = 2;
+ goto out3;
+ }
+
+ bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
if (!bs1) {
error_report("Can't open file %s", filename1);
ret = 2;
goto out3;
}
- bs2 = bdrv_new_open(filename2, fmt2, BDRV_O_FLAGS, true, quiet);
+ bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
if (!bs2) {
error_report("Can't open file %s", filename2);
ret = 2;
buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
- bdrv_get_geometry(bs1, &bs_sectors);
- total_sectors1 = bs_sectors;
- bdrv_get_geometry(bs2, &bs_sectors);
- total_sectors2 = bs_sectors;
+ total_sectors1 = bdrv_nb_sectors(bs1);
+ if (total_sectors1 < 0) {
+ error_report("Can't get size of %s: %s",
+ filename1, strerror(-total_sectors1));
+ ret = 4;
+ goto out;
+ }
+ total_sectors2 = bdrv_nb_sectors(bs2);
+ if (total_sectors2 < 0) {
+ error_report("Can't get size of %s: %s",
+ filename2, strerror(-total_sectors2));
+ ret = 4;
+ goto out;
+ }
total_sectors = MIN(total_sectors1, total_sectors2);
progress_base = MAX(total_sectors1, total_sectors2);
{
int c, n, n1, bs_n, bs_i, compress, cluster_sectors, skip_create;
int64_t ret = 0;
- int progress = 0, flags;
- const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
+ int progress = 0, flags, src_flags;
+ const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
BlockDriver *drv, *proto_drv;
BlockDriverState **bs = NULL, *out_bs = NULL;
int64_t total_sectors, nb_sectors, sector_num, bs_offset;
- uint64_t bs_sectors;
+ int64_t *bs_sectors = NULL;
uint8_t * buf = NULL;
size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
const uint8_t *buf1;
BlockDriverInfo bdi;
- QEMUOptionParameter *param = NULL, *create_options = NULL;
- QEMUOptionParameter *out_baseimg_param;
+ QemuOpts *opts = NULL;
+ QemuOptsList *create_opts = NULL;
+ const char *out_baseimg_param;
char *options = NULL;
const char *snapshot_name = NULL;
int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
fmt = NULL;
out_fmt = "raw";
cache = "unsafe";
+ src_cache = BDRV_DEFAULT_CACHE;
out_baseimg = NULL;
compress = 0;
skip_create = 0;
for(;;) {
- c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:qnl:");
+ c = getopt(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn");
if (c == -1) {
break;
}
case 't':
cache = optarg;
break;
+ case 'T':
+ src_cache = optarg;
+ break;
case 'q':
quiet = true;
break;
}
if (bs_n < 1) {
- help();
+ error_exit("Must specify image file name");
}
goto out;
}
+ src_flags = BDRV_O_FLAGS;
+ ret = bdrv_parse_cache_flags(src_cache, &src_flags);
+ if (ret < 0) {
+ error_report("Invalid source cache option: %s", src_cache);
+ goto out;
+ }
+
qemu_progress_print(0, 100);
- bs = g_malloc0(bs_n * sizeof(BlockDriverState *));
+ bs = g_new0(BlockDriverState *, bs_n);
+ bs_sectors = g_new(int64_t, bs_n);
total_sectors = 0;
for (bs_i = 0; bs_i < bs_n; bs_i++) {
- bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true,
- quiet);
+ char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
+ : g_strdup("source");
+ bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
+ true, quiet);
+ g_free(id);
if (!bs[bs_i]) {
error_report("Could not open '%s'", argv[optind + bs_i]);
ret = -1;
goto out;
}
- bdrv_get_geometry(bs[bs_i], &bs_sectors);
- total_sectors += bs_sectors;
+ bs_sectors[bs_i] = bdrv_nb_sectors(bs[bs_i]);
+ if (bs_sectors[bs_i] < 0) {
+ error_report("Could not get size of %s: %s",
+ argv[optind + bs_i], strerror(-bs_sectors[bs_i]));
+ ret = -1;
+ goto out;
+ }
+ total_sectors += bs_sectors[bs_i];
}
if (sn_opts) {
goto out;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
+ create_opts = qemu_opts_append(create_opts, drv->create_opts);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
- if (options) {
- param = parse_option_parameters(options, create_options, param);
- if (param == NULL) {
- error_report("Invalid options for file format '%s'.", out_fmt);
- ret = -1;
- goto out;
- }
- } else {
- param = parse_option_parameters("", create_options, param);
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ if (options && qemu_opts_do_parse(opts, options, NULL)) {
+ error_report("Invalid options for file format '%s'", out_fmt);
+ ret = -1;
+ goto out;
}
- set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
- ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
+ ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
if (ret < 0) {
goto out;
}
/* Get backing file name if -o backing_file was used */
- out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
+ out_baseimg_param = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
if (out_baseimg_param) {
- out_baseimg = out_baseimg_param->value.s;
+ out_baseimg = out_baseimg_param;
}
/* Check if compression is supported */
if (compress) {
- QEMUOptionParameter *encryption =
- get_option_parameter(param, BLOCK_OPT_ENCRYPT);
- QEMUOptionParameter *preallocation =
- get_option_parameter(param, BLOCK_OPT_PREALLOC);
+ bool encryption =
+ qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
+ const char *preallocation =
+ qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
if (!drv->bdrv_write_compressed) {
error_report("Compression not supported for this file format");
goto out;
}
- if (encryption && encryption->value.n) {
+ if (encryption) {
error_report("Compression and encryption not supported at "
"the same time");
ret = -1;
goto out;
}
- if (preallocation && preallocation->value.s
- && strcmp(preallocation->value.s, "off"))
+ if (preallocation
+ && strcmp(preallocation, "off"))
{
error_report("Compression and preallocation not supported at "
"the same time");
if (!skip_create) {
/* Create the new image */
- ret = bdrv_create(drv, out_filename, param, &local_err);
+ ret = bdrv_create(drv, out_filename, opts, &local_err);
if (ret < 0) {
error_report("%s: error while converting %s: %s",
out_filename, out_fmt, error_get_pretty(local_err));
ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
- return -1;
+ goto out;
}
- out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
+ out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
if (!out_bs) {
ret = -1;
goto out;
bs_i = 0;
bs_offset = 0;
- bdrv_get_geometry(bs[0], &bs_sectors);
/* increase bufsectors from the default 4096 (2M) if opt_transfer_length
* or discard_alignment of the out_bs is greater. Limit to 32768 (16MB)
buf = qemu_blockalign(out_bs, bufsectors * BDRV_SECTOR_SIZE);
if (skip_create) {
- int64_t output_length = bdrv_getlength(out_bs);
- if (output_length < 0) {
+ int64_t output_sectors = bdrv_nb_sectors(out_bs);
+ if (output_sectors < 0) {
error_report("unable to get output image length: %s\n",
- strerror(-output_length));
+ strerror(-output_sectors));
ret = -1;
goto out;
- } else if (output_length < total_sectors << BDRV_SECTOR_BITS) {
+ } else if (output_sectors < total_sectors) {
error_report("output file is smaller than input file");
ret = -1;
goto out;
goto out;
}
} else {
+ compress = compress || bdi.needs_compressed_writes;
cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
}
buf2 = buf;
while (remainder > 0) {
int nlow;
- while (bs_num == bs_sectors) {
+ while (bs_num == bs_sectors[bs_i]) {
+ bs_offset += bs_sectors[bs_i];
bs_i++;
assert (bs_i < bs_n);
- bs_offset += bs_sectors;
- bdrv_get_geometry(bs[bs_i], &bs_sectors);
bs_num = 0;
/* printf("changing part: sector_num=%" PRId64 ", "
"bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
- "\n", sector_num, bs_i, bs_offset, bs_sectors); */
+ "\n", sector_num, bs_i, bs_offset, bs_sectors[bs_i]); */
}
- assert (bs_num < bs_sectors);
+ assert (bs_num < bs_sectors[bs_i]);
- nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
+ nlow = remainder > bs_sectors[bs_i] - bs_num
+ ? bs_sectors[bs_i] - bs_num : remainder;
ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
if (ret < 0) {
break;
}
- while (sector_num - bs_offset >= bs_sectors) {
+ while (sector_num - bs_offset >= bs_sectors[bs_i]) {
+ bs_offset += bs_sectors[bs_i];
bs_i ++;
assert (bs_i < bs_n);
- bs_offset += bs_sectors;
- bdrv_get_geometry(bs[bs_i], &bs_sectors);
/* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
"bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
- sector_num, bs_i, bs_offset, bs_sectors); */
+ sector_num, bs_i, bs_offset, bs_sectors[bs_i]); */
}
if ((out_baseimg || has_zero_init) &&
}
}
- n = MIN(n, bs_sectors - (sector_num - bs_offset));
+ n = MIN(n, bs_sectors[bs_i] - (sector_num - bs_offset));
sectors_read += n;
if (count_allocated_sectors) {
qemu_progress_print(100, 0);
}
qemu_progress_end();
- free_option_parameters(create_options);
- free_option_parameters(param);
+ qemu_opts_del(opts);
+ qemu_opts_free(create_opts);
qemu_vfree(buf);
if (sn_opts) {
qemu_opts_del(sn_opts);
}
g_free(bs);
}
+ g_free(bs_sectors);
fail_getopt:
g_free(options);
static void dump_json_image_info_list(ImageInfoList *list)
{
- Error *errp = NULL;
+ Error *local_err = NULL;
QString *str;
QmpOutputVisitor *ov = qmp_output_visitor_new();
QObject *obj;
visit_type_ImageInfoList(qmp_output_get_visitor(ov),
- &list, NULL, &errp);
+ &list, NULL, &local_err);
obj = qmp_output_get_qobject(ov);
str = qobject_to_json_pretty(obj);
assert(str != NULL);
static void dump_json_image_info(ImageInfo *info)
{
- Error *errp = NULL;
+ Error *local_err = NULL;
QString *str;
QmpOutputVisitor *ov = qmp_output_visitor_new();
QObject *obj;
visit_type_ImageInfo(qmp_output_get_visitor(ov),
- &info, NULL, &errp);
+ &info, NULL, &local_err);
obj = qmp_output_get_qobject(ov);
str = qobject_to_json_pretty(obj);
assert(str != NULL);
}
g_hash_table_insert(filenames, (gpointer)filename, NULL);
- bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
- false, false);
+ bs = bdrv_new_open("image", filename, fmt,
+ BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
if (!bs) {
goto err;
}
if (err) {
error_report("%s", error_get_pretty(err));
error_free(err);
+ bdrv_unref(bs);
goto err;
}
}
}
if (optind != argc - 1) {
- help();
+ error_exit("Expecting one image file name");
}
filename = argv[optind++];
break;
}
}
- if (optind >= argc) {
- help();
+ if (optind != argc - 1) {
+ error_exit("Expecting one image file name");
}
- filename = argv[optind++];
+ filename = argv[optind];
if (output && !strcmp(output, "json")) {
output_format = OFORMAT_JSON;
return 1;
}
- bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS, true, false);
+ bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
if (!bs) {
return 1;
}
return 0;
case 'l':
if (action) {
- help();
+ error_exit("Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_LIST;
break;
case 'a':
if (action) {
- help();
+ error_exit("Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_APPLY;
break;
case 'c':
if (action) {
- help();
+ error_exit("Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_CREATE;
break;
case 'd':
if (action) {
- help();
+ error_exit("Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_DELETE;
}
if (optind != argc - 1) {
- help();
+ error_exit("Expecting one image file name");
}
filename = argv[optind++];
/* Open the image */
- bs = bdrv_new_open(filename, NULL, bdrv_oflags, true, quiet);
+ bs = bdrv_new_open("image", filename, NULL, bdrv_oflags, true, quiet);
if (!bs) {
return 1;
}
static int img_rebase(int argc, char **argv)
{
- BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
+ BlockDriverState *bs = NULL, *bs_old_backing = NULL, *bs_new_backing = NULL;
BlockDriver *old_backing_drv, *new_backing_drv;
char *filename;
- const char *fmt, *cache, *out_basefmt, *out_baseimg;
- int c, flags, ret;
+ const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg;
+ int c, flags, src_flags, ret;
int unsafe = 0;
int progress = 0;
bool quiet = false;
/* Parse commandline parameters */
fmt = NULL;
cache = BDRV_DEFAULT_CACHE;
+ src_cache = BDRV_DEFAULT_CACHE;
out_baseimg = NULL;
out_basefmt = NULL;
for(;;) {
- c = getopt(argc, argv, "uhf:F:b:pt:q");
+ c = getopt(argc, argv, "hf:F:b:upt:T:q");
if (c == -1) {
break;
}
case 't':
cache = optarg;
break;
+ case 'T':
+ src_cache = optarg;
+ break;
case 'q':
quiet = true;
break;
progress = 0;
}
- if ((optind != argc - 1) || (!unsafe && !out_baseimg)) {
- help();
+ if (optind != argc - 1) {
+ error_exit("Expecting one image file name");
+ }
+ if (!unsafe && !out_baseimg) {
+ error_exit("Must specify backing file (-b) or use unsafe mode (-u)");
}
filename = argv[optind++];
ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
- return -1;
+ goto out;
+ }
+
+ src_flags = BDRV_O_FLAGS;
+ ret = bdrv_parse_cache_flags(src_cache, &src_flags);
+ if (ret < 0) {
+ error_report("Invalid source cache option: %s", src_cache);
+ goto out;
}
/*
* Ignore the old backing file for unsafe rebase in case we want to correct
* the reference to a renamed or moved backing file.
*/
- bs = bdrv_new_open(filename, fmt, flags, true, quiet);
+ bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
if (!bs) {
- return 1;
+ ret = -1;
+ goto out;
}
/* Find the right drivers for the backing files */
}
/* For safe rebasing we need to compare old and new backing file */
- if (unsafe) {
- /* Make the compiler happy */
- bs_old_backing = NULL;
- bs_new_backing = NULL;
- } else {
+ if (!unsafe) {
char backing_name[1024];
- bs_old_backing = bdrv_new("old_backing");
+ bs_old_backing = bdrv_new("old_backing", &error_abort);
bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
- ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, BDRV_O_FLAGS,
+ ret = bdrv_open(&bs_old_backing, backing_name, NULL, NULL, src_flags,
old_backing_drv, &local_err);
if (ret) {
error_report("Could not open old backing file '%s': %s",
goto out;
}
if (out_baseimg[0]) {
- bs_new_backing = bdrv_new("new_backing");
- ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL,
- BDRV_O_FLAGS, new_backing_drv, &local_err);
+ bs_new_backing = bdrv_new("new_backing", &error_abort);
+ ret = bdrv_open(&bs_new_backing, out_baseimg, NULL, NULL, src_flags,
+ new_backing_drv, &local_err);
if (ret) {
error_report("Could not open new backing file '%s': %s",
out_baseimg, error_get_pretty(local_err));
* the image is the same as the original one at any time.
*/
if (!unsafe) {
- uint64_t num_sectors;
- uint64_t old_backing_num_sectors;
- uint64_t new_backing_num_sectors = 0;
+ int64_t num_sectors;
+ int64_t old_backing_num_sectors;
+ int64_t new_backing_num_sectors = 0;
uint64_t sector;
int n;
uint8_t * buf_old;
buf_old = qemu_blockalign(bs, IO_BUF_SIZE);
buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
- bdrv_get_geometry(bs, &num_sectors);
- bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
+ num_sectors = bdrv_nb_sectors(bs);
+ if (num_sectors < 0) {
+ error_report("Could not get size of '%s': %s",
+ filename, strerror(-num_sectors));
+ ret = -1;
+ goto out;
+ }
+ old_backing_num_sectors = bdrv_nb_sectors(bs_old_backing);
+ if (old_backing_num_sectors < 0) {
+ char backing_name[1024];
+
+ bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
+ error_report("Could not get size of '%s': %s",
+ backing_name, strerror(-old_backing_num_sectors));
+ ret = -1;
+ goto out;
+ }
if (bs_new_backing) {
- bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
+ new_backing_num_sectors = bdrv_nb_sectors(bs_new_backing);
+ if (new_backing_num_sectors < 0) {
+ error_report("Could not get size of '%s': %s",
+ out_baseimg, strerror(-new_backing_num_sectors));
+ ret = -1;
+ goto out;
+ }
}
if (num_sectors != 0) {
/* Remove size from argv manually so that negative numbers are not treated
* as options by getopt. */
if (argc < 3) {
- help();
+ error_exit("Not enough arguments");
return 1;
}
}
}
if (optind != argc - 1) {
- help();
+ error_exit("Expecting one image file name");
}
filename = argv[optind++];
n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
qemu_opts_del(param);
- bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
+ bs = bdrv_new_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
+ true, quiet);
if (!bs) {
ret = -1;
goto out;
{
int c, ret = 0;
char *options = NULL;
- QEMUOptionParameter *create_options = NULL, *options_param = NULL;
- const char *fmt = NULL, *filename;
+ QemuOptsList *create_opts = NULL;
+ QemuOpts *opts = NULL;
+ const char *fmt = NULL, *filename, *cache;
+ int flags;
bool quiet = false;
BlockDriverState *bs = NULL;
+ cache = BDRV_DEFAULT_CACHE;
for (;;) {
- c = getopt(argc, argv, "hqf:o:");
+ c = getopt(argc, argv, "ho:f:t:q");
if (c == -1) {
break;
}
case 'f':
fmt = optarg;
break;
+ case 't':
+ cache = optarg;
+ break;
case 'q':
quiet = true;
break;
}
if (!options) {
- help();
+ error_exit("Must specify options (-o)");
}
filename = (optind == argc - 1) ? argv[argc - 1] : NULL;
}
if (optind != argc - 1) {
- help();
+ error_exit("Expecting one image file name");
+ }
+
+ flags = BDRV_O_FLAGS | BDRV_O_RDWR;
+ ret = bdrv_parse_cache_flags(cache, &flags);
+ if (ret < 0) {
+ error_report("Invalid cache option: %s", cache);
+ goto out;
}
- bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
+ bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
if (!bs) {
error_report("Could not open image '%s'", filename);
ret = -1;
goto out;
}
- create_options = append_option_parameters(create_options,
- bs->drv->create_options);
- options_param = parse_option_parameters(options, create_options,
- options_param);
- if (options_param == NULL) {
+ create_opts = qemu_opts_append(create_opts, bs->drv->create_opts);
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ if (options && qemu_opts_do_parse(opts, options, NULL)) {
error_report("Invalid options for file format '%s'", fmt);
ret = -1;
goto out;
}
- ret = bdrv_amend_options(bs, options_param);
+ ret = bdrv_amend_options(bs, opts);
if (ret < 0) {
error_report("Error while amending options: %s", strerror(-ret));
goto out;
if (bs) {
bdrv_unref(bs);
}
- free_option_parameters(create_options);
- free_option_parameters(options_param);
+ qemu_opts_del(opts);
+ qemu_opts_free(create_opts);
g_free(options);
if (ret) {
{
const img_cmd_t *cmd;
const char *cmdname;
+ int c;
+ static const struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
#ifdef CONFIG_POSIX
signal(SIGPIPE, SIG_IGN);
qemu_init_main_loop();
bdrv_init();
- if (argc < 2)
- help();
+ if (argc < 2) {
+ error_exit("Not enough arguments");
+ }
cmdname = argv[1];
- argc--; argv++;
/* find the command */
- for(cmd = img_cmds; cmd->name != NULL; cmd++) {
+ for (cmd = img_cmds; cmd->name != NULL; cmd++) {
if (!strcmp(cmdname, cmd->name)) {
- return cmd->handler(argc, argv);
+ return cmd->handler(argc - 1, argv + 1);
}
}
+ c = getopt_long(argc, argv, "h", long_options, NULL);
+
+ if (c == 'h') {
+ help();
+ }
+ if (c == 'v') {
+ printf(QEMU_IMG_VERSION);
+ return 0;
+ }
+
/* not found */
- help();
- return 0;
+ error_exit("Command not found: %s", cmdname);
}