static int vmdk_write(BlockDriverState *bs, int64_t sector_num,

                     const uint8_t *buf, int nb_sectors)

{

    BDRVVmdkState *s = bs->opaque;

    VmdkExtent *extent = NULL;

    int n;

    int64_t index_in_cluster;

    uint64_t cluster_offset;

    VmdkMetaData m_data;



    if (sector_num > bs->total_sectors) {

        fprintf(stderr,

                "(VMDK) Wrong offset: sector_num=0x%" PRIx64

                " total_sectors=0x%" PRIx64 "\n",

                sector_num, bs->total_sectors);

        return -1;

    }



    while (nb_sectors > 0) {

        extent = find_extent(s, sector_num, extent);

        if (!extent) {

            return -EIO;

        }

        cluster_offset = get_cluster_offset(

                                bs,

                                extent,

                                &m_data,

                                sector_num << 9, 1);

        if (!cluster_offset) {

            return -1;

        }

        index_in_cluster = sector_num % extent->cluster_sectors;

        n = extent->cluster_sectors - index_in_cluster;

        if (n > nb_sectors) {

            n = nb_sectors;

        }



        if (bdrv_pwrite(bs->file,

                        cluster_offset + index_in_cluster * 512,

                        buf, n * 512)

                != n * 512) {

            return -1;

        }

        if (m_data.valid) {

            /* update L2 tables */

            if (vmdk_L2update(extent, &m_data) == -1) {

                return -1;

            }

        }

        nb_sectors -= n;

        sector_num += n;

        buf += n * 512;



        // update CID on the first write every time the virtual disk is opened

        if (!s->cid_updated) {

            vmdk_write_cid(bs, time(NULL));

            s->cid_updated = true;

        }

    }

    return 0;

}

static int vmdk_write(BlockDriverState *bs, int64_t sector_num,

                     const uint8_t *buf, int nb_sectors)

{

    BDRVVmdkState *s = bs->opaque;

    VmdkExtent *extent = NULL;

    int n;

    int64_t index_in_cluster;

    uint64_t cluster_offset;

    VmdkMetaData m_data;



    if (sector_num > bs->total_sectors) {

        fprintf(stderr,

                "(VMDK) Wrong offset: sector_num=0x%" PRIx64

                " total_sectors=0x%" PRIx64 "\n",

                sector_num, bs->total_sectors);

        return -1;

    }



    while (nb_sectors > 0) {

        extent = find_extent(s, sector_num, extent);

        if (!extent) {

            return -EIO;

        }

        cluster_offset = get_cluster_offset(

                                bs,

                                extent,

                                &m_data,

                                sector_num << 9, 1);

        if (!cluster_offset) {

            return -1;

        }

        index_in_cluster = sector_num % extent->cluster_sectors;

        n = extent->cluster_sectors - index_in_cluster;

        if (n > nb_sectors) {

            n = nb_sectors;

        }



        if (bdrv_pwrite(bs->file,

                        cluster_offset + index_in_cluster * 512,

                        buf, n * 512)

                != n * 512) {

            return -1;

        }

        if (m_data.valid) {

            

            if (vmdk_L2update(extent, &m_data) == -1) {

                return -1;

            }

        }

        nb_sectors -= n;

        sector_num += n;

        buf += n * 512;



        

        if (!s->cid_updated) {

            vmdk_write_cid(bs, time(NULL));

            s->cid_updated = true;

        }

    }

    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, int64_t VAR_1,

                     const uint8_t *VAR_2, int VAR_3)

{

    BDRVVmdkState *s = VAR_0->opaque;

    VmdkExtent *extent = NULL;

    int VAR_4;

    int64_t index_in_cluster;

    uint64_t cluster_offset;

    VmdkMetaData m_data;



    if (VAR_1 > VAR_0->total_sectors) {

        fprintf(stderr,

                "(VMDK) Wrong offset: VAR_1=0x%" PRIx64

                " total_sectors=0x%" PRIx64 "\VAR_4",

                VAR_1, VAR_0->total_sectors);

        return -1;

    }



    while (VAR_3 > 0) {

        extent = find_extent(s, VAR_1, extent);

        if (!extent) {

            return -EIO;

        }

        cluster_offset = get_cluster_offset(

                                VAR_0,

                                extent,

                                &m_data,

                                VAR_1 << 9, 1);

        if (!cluster_offset) {

            return -1;

        }

        index_in_cluster = VAR_1 % extent->cluster_sectors;

        VAR_4 = extent->cluster_sectors - index_in_cluster;

        if (VAR_4 > VAR_3) {

            VAR_4 = VAR_3;

        }



        if (bdrv_pwrite(VAR_0->file,

                        cluster_offset + index_in_cluster * 512,

                        VAR_2, VAR_4 * 512)

                != VAR_4 * 512) {

            return -1;

        }

        if (m_data.valid) {

            

            if (vmdk_L2update(extent, &m_data) == -1) {

                return -1;

            }

        }

        VAR_3 -= VAR_4;

        VAR_1 += VAR_4;

        VAR_2 += VAR_4 * 512;



        

        if (!s->cid_updated) {

            vmdk_write_cid(VAR_0, time(NULL));

            s->cid_updated = true;

        }

    }

    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, int64_t VAR_1,
const uint8_t *VAR_2, int VAR_3)
{ BDRVVmdkState *s = VAR_0->opaque; VmdkExtent *extent = NULL; int VAR_4; int64_t index_in_cluster; uint64_t cluster_offset; VmdkMetaData m_data; if (VAR_1 > VAR_0->total_sectors) { fprintf(stderr,
"(VMDK) Wrong offset: VAR_1=0x%" PRIx64
" total_sectors=0x%" PRIx64 "\VAR_4",
VAR_1, VAR_0->total_sectors); return -1; } while (VAR_3 > 0) { extent = find_extent(s, VAR_1, extent); if (!extent) { return -EIO; } cluster_offset = get_cluster_offset(
VAR_0,
extent,
&m_data,
VAR_1 << 9, 1); if (!cluster_offset) { return -1; } index_in_cluster = VAR_1 % extent->cluster_sectors; VAR_4 = extent->cluster_sectors - index_in_cluster; if (VAR_4 > VAR_3) { VAR_4 = VAR_3; } if (bdrv_pwrite(VAR_0->file,
cluster_offset + index_in_cluster * 512,
VAR_2, VAR_4 * 512)
!= VAR_4 * 512) { return -1; } if (m_data.valid) { if (vmdk_L2update(extent, &m_data) == -1) { return -1; } } VAR_3 -= VAR_4; VAR_1 += VAR_4; VAR_2 += VAR_4 * 512; if (!s->cid_updated) { vmdk_write_cid(VAR_0, time(NULL)); s->cid_updated = true; } } return 0; }