From patchwork Sat Jun 27 00:41:50 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ram Pai X-Patchwork-Id: 32645 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n5R0g28V021119 for ; Sat, 27 Jun 2009 00:42:02 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753947AbZF0Alz (ORCPT ); Fri, 26 Jun 2009 20:41:55 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753930AbZF0Alz (ORCPT ); Fri, 26 Jun 2009 20:41:55 -0400 Received: from e37.co.us.ibm.com ([32.97.110.158]:41826 "EHLO e37.co.us.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753872AbZF0Aly (ORCPT ); Fri, 26 Jun 2009 20:41:54 -0400 Received: from d03relay02.boulder.ibm.com (d03relay02.boulder.ibm.com [9.17.195.227]) by e37.co.us.ibm.com (8.13.1/8.13.1) with ESMTP id n5R0fErV018515 for ; Fri, 26 Jun 2009 18:41:14 -0600 Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by d03relay02.boulder.ibm.com (8.13.8/8.13.8/NCO v9.2) with ESMTP id n5R0fv6Q156210 for ; Fri, 26 Jun 2009 18:41:57 -0600 Received: from d03av02.boulder.ibm.com (loopback [127.0.0.1]) by d03av02.boulder.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n5R0fr1P024857 for ; Fri, 26 Jun 2009 18:41:56 -0600 Received: from [9.65.27.211] (sig-9-65-27-211.mts.ibm.com [9.65.27.211]) by d03av02.boulder.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n5R0fqsK024821; Fri, 26 Jun 2009 18:41:52 -0600 Subject: rev2 [PATCH] support colon in filenames From: Ram Pai Reply-To: linuxram@us.ibm.com To: Kevin Wolf Cc: kvm-devel , qemu-devel@nongnu.org, Anthony Liguori In-Reply-To: <4A447C8D.5000104@kevin-wolf.de> References: <1245862739.6278.7.camel@localhost> <1245866233.6278.17.camel@localhost> <4A434009.5010009@redhat.com> <1245998284.6278.99.camel@localhost> <4A447C8D.5000104@kevin-wolf.de> Organization: IBM Corporation Date: Fri, 26 Jun 2009 17:41:50 -0700 Message-Id: <1246063310.6278.115.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.24.3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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 Changelog w.r.t to iteration 0: 1) removes flexibility added to nbd semantics eg -- nbd:\::9999 2) introduce the file: protocol to indicate local file Changelog w.r.t to iteration 1: 1) generically handles 'file:' protocol in find_protocol 2) centralizes 'filename' pruning before the call to open(). 3) fixes buffer overflow seen in fill_token() 4) adheres to codying style 5) patch against upstream qemu tree Signed-off-by: Ram Pai ----------------------------------------------------------------------- block.c | 27 +++++++++++++++++---------- block.h | 2 ++ block/dmg.c | 2 +- block/raw-posix.c | 1 + cutils.c | 26 ++++++++++++++++++++++++++ qemu-common.h | 1 + 6 files changed, 48 insertions(+), 11 deletions(-) --- 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 diff --git a/block.c b/block.c index aca5a6d..3fe9317 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 71e87fc..b595772 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 262560f..dd98af4 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 fa1a394..31b68ff 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 0623cf7..73d4e1f 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 fdc3679..5b8ac77 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);