Problem: It is impossible to feed filenames with the character colon because qemu interprets such names as a protocol. For example a filename scsi:0, is interpreted as a protocol by name "scsi". This patch allows users to espace colon characters. For example the above filename can now be expressed as 'scsi\:0' Here are couple of examples: ndb:\::9999 is treated as a ndb protocol with a hostname ':' on port 9999 scsi\:0\:abc is a local file scsi:0:abc http\://myweb is a local file by name http://myweb nbd\::localhost:2558 is a protocol by name nbd: Signed-off-by: Ram Pai <linuxram@xxxxxxxxxx> ----------------------------------------------------------------------- block.c | 26 +++++++++++++++++--------- block/nbd.c | 19 ++++++++++++++----- block/raw-posix.c | 24 +++++++++++++++++------- cutils.c | 22 ++++++++++++++++++++++ qemu-common.h | 1 + vl.c | 3 +-- 6 files changed, 72 insertions(+), 23 deletions(-) diff --git a/block.c b/block.c index aca5a6d..80bded9 100644 --- a/block.c +++ b/block.c @@ -225,22 +225,30 @@ static BlockDriver *find_protocol(const char *filename) { BlockDriver *drv1; char protocol[128]; - int len; - const char *p; + char *p = protocol; + const char *f=filename; + int len = strnlen(filename, 128); #ifdef _WIN32 if (is_windows_drive(filename) || is_windows_drive_prefix(filename)) return bdrv_find_format("raw"); #endif - p = strchr(filename, ':'); - if (!p) + while ( f < filename+len ) { + if ( *f == ':' ) + break; + if ( *f == '\\') { + f++; + if ( *f == '\0') + break; + } + *p++ = *f++; + } + *p='\0'; + + if (*f != ':') 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)) diff --git a/block/nbd.c b/block/nbd.c index 47d4778..a011cc7 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -64,18 +64,27 @@ static int nbd_open(BlockDriverState *bs, const char* filename, int flags) } else { uint16_t port; - char *p, *r; + char *q, *p, *r; char hostname[128]; pstrcpy(hostname, 128, host); - p = strchr(hostname, ':'); - if (p == NULL) + q=p=hostname; + while ( p < hostname+128 ) { + if (*p == ':') + break; + if ( *p == '\\' ) { + p++; + if (*p =='\0') + break; + } + *q++=*p++; + } + if (*p != ':') return -EINVAL; - *p = '\0'; + *q='\0'; p++; - port = strtol(p, &r, 0); if (r == p) return -EINVAL; diff --git a/block/raw-posix.c b/block/raw-posix.c index 41bfa37..98ede17 100644 --- a/block/raw-posix.c +++ b/block/raw-posix.c @@ -124,6 +124,16 @@ static int fd_open(BlockDriverState *bs); static int cdrom_reopen(BlockDriverState *bs); #endif +static int _open(const char *filename, int flags, ...) +{ + char myfile[PATH_MAX]; + va_list ap; + va_start(ap, flags); + return open(esc_string(myfile, PATH_MAX, filename), + flags, ap); +} + + static int raw_open_common(BlockDriverState *bs, const char *filename, int flags) { @@ -151,7 +161,7 @@ static int raw_open_common(BlockDriverState *bs, const char *filename, s->open_flags |= O_DSYNC; s->fd = -1; - fd = open(filename, s->open_flags, 0644); + fd = _open(filename, s->open_flags, 0644); if (fd < 0) { ret = -errno; if (ret == -EROFS) @@ -844,7 +854,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options) options++; } - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, + fd = _open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (fd < 0) return -EIO; @@ -985,7 +995,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) if ( bsdPath[ 0 ] != '\0' ) { strcat(bsdPath,"s0"); /* some CDs don't have a partition 0 */ - fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); + fd = _open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) { bsdPath[strlen(bsdPath)-1] = '1'; } else { @@ -1037,7 +1047,7 @@ static int fd_open(BlockDriverState *bs) #endif return -EIO; } - s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK); + s->fd = _open(bs->filename, s->open_flags & ~O_NONBLOCK); if (s->fd < 0) { s->fd_error_time = qemu_get_clock(rt_clock); s->fd_got_error = 1; @@ -1133,7 +1143,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options) options++; } - fd = open(filename, O_WRONLY | O_BINARY); + fd = _open(filename, O_WRONLY | O_BINARY); if (fd < 0) return -EIO; @@ -1239,7 +1249,7 @@ static int floppy_eject(BlockDriverState *bs, int eject_flag) close(s->fd); s->fd = -1; } - fd = open(bs->filename, s->open_flags | O_NONBLOCK); + fd = _open(bs->filename, s->open_flags | O_NONBLOCK); if (fd >= 0) { if (ioctl(fd, FDEJECT, 0) < 0) perror("FDEJECT"); @@ -1399,7 +1409,7 @@ static int cdrom_reopen(BlockDriverState *bs) */ if (s->fd >= 0) close(s->fd); - fd = open(bs->filename, s->open_flags, 0644); + fd = _open(bs->filename, s->open_flags, 0644); if (fd < 0) { s->fd = -1; return -EIO; diff --git a/cutils.c b/cutils.c index 6ea0c49..63c196d 100644 --- a/cutils.c +++ b/cutils.c @@ -24,6 +24,28 @@ #include "qemu-common.h" #include "host-utils.h" +/* + * prune escape character '\' + */ +char *esc_string(char *buf, int buf_size, const char *str) +{ + const char *p=str; + int len = strlen(str); + char *q=buf; + + len = (buf_size < len) ? buf_size: len; + while (p < str+len) { + if (*p == '\\') { + p++; + if (*p == '\0') + break; + } + *q++ = *p++; + } + *q='\0'; + return buf; +} + void pstrcpy(char *buf, int buf_size, const char *str) { int c; diff --git a/qemu-common.h b/qemu-common.h index 2dcb224..1e510dc 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 */ +char *esc_string(char *buf, int buf_size, const char *str); 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); diff --git a/vl.c b/vl.c index 7278999..5d7b024 100644 --- a/vl.c +++ b/vl.c @@ -2583,8 +2583,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void *opaque) else if (cache == 3) /* not specified */ bdrv_flags |= BDRV_O_CACHE_DEF; if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) { - fprintf(stderr, "qemu: could not open disk image %s\n", - file); + fprintf(stderr, "qemu: could not open disk image %s\n", file); return -1; } if (bdrv_key_required(bdrv)) -- 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