VMDK.cpp revision 870daa6c20c3a45b8a665f37def6c14a3a3072c9
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * VMDK disk image, core code.
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * Copyright (C) 2006-2011 Oracle Corporation
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * This file is part of VirtualBox Open Source Edition (OSE), as
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * available from http://www.virtualbox.org. This file is free software;
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * you can redistribute it and/or modify it under the terms of the GNU
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * General Public License (GPL) as published by the Free Software
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * Foundation, in version 2 as it comes in the "COPYING" file of the
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
44aae046c38e796e581110b7ecdf4478167d684dBob Halley * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
44aae046c38e796e581110b7ecdf4478167d684dBob Halley/*******************************************************************************
44aae046c38e796e581110b7ecdf4478167d684dBob Halley* Header Files *
44aae046c38e796e581110b7ecdf4478167d684dBob Halley*******************************************************************************/
44aae046c38e796e581110b7ecdf4478167d684dBob Halley/*******************************************************************************
193738b819e3c699f9edd18864a6810fcfcec855Andreas Gustafsson* Constants And Macros, Structures and Typedefs *
fd35453765c6494d077edca44f4d998af5fd4cfaDavid Lawrence*******************************************************************************/
44aae046c38e796e581110b7ecdf4478167d684dBob Halley/** Maximum encoded string size (including NUL) we allow for VMDK images.
634c61d2ddf514c3b1f5c8d49c2d2375df20a8b6Andreas Gustafsson * Deliberately not set high to avoid running out of descriptor space. */
634c61d2ddf514c3b1f5c8d49c2d2375df20a8b6Andreas Gustafsson/** VMDK descriptor DDB entry for PCHS cylinders. */
634c61d2ddf514c3b1f5c8d49c2d2375df20a8b6Andreas Gustafsson#define VMDK_DDB_GEO_PCHS_CYLINDERS "ddb.geometry.cylinders"
44aae046c38e796e581110b7ecdf4478167d684dBob Halley/** VMDK descriptor DDB entry for PCHS heads. */
44aae046c38e796e581110b7ecdf4478167d684dBob Halley#define VMDK_DDB_GEO_PCHS_HEADS "ddb.geometry.heads"
fd35453765c6494d077edca44f4d998af5fd4cfaDavid Lawrence/** VMDK descriptor DDB entry for PCHS sectors. */
#define VMDK_COMPRESSION_NONE 0
#define VMDK_MARKER_EOS 0
typedef struct SparseExtentHeader
bool uncleanShutdown;
char singleEndLineChar;
char nonEndLineChar;
char doubleEndLineChar1;
char doubleEndLineChar2;
#pragma pack()
typedef struct VMDKMARKER
#pragma pack()
#ifdef VBOX_WITH_VMDK_ESX
typedef struct COWDisk_Header
#pragma pack()
typedef enum VMDKETYPE
#ifdef VBOX_WITH_VMDK_ESX
typedef enum VMDKACCESS
VMDKACCESS_NOACCESS = 0,
typedef struct VMDKFILE
const char *pszFilename;
unsigned fOpen;
bool fAsyncIO;
unsigned uReferences;
bool fDelete;
typedef struct VMDKEXTENT
const char *pszBasename;
const char *pszFullname;
char *pDescData;
bool fUncleanShutdown;
bool fMetaDirty;
bool fFooter;
void *pvCompGrain;
void *pvGrain;
typedef struct VMDKDESCRIPTOR
unsigned uFirstDesc;
unsigned uFirstExtent;
unsigned uFirstDDB;
unsigned cLines;
bool fDirty;
typedef struct VMDKGTCACHEENTRY
typedef struct VMDKGTCACHE
unsigned cEntries;
typedef struct VMDKIMAGE
const char *pszFilename;
unsigned cExtents;
* and allocating/freeing an array in the read/write functions every time
unsigned cSegments;
unsigned uOpenFlags;
unsigned uImageFlags;
char *pDescData;
} VMDKIMAGE;
typedef struct VMDKCOMPRESSIO
void *pvCompGrain;
typedef struct VMDKGRAINALLOCASYNC
bool fIoErr;
unsigned cIoXfersPending;
bool fGTUpdateNeeded;
bool fDelete);
static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);
return rc;
return VERR_NO_MEMORY;
return VERR_NO_MEMORY;
return rc;
if (pNext)
if (pPrev)
return rc;
static DECLCALLBACK(int) vmdkFileInflateHelper(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbBuf)
cbBuf--;
if (!cbBuf)
if (pcbBuf)
return VINF_SUCCESS;
cbBuf);
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
int rc;
if (!pcvMarker)
NULL);
return rc;
if (cbCompSize == 0)
return VERR_VD_VMDK_INVALID_FORMAT;
return VERR_VD_VMDK_INVALID_FORMAT;
if (puLBA)
if (pcbMarkerData)
return rc;
return rc;
return rc;
cbBuf--;
if (!cbBuf)
return VINF_SUCCESS;
return VERR_BUFFER_OVERFLOW;
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
int rc;
return rc;
if (pcbMarkerData)
return rc;
return rc;
return rc;
if (!cb)
return VERR_BUFFER_OVERFLOW;
return rc;
* Internal: allocate the compressed/uncompressed buffers for streamOptimized
goto out;
goto out;
out:
return rc;
if (!pGD)
goto out;
if (!pRGD)
goto out;
out:
return rc;
goto out;
goto out;
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname);
goto out;
if (!pTmpGT1)
goto out;
if (!pTmpGT2)
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname);
goto out;
out:
return rc;
if (fPreAlloc)
+ cbGTRounded;
cbGTRounded = 0;
goto out;
goto out;
goto out;
if (fPreAlloc)
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname);
goto out;
out:
return rc;
char *pszQ;
char *pszUnquoted;
pszStr++;
pszQ++;
pszStr++;
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrectly quoted value in descriptor in '%s'"), pImage->pszFilename);
if (!pszUnquoted)
return VERR_NO_MEMORY;
if (ppszNext)
return VINF_SUCCESS;
const char *pszLine)
return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
return VINF_SUCCESS;
const char *pszValue;
while (uStart != 0)
pszValue++;
return !!uStart;
unsigned uStart,
char *pszTmp;
unsigned uLast = 0;
while (uStart != 0)
pszTmp++;
pszTmp++;
pszTmp++;
if (uStart)
if (pszValue)
return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
if (!pszValue)
return VINF_SUCCESS;
return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
return VINF_SUCCESS;
const char *pszValue;
&pszValue))
return VERR_VD_VMDK_VALUE_NOT_FOUND;
const char *pszValue;
char *pszValueUnquoted;
&pszValue))
return VERR_VD_VMDK_VALUE_NOT_FOUND;
return rc;
return rc;
char *pszValueQuoted;
if (!pszValueQuoted)
return VERR_NO_STR_MEMORY;
return rc;
if (!uEntry)
char *pszTmp;
while (uStart)
return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
return VINF_SUCCESS;
const char *pszValue;
char *pszValueUnquoted;
&pszValue))
return VERR_VD_VMDK_VALUE_NOT_FOUND;
return rc;
return rc;
const char *pszValue;
char *pszValueUnquoted;
&pszValue))
return VERR_VD_VMDK_VALUE_NOT_FOUND;
return rc;
return rc;
const char *pszValue;
char *pszValueUnquoted;
&pszValue))
return VERR_VD_VMDK_VALUE_NOT_FOUND;
return rc;
return rc;
int rc;
char *pszValQuoted;
if (pszVal)
if (!pszValQuoted)
return VERR_NO_STR_MEMORY;
if (pszValQuoted)
return rc;
char *pszUuid;
if (!pszUuid)
return VERR_NO_STR_MEMORY;
pszUuid);
return rc;
char *pszValue;
if (!pszValue)
return VERR_NO_STR_MEMORY;
pszValue);
return rc;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: unsupported end of line in descriptor in '%s'"), pImage->pszFilename);
goto out;
pTmp++;
pTmp++;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor does not start as expected in '%s'"), pImage->pszFilename);
goto out;
for (unsigned i = 0; i < cLine; i++)
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
goto out;
uLastNonEmptyLine = 0;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
goto out;
uLastNonEmptyLine = 0;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
goto out;
uLastNonEmptyLine = 0;
if (uLastNonEmptyLine)
uLastNonEmptyLine = i;
out:
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
int rc;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
goto out;
out:
return rc;
int rc;
unsigned cExtents;
unsigned uLine;
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error finding key 'version' in descriptor in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, VERR_VD_VMDK_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: unsupported format version in descriptor in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot get image type from descriptor in '%s'"), pImage->pszFilename);
uLine != 0;
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image may only have one extent in '%s'"), pImage->pszFilename);
return rc;
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
#ifdef VBOX_WITH_VMDK_ESX
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
pszLine++;
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
char *pszBasename;
return rc;
pszLine++;
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image modification UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent modification UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
return VINF_SUCCESS;
unsigned offDescriptor = 0;
if (!pszDescriptor)
return VERR_NO_MEMORY;
if (cbLimit)
rc = vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename);
if (!pszDescriptorNew)
if (cb > 0)
else if (pszDescriptor)
return rc;
void *pvDescriptor;
uOffset = 0;
cbLimit = 0;
return VERR_INVALID_PARAMETER;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
return rc;
void *pvDescriptor;
uOffset = 0;
cbLimit = 0;
return VERR_INVALID_PARAMETER;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
return rc;
static int vmdkValidateHeader(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, const SparseExtentHeader *pHeader)
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect magic in sparse extent header in '%s'"), pExtent->pszFullname);
return rc;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: incorrect version in sparse extent header in '%s', not a VMDK 1.0/1.1 conforming file"), pExtent->pszFullname);
return rc;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: corrupted by CR/LF translation in '%s'"), pExtent->pszFullname);
return rc;
return rc;
bool fMagicAlreadyRead)
int rc;
if (!fMagicAlreadyRead)
sizeof(Header)
NULL);
vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading extent header in '%s'"), pExtent->pszFullname);
goto out;
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname);
goto out;
vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading extent footer in '%s'"), pExtent->pszFullname);
goto out;
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent embedded descriptor config in '%s'"), pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot resolve grain directory offset in '%s'"), pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect grain directory size in '%s'"), pExtent->pszFullname);
goto out;
out:
return rc;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
goto out;
&& (pExtent->enmType != VMDKETYPE_FLAT || pExtent->cNominalSectors + pExtent->uSectorOffset > VMDK_BYTE2SECTOR(cbExtentSize)))
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: file size is not a multiple of 512 in '%s', file is truncated or otherwise garbled"), pExtent->pszFullname);
goto out;
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: invalid extent grain size %u in '%s'"), pExtent->cSectorsPerGrain, pExtent->pszFullname);
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: grain table cache size problem in '%s'"), pExtent->pszFullname);
goto out;
goto out;
out:
return rc;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
return rc;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
return rc;
#ifdef VBOX_WITH_VMDK_ESX
vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading ESX sparse extent header in '%s'"), pExtent->pszFullname);
goto out;
goto out;
goto out;
goto out;
goto out;
out:
return rc;
bool fDelete)
#ifdef VBOX_WITH_VMDK_ESX
return VERR_NO_MEMORY;
for (unsigned j = 0; j < VMDK_GT_CACHE_SIZE; j++)
return VINF_SUCCESS;
if (pExtents)
for (unsigned i = 0; i < cExtents; i++)
return rc;
int rc;
goto out;
vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading the magic number in '%s'"), pImage->pszFilename);
goto out;
goto out;
goto out;
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image without descriptor in '%s'"), pImage->pszFilename);
goto out;
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pExtent->pszFullname);
goto out;
goto out;
goto out;
goto out;
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor in '%s' is too short"), pImage->pszFilename);
goto out;
goto out;
&cbRead);
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pImage->pszFilename);
goto out;
rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot read descriptor in '%s'"), pImage->pszFilename);
goto out;
goto out;
unsigned cFlatExtents = 0;
goto out;
cFlatExtents++;
char *pszFullname;
if (!pszFullname)
goto out;
if (!pszDirname)
goto out;
if (!pszFullname)
goto out;
case VMDKETYPE_HOSTED_SPARSE:
goto out;
goto out;
goto out;
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
goto out;
case VMDKETYPE_ZERO:
goto out;
#ifdef VBOX_WITH_VMDK_ESX
out:
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
if (!pszBasename)
return VERR_NO_MEMORY;
return VERR_NO_MEMORY;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname);
unsigned cExtents = 0;
return vdIfError(pImage->pIfError, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: incorrect partition data area ordering set up by the caller in '%s'"), pImage->pszFilename);
cExtents++;
cExtents++;
cExtents++;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: invalid filename '%s'"), pImage->pszFilename);
if (!pszBaseBase)
return VERR_NO_MEMORY;
cExtents = 0;
uStart = 0;
if (!pszBasename)
return VERR_NO_MEMORY;
if (!pszDirname)
return VERR_NO_STR_MEMORY;
if (!pszDirname)
return VERR_NO_STR_MEMORY;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname);
if (!pszBasename)
return VERR_NO_MEMORY;
return VERR_NO_MEMORY;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
return rc;
unsigned uImageFlags,
cExtents++;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename);
for (unsigned i = 0; i < cExtents; i++)
if (!pszBasename)
return VERR_NO_MEMORY;
char *pszTmp;
if (!pszTmp)
return VERR_NO_STR_MEMORY;
if (!pszBasename)
return VERR_NO_MEMORY;
if (!pszBasedirectory)
return VERR_NO_STR_MEMORY;
if (!pszFullname)
return VERR_NO_STR_MEMORY;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname);
if (!pvBuf)
return VERR_NO_MEMORY;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: writing block failed for '%s'"), pImage->pszFilename);
if (pfnProgress)
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set controller type to lsilogic in '%s'"), pImage->pszFilename);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
return rc;
unsigned uImageFlags,
int rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
if (!pszBasename)
return VERR_NO_MEMORY;
if (!pszFullname)
return VERR_NO_STR_MEMORY;
& ~RTFILE_O_READ,
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
return rc;
int rc;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new descriptor in '%s'"), pImage->pszFilename);
goto out;
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not insert the extent list into descriptor in '%s'"), pImage->pszFilename);
goto out;
goto out;
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in new descriptor in '%s'"), pImage->pszFilename);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in new descriptor in '%s'"), pImage->pszFilename);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in new descriptor in '%s'"), pImage->pszFilename);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent modification UUID in new descriptor in '%s'"), pImage->pszFilename);
goto out;
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot set image comment in '%s'"), pImage->pszFilename);
goto out;
pImage->pExtents[0].cDescriptorSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64( pImage->Descriptor.aLines[pImage->Descriptor.cLines]
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK header in '%s'"), pImage->pszFilename);
goto out;
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK descriptor in '%s'"), pImage->pszFilename);
goto out;
out:
return rc;
char *pszCommentEncoded;
if (pszComment)
if (!pszCommentEncoded)
return VERR_NO_MEMORY;
if (pszComment)
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image comment in descriptor in '%s'"), pImage->pszFilename);
return VINF_SUCCESS;
uint32_t cCacheLines = RT_ALIGN(pExtent->cGTEntries, VMDK_GT_CACHELINE_SIZE) / VMDK_GT_CACHELINE_SIZE;
uint32_t cCacheLines = RT_ALIGN(pExtent->cGTEntries, VMDK_GT_CACHELINE_SIZE) / VMDK_GT_CACHELINE_SIZE;
bool fAllZero = true;
if (*pGTTmp)
fAllZero = false;
if (!fAllZero)
if (fAllZero)
return VINF_SUCCESS;
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return VERR_INTERNAL_ERROR;
NULL);
return rc;
if (pImage)
#ifdef VBOX_WITH_VMDK_ESX
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
pMarker->uSector = VMDK_BYTE2SECTOR(RT_ALIGN_64(RT_H2LE_U64(pExtent->cGDEntries * sizeof(uint32_t)), 512));
NULL);
return rc;
goto out;
case VMDKETYPE_HOSTED_SPARSE:
goto out;
if (!uFileOffset)
goto out;
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
case VMDKETYPE_ZERO:
case VMDKETYPE_HOSTED_SPARSE:
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
case VMDKETYPE_ZERO:
out:
return rc;
if (pExtent)
return rc;
unsigned uExtent)
int rc;
/* For newly created and readonly/sequentially opened streamOptimized
*puExtentSector = 0;
return VINF_SUCCESS;
return VERR_OUT_OF_RANGE;
if (!uGTSector)
*puExtentSector = 0;
return VINF_SUCCESS;
VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);
for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
if (uGrainSector)
*puExtentSector = 0;
return VINF_SUCCESS;
int rc;
return VERR_OUT_OF_RANGE;
if (!uGTSector)
*puExtentSector = 0;
return VINF_SUCCESS;
VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return rc;
for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
if (uGrainSector)
*puExtentSector = 0;
return VINF_SUCCESS;
int rc;
return VERR_OUT_OF_RANGE;
if (!uGTSector)
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return VERR_VD_VMDK_INVALID_HEADER;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return VERR_VD_VMDK_INVALID_HEADER;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return vdIfError(pImage->pIfError, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
#ifdef VBOX_WITH_VMDK_ESX
return rc;
int rc;
if ( cbWrite == 0
return VERR_INVALID_PARAMETER;
cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSector % pExtent->cSectorsPerGrain));
return VERR_VD_VMDK_INVALID_WRITE;
return VINF_SUCCESS;
return rc;
return rc;
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return VERR_INTERNAL_ERROR;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname);
return rc;
VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return rc;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
#ifdef VBOX_WITH_VMDK_ESX
return rc;
static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
return rc;
int rc;
if (!pGrainAlloc)
return VERR_NO_MEMORY;
return VERR_OUT_OF_RANGE;
if (!uGTSector)
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return VERR_VD_VMDK_INVALID_HEADER;
if (!paGTDataTmp)
return VERR_NO_MEMORY;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return VERR_VD_VMDK_INVALID_HEADER;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
if (!uFileOffset)
return VERR_INTERNAL_ERROR;
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
return rc;
int rc;
return VERR_VD_VMDK_INVALID_STATE;
return VERR_VD_VMDK_INVALID_STATE;
NULL);
return rc;
NULL);
return rc;
case VMDK_MARKER_EOS:
case VMDK_MARKER_GT:
case VMDK_MARKER_GD:
case VMDK_MARKER_FOOTER:
return VERR_VD_VMDK_INVALID_STATE;
return rc;
return VERR_VD_VMDK_INVALID_STATE;
return VERR_VD_BLOCK_FREE;
cbRead);
return VINF_SUCCESS;
const char *pszByWhat)
if (!pszFoundStr)
return NULL;
if (pszNewStr)
return pszNewStr;
if ( !pszFilename
|| !*pszFilename
goto out;
if (!pImage)
goto out;
out:
return rc;
LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
int rc;
goto out;
|| !*pszFilename
goto out;
if (!pImage)
goto out;
out:
return rc;
LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p\n", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
int rc;
if (pIfProgress)
goto out;
goto out;
if ( !cbSize
goto out;
|| !*pszFilename
#ifndef VBOX_WITH_VMDK_ESX
goto out;
if (!pImage)
goto out;
goto out;
goto out;
out:
return rc;
bool fImageFreed = false;
bool fEmbeddedDesc = false;
unsigned cExtents = 0;
const char *pszOldImageName;
unsigned i, line;
if ( !pImage
|| !*pszFilename)
goto out;
goto out;
fEmbeddedDesc = false;
fEmbeddedDesc = true;
goto out;
i < cExtents;
if (!apszNewLines[i])
goto rollback;
for (i = 0; i < cExtents; i++)
if (!apszNewName[i])
goto rollback;
goto rollback;
fImageFreed = true;
if (!fEmbeddedDesc)
goto rollback;
goto out;
int rrc;
if (!fImageFreed)
for (i = 0; i <= cExtents; i++)
if (apszOldName[i])
if (fEmbeddedDesc)
out:
if (apszOldName)
for (i = 0; i <= cExtents; i++)
if (apszOldName[i])
if (apszNewName)
for (i = 0; i <= cExtents; i++)
if (apszNewName[i])
if (apszNewLines)
for (i = 0; i < cExtents; i++)
if (apszNewLines[i])
if (pszOldDescName)
if (pszOldBaseName)
if (pszNewBaseName)
if (pszOldFullName)
if (pszNewFullName)
return rc;
int rc;
return rc;
LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
int rc;
|| cbToRead == 0)
goto out;
goto out;
goto out;
cbToRead = RT_MIN(cbToRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
case VMDKETYPE_HOSTED_SPARSE:
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
goto out;
cbToRead = RT_MIN(cbToRead, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
if (uSectorExtentAbs == 0)
goto out;
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
case VMDKETYPE_ZERO:
if (pcbActuallyRead)
out:
return rc;
LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
int rc;
goto out;
if (cbToWrite == 0)
goto out;
goto out;
goto out;
case VMDKETYPE_HOSTED_SPARSE:
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
goto out;
cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
goto out;
if (uSectorExtentAbs == 0)
*pcbPreRead = 0;
*pcbPostRead = 0;
cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
case VMDKETYPE_ZERO:
cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
if (pcbWriteProcess)
out:
return rc;
return rc;
if (pImage)
return VMDK_IMAGE_VERSION;
if (pImage)
if (pImage)
return cb;
int rc;
if (pImage)
LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
return rc;
LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
int rc;
if (pImage)
goto out;
goto out;
goto out;
out:
return rc;
int rc;
if (pImage)
LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
return rc;
LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
int rc;
if (pImage)
goto out;
goto out;
goto out;
out:
return rc;
unsigned uImageFlags;
if (pImage)
uImageFlags = 0;
return uImageFlags;
unsigned uOpenFlags;
if (pImage)
uOpenFlags = 0;
return uOpenFlags;
int rc;
if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
goto out;
goto out;
out:
return rc;
LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
int rc;
if (pImage)
goto out;
if (pszComment)
if (pszCommentEncoded)
out:
return rc;
int rc;
goto out;
goto out;
if (pImage)
out:
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
int rc;
if (pImage)
return rc;
int rc;
if (pImage)
return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor in '%s'"), pImage->pszFilename);
return rc;
if (pImage)
vdIfErrorMessage(pImage->pIfError, "Header: uuidModification={%RTuuid}\n", &pImage->ModificationUuid);
vdIfErrorMessage(pImage->pIfError, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid);
int rc;
|| cbRead == 0)
goto out;
goto out;
goto out;
cbRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
case VMDKETYPE_HOSTED_SPARSE:
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
goto out;
cbRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
if (uSectorExtentAbs == 0)
AssertMsg(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), ("Async I/O is not supported for stream optimized VMDK's\n"));
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
case VMDKETYPE_ZERO:
if (pcbActuallyRead)
out:
return rc;
LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
int rc;
goto out;
if (cbWrite == 0)
goto out;
goto out;
goto out;
case VMDKETYPE_HOSTED_SPARSE:
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
goto out;
cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
goto out;
if (uSectorExtentAbs == 0)
*pcbPreRead = 0;
*pcbPostRead = 0;
cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
case VMDKETYPE_ZERO:
cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
if (pcbWriteProcess)
out:
return rc;
goto out;
case VMDKETYPE_HOSTED_SPARSE:
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
goto out;
if (!uFileOffset)
goto out;
goto out;
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
case VMDKETYPE_ZERO:
case VMDKETYPE_HOSTED_SPARSE:
#ifdef VBOX_WITH_VMDK_ESX
case VMDKETYPE_ESX_SPARSE:
case VMDKETYPE_VMFS:
case VMDKETYPE_FLAT:
case VMDKETYPE_ZERO:
out:
return rc;
sizeof(VBOXHDDBACKEND),
| VD_CAP_VFS,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,