Commit 707c0dbc97cddfe8d2441b8259c6c526d99f2dd8

Authored by Ram Pai
Committed by Anthony Liguori
1 parent ab4e5602

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>
@@ -225,7 +225,7 @@ static BlockDriver *find_protocol(const char *filename) @@ -225,7 +225,7 @@ static BlockDriver *find_protocol(const char *filename)
225 { 225 {
226 BlockDriver *drv1; 226 BlockDriver *drv1;
227 char protocol[128]; 227 char protocol[128];
228 - int len; 228 + int len = strnlen(filename, 127)+1;
229 const char *p; 229 const char *p;
230 230
231 #ifdef _WIN32 231 #ifdef _WIN32
@@ -233,14 +233,9 @@ static BlockDriver *find_protocol(const char *filename) @@ -233,14 +233,9 @@ static BlockDriver *find_protocol(const char *filename)
233 is_windows_drive_prefix(filename)) 233 is_windows_drive_prefix(filename))
234 return bdrv_find_format("raw"); 234 return bdrv_find_format("raw");
235 #endif 235 #endif
236 - p = strchr(filename, ':');  
237 - if (!p) 236 + p = fill_token(protocol, len, filename, ':');
  237 + if (*p != ':')
238 return bdrv_find_format("raw"); 238 return bdrv_find_format("raw");
239 - len = p - filename;  
240 - if (len > sizeof(protocol) - 1)  
241 - len = sizeof(protocol) - 1;  
242 - memcpy(protocol, filename, len);  
243 - protocol[len] = '\0';  
244 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { 239 for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
245 if (drv1->protocol_name && 240 if (drv1->protocol_name &&
246 !strcmp(drv1->protocol_name, protocol)) 241 !strcmp(drv1->protocol_name, protocol))
@@ -414,9 +409,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, @@ -414,9 +409,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
414 open_flags = BDRV_O_RDWR | (flags & BDRV_O_CACHE_MASK); 409 open_flags = BDRV_O_RDWR | (flags & BDRV_O_CACHE_MASK);
415 else 410 else
416 open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT); 411 open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
417 - ret = drv->bdrv_open(bs, filename, open_flags); 412 + ret = bdrv_open3(bs, filename, open_flags, drv);
418 if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) { 413 if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
419 - ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR); 414 + ret = bdrv_open3(bs, filename, open_flags & ~BDRV_O_RDWR, drv);
420 bs->read_only = 1; 415 bs->read_only = 1;
421 } 416 }
422 if (ret < 0) { 417 if (ret < 0) {
@@ -461,6 +456,18 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, @@ -461,6 +456,18 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
461 return 0; 456 return 0;
462 } 457 }
463 458
  459 +int bdrv_open3(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv)
  460 +{
  461 + char myfile[PATH_MAX];
  462 + const char *f;
  463 +
  464 + if (!strstart(filename, "file:", &f)) {
  465 + fill_token(myfile, PATH_MAX, filename, '\0');
  466 + return drv->bdrv_open(bs,myfile,flags);
  467 + }
  468 + return drv->bdrv_open(bs,f,flags);
  469 +}
  470 +
464 void bdrv_close(BlockDriverState *bs) 471 void bdrv_close(BlockDriverState *bs)
465 { 472 {
466 if (bs->drv) { 473 if (bs->drv) {
@@ -58,6 +58,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags); @@ -58,6 +58,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
58 int bdrv_open(BlockDriverState *bs, const char *filename, int flags); 58 int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
59 int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, 59 int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
60 BlockDriver *drv); 60 BlockDriver *drv);
  61 +int bdrv_open3(BlockDriverState *bs, const char *filename, int flags,
  62 + BlockDriver *drv);
61 void bdrv_close(BlockDriverState *bs); 63 void bdrv_close(BlockDriverState *bs);
62 int bdrv_check(BlockDriverState *bs); 64 int bdrv_check(BlockDriverState *bs);
63 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 65 int bdrv_read(BlockDriverState *bs, int64_t sector_num,
block/dmg.c
@@ -94,7 +94,7 @@ dmg_close: @@ -94,7 +94,7 @@ dmg_close:
94 close(s->fd); 94 close(s->fd);
95 /* open raw instead */ 95 /* open raw instead */
96 bs->drv=bdrv_find_format("raw"); 96 bs->drv=bdrv_find_format("raw");
97 - return bs->drv->bdrv_open(bs, filename, flags); 97 + return bdrv_open3(bs, filename, flags, bs->drv);
98 } 98 }
99 info_begin=read_off(s->fd); 99 info_begin=read_off(s->fd);
100 if(info_begin==0) 100 if(info_begin==0)
block/raw-posix.c
@@ -892,6 +892,7 @@ static BlockDriver bdrv_raw = { @@ -892,6 +892,7 @@ static BlockDriver bdrv_raw = {
892 .bdrv_getlength = raw_getlength, 892 .bdrv_getlength = raw_getlength,
893 893
894 .create_options = raw_create_options, 894 .create_options = raw_create_options,
  895 + .protocol_name = "file",
895 }; 896 };
896 897
897 /***********************************************/ 898 /***********************************************/
cutils.c
@@ -24,6 +24,32 @@ @@ -24,6 +24,32 @@
24 #include "qemu-common.h" 24 #include "qemu-common.h"
25 #include "host-utils.h" 25 #include "host-utils.h"
26 26
  27 +/*
  28 + * fill first 'len' characters of 'buff' with pruned
  29 + * contents of 'str' delimited by the character 'c'.
  30 + * Escape character '\' is pruned off.
  31 + * Return pointer to the delimiting character.
  32 + */
  33 +const char *fill_token(char *buf, const int len, const char *str, const char c)
  34 +{
  35 + const char *p=str;
  36 + char *q=buf;
  37 +
  38 + while (p < str+len-1) {
  39 + if (*p == c)
  40 + break;
  41 + if (*p == '\\') {
  42 + p++;
  43 + if (*p == '\0')
  44 + break;
  45 + }
  46 + *q++ = *p++;
  47 + }
  48 + *q='\0';
  49 + return p;
  50 +}
  51 +
  52 +
27 void pstrcpy(char *buf, int buf_size, const char *str) 53 void pstrcpy(char *buf, int buf_size, const char *str)
28 { 54 {
29 int c; 55 int c;
qemu-common.h
@@ -104,6 +104,7 @@ void qemu_get_timedate(struct tm *tm, int offset); @@ -104,6 +104,7 @@ void qemu_get_timedate(struct tm *tm, int offset);
104 int qemu_timedate_diff(struct tm *tm); 104 int qemu_timedate_diff(struct tm *tm);
105 105
106 /* cutils.c */ 106 /* cutils.c */
  107 +const char *fill_token(char *buf, int buf_size, const char *str, char);
107 void pstrcpy(char *buf, int buf_size, const char *str); 108 void pstrcpy(char *buf, int buf_size, const char *str);
108 char *pstrcat(char *buf, int buf_size, const char *s); 109 char *pstrcat(char *buf, int buf_size, const char *s);
109 int strstart(const char *str, const char *val, const char **ptr); 110 int strstart(const char *str, const char *val, const char **ptr);