VirtualBox

Changeset 32768 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Sep 26, 2010 6:04:06 PM (14 years ago)
Author:
vboxsync
Message:

DMG: Cleanup, speedup and readonly support for compressed DMG images

File:
1 edited

Legend:

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

    r32553 r32768  
    2929#include <iprt/string.h>
    3030#include <iprt/base64.h>
    31 #ifdef VBOXDMG_TESTING
    32 # include <iprt/initterm.h>
    33 # include <iprt/stream.h>
    34 #endif
     31#include <iprt/zip.h>
    3532
    3633/*******************************************************************************
     
    3936
    4037/** Sector size, multiply with all sector counts to get number of bytes. */
    41 #define VBOXDMG_SECTOR_SIZE 512
     38#define DMG_SECTOR_SIZE 512
     39
     40/** Convert block number/size to byte offset/size. */
     41#define DMG_BLOCK2BYTE(u)          ((uint64_t)(u) << 9)
     42
     43/** Convert byte offset/size to block number/size. */
     44#define DMG_BYTE2BLOCK(u)          ((u) >> 9)
    4245
    4346/**
    4447 * UDIF checksum structure.
    4548 */
    46 typedef struct VBOXUDIFCKSUM
     49typedef struct DMGUDIFCKSUM
    4750{
    4851    uint32_t        u32Kind;                    /**< The kind of checksum.  */
     
    5356        uint32_t    au32[32];                   /**< 32-bit view. */
    5457    }               uSum;                       /**< The checksum. */
    55 } VBOXUDIFCKSUM;
    56 AssertCompileSize(VBOXUDIFCKSUM, 8 + 128);
    57 typedef VBOXUDIFCKSUM *PVBOXUDIFCKSUM;
    58 typedef const VBOXUDIFCKSUM *PCVBOXUDIFCKSUM;
    59 
    60 /** @name Checksum Kind (VBOXUDIFCKSUM::u32Kind)
     58} DMGUDIFCKSUM;
     59AssertCompileSize(DMGUDIFCKSUM, 8 + 128);
     60typedef DMGUDIFCKSUM *PDMGUDIFCKSUM;
     61typedef const DMGUDIFCKSUM *PCDMGUDIFCKSUM;
     62
     63/** @name Checksum Kind (DMGUDIFCKSUM::u32Kind)
    6164 * @{ */
    6265/** No checksum. */
    63 #define VBOXUDIFCKSUM_NONE          UINT32_C(0)
     66#define DMGUDIFCKSUM_NONE          UINT32_C(0)
    6467/** CRC-32. */
    65 #define VBOXUDIFCKSUM_CRC32         UINT32_C(2)
     68#define DMGUDIFCKSUM_CRC32         UINT32_C(2)
    6669/** @} */
    6770
     
    7174 * representation of it for simplicity.
    7275 */
    73 typedef RTUUID VBOXUDIFID;
    74 AssertCompileSize(VBOXUDIFID, 16);
    75 typedef VBOXUDIFID *PVBOXUDIFID;
    76 typedef const VBOXUDIFID *PCVBOXUDIFID;
     76typedef RTUUID DMGUDIFID;
     77AssertCompileSize(DMGUDIFID, 16);
     78typedef DMGUDIFID *PDMGUDIFID;
     79typedef const DMGUDIFID *PCDMGUDIFID;
    7780
    7881/**
     
    8689 */
    8790#pragma pack(1)
    88 typedef struct VBOXUDIF
    89 {
    90     uint32_t            u32Magic;               /**< 0x000 - Magic, 'koly' (VBOXUDIF_MAGIC).                       (fUDIFSignature) */
    91     uint32_t            u32Version;             /**< 0x004 - The UDIF version (VBOXUDIF_VER_CURRENT).              (fUDIFVersion) */
     91typedef struct DMGUDIF
     92{
     93    uint32_t            u32Magic;               /**< 0x000 - Magic, 'koly' (DMGUDIF_MAGIC).                       (fUDIFSignature) */
     94    uint32_t            u32Version;             /**< 0x004 - The UDIF version (DMGUDIF_VER_CURRENT).              (fUDIFVersion) */
    9295    uint32_t            cbFooter;               /**< 0x008 - The size of the this structure (512).                 (fUDIFHeaderSize) */
    9396    uint32_t            fFlags;                 /**< 0x00c - Flags.                                                (fUDIFFlags) */
     
    99102    uint32_t            iSegment;               /**< 0x038 - The segment number of this file.                      (fUDIFSegmentNumber) */
    100103    uint32_t            cSegments;              /**< 0x03c - The number of segments.                               (fUDIFSegmentCount) */
    101     VBOXUDIFID          SegmentId;              /**< 0x040 - The segment ID.                                       (fUDIFSegmentID) */
    102     VBOXUDIFCKSUM       DataCkSum;              /**< 0x050 - The data checksum.                                    (fUDIFDataForkChecksum) */
     104    DMGUDIFID           SegmentId;              /**< 0x040 - The segment ID.                                       (fUDIFSegmentID) */
     105    DMGUDIFCKSUM        DataCkSum;              /**< 0x050 - The data checksum.                                    (fUDIFDataForkChecksum) */
    103106    uint64_t            offXml;                 /**< 0x0d8 - The XML offset (.plist kind of data).                 (fUDIFXMLOffset) */
    104107    uint64_t            cbXml;                  /**< 0x0e0 - The size of the XML.                                  (fUDIFXMLSize) */
    105108    uint8_t             abUnknown[120];         /**< 0x0e8 - Unknown stuff, hdiutil doesn't dump it... */
    106     VBOXUDIFCKSUM       MasterCkSum;            /**< 0x160 - The master checksum.                                  (fUDIFMasterChecksum) */
     109    DMGUDIFCKSUM        MasterCkSum;            /**< 0x160 - The master checksum.                                  (fUDIFMasterChecksum) */
    107110    uint32_t            u32Type;                /**< 0x1e8 - The image type.                                       (fUDIFImageVariant) */
    108111    uint64_t            cSectors;               /**< 0x1ec - The sector count. Warning! Unaligned!                 (fUDISectorCount) */
    109112    uint32_t            au32Unknown[3];         /**< 0x1f4 - Unknown stuff, hdiutil doesn't dump it... */
    110 } VBOXUDIF;
     113} DMGUDIF;
    111114#pragma pack(0)
    112 AssertCompileSize(VBOXUDIF, 512);
    113 AssertCompileMemberOffset(VBOXUDIF, cbRsrc,   0x030);
    114 AssertCompileMemberOffset(VBOXUDIF, cbXml,    0x0e0);
    115 AssertCompileMemberOffset(VBOXUDIF, cSectors, 0x1ec);
    116 
    117 typedef VBOXUDIF *PVBOXUDIF;
    118 typedef const VBOXUDIF *PCVBOXUDIF;
    119 
    120 /** The UDIF magic 'koly' (VBOXUDIF::u32Magic). */
    121 #define VBOXUDIF_MAGIC              UINT32_C(0x6b6f6c79)
    122 
    123 /** The current UDIF version (VBOXUDIF::u32Version).
     115AssertCompileSize(DMGUDIF, 512);
     116AssertCompileMemberOffset(DMGUDIF, cbRsrc,   0x030);
     117AssertCompileMemberOffset(DMGUDIF, cbXml,    0x0e0);
     118AssertCompileMemberOffset(DMGUDIF, cSectors, 0x1ec);
     119
     120typedef DMGUDIF *PDMGUDIF;
     121typedef const DMGUDIF *PCDMGUDIF;
     122
     123/** The UDIF magic 'koly' (DMGUDIF::u32Magic). */
     124#define DMGUDIF_MAGIC              UINT32_C(0x6b6f6c79)
     125
     126/** The current UDIF version (DMGUDIF::u32Version).
    124127 * This is currently the only we recognizes and will create. */
    125 #define VBOXUDIF_VER_CURRENT        4
    126 
    127 /** @name UDIF flags (VBOXUDIF::fFlags).
     128#define DMGUDIF_VER_CURRENT        4
     129
     130/** @name UDIF flags (DMGUDIF::fFlags).
    128131 * @{ */
    129132/** Flatten image whatever that means.
    130133 * (hdiutil -debug calls it kUDIFFlagsFlattened.) */
    131 #define VBOXUDIF_FLAGS_FLATTENED    RT_BIT_32(0)
     134#define DMGUDIF_FLAGS_FLATTENED    RT_BIT_32(0)
    132135/** Internet enabled image.
    133136 * (hdiutil -debug calls it kUDIFFlagsInternetEnabled) */
    134 #define VBOXUDIF_FLAGS_INET_ENABLED RT_BIT_32(2)
     137#define DMGUDIF_FLAGS_INET_ENABLED RT_BIT_32(2)
    135138/** Mask of known bits. */
    136 #define VBOXUDIF_FLAGS_KNOWN_MASK   (RT_BIT_32(0) | RT_BIT_32(2))
     139#define DMGUDIF_FLAGS_KNOWN_MASK   (RT_BIT_32(0) | RT_BIT_32(2))
    137140/** @} */
    138141
    139 /** @name UDIF Image Types (VBOXUDIF::u32Type).
     142/** @name UDIF Image Types (DMGUDIF::u32Type).
    140143 * @{ */
    141144/** Device image type. (kUDIFDeviceImageType) */
    142 #define VBOXUDIF_TYPE_DEVICE        1
     145#define DMGUDIF_TYPE_DEVICE        1
    143146/** Device image type. (kUDIFPartitionImageType) */
    144 #define VBOXUDIF_TYPE_PARTITION     2
     147#define DMGUDIF_TYPE_PARTITION     2
    145148/** @}  */
    146149
     
    153156 */
    154157#pragma pack(1)
    155 typedef struct VBOXBLKX
    156 {
    157     uint32_t            u32Magic;               /**< 0x000 - Magic, 'mish' (VBOXBLKX_MAGIC). */
    158     uint32_t            u32Version;             /**< 0x004 - The BLKX version (VBOXBLKX_VER_CURRENT). */
     158typedef struct DMGBLKX
     159{
     160    uint32_t            u32Magic;               /**< 0x000 - Magic, 'mish' (DMGBLKX_MAGIC). */
     161    uint32_t            u32Version;             /**< 0x004 - The BLKX version (DMGBLKX_VER_CURRENT). */
    159162    uint64_t            cSectornumberFirst;     /**< 0x008 - The first sector number the block represents in the virtual device. */
    160163    uint64_t            cSectors;               /**< 0x010 - Number of sectors this block represents. */
     
    163166    uint32_t            u32BlocksDescriptor;    /**< 0x024 - Blocks descriptor. */
    164167    uint8_t             abReserved[24];
    165     VBOXUDIFCKSUM       BlkxCkSum;              /**< 0x03c - Checksum for the BLKX table. */
     168    DMGUDIFCKSUM        BlkxCkSum;              /**< 0x03c - Checksum for the BLKX table. */
    166169    uint32_t            cBlocksRunCount;        /**< 0x    - Number of entries in the blkx run table afterwards. */
    167 } VBOXBLKX;
     170} DMGBLKX;
    168171#pragma pack(0)
    169 AssertCompileSize(VBOXBLKX, 204);
    170 
    171 typedef VBOXBLKX *PVBOXBLKX;
    172 typedef const VBOXBLKX *PCVBOXBLKX;
    173 
    174 /** The BLKX magic 'mish' (VBOXBLKX::u32Magic). */
    175 #define VBOXBLKX_MAGIC              UINT32_C(0x6d697368)
    176 /** BLKX version (VBOXBLKX::u32Version). */
    177 #define VBOXBLKX_VERSION            UINT32_C(0x00000001)
     172AssertCompileSize(DMGBLKX, 204);
     173
     174typedef DMGBLKX *PDMGBLKX;
     175typedef const DMGBLKX *PCDMGBLKX;
     176
     177/** The BLKX magic 'mish' (DMGBLKX::u32Magic). */
     178#define DMGBLKX_MAGIC              UINT32_C(0x6d697368)
     179/** BLKX version (DMGBLKX::u32Version). */
     180#define DMGBLKX_VERSION            UINT32_C(0x00000001)
    178181
    179182/** Blocks descriptor type: entire device. */
    180 #define VBOXBLKX_DESC_ENTIRE_DEVICE UINT32_C(0xfffffffe)
     183#define DMGBLKX_DESC_ENTIRE_DEVICE UINT32_C(0xfffffffe)
    181184
    182185/**
     
    186189 */
    187190#pragma pack(1)
    188 typedef struct VBOXBLKXDESC
     191typedef struct DMGBLKXDESC
    189192{
    190193    uint32_t            u32Type;                /**< 0x000 - Type of the descriptor. */
     
    194197    uint64_t            offData;                /**< 0x018 - Offset in the image where the data starts. */
    195198    uint64_t            cbData;                 /**< 0x020 - Number of bytes in the image. */
    196 } VBOXBLKXDESC;
     199} DMGBLKXDESC;
    197200#pragma pack(0)
    198 AssertCompileSize(VBOXBLKXDESC, 40);
    199 
    200 typedef VBOXBLKXDESC *PVBOXBLKXDESC;
    201 typedef const VBOXBLKXDESC *PCVBOXBLKXDESC;
     201AssertCompileSize(DMGBLKXDESC, 40);
     202
     203typedef DMGBLKXDESC *PDMGBLKXDESC;
     204typedef const DMGBLKXDESC *PCDMGBLKXDESC;
    202205
    203206/** Raw image data type. */
    204 #define VBOXBLKXDESC_TYPE_RAW        1
     207#define DMGBLKXDESC_TYPE_RAW        1
    205208/** Ignore type. */
    206 #define VBOXBLKXDESC_TYPE_IGNORE     2
     209#define DMGBLKXDESC_TYPE_IGNORE     2
     210/** Compressed with zlib type. */
     211#define DMGBLKXDESC_TYPE_ZLIB       UINT32_C(0x80000005)
    207212/** Comment type. */
    208 #define VBOXBLKXDESC_TYPE_COMMENT    UINT32_C(0x7ffffffe)
     213#define DMGBLKXDESC_TYPE_COMMENT    UINT32_C(0x7ffffffe)
    209214/** Terminator type. */
    210 #define VBOXBLKXDESC_TYPE_TERMINATOR UINT32_C(0xffffffff)
     215#define DMGBLKXDESC_TYPE_TERMINATOR UINT32_C(0xffffffff)
    211216
    212217/**
    213218 * UDIF Resource Entry.
    214219 */
    215 typedef struct VBOXUDIFRSRCENTRY
     220typedef struct DMGUDIFRSRCENTRY
    216221{
    217222    /** The ID. */
     
    227232    /** The raw data. */
    228233    uint8_t            *pbData;
    229 } VBOXUDIFRSRCENTRY;
     234} DMGUDIFRSRCENTRY;
    230235/** Pointer to an UDIF resource entry. */
    231 typedef VBOXUDIFRSRCENTRY *PVBOXUDIFRSRCENTRY;
     236typedef DMGUDIFRSRCENTRY *PDMGUDIFRSRCENTRY;
    232237/** Pointer to a const UDIF resource entry. */
    233 typedef VBOXUDIFRSRCENTRY const *PCVBOXUDIFRSRCENTRY;
     238typedef DMGUDIFRSRCENTRY const *PCDMGUDIFRSRCENTRY;
    234239
    235240/**
    236241 * UDIF Resource Array.
    237242 */
    238 typedef struct VBOXUDIFRSRCARRAY
     243typedef struct DMGUDIFRSRCARRAY
    239244{
    240245    /** The array name. */
     
    246251     * size if DMGs with more are found.
    247252     * r=aeichner: Saw one with 6 here (image of a whole DVD) */
    248     VBOXUDIFRSRCENTRY   aEntries[10];
    249 } VBOXUDIFRSRCARRAY;
     253    DMGUDIFRSRCENTRY    aEntries[10];
     254} DMGUDIFRSRCARRAY;
    250255/** Pointer to a UDIF resource array. */
    251 typedef VBOXUDIFRSRCARRAY *PVBOXUDIFRSRCARRAY;
     256typedef DMGUDIFRSRCARRAY *PDMGUDIFRSRCARRAY;
    252257/** Pointer to a const UDIF resource array. */
    253 typedef VBOXUDIFRSRCARRAY const *PCVBOXUDIFRSRCARRAY;
     258typedef DMGUDIFRSRCARRAY const *PCDMGUDIFRSRCARRAY;
    254259
    255260/**
     
    264269    /** Zero extent, reads return 0 and writes have no effect. */
    265270    DMGEXTENTTYPE_ZERO,
     271    /** Compressed extent - compression method ZLIB. */
     272    DMGEXTENTTYPE_COMP_ZLIB,
    266273    /** 32bit hack. */
    267274    DMGEXTENTTYPE_32BIT_HACK = 0x7fffffff
     
    273280typedef struct DMGEXTENT
    274281{
    275     /** Next DMG extent, sorted by virtual sector count. */
    276     struct DMGEXTENT    *pNext;
    277282    /** Extent type. */
    278283    DMGEXTENTTYPE        enmType;
    279     /** First byte this extent describes. */
    280     uint64_t             offExtent;
    281     /** Number of bytes this extent describes. */
    282     uint64_t             cbExtent;
     284    /** First sector this extent describes. */
     285    uint64_t             uSectorExtent;
     286    /** Number of sectors this extent describes. */
     287    uint64_t             cSectorsExtent;
    283288    /** Start offset in the real file. */
    284289    uint64_t             offFileStart;
     290    /** Number of bytes for the extent data in the file. */
     291    uint64_t             cbFile;
    285292} DMGEXTENT;
    286293/** Pointer to an DMG extent. */
     
    328335     * A lazy bird ASSUME there are only two arrays in the resource-fork section in
    329336     * the XML, namely 'blkx' and 'plst'. These have been assigned fixed indexes. */
    330     VBOXUDIFRSRCARRAY   aRsrcs[2];
     337    DMGUDIFRSRCARRAY    aRsrcs[2];
    331338    /** The UDIF footer. */
    332     VBOXUDIF            Ftr;
    333 
    334     /** First extent in the list. */
    335     PDMGEXTENT          pExtentFirst;
    336     /** Last extent in the list. */
    337     PDMGEXTENT          pExtentLast;
     339    DMGUDIF             Ftr;
     340
     341    /** Number of valid extents in the array. */
     342    unsigned            cExtents;
     343    /** Number of entries the array can hold. */
     344    unsigned            cExtentsMax;
     345    /** Pointer to the extent array. */
     346    PDMGEXTENT          paExtents;
     347    /** Index of the last accessed extent. */
     348    unsigned            idxExtentLast;
     349
     350    /** Extent which owns the data in the buffer. */
     351    PDMGEXTENT          pExtentDecomp;
     352    /** Buffer holding the decompressed data for a extent. */
     353    void               *pvDecompExtent;
     354    /** Size of the buffer. */
     355    size_t              cbDecompExtent;
    338356} DMGIMAGE;
    339357/** Pointer to an instance of the DMG Image Interpreter. */
    340358typedef DMGIMAGE *PDMGIMAGE;
    341359
    342 /** @name Resources indexes (into VBOXDMG::aRsrcs).
     360/** @name Resources indexes (into DMG::aRsrcs).
    343361 * @{ */
    344 #define VBOXDMG_RSRC_IDX_BLKX   0
    345 #define VBOXDMG_RSRC_IDX_PLST   1
     362#define DMG_RSRC_IDX_BLKX   0
     363#define DMG_RSRC_IDX_PLST   1
    346364/** @} */
    347365
     366/** State for the input callout of the inflate reader. */
     367typedef struct DMGINFLATESTATE
     368{
     369    /* Image this operation relates to. */
     370    PDMGIMAGE pImage;
     371    /* Total size of the data to read. */
     372    size_t    cbSize;
     373    /* Offset in the file to read. */
     374    uint64_t  uFileOffset;
     375    /* Current read position. */
     376    ssize_t   iOffset;
     377} DMGINFLATESTATE;
    348378
    349379/*******************************************************************************
    350380*   Defined Constants And Macros                                               *
    351381*******************************************************************************/
    352 /** @def VBOXDMG_PRINTF
    353  * Wrapper for RTPrintf/LogRel.
    354  */
    355 #ifdef VBOXDMG_TESTING
    356 # define VBOXDMG_PRINTF(a)  RTPrintf a
    357 #else
    358 # define VBOXDMG_PRINTF(a)  LogRel(a)
    359 #endif
    360 
    361 /** @def VBOXDMG_VALIDATE
     382/** @def DMG_PRINTF
     383 * Wrapper for LogRel.
     384 */
     385#define DMG_PRINTF(a)  LogRel(a)
     386
     387/** @def DMG_VALIDATE
    362388 * For validating a struct thing and log/print what's wrong.
    363389 */
    364 #ifdef VBOXDMG_TESTING
    365 # define VBOXDMG_VALIDATE(expr, logstuff) \
     390# define DMG_VALIDATE(expr, logstuff) \
    366391    do { \
    367392        if (!(expr)) \
    368393        { \
    369             RTPrintf("tstVBoxDMG: validation failed: %s\ntstVBoxDMG: ", #expr); \
    370             RTPrintf logstuff; \
    371             fRc = false; \
    372         } \
    373     } while (0)
    374 #else
    375 # define VBOXDMG_VALIDATE(expr, logstuff) \
    376     do { \
    377         if (!(expr)) \
    378         { \
    379             LogRel(("vboxdmg: validation failed: %s\nvboxdmg: ", #expr)); \
     394            LogRel(("DMG: validation failed: %s\nDMG: ", #expr)); \
    380395            LogRel(logstuff); \
    381396            fRc = false; \
    382397        } \
    383398    } while (0)
    384 #endif
    385 
    386399
    387400/** VBoxDMG: Unable to parse the XML. */
     
    403416*   Internal Functions                                                         *
    404417*******************************************************************************/
    405 static void vboxdmgUdifFtrHost2FileEndian(PVBOXUDIF pUdif);
    406 static void vboxdmgUdifFtrFile2HostEndian(PVBOXUDIF pUdif);
    407 
    408 static void vboxdmgUdifIdHost2FileEndian(PVBOXUDIFID pId);
    409 static void vboxdmgUdifIdFile2HostEndian(PVBOXUDIFID pId);
    410 
    411 static void vboxdmgUdifCkSumHost2FileEndian(PVBOXUDIFCKSUM pCkSum);
    412 static void vboxdmgUdifCkSumFile2HostEndian(PVBOXUDIFCKSUM pCkSum);
    413 static bool vboxdmgUdifCkSumIsValid(PCVBOXUDIFCKSUM pCkSum, const char *pszPrefix);
     418static void dmgUdifFtrHost2FileEndian(PDMGUDIF pUdif);
     419static void dmgUdifFtrFile2HostEndian(PDMGUDIF pUdif);
     420
     421static void dmgUdifIdHost2FileEndian(PDMGUDIFID pId);
     422static void dmgUdifIdFile2HostEndian(PDMGUDIFID pId);
     423
     424static void dmgUdifCkSumHost2FileEndian(PDMGUDIFCKSUM pCkSum);
     425static void dmgUdifCkSumFile2HostEndian(PDMGUDIFCKSUM pCkSum);
     426static bool dmgUdifCkSumIsValid(PCDMGUDIFCKSUM pCkSum, const char *pszPrefix);
    414427
    415428/**
     
    513526}
    514527
     528static DECLCALLBACK(int) dmgFileInflateHelper(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbBuf)
     529{
     530    DMGINFLATESTATE *pInflateState = (DMGINFLATESTATE *)pvUser;
     531
     532    Assert(cbBuf);
     533    if (pInflateState->iOffset < 0)
     534    {
     535        *(uint8_t *)pvBuf = RTZIPTYPE_ZLIB;
     536        if (pcbBuf)
     537            *pcbBuf = 1;
     538        pInflateState->iOffset = 0;
     539        return VINF_SUCCESS;
     540    }
     541    cbBuf = RT_MIN(cbBuf, pInflateState->cbSize);
     542    int rc = dmgFileReadSync(pInflateState->pImage, pInflateState->uFileOffset,
     543                             pvBuf, cbBuf, NULL);
     544    if (RT_FAILURE(rc))
     545        return rc;
     546    pInflateState->uFileOffset += cbBuf;
     547    pInflateState->iOffset += cbBuf;
     548    pInflateState->cbSize -= cbBuf;
     549    Assert(pcbBuf);
     550    *pcbBuf = cbBuf;
     551    return VINF_SUCCESS;
     552}
     553
     554/**
     555 * Internal: read from a file and inflate the compressed data,
     556 * distinguishing between async and normal operation
     557 */
     558DECLINLINE(int) dmgFileInflateSync(PDMGIMAGE pImage, uint64_t uOffset, size_t cbToRead,
     559                                   void *pvBuf, size_t cbBuf)
     560{
     561    int rc;
     562    PRTZIPDECOMP pZip = NULL;
     563    DMGINFLATESTATE InflateState;
     564    size_t cbActuallyRead;
     565
     566    InflateState.pImage      = pImage;
     567    InflateState.cbSize      = cbToRead;
     568    InflateState.uFileOffset = uOffset;
     569    InflateState.iOffset     = -1;
     570
     571    rc = RTZipDecompCreate(&pZip, &InflateState, dmgFileInflateHelper);
     572    if (RT_FAILURE(rc))
     573        return rc;
     574    rc = RTZipDecompress(pZip, pvBuf, cbBuf, &cbActuallyRead);
     575    RTZipDecompDestroy(pZip);
     576    if (RT_FAILURE(rc))
     577        return rc;
     578    if (cbActuallyRead != cbBuf)
     579        rc = VERR_VD_VMDK_INVALID_FORMAT;
     580    return rc;
     581}
    515582
    516583/**
     
    518585 * @param   pUdif       The structure.
    519586 */
    520 static void vboxdmgSwapEndianUdif(PVBOXUDIF pUdif)
     587static void dmgSwapEndianUdif(PDMGUDIF pUdif)
    521588{
    522589#ifndef RT_BIG_ENDIAN
     
    544611 * @param   pUdif       The structure.
    545612 */
    546 static void vboxdmgUdifFtrHost2FileEndian(PVBOXUDIF pUdif)
    547 {
    548     vboxdmgSwapEndianUdif(pUdif);
    549     vboxdmgUdifIdHost2FileEndian(&pUdif->SegmentId);
    550     vboxdmgUdifCkSumHost2FileEndian(&pUdif->DataCkSum);
    551     vboxdmgUdifCkSumHost2FileEndian(&pUdif->MasterCkSum);
     613static void dmgUdifFtrHost2FileEndian(PDMGUDIF pUdif)
     614{
     615    dmgSwapEndianUdif(pUdif);
     616    dmgUdifIdHost2FileEndian(&pUdif->SegmentId);
     617    dmgUdifCkSumHost2FileEndian(&pUdif->DataCkSum);
     618    dmgUdifCkSumHost2FileEndian(&pUdif->MasterCkSum);
    552619}
    553620
     
    557624 * @param   pUdif       The structure.
    558625 */
    559 static void vboxdmgUdifFtrFile2HostEndian(PVBOXUDIF pUdif)
    560 {
    561     vboxdmgSwapEndianUdif(pUdif);
    562     vboxdmgUdifIdFile2HostEndian(&pUdif->SegmentId);
    563     vboxdmgUdifCkSumFile2HostEndian(&pUdif->DataCkSum);
    564     vboxdmgUdifCkSumFile2HostEndian(&pUdif->MasterCkSum);
     626static void dmgUdifFtrFile2HostEndian(PDMGUDIF pUdif)
     627{
     628    dmgSwapEndianUdif(pUdif);
     629    dmgUdifIdFile2HostEndian(&pUdif->SegmentId);
     630    dmgUdifCkSumFile2HostEndian(&pUdif->DataCkSum);
     631    dmgUdifCkSumFile2HostEndian(&pUdif->MasterCkSum);
    565632}
    566633
     
    569636 * @param   pBlkx       The blkx structure.
    570637 */
    571 static void vboxdmgBlkxFile2HostEndian(PVBOXBLKX pBlkx)
     638static void dmgBlkxFile2HostEndian(PDMGBLKX pBlkx)
    572639{
    573640    pBlkx->u32Magic            = RT_BE2H_U32(pBlkx->u32Magic);
     
    579646    pBlkx->u32BlocksDescriptor = RT_BE2H_U32(pBlkx->u32BlocksDescriptor);
    580647    pBlkx->cBlocksRunCount     = RT_BE2H_U32(pBlkx->cBlocksRunCount);
    581     vboxdmgUdifCkSumFile2HostEndian(&pBlkx->BlkxCkSum);
     648    dmgUdifCkSumFile2HostEndian(&pBlkx->BlkxCkSum);
    582649}
    583650
     
    586653 * @param   pBlkxDesc   The blkx descriptor structure.
    587654 */
    588 static void vboxdmgBlkxDescFile2HostEndian(PVBOXBLKXDESC pBlkxDesc)
     655static void dmgBlkxDescFile2HostEndian(PDMGBLKXDESC pBlkxDesc)
    589656{
    590657    pBlkxDesc->u32Type        = RT_BE2H_U32(pBlkxDesc->u32Type);
     
    603670 * @param   offFtr      The offset of the structure.
    604671 */
    605 static bool vboxdmgUdifFtrIsValid(PCVBOXUDIF pFtr, uint64_t offFtr)
     672static bool dmgUdifFtrIsValid(PCDMGUDIF pFtr, uint64_t offFtr)
    606673{
    607674    bool fRc = true;
    608675
    609     VBOXDMG_VALIDATE(!(pFtr->fFlags & ~VBOXUDIF_FLAGS_KNOWN_MASK), ("fFlags=%#RX32 fKnown=%RX32\n", pFtr->fFlags, VBOXUDIF_FLAGS_KNOWN_MASK));
    610     VBOXDMG_VALIDATE(pFtr->offRunData < offFtr, ("offRunData=%#RX64\n", pFtr->offRunData));
    611     VBOXDMG_VALIDATE(pFtr->cbData    <= offFtr && pFtr->offData + pFtr->cbData <= offFtr, ("cbData=%#RX64 offData=%#RX64 offFtr=%#RX64\n", pFtr->cbData, pFtr->offData, offFtr));
    612     VBOXDMG_VALIDATE(pFtr->offData    < offFtr, ("offData=%#RX64\n", pFtr->offData));
    613     VBOXDMG_VALIDATE(pFtr->cbRsrc    <= offFtr && pFtr->offRsrc + pFtr->cbRsrc <= offFtr, ("cbRsrc=%#RX64 offRsrc=%#RX64 offFtr=%#RX64\n", pFtr->cbRsrc, pFtr->offRsrc, offFtr));
    614     VBOXDMG_VALIDATE(pFtr->offRsrc    < offFtr, ("offRsrc=%#RX64\n", pFtr->offRsrc));
    615     VBOXDMG_VALIDATE(pFtr->cSegments <= 1,      ("cSegments=%RU32\n", pFtr->cSegments));
    616     VBOXDMG_VALIDATE(pFtr->iSegment  == 0 || pFtr->iSegment == 1, ("iSegment=%RU32 cSegments=%RU32\n", pFtr->iSegment, pFtr->cSegments));
    617     VBOXDMG_VALIDATE(pFtr->cbXml    <= offFtr && pFtr->offXml + pFtr->cbXml <= offFtr, ("cbXml=%#RX64 offXml=%#RX64 offFtr=%#RX64\n", pFtr->cbXml, pFtr->offXml, offFtr));
    618     VBOXDMG_VALIDATE(pFtr->offXml    < offFtr,  ("offXml=%#RX64\n", pFtr->offXml));
    619     VBOXDMG_VALIDATE(pFtr->cbXml     > 128,     ("cbXml=%#RX64\n", pFtr->cbXml));
    620     VBOXDMG_VALIDATE(pFtr->cbXml     < _1M,     ("cbXml=%#RX64\n", pFtr->cbXml));
    621     VBOXDMG_VALIDATE(pFtr->u32Type == VBOXUDIF_TYPE_DEVICE || pFtr->u32Type == VBOXUDIF_TYPE_PARTITION,  ("u32Type=%RU32\n", pFtr->u32Type));
    622     VBOXDMG_VALIDATE(pFtr->cSectors != 0,       ("cSectors=%#RX64\n", pFtr->cSectors));
    623     fRc &= vboxdmgUdifCkSumIsValid(&pFtr->DataCkSum, "DataCkSum");
    624     fRc &= vboxdmgUdifCkSumIsValid(&pFtr->MasterCkSum, "MasterCkSum");
     676    DMG_VALIDATE(!(pFtr->fFlags & ~DMGUDIF_FLAGS_KNOWN_MASK), ("fFlags=%#RX32 fKnown=%RX32\n", pFtr->fFlags, DMGUDIF_FLAGS_KNOWN_MASK));
     677    DMG_VALIDATE(pFtr->offRunData < offFtr, ("offRunData=%#RX64\n", pFtr->offRunData));
     678    DMG_VALIDATE(pFtr->cbData    <= offFtr && pFtr->offData + pFtr->cbData <= offFtr, ("cbData=%#RX64 offData=%#RX64 offFtr=%#RX64\n", pFtr->cbData, pFtr->offData, offFtr));
     679    DMG_VALIDATE(pFtr->offData    < offFtr, ("offData=%#RX64\n", pFtr->offData));
     680    DMG_VALIDATE(pFtr->cbRsrc    <= offFtr && pFtr->offRsrc + pFtr->cbRsrc <= offFtr, ("cbRsrc=%#RX64 offRsrc=%#RX64 offFtr=%#RX64\n", pFtr->cbRsrc, pFtr->offRsrc, offFtr));
     681    DMG_VALIDATE(pFtr->offRsrc    < offFtr, ("offRsrc=%#RX64\n", pFtr->offRsrc));
     682    DMG_VALIDATE(pFtr->cSegments <= 1,      ("cSegments=%RU32\n", pFtr->cSegments));
     683    DMG_VALIDATE(pFtr->iSegment  == 0 || pFtr->iSegment == 1, ("iSegment=%RU32 cSegments=%RU32\n", pFtr->iSegment, pFtr->cSegments));
     684    DMG_VALIDATE(pFtr->cbXml    <= offFtr && pFtr->offXml + pFtr->cbXml <= offFtr, ("cbXml=%#RX64 offXml=%#RX64 offFtr=%#RX64\n", pFtr->cbXml, pFtr->offXml, offFtr));
     685    DMG_VALIDATE(pFtr->offXml    < offFtr,  ("offXml=%#RX64\n", pFtr->offXml));
     686    DMG_VALIDATE(pFtr->cbXml     > 128,     ("cbXml=%#RX64\n", pFtr->cbXml));
     687    DMG_VALIDATE(pFtr->cbXml     < 10 * _1M,     ("cbXml=%#RX64\n", pFtr->cbXml));
     688    DMG_VALIDATE(pFtr->u32Type == DMGUDIF_TYPE_DEVICE || pFtr->u32Type == DMGUDIF_TYPE_PARTITION,  ("u32Type=%RU32\n", pFtr->u32Type));
     689    DMG_VALIDATE(pFtr->cSectors != 0,       ("cSectors=%#RX64\n", pFtr->cSectors));
     690    fRc &= dmgUdifCkSumIsValid(&pFtr->DataCkSum, "DataCkSum");
     691    fRc &= dmgUdifCkSumIsValid(&pFtr->MasterCkSum, "MasterCkSum");
    625692
    626693    return fRc;
     
    628695
    629696
    630 static bool vboxdmgBlkxIsValid(PCVBOXBLKX pBlkx)
     697static bool dmgBlkxIsValid(PCDMGBLKX pBlkx)
    631698{
    632699    bool fRc = true;
    633700
    634     fRc &= vboxdmgUdifCkSumIsValid(&pBlkx->BlkxCkSum, "BlkxCkSum");
    635     VBOXDMG_VALIDATE(pBlkx->u32Magic == VBOXBLKX_MAGIC, ("u32Magic=%#RX32 u32MagicExpected=%#RX32\n", pBlkx->u32Magic, VBOXBLKX_MAGIC));
    636     VBOXDMG_VALIDATE(pBlkx->u32Version == VBOXBLKX_VERSION, ("u32Version=%#RX32 u32VersionExpected=%#RX32\n", pBlkx->u32Magic, VBOXBLKX_VERSION));
     701    fRc &= dmgUdifCkSumIsValid(&pBlkx->BlkxCkSum, "BlkxCkSum");
     702    DMG_VALIDATE(pBlkx->u32Magic == DMGBLKX_MAGIC, ("u32Magic=%#RX32 u32MagicExpected=%#RX32\n", pBlkx->u32Magic, DMGBLKX_MAGIC));
     703    DMG_VALIDATE(pBlkx->u32Version == DMGBLKX_VERSION, ("u32Version=%#RX32 u32VersionExpected=%#RX32\n", pBlkx->u32Magic, DMGBLKX_VERSION));
    637704
    638705    return fRc;
     
    643710 * @param   pId         The structure.
    644711 */
    645 static void vboxdmgUdifIdHost2FileEndian(PVBOXUDIFID pId)
     712static void dmgUdifIdHost2FileEndian(PDMGUDIFID pId)
    646713{
    647714    NOREF(pId);
     
    653720 * @param   pId         The structure.
    654721 */
    655 static void vboxdmgUdifIdFile2HostEndian(PVBOXUDIFID pId)
    656 {
    657     vboxdmgUdifIdHost2FileEndian(pId);
     722static void dmgUdifIdFile2HostEndian(PDMGUDIFID pId)
     723{
     724    dmgUdifIdHost2FileEndian(pId);
    658725}
    659726
     
    663730 * @param   pCkSum      The structure.
    664731 */
    665 static void vboxdmgSwapEndianUdifCkSum(PVBOXUDIFCKSUM pCkSum, uint32_t u32Kind, uint32_t cBits)
     732static void dmgSwapEndianUdifCkSum(PDMGUDIFCKSUM pCkSum, uint32_t u32Kind, uint32_t cBits)
    666733{
    667734#ifdef RT_BIG_ENDIAN
     
    672739    switch (u32Kind)
    673740    {
    674         case VBOXUDIFCKSUM_NONE:
     741        case DMGUDIFCKSUM_NONE:
    675742            /* nothing to do here */
    676743            break;
    677744
    678         case VBOXUDIFCKSUM_CRC32:
     745        case DMGUDIFCKSUM_CRC32:
    679746            Assert(cBits == 32);
    680747            pCkSum->u32Kind      = RT_BSWAP_U32(pCkSum->u32Kind);
     
    696763 * @param   pCkSum      The structure.
    697764 */
    698 static void vboxdmgUdifCkSumHost2FileEndian(PVBOXUDIFCKSUM pCkSum)
    699 {
    700     vboxdmgSwapEndianUdifCkSum(pCkSum, pCkSum->u32Kind, pCkSum->cBits);
     765static void dmgUdifCkSumHost2FileEndian(PDMGUDIFCKSUM pCkSum)
     766{
     767    dmgSwapEndianUdifCkSum(pCkSum, pCkSum->u32Kind, pCkSum->cBits);
    701768}
    702769
     
    706773 * @param   pCkSum      The structure.
    707774 */
    708 static void vboxdmgUdifCkSumFile2HostEndian(PVBOXUDIFCKSUM pCkSum)
    709 {
    710     vboxdmgSwapEndianUdifCkSum(pCkSum, RT_BE2H_U32(pCkSum->u32Kind), RT_BE2H_U32(pCkSum->cBits));
     775static void dmgUdifCkSumFile2HostEndian(PDMGUDIFCKSUM pCkSum)
     776{
     777    dmgSwapEndianUdifCkSum(pCkSum, RT_BE2H_U32(pCkSum->u32Kind), RT_BE2H_U32(pCkSum->cBits));
    711778}
    712779
     
    720787 * @remarks This does not check the checksummed data.
    721788 */
    722 static bool vboxdmgUdifCkSumIsValid(PCVBOXUDIFCKSUM pCkSum, const char *pszPrefix)
     789static bool dmgUdifCkSumIsValid(PCDMGUDIFCKSUM pCkSum, const char *pszPrefix)
    723790{
    724791    bool fRc = true;
     
    726793    switch (pCkSum->u32Kind)
    727794    {
    728         case VBOXUDIFCKSUM_NONE:
    729             VBOXDMG_VALIDATE(pCkSum->cBits == 0, ("%s/NONE: cBits=%d\n", pszPrefix, pCkSum->cBits));
     795        case DMGUDIFCKSUM_NONE:
     796            DMG_VALIDATE(pCkSum->cBits == 0, ("%s/NONE: cBits=%d\n", pszPrefix, pCkSum->cBits));
    730797            break;
    731798
    732         case VBOXUDIFCKSUM_CRC32:
    733             VBOXDMG_VALIDATE(pCkSum->cBits == 32, ("%s/NONE: cBits=%d\n", pszPrefix, pCkSum->cBits));
     799        case DMGUDIFCKSUM_CRC32:
     800            DMG_VALIDATE(pCkSum->cBits == 32, ("%s/NONE: cBits=%d\n", pszPrefix, pCkSum->cBits));
    734801            break;
    735802
    736803        default:
    737             VBOXDMG_VALIDATE(0, ("%s: u32Kind=%#RX32\n", pszPrefix, pCkSum->u32Kind));
     804            DMG_VALIDATE(0, ("%s: u32Kind=%#RX32\n", pszPrefix, pCkSum->u32Kind));
    738805            break;
    739806    }
     
    803870        if (fDelete && pThis->pszFilename)
    804871            dmgFileDelete(pThis, pThis->pszFilename);
     872
     873        if (pThis->pvDecompExtent)
     874        {
     875            RTMemFree(pThis->pvDecompExtent);
     876            pThis->pvDecompExtent = NULL;
     877            pThis->cbDecompExtent = 0;
     878        }
     879
    805880    }
    806881
     
    857932 * @param   pszCur      The current position.
    858933 */
    859 static const char *vboxdmgXmlFindTagEnd(const char *pszCur)
     934static const char *dmgXmlFindTagEnd(const char *pszCur)
    860935{
    861936    /* Might want to take quoted '>' into account? */
     
    877952 * @param   pszTag      The tag name.
    878953 */
    879 static const char *vboxdmgXmlFindEndTag(const char **ppszCur, const char *pszTag)
     954static const char *dmgXmlFindEndTag(const char **ppszCur, const char *pszTag)
    880955{
    881956    const char         *psz = *ppszCur;
     
    908983 * @param   pi32        Where to store the value.
    909984 */
    910 static const char *vboxdmgXmlParseS32(const char **ppszCur, int32_t *pi32)
     985static const char *dmgXmlParseS32(const char **ppszCur, int32_t *pi32)
    911986{
    912987    const char *psz = *ppszCur;
     
    9361011 * @param   pu32        Where to store the value.
    9371012 */
    938 static const char *vboxdmgXmlParseU32(const char **ppszCur, uint32_t *pu32)
     1013static const char *dmgXmlParseU32(const char **ppszCur, uint32_t *pu32)
    9391014{
    9401015    const char *psz = *ppszCur;
     
    9651040 *                      must free this using RTMemFree.
    9661041 */
    967 static const char *vboxdmgXmlParseString(const char **ppszCur, char **ppszString)
     1042static const char *dmgXmlParseString(const char **ppszCur, char **ppszString)
    9681043{
    9691044    const char *psz = *ppszCur;
     
    9751050
    9761051    const char *pszStart = psz;
    977     const char *pszEnd = vboxdmgXmlFindEndTag(&psz, "string");
     1052    const char *pszEnd = dmgXmlFindEndTag(&psz, "string");
    9781053    if (!pszEnd)
    9791054        return *ppszCur;
     
    9981073 * @param   pcbData     The number of bytes we're returning.
    9991074 */
    1000 static const char *vboxdmgXmlParseData(const char **ppszCur, uint8_t **ppbData, size_t *pcbData)
     1075static const char *dmgXmlParseData(const char **ppszCur, uint8_t **ppbData, size_t *pcbData)
    10011076{
    10021077    const char *psz = *ppszCur;
     
    10351110 * Parses the XML resource-fork in a rather presumptive manner.
    10361111 *
    1037  * This function is supposed to construct the VBOXDMG::aRsrcs instance data
     1112 * This function is supposed to construct the DMG::aRsrcs instance data
    10381113 * parts.
    10391114 *
     
    10431118 * @param   cch         The size of the the XML text.
    10441119 */
    1045 static const char *vboxdmgOpenXmlToRsrc(PDMGIMAGE pThis, char const *pszXml)
     1120static const char *dmgOpenXmlToRsrc(PDMGIMAGE pThis, char const *pszXml)
    10461121{
    10471122    const char *psz = pszXml;
     
    10771152    REQUIRE_WORD(psz, "plist");
    10781153    REQUIRE_WORD(psz, "PUBLIC");
    1079     psz = vboxdmgXmlFindTagEnd(psz);
     1154    psz = dmgXmlFindTagEnd(psz);
    10801155    REQUIRE_WORD(psz, ">");
    10811156
     
    11081183        {
    11091184            REQUIRE_WORD(psz, "<key>blkx</key>");
    1110             iRsrc = VBOXDMG_RSRC_IDX_BLKX;
     1185            iRsrc = DMG_RSRC_IDX_BLKX;
    11111186            strcpy(&pThis->aRsrcs[iRsrc].szName[0], "blkx");
    11121187        }
     
    11141189        {
    11151190            REQUIRE_WORD(psz, "<key>plst</key>");
    1116             iRsrc = VBOXDMG_RSRC_IDX_PLST;
     1191            iRsrc = DMG_RSRC_IDX_PLST;
    11171192            strcpy(&pThis->aRsrcs[iRsrc].szName[0], "plst");
    11181193        }
     
    11401215                {
    11411216                    REQUIRE_WORD(psz, "<key>Attributes</key>");
    1142                     pszErr = vboxdmgXmlParseU32(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].fAttributes);
     1217                    pszErr = dmgXmlParseU32(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].fAttributes);
    11431218                }
    11441219                else if (STARTS_WITH_WORD(psz, "<key>ID</key>"))
    11451220                {
    11461221                    REQUIRE_WORD(psz, "<key>ID</key>");
    1147                     pszErr = vboxdmgXmlParseS32(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].iId);
     1222                    pszErr = dmgXmlParseS32(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].iId);
    11481223                }
    11491224                else if (STARTS_WITH_WORD(psz, "<key>Name</key>"))
    11501225                {
    11511226                    REQUIRE_WORD(psz, "<key>Name</key>");
    1152                     pszErr = vboxdmgXmlParseString(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].pszName);
     1227                    pszErr = dmgXmlParseString(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].pszName);
    11531228                }
    11541229                else if (STARTS_WITH_WORD(psz, "<key>CFName</key>"))
    11551230                {
    11561231                    REQUIRE_WORD(psz, "<key>CFName</key>");
    1157                     pszErr = vboxdmgXmlParseString(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].pszCFName);
     1232                    pszErr = dmgXmlParseString(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].pszCFName);
    11581233                }
    11591234                else if (STARTS_WITH_WORD(psz, "<key>Data</key>"))
    11601235                {
    11611236                    REQUIRE_WORD(psz, "<key>Data</key>");
    1162                     pszErr = vboxdmgXmlParseData(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].pbData, &pThis->aRsrcs[iRsrc].aEntries[i].cbData);
     1237                    pszErr = dmgXmlParseData(&psz, &pThis->aRsrcs[iRsrc].aEntries[i].pbData, &pThis->aRsrcs[iRsrc].aEntries[i].cbData);
    11631238                }
    11641239                else
     
    12071282 */
    12081283static int dmgGetRsrcData(PDMGIMAGE pThis, const char *pcszRsrcName,
    1209                           PCVBOXUDIFRSRCARRAY *ppcRsrc)
     1284                          PCDMGUDIFRSRCARRAY *ppcRsrc)
    12101285{
    12111286    int rc = VERR_NOT_FOUND;
     
    12281303 *
    12291304 * @returns VBox status code.
    1230  * @param   pThis     DMG instance data.
    1231  * @param   pBlkxDesc The blkx descriptor.
    1232  */
    1233 static int vboxdmgExtentCreateFromBlkxDesc(PDMGIMAGE pThis, uint64_t offDevice, PVBOXBLKXDESC pBlkxDesc)
     1305 * @param   pThis          DMG instance data.
     1306 * @param   uSectorPart    First sector the partition owning the blkx descriptor has.
     1307 * @param   pBlkxDesc      The blkx descriptor.
     1308 */
     1309static int dmgExtentCreateFromBlkxDesc(PDMGIMAGE pThis, uint64_t uSectorPart, PDMGBLKXDESC pBlkxDesc)
    12341310{
    12351311    int rc = VINF_SUCCESS;
     
    12371313    PDMGEXTENT pExtentNew = NULL;
    12381314
    1239     if (pBlkxDesc->u32Type == VBOXBLKXDESC_TYPE_RAW)
     1315    if (pBlkxDesc->u32Type == DMGBLKXDESC_TYPE_RAW)
    12401316        enmExtentTypeNew = DMGEXTENTTYPE_RAW;
    1241     else if (pBlkxDesc->u32Type == VBOXBLKXDESC_TYPE_IGNORE)
     1317    else if (pBlkxDesc->u32Type == DMGBLKXDESC_TYPE_IGNORE)
    12421318        enmExtentTypeNew = DMGEXTENTTYPE_ZERO;
     1319    else if (pBlkxDesc->u32Type == DMGBLKXDESC_TYPE_ZLIB)
     1320        enmExtentTypeNew = DMGEXTENTTYPE_COMP_ZLIB;
    12431321    else
     1322    {
    12441323        AssertMsgFailed(("This method supports only raw or zero extents!\n"));
    1245 
     1324        return VERR_NOT_SUPPORTED;
     1325    }
     1326
     1327    /** @todo: Merge raw extents if possible to save memory. */
    12461328#if 0
    12471329    pExtentNew = pThis->pExtentLast;
    12481330    if (   pExtentNew
    12491331        && pExtentNew->enmType == enmExtentTypeNew
    1250         && pExtentNew->offExtent + pExtentNew->cbExtent == offDevice + pBlkxDesc->u64SectorStart * VBOXDMG_SECTOR_SIZE;
     1332        && enmExtentTypeNew == DMGEXTENTTYPE_RAW
     1333        && pExtentNew->uSectorExtent + pExtentNew->cSectorsExtent == offDevice + pBlkxDesc->u64SectorStart * DMG_SECTOR_SIZE;
    12511334        && pExtentNew->offFileStart + pExtentNew->cbExtent == pBlkxDesc->offData)
    12521335    {
     
    12571340#endif
    12581341    {
    1259         /* Create a new extent. */
    1260         pExtentNew = (PDMGEXTENT)RTMemAllocZ(sizeof(DMGEXTENT));
    1261         if (pExtentNew)
     1342        if (pThis->cExtentsMax == pThis->cExtents)
    12621343        {
    1263             pExtentNew->pNext        = NULL;
    1264             pExtentNew->enmType      = enmExtentTypeNew;
    1265             pExtentNew->offExtent    = offDevice + pBlkxDesc->u64SectorStart * VBOXDMG_SECTOR_SIZE;
    1266             pExtentNew->offFileStart = pBlkxDesc->offData;
    1267             pExtentNew->cbExtent     = pBlkxDesc->u64SectorCount * VBOXDMG_SECTOR_SIZE;
    1268             Assert(   pBlkxDesc->cbData == pBlkxDesc->u64SectorCount * VBOXDMG_SECTOR_SIZE
    1269                    || enmExtentTypeNew == DMGEXTENTTYPE_ZERO);
    1270 
    1271             if (!pThis->pExtentLast)
     1344            pThis->cExtentsMax += 64;
     1345
     1346            /* Increase the array. */
     1347            PDMGEXTENT paExtentsNew = (PDMGEXTENT)RTMemRealloc(pThis->paExtents, sizeof(DMGEXTENT) * pThis->cExtentsMax);
     1348            if (!paExtentsNew)
    12721349            {
    1273                 pThis->pExtentFirst = pExtentNew;
    1274                 pThis->pExtentLast  = pExtentNew;
     1350                rc = VERR_NO_MEMORY;
     1351                pThis->cExtentsMax -= 64;
    12751352            }
    12761353            else
    1277             {
    1278                 pThis->pExtentLast->pNext = pExtentNew;
    1279                 pThis->pExtentLast        = pExtentNew;
    1280             }
     1354                pThis->paExtents = paExtentsNew;
     1355        }
     1356
     1357        if (RT_SUCCESS(rc))
     1358        {
     1359            pExtentNew = &pThis->paExtents[pThis->cExtents++];
     1360
     1361            pExtentNew->enmType        = enmExtentTypeNew;
     1362            pExtentNew->uSectorExtent  = uSectorPart + pBlkxDesc->u64SectorStart;
     1363            pExtentNew->cSectorsExtent = pBlkxDesc->u64SectorCount;
     1364            pExtentNew->offFileStart   = pBlkxDesc->offData;
     1365            pExtentNew->cbFile         = pBlkxDesc->cbData;
     1366        }
     1367    }
     1368
     1369    return rc;
     1370}
     1371
     1372/**
     1373 * Find the extent for the given sector number.
     1374 */
     1375static PDMGEXTENT dmgExtentGetFromOffset(PDMGIMAGE pThis, uint64_t uSector)
     1376{
     1377    /*
     1378     * We assume that the array is ordered from lower to higher sector
     1379     * numbers.
     1380     * This makes it possible to bisect the array to find the extent
     1381     * faster than using a linked list.
     1382     */
     1383    PDMGEXTENT pExtent = NULL;
     1384    unsigned idxCur = pThis->idxExtentLast;
     1385    unsigned idxMax = pThis->cExtents;
     1386    unsigned idxMin = 0;
     1387
     1388    while (idxMin < idxMax)
     1389    {
     1390        PDMGEXTENT pExtentCur = &pThis->paExtents[idxCur];
     1391
     1392        /* Determine the search direction. */
     1393        if (uSector < pExtentCur->uSectorExtent)
     1394        {
     1395            /* Search left from the current extent. */
     1396            idxMax = idxCur;
     1397        }
     1398        else if (uSector >= pExtentCur->uSectorExtent + pExtentCur->cSectorsExtent)
     1399        {
     1400            /* Search right from the current extent. */
     1401            idxMin = idxCur;
    12811402        }
    12821403        else
    1283             rc = VERR_NO_MEMORY;
    1284     }
    1285 
    1286     return rc;
    1287 }
    1288 
    1289 /**
    1290  * Find the extent for the given offset.
    1291  */
    1292 static PDMGEXTENT dmgExtentGetFromOffset(PDMGIMAGE pThis, uint64_t uOffset)
    1293 {
    1294     PDMGEXTENT pExtent = pThis->pExtentFirst;
    1295 
    1296     while (   pExtent
    1297            && (   uOffset < pExtent->offExtent
    1298                || uOffset - pExtent->offExtent >= pExtent->cbExtent))
    1299         pExtent = pExtent->pNext;
     1404        {
     1405            /* The sector lies in the extent, stop searching. */
     1406            pExtent = pExtentCur;
     1407            break;
     1408        }
     1409
     1410        idxCur = idxMin + (idxMax - idxMin) / 2;
     1411    }
     1412
     1413    if (pExtent)
     1414        pThis->idxExtentLast = idxCur;
    13001415
    13011416    return pExtent;
     
    13051420 * Goes through the BLKX structure and creates the necessary extents.
    13061421 */
    1307 static int vboxdmgBlkxParse(PDMGIMAGE pThis, PVBOXBLKX pBlkx)
     1422static int dmgBlkxParse(PDMGIMAGE pThis, PDMGBLKX pBlkx)
    13081423{
    13091424    int rc = VINF_SUCCESS;
    1310     PVBOXBLKXDESC pBlkxDesc = (PVBOXBLKXDESC)(pBlkx + 1);
     1425    PDMGBLKXDESC pBlkxDesc = (PDMGBLKXDESC)(pBlkx + 1);
    13111426
    13121427    for (unsigned i = 0; i < pBlkx->cBlocksRunCount; i++)
    13131428    {
    1314         vboxdmgBlkxDescFile2HostEndian(pBlkxDesc);
     1429        dmgBlkxDescFile2HostEndian(pBlkxDesc);
    13151430
    13161431        switch (pBlkxDesc->u32Type)
    13171432        {
    1318             case VBOXBLKXDESC_TYPE_RAW:
    1319             case VBOXBLKXDESC_TYPE_IGNORE:
     1433            case DMGBLKXDESC_TYPE_RAW:
     1434            case DMGBLKXDESC_TYPE_IGNORE:
     1435            case DMGBLKXDESC_TYPE_ZLIB:
    13201436            {
    1321                 rc = vboxdmgExtentCreateFromBlkxDesc(pThis, pBlkx->cSectornumberFirst * VBOXDMG_SECTOR_SIZE, pBlkxDesc);
     1437                rc = dmgExtentCreateFromBlkxDesc(pThis, pBlkx->cSectornumberFirst, pBlkxDesc);
    13221438                break;
    13231439            }
    1324             case VBOXBLKXDESC_TYPE_COMMENT:
    1325             case VBOXBLKXDESC_TYPE_TERMINATOR:
     1440            case DMGBLKXDESC_TYPE_COMMENT:
     1441            case DMGBLKXDESC_TYPE_TERMINATOR:
    13261442                break;
    13271443            default:
     
    13301446        }
    13311447
    1332         if (   pBlkxDesc->u32Type == VBOXBLKXDESC_TYPE_TERMINATOR
     1448        if (   pBlkxDesc->u32Type == DMGBLKXDESC_TYPE_TERMINATOR
    13331449            || RT_FAILURE(rc))
    13341450                break;
     
    13831499    if (RT_FAILURE(rc))
    13841500        return rc;
    1385     vboxdmgUdifFtrFile2HostEndian(&pThis->Ftr);
     1501    dmgUdifFtrFile2HostEndian(&pThis->Ftr);
    13861502
    13871503    /*
    13881504     * Do we recognize the footer structure? If so, is it valid?
    13891505     */
    1390     if (pThis->Ftr.u32Magic != VBOXUDIF_MAGIC)
     1506    if (pThis->Ftr.u32Magic != DMGUDIF_MAGIC)
    13911507        return VERR_VD_DMG_INVALID_HEADER;
    1392     if (pThis->Ftr.u32Version != VBOXUDIF_VER_CURRENT)
     1508    if (pThis->Ftr.u32Version != DMGUDIF_VER_CURRENT)
    13931509        return VERR_VD_DMG_INVALID_HEADER;
    13941510    if (pThis->Ftr.cbFooter != sizeof(pThis->Ftr))
    13951511        return VERR_VD_DMG_INVALID_HEADER;
    13961512
    1397     if (!vboxdmgUdifFtrIsValid(&pThis->Ftr, pThis->cbFile - sizeof(pThis->Ftr)))
    1398     {
    1399         VBOXDMG_PRINTF(("Bad DMG: '%s' cbFile=%RTfoff\n", pThis->pszFilename, pThis->cbFile));
     1513    if (!dmgUdifFtrIsValid(&pThis->Ftr, pThis->cbFile - sizeof(pThis->Ftr)))
     1514    {
     1515        DMG_PRINTF(("Bad DMG: '%s' cbFile=%RTfoff\n", pThis->pszFilename, pThis->cbFile));
    14001516        return VERR_VD_DMG_INVALID_HEADER;
    14011517    }
    14021518
    1403     pThis->cbSize = pThis->Ftr.cSectors * VBOXDMG_SECTOR_SIZE;
     1519    pThis->cbSize = pThis->Ftr.cSectors * DMG_SECTOR_SIZE;
    14041520
    14051521    /*
     
    14141530    {
    14151531        pszXml[cchXml] = '\0';
    1416         const char *pszError = vboxdmgOpenXmlToRsrc(pThis, pszXml);
     1532        const char *pszError = dmgOpenXmlToRsrc(pThis, pszXml);
    14171533        if (!pszError)
    14181534        {
    1419             PCVBOXUDIFRSRCARRAY pRsrcBlkx = NULL;
     1535            PCDMGUDIFRSRCARRAY pRsrcBlkx = NULL;
    14201536
    14211537            rc = dmgGetRsrcData(pThis, "blkx", &pRsrcBlkx);
     
    14241540                for (unsigned idxBlkx = 0; idxBlkx < pRsrcBlkx->cEntries; idxBlkx++)
    14251541                {
    1426                     PVBOXBLKX pBlkx = NULL;
    1427 
    1428                     if (pRsrcBlkx->aEntries[idxBlkx].cbData < sizeof(VBOXBLKX))
     1542                    PDMGBLKX pBlkx = NULL;
     1543
     1544                    if (pRsrcBlkx->aEntries[idxBlkx].cbData < sizeof(DMGBLKX))
    14291545                    {
    14301546                        rc = VERR_VD_DMG_INVALID_HEADER;
     
    14321548                    }
    14331549
    1434                     pBlkx = (PVBOXBLKX)RTMemAllocZ(pRsrcBlkx->aEntries[idxBlkx].cbData);
     1550                    pBlkx = (PDMGBLKX)RTMemAllocZ(pRsrcBlkx->aEntries[idxBlkx].cbData);
    14351551                    if (!pBlkx)
    14361552                    {
     
    14411557                    memcpy(pBlkx, pRsrcBlkx->aEntries[idxBlkx].pbData, pRsrcBlkx->aEntries[idxBlkx].cbData);
    14421558
    1443                     vboxdmgBlkxFile2HostEndian(pBlkx);
    1444 
    1445                     if (   vboxdmgBlkxIsValid(pBlkx)
    1446                         && pRsrcBlkx->aEntries[idxBlkx].cbData == pBlkx->cBlocksRunCount * sizeof(VBOXBLKXDESC) + sizeof(VBOXBLKX))
    1447                         rc = vboxdmgBlkxParse(pThis, pBlkx);
     1559                    dmgBlkxFile2HostEndian(pBlkx);
     1560
     1561                    if (   dmgBlkxIsValid(pBlkx)
     1562                        && pRsrcBlkx->aEntries[idxBlkx].cbData == pBlkx->cBlocksRunCount * sizeof(DMGBLKXDESC) + sizeof(DMGBLKX))
     1563                        rc = dmgBlkxParse(pThis, pBlkx);
    14481564                    else
    14491565                        rc = VERR_VD_DMG_INVALID_HEADER;
     
    14611577        else
    14621578        {
    1463             VBOXDMG_PRINTF(("**** XML DUMP BEGIN ***\n%s\n**** XML DUMP END ****\n", pszXml));
    1464             VBOXDMG_PRINTF(("**** Bad XML at %#lx (%lu) ***\n%.256s\n**** Bad XML END ****\n",
     1579            DMG_PRINTF(("**** XML DUMP BEGIN ***\n%s\n**** XML DUMP END ****\n", pszXml));
     1580            DMG_PRINTF(("**** Bad XML at %#lx (%lu) ***\n%.256s\n**** Bad XML END ****\n",
    14651581                            (unsigned long)(pszError - pszXml), (unsigned long)(pszError - pszXml), pszError));
    14661582            rc = VERR_VD_DMG_XML_PARSE_ERROR;
     
    14831599    PVDIOSTORAGE pStorage;
    14841600    uint64_t cbFile, offFtr = 0;
    1485     VBOXUDIF Ftr;
     1601    DMGUDIF Ftr;
    14861602
    14871603    /* Get I/O interface. */
     
    15141630    if (RT_SUCCESS(rc))
    15151631    {
    1516         vboxdmgUdifFtrFile2HostEndian(&Ftr);
     1632        dmgUdifFtrFile2HostEndian(&Ftr);
    15171633
    15181634        /*
    15191635         * Do we recognize this stuff? Does it look valid?
    15201636         */
    1521         if (    Ftr.u32Magic    == VBOXUDIF_MAGIC
    1522             &&  Ftr.u32Version  == VBOXUDIF_VER_CURRENT
     1637        if (    Ftr.u32Magic    == DMGUDIF_MAGIC
     1638            &&  Ftr.u32Version  == DMGUDIF_VER_CURRENT
    15231639            &&  Ftr.cbFooter    == sizeof(Ftr))
    15241640        {
    1525             if (vboxdmgUdifFtrIsValid(&Ftr, offFtr))
     1641            if (dmgUdifFtrIsValid(&Ftr, offFtr))
    15261642                rc = VINF_SUCCESS;
    15271643            else
    15281644            {
    1529                 VBOXDMG_PRINTF(("Bad DMG: '%s' offFtr=%RTfoff\n", pszFilename, offFtr));
     1645                DMG_PRINTF(("Bad DMG: '%s' offFtr=%RTfoff\n", pszFilename, offFtr));
    15301646                rc = VERR_VD_DMG_INVALID_HEADER;
    15311647            }
     
    16551771
    16561772    AssertPtr(pThis);
    1657     Assert(uOffset % 512 == 0);
    1658     Assert(cbToRead % 512 == 0);
     1773    Assert(uOffset % DMG_SECTOR_SIZE == 0);
     1774    Assert(cbToRead % DMG_SECTOR_SIZE == 0);
    16591775
    16601776    if (   uOffset + cbToRead > pThis->cbSize
     
    16651781    }
    16661782
    1667     pExtent = dmgExtentGetFromOffset(pThis, uOffset);
     1783    pExtent = dmgExtentGetFromOffset(pThis, DMG_BYTE2BLOCK(uOffset));
    16681784
    16691785    if (pExtent)
    16701786    {
    1671         uint64_t offExtentRel = uOffset - pExtent->offExtent;
     1787        uint64_t uExtentRel = DMG_BYTE2BLOCK(uOffset) - pExtent->uSectorExtent;
    16721788
    16731789        /* Remain in this extent. */
    1674         cbToRead = RT_MIN(cbToRead, pExtent->cbExtent - offExtentRel);
     1790        cbToRead = RT_MIN(cbToRead, DMG_BLOCK2BYTE(pExtent->cSectorsExtent - uExtentRel));
    16751791
    16761792        switch (pExtent->enmType)
     
    16781794            case DMGEXTENTTYPE_RAW:
    16791795            {
    1680                 rc = dmgFileReadSync(pThis, pExtent->offFileStart + offExtentRel, pvBuf, cbToRead, NULL);
     1796                rc = dmgFileReadSync(pThis, pExtent->offFileStart + DMG_BLOCK2BYTE(uExtentRel), pvBuf, cbToRead, NULL);
    16811797                break;
    16821798            }
     
    16841800            {
    16851801                memset(pvBuf, 0, cbToRead);
     1802                break;
     1803            }
     1804            case DMGEXTENTTYPE_COMP_ZLIB:
     1805            {
     1806                if (pThis->pExtentDecomp != pExtent)
     1807                {
     1808                    if (DMG_BLOCK2BYTE(pExtent->cSectorsExtent) > pThis->cbDecompExtent)
     1809                    {
     1810                        if (RT_LIKELY(pThis->pvDecompExtent))
     1811                            RTMemFree(pThis->pvDecompExtent);
     1812
     1813                        pThis->pvDecompExtent = RTMemAllocZ(DMG_BLOCK2BYTE(pExtent->cSectorsExtent));
     1814                        if (!pThis->pvDecompExtent)
     1815                            rc = VERR_NO_MEMORY;
     1816                        else
     1817                            pThis->cbDecompExtent = DMG_BLOCK2BYTE(pExtent->cSectorsExtent);
     1818                    }
     1819
     1820                    if (RT_SUCCESS(rc))
     1821                    {
     1822                        rc = dmgFileInflateSync(pThis, pExtent->offFileStart, pExtent->cbFile,
     1823                                                pThis->pvDecompExtent,
     1824                                                RT_MIN(pThis->cbDecompExtent, DMG_BLOCK2BYTE(pExtent->cSectorsExtent)));
     1825                        if (RT_SUCCESS(rc))
     1826                            pThis->pExtentDecomp = pExtent;
     1827                    }
     1828                }
     1829
     1830                if (RT_SUCCESS(rc))
     1831                    memcpy(pvBuf, (uint8_t *)pThis->pvDecompExtent + DMG_BLOCK2BYTE(uExtentRel), cbToRead);
    16861832                break;
    16871833            }
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