9ae3a8
From 8f9ad0991d9dd978f342ff4dcc58a18d8f1a73c4 Mon Sep 17 00:00:00 2001
9ae3a8
From: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Date: Mon, 9 Sep 2013 14:27:58 +0200
9ae3a8
Subject: [PATCH 07/38] block: Don't parse protocol from file.filename
9ae3a8
9ae3a8
RH-Author: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Message-id: <1378736903-18489-8-git-send-email-kwolf@redhat.com>
9ae3a8
Patchwork-id: 54194
9ae3a8
O-Subject: [RHEL-7.0 qemu-kvm PATCH 07/32] block: Don't parse protocol from file.filename
9ae3a8
Bugzilla: 1005818
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Max Reitz <mreitz@redhat.com>
9ae3a8
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
9ae3a8
Bugzilla: 1005818
9ae3a8
9ae3a8
One of the major reasons for doing something new for -blockdev and
9ae3a8
blockdev-add was that the old block layer code parses filenames instead
9ae3a8
of just taking them literally. So we should really leave it untouched
9ae3a8
when it's passing using the new interfaces (like -drive
9ae3a8
file.filename=...).
9ae3a8
9ae3a8
This allows opening relative file names that contain a colon.
9ae3a8
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Reviewed-by: Eric Blake <eblake@redhat.com>
9ae3a8
(cherry picked from commit 98289620e0460fa595581020ab20127da4a2fc44)
9ae3a8
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
---
9ae3a8
 block.c                    | 17 ++++++++++++-----
9ae3a8
 block/sheepdog.c           |  2 +-
9ae3a8
 include/block/block.h      |  3 ++-
9ae3a8
 qemu-img.c                 |  4 ++--
9ae3a8
 tests/qemu-iotests/051     | 12 ++++++++++++
9ae3a8
 tests/qemu-iotests/051.out | 14 ++++++++++++++
9ae3a8
 6 files changed, 43 insertions(+), 9 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 block.c                    |   17 ++++++++++++-----
9ae3a8
 block/sheepdog.c           |    2 +-
9ae3a8
 include/block/block.h      |    3 ++-
9ae3a8
 qemu-img.c                 |    4 ++--
9ae3a8
 tests/qemu-iotests/051     |   12 ++++++++++++
9ae3a8
 tests/qemu-iotests/051.out |   14 ++++++++++++++
9ae3a8
 6 files changed, 43 insertions(+), 9 deletions(-)
9ae3a8
9ae3a8
diff --git a/block.c b/block.c
9ae3a8
index 3c869e4..2584ec7 100644
9ae3a8
--- a/block.c
9ae3a8
+++ b/block.c
9ae3a8
@@ -419,7 +419,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
9ae3a8
 {
9ae3a8
     BlockDriver *drv;
9ae3a8
 
9ae3a8
-    drv = bdrv_find_protocol(filename);
9ae3a8
+    drv = bdrv_find_protocol(filename, true);
9ae3a8
     if (drv == NULL) {
9ae3a8
         return -ENOENT;
9ae3a8
     }
9ae3a8
@@ -484,7 +484,8 @@ static BlockDriver *find_hdev_driver(const char *filename)
9ae3a8
     return drv;
9ae3a8
 }
9ae3a8
 
9ae3a8
-BlockDriver *bdrv_find_protocol(const char *filename)
9ae3a8
+BlockDriver *bdrv_find_protocol(const char *filename,
9ae3a8
+                                bool allow_protocol_prefix)
9ae3a8
 {
9ae3a8
     BlockDriver *drv1;
9ae3a8
     char protocol[128];
9ae3a8
@@ -505,9 +506,10 @@ BlockDriver *bdrv_find_protocol(const char *filename)
9ae3a8
         return drv1;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    if (!path_has_protocol(filename)) {
9ae3a8
+    if (!path_has_protocol(filename) || !allow_protocol_prefix) {
9ae3a8
         return bdrv_find_format("file");
9ae3a8
     }
9ae3a8
+
9ae3a8
     p = strchr(filename, ':');
9ae3a8
     assert(p != NULL);
9ae3a8
     len = p - filename;
9ae3a8
@@ -786,6 +788,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
9ae3a8
     BlockDriverState *bs;
9ae3a8
     BlockDriver *drv;
9ae3a8
     const char *drvname;
9ae3a8
+    bool allow_protocol_prefix = false;
9ae3a8
     int ret;
9ae3a8
 
9ae3a8
     /* NULL means an empty set of options */
9ae3a8
@@ -802,6 +805,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
9ae3a8
         filename = qdict_get_try_str(options, "filename");
9ae3a8
     } else if (filename && !qdict_haskey(options, "filename")) {
9ae3a8
         qdict_put(options, "filename", qstring_from_str(filename));
9ae3a8
+        allow_protocol_prefix = true;
9ae3a8
     } else {
9ae3a8
         qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and "
9ae3a8
                       "'filename' options at the same time");
9ae3a8
@@ -815,7 +819,10 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename,
9ae3a8
         drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR));
9ae3a8
         qdict_del(options, "driver");
9ae3a8
     } else if (filename) {
9ae3a8
-        drv = bdrv_find_protocol(filename);
9ae3a8
+        drv = bdrv_find_protocol(filename, allow_protocol_prefix);
9ae3a8
+        if (!drv) {
9ae3a8
+            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol");
9ae3a8
+        }
9ae3a8
     } else {
9ae3a8
         qerror_report(ERROR_CLASS_GENERIC_ERROR,
9ae3a8
                       "Must specify either driver or file");
9ae3a8
@@ -4770,7 +4777,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
9ae3a8
         return;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    proto_drv = bdrv_find_protocol(filename);
9ae3a8
+    proto_drv = bdrv_find_protocol(filename, true);
9ae3a8
     if (!proto_drv) {
9ae3a8
         error_setg(errp, "Unknown protocol '%s'", filename);
9ae3a8
         return;
9ae3a8
diff --git a/block/sheepdog.c b/block/sheepdog.c
9ae3a8
index 21a4edf..2758c26 100644
9ae3a8
--- a/block/sheepdog.c
9ae3a8
+++ b/block/sheepdog.c
9ae3a8
@@ -1510,7 +1510,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
9ae3a8
         BlockDriver *drv;
9ae3a8
 
9ae3a8
         /* Currently, only Sheepdog backing image is supported. */
9ae3a8
-        drv = bdrv_find_protocol(backing_file);
9ae3a8
+        drv = bdrv_find_protocol(backing_file, true);
9ae3a8
         if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
9ae3a8
             error_report("backing_file must be a sheepdog image");
9ae3a8
             ret = -EINVAL;
9ae3a8
diff --git a/include/block/block.h b/include/block/block.h
9ae3a8
index db7bc4f..174295b 100644
9ae3a8
--- a/include/block/block.h
9ae3a8
+++ b/include/block/block.h
9ae3a8
@@ -122,7 +122,8 @@ bool bdrv_io_limits_enabled(BlockDriverState *bs);
9ae3a8
 
9ae3a8
 void bdrv_init(void);
9ae3a8
 void bdrv_init_with_whitelist(void);
9ae3a8
-BlockDriver *bdrv_find_protocol(const char *filename);
9ae3a8
+BlockDriver *bdrv_find_protocol(const char *filename,
9ae3a8
+                                bool allow_protocol_prefix);
9ae3a8
 BlockDriver *bdrv_find_format(const char *format_name);
9ae3a8
 BlockDriver *bdrv_find_whitelisted_format(const char *format_name,
9ae3a8
                                           bool readonly);
9ae3a8
diff --git a/qemu-img.c b/qemu-img.c
9ae3a8
index 673d80f..3b11414 100644
9ae3a8
--- a/qemu-img.c
9ae3a8
+++ b/qemu-img.c
9ae3a8
@@ -238,7 +238,7 @@ static int print_block_option_help(const char *filename, const char *fmt)
9ae3a8
         return 1;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    proto_drv = bdrv_find_protocol(filename);
9ae3a8
+    proto_drv = bdrv_find_protocol(filename, true);
9ae3a8
     if (!proto_drv) {
9ae3a8
         error_report("Unknown protocol '%s'", filename);
9ae3a8
         return 1;
9ae3a8
@@ -1261,7 +1261,7 @@ static int img_convert(int argc, char **argv)
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    proto_drv = bdrv_find_protocol(out_filename);
9ae3a8
+    proto_drv = bdrv_find_protocol(out_filename, true);
9ae3a8
     if (!proto_drv) {
9ae3a8
         error_report("Unknown protocol '%s'", out_filename);
9ae3a8
         ret = -1;
9ae3a8
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
9ae3a8
index 8039e23..1cf8bf7 100755
9ae3a8
--- a/tests/qemu-iotests/051
9ae3a8
+++ b/tests/qemu-iotests/051
9ae3a8
@@ -149,6 +149,18 @@ echo
9ae3a8
 run_qemu -drive file=$TEST_IMG,file.driver=file
9ae3a8
 run_qemu -drive file=$TEST_IMG,file.driver=qcow2
9ae3a8
 
9ae3a8
+echo
9ae3a8
+echo === Parsing protocol from file name ===
9ae3a8
+echo
9ae3a8
+
9ae3a8
+# Protocol strings are supposed to be parsed from traditional option strings,
9ae3a8
+# but not when using driver-specific options. We can distinguish them by the
9ae3a8
+# error message for non-existing files.
9ae3a8
+
9ae3a8
+run_qemu -hda foo:bar
9ae3a8
+run_qemu -drive file=foo:bar
9ae3a8
+run_qemu -drive file.filename=foo:bar
9ae3a8
+
9ae3a8
 # success, all done
9ae3a8
 echo "*** done"
9ae3a8
 rm -f $seq.full
9ae3a8
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
9ae3a8
index 3d1ac7b..6b3d636 100644
9ae3a8
--- a/tests/qemu-iotests/051.out
9ae3a8
+++ b/tests/qemu-iotests/051.out
9ae3a8
@@ -169,4 +169,18 @@ Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2
9ae3a8
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Can't use 'qcow2' as a block driver for the protocol level
9ae3a8
 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Invalid argument
9ae3a8
 
9ae3a8
+
9ae3a8
+=== Parsing protocol from file name ===
9ae3a8
+
9ae3a8
+Testing: -hda foo:bar
9ae3a8
+QEMU_PROG: -hda foo:bar: Unknown protocol
9ae3a8
+QEMU_PROG: -hda foo:bar: could not open disk image foo:bar: No such file or directory
9ae3a8
+
9ae3a8
+Testing: -drive file=foo:bar
9ae3a8
+QEMU_PROG: -drive file=foo:bar: Unknown protocol
9ae3a8
+QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: No such file or directory
9ae3a8
+
9ae3a8
+Testing: -drive file.filename=foo:bar
9ae3a8
+QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: No such file or directory
9ae3a8
+
9ae3a8
 *** done
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8