static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,

                                 uint64_t end_offset, void **p_feature_table,

                                 int flags, Error **errp)

{

    BDRVQcow2State *s = bs->opaque;

    QCowExtension ext;

    uint64_t offset;

    int ret;



#ifdef DEBUG_EXT

    printf("qcow2_read_extensions: start=%ld end=%ld\n", start_offset, end_offset);

#endif

    offset = start_offset;

    while (offset < end_offset) {



#ifdef DEBUG_EXT

        /* Sanity check */

        if (offset > s->cluster_size)

            printf("qcow2_read_extension: suspicious offset %lu\n", offset);



        printf("attempting to read extended header in offset %lu\n", offset);

#endif



        ret = bdrv_pread(bs->file, offset, &ext, sizeof(ext));

        if (ret < 0) {

            error_setg_errno(errp, -ret, "qcow2_read_extension: ERROR: "

                             "pread fail from offset %" PRIu64, offset);

            return 1;

        }

        be32_to_cpus(&ext.magic);

        be32_to_cpus(&ext.len);

        offset += sizeof(ext);

#ifdef DEBUG_EXT

        printf("ext.magic = 0x%x\n", ext.magic);

#endif

        if (offset > end_offset || ext.len > end_offset - offset) {

            error_setg(errp, "Header extension too large");

            return -EINVAL;

        }



        switch (ext.magic) {

        case QCOW2_EXT_MAGIC_END:

            return 0;



        case QCOW2_EXT_MAGIC_BACKING_FORMAT:

            if (ext.len >= sizeof(bs->backing_format)) {

                error_setg(errp, "ERROR: ext_backing_format: len=%" PRIu32

                           " too large (>=%zu)", ext.len,

                           sizeof(bs->backing_format));

                return 2;

            }

            ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);

            if (ret < 0) {

                error_setg_errno(errp, -ret, "ERROR: ext_backing_format: "

                                 "Could not read format name");

                return 3;

            }

            bs->backing_format[ext.len] = '\0';

            s->image_backing_format = g_strdup(bs->backing_format);

#ifdef DEBUG_EXT

            printf("Qcow2: Got format extension %s\n", bs->backing_format);

#endif

            break;



        case QCOW2_EXT_MAGIC_FEATURE_TABLE:

            if (p_feature_table != NULL) {

                void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));

                ret = bdrv_pread(bs->file, offset , feature_table, ext.len);

                if (ret < 0) {

                    error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "

                                     "Could not read table");

                    return ret;

                }



                *p_feature_table = feature_table;

            }

            break;



        case QCOW2_EXT_MAGIC_CRYPTO_HEADER: {

            unsigned int cflags = 0;

            if (s->crypt_method_header != QCOW_CRYPT_LUKS) {

                error_setg(errp, "CRYPTO header extension only "

                           "expected with LUKS encryption method");

                return -EINVAL;

            }

            if (ext.len != sizeof(Qcow2CryptoHeaderExtension)) {

                error_setg(errp, "CRYPTO header extension size %u, "

                           "but expected size %zu", ext.len,

                           sizeof(Qcow2CryptoHeaderExtension));

                return -EINVAL;

            }



            ret = bdrv_pread(bs->file, offset, &s->crypto_header, ext.len);

            if (ret < 0) {

                error_setg_errno(errp, -ret,

                                 "Unable to read CRYPTO header extension");

                return ret;

            }

            be64_to_cpus(&s->crypto_header.offset);

            be64_to_cpus(&s->crypto_header.length);



            if ((s->crypto_header.offset % s->cluster_size) != 0) {

                error_setg(errp, "Encryption header offset '%" PRIu64 "' is "

                           "not a multiple of cluster size '%u'",

                           s->crypto_header.offset, s->cluster_size);

                return -EINVAL;

            }



            if (flags & BDRV_O_NO_IO) {

                cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;

            }

            s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",

                                           qcow2_crypto_hdr_read_func,

                                           bs, cflags, errp);

            if (!s->crypto) {

                return -EINVAL;

            }

        }   break;



        default:

            /* unknown magic - save it in case we need to rewrite the header */

            {

                Qcow2UnknownHeaderExtension *uext;



                uext = g_malloc0(sizeof(*uext)  + ext.len);

                uext->magic = ext.magic;

                uext->len = ext.len;

                QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);



                ret = bdrv_pread(bs->file, offset , uext->data, uext->len);

                if (ret < 0) {

                    error_setg_errno(errp, -ret, "ERROR: unknown extension: "

                                     "Could not read data");

                    return ret;

                }

            }

            break;

        }



        offset += ((ext.len + 7) & ~7);

    }



    return 0;

}

static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,

                                 uint64_t end_offset, void **p_feature_table,

                                 int flags, Error **errp)

{

    BDRVQcow2State *s = bs->opaque;

    QCowExtension ext;

    uint64_t offset;

    int ret;



#ifdef DEBUG_EXT

    printf("qcow2_read_extensions: start=%ld end=%ld\n", start_offset, end_offset);

#endif

    offset = start_offset;

    while (offset < end_offset) {



#ifdef DEBUG_EXT

        

        if (offset > s->cluster_size)

            printf("qcow2_read_extension: suspicious offset %lu\n", offset);



        printf("attempting to read extended header in offset %lu\n", offset);

#endif



        ret = bdrv_pread(bs->file, offset, &ext, sizeof(ext));

        if (ret < 0) {

            error_setg_errno(errp, -ret, "qcow2_read_extension: ERROR: "

                             "pread fail from offset %" PRIu64, offset);

            return 1;

        }

        be32_to_cpus(&ext.magic);

        be32_to_cpus(&ext.len);

        offset += sizeof(ext);

#ifdef DEBUG_EXT

        printf("ext.magic = 0x%x\n", ext.magic);

#endif

        if (offset > end_offset || ext.len > end_offset - offset) {

            error_setg(errp, "Header extension too large");

            return -EINVAL;

        }



        switch (ext.magic) {

        case QCOW2_EXT_MAGIC_END:

            return 0;



        case QCOW2_EXT_MAGIC_BACKING_FORMAT:

            if (ext.len >= sizeof(bs->backing_format)) {

                error_setg(errp, "ERROR: ext_backing_format: len=%" PRIu32

                           " too large (>=%zu)", ext.len,

                           sizeof(bs->backing_format));

                return 2;

            }

            ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);

            if (ret < 0) {

                error_setg_errno(errp, -ret, "ERROR: ext_backing_format: "

                                 "Could not read format name");

                return 3;

            }

            bs->backing_format[ext.len] = '\0';

            s->image_backing_format = g_strdup(bs->backing_format);

#ifdef DEBUG_EXT

            printf("Qcow2: Got format extension %s\n", bs->backing_format);

#endif

            break;



        case QCOW2_EXT_MAGIC_FEATURE_TABLE:

            if (p_feature_table != NULL) {

                void* feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));

                ret = bdrv_pread(bs->file, offset , feature_table, ext.len);

                if (ret < 0) {

                    error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "

                                     "Could not read table");

                    return ret;

                }



                *p_feature_table = feature_table;

            }

            break;



        case QCOW2_EXT_MAGIC_CRYPTO_HEADER: {

            unsigned int cflags = 0;

            if (s->crypt_method_header != QCOW_CRYPT_LUKS) {

                error_setg(errp, "CRYPTO header extension only "

                           "expected with LUKS encryption method");

                return -EINVAL;

            }

            if (ext.len != sizeof(Qcow2CryptoHeaderExtension)) {

                error_setg(errp, "CRYPTO header extension size %u, "

                           "but expected size %zu", ext.len,

                           sizeof(Qcow2CryptoHeaderExtension));

                return -EINVAL;

            }



            ret = bdrv_pread(bs->file, offset, &s->crypto_header, ext.len);

            if (ret < 0) {

                error_setg_errno(errp, -ret,

                                 "Unable to read CRYPTO header extension");

                return ret;

            }

            be64_to_cpus(&s->crypto_header.offset);

            be64_to_cpus(&s->crypto_header.length);



            if ((s->crypto_header.offset % s->cluster_size) != 0) {

                error_setg(errp, "Encryption header offset '%" PRIu64 "' is "

                           "not a multiple of cluster size '%u'",

                           s->crypto_header.offset, s->cluster_size);

                return -EINVAL;

            }



            if (flags & BDRV_O_NO_IO) {

                cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;

            }

            s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",

                                           qcow2_crypto_hdr_read_func,

                                           bs, cflags, errp);

            if (!s->crypto) {

                return -EINVAL;

            }

        }   break;



        default:

            

            {

                Qcow2UnknownHeaderExtension *uext;



                uext = g_malloc0(sizeof(*uext)  + ext.len);

                uext->magic = ext.magic;

                uext->len = ext.len;

                QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);



                ret = bdrv_pread(bs->file, offset , uext->data, uext->len);

                if (ret < 0) {

                    error_setg_errno(errp, -ret, "ERROR: unknown extension: "

                                     "Could not read data");

                    return ret;

                }

            }

            break;

        }



        offset += ((ext.len + 7) & ~7);

    }



    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,

                                 uint64_t VAR_2, void **VAR_3,

                                 int VAR_4, Error **VAR_5)

{

    BDRVQcow2State *s = VAR_0->opaque;

    QCowExtension ext;

    uint64_t offset;

    int VAR_6;



#ifdef DEBUG_EXT

    printf("FUNC_0: start=%ld end=%ld\n", VAR_1, VAR_2);

#endif

    offset = VAR_1;

    while (offset < VAR_2) {



#ifdef DEBUG_EXT

        

        if (offset > s->cluster_size)

            printf("qcow2_read_extension: suspicious offset %lu\n", offset);



        printf("attempting to read extended header in offset %lu\n", offset);

#endif



        VAR_6 = bdrv_pread(VAR_0->file, offset, &ext, sizeof(ext));

        if (VAR_6 < 0) {

            error_setg_errno(VAR_5, -VAR_6, "qcow2_read_extension: ERROR: "

                             "pread fail from offset %" PRIu64, offset);

            return 1;

        }

        be32_to_cpus(&ext.magic);

        be32_to_cpus(&ext.len);

        offset += sizeof(ext);

#ifdef DEBUG_EXT

        printf("ext.magic = 0x%x\n", ext.magic);

#endif

        if (offset > VAR_2 || ext.len > VAR_2 - offset) {

            error_setg(VAR_5, "Header extension too large");

            return -EINVAL;

        }



        switch (ext.magic) {

        case QCOW2_EXT_MAGIC_END:

            return 0;



        case QCOW2_EXT_MAGIC_BACKING_FORMAT:

            if (ext.len >= sizeof(VAR_0->backing_format)) {

                error_setg(VAR_5, "ERROR: ext_backing_format: len=%" PRIu32

                           " too large (>=%zu)", ext.len,

                           sizeof(VAR_0->backing_format));

                return 2;

            }

            VAR_6 = bdrv_pread(VAR_0->file, offset, VAR_0->backing_format, ext.len);

            if (VAR_6 < 0) {

                error_setg_errno(VAR_5, -VAR_6, "ERROR: ext_backing_format: "

                                 "Could not read format name");

                return 3;

            }

            VAR_0->backing_format[ext.len] = '\0';

            s->image_backing_format = g_strdup(VAR_0->backing_format);

#ifdef DEBUG_EXT

            printf("Qcow2: Got format extension %s\n", VAR_0->backing_format);

#endif

            break;



        case QCOW2_EXT_MAGIC_FEATURE_TABLE:

            if (VAR_3 != NULL) {

                void* VAR_7 = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));

                VAR_6 = bdrv_pread(VAR_0->file, offset , VAR_7, ext.len);

                if (VAR_6 < 0) {

                    error_setg_errno(VAR_5, -VAR_6, "ERROR: ext_feature_table: "

                                     "Could not read table");

                    return VAR_6;

                }



                *VAR_3 = VAR_7;

            }

            break;



        case QCOW2_EXT_MAGIC_CRYPTO_HEADER: {

            unsigned int VAR_8 = 0;

            if (s->crypt_method_header != QCOW_CRYPT_LUKS) {

                error_setg(VAR_5, "CRYPTO header extension only "

                           "expected with LUKS encryption method");

                return -EINVAL;

            }

            if (ext.len != sizeof(Qcow2CryptoHeaderExtension)) {

                error_setg(VAR_5, "CRYPTO header extension size %u, "

                           "but expected size %zu", ext.len,

                           sizeof(Qcow2CryptoHeaderExtension));

                return -EINVAL;

            }



            VAR_6 = bdrv_pread(VAR_0->file, offset, &s->crypto_header, ext.len);

            if (VAR_6 < 0) {

                error_setg_errno(VAR_5, -VAR_6,

                                 "Unable to read CRYPTO header extension");

                return VAR_6;

            }

            be64_to_cpus(&s->crypto_header.offset);

            be64_to_cpus(&s->crypto_header.length);



            if ((s->crypto_header.offset % s->cluster_size) != 0) {

                error_setg(VAR_5, "Encryption header offset '%" PRIu64 "' is "

                           "not a multiple of cluster size '%u'",

                           s->crypto_header.offset, s->cluster_size);

                return -EINVAL;

            }



            if (VAR_4 & BDRV_O_NO_IO) {

                VAR_8 |= QCRYPTO_BLOCK_OPEN_NO_IO;

            }

            s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",

                                           qcow2_crypto_hdr_read_func,

                                           VAR_0, VAR_8, VAR_5);

            if (!s->crypto) {

                return -EINVAL;

            }

        }   break;



        default:

            

            {

                Qcow2UnknownHeaderExtension *uext;



                uext = g_malloc0(sizeof(*uext)  + ext.len);

                uext->magic = ext.magic;

                uext->len = ext.len;

                QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);



                VAR_6 = bdrv_pread(VAR_0->file, offset , uext->data, uext->len);

                if (VAR_6 < 0) {

                    error_setg_errno(VAR_5, -VAR_6, "ERROR: unknown extension: "

                                     "Could not read data");

                    return VAR_6;

                }

            }

            break;

        }



        offset += ((ext.len + 7) & ~7);

    }



    return 0;

}

static int FUNC_0(BlockDriverState *VAR_0, uint64_t VAR_1,
uint64_t VAR_2, void **VAR_3,
int VAR_4, Error **VAR_5)
{ BDRVQcow2State *s = VAR_0->opaque; QCowExtension ext; uint64_t offset; int VAR_6; #ifdef DEBUG_EXT
printf("FUNC_0: start=%ld end=%ld\n", VAR_1, VAR_2); #endif
offset = VAR_1; while (offset < VAR_2) { #ifdef DEBUG_EXT
if (offset > s->cluster_size)
printf("qcow2_read_extension: suspicious offset %lu\n", offset); printf("attempting to read extended header in offset %lu\n", offset); #endif
VAR_6 = bdrv_pread(VAR_0->file, offset, &ext, sizeof(ext)); if (VAR_6 < 0) { error_setg_errno(VAR_5, -VAR_6, "qcow2_read_extension: ERROR: "
"pread fail from offset %" PRIu64, offset); return 1; } be32_to_cpus(&ext.magic); be32_to_cpus(&ext.len); offset += sizeof(ext); #ifdef DEBUG_EXT
printf("ext.magic = 0x%x\n", ext.magic); #endif
if (offset > VAR_2 || ext.len > VAR_2 - offset) { error_setg(VAR_5, "Header extension too large"); return -EINVAL; } switch (ext.magic) { case QCOW2_EXT_MAGIC_END:
return 0; case QCOW2_EXT_MAGIC_BACKING_FORMAT:
if (ext.len >= sizeof(VAR_0->backing_format)) { error_setg(VAR_5, "ERROR: ext_backing_format: len=%" PRIu32
" too large (>=%zu)", ext.len,
sizeof(VAR_0->backing_format)); return 2; } VAR_6 = bdrv_pread(VAR_0->file, offset, VAR_0->backing_format, ext.len); if (VAR_6 < 0) { error_setg_errno(VAR_5, -VAR_6, "ERROR: ext_backing_format: "
"Could not read format name"); return 3; } VAR_0->backing_format[ext.len] = '\0'; s->image_backing_format = g_strdup(VAR_0->backing_format); #ifdef DEBUG_EXT
printf("Qcow2: Got format extension %s\n", VAR_0->backing_format); #endif
break; case QCOW2_EXT_MAGIC_FEATURE_TABLE:
if (VAR_3 != NULL) { void* VAR_7 = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature)); VAR_6 = bdrv_pread(VAR_0->file, offset , VAR_7, ext.len); if (VAR_6 < 0) { error_setg_errno(VAR_5, -VAR_6, "ERROR: ext_feature_table: "
"Could not read table"); return VAR_6; } *VAR_3 = VAR_7; } break; case QCOW2_EXT_MAGIC_CRYPTO_HEADER: { unsigned int VAR_8 = 0; if (s->crypt_method_header != QCOW_CRYPT_LUKS) { error_setg(VAR_5, "CRYPTO header extension only "
"expected with LUKS encryption method"); return -EINVAL; } if (ext.len != sizeof(Qcow2CryptoHeaderExtension)) { error_setg(VAR_5, "CRYPTO header extension size %u, "
"but expected size %zu", ext.len,
sizeof(Qcow2CryptoHeaderExtension)); return -EINVAL; } VAR_6 = bdrv_pread(VAR_0->file, offset, &s->crypto_header, ext.len); if (VAR_6 < 0) { error_setg_errno(VAR_5, -VAR_6,
"Unable to read CRYPTO header extension"); return VAR_6; } be64_to_cpus(&s->crypto_header.offset); be64_to_cpus(&s->crypto_header.length); if ((s->crypto_header.offset % s->cluster_size) != 0) { error_setg(VAR_5, "Encryption header offset '%" PRIu64 "' is "
"not a multiple of cluster size '%u'",
s->crypto_header.offset, s->cluster_size); return -EINVAL; } if (VAR_4 & BDRV_O_NO_IO) { VAR_8 |= QCRYPTO_BLOCK_OPEN_NO_IO; } s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
qcow2_crypto_hdr_read_func,
VAR_0, VAR_8, VAR_5); if (!s->crypto) { return -EINVAL; } }   break; default:
{ Qcow2UnknownHeaderExtension *uext; uext = g_malloc0(sizeof(*uext)  + ext.len); uext->magic = ext.magic; uext->len = ext.len; QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next); VAR_6 = bdrv_pread(VAR_0->file, offset , uext->data, uext->len); if (VAR_6 < 0) { error_setg_errno(VAR_5, -VAR_6, "ERROR: unknown extension: "
"Could not read data"); return VAR_6; } } break; } offset += ((ext.len + 7) & ~7); } return 0; }