rev2 [PATCH] support colon in filenames

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Problem: It is impossible to feed filenames with the character colon because
qemu interprets such names as a protocol. For example filename scsi:0, is
interpreted as a protocol by name "scsi".

This patch allows user to espace colon characters. For example the above
filename can now be expressed either as 'scsi\:0' or as file:scsi:0

anything following the "file:" tag is interpreted verbatin. However if "file:"
tag is omitted then any colon characters in the string must be escaped using
backslash.

Here are couple of examples:

scsi\:0\:abc is a local file scsi:0:abc
http\://myweb is a local file by name http://myweb
file:scsi:0:abc is a local file scsi:0:abc
file:http://myweb is a local file by name http://myweb

Changelog w.r.t to iteration 0:
   1) removes flexibility added to nbd semantics  eg -- nbd:\::9999
   2) introduce the file: protocol to indicate local file

Changelog w.r.t to iteration 1:
   1) generically handles 'file:' protocol in find_protocol
   2) centralizes 'filename' pruning before the call to open().
   3) fixes buffer overflow seen in fill_token()
   4) adheres to codying style
   5) patch against upstream qemu tree
 
Signed-off-by: Ram Pai <linuxram@xxxxxxxxxx>
-----------------------------------------------------------------------

 block.c           |   27 +++++++++++++++++----------
 block.h           |    2 ++
 block/dmg.c       |    2 +-
 block/raw-posix.c |    1 +
 cutils.c          |   26 ++++++++++++++++++++++++++
 qemu-common.h     |    1 +
 6 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/block.c b/block.c
index aca5a6d..3fe9317 100644
--- a/block.c
+++ b/block.c
@@ -225,7 +225,7 @@ static BlockDriver *find_protocol(const char *filename)
 {
     BlockDriver *drv1;
     char protocol[128];
-    int len;
+    int len = strnlen(filename, 127)+1;
     const char *p;
 
 #ifdef _WIN32
@@ -233,14 +233,9 @@ static BlockDriver *find_protocol(const char *filename)
         is_windows_drive_prefix(filename))
         return bdrv_find_format("raw");
 #endif
-    p = strchr(filename, ':');
-    if (!p)
+    p = fill_token(protocol, len, filename, ':');
+    if (*p != ':')
         return bdrv_find_format("raw");
-    len = p - filename;
-    if (len > sizeof(protocol) - 1)
-        len = sizeof(protocol) - 1;
-    memcpy(protocol, filename, len);
-    protocol[len] = '\0';
     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
         if (drv1->protocol_name &&
             !strcmp(drv1->protocol_name, protocol))
@@ -414,9 +409,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
         open_flags = BDRV_O_RDWR | (flags & BDRV_O_CACHE_MASK);
     else
         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
-    ret = drv->bdrv_open(bs, filename, open_flags);
+    ret = bdrv_open3(bs, filename, open_flags, drv);
     if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
-        ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
+        ret = bdrv_open3(bs, filename, open_flags & ~BDRV_O_RDWR, drv);
         bs->read_only = 1;
     }
     if (ret < 0) {
@@ -461,6 +456,18 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
     return 0;
 }
 
+int bdrv_open3(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv)
+{
+    char myfile[PATH_MAX];
+    const char *f;
+
+    if (!strstart(filename, "file:", &f)) {
+        fill_token(myfile, PATH_MAX, filename, '\0');
+        return drv->bdrv_open(bs,myfile,flags);
+    }
+    return drv->bdrv_open(bs,f,flags);
+}
+
 void bdrv_close(BlockDriverState *bs)
 {
     if (bs->drv) {
diff --git a/block.h b/block.h
index 71e87fc..b595772 100644
--- a/block.h
+++ b/block.h
@@ -58,6 +58,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
 int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
 int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
                BlockDriver *drv);
+int bdrv_open3(BlockDriverState *bs, const char *filename, int flags,
+               BlockDriver *drv);
 void bdrv_close(BlockDriverState *bs);
 int bdrv_check(BlockDriverState *bs);
 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
diff --git a/block/dmg.c b/block/dmg.c
index 262560f..dd98af4 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -94,7 +94,7 @@ dmg_close:
 	close(s->fd);
 	/* open raw instead */
 	bs->drv=bdrv_find_format("raw");
-	return bs->drv->bdrv_open(bs, filename, flags);
+	return bdrv_open3(bs, filename, flags, bs->drv);
     }
     info_begin=read_off(s->fd);
     if(info_begin==0)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index fa1a394..31b68ff 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -892,6 +892,7 @@ static BlockDriver bdrv_raw = {
     .bdrv_getlength = raw_getlength,
 
     .create_options = raw_create_options,
+    .protocol_name = "file",
 };
 
 /***********************************************/
diff --git a/cutils.c b/cutils.c
index 0623cf7..73d4e1f 100644
--- a/cutils.c
+++ b/cutils.c
@@ -24,6 +24,32 @@
 #include "qemu-common.h"
 #include "host-utils.h"
 
+/*
+ * fill first 'len' characters of 'buff' with pruned
+ * contents of 'str' delimited by the character 'c'.
+ * Escape character '\' is pruned off.
+ * Return pointer to the delimiting character.
+ */
+const char *fill_token(char *buf, const int len, const char *str, const char c)
+{
+    const char *p=str;
+    char *q=buf;
+
+    while (p < str+len-1) {
+    if (*p == c)
+        break;
+        if (*p == '\\') {
+            p++;
+            if (*p == '\0')
+                break;
+        }
+        *q++ = *p++;
+    }
+    *q='\0';
+    return p;
+}
+
+
 void pstrcpy(char *buf, int buf_size, const char *str)
 {
     int c;
diff --git a/qemu-common.h b/qemu-common.h
index fdc3679..5b8ac77 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -104,6 +104,7 @@ void qemu_get_timedate(struct tm *tm, int offset);
 int qemu_timedate_diff(struct tm *tm);
 
 /* cutils.c */
+const char *fill_token(char *buf, int buf_size, const char *str, char);
 void pstrcpy(char *buf, int buf_size, const char *str);
 char *pstrcat(char *buf, int buf_size, const char *s);
 int strstart(const char *str, const char *val, const char **ptr);


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux