static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
                      Error **errp)
{
    BDRVBochsState *s = bs->opaque;
    uint32_t i;
    struct bochs_header bochs;
    int ret;
    bs->read_only = 1; // no write support yet
    ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
    if (ret < 0) {
        return ret;
    if (strcmp(bochs.magic, HEADER_MAGIC) ||
        strcmp(bochs.type, REDOLOG_TYPE) ||
        strcmp(bochs.subtype, GROWING_TYPE) ||
	((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
	(le32_to_cpu(bochs.version) != HEADER_V1))) {
        error_setg(errp, "Image not in Bochs format");
        return -EINVAL;
    if (le32_to_cpu(bochs.version) == HEADER_V1) {
        bs->total_sectors = le64_to_cpu(bochs.extra.redolog_v1.disk) / 512;
    } else {
        bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
    s->catalog_size = le32_to_cpu(bochs.catalog);
    s->catalog_bitmap = g_malloc(s->catalog_size * 4);
    ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
                     s->catalog_size * 4);
    if (ret < 0) {
        goto fail;
    for (i = 0; i < s->catalog_size; i++)
	le32_to_cpus(&s->catalog_bitmap[i]);
    s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.bitmap) - 1) / 512;
    s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
    s->extent_size = le32_to_cpu(bochs.extent);
    if (s->catalog_size < bs->total_sectors / s->extent_size) {
        error_setg(errp, "Catalog size is too small for this disk size");
        ret = -EINVAL;
        goto fail;
    qemu_co_mutex_init(&s->lock);
    return 0;
fail:
    g_free(s->catalog_bitmap);
    return ret;
static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
                      Error **errp)
{
    BDRVBochsState *s = bs->opaque;
    uint32_t i;
    struct bochs_header bochs;
    int ret;
    bs->read_only = 1; 
    ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
    if (ret < 0) {
        return ret;
    if (strcmp(bochs.magic, HEADER_MAGIC) ||
        strcmp(bochs.type, REDOLOG_TYPE) ||
        strcmp(bochs.subtype, GROWING_TYPE) ||
	((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
	(le32_to_cpu(bochs.version) != HEADER_V1))) {
        error_setg(errp, "Image not in Bochs format");
        return -EINVAL;
    if (le32_to_cpu(bochs.version) == HEADER_V1) {
        bs->total_sectors = le64_to_cpu(bochs.extra.redolog_v1.disk) / 512;
    } else {
        bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
    s->catalog_size = le32_to_cpu(bochs.catalog);
    s->catalog_bitmap = g_malloc(s->catalog_size * 4);
    ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
                     s->catalog_size * 4);
    if (ret < 0) {
        goto fail;
    for (i = 0; i < s->catalog_size; i++)
	le32_to_cpus(&s->catalog_bitmap[i]);
    s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
    s->bitmap_blocks = 1 + (le32_to_cpu(bochs.bitmap) - 1) / 512;
    s->extent_blocks = 1 + (le32_to_cpu(bochs.extent) - 1) / 512;
    s->extent_size = le32_to_cpu(bochs.extent);
    if (s->catalog_size < bs->total_sectors / s->extent_size) {
        error_setg(errp, "Catalog size is too small for this disk size");
        ret = -EINVAL;
        goto fail;
    qemu_co_mutex_init(&s->lock);
    return 0;
fail:
    g_free(s->catalog_bitmap);
    return ret;
static int FUNC_0(BlockDriverState *VAR_0, QDict *VAR_1, int VAR_2,
                      Error **VAR_3)
{
    BDRVBochsState *s = VAR_0->opaque;
    uint32_t i;
    struct bochs_header VAR_4;
    int VAR_5;
    VAR_0->read_only = 1; 
    VAR_5 = bdrv_pread(VAR_0->file, 0, &VAR_4, sizeof(VAR_4));
    if (VAR_5 < 0) {
        return VAR_5;
    if (strcmp(VAR_4.magic, HEADER_MAGIC) ||
        strcmp(VAR_4.type, REDOLOG_TYPE) ||
        strcmp(VAR_4.subtype, GROWING_TYPE) ||
	((le32_to_cpu(VAR_4.version) != HEADER_VERSION) &&
	(le32_to_cpu(VAR_4.version) != HEADER_V1))) {
        error_setg(VAR_3, "Image not in Bochs format");
        return -EINVAL;
    if (le32_to_cpu(VAR_4.version) == HEADER_V1) {
        VAR_0->total_sectors = le64_to_cpu(VAR_4.extra.redolog_v1.disk) / 512;
    } else {
        VAR_0->total_sectors = le64_to_cpu(VAR_4.extra.redolog.disk) / 512;
    s->catalog_size = le32_to_cpu(VAR_4.catalog);
    s->catalog_bitmap = g_malloc(s->catalog_size * 4);
    VAR_5 = bdrv_pread(VAR_0->file, le32_to_cpu(VAR_4.header), s->catalog_bitmap,
                     s->catalog_size * 4);
    if (VAR_5 < 0) {
        goto fail;
    for (i = 0; i < s->catalog_size; i++)
	le32_to_cpus(&s->catalog_bitmap[i]);
    s->data_offset = le32_to_cpu(VAR_4.header) + (s->catalog_size * 4);
    s->bitmap_blocks = 1 + (le32_to_cpu(VAR_4.bitmap) - 1) / 512;
    s->extent_blocks = 1 + (le32_to_cpu(VAR_4.extent) - 1) / 512;
    s->extent_size = le32_to_cpu(VAR_4.extent);
    if (s->catalog_size < VAR_0->total_sectors / s->extent_size) {
        error_setg(VAR_3, "Catalog size is too small for this disk size");
        VAR_5 = -EINVAL;
        goto fail;
    qemu_co_mutex_init(&s->lock);
    return 0;
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)
{ BDRVBochsState *s = VAR_0->opaque; uint32_t i; struct bochs_header VAR_4; int VAR_5; VAR_0->read_only = 1; VAR_5 = bdrv_pread(VAR_0->file, 0, &VAR_4, sizeof(VAR_4)); if (VAR_5 < 0) { return VAR_5; if (strcmp(VAR_4.magic, HEADER_MAGIC) ||
strcmp(VAR_4.type, REDOLOG_TYPE) ||
strcmp(VAR_4.subtype, GROWING_TYPE) ||
((le32_to_cpu(VAR_4.version) != HEADER_VERSION) &&
(le32_to_cpu(VAR_4.version) != HEADER_V1))) { error_setg(VAR_3, "Image not in Bochs format"); return -EINVAL; if (le32_to_cpu(VAR_4.version) == HEADER_V1) { VAR_0->total_sectors = le64_to_cpu(VAR_4.extra.redolog_v1.disk) / 512; } else { VAR_0->total_sectors = le64_to_cpu(VAR_4.extra.redolog.disk) / 512; s->catalog_size = le32_to_cpu(VAR_4.catalog); s->catalog_bitmap = g_malloc(s->catalog_size * 4); VAR_5 = bdrv_pread(VAR_0->file, le32_to_cpu(VAR_4.header), s->catalog_bitmap,
s->catalog_size * 4); if (VAR_5 < 0) { goto fail; for (i = 0; i < s->catalog_size; i++) le32_to_cpus(&s->catalog_bitmap[i]); s->data_offset = le32_to_cpu(VAR_4.header) + (s->catalog_size * 4); s->bitmap_blocks = 1 + (le32_to_cpu(VAR_4.bitmap) - 1) / 512; s->extent_blocks = 1 + (le32_to_cpu(VAR_4.extent) - 1) / 512; s->extent_size = le32_to_cpu(VAR_4.extent); if (s->catalog_size < VAR_0->total_sectors / s->extent_size) { error_setg(VAR_3, "Catalog size is too small for this disk size"); VAR_5 = -EINVAL; goto fail; qemu_co_mutex_init(&s->lock); return 0; fail:
g_free(s->catalog_bitmap); return VAR_5;