Skip to content

Commit

Permalink
block: Don't parse protocol from file.filename
Browse files Browse the repository at this point in the history
One of the major reasons for doing something new for -blockdev and
blockdev-add was that the old block layer code parses filenames instead
of just taking them literally. So we should really leave it untouched
when it's passing using the new interfaces (like -drive
file.filename=...).

This allows opening relative file names that contain a colon.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
  • Loading branch information
kevmw committed Jul 15, 2013
1 parent de90930 commit 9828962
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 9 deletions.
17 changes: 12 additions & 5 deletions block.c
Expand Up @@ -417,7 +417,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
{
BlockDriver *drv;

drv = bdrv_find_protocol(filename);
drv = bdrv_find_protocol(filename, true);
if (drv == NULL) {
return -ENOENT;
}
Expand Down Expand Up @@ -482,7 +482,8 @@ static BlockDriver *find_hdev_driver(const char *filename)
return drv;
}

BlockDriver *bdrv_find_protocol(const char *filename)
BlockDriver *bdrv_find_protocol(const char *filename,
bool allow_protocol_prefix)
{
BlockDriver *drv1;
char protocol[128];
Expand All @@ -503,9 +504,10 @@ BlockDriver *bdrv_find_protocol(const char *filename)
return drv1;
}

if (!path_has_protocol(filename)) {
if (!path_has_protocol(filename) || !allow_protocol_prefix) {
return bdrv_find_format("file");
}

p = strchr(filename, ':');
assert(p != NULL);
len = p - filename;
Expand Down Expand Up @@ -784,6 +786,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
BlockDriverState *bs;
BlockDriver *drv;
const char *drvname;
bool allow_protocol_prefix = false;
int ret;

/* NULL means an empty set of options */
Expand All @@ -800,6 +803,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
filename = qdict_get_try_str(options, "filename");
} else if (filename && !qdict_haskey(options, "filename")) {
qdict_put(options, "filename", qstring_from_str(filename));
allow_protocol_prefix = true;
} else {
qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and "
"'filename' options at the same time");
Expand All @@ -813,7 +817,10 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
qdict_del(options, "driver");
} else if (filename) {
drv = bdrv_find_protocol(filename);
drv = bdrv_find_protocol(filename, allow_protocol_prefix);
if (!drv) {
qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol");
}
} else {
qerror_report(ERROR_CLASS_GENERIC_ERROR,
"Must specify either driver or file");
Expand Down Expand Up @@ -4452,7 +4459,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
return;
}

proto_drv = bdrv_find_protocol(filename);
proto_drv = bdrv_find_protocol(filename, true);
if (!proto_drv) {
error_setg(errp, "Unknown protocol '%s'", filename);
return;
Expand Down
2 changes: 1 addition & 1 deletion block/sheepdog.c
Expand Up @@ -1510,7 +1510,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
BlockDriver *drv;

/* Currently, only Sheepdog backing image is supported. */
drv = bdrv_find_protocol(backing_file);
drv = bdrv_find_protocol(backing_file, true);
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
error_report("backing_file must be a sheepdog image");
ret = -EINVAL;
Expand Down
3 changes: 2 additions & 1 deletion include/block/block.h
Expand Up @@ -111,7 +111,8 @@ bool bdrv_io_limits_enabled(BlockDriverState *bs);

void bdrv_init(void);
void bdrv_init_with_whitelist(void);
BlockDriver *bdrv_find_protocol(const char *filename);
BlockDriver *bdrv_find_protocol(const char *filename,
bool allow_protocol_prefix);
BlockDriver *bdrv_find_format(const char *format_name);
BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
bool readonly);
Expand Down
4 changes: 2 additions & 2 deletions qemu-img.c
Expand Up @@ -240,7 +240,7 @@ static int print_block_option_help(const char *filename, const char *fmt)
return 1;
}

proto_drv = bdrv_find_protocol(filename);
proto_drv = bdrv_find_protocol(filename, true);
if (!proto_drv) {
error_report("Unknown protocol '%s'", filename);
return 1;
Expand Down Expand Up @@ -1261,7 +1261,7 @@ static int img_convert(int argc, char **argv)
goto out;
}

proto_drv = bdrv_find_protocol(out_filename);
proto_drv = bdrv_find_protocol(out_filename, true);
if (!proto_drv) {
error_report("Unknown protocol '%s'", out_filename);
ret = -1;
Expand Down
12 changes: 12 additions & 0 deletions tests/qemu-iotests/051
Expand Up @@ -149,6 +149,18 @@ echo
run_qemu -drive file=$TEST_IMG,file.driver=file
run_qemu -drive file=$TEST_IMG,file.driver=qcow2

echo
echo === Parsing protocol from file name ===
echo

# Protocol strings are supposed to be parsed from traditional option strings,
# but not when using driver-specific options. We can distinguish them by the
# error message for non-existing files.

run_qemu -hda foo:bar
run_qemu -drive file=foo:bar
run_qemu -drive file.filename=foo:bar

# success, all done
echo "*** done"
rm -f $seq.full
Expand Down
14 changes: 14 additions & 0 deletions tests/qemu-iotests/051.out
Expand Up @@ -169,4 +169,18 @@ Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Can't use 'qcow2' as a block driver for the protocol level
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Invalid argument


=== Parsing protocol from file name ===

Testing: -hda foo:bar
QEMU_PROG: -hda foo:bar: Unknown protocol
QEMU_PROG: -hda foo:bar: could not open disk image foo:bar: No such file or directory

Testing: -drive file=foo:bar
QEMU_PROG: -drive file=foo:bar: Unknown protocol
QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: No such file or directory

Testing: -drive file.filename=foo:bar
QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: No such file or directory

*** done

0 comments on commit 9828962

Please sign in to comment.