int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,

              int flags, BlockDriver *drv)

{

    int ret;

    /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */

    char tmp_filename[PATH_MAX + 1];

    BlockDriverState *file = NULL;

    QDict *file_options = NULL;



    /* NULL means an empty set of options */

    if (options == NULL) {

        options = qdict_new();

    }



    bs->options = options;

    options = qdict_clone_shallow(options);



    /* For snapshot=on, create a temporary qcow2 overlay */

    if (flags & BDRV_O_SNAPSHOT) {

        BlockDriverState *bs1;

        int64_t total_size;

        BlockDriver *bdrv_qcow2;

        QEMUOptionParameter *create_options;

        char backing_filename[PATH_MAX];



        if (qdict_size(options) != 0) {

            error_report("Can't use snapshot=on with driver-specific options");

            ret = -EINVAL;

            goto fail;

        }

        assert(filename != NULL);



        /* 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, NULL, 0, drv);

        if (ret < 0) {

            bdrv_delete(bs1);

            goto fail;

        }

        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;



        bdrv_delete(bs1);



        ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));

        if (ret < 0) {

            goto fail;

        }



        /* Real path is meaningless for protocols */

        if (path_has_protocol(filename)) {

            snprintf(backing_filename, sizeof(backing_filename),

                     "%s", filename);

        } else if (!realpath(filename, backing_filename)) {

            ret = -errno;

            goto fail;

        }



        bdrv_qcow2 = bdrv_find_format("qcow2");

        create_options = parse_option_parameters("", bdrv_qcow2->create_options,

                                                 NULL);



        set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);

        set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE,

                             backing_filename);

        if (drv) {

            set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT,

                drv->format_name);

        }



        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options);

        free_option_parameters(create_options);

        if (ret < 0) {

            goto fail;

        }



        filename = tmp_filename;

        drv = bdrv_qcow2;

        bs->is_temporary = 1;

    }



    /* Open image file without format layer */

    if (flags & BDRV_O_RDWR) {

        flags |= BDRV_O_ALLOW_RDWR;

    }



    extract_subqdict(options, &file_options, "file.");



    ret = bdrv_file_open(&file, filename, file_options,

                         bdrv_open_flags(bs, flags));

    if (ret < 0) {

        goto fail;

    }



    /* Find the right image format driver */

    if (!drv) {

        ret = find_image_format(file, filename, &drv);

    }



    if (!drv) {

        goto unlink_and_fail;

    }



    /* Open the image */

    ret = bdrv_open_common(bs, file, filename, options, flags, drv);

    if (ret < 0) {

        goto unlink_and_fail;

    }



    if (bs->file != file) {

        bdrv_delete(file);

        file = NULL;

    }



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

    if ((flags & BDRV_O_NO_BACKING) == 0) {

        ret = bdrv_open_backing_file(bs);

        if (ret < 0) {

            goto close_and_fail;

        }

    }



    /* Check if any unknown options were used */

    if (qdict_size(options) != 0) {

        const QDictEntry *entry = qdict_first(options);

        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by "

            "device '%s' doesn't support the option '%s'",

            drv->format_name, bs->device_name, entry->key);



        ret = -EINVAL;

        goto close_and_fail;

    }

    QDECREF(options);



    if (!bdrv_key_required(bs)) {

        bdrv_dev_change_media_cb(bs, true);

    }



    /* throttling disk I/O limits */

    if (bs->io_limits_enabled) {

        bdrv_io_limits_enable(bs);

    }



    return 0;



unlink_and_fail:

    if (file != NULL) {

        bdrv_delete(file);

    }

    if (bs->is_temporary) {

        unlink(filename);

    }

fail:

    QDECREF(bs->options);

    QDECREF(options);

    bs->options = NULL;

    return ret;



close_and_fail:

    bdrv_close(bs);

    QDECREF(options);

    return ret;

}

int bdrv_open(BlockDriverState *bs, const char *filename, QDict *options,

              int flags, BlockDriver *drv)

{

    int ret;

    

    char tmp_filename[PATH_MAX + 1];

    BlockDriverState *file = NULL;

    QDict *file_options = NULL;



    

    if (options == NULL) {

        options = qdict_new();

    }



    bs->options = options;

    options = qdict_clone_shallow(options);



    

    if (flags & BDRV_O_SNAPSHOT) {

        BlockDriverState *bs1;

        int64_t total_size;

        BlockDriver *bdrv_qcow2;

        QEMUOptionParameter *create_options;

        char backing_filename[PATH_MAX];



        if (qdict_size(options) != 0) {

            error_report("Can't use snapshot=on with driver-specific options");

            ret = -EINVAL;

            goto fail;

        }

        assert(filename != NULL);



        





        

        bs1 = bdrv_new("");

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

        if (ret < 0) {

            bdrv_delete(bs1);

            goto fail;

        }

        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;



        bdrv_delete(bs1);



        ret = get_tmp_filename(tmp_filename, sizeof(tmp_filename));

        if (ret < 0) {

            goto fail;

        }



        

        if (path_has_protocol(filename)) {

            snprintf(backing_filename, sizeof(backing_filename),

                     "%s", filename);

        } else if (!realpath(filename, backing_filename)) {

            ret = -errno;

            goto fail;

        }



        bdrv_qcow2 = bdrv_find_format("qcow2");

        create_options = parse_option_parameters("", bdrv_qcow2->create_options,

                                                 NULL);



        set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);

        set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE,

                             backing_filename);

        if (drv) {

            set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT,

                drv->format_name);

        }



        ret = bdrv_create(bdrv_qcow2, tmp_filename, create_options);

        free_option_parameters(create_options);

        if (ret < 0) {

            goto fail;

        }



        filename = tmp_filename;

        drv = bdrv_qcow2;

        bs->is_temporary = 1;

    }



    

    if (flags & BDRV_O_RDWR) {

        flags |= BDRV_O_ALLOW_RDWR;

    }



    extract_subqdict(options, &file_options, "file.");



    ret = bdrv_file_open(&file, filename, file_options,

                         bdrv_open_flags(bs, flags));

    if (ret < 0) {

        goto fail;

    }



    

    if (!drv) {

        ret = find_image_format(file, filename, &drv);

    }



    if (!drv) {

        goto unlink_and_fail;

    }



    

    ret = bdrv_open_common(bs, file, filename, options, flags, drv);

    if (ret < 0) {

        goto unlink_and_fail;

    }



    if (bs->file != file) {

        bdrv_delete(file);

        file = NULL;

    }



    

    if ((flags & BDRV_O_NO_BACKING) == 0) {

        ret = bdrv_open_backing_file(bs);

        if (ret < 0) {

            goto close_and_fail;

        }

    }



    

    if (qdict_size(options) != 0) {

        const QDictEntry *entry = qdict_first(options);

        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by "

            "device '%s' doesn't support the option '%s'",

            drv->format_name, bs->device_name, entry->key);



        ret = -EINVAL;

        goto close_and_fail;

    }

    QDECREF(options);



    if (!bdrv_key_required(bs)) {

        bdrv_dev_change_media_cb(bs, true);

    }



    

    if (bs->io_limits_enabled) {

        bdrv_io_limits_enable(bs);

    }



    return 0;



unlink_and_fail:

    if (file != NULL) {

        bdrv_delete(file);

    }

    if (bs->is_temporary) {

        unlink(filename);

    }

fail:

    QDECREF(bs->options);

    QDECREF(options);

    bs->options = NULL;

    return ret;



close_and_fail:

    bdrv_close(bs);

    QDECREF(options);

    return ret;

}

        ret = bdrv_open_backing_file(bs);
int FUNC_0(BlockDriverState *VAR_0, const char *VAR_1, QDict *VAR_2,

              int VAR_3, BlockDriver *VAR_4)

{

    int VAR_5;

    

    char VAR_6[PATH_MAX + 1];

    BlockDriverState *file = NULL;

    QDict *file_options = NULL;



    

    if (VAR_2 == NULL) {

        VAR_2 = qdict_new();

    }



    VAR_0->VAR_2 = VAR_2;

    VAR_2 = qdict_clone_shallow(VAR_2);



    

    if (VAR_3 & BDRV_O_SNAPSHOT) {

        BlockDriverState *bs1;

        int64_t total_size;

        BlockDriver *bdrv_qcow2;

        QEMUOptionParameter *create_options;

        char VAR_7[PATH_MAX];



        if (qdict_size(VAR_2) != 0) {

            error_report("Can't use snapshot=on with driver-specific VAR_2");

            VAR_5 = -EINVAL;

            goto fail;

        }

        assert(VAR_1 != NULL);



        





        

        bs1 = bdrv_new("");

        VAR_5 = FUNC_0(bs1, VAR_1, NULL, 0, VAR_4);

        if (VAR_5 < 0) {

            bdrv_delete(bs1);

            goto fail;

        }

        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;



        bdrv_delete(bs1);



        VAR_5 = get_tmp_filename(VAR_6, sizeof(VAR_6));

        if (VAR_5 < 0) {

            goto fail;

        }



        

        if (path_has_protocol(VAR_1)) {

            snprintf(VAR_7, sizeof(VAR_7),

                     "%s", VAR_1);

        } else if (!realpath(VAR_1, VAR_7)) {

            VAR_5 = -errno;

            goto fail;

        }



        bdrv_qcow2 = bdrv_find_format("qcow2");

        create_options = parse_option_parameters("", bdrv_qcow2->create_options,

                                                 NULL);



        set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size);

        set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE,

                             VAR_7);

        if (VAR_4) {

            set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT,

                VAR_4->format_name);

        }



        VAR_5 = bdrv_create(bdrv_qcow2, VAR_6, create_options);

        free_option_parameters(create_options);

        if (VAR_5 < 0) {

            goto fail;

        }



        VAR_1 = VAR_6;

        VAR_4 = bdrv_qcow2;

        VAR_0->is_temporary = 1;

    }



    

    if (VAR_3 & BDRV_O_RDWR) {

        VAR_3 |= BDRV_O_ALLOW_RDWR;

    }



    extract_subqdict(VAR_2, &file_options, "file.");



    VAR_5 = bdrv_file_open(&file, VAR_1, file_options,

                         bdrv_open_flags(VAR_0, VAR_3));

    if (VAR_5 < 0) {

        goto fail;

    }



    

    if (!VAR_4) {

        VAR_5 = find_image_format(file, VAR_1, &VAR_4);

    }



    if (!VAR_4) {

        goto unlink_and_fail;

    }



    

    VAR_5 = bdrv_open_common(VAR_0, file, VAR_1, VAR_2, VAR_3, VAR_4);

    if (VAR_5 < 0) {

        goto unlink_and_fail;

    }



    if (VAR_0->file != file) {

        bdrv_delete(file);

        file = NULL;

    }



    

    if ((VAR_3 & BDRV_O_NO_BACKING) == 0) {

        VAR_5 = bdrv_open_backing_file(VAR_0);

        if (VAR_5 < 0) {

            goto close_and_fail;

        }

    }



    

    if (qdict_size(VAR_2) != 0) {

        const QDictEntry *VAR_8 = qdict_first(VAR_2);

        qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by "

            "device '%s' doesn't support the option '%s'",

            VAR_4->format_name, VAR_0->device_name, VAR_8->key);



        VAR_5 = -EINVAL;

        goto close_and_fail;

    }

    QDECREF(VAR_2);



    if (!bdrv_key_required(VAR_0)) {

        bdrv_dev_change_media_cb(VAR_0, true);

    }



    

    if (VAR_0->io_limits_enabled) {

        bdrv_io_limits_enable(VAR_0);

    }



    return 0;



unlink_and_fail:

    if (file != NULL) {

        bdrv_delete(file);

    }

    if (VAR_0->is_temporary) {

        unlink(VAR_1);

    }

fail:

    QDECREF(VAR_0->VAR_2);

    QDECREF(VAR_2);

    VAR_0->VAR_2 = NULL;

    return VAR_5;



close_and_fail:

    bdrv_close(VAR_0);

    QDECREF(VAR_2);

    return VAR_5;

}

int FUNC_0(BlockDriverState *VAR_0, const char *VAR_1, QDict *VAR_2,
int VAR_3, BlockDriver *VAR_4)
{ int VAR_5; char VAR_6[PATH_MAX + 1]; BlockDriverState *file = NULL; QDict *file_options = NULL; if (VAR_2 == NULL) { VAR_2 = qdict_new(); } VAR_0->VAR_2 = VAR_2; VAR_2 = qdict_clone_shallow(VAR_2); if (VAR_3 & BDRV_O_SNAPSHOT) { BlockDriverState *bs1; int64_t total_size; BlockDriver *bdrv_qcow2; QEMUOptionParameter *create_options; char VAR_7[PATH_MAX]; if (qdict_size(VAR_2) != 0) { error_report("Can't use snapshot=on with driver-specific VAR_2"); VAR_5 = -EINVAL; goto fail; } assert(VAR_1 != NULL); bs1 = bdrv_new(""); VAR_5 = FUNC_0(bs1, VAR_1, NULL, 0, VAR_4); if (VAR_5 < 0) { bdrv_delete(bs1); goto fail; } total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK; bdrv_delete(bs1); VAR_5 = get_tmp_filename(VAR_6, sizeof(VAR_6)); if (VAR_5 < 0) { goto fail; } if (path_has_protocol(VAR_1)) { snprintf(VAR_7, sizeof(VAR_7),
"%s", VAR_1); } else if (!realpath(VAR_1, VAR_7)) { VAR_5 = -errno; goto fail; } bdrv_qcow2 = bdrv_find_format("qcow2"); create_options = parse_option_parameters("", bdrv_qcow2->create_options,
NULL); set_option_parameter_int(create_options, BLOCK_OPT_SIZE, total_size); set_option_parameter(create_options, BLOCK_OPT_BACKING_FILE,
VAR_7); if (VAR_4) { set_option_parameter(create_options, BLOCK_OPT_BACKING_FMT,
VAR_4->format_name); } VAR_5 = bdrv_create(bdrv_qcow2, VAR_6, create_options); free_option_parameters(create_options); if (VAR_5 < 0) { goto fail; } VAR_1 = VAR_6; VAR_4 = bdrv_qcow2; VAR_0->is_temporary = 1; } if (VAR_3 & BDRV_O_RDWR) { VAR_3 |= BDRV_O_ALLOW_RDWR; } extract_subqdict(VAR_2, &file_options, "file."); VAR_5 = bdrv_file_open(&file, VAR_1, file_options,
bdrv_open_flags(VAR_0, VAR_3)); if (VAR_5 < 0) { goto fail; } if (!VAR_4) { VAR_5 = find_image_format(file, VAR_1, &VAR_4); } if (!VAR_4) { goto unlink_and_fail; } VAR_5 = bdrv_open_common(VAR_0, file, VAR_1, VAR_2, VAR_3, VAR_4); if (VAR_5 < 0) { goto unlink_and_fail; } if (VAR_0->file != file) { bdrv_delete(file); file = NULL; } if ((VAR_3 & BDRV_O_NO_BACKING) == 0) { VAR_5 = bdrv_open_backing_file(VAR_0); if (VAR_5 < 0) { goto close_and_fail; } } if (qdict_size(VAR_2) != 0) { const QDictEntry *VAR_8 = qdict_first(VAR_2); qerror_report(ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by "
"device '%s' doesn't support the option '%s'",
VAR_4->format_name, VAR_0->device_name, VAR_8->key); VAR_5 = -EINVAL; goto close_and_fail; } QDECREF(VAR_2); if (!bdrv_key_required(VAR_0)) { bdrv_dev_change_media_cb(VAR_0, true); } if (VAR_0->io_limits_enabled) { bdrv_io_limits_enable(VAR_0); } return 0; unlink_and_fail:
if (file != NULL) { bdrv_delete(file); } if (VAR_0->is_temporary) { unlink(VAR_1); } fail:
QDECREF(VAR_0->VAR_2); QDECREF(VAR_2); VAR_0->VAR_2 = NULL; return VAR_5; close_and_fail:
bdrv_close(VAR_0); QDECREF(VAR_2); return VAR_5; }