aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRam Pai <linuxram@us.ibm.com>2009-06-26 17:41:50 -0700
committerAnthony Liguori <aliguori@us.ibm.com>2009-06-29 13:50:05 -0500
commit707c0dbc97cddfe8d2441b8259c6c526d99f2dd8 (patch)
treeb577fac92b2f94e300f1ce73804febecb615fdc8
parentab4e5602a88402fdf7109e5093cace35a7471699 (diff)
support colon in filenames
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 Signed-off-by: Ram Pai <linuxram@us.ibm.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
-rw-r--r--block.c27
-rw-r--r--block.h2
-rw-r--r--block/dmg.c2
-rw-r--r--block/raw-posix.c1
-rw-r--r--cutils.c26
-rw-r--r--qemu-common.h1
6 files changed, 48 insertions, 11 deletions
diff --git a/block.c b/block.c
index aca5a6d282..3fe9317023 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 71e87fc9e1..b595772c3c 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 262560ffd3..dd98af4376 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 fa1a39462a..31b68ff813 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 0623cf70da..73d4e1fbbd 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 fdc367997d..5b8ac77f09 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);