Commit 926c2d23dfa599ea8c8213342b21cfe56b1d22ca

Authored by balrog
1 parent fe8f78e4

Support multipart images as input to qemu-img (Salvador Fandino).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3496 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 82 additions and 18 deletions
qemu-img.c
@@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
23 */ 23 */
24 #include "vl.h" 24 #include "vl.h"
25 #include "block_int.h" 25 #include "block_int.h"
  26 +#include <assert.h>
26 27
27 #ifdef _WIN32 28 #ifdef _WIN32
28 #include <windows.h> 29 #include <windows.h>
@@ -101,7 +102,7 @@ void help(void) @@ -101,7 +102,7 @@ void help(void)
101 "Command syntax:\n" 102 "Command syntax:\n"
102 " create [-e] [-6] [-b base_image] [-f fmt] filename [size]\n" 103 " create [-e] [-6] [-b base_image] [-f fmt] filename [size]\n"
103 " commit [-f fmt] filename\n" 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 " info [-f fmt] filename\n" 106 " info [-f fmt] filename\n"
106 "\n" 107 "\n"
107 "Command parameters:\n" 108 "Command parameters:\n"
@@ -418,11 +419,11 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum) @@ -418,11 +419,11 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
418 419
419 static int img_convert(int argc, char **argv) 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 BlockDriver *drv; 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 uint8_t buf[IO_BUF_SIZE]; 427 uint8_t buf[IO_BUF_SIZE];
427 const uint8_t *buf1; 428 const uint8_t *buf1;
428 BlockDriverInfo bdi; 429 BlockDriverInfo bdi;
@@ -455,14 +456,24 @@ static int img_convert(int argc, char **argv) @@ -455,14 +456,24 @@ static int img_convert(int argc, char **argv)
455 break; 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 drv = bdrv_find_format(out_fmt); 478 drv = bdrv_find_format(out_fmt);
468 if (!drv) 479 if (!drv)
@@ -475,7 +486,7 @@ static int img_convert(int argc, char **argv) @@ -475,7 +486,7 @@ static int img_convert(int argc, char **argv)
475 error("Alternative compatibility level not supported for this file format"); 486 error("Alternative compatibility level not supported for this file format");
476 if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS) 487 if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
477 error("Compression and encryption not supported at the same time"); 488 error("Compression and encryption not supported at the same time");
478 - bdrv_get_geometry(bs, &total_sectors); 489 +
479 ret = bdrv_create(drv, out_filename, total_sectors, NULL, flags); 490 ret = bdrv_create(drv, out_filename, total_sectors, NULL, flags);
480 if (ret < 0) { 491 if (ret < 0) {
481 if (ret == -ENOTSUP) { 492 if (ret == -ENOTSUP) {
@@ -487,7 +498,11 @@ static int img_convert(int argc, char **argv) @@ -487,7 +498,11 @@ static int img_convert(int argc, char **argv)
487 498
488 out_bs = bdrv_new_open(out_filename, out_fmt); 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 if (bdrv_get_info(out_bs, &bdi) < 0) 506 if (bdrv_get_info(out_bs, &bdi) < 0)
492 error("could not get block driver info"); 507 error("could not get block driver info");
493 cluster_size = bdi.cluster_size; 508 cluster_size = bdi.cluster_size;
@@ -496,6 +511,10 @@ static int img_convert(int argc, char **argv) @@ -496,6 +511,10 @@ static int img_convert(int argc, char **argv)
496 cluster_sectors = cluster_size >> 9; 511 cluster_sectors = cluster_size >> 9;
497 sector_num = 0; 512 sector_num = 0;
498 for(;;) { 513 for(;;) {
  514 + int64_t bs_num;
  515 + int remainder;
  516 + uint8_t *buf2;
  517 +
499 nb_sectors = total_sectors - sector_num; 518 nb_sectors = total_sectors - sector_num;
500 if (nb_sectors <= 0) 519 if (nb_sectors <= 0)
501 break; 520 break;
@@ -503,8 +522,37 @@ static int img_convert(int argc, char **argv) @@ -503,8 +522,37 @@ static int img_convert(int argc, char **argv)
503 n = cluster_sectors; 522 n = cluster_sectors;
504 else 523 else
505 n = nb_sectors; 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 if (n < cluster_sectors) 556 if (n < cluster_sectors)
509 memset(buf + n * 512, 0, cluster_size - n * 512); 557 memset(buf + n * 512, 0, cluster_size - n * 512);
510 if (is_not_zero(buf, cluster_size)) { 558 if (is_not_zero(buf, cluster_size)) {
@@ -527,7 +575,21 @@ static int img_convert(int argc, char **argv) @@ -527,7 +575,21 @@ static int img_convert(int argc, char **argv)
527 n = (IO_BUF_SIZE / 512); 575 n = (IO_BUF_SIZE / 512);
528 else 576 else
529 n = nb_sectors; 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 error("error while reading"); 593 error("error while reading");
532 /* NOTE: at the same time we convert, we do not write zero 594 /* NOTE: at the same time we convert, we do not write zero
533 sectors to have a chance to compress the image. Ideally, we 595 sectors to have a chance to compress the image. Ideally, we
@@ -545,7 +607,9 @@ static int img_convert(int argc, char **argv) @@ -545,7 +607,9 @@ static int img_convert(int argc, char **argv)
545 } 607 }
546 } 608 }
547 bdrv_delete(out_bs); 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 return 0; 613 return 0;
550 } 614 }
551 615