static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,

                            int64_t offset_in_cluster, QEMUIOVector *qiov,

                            int bytes)

{

    int ret;

    int cluster_bytes, buf_bytes;

    uint8_t *cluster_buf, *compressed_data;

    uint8_t *uncomp_buf;

    uint32_t data_len;

    VmdkGrainMarker *marker;

    uLongf buf_len;





    if (!extent->compressed) {

        ret = bdrv_co_preadv(extent->file->bs,

                             cluster_offset + offset_in_cluster, bytes,

                             qiov, 0);

        if (ret < 0) {

            return ret;

        }

        return 0;

    }

    cluster_bytes = extent->cluster_sectors * 512;

    /* Read two clusters in case GrainMarker + compressed data > one cluster */

    buf_bytes = cluster_bytes * 2;

    cluster_buf = g_malloc(buf_bytes);

    uncomp_buf = g_malloc(cluster_bytes);

    ret = bdrv_pread(extent->file,

                cluster_offset,

                cluster_buf, buf_bytes);

    if (ret < 0) {

        goto out;

    }

    compressed_data = cluster_buf;

    buf_len = cluster_bytes;

    data_len = cluster_bytes;

    if (extent->has_marker) {

        marker = (VmdkGrainMarker *)cluster_buf;

        compressed_data = marker->data;

        data_len = le32_to_cpu(marker->size);

    }

    if (!data_len || data_len > buf_bytes) {

        ret = -EINVAL;

        goto out;

    }

    ret = uncompress(uncomp_buf, &buf_len, compressed_data, data_len);

    if (ret != Z_OK) {

        ret = -EINVAL;

        goto out;



    }

    if (offset_in_cluster < 0 ||

            offset_in_cluster + bytes > buf_len) {

        ret = -EINVAL;

        goto out;

    }

    qemu_iovec_from_buf(qiov, 0, uncomp_buf + offset_in_cluster, bytes);

    ret = 0;



 out:

    g_free(uncomp_buf);

    g_free(cluster_buf);

    return ret;

}

static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,

                            int64_t offset_in_cluster, QEMUIOVector *qiov,

                            int bytes)

{

    int ret;

    int cluster_bytes, buf_bytes;

    uint8_t *cluster_buf, *compressed_data;

    uint8_t *uncomp_buf;

    uint32_t data_len;

    VmdkGrainMarker *marker;

    uLongf buf_len;





    if (!extent->compressed) {

        ret = bdrv_co_preadv(extent->file->bs,

                             cluster_offset + offset_in_cluster, bytes,

                             qiov, 0);

        if (ret < 0) {

            return ret;

        }

        return 0;

    }

    cluster_bytes = extent->cluster_sectors * 512;

    

    buf_bytes = cluster_bytes * 2;

    cluster_buf = g_malloc(buf_bytes);

    uncomp_buf = g_malloc(cluster_bytes);

    ret = bdrv_pread(extent->file,

                cluster_offset,

                cluster_buf, buf_bytes);

    if (ret < 0) {

        goto out;

    }

    compressed_data = cluster_buf;

    buf_len = cluster_bytes;

    data_len = cluster_bytes;

    if (extent->has_marker) {

        marker = (VmdkGrainMarker *)cluster_buf;

        compressed_data = marker->data;

        data_len = le32_to_cpu(marker->size);

    }

    if (!data_len || data_len > buf_bytes) {

        ret = -EINVAL;

        goto out;

    }

    ret = uncompress(uncomp_buf, &buf_len, compressed_data, data_len);

    if (ret != Z_OK) {

        ret = -EINVAL;

        goto out;



    }

    if (offset_in_cluster < 0 ||

            offset_in_cluster + bytes > buf_len) {

        ret = -EINVAL;

        goto out;

    }

    qemu_iovec_from_buf(qiov, 0, uncomp_buf + offset_in_cluster, bytes);

    ret = 0;



 out:

    g_free(uncomp_buf);

    g_free(cluster_buf);

    return ret;

}

static int FUNC_0(VmdkExtent *VAR_0, int64_t VAR_1,

                            int64_t VAR_2, QEMUIOVector *VAR_3,

                            int VAR_4)

{

    int VAR_5;

    int VAR_6, VAR_7;

    uint8_t *cluster_buf, *compressed_data;

    uint8_t *uncomp_buf;

    uint32_t data_len;

    VmdkGrainMarker *marker;

    uLongf buf_len;





    if (!VAR_0->compressed) {

        VAR_5 = bdrv_co_preadv(VAR_0->file->bs,

                             VAR_1 + VAR_2, VAR_4,

                             VAR_3, 0);

        if (VAR_5 < 0) {

            return VAR_5;

        }

        return 0;

    }

    VAR_6 = VAR_0->cluster_sectors * 512;

    

    VAR_7 = VAR_6 * 2;

    cluster_buf = g_malloc(VAR_7);

    uncomp_buf = g_malloc(VAR_6);

    VAR_5 = bdrv_pread(VAR_0->file,

                VAR_1,

                cluster_buf, VAR_7);

    if (VAR_5 < 0) {

        goto out;

    }

    compressed_data = cluster_buf;

    buf_len = VAR_6;

    data_len = VAR_6;

    if (VAR_0->has_marker) {

        marker = (VmdkGrainMarker *)cluster_buf;

        compressed_data = marker->data;

        data_len = le32_to_cpu(marker->size);

    }

    if (!data_len || data_len > VAR_7) {

        VAR_5 = -EINVAL;

        goto out;

    }

    VAR_5 = uncompress(uncomp_buf, &buf_len, compressed_data, data_len);

    if (VAR_5 != Z_OK) {

        VAR_5 = -EINVAL;

        goto out;



    }

    if (VAR_2 < 0 ||

            VAR_2 + VAR_4 > buf_len) {

        VAR_5 = -EINVAL;

        goto out;

    }

    qemu_iovec_from_buf(VAR_3, 0, uncomp_buf + VAR_2, VAR_4);

    VAR_5 = 0;



 out:

    g_free(uncomp_buf);

    g_free(cluster_buf);

    return VAR_5;

}

static int FUNC_0(VmdkExtent *VAR_0, int64_t VAR_1,
int64_t VAR_2, QEMUIOVector *VAR_3,
int VAR_4)
{ int VAR_5; int VAR_6, VAR_7; uint8_t *cluster_buf, *compressed_data; uint8_t *uncomp_buf; uint32_t data_len; VmdkGrainMarker *marker; uLongf buf_len; if (!VAR_0->compressed) { VAR_5 = bdrv_co_preadv(VAR_0->file->bs,
VAR_1 + VAR_2, VAR_4,
VAR_3, 0); if (VAR_5 < 0) { return VAR_5; } return 0; } VAR_6 = VAR_0->cluster_sectors * 512; VAR_7 = VAR_6 * 2; cluster_buf = g_malloc(VAR_7); uncomp_buf = g_malloc(VAR_6); VAR_5 = bdrv_pread(VAR_0->file,
VAR_1,
cluster_buf, VAR_7); if (VAR_5 < 0) { goto out; } compressed_data = cluster_buf; buf_len = VAR_6; data_len = VAR_6; if (VAR_0->has_marker) { marker = (VmdkGrainMarker *)cluster_buf; compressed_data = marker->data; data_len = le32_to_cpu(marker->size); } if (!data_len || data_len > VAR_7) { VAR_5 = -EINVAL; goto out; } VAR_5 = uncompress(uncomp_buf, &buf_len, compressed_data, data_len); if (VAR_5 != Z_OK) { VAR_5 = -EINVAL; goto out; } if (VAR_2 < 0 ||
VAR_2 + VAR_4 > buf_len) { VAR_5 = -EINVAL; goto out; } qemu_iovec_from_buf(VAR_3, 0, uncomp_buf + VAR_2, VAR_4); VAR_5 = 0; out:
g_free(uncomp_buf); g_free(cluster_buf); return VAR_5; }