diff options
author | Fam Zheng <famcool@gmail.com> | 2011-08-12 23:19:33 +0800 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2011-09-06 12:33:03 +0200 |
commit | f16f509d17de295300404f94598b558ac5b8cfdd (patch) | |
tree | ba33fa9d48417cbb80d022b5ba2d8b5192b85f73 /block/vmdk.c | |
parent | 6c031aac4d697d7acbfd5eaa73f47d494cee9937 (diff) | |
download | qemu-f16f509d17de295300404f94598b558ac5b8cfdd.zip qemu-f16f509d17de295300404f94598b558ac5b8cfdd.tar.gz qemu-f16f509d17de295300404f94598b558ac5b8cfdd.tar.bz2 |
VMDK: bugfix, open Haiku vmdk image
Haiku provides a specially formed vmdk image, which let qemu abort. It a
combination of sparse header and flat data (i.e. with not l1/l2 table at
all). The fix is turn to descriptor when sparse header is zero in field
'capacity'.
Signed-off-by: Fam Zheng <famcool@gmail.com>
Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'block/vmdk.c')
-rw-r--r-- | block/vmdk.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/block/vmdk.c b/block/vmdk.c index 54f7441..892b18e 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -408,6 +408,9 @@ static int vmdk_open_vmdk3(BlockDriverState *bs, return ret; } +static int vmdk_open_desc_file(BlockDriverState *bs, int flags, + int64_t desc_offset); + static int vmdk_open_vmdk4(BlockDriverState *bs, BlockDriverState *file, int flags) @@ -422,6 +425,9 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, if (ret < 0) { return ret; } + if (header.capacity == 0 && header.desc_offset) { + return vmdk_open_desc_file(bs, flags, header.desc_offset << 9); + } l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte) * le64_to_cpu(header.granularity); if (l1_entry_sectors <= 0) { @@ -559,7 +565,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, extent = vmdk_add_extent(bs, extent_file, true, sectors, 0, 0, 0, 0, sectors); - extent->flat_start_offset = flat_offset; + extent->flat_start_offset = flat_offset << 9; } else if (!strcmp(type, "SPARSE")) { /* SPARSE extent */ ret = vmdk_open_sparse(bs, extent_file, bs->open_flags); @@ -582,14 +588,15 @@ next_line: return 0; } -static int vmdk_open_desc_file(BlockDriverState *bs, int flags) +static int vmdk_open_desc_file(BlockDriverState *bs, int flags, + int64_t desc_offset) { int ret; char buf[2048]; char ct[128]; BDRVVmdkState *s = bs->opaque; - ret = bdrv_pread(bs->file, 0, buf, sizeof(buf)); + ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf)); if (ret < 0) { return ret; } @@ -635,7 +642,7 @@ static int vmdk_open(BlockDriverState *bs, int flags) s->parent_cid = vmdk_read_cid(bs, 1); return 0; } else { - return vmdk_open_desc_file(bs, flags); + return vmdk_open_desc_file(bs, flags, 0); } } |