static int img_compare(int argc, char **argv)

{

    const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;

    BlockBackend *blk1, *blk2;

    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;

    int flags;

    int64_t total_sectors;

    int64_t sector_num = 0;

    int64_t nb_sectors;

    int c, pnum;

    uint64_t progress_base;



    cache = BDRV_DEFAULT_CACHE;

    for (;;) {

        c = getopt(argc, argv, "hf:F:T:pqs");

        if (c == -1) {

            break;

        }

        switch (c) {

        case '?':

        case 'h':

            help();

            break;

        case 'f':

            fmt1 = optarg;

            break;

        case 'F':

            fmt2 = optarg;

            break;

        case 'T':

            cache = optarg;

            break;

        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;

    }





    if (optind != argc - 2) {

        error_exit("Expecting two image file names");

    }

    filename1 = argv[optind++];

    filename2 = argv[optind++];



    /* Initialize before goto out */

    qemu_progress_init(progress, 2.0);



    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;

    }



    blk1 = img_open("image_1", filename1, fmt1, flags, true, quiet);

    if (!blk1) {

        ret = 2;

        goto out3;

    }

    bs1 = blk_bs(blk1);



    blk2 = img_open("image_2", filename2, fmt2, flags, true, quiet);

    if (!blk2) {

        ret = 2;

        goto out2;

    }

    bs2 = blk_bs(blk2);



    buf1 = blk_blockalign(blk1, IO_BUF_SIZE);

    buf2 = blk_blockalign(blk2, IO_BUF_SIZE);

    total_sectors1 = blk_nb_sectors(blk1);

    if (total_sectors1 < 0) {

        error_report("Can't get size of %s: %s",

                     filename1, strerror(-total_sectors1));

        ret = 4;

        goto out;

    }

    total_sectors2 = blk_nb_sectors(blk2);

    if (total_sectors2 < 0) {

        error_report("Can't get size of %s: %s",

                     filename2, strerror(-total_sectors2));

        ret = 4;

        goto out;

    }

    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 (;;) {

        int64_t status1, status2;

        nb_sectors = sectors_to_process(total_sectors, sector_num);

        if (nb_sectors <= 0) {

            break;

        }

        status1 = bdrv_get_block_status_above(bs1, NULL, sector_num,

                                              total_sectors1 - sector_num,

                                              &pnum1);

        if (status1 < 0) {

            ret = 3;

            error_report("Sector allocation test failed for %s", filename1);

            goto out;

        }

        allocated1 = status1 & BDRV_BLOCK_ALLOCATED;



        status2 = bdrv_get_block_status_above(bs2, NULL, sector_num,

                                              total_sectors2 - sector_num,

                                              &pnum2);

        if (status2 < 0) {

            ret = 3;

            error_report("Sector allocation test failed for %s", filename2);

            goto out;

        }

        allocated2 = status2 & BDRV_BLOCK_ALLOCATED;

        if (pnum1) {

            nb_sectors = MIN(nb_sectors, pnum1);

        }

        if (pnum2) {

            nb_sectors = MIN(nb_sectors, pnum2);

        }



        if (strict) {

            if ((status1 & ~BDRV_BLOCK_OFFSET_MASK) !=

                (status2 & ~BDRV_BLOCK_OFFSET_MASK)) {

                ret = 1;

                qprintf(quiet, "Strict mode: Offset %" PRId64

                        " block status mismatch!\n",

                        sectors_to_bytes(sector_num));

                goto out;

            }

        }

        if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) {

            nb_sectors = MIN(pnum1, pnum2);

        } else if (allocated1 == allocated2) {

            if (allocated1) {

                ret = blk_read(blk1, 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 = blk_read(blk2, 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));

                    ret = 1;

                    goto out;

                }

            }

        } else {



            if (allocated1) {

                ret = check_empty_sectors(blk1, sector_num, nb_sectors,

                                          filename1, buf1, quiet);

            } else {

                ret = check_empty_sectors(blk2, 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));

                    ret = 4;

                }

                goto out;

            }

        }

        sector_num += nb_sectors;

        qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);

    }



    if (total_sectors1 != total_sectors2) {

        BlockBackend *blk_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;

            blk_over = blk1;

            filename_over = filename1;

        } else {

            total_sectors_over = total_sectors2;

            blk_over = blk2;

            filename_over = filename2;

        }



        for (;;) {

            nb_sectors = sectors_to_process(total_sectors_over, sector_num);

            if (nb_sectors <= 0) {

                break;

            }

            ret = bdrv_is_allocated_above(blk_bs(blk_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(blk_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));

                        ret = 4;

                    }

                    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);

    blk_unref(blk2);

out2:

    blk_unref(blk1);

out3:

    qemu_progress_end();

    return ret;

}

static int img_compare(int argc, char **argv)

{

    const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;

    BlockBackend *blk1, *blk2;

    BlockDriverState *bs1, *bs2;

    int64_t total_sectors1, total_sectors2;

    uint8_t *buf1 = NULL, *buf2 = NULL;

    int pnum1, pnum2;

    int allocated1, allocated2;

    int ret = 0; 

    bool progress = false, quiet = false, strict = false;

    int flags;

    int64_t total_sectors;

    int64_t sector_num = 0;

    int64_t nb_sectors;

    int c, pnum;

    uint64_t progress_base;



    cache = BDRV_DEFAULT_CACHE;

    for (;;) {

        c = getopt(argc, argv, "hf:F:T:pqs");

        if (c == -1) {

            break;

        }

        switch (c) {

        case '?':

        case 'h':

            help();

            break;

        case 'f':

            fmt1 = optarg;

            break;

        case 'F':

            fmt2 = optarg;

            break;

        case 'T':

            cache = optarg;

            break;

        case 'p':

            progress = true;

            break;

        case 'q':

            quiet = true;

            break;

        case 's':

            strict = true;

            break;

        }

    }



    

    if (quiet) {

        progress = false;

    }





    if (optind != argc - 2) {

        error_exit("Expecting two image file names");

    }

    filename1 = argv[optind++];

    filename2 = argv[optind++];



    

    qemu_progress_init(progress, 2.0);



    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;

    }



    blk1 = img_open("image_1", filename1, fmt1, flags, true, quiet);

    if (!blk1) {

        ret = 2;

        goto out3;

    }

    bs1 = blk_bs(blk1);



    blk2 = img_open("image_2", filename2, fmt2, flags, true, quiet);

    if (!blk2) {

        ret = 2;

        goto out2;

    }

    bs2 = blk_bs(blk2);



    buf1 = blk_blockalign(blk1, IO_BUF_SIZE);

    buf2 = blk_blockalign(blk2, IO_BUF_SIZE);

    total_sectors1 = blk_nb_sectors(blk1);

    if (total_sectors1 < 0) {

        error_report("Can't get size of %s: %s",

                     filename1, strerror(-total_sectors1));

        ret = 4;

        goto out;

    }

    total_sectors2 = blk_nb_sectors(blk2);

    if (total_sectors2 < 0) {

        error_report("Can't get size of %s: %s",

                     filename2, strerror(-total_sectors2));

        ret = 4;

        goto out;

    }

    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 (;;) {

        int64_t status1, status2;

        nb_sectors = sectors_to_process(total_sectors, sector_num);

        if (nb_sectors <= 0) {

            break;

        }

        status1 = bdrv_get_block_status_above(bs1, NULL, sector_num,

                                              total_sectors1 - sector_num,

                                              &pnum1);

        if (status1 < 0) {

            ret = 3;

            error_report("Sector allocation test failed for %s", filename1);

            goto out;

        }

        allocated1 = status1 & BDRV_BLOCK_ALLOCATED;



        status2 = bdrv_get_block_status_above(bs2, NULL, sector_num,

                                              total_sectors2 - sector_num,

                                              &pnum2);

        if (status2 < 0) {

            ret = 3;

            error_report("Sector allocation test failed for %s", filename2);

            goto out;

        }

        allocated2 = status2 & BDRV_BLOCK_ALLOCATED;

        if (pnum1) {

            nb_sectors = MIN(nb_sectors, pnum1);

        }

        if (pnum2) {

            nb_sectors = MIN(nb_sectors, pnum2);

        }



        if (strict) {

            if ((status1 & ~BDRV_BLOCK_OFFSET_MASK) !=

                (status2 & ~BDRV_BLOCK_OFFSET_MASK)) {

                ret = 1;

                qprintf(quiet, "Strict mode: Offset %" PRId64

                        " block status mismatch!\n",

                        sectors_to_bytes(sector_num));

                goto out;

            }

        }

        if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) {

            nb_sectors = MIN(pnum1, pnum2);

        } else if (allocated1 == allocated2) {

            if (allocated1) {

                ret = blk_read(blk1, 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 = blk_read(blk2, 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));

                    ret = 1;

                    goto out;

                }

            }

        } else {



            if (allocated1) {

                ret = check_empty_sectors(blk1, sector_num, nb_sectors,

                                          filename1, buf1, quiet);

            } else {

                ret = check_empty_sectors(blk2, 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));

                    ret = 4;

                }

                goto out;

            }

        }

        sector_num += nb_sectors;

        qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);

    }



    if (total_sectors1 != total_sectors2) {

        BlockBackend *blk_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;

            blk_over = blk1;

            filename_over = filename1;

        } else {

            total_sectors_over = total_sectors2;

            blk_over = blk2;

            filename_over = filename2;

        }



        for (;;) {

            nb_sectors = sectors_to_process(total_sectors_over, sector_num);

            if (nb_sectors <= 0) {

                break;

            }

            ret = bdrv_is_allocated_above(blk_bs(blk_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(blk_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));

                        ret = 4;

                    }

                    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);

    blk_unref(blk2);

out2:

    blk_unref(blk1);

out3:

    qemu_progress_end();

    return ret;

}

static int FUNC_0(int VAR_0, char **VAR_1)

{

    const char *VAR_2 = NULL, *VAR_3 = NULL, *VAR_4, *VAR_5, *VAR_6;

    BlockBackend *blk1, *blk2;

    BlockDriverState *bs1, *bs2;

    int64_t total_sectors1, total_sectors2;

    uint8_t *buf1 = NULL, *buf2 = NULL;

    int VAR_7, VAR_8;

    int VAR_9, VAR_10;

    int VAR_11 = 0; 

    bool progress = false, quiet = false, strict = false;

    int VAR_12;

    int64_t total_sectors;

    int64_t sector_num = 0;

    int64_t nb_sectors;

    int VAR_13, VAR_14;

    uint64_t progress_base;



    VAR_4 = BDRV_DEFAULT_CACHE;

    for (;;) {

        VAR_13 = getopt(VAR_0, VAR_1, "hf:F:T:pqs");

        if (VAR_13 == -1) {

            break;

        }

        switch (VAR_13) {

        case '?':

        case 'h':

            help();

            break;

        case 'f':

            VAR_2 = optarg;

            break;

        case 'F':

            VAR_3 = optarg;

            break;

        case 'T':

            VAR_4 = optarg;

            break;

        case 'p':

            progress = true;

            break;

        case 'q':

            quiet = true;

            break;

        case 's':

            strict = true;

            break;

        }

    }



    

    if (quiet) {

        progress = false;

    }





    if (optind != VAR_0 - 2) {

        error_exit("Expecting two image file names");

    }

    VAR_5 = VAR_1[optind++];

    VAR_6 = VAR_1[optind++];



    

    qemu_progress_init(progress, 2.0);



    VAR_12 = BDRV_O_FLAGS;

    VAR_11 = bdrv_parse_cache_flags(VAR_4, &VAR_12);

    if (VAR_11 < 0) {

        error_report("Invalid source VAR_4 option: %s", VAR_4);

        VAR_11 = 2;

        goto out3;

    }



    blk1 = img_open("image_1", VAR_5, VAR_2, VAR_12, true, quiet);

    if (!blk1) {

        VAR_11 = 2;

        goto out3;

    }

    bs1 = blk_bs(blk1);



    blk2 = img_open("image_2", VAR_6, VAR_3, VAR_12, true, quiet);

    if (!blk2) {

        VAR_11 = 2;

        goto out2;

    }

    bs2 = blk_bs(blk2);



    buf1 = blk_blockalign(blk1, IO_BUF_SIZE);

    buf2 = blk_blockalign(blk2, IO_BUF_SIZE);

    total_sectors1 = blk_nb_sectors(blk1);

    if (total_sectors1 < 0) {

        error_report("Can't get size of %s: %s",

                     VAR_5, strerror(-total_sectors1));

        VAR_11 = 4;

        goto out;

    }

    total_sectors2 = blk_nb_sectors(blk2);

    if (total_sectors2 < 0) {

        error_report("Can't get size of %s: %s",

                     VAR_6, strerror(-total_sectors2));

        VAR_11 = 4;

        goto out;

    }

    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) {

        VAR_11 = 1;

        qprintf(quiet, "Strict mode: Image size mismatch!\n");

        goto out;

    }



    for (;;) {

        int64_t status1, status2;

        nb_sectors = sectors_to_process(total_sectors, sector_num);

        if (nb_sectors <= 0) {

            break;

        }

        status1 = bdrv_get_block_status_above(bs1, NULL, sector_num,

                                              total_sectors1 - sector_num,

                                              &VAR_7);

        if (status1 < 0) {

            VAR_11 = 3;

            error_report("Sector allocation test failed for %s", VAR_5);

            goto out;

        }

        VAR_9 = status1 & BDRV_BLOCK_ALLOCATED;



        status2 = bdrv_get_block_status_above(bs2, NULL, sector_num,

                                              total_sectors2 - sector_num,

                                              &VAR_8);

        if (status2 < 0) {

            VAR_11 = 3;

            error_report("Sector allocation test failed for %s", VAR_6);

            goto out;

        }

        VAR_10 = status2 & BDRV_BLOCK_ALLOCATED;

        if (VAR_7) {

            nb_sectors = MIN(nb_sectors, VAR_7);

        }

        if (VAR_8) {

            nb_sectors = MIN(nb_sectors, VAR_8);

        }



        if (strict) {

            if ((status1 & ~BDRV_BLOCK_OFFSET_MASK) !=

                (status2 & ~BDRV_BLOCK_OFFSET_MASK)) {

                VAR_11 = 1;

                qprintf(quiet, "Strict mode: Offset %" PRId64

                        " block status mismatch!\n",

                        sectors_to_bytes(sector_num));

                goto out;

            }

        }

        if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) {

            nb_sectors = MIN(VAR_7, VAR_8);

        } else if (VAR_9 == VAR_10) {

            if (VAR_9) {

                VAR_11 = blk_read(blk1, sector_num, buf1, nb_sectors);

                if (VAR_11 < 0) {

                    error_report("Error while reading offset %" PRId64 " of %s:"

                                 " %s", sectors_to_bytes(sector_num), VAR_5,

                                 strerror(-VAR_11));

                    VAR_11 = 4;

                    goto out;

                }

                VAR_11 = blk_read(blk2, sector_num, buf2, nb_sectors);

                if (VAR_11 < 0) {

                    error_report("Error while reading offset %" PRId64

                                 " of %s: %s", sectors_to_bytes(sector_num),

                                 VAR_6, strerror(-VAR_11));

                    VAR_11 = 4;

                    goto out;

                }

                VAR_11 = compare_sectors(buf1, buf2, nb_sectors, &VAR_14);

                if (VAR_11 || VAR_14 != nb_sectors) {

                    qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",

                            sectors_to_bytes(

                                VAR_11 ? sector_num : sector_num + VAR_14));

                    VAR_11 = 1;

                    goto out;

                }

            }

        } else {



            if (VAR_9) {

                VAR_11 = check_empty_sectors(blk1, sector_num, nb_sectors,

                                          VAR_5, buf1, quiet);

            } else {

                VAR_11 = check_empty_sectors(blk2, sector_num, nb_sectors,

                                          VAR_6, buf1, quiet);

            }

            if (VAR_11) {

                if (VAR_11 < 0) {

                    error_report("Error while reading offset %" PRId64 ": %s",

                                 sectors_to_bytes(sector_num), strerror(-VAR_11));

                    VAR_11 = 4;

                }

                goto out;

            }

        }

        sector_num += nb_sectors;

        qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);

    }



    if (total_sectors1 != total_sectors2) {

        BlockBackend *blk_over;

        int64_t total_sectors_over;

        const char *VAR_15;



        qprintf(quiet, "Warning: Image size mismatch!\n");

        if (total_sectors1 > total_sectors2) {

            total_sectors_over = total_sectors1;

            blk_over = blk1;

            VAR_15 = VAR_5;

        } else {

            total_sectors_over = total_sectors2;

            blk_over = blk2;

            VAR_15 = VAR_6;

        }



        for (;;) {

            nb_sectors = sectors_to_process(total_sectors_over, sector_num);

            if (nb_sectors <= 0) {

                break;

            }

            VAR_11 = bdrv_is_allocated_above(blk_bs(blk_over), NULL, sector_num,

                                          nb_sectors, &VAR_14);

            if (VAR_11 < 0) {

                VAR_11 = 3;

                error_report("Sector allocation test failed for %s",

                             VAR_15);

                goto out;



            }

            nb_sectors = VAR_14;

            if (VAR_11) {

                VAR_11 = check_empty_sectors(blk_over, sector_num, nb_sectors,

                                          VAR_15, buf1, quiet);

                if (VAR_11) {

                    if (VAR_11 < 0) {

                        error_report("Error while reading offset %" PRId64

                                     " of %s: %s", sectors_to_bytes(sector_num),

                                     VAR_15, strerror(-VAR_11));

                        VAR_11 = 4;

                    }

                    goto out;

                }

            }

            sector_num += nb_sectors;

            qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);

        }

    }



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

    VAR_11 = 0;



out:

    qemu_vfree(buf1);

    qemu_vfree(buf2);

    blk_unref(blk2);

out2:

    blk_unref(blk1);

out3:

    qemu_progress_end();

    return VAR_11;

}

static int FUNC_0(int VAR_0, char **VAR_1)
{ const char *VAR_2 = NULL, *VAR_3 = NULL, *VAR_4, *VAR_5, *VAR_6; BlockBackend *blk1, *blk2; BlockDriverState *bs1, *bs2; int64_t total_sectors1, total_sectors2; uint8_t *buf1 = NULL, *buf2 = NULL; int VAR_7, VAR_8; int VAR_9, VAR_10; int VAR_11 = 0; bool progress = false, quiet = false, strict = false; int VAR_12; int64_t total_sectors; int64_t sector_num = 0; int64_t nb_sectors; int VAR_13, VAR_14; uint64_t progress_base; VAR_4 = BDRV_DEFAULT_CACHE; for (;;) { VAR_13 = getopt(VAR_0, VAR_1, "hf:F:T:pqs"); if (VAR_13 == -1) { break; } switch (VAR_13) { case '?':
case 'h':
help(); break; case 'f':
VAR_2 = optarg; break; case 'F':
VAR_3 = optarg; break; case 'T':
VAR_4 = optarg; break; case 'p':
progress = true; break; case 'q':
quiet = true; break; case 's':
strict = true; break; } } if (quiet) { progress = false; } if (optind != VAR_0 - 2) { error_exit("Expecting two image file names"); } VAR_5 = VAR_1[optind++]; VAR_6 = VAR_1[optind++]; qemu_progress_init(progress, 2.0); VAR_12 = BDRV_O_FLAGS; VAR_11 = bdrv_parse_cache_flags(VAR_4, &VAR_12); if (VAR_11 < 0) { error_report("Invalid source VAR_4 option: %s", VAR_4); VAR_11 = 2; goto out3; } blk1 = img_open("image_1", VAR_5, VAR_2, VAR_12, true, quiet); if (!blk1) { VAR_11 = 2; goto out3; } bs1 = blk_bs(blk1); blk2 = img_open("image_2", VAR_6, VAR_3, VAR_12, true, quiet); if (!blk2) { VAR_11 = 2; goto out2; } bs2 = blk_bs(blk2); buf1 = blk_blockalign(blk1, IO_BUF_SIZE); buf2 = blk_blockalign(blk2, IO_BUF_SIZE); total_sectors1 = blk_nb_sectors(blk1); if (total_sectors1 < 0) { error_report("Can't get size of %s: %s",
VAR_5, strerror(-total_sectors1)); VAR_11 = 4; goto out; } total_sectors2 = blk_nb_sectors(blk2); if (total_sectors2 < 0) { error_report("Can't get size of %s: %s",
VAR_6, strerror(-total_sectors2)); VAR_11 = 4; goto out; } 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) { VAR_11 = 1; qprintf(quiet, "Strict mode: Image size mismatch!\n"); goto out; } for (;;) { int64_t status1, status2; nb_sectors = sectors_to_process(total_sectors, sector_num); if (nb_sectors <= 0) { break; } status1 = bdrv_get_block_status_above(bs1, NULL, sector_num,
total_sectors1 - sector_num,
&VAR_7); if (status1 < 0) { VAR_11 = 3; error_report("Sector allocation test failed for %s", VAR_5); goto out; } VAR_9 = status1 & BDRV_BLOCK_ALLOCATED; status2 = bdrv_get_block_status_above(bs2, NULL, sector_num,
total_sectors2 - sector_num,
&VAR_8); if (status2 < 0) { VAR_11 = 3; error_report("Sector allocation test failed for %s", VAR_6); goto out; } VAR_10 = status2 & BDRV_BLOCK_ALLOCATED; if (VAR_7) { nb_sectors = MIN(nb_sectors, VAR_7); } if (VAR_8) { nb_sectors = MIN(nb_sectors, VAR_8); } if (strict) { if ((status1 & ~BDRV_BLOCK_OFFSET_MASK) !=
(status2 & ~BDRV_BLOCK_OFFSET_MASK)) { VAR_11 = 1; qprintf(quiet, "Strict mode: Offset %" PRId64
" block status mismatch!\n",
sectors_to_bytes(sector_num)); goto out; } } if ((status1 & BDRV_BLOCK_ZERO) && (status2 & BDRV_BLOCK_ZERO)) { nb_sectors = MIN(VAR_7, VAR_8); } else if (VAR_9 == VAR_10) { if (VAR_9) { VAR_11 = blk_read(blk1, sector_num, buf1, nb_sectors); if (VAR_11 < 0) { error_report("Error while reading offset %" PRId64 " of %s:"
" %s", sectors_to_bytes(sector_num), VAR_5,
strerror(-VAR_11)); VAR_11 = 4; goto out; } VAR_11 = blk_read(blk2, sector_num, buf2, nb_sectors); if (VAR_11 < 0) { error_report("Error while reading offset %" PRId64
" of %s: %s", sectors_to_bytes(sector_num),
VAR_6, strerror(-VAR_11)); VAR_11 = 4; goto out; } VAR_11 = compare_sectors(buf1, buf2, nb_sectors, &VAR_14); if (VAR_11 || VAR_14 != nb_sectors) { qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
sectors_to_bytes(
VAR_11 ? sector_num : sector_num + VAR_14)); VAR_11 = 1; goto out; } } } else { if (VAR_9) { VAR_11 = check_empty_sectors(blk1, sector_num, nb_sectors,
VAR_5, buf1, quiet); } else { VAR_11 = check_empty_sectors(blk2, sector_num, nb_sectors,
VAR_6, buf1, quiet); } if (VAR_11) { if (VAR_11 < 0) { error_report("Error while reading offset %" PRId64 ": %s",
sectors_to_bytes(sector_num), strerror(-VAR_11)); VAR_11 = 4; } goto out; } } sector_num += nb_sectors; qemu_progress_print(((float) nb_sectors / progress_base)*100, 100); } if (total_sectors1 != total_sectors2) { BlockBackend *blk_over; int64_t total_sectors_over; const char *VAR_15; qprintf(quiet, "Warning: Image size mismatch!\n"); if (total_sectors1 > total_sectors2) { total_sectors_over = total_sectors1; blk_over = blk1; VAR_15 = VAR_5; } else { total_sectors_over = total_sectors2; blk_over = blk2; VAR_15 = VAR_6; } for (;;) { nb_sectors = sectors_to_process(total_sectors_over, sector_num); if (nb_sectors <= 0) { break; } VAR_11 = bdrv_is_allocated_above(blk_bs(blk_over), NULL, sector_num,
nb_sectors, &VAR_14); if (VAR_11 < 0) { VAR_11 = 3; error_report("Sector allocation test failed for %s",
VAR_15); goto out; } nb_sectors = VAR_14; if (VAR_11) { VAR_11 = check_empty_sectors(blk_over, sector_num, nb_sectors,
VAR_15, buf1, quiet); if (VAR_11) { if (VAR_11 < 0) { error_report("Error while reading offset %" PRId64
" of %s: %s", sectors_to_bytes(sector_num),
VAR_15, strerror(-VAR_11)); VAR_11 = 4; } goto out; } } sector_num += nb_sectors; qemu_progress_print(((float) nb_sectors / progress_base)*100, 100); } } qprintf(quiet, "Images are identical.\n"); VAR_11 = 0; out:
qemu_vfree(buf1); qemu_vfree(buf2); blk_unref(blk2); out2:
blk_unref(blk1); out3:
qemu_progress_end(); return VAR_11; }