static int dmg_open(BlockDriverState *bs, QDict *options, int flags,

                    Error **errp)

{

    BDRVDMGState *s = bs->opaque;

    DmgHeaderState ds;

    uint64_t rsrc_fork_offset, rsrc_fork_length;

    uint64_t plist_xml_offset, plist_xml_length;

    int64_t offset;

    int ret;



    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,

                               false, errp);

    if (!bs->file) {

        return -EINVAL;

    }



    block_module_load_one("dmg-bz2");

    bs->read_only = true;



    s->n_chunks = 0;

    s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;

    /* used by dmg_read_mish_block to keep track of the current I/O position */

    ds.data_fork_offset = 0;

    ds.max_compressed_size = 1;

    ds.max_sectors_per_chunk = 1;



    /* locate the UDIF trailer */

    offset = dmg_find_koly_offset(bs->file, errp);

    if (offset < 0) {

        ret = offset;

        goto fail;

    }



    /* offset of data fork (DataForkOffset) */

    ret = read_uint64(bs, offset + 0x18, &ds.data_fork_offset);

    if (ret < 0) {

        goto fail;

    } else if (ds.data_fork_offset > offset) {

        ret = -EINVAL;

        goto fail;

    }



    /* offset of resource fork (RsrcForkOffset) */

    ret = read_uint64(bs, offset + 0x28, &rsrc_fork_offset);

    if (ret < 0) {

        goto fail;

    }

    ret = read_uint64(bs, offset + 0x30, &rsrc_fork_length);

    if (ret < 0) {

        goto fail;

    }

    if (rsrc_fork_offset >= offset ||

        rsrc_fork_length > offset - rsrc_fork_offset) {

        ret = -EINVAL;

        goto fail;

    }

    /* offset of property list (XMLOffset) */

    ret = read_uint64(bs, offset + 0xd8, &plist_xml_offset);

    if (ret < 0) {

        goto fail;

    }

    ret = read_uint64(bs, offset + 0xe0, &plist_xml_length);

    if (ret < 0) {

        goto fail;

    }

    if (plist_xml_offset >= offset ||

        plist_xml_length > offset - plist_xml_offset) {

        ret = -EINVAL;

        goto fail;

    }

    ret = read_uint64(bs, offset + 0x1ec, (uint64_t *)&bs->total_sectors);

    if (ret < 0) {

        goto fail;

    }

    if (bs->total_sectors < 0) {

        ret = -EINVAL;

        goto fail;

    }

    if (rsrc_fork_length != 0) {

        ret = dmg_read_resource_fork(bs, &ds,

                                     rsrc_fork_offset, rsrc_fork_length);

        if (ret < 0) {

            goto fail;

        }

    } else if (plist_xml_length != 0) {

        ret = dmg_read_plist_xml(bs, &ds, plist_xml_offset, plist_xml_length);

        if (ret < 0) {

            goto fail;

        }

    } else {

        ret = -EINVAL;

        goto fail;

    }



    /* initialize zlib engine */

    s->compressed_chunk = qemu_try_blockalign(bs->file->bs,

                                              ds.max_compressed_size + 1);

    s->uncompressed_chunk = qemu_try_blockalign(bs->file->bs,

                                                512 * ds.max_sectors_per_chunk);

    if (s->compressed_chunk == NULL || s->uncompressed_chunk == NULL) {

        ret = -ENOMEM;

        goto fail;

    }



    if (inflateInit(&s->zstream) != Z_OK) {

        ret = -EINVAL;

        goto fail;

    }



    s->current_chunk = s->n_chunks;



    qemu_co_mutex_init(&s->lock);

    return 0;



fail:

    g_free(s->types);

    g_free(s->offsets);

    g_free(s->lengths);

    g_free(s->sectors);

    g_free(s->sectorcounts);

    qemu_vfree(s->compressed_chunk);

    qemu_vfree(s->uncompressed_chunk);

    return ret;

}

static int dmg_open(BlockDriverState *bs, QDict *options, int flags,

                    Error **errp)

{

    BDRVDMGState *s = bs->opaque;

    DmgHeaderState ds;

    uint64_t rsrc_fork_offset, rsrc_fork_length;

    uint64_t plist_xml_offset, plist_xml_length;

    int64_t offset;

    int ret;



    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,

                               false, errp);

    if (!bs->file) {

        return -EINVAL;

    }



    block_module_load_one("dmg-bz2");

    bs->read_only = true;



    s->n_chunks = 0;

    s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;

    

    ds.data_fork_offset = 0;

    ds.max_compressed_size = 1;

    ds.max_sectors_per_chunk = 1;



    

    offset = dmg_find_koly_offset(bs->file, errp);

    if (offset < 0) {

        ret = offset;

        goto fail;

    }



    

    ret = read_uint64(bs, offset + 0x18, &ds.data_fork_offset);

    if (ret < 0) {

        goto fail;

    } else if (ds.data_fork_offset > offset) {

        ret = -EINVAL;

        goto fail;

    }



    

    ret = read_uint64(bs, offset + 0x28, &rsrc_fork_offset);

    if (ret < 0) {

        goto fail;

    }

    ret = read_uint64(bs, offset + 0x30, &rsrc_fork_length);

    if (ret < 0) {

        goto fail;

    }

    if (rsrc_fork_offset >= offset ||

        rsrc_fork_length > offset - rsrc_fork_offset) {

        ret = -EINVAL;

        goto fail;

    }

    

    ret = read_uint64(bs, offset + 0xd8, &plist_xml_offset);

    if (ret < 0) {

        goto fail;

    }

    ret = read_uint64(bs, offset + 0xe0, &plist_xml_length);

    if (ret < 0) {

        goto fail;

    }

    if (plist_xml_offset >= offset ||

        plist_xml_length > offset - plist_xml_offset) {

        ret = -EINVAL;

        goto fail;

    }

    ret = read_uint64(bs, offset + 0x1ec, (uint64_t *)&bs->total_sectors);

    if (ret < 0) {

        goto fail;

    }

    if (bs->total_sectors < 0) {

        ret = -EINVAL;

        goto fail;

    }

    if (rsrc_fork_length != 0) {

        ret = dmg_read_resource_fork(bs, &ds,

                                     rsrc_fork_offset, rsrc_fork_length);

        if (ret < 0) {

            goto fail;

        }

    } else if (plist_xml_length != 0) {

        ret = dmg_read_plist_xml(bs, &ds, plist_xml_offset, plist_xml_length);

        if (ret < 0) {

            goto fail;

        }

    } else {

        ret = -EINVAL;

        goto fail;

    }



    

    s->compressed_chunk = qemu_try_blockalign(bs->file->bs,

                                              ds.max_compressed_size + 1);

    s->uncompressed_chunk = qemu_try_blockalign(bs->file->bs,

                                                512 * ds.max_sectors_per_chunk);

    if (s->compressed_chunk == NULL || s->uncompressed_chunk == NULL) {

        ret = -ENOMEM;

        goto fail;

    }



    if (inflateInit(&s->zstream) != Z_OK) {

        ret = -EINVAL;

        goto fail;

    }



    s->current_chunk = s->n_chunks;



    qemu_co_mutex_init(&s->lock);

    return 0;



fail:

    g_free(s->types);

    g_free(s->offsets);

    g_free(s->lengths);

    g_free(s->sectors);

    g_free(s->sectorcounts);

    qemu_vfree(s->compressed_chunk);

    qemu_vfree(s->uncompressed_chunk);

    return ret;

}

static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2,

                    Error **VAR_3)

{

    BDRVDMGState *s = VAR_0->opaque;

    DmgHeaderState ds;

    uint64_t rsrc_fork_offset, rsrc_fork_length;

    uint64_t plist_xml_offset, plist_xml_length;

    int64_t offset;

    int VAR_4;



    VAR_0->file = bdrv_open_child(NULL, VAR_1, "file", VAR_0, &child_file,

                               false, VAR_3);

    if (!VAR_0->file) {

        return -EINVAL;

    }



    block_module_load_one("dmg-bz2");

    VAR_0->read_only = true;



    s->n_chunks = 0;

    s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;

    

    ds.data_fork_offset = 0;

    ds.max_compressed_size = 1;

    ds.max_sectors_per_chunk = 1;



    

    offset = dmg_find_koly_offset(VAR_0->file, VAR_3);

    if (offset < 0) {

        VAR_4 = offset;

        goto fail;

    }



    

    VAR_4 = read_uint64(VAR_0, offset + 0x18, &ds.data_fork_offset);

    if (VAR_4 < 0) {

        goto fail;

    } else if (ds.data_fork_offset > offset) {

        VAR_4 = -EINVAL;

        goto fail;

    }



    

    VAR_4 = read_uint64(VAR_0, offset + 0x28, &rsrc_fork_offset);

    if (VAR_4 < 0) {

        goto fail;

    }

    VAR_4 = read_uint64(VAR_0, offset + 0x30, &rsrc_fork_length);

    if (VAR_4 < 0) {

        goto fail;

    }

    if (rsrc_fork_offset >= offset ||

        rsrc_fork_length > offset - rsrc_fork_offset) {

        VAR_4 = -EINVAL;

        goto fail;

    }

    

    VAR_4 = read_uint64(VAR_0, offset + 0xd8, &plist_xml_offset);

    if (VAR_4 < 0) {

        goto fail;

    }

    VAR_4 = read_uint64(VAR_0, offset + 0xe0, &plist_xml_length);

    if (VAR_4 < 0) {

        goto fail;

    }

    if (plist_xml_offset >= offset ||

        plist_xml_length > offset - plist_xml_offset) {

        VAR_4 = -EINVAL;

        goto fail;

    }

    VAR_4 = read_uint64(VAR_0, offset + 0x1ec, (uint64_t *)&VAR_0->total_sectors);

    if (VAR_4 < 0) {

        goto fail;

    }

    if (VAR_0->total_sectors < 0) {

        VAR_4 = -EINVAL;

        goto fail;

    }

    if (rsrc_fork_length != 0) {

        VAR_4 = dmg_read_resource_fork(VAR_0, &ds,

                                     rsrc_fork_offset, rsrc_fork_length);

        if (VAR_4 < 0) {

            goto fail;

        }

    } else if (plist_xml_length != 0) {

        VAR_4 = dmg_read_plist_xml(VAR_0, &ds, plist_xml_offset, plist_xml_length);

        if (VAR_4 < 0) {

            goto fail;

        }

    } else {

        VAR_4 = -EINVAL;

        goto fail;

    }



    

    s->compressed_chunk = qemu_try_blockalign(VAR_0->file->VAR_0,

                                              ds.max_compressed_size + 1);

    s->uncompressed_chunk = qemu_try_blockalign(VAR_0->file->VAR_0,

                                                512 * ds.max_sectors_per_chunk);

    if (s->compressed_chunk == NULL || s->uncompressed_chunk == NULL) {

        VAR_4 = -ENOMEM;

        goto fail;

    }



    if (inflateInit(&s->zstream) != Z_OK) {

        VAR_4 = -EINVAL;

        goto fail;

    }



    s->current_chunk = s->n_chunks;



    qemu_co_mutex_init(&s->lock);

    return 0;



fail:

    g_free(s->types);

    g_free(s->offsets);

    g_free(s->lengths);

    g_free(s->sectors);

    g_free(s->sectorcounts);

    qemu_vfree(s->compressed_chunk);

    qemu_vfree(s->uncompressed_chunk);

    return VAR_4;

}

static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2,
Error **VAR_3)
{ BDRVDMGState *s = VAR_0->opaque; DmgHeaderState ds; uint64_t rsrc_fork_offset, rsrc_fork_length; uint64_t plist_xml_offset, plist_xml_length; int64_t offset; int VAR_4; VAR_0->file = bdrv_open_child(NULL, VAR_1, "file", VAR_0, &child_file,
false, VAR_3); if (!VAR_0->file) { return -EINVAL; } block_module_load_one("dmg-bz2"); VAR_0->read_only = true; s->n_chunks = 0; s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; ds.data_fork_offset = 0; ds.max_compressed_size = 1; ds.max_sectors_per_chunk = 1; offset = dmg_find_koly_offset(VAR_0->file, VAR_3); if (offset < 0) { VAR_4 = offset; goto fail; } VAR_4 = read_uint64(VAR_0, offset + 0x18, &ds.data_fork_offset); if (VAR_4 < 0) { goto fail; } else if (ds.data_fork_offset > offset) { VAR_4 = -EINVAL; goto fail; } VAR_4 = read_uint64(VAR_0, offset + 0x28, &rsrc_fork_offset); if (VAR_4 < 0) { goto fail; } VAR_4 = read_uint64(VAR_0, offset + 0x30, &rsrc_fork_length); if (VAR_4 < 0) { goto fail; } if (rsrc_fork_offset >= offset ||
rsrc_fork_length > offset - rsrc_fork_offset) { VAR_4 = -EINVAL; goto fail; } VAR_4 = read_uint64(VAR_0, offset + 0xd8, &plist_xml_offset); if (VAR_4 < 0) { goto fail; } VAR_4 = read_uint64(VAR_0, offset + 0xe0, &plist_xml_length); if (VAR_4 < 0) { goto fail; } if (plist_xml_offset >= offset ||
plist_xml_length > offset - plist_xml_offset) { VAR_4 = -EINVAL; goto fail; } VAR_4 = read_uint64(VAR_0, offset + 0x1ec, (uint64_t *)&VAR_0->total_sectors); if (VAR_4 < 0) { goto fail; } if (VAR_0->total_sectors < 0) { VAR_4 = -EINVAL; goto fail; } if (rsrc_fork_length != 0) { VAR_4 = dmg_read_resource_fork(VAR_0, &ds,
rsrc_fork_offset, rsrc_fork_length); if (VAR_4 < 0) { goto fail; } } else if (plist_xml_length != 0) { VAR_4 = dmg_read_plist_xml(VAR_0, &ds, plist_xml_offset, plist_xml_length); if (VAR_4 < 0) { goto fail; } } else { VAR_4 = -EINVAL; goto fail; } s->compressed_chunk = qemu_try_blockalign(VAR_0->file->VAR_0,
ds.max_compressed_size + 1); s->uncompressed_chunk = qemu_try_blockalign(VAR_0->file->VAR_0,
512 * ds.max_sectors_per_chunk); if (s->compressed_chunk == NULL || s->uncompressed_chunk == NULL) { VAR_4 = -ENOMEM; goto fail; } if (inflateInit(&s->zstream) != Z_OK) { VAR_4 = -EINVAL; goto fail; } s->current_chunk = s->n_chunks; qemu_co_mutex_init(&s->lock); return 0; fail:
g_free(s->types); g_free(s->offsets); g_free(s->lengths); g_free(s->sectors); g_free(s->sectorcounts); qemu_vfree(s->compressed_chunk); qemu_vfree(s->uncompressed_chunk); return VAR_4; }