-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
>From bc09a7473b0382fbac7c3702b668acc1b04f1e9c Mon Sep 17 00:00:00 2001
From: Richard Jones <rjo...@redhat.com>
Date: Fri, 18 Dec 2009 15:36:17 +0000
Subject: [PATCH 2/2] VMDK4: Parse and check the createType (VMDK file type) 
field.

Currently qemu fails to read VMDK subformats such as streamOptimized.
It silently corrupts these files when it reads them.

>From the embedded descriptor, parse the createType field and check it
against a short list of subformats which are likely to work.
---
 block/vmdk.c |   21 +++++++++++++++++++++
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/block/vmdk.c b/block/vmdk.c
index 71680f0..c0b3160 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -81,6 +81,7 @@ typedef struct BDRVVmdkState {
     /* VMDK4 fields */
     int64_t cid_offset;
     int64_t parent_cid_offset;
+    char *create_type;
 } BDRVVmdkState;
 
 typedef struct VmdkMetaData {
@@ -161,6 +162,13 @@ static int vmdk4_parse_desc_assignment(BlockDriverState 
*bs,
     if (!strncmp(p, "parentCID=", 10))
         s->parent_cid_offset = file_offset + 10;
 
+    if (strncmp(p, "createType=\"", 12) == 0) {
+        p[len-1] = '\0';        /* Remove trailing double quote. */
+        if (s->create_type)
+            qemu_free(s->create_type);
+        s->create_type = qemu_strdup(p+12);
+    }
+
     return 0;
 }
 
@@ -174,6 +182,7 @@ static int vmdk4_parse_desc(BlockDriverState *bs, 
VMDK4Header *header)
 
     s->cid_offset = 0;
     s->parent_cid_offset = 0;
+    s->create_type = NULL;
 
     /* Stored in the header are the offset/size in sectors. */
     desc_size = le64_to_cpu(header->desc_size) * SECTOR_SIZE;
@@ -521,6 +530,16 @@ static int vmdk_open(BlockDriverState *bs, const char 
*filename, int flags)
         if (vmdk4_parse_desc(bs, &header) == -1)
             goto fail;
 
+        if (s->create_type &&
+            !(!strcmp(s->create_type, "monolithicSparse") ||
+              !strcmp(s->create_type, "monolithicFlat") ||
+              !strcmp(s->create_type, "twoGbMaxExtentSparse") ||
+              !strcmp(s->create_type, "twoGbMaxExtentFlat"))) {
+            fprintf (stderr, "vmdk: disk type '%s' is not supported by qemu\n",
+                     s->create_type);
+            goto fail;
+        }
+
         if (parent_open)
             s->is_parent = 1;
         else
@@ -559,6 +578,7 @@ static int vmdk_open(BlockDriverState *bs, const char 
*filename, int flags)
     qemu_free(s->l1_backup_table);
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
+    qemu_free(s->create_type);
     bdrv_delete(s->hd);
     return -1;
 }
@@ -927,6 +947,7 @@ static void vmdk_close(BlockDriverState *bs)
 
     qemu_free(s->l1_table);
     qemu_free(s->l2_cache);
+    qemu_free(s->create_type);
     // try to close parent image, if exist
     vmdk_parent_close(s->hd);
     bdrv_delete(s->hd);
-- 
1.6.5.2

Reply via email to