VirtualBox

Ignore:
Timestamp:
Sep 12, 2010 4:09:57 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
65797
Message:

VD: Fun with DMG images, booting from them seems to work

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DMGHDDCore.cpp

    r32431 r32432  
    55
    66/*
    7  * Copyright (C) 2009 Oracle Corporation
     7 * Copyright (C) 2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020*******************************************************************************/
    2121#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo log group */
    22 #include <VBox/VBoxHDD.h>
     22#include <VBox/VBoxHDD-Plugin.h>
    2323#include <VBox/log.h>
    2424#include <VBox/err.h>
     
    3535#endif
    3636
    37 
    3837/*******************************************************************************
    3938*   Structures and Typedefs                                                    *
    4039*******************************************************************************/
     40
     41/** Sector size, multiply with all sector counts to get number of bytes. */
     42#define VBOXDMG_SECTOR_SIZE 512
     43
    4144/**
    4245 * UDIF checksum structure.
     
    144147
    145148/**
     149 * BLKX data.
     150 *
     151 * This contains the start offset and size of raw data sotred in the image.
     152 *
     153 * All fields are stored in big endian format.
     154 */
     155#pragma pack(1)
     156typedef struct VBOXBLKX
     157{
     158    uint32_t            u32Magic;               /**< 0x000 - Magic, 'mish' (VBOXBLKX_MAGIC). */
     159    uint32_t            u32Version;             /**< 0x004 - The BLKX version (VBOXBLKX_VER_CURRENT). */
     160    uint64_t            cSectornumberFirst;     /**< 0x008 - The first sector number the block represents in the virtual device. */
     161    uint64_t            cSectors;               /**< 0x010 - Number of sectors this block represents. */
     162    uint64_t            offDataStart;           /**< 0x018 - Start offset for raw data. */
     163    uint32_t            cSectorsDecompress;     /**< 0x020 - Size of the buffer in sectors needed to decompress. */
     164    uint32_t            u32BlocksDescriptor;    /**< 0x024 - Blocks descriptor. */
     165    uint8_t             abReserved[24];
     166    VBOXUDIFCKSUM       BlkxCkSum;              /**< 0x03c - Checksum for the BLKX table. */
     167    uint32_t            cBlocksRunCount;        /**< 0x    - Number of entries in the blkx run table afterwards. */
     168} VBOXBLKX;
     169#pragma pack(0)
     170AssertCompileSize(VBOXBLKX, 204);
     171
     172typedef VBOXBLKX *PVBOXBLKX;
     173typedef const VBOXBLKX *PCVBOXBLKX;
     174
     175/** The BLKX magic 'mish' (VBOXBLKX::u32Magic). */
     176#define VBOXBLKX_MAGIC              UINT32_C(0x6d697368)
     177/** BLKX version (VBOXBLKX::u32Version). */
     178#define VBOXBLKX_VERSION            UINT32_C(0x00000001)
     179
     180/** Blocks descriptor type: entire device. */
     181#define VBOXBLKX_DESC_ENTIRE_DEVICE UINT32_C(0xfffffffe)
     182
     183/**
     184 * BLKX table descriptor.
     185 *
     186 * All fields are stored in big endian format.
     187 */
     188#pragma pack(1)
     189typedef struct VBOXBLKXDESC
     190{
     191    uint32_t            u32Type;                /**< 0x000 - Type of the descriptor. */
     192    uint32_t            u32Reserved;            /**< 0x004 - Reserved, but contains +beg or +end in case thisi is a comment descriptor. */
     193    uint64_t            u64SectorStart;         /**< 0x008 - First sector number in the block this entry describes. */
     194    uint64_t            u64SectorCount;         /**< 0x010 - Number of sectors this entry describes. */
     195    uint64_t            offData;                /**< 0x018 - Offset in the image where the data starts. */
     196    uint64_t            cbData;                 /**< 0x020 - Number of bytes in the image. */
     197} VBOXBLKXDESC;
     198#pragma pack(0)
     199AssertCompileSize(VBOXBLKXDESC, 40);
     200
     201typedef VBOXBLKXDESC *PVBOXBLKXDESC;
     202typedef const VBOXBLKXDESC *PCVBOXBLKXDESC;
     203
     204/** Raw image data type. */
     205#define VBOXBLKXDESC_TYPE_RAW        1
     206/** Ignore type. */
     207#define VBOXBLKXDESC_TYPE_IGNORE     2
     208/** Comment type. */
     209#define VBOXBLKXDESC_TYPE_COMMENT    UINT32_C(0x7ffffffe)
     210/** Terminator type. */
     211#define VBOXBLKXDESC_TYPE_TERMINATOR UINT32_C(0xffffffff)
     212
     213/**
    146214 * UDIF Resource Entry.
    147215 */
     
    177245    /** The array entries.
    178246     * A lazy bird ASSUME there are no more than 4 entries in any DMG. Increase the
    179      * size if DMGs with more are found. */
    180     VBOXUDIFRSRCENTRY   aEntries[4];
     247     * size if DMGs with more are found.
     248     * r=aeichner: Saw one with 6 here (image of a whole DVD) */
     249    VBOXUDIFRSRCENTRY   aEntries[10];
    181250} VBOXUDIFRSRCARRAY;
    182251/** Pointer to a UDIF resource array. */
     
    185254typedef VBOXUDIFRSRCARRAY const *PCVBOXUDIFRSRCARRAY;
    186255
    187 
     256/**
     257 * DMG extent types.
     258 */
     259typedef enum DMGEXTENTTYPE
     260{
     261    /** Null, never used. */
     262    DMGEXTENTTYPE_NULL = 0,
     263    /** Raw image data. */
     264    DMGEXTENTTYPE_RAW,
     265    /** Zero extent, reads return 0 and writes have no effect. */
     266    DMGEXTENTTYPE_ZERO,
     267    /** 32bit hack. */
     268    DMGEXTENTTYPE_32BIT_HACK = 0x7fffffff
     269} DMGEXTENTTYPE, *PDMGEXTENTTYPE;
     270
     271/**
     272 * DMG extent mapping a virtual image block to real file offsets.
     273 */
     274typedef struct DMGEXTENT
     275{
     276    /** Next DMG extent, sorted by virtual sector count. */
     277    struct DMGEXTENT    *pNext;
     278    /** Extent type. */
     279    DMGEXTENTTYPE        enmType;
     280    /** First byte this extent describes. */
     281    uint64_t             offExtent;
     282    /** Number of bytes this extent describes. */
     283    uint64_t             cbExtent;
     284    /** Start offset in the real file. */
     285    uint64_t             offFileStart;
     286} DMGEXTENT;
     287/** Pointer to an DMG extent. */
     288typedef DMGEXTENT *PDMGEXTENT;
    188289
    189290/**
    190291 * VirtualBox Apple Disk Image (DMG) interpreter instance data.
    191292 */
    192 typedef struct VBOXDMG
    193 {
    194     /** The open image file. */
    195     RTFILE              hFile;
    196     /** The current file size. */
     293typedef struct DMGIMAGE
     294{
     295    /** Pointer to the per-disk VD interface list. */
     296    PVDINTERFACE        pVDIfsDisk;
     297    /** Pointer to the per-image VD interface list. */
     298    PVDINTERFACE        pVDIfsImage;
     299
     300    /** Storage handle. */
     301    PVDIOSTORAGE        pStorage;
     302    /** Size of the image. */
    197303    uint64_t            cbFile;
     304    /** I/O interface. */
     305    PVDINTERFACE        pInterfaceIO;
     306    /** Async I/O interface callbacks. */
     307    PVDINTERFACEIO      pInterfaceIOCallbacks;
     308    /** Error callback. */
     309    PVDINTERFACE        pInterfaceError;
     310    /** Opaque data for error callback. */
     311    PVDINTERFACEERROR   pInterfaceErrorCallbacks;
    198312    /** Flags the image was opened with. */
    199     uint32_t            fOpenFlags;
     313    uint32_t            uOpenFlags;
     314    /** Image flags. */
     315    unsigned            uImageFlags;
    200316    /** The filename.
    201317     * Kept around for logging and delete-on-close purposes. */
     
    207323    /** The UDIF footer. */
    208324    VBOXUDIF            Ftr;
    209 } VBOXDMG;
     325
     326    /** Total size of the virtual image. */
     327    uint64_t            cbSize;
     328    /** Physical geometry of this image. */
     329    PDMMEDIAGEOMETRY    PCHSGeometry;
     330    /** Logical geometry of this image. */
     331    PDMMEDIAGEOMETRY    LCHSGeometry;
     332    /** First extent in the list. */
     333    PDMGEXTENT          pExtentFirst;
     334    /** Last extent in the list. */
     335    PDMGEXTENT          pExtentLast;
     336} DMGIMAGE;
    210337/** Pointer to an instance of the DMG Image Interpreter. */
    211 typedef VBOXDMG *PVBOXDMG;
     338typedef DMGIMAGE *PDMGIMAGE;
    212339
    213340/** @name Resources indexes (into VBOXDMG::aRsrcs).
     
    273400static bool vboxdmgUdifCkSumIsValid(PCVBOXUDIFCKSUM pCkSum, const char *pszPrefix);
    274401
     402/**
     403 * Internal: signal an error to the frontend.
     404 */
     405DECLINLINE(int) dmgError(PDMGIMAGE pImage, int rc, RT_SRC_POS_DECL,
     406                         const char *pszFormat, ...)
     407{
     408    va_list va;
     409    va_start(va, pszFormat);
     410    if (pImage->pInterfaceError)
     411        pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
     412                                                   pszFormat, va);
     413    va_end(va);
     414    return rc;
     415}
     416
     417static int dmgFileOpen(PDMGIMAGE pImage, bool fReadonly, bool fCreate)
     418{
     419    AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
     420
     421    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
     422
     423    if (fCreate)
     424        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
     425
     426    return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     427                                                  pImage->pszFilename,
     428                                                  uOpenFlags,
     429                                                  &pImage->pStorage);
     430}
     431
     432static int dmgFileClose(PDMGIMAGE pImage)
     433{
     434    int rc = VINF_SUCCESS;
     435
     436    if (pImage->pStorage)
     437        rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     438                                                     pImage->pStorage);
     439
     440    pImage->pStorage = NULL;
     441
     442    return rc;
     443}
     444
     445static int dmgFileFlushSync(PDMGIMAGE pImage)
     446{
     447    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     448                                                       pImage->pStorage);
     449}
     450
     451static int dmgFileGetSize(PDMGIMAGE pImage, uint64_t *pcbSize)
     452{
     453    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     454                                                     pImage->pStorage,
     455                                                     pcbSize);
     456}
     457
     458static int dmgFileSetSize(PDMGIMAGE pImage, uint64_t cbSize)
     459{
     460    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     461                                                     pImage->pStorage,
     462                                                     cbSize);
     463}
     464
     465static int dmgFileWriteSync(PDMGIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
     466{
     467    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     468                                                       pImage->pStorage,
     469                                                       off, cbWrite, pcvBuf,
     470                                                       pcbWritten);
     471}
     472
     473static int dmgFileReadSync(PDMGIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
     474{
     475    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     476                                                      pImage->pStorage,
     477                                                      off, cbRead, pvBuf,
     478                                                      pcbRead);
     479}
     480
     481static bool dmgFileOpened(PDMGIMAGE pImage)
     482{
     483    return pImage->pStorage != NULL;
     484}
    275485
    276486/**
     
    325535}
    326536
     537/**
     538 * Swaps endian from file to host cpu.
     539 * @param   pBlkx       The blkx structure.
     540 */
     541static void vboxdmgBlkxFile2HostEndian(PVBOXBLKX pBlkx)
     542{
     543    pBlkx->u32Magic            = RT_BE2H_U32(pBlkx->u32Magic);
     544    pBlkx->u32Version          = RT_BE2H_U32(pBlkx->u32Version);
     545    pBlkx->cSectornumberFirst  = RT_BE2H_U64(pBlkx->cSectornumberFirst);
     546    pBlkx->cSectors            = RT_BE2H_U64(pBlkx->cSectors);
     547    pBlkx->offDataStart        = RT_BE2H_U64(pBlkx->offDataStart);
     548    pBlkx->cSectorsDecompress  = RT_BE2H_U32(pBlkx->cSectorsDecompress);
     549    pBlkx->u32BlocksDescriptor = RT_BE2H_U32(pBlkx->u32BlocksDescriptor);
     550    pBlkx->cBlocksRunCount     = RT_BE2H_U32(pBlkx->cBlocksRunCount);
     551    vboxdmgUdifCkSumFile2HostEndian(&pBlkx->BlkxCkSum);
     552}
     553
     554/**
     555 * Swaps endian from file to host cpu.
     556 * @param   pBlkxDesc   The blkx descriptor structure.
     557 */
     558static void vboxdmgBlkxDescFile2HostEndian(PVBOXBLKXDESC pBlkxDesc)
     559{
     560    pBlkxDesc->u32Type        = RT_BE2H_U32(pBlkxDesc->u32Type);
     561    pBlkxDesc->u32Reserved    = RT_BE2H_U32(pBlkxDesc->u32Reserved);
     562    pBlkxDesc->u64SectorStart = RT_BE2H_U64(pBlkxDesc->u64SectorStart);
     563    pBlkxDesc->u64SectorCount = RT_BE2H_U64(pBlkxDesc->u64SectorCount);
     564    pBlkxDesc->offData        = RT_BE2H_U64(pBlkxDesc->offData);
     565    pBlkxDesc->cbData         = RT_BE2H_U64(pBlkxDesc->cbData);
     566}
    327567
    328568/**
     
    344584    VBOXDMG_VALIDATE(pFtr->offRsrc    < offFtr, ("offRsrc=%#RX64\n", pFtr->offRsrc));
    345585    VBOXDMG_VALIDATE(pFtr->cSegments <= 1,      ("cSegments=%RU32\n", pFtr->cSegments));
    346     VBOXDMG_VALIDATE(pFtr->iSegment  == 0,      ("iSegment=%RU32 cSegments=%RU32\n", pFtr->iSegment, pFtr->cSegments));
     586    VBOXDMG_VALIDATE(pFtr->iSegment  == 0 || pFtr->iSegment == 1, ("iSegment=%RU32 cSegments=%RU32\n", pFtr->iSegment, pFtr->cSegments));
    347587    VBOXDMG_VALIDATE(pFtr->cbXml    <= offFtr && pFtr->offXml + pFtr->cbXml <= offFtr, ("cbXml=%#RX64 offXml=%#RX64 offFtr=%#RX64\n", pFtr->cbXml, pFtr->offXml, offFtr));
    348588    VBOXDMG_VALIDATE(pFtr->offXml    < offFtr,  ("offXml=%#RX64\n", pFtr->offXml));
     
    351591    VBOXDMG_VALIDATE(pFtr->u32Type == VBOXUDIF_TYPE_DEVICE || pFtr->u32Type == VBOXUDIF_TYPE_PARTITION,  ("u32Type=%RU32\n", pFtr->u32Type));
    352592    VBOXDMG_VALIDATE(pFtr->cSectors != 0,       ("cSectors=%#RX64\n", pFtr->cSectors));
    353     vboxdmgUdifCkSumIsValid(&pFtr->DataCkSum, "DataCkSum");
    354     vboxdmgUdifCkSumIsValid(&pFtr->MasterCkSum, "MasterCkSum");
     593    fRc &= vboxdmgUdifCkSumIsValid(&pFtr->DataCkSum, "DataCkSum");
     594    fRc &= vboxdmgUdifCkSumIsValid(&pFtr->MasterCkSum, "MasterCkSum");
    355595
    356596    return fRc;
    357597}
    358598
     599
     600static bool vboxdmgBlkxIsValid(PCVBOXBLKX pBlkx)
     601{
     602    bool fRc = true;
     603
     604    fRc &= vboxdmgUdifCkSumIsValid(&pBlkx->BlkxCkSum, "BlkxCkSum");
     605    VBOXDMG_VALIDATE(pBlkx->u32Magic == VBOXBLKX_MAGIC, ("u32Magic=%#RX32 u32MagicExpected=%#RX32\n", pBlkx->u32Magic, VBOXBLKX_MAGIC));
     606    VBOXDMG_VALIDATE(pBlkx->u32Version == VBOXBLKX_VERSION, ("u32Version=%#RX32 u32VersionExpected=%#RX32\n", pBlkx->u32Magic, VBOXBLKX_VERSION));
     607
     608    return fRc;
     609}
    359610
    360611/**
     
    464715static DECLCALLBACK(int) vboxdmgClose(void *pvBackendData, bool fDelete)
    465716{
    466     PVBOXDMG pThis = (PVBOXDMG)pvBackendData;
    467 
    468     if (pThis->hFile != NIL_RTFILE)
     717    PDMGIMAGE pThis = (PDMGIMAGE)pvBackendData;
     718
     719    if (dmgFileOpened(pThis))
    469720    {
    470721        /*
     
    476727         * Close the file.
    477728         */
    478         RTFileClose(pThis->hFile);
    479         pThis->hFile = NIL_RTFILE;
     729        dmgFileClose(pThis);
    480730    }
    481731
     
    745995 * @param   cch         The size of the the XML text.
    746996 */
    747 static const char *vboxdmgOpenXmlToRsrc(PVBOXDMG pThis, char const *pszXml)
     997static const char *vboxdmgOpenXmlToRsrc(PDMGIMAGE pThis, char const *pszXml)
    748998{
    749999    const char *psz = pszXml;
     
    8711121            REQUIRE_END_TAG(psz, "dict");
    8721122
     1123            pThis->aRsrcs[iRsrc].cEntries++;
    8731124        } /* while not </array> */
    8741125        REQUIRE_END_TAG(psz, "array");
     
    9001151#undef STARTS_WITH
    9011152
     1153/**
     1154 * Returns the data attached to a resource.
     1155 *
     1156 * @returns VBox status code.
     1157 * @param   pThis        The DMG instance data.
     1158 * @param   pcszRsrcName Name of the resource to get.
     1159 */
     1160static int dmgGetRsrcData(PDMGIMAGE pThis, const char *pcszRsrcName,
     1161                          PCVBOXUDIFRSRCARRAY *ppcRsrc)
     1162{
     1163    int rc = VERR_NOT_FOUND;
     1164
     1165    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aRsrcs); i++)
     1166    {
     1167        if (!strcmp(pThis->aRsrcs[i].szName, pcszRsrcName))
     1168        {
     1169            *ppcRsrc = &pThis->aRsrcs[i];
     1170            rc = VINF_SUCCESS;
     1171            break;
     1172        }
     1173    }
     1174
     1175    return rc;
     1176}
     1177
     1178/**
     1179 * Creates a new extent from the given blkx descriptor.
     1180 *
     1181 * @returns VBox status code.
     1182 * @param   pThis     DMG instance data.
     1183 * @param   pBlkxDesc The blkx descriptor.
     1184 */
     1185static int vboxdmgExtentCreateFromBlkxDesc(PDMGIMAGE pThis, uint64_t offDevice, PVBOXBLKXDESC pBlkxDesc)
     1186{
     1187    int rc = VINF_SUCCESS;
     1188    DMGEXTENTTYPE enmExtentTypeNew;
     1189    PDMGEXTENT pExtentNew = NULL;
     1190
     1191    if (pBlkxDesc->u32Type == VBOXBLKXDESC_TYPE_RAW)
     1192        enmExtentTypeNew = DMGEXTENTTYPE_RAW;
     1193    else if (pBlkxDesc->u32Type == VBOXBLKXDESC_TYPE_IGNORE)
     1194        enmExtentTypeNew = DMGEXTENTTYPE_ZERO;
     1195    else
     1196        AssertMsgFailed(("This method supports only raw or zero extents!\n"));
     1197
     1198#if 0
     1199    pExtentNew = pThis->pExtentLast;
     1200    if (   pExtentNew
     1201        && pExtentNew->enmType == enmExtentTypeNew
     1202        && pExtentNew->offExtent + pExtentNew->cbExtent == offDevice + pBlkxDesc->u64SectorStart * VBOXDMG_SECTOR_SIZE;
     1203        && pExtentNew->offFileStart + pExtentNew->cbExtent == pBlkxDesc->offData)
     1204    {
     1205        /* Increase the last extent. */
     1206        pExtentNew->cbExtent += pBlkxDesc->cbData;
     1207    }
     1208    else
     1209#endif
     1210    {
     1211        /* Create a new extent. */
     1212        pExtentNew = (PDMGEXTENT)RTMemAllocZ(sizeof(DMGEXTENT));
     1213        if (pExtentNew)
     1214        {
     1215            pExtentNew->pNext        = NULL;
     1216            pExtentNew->enmType      = enmExtentTypeNew;
     1217            pExtentNew->offExtent    = offDevice + pBlkxDesc->u64SectorStart * VBOXDMG_SECTOR_SIZE;
     1218            pExtentNew->offFileStart = pBlkxDesc->offData;
     1219            pExtentNew->cbExtent     = pBlkxDesc->u64SectorCount * VBOXDMG_SECTOR_SIZE;
     1220            Assert(   pBlkxDesc->cbData == pBlkxDesc->u64SectorCount * VBOXDMG_SECTOR_SIZE
     1221                   || enmExtentTypeNew == DMGEXTENTTYPE_ZERO);
     1222
     1223            if (!pThis->pExtentLast)
     1224            {
     1225                pThis->pExtentFirst = pExtentNew;
     1226                pThis->pExtentLast  = pExtentNew;
     1227            }
     1228            else
     1229            {
     1230                pThis->pExtentLast->pNext = pExtentNew;
     1231                pThis->pExtentLast        = pExtentNew;
     1232            }
     1233        }
     1234        else
     1235            rc = VERR_NO_MEMORY;
     1236    }
     1237
     1238    return rc;
     1239}
     1240
     1241/**
     1242 * Find the extent for the given offset.
     1243 */
     1244static PDMGEXTENT dmgExtentGetFromOffset(PDMGIMAGE pThis, uint64_t uOffset)
     1245{
     1246    PDMGEXTENT pExtent = pThis->pExtentFirst;
     1247
     1248    while (   pExtent
     1249           && (   uOffset < pExtent->offExtent
     1250               || uOffset - pExtent->offExtent >= pExtent->cbExtent))
     1251        pExtent = pExtent->pNext;
     1252
     1253    return pExtent;
     1254}
     1255
     1256/**
     1257 * Goes through the BLKX structure and creates the necessary extents.
     1258 */
     1259static int vboxdmgBlkxParse(PDMGIMAGE pThis, PVBOXBLKX pBlkx)
     1260{
     1261    int rc = VINF_SUCCESS;
     1262    PVBOXBLKXDESC pBlkxDesc = (PVBOXBLKXDESC)(pBlkx + 1);
     1263
     1264    for (unsigned i = 0; i < pBlkx->cBlocksRunCount; i++)
     1265    {
     1266        vboxdmgBlkxDescFile2HostEndian(pBlkxDesc);
     1267
     1268        switch (pBlkxDesc->u32Type)
     1269        {
     1270            case VBOXBLKXDESC_TYPE_RAW:
     1271            case VBOXBLKXDESC_TYPE_IGNORE:
     1272            {
     1273                rc = vboxdmgExtentCreateFromBlkxDesc(pThis, pBlkx->cSectornumberFirst * VBOXDMG_SECTOR_SIZE, pBlkxDesc);
     1274                break;
     1275            }
     1276            case VBOXBLKXDESC_TYPE_COMMENT:
     1277            case VBOXBLKXDESC_TYPE_TERMINATOR:
     1278                break;
     1279            default:
     1280                rc = VERR_VD_GEN_INVALID_HEADER;
     1281                break;
     1282        }
     1283
     1284        if (   pBlkxDesc->u32Type == VBOXBLKXDESC_TYPE_TERMINATOR
     1285            || RT_FAILURE(rc))
     1286                break;
     1287
     1288        pBlkxDesc++;
     1289    }
     1290
     1291    return rc;
     1292}
    9021293
    9031294/**
     
    9111302 * @param   pThis       The DMG instance data.
    9121303 */
    913 static int vboxdmgOpenWorker(PVBOXDMG pThis)
     1304static int vboxdmgOpenWorker(PDMGIMAGE pThis)
    9141305{
    9151306    /*
    9161307     * Read the footer.
    9171308     */
    918     int rc = RTFileGetSize(pThis->hFile, &pThis->cbFile);
     1309    int rc = dmgFileGetSize(pThis, &pThis->cbFile);
    9191310    if (RT_FAILURE(rc))
    9201311        return rc;
    9211312    if (pThis->cbFile < 1024)
    9221313        return VERR_VD_GEN_INVALID_HEADER;
    923     rc = RTFileReadAt(pThis->hFile, pThis->cbFile - sizeof(pThis->Ftr), &pThis->Ftr, sizeof(pThis->Ftr), NULL);
     1314    rc = dmgFileReadSync(pThis, pThis->cbFile - sizeof(pThis->Ftr), &pThis->Ftr, sizeof(pThis->Ftr), NULL);
    9241315    if (RT_FAILURE(rc))
    9251316        return rc;
     
    9421333    }
    9431334
     1335    pThis->cbSize = pThis->Ftr.cSectors * VBOXDMG_SECTOR_SIZE;
     1336
    9441337    /*
    9451338     * Read and parse the XML portion.
     
    9491342    if (!pszXml)
    9501343        return VERR_NO_MEMORY;
    951     rc = RTFileReadAt(pThis->hFile, pThis->Ftr.offXml, pszXml, cchXml, NULL);
     1344    rc = dmgFileReadSync(pThis, pThis->Ftr.offXml, pszXml, cchXml, NULL);
    9521345    if (RT_SUCCESS(rc))
    9531346    {
     
    9561349        if (!pszError)
    9571350        {
    958             /*
    959              * What is next?
    960              */
     1351            PCVBOXUDIFRSRCARRAY pRsrcBlkx = NULL;
     1352
     1353            rc = dmgGetRsrcData(pThis, "blkx", &pRsrcBlkx);
     1354            if (RT_SUCCESS(rc))
     1355            {
     1356                for (unsigned idxBlkx = 0; idxBlkx < pRsrcBlkx->cEntries; idxBlkx++)
     1357                {
     1358                    PVBOXBLKX pBlkx = NULL;
     1359
     1360                    if (pRsrcBlkx->aEntries[idxBlkx].cbData < sizeof(VBOXBLKX))
     1361                    {
     1362                        rc = VERR_VD_GEN_INVALID_HEADER;
     1363                        break;
     1364                    }
     1365
     1366                    pBlkx = (PVBOXBLKX)RTMemAllocZ(pRsrcBlkx->aEntries[idxBlkx].cbData);
     1367                    if (!pBlkx)
     1368                    {
     1369                        rc = VERR_NO_MEMORY;
     1370                        break;
     1371                    }
     1372
     1373                    memcpy(pBlkx, pRsrcBlkx->aEntries[idxBlkx].pbData, pRsrcBlkx->aEntries[idxBlkx].cbData);
     1374
     1375                    vboxdmgBlkxFile2HostEndian(pBlkx);
     1376
     1377                    if (   vboxdmgBlkxIsValid(pBlkx)
     1378                        && pRsrcBlkx->aEntries[idxBlkx].cbData == pBlkx->cBlocksRunCount * sizeof(VBOXBLKXDESC) + sizeof(VBOXBLKX))
     1379                        rc = vboxdmgBlkxParse(pThis, pBlkx);
     1380                    else
     1381                        rc = VERR_VD_GEN_INVALID_HEADER;
     1382
     1383                    if (RT_FAILURE(rc))
     1384                    {
     1385                        RTMemFree(pBlkx);
     1386                        break;
     1387                    }
     1388                }
     1389            }
     1390            else
     1391                rc = VERR_VD_GEN_INVALID_HEADER;
    9611392        }
    9621393        else
     
    9771408
    9781409
    979 
    9801410/** @copydoc VBOXHDDBACKEND::pfnOpen */
    981 static DECLCALLBACK(int) vboxdmgOpen(const char *pszFilename, unsigned fOpenFlags,
    982                                      PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    983                                      void **ppvBackendData)
     1411static DECLCALLBACK(int) dmgOpen(const char *pszFilename, unsigned fOpenFlags,
     1412                                 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     1413                                 void **ppvBackendData)
    9841414{
    9851415    /*
     
    9971427     * then hand it over to a worker function that does all the rest.
    9981428     */
    999     PVBOXDMG pThis = (PVBOXDMG)RTMemAllocZ(sizeof(*pThis));
     1429    PDMGIMAGE pThis = (PDMGIMAGE)RTMemAllocZ(sizeof(*pThis));
    10001430    if (!pThis)
    10011431        return VERR_NO_MEMORY;
    1002     pThis->fOpenFlags  = fOpenFlags;
     1432    pThis->uOpenFlags  = fOpenFlags;
    10031433    pThis->pszFilename = pszFilename;
    1004     pThis->hFile       = NIL_RTFILE;
    1005     //pThis->cbFile      = 0;
    1006 
    1007     int rc = RTFileOpen(&pThis->hFile, pszFilename,
    1008                         (fOpenFlags & VD_OPEN_FLAGS_READONLY ? RTFILE_O_READ : RTFILE_O_READWRITE)
    1009                         | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     1434    pThis->pStorage    = NULL;
     1435    pThis->pVDIfsDisk  = pVDIfsDisk;
     1436    pThis->pVDIfsImage = pVDIfsImage;
     1437
     1438    pThis->pInterfaceError = VDInterfaceGet(pThis->pVDIfsDisk, VDINTERFACETYPE_ERROR);
     1439    if (pThis->pInterfaceError)
     1440        pThis->pInterfaceErrorCallbacks = VDGetInterfaceError(pThis->pInterfaceError);
     1441
     1442    /* Try to get I/O interface. */
     1443    pThis->pInterfaceIO = VDInterfaceGet(pThis->pVDIfsImage, VDINTERFACETYPE_IO);
     1444    AssertPtr(pThis->pInterfaceIO);
     1445    pThis->pInterfaceIOCallbacks = VDGetInterfaceIO(pThis->pInterfaceIO);
     1446    AssertPtr(pThis->pInterfaceIOCallbacks);
     1447
     1448    int rc = dmgFileOpen(pThis, (fOpenFlags & VD_OPEN_FLAGS_READONLY ? true : false),
     1449                         false);
    10101450    if (RT_SUCCESS(rc))
    10111451    {
     
    10251465
    10261466/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
    1027 static DECLCALLBACK(int) vboxdmgCheckIfValid(const char *pszFilename)
     1467static DECLCALLBACK(int) dmgCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
    10281468{
    10291469    /*
     
    10701510}
    10711511
    1072 
    1073 
    1074 
    1075 #ifdef VBOXDMG_TESTING
    1076 int main(int argc, char **argv)
    1077 {
    1078     RTR3Init();
    1079 
    1080     const char *psz = argv[1];
    1081     if (!psz || argv[2])
    1082     {
    1083         RTPrintf("syntax: tstVBoxDMG <image>\n");
     1512/** @copydoc VBOXHDDBACKEND::pfnCreate */
     1513static int dmgCreate(const char *pszFilename, uint64_t cbSize,
     1514                     unsigned uImageFlags, const char *pszComment,
     1515                     PCPDMMEDIAGEOMETRY pPCHSGeometry,
     1516                     PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
     1517                     unsigned uOpenFlags, unsigned uPercentStart,
     1518                     unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
     1519                     PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
     1520                     void **ppBackendData)
     1521{
     1522    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p",
     1523                 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
     1524    return VERR_NOT_SUPPORTED;
     1525}
     1526
     1527/** @copydoc VBOXHDDBACKEND::pfnRename */
     1528static int dmgRename(void *pBackendData, const char *pszFilename)
     1529{
     1530    LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
     1531    int rc = VERR_NOT_SUPPORTED;
     1532
     1533    LogFlowFunc(("returns %Rrc\n", rc));
     1534    return rc;
     1535}
     1536
     1537/** @copydoc VBOXHDDBACKEND::pfnClose */
     1538static int dmgClose(void *pBackendData, bool fDelete)
     1539{
     1540    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
     1541    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1542    int rc = VINF_SUCCESS;
     1543
     1544    /* Freeing a never allocated image (e.g. because the open failed) is
     1545     * not signalled as an error. After all nothing bad happens. */
     1546    if (pImage)
     1547        vboxdmgClose(pImage, fDelete);
     1548
     1549    LogFlowFunc(("returns %Rrc\n", rc));
     1550    return rc;
     1551}
     1552
     1553/** @copydoc VBOXHDDBACKEND::pfnRead */
     1554static int dmgRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
     1555                   size_t cbToRead, size_t *pcbActuallyRead)
     1556{
     1557    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     1558    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1559    PDMGEXTENT pExtent = NULL;
     1560    int rc;
     1561
     1562    Assert(pImage);
     1563    Assert(uOffset % 512 == 0);
     1564    Assert(cbToRead % 512 == 0);
     1565
     1566    if (   uOffset + cbToRead > pImage->cbSize
     1567        || cbToRead == 0)
     1568    {
     1569        rc = VERR_INVALID_PARAMETER;
     1570        goto out;
     1571    }
     1572
     1573    pExtent = dmgExtentGetFromOffset(pImage, uOffset);
     1574
     1575    if (pExtent)
     1576    {
     1577        uint64_t offExtentRel = uOffset - pExtent->offExtent;
     1578
     1579        /* Remain in this extent. */
     1580        cbToRead = RT_MIN(cbToRead, pExtent->cbExtent - offExtentRel);
     1581
     1582        switch (pExtent->enmType)
     1583        {
     1584            case DMGEXTENTTYPE_RAW:
     1585            {
     1586                rc = dmgFileReadSync(pImage, pExtent->offFileStart + offExtentRel, pvBuf, cbToRead, NULL);
     1587                break;
     1588            }
     1589            case DMGEXTENTTYPE_ZERO:
     1590            {
     1591                memset(pvBuf, 0, cbToRead);
     1592                break;
     1593            }
     1594            default:
     1595                AssertMsgFailed(("Invalid extent type\n"));
     1596        }
     1597
     1598        if (RT_SUCCESS(rc))
     1599            *pcbActuallyRead = cbToRead;
     1600    }
     1601    else
     1602        rc = VERR_INVALID_PARAMETER;
     1603
     1604out:
     1605    LogFlowFunc(("returns %Rrc\n", rc));
     1606    return rc;
     1607}
     1608
     1609/** @copydoc VBOXHDDBACKEND::pfnWrite */
     1610static int dmgWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
     1611                    size_t cbToWrite, size_t *pcbWriteProcess,
     1612                    size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
     1613{
     1614    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     1615                 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     1616    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1617    int rc;
     1618
     1619    Assert(pImage);
     1620    Assert(uOffset % 512 == 0);
     1621    Assert(cbToWrite % 512 == 0);
     1622
     1623    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1624    {
     1625        rc = VERR_VD_IMAGE_READ_ONLY;
     1626        goto out;
     1627    }
     1628
     1629    AssertMsgFailed(("Not implemented\n"));
     1630
     1631out:
     1632    LogFlowFunc(("returns %Rrc\n", rc));
     1633    return rc;
     1634}
     1635
     1636/** @copydoc VBOXHDDBACKEND::pfnFlush */
     1637static int dmgFlush(void *pBackendData)
     1638{
     1639    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1640    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1641    int rc = VINF_SUCCESS;
     1642
     1643    AssertMsgFailed(("Not implemented\n"));
     1644    LogFlowFunc(("returns %Rrc\n", rc));
     1645    return rc;
     1646}
     1647
     1648/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
     1649static unsigned dmgGetVersion(void *pBackendData)
     1650{
     1651    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1652    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1653
     1654    Assert(pImage);
     1655
     1656    if (pImage)
    10841657        return 1;
    1085     }
    1086 
    1087     RTPrintf("tstVBoxDMG: TESTING '%s'...\n", psz);
    1088 
    1089     /* test 1 - vboxdmgCheckIfValid */
    1090     int rc = vboxdmgCheckIfValid(psz);
    1091     if (RT_FAILURE(rc))
    1092     {
    1093         RTPrintf("tstVBoxDMG: vboxdmgCheckIfValid failed, rc=%Rrc\n", rc);
    1094         return 1;
    1095     }
    1096     RTPrintf("tstVBoxDMG: vboxdmgCheckIfValid succeeded (rc=%Rrc)\n", rc);
    1097 
    1098 
    1099     /* test 1 - vboxdmgOpen(RDONLY) & Close. */
    1100     void *pvOpaque = NULL;
    1101     rc = vboxdmgOpen(psz, VD_OPEN_FLAGS_READONLY, NULL, NULL, &pvOpaque);
    1102     if (RT_FAILURE(rc))
    1103     {
    1104         RTPrintf("tstVBoxDMG: vboxdmgOpen(RDONLY) failed, rc=%Rrc\n", rc);
    1105         return 1;
    1106     }
    1107 
    1108     rc = vboxdmgClose(pvOpaque, false /* fDelete */);
    1109     if (RT_FAILURE(rc))
    1110     {
    1111         RTPrintf("tstVBoxDMG: vboxdmgClose(RDONLY) failed, rc=%Rrc\n", rc);
    1112         return 1;
    1113     }
    1114 
    1115 
    1116     RTPrintf("tstVBoxDMG: SUCCESS\n");
    1117     return 0;
    1118 }
     1658    else
     1659        return 0;
     1660}
     1661
     1662/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     1663static uint64_t dmgGetSize(void *pBackendData)
     1664{
     1665    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1666    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1667
     1668    Assert(pImage);
     1669
     1670    if (pImage)
     1671        return pImage->cbSize;
     1672    else
     1673        return 0;
     1674}
     1675
     1676/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
     1677static uint64_t dmgGetFileSize(void *pBackendData)
     1678{
     1679    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1680    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1681    uint64_t cb = 0;
     1682
     1683    Assert(pImage);
     1684
     1685    if (pImage)
     1686    {
     1687        uint64_t cbFile;
     1688        if (dmgFileOpened(pImage))
     1689        {
     1690            int rc = dmgFileGetSize(pImage, &cbFile);
     1691            if (RT_SUCCESS(rc))
     1692                cb += cbFile;
     1693        }
     1694    }
     1695
     1696    LogFlowFunc(("returns %lld\n", cb));
     1697    return cb;
     1698}
     1699
     1700/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
     1701static int dmgGetPCHSGeometry(void *pBackendData,
     1702                              PPDMMEDIAGEOMETRY pPCHSGeometry)
     1703{
     1704    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     1705    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1706    int rc;
     1707
     1708    Assert(pImage);
     1709
     1710    if (pImage)
     1711    {
     1712        if (pImage->PCHSGeometry.cCylinders)
     1713        {
     1714            *pPCHSGeometry = pImage->PCHSGeometry;
     1715            rc = VINF_SUCCESS;
     1716        }
     1717        else
     1718            rc = VERR_VD_GEOMETRY_NOT_SET;
     1719    }
     1720    else
     1721        rc = VERR_VD_NOT_OPENED;
     1722
     1723    LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     1724    return rc;
     1725}
     1726
     1727/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
     1728static int dmgSetPCHSGeometry(void *pBackendData,
     1729                              PCPDMMEDIAGEOMETRY pPCHSGeometry)
     1730{
     1731    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n",
     1732                 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     1733    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1734    int rc;
     1735
     1736    Assert(pImage);
     1737
     1738    if (pImage)
     1739    {
     1740        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1741        {
     1742            rc = VERR_VD_IMAGE_READ_ONLY;
     1743            goto out;
     1744        }
     1745
     1746        pImage->PCHSGeometry = *pPCHSGeometry;
     1747        rc = VINF_SUCCESS;
     1748    }
     1749    else
     1750        rc = VERR_VD_NOT_OPENED;
     1751
     1752out:
     1753    LogFlowFunc(("returns %Rrc\n", rc));
     1754    return rc;
     1755}
     1756
     1757/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
     1758static int dmgGetLCHSGeometry(void *pBackendData,
     1759                              PPDMMEDIAGEOMETRY pLCHSGeometry)
     1760{
     1761     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     1762    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1763    int rc;
     1764
     1765    Assert(pImage);
     1766
     1767    if (pImage)
     1768    {
     1769        if (pImage->LCHSGeometry.cCylinders)
     1770        {
     1771            *pLCHSGeometry = pImage->LCHSGeometry;
     1772            rc = VINF_SUCCESS;
     1773        }
     1774        else
     1775            rc = VERR_VD_GEOMETRY_NOT_SET;
     1776    }
     1777    else
     1778        rc = VERR_VD_NOT_OPENED;
     1779
     1780    LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     1781    return rc;
     1782}
     1783
     1784/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     1785static int dmgSetLCHSGeometry(void *pBackendData,
     1786                               PCPDMMEDIAGEOMETRY pLCHSGeometry)
     1787{
     1788    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n",
     1789                 pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     1790    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1791    int rc;
     1792
     1793    Assert(pImage);
     1794
     1795    if (pImage)
     1796    {
     1797        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1798        {
     1799            rc = VERR_VD_IMAGE_READ_ONLY;
     1800            goto out;
     1801        }
     1802
     1803        pImage->LCHSGeometry = *pLCHSGeometry;
     1804        rc = VINF_SUCCESS;
     1805    }
     1806    else
     1807        rc = VERR_VD_NOT_OPENED;
     1808
     1809out:
     1810    LogFlowFunc(("returns %Rrc\n", rc));
     1811    return rc;
     1812}
     1813
     1814/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     1815static unsigned dmgGetImageFlags(void *pBackendData)
     1816{
     1817    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1818    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1819    unsigned uImageFlags;
     1820
     1821    Assert(pImage);
     1822
     1823    if (pImage)
     1824        uImageFlags = pImage->uImageFlags;
     1825    else
     1826        uImageFlags = 0;
     1827
     1828    LogFlowFunc(("returns %#x\n", uImageFlags));
     1829    return uImageFlags;
     1830}
     1831
     1832/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     1833static unsigned dmgGetOpenFlags(void *pBackendData)
     1834{
     1835    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1836    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1837    unsigned uOpenFlags;
     1838
     1839    Assert(pImage);
     1840
     1841    if (pImage)
     1842        uOpenFlags = pImage->uOpenFlags;
     1843    else
     1844        uOpenFlags = 0;
     1845
     1846    LogFlowFunc(("returns %#x\n", uOpenFlags));
     1847    return uOpenFlags;
     1848}
     1849
     1850/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
     1851static int dmgSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     1852{
     1853    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     1854    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1855    int rc;
     1856
     1857    /* Image must be opened and the new flags must be valid. Just readonly and
     1858     * info flags are supported. */
     1859    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO)))
     1860    {
     1861        rc = VERR_INVALID_PARAMETER;
     1862        goto out;
     1863    }
     1864
     1865#if 0
     1866    /* Implement this operation via reopening the image. */
     1867    rawFreeImage(pImage, false);
     1868    rc = rawOpenImage(pImage, uOpenFlags);
    11191869#endif
    11201870
     1871out:
     1872    LogFlowFunc(("returns %Rrc\n", rc));
     1873    return rc;
     1874}
     1875
     1876/** @copydoc VBOXHDDBACKEND::pfnGetComment */
     1877static int dmgGetComment(void *pBackendData, char *pszComment,
     1878                         size_t cbComment)
     1879{
     1880    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     1881    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1882    int rc;
     1883
     1884    Assert(pImage);
     1885
     1886    if (pImage)
     1887    {
     1888        if (pszComment)
     1889            *pszComment = '\0';
     1890        rc = VINF_SUCCESS;
     1891    }
     1892    else
     1893        rc = VERR_VD_NOT_OPENED;
     1894
     1895    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     1896    return rc;
     1897}
     1898
     1899/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     1900static int dmgSetComment(void *pBackendData, const char *pszComment)
     1901{
     1902    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     1903    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1904    int rc;
     1905
     1906    Assert(pImage);
     1907
     1908    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1909    {
     1910        rc = VERR_VD_IMAGE_READ_ONLY;
     1911        goto out;
     1912    }
     1913
     1914    if (pImage)
     1915        rc = VERR_NOT_SUPPORTED;
     1916    else
     1917        rc = VERR_VD_NOT_OPENED;
     1918
     1919out:
     1920    LogFlowFunc(("returns %Rrc\n", rc));
     1921    return rc;
     1922}
     1923
     1924/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     1925static int dmgGetUuid(void *pBackendData, PRTUUID pUuid)
     1926{
     1927    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     1928    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1929    int rc;
     1930
     1931    Assert(pImage);
     1932
     1933    if (pImage)
     1934        rc = VERR_NOT_SUPPORTED;
     1935    else
     1936        rc = VERR_VD_NOT_OPENED;
     1937
     1938    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     1939    return rc;
     1940}
     1941
     1942/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
     1943static int dmgSetUuid(void *pBackendData, PCRTUUID pUuid)
     1944{
     1945    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     1946    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1947    int rc;
     1948
     1949    LogFlowFunc(("%RTuuid\n", pUuid));
     1950    Assert(pImage);
     1951
     1952    if (pImage)
     1953    {
     1954        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1955            rc = VERR_NOT_SUPPORTED;
     1956        else
     1957            rc = VERR_VD_IMAGE_READ_ONLY;
     1958    }
     1959    else
     1960        rc = VERR_VD_NOT_OPENED;
     1961
     1962    LogFlowFunc(("returns %Rrc\n", rc));
     1963    return rc;
     1964}
     1965
     1966/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
     1967static int dmgGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     1968{
     1969    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     1970    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1971    int rc;
     1972
     1973    Assert(pImage);
     1974
     1975    if (pImage)
     1976        rc = VERR_NOT_SUPPORTED;
     1977    else
     1978        rc = VERR_VD_NOT_OPENED;
     1979
     1980    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     1981    return rc;
     1982}
     1983
     1984/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
     1985static int dmgSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     1986{
     1987    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     1988    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1989    int rc;
     1990
     1991    Assert(pImage);
     1992
     1993    if (pImage)
     1994    {
     1995        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1996            rc = VERR_NOT_SUPPORTED;
     1997        else
     1998            rc = VERR_VD_IMAGE_READ_ONLY;
     1999    }
     2000    else
     2001        rc = VERR_VD_NOT_OPENED;
     2002
     2003    LogFlowFunc(("returns %Rrc\n", rc));
     2004    return rc;
     2005}
     2006
     2007/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
     2008static int dmgGetParentUuid(void *pBackendData, PRTUUID pUuid)
     2009{
     2010    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2011    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2012    int rc;
     2013
     2014    Assert(pImage);
     2015
     2016    if (pImage)
     2017        rc = VERR_NOT_SUPPORTED;
     2018    else
     2019        rc = VERR_VD_NOT_OPENED;
     2020
     2021    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2022    return rc;
     2023}
     2024
     2025/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
     2026static int dmgSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     2027{
     2028    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2029    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2030    int rc;
     2031
     2032    Assert(pImage);
     2033
     2034    if (pImage)
     2035    {
     2036        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2037            rc = VERR_NOT_SUPPORTED;
     2038        else
     2039            rc = VERR_VD_IMAGE_READ_ONLY;
     2040    }
     2041    else
     2042        rc = VERR_VD_NOT_OPENED;
     2043
     2044    LogFlowFunc(("returns %Rrc\n", rc));
     2045    return rc;
     2046}
     2047
     2048/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
     2049static int dmgGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     2050{
     2051    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2052    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2053    int rc;
     2054
     2055    Assert(pImage);
     2056
     2057    if (pImage)
     2058        rc = VERR_NOT_SUPPORTED;
     2059    else
     2060        rc = VERR_VD_NOT_OPENED;
     2061
     2062    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2063    return rc;
     2064}
     2065
     2066/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
     2067static int dmgSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2068{
     2069    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2070    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2071    int rc;
     2072
     2073    Assert(pImage);
     2074
     2075    if (pImage)
     2076    {
     2077        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2078            rc = VERR_NOT_SUPPORTED;
     2079        else
     2080            rc = VERR_VD_IMAGE_READ_ONLY;
     2081    }
     2082    else
     2083        rc = VERR_VD_NOT_OPENED;
     2084
     2085    LogFlowFunc(("returns %Rrc\n", rc));
     2086    return rc;
     2087}
     2088
     2089/** @copydoc VBOXHDDBACKEND::pfnDump */
     2090static void dmgDump(void *pBackendData)
     2091{
     2092    PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2093
     2094    Assert(pImage);
     2095    if (pImage)
     2096    {
     2097        pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
     2098                    pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
     2099                    pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
     2100                    pImage->cbSize / 512);
     2101    }
     2102}
     2103
     2104static int dmgGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
     2105{
     2106    int rc = VERR_NOT_IMPLEMENTED;
     2107    LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
     2108    return rc;
     2109}
     2110
     2111static int dmgGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
     2112{
     2113    int rc = VERR_NOT_IMPLEMENTED;
     2114    LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
     2115    return rc;
     2116}
     2117
     2118static int dmgSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
     2119{
     2120    int rc = VERR_NOT_IMPLEMENTED;
     2121    LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
     2122    return rc;
     2123}
     2124
     2125static int dmgGetParentFilename(void *pvBackendData, char **ppszParentFilename)
     2126{
     2127    int rc = VERR_NOT_IMPLEMENTED;
     2128    LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
     2129    return rc;
     2130}
     2131
     2132static int dmgSetParentFilename(void *pvBackendData, const char *pszParentFilename)
     2133{
     2134    int rc = VERR_NOT_IMPLEMENTED;
     2135    LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
     2136    return rc;
     2137}
     2138
     2139
     2140VBOXHDDBACKEND g_DmgBackend =
     2141{
     2142    /* pszBackendName */
     2143    "DMG",
     2144    /* cbSize */
     2145    sizeof(VBOXHDDBACKEND),
     2146    /* uBackendCaps */
     2147    VD_CAP_FILE,
     2148    /* papszFileExtensions */
     2149    NULL,
     2150    /* paConfigInfo */
     2151    NULL,
     2152    /* hPlugin */
     2153    NIL_RTLDRMOD,
     2154    /* pfnCheckIfValid */
     2155    dmgCheckIfValid,
     2156    /* pfnOpen */
     2157    dmgOpen,
     2158    /* pfnCreate */
     2159    dmgCreate,
     2160    /* pfnRename */
     2161    dmgRename,
     2162    /* pfnClose */
     2163    dmgClose,
     2164    /* pfnRead */
     2165    dmgRead,
     2166    /* pfnWrite */
     2167    dmgWrite,
     2168    /* pfnFlush */
     2169    dmgFlush,
     2170    /* pfnGetVersion */
     2171    dmgGetVersion,
     2172    /* pfnGetSize */
     2173    dmgGetSize,
     2174    /* pfnGetFileSize */
     2175    dmgGetFileSize,
     2176    /* pfnGetPCHSGeometry */
     2177    dmgGetPCHSGeometry,
     2178    /* pfnSetPCHSGeometry */
     2179    dmgSetPCHSGeometry,
     2180    /* pfnGetLCHSGeometry */
     2181    dmgGetLCHSGeometry,
     2182    /* pfnSetLCHSGeometry */
     2183    dmgSetLCHSGeometry,
     2184    /* pfnGetImageFlags */
     2185    dmgGetImageFlags,
     2186    /* pfnGetOpenFlags */
     2187    dmgGetOpenFlags,
     2188    /* pfnSetOpenFlags */
     2189    dmgSetOpenFlags,
     2190    /* pfnGetComment */
     2191    dmgGetComment,
     2192    /* pfnSetComment */
     2193    dmgSetComment,
     2194    /* pfnGetUuid */
     2195    dmgGetUuid,
     2196    /* pfnSetUuid */
     2197    dmgSetUuid,
     2198    /* pfnGetModificationUuid */
     2199    dmgGetModificationUuid,
     2200    /* pfnSetModificationUuid */
     2201    dmgSetModificationUuid,
     2202    /* pfnGetParentUuid */
     2203    dmgGetParentUuid,
     2204    /* pfnSetParentUuid */
     2205    dmgSetParentUuid,
     2206    /* pfnGetParentModificationUuid */
     2207    dmgGetParentModificationUuid,
     2208    /* pfnSetParentModificationUuid */
     2209    dmgSetParentModificationUuid,
     2210    /* pfnDump */
     2211    dmgDump,
     2212    /* pfnGetTimeStamp */
     2213    dmgGetTimeStamp,
     2214    /* pfnGetParentTimeStamp */
     2215    dmgGetParentTimeStamp,
     2216    /* pfnSetParentTimeStamp */
     2217    dmgSetParentTimeStamp,
     2218    /* pfnGetParentFilename */
     2219    dmgGetParentFilename,
     2220    /* pfnSetParentFilename */
     2221    dmgSetParentFilename,
     2222    /* pfnIsAsyncIOSupported */
     2223    NULL,
     2224    /* pfnAsyncRead */
     2225    NULL,
     2226    /* pfnAsyncWrite */
     2227    NULL,
     2228    /* pfnAsyncFlush */
     2229    NULL,
     2230    /* pfnComposeLocation */
     2231    genericFileComposeLocation,
     2232    /* pfnComposeName */
     2233    genericFileComposeName,
     2234    /* pfnCompact */
     2235    NULL,
     2236    /* pfnResize */
     2237    NULL
     2238};
     2239
Note: See TracChangeset for help on using the changeset viewer.

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