int bdrv_open(BlockDriverState *bs, const char *filename, int flags,

              BlockDriver *drv)

{

    int ret, open_flags;

    char tmp_filename[PATH_MAX];

    char backing_filename[PATH_MAX];



    bs->is_temporary = 0;

    bs->encrypted = 0;

    bs->valid_key = 0;

    bs->open_flags = flags;

    /* buffer_alignment defaulted to 512, drivers can change this value */

    bs->buffer_alignment = 512;



    if (flags & BDRV_O_SNAPSHOT) {

        BlockDriverState *bs1;

        int64_t total_size;

        int is_protocol = 0;

        BlockDriver *bdrv_qcow2;

        QEMUOptionParameter *options;



        /* if snapshot, we create a temporary backing file and open it

           instead of opening 'filename' directly */



        /* if there is a backing file, use it */

        bs1 = bdrv_new("");

        ret = bdrv_open(bs1, filename, 0, drv);

        if (ret < 0) {

            bdrv_delete(bs1);

            return ret;

        }

        total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS;



        if (bs1->drv && bs1->drv->protocol_name)

            is_protocol = 1;



        bdrv_delete(bs1);



        get_tmp_filename(tmp_filename, sizeof(tmp_filename));



        /* Real path is meaningless for protocols */

        if (is_protocol)

            snprintf(backing_filename, sizeof(backing_filename),

                     "%s", filename);

        else if (!realpath(filename, backing_filename))

            return -errno;



        bdrv_qcow2 = bdrv_find_format("qcow2");

        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);



        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);

        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);

        if (drv) {

            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,

                drv->format_name);

        }



        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);

        if (ret < 0) {

            return ret;

        }



        filename = tmp_filename;

        drv = bdrv_qcow2;

        bs->is_temporary = 1;

    }



    pstrcpy(bs->filename, sizeof(bs->filename), filename);



    if (!drv) {

        drv = find_hdev_driver(filename);

        if (!drv) {

            drv = find_image_format(filename);

        }

    }



    if (!drv) {

        ret = -ENOENT;

        goto unlink_and_fail;

    }

    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {

        ret = -ENOTSUP;

        goto unlink_and_fail;

    }



    bs->drv = drv;

    bs->opaque = qemu_mallocz(drv->instance_size);



    /*

     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a

     * write cache to the guest.  We do need the fdatasync to flush

     * out transactions for block allocations, and we maybe have a

     * volatile write cache in our backing device to deal with.

     */

    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))

        bs->enable_write_cache = 1;



    /*

     * Clear flags that are internal to the block layer before opening the

     * image.

     */

    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);



    /*

     * Snapshots should be writeable.

     */

    if (bs->is_temporary) {

        open_flags |= BDRV_O_RDWR;

    }



    ret = drv->bdrv_open(bs, filename, open_flags);

    if (ret < 0) {

        goto free_and_fail;

    }



    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);

    if (drv->bdrv_getlength) {

        bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;

    }

#ifndef _WIN32

    if (bs->is_temporary) {

        unlink(filename);

    }

#endif

    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {

        /* if there is a backing file, use it */

        BlockDriver *back_drv = NULL;

        bs->backing_hd = bdrv_new("");

        path_combine(backing_filename, sizeof(backing_filename),

                     filename, bs->backing_file);

        if (bs->backing_format[0] != '\0')

            back_drv = bdrv_find_format(bs->backing_format);



        /* backing files always opened read-only */

        open_flags &= ~BDRV_O_RDWR;



        ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv);

        if (ret < 0) {

            bdrv_close(bs);

            return ret;

        }

        if (bs->is_temporary) {

            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);

        } else {

            /* base image inherits from "parent" */

            bs->backing_hd->keep_read_only = bs->keep_read_only;

        }

    }



    if (!bdrv_key_required(bs)) {

        /* call the change callback */

        bs->media_changed = 1;

        if (bs->change_cb)

            bs->change_cb(bs->change_opaque);

    }

    return 0;



free_and_fail:

    qemu_free(bs->opaque);

    bs->opaque = NULL;

    bs->drv = NULL;

unlink_and_fail:

    if (bs->is_temporary)

        unlink(filename);

    return ret;

}

int bdrv_open(BlockDriverState *bs, const char *filename, int flags,

              BlockDriver *drv)

{

    int ret, open_flags;

    char tmp_filename[PATH_MAX];

    char backing_filename[PATH_MAX];



    bs->is_temporary = 0;

    bs->encrypted = 0;

    bs->valid_key = 0;

    bs->open_flags = flags;

    

    bs->buffer_alignment = 512;



    if (flags & BDRV_O_SNAPSHOT) {

        BlockDriverState *bs1;

        int64_t total_size;

        int is_protocol = 0;

        BlockDriver *bdrv_qcow2;

        QEMUOptionParameter *options;



        





        

        bs1 = bdrv_new("");

        ret = bdrv_open(bs1, filename, 0, drv);

        if (ret < 0) {

            bdrv_delete(bs1);

            return ret;

        }

        total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS;



        if (bs1->drv && bs1->drv->protocol_name)

            is_protocol = 1;



        bdrv_delete(bs1);



        get_tmp_filename(tmp_filename, sizeof(tmp_filename));



        

        if (is_protocol)

            snprintf(backing_filename, sizeof(backing_filename),

                     "%s", filename);

        else if (!realpath(filename, backing_filename))

            return -errno;



        bdrv_qcow2 = bdrv_find_format("qcow2");

        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);



        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);

        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);

        if (drv) {

            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,

                drv->format_name);

        }



        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);

        if (ret < 0) {

            return ret;

        }



        filename = tmp_filename;

        drv = bdrv_qcow2;

        bs->is_temporary = 1;

    }



    pstrcpy(bs->filename, sizeof(bs->filename), filename);



    if (!drv) {

        drv = find_hdev_driver(filename);

        if (!drv) {

            drv = find_image_format(filename);

        }

    }



    if (!drv) {

        ret = -ENOENT;

        goto unlink_and_fail;

    }

    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {

        ret = -ENOTSUP;

        goto unlink_and_fail;

    }



    bs->drv = drv;

    bs->opaque = qemu_mallocz(drv->instance_size);



    











    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))

        bs->enable_write_cache = 1;



    







    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);



    





    if (bs->is_temporary) {

        open_flags |= BDRV_O_RDWR;

    }



    ret = drv->bdrv_open(bs, filename, open_flags);

    if (ret < 0) {

        goto free_and_fail;

    }



    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);

    if (drv->bdrv_getlength) {

        bs->total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;

    }

#ifndef _WIN32

    if (bs->is_temporary) {

        unlink(filename);

    }

#endif

    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {

        

        BlockDriver *back_drv = NULL;

        bs->backing_hd = bdrv_new("");

        path_combine(backing_filename, sizeof(backing_filename),

                     filename, bs->backing_file);

        if (bs->backing_format[0] != '\0')

            back_drv = bdrv_find_format(bs->backing_format);



        

        open_flags &= ~BDRV_O_RDWR;



        ret = bdrv_open(bs->backing_hd, backing_filename, open_flags, back_drv);

        if (ret < 0) {

            bdrv_close(bs);

            return ret;

        }

        if (bs->is_temporary) {

            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);

        } else {

            

            bs->backing_hd->keep_read_only = bs->keep_read_only;

        }

    }



    if (!bdrv_key_required(bs)) {

        

        bs->media_changed = 1;

        if (bs->change_cb)

            bs->change_cb(bs->change_opaque);

    }

    return 0;



free_and_fail:

    qemu_free(bs->opaque);

    bs->opaque = NULL;

    bs->drv = NULL;

unlink_and_fail:

    if (bs->is_temporary)

        unlink(filename);

    return ret;

}

int FUNC_0(BlockDriverState *VAR_0, const char *VAR_1, int VAR_2,

              BlockDriver *VAR_3)

{

    int VAR_4, VAR_5;

    char VAR_6[PATH_MAX];

    char VAR_7[PATH_MAX];



    VAR_0->is_temporary = 0;

    VAR_0->encrypted = 0;

    VAR_0->valid_key = 0;

    VAR_0->VAR_5 = VAR_2;

    

    VAR_0->buffer_alignment = 512;



    if (VAR_2 & BDRV_O_SNAPSHOT) {

        BlockDriverState *bs1;

        int64_t total_size;

        int VAR_8 = 0;

        BlockDriver *bdrv_qcow2;

        QEMUOptionParameter *options;



        





        

        bs1 = bdrv_new("");

        VAR_4 = FUNC_0(bs1, VAR_1, 0, VAR_3);

        if (VAR_4 < 0) {

            bdrv_delete(bs1);

            return VAR_4;

        }

        total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS;



        if (bs1->VAR_3 && bs1->VAR_3->protocol_name)

            VAR_8 = 1;



        bdrv_delete(bs1);



        get_tmp_filename(VAR_6, sizeof(VAR_6));



        

        if (VAR_8)

            snprintf(VAR_7, sizeof(VAR_7),

                     "%s", VAR_1);

        else if (!realpath(VAR_1, VAR_7))

            return -errno;



        bdrv_qcow2 = bdrv_find_format("qcow2");

        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);



        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);

        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, VAR_7);

        if (VAR_3) {

            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,

                VAR_3->format_name);

        }



        VAR_4 = bdrv_create(bdrv_qcow2, VAR_6, options);

        if (VAR_4 < 0) {

            return VAR_4;

        }



        VAR_1 = VAR_6;

        VAR_3 = bdrv_qcow2;

        VAR_0->is_temporary = 1;

    }



    pstrcpy(VAR_0->VAR_1, sizeof(VAR_0->VAR_1), VAR_1);



    if (!VAR_3) {

        VAR_3 = find_hdev_driver(VAR_1);

        if (!VAR_3) {

            VAR_3 = find_image_format(VAR_1);

        }

    }



    if (!VAR_3) {

        VAR_4 = -ENOENT;

        goto unlink_and_fail;

    }

    if (use_bdrv_whitelist && !bdrv_is_whitelisted(VAR_3)) {

        VAR_4 = -ENOTSUP;

        goto unlink_and_fail;

    }



    VAR_0->VAR_3 = VAR_3;

    VAR_0->opaque = qemu_mallocz(VAR_3->instance_size);



    











    if (VAR_2 & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))

        VAR_0->enable_write_cache = 1;



    







    VAR_5 = VAR_2 & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);



    





    if (VAR_0->is_temporary) {

        VAR_5 |= BDRV_O_RDWR;

    }



    VAR_4 = VAR_3->FUNC_0(VAR_0, VAR_1, VAR_5);

    if (VAR_4 < 0) {

        goto free_and_fail;

    }



    VAR_0->keep_read_only = VAR_0->read_only = !(VAR_5 & BDRV_O_RDWR);

    if (VAR_3->bdrv_getlength) {

        VAR_0->total_sectors = bdrv_getlength(VAR_0) >> BDRV_SECTOR_BITS;

    }

#ifndef _WIN32

    if (VAR_0->is_temporary) {

        unlink(VAR_1);

    }

#endif

    if ((VAR_2 & BDRV_O_NO_BACKING) == 0 && VAR_0->backing_file[0] != '\0') {

        

        BlockDriver *back_drv = NULL;

        VAR_0->backing_hd = bdrv_new("");

        path_combine(VAR_7, sizeof(VAR_7),

                     VAR_1, VAR_0->backing_file);

        if (VAR_0->backing_format[0] != '\0')

            back_drv = bdrv_find_format(VAR_0->backing_format);



        

        VAR_5 &= ~BDRV_O_RDWR;



        VAR_4 = FUNC_0(VAR_0->backing_hd, VAR_7, VAR_5, back_drv);

        if (VAR_4 < 0) {

            bdrv_close(VAR_0);

            return VAR_4;

        }

        if (VAR_0->is_temporary) {

            VAR_0->backing_hd->keep_read_only = !(VAR_2 & BDRV_O_RDWR);

        } else {

            

            VAR_0->backing_hd->keep_read_only = VAR_0->keep_read_only;

        }

    }



    if (!bdrv_key_required(VAR_0)) {

        

        VAR_0->media_changed = 1;

        if (VAR_0->change_cb)

            VAR_0->change_cb(VAR_0->change_opaque);

    }

    return 0;



free_and_fail:

    qemu_free(VAR_0->opaque);

    VAR_0->opaque = NULL;

    VAR_0->VAR_3 = NULL;

unlink_and_fail:

    if (VAR_0->is_temporary)

        unlink(VAR_1);

    return VAR_4;

}

int FUNC_0(BlockDriverState *VAR_0, const char *VAR_1, int VAR_2,
BlockDriver *VAR_3)
{ int VAR_4, VAR_5; char VAR_6[PATH_MAX]; char VAR_7[PATH_MAX]; VAR_0->is_temporary = 0; VAR_0->encrypted = 0; VAR_0->valid_key = 0; VAR_0->VAR_5 = VAR_2; VAR_0->buffer_alignment = 512; if (VAR_2 & BDRV_O_SNAPSHOT) { BlockDriverState *bs1; int64_t total_size; int VAR_8 = 0; BlockDriver *bdrv_qcow2; QEMUOptionParameter *options; bs1 = bdrv_new(""); VAR_4 = FUNC_0(bs1, VAR_1, 0, VAR_3); if (VAR_4 < 0) { bdrv_delete(bs1); return VAR_4; } total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS; if (bs1->VAR_3 && bs1->VAR_3->protocol_name)
VAR_8 = 1; bdrv_delete(bs1); get_tmp_filename(VAR_6, sizeof(VAR_6)); if (VAR_8)
snprintf(VAR_7, sizeof(VAR_7),
"%s", VAR_1); else if (!realpath(VAR_1, VAR_7))
return -errno; bdrv_qcow2 = bdrv_find_format("qcow2"); options = parse_option_parameters("", bdrv_qcow2->create_options, NULL); set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512); set_option_parameter(options, BLOCK_OPT_BACKING_FILE, VAR_7); if (VAR_3) { set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
VAR_3->format_name); } VAR_4 = bdrv_create(bdrv_qcow2, VAR_6, options); if (VAR_4 < 0) { return VAR_4; } VAR_1 = VAR_6; VAR_3 = bdrv_qcow2; VAR_0->is_temporary = 1; } pstrcpy(VAR_0->VAR_1, sizeof(VAR_0->VAR_1), VAR_1); if (!VAR_3) { VAR_3 = find_hdev_driver(VAR_1); if (!VAR_3) { VAR_3 = find_image_format(VAR_1); } } if (!VAR_3) { VAR_4 = -ENOENT; goto unlink_and_fail; } if (use_bdrv_whitelist && !bdrv_is_whitelisted(VAR_3)) { VAR_4 = -ENOTSUP; goto unlink_and_fail; } VAR_0->VAR_3 = VAR_3; VAR_0->opaque = qemu_mallocz(VAR_3->instance_size); if (VAR_2 & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
VAR_0->enable_write_cache = 1; VAR_5 = VAR_2 & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); if (VAR_0->is_temporary) { VAR_5 |= BDRV_O_RDWR; } VAR_4 = VAR_3->FUNC_0(VAR_0, VAR_1, VAR_5); if (VAR_4 < 0) { goto free_and_fail; } VAR_0->keep_read_only = VAR_0->read_only = !(VAR_5 & BDRV_O_RDWR); if (VAR_3->bdrv_getlength) { VAR_0->total_sectors = bdrv_getlength(VAR_0) >> BDRV_SECTOR_BITS; } #ifndef _WIN32
if (VAR_0->is_temporary) { unlink(VAR_1); } #endif
if ((VAR_2 & BDRV_O_NO_BACKING) == 0 && VAR_0->backing_file[0] != '\0') { BlockDriver *back_drv = NULL; VAR_0->backing_hd = bdrv_new(""); path_combine(VAR_7, sizeof(VAR_7),
VAR_1, VAR_0->backing_file); if (VAR_0->backing_format[0] != '\0')
back_drv = bdrv_find_format(VAR_0->backing_format); VAR_5 &= ~BDRV_O_RDWR; VAR_4 = FUNC_0(VAR_0->backing_hd, VAR_7, VAR_5, back_drv); if (VAR_4 < 0) { bdrv_close(VAR_0); return VAR_4; } if (VAR_0->is_temporary) { VAR_0->backing_hd->keep_read_only = !(VAR_2 & BDRV_O_RDWR); } else { VAR_0->backing_hd->keep_read_only = VAR_0->keep_read_only; } } if (!bdrv_key_required(VAR_0)) { VAR_0->media_changed = 1; if (VAR_0->change_cb)
VAR_0->change_cb(VAR_0->change_opaque); } return 0; free_and_fail:
qemu_free(VAR_0->opaque); VAR_0->opaque = NULL; VAR_0->VAR_3 = NULL; unlink_and_fail:
if (VAR_0->is_temporary)
unlink(VAR_1); return VAR_4; }