static int qcow2_open(BlockDriverState *bs, int flags)

{

    BDRVQcowState *s = bs->opaque;

    int len, i, ret = 0;

    QCowHeader header;

    uint64_t ext_end;



    ret = bdrv_pread(bs->file, 0, &header, sizeof(header));

    if (ret < 0) {

        goto fail;

    }

    be32_to_cpus(&header.magic);

    be32_to_cpus(&header.version);

    be64_to_cpus(&header.backing_file_offset);

    be32_to_cpus(&header.backing_file_size);

    be64_to_cpus(&header.size);

    be32_to_cpus(&header.cluster_bits);

    be32_to_cpus(&header.crypt_method);

    be64_to_cpus(&header.l1_table_offset);

    be32_to_cpus(&header.l1_size);

    be64_to_cpus(&header.refcount_table_offset);

    be32_to_cpus(&header.refcount_table_clusters);

    be64_to_cpus(&header.snapshots_offset);

    be32_to_cpus(&header.nb_snapshots);



    if (header.magic != QCOW_MAGIC) {

        ret = -EINVAL;

        goto fail;

    }

    if (header.version < 2 || header.version > 3) {

        report_unsupported(bs, "QCOW version %d", header.version);

        ret = -ENOTSUP;

        goto fail;

    }



    s->qcow_version = header.version;



    /* Initialise version 3 header fields */

    if (header.version == 2) {

        header.incompatible_features    = 0;

        header.compatible_features      = 0;

        header.autoclear_features       = 0;

        header.refcount_order           = 4;

        header.header_length            = 72;

    } else {

        be64_to_cpus(&header.incompatible_features);

        be64_to_cpus(&header.compatible_features);

        be64_to_cpus(&header.autoclear_features);

        be32_to_cpus(&header.refcount_order);

        be32_to_cpus(&header.header_length);

    }



    if (header.header_length > sizeof(header)) {

        s->unknown_header_fields_size = header.header_length - sizeof(header);

        s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);

        ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields,

                         s->unknown_header_fields_size);

        if (ret < 0) {

            goto fail;

        }

    }



    if (header.backing_file_offset) {

        ext_end = header.backing_file_offset;

    } else {

        ext_end = 1 << header.cluster_bits;

    }



    /* Handle feature bits */

    s->incompatible_features    = header.incompatible_features;

    s->compatible_features      = header.compatible_features;

    s->autoclear_features       = header.autoclear_features;



    if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {

        void *feature_table = NULL;

        qcow2_read_extensions(bs, header.header_length, ext_end,

                              &feature_table);

        report_unsupported_feature(bs, feature_table,

                                   s->incompatible_features &

                                   ~QCOW2_INCOMPAT_MASK);

        ret = -ENOTSUP;

        goto fail;

    }



    /* Check support for various header values */

    if (header.refcount_order != 4) {

        report_unsupported(bs, "%d bit reference counts",

                           1 << header.refcount_order);

        ret = -ENOTSUP;

        goto fail;

    }



    if (header.cluster_bits < MIN_CLUSTER_BITS ||

        header.cluster_bits > MAX_CLUSTER_BITS) {

        ret = -EINVAL;

        goto fail;

    }

    if (header.crypt_method > QCOW_CRYPT_AES) {

        ret = -EINVAL;

        goto fail;

    }

    s->crypt_method_header = header.crypt_method;

    if (s->crypt_method_header) {

        bs->encrypted = 1;

    }

    s->cluster_bits = header.cluster_bits;

    s->cluster_size = 1 << s->cluster_bits;

    s->cluster_sectors = 1 << (s->cluster_bits - 9);

    s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */

    s->l2_size = 1 << s->l2_bits;

    bs->total_sectors = header.size / 512;

    s->csize_shift = (62 - (s->cluster_bits - 8));

    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;

    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;

    s->refcount_table_offset = header.refcount_table_offset;

    s->refcount_table_size =

        header.refcount_table_clusters << (s->cluster_bits - 3);



    s->snapshots_offset = header.snapshots_offset;

    s->nb_snapshots = header.nb_snapshots;



    /* read the level 1 table */

    s->l1_size = header.l1_size;

    s->l1_vm_state_index = size_to_l1(s, header.size);

    /* the L1 table must contain at least enough entries to put

       header.size bytes */

    if (s->l1_size < s->l1_vm_state_index) {

        ret = -EINVAL;

        goto fail;

    }

    s->l1_table_offset = header.l1_table_offset;

    if (s->l1_size > 0) {

        s->l1_table = g_malloc0(

            align_offset(s->l1_size * sizeof(uint64_t), 512));

        ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,

                         s->l1_size * sizeof(uint64_t));

        if (ret < 0) {

            goto fail;

        }

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

            be64_to_cpus(&s->l1_table[i]);

        }

    }



    /* alloc L2 table/refcount block cache */

    s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE);

    s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE);



    s->cluster_cache = g_malloc(s->cluster_size);

    /* one more sector for decompressed data alignment */

    s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size

                                  + 512);

    s->cluster_cache_offset = -1;

    s->flags = flags;



    ret = qcow2_refcount_init(bs);

    if (ret != 0) {

        goto fail;

    }



    QLIST_INIT(&s->cluster_allocs);



    /* read qcow2 extensions */

    if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL)) {

        ret = -EINVAL;

        goto fail;

    }



    /* read the backing file name */

    if (header.backing_file_offset != 0) {

        len = header.backing_file_size;

        if (len > 1023) {

            len = 1023;

        }

        ret = bdrv_pread(bs->file, header.backing_file_offset,

                         bs->backing_file, len);

        if (ret < 0) {

            goto fail;

        }

        bs->backing_file[len] = '\0';

    }



    ret = qcow2_read_snapshots(bs);

    if (ret < 0) {

        goto fail;

    }



    /* Clear unknown autoclear feature bits */

    if (!bs->read_only && s->autoclear_features != 0) {

        s->autoclear_features = 0;

        ret = qcow2_update_header(bs);

        if (ret < 0) {

            goto fail;

        }

    }



    /* Initialise locks */

    qemu_co_mutex_init(&s->lock);



    /* Repair image if dirty */

    if ((s->incompatible_features & QCOW2_INCOMPAT_DIRTY) &&

        !bs->read_only) {

        BdrvCheckResult result = {0};



        ret = qcow2_check_refcounts(bs, &result, BDRV_FIX_ERRORS);

        if (ret < 0) {

            goto fail;

        }



        ret = qcow2_mark_clean(bs);

        if (ret < 0) {

            goto fail;

        }

    }



#ifdef DEBUG_ALLOC

    {

        BdrvCheckResult result = {0};

        qcow2_check_refcounts(bs, &result, 0);

    }

#endif

    return ret;



 fail:

    g_free(s->unknown_header_fields);

    cleanup_unknown_header_ext(bs);

    qcow2_free_snapshots(bs);

    qcow2_refcount_close(bs);

    g_free(s->l1_table);

    if (s->l2_table_cache) {

        qcow2_cache_destroy(bs, s->l2_table_cache);

    }

    g_free(s->cluster_cache);

    qemu_vfree(s->cluster_data);

    return ret;

}

static int qcow2_open(BlockDriverState *bs, int flags)

{

    BDRVQcowState *s = bs->opaque;

    int len, i, ret = 0;

    QCowHeader header;

    uint64_t ext_end;



    ret = bdrv_pread(bs->file, 0, &header, sizeof(header));

    if (ret < 0) {

        goto fail;

    }

    be32_to_cpus(&header.magic);

    be32_to_cpus(&header.version);

    be64_to_cpus(&header.backing_file_offset);

    be32_to_cpus(&header.backing_file_size);

    be64_to_cpus(&header.size);

    be32_to_cpus(&header.cluster_bits);

    be32_to_cpus(&header.crypt_method);

    be64_to_cpus(&header.l1_table_offset);

    be32_to_cpus(&header.l1_size);

    be64_to_cpus(&header.refcount_table_offset);

    be32_to_cpus(&header.refcount_table_clusters);

    be64_to_cpus(&header.snapshots_offset);

    be32_to_cpus(&header.nb_snapshots);



    if (header.magic != QCOW_MAGIC) {

        ret = -EINVAL;

        goto fail;

    }

    if (header.version < 2 || header.version > 3) {

        report_unsupported(bs, "QCOW version %d", header.version);

        ret = -ENOTSUP;

        goto fail;

    }



    s->qcow_version = header.version;



    

    if (header.version == 2) {

        header.incompatible_features    = 0;

        header.compatible_features      = 0;

        header.autoclear_features       = 0;

        header.refcount_order           = 4;

        header.header_length            = 72;

    } else {

        be64_to_cpus(&header.incompatible_features);

        be64_to_cpus(&header.compatible_features);

        be64_to_cpus(&header.autoclear_features);

        be32_to_cpus(&header.refcount_order);

        be32_to_cpus(&header.header_length);

    }



    if (header.header_length > sizeof(header)) {

        s->unknown_header_fields_size = header.header_length - sizeof(header);

        s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);

        ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields,

                         s->unknown_header_fields_size);

        if (ret < 0) {

            goto fail;

        }

    }



    if (header.backing_file_offset) {

        ext_end = header.backing_file_offset;

    } else {

        ext_end = 1 << header.cluster_bits;

    }



    

    s->incompatible_features    = header.incompatible_features;

    s->compatible_features      = header.compatible_features;

    s->autoclear_features       = header.autoclear_features;



    if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {

        void *feature_table = NULL;

        qcow2_read_extensions(bs, header.header_length, ext_end,

                              &feature_table);

        report_unsupported_feature(bs, feature_table,

                                   s->incompatible_features &

                                   ~QCOW2_INCOMPAT_MASK);

        ret = -ENOTSUP;

        goto fail;

    }



    

    if (header.refcount_order != 4) {

        report_unsupported(bs, "%d bit reference counts",

                           1 << header.refcount_order);

        ret = -ENOTSUP;

        goto fail;

    }



    if (header.cluster_bits < MIN_CLUSTER_BITS ||

        header.cluster_bits > MAX_CLUSTER_BITS) {

        ret = -EINVAL;

        goto fail;

    }

    if (header.crypt_method > QCOW_CRYPT_AES) {

        ret = -EINVAL;

        goto fail;

    }

    s->crypt_method_header = header.crypt_method;

    if (s->crypt_method_header) {

        bs->encrypted = 1;

    }

    s->cluster_bits = header.cluster_bits;

    s->cluster_size = 1 << s->cluster_bits;

    s->cluster_sectors = 1 << (s->cluster_bits - 9);

    s->l2_bits = s->cluster_bits - 3; 

    s->l2_size = 1 << s->l2_bits;

    bs->total_sectors = header.size / 512;

    s->csize_shift = (62 - (s->cluster_bits - 8));

    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;

    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;

    s->refcount_table_offset = header.refcount_table_offset;

    s->refcount_table_size =

        header.refcount_table_clusters << (s->cluster_bits - 3);



    s->snapshots_offset = header.snapshots_offset;

    s->nb_snapshots = header.nb_snapshots;



    

    s->l1_size = header.l1_size;

    s->l1_vm_state_index = size_to_l1(s, header.size);

    



    if (s->l1_size < s->l1_vm_state_index) {

        ret = -EINVAL;

        goto fail;

    }

    s->l1_table_offset = header.l1_table_offset;

    if (s->l1_size > 0) {

        s->l1_table = g_malloc0(

            align_offset(s->l1_size * sizeof(uint64_t), 512));

        ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,

                         s->l1_size * sizeof(uint64_t));

        if (ret < 0) {

            goto fail;

        }

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

            be64_to_cpus(&s->l1_table[i]);

        }

    }



    

    s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE);

    s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE);



    s->cluster_cache = g_malloc(s->cluster_size);

    

    s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size

                                  + 512);

    s->cluster_cache_offset = -1;

    s->flags = flags;



    ret = qcow2_refcount_init(bs);

    if (ret != 0) {

        goto fail;

    }



    QLIST_INIT(&s->cluster_allocs);



    

    if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL)) {

        ret = -EINVAL;

        goto fail;

    }



    

    if (header.backing_file_offset != 0) {

        len = header.backing_file_size;

        if (len > 1023) {

            len = 1023;

        }

        ret = bdrv_pread(bs->file, header.backing_file_offset,

                         bs->backing_file, len);

        if (ret < 0) {

            goto fail;

        }

        bs->backing_file[len] = '\0';

    }



    ret = qcow2_read_snapshots(bs);

    if (ret < 0) {

        goto fail;

    }



    

    if (!bs->read_only && s->autoclear_features != 0) {

        s->autoclear_features = 0;

        ret = qcow2_update_header(bs);

        if (ret < 0) {

            goto fail;

        }

    }



    

    qemu_co_mutex_init(&s->lock);



    

    if ((s->incompatible_features & QCOW2_INCOMPAT_DIRTY) &&

        !bs->read_only) {

        BdrvCheckResult result = {0};



        ret = qcow2_check_refcounts(bs, &result, BDRV_FIX_ERRORS);

        if (ret < 0) {

            goto fail;

        }



        ret = qcow2_mark_clean(bs);

        if (ret < 0) {

            goto fail;

        }

    }



#ifdef DEBUG_ALLOC

    {

        BdrvCheckResult result = {0};

        qcow2_check_refcounts(bs, &result, 0);

    }

#endif

    return ret;



 fail:

    g_free(s->unknown_header_fields);

    cleanup_unknown_header_ext(bs);

    qcow2_free_snapshots(bs);

    qcow2_refcount_close(bs);

    g_free(s->l1_table);

    if (s->l2_table_cache) {

        qcow2_cache_destroy(bs, s->l2_table_cache);

    }

    g_free(s->cluster_cache);

    qemu_vfree(s->cluster_data);

    return ret;

}

static int FUNC_0(BlockDriverState *VAR_0, int VAR_1)

{

    BDRVQcowState *s = VAR_0->opaque;

    int VAR_2, VAR_3, VAR_4 = 0;

    QCowHeader header;

    uint64_t ext_end;



    VAR_4 = bdrv_pread(VAR_0->file, 0, &header, sizeof(header));

    if (VAR_4 < 0) {

        goto fail;

    }

    be32_to_cpus(&header.magic);

    be32_to_cpus(&header.version);

    be64_to_cpus(&header.backing_file_offset);

    be32_to_cpus(&header.backing_file_size);

    be64_to_cpus(&header.size);

    be32_to_cpus(&header.cluster_bits);

    be32_to_cpus(&header.crypt_method);

    be64_to_cpus(&header.l1_table_offset);

    be32_to_cpus(&header.l1_size);

    be64_to_cpus(&header.refcount_table_offset);

    be32_to_cpus(&header.refcount_table_clusters);

    be64_to_cpus(&header.snapshots_offset);

    be32_to_cpus(&header.nb_snapshots);



    if (header.magic != QCOW_MAGIC) {

        VAR_4 = -EINVAL;

        goto fail;

    }

    if (header.version < 2 || header.version > 3) {

        report_unsupported(VAR_0, "QCOW version %d", header.version);

        VAR_4 = -ENOTSUP;

        goto fail;

    }



    s->qcow_version = header.version;



    

    if (header.version == 2) {

        header.incompatible_features    = 0;

        header.compatible_features      = 0;

        header.autoclear_features       = 0;

        header.refcount_order           = 4;

        header.header_length            = 72;

    } else {

        be64_to_cpus(&header.incompatible_features);

        be64_to_cpus(&header.compatible_features);

        be64_to_cpus(&header.autoclear_features);

        be32_to_cpus(&header.refcount_order);

        be32_to_cpus(&header.header_length);

    }



    if (header.header_length > sizeof(header)) {

        s->unknown_header_fields_size = header.header_length - sizeof(header);

        s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);

        VAR_4 = bdrv_pread(VAR_0->file, sizeof(header), s->unknown_header_fields,

                         s->unknown_header_fields_size);

        if (VAR_4 < 0) {

            goto fail;

        }

    }



    if (header.backing_file_offset) {

        ext_end = header.backing_file_offset;

    } else {

        ext_end = 1 << header.cluster_bits;

    }



    

    s->incompatible_features    = header.incompatible_features;

    s->compatible_features      = header.compatible_features;

    s->autoclear_features       = header.autoclear_features;



    if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {

        void *VAR_5 = NULL;

        qcow2_read_extensions(VAR_0, header.header_length, ext_end,

                              &VAR_5);

        report_unsupported_feature(VAR_0, VAR_5,

                                   s->incompatible_features &

                                   ~QCOW2_INCOMPAT_MASK);

        VAR_4 = -ENOTSUP;

        goto fail;

    }



    

    if (header.refcount_order != 4) {

        report_unsupported(VAR_0, "%d bit reference counts",

                           1 << header.refcount_order);

        VAR_4 = -ENOTSUP;

        goto fail;

    }



    if (header.cluster_bits < MIN_CLUSTER_BITS ||

        header.cluster_bits > MAX_CLUSTER_BITS) {

        VAR_4 = -EINVAL;

        goto fail;

    }

    if (header.crypt_method > QCOW_CRYPT_AES) {

        VAR_4 = -EINVAL;

        goto fail;

    }

    s->crypt_method_header = header.crypt_method;

    if (s->crypt_method_header) {

        VAR_0->encrypted = 1;

    }

    s->cluster_bits = header.cluster_bits;

    s->cluster_size = 1 << s->cluster_bits;

    s->cluster_sectors = 1 << (s->cluster_bits - 9);

    s->l2_bits = s->cluster_bits - 3; 

    s->l2_size = 1 << s->l2_bits;

    VAR_0->total_sectors = header.size / 512;

    s->csize_shift = (62 - (s->cluster_bits - 8));

    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;

    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;

    s->refcount_table_offset = header.refcount_table_offset;

    s->refcount_table_size =

        header.refcount_table_clusters << (s->cluster_bits - 3);



    s->snapshots_offset = header.snapshots_offset;

    s->nb_snapshots = header.nb_snapshots;



    

    s->l1_size = header.l1_size;

    s->l1_vm_state_index = size_to_l1(s, header.size);

    



    if (s->l1_size < s->l1_vm_state_index) {

        VAR_4 = -EINVAL;

        goto fail;

    }

    s->l1_table_offset = header.l1_table_offset;

    if (s->l1_size > 0) {

        s->l1_table = g_malloc0(

            align_offset(s->l1_size * sizeof(uint64_t), 512));

        VAR_4 = bdrv_pread(VAR_0->file, s->l1_table_offset, s->l1_table,

                         s->l1_size * sizeof(uint64_t));

        if (VAR_4 < 0) {

            goto fail;

        }

        for(VAR_3 = 0;VAR_3 < s->l1_size; VAR_3++) {

            be64_to_cpus(&s->l1_table[VAR_3]);

        }

    }



    

    s->l2_table_cache = qcow2_cache_create(VAR_0, L2_CACHE_SIZE);

    s->refcount_block_cache = qcow2_cache_create(VAR_0, REFCOUNT_CACHE_SIZE);



    s->cluster_cache = g_malloc(s->cluster_size);

    

    s->cluster_data = qemu_blockalign(VAR_0, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size

                                  + 512);

    s->cluster_cache_offset = -1;

    s->VAR_1 = VAR_1;



    VAR_4 = qcow2_refcount_init(VAR_0);

    if (VAR_4 != 0) {

        goto fail;

    }



    QLIST_INIT(&s->cluster_allocs);



    

    if (qcow2_read_extensions(VAR_0, header.header_length, ext_end, NULL)) {

        VAR_4 = -EINVAL;

        goto fail;

    }



    

    if (header.backing_file_offset != 0) {

        VAR_2 = header.backing_file_size;

        if (VAR_2 > 1023) {

            VAR_2 = 1023;

        }

        VAR_4 = bdrv_pread(VAR_0->file, header.backing_file_offset,

                         VAR_0->backing_file, VAR_2);

        if (VAR_4 < 0) {

            goto fail;

        }

        VAR_0->backing_file[VAR_2] = '\0';

    }



    VAR_4 = qcow2_read_snapshots(VAR_0);

    if (VAR_4 < 0) {

        goto fail;

    }



    

    if (!VAR_0->read_only && s->autoclear_features != 0) {

        s->autoclear_features = 0;

        VAR_4 = qcow2_update_header(VAR_0);

        if (VAR_4 < 0) {

            goto fail;

        }

    }



    

    qemu_co_mutex_init(&s->lock);



    

    if ((s->incompatible_features & QCOW2_INCOMPAT_DIRTY) &&

        !VAR_0->read_only) {

        BdrvCheckResult result = {0};



        VAR_4 = qcow2_check_refcounts(VAR_0, &result, BDRV_FIX_ERRORS);

        if (VAR_4 < 0) {

            goto fail;

        }



        VAR_4 = qcow2_mark_clean(VAR_0);

        if (VAR_4 < 0) {

            goto fail;

        }

    }



#ifdef DEBUG_ALLOC

    {

        BdrvCheckResult result = {0};

        qcow2_check_refcounts(VAR_0, &result, 0);

    }

#endif

    return VAR_4;



 fail:

    g_free(s->unknown_header_fields);

    cleanup_unknown_header_ext(VAR_0);

    qcow2_free_snapshots(VAR_0);

    qcow2_refcount_close(VAR_0);

    g_free(s->l1_table);

    if (s->l2_table_cache) {

        qcow2_cache_destroy(VAR_0, s->l2_table_cache);

    }

    g_free(s->cluster_cache);

    qemu_vfree(s->cluster_data);

    return VAR_4;

}

static int FUNC_0(BlockDriverState *VAR_0, int VAR_1)
{ BDRVQcowState *s = VAR_0->opaque; int VAR_2, VAR_3, VAR_4 = 0; QCowHeader header; uint64_t ext_end; VAR_4 = bdrv_pread(VAR_0->file, 0, &header, sizeof(header)); if (VAR_4 < 0) { goto fail; } be32_to_cpus(&header.magic); be32_to_cpus(&header.version); be64_to_cpus(&header.backing_file_offset); be32_to_cpus(&header.backing_file_size); be64_to_cpus(&header.size); be32_to_cpus(&header.cluster_bits); be32_to_cpus(&header.crypt_method); be64_to_cpus(&header.l1_table_offset); be32_to_cpus(&header.l1_size); be64_to_cpus(&header.refcount_table_offset); be32_to_cpus(&header.refcount_table_clusters); be64_to_cpus(&header.snapshots_offset); be32_to_cpus(&header.nb_snapshots); if (header.magic != QCOW_MAGIC) { VAR_4 = -EINVAL; goto fail; } if (header.version < 2 || header.version > 3) { report_unsupported(VAR_0, "QCOW version %d", header.version); VAR_4 = -ENOTSUP; goto fail; } s->qcow_version = header.version; if (header.version == 2) { header.incompatible_features    = 0; header.compatible_features      = 0; header.autoclear_features       = 0; header.refcount_order           = 4; header.header_length            = 72; } else { be64_to_cpus(&header.incompatible_features); be64_to_cpus(&header.compatible_features); be64_to_cpus(&header.autoclear_features); be32_to_cpus(&header.refcount_order); be32_to_cpus(&header.header_length); } if (header.header_length > sizeof(header)) { s->unknown_header_fields_size = header.header_length - sizeof(header); s->unknown_header_fields = g_malloc(s->unknown_header_fields_size); VAR_4 = bdrv_pread(VAR_0->file, sizeof(header), s->unknown_header_fields,
s->unknown_header_fields_size); if (VAR_4 < 0) { goto fail; } } if (header.backing_file_offset) { ext_end = header.backing_file_offset; } else { ext_end = 1 << header.cluster_bits; } s->incompatible_features    = header.incompatible_features; s->compatible_features      = header.compatible_features; s->autoclear_features       = header.autoclear_features; if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) { void *VAR_5 = NULL; qcow2_read_extensions(VAR_0, header.header_length, ext_end,
&VAR_5); report_unsupported_feature(VAR_0, VAR_5,
s->incompatible_features &
~QCOW2_INCOMPAT_MASK); VAR_4 = -ENOTSUP; goto fail; } if (header.refcount_order != 4) { report_unsupported(VAR_0, "%d bit reference counts",
1 << header.refcount_order); VAR_4 = -ENOTSUP; goto fail; } if (header.cluster_bits < MIN_CLUSTER_BITS ||
header.cluster_bits > MAX_CLUSTER_BITS) { VAR_4 = -EINVAL; goto fail; } if (header.crypt_method > QCOW_CRYPT_AES) { VAR_4 = -EINVAL; goto fail; } s->crypt_method_header = header.crypt_method; if (s->crypt_method_header) { VAR_0->encrypted = 1; } s->cluster_bits = header.cluster_bits; s->cluster_size = 1 << s->cluster_bits; s->cluster_sectors = 1 << (s->cluster_bits - 9); s->l2_bits = s->cluster_bits - 3; s->l2_size = 1 << s->l2_bits; VAR_0->total_sectors = header.size / 512; s->csize_shift = (62 - (s->cluster_bits - 8)); s->csize_mask = (1 << (s->cluster_bits - 8)) - 1; s->cluster_offset_mask = (1LL << s->csize_shift) - 1; s->refcount_table_offset = header.refcount_table_offset; s->refcount_table_size =
header.refcount_table_clusters << (s->cluster_bits - 3); s->snapshots_offset = header.snapshots_offset; s->nb_snapshots = header.nb_snapshots; s->l1_size = header.l1_size; s->l1_vm_state_index = size_to_l1(s, header.size); if (s->l1_size < s->l1_vm_state_index) { VAR_4 = -EINVAL; goto fail; } s->l1_table_offset = header.l1_table_offset; if (s->l1_size > 0) { s->l1_table = g_malloc0(
align_offset(s->l1_size * sizeof(uint64_t), 512)); VAR_4 = bdrv_pread(VAR_0->file, s->l1_table_offset, s->l1_table,
s->l1_size * sizeof(uint64_t)); if (VAR_4 < 0) { goto fail; } for(VAR_3 = 0;VAR_3 < s->l1_size; VAR_3++) { be64_to_cpus(&s->l1_table[VAR_3]); } } s->l2_table_cache = qcow2_cache_create(VAR_0, L2_CACHE_SIZE); s->refcount_block_cache = qcow2_cache_create(VAR_0, REFCOUNT_CACHE_SIZE); s->cluster_cache = g_malloc(s->cluster_size); s->cluster_data = qemu_blockalign(VAR_0, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
+ 512); s->cluster_cache_offset = -1; s->VAR_1 = VAR_1; VAR_4 = qcow2_refcount_init(VAR_0); if (VAR_4 != 0) { goto fail; } QLIST_INIT(&s->cluster_allocs); if (qcow2_read_extensions(VAR_0, header.header_length, ext_end, NULL)) { VAR_4 = -EINVAL; goto fail; } if (header.backing_file_offset != 0) { VAR_2 = header.backing_file_size; if (VAR_2 > 1023) { VAR_2 = 1023; } VAR_4 = bdrv_pread(VAR_0->file, header.backing_file_offset,
VAR_0->backing_file, VAR_2); if (VAR_4 < 0) { goto fail; } VAR_0->backing_file[VAR_2] = '\0'; } VAR_4 = qcow2_read_snapshots(VAR_0); if (VAR_4 < 0) { goto fail; } if (!VAR_0->read_only && s->autoclear_features != 0) { s->autoclear_features = 0; VAR_4 = qcow2_update_header(VAR_0); if (VAR_4 < 0) { goto fail; } } qemu_co_mutex_init(&s->lock); if ((s->incompatible_features & QCOW2_INCOMPAT_DIRTY) &&
!VAR_0->read_only) { BdrvCheckResult result = {0}; VAR_4 = qcow2_check_refcounts(VAR_0, &result, BDRV_FIX_ERRORS); if (VAR_4 < 0) { goto fail; } VAR_4 = qcow2_mark_clean(VAR_0); if (VAR_4 < 0) { goto fail; } } #ifdef DEBUG_ALLOC
{ BdrvCheckResult result = {0}; qcow2_check_refcounts(VAR_0, &result, 0); } #endif
return VAR_4; fail:
g_free(s->unknown_header_fields); cleanup_unknown_header_ext(VAR_0); qcow2_free_snapshots(VAR_0); qcow2_refcount_close(VAR_0); g_free(s->l1_table); if (s->l2_table_cache) { qcow2_cache_destroy(VAR_0, s->l2_table_cache); } g_free(s->cluster_cache); qemu_vfree(s->cluster_data); return VAR_4; }