From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LKzPm-0007OA-TR for qemu-devel@nongnu.org; Thu, 08 Jan 2009 13:15:30 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LKzPm-0007Ny-6W for qemu-devel@nongnu.org; Thu, 08 Jan 2009 13:15:30 -0500 Received: from [199.232.76.173] (port=54929 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LKzPl-0007Nt-OB for qemu-devel@nongnu.org; Thu, 08 Jan 2009 13:15:29 -0500 Received: from mx2.redhat.com ([66.187.237.31]:58020) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LKzPl-0003rT-7M for qemu-devel@nongnu.org; Thu, 08 Jan 2009 13:15:29 -0500 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n08IFS0M002857 for ; Thu, 8 Jan 2009 13:15:28 -0500 Message-ID: <496642BD.4010706@redhat.com> Date: Thu, 08 Jan 2009 20:15:25 +0200 From: Uri Lublin MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] qemu: block.c: introducing "fmt:FMT:" prefix to image-filenames Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, Uri Lublin From: Uri Lublin Changes from my last post: * rebase for qemu. * if find_image_format() returns NULL set "raw" drv instead of returning with error. This fixes breakage of '-cdrom isofile' The purpose of this prefix is to 1. Provide a way to know the backing file format without probing it (setting the format upon creation time). 2. Enable using qcow2 format (and others) over host block devices. (only if the user specifically asks for it). If no fmt:FMT: is provided we go back to probing. Based on a similar patch from Shahar Frank. http://lists.gnu.org/archive/html/qemu-devel/2008-12/msg01083.html Also fixes a security flaw found by Daniel P. Berrange on the above thread which summarizes: "Autoprobing: just say no." Examples: backing file format is qcow2 (even though it's on a host block device) $ qemu-img create -b fmt:qcow2:/dev/loop0 -f qcow2 /tmp/uuu.qcow2 force backing file format to raw (no probing) $ qemu-img create -f raw /tmp/image1.raw 10G $ qemu-img create -b fmt:raw:/tmp/image1.raw -f qcow2 /tmp/image1.qcow2 Use together with other protocols, e.g. nbd $ qemu-nbd -v -n --snapshot -t -k /tmp/uuu.socket fmt:qcow2:/tmp/images/uuu.qcow2 & $ qemu-img info nbd:unix:/tmp/uuu.socket $ qemu-system-x86_64 -snapshot -hda nbd:unix:/tmp/uuu.socket Or fat $ qemu-system-x86_64 -hda fmt:qcow2:/tmp/uuu.qcow2 -hdb fat:floppy:/tmp/images Signed-off-by: Uri Lublin --- block.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 61 insertions(+), 13 deletions(-) diff --git a/block.c b/block.c index 28d63d7..82959d6 100644 --- a/block.c +++ b/block.c @@ -71,7 +71,7 @@ int path_is_absolute(const char *path) if (*path == '/' || *path == '\\') return 1; #endif - p = strchr(path, ':'); + p = strrchr(path, ':'); if (p) p++; else @@ -95,10 +95,23 @@ void path_combine(char *dest, int dest_size, if (dest_size <= 0) return; + + /* copy "fmt:" prefix of filename if exists */ + p = strrchr(filename, ':'); + if (p) { + len = p - filename + 1; + if (dest_size <= len) + return; + strncpy(dest, filename, len); + filename += len; + dest += len; + dest_size -= len; + } + if (path_is_absolute(filename)) { pstrcpy(dest, dest_size, filename); } else { - p = strchr(base_path, ':'); + p = strrchr(base_path, ':'); if (p) p++; else @@ -226,30 +239,51 @@ static int is_windows_drive(const char *filename) } #endif +static const char *raw_filename(const char *filename) +{ + char *_filename; + + _filename = strrchr(filename, ':'); + if (_filename) + return _filename + 1; + else + return filename; +} + static BlockDriver *find_protocol(const char *filename) { BlockDriver *drv1; char protocol[128]; - int len; + int len, is_fmt = 0; const char *p; + if (!strncmp(filename, "fmt:", 4)) { + filename += 4; + is_fmt = 1; + } + #ifdef _WIN32 if (is_windows_drive(filename) || is_windows_drive_prefix(filename)) - return &bdrv_raw; + return NULL; #endif p = strchr(filename, ':'); if (!p) - return &bdrv_raw; + return NULL; 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)) - return drv1; + if (is_fmt) { + if (!strcmp(drv1->format_name, protocol)) + return drv1; + } else { + if (drv1->protocol_name && + !strcmp(drv1->protocol_name, protocol)) + return drv1; + } } return NULL; } @@ -267,6 +301,14 @@ static BlockDriver *find_image_format(const char *filename) recognized as a host CDROM */ if (strstart(filename, "/dev/cdrom", NULL)) return &bdrv_host_device; + + drv = find_protocol(filename); + if ((drv != NULL) && (drv->protocol_name == NULL)) + return drv; + + if (drv == NULL) + filename = raw_filename(filename); + #ifdef _WIN32 if (is_windows_drive(filename)) return &bdrv_host_device; @@ -280,7 +322,6 @@ static BlockDriver *find_image_format(const char *filename) } #endif - drv = find_protocol(filename); /* no need to test disk image formats for vvfat */ if (drv == &bdrv_vvfat) return drv; @@ -370,8 +411,11 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, if (is_protocol) snprintf(backing_filename, sizeof(backing_filename), "%s", filename); - else - realpath(filename, backing_filename); + else { + const char *p; + p = realpath(raw_filename(filename), backing_filename); + path_combine(backing_filename, sizeof(backing_filename), p, filename); + } if (bdrv_create(&bdrv_qcow2, tmp_filename, total_size, backing_filename, 0) < 0) { @@ -385,12 +429,12 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, if (flags & BDRV_O_FILE) { drv = find_protocol(filename); if (!drv) - return -ENOENT; + drv = &bdrv_raw; } else { if (!drv) { drv = find_image_format(filename); if (!drv) - return -1; + drv = &bdrv_raw; } } bs->drv = drv; @@ -403,6 +447,10 @@ 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); + + if (drv && !drv->protocol_name) + filename = raw_filename(filename); + ret = drv->bdrv_open(bs, filename, open_flags); if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) { ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR); -- 1.6.0.6