static int get_block_status(BlockDriverState *bs, int64_t offset,

                            int64_t bytes, MapEntry *e)

{

    int64_t ret;

    int depth;

    BlockDriverState *file;

    bool has_offset;

    int nb_sectors = bytes >> BDRV_SECTOR_BITS;



    assert(bytes < INT_MAX);

    /* As an optimization, we could cache the current range of unallocated

     * clusters in each file of the chain, and avoid querying the same

     * range repeatedly.

     */



    depth = 0;

    for (;;) {

        ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS, nb_sectors,

                                    &nb_sectors, &file);

        if (ret < 0) {

            return ret;

        }

        assert(nb_sectors);

        if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {

            break;

        }

        bs = backing_bs(bs);

        if (bs == NULL) {

            ret = 0;

            break;

        }



        depth++;

    }



    has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);



    *e = (MapEntry) {

        .start = offset,

        .length = nb_sectors * BDRV_SECTOR_SIZE,

        .data = !!(ret & BDRV_BLOCK_DATA),

        .zero = !!(ret & BDRV_BLOCK_ZERO),

        .offset = ret & BDRV_BLOCK_OFFSET_MASK,

        .has_offset = has_offset,

        .depth = depth,

        .has_filename = file && has_offset,

        .filename = file && has_offset ? file->filename : NULL,

    };



    return 0;

}

static int get_block_status(BlockDriverState *bs, int64_t offset,

                            int64_t bytes, MapEntry *e)

{

    int64_t ret;

    int depth;

    BlockDriverState *file;

    bool has_offset;

    int nb_sectors = bytes >> BDRV_SECTOR_BITS;



    assert(bytes < INT_MAX);

    









    depth = 0;

    for (;;) {

        ret = bdrv_get_block_status(bs, offset >> BDRV_SECTOR_BITS, nb_sectors,

                                    &nb_sectors, &file);

        if (ret < 0) {

            return ret;

        }

        assert(nb_sectors);

        if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {

            break;

        }

        bs = backing_bs(bs);

        if (bs == NULL) {

            ret = 0;

            break;

        }



        depth++;

    }



    has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);



    *e = (MapEntry) {

        .start = offset,

        .length = nb_sectors * BDRV_SECTOR_SIZE,

        .data = !!(ret & BDRV_BLOCK_DATA),

        .zero = !!(ret & BDRV_BLOCK_ZERO),

        .offset = ret & BDRV_BLOCK_OFFSET_MASK,

        .has_offset = has_offset,

        .depth = depth,

        .has_filename = file && has_offset,

        .filename = file && has_offset ? file->filename : NULL,

    };



    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, int64_t VAR_1,

                            int64_t VAR_2, MapEntry *VAR_3)

{

    int64_t ret;

    int VAR_4;

    BlockDriverState *file;

    bool has_offset;

    int VAR_5 = VAR_2 >> BDRV_SECTOR_BITS;



    assert(VAR_2 < INT_MAX);

    









    VAR_4 = 0;

    for (;;) {

        ret = bdrv_get_block_status(VAR_0, VAR_1 >> BDRV_SECTOR_BITS, VAR_5,

                                    &VAR_5, &file);

        if (ret < 0) {

            return ret;

        }

        assert(VAR_5);

        if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) {

            break;

        }

        VAR_0 = backing_bs(VAR_0);

        if (VAR_0 == NULL) {

            ret = 0;

            break;

        }



        VAR_4++;

    }



    has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID);



    *VAR_3 = (MapEntry) {

        .start = VAR_1,

        .length = VAR_5 * BDRV_SECTOR_SIZE,

        .data = !!(ret & BDRV_BLOCK_DATA),

        .zero = !!(ret & BDRV_BLOCK_ZERO),

        .VAR_1 = ret & BDRV_BLOCK_OFFSET_MASK,

        .has_offset = has_offset,

        .VAR_4 = VAR_4,

        .has_filename = file && has_offset,

        .filename = file && has_offset ? file->filename : NULL,

    };



    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, int64_t VAR_1,
int64_t VAR_2, MapEntry *VAR_3)
{ int64_t ret; int VAR_4; BlockDriverState *file; bool has_offset; int VAR_5 = VAR_2 >> BDRV_SECTOR_BITS; assert(VAR_2 < INT_MAX); VAR_4 = 0; for (;;) { ret = bdrv_get_block_status(VAR_0, VAR_1 >> BDRV_SECTOR_BITS, VAR_5,
&VAR_5, &file); if (ret < 0) { return ret; } assert(VAR_5); if (ret & (BDRV_BLOCK_ZERO|BDRV_BLOCK_DATA)) { break; } VAR_0 = backing_bs(VAR_0); if (VAR_0 == NULL) { ret = 0; break; } VAR_4++; } has_offset = !!(ret & BDRV_BLOCK_OFFSET_VALID); *VAR_3 = (MapEntry) { .start = VAR_1,
.length = VAR_5 * BDRV_SECTOR_SIZE,
.data = !!(ret & BDRV_BLOCK_DATA),
.zero = !!(ret & BDRV_BLOCK_ZERO),
.VAR_1 = ret & BDRV_BLOCK_OFFSET_MASK,
.has_offset = has_offset,
.VAR_4 = VAR_4,
.has_filename = file && has_offset,
.filename = file && has_offset ? file->filename : NULL,
}; return 0; }