int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
              BlockDriver *drv)
{
    int ret;
    int probed = 0;
    if (flags & BDRV_O_SNAPSHOT) {
        BlockDriverState *bs1;
        int64_t total_size;
        int is_protocol = 0;
        BlockDriver *bdrv_qcow2;
        QEMUOptionParameter *options;
        char tmp_filename[PATH_MAX];
        char backing_filename[PATH_MAX];
        /* 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_MASK;
        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);
        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);
        free_option_parameters(options);
        if (ret < 0) {
            return ret;
        }
        filename = tmp_filename;
        drv = bdrv_qcow2;
        bs->is_temporary = 1;
    }
    /* Find the right image format driver */
    if (!drv) {
        drv = find_image_format(filename);
        probed = 1;
    }
    if (!drv) {
        ret = -ENOENT;
        goto unlink_and_fail;
    }
    /* Open the image */
    ret = bdrv_open_common(bs, filename, flags, drv);
    if (ret < 0) {
        goto unlink_and_fail;
    }
    /* If there is a backing file, use it */
    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
        char backing_filename[PATH_MAX];
        int back_flags;
        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 */
        back_flags =
            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
        ret = bdrv_open(bs->backing_hd, backing_filename, back_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;
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;
    int probed = 0;
    if (flags & BDRV_O_SNAPSHOT) {
        BlockDriverState *bs1;
        int64_t total_size;
        int is_protocol = 0;
        BlockDriver *bdrv_qcow2;
        QEMUOptionParameter *options;
        char tmp_filename[PATH_MAX];
        char backing_filename[PATH_MAX];
        

        
        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_MASK;
        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);
        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);
        free_option_parameters(options);
        if (ret < 0) {
            return ret;
        }
        filename = tmp_filename;
        drv = bdrv_qcow2;
        bs->is_temporary = 1;
    }
    
    if (!drv) {
        drv = find_image_format(filename);
        probed = 1;
    }
    if (!drv) {
        ret = -ENOENT;
        goto unlink_and_fail;
    }
    
    ret = bdrv_open_common(bs, filename, flags, drv);
    if (ret < 0) {
        goto unlink_and_fail;
    }
    
    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
        char backing_filename[PATH_MAX];
        int back_flags;
        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);
        
        back_flags =
            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
        ret = bdrv_open(bs->backing_hd, backing_filename, back_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;
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;
    int VAR_5 = 0;
    if (VAR_2 & BDRV_O_SNAPSHOT) {
        BlockDriverState *bs1;
        int64_t total_size;
        int VAR_6 = 0;
        BlockDriver *bdrv_qcow2;
        QEMUOptionParameter *options;
        char VAR_7[PATH_MAX];
        char VAR_9[PATH_MAX];
        

        
        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_MASK;
        if (bs1->VAR_3 && bs1->VAR_3->protocol_name)
            VAR_6 = 1;
        bdrv_delete(bs1);
        get_tmp_filename(VAR_7, sizeof(VAR_7));
        
        if (VAR_6)
            snprintf(VAR_9, sizeof(VAR_9),
                     "%s", VAR_1);
        else if (!realpath(VAR_1, VAR_9))
            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);
        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, VAR_9);
        if (VAR_3) {
            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
                VAR_3->format_name);
        }
        VAR_4 = bdrv_create(bdrv_qcow2, VAR_7, options);
        free_option_parameters(options);
        if (VAR_4 < 0) {
            return VAR_4;
        }
        VAR_1 = VAR_7;
        VAR_3 = bdrv_qcow2;
        VAR_0->is_temporary = 1;
    }
    
    if (!VAR_3) {
        VAR_3 = find_image_format(VAR_1);
        VAR_5 = 1;
    }
    if (!VAR_3) {
        VAR_4 = -ENOENT;
        goto unlink_and_fail;
    }
    
    VAR_4 = bdrv_open_common(VAR_0, VAR_1, VAR_2, VAR_3);
    if (VAR_4 < 0) {
        goto unlink_and_fail;
    }
    
    if ((VAR_2 & BDRV_O_NO_BACKING) == 0 && VAR_0->backing_file[0] != '\0') {
        char VAR_9[PATH_MAX];
        int VAR_9;
        BlockDriver *back_drv = NULL;
        VAR_0->backing_hd = bdrv_new("");
        path_combine(VAR_9, sizeof(VAR_9),
                     VAR_1, VAR_0->backing_file);
        if (VAR_0->backing_format[0] != '\0')
            back_drv = bdrv_find_format(VAR_0->backing_format);
        
        VAR_9 =
            VAR_2 & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
        VAR_4 = FUNC_0(VAR_0->backing_hd, VAR_9, VAR_9, 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;
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; int VAR_5 = 0; if (VAR_2 & BDRV_O_SNAPSHOT) { BlockDriverState *bs1; int64_t total_size; int VAR_6 = 0; BlockDriver *bdrv_qcow2; QEMUOptionParameter *options; char VAR_7[PATH_MAX]; char VAR_9[PATH_MAX]; 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_MASK; if (bs1->VAR_3 && bs1->VAR_3->protocol_name)
VAR_6 = 1; bdrv_delete(bs1); get_tmp_filename(VAR_7, sizeof(VAR_7)); if (VAR_6)
snprintf(VAR_9, sizeof(VAR_9),
"%s", VAR_1); else if (!realpath(VAR_1, VAR_9))
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); set_option_parameter(options, BLOCK_OPT_BACKING_FILE, VAR_9); if (VAR_3) { set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
VAR_3->format_name); } VAR_4 = bdrv_create(bdrv_qcow2, VAR_7, options); free_option_parameters(options); if (VAR_4 < 0) { return VAR_4; } VAR_1 = VAR_7; VAR_3 = bdrv_qcow2; VAR_0->is_temporary = 1; } if (!VAR_3) { VAR_3 = find_image_format(VAR_1); VAR_5 = 1; } if (!VAR_3) { VAR_4 = -ENOENT; goto unlink_and_fail; } VAR_4 = bdrv_open_common(VAR_0, VAR_1, VAR_2, VAR_3); if (VAR_4 < 0) { goto unlink_and_fail; } if ((VAR_2 & BDRV_O_NO_BACKING) == 0 && VAR_0->backing_file[0] != '\0') { char VAR_9[PATH_MAX]; int VAR_9; BlockDriver *back_drv = NULL; VAR_0->backing_hd = bdrv_new(""); path_combine(VAR_9, sizeof(VAR_9),
VAR_1, VAR_0->backing_file); if (VAR_0->backing_format[0] != '\0')
back_drv = bdrv_find_format(VAR_0->backing_format); VAR_9 =
VAR_2 & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING); VAR_4 = FUNC_0(VAR_0->backing_hd, VAR_9, VAR_9, 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; unlink_and_fail:
if (VAR_0->is_temporary) { unlink(VAR_1); } return VAR_4; }