VirtualBox

Changeset 87052 in vbox for trunk/src/VBox/Storage


Ignore:
Timestamp:
Dec 8, 2020 1:21:08 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
141811
Message:

Main: bugref:9224: Fixed scm errors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/VMDK.cpp

    r87051 r87052  
    33 * VMDK disk image, core code.
    44 */
    5 
    65/*
    76 * Copyright (C) 2006-2020 Oracle Corporation
     
    1514 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1615 */
    17 
    18 
    1916/*********************************************************************************************************************************
    2017*   Header Files                                                                                                                 *
     
    2421#include <VBox/vd-plugin.h>
    2522#include <VBox/err.h>
    26 
    2723#include <iprt/assert.h>
    2824#include <iprt/alloc.h>
     
    6460#include <errno.h>
    6561#endif
    66 
    6762#include "VDBackends.h"
    68 
    69 
    7063/*********************************************************************************************************************************
    7164*   Constants And Macros, Structures and Typedefs                                                                                *
    7265*********************************************************************************************************************************/
    73 
    7466/** Maximum encoded string size (including NUL) we allow for VMDK images.
    7567 * Deliberately not set high to avoid running out of descriptor space. */
    7668#define VMDK_ENCODED_COMMENT_MAX 1024
    77 
    7869/** VMDK descriptor DDB entry for PCHS cylinders. */
    7970#define VMDK_DDB_GEO_PCHS_CYLINDERS "ddb.geometry.cylinders"
    80 
    8171/** VMDK descriptor DDB entry for PCHS heads. */
    8272#define VMDK_DDB_GEO_PCHS_HEADS "ddb.geometry.heads"
    83 
    8473/** VMDK descriptor DDB entry for PCHS sectors. */
    8574#define VMDK_DDB_GEO_PCHS_SECTORS "ddb.geometry.sectors"
    86 
    8775/** VMDK descriptor DDB entry for LCHS cylinders. */
    8876#define VMDK_DDB_GEO_LCHS_CYLINDERS "ddb.geometry.biosCylinders"
    89 
    9077/** VMDK descriptor DDB entry for LCHS heads. */
    9178#define VMDK_DDB_GEO_LCHS_HEADS "ddb.geometry.biosHeads"
    92 
    9379/** VMDK descriptor DDB entry for LCHS sectors. */
    9480#define VMDK_DDB_GEO_LCHS_SECTORS "ddb.geometry.biosSectors"
    95 
    9681/** VMDK descriptor DDB entry for image UUID. */
    9782#define VMDK_DDB_IMAGE_UUID "ddb.uuid.image"
    98 
    9983/** VMDK descriptor DDB entry for image modification UUID. */
    10084#define VMDK_DDB_MODIFICATION_UUID "ddb.uuid.modification"
    101 
    10285/** VMDK descriptor DDB entry for parent image UUID. */
    10386#define VMDK_DDB_PARENT_UUID "ddb.uuid.parent"
    104 
    10587/** VMDK descriptor DDB entry for parent image modification UUID. */
    10688#define VMDK_DDB_PARENT_MODIFICATION_UUID "ddb.uuid.parentmodification"
    107 
    10889/** No compression for streamOptimized files. */
    10990#define VMDK_COMPRESSION_NONE 0
    110 
    11191/** Deflate compression for streamOptimized files. */
    11292#define VMDK_COMPRESSION_DEFLATE 1
    113 
    11493/** Marker that the actual GD value is stored in the footer. */
    11594#define VMDK_GD_AT_END 0xffffffffffffffffULL
    116 
    11795/** Marker for end-of-stream in streamOptimized images. */
    11896#define VMDK_MARKER_EOS 0
    119 
    12097/** Marker for grain table block in streamOptimized images. */
    12198#define VMDK_MARKER_GT 1
    122 
    12399/** Marker for grain directory block in streamOptimized images. */
    124100#define VMDK_MARKER_GD 2
    125 
    126101/** Marker for footer in streamOptimized images. */
    127102#define VMDK_MARKER_FOOTER 3
    128 
    129103/** Marker for unknown purpose in streamOptimized images.
    130104 * Shows up in very recent images created by vSphere, but only sporadically.
    131105 * They "forgot" to document that one in the VMDK specification. */
    132106#define VMDK_MARKER_UNSPECIFIED 4
    133 
    134107/** Dummy marker for "don't check the marker value". */
    135108#define VMDK_MARKER_IGNORE 0xffffffffU
    136 
    137109/**
    138110 * Magic number for hosted images created by VMware Workstation 4, VMware
     
    140112 */
    141113#define VMDK_SPARSE_MAGICNUMBER 0x564d444b /* 'V' 'M' 'D' 'K' */
    142 
    143114/**
    144115 * VMDK hosted binary extent header. The "Sparse" is a total misnomer, as
     
    168139} SparseExtentHeader;
    169140#pragma pack()
    170 
    171141/** The maximum allowed descriptor size in the extent header in sectors. */
    172142#define VMDK_SPARSE_DESCRIPTOR_SIZE_MAX UINT64_C(20480) /* 10MB */
    173 
    174143/** VMDK capacity for a single chunk when 2G splitting is turned on. Should be
    175144 * divisible by the default grain size (64K) */
    176145#define VMDK_2G_SPLIT_SIZE (2047 * 1024 * 1024)
    177 
    178146/** VMDK streamOptimized file format marker. The type field may or may not
    179147 * be actually valid, but there's always data to read there. */
     
    186154} VMDKMARKER, *PVMDKMARKER;
    187155#pragma pack()
    188 
    189 
    190156/** Convert sector number/size to byte offset/size. */
    191157#define VMDK_SECTOR2BYTE(u) ((uint64_t)(u) << 9)
    192 
    193158/** Convert byte offset/size to sector number/size. */
    194159#define VMDK_BYTE2SECTOR(u) ((u) >> 9)
    195 
    196160/**
    197161 * VMDK extent type.
     
    208172    VMDKETYPE_VMFS
    209173} VMDKETYPE, *PVMDKETYPE;
    210 
    211174/**
    212175 * VMDK access type for a extent.
     
    221184    VMDKACCESS_READWRITE
    222185} VMDKACCESS, *PVMDKACCESS;
    223 
    224186/** Forward declaration for PVMDKIMAGE. */
    225187typedef struct VMDKIMAGE *PVMDKIMAGE;
    226 
    227188/**
    228189 * Extents files entry. Used for opening a particular file only once.
     
    249210    struct VMDKFILE *pPrev;
    250211} VMDKFILE, *PVMDKFILE;
    251 
    252212/**
    253213 * VMDK extent data structure.
     
    330290    struct VMDKIMAGE *pImage;
    331291} VMDKEXTENT, *PVMDKEXTENT;
    332 
    333292/**
    334293 * Grain table cache size. Allocated per image.
    335294 */
    336295#define VMDK_GT_CACHE_SIZE 256
    337 
    338296/**
    339297 * Grain table block size. Smaller than an actual grain table block to allow
     
    342300 */
    343301#define VMDK_GT_CACHELINE_SIZE 128
    344 
    345 
    346302/**
    347303 * Maximum number of lines in a descriptor file. Not worth the effort of
     
    351307 */
    352308#define VMDK_DESCRIPTOR_LINES_MAX   1100U
    353 
    354309/**
    355310 * Parsed descriptor information. Allows easy access and update of the
     
    375330    unsigned    aNextLines[VMDK_DESCRIPTOR_LINES_MAX];
    376331} VMDKDESCRIPTOR, *PVMDKDESCRIPTOR;
    377 
    378 
    379332/**
    380333 * Cache entry for translating extent/sector to a sector number in that
     
    390343    uint32_t    aGTData[VMDK_GT_CACHELINE_SIZE];
    391344} VMDKGTCACHEENTRY, *PVMDKGTCACHEENTRY;
    392 
    393345/**
    394346 * Cache data structure for blocks of grain table entries. For now this is a
     
    404356    unsigned            cEntries;
    405357} VMDKGTCACHE, *PVMDKGTCACHE;
    406 
    407358/**
    408359 * Complete VMDK image data structure. Mainly a collection of extents and a few
     
    415366    /** Descriptor file if applicable. */
    416367    PVMDKFILE         pFile;
    417 
    418368    /** Pointer to the per-disk VD interface list. */
    419369    PVDINTERFACE      pVDIfsDisk;
    420370    /** Pointer to the per-image VD interface list. */
    421371    PVDINTERFACE      pVDIfsImage;
    422 
    423372    /** Error interface. */
    424373    PVDINTERFACEERROR pIfError;
    425374    /** I/O interface. */
    426375    PVDINTERFACEIOINT pIfIo;
    427 
    428 
    429376    /** Pointer to the image extents. */
    430377    PVMDKEXTENT     pExtents;
     
    434381     * times only once (happens mainly with raw partition access). */
    435382    PVMDKFILE       pFiles;
    436 
    437383    /**
    438384     * Pointer to an array of segment entries for async I/O.
     
    444390    /** Entries available in the segments array. */
    445391    unsigned        cSegments;
    446 
    447392    /** Open flags passed by VBoxHD layer. */
    448393    unsigned        uOpenFlags;
     
    463408    /** Parent image modification UUID. */
    464409    RTUUID          ParentModificationUuid;
    465 
    466410    /** Pointer to grain table cache, if this image contains sparse extents. */
    467411    PVMDKGTCACHE    pGTCache;
     
    475419    VDREGIONLIST    RegionList;
    476420} VMDKIMAGE;
    477 
    478 
    479421/** State for the input/output callout of the inflate reader/deflate writer. */
    480422typedef struct VMDKCOMPRESSIO
     
    489431    void *pvCompGrain;
    490432} VMDKCOMPRESSIO;
    491 
    492 
    493433/** Tracks async grain allocation. */
    494434typedef struct VMDKGRAINALLOCASYNC
     
    512452    uint64_t    uRGTSector;
    513453} VMDKGRAINALLOCASYNC, *PVMDKGRAINALLOCASYNC;
    514 
    515454/**
    516455 * State information for vmdkRename() and helpers.
     
    550489/** Pointer to a VMDK rename state. */
    551490typedef VMDKRENAMESTATE *PVMDKRENAMESTATE;
    552 
    553 
    554491/*********************************************************************************************************************************
    555492*   Static Variables                                                                                                             *
    556493*********************************************************************************************************************************/
    557 
    558494/** NULL-terminated array of supported file extensions. */
    559495static const VDFILEEXTENSION s_aVmdkFileExtensions[] =
     
    562498    {NULL, VDTYPE_INVALID}
    563499};
    564 
    565500/** NULL-terminated array of configuration option. */
    566501static const VDCONFIGINFO s_aVmdkConfigInfo[] =
     
    571506    { "BootSector",                     NULL,                             VDCFGVALUETYPE_BYTES,        0 },
    572507    { "Relative",                       NULL,                             VDCFGVALUETYPE_INTEGER,      0 },
    573 
    574508    /* End of options list */
    575509    { NULL,                             NULL,                             VDCFGVALUETYPE_INTEGER,      0 }
    576510};
    577 
    578 
    579511/*********************************************************************************************************************************
    580512*   Internal Functions                                                                                                           *
    581513*********************************************************************************************************************************/
    582 
    583514static void vmdkFreeStreamBuffers(PVMDKEXTENT pExtent);
    584515static int vmdkFreeExtentData(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    585516                              bool fDelete);
    586 
    587517static int vmdkCreateExtents(PVMDKIMAGE pImage, unsigned cExtents);
    588518static int vmdkFlushImage(PVMDKIMAGE pImage, PVDIOCTX pIoCtx);
    589519static int vmdkSetImageComment(PVMDKIMAGE pImage, const char *pszComment);
    590520static int vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete, bool fFlush);
    591 
    592521static DECLCALLBACK(int) vmdkAllocGrainComplete(void *pBackendData, PVDIOCTX pIoCtx,
    593522                                                void *pvUser, int rcReq);
    594 
    595523/**
    596524 * Internal: open a file (using a file descriptor cache to ensure each file
     
    602530    int rc = VINF_SUCCESS;
    603531    PVMDKFILE pVmdkFile;
    604 
    605532    for (pVmdkFile = pImage->pFiles;
    606533         pVmdkFile != NULL;
     
    611538            Assert(fOpen == pVmdkFile->fOpen);
    612539            pVmdkFile->uReferences++;
    613 
    614540            *ppVmdkFile = pVmdkFile;
    615 
    616541            return rc;
    617542        }
    618543    }
    619 
    620544    /* If we get here, there's no matching entry in the cache. */
    621545    pVmdkFile = (PVMDKFILE)RTMemAllocZ(sizeof(VMDKFILE));
     
    625549        return VERR_NO_MEMORY;
    626550    }
    627 
    628551    pVmdkFile->pszFilename = RTStrDup(pszFilename);
    629552    if (!pVmdkFile->pszFilename)
     
    633556        return VERR_NO_MEMORY;
    634557    }
    635 
    636558    if (pszBasename)
    637559    {
     
    645567        }
    646568    }
    647 
    648569    pVmdkFile->fOpen = fOpen;
    649 
    650570    rc = vdIfIoIntFileOpen(pImage->pIfIo, pszFilename, fOpen,
    651571                           &pVmdkFile->pStorage);
     
    666586        *ppVmdkFile = NULL;
    667587    }
    668 
    669     return rc;
    670 }
    671 
     588    return rc;
     589}
    672590/**
    673591 * Internal: close a file, updating the file descriptor cache.
     
    677595    int rc = VINF_SUCCESS;
    678596    PVMDKFILE pVmdkFile = *ppVmdkFile;
    679 
    680597    AssertPtr(pVmdkFile);
    681 
    682598    pVmdkFile->fDelete |= fDelete;
    683599    Assert(pVmdkFile->uReferences);
     
    687603        PVMDKFILE pPrev;
    688604        PVMDKFILE pNext;
    689 
    690605        /* Unchain the element from the list. */
    691606        pPrev = pVmdkFile->pPrev;
    692607        pNext = pVmdkFile->pNext;
    693 
    694608        if (pNext)
    695609            pNext->pPrev = pPrev;
     
    698612        else
    699613            pImage->pFiles = pNext;
    700 
    701614        rc = vdIfIoIntFileClose(pImage->pIfIo, pVmdkFile->pStorage);
    702 
    703615        bool fFileDel = pVmdkFile->fDelete;
    704616        if (   pVmdkFile->pszBasename
     
    713625                fFileDel = false;
    714626        }
    715 
    716627        if (fFileDel)
    717628        {
     
    727638        RTMemFree(pVmdkFile);
    728639    }
    729 
    730640    *ppVmdkFile = NULL;
    731641    return rc;
    732642}
    733 
    734643/*#define VMDK_USE_BLOCK_DECOMP_API - test and enable */
    735644#ifndef VMDK_USE_BLOCK_DECOMP_API
     
    738647    VMDKCOMPRESSIO *pInflateState = (VMDKCOMPRESSIO *)pvUser;
    739648    size_t cbInjected = 0;
    740 
    741649    Assert(cbBuf);
    742650    if (pInflateState->iOffset < 0)
     
    764672}
    765673#endif
    766 
    767674/**
    768675 * Internal: read from a file and inflate the compressed data,
     
    780687    VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain;
    781688    size_t cbCompSize, cbActuallyRead;
    782 
    783689    if (!pcvMarker)
    784690    {
     
    795701        pMarker->cbSize = RT_H2LE_U32(pMarker->cbSize);
    796702    }
    797 
    798703    cbCompSize = RT_LE2H_U32(pMarker->cbSize);
    799704    if (cbCompSize == 0)
     
    802707        return VERR_VD_VMDK_INVALID_FORMAT;
    803708    }
    804 
    805709    /* Sanity check - the expansion ratio should be much less than 2. */
    806710    Assert(cbCompSize < 2 * cbToRead);
    807711    if (cbCompSize >= 2 * cbToRead)
    808712        return VERR_VD_VMDK_INVALID_FORMAT;
    809 
    810713    /* Compressed grain marker. Data follows immediately. */
    811714    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
     
    817720                                          512)
    818721                               - RT_UOFFSETOF(VMDKMARKER, uType));
    819 
    820722    if (puLBA)
    821723        *puLBA = RT_LE2H_U64(pMarker->uSector);
     
    824726                                  + RT_UOFFSETOF(VMDKMARKER, uType),
    825727                                  512);
    826 
    827728#ifdef VMDK_USE_BLOCK_DECOMP_API
    828729    rc = RTZipBlockDecompress(RTZIPTYPE_ZLIB, 0 /*fFlags*/,
     
    835736    InflateState.cbCompGrain = cbCompSize + RT_UOFFSETOF(VMDKMARKER, uType);
    836737    InflateState.pvCompGrain = pExtent->pvCompGrain;
    837 
    838738    rc = RTZipDecompCreate(&pZip, &InflateState, vmdkFileInflateHelper);
    839739    if (RT_FAILURE(rc))
     
    852752    return rc;
    853753}
    854 
    855754static DECLCALLBACK(int) vmdkFileDeflateHelper(void *pvUser, const void *pvBuf, size_t cbBuf)
    856755{
    857756    VMDKCOMPRESSIO *pDeflateState = (VMDKCOMPRESSIO *)pvUser;
    858 
    859757    Assert(cbBuf);
    860758    if (pDeflateState->iOffset < 0)
     
    873771    return VINF_SUCCESS;
    874772}
    875 
    876773/**
    877774 * Internal: deflate the uncompressed data and write to a file,
     
    886783    PRTZIPCOMP pZip = NULL;
    887784    VMDKCOMPRESSIO DeflateState;
    888 
    889785    DeflateState.pImage = pImage;
    890786    DeflateState.iOffset = -1;
    891787    DeflateState.cbCompGrain = pExtent->cbCompGrain;
    892788    DeflateState.pvCompGrain = pExtent->pvCompGrain;
    893 
    894789    rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper,
    895790                         RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT);
     
    904799        Assert(   DeflateState.iOffset > 0
    905800               && (size_t)DeflateState.iOffset <= DeflateState.cbCompGrain);
    906 
    907801        /* pad with zeroes to get to a full sector size */
    908802        uint32_t uSize = DeflateState.iOffset;
     
    914808            uSize = uSizeAlign;
    915809        }
    916 
    917810        if (pcbMarkerData)
    918811            *pcbMarkerData = uSize;
    919 
    920812        /* Compressed grain marker. Data follows immediately. */
    921813        VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain;
     
    930822    return rc;
    931823}
    932 
    933 
    934824/**
    935825 * Internal: check if all files are closed, prevent leaking resources.
     
    939829    int rc = VINF_SUCCESS, rc2;
    940830    PVMDKFILE pVmdkFile;
    941 
    942831    Assert(pImage->pFiles == NULL);
    943832    for (pVmdkFile = pImage->pFiles;
     
    948837                pVmdkFile->pszFilename));
    949838        pImage->pFiles = pVmdkFile->pNext;
    950 
    951839        rc2 = vmdkFileClose(pImage, &pVmdkFile, pVmdkFile->fDelete);
    952 
    953840        if (RT_SUCCESS(rc))
    954841            rc = rc2;
     
    956843    return rc;
    957844}
    958 
    959845/**
    960846 * Internal: truncate a string (at a UTF8 code point boundary) and encode the
     
    965851    char szEnc[VMDK_ENCODED_COMMENT_MAX + 3];
    966852    char *pszDst = szEnc;
    967 
    968853    AssertPtr(psz);
    969 
    970854    for (; *psz; psz = RTStrNextCp(psz))
    971855    {
     
    998882    return RTStrDup(szEnc);
    999883}
    1000 
    1001884/**
    1002885 * Internal: decode a string and store it into the specified string.
     
    1006889    int rc = VINF_SUCCESS;
    1007890    char szBuf[4];
    1008 
    1009891    if (!cb)
    1010892        return VERR_BUFFER_OVERFLOW;
    1011 
    1012893    AssertPtr(psz);
    1013 
    1014894    for (; *pszEncoded; pszEncoded = RTStrNextCp(pszEncoded))
    1015895    {
     
    1034914        else
    1035915            pszDst = RTStrPutCp(pszDst, Cp);
    1036 
    1037916        /* Need to leave space for terminating NUL. */
    1038917        if ((size_t)(pszDst - szBuf) + 1 >= cb)
     
    1047926    return rc;
    1048927}
    1049 
    1050928/**
    1051929 * Internal: free all buffers associated with grain directories.
     
    1064942    }
    1065943}
    1066 
    1067944/**
    1068945 * Internal: allocate the compressed/uncompressed buffers for streamOptimized
     
    1072949{
    1073950    int rc = VINF_SUCCESS;
    1074 
    1075951    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    1076952    {
     
    1091967            rc = VERR_NO_MEMORY;
    1092968    }
    1093 
    1094969    if (RT_FAILURE(rc))
    1095970        vmdkFreeStreamBuffers(pExtent);
    1096971    return rc;
    1097972}
    1098 
    1099973/**
    1100974 * Internal: allocate all buffers associated with grain directories.
     
    1105979    int rc = VINF_SUCCESS;
    1106980    size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);
    1107 
    1108981    pExtent->pGD = (uint32_t *)RTMemAllocZ(cbGD);
    1109982    if (RT_LIKELY(pExtent->pGD))
     
    1118991    else
    1119992        rc = VERR_NO_MEMORY;
    1120 
    1121993    if (RT_FAILURE(rc))
    1122994        vmdkFreeGrainDirectory(pExtent);
    1123995    return rc;
    1124996}
    1125 
    1126997/**
    1127998 * Converts the grain directory from little to host endianess.
     
    11341005{
    11351006    uint32_t *pGDTmp = pGD;
    1136 
    11371007    for (uint32_t i = 0; i < cGDEntries; i++, pGDTmp++)
    11381008        *pGDTmp = RT_LE2H_U32(*pGDTmp);
    11391009}
    1140 
    11411010/**
    11421011 * Read the grain directory and allocated grain tables verifying them against
     
    11511020    int rc = VINF_SUCCESS;
    11521021    size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);
    1153 
    11541022    AssertReturn((   pExtent->enmType == VMDKETYPE_HOSTED_SPARSE
    11551023                  && pExtent->uSectorGD != VMDK_GD_AT_END
    11561024                  && pExtent->uSectorRGD != VMDK_GD_AT_END), VERR_INTERNAL_ERROR);
    1157 
    11581025    rc = vmdkAllocGrainDirectory(pImage, pExtent);
    11591026    if (RT_SUCCESS(rc))
     
    11671034        {
    11681035            vmdkGrainDirectoryConvToHost(pExtent->pGD, pExtent->cGDEntries);
    1169 
    11701036            if (   pExtent->uSectorRGD
    11711037                && !(pImage->uOpenFlags & VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))
     
    11791045                {
    11801046                    vmdkGrainDirectoryConvToHost(pExtent->pRGD, pExtent->cGDEntries);
    1181 
    11821047                    /* Check grain table and redundant grain table for consistency. */
    11831048                    size_t cbGT = pExtent->cGTEntries * sizeof(uint32_t);
    11841049                    size_t cbGTBuffers = cbGT; /* Start with space for one GT. */
    11851050                    size_t cbGTBuffersMax = _1M;
    1186 
    11871051                    uint32_t *pTmpGT1 = (uint32_t *)RTMemAlloc(cbGTBuffers);
    11881052                    uint32_t *pTmpGT2 = (uint32_t *)RTMemAlloc(cbGTBuffers);
    1189 
    11901053                    if (   !pTmpGT1
    11911054                        || !pTmpGT2)
    11921055                        rc = VERR_NO_MEMORY;
    1193 
    11941056                    size_t i = 0;
    11951057                    uint32_t *pGDTmp = pExtent->pGD;
    11961058                    uint32_t *pRGDTmp = pExtent->pRGD;
    1197 
    11981059                    /* Loop through all entries. */
    11991060                    while (i < pExtent->cGDEntries)
     
    12021063                        uint32_t uRGTStart = *pRGDTmp;
    12031064                        size_t   cbGTRead = cbGT;
    1204 
    12051065                        /* If no grain table is allocated skip the entry. */
    12061066                        if (*pGDTmp == 0 && *pRGDTmp == 0)
     
    12091069                            continue;
    12101070                        }
    1211 
    12121071                        if (*pGDTmp == 0 || *pRGDTmp == 0 || *pGDTmp == *pRGDTmp)
    12131072                        {
     
    12191078                            break;
    12201079                        }
    1221 
    12221080                        i++;
    12231081                        pGDTmp++;
    12241082                        pRGDTmp++;
    1225 
    12261083                        /*
    12271084                         * Read a few tables at once if adjacent to decrease the number
     
    12371094                                continue;
    12381095                            }
    1239 
    12401096                            if (*pGDTmp == 0 || *pRGDTmp == 0 || *pGDTmp == *pRGDTmp)
    12411097                            {
     
    12471103                                break;
    12481104                            }
    1249 
    12501105                            /* Check that the start offsets are adjacent.*/
    12511106                            if (   VMDK_SECTOR2BYTE(uGTStart) + cbGTRead != VMDK_SECTOR2BYTE(*pGDTmp)
    12521107                                || VMDK_SECTOR2BYTE(uRGTStart) + cbGTRead != VMDK_SECTOR2BYTE(*pRGDTmp))
    12531108                                break;
    1254 
    12551109                            i++;
    12561110                            pGDTmp++;
     
    12581112                            cbGTRead += cbGT;
    12591113                        }
    1260 
    12611114                        /* Increase buffers if required. */
    12621115                        if (   RT_SUCCESS(rc)
     
    12761129                            else
    12771130                                rc = VERR_NO_MEMORY;
    1278 
    12791131                            if (rc == VERR_NO_MEMORY)
    12801132                            {
     
    12831135                                i -= cbGTRead / cbGT;
    12841136                                cbGTRead = cbGT;
    1285 
    12861137                                /* Don't try to increase the buffer again in the next run. */
    12871138                                cbGTBuffersMax = cbGTBuffers;
    12881139                            }
    12891140                        }
    1290 
    12911141                        if (RT_SUCCESS(rc))
    12921142                        {
     
    13211171                        }
    13221172                    } /* while (i < pExtent->cGDEntries) */
    1323 
    13241173                    /** @todo figure out what to do for unclean VMDKs. */
    13251174                    if (pTmpGT1)
     
    13371186                           N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname, rc);
    13381187    }
    1339 
    13401188    if (RT_FAILURE(rc))
    13411189        vmdkFreeGrainDirectory(pExtent);
    13421190    return rc;
    13431191}
    1344 
    13451192/**
    13461193 * Creates a new grain directory for the given extent at the given start sector.
     
    13611208    size_t cbGTRounded;
    13621209    uint64_t cbOverhead;
    1363 
    13641210    if (fPreAlloc)
    13651211    {
     
    13751221        cbOverhead = VMDK_SECTOR2BYTE(uStartSector) + cbGDRounded;
    13761222    }
    1377 
    13781223    /* For streamOptimized extents there is only one grain directory,
    13791224     * and for all others take redundant grain directory into account. */
     
    13901235        rc = vdIfIoIntFileSetSize(pImage->pIfIo, pExtent->pFile->pStorage, cbOverhead);
    13911236    }
    1392 
    13931237    if (RT_SUCCESS(rc))
    13941238    {
    13951239        pExtent->uAppendPosition = cbOverhead;
    13961240        pExtent->cOverheadSectors = VMDK_BYTE2SECTOR(cbOverhead);
    1397 
    13981241        if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    13991242        {
     
    14061249            pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded);
    14071250        }
    1408 
    14091251        rc = vmdkAllocStreamBuffers(pImage, pExtent);
    14101252        if (RT_SUCCESS(rc))
     
    14161258                uint32_t uGTSectorLE;
    14171259                uint64_t uOffsetSectors;
    1418 
    14191260                if (pExtent->pRGD)
    14201261                {
     
    14361277                    }
    14371278                }
    1438 
    14391279                if (RT_SUCCESS(rc))
    14401280                {
     
    14591299        }
    14601300    }
    1461 
    14621301    if (RT_FAILURE(rc))
    14631302        vmdkFreeGrainDirectory(pExtent);
    14641303    return rc;
    14651304}
    1466 
    14671305/**
    14681306 * Unquotes the given string returning the result in a separate buffer.
     
    14821320    char *pszQ;
    14831321    char *pszUnquoted;
    1484 
    14851322    /* Skip over whitespace. */
    14861323    while (*pszStr == ' ' || *pszStr == '\t')
    14871324        pszStr++;
    1488 
    14891325    if (*pszStr != '"')
    14901326    {
     
    15011337                             pImage->pszFilename, pszStart);
    15021338    }
    1503 
    15041339    pszUnquoted = (char *)RTMemTmpAlloc(pszQ - pszStr + 1);
    15051340    if (!pszUnquoted)
     
    15121347    return VINF_SUCCESS;
    15131348}
    1514 
    15151349static int vmdkDescInitStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    15161350                           const char *pszLine)
     
    15181352    char *pEnd = pDescriptor->aLines[pDescriptor->cLines];
    15191353    ssize_t cbDiff = strlen(pszLine) + 1;
    1520 
    15211354    if (    pDescriptor->cLines >= VMDK_DESCRIPTOR_LINES_MAX - 1
    15221355        &&  pEnd - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff)
    15231356        return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
    1524 
    15251357    memcpy(pEnd, pszLine, cbDiff);
    15261358    pDescriptor->cLines++;
    15271359    pDescriptor->aLines[pDescriptor->cLines] = pEnd + cbDiff;
    15281360    pDescriptor->fDirty = true;
    1529 
    15301361    return VINF_SUCCESS;
    15311362}
    1532 
    15331363static bool vmdkDescGetStr(PVMDKDESCRIPTOR pDescriptor, unsigned uStart,
    15341364                           const char *pszKey, const char **ppszValue)
     
    15361366    size_t cbKey = strlen(pszKey);
    15371367    const char *pszValue;
    1538 
    15391368    while (uStart != 0)
    15401369    {
     
    15551384    return !!uStart;
    15561385}
    1557 
    15581386static int vmdkDescSetStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    15591387                          unsigned uStart,
     
    15631391    size_t cbKey = strlen(pszKey);
    15641392    unsigned uLast = 0;
    1565 
    15661393    while (uStart != 0)
    15671394    {
     
    15981425                > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff)
    15991426                return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
    1600 
    16011427            memmove(pszTmp + cbNewVal, pszTmp + cbOldVal,
    16021428                    pDescriptor->aLines[pDescriptor->cLines] - pszTmp - cbOldVal);
     
    16611487        for (unsigned i = uStart + 1; i <= pDescriptor->cLines; i++)
    16621488            pDescriptor->aLines[i] += cbDiff;
    1663 
    16641489        /* Adjust starting line numbers of following descriptor sections. */
    16651490        if (uStart <= pDescriptor->uFirstExtent)
     
    16711496    return VINF_SUCCESS;
    16721497}
    1673 
    16741498static int vmdkDescBaseGetU32(PVMDKDESCRIPTOR pDescriptor, const char *pszKey,
    16751499                              uint32_t *puValue)
    16761500{
    16771501    const char *pszValue;
    1678 
    16791502    if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDesc, pszKey,
    16801503                        &pszValue))
     
    16821505    return RTStrToUInt32Ex(pszValue, NULL, 10, puValue);
    16831506}
    1684 
    16851507/**
    16861508 * Returns the value of the given key as a string allocating the necessary memory.
     
    16991521    const char *pszValue;
    17001522    char *pszValueUnquoted;
    1701 
    17021523    if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDesc, pszKey,
    17031524                        &pszValue))
     
    17091530    return rc;
    17101531}
    1711 
    17121532static int vmdkDescBaseSetStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    17131533                              const char *pszKey, const char *pszValue)
    17141534{
    17151535    char *pszValueQuoted;
    1716 
    17171536    RTStrAPrintf(&pszValueQuoted, "\"%s\"", pszValue);
    17181537    if (!pszValueQuoted)
     
    17231542    return rc;
    17241543}
    1725 
    17261544static void vmdkDescExtRemoveDummy(PVMDKIMAGE pImage,
    17271545                                   PVMDKDESCRIPTOR pDescriptor)
     
    17301548    unsigned uEntry = pDescriptor->uFirstExtent;
    17311549    ssize_t cbDiff;
    1732 
    17331550    if (!uEntry)
    17341551        return;
    1735 
    17361552    cbDiff = strlen(pDescriptor->aLines[uEntry]) + 1;
    17371553    /* Move everything including \0 in the entry marking the end of buffer. */
     
    17491565    if (pDescriptor->uFirstDDB)
    17501566        pDescriptor->uFirstDDB--;
    1751 
    17521567    return;
    17531568}
    1754 
    17551569static int vmdkDescExtInsert(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    17561570                             VMDKACCESS enmAccess, uint64_t cNominalSectors,
     
    17641578    char szExt[1024];
    17651579    ssize_t cbDiff;
    1766 
    17671580    Assert((unsigned)enmAccess < RT_ELEMENTS(apszAccess));
    17681581    Assert((unsigned)enmType < RT_ELEMENTS(apszType));
    1769 
    17701582    /* Find last entry in extent description. */
    17711583    while (uStart)
     
    17751587        uStart = pDescriptor->aNextLines[uStart];
    17761588    }
    1777 
    17781589    if (enmType == VMDKETYPE_ZERO)
    17791590    {
     
    17941605    }
    17951606    cbDiff = strlen(szExt) + 1;
    1796 
    17971607    /* Check for buffer overflow. */
    17981608    if (   (pDescriptor->cLines >= VMDK_DESCRIPTOR_LINES_MAX - 1)
     
    18001610            - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff))
    18011611        return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
    1802 
    18031612    for (unsigned i = pDescriptor->cLines + 1; i > uLast + 1; i--)
    18041613    {
     
    18191628    for (unsigned i = uStart + 1; i <= pDescriptor->cLines; i++)
    18201629        pDescriptor->aLines[i] += cbDiff;
    1821 
    18221630    /* Adjust starting line numbers of following descriptor sections. */
    18231631    if (uStart <= pDescriptor->uFirstDDB)
    18241632        pDescriptor->uFirstDDB++;
    1825 
    18261633    pDescriptor->fDirty = true;
    18271634    return VINF_SUCCESS;
    18281635}
    1829 
    18301636/**
    18311637 * Returns the value of the given key from the DDB as a string allocating
     
    18451651    const char *pszValue;
    18461652    char *pszValueUnquoted;
    1847 
    18481653    if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey,
    18491654                        &pszValue))
     
    18551660    return rc;
    18561661}
    1857 
    18581662static int vmdkDescDDBGetU32(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    18591663                             const char *pszKey, uint32_t *puValue)
     
    18611665    const char *pszValue;
    18621666    char *pszValueUnquoted;
    1863 
    18641667    if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey,
    18651668                        &pszValue))
     
    18721675    return rc;
    18731676}
    1874 
    18751677static int vmdkDescDDBGetUuid(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    18761678                              const char *pszKey, PRTUUID pUuid)
     
    18781680    const char *pszValue;
    18791681    char *pszValueUnquoted;
    1880 
    18811682    if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey,
    18821683                        &pszValue))
     
    18891690    return rc;
    18901691}
    1891 
    18921692static int vmdkDescDDBSetStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    18931693                             const char *pszKey, const char *pszVal)
     
    18951695    int rc;
    18961696    char *pszValQuoted;
    1897 
    18981697    if (pszVal)
    18991698    {
     
    19101709    return rc;
    19111710}
    1912 
    19131711static int vmdkDescDDBSetUuid(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    19141712                              const char *pszKey, PCRTUUID pUuid)
    19151713{
    19161714    char *pszUuid;
    1917 
    19181715    RTStrAPrintf(&pszUuid, "\"%RTuuid\"", pUuid);
    19191716    if (!pszUuid)
     
    19241721    return rc;
    19251722}
    1926 
    19271723static int vmdkDescDDBSetU32(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor,
    19281724                             const char *pszKey, uint32_t uValue)
    19291725{
    19301726    char *pszValue;
    1931 
    19321727    RTStrAPrintf(&pszValue, "\"%d\"", uValue);
    19331728    if (!pszValue)
     
    19381733    return rc;
    19391734}
    1940 
    19411735/**
    19421736 * Splits the descriptor data into individual lines checking for correct line
     
    19521746    unsigned cLine = 0;
    19531747    int rc = VINF_SUCCESS;
    1954 
    19551748    while (   RT_SUCCESS(rc)
    19561749           && *pszTmp != '\0')
     
    19631756            break;
    19641757        }
    1965 
    19661758        while (*pszTmp != '\0' && *pszTmp != '\n')
    19671759        {
     
    19811773            pszTmp++;
    19821774        }
    1983 
    19841775        if (RT_FAILURE(rc))
    19851776            break;
    1986 
    19871777        /* Get rid of LF character. */
    19881778        if (*pszTmp == '\n')
     
    19921782        }
    19931783    }
    1994 
    19951784    if (RT_SUCCESS(rc))
    19961785    {
     
    19991788        pDesc->aLines[cLine] = pszTmp;
    20001789    }
    2001 
    2002     return rc;
    2003 }
    2004 
     1790    return rc;
     1791}
    20051792static int vmdkPreprocessDescriptor(PVMDKIMAGE pImage, char *pDescData,
    20061793                                    size_t cbDescData, PVMDKDESCRIPTOR pDescriptor)
     
    20191806        {
    20201807            unsigned uLastNonEmptyLine = 0;
    2021 
    20221808            /* Initialize those, because we need to be able to reopen an image. */
    20231809            pDescriptor->uFirstDesc = 0;
     
    20851871        }
    20861872    }
    2087 
    2088     return rc;
    2089 }
    2090 
     1873    return rc;
     1874}
    20911875static int vmdkDescSetPCHSGeometry(PVMDKIMAGE pImage,
    20921876                                   PCVDGEOMETRY pPCHSGeometry)
     
    21071891    return rc;
    21081892}
    2109 
    21101893static int vmdkDescSetLCHSGeometry(PVMDKIMAGE pImage,
    21111894                                   PCVDGEOMETRY pLCHSGeometry)
     
    21181901    rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor,
    21191902                           VMDK_DDB_GEO_LCHS_HEADS,
    2120 
    21211903                           pLCHSGeometry->cHeads);
    21221904    if (RT_FAILURE(rc))
     
    21271909    return rc;
    21281910}
    2129 
    21301911static int vmdkCreateDescriptor(PVMDKIMAGE pImage, char *pDescData,
    21311912                                size_t cbDescData, PVMDKDESCRIPTOR pDescriptor)
     
    21391920    pDescriptor->aLines[pDescriptor->cLines] = pDescData;
    21401921    memset(pDescriptor->aNextLines, '\0', sizeof(pDescriptor->aNextLines));
    2141 
    21421922    int rc = vmdkDescInitStr(pImage, pDescriptor, "# Disk DescriptorFile");
    21431923    if (RT_SUCCESS(rc))
     
    21711951    {
    21721952        pDescriptor->uFirstDDB = pDescriptor->cLines - 1;
    2173 
    21741953        /* Now that the framework is in place, use the normal functions to insert
    21751954         * the remaining keys. */
     
    21841963    if (RT_SUCCESS(rc))
    21851964        rc = vmdkDescDDBSetStr(pImage, pDescriptor, "ddb.adapterType", "ide");
    2186 
    2187     return rc;
    2188 }
    2189 
     1965    return rc;
     1966}
    21901967static int vmdkParseDescriptor(PVMDKIMAGE pImage, char *pDescData, size_t cbDescData)
    21911968{
     
    21941971    unsigned uLine;
    21951972    unsigned i;
    2196 
    21971973    rc = vmdkPreprocessDescriptor(pImage, pDescData, cbDescData,
    21981974                                  &pImage->Descriptor);
    21991975    if (RT_FAILURE(rc))
    22001976        return rc;
    2201 
    22021977    /* Check version, must be 1. */
    22031978    uint32_t uVersion;
     
    22071982    if (uVersion != 1)
    22081983        return vdIfError(pImage->pIfError, VERR_VD_VMDK_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: unsupported format version in descriptor in '%s'"), pImage->pszFilename);
    2209 
    22101984    /* Get image creation type and determine image flags. */
    22111985    char *pszCreateType = NULL;   /* initialized to make gcc shut up */
     
    22251999        pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED | VD_VMDK_IMAGE_FLAGS_ESX;
    22262000    RTMemTmpFree(pszCreateType);
    2227 
    22282001    /* Count the number of extent config entries. */
    22292002    for (uLine = pImage->Descriptor.uFirstExtent, cExtents = 0;
     
    22312004         uLine = pImage->Descriptor.aNextLines[uLine], cExtents++)
    22322005        /* nothing */;
    2233 
    22342006    if (!pImage->pDescData && cExtents != 1)
    22352007    {
     
    22372009        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);
    22382010    }
    2239 
    22402011    if (pImage->pDescData)
    22412012    {
     
    22452016            return rc;
    22462017    }
    2247 
    22482018    for (i = 0, uLine = pImage->Descriptor.uFirstExtent;
    22492019         i < cExtents; i++, uLine = pImage->Descriptor.aNextLines[uLine])
    22502020    {
    22512021        char *pszLine = pImage->Descriptor.aLines[uLine];
    2252 
    22532022        /* Access type of the extent. */
    22542023        if (!strncmp(pszLine, "RW", 2))
     
    22712040        if (*pszLine++ != ' ')
    22722041            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
    2273 
    22742042        /* Nominal size of the extent. */
    22752043        rc = RTStrToUInt64Ex(pszLine, &pszLine, 10,
     
    22792047        if (*pszLine++ != ' ')
    22802048            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
    2281 
    22822049        /* Type of the extent. */
    22832050        if (!strncmp(pszLine, "SPARSE", 6))
     
    23032070        else
    23042071            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
    2305 
    23062072        if (pImage->pExtents[i].enmType == VMDKETYPE_ZERO)
    23072073        {
     
    23182084            if (*pszLine++ != ' ')
    23192085                return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
    2320 
    23212086            /* Basename of the image. Surrounded by quotes. */
    23222087            char *pszBasename;
     
    23372102                }
    23382103            }
    2339 
    23402104            if (*pszLine != '\0')
    23412105                return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
    23422106        }
    23432107    }
    2344 
    23452108    /* Determine PCHS geometry (autogenerate if necessary). */
    23462109    rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor,
     
    23772140        pImage->PCHSGeometry.cSectors = 63;
    23782141    }
    2379 
    23802142    /* Determine LCHS geometry (set to 0 if not specified). */
    23812143    rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor,
     
    24082170        pImage->LCHSGeometry.cSectors = 0;
    24092171    }
    2410 
    24112172    /* Get image UUID. */
    24122173    rc = vmdkDescDDBGetUuid(pImage, &pImage->Descriptor, VMDK_DDB_IMAGE_UUID,
     
    24322193    else if (RT_FAILURE(rc))
    24332194        return rc;
    2434 
    24352195    /* Get image modification UUID. */
    24362196    rc = vmdkDescDDBGetUuid(pImage, &pImage->Descriptor,
     
    24582218    else if (RT_FAILURE(rc))
    24592219        return rc;
    2460 
    24612220    /* Get UUID of parent image. */
    24622221    rc = vmdkDescDDBGetUuid(pImage, &pImage->Descriptor, VMDK_DDB_PARENT_UUID,
     
    24822241    else if (RT_FAILURE(rc))
    24832242        return rc;
    2484 
    24852243    /* Get parent image modification UUID. */
    24862244    rc = vmdkDescDDBGetUuid(pImage, &pImage->Descriptor,
     
    25062264    else if (RT_FAILURE(rc))
    25072265        return rc;
    2508 
    25092266    return VINF_SUCCESS;
    25102267}
    2511 
    25122268/**
    25132269 * Internal : Prepares the descriptor to write to the image.
     
    25172273{
    25182274    int rc = VINF_SUCCESS;
    2519 
    25202275    /*
    25212276     * Allocate temporary descriptor buffer.
     
    25262281    char *pszDescriptor = (char *)RTMemAllocZ(cbDescriptor);
    25272282    size_t offDescriptor = 0;
    2528 
    25292283    if (!pszDescriptor)
    25302284        return VERR_NO_MEMORY;
    2531 
    25322285    for (unsigned i = 0; i < pImage->Descriptor.cLines; i++)
    25332286    {
    25342287        const char *psz = pImage->Descriptor.aLines[i];
    25352288        size_t cb = strlen(psz);
    2536 
    25372289        /*
    25382290         * Increase the descriptor if there is no limit and
     
    25502302                char *pszDescriptorNew = NULL;
    25512303                LogFlow(("Increasing descriptor cache\n"));
    2552 
    25532304                pszDescriptorNew = (char *)RTMemRealloc(pszDescriptor, cbDescriptor + cb + 4 * _1K);
    25542305                if (!pszDescriptorNew)
     
    25612312            }
    25622313        }
    2563 
    25642314        if (cb > 0)
    25652315        {
     
    25672317            offDescriptor += cb;
    25682318        }
    2569 
    25702319        memcpy(pszDescriptor + offDescriptor, "\n", 1);
    25712320        offDescriptor++;
    25722321    }
    2573 
    25742322    if (RT_SUCCESS(rc))
    25752323    {
     
    25792327    else if (pszDescriptor)
    25802328        RTMemFree(pszDescriptor);
    2581 
    2582     return rc;
    2583 }
    2584 
     2329    return rc;
     2330}
    25852331/**
    25862332 * Internal: write/update the descriptor part of the image.
     
    25942340    void *pvDescriptor = NULL;
    25952341    size_t cbDescriptor;
    2596 
    25972342    if (pImage->pDescData)
    25982343    {
     
    26122357    if (pDescFile == NULL)
    26132358        return VERR_INVALID_PARAMETER;
    2614 
    26152359    rc = vmdkDescriptorPrepare(pImage, cbLimit, &pvDescriptor, &cbDescriptor);
    26162360    if (RT_SUCCESS(rc))
     
    26242368            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
    26252369    }
    2626 
    26272370    if (RT_SUCCESS(rc) && !cbLimit)
    26282371    {
     
    26312374            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
    26322375    }
    2633 
    26342376    if (RT_SUCCESS(rc))
    26352377        pImage->Descriptor.fDirty = false;
    2636 
    26372378    if (pvDescriptor)
    26382379        RTMemFree(pvDescriptor);
    26392380    return rc;
    2640 
    2641 }
    2642 
     2381}
    26432382/**
    26442383 * Internal: validate the consistency check values in a binary header.
     
    26742413    return rc;
    26752414}
    2676 
    26772415/**
    26782416 * Internal: read metadata belonging to an extent with binary header, i.e.
     
    26842422    SparseExtentHeader Header;
    26852423    int rc;
    2686 
    26872424    if (!fMagicAlreadyRead)
    26882425        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage, 0,
     
    26972434                                   - RT_UOFFSETOF(SparseExtentHeader, version));
    26982435    }
    2699 
    27002436    if (RT_SUCCESS(rc))
    27012437    {
     
    27042440        {
    27052441            uint64_t cbFile = 0;
    2706 
    27072442            if (    (RT_LE2H_U32(Header.flags) & RT_BIT(17))
    27082443                &&  RT_LE2H_U64(Header.gdOffset) == VMDK_GD_AT_END)
    27092444                pExtent->fFooter = true;
    2710 
    27112445            if (   !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    27122446                || (   pExtent->fFooter
     
    27172451                    rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname);
    27182452            }
    2719 
    27202453            if (RT_SUCCESS(rc))
    27212454            {
    27222455                if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    27232456                    pExtent->uAppendPosition = RT_ALIGN_64(cbFile, 512);
    2724 
    27252457                if (   pExtent->fFooter
    27262458                    && (   !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     
    27362468                        rc = VERR_VD_VMDK_INVALID_HEADER;
    27372469                    }
    2738 
    27392470                    if (RT_SUCCESS(rc))
    27402471                        rc = vmdkValidateHeader(pImage, pExtent, &Header);
     
    27422473                    pExtent->uAppendPosition = 0;
    27432474                }
    2744 
    27452475                if (RT_SUCCESS(rc))
    27462476                {
     
    27652495                        pExtent->uSectorRGD     = 0;
    27662496                    }
    2767 
    27682497                    if (pExtent->uDescriptorSector && !pExtent->cDescriptorSectors)
    27692498                        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS,
    27702499                                       N_("VMDK: inconsistent embedded descriptor config in '%s'"), pExtent->pszFullname);
    2771 
    27722500                    if (   RT_SUCCESS(rc)
    27732501                        && (   pExtent->uSectorGD == VMDK_GD_AT_END
     
    27772505                        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS,
    27782506                                       N_("VMDK: cannot resolve grain directory offset in '%s'"), pExtent->pszFullname);
    2779 
    27802507                    if (RT_SUCCESS(rc))
    27812508                    {
     
    27882515                            pExtent->cSectorsPerGDE = cSectorsPerGDE;
    27892516                            pExtent->cGDEntries = (pExtent->cSectors + cSectorsPerGDE - 1) / cSectorsPerGDE;
    2790 
    27912517                            /* Fix up the number of descriptor sectors, as some flat images have
    27922518                             * really just one, and this causes failures when inserting the UUID
     
    28112537        rc = VERR_VD_VMDK_INVALID_HEADER;
    28122538    }
    2813 
    28142539    if (RT_FAILURE(rc))
    28152540        vmdkFreeExtentData(pImage, pExtent, false);
    2816 
    2817     return rc;
    2818 }
    2819 
     2541    return rc;
     2542}
    28202543/**
    28212544 * Internal: read additional metadata belonging to an extent. For those
     
    28252548{
    28262549    int rc = VINF_SUCCESS;
    2827 
    28282550/* disabled the check as there are too many truncated vmdk images out there */
    28292551#ifdef VBOX_WITH_VMDK_STRICT_SIZE_CHECK
     
    28652587                    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    28662588                        pExtent->uAppendPosition = 0;
    2867 
    28682589                    if (   !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    28692590                        || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     
    28792600        }
    28802601    }
    2881 
    28822602    if (RT_FAILURE(rc))
    28832603        vmdkFreeExtentData(pImage, pExtent, false);
    2884 
    2885     return rc;
    2886 }
    2887 
     2604    return rc;
     2605}
    28882606/**
    28892607 * Internal: write/update the metadata for a sparse extent.
     
    28932611{
    28942612    SparseExtentHeader Header;
    2895 
    28962613    memset(&Header, '\0', sizeof(Header));
    28972614    Header.magicNumber = RT_H2LE_U32(VMDK_SPARSE_MAGICNUMBER);
     
    29362653    Header.doubleEndLineChar2 = '\n';
    29372654    Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);
    2938 
    29392655    int rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pExtent->pFile->pStorage,
    29402656                                    uOffset, &Header, sizeof(Header),
     
    29442660    return rc;
    29452661}
    2946 
    29472662/**
    29482663 * Internal: free the buffers used for streamOptimized images.
     
    29612676    }
    29622677}
    2963 
    29642678/**
    29652679 * Internal: free the memory used by the extent data structure, optionally
     
    29752689{
    29762690    int rc = VINF_SUCCESS;
    2977 
    29782691    vmdkFreeGrainDirectory(pExtent);
    29792692    if (pExtent->pDescData)
     
    30022715    }
    30032716    vmdkFreeStreamBuffers(pExtent);
    3004 
    3005     return rc;
    3006 }
    3007 
     2717    return rc;
     2718}
    30082719/**
    30092720 * Internal: allocate grain table cache if necessary for this image.
     
    30122723{
    30132724    PVMDKEXTENT pExtent;
    3014 
    30152725    /* Allocate grain table cache if any sparse extent is present. */
    30162726    for (unsigned i = 0; i < pImage->cExtents; i++)
     
    30322742        }
    30332743    }
    3034 
    30352744    return VINF_SUCCESS;
    30362745}
    3037 
    30382746/**
    30392747 * Internal: allocate the given number of extents.
     
    30632771    else
    30642772        rc = VERR_NO_MEMORY;
    3065 
    3066     return rc;
    3067 }
    3068 
     2773    return rc;
     2774}
    30692775/**
    30702776 * Reads and processes the descriptor embedded in sparse images.
     
    31142820                {
    31152821                    uint64_t cDescriptorSectorsOld = pExtent->cDescriptorSectors;
    3116 
    31172822                    pExtent->cDescriptorSectors = 4;
    31182823                    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     
    31792884            rc = VERR_NO_MEMORY;
    31802885    }
    3181 
    3182     return rc;
    3183 }
    3184 
     2886    return rc;
     2887}
    31852888/**
    31862889 * Reads the descriptor from a pure text file.
     
    32692972                        else
    32702973                            pExtent->pszFullname = NULL;
    3271 
    32722974                        unsigned uOpenFlags = pImage->uOpenFlags | ((pExtent->enmAccess == VMDKACCESS_READONLY) ? VD_OPEN_FLAGS_READONLY : 0);
    32732975                        switch (pExtent->enmType)
     
    32902992                                if (RT_FAILURE(rc))
    32912993                                    break;
    3292 
    32932994                                /* Mark extent as unclean if opened in read-write mode. */
    32942995                                if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     
    33273028    else if (RT_SUCCESS(rc))
    33283029        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor in '%s' is too short"), pImage->pszFilename);
    3329 
    3330     return rc;
    3331 }
    3332 
     3030    return rc;
     3031}
    33333032/**
    33343033 * Read and process the descriptor based on the image type.
     
    33413040{
    33423041    uint32_t u32Magic;
    3343 
    33443042    /* Read magic (if present). */
    33453043    int rc = vdIfIoIntFileReadSync(pImage->pIfIo, pFile->pStorage, 0,
     
    33583056        rc = VERR_VD_VMDK_INVALID_HEADER;
    33593057    }
    3360 
    3361     return rc;
    3362 }
    3363 
     3058    return rc;
     3059}
    33643060/**
    33653061 * Internal: Open an image, constructing all necessary data structures.
     
    33713067    pImage->pIfIo      = VDIfIoIntGet(pImage->pVDIfsImage);
    33723068    AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
    3373 
    33743069    /*
    33753070     * Open the image.
     
    33843079    {
    33853080        pImage->pFile = pFile;
    3386 
    33873081        rc = vmdkDescriptorRead(pImage, pFile);
    33883082        if (RT_SUCCESS(rc))
     
    34023096                }
    34033097            }
    3404 
    34053098            /* Update the image metadata now in case has changed. */
    34063099            rc = vmdkFlushImage(pImage, NULL);
     
    34223115                             ||  pExtent->enmType == VMDKETYPE_ZERO)
    34233116                        pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED;
    3424 
    34253117                    pImage->cbSize += VMDK_SECTOR2BYTE(pExtent->cNominalSectors);
    34263118                }
    3427 
    34283119                if (   !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    34293120                    || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     
    34353126    /* else: Do NOT signal an appropriate error here, as the VD layer has the
    34363127     *       choice of retrying the open if it failed. */
    3437 
    34383128    if (RT_SUCCESS(rc))
    34393129    {
     
    34413131        pImage->RegionList.fFlags   = 0;
    34423132        pImage->RegionList.cRegions = 1;
    3443 
    34443133        pRegion->offRegion            = 0; /* Disk start. */
    34453134        pRegion->cbBlock              = 512;
     
    34543143    return rc;
    34553144}
    3456 
    34573145/**
    34583146 * Frees a raw descriptor.
     
    34633151    if (!pRawDesc)
    34643152        return VINF_SUCCESS;
    3465 
    34663153    RTStrFree(pRawDesc->pszRawDisk);
    34673154    pRawDesc->pszRawDisk = NULL;
    3468 
    34693155    /* Partitions: */
    34703156    for (unsigned i = 0; i < pRawDesc->cPartDescs; i++)
     
    34723158        RTStrFree(pRawDesc->pPartDescs[i].pszRawDevice);
    34733159        pRawDesc->pPartDescs[i].pszRawDevice = NULL;
    3474 
    34753160        RTMemFree(pRawDesc->pPartDescs[i].pvPartitionData);
    34763161        pRawDesc->pPartDescs[i].pvPartitionData = NULL;
    34773162    }
    3478 
    34793163    RTMemFree(pRawDesc->pPartDescs);
    34803164    pRawDesc->pPartDescs = NULL;
    3481 
    34823165    RTMemFree(pRawDesc);
    34833166    return VINF_SUCCESS;
    34843167}
    3485 
    34863168/**
    34873169 * Helper that grows the raw partition descriptor table by @a cToAdd entries,
     
    35003182        pRawDesc->cPartDescs = cNew;
    35013183        pRawDesc->pPartDescs = paNew;
    3502 
    35033184        *ppRet = &paNew[cOld];
    35043185        return VINF_SUCCESS;
     
    35093190                     pImage->pszFilename, cOld, cNew);
    35103191}
    3511 
    35123192/**
    35133193 * @callback_method_impl{FNRTSORTCMP}
     
    35193199    return iDelta < 0 ? -1 : iDelta > 0 ? 1 : 0;
    35203200}
    3521 
    35223201/**
    35233202 * Post processes the partition descriptors.
     
    35313210     */
    35323211    RTSortShell(pRawDesc->pPartDescs, pRawDesc->cPartDescs, sizeof(pRawDesc->pPartDescs[0]), vmdkRawDescPartComp, NULL);
    3533 
    35343212    /*
    35353213     * Check that we don't have overlapping descriptors.  If we do, that's an
     
    35463224                             paPartDescs[i].pvPartitionData ? " (data)" : "");
    35473225        offLast -= 1;
    3548 
    35493226        if (i + 1 < pRawDesc->cPartDescs && offLast >= paPartDescs[i + 1].offStartInVDisk)
    35503227            return vdIfError(pImage->pIfError, VERR_FILESYSTEM_CORRUPT /*?*/, RT_SRC_POS,
     
    35593236                             paPartDescs[i].pvPartitionData ? " (data)" : "", cbSize);
    35603237    }
    3561 
    35623238    return VINF_SUCCESS;
    35633239}
    3564 
    3565 
    35663240#ifdef RT_OS_LINUX
    35673241/**
     
    35863260    size_t const cchDir = RTPathEnsureTrailingSeparator(pszBlockDevDir, cbBlockDevDir);
    35873261    AssertReturn(cchDir > 0, VERR_BUFFER_OVERFLOW);
    3588 
    35893262    RTDIR hDir = NIL_RTDIR;
    35903263    int rc = RTDirOpen(&hDir, pszBlockDevDir);
     
    36043277                    rc = RTStrCopy(&pszBlockDevDir[cchDir], cbBlockDevDir - cchDir, Entry.szName);
    36053278                    AssertContinue(RT_SUCCESS(rc)); /* should not happen! */
    3606 
    36073279                    dev_t uThisDevNo = ~uDevToLocate;
    36083280                    rc = RTLinuxSysFsReadDevNumFile(&uThisDevNo, "%s/dev", pszBlockDevDir);
     
    36343306}
    36353307#endif /* RT_OS_LINUX */
    3636 
    36373308#ifdef RT_OS_FREEBSD
    3638 
    3639 
    36403309/**
    36413310 * Reads the config data from the provider and returns offset and size
     
    36503319    gconfig *pConfEntry;
    36513320    int rc = VERR_NOT_FOUND;
    3652 
    36533321    /*
    36543322     * Required parameters are located in the list containing key/value pairs.
     
    36813349    return rc;
    36823350}
    3683 
    3684 
    36853351/**
    36863352 * Searches the partition specified by name and calculates its size and absolute offset.
     
    37013367    AssertReturn(pcbAbsoluteOffset,  VERR_INVALID_PARAMETER);
    37023368    AssertReturn(pcbSize,            VERR_INVALID_PARAMETER);
    3703 
    37043369    ggeom *pParentGeom;
    37053370    int rc = VERR_NOT_FOUND;
     
    37143379    if (RT_FAILURE(rc))
    37153380        return rc;
    3716 
    37173381    gprovider *pProvider;
    37183382    /*
     
    37263390            return vmdkReadPartitionsParamsFromProvider(pProvider, pcbAbsoluteOffset, pcbSize);
    37273391    }
    3728 
    37293392    /*
    37303393     * No provider found. Go over the parent geom again
     
    37363399     * provider
    37373400     */
    3738 
    37393401    LIST_FOREACH(pProvider, &pParentGeom->lg_provider, lg_provider)
    37403402    {
     
    37443406        if (RT_FAILURE(rc))
    37453407            return rc;
    3746 
    37473408        uint64_t cbProviderOffset = 0;
    37483409        uint64_t cbProviderSize = 0;
     
    37553416        }
    37563417    }
    3757 
    37583418    return VERR_NOT_FOUND;
    37593419}
    37603420#endif
    3761 
    3762 
    37633421/**
    37643422 * Attempts to verify the raw partition path.
     
    37703428{
    37713429    RT_NOREF(pImage, pPartDesc, idxPartition, pszRawDrive, hRawDrive, cbSector, hVol);
    3772 
    37733430    /*
    37743431     * Try open the raw partition device.
     
    37803437                         N_("VMDK: Image path: '%s'. Failed to open partition #%u on '%s' via '%s' (%Rrc)"),
    37813438                         pImage->pszFilename, idxPartition, pszRawDrive, pPartDesc->pszRawDevice, rc);
    3782 
    37833439    /*
    37843440     * Compare the partition UUID if we can get it.
     
    37863442#ifdef RT_OS_WINDOWS
    37873443    DWORD cbReturned;
    3788 
    37893444    /* 1. Get the device numbers for both handles, they should have the same disk. */
    37903445    STORAGE_DEVICE_NUMBER DevNum1;
     
    37953450                       N_("VMDK: Image path: '%s'. IOCTL_STORAGE_GET_DEVICE_NUMBER failed on '%s': %u"),
    37963451                       pImage->pszFilename, pszRawDrive, GetLastError());
    3797 
    37983452    STORAGE_DEVICE_NUMBER DevNum2;
    37993453    RT_ZERO(DevNum2);
     
    38873541            rc = VERR_NO_TMP_MEMORY;
    38883542    }
    3889 
    38903543#elif defined(RT_OS_LINUX)
    38913544    RT_NOREF(hVol);
    3892 
    38933545    /* Stat the two devices first to get their device numbers.  (We probably
    38943546       could make some assumptions here about the major & minor number assignments
     
    39113563        {
    39123564            rc = vmdkFindSysBlockDevPath(pImage, szSysPath, sizeof(szSysPath), StDrive.st_rdev, pszRawDrive);
    3913 
    39143565            /* Now, scan the directories under that again for a partition device
    39153566               matching the hRawPart device's number: */
    39163567            if (RT_SUCCESS(rc))
    39173568                rc = vmdkFindSysBlockDevPath(pImage, szSysPath, sizeof(szSysPath), StPart.st_rdev, pPartDesc->pszRawDevice);
    3918 
    39193569            /* Having found the /sys/block/device/partition/ path, we can finally
    39203570               read the partition attributes and compare with hVol. */
     
    39293579                                   pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, iLnxPartition, idxPartition);
    39303580                /* else: ignore failure? */
    3931 
    39323581                /* start offset: */
    39333582                uint32_t const cbLnxSector = 512; /* It's hardcoded in the Linux kernel */
     
    39433592                    /* else: ignore failure? */
    39443593                }
    3945 
    39463594                /* the size: */
    39473595                if (RT_SUCCESS(rc))
     
    39603608        /* else: We've got nothing to work on, so only do content comparison. */
    39613609    }
    3962 
    39633610#elif defined(RT_OS_FREEBSD)
    39643611    char szDriveDevName[256];
     
    39913638                rc = vdIfError(pImage->pIfError, VERR_GENERAL_FAILURE, RT_SRC_POS,
    39923639                               N_("VMDK: Image path: '%s'. 'PART' class not found in the GEOM tree"), pImage->pszFilename);
    3993 
    3994 
    39953640            if (RT_SUCCESS(rc))
    39963641            {
     
    40153660                                   pImage->pszFilename, pPartDesc->pszRawDevice, pszRawDrive, rc);
    40163661            }
    4017 
    40183662            geom_deletetree(&geomMesh);
    40193663        }
     
    40223666                           N_("VMDK: Image path: '%s'. geom_gettree failed: %d"), pImage->pszFilename, err);
    40233667    }
    4024 
    40253668#elif defined(RT_OS_SOLARIS)
    40263669    RT_NOREF(hVol);
    4027 
    40283670    dk_cinfo dkiDriveInfo;
    40293671    dk_cinfo dkiPartInfo;
     
    40733715             * using another way. If there is an error, it returns errno which will be handled below.
    40743716             */
    4075 
    40763717            uint32_t numPartition = (uint32_t)dkiPartInfo.dki_partition;
    40773718            if (numPartition > NDKMAP)
     
    41083749                           N_("VMDK: Image path: '%s'. Partition #%u path ('%s') verification failed on '%s': Start offset %RI64, expected %RU64"),
    41093750                           pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, cbOffset, pPartDesc->offStartInVDisk);
    4110 
    41113751        if (RT_SUCCESS(rc) && cbSize != pPartDesc->cbData)
    41123752            rc = vdIfError(pImage->pIfError, VERR_MISMATCH, RT_SRC_POS,
     
    41143754                           pImage->pszFilename, idxPartition, pPartDesc->pszRawDevice, pszRawDrive, cbSize, pPartDesc->cbData);
    41153755    }
    4116 
    41173756#else
    41183757    RT_NOREF(hVol); /* PORTME */
     
    41323771        {
    41333772            uint8_t *pbSector2 = pbSector1 + cbToCompare;
    4134 
    41353773            /* Do the comparing, we repeat if it fails and the data might be volatile. */
    41363774            uint64_t uPrevCrc1 = 0;
     
    41483786                        {
    41493787                            rc = VERR_MISMATCH;
    4150 
    41513788                            /* Do data stability checks before repeating: */
    41523789                            uint64_t const uCrc1 = RTCrc64(pbSector1, cbToCompare);
     
    41813818                    offMissmatch++;
    41823819                int cbSample = (int)RT_MIN(cbToCompare - offMissmatch, 16);
    4183 
    41843820                if (cStable > 0)
    41853821                    rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS,
     
    41953831                }
    41963832            }
    4197 
    41983833            RTMemTmpFree(pbSector1);
    41993834        }
     
    42063841    return rc;
    42073842}
    4208 
    42093843#ifdef RT_OS_WINDOWS
    42103844/**
     
    42283862}
    42293863#endif /* RT_OS_WINDOWS */
    4230 
    42313864/**
    42323865 * Worker for vmdkMakeRawDescriptor that adds partition descriptors when the
     
    42453878{
    42463879    *phVolToRelease = NIL_RTDVMVOLUME;
    4247 
    42483880    /* Check sanity/understanding. */
    42493881    Assert(fPartitions);
    42503882    Assert((fPartitions & fPartitionsReadOnly) == fPartitionsReadOnly); /* RO should be a sub-set */
    4251 
    42523883    /*
    42533884     * Allocate on descriptor for each volume up front.
    42543885     */
    42553886    uint32_t const cVolumes = RTDvmMapGetValidVolumes(hVolMgr);
    4256 
    42573887    PVDISKRAWPARTDESC paPartDescs = NULL;
    42583888    int rc = vmdkRawDescAppendPartDesc(pImage, pRawDesc, cVolumes, &paPartDescs);
    42593889    AssertRCReturn(rc, rc);
    4260 
    42613890    /*
    42623891     * Enumerate the partitions (volumes) on the disk and create descriptors for each of them.
     
    42813910        Assert(cRefs != UINT32_MAX); RT_NOREF(cRefs);
    42823911        *phVolToRelease = hVol = hVolNext;
    4283 
    42843912        /*
    42853913         * Depending on the fPartitions selector and associated read-only mask,
     
    42883916         */
    42893917        paPartDescs[i].cbData = RTDvmVolumeGetSize(hVol);
    4290 
    42913918        uint64_t offVolumeEndIgnored = 0;
    42923919        rc = RTDvmVolumeQueryRange(hVol, &paPartDescs[i].offStartInVDisk, &offVolumeEndIgnored);
     
    42963923                             pImage->pszFilename, i, pszRawDrive, rc);
    42973924        Assert(paPartDescs[i].cbData == offVolumeEndIgnored + 1 - paPartDescs[i].offStartInVDisk);
    4298 
    42993925        /* Note! The index must match IHostDrivePartition::number. */
    43003926        uint32_t idxPartition = RTDvmVolumeGetIndex(hVol, RTDVMVOLIDX_HOST);
     
    43053931            if (fPartitionsReadOnly & RT_BIT_32(idxPartition))
    43063932                paPartDescs[i].uFlags |= VDISKRAW_READONLY;
    4307 
    43083933            if (!fRelative)
    43093934            {
     
    43263951                 */
    43273952                paPartDescs[i].offStartInDevice = 0;
    4328 
    43293953#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
    43303954                /* /dev/rdisk1 -> /dev/rdisk1s2 (s=slice) */
     
    43403964                if (pRawDesc->enmPartitioningType == VDISKPARTTYPE_MBR)
    43413965                {
    4342                     /* 
     3966                    /*
    43433967                     * MBR partitions have device nodes in form /dev/(r)dsk/cXtYdZpK
    43443968                     * where X is the controller,
     
    43804004#endif
    43814005                AssertPtrReturn(paPartDescs[i].pszRawDevice, VERR_NO_STR_MEMORY);
    4382 
    43834006                rc = vmdkRawDescVerifyPartitionPath(pImage, &paPartDescs[i], idxPartition, pszRawDrive, hRawDrive, cbSector, hVol);
    43844007                AssertRCReturn(rc, rc);
     
    43924015        }
    43934016    } /* for each volume */
    4394 
    43954017    RTDvmVolumeRelease(hVol);
    43964018    *phVolToRelease = NIL_RTDVMVOLUME;
    4397 
    43984019    /*
    43994020     * Check that we found all the partitions the user selected.
     
    44104031                             pImage->pszFilename, pszRawDrive, szLeft);
    44114032    }
    4412 
    44134033    return VINF_SUCCESS;
    44144034}
    4415 
    44164035/**
    44174036 * Worker for vmdkMakeRawDescriptor that adds partition descriptors with copies
     
    44444063                         pImage->pszFilename, pszRawDrive, rc);
    44454064    AssertReturn(cLocations > 0 && cLocations < _16M, VERR_INTERNAL_ERROR_5);
    4446 
    44474065    /* We can allocate the partition descriptors here to save an intentation level. */
    44484066    PVDISKRAWPARTDESC paPartDescs = NULL;
    44494067    rc = vmdkRawDescAppendPartDesc(pImage, pRawDesc, (uint32_t)cLocations, &paPartDescs);
    44504068    AssertRCReturn(rc, rc);
    4451 
    44524069    /* Allocate the result table and repeat the location table query: */
    44534070    PRTDVMTABLELOCATION paLocations = (PRTDVMTABLELOCATION)RTMemAllocZ(sizeof(paLocations[0]) * cLocations);
     
    45294146    return rc;
    45304147}
    4531 
    45324148/**
    45334149 * Opens the volume manager for the raw drive when in selected-partition mode.
     
    45454161{
    45464162    *phVolMgr = NIL_RTDVM;
    4547 
    45484163    RTVFSFILE hVfsFile = NIL_RTVFSFILE;
    45494164    int rc = RTVfsFileFromRTFile(hRawDrive, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, true /*fLeaveOpen*/, &hVfsFile);
     
    45524167                         N_("VMDK: Image path: '%s'.  RTVfsFileFromRTFile failed for '%s' handle (%Rrc)"),
    45534168                         pImage->pszFilename, pszRawDrive, rc);
    4554 
    45554169    RTDVM hVolMgr = NIL_RTDVM;
    45564170    rc = RTDvmCreate(&hVolMgr, hVfsFile, cbSector, 0 /*fFlags*/);
    4557 
    45584171    RTVfsFileRelease(hVfsFile);
    4559 
    45604172    if (RT_FAILURE(rc))
    45614173        return vdIfError(pImage->pIfError, rc, RT_SRC_POS,
    45624174                         N_("VMDK: Image path: '%s'. Failed to create volume manager instance for '%s' (%Rrc)"),
    45634175                         pImage->pszFilename, pszRawDrive, rc);
    4564 
    45654176    rc = RTDvmMapOpen(hVolMgr);
    45664177    if (RT_SUCCESS(rc))
     
    45734184                     pImage->pszFilename, pszRawDrive, rc);
    45744185}
    4575 
    45764186/**
    45774187 * Opens the raw drive device and get the sizes for it.
     
    45974207                         N_("VMDK: Image path: '%s'. Failed to open the raw drive '%s' for reading (%Rrc)"),
    45984208                         pImage->pszFilename, pszRawDrive, rc);
    4599 
    46004209    /*
    46014210     * Get the sector size.
     
    46464255    return rc;
    46474256}
    4648 
    46494257/**
    46504258 * Reads the raw disk configuration, leaving initalization and cleanup to the
     
    46634271        return vdIfError(pImage->pIfError, VERR_INVALID_PARAMETER, RT_SRC_POS,
    46644272                         N_("VMDK: Image path: '%s'. Getting config interface failed"), pImage->pszFilename);
    4665 
    46664273    /*
    46674274     * RawDrive = path
     
    46724279                         N_("VMDK: Image path: '%s'. Getting 'RawDrive' configuration failed (%Rrc)"), pImage->pszFilename, rc);
    46734280    AssertPtrReturn(*ppszRawDrive, VERR_INTERNAL_ERROR_3);
    4674 
    46754281    /*
    46764282     * Partitions=n[r][,...]
     
    46784284    uint32_t const cMaxPartitionBits = sizeof(*pfPartitions) * 8 /* ASSUMES 8 bits per char */;
    46794285    *pfPartitions = *pfPartitionsReadOnly = 0;
    4680 
    46814286    rc = VDCFGQueryStringAlloc(pImgCfg, "Partitions", ppszFreeMe);
    46824287    if (RT_SUCCESS(rc))
     
    47124317                                 pImage->pszFilename, psz);
    47134318        }
    4714 
    47154319        RTStrFree(*ppszFreeMe);
    47164320        *ppszFreeMe = NULL;
     
    47194323        return vdIfError(pImage->pIfError, rc, RT_SRC_POS,
    47204324                         N_("VMDK: Image path: '%s'. Getting 'Partitions' configuration failed (%Rrc)"), pImage->pszFilename, rc);
    4721 
    47224325    /*
    47234326     * BootSector=base64
     
    47394342                             N_("VMDK: Image path: '%s'. Custom bootsector for '%s' is way too big: %zu bytes, max 4MB"),
    47404343                             pImage->pszFilename, *ppszRawDrive, cbBootSector);
    4741 
    47424344        /* Refuse the boot sector if whole-drive.  This used to be done quietly,
    47434345           however, bird disagrees and thinks the user should be told that what
     
    47484350                             N_("VMDK: Image path: '%s'. Custom bootsector for '%s' is not supported for whole-drive configurations, only when selecting partitions"),
    47494351                             pImage->pszFilename, *ppszRawDrive);
    4750 
    47514352        *pcbBootSector = (size_t)cbBootSector;
    47524353        *ppvBootSector = RTMemAlloc((size_t)cbBootSector);
     
    47554356                             N_("VMDK: Image path: '%s'. Failed to allocate %zd bytes for the custom bootsector for '%s'"),
    47564357                             pImage->pszFilename, cbBootSector, *ppszRawDrive);
    4757 
    47584358        rc = RTBase64Decode(*ppszFreeMe, *ppvBootSector, cbBootSector, NULL /*pcbActual*/, NULL /*ppszEnd*/);
    47594359        if (RT_FAILURE(rc))
     
    47614361                              N_("VMDK: Image path: '%s'. Base64 decoding of the custom boot sector for '%s' failed (%Rrc)"),
    47624362                              pImage->pszFilename, *ppszRawDrive, rc);
    4763 
    47644363        RTStrFree(*ppszFreeMe);
    47654364        *ppszFreeMe = NULL;
     
    47684367        return vdIfError(pImage->pIfError, rc, RT_SRC_POS,
    47694368                         N_("VMDK: Image path: '%s'. Getting 'BootSector' configuration failed (%Rrc)"), pImage->pszFilename, rc);
    4770 
    47714369    /*
    47724370     * Relative=0/1
     
    47964394        *pfRelative = false;
    47974395#endif
    4798 
    47994396    return VINF_SUCCESS;
    48004397}
    4801 
    48024398/**
    48034399 * Creates a raw drive (nee disk) descriptor.
     
    48184414    /* Make sure it's NULL. */
    48194415    *ppRaw = NULL;
    4820 
    48214416    /*
    48224417     * Read the configuration.
     
    48704465                    //pRawDesc->cPartDescs = 0;
    48714466                    //pRawDesc->pPartDescs = NULL;
    4872 
    48734467                    /* We need to parse the partition map to complete the descriptor: */
    48744468                    RTDVM hVolMgr = NIL_RTDVM;
     
    48824476                            pRawDesc->enmPartitioningType = enmFormatType == RTDVMFORMATTYPE_MBR
    48834477                                                          ? VDISKPARTTYPE_MBR : VDISKPARTTYPE_GPT;
    4884 
    48854478                            /* Add copies of the partition tables:  */
    48864479                            rc = vmdkRawDescDoCopyPartitionTables(pImage, hVolMgr, pRawDesc, pszRawDrive, hRawDrive,
     
    48944487                                                             fPartitions, fPartitionsReadOnly, fRelative, &hVolRelease);
    48954488                                RTDvmVolumeRelease(hVolRelease);
    4896 
    48974489                                /* Finally, sort the partition and check consistency (overlaps, etc): */
    48984490                                if (RT_SUCCESS(rc))
     
    49384530    return rc;
    49394531}
    4940 
    49414532/**
    49424533 * Internal: create VMDK images for raw disk/partition access.
     
    49474538    int rc = VINF_SUCCESS;
    49484539    PVMDKEXTENT pExtent;
    4949 
    49504540    if (pRaw->uFlags & VDISKRAW_DISK)
    49514541    {
     
    49624552        if (RT_FAILURE(rc))
    49634553            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
    4964 
    49654554        /* Set up basename for extent description. Cannot use StrDup. */
    49664555        size_t cbBasename = strlen(pRaw->pszRawDisk) + 1;
     
    49794568        pExtent->enmAccess = (pRaw->uFlags & VDISKRAW_READONLY) ? VMDKACCESS_READONLY : VMDKACCESS_READWRITE;
    49804569        pExtent->fMetaDirty = false;
    4981 
    49824570        /* Open flat image, the raw disk. */
    49834571        rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
     
    49924580         * file, write the partition information to a flat extent and
    49934581         * open all the (flat) raw disk partitions. */
    4994 
    49954582        /* First pass over the partition data areas to determine how many
    49964583         * extents we need. One data area can require up to 2 extents, as
     
    50044591                return vdIfError(pImage->pIfError, VERR_INVALID_PARAMETER, RT_SRC_POS,
    50054592                                 N_("VMDK: incorrect partition data area ordering set up by the caller in '%s'"), pImage->pszFilename);
    5006 
    50074593            if (uStart < pPart->offStartInVDisk)
    50084594                cExtents++;
     
    50134599        if (uStart != cbSize)
    50144600            cExtents++;
    5015 
    50164601        rc = vmdkCreateExtents(pImage, cExtents);
    50174602        if (RT_FAILURE(rc))
    50184603            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
    5019 
    50204604        /* Create raw partition descriptor file. */
    50214605        rc = vmdkFileOpen(pImage, &pImage->pFile, NULL, pImage->pszFilename,
     
    50244608        if (RT_FAILURE(rc))
    50254609            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
    5026 
    50274610        /* Create base filename for the partition table extent. */
    50284611        /** @todo remove fixed buffer without creating memory leaks. */
     
    50394622                    pszBaseBase, pszSuff);
    50404623        RTStrFree(pszBaseBase);
    5041 
    50424624        /* Second pass over the partitions, now define all extents. */
    50434625        uint64_t uPartOffset = 0;
     
    50484630            PVDISKRAWPARTDESC pPart = &pRaw->pPartDescs[i];
    50494631            pExtent = &pImage->pExtents[cExtents++];
    5050 
    50514632            if (uStart < pPart->offStartInVDisk)
    50524633            {
     
    50624643            }
    50634644            uStart = pPart->offStartInVDisk + pPart->cbData;
    5064 
    50654645            if (pPart->pvPartitionData)
    50664646            {
     
    50724652                memcpy(pszBasename, pszPartition, cbBasename);
    50734653                pExtent->pszBasename = pszBasename;
    5074 
    50754654                /* Set up full name for partition extent. */
    50764655                char *pszDirname = RTStrDup(pImage->pszFilename);
     
    50884667                pExtent->enmAccess = VMDKACCESS_READWRITE;
    50894668                pExtent->fMetaDirty = false;
    5090 
    50914669                /* Create partition table flat image. */
    50924670                rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
     
    51234701                    pExtent->enmAccess = (pPart->uFlags & VDISKRAW_READONLY) ? VMDKACCESS_READONLY : VMDKACCESS_READWRITE;
    51244702                    pExtent->fMetaDirty = false;
    5125 
    51264703                    /* Open flat image, the raw partition. */
    51274704                    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
     
    51564733        }
    51574734    }
    5158 
    51594735    rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType",
    51604736                            (pRaw->uFlags & VDISKRAW_DISK) ?
     
    51644740    return rc;
    51654741}
    5166 
    51674742/**
    51684743 * Internal: create a regular (i.e. file-backed) VMDK image.
     
    51764751    uint64_t cbOffset = 0;
    51774752    uint64_t cbRemaining = cbSize;
    5178 
    51794753    if (uImageFlags & VD_VMDK_IMAGE_FLAGS_SPLIT_2G)
    51804754    {
     
    51884762    if (RT_FAILURE(rc))
    51894763        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
    5190 
    51914764    /* Basename strings needed for constructing the extent names. */
    51924765    char *pszBasenameSubstr = RTPathFilename(pImage->pszFilename);
    51934766    AssertPtr(pszBasenameSubstr);
    51944767    size_t cbBasenameSubstr = strlen(pszBasenameSubstr) + 1;
    5195 
    51964768    /* Create separate descriptor file if necessary. */
    51974769    if (cExtents != 1 || (uImageFlags & VD_IMAGE_FLAGS_FIXED))
     
    52054777    else
    52064778        pImage->pFile = NULL;
    5207 
    52084779    /* Set up all extents. */
    52094780    for (unsigned i = 0; i < cExtents; i++)
     
    52114782        PVMDKEXTENT pExtent = &pImage->pExtents[i];
    52124783        uint64_t cbExtent = cbRemaining;
    5213 
    52144784        /* Set up fullname/basename for extent description. Cannot use StrDup
    52154785         * for basename, as it is not guaranteed that the memory can be freed
     
    52684838            return VERR_NO_STR_MEMORY;
    52694839        pExtent->pszFullname = pszFullname;
    5270 
    52714840        /* Create file for extent. */
    52724841        rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
     
    52844853                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname);
    52854854        }
    5286 
    52874855        /* Place descriptor file information (where integrated). */
    52884856        if (cExtents == 1 && !(uImageFlags & VD_IMAGE_FLAGS_FIXED))
     
    52944862            pImage->pDescData = NULL;
    52954863        }
    5296 
    52974864        if (!(uImageFlags & VD_IMAGE_FLAGS_FIXED))
    52984865        {
     
    53224889                pExtent->enmType = VMDKETYPE_FLAT;
    53234890        }
    5324 
    53254891        pExtent->enmAccess = VMDKACCESS_READWRITE;
    53264892        pExtent->fUncleanShutdown = true;
     
    53284894        pExtent->uSectorOffset = 0;
    53294895        pExtent->fMetaDirty = true;
    5330 
    53314896        if (!(uImageFlags & VD_IMAGE_FLAGS_FIXED))
    53324897        {
     
    53404905                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
    53414906        }
    5342 
    53434907        cbOffset += cbExtent;
    5344 
    53454908        if (RT_SUCCESS(rc))
    53464909            vdIfProgress(pIfProgress, uPercentStart + cbOffset * uPercentSpan / cbSize);
    5347 
    53484910        cbRemaining -= cbExtent;
    53494911    }
    5350 
    53514912    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_ESX)
    53524913    {
     
    53574918            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set controller type to lsilogic in '%s'"), pImage->pszFilename);
    53584919    }
    5359 
    53604920    const char *pszDescType = NULL;
    53614921    if (uImageFlags & VD_IMAGE_FLAGS_FIXED)
     
    53834943    return rc;
    53844944}
    5385 
    53864945/**
    53874946 * Internal: Create a real stream optimized VMDK using only linear writes.
     
    53924951    if (RT_FAILURE(rc))
    53934952        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
    5394 
    53954953    /* Basename strings needed for constructing the extent names. */
    53964954    const char *pszBasenameSubstr = RTPathFilename(pImage->pszFilename);
    53974955    AssertPtr(pszBasenameSubstr);
    53984956    size_t cbBasenameSubstr = strlen(pszBasenameSubstr) + 1;
    5399 
    54004957    /* No separate descriptor file. */
    54014958    pImage->pFile = NULL;
    5402 
    54034959    /* Set up all extents. */
    54044960    PVMDKEXTENT pExtent = &pImage->pExtents[0];
    5405 
    54064961    /* Set up fullname/basename for extent description. Cannot use StrDup
    54074962     * for basename, as it is not guaranteed that the memory can be freed
     
    54134968    memcpy(pszBasename, pszBasenameSubstr, cbBasenameSubstr);
    54144969    pExtent->pszBasename = pszBasename;
    5415 
    54164970    char *pszBasedirectory = RTStrDup(pImage->pszFilename);
    54174971    RTPathStripFilename(pszBasedirectory);
     
    54214975        return VERR_NO_STR_MEMORY;
    54224976    pExtent->pszFullname = pszFullname;
    5423 
    54244977    /* Create file for extent. Make it write only, no reading allowed. */
    54254978    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszBasename, pExtent->pszFullname,
     
    54294982    if (RT_FAILURE(rc))
    54304983        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
    5431 
    54324984    /* Place descriptor file information. */
    54334985    pExtent->uDescriptorSector = 1;
     
    54364988    pExtent->pDescData = pImage->pDescData;
    54374989    pImage->pDescData = NULL;
    5438 
    54394990    uint64_t cSectorsPerGDE, cSectorsPerGD;
    54404991    pExtent->enmType = VMDKETYPE_HOSTED_SPARSE;
     
    54464997    pExtent->cGDEntries = (pExtent->cSectors + cSectorsPerGDE - 1) / cSectorsPerGDE;
    54474998    cSectorsPerGD = (pExtent->cGDEntries + (512 / sizeof(uint32_t) - 1)) / (512 / sizeof(uint32_t));
    5448 
    54494999    /* The spec says version is 1 for all VMDKs, but the vast
    54505000     * majority of streamOptimized VMDKs actually contain
     
    54535003    pExtent->uCompression = VMDK_COMPRESSION_DEFLATE;
    54545004    pExtent->fFooter = true;
    5455 
    54565005    pExtent->enmAccess = VMDKACCESS_READONLY;
    54575006    pExtent->fUncleanShutdown = false;
     
    54595008    pExtent->uSectorOffset = 0;
    54605009    pExtent->fMetaDirty = true;
    5461 
    54625010    /* Create grain directory, without preallocating it straight away. It will
    54635011     * be constructed on the fly when writing out the data and written when
     
    54685016    if (RT_FAILURE(rc))
    54695017        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
    5470 
    54715018    rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType",
    54725019                            "streamOptimized");
    54735020    if (RT_FAILURE(rc))
    54745021        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
    5475 
    5476     return rc;
    5477 }
    5478 
     5022    return rc;
     5023}
    54795024/**
    54805025 * Initializes the UUID fields in the DDB.
     
    55125057        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS,
    55135058                       N_("VMDK: error storing image UUID in new descriptor in '%s'"), pImage->pszFilename);
    5514 
    5515     return rc;
    5516 }
    5517 
     5059    return rc;
     5060}
    55185061/**
    55195062 * Internal: The actual code for creating any VMDK variant currently in
     
    55285071{
    55295072    pImage->uImageFlags = uImageFlags;
    5530 
    55315073    pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
    55325074    pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
    55335075    AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
    5534 
    55355076    int rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc,
    55365077                                  &pImage->Descriptor);
     
    55445085            if (RT_FAILURE(rc))
    55455086                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could get raw descriptor for '%s'"), pImage->pszFilename);
    5546 
    55475087            rc = vmdkCreateRawImage(pImage, pRaw, cbSize);
    55485088            vmdkRawDescFree(pRaw);
     
    55605100                                        uPercentSpan * 95 / 100);
    55615101        }
    5562 
    55635102        if (RT_SUCCESS(rc))
    55645103        {
    55655104            vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 98 / 100);
    5566 
    55675105            pImage->cbSize = cbSize;
    5568 
    55695106            for (unsigned i = 0; i < pImage->cExtents; i++)
    55705107            {
    55715108                PVMDKEXTENT pExtent = &pImage->pExtents[i];
    5572 
    55735109                rc = vmdkDescExtInsert(pImage, &pImage->Descriptor, pExtent->enmAccess,
    55745110                                       pExtent->cNominalSectors, pExtent->enmType,
     
    55805116                }
    55815117            }
    5582 
    55835118            if (RT_SUCCESS(rc))
    55845119                vmdkDescExtRemoveDummy(pImage, &pImage->Descriptor);
    5585 
    55865120            if (   RT_SUCCESS(rc)
    55875121                && pPCHSGeometry->cCylinders != 0
     
    55895123                && pPCHSGeometry->cSectors != 0)
    55905124                rc = vmdkDescSetPCHSGeometry(pImage, pPCHSGeometry);
    5591 
    55925125            if (   RT_SUCCESS(rc)
    55935126                && pLCHSGeometry->cCylinders != 0
     
    55955128                && pLCHSGeometry->cSectors != 0)
    55965129                rc = vmdkDescSetLCHSGeometry(pImage, pLCHSGeometry);
    5597 
    55985130            pImage->LCHSGeometry = *pLCHSGeometry;
    55995131            pImage->PCHSGeometry = *pPCHSGeometry;
    5600 
    56015132            pImage->ImageUuid = *pUuid;
    56025133            RTUuidClear(&pImage->ParentUuid);
    56035134            RTUuidClear(&pImage->ModificationUuid);
    56045135            RTUuidClear(&pImage->ParentModificationUuid);
    5605 
    56065136            if (RT_SUCCESS(rc))
    56075137                rc = vmdkCreateImageDdbUuidsInit(pImage);
    5608 
    56095138            if (RT_SUCCESS(rc))
    56105139                rc = vmdkAllocateGrainTableCache(pImage);
    5611 
    56125140            if (RT_SUCCESS(rc))
    56135141            {
     
    56165144                    rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot set image comment in '%s'"), pImage->pszFilename);
    56175145            }
    5618 
    56195146            if (RT_SUCCESS(rc))
    56205147            {
    56215148                vdIfProgress(pIfProgress, uPercentStart + uPercentSpan * 99 / 100);
    5622 
    56235149                if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    56245150                {
     
    56455171    else
    56465172        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new descriptor in '%s'"), pImage->pszFilename);
    5647 
    5648 
    56495173    if (RT_SUCCESS(rc))
    56505174    {
     
    56525176        pImage->RegionList.fFlags   = 0;
    56535177        pImage->RegionList.cRegions = 1;
    5654 
    56555178        pRegion->offRegion            = 0; /* Disk start. */
    56565179        pRegion->cbBlock              = 512;
     
    56605183        pRegion->cbMetadata           = 0;
    56615184        pRegion->cRegionBlocksOrBytes = pImage->cbSize;
    5662 
    56635185        vdIfProgress(pIfProgress, uPercentStart + uPercentSpan);
    56645186    }
     
    56675189    return rc;
    56685190}
    5669 
    56705191/**
    56715192 * Internal: Update image comment.
     
    56805201            return VERR_NO_MEMORY;
    56815202    }
    5682 
    56835203    int rc = vmdkDescDDBSetStr(pImage, &pImage->Descriptor,
    56845204                               "ddb.comment", pszCommentEncoded);
     
    56895209    return VINF_SUCCESS;
    56905210}
    5691 
    56925211/**
    56935212 * Internal. Clear the grain table buffer for real stream optimized writing.
     
    57005219               VMDK_GT_CACHELINE_SIZE * sizeof(uint32_t));
    57015220}
    5702 
    57035221/**
    57045222 * Internal. Flush the grain table buffer for real stream optimized writing.
     
    57095227    int rc = VINF_SUCCESS;
    57105228    uint32_t cCacheLines = RT_ALIGN(pExtent->cGTEntries, VMDK_GT_CACHELINE_SIZE) / VMDK_GT_CACHELINE_SIZE;
    5711 
    57125229    /* VMware does not write out completely empty grain tables in the case
    57135230     * of streamOptimized images, which according to my interpretation of
     
    57315248    if (fAllZero)
    57325249        return VINF_SUCCESS;
    5733 
    57345250    uint64_t uFileOffset = pExtent->uAppendPosition;
    57355251    if (!uFileOffset)
     
    57375253    /* Align to sector, as the previous write could have been any size. */
    57385254    uFileOffset = RT_ALIGN_64(uFileOffset, 512);
    5739 
    57405255    /* Grain table marker. */
    57415256    uint8_t aMarker[512];
     
    57485263    AssertRC(rc);
    57495264    uFileOffset += 512;
    5750 
    57515265    if (!pExtent->pGD || pExtent->pGD[uGDEntry])
    57525266        return VERR_INTERNAL_ERROR;
    5753 
    57545267    pExtent->pGD[uGDEntry] = VMDK_BYTE2SECTOR(uFileOffset);
    5755 
    57565268    for (uint32_t i = 0; i < cCacheLines; i++)
    57575269    {
     
    57615273        for (uint32_t j = 0; j < VMDK_GT_CACHELINE_SIZE; j++, pGTTmp++)
    57625274            *pGTTmp = RT_H2LE_U32(*pGTTmp);
    5763 
    57645275        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage, uFileOffset,
    57655276                                    &pImage->pGTCache->aGTCache[i].aGTData[0],
     
    57735284    return rc;
    57745285}
    5775 
    57765286/**
    57775287 * Internal. Free all allocated space for representing an image, and optionally
     
    57815291{
    57825292    int rc = VINF_SUCCESS;
    5783 
    57845293    /* Freeing a never allocated image (e.g. because the open failed) is
    57855294     * not signalled as an error. After all nothing bad happens. */
     
    58075316                        pImage->pExtents[i].fMetaDirty = true;
    58085317                    }
    5809 
    58105318                    /* From now on it's not safe to append any more data. */
    58115319                    pImage->pExtents[i].uAppendPosition = 0;
     
    58135321            }
    58145322        }
    5815 
    58165323        if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    58175324        {
     
    58325339                    AssertRC(rc);
    58335340                }
    5834 
    58355341                uint64_t uFileOffset = pExtent->uAppendPosition;
    58365342                if (!uFileOffset)
    58375343                    return VERR_INTERNAL_ERROR;
    58385344                uFileOffset = RT_ALIGN_64(uFileOffset, 512);
    5839 
    58405345                /* From now on it's not safe to append any more data. */
    58415346                pExtent->uAppendPosition = 0;
    5842 
    58435347                /* Grain directory marker. */
    58445348                uint8_t aMarker[512];
     
    58515355                AssertRC(rc);
    58525356                uFileOffset += 512;
    5853 
    58545357                /* Write grain directory in little endian style. The array will
    58555358                 * not be used after this, so convert in place. */
     
    58615364                                            pExtent->cGDEntries * sizeof(uint32_t));
    58625365                AssertRC(rc);
    5863 
    58645366                pExtent->uSectorGD = VMDK_BYTE2SECTOR(uFileOffset);
    58655367                pExtent->uSectorRGD = VMDK_BYTE2SECTOR(uFileOffset);
     
    58675369                                          + pExtent->cGDEntries * sizeof(uint32_t),
    58685370                                          512);
    5869 
    58705371                /* Footer marker. */
    58715372                memset(pMarker, '\0', sizeof(aMarker));
     
    58755376                                            uFileOffset, aMarker, sizeof(aMarker));
    58765377                AssertRC(rc);
    5877 
    58785378                uFileOffset += 512;
    58795379                rc = vmdkWriteMetaSparseExtent(pImage, pExtent, uFileOffset, NULL);
    58805380                AssertRC(rc);
    5881 
    58825381                uFileOffset += 512;
    58835382                /* End-of-stream marker. */
     
    58905389        else if (!fDelete && fFlush)
    58915390            vmdkFlushImage(pImage, NULL);
    5892 
    58935391        if (pImage->pExtents != NULL)
    58945392        {
     
    59125410        if (RT_SUCCESS(rc))
    59135411            rc = rc2; /* Propogate any error when closing the file. */
    5914 
    59155412        if (pImage->pGTCache)
    59165413        {
     
    59245421        }
    59255422    }
    5926 
    59275423    LogFlowFunc(("returns %Rrc\n", rc));
    59285424    return rc;
    59295425}
    5930 
    59315426/**
    59325427 * Internal. Flush image data (and metadata) to disk.
     
    59365431    PVMDKEXTENT pExtent;
    59375432    int rc = VINF_SUCCESS;
    5938 
    59395433    /* Update descriptor if changed. */
    59405434    if (pImage->Descriptor.fDirty)
    59415435        rc = vmdkWriteDescriptor(pImage, pIoCtx);
    5942 
    59435436    if (RT_SUCCESS(rc))
    59445437    {
     
    59765469                }
    59775470            }
    5978 
    59795471            if (RT_FAILURE(rc))
    59805472                break;
    5981 
    59825473            switch (pExtent->enmType)
    59835474            {
     
    60015492        }
    60025493    }
    6003 
    6004     return rc;
    6005 }
    6006 
     5494    return rc;
     5495}
    60075496/**
    60085497 * Internal. Find extent corresponding to the sector number in the disk.
     
    60135502    PVMDKEXTENT pExtent = NULL;
    60145503    int rc = VINF_SUCCESS;
    6015 
    60165504    for (unsigned i = 0; i < pImage->cExtents; i++)
    60175505    {
     
    60245512        offSector -= pImage->pExtents[i].cNominalSectors;
    60255513    }
    6026 
    60275514    if (pExtent)
    60285515        *ppExtent = pExtent;
    60295516    else
    60305517        rc = VERR_IO_SECTOR_NOT_FOUND;
    6031 
    6032     return rc;
    6033 }
    6034 
     5518    return rc;
     5519}
    60355520/**
    60365521 * Internal. Hash function for placing the grain table hash entries.
     
    60435528    return (uSector + uExtent) % pCache->cEntries;
    60445529}
    6045 
    60465530/**
    60475531 * Internal. Get sector number in the extent file from the relative sector
     
    60585542    uint32_t aGTDataTmp[VMDK_GT_CACHELINE_SIZE];
    60595543    int rc;
    6060 
    60615544    /* For newly created and readonly/sequentially opened streamOptimized
    60625545     * images this must be a no-op, as the grain directory is not there. */
     
    60705553        return VINF_SUCCESS;
    60715554    }
    6072 
    60735555    uGDIndex = uSector / pExtent->cSectorsPerGDE;
    60745556    if (uGDIndex >= pExtent->cGDEntries)
     
    60825564        return VINF_SUCCESS;
    60835565    }
    6084 
    60855566    uGTBlock = uSector / (pExtent->cSectorsPerGrain * VMDK_GT_CACHELINE_SIZE);
    60865567    uGTHash = vmdkGTCacheHash(pCache, uGTBlock, pExtent->uExtent);
     
    61115592    return VINF_SUCCESS;
    61125593}
    6113 
    61145594/**
    61155595 * Internal. Writes the grain and also if necessary the grain tables.
     
    61265606    const void *pData;
    61275607    int rc;
    6128 
    61295608    /* Very strict requirements: always write at least one full grain, with
    61305609     * proper alignment. Everything else would require reading of already
     
    61395618        || uSector + VMDK_BYTE2SECTOR(cbWrite) > pExtent->cNominalSectors)
    61405619        return VERR_INVALID_PARAMETER;
    6141 
    61425620    /* Clip write range to at most the rest of the grain. */
    61435621    cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSector % pExtent->cSectorsPerGrain));
    6144 
    61455622    /* Do not allow to go back. */
    61465623    uGrain = uSector / pExtent->cSectorsPerGrain;
     
    61515628    if (uGrain < pExtent->uLastGrainAccess)
    61525629        return VERR_VD_VMDK_INVALID_WRITE;
    6153 
    61545630    /* Zero byte write optimization. Since we don't tell VBoxHDD that we need
    61555631     * to allocate something, we also need to detect the situation ourself. */
     
    61575633        && vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbWrite, true /* fAdvance */))
    61585634        return VINF_SUCCESS;
    6159 
    61605635    if (uGDEntry != uLastGDEntry)
    61615636    {
     
    61715646        }
    61725647    }
    6173 
    61745648    uint64_t uFileOffset;
    61755649    uFileOffset = pExtent->uAppendPosition;
     
    61785652    /* Align to sector, as the previous write could have been any size. */
    61795653    uFileOffset = RT_ALIGN_64(uFileOffset, 512);
    6180 
    61815654    /* Paranoia check: extent type, grain table buffer presence and
    61825655     * grain table buffer space. Also grain table entry must be clear. */
     
    61865659        || pImage->pGTCache->aGTCache[uCacheLine].aGTData[uCacheEntry])
    61875660        return VERR_INTERNAL_ERROR;
    6188 
    61895661    /* Update grain table entry. */
    61905662    pImage->pGTCache->aGTCache[uCacheLine].aGTData[uCacheEntry] = VMDK_BYTE2SECTOR(uFileOffset);
    6191 
    61925663    if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))
    61935664    {
     
    62025673        unsigned cSegments = 1;
    62035674        size_t cbSeg = 0;
    6204 
    62055675        cbSeg = vdIfIoIntIoCtxSegArrayCreate(pImage->pIfIo, pIoCtx, &Segment,
    62065676                                             &cSegments, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
     
    62195689    pExtent->uLastGrainAccess = uGrain;
    62205690    pExtent->uAppendPosition += cbGrain;
    6221 
    6222     return rc;
    6223 }
    6224 
     5691    return rc;
     5692}
    62255693/**
    62265694 * Internal: Updates the grain table during grain allocation.
     
    62365704    uint64_t uSector = pGrainAlloc->uSector;
    62375705    PVMDKGTCACHEENTRY pGTCacheEntry;
    6238 
    62395706    LogFlowFunc(("pImage=%#p pExtent=%#p pCache=%#p pIoCtx=%#p pGrainAlloc=%#p\n",
    62405707                 pImage, pExtent, pCache, pIoCtx, pGrainAlloc));
    6241 
    62425708    uGTSector = pGrainAlloc->uGTSector;
    62435709    uRGTSector = pGrainAlloc->uRGTSector;
    62445710    LogFlow(("uGTSector=%llu uRGTSector=%llu\n", uGTSector, uRGTSector));
    6245 
    62465711    /* Update the grain table (and the cache). */
    62475712    uGTBlock = uSector / (pExtent->cSectorsPerGrain * VMDK_GT_CACHELINE_SIZE);
     
    63065771            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
    63075772    }
    6308 
    63095773    LogFlowFunc(("leaving rc=%Rrc\n", rc));
    63105774    return rc;
    63115775}
    6312 
    63135776/**
    63145777 * Internal - complete the grain allocation by updating disk grain table if required.
     
    63205783    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    63215784    PVMDKGRAINALLOCASYNC pGrainAlloc = (PVMDKGRAINALLOCASYNC)pvUser;
    6322 
    63235785    LogFlowFunc(("pBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc\n",
    63245786                 pBackendData, pIoCtx, pvUser, rcReq));
    6325 
    63265787    pGrainAlloc->cIoXfersPending--;
    63275788    if (!pGrainAlloc->cIoXfersPending && pGrainAlloc->fGTUpdateNeeded)
    63285789        rc = vmdkAllocGrainGTUpdate(pImage, pGrainAlloc->pExtent, pIoCtx, pGrainAlloc);
    6329 
    63305790    if (!pGrainAlloc->cIoXfersPending)
    63315791    {
     
    63335793        RTMemFree(pGrainAlloc);
    63345794    }
    6335 
    63365795    LogFlowFunc(("Leaving rc=%Rrc\n", rc));
    63375796    return rc;
    63385797}
    6339 
    63405798/**
    63415799 * Internal. Allocates a new grain table (if necessary).
     
    63495807    PVMDKGRAINALLOCASYNC pGrainAlloc = NULL;
    63505808    int rc;
    6351 
    63525809    LogFlowFunc(("pCache=%#p pExtent=%#p pIoCtx=%#p uSector=%llu cbWrite=%llu\n",
    63535810                 pCache, pExtent, pIoCtx, uSector, cbWrite));
    6354 
    63555811    pGrainAlloc = (PVMDKGRAINALLOCASYNC)RTMemAllocZ(sizeof(VMDKGRAINALLOCASYNC));
    63565812    if (!pGrainAlloc)
    63575813        return VERR_NO_MEMORY;
    6358 
    63595814    pGrainAlloc->pExtent = pExtent;
    63605815    pGrainAlloc->uSector = uSector;
    6361 
    63625816    uGDIndex = uSector / pExtent->cSectorsPerGDE;
    63635817    if (uGDIndex >= pExtent->cGDEntries)
     
    63745828    {
    63755829        LogFlow(("Allocating new grain table\n"));
    6376 
    63775830        /* There is no grain table referenced by this grain directory
    63785831         * entry. So there is absolutely no data in this area. Allocate
     
    63855838        }
    63865839        Assert(!(uFileOffset % 512));
    6387 
    63885840        uFileOffset = RT_ALIGN_64(uFileOffset, 512);
    63895841        uGTSector = VMDK_BYTE2SECTOR(uFileOffset);
    6390 
    63915842        /* Normally the grain table is preallocated for hosted sparse extents
    63925843         * that support more than 32 bit sector numbers. So this shouldn't
     
    63975848            return VERR_VD_VMDK_INVALID_HEADER;
    63985849        }
    6399 
    64005850        /* Write grain table by writing the required number of grain table
    64015851         * cache chunks. Allocate memory dynamically here or we flood the
     
    64035853        size_t cbGTDataTmp = pExtent->cGTEntries * sizeof(uint32_t);
    64045854        uint32_t *paGTDataTmp = (uint32_t *)RTMemTmpAllocZ(cbGTDataTmp);
    6405 
    64065855        if (!paGTDataTmp)
    64075856        {
     
    64095858            return VERR_NO_MEMORY;
    64105859        }
    6411 
    64125860        memset(paGTDataTmp, '\0', cbGTDataTmp);
    64135861        rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pExtent->pFile->pStorage,
     
    64255873        pExtent->uAppendPosition = RT_ALIGN_64(  pExtent->uAppendPosition
    64265874                                               + cbGTDataTmp, 512);
    6427 
    64285875        if (pExtent->pRGD)
    64295876        {
     
    64345881            Assert(!(uFileOffset % 512));
    64355882            uRGTSector = VMDK_BYTE2SECTOR(uFileOffset);
    6436 
    64375883            /* Normally the redundant grain table is preallocated for hosted
    64385884             * sparse extents that support more than 32 bit sector numbers. So
     
    64435889                return VERR_VD_VMDK_INVALID_HEADER;
    64445890            }
    6445 
    64465891            /* Write grain table by writing the required number of grain table
    64475892             * cache chunks. Allocate memory dynamically here or we flood the
     
    64585903                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
    64595904            }
    6460 
    64615905            pExtent->uAppendPosition = pExtent->uAppendPosition + cbGTDataTmp;
    64625906        }
    6463 
    64645907        RTMemTmpFree(paGTDataTmp);
    6465 
    64665908        /* Update the grain directory on disk (doing it before writing the
    64675909         * grain table will result in a garbled extent if the operation is
     
    64895931                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
    64905932        }
    6491 
    64925933        /* As the final step update the in-memory copy of the GDs. */
    64935934        pExtent->pGD[uGDIndex] = uGTSector;
     
    64955936            pExtent->pRGD[uGDIndex] = uRGTSector;
    64965937    }
    6497 
    64985938    LogFlow(("uGTSector=%llu uRGTSector=%llu\n", uGTSector, uRGTSector));
    64995939    pGrainAlloc->uGTSector = uGTSector;
    65005940    pGrainAlloc->uRGTSector = uRGTSector;
    6501 
    65025941    uFileOffset = pExtent->uAppendPosition;
    65035942    if (!uFileOffset)
    65045943        return VERR_INTERNAL_ERROR;
    65055944    Assert(!(uFileOffset % 512));
    6506 
    65075945    pGrainAlloc->uGrainOffset = uFileOffset;
    6508 
    65095946    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    65105947    {
     
    65125949                        ("Accesses to stream optimized images must be synchronous\n"),
    65135950                        VERR_INVALID_STATE);
    6514 
    65155951        if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))
    65165952            return vdIfError(pImage->pIfError, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname);
    6517 
    65185953        /* Invalidate cache, just in case some code incorrectly allows mixing
    65195954         * of reads and writes. Normally shouldn't be needed. */
    65205955        pExtent->uGrainSectorAbs = 0;
    6521 
    65225956        /* Write compressed data block and the markers. */
    65235957        uint32_t cbGrain = 0;
     
    65255959        RTSGSEG Segment;
    65265960        unsigned cSegments = 1;
    6527 
    65285961        cbSeg = vdIfIoIntIoCtxSegArrayCreate(pImage->pIfIo, pIoCtx, &Segment,
    65295962                                             &cSegments, cbWrite);
    65305963        Assert(cbSeg == cbWrite);
    6531 
    65325964        rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset,
    65335965                                 Segment.pvSeg, cbWrite, uSector, &cbGrain);
     
    65505982        else if (RT_FAILURE(rc))
    65515983            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
    6552 
    65535984        pExtent->uAppendPosition += cbWrite;
    65545985    }
    6555 
    65565986    rc = vmdkAllocGrainGTUpdate(pImage, pExtent, pIoCtx, pGrainAlloc);
    6557 
    65585987    if (!pGrainAlloc->cIoXfersPending)
    65595988    {
     
    65615990        RTMemFree(pGrainAlloc);
    65625991    }
    6563 
    65645992    LogFlowFunc(("leaving rc=%Rrc\n", rc));
    6565 
    6566     return rc;
    6567 }
    6568 
     5993    return rc;
     5994}
    65695995/**
    65705996 * Internal. Reads the contents by sequentially going over the compressed
     
    65766002{
    65776003    int rc;
    6578 
    65796004    LogFlowFunc(("pImage=%#p pExtent=%#p uSector=%llu pIoCtx=%#p cbRead=%llu\n",
    65806005                 pImage, pExtent, uSector, pIoCtx, cbRead));
    6581 
    65826006    AssertMsgReturn(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx),
    65836007                    ("Async I/O not supported for sequential stream optimized images\n"),
    65846008                    VERR_INVALID_STATE);
    6585 
    65866009    /* Do not allow to go back. */
    65876010    uint32_t uGrain = uSector / pExtent->cSectorsPerGrain;
     
    65896012        return VERR_VD_VMDK_INVALID_STATE;
    65906013    pExtent->uLastGrainAccess = uGrain;
    6591 
    65926014    /* After a previous error do not attempt to recover, as it would need
    65936015     * seeking (in the general case backwards which is forbidden). */
    65946016    if (!pExtent->uGrainSectorAbs)
    65956017        return VERR_VD_VMDK_INVALID_STATE;
    6596 
    65976018    /* Check if we need to read something from the image or if what we have
    65986019     * in the buffer is good to fulfill the request. */
     
    66016022        uint32_t uGrainSectorAbs =   pExtent->uGrainSectorAbs
    66026023                                   + VMDK_BYTE2SECTOR(pExtent->cbGrainStreamRead);
    6603 
    66046024        /* Get the marker from the next data block - and skip everything which
    66056025         * is not a compressed grain. If it's a compressed grain which is for
     
    66166036            Marker.uSector = RT_LE2H_U64(Marker.uSector);
    66176037            Marker.cbSize = RT_LE2H_U32(Marker.cbSize);
    6618 
    66196038            if (Marker.cbSize == 0)
    66206039            {
     
    66956114            }
    66966115        } while (Marker.uType != VMDK_MARKER_EOS);
    6697 
    66986116        pExtent->uGrainSectorAbs = uGrainSectorAbs;
    6699 
    67006117        if (!pExtent->cbGrainStreamRead && Marker.uType == VMDK_MARKER_EOS)
    67016118        {
     
    67066123        }
    67076124    }
    6708 
    67096125    if (pExtent->uGrain > uSector / pExtent->cSectorsPerGrain)
    67106126    {
     
    67146130        return VERR_VD_BLOCK_FREE;
    67156131    }
    6716 
    67176132    uint32_t uSectorInGrain = uSector % pExtent->cSectorsPerGrain;
    67186133    vdIfIoIntIoCtxCopyTo(pImage->pIfIo, pIoCtx,
     
    67226137    return VINF_SUCCESS;
    67236138}
    6724 
    67256139/**
    67266140 * Replaces a fragment of a string with the specified string.
     
    67916205    return pszNewStr;
    67926206}
    6793 
    6794 
    67956207/** @copydoc VDIMAGEBACKEND::pfnProbe */
    67966208static DECLCALLBACK(int) vmdkProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     
    68006212    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p penmType=%#p\n",
    68016213                 pszFilename, pVDIfsDisk, pVDIfsImage, penmType));
    6802 
    68036214    AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
    6804 
    68056215    int rc = VINF_SUCCESS;
    68066216    PVMDKIMAGE pImage = (PVMDKIMAGE)RTMemAllocZ(RT_UOFFSETOF(VMDKIMAGE, RegionList.aRegions[1]));
     
    68206230        vmdkFreeImage(pImage, false, false /*fFlush*/);
    68216231        RTMemFree(pImage);
    6822 
    68236232        if (RT_SUCCESS(rc))
    68246233            *penmType = VDTYPE_HDD;
     
    68266235    else
    68276236        rc = VERR_NO_MEMORY;
    6828 
    68296237    LogFlowFunc(("returns %Rrc\n", rc));
    68306238    return rc;
    68316239}
    6832 
    68336240/** @copydoc VDIMAGEBACKEND::pfnOpen */
    68346241static DECLCALLBACK(int) vmdkOpen(const char *pszFilename, unsigned uOpenFlags,
     
    68376244{
    68386245    RT_NOREF1(enmType); /**< @todo r=klaus make use of the type info. */
    6839 
    68406246    LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p enmType=%u ppBackendData=%#p\n",
    68416247                 pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, enmType, ppBackendData));
    68426248    int rc;
    6843 
    68446249    /* Check open flags. All valid flags are supported. */
    68456250    AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
    68466251    AssertReturn((VALID_PTR(pszFilename) && *pszFilename), VERR_INVALID_PARAMETER);
    6847 
    68486252    PVMDKIMAGE pImage = (PVMDKIMAGE)RTMemAllocZ(RT_UOFFSETOF(VMDKIMAGE, RegionList.aRegions[1]));
    68496253    if (RT_LIKELY(pImage))
     
    68576261        pImage->pVDIfsDisk = pVDIfsDisk;
    68586262        pImage->pVDIfsImage = pVDIfsImage;
    6859 
    68606263        rc = vmdkOpenImage(pImage, uOpenFlags);
    68616264        if (RT_SUCCESS(rc))
     
    68666269    else
    68676270        rc = VERR_NO_MEMORY;
    6868 
    68696271    LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
    68706272    return rc;
    68716273}
    6872 
    68736274/** @copydoc VDIMAGEBACKEND::pfnCreate */
    68746275static DECLCALLBACK(int) vmdkCreate(const char *pszFilename, uint64_t cbSize,
     
    68846285                 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, enmType, ppBackendData));
    68856286    int rc;
    6886 
    68876287    /* Check the VD container type and image flags. */
    68886288    if (   enmType != VDTYPE_HDD
    68896289        || (uImageFlags & ~VD_VMDK_IMAGE_FLAGS_MASK) != 0)
    68906290        return VERR_VD_INVALID_TYPE;
    6891 
    68926291    /* Check size. Maximum 256TB-64K for sparse images, otherwise unlimited. */
    68936292    if (   !(uImageFlags & VD_VMDK_IMAGE_FLAGS_RAWDISK)
     
    68956294            || (!(uImageFlags & VD_IMAGE_FLAGS_FIXED) && cbSize >= _1T * 256 - _64K)))
    68966295        return VERR_VD_INVALID_SIZE;
    6897 
    68986296    /* Check image flags for invalid combinations. */
    68996297    if (   (uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    69006298        && (uImageFlags & ~(VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED | VD_IMAGE_FLAGS_DIFF)))
    69016299        return VERR_INVALID_PARAMETER;
    6902 
    69036300    /* Check open flags. All valid flags are supported. */
    69046301    AssertReturn(!(uOpenFlags & ~VD_OPEN_FLAGS_MASK), VERR_INVALID_PARAMETER);
     
    69106307                      && !(uImageFlags & VD_IMAGE_FLAGS_FIXED)),
    69116308                 VERR_INVALID_PARAMETER);
    6912 
    69136309    PVMDKIMAGE pImage = (PVMDKIMAGE)RTMemAllocZ(RT_UOFFSETOF(VMDKIMAGE, RegionList.aRegions[1]));
    69146310    if (RT_LIKELY(pImage))
    69156311    {
    69166312        PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
    6917 
    69186313        pImage->pszFilename = pszFilename;
    69196314        pImage->pFile = NULL;
     
    69466341                    rc = vmdkOpenImage(pImage, uOpenFlags);
    69476342                }
    6948 
    69496343                if (RT_SUCCESS(rc))
    69506344                    *ppBackendData = pImage;
    69516345            }
    6952 
    69536346            if (RT_FAILURE(rc))
    69546347                RTMemFree(pImage->pDescData);
     
    69566349        else
    69576350            rc = VERR_NO_MEMORY;
    6958 
    69596351        if (RT_FAILURE(rc))
    69606352            RTMemFree(pImage);
     
    69626354    else
    69636355        rc = VERR_NO_MEMORY;
    6964 
    69656356    LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
    69666357    return rc;
    69676358}
    6968 
    69696359/**
    69706360 * Prepares the state for renaming a VMDK image, setting up the state and allocating
     
    69796369{
    69806370    AssertReturn(RTPathFilename(pszFilename) != NULL, VERR_INVALID_PARAMETER);
    6981 
    69826371    int rc = VINF_SUCCESS;
    6983 
    69846372    memset(&pRenameState->DescriptorCopy, 0, sizeof(pRenameState->DescriptorCopy));
    6985 
    69866373    /*
    69876374     * Allocate an array to store both old and new names of renamed files
     
    70096396            pRenameState->fEmbeddedDesc = true;
    70106397        }
    7011 
    70126398        /* Save the descriptor content. */
    70136399        pRenameState->DescriptorCopy.cLines = pImage->Descriptor.cLines;
     
    70216407            }
    70226408        }
    7023 
    70246409        if (RT_SUCCESS(rc))
    70256410        {
     
    70286413            AssertReturn(pRenameState->pszNewBaseName, VERR_NO_STR_MEMORY);
    70296414            RTPathStripSuffix(pRenameState->pszNewBaseName);
    7030 
    70316415            pRenameState->pszOldBaseName = RTStrDup(RTPathFilename(pImage->pszFilename));
    70326416            AssertReturn(pRenameState->pszOldBaseName, VERR_NO_STR_MEMORY);
    70336417            RTPathStripSuffix(pRenameState->pszOldBaseName);
    7034 
    70356418            /* Prepare both old and new full names used for string replacement.
    70366419               Note! Must abspath the stuff here, so the strstr weirdness later in
     
    70406423            AssertReturn(pRenameState->pszNewFullName, VERR_NO_STR_MEMORY);
    70416424            RTPathStripSuffix(pRenameState->pszNewFullName);
    7042 
    70436425            pRenameState->pszOldFullName = RTPathAbsDup(pImage->pszFilename);
    70446426            AssertReturn(pRenameState->pszOldFullName, VERR_NO_STR_MEMORY);
    70456427            RTPathStripSuffix(pRenameState->pszOldFullName);
    7046 
    70476428            /* Save the old name for easy access to the old descriptor file. */
    70486429            pRenameState->pszOldDescName = RTStrDup(pImage->pszFilename);
    70496430            AssertReturn(pRenameState->pszOldDescName, VERR_NO_STR_MEMORY);
    7050 
    70516431            /* Save old image name. */
    70526432            pRenameState->pszOldImageName = pImage->pszFilename;
     
    70556435    else
    70566436        rc = VERR_NO_TMP_MEMORY;
    7057 
    7058     return rc;
    7059 }
    7060 
     6437    return rc;
     6438}
    70616439/**
    70626440 * Destroys the given rename state, freeing all allocated memory.
     
    71026480        RTStrFree(pRenameState->pszNewFullName);
    71036481}
    7104 
    71056482/**
    71066483 * Rolls back the rename operation to the original state.
     
    71136490{
    71146491    int rc = VINF_SUCCESS;
    7115 
    71166492    if (!pRenameState->fImageFreed)
    71176493    {
     
    71226498        vmdkFreeImage(pImage, false, true /*fFlush*/);
    71236499    }
    7124 
    71256500    /* Rename files back. */
    71266501    for (unsigned i = 0; i <= pRenameState->cExtents; i++)
     
    71616536    pImage->pszFilename = pRenameState->pszOldImageName;
    71626537    rc = vmdkOpenImage(pImage, pImage->uOpenFlags);
    7163 
    7164     return rc;
    7165 }
    7166 
     6538    return rc;
     6539}
    71676540/**
    71686541 * Rename worker doing the real work.
     
    71776550    int rc = VINF_SUCCESS;
    71786551    unsigned i, line;
    7179 
    71806552    /* Update the descriptor with modified extent names. */
    71816553    for (i = 0, line = pImage->Descriptor.uFirstExtent;
     
    71946566        pImage->Descriptor.aLines[line] = pRenameState->apszNewLines[i];
    71956567    }
    7196 
    71976568    if (RT_SUCCESS(rc))
    71986569    {
     
    72016572        /* Flush the descriptor now, in case it is embedded. */
    72026573        vmdkFlushImage(pImage, NULL);
    7203 
    72046574        /* Close and rename/move extents. */
    72056575        for (i = 0; i < pRenameState->cExtents; i++)
     
    72196589            if (RT_FAILURE(rc))
    72206590                break;;
    7221 
    72226591            /* Rename the extent file. */
    72236592            rc = vdIfIoIntFileMove(pImage->pIfIo, pExtent->pszFullname, pRenameState->apszNewName[i], 0);
     
    72276596            pRenameState->apszOldName[i] = RTStrDup(pExtent->pszFullname);
    72286597        }
    7229 
    72306598        if (RT_SUCCESS(rc))
    72316599        {
     
    72356603            {
    72366604                pRenameState->fImageFreed = true;
    7237 
    72386605                /* Last elements of new/old name arrays are intended for
    72396606                 * storing descriptor's names.
     
    72506617                    }
    72516618                }
    7252 
    72536619                /* Update pImage with the new information. */
    72546620                pImage->pszFilename = pszFilename;
    7255 
    72566621                /* Open the new image. */
    72576622                rc = vmdkOpenImage(pImage, pImage->uOpenFlags);
     
    72596624        }
    72606625    }
    7261 
    7262     return rc;
    7263 }
    7264 
     6626    return rc;
     6627}
    72656628/** @copydoc VDIMAGEBACKEND::pfnRename */
    72666629static DECLCALLBACK(int) vmdkRename(void *pBackendData, const char *pszFilename)
    72676630{
    72686631    LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
    7269 
    72706632    PVMDKIMAGE  pImage  = (PVMDKIMAGE)pBackendData;
    72716633    VMDKRENAMESTATE RenameState;
    7272 
    72736634    memset(&RenameState, 0, sizeof(RenameState));
    7274 
    72756635    /* Check arguments. */
    72766636    AssertReturn((   pImage
     
    72786638                  && *pszFilename
    72796639                  && !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_RAWDISK)), VERR_INVALID_PARAMETER);
    7280 
    72816640    int rc = vmdkRenameStatePrepare(pImage, &RenameState, pszFilename);
    72826641    if (RT_SUCCESS(rc))
    72836642    {
    72846643        /* --- Up to this point we have not done any damage yet. --- */
    7285 
    72866644        rc = vmdkRenameWorker(pImage, &RenameState, pszFilename);
    72876645        /* Roll back all changes in case of failure. */
     
    72926650        }
    72936651    }
    7294 
    72956652    vmdkRenameStateDestroy(&RenameState);
    72966653    LogFlowFunc(("returns %Rrc\n", rc));
    72976654    return rc;
    72986655}
    7299 
    73006656/** @copydoc VDIMAGEBACKEND::pfnClose */
    73016657static DECLCALLBACK(int) vmdkClose(void *pBackendData, bool fDelete)
     
    73036659    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
    73046660    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7305 
    73066661    int rc = vmdkFreeImage(pImage, fDelete, true /*fFlush*/);
    73076662    RTMemFree(pImage);
    7308 
    73096663    LogFlowFunc(("returns %Rrc\n", rc));
    73106664    return rc;
    73116665}
    7312 
    73136666/** @copydoc VDIMAGEBACKEND::pfnRead */
    73146667static DECLCALLBACK(int) vmdkRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     
    73186671                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    73196672    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7320 
    73216673    AssertPtr(pImage);
    73226674    Assert(uOffset % 512 == 0);
     
    73246676    AssertReturn((VALID_PTR(pIoCtx) && cbToRead), VERR_INVALID_PARAMETER);
    73256677    AssertReturn(uOffset + cbToRead <= pImage->cbSize, VERR_INVALID_PARAMETER);
    7326 
    73276678    /* Find the extent and check access permissions as defined in the extent descriptor. */
    73286679    PVMDKEXTENT pExtent;
     
    73356686        /* Clip read range to remain in this extent. */
    73366687        cbToRead = RT_MIN(cbToRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    7337 
    73386688        /* Handle the read according to the current extent type. */
    73396689        switch (pExtent->enmType)
     
    73426692            {
    73436693                uint64_t uSectorExtentAbs;
    7344 
    73456694                rc = vmdkGetSector(pImage, pIoCtx, pExtent, uSectorExtentRel, &uSectorExtentAbs);
    73466695                if (RT_FAILURE(rc))
     
    73666715                        AssertMsg(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx),
    73676716                                  ("Async I/O is not supported for stream optimized VMDK's\n"));
    7368 
    73696717                        uint32_t uSectorInGrain = uSectorExtentRel % pExtent->cSectorsPerGrain;
    73706718                        uSectorExtentAbs -= uSectorInGrain;
     
    74076755            {
    74086756                size_t cbSet;
    7409 
    74106757                cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
    74116758                Assert(cbSet == cbToRead);
     
    74186765    else if (RT_SUCCESS(rc))
    74196766        rc = VERR_VD_VMDK_INVALID_STATE;
    7420 
    74216767    LogFlowFunc(("returns %Rrc\n", rc));
    74226768    return rc;
    74236769}
    7424 
    74256770/** @copydoc VDIMAGEBACKEND::pfnWrite */
    74266771static DECLCALLBACK(int) vmdkWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     
    74326777    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    74336778    int rc;
    7434 
    74356779    AssertPtr(pImage);
    74366780    Assert(uOffset % 512 == 0);
    74376781    Assert(cbToWrite % 512 == 0);
    74386782    AssertReturn((VALID_PTR(pIoCtx) && cbToWrite), VERR_INVALID_PARAMETER);
    7439 
    74406783    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    74416784    {
     
    74436786        uint64_t uSectorExtentRel;
    74446787        uint64_t uSectorExtentAbs;
    7445 
    74466788        /* No size check here, will do that later when the extent is located.
    74476789         * There are sparse images out there which according to the spec are
     
    74506792         * grain boundaries, and with the nominal size not being a multiple of the
    74516793         * grain size), this would prevent writing to the last grain. */
    7452 
    74536794        rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset),
    74546795                            &pExtent, &uSectorExtentRel);
     
    75486889                }
    75496890            }
    7550 
    75516891            if (pcbWriteProcess)
    75526892                *pcbWriteProcess = cbToWrite;
     
    75556895    else
    75566896        rc = VERR_VD_IMAGE_READ_ONLY;
    7557 
    75586897    LogFlowFunc(("returns %Rrc\n", rc));
    75596898    return rc;
    75606899}
    7561 
    75626900/** @copydoc VDIMAGEBACKEND::pfnFlush */
    75636901static DECLCALLBACK(int) vmdkFlush(void *pBackendData, PVDIOCTX pIoCtx)
    75646902{
    75656903    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7566 
    75676904    return vmdkFlushImage(pImage, pIoCtx);
    75686905}
    7569 
    75706906/** @copydoc VDIMAGEBACKEND::pfnGetVersion */
    75716907static DECLCALLBACK(unsigned) vmdkGetVersion(void *pBackendData)
     
    75736909    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    75746910    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7575 
    75766911    AssertPtrReturn(pImage, 0);
    7577 
    75786912    return VMDK_IMAGE_VERSION;
    75796913}
    7580 
    75816914/** @copydoc VDIMAGEBACKEND::pfnGetFileSize */
    75826915static DECLCALLBACK(uint64_t) vmdkGetFileSize(void *pBackendData)
     
    75856918    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    75866919    uint64_t cb = 0;
    7587 
    75886920    AssertPtrReturn(pImage, 0);
    7589 
    75906921    if (pImage->pFile != NULL)
    75916922    {
     
    76056936        }
    76066937    }
    7607 
    76086938    LogFlowFunc(("returns %lld\n", cb));
    76096939    return cb;
    76106940}
    7611 
    76126941/** @copydoc VDIMAGEBACKEND::pfnGetPCHSGeometry */
    76136942static DECLCALLBACK(int) vmdkGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
     
    76166945    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    76176946    int rc = VINF_SUCCESS;
    7618 
    76196947    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7620 
    76216948    if (pImage->PCHSGeometry.cCylinders)
    76226949        *pPCHSGeometry = pImage->PCHSGeometry;
    76236950    else
    76246951        rc = VERR_VD_GEOMETRY_NOT_SET;
    7625 
    76266952    LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    76276953    return rc;
    76286954}
    7629 
    76306955/** @copydoc VDIMAGEBACKEND::pfnSetPCHSGeometry */
    76316956static DECLCALLBACK(int) vmdkSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
     
    76356960    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    76366961    int rc = VINF_SUCCESS;
    7637 
    76386962    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7639 
    76406963    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    76416964    {
     
    76516974    else
    76526975        rc = VERR_VD_IMAGE_READ_ONLY;
    7653 
    76546976    LogFlowFunc(("returns %Rrc\n", rc));
    76556977    return rc;
    76566978}
    7657 
    76586979/** @copydoc VDIMAGEBACKEND::pfnGetLCHSGeometry */
    76596980static DECLCALLBACK(int) vmdkGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
     
    76626983    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    76636984    int rc = VINF_SUCCESS;
    7664 
    76656985    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7666 
    76676986    if (pImage->LCHSGeometry.cCylinders)
    76686987        *pLCHSGeometry = pImage->LCHSGeometry;
    76696988    else
    76706989        rc = VERR_VD_GEOMETRY_NOT_SET;
    7671 
    76726990    LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    76736991    return rc;
    76746992}
    7675 
    76766993/** @copydoc VDIMAGEBACKEND::pfnSetLCHSGeometry */
    76776994static DECLCALLBACK(int) vmdkSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
     
    76816998    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    76826999    int rc = VINF_SUCCESS;
    7683 
    76847000    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7685 
    76867001    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    76877002    {
     
    76977012    else
    76987013        rc = VERR_VD_IMAGE_READ_ONLY;
    7699 
    77007014    LogFlowFunc(("returns %Rrc\n", rc));
    77017015    return rc;
    77027016}
    7703 
    77047017/** @copydoc VDIMAGEBACKEND::pfnQueryRegions */
    77057018static DECLCALLBACK(int) vmdkQueryRegions(void *pBackendData, PCVDREGIONLIST *ppRegionList)
     
    77077020    LogFlowFunc(("pBackendData=%#p ppRegionList=%#p\n", pBackendData, ppRegionList));
    77087021    PVMDKIMAGE pThis = (PVMDKIMAGE)pBackendData;
    7709 
    77107022    AssertPtrReturn(pThis, VERR_VD_NOT_OPENED);
    7711 
    77127023    *ppRegionList = &pThis->RegionList;
    77137024    LogFlowFunc(("returns %Rrc\n", VINF_SUCCESS));
    77147025    return VINF_SUCCESS;
    77157026}
    7716 
    77177027/** @copydoc VDIMAGEBACKEND::pfnRegionListRelease */
    77187028static DECLCALLBACK(void) vmdkRegionListRelease(void *pBackendData, PCVDREGIONLIST pRegionList)
     
    77227032    PVMDKIMAGE pThis = (PVMDKIMAGE)pBackendData;
    77237033    AssertPtr(pThis); RT_NOREF(pThis);
    7724 
    77257034    /* Nothing to do here. */
    77267035}
    7727 
    77287036/** @copydoc VDIMAGEBACKEND::pfnGetImageFlags */
    77297037static DECLCALLBACK(unsigned) vmdkGetImageFlags(void *pBackendData)
     
    77317039    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    77327040    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7733 
    77347041    AssertPtrReturn(pImage, 0);
    7735 
    77367042    LogFlowFunc(("returns %#x\n", pImage->uImageFlags));
    77377043    return pImage->uImageFlags;
    77387044}
    7739 
    77407045/** @copydoc VDIMAGEBACKEND::pfnGetOpenFlags */
    77417046static DECLCALLBACK(unsigned) vmdkGetOpenFlags(void *pBackendData)
     
    77437048    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    77447049    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7745 
    77467050    AssertPtrReturn(pImage, 0);
    7747 
    77487051    LogFlowFunc(("returns %#x\n", pImage->uOpenFlags));
    77497052    return pImage->uOpenFlags;
    77507053}
    7751 
    77527054/** @copydoc VDIMAGEBACKEND::pfnSetOpenFlags */
    77537055static DECLCALLBACK(int) vmdkSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     
    77567058    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    77577059    int rc;
    7758 
    77597060    /* Image must be opened and the new flags must be valid. */
    77607061    if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
     
    77797080        }
    77807081    }
    7781 
    77827082    LogFlowFunc(("returns %Rrc\n", rc));
    77837083    return rc;
    77847084}
    7785 
    77867085/** @copydoc VDIMAGEBACKEND::pfnGetComment */
    77877086static DECLCALLBACK(int) vmdkGetComment(void *pBackendData, char *pszComment, size_t cbComment)
     
    77897088    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
    77907089    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7791 
    77927090    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7793 
    77947091    char *pszCommentEncoded = NULL;
    77957092    int rc = vmdkDescDDBGetStr(pImage, &pImage->Descriptor,
     
    78007097        rc = VINF_SUCCESS;
    78017098    }
    7802 
    78037099    if (RT_SUCCESS(rc))
    78047100    {
     
    78077103        else if (pszComment)
    78087104                *pszComment = '\0';
    7809 
    78107105        if (pszCommentEncoded)
    78117106            RTMemTmpFree(pszCommentEncoded);
    78127107    }
    7813 
    78147108    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    78157109    return rc;
    78167110}
    7817 
    78187111/** @copydoc VDIMAGEBACKEND::pfnSetComment */
    78197112static DECLCALLBACK(int) vmdkSetComment(void *pBackendData, const char *pszComment)
     
    78227115    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    78237116    int rc;
    7824 
    78257117    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7826 
    78277118    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    78287119    {
     
    78347125    else
    78357126        rc = VERR_VD_IMAGE_READ_ONLY;
    7836 
    78377127    LogFlowFunc(("returns %Rrc\n", rc));
    78387128    return rc;
    78397129}
    7840 
    78417130/** @copydoc VDIMAGEBACKEND::pfnGetUuid */
    78427131static DECLCALLBACK(int) vmdkGetUuid(void *pBackendData, PRTUUID pUuid)
     
    78447133    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    78457134    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7846 
    78477135    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7848 
    78497136    *pUuid = pImage->ImageUuid;
    7850 
    78517137    LogFlowFunc(("returns %Rrc (%RTuuid)\n", VINF_SUCCESS, pUuid));
    78527138    return VINF_SUCCESS;
    78537139}
    7854 
    78557140/** @copydoc VDIMAGEBACKEND::pfnSetUuid */
    78567141static DECLCALLBACK(int) vmdkSetUuid(void *pBackendData, PCRTUUID pUuid)
     
    78597144    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    78607145    int rc = VINF_SUCCESS;
    7861 
    78627146    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7863 
    78647147    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    78657148    {
     
    78787161    else
    78797162        rc = VERR_VD_IMAGE_READ_ONLY;
    7880 
    78817163    LogFlowFunc(("returns %Rrc\n", rc));
    78827164    return rc;
    78837165}
    7884 
    78857166/** @copydoc VDIMAGEBACKEND::pfnGetModificationUuid */
    78867167static DECLCALLBACK(int) vmdkGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     
    78887169    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    78897170    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7890 
    78917171    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7892 
    78937172    *pUuid = pImage->ModificationUuid;
    7894 
    78957173    LogFlowFunc(("returns %Rrc (%RTuuid)\n", VINF_SUCCESS, pUuid));
    78967174    return VINF_SUCCESS;
    78977175}
    7898 
    78997176/** @copydoc VDIMAGEBACKEND::pfnSetModificationUuid */
    79007177static DECLCALLBACK(int) vmdkSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     
    79037180    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    79047181    int rc = VINF_SUCCESS;
    7905 
    79067182    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7907 
    79087183    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    79097184    {
     
    79257200    else
    79267201        rc = VERR_VD_IMAGE_READ_ONLY;
    7927 
    79287202    LogFlowFunc(("returns %Rrc\n", rc));
    79297203    return rc;
    79307204}
    7931 
    79327205/** @copydoc VDIMAGEBACKEND::pfnGetParentUuid */
    79337206static DECLCALLBACK(int) vmdkGetParentUuid(void *pBackendData, PRTUUID pUuid)
     
    79357208    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    79367209    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7937 
    79387210    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7939 
    79407211    *pUuid = pImage->ParentUuid;
    7941 
    79427212    LogFlowFunc(("returns %Rrc (%RTuuid)\n", VINF_SUCCESS, pUuid));
    79437213    return VINF_SUCCESS;
    79447214}
    7945 
    79467215/** @copydoc VDIMAGEBACKEND::pfnSetParentUuid */
    79477216static DECLCALLBACK(int) vmdkSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     
    79507219    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    79517220    int rc = VINF_SUCCESS;
    7952 
    79537221    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7954 
    79557222    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    79567223    {
     
    79697236    else
    79707237        rc = VERR_VD_IMAGE_READ_ONLY;
    7971 
    79727238    LogFlowFunc(("returns %Rrc\n", rc));
    79737239    return rc;
    79747240}
    7975 
    79767241/** @copydoc VDIMAGEBACKEND::pfnGetParentModificationUuid */
    79777242static DECLCALLBACK(int) vmdkGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     
    79797244    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    79807245    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7981 
    79827246    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7983 
    79847247    *pUuid = pImage->ParentModificationUuid;
    7985 
    79867248    LogFlowFunc(("returns %Rrc (%RTuuid)\n", VINF_SUCCESS, pUuid));
    79877249    return VINF_SUCCESS;
    79887250}
    7989 
    79907251/** @copydoc VDIMAGEBACKEND::pfnSetParentModificationUuid */
    79917252static DECLCALLBACK(int) vmdkSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     
    79947255    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    79957256    int rc = VINF_SUCCESS;
    7996 
    79977257    AssertPtrReturn(pImage, VERR_VD_NOT_OPENED);
    7998 
    79997258    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    80007259    {
     
    80127271    else
    80137272        rc = VERR_VD_IMAGE_READ_ONLY;
    8014 
    80157273    LogFlowFunc(("returns %Rrc\n", rc));
    80167274    return rc;
    80177275}
    8018 
    80197276/** @copydoc VDIMAGEBACKEND::pfnDump */
    80207277static DECLCALLBACK(void) vmdkDump(void *pBackendData)
    80217278{
    80227279    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    8023 
    80247280    AssertPtrReturnVoid(pImage);
    80257281    vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
     
    80327288    vdIfErrorMessage(pImage->pIfError, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid);
    80337289}
    8034 
    8035 
    8036 
    80377290const VDIMAGEBACKEND g_VmdkBackend =
    80387291{
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette