Re: [PATCH] support colon in filenames

Ram Pai
2009-06-24T17:57:13Z

Copying the qemu-devel mailing list too.

On Wed, 2009-06-24 at 09:58 -0700, Ram Pai wrote:
> 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@us.ibm.com>
> -----------------------------------------------------------------------
>
>
> 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@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html