int qcow2_update_header(BlockDriverState *bs)

{

    BDRVQcowState *s = bs->opaque;

    QCowHeader *header;

    char *buf;

    size_t buflen = s->cluster_size;

    int ret;

    uint64_t total_size;

    uint32_t refcount_table_clusters;

    size_t header_length;

    Qcow2UnknownHeaderExtension *uext;



    buf = qemu_blockalign(bs, buflen);



    /* Header structure */

    header = (QCowHeader*) buf;



    if (buflen < sizeof(*header)) {

        ret = -ENOSPC;

        goto fail;

    }



    header_length = sizeof(*header) + s->unknown_header_fields_size;

    total_size = bs->total_sectors * BDRV_SECTOR_SIZE;

    refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);



    *header = (QCowHeader) {

        /* Version 2 fields */

        .magic                  = cpu_to_be32(QCOW_MAGIC),

        .version                = cpu_to_be32(s->qcow_version),

        .backing_file_offset    = 0,

        .backing_file_size      = 0,

        .cluster_bits           = cpu_to_be32(s->cluster_bits),

        .size                   = cpu_to_be64(total_size),

        .crypt_method           = cpu_to_be32(s->crypt_method_header),

        .l1_size                = cpu_to_be32(s->l1_size),

        .l1_table_offset        = cpu_to_be64(s->l1_table_offset),

        .refcount_table_offset  = cpu_to_be64(s->refcount_table_offset),

        .refcount_table_clusters = cpu_to_be32(refcount_table_clusters),

        .nb_snapshots           = cpu_to_be32(s->nb_snapshots),

        .snapshots_offset       = cpu_to_be64(s->snapshots_offset),



        /* Version 3 fields */

        .incompatible_features  = cpu_to_be64(s->incompatible_features),

        .compatible_features    = cpu_to_be64(s->compatible_features),

        .autoclear_features     = cpu_to_be64(s->autoclear_features),

        .refcount_order         = cpu_to_be32(3 + REFCOUNT_SHIFT),

        .header_length          = cpu_to_be32(header_length),

    };



    /* For older versions, write a shorter header */

    switch (s->qcow_version) {

    case 2:

        ret = offsetof(QCowHeader, incompatible_features);

        break;

    case 3:

        ret = sizeof(*header);

        break;

    default:

        return -EINVAL;

    }



    buf += ret;

    buflen -= ret;

    memset(buf, 0, buflen);



    /* Preserve any unknown field in the header */

    if (s->unknown_header_fields_size) {

        if (buflen < s->unknown_header_fields_size) {

            ret = -ENOSPC;

            goto fail;

        }



        memcpy(buf, s->unknown_header_fields, s->unknown_header_fields_size);

        buf += s->unknown_header_fields_size;

        buflen -= s->unknown_header_fields_size;

    }



    /* Backing file format header extension */

    if (*bs->backing_format) {

        ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BACKING_FORMAT,

                             bs->backing_format, strlen(bs->backing_format),

                             buflen);

        if (ret < 0) {

            goto fail;

        }



        buf += ret;

        buflen -= ret;

    }



    /* Feature table */

    Qcow2Feature features[] = {

        /* no feature defined yet */

    };



    ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,

                         features, sizeof(features), buflen);

    if (ret < 0) {

        goto fail;

    }

    buf += ret;

    buflen -= ret;



    /* Keep unknown header extensions */

    QLIST_FOREACH(uext, &s->unknown_header_ext, next) {

        ret = header_ext_add(buf, uext->magic, uext->data, uext->len, buflen);

        if (ret < 0) {

            goto fail;

        }



        buf += ret;

        buflen -= ret;

    }



    /* End of header extensions */

    ret = header_ext_add(buf, QCOW2_EXT_MAGIC_END, NULL, 0, buflen);

    if (ret < 0) {

        goto fail;

    }



    buf += ret;

    buflen -= ret;



    /* Backing file name */

    if (*bs->backing_file) {

        size_t backing_file_len = strlen(bs->backing_file);



        if (buflen < backing_file_len) {

            ret = -ENOSPC;

            goto fail;

        }



        strncpy(buf, bs->backing_file, buflen);



        header->backing_file_offset = cpu_to_be64(buf - ((char*) header));

        header->backing_file_size   = cpu_to_be32(backing_file_len);

    }



    /* Write the new header */

    ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size);

    if (ret < 0) {

        goto fail;

    }



    ret = 0;

fail:

    qemu_vfree(header);

    return ret;

}

int qcow2_update_header(BlockDriverState *bs)

{

    BDRVQcowState *s = bs->opaque;

    QCowHeader *header;

    char *buf;

    size_t buflen = s->cluster_size;

    int ret;

    uint64_t total_size;

    uint32_t refcount_table_clusters;

    size_t header_length;

    Qcow2UnknownHeaderExtension *uext;



    buf = qemu_blockalign(bs, buflen);



    

    header = (QCowHeader*) buf;



    if (buflen < sizeof(*header)) {

        ret = -ENOSPC;

        goto fail;

    }



    header_length = sizeof(*header) + s->unknown_header_fields_size;

    total_size = bs->total_sectors * BDRV_SECTOR_SIZE;

    refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);



    *header = (QCowHeader) {

        

        .magic                  = cpu_to_be32(QCOW_MAGIC),

        .version                = cpu_to_be32(s->qcow_version),

        .backing_file_offset    = 0,

        .backing_file_size      = 0,

        .cluster_bits           = cpu_to_be32(s->cluster_bits),

        .size                   = cpu_to_be64(total_size),

        .crypt_method           = cpu_to_be32(s->crypt_method_header),

        .l1_size                = cpu_to_be32(s->l1_size),

        .l1_table_offset        = cpu_to_be64(s->l1_table_offset),

        .refcount_table_offset  = cpu_to_be64(s->refcount_table_offset),

        .refcount_table_clusters = cpu_to_be32(refcount_table_clusters),

        .nb_snapshots           = cpu_to_be32(s->nb_snapshots),

        .snapshots_offset       = cpu_to_be64(s->snapshots_offset),



        

        .incompatible_features  = cpu_to_be64(s->incompatible_features),

        .compatible_features    = cpu_to_be64(s->compatible_features),

        .autoclear_features     = cpu_to_be64(s->autoclear_features),

        .refcount_order         = cpu_to_be32(3 + REFCOUNT_SHIFT),

        .header_length          = cpu_to_be32(header_length),

    };



    

    switch (s->qcow_version) {

    case 2:

        ret = offsetof(QCowHeader, incompatible_features);

        break;

    case 3:

        ret = sizeof(*header);

        break;

    default:

        return -EINVAL;

    }



    buf += ret;

    buflen -= ret;

    memset(buf, 0, buflen);



    

    if (s->unknown_header_fields_size) {

        if (buflen < s->unknown_header_fields_size) {

            ret = -ENOSPC;

            goto fail;

        }



        memcpy(buf, s->unknown_header_fields, s->unknown_header_fields_size);

        buf += s->unknown_header_fields_size;

        buflen -= s->unknown_header_fields_size;

    }



    

    if (*bs->backing_format) {

        ret = header_ext_add(buf, QCOW2_EXT_MAGIC_BACKING_FORMAT,

                             bs->backing_format, strlen(bs->backing_format),

                             buflen);

        if (ret < 0) {

            goto fail;

        }



        buf += ret;

        buflen -= ret;

    }



    

    Qcow2Feature features[] = {

        

    };



    ret = header_ext_add(buf, QCOW2_EXT_MAGIC_FEATURE_TABLE,

                         features, sizeof(features), buflen);

    if (ret < 0) {

        goto fail;

    }

    buf += ret;

    buflen -= ret;



    

    QLIST_FOREACH(uext, &s->unknown_header_ext, next) {

        ret = header_ext_add(buf, uext->magic, uext->data, uext->len, buflen);

        if (ret < 0) {

            goto fail;

        }



        buf += ret;

        buflen -= ret;

    }



    

    ret = header_ext_add(buf, QCOW2_EXT_MAGIC_END, NULL, 0, buflen);

    if (ret < 0) {

        goto fail;

    }



    buf += ret;

    buflen -= ret;



    

    if (*bs->backing_file) {

        size_t backing_file_len = strlen(bs->backing_file);



        if (buflen < backing_file_len) {

            ret = -ENOSPC;

            goto fail;

        }



        strncpy(buf, bs->backing_file, buflen);



        header->backing_file_offset = cpu_to_be64(buf - ((char*) header));

        header->backing_file_size   = cpu_to_be32(backing_file_len);

    }



    

    ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size);

    if (ret < 0) {

        goto fail;

    }



    ret = 0;

fail:

    qemu_vfree(header);

    return ret;

}

        return -EINVAL;
int FUNC_0(BlockDriverState *VAR_0)

{

    BDRVQcowState *s = VAR_0->opaque;

    QCowHeader *header;

    char *VAR_1;

    size_t buflen = s->cluster_size;

    int VAR_2;

    uint64_t total_size;

    uint32_t refcount_table_clusters;

    size_t header_length;

    Qcow2UnknownHeaderExtension *uext;



    VAR_1 = qemu_blockalign(VAR_0, buflen);



    

    header = (QCowHeader*) VAR_1;



    if (buflen < sizeof(*header)) {

        VAR_2 = -ENOSPC;

        goto fail;

    }



    header_length = sizeof(*header) + s->unknown_header_fields_size;

    total_size = VAR_0->total_sectors * BDRV_SECTOR_SIZE;

    refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);



    *header = (QCowHeader) {

        

        .magic                  = cpu_to_be32(QCOW_MAGIC),

        .version                = cpu_to_be32(s->qcow_version),

        .backing_file_offset    = 0,

        .backing_file_size      = 0,

        .cluster_bits           = cpu_to_be32(s->cluster_bits),

        .size                   = cpu_to_be64(total_size),

        .crypt_method           = cpu_to_be32(s->crypt_method_header),

        .l1_size                = cpu_to_be32(s->l1_size),

        .l1_table_offset        = cpu_to_be64(s->l1_table_offset),

        .refcount_table_offset  = cpu_to_be64(s->refcount_table_offset),

        .refcount_table_clusters = cpu_to_be32(refcount_table_clusters),

        .nb_snapshots           = cpu_to_be32(s->nb_snapshots),

        .snapshots_offset       = cpu_to_be64(s->snapshots_offset),



        

        .incompatible_features  = cpu_to_be64(s->incompatible_features),

        .compatible_features    = cpu_to_be64(s->compatible_features),

        .autoclear_features     = cpu_to_be64(s->autoclear_features),

        .refcount_order         = cpu_to_be32(3 + REFCOUNT_SHIFT),

        .header_length          = cpu_to_be32(header_length),

    };



    

    switch (s->qcow_version) {

    case 2:

        VAR_2 = offsetof(QCowHeader, incompatible_features);

        break;

    case 3:

        VAR_2 = sizeof(*header);

        break;

    default:

        return -EINVAL;

    }



    VAR_1 += VAR_2;

    buflen -= VAR_2;

    memset(VAR_1, 0, buflen);



    

    if (s->unknown_header_fields_size) {

        if (buflen < s->unknown_header_fields_size) {

            VAR_2 = -ENOSPC;

            goto fail;

        }



        memcpy(VAR_1, s->unknown_header_fields, s->unknown_header_fields_size);

        VAR_1 += s->unknown_header_fields_size;

        buflen -= s->unknown_header_fields_size;

    }



    

    if (*VAR_0->backing_format) {

        VAR_2 = header_ext_add(VAR_1, QCOW2_EXT_MAGIC_BACKING_FORMAT,

                             VAR_0->backing_format, strlen(VAR_0->backing_format),

                             buflen);

        if (VAR_2 < 0) {

            goto fail;

        }



        VAR_1 += VAR_2;

        buflen -= VAR_2;

    }



    

    Qcow2Feature features[] = {

        

    };



    VAR_2 = header_ext_add(VAR_1, QCOW2_EXT_MAGIC_FEATURE_TABLE,

                         features, sizeof(features), buflen);

    if (VAR_2 < 0) {

        goto fail;

    }

    VAR_1 += VAR_2;

    buflen -= VAR_2;



    

    QLIST_FOREACH(uext, &s->unknown_header_ext, next) {

        VAR_2 = header_ext_add(VAR_1, uext->magic, uext->data, uext->len, buflen);

        if (VAR_2 < 0) {

            goto fail;

        }



        VAR_1 += VAR_2;

        buflen -= VAR_2;

    }



    

    VAR_2 = header_ext_add(VAR_1, QCOW2_EXT_MAGIC_END, NULL, 0, buflen);

    if (VAR_2 < 0) {

        goto fail;

    }



    VAR_1 += VAR_2;

    buflen -= VAR_2;



    

    if (*VAR_0->backing_file) {

        size_t backing_file_len = strlen(VAR_0->backing_file);



        if (buflen < backing_file_len) {

            VAR_2 = -ENOSPC;

            goto fail;

        }



        strncpy(VAR_1, VAR_0->backing_file, buflen);



        header->backing_file_offset = cpu_to_be64(VAR_1 - ((char*) header));

        header->backing_file_size   = cpu_to_be32(backing_file_len);

    }



    

    VAR_2 = bdrv_pwrite(VAR_0->file, 0, header, s->cluster_size);

    if (VAR_2 < 0) {

        goto fail;

    }



    VAR_2 = 0;

fail:

    qemu_vfree(header);

    return VAR_2;

}

int FUNC_0(BlockDriverState *VAR_0)
{ BDRVQcowState *s = VAR_0->opaque; QCowHeader *header; char *VAR_1; size_t buflen = s->cluster_size; int VAR_2; uint64_t total_size; uint32_t refcount_table_clusters; size_t header_length; Qcow2UnknownHeaderExtension *uext; VAR_1 = qemu_blockalign(VAR_0, buflen); header = (QCowHeader*) VAR_1; if (buflen < sizeof(*header)) { VAR_2 = -ENOSPC; goto fail; } header_length = sizeof(*header) + s->unknown_header_fields_size; total_size = VAR_0->total_sectors * BDRV_SECTOR_SIZE; refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3); *header = (QCowHeader) { .magic                  = cpu_to_be32(QCOW_MAGIC),
.version                = cpu_to_be32(s->qcow_version),
.backing_file_offset    = 0,
.backing_file_size      = 0,
.cluster_bits           = cpu_to_be32(s->cluster_bits),
.size                   = cpu_to_be64(total_size),
.crypt_method           = cpu_to_be32(s->crypt_method_header),
.l1_size                = cpu_to_be32(s->l1_size),
.l1_table_offset        = cpu_to_be64(s->l1_table_offset),
.refcount_table_offset  = cpu_to_be64(s->refcount_table_offset),
.refcount_table_clusters = cpu_to_be32(refcount_table_clusters),
.nb_snapshots           = cpu_to_be32(s->nb_snapshots),
.snapshots_offset       = cpu_to_be64(s->snapshots_offset),
.incompatible_features  = cpu_to_be64(s->incompatible_features),
.compatible_features    = cpu_to_be64(s->compatible_features),
.autoclear_features     = cpu_to_be64(s->autoclear_features),
.refcount_order         = cpu_to_be32(3 + REFCOUNT_SHIFT),
.header_length          = cpu_to_be32(header_length),
}; switch (s->qcow_version) { case 2:
VAR_2 = offsetof(QCowHeader, incompatible_features); break; case 3:
VAR_2 = sizeof(*header); break; default:
return -EINVAL; } VAR_1 += VAR_2; buflen -= VAR_2; memset(VAR_1, 0, buflen); if (s->unknown_header_fields_size) { if (buflen < s->unknown_header_fields_size) { VAR_2 = -ENOSPC; goto fail; } memcpy(VAR_1, s->unknown_header_fields, s->unknown_header_fields_size); VAR_1 += s->unknown_header_fields_size; buflen -= s->unknown_header_fields_size; } if (*VAR_0->backing_format) { VAR_2 = header_ext_add(VAR_1, QCOW2_EXT_MAGIC_BACKING_FORMAT,
VAR_0->backing_format, strlen(VAR_0->backing_format),
buflen); if (VAR_2 < 0) { goto fail; } VAR_1 += VAR_2; buflen -= VAR_2; } Qcow2Feature features[] = { }; VAR_2 = header_ext_add(VAR_1, QCOW2_EXT_MAGIC_FEATURE_TABLE,
features, sizeof(features), buflen); if (VAR_2 < 0) { goto fail; } VAR_1 += VAR_2; buflen -= VAR_2; QLIST_FOREACH(uext, &s->unknown_header_ext, next) { VAR_2 = header_ext_add(VAR_1, uext->magic, uext->data, uext->len, buflen); if (VAR_2 < 0) { goto fail; } VAR_1 += VAR_2; buflen -= VAR_2; } VAR_2 = header_ext_add(VAR_1, QCOW2_EXT_MAGIC_END, NULL, 0, buflen); if (VAR_2 < 0) { goto fail; } VAR_1 += VAR_2; buflen -= VAR_2; if (*VAR_0->backing_file) { size_t backing_file_len = strlen(VAR_0->backing_file); if (buflen < backing_file_len) { VAR_2 = -ENOSPC; goto fail; } strncpy(VAR_1, VAR_0->backing_file, buflen); header->backing_file_offset = cpu_to_be64(VAR_1 - ((char*) header)); header->backing_file_size   = cpu_to_be32(backing_file_len); } VAR_2 = bdrv_pwrite(VAR_0->file, 0, header, s->cluster_size); if (VAR_2 < 0) { goto fail; } VAR_2 = 0; fail:
qemu_vfree(header); return VAR_2; }