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

                          Error **errp)

{

    BDRVParallelsState *s = bs->opaque;

    int i;

    ParallelsHeader ph;

    int ret;



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

    if (ret < 0) {

        goto fail;

    }



    bs->total_sectors = le64_to_cpu(ph.nb_sectors);



    if (le32_to_cpu(ph.version) != HEADER_VERSION) {

        goto fail_format;

    }

    if (!memcmp(ph.magic, HEADER_MAGIC, 16)) {

        s->off_multiplier = 1;

        bs->total_sectors = 0xffffffff & bs->total_sectors;

    } else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) {

        s->off_multiplier = le32_to_cpu(ph.tracks);

    } else {

        goto fail_format;

    }



    s->tracks = le32_to_cpu(ph.tracks);

    if (s->tracks == 0) {

        error_setg(errp, "Invalid image: Zero sectors per track");

        ret = -EINVAL;

        goto fail;

    }

    if (s->tracks > INT32_MAX/513) {

        error_setg(errp, "Invalid image: Too big cluster");

        ret = -EFBIG;

        goto fail;

    }



    s->catalog_size = le32_to_cpu(ph.catalog_entries);

    if (s->catalog_size > INT_MAX / sizeof(uint32_t)) {

        error_setg(errp, "Catalog too large");

        ret = -EFBIG;

        goto fail;

    }

    s->catalog_bitmap = g_try_new(uint32_t, s->catalog_size);

    if (s->catalog_size && s->catalog_bitmap == NULL) {

        ret = -ENOMEM;

        goto fail;

    }



    ret = bdrv_pread(bs->file, sizeof(ParallelsHeader),

                     s->catalog_bitmap, s->catalog_size * sizeof(uint32_t));

    if (ret < 0) {

        goto fail;

    }



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

        le32_to_cpus(&s->catalog_bitmap[i]);



    s->has_truncate = bdrv_has_zero_init(bs->file) &&

                      bdrv_truncate(bs->file, bdrv_getlength(bs->file)) == 0;



    qemu_co_mutex_init(&s->lock);

    return 0;



fail_format:

    error_setg(errp, "Image not in Parallels format");

    ret = -EINVAL;

fail:

    g_free(s->catalog_bitmap);

    return ret;

}

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

                          Error **errp)

{

    BDRVParallelsState *s = bs->opaque;

    int i;

    ParallelsHeader ph;

    int ret;



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

    if (ret < 0) {

        goto fail;

    }



    bs->total_sectors = le64_to_cpu(ph.nb_sectors);



    if (le32_to_cpu(ph.version) != HEADER_VERSION) {

        goto fail_format;

    }

    if (!memcmp(ph.magic, HEADER_MAGIC, 16)) {

        s->off_multiplier = 1;

        bs->total_sectors = 0xffffffff & bs->total_sectors;

    } else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) {

        s->off_multiplier = le32_to_cpu(ph.tracks);

    } else {

        goto fail_format;

    }



    s->tracks = le32_to_cpu(ph.tracks);

    if (s->tracks == 0) {

        error_setg(errp, "Invalid image: Zero sectors per track");

        ret = -EINVAL;

        goto fail;

    }

    if (s->tracks > INT32_MAX/513) {

        error_setg(errp, "Invalid image: Too big cluster");

        ret = -EFBIG;

        goto fail;

    }



    s->catalog_size = le32_to_cpu(ph.catalog_entries);

    if (s->catalog_size > INT_MAX / sizeof(uint32_t)) {

        error_setg(errp, "Catalog too large");

        ret = -EFBIG;

        goto fail;

    }

    s->catalog_bitmap = g_try_new(uint32_t, s->catalog_size);

    if (s->catalog_size && s->catalog_bitmap == NULL) {

        ret = -ENOMEM;

        goto fail;

    }



    ret = bdrv_pread(bs->file, sizeof(ParallelsHeader),

                     s->catalog_bitmap, s->catalog_size * sizeof(uint32_t));

    if (ret < 0) {

        goto fail;

    }



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

        le32_to_cpus(&s->catalog_bitmap[i]);



    s->has_truncate = bdrv_has_zero_init(bs->file) &&

                      bdrv_truncate(bs->file, bdrv_getlength(bs->file)) == 0;



    qemu_co_mutex_init(&s->lock);

    return 0;



fail_format:

    error_setg(errp, "Image not in Parallels format");

    ret = -EINVAL;

fail:

    g_free(s->catalog_bitmap);

    return ret;

}

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

                          Error **VAR_3)

{

    BDRVParallelsState *s = VAR_0->opaque;

    int VAR_4;

    ParallelsHeader ph;

    int VAR_5;



    VAR_5 = bdrv_pread(VAR_0->file, 0, &ph, sizeof(ph));

    if (VAR_5 < 0) {

        goto fail;

    }



    VAR_0->total_sectors = le64_to_cpu(ph.nb_sectors);



    if (le32_to_cpu(ph.version) != HEADER_VERSION) {

        goto fail_format;

    }

    if (!memcmp(ph.magic, HEADER_MAGIC, 16)) {

        s->off_multiplier = 1;

        VAR_0->total_sectors = 0xffffffff & VAR_0->total_sectors;

    } else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) {

        s->off_multiplier = le32_to_cpu(ph.tracks);

    } else {

        goto fail_format;

    }



    s->tracks = le32_to_cpu(ph.tracks);

    if (s->tracks == 0) {

        error_setg(VAR_3, "Invalid image: Zero sectors per track");

        VAR_5 = -EINVAL;

        goto fail;

    }

    if (s->tracks > INT32_MAX/513) {

        error_setg(VAR_3, "Invalid image: Too big cluster");

        VAR_5 = -EFBIG;

        goto fail;

    }



    s->catalog_size = le32_to_cpu(ph.catalog_entries);

    if (s->catalog_size > INT_MAX / sizeof(uint32_t)) {

        error_setg(VAR_3, "Catalog too large");

        VAR_5 = -EFBIG;

        goto fail;

    }

    s->catalog_bitmap = g_try_new(uint32_t, s->catalog_size);

    if (s->catalog_size && s->catalog_bitmap == NULL) {

        VAR_5 = -ENOMEM;

        goto fail;

    }



    VAR_5 = bdrv_pread(VAR_0->file, sizeof(ParallelsHeader),

                     s->catalog_bitmap, s->catalog_size * sizeof(uint32_t));

    if (VAR_5 < 0) {

        goto fail;

    }



    for (VAR_4 = 0; VAR_4 < s->catalog_size; VAR_4++)

        le32_to_cpus(&s->catalog_bitmap[VAR_4]);



    s->has_truncate = bdrv_has_zero_init(VAR_0->file) &&

                      bdrv_truncate(VAR_0->file, bdrv_getlength(VAR_0->file)) == 0;



    qemu_co_mutex_init(&s->lock);

    return 0;



fail_format:

    error_setg(VAR_3, "Image not in Parallels format");

    VAR_5 = -EINVAL;

fail:

    g_free(s->catalog_bitmap);

    return VAR_5;

}

static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2,
Error **VAR_3)
{ BDRVParallelsState *s = VAR_0->opaque; int VAR_4; ParallelsHeader ph; int VAR_5; VAR_5 = bdrv_pread(VAR_0->file, 0, &ph, sizeof(ph)); if (VAR_5 < 0) { goto fail; } VAR_0->total_sectors = le64_to_cpu(ph.nb_sectors); if (le32_to_cpu(ph.version) != HEADER_VERSION) { goto fail_format; } if (!memcmp(ph.magic, HEADER_MAGIC, 16)) { s->off_multiplier = 1; VAR_0->total_sectors = 0xffffffff & VAR_0->total_sectors; } else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) { s->off_multiplier = le32_to_cpu(ph.tracks); } else { goto fail_format; } s->tracks = le32_to_cpu(ph.tracks); if (s->tracks == 0) { error_setg(VAR_3, "Invalid image: Zero sectors per track"); VAR_5 = -EINVAL; goto fail; } if (s->tracks > INT32_MAX/513) { error_setg(VAR_3, "Invalid image: Too big cluster"); VAR_5 = -EFBIG; goto fail; } s->catalog_size = le32_to_cpu(ph.catalog_entries); if (s->catalog_size > INT_MAX / sizeof(uint32_t)) { error_setg(VAR_3, "Catalog too large"); VAR_5 = -EFBIG; goto fail; } s->catalog_bitmap = g_try_new(uint32_t, s->catalog_size); if (s->catalog_size && s->catalog_bitmap == NULL) { VAR_5 = -ENOMEM; goto fail; } VAR_5 = bdrv_pread(VAR_0->file, sizeof(ParallelsHeader),
s->catalog_bitmap, s->catalog_size * sizeof(uint32_t)); if (VAR_5 < 0) { goto fail; } for (VAR_4 = 0; VAR_4 < s->catalog_size; VAR_4++) le32_to_cpus(&s->catalog_bitmap[VAR_4]); s->has_truncate = bdrv_has_zero_init(VAR_0->file) &&
bdrv_truncate(VAR_0->file, bdrv_getlength(VAR_0->file)) == 0; qemu_co_mutex_init(&s->lock); return 0; fail_format:
error_setg(VAR_3, "Image not in Parallels format"); VAR_5 = -EINVAL; fail:
g_free(s->catalog_bitmap); return VAR_5; }