"QEMU disk image utility\n"
"\n"
"Command syntax:\n"
+ " check [-f fmt] filename\n"
" create [-e] [-6] [-F fmt] [-b base_image] [-f fmt] filename [size]\n"
" commit [-f fmt] filename\n"
" convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
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("Error while formatting");
}
return 0;
}
+static int img_check(int argc, char **argv)
+{
+ int c, ret;
+ const char *filename, *fmt;
+ BlockDriver *drv;
+ BlockDriverState *bs;
+
+ fmt = NULL;
+ for(;;) {
+ c = getopt(argc, argv, "f:h");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ }
+ }
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+
+ bs = bdrv_new("");
+ if (!bs)
+ error("Not enough memory");
+ if (fmt) {
+ drv = bdrv_find_format(fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
+ } else {
+ drv = NULL;
+ }
+ if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
+ error("Could not open '%s'", filename);
+ }
+ ret = bdrv_check(bs);
+ switch(ret) {
+ case 0:
+ printf("No errors were found on the image.\n");
+ break;
+ case -ENOTSUP:
+ error("This image format does not support checks");
+ break;
+ default:
+ if (ret < 0) {
+ error("An error occurred during the check");
+ } else {
+ printf("%d errors were found on the image.\n", ret);
+ }
+ break;
+ }
+
+ bdrv_delete(bs);
+ return 0;
+}
+
static int img_commit(int argc, char **argv)
{
int c, ret;
ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
if (ret < 0) {
if (ret == -ENOTSUP) {
- error("Formatting not supported for file format '%s'", fmt);
+ error("Formatting not supported for file format '%s'", out_fmt);
+ } else if (ret == -EFBIG) {
+ error("The image size is too large for file format '%s'", out_fmt);
} else {
error("Error while formatting '%s'", out_filename);
}
if (n > bs_offset + bs_sectors - sector_num)
n = bs_offset + bs_sectors - sector_num;
- /* If the output image is being created as a copy on write image,
- assume that sectors which are unallocated in the input image
- are present in both the output's and input's base images (no
- need to copy them). */
- if (out_baseimg) {
- if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, n, &n1)) {
- sector_num += n1;
- continue;
- }
- /* The next 'n1' sectors are allocated in the input image. Copy
- only those as they may be followed by unallocated sectors. */
- n = n1;
+ if (drv != &bdrv_host_device) {
+ if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
+ n, &n1)) {
+ sector_num += n1;
+ continue;
+ }
+ /* The next 'n1' sectors are allocated in the input image. Copy
+ only those as they may be followed by unallocated sectors. */
+ n = n1;
+ } else {
+ n1 = n;
}
if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
while (n > 0) {
/* If the output image is being created as a copy on write image,
copy all sectors even the ones containing only NUL bytes,
- because they may differ from the sectors in the base image. */
- if (out_baseimg || is_allocated_sectors(buf1, n, &n1)) {
+ because they may differ from the sectors in the base image.
+
+ If the output is to a host device, we also write out
+ sectors that are entirely 0, since whatever data was
+ already there is garbage, not 0s. */
+ if (drv == &bdrv_host_device || out_baseimg ||
+ is_allocated_sectors(buf1, n, &n1)) {
if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
error("error while writing");
}
argc--; argv++;
if (!strcmp(cmd, "create")) {
img_create(argc, argv);
+ } else if (!strcmp(cmd, "check")) {
+ img_check(argc, argv);
} else if (!strcmp(cmd, "commit")) {
img_commit(argc, argv);
} else if (!strcmp(cmd, "convert")) {