Revision 926c2d23 qemu-img.c
b/qemu-img.c | ||
---|---|---|
23 | 23 |
*/ |
24 | 24 |
#include "vl.h" |
25 | 25 |
#include "block_int.h" |
26 |
#include <assert.h> |
|
26 | 27 |
|
27 | 28 |
#ifdef _WIN32 |
28 | 29 |
#include <windows.h> |
... | ... | |
101 | 102 |
"Command syntax:\n" |
102 | 103 |
" create [-e] [-6] [-b base_image] [-f fmt] filename [size]\n" |
103 | 104 |
" commit [-f fmt] filename\n" |
104 |
" convert [-c] [-e] [-6] [-f fmt] filename [-O output_fmt] output_filename\n" |
|
105 |
" convert [-c] [-e] [-6] [-f fmt] filename [filename2 [...]] [-O output_fmt] output_filename\n"
|
|
105 | 106 |
" info [-f fmt] filename\n" |
106 | 107 |
"\n" |
107 | 108 |
"Command parameters:\n" |
... | ... | |
418 | 419 |
|
419 | 420 |
static int img_convert(int argc, char **argv) |
420 | 421 |
{ |
421 |
int c, ret, n, n1, flags, cluster_size, cluster_sectors; |
|
422 |
const char *filename, *fmt, *out_fmt, *out_filename;
|
|
422 |
int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
|
|
423 |
const char *fmt, *out_fmt, *out_filename; |
|
423 | 424 |
BlockDriver *drv; |
424 |
BlockDriverState *bs, *out_bs; |
|
425 |
int64_t total_sectors, nb_sectors, sector_num; |
|
425 |
BlockDriverState **bs, *out_bs;
|
|
426 |
int64_t total_sectors, nb_sectors, sector_num, bs_offset, bs_sectors;
|
|
426 | 427 |
uint8_t buf[IO_BUF_SIZE]; |
427 | 428 |
const uint8_t *buf1; |
428 | 429 |
BlockDriverInfo bdi; |
... | ... | |
455 | 456 |
break; |
456 | 457 |
} |
457 | 458 |
} |
458 |
if (optind >= argc) |
|
459 |
help(); |
|
460 |
filename = argv[optind++]; |
|
461 |
if (optind >= argc) |
|
462 |
help(); |
|
463 |
out_filename = argv[optind++]; |
|
464 | 459 |
|
465 |
bs = bdrv_new_open(filename, fmt); |
|
460 |
bs_n = argc - optind - 1; |
|
461 |
if (bs_n < 1) help(); |
|
462 |
|
|
463 |
out_filename = argv[argc - 1]; |
|
464 |
|
|
465 |
bs = calloc(bs_n, sizeof(BlockDriverState *)); |
|
466 |
if (!bs) |
|
467 |
error("Out of memory"); |
|
468 |
|
|
469 |
total_sectors = 0; |
|
470 |
for (bs_i = 0; bs_i < bs_n; bs_i++) { |
|
471 |
bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt); |
|
472 |
if (!bs[bs_i]) |
|
473 |
error("Could not open '%s'", argv[optind + bs_i]); |
|
474 |
bdrv_get_geometry(bs[bs_i], &bs_sectors); |
|
475 |
total_sectors += bs_sectors; |
|
476 |
} |
|
466 | 477 |
|
467 | 478 |
drv = bdrv_find_format(out_fmt); |
468 | 479 |
if (!drv) |
... | ... | |
475 | 486 |
error("Alternative compatibility level not supported for this file format"); |
476 | 487 |
if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS) |
477 | 488 |
error("Compression and encryption not supported at the same time"); |
478 |
bdrv_get_geometry(bs, &total_sectors); |
|
489 |
|
|
479 | 490 |
ret = bdrv_create(drv, out_filename, total_sectors, NULL, flags); |
480 | 491 |
if (ret < 0) { |
481 | 492 |
if (ret == -ENOTSUP) { |
... | ... | |
487 | 498 |
|
488 | 499 |
out_bs = bdrv_new_open(out_filename, out_fmt); |
489 | 500 |
|
490 |
if (flags && BLOCK_FLAG_COMPRESS) { |
|
501 |
bs_i = 0; |
|
502 |
bs_offset = 0; |
|
503 |
bdrv_get_geometry(bs[0], &bs_sectors); |
|
504 |
|
|
505 |
if (flags & BLOCK_FLAG_COMPRESS) { |
|
491 | 506 |
if (bdrv_get_info(out_bs, &bdi) < 0) |
492 | 507 |
error("could not get block driver info"); |
493 | 508 |
cluster_size = bdi.cluster_size; |
... | ... | |
496 | 511 |
cluster_sectors = cluster_size >> 9; |
497 | 512 |
sector_num = 0; |
498 | 513 |
for(;;) { |
514 |
int64_t bs_num; |
|
515 |
int remainder; |
|
516 |
uint8_t *buf2; |
|
517 |
|
|
499 | 518 |
nb_sectors = total_sectors - sector_num; |
500 | 519 |
if (nb_sectors <= 0) |
501 | 520 |
break; |
... | ... | |
503 | 522 |
n = cluster_sectors; |
504 | 523 |
else |
505 | 524 |
n = nb_sectors; |
506 |
if (bdrv_read(bs, sector_num, buf, n) < 0) |
|
507 |
error("error while reading"); |
|
525 |
|
|
526 |
bs_num = sector_num - bs_offset; |
|
527 |
assert (bs_num >= 0); |
|
528 |
remainder = n; |
|
529 |
buf2 = buf; |
|
530 |
while (remainder > 0) { |
|
531 |
int nlow; |
|
532 |
while (bs_num == bs_sectors) { |
|
533 |
bs_i++; |
|
534 |
assert (bs_i < bs_n); |
|
535 |
bs_offset += bs_sectors; |
|
536 |
bdrv_get_geometry(bs[bs_i], &bs_sectors); |
|
537 |
bs_num = 0; |
|
538 |
/* printf("changing part: sector_num=%lld, " |
|
539 |
"bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n", |
|
540 |
sector_num, bs_i, bs_offset, bs_sectors); */ |
|
541 |
} |
|
542 |
assert (bs_num < bs_sectors); |
|
543 |
|
|
544 |
nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder; |
|
545 |
|
|
546 |
if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) |
|
547 |
error("error while reading"); |
|
548 |
|
|
549 |
buf2 += nlow * 512; |
|
550 |
bs_num += nlow; |
|
551 |
|
|
552 |
remainder -= nlow; |
|
553 |
} |
|
554 |
assert (remainder == 0); |
|
555 |
|
|
508 | 556 |
if (n < cluster_sectors) |
509 | 557 |
memset(buf + n * 512, 0, cluster_size - n * 512); |
510 | 558 |
if (is_not_zero(buf, cluster_size)) { |
... | ... | |
527 | 575 |
n = (IO_BUF_SIZE / 512); |
528 | 576 |
else |
529 | 577 |
n = nb_sectors; |
530 |
if (bdrv_read(bs, sector_num, buf, n) < 0) |
|
578 |
|
|
579 |
while (sector_num - bs_offset >= bs_sectors) { |
|
580 |
bs_i ++; |
|
581 |
assert (bs_i < bs_n); |
|
582 |
bs_offset += bs_sectors; |
|
583 |
bdrv_get_geometry(bs[bs_i], &bs_sectors); |
|
584 |
/* printf("changing part: sector_num=%lld, bs_i=%d, " |
|
585 |
"bs_offset=%lld, bs_sectors=%lld\n", |
|
586 |
sector_num, bs_i, bs_offset, bs_sectors); */ |
|
587 |
} |
|
588 |
|
|
589 |
if (n > bs_offset + bs_sectors - sector_num) |
|
590 |
n = bs_offset + bs_sectors - sector_num; |
|
591 |
|
|
592 |
if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) |
|
531 | 593 |
error("error while reading"); |
532 | 594 |
/* NOTE: at the same time we convert, we do not write zero |
533 | 595 |
sectors to have a chance to compress the image. Ideally, we |
... | ... | |
545 | 607 |
} |
546 | 608 |
} |
547 | 609 |
bdrv_delete(out_bs); |
548 |
bdrv_delete(bs); |
|
610 |
for (bs_i = 0; bs_i < bs_n; bs_i++) |
|
611 |
bdrv_delete(bs[bs_i]); |
|
612 |
free(bs); |
|
549 | 613 |
return 0; |
550 | 614 |
} |
551 | 615 |
|
Also available in: Unified diff