static int img_convert(int argc, char **argv) { int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors; const char *fmt, *out_fmt, *out_baseimg, *out_filename; BlockDriver *drv; BlockDriverState **bs, *out_bs; int64_t total_sectors, nb_sectors, sector_num, bs_offset; uint64_t bs_sectors; uint8_t buf[IO_BUF_SIZE]; const uint8_t *buf1; BlockDriverInfo bdi; fmt = NULL; out_fmt = "raw"; out_baseimg = NULL; flags = 0; for(;;) { c = getopt(argc, argv, "f:O:B:hce6"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'B': out_baseimg = optarg; break; case 'c': flags |= BLOCK_FLAG_COMPRESS; break; case 'e': flags |= BLOCK_FLAG_ENCRYPT; break; case '6': flags |= BLOCK_FLAG_COMPAT6; break; } } bs_n = argc - optind - 1; if (bs_n < 1) help(); out_filename = argv[argc - 1]; if (bs_n > 1 && out_baseimg) error("-B makes no sense when concatenating multiple input images"); bs = calloc(bs_n, sizeof(BlockDriverState *)); if (!bs) error("Out of memory"); 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_CACHE_WB|BDRV_O_RDONLY); if (!bs[bs_i]) error("Could not open '%s'", argv[optind + bs_i]); bdrv_get_geometry(bs[bs_i], &bs_sectors); total_sectors += bs_sectors; } drv = bdrv_find_format(out_fmt); if (!drv) error("Unknown file format '%s'", out_fmt); if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Compression not supported for this file format"); if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Encryption not supported for this file format"); if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk) error("Alternative compatibility level not supported for this file format"); 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); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting not supported for file format '%s'", fmt); } else { error("Error while formatting '%s'", out_filename); } } out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_CACHE_WB|BDRV_O_RDWR); bs_i = 0; bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); if (flags & BLOCK_FLAG_COMPRESS) { if (bdrv_get_info(out_bs, &bdi) < 0) error("could not get block driver info"); cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) error("invalid cluster size"); cluster_sectors = cluster_size >> 9; sector_num = 0; for(;;) { int64_t bs_num; int remainder; uint8_t *buf2; nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; bs_num = sector_num - bs_offset; assert (bs_num >= 0); remainder = n; buf2 = buf; while (remainder > 0) { int nlow; while (bs_num == bs_sectors) { 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=%lld, " "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n", sector_num, bs_i, bs_offset, bs_sectors); */ } assert (bs_num < bs_sectors); nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder; if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) error("error while reading"); buf2 += nlow * 512; bs_num += nlow; remainder -= nlow; } assert (remainder == 0); if (n < cluster_sectors) memset(buf + n * 512, 0, cluster_size - n * 512); if (is_not_zero(buf, cluster_size)) { if (bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors) != 0) error("error while compressing sector %" PRId64, sector_num); } sector_num += n; } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {
static int img_convert(int argc, char **argv) { int c, ret, n, n1, compress, cluster_size, cluster_sectors, encrypt; const char *filename, *fmt, *out_fmt, *out_filename; BlockDriver *drv; BlockDriverState *bs, *out_bs; int64_t total_sectors, nb_sectors, sector_num; uint8_t buf[IO_BUF_SIZE]; const uint8_t *buf1; BlockDriverInfo bdi; fmt = NULL; out_fmt = "raw"; compress = 0; encrypt = 0; for(;;) { c = getopt(argc, argv, "f:O:hce"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'c': compress = 1; break; case 'e': encrypt = 1; break; } } if (optind >= argc) help(); filename = argv[optind++]; if (optind >= argc) help(); out_filename = argv[optind++]; bs = bdrv_new_open(filename, fmt); drv = bdrv_find_format(out_fmt); if (!drv) error("Unknown file format '%s'", fmt); if (compress && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Compression not supported for this file format"); if (encrypt && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Encryption not supported for this file format"); if (compress && encrypt) error("Compression and encryption not supported at the same time"); bdrv_get_geometry(bs, &total_sectors); ret = bdrv_create(drv, out_filename, total_sectors, NULL, encrypt); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting not supported for file format '%s'", fmt); } else { error("Error while formatting '%s'", out_filename); } } out_bs = bdrv_new_open(out_filename, out_fmt); if (compress) { if (bdrv_get_info(out_bs, &bdi) < 0) error("could not get block driver info"); cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) error("invalid cluster size"); cluster_sectors = cluster_size >> 9; sector_num = 0; for(;;) { nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; if (bdrv_read(bs, sector_num, buf, n) < 0) error("error while reading"); if (n < cluster_sectors) memset(buf + n * 512, 0, cluster_size - n * 512); if (is_not_zero(buf, cluster_size)) { if (bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors) != 0) error("error while compressing sector %" PRId64, sector_num); } sector_num += n; } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {