static int vhdx_create_new_region_table(BlockDriverState *bs,

                                        uint64_t image_size,

                                        uint32_t block_size,

                                        uint32_t sector_size,

                                        uint32_t log_size,

                                        bool use_zero_blocks,

                                        VHDXImageType type,

                                        uint64_t *metadata_offset)

{

    int ret = 0;

    uint32_t offset = 0;

    void *buffer = NULL;

    uint64_t bat_file_offset;

    uint32_t bat_length;

    BDRVVHDXState *s = NULL;

    VHDXRegionTableHeader *region_table;

    VHDXRegionTableEntry *rt_bat;

    VHDXRegionTableEntry *rt_metadata;



    assert(metadata_offset != NULL);



    /* Populate enough of the BDRVVHDXState to be able to use the

     * pre-existing BAT calculation, translation, and update functions */

    s = g_new0(BDRVVHDXState, 1);



    s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *

                     (uint64_t) sector_size / (uint64_t) block_size;



    s->sectors_per_block = block_size / sector_size;

    s->virtual_disk_size = image_size;

    s->block_size = block_size;

    s->logical_sector_size = sector_size;



    vhdx_set_shift_bits(s);



    vhdx_calc_bat_entries(s);



    /* At this point the VHDX state is populated enough for creation */



    /* a single buffer is used so we can calculate the checksum over the

     * entire 64KB block */

    buffer = g_malloc0(VHDX_HEADER_BLOCK_SIZE);

    region_table = buffer;

    offset += sizeof(VHDXRegionTableHeader);

    rt_bat = buffer + offset;

    offset += sizeof(VHDXRegionTableEntry);

    rt_metadata  = buffer + offset;



    region_table->signature = VHDX_REGION_SIGNATURE;

    region_table->entry_count = 2;   /* BAT and Metadata */



    rt_bat->guid        = bat_guid;

    rt_bat->length      = ROUND_UP(s->bat_entries * sizeof(VHDXBatEntry), MiB);

    rt_bat->file_offset = ROUND_UP(VHDX_HEADER_SECTION_END + log_size, MiB);

    s->bat_offset = rt_bat->file_offset;



    rt_metadata->guid        = metadata_guid;

    rt_metadata->file_offset = ROUND_UP(rt_bat->file_offset + rt_bat->length,

                                        MiB);

    rt_metadata->length      = 1 * MiB; /* min size, and more than enough */

    *metadata_offset = rt_metadata->file_offset;



    bat_file_offset = rt_bat->file_offset;

    bat_length = rt_bat->length;



    vhdx_region_header_le_export(region_table);

    vhdx_region_entry_le_export(rt_bat);

    vhdx_region_entry_le_export(rt_metadata);



    vhdx_update_checksum(buffer, VHDX_HEADER_BLOCK_SIZE,

                         offsetof(VHDXRegionTableHeader, checksum));





    /* The region table gives us the data we need to create the BAT,

     * so do that now */

    ret = vhdx_create_bat(bs, s, image_size, type, use_zero_blocks,

                          bat_file_offset, bat_length);

    if (ret < 0) {

        goto exit;

    }



    /* Now write out the region headers to disk */

    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE_OFFSET, buffer,

                      VHDX_HEADER_BLOCK_SIZE);

    if (ret < 0) {

        goto exit;

    }



    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE2_OFFSET, buffer,

                      VHDX_HEADER_BLOCK_SIZE);

    if (ret < 0) {

        goto exit;

    }



exit:

    g_free(s);

    g_free(buffer);

    return ret;

}

static int vhdx_create_new_region_table(BlockDriverState *bs,

                                        uint64_t image_size,

                                        uint32_t block_size,

                                        uint32_t sector_size,

                                        uint32_t log_size,

                                        bool use_zero_blocks,

                                        VHDXImageType type,

                                        uint64_t *metadata_offset)

{

    int ret = 0;

    uint32_t offset = 0;

    void *buffer = NULL;

    uint64_t bat_file_offset;

    uint32_t bat_length;

    BDRVVHDXState *s = NULL;

    VHDXRegionTableHeader *region_table;

    VHDXRegionTableEntry *rt_bat;

    VHDXRegionTableEntry *rt_metadata;



    assert(metadata_offset != NULL);



    



    s = g_new0(BDRVVHDXState, 1);



    s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *

                     (uint64_t) sector_size / (uint64_t) block_size;



    s->sectors_per_block = block_size / sector_size;

    s->virtual_disk_size = image_size;

    s->block_size = block_size;

    s->logical_sector_size = sector_size;



    vhdx_set_shift_bits(s);



    vhdx_calc_bat_entries(s);



    



    



    buffer = g_malloc0(VHDX_HEADER_BLOCK_SIZE);

    region_table = buffer;

    offset += sizeof(VHDXRegionTableHeader);

    rt_bat = buffer + offset;

    offset += sizeof(VHDXRegionTableEntry);

    rt_metadata  = buffer + offset;



    region_table->signature = VHDX_REGION_SIGNATURE;

    region_table->entry_count = 2;   



    rt_bat->guid        = bat_guid;

    rt_bat->length      = ROUND_UP(s->bat_entries * sizeof(VHDXBatEntry), MiB);

    rt_bat->file_offset = ROUND_UP(VHDX_HEADER_SECTION_END + log_size, MiB);

    s->bat_offset = rt_bat->file_offset;



    rt_metadata->guid        = metadata_guid;

    rt_metadata->file_offset = ROUND_UP(rt_bat->file_offset + rt_bat->length,

                                        MiB);

    rt_metadata->length      = 1 * MiB; 

    *metadata_offset = rt_metadata->file_offset;



    bat_file_offset = rt_bat->file_offset;

    bat_length = rt_bat->length;



    vhdx_region_header_le_export(region_table);

    vhdx_region_entry_le_export(rt_bat);

    vhdx_region_entry_le_export(rt_metadata);



    vhdx_update_checksum(buffer, VHDX_HEADER_BLOCK_SIZE,

                         offsetof(VHDXRegionTableHeader, checksum));





    



    ret = vhdx_create_bat(bs, s, image_size, type, use_zero_blocks,

                          bat_file_offset, bat_length);

    if (ret < 0) {

        goto exit;

    }



    

    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE_OFFSET, buffer,

                      VHDX_HEADER_BLOCK_SIZE);

    if (ret < 0) {

        goto exit;

    }



    ret = bdrv_pwrite(bs, VHDX_REGION_TABLE2_OFFSET, buffer,

                      VHDX_HEADER_BLOCK_SIZE);

    if (ret < 0) {

        goto exit;

    }



exit:

    g_free(s);

    g_free(buffer);

    return ret;

}

static int FUNC_0(BlockDriverState *VAR_0,

                                        uint64_t VAR_1,

                                        uint32_t VAR_2,

                                        uint32_t VAR_3,

                                        uint32_t VAR_4,

                                        bool VAR_5,

                                        VHDXImageType VAR_6,

                                        uint64_t *VAR_7)

{

    int VAR_8 = 0;

    uint32_t offset = 0;

    void *VAR_9 = NULL;

    uint64_t bat_file_offset;

    uint32_t bat_length;

    BDRVVHDXState *s = NULL;

    VHDXRegionTableHeader *region_table;

    VHDXRegionTableEntry *rt_bat;

    VHDXRegionTableEntry *rt_metadata;



    assert(VAR_7 != NULL);



    



    s = g_new0(BDRVVHDXState, 1);



    s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *

                     (uint64_t) VAR_3 / (uint64_t) VAR_2;



    s->sectors_per_block = VAR_2 / VAR_3;

    s->virtual_disk_size = VAR_1;

    s->VAR_2 = VAR_2;

    s->logical_sector_size = VAR_3;



    vhdx_set_shift_bits(s);



    vhdx_calc_bat_entries(s);



    



    



    VAR_9 = g_malloc0(VHDX_HEADER_BLOCK_SIZE);

    region_table = VAR_9;

    offset += sizeof(VHDXRegionTableHeader);

    rt_bat = VAR_9 + offset;

    offset += sizeof(VHDXRegionTableEntry);

    rt_metadata  = VAR_9 + offset;



    region_table->signature = VHDX_REGION_SIGNATURE;

    region_table->entry_count = 2;   



    rt_bat->guid        = bat_guid;

    rt_bat->length      = ROUND_UP(s->bat_entries * sizeof(VHDXBatEntry), MiB);

    rt_bat->file_offset = ROUND_UP(VHDX_HEADER_SECTION_END + VAR_4, MiB);

    s->bat_offset = rt_bat->file_offset;



    rt_metadata->guid        = metadata_guid;

    rt_metadata->file_offset = ROUND_UP(rt_bat->file_offset + rt_bat->length,

                                        MiB);

    rt_metadata->length      = 1 * MiB; 

    *VAR_7 = rt_metadata->file_offset;



    bat_file_offset = rt_bat->file_offset;

    bat_length = rt_bat->length;



    vhdx_region_header_le_export(region_table);

    vhdx_region_entry_le_export(rt_bat);

    vhdx_region_entry_le_export(rt_metadata);



    vhdx_update_checksum(VAR_9, VHDX_HEADER_BLOCK_SIZE,

                         offsetof(VHDXRegionTableHeader, checksum));





    



    VAR_8 = vhdx_create_bat(VAR_0, s, VAR_1, VAR_6, VAR_5,

                          bat_file_offset, bat_length);

    if (VAR_8 < 0) {

        goto exit;

    }



    

    VAR_8 = bdrv_pwrite(VAR_0, VHDX_REGION_TABLE_OFFSET, VAR_9,

                      VHDX_HEADER_BLOCK_SIZE);

    if (VAR_8 < 0) {

        goto exit;

    }



    VAR_8 = bdrv_pwrite(VAR_0, VHDX_REGION_TABLE2_OFFSET, VAR_9,

                      VHDX_HEADER_BLOCK_SIZE);

    if (VAR_8 < 0) {

        goto exit;

    }



exit:

    g_free(s);

    g_free(VAR_9);

    return VAR_8;

}

static int FUNC_0(BlockDriverState *VAR_0,
uint64_t VAR_1,
uint32_t VAR_2,
uint32_t VAR_3,
uint32_t VAR_4,
bool VAR_5,
VHDXImageType VAR_6,
uint64_t *VAR_7)
{ int VAR_8 = 0; uint32_t offset = 0; void *VAR_9 = NULL; uint64_t bat_file_offset; uint32_t bat_length; BDRVVHDXState *s = NULL; VHDXRegionTableHeader *region_table; VHDXRegionTableEntry *rt_bat; VHDXRegionTableEntry *rt_metadata; assert(VAR_7 != NULL); s = g_new0(BDRVVHDXState, 1); s->chunk_ratio = (VHDX_MAX_SECTORS_PER_BLOCK) *
(uint64_t) VAR_3 / (uint64_t) VAR_2; s->sectors_per_block = VAR_2 / VAR_3; s->virtual_disk_size = VAR_1; s->VAR_2 = VAR_2; s->logical_sector_size = VAR_3; vhdx_set_shift_bits(s); vhdx_calc_bat_entries(s); VAR_9 = g_malloc0(VHDX_HEADER_BLOCK_SIZE); region_table = VAR_9; offset += sizeof(VHDXRegionTableHeader); rt_bat = VAR_9 + offset; offset += sizeof(VHDXRegionTableEntry); rt_metadata  = VAR_9 + offset; region_table->signature = VHDX_REGION_SIGNATURE; region_table->entry_count = 2; rt_bat->guid        = bat_guid; rt_bat->length      = ROUND_UP(s->bat_entries * sizeof(VHDXBatEntry), MiB); rt_bat->file_offset = ROUND_UP(VHDX_HEADER_SECTION_END + VAR_4, MiB); s->bat_offset = rt_bat->file_offset; rt_metadata->guid        = metadata_guid; rt_metadata->file_offset = ROUND_UP(rt_bat->file_offset + rt_bat->length,
MiB); rt_metadata->length      = 1 * MiB; *VAR_7 = rt_metadata->file_offset; bat_file_offset = rt_bat->file_offset; bat_length = rt_bat->length; vhdx_region_header_le_export(region_table); vhdx_region_entry_le_export(rt_bat); vhdx_region_entry_le_export(rt_metadata); vhdx_update_checksum(VAR_9, VHDX_HEADER_BLOCK_SIZE,
offsetof(VHDXRegionTableHeader, checksum)); VAR_8 = vhdx_create_bat(VAR_0, s, VAR_1, VAR_6, VAR_5,
bat_file_offset, bat_length); if (VAR_8 < 0) { goto exit; } VAR_8 = bdrv_pwrite(VAR_0, VHDX_REGION_TABLE_OFFSET, VAR_9,
VHDX_HEADER_BLOCK_SIZE); if (VAR_8 < 0) { goto exit; } VAR_8 = bdrv_pwrite(VAR_0, VHDX_REGION_TABLE2_OFFSET, VAR_9,
VHDX_HEADER_BLOCK_SIZE); if (VAR_8 < 0) { goto exit; } exit:
g_free(s); g_free(VAR_9); return VAR_8; }