There are several occurrence of magic number 0x200 as the descriptor offset within mono sparse image file. This is not the case for images with separate descriptor file. So a field is added to BDRVVmdkState to hold the correct value.
Signed-off-by: Fam Zheng <famc...@gmail.com> --- block/vmdk.c | 26 ++++++++++++++++---------- 1 files changed, 16 insertions(+), 10 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 81c1054..c3f0ab6 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -81,6 +81,7 @@ typedef struct VmdkExtent { } VmdkExtent; typedef struct BDRVVmdkState { + int desc_offset; int num_extents; uint32_t parent_cid; VmdkExtent *extents; @@ -160,10 +161,11 @@ static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent) uint32_t cid; const char *p_name, *cid_str; size_t cid_str_size; + BDRVVmdkState *s = bs->opaque; - /* the descriptor offset = 0x200 */ - if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE) + if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) { return 0; + } if (parent) { cid_str = "parentCID"; @@ -185,10 +187,11 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) { char desc[DESC_SIZE], tmp_desc[DESC_SIZE]; char *p_name, *tmp_str; + BDRVVmdkState *s = bs->opaque; - /* the descriptor offset = 0x200 */ - if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE) - return -1; + if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) { + return -EIO; + } tmp_str = strstr(desc,"parentCID"); pstrcpy(tmp_desc, sizeof(tmp_desc), tmp_str); @@ -198,8 +201,9 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid) pstrcat(desc, sizeof(desc), tmp_desc); } - if (bdrv_pwrite_sync(bs->file, 0x200, desc, DESC_SIZE) < 0) - return -1; + if (bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE) < 0) { + return -EIO; + } return 0; } @@ -283,7 +287,6 @@ static int vmdk_snapshot_create(const char *filename, const char *backing_file) ret = -errno; goto fail; } - /* the descriptor offset = 0x200 */ if (lseek(p_fd, 0x200, SEEK_SET) == -1) { ret = -errno; goto fail; @@ -387,10 +390,11 @@ static int vmdk_parent_open(BlockDriverState *bs) { char *p_name; char desc[DESC_SIZE]; + BDRVVmdkState *s = bs->opaque; - /* the descriptor offset = 0x200 */ - if (bdrv_pread(bs->file, 0x200, desc, DESC_SIZE) != DESC_SIZE) + if (bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE) != DESC_SIZE) { return -1; + } if ((p_name = strstr(desc,"parentFileNameHint")) != NULL) { char *end_name; @@ -518,6 +522,7 @@ static int vmdk_open_vmdk3(BlockDriverState *bs, int flags) VmdkExtent *extent; BDRVVmdkState *s = bs->opaque; + s->desc_offset = 0x200; ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)); if (ret != sizeof(header)) { ret = ret < 0 ? ret : -EIO; @@ -545,6 +550,7 @@ static int vmdk_open_vmdk4(BlockDriverState *bs, int flags) BDRVVmdkState *s = bs->opaque; VmdkExtent *extent; + s->desc_offset = 0x200; ret = bdrv_pread(bs->file, sizeof(magic), &header, sizeof(header)); if (ret != sizeof(header)) { ret = ret < 0 ? ret : -EIO;