Commit 707c0dbc97cddfe8d2441b8259c6c526d99f2dd8
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>
Showing
6 changed files
with
48 additions
and
11 deletions
block.c
| @@ -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) { |
block.h
| @@ -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); |