static int qcow2_write_snapshots(BlockDriverState *bs)

{

    BDRVQcowState *s = bs->opaque;

    QCowSnapshot *sn;

    QCowSnapshotHeader h;

    QCowSnapshotExtraData extra;

    int i, name_size, id_str_size, snapshots_size;

    struct {

        uint32_t nb_snapshots;

        uint64_t snapshots_offset;

    } QEMU_PACKED header_data;

    int64_t offset, snapshots_offset;

    int ret;



    /* compute the size of the snapshots */

    offset = 0;

    for(i = 0; i < s->nb_snapshots; i++) {

        sn = s->snapshots + i;

        offset = align_offset(offset, 8);

        offset += sizeof(h);

        offset += sizeof(extra);

        offset += strlen(sn->id_str);

        offset += strlen(sn->name);

    }

    snapshots_size = offset;



    /* Allocate space for the new snapshot list */

    snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);

    bdrv_flush(bs->file);

    offset = snapshots_offset;

    if (offset < 0) {

        return offset;

    }



    /* Write all snapshots to the new list */

    for(i = 0; i < s->nb_snapshots; i++) {

        sn = s->snapshots + i;

        memset(&h, 0, sizeof(h));

        h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);

        h.l1_size = cpu_to_be32(sn->l1_size);

        /* If it doesn't fit in 32 bit, older implementations should treat it

         * as a disk-only snapshot rather than truncate the VM state */

        if (sn->vm_state_size <= 0xffffffff) {

            h.vm_state_size = cpu_to_be32(sn->vm_state_size);

        }

        h.date_sec = cpu_to_be32(sn->date_sec);

        h.date_nsec = cpu_to_be32(sn->date_nsec);

        h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);

        h.extra_data_size = cpu_to_be32(sizeof(extra));



        memset(&extra, 0, sizeof(extra));

        extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);

        extra.disk_size = cpu_to_be64(sn->disk_size);



        id_str_size = strlen(sn->id_str);

        name_size = strlen(sn->name);

        h.id_str_size = cpu_to_be16(id_str_size);

        h.name_size = cpu_to_be16(name_size);

        offset = align_offset(offset, 8);



        ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));

        if (ret < 0) {

            goto fail;

        }

        offset += sizeof(h);



        ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra));

        if (ret < 0) {

            goto fail;

        }

        offset += sizeof(extra);



        ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);

        if (ret < 0) {

            goto fail;

        }

        offset += id_str_size;



        ret = bdrv_pwrite(bs->file, offset, sn->name, name_size);

        if (ret < 0) {

            goto fail;

        }

        offset += name_size;

    }



    /*

     * Update the header to point to the new snapshot table. This requires the

     * new table and its refcounts to be stable on disk.

     */

    ret = bdrv_flush(bs);

    if (ret < 0) {

        goto fail;

    }



    QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=

        offsetof(QCowHeader, nb_snapshots) + sizeof(header_data.nb_snapshots));



    header_data.nb_snapshots        = cpu_to_be32(s->nb_snapshots);

    header_data.snapshots_offset    = cpu_to_be64(snapshots_offset);



    ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),

                           &header_data, sizeof(header_data));

    if (ret < 0) {

        goto fail;

    }



    /* free the old snapshot table */

    qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size);

    s->snapshots_offset = snapshots_offset;

    s->snapshots_size = snapshots_size;

    return 0;



fail:

    return ret;

}

static int qcow2_write_snapshots(BlockDriverState *bs)

{

    BDRVQcowState *s = bs->opaque;

    QCowSnapshot *sn;

    QCowSnapshotHeader h;

    QCowSnapshotExtraData extra;

    int i, name_size, id_str_size, snapshots_size;

    struct {

        uint32_t nb_snapshots;

        uint64_t snapshots_offset;

    } QEMU_PACKED header_data;

    int64_t offset, snapshots_offset;

    int ret;



    

    offset = 0;

    for(i = 0; i < s->nb_snapshots; i++) {

        sn = s->snapshots + i;

        offset = align_offset(offset, 8);

        offset += sizeof(h);

        offset += sizeof(extra);

        offset += strlen(sn->id_str);

        offset += strlen(sn->name);

    }

    snapshots_size = offset;



    

    snapshots_offset = qcow2_alloc_clusters(bs, snapshots_size);

    bdrv_flush(bs->file);

    offset = snapshots_offset;

    if (offset < 0) {

        return offset;

    }



    

    for(i = 0; i < s->nb_snapshots; i++) {

        sn = s->snapshots + i;

        memset(&h, 0, sizeof(h));

        h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);

        h.l1_size = cpu_to_be32(sn->l1_size);

        



        if (sn->vm_state_size <= 0xffffffff) {

            h.vm_state_size = cpu_to_be32(sn->vm_state_size);

        }

        h.date_sec = cpu_to_be32(sn->date_sec);

        h.date_nsec = cpu_to_be32(sn->date_nsec);

        h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);

        h.extra_data_size = cpu_to_be32(sizeof(extra));



        memset(&extra, 0, sizeof(extra));

        extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);

        extra.disk_size = cpu_to_be64(sn->disk_size);



        id_str_size = strlen(sn->id_str);

        name_size = strlen(sn->name);

        h.id_str_size = cpu_to_be16(id_str_size);

        h.name_size = cpu_to_be16(name_size);

        offset = align_offset(offset, 8);



        ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));

        if (ret < 0) {

            goto fail;

        }

        offset += sizeof(h);



        ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra));

        if (ret < 0) {

            goto fail;

        }

        offset += sizeof(extra);



        ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);

        if (ret < 0) {

            goto fail;

        }

        offset += id_str_size;



        ret = bdrv_pwrite(bs->file, offset, sn->name, name_size);

        if (ret < 0) {

            goto fail;

        }

        offset += name_size;

    }



    







    ret = bdrv_flush(bs);

    if (ret < 0) {

        goto fail;

    }



    QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=

        offsetof(QCowHeader, nb_snapshots) + sizeof(header_data.nb_snapshots));



    header_data.nb_snapshots        = cpu_to_be32(s->nb_snapshots);

    header_data.snapshots_offset    = cpu_to_be64(snapshots_offset);



    ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),

                           &header_data, sizeof(header_data));

    if (ret < 0) {

        goto fail;

    }



    

    qcow2_free_clusters(bs, s->snapshots_offset, s->snapshots_size);

    s->snapshots_offset = snapshots_offset;

    s->snapshots_size = snapshots_size;

    return 0;



fail:

    return ret;

}

    bdrv_flush(bs->file);
static int FUNC_0(BlockDriverState *VAR_0)

{

    BDRVQcowState *s = VAR_0->opaque;

    QCowSnapshot *sn;

    QCowSnapshotHeader h;

    QCowSnapshotExtraData extra;

    int VAR_1, VAR_2, VAR_3, VAR_4;

    struct {

        uint32_t nb_snapshots;

        uint64_t snapshots_offset;

    } QEMU_PACKED VAR_5;

    int64_t offset, snapshots_offset;

    int VAR_6;



    

    offset = 0;

    for(VAR_1 = 0; VAR_1 < s->nb_snapshots; VAR_1++) {

        sn = s->snapshots + VAR_1;

        offset = align_offset(offset, 8);

        offset += sizeof(h);

        offset += sizeof(extra);

        offset += strlen(sn->id_str);

        offset += strlen(sn->name);

    }

    VAR_4 = offset;



    

    snapshots_offset = qcow2_alloc_clusters(VAR_0, VAR_4);

    bdrv_flush(VAR_0->file);

    offset = snapshots_offset;

    if (offset < 0) {

        return offset;

    }



    

    for(VAR_1 = 0; VAR_1 < s->nb_snapshots; VAR_1++) {

        sn = s->snapshots + VAR_1;

        memset(&h, 0, sizeof(h));

        h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);

        h.l1_size = cpu_to_be32(sn->l1_size);

        



        if (sn->vm_state_size <= 0xffffffff) {

            h.vm_state_size = cpu_to_be32(sn->vm_state_size);

        }

        h.date_sec = cpu_to_be32(sn->date_sec);

        h.date_nsec = cpu_to_be32(sn->date_nsec);

        h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);

        h.extra_data_size = cpu_to_be32(sizeof(extra));



        memset(&extra, 0, sizeof(extra));

        extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size);

        extra.disk_size = cpu_to_be64(sn->disk_size);



        VAR_3 = strlen(sn->id_str);

        VAR_2 = strlen(sn->name);

        h.VAR_3 = cpu_to_be16(VAR_3);

        h.VAR_2 = cpu_to_be16(VAR_2);

        offset = align_offset(offset, 8);



        VAR_6 = bdrv_pwrite(VAR_0->file, offset, &h, sizeof(h));

        if (VAR_6 < 0) {

            goto fail;

        }

        offset += sizeof(h);



        VAR_6 = bdrv_pwrite(VAR_0->file, offset, &extra, sizeof(extra));

        if (VAR_6 < 0) {

            goto fail;

        }

        offset += sizeof(extra);



        VAR_6 = bdrv_pwrite(VAR_0->file, offset, sn->id_str, VAR_3);

        if (VAR_6 < 0) {

            goto fail;

        }

        offset += VAR_3;



        VAR_6 = bdrv_pwrite(VAR_0->file, offset, sn->name, VAR_2);

        if (VAR_6 < 0) {

            goto fail;

        }

        offset += VAR_2;

    }



    







    VAR_6 = bdrv_flush(VAR_0);

    if (VAR_6 < 0) {

        goto fail;

    }



    QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=

        offsetof(QCowHeader, nb_snapshots) + sizeof(VAR_5.nb_snapshots));



    VAR_5.nb_snapshots        = cpu_to_be32(s->nb_snapshots);

    VAR_5.snapshots_offset    = cpu_to_be64(snapshots_offset);



    VAR_6 = bdrv_pwrite_sync(VAR_0->file, offsetof(QCowHeader, nb_snapshots),

                           &VAR_5, sizeof(VAR_5));

    if (VAR_6 < 0) {

        goto fail;

    }



    

    qcow2_free_clusters(VAR_0, s->snapshots_offset, s->VAR_4);

    s->snapshots_offset = snapshots_offset;

    s->VAR_4 = VAR_4;

    return 0;



fail:

    return VAR_6;

}

static int FUNC_0(BlockDriverState *VAR_0)
{ BDRVQcowState *s = VAR_0->opaque; QCowSnapshot *sn; QCowSnapshotHeader h; QCowSnapshotExtraData extra; int VAR_1, VAR_2, VAR_3, VAR_4; struct { uint32_t nb_snapshots; uint64_t snapshots_offset; } QEMU_PACKED VAR_5; int64_t offset, snapshots_offset; int VAR_6; offset = 0; for(VAR_1 = 0; VAR_1 < s->nb_snapshots; VAR_1++) { sn = s->snapshots + VAR_1; offset = align_offset(offset, 8); offset += sizeof(h); offset += sizeof(extra); offset += strlen(sn->id_str); offset += strlen(sn->name); } VAR_4 = offset; snapshots_offset = qcow2_alloc_clusters(VAR_0, VAR_4); bdrv_flush(VAR_0->file); offset = snapshots_offset; if (offset < 0) { return offset; } for(VAR_1 = 0; VAR_1 < s->nb_snapshots; VAR_1++) { sn = s->snapshots + VAR_1; memset(&h, 0, sizeof(h)); h.l1_table_offset = cpu_to_be64(sn->l1_table_offset); h.l1_size = cpu_to_be32(sn->l1_size); if (sn->vm_state_size <= 0xffffffff) { h.vm_state_size = cpu_to_be32(sn->vm_state_size); } h.date_sec = cpu_to_be32(sn->date_sec); h.date_nsec = cpu_to_be32(sn->date_nsec); h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec); h.extra_data_size = cpu_to_be32(sizeof(extra)); memset(&extra, 0, sizeof(extra)); extra.vm_state_size_large = cpu_to_be64(sn->vm_state_size); extra.disk_size = cpu_to_be64(sn->disk_size); VAR_3 = strlen(sn->id_str); VAR_2 = strlen(sn->name); h.VAR_3 = cpu_to_be16(VAR_3); h.VAR_2 = cpu_to_be16(VAR_2); offset = align_offset(offset, 8); VAR_6 = bdrv_pwrite(VAR_0->file, offset, &h, sizeof(h)); if (VAR_6 < 0) { goto fail; } offset += sizeof(h); VAR_6 = bdrv_pwrite(VAR_0->file, offset, &extra, sizeof(extra)); if (VAR_6 < 0) { goto fail; } offset += sizeof(extra); VAR_6 = bdrv_pwrite(VAR_0->file, offset, sn->id_str, VAR_3); if (VAR_6 < 0) { goto fail; } offset += VAR_3; VAR_6 = bdrv_pwrite(VAR_0->file, offset, sn->name, VAR_2); if (VAR_6 < 0) { goto fail; } offset += VAR_2; } VAR_6 = bdrv_flush(VAR_0); if (VAR_6 < 0) { goto fail; } QEMU_BUILD_BUG_ON(offsetof(QCowHeader, snapshots_offset) !=
offsetof(QCowHeader, nb_snapshots) + sizeof(VAR_5.nb_snapshots)); VAR_5.nb_snapshots        = cpu_to_be32(s->nb_snapshots); VAR_5.snapshots_offset    = cpu_to_be64(snapshots_offset); VAR_6 = bdrv_pwrite_sync(VAR_0->file, offsetof(QCowHeader, nb_snapshots),
&VAR_5, sizeof(VAR_5)); if (VAR_6 < 0) { goto fail; } qcow2_free_clusters(VAR_0, s->snapshots_offset, s->VAR_4); s->snapshots_offset = snapshots_offset; s->VAR_4 = VAR_4; return 0; fail:
return VAR_6; }