qemu-img.c 86.1 KB
Newer Older
bellard's avatar
bellard committed
1
/*
bellard's avatar
bellard committed
2
 * QEMU disk image utility
3
 *
bellard's avatar
bellard committed
4
 * Copyright (c) 2003-2008 Fabrice Bellard
5
 *
bellard's avatar
bellard committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24 25
#include "qapi-visit.h"
#include "qapi/qmp-output-visitor.h"
26
#include "qapi/qmp/qjson.h"
pbrook's avatar
pbrook committed
27
#include "qemu-common.h"
28 29 30
#include "qemu/option.h"
#include "qemu/error-report.h"
#include "qemu/osdep.h"
31
#include "sysemu/sysemu.h"
32
#include "sysemu/block-backend.h"
33
#include "block/block_int.h"
34
#include "block/qapi.h"
35
#include <getopt.h>
36

37 38 39
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
                          ", Copyright (c) 2004-2008 Fabrice Bellard\n"

40
typedef struct img_cmd_t {
41 42
    const char *name;
    int (*handler)(int argc, char **argv);
43
} img_cmd_t;
44

45 46 47 48 49 50 51 52 53 54
enum {
    OPTION_OUTPUT = 256,
    OPTION_BACKING_CHAIN = 257,
};

typedef enum OutputFormat {
    OFORMAT_JSON,
    OFORMAT_HUMAN,
} OutputFormat;

55
/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
56
#define BDRV_O_FLAGS BDRV_O_CACHE_WB
57
#define BDRV_DEFAULT_CACHE "writeback"
58

59
static void format_print(void *opaque, const char *name)
bellard's avatar
bellard committed
60
{
61
    printf(" %s", name);
bellard's avatar
bellard committed
62 63
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77
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);
}

blueswir1's avatar
blueswir1 committed
78
/* Please keep in synch with qemu-img.texi */
79
static void QEMU_NORETURN help(void)
bellard's avatar
bellard committed
80
{
81
    const char *help_msg =
82
           QEMU_IMG_VERSION
83 84 85 86
           "usage: qemu-img command [command options]\n"
           "QEMU disk image utility\n"
           "\n"
           "Command syntax:\n"
87 88 89 90 91
#define DEF(option, callback, arg_string)        \
           "  " arg_string "\n"
#include "qemu-img-cmds.h"
#undef DEF
#undef GEN_DOCS
92 93 94 95
           "\n"
           "Command parameters:\n"
           "  'filename' is a disk image filename\n"
           "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
96
           "  'cache' is the cache mode used to write the output disk image, the valid\n"
97 98
           "    options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
           "    'directsync' and 'unsafe' (default for convert)\n"
99 100
           "  'src_cache' is the cache mode used to read input disk images, the valid\n"
           "    options are the same as for the 'cache' option\n"
101
           "  'size' is the disk image size in bytes. Optional suffixes\n"
102 103 104
           "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
           "    'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P)  are\n"
           "    supported. 'b' is ignored.\n"
105 106 107 108 109
           "  'output_filename' is the destination disk image filename\n"
           "  'output_fmt' is the destination format\n"
           "  'options' is a comma separated list of format specific options in a\n"
           "    name=value format. Use -o ? for an overview of the options supported by the\n"
           "    used format\n"
110 111 112 113 114
           "  'snapshot_param' is param used for internal snapshot, format\n"
           "    is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
           "    '[ID_OR_NAME]'\n"
           "  'snapshot_id_or_name' is deprecated, use 'snapshot_param'\n"
           "    instead\n"
115 116 117 118 119
           "  '-c' indicates that target image must be compressed (qcow format only)\n"
           "  '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
           "       match exactly. The image doesn't need a working backing file before\n"
           "       rebasing in this case (useful for renaming the backing file)\n"
           "  '-h' with or without a command shows this help and lists the supported formats\n"
120
           "  '-p' show progress of command (only certain commands)\n"
121
           "  '-q' use Quiet mode - do not print any output (except errors)\n"
122 123 124 125 126
           "  '-S' indicates the consecutive number of bytes (defaults to 4k) that must\n"
           "       contain only zeros for qemu-img to create a sparse image during\n"
           "       conversion. If the number of bytes is 0, the source will not be scanned for\n"
           "       unallocated or zero sectors, and the destination image will always be\n"
           "       fully allocated\n"
127
           "  '--output' takes the format in which the output must be done (human or json)\n"
128 129
           "  '-n' skips the target volume creation (useful if the volume is created\n"
           "       prior to running qemu-img)\n"
130
           "\n"
131 132 133 134
           "Parameters to check subcommand:\n"
           "  '-r' tries to repair any inconsistencies that are found during the check.\n"
           "       '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
           "       kinds of errors, with a higher risk of choosing the wrong fix or\n"
135
           "       hiding corruption that has already occurred.\n"
136
           "\n"
137 138 139 140 141
           "Parameters to snapshot subcommand:\n"
           "  'snapshot' is the name of the snapshot to create, apply or delete\n"
           "  '-a' applies a snapshot (revert disk to saved state)\n"
           "  '-c' creates a snapshot\n"
           "  '-d' deletes a snapshot\n"
142 143 144 145 146 147
           "  '-l' lists all snapshots in the given image\n"
           "\n"
           "Parameters to compare subcommand:\n"
           "  '-f' first image format\n"
           "  '-F' second image format\n"
           "  '-s' run in Strict mode - fail on different image size or sector allocation\n";
148 149

    printf("%s\nSupported formats:", help_msg);
150
    bdrv_iterate_format(format_print, NULL);
bellard's avatar
bellard committed
151
    printf("\n");
152
    exit(EXIT_SUCCESS);
bellard's avatar
bellard committed
153 154
}

155
static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
156 157 158 159 160 161 162 163 164 165 166
{
    int ret = 0;
    if (!quiet) {
        va_list args;
        va_start(args, fmt);
        ret = vprintf(fmt, args);
        va_end(args);
    }
    return ret;
}

bellard's avatar
bellard committed
167 168 169 170 171
#if defined(WIN32)
/* XXX: put correct support for win32 */
static int read_password(char *buf, int buf_size)
{
    int c, i;
172

bellard's avatar
bellard committed
173 174 175 176 177
    printf("Password: ");
    fflush(stdout);
    i = 0;
    for(;;) {
        c = getchar();
178 179 180 181
        if (c < 0) {
            buf[i] = '\0';
            return -1;
        } else if (c == '\n') {
bellard's avatar
bellard committed
182
            break;
183
        } else if (i < (buf_size - 1)) {
bellard's avatar
bellard committed
184
            buf[i++] = c;
185
        }
bellard's avatar
bellard committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
    }
    buf[i] = '\0';
    return 0;
}

#else

#include <termios.h>

static struct termios oldtty;

static void term_exit(void)
{
    tcsetattr (0, TCSANOW, &oldtty);
}

static void term_init(void)
{
    struct termios tty;

    tcgetattr (0, &tty);
    oldtty = tty;

    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
                          |INLCR|IGNCR|ICRNL|IXON);
    tty.c_oflag |= OPOST;
    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
    tty.c_cflag &= ~(CSIZE|PARENB);
    tty.c_cflag |= CS8;
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 0;
217

bellard's avatar
bellard committed
218 219 220 221 222
    tcsetattr (0, TCSANOW, &tty);

    atexit(term_exit);
}

pbrook's avatar
pbrook committed
223
static int read_password(char *buf, int buf_size)
bellard's avatar
bellard committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
{
    uint8_t ch;
    int i, ret;

    printf("password: ");
    fflush(stdout);
    term_init();
    i = 0;
    for(;;) {
        ret = read(0, &ch, 1);
        if (ret == -1) {
            if (errno == EAGAIN || errno == EINTR) {
                continue;
            } else {
                break;
            }
        } else if (ret == 0) {
            ret = -1;
            break;
        } else {
            if (ch == '\r') {
                ret = 0;
                break;
            }
            if (i < (buf_size - 1))
                buf[i++] = ch;
        }
    }
    term_exit();
    buf[i] = '\0';
    printf("\n");
    return ret;
}
#endif

259 260 261
static int print_block_option_help(const char *filename, const char *fmt)
{
    BlockDriver *drv, *proto_drv;
262
    QemuOptsList *create_opts = NULL;
263 264 265 266

    /* Find driver and parse its options */
    drv = bdrv_find_format(fmt);
    if (!drv) {
267
        error_report("Unknown file format '%s'", fmt);
268 269 270
        return 1;
    }

271
    create_opts = qemu_opts_append(create_opts, drv->create_opts);
272 273 274 275
    if (filename) {
        proto_drv = bdrv_find_protocol(filename, true);
        if (!proto_drv) {
            error_report("Unknown protocol '%s'", filename);
276
            qemu_opts_free(create_opts);
277 278
            return 1;
        }
279
        create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
280 281
    }

282 283
    qemu_opts_print_help(create_opts);
    qemu_opts_free(create_opts);
284 285 286
    return 0;
}

287 288 289
static BlockBackend *img_open(const char *id, const char *filename,
                              const char *fmt, int flags,
                              bool require_io, bool quiet)
290
{
291
    BlockBackend *blk;
292 293 294
    BlockDriverState *bs;
    BlockDriver *drv;
    char password[256];
295
    Error *local_err = NULL;
296
    int ret;
297

298 299
    blk = blk_new_with_bs(id, &error_abort);
    bs = blk_bs(blk);
300

301 302
    if (fmt) {
        drv = bdrv_find_format(fmt);
303
        if (!drv) {
304
            error_report("Unknown file format '%s'", fmt);
305 306
            goto fail;
        }
307 308 309
    } else {
        drv = NULL;
    }
310

311
    ret = bdrv_open(&bs, filename, NULL, NULL, flags, drv, &local_err);
312
    if (ret < 0) {
313 314 315
        error_report("Could not open '%s': %s", filename,
                     error_get_pretty(local_err));
        error_free(local_err);
316
        goto fail;
317
    }
318

319
    if (bdrv_is_encrypted(bs) && require_io) {
320
        qprintf(quiet, "Disk image '%s' is encrypted.\n", filename);
321
        if (read_password(password, sizeof(password)) < 0) {
322
            error_report("No password given");
323 324 325
            goto fail;
        }
        if (bdrv_set_key(bs, password) < 0) {
326
            error_report("invalid password");
327 328
            goto fail;
        }
329
    }
330
    return blk;
331
fail:
332
    bdrv_unref(bs);
333
    blk_unref(blk);
334
    return NULL;
335 336
}

337
static int add_old_style_options(const char *fmt, QemuOpts *opts,
338 339
                                 const char *base_filename,
                                 const char *base_fmt)
340 341
{
    if (base_filename) {
342
        if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
343 344
            error_report("Backing file not supported for file format '%s'",
                         fmt);
345
            return -1;
346 347 348
        }
    }
    if (base_fmt) {
349
        if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
350 351
            error_report("Backing file format not supported for file "
                         "format '%s'", fmt);
352
            return -1;
353 354
        }
    }
355
    return 0;
356 357
}

bellard's avatar
bellard committed
358 359
static int img_create(int argc, char **argv)
{
360
    int c;
361
    uint64_t img_size = -1;
bellard's avatar
bellard committed
362
    const char *fmt = "raw";
363
    const char *base_fmt = NULL;
bellard's avatar
bellard committed
364 365
    const char *filename;
    const char *base_filename = NULL;
366
    char *options = NULL;
367
    Error *local_err = NULL;
368
    bool quiet = false;
369

bellard's avatar
bellard committed
370
    for(;;) {
371
        c = getopt(argc, argv, "F:b:f:he6o:q");
372
        if (c == -1) {
bellard's avatar
bellard committed
373
            break;
374
        }
bellard's avatar
bellard committed
375
        switch(c) {
376
        case '?':
bellard's avatar
bellard committed
377 378 379
        case 'h':
            help();
            break;
380 381 382
        case 'F':
            base_fmt = optarg;
            break;
bellard's avatar
bellard committed
383 384 385 386 387 388 389
        case 'b':
            base_filename = optarg;
            break;
        case 'f':
            fmt = optarg;
            break;
        case 'e':
390
            error_report("option -e is deprecated, please use \'-o "
391
                  "encryption\' instead!");
392
            goto fail;
393
        case '6':
394
            error_report("option -6 is deprecated, please use \'-o "
395
                  "compat6\' instead!");
396
            goto fail;
397
        case 'o':
398 399 400 401 402 403 404 405 406 407 408
            if (!is_valid_option_list(optarg)) {
                error_report("Invalid option list: %s", optarg);
                goto fail;
            }
            if (!options) {
                options = g_strdup(optarg);
            } else {
                char *old_options = options;
                options = g_strdup_printf("%s,%s", options, optarg);
                g_free(old_options);
            }
409
            break;
410 411 412
        case 'q':
            quiet = true;
            break;
bellard's avatar
bellard committed
413 414
        }
    }
415

416
    /* Get the filename */
417 418 419 420 421 422
    filename = (optind < argc) ? argv[optind] : NULL;
    if (options && has_help_option(options)) {
        g_free(options);
        return print_block_option_help(filename, fmt);
    }

423
    if (optind >= argc) {
424
        error_exit("Expecting image file name");
425
    }
426
    optind++;
427

428 429
    /* Get image size, if specified */
    if (optind < argc) {
430
        int64_t sval;
431 432 433
        char *end;
        sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
        if (sval < 0 || *end) {
434 435 436 437
            if (sval == -ERANGE) {
                error_report("Image size must be less than 8 EiB!");
            } else {
                error_report("Invalid image size specified! You may use k, M, "
438 439 440
                      "G, T, P or E suffixes for ");
                error_report("kilobytes, megabytes, gigabytes, terabytes, "
                             "petabytes and exabytes.");
441
            }
442
            goto fail;
443 444 445
        }
        img_size = (uint64_t)sval;
    }
446
    if (optind != argc) {
447
        error_exit("Unexpected argument: %s", argv[optind]);
448
    }
449

450
    bdrv_img_create(filename, fmt, base_filename, base_fmt,
451
                    options, img_size, BDRV_O_FLAGS, &local_err, quiet);
452
    if (local_err) {
453
        error_report("%s: %s", filename, error_get_pretty(local_err));
454
        error_free(local_err);
455
        goto fail;
456
    }
457

458
    g_free(options);
bellard's avatar
bellard committed
459
    return 0;
460 461 462 463

fail:
    g_free(options);
    return 1;
bellard's avatar
bellard committed
464 465
}

466
static void dump_json_image_check(ImageCheck *check, bool quiet)
467
{
468
    Error *local_err = NULL;
469 470 471 472
    QString *str;
    QmpOutputVisitor *ov = qmp_output_visitor_new();
    QObject *obj;
    visit_type_ImageCheck(qmp_output_get_visitor(ov),
473
                          &check, NULL, &local_err);
474 475 476
    obj = qmp_output_get_qobject(ov);
    str = qobject_to_json_pretty(obj);
    assert(str != NULL);
477
    qprintf(quiet, "%s\n", qstring_get_str(str));
478 479 480 481 482
    qobject_decref(obj);
    qmp_output_visitor_cleanup(ov);
    QDECREF(str);
}

483
static void dump_human_image_check(ImageCheck *check, bool quiet)
484 485
{
    if (!(check->corruptions || check->leaks || check->check_errors)) {
486
        qprintf(quiet, "No errors were found on the image.\n");
487 488
    } else {
        if (check->corruptions) {
489 490 491 492
            qprintf(quiet, "\n%" PRId64 " errors were found on the image.\n"
                    "Data may be corrupted, or further writes to the image "
                    "may corrupt it.\n",
                    check->corruptions);
493 494 495
        }

        if (check->leaks) {
496 497 498 499
            qprintf(quiet,
                    "\n%" PRId64 " leaked clusters were found on the image.\n"
                    "This means waste of disk space, but no harm to data.\n",
                    check->leaks);
500 501 502
        }

        if (check->check_errors) {
503 504 505 506
            qprintf(quiet,
                    "\n%" PRId64
                    " internal errors have occurred during the check.\n",
                    check->check_errors);
507 508 509 510
        }
    }

    if (check->total_clusters != 0 && check->allocated_clusters != 0) {
511 512 513 514 515 516 517
        qprintf(quiet, "%" PRId64 "/%" PRId64 " = %0.2f%% allocated, "
                "%0.2f%% fragmented, %0.2f%% compressed clusters\n",
                check->allocated_clusters, check->total_clusters,
                check->allocated_clusters * 100.0 / check->total_clusters,
                check->fragmented_clusters * 100.0 / check->allocated_clusters,
                check->compressed_clusters * 100.0 /
                check->allocated_clusters);
518 519 520
    }

    if (check->image_end_offset) {
521 522
        qprintf(quiet,
                "Image end offset: %" PRId64 "\n", check->image_end_offset);
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
    }
}

static int collect_image_check(BlockDriverState *bs,
                   ImageCheck *check,
                   const char *filename,
                   const char *fmt,
                   int fix)
{
    int ret;
    BdrvCheckResult result;

    ret = bdrv_check(bs, &result, fix);
    if (ret < 0) {
        return ret;
    }

    check->filename                 = g_strdup(filename);
    check->format                   = g_strdup(bdrv_get_format_name(bs));
    check->check_errors             = result.check_errors;
    check->corruptions              = result.corruptions;
    check->has_corruptions          = result.corruptions != 0;
    check->leaks                    = result.leaks;
    check->has_leaks                = result.leaks != 0;
    check->corruptions_fixed        = result.corruptions_fixed;
    check->has_corruptions_fixed    = result.corruptions != 0;
    check->leaks_fixed              = result.leaks_fixed;
    check->has_leaks_fixed          = result.leaks != 0;
    check->image_end_offset         = result.image_end_offset;
    check->has_image_end_offset     = result.image_end_offset != 0;
    check->total_clusters           = result.bfi.total_clusters;
    check->has_total_clusters       = result.bfi.total_clusters != 0;
    check->allocated_clusters       = result.bfi.allocated_clusters;
    check->has_allocated_clusters   = result.bfi.allocated_clusters != 0;
    check->fragmented_clusters      = result.bfi.fragmented_clusters;
    check->has_fragmented_clusters  = result.bfi.fragmented_clusters != 0;
559 560
    check->compressed_clusters      = result.bfi.compressed_clusters;
    check->has_compressed_clusters  = result.bfi.compressed_clusters != 0;
561 562 563 564

    return 0;
}

565 566 567
/*
 * Checks an image for consistency. Exit codes:
 *
568 569 570 571 572
 *  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
573
 */
574 575 576
static int img_check(int argc, char **argv)
{
    int c, ret;
577
    OutputFormat output_format = OFORMAT_HUMAN;
578
    const char *filename, *fmt, *output, *cache;
579
    BlockBackend *blk;
580
    BlockDriverState *bs;
581
    int fix = 0;
582
    int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
583
    ImageCheck *check;
584
    bool quiet = false;
585 586

    fmt = NULL;
587
    output = NULL;
588
    cache = BDRV_DEFAULT_CACHE;
589
    for(;;) {
590 591 592 593
        int option_index = 0;
        static const struct option long_options[] = {
            {"help", no_argument, 0, 'h'},
            {"format", required_argument, 0, 'f'},
594
            {"repair", required_argument, 0, 'r'},
595 596 597
            {"output", required_argument, 0, OPTION_OUTPUT},
            {0, 0, 0, 0}
        };
598
        c = getopt_long(argc, argv, "hf:r:T:q",
599
                        long_options, &option_index);
600
        if (c == -1) {
601
            break;
602
        }
603
        switch(c) {
604
        case '?':
605 606 607 608 609 610
        case 'h':
            help();
            break;
        case 'f':
            fmt = optarg;
            break;
611 612 613 614 615 616 617 618
        case 'r':
            flags |= BDRV_O_RDWR;

            if (!strcmp(optarg, "leaks")) {
                fix = BDRV_FIX_LEAKS;
            } else if (!strcmp(optarg, "all")) {
                fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
            } else {
619 620
                error_exit("Unknown option value for -r "
                           "(expecting 'leaks' or 'all'): %s", optarg);
621 622
            }
            break;
623 624 625
        case OPTION_OUTPUT:
            output = optarg;
            break;
626 627 628
        case 'T':
            cache = optarg;
            break;
629 630 631
        case 'q':
            quiet = true;
            break;
632 633
        }
    }
634
    if (optind != argc - 1) {
635
        error_exit("Expecting one image file name");
636
    }
637 638
    filename = argv[optind++];

639 640 641 642 643 644 645 646 647
    if (output && !strcmp(output, "json")) {
        output_format = OFORMAT_JSON;
    } else if (output && !strcmp(output, "human")) {
        output_format = OFORMAT_HUMAN;
    } else if (output) {
        error_report("--output must be used with human or json as argument.");
        return 1;
    }

648 649 650 651 652 653
    ret = bdrv_parse_cache_flags(cache, &flags);
    if (ret < 0) {
        error_report("Invalid source cache option: %s", cache);
        return 1;
    }

654 655 656
    blk = img_open("image", filename, fmt, flags, true, quiet);
    if (!blk) {
        return 1;
657
    }
658
    bs = blk_bs(blk);
659 660 661

    check = g_new0(ImageCheck, 1);
    ret = collect_image_check(bs, check, filename, fmt, fix);
662 663

    if (ret == -ENOTSUP) {
664
        error_report("This image format does not support checks");
665
        ret = 63;
666
        goto fail;
667 668
    }

669 670
    if (check->corruptions_fixed || check->leaks_fixed) {
        int corruptions_fixed, leaks_fixed;
671

672 673
        leaks_fixed         = check->leaks_fixed;
        corruptions_fixed   = check->corruptions_fixed;
674

675
        if (output_format == OFORMAT_HUMAN) {
676 677 678 679 680 681 682
            qprintf(quiet,
                    "The following inconsistencies were found and repaired:\n\n"
                    "    %" PRId64 " leaked clusters\n"
                    "    %" PRId64 " corruptions\n\n"
                    "Double checking the fixed image now...\n",
                    check->leaks_fixed,
                    check->corruptions_fixed);
683 684
        }

685
        ret = collect_image_check(bs, check, filename, fmt, 0);
686

687 688
        check->leaks_fixed          = leaks_fixed;
        check->corruptions_fixed    = corruptions_fixed;
689 690
    }

691 692
    switch (output_format) {
    case OFORMAT_HUMAN:
693
        dump_human_image_check(check, quiet);
694 695
        break;
    case OFORMAT_JSON:
696
        dump_json_image_check(check, quiet);
697
        break;
698 699
    }

700 701 702
    if (ret || check->check_errors) {
        ret = 1;
        goto fail;
703
    }
704

705 706 707 708
    if (check->corruptions) {
        ret = 2;
    } else if (check->leaks) {
        ret = 3;
709
    } else {
710
        ret = 0;
711
    }
712 713 714

fail:
    qapi_free_ImageCheck(check);
715
    bdrv_unref(bs);
716
    blk_unref(blk);
717 718

    return ret;
719 720
}

bellard's avatar
bellard committed
721 722
static int img_commit(int argc, char **argv)
{
723 724
    int c, ret, flags;
    const char *filename, *fmt, *cache;
725
    BlockBackend *blk;
bellard's avatar
bellard committed
726
    BlockDriverState *bs;
727
    bool quiet = false;
bellard's avatar
bellard committed
728 729

    fmt = NULL;
730
    cache = BDRV_DEFAULT_CACHE;
bellard's avatar
bellard committed
731
    for(;;) {
732
        c = getopt(argc, argv, "f:ht:q");
733
        if (c == -1) {
bellard's avatar
bellard committed
734
            break;
735
        }
bellard's avatar
bellard committed
736
        switch(c) {
737
        case '?':
bellard's avatar
bellard committed
738 739 740 741 742 743
        case 'h':
            help();
            break;
        case 'f':
            fmt = optarg;
            break;
744 745 746
        case 't':
            cache = optarg;
            break;
747 748 749
        case 'q':
            quiet = true;
            break;
bellard's avatar
bellard committed
750 751
        }
    }
752
    if (optind != argc - 1) {
753
        error_exit("Expecting one image file name");
754
    }
bellard's avatar
bellard committed
755 756
    filename = argv[optind++];

757
    flags = BDRV_O_RDWR;
758
    ret = bdrv_parse_cache_flags(cache, &flags);
759 760
    if (ret < 0) {
        error_report("Invalid cache option: %s", cache);
761
        return 1;
762 763
    }

764 765 766
    blk = img_open("image", filename, fmt, flags, true, quiet);
    if (!blk) {
        return 1;
767
    }
768 769
    bs = blk_bs(blk);

bellard's avatar
bellard committed
770 771 772
    ret = bdrv_commit(bs);
    switch(ret) {
    case 0:
773
        qprintf(quiet, "Image committed.\n");
bellard's avatar
bellard committed
774 775
        break;
    case -ENOENT:
776
        error_report("No disk inserted");
bellard's avatar
bellard committed
777 778
        break;
    case -EACCES:
779
        error_report("Image is read-only");
bellard's avatar
bellard committed
780 781
        break;
    case -ENOTSUP:
782
        error_report("Image is already committed");
bellard's avatar
bellard committed
783 784
        break;
    default:
785
        error_report("Error while committing image");
bellard's avatar
bellard committed
786 787 788
        break;
    }

789
    bdrv_unref(bs);
790
    blk_unref(blk);
791 792 793
    if (ret) {
        return 1;
    }
bellard's avatar
bellard committed
794 795 796
    return 0;
}

797 798 799 800 801 802 803
/*
 * Returns true iff the first sector pointed to by 'buf' contains at least
 * a non-NUL byte.
 *
 * 'pnum' is set to the number of sectors (including and immediately following
 * the first one) that are known to be in the same allocated/unallocated state.
 */
bellard's avatar
bellard committed
804 805
static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
{
806 807
    bool is_zero;
    int i;
bellard's avatar
bellard committed
808 809 810 811 812

    if (n <= 0) {
        *pnum = 0;
        return 0;
    }
813
    is_zero = buffer_is_zero(buf, 512);
bellard's avatar
bellard committed
814 815
    for(i = 1; i < n; i++) {
        buf += 512;
816
        if (is_zero != buffer_is_zero(buf, 512)) {
bellard's avatar
bellard committed
817
            break;
818
        }
bellard's avatar
bellard committed
819 820
    }
    *pnum = i;
821
    return !is_zero;
bellard's avatar
bellard committed
822 823
}

824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
/*
 * Like is_allocated_sectors, but if the buffer starts with a used sector,
 * up to 'min' consecutive sectors containing zeros are ignored. This avoids
 * breaking up write requests for only small sparse areas.
 */
static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
    int min)
{
    int ret;
    int num_checked, num_used;

    if (n < min) {
        min = n;
    }

    ret = is_allocated_sectors(buf, n, pnum);
    if (!ret) {
        return ret;
    }

    num_used = *pnum;
    buf += BDRV_SECTOR_SIZE * *pnum;
    n -= *pnum;
    num_checked = num_used;

    while (n > 0) {
        ret = is_allocated_sectors(buf, n, pnum);

        buf += BDRV_SECTOR_SIZE * *pnum;
        n -= *pnum;
        num_checked += *pnum;
        if (ret) {
            num_used = num_checked;
        } else if (*pnum >= min) {
            break;
        }
    }

    *pnum = num_used;
    return 1;
}

Kevin Wolf's avatar
Kevin Wolf committed
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
/*
 * Compares two buffers sector by sector. Returns 0 if the first sector of both
 * buffers matches, non-zero otherwise.
 *
 * pnum is set to the number of sectors (including and immediately following
 * the first one) that are known to have the same comparison result
 */
static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
    int *pnum)
{
    int res, i;

    if (n <= 0) {
        *pnum = 0;
        return 0;
    }

    res = !!memcmp(buf1, buf2, 512);
    for(i = 1; i < n; i++) {
        buf1 += 512;
        buf2 += 512;

        if (!!memcmp(buf1, buf2, 512) != res) {
            break;
        }
    }

    *pnum = i;
    return res;
}

897
#define IO_BUF_SIZE (2 * 1024 * 1024)
bellard's avatar
bellard committed
898

899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
static int64_t sectors_to_bytes(int64_t sectors)
{
    return sectors << BDRV_SECTOR_BITS;
}

static int64_t sectors_to_process(int64_t total, int64_t from)
{
    return MIN(total - from, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
}

/*
 * Check if passed sectors are empty (not allocated or contain only 0 bytes)
 *
 * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero
 * data and negative value on error.
 *
 * @param bs:  Driver used for accessing file
 * @param sect_num: Number of first sector to check
 * @param sect_count: Number of sectors to check
 * @param filename: Name of disk file we are checking (logging purpose)
 * @param buffer: Allocated buffer for storing read data
 * @param quiet: Flag for quiet mode
 */
static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
                               int sect_count, const char *filename,
                               uint8_t *buffer, bool quiet)
{
    int pnum, ret = 0;
    ret = bdrv_read(bs, sect_num, buffer, sect_count);
    if (ret < 0) {
        error_report("Error while reading offset %" PRId64 " of %s: %s",
                     sectors_to_bytes(sect_num), filename, strerror(-ret));
        return ret;
    }
    ret = is_allocated_sectors(buffer, sect_count, &pnum);
    if (ret || pnum != sect_count) {
        qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
                sectors_to_bytes(ret ? sect_num : sect_num + pnum));
        return 1;
    }

    return 0;
}

/*
 * Compares two images. Exit codes:
 *
 * 0 - Images are identical
 * 1 - Images differ
 * >1 - Error occurred
 */
static int img_compare(int argc, char **argv)
{
952
    const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
953
    BlockBackend *blk1, *blk2;
954 955 956 957 958 959 960
    BlockDriverState *bs1, *bs2;
    int64_t total_sectors1, total_sectors2;
    uint8_t *buf1 = NULL, *buf2 = NULL;
    int pnum1, pnum2;
    int allocated1, allocated2;
    int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
    bool progress = false, quiet = false, strict = false;
961
    int flags;
962 963 964 965 966 967
    int64_t total_sectors;
    int64_t sector_num = 0;
    int64_t nb_sectors;
    int c, pnum;
    uint64_t progress_base;

968
    cache = BDRV_DEFAULT_CACHE;
969
    for (;;) {
970
        c = getopt(argc, argv, "hf:F:T:pqs");
971 972 973 974 975 976 977 978 979 980 981 982 983 984
        if (c == -1) {
            break;
        }
        switch (c) {
        case '?':
        case 'h':
            help();
            break;
        case 'f':
            fmt1 = optarg;
            break;
        case 'F':
            fmt2 = optarg;
            break;
985 986 987
        case 'T':
            cache = optarg;
            break;
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
        case 'p':
            progress = true;
            break;
        case 'q':
            quiet = true;
            break;
        case 's':
            strict = true;
            break;
        }
    }

    /* Progress is not shown in Quiet mode */
    if (quiet) {
        progress = false;
    }


1006
    if (optind != argc - 2) {
1007
        error_exit("Expecting two image file names");
1008 1009 1010 1011
    }
    filename1 = argv[optind++];
    filename2 = argv[optind++];

1012 1013 1014
    /* Initialize before goto out */
    qemu_progress_init(progress, 2.0);

1015 1016 1017 1018 1019 1020 1021 1022
    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;
    }

1023 1024
    blk1 = img_open("image_1", filename1, fmt1, flags, true, quiet);
    if (!blk1) {
1025 1026
        error_report("Can't open file %s", filename1);
        ret = 2;
1027
        goto out3;
1028
    }
1029
    bs1 = blk_bs(blk1);
1030

1031 1032
    blk2 = img_open("image_2", filename2, fmt2, flags, true, quiet);
    if (!blk2) {
1033 1034
        error_report("Can't open file %s", filename2);
        ret = 2;
1035
        goto out2;
1036
    }
1037
    bs2 = blk_bs(blk2);
1038 1039 1040

    buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
    buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
    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;
    }
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
    total_sectors = MIN(total_sectors1, total_sectors2);
    progress_base = MAX(total_sectors1, total_sectors2);

    qemu_progress_print(0, 100);

    if (strict && total_sectors1 != total_sectors2) {
        ret = 1;
        qprintf(quiet, "Strict mode: Image size mismatch!\n");
        goto out;
    }

    for (;;) {
        nb_sectors = sectors_to_process(total_sectors, sector_num);
        if (nb_sectors <= 0) {
            break;
        }
        allocated1 = bdrv_is_allocated_above(bs1, NULL, sector_num, nb_sectors,
                                             &pnum1);
        if (allocated1 < 0) {
            ret = 3;
            error_report("Sector allocation test failed for %s", filename1);
            goto out;
        }

        allocated2 = bdrv_is_allocated_above(bs2, NULL, sector_num, nb_sectors,
                                             &pnum2);
        if (allocated2 < 0) {
            ret = 3;
            error_report("Sector allocation test failed for %s", filename2);
            goto out;
        }
        nb_sectors = MIN(pnum1, pnum2);

        if (allocated1 == allocated2) {
            if (allocated1) {
                ret = bdrv_read(bs1, sector_num, buf1, nb_sectors);
                if (ret < 0) {
                    error_report("Error while reading offset %" PRId64 " of %s:"
                                 " %s", sectors_to_bytes(sector_num), filename1,
                                 strerror(-ret));
                    ret = 4;
                    goto out;
                }
                ret = bdrv_read(bs2, sector_num, buf2, nb_sectors);
                if (ret < 0) {
                    error_report("Error while reading offset %" PRId64
                                 " of %s: %s", sectors_to_bytes(sector_num),
                                 filename2, strerror(-ret));
                    ret = 4;
                    goto out;
                }
                ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
                if (ret || pnum != nb_sectors) {
                    qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
                            sectors_to_bytes(
                                ret ? sector_num : sector_num + pnum));
1111
                    ret = 1;
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
                    goto out;
                }
            }
        } else {
            if (strict) {
                ret = 1;
                qprintf(quiet, "Strict mode: Offset %" PRId64
                        " allocation mismatch!\n",
                        sectors_to_bytes(sector_num));
                goto out;
            }

            if (allocated1) {
                ret = check_empty_sectors(bs1, sector_num, nb_sectors,
                                          filename1, buf1, quiet);
            } else {
                ret = check_empty_sectors(bs2, sector_num, nb_sectors,
                                          filename2, buf1, quiet);
            }
            if (ret) {
                if (ret < 0) {
                    error_report("Error while reading offset %" PRId64 ": %s",
                                 sectors_to_bytes(sector_num), strerror(-ret));
1135
                    ret = 4;
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
                }
                goto out;
            }
        }
        sector_num += nb_sectors;
        qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
    }

    if (total_sectors1 != total_sectors2) {
        BlockDriverState *bs_over;
        int64_t total_sectors_over;
        const char *filename_over;

        qprintf(quiet, "Warning: Image size mismatch!\n");
        if (total_sectors1 > total_sectors2) {
            total_sectors_over = total_sectors1;
            bs_over = bs1;
            filename_over = filename1;
        } else {
            total_sectors_over = total_sectors2;
            bs_over = bs2;
            filename_over = filename2;
        }

        for (;;) {
            nb_sectors = sectors_to_process(total_sectors_over, sector_num);
            if (nb_sectors <= 0) {
                break;
            }
            ret = bdrv_is_allocated_above(bs_over, NULL, sector_num,
                                          nb_sectors, &pnum);
            if (ret < 0) {
                ret = 3;
                error_report("Sector allocation test failed for %s",
                             filename_over);
                goto out;

            }
            nb_sectors = pnum;
            if (ret) {
                ret = check_empty_sectors(bs_over, sector_num, nb_sectors,
                                          filename_over, buf1, quiet);
                if (ret) {
                    if (ret < 0) {
                        error_report("Error while reading offset %" PRId64
                                     " of %s: %s", sectors_to_bytes(sector_num),
                                     filename_over, strerror(-ret));
1183
                        ret = 4;
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
                    }
                    goto out;
                }
            }
            sector_num += nb_sectors;
            qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
        }
    }

    qprintf(quiet, "Images are identical.\n");
    ret = 0;

out:
    qemu_vfree(buf1);
    qemu_vfree(buf2);
1199 1200
    bdrv_unref(bs2);
    blk_unref(blk2);
1201
out2:
1202
    bdrv_unref(bs1);
1203
    blk_unref(blk1);
1204 1205 1206 1207 1208
out3:
    qemu_progress_end();
    return ret;
}

bellard's avatar
bellard committed
1209 1210
static int img_convert(int argc, char **argv)
{
1211
    int c, n, n1, bs_n, bs_i, compress, cluster_sectors, skip_create;
1212
    int64_t ret = 0;
1213 1214
    int progress = 0, flags, src_flags;
    const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
1215
    BlockDriver *drv, *proto_drv;
1216
    BlockBackend **blk = NULL, *out_blk = NULL;
1217
    BlockDriverState **bs = NULL, *out_bs = NULL;
1218
    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
1219
    int64_t *bs_sectors = NULL;
1220
    uint8_t * buf = NULL;
1221
    size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
bellard's avatar
bellard committed
1222
    const uint8_t *buf1;
bellard's avatar
bellard committed
1223
    BlockDriverInfo bdi;
1224 1225 1226
    QemuOpts *opts = NULL;
    QemuOptsList *create_opts = NULL;
    const char *out_baseimg_param;
1227
    char *options = NULL;
1228
    const char *snapshot_name = NULL;
1229
    int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
1230
    bool quiet = false;
1231
    Error *local_err = NULL;
1232
    QemuOpts *sn_opts = NULL;
bellard's avatar
bellard committed
1233 1234 1235

    fmt = NULL;
    out_fmt = "raw";
1236
    cache = "unsafe";
1237
    src_cache = BDRV_DEFAULT_CACHE;
1238
    out_baseimg = NULL;
1239
    compress = 0;
1240
    skip_create = 0;
bellard's avatar
bellard committed
1241
    for(;;) {
1242
        c = getopt(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn");
1243
        if (c == -1) {
bellard's avatar
bellard committed
1244
            break;
1245
        }
bellard's avatar
bellard committed
1246
        switch(c) {
1247
        case '?':
bellard's avatar
bellard committed
1248 1249 1250 1251 1252 1253 1254 1255 1256
        case 'h':
            help();
            break;
        case 'f':
            fmt = optarg;
            break;
        case 'O':
            out_fmt = optarg;
            break;
1257 1258 1259
        case 'B':
            out_baseimg = optarg;
            break;
bellard's avatar
bellard committed
1260
        case 'c':
1261
            compress = 1;
bellard's avatar
bellard committed
1262 1263
            break;
        case 'e':
1264
            error_report("option -e is deprecated, please use \'-o "
1265
                  "encryption\' instead!");
1266
            ret = -1;
1267
            goto fail_getopt;
1268
        case '6':
1269
            error_report("option -6 is deprecated, please use \'-o "
1270
                  "compat6\' instead!");
1271
            ret = -1;
1272
            goto fail_getopt;
1273
        case 'o':
1274 1275 1276
            if (!is_valid_option_list(optarg)) {
                error_report("Invalid option list: %s", optarg);
                ret = -1;
1277
                goto fail_getopt;
1278 1279 1280 1281 1282 1283 1284 1285
            }
            if (!options) {
                options = g_strdup(optarg);
            } else {
                char *old_options = options;
                options = g_strdup_printf("%s,%s", options, optarg);
                g_free(old_options);
            }
1286
            break;
1287 1288 1289
        case 's':
            snapshot_name = optarg;
            break;
1290 1291 1292 1293 1294 1295
        case 'l':
            if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
                sn_opts = qemu_opts_parse(&internal_snapshot_opts, optarg, 0);
                if (!sn_opts) {
                    error_report("Failed in parsing snapshot param '%s'",
                                 optarg);
1296
                    ret = -1;
1297
                    goto fail_getopt;
1298 1299 1300 1301 1302
                }
            } else {
                snapshot_name = optarg;
            }
            break;
1303 1304 1305
        case 'S':
        {
            int64_t sval;
1306 1307 1308
            char *end;
            sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
            if (sval < 0 || *end) {
1309
                error_report("Invalid minimum zero buffer size for sparse output specified");
1310
                ret = -1;
1311
                goto fail_getopt;
1312 1313 1314 1315 1316
            }

            min_sparse = sval / BDRV_SECTOR_SIZE;
            break;
        }
1317 1318 1319
        case 'p':
            progress = 1;
            break;
1320 1321 1322
        case 't':
            cache = optarg;
            break;
1323 1324 1325
        case 'T':
            src_cache = optarg;
            break;
1326 1327 1328
        case 'q':
            quiet = true;
            break;
1329 1330 1331
        case 'n':
            skip_create = 1;
            break;
bellard's avatar
bellard committed
1332 1333
        }
    }
1334

1335
    /* Initialize before goto out */
1336 1337 1338
    if (quiet) {
        progress = 0;
    }
1339 1340
    qemu_progress_init(progress, 1.0);

1341

1342
    bs_n = argc - optind - 1;
1343
    out_filename = bs_n >= 1 ? argv[argc - 1] : NULL;
1344

1345
    if (options && has_help_option(options)) {
1346 1347 1348 1349
        ret = print_block_option_help(out_filename, out_fmt);
        goto out;
    }

1350
    if (bs_n < 1) {
1351
        error_exit("Must specify image file name");
1352 1353 1354
    }


1355
    if (bs_n > 1 && out_baseimg) {
1356 1357
        error_report("-B makes no sense when concatenating multiple input "
                     "images");
1358 1359
        ret = -1;
        goto out;
1360
    }
1361

1362 1363 1364 1365 1366 1367 1368
    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;
    }

1369 1370
    qemu_progress_print(0, 100);

1371
    blk = g_new0(BlockBackend *, bs_n);
1372
    bs = g_new0(BlockDriverState *, bs_n);
1373
    bs_sectors = g_new(int64_t, bs_n);
1374 1375 1376

    total_sectors = 0;
    for (bs_i = 0; bs_i < bs_n; bs_i++) {
Kevin Wolf's avatar
Kevin Wolf committed
1377
        char *id = bs_n > 1 ? g_strdup_printf("source_%d", bs_i)
1378
                            : g_strdup("source")