Changeset 32432 in vbox for trunk/src/VBox/Devices/Storage/DMGHDDCore.cpp
- Timestamp:
- Sep 12, 2010 4:09:57 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 65797
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DMGHDDCore.cpp
r32431 r32432 5 5 6 6 /* 7 * Copyright (C) 20 09Oracle Corporation7 * Copyright (C) 2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 20 20 *******************************************************************************/ 21 21 #define LOG_GROUP LOG_GROUP_DEFAULT /** @todo log group */ 22 #include <VBox/VBoxHDD .h>22 #include <VBox/VBoxHDD-Plugin.h> 23 23 #include <VBox/log.h> 24 24 #include <VBox/err.h> … … 35 35 #endif 36 36 37 38 37 /******************************************************************************* 39 38 * Structures and Typedefs * 40 39 *******************************************************************************/ 40 41 /** Sector size, multiply with all sector counts to get number of bytes. */ 42 #define VBOXDMG_SECTOR_SIZE 512 43 41 44 /** 42 45 * UDIF checksum structure. … … 144 147 145 148 /** 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) 156 typedef 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) 170 AssertCompileSize(VBOXBLKX, 204); 171 172 typedef VBOXBLKX *PVBOXBLKX; 173 typedef 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) 189 typedef 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) 199 AssertCompileSize(VBOXBLKXDESC, 40); 200 201 typedef VBOXBLKXDESC *PVBOXBLKXDESC; 202 typedef 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 /** 146 214 * UDIF Resource Entry. 147 215 */ … … 177 245 /** The array entries. 178 246 * 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]; 181 250 } VBOXUDIFRSRCARRAY; 182 251 /** Pointer to a UDIF resource array. */ … … 185 254 typedef VBOXUDIFRSRCARRAY const *PCVBOXUDIFRSRCARRAY; 186 255 187 256 /** 257 * DMG extent types. 258 */ 259 typedef 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 */ 274 typedef 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. */ 288 typedef DMGEXTENT *PDMGEXTENT; 188 289 189 290 /** 190 291 * VirtualBox Apple Disk Image (DMG) interpreter instance data. 191 292 */ 192 typedef struct VBOXDMG 193 { 194 /** The open image file. */ 195 RTFILE hFile; 196 /** The current file size. */ 293 typedef 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. */ 197 303 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; 198 312 /** Flags the image was opened with. */ 199 uint32_t fOpenFlags; 313 uint32_t uOpenFlags; 314 /** Image flags. */ 315 unsigned uImageFlags; 200 316 /** The filename. 201 317 * Kept around for logging and delete-on-close purposes. */ … … 207 323 /** The UDIF footer. */ 208 324 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; 210 337 /** Pointer to an instance of the DMG Image Interpreter. */ 211 typedef VBOXDMG *PVBOXDMG;338 typedef DMGIMAGE *PDMGIMAGE; 212 339 213 340 /** @name Resources indexes (into VBOXDMG::aRsrcs). … … 273 400 static bool vboxdmgUdifCkSumIsValid(PCVBOXUDIFCKSUM pCkSum, const char *pszPrefix); 274 401 402 /** 403 * Internal: signal an error to the frontend. 404 */ 405 DECLINLINE(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 417 static 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 432 static 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 445 static int dmgFileFlushSync(PDMGIMAGE pImage) 446 { 447 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 448 pImage->pStorage); 449 } 450 451 static int dmgFileGetSize(PDMGIMAGE pImage, uint64_t *pcbSize) 452 { 453 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 454 pImage->pStorage, 455 pcbSize); 456 } 457 458 static int dmgFileSetSize(PDMGIMAGE pImage, uint64_t cbSize) 459 { 460 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 461 pImage->pStorage, 462 cbSize); 463 } 464 465 static 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 473 static 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 481 static bool dmgFileOpened(PDMGIMAGE pImage) 482 { 483 return pImage->pStorage != NULL; 484 } 275 485 276 486 /** … … 325 535 } 326 536 537 /** 538 * Swaps endian from file to host cpu. 539 * @param pBlkx The blkx structure. 540 */ 541 static 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 */ 558 static 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 } 327 567 328 568 /** … … 344 584 VBOXDMG_VALIDATE(pFtr->offRsrc < offFtr, ("offRsrc=%#RX64\n", pFtr->offRsrc)); 345 585 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)); 347 587 VBOXDMG_VALIDATE(pFtr->cbXml <= offFtr && pFtr->offXml + pFtr->cbXml <= offFtr, ("cbXml=%#RX64 offXml=%#RX64 offFtr=%#RX64\n", pFtr->cbXml, pFtr->offXml, offFtr)); 348 588 VBOXDMG_VALIDATE(pFtr->offXml < offFtr, ("offXml=%#RX64\n", pFtr->offXml)); … … 351 591 VBOXDMG_VALIDATE(pFtr->u32Type == VBOXUDIF_TYPE_DEVICE || pFtr->u32Type == VBOXUDIF_TYPE_PARTITION, ("u32Type=%RU32\n", pFtr->u32Type)); 352 592 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"); 355 595 356 596 return fRc; 357 597 } 358 598 599 600 static 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 } 359 610 360 611 /** … … 464 715 static DECLCALLBACK(int) vboxdmgClose(void *pvBackendData, bool fDelete) 465 716 { 466 P VBOXDMG pThis = (PVBOXDMG)pvBackendData;467 468 if ( pThis->hFile != NIL_RTFILE)717 PDMGIMAGE pThis = (PDMGIMAGE)pvBackendData; 718 719 if (dmgFileOpened(pThis)) 469 720 { 470 721 /* … … 476 727 * Close the file. 477 728 */ 478 RTFileClose(pThis->hFile); 479 pThis->hFile = NIL_RTFILE; 729 dmgFileClose(pThis); 480 730 } 481 731 … … 745 995 * @param cch The size of the the XML text. 746 996 */ 747 static const char *vboxdmgOpenXmlToRsrc(P VBOXDMGpThis, char const *pszXml)997 static const char *vboxdmgOpenXmlToRsrc(PDMGIMAGE pThis, char const *pszXml) 748 998 { 749 999 const char *psz = pszXml; … … 871 1121 REQUIRE_END_TAG(psz, "dict"); 872 1122 1123 pThis->aRsrcs[iRsrc].cEntries++; 873 1124 } /* while not </array> */ 874 1125 REQUIRE_END_TAG(psz, "array"); … … 900 1151 #undef STARTS_WITH 901 1152 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 */ 1160 static 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 */ 1185 static 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 */ 1244 static 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 */ 1259 static 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 } 902 1293 903 1294 /** … … 911 1302 * @param pThis The DMG instance data. 912 1303 */ 913 static int vboxdmgOpenWorker(P VBOXDMGpThis)1304 static int vboxdmgOpenWorker(PDMGIMAGE pThis) 914 1305 { 915 1306 /* 916 1307 * Read the footer. 917 1308 */ 918 int rc = RTFileGetSize(pThis->hFile, &pThis->cbFile);1309 int rc = dmgFileGetSize(pThis, &pThis->cbFile); 919 1310 if (RT_FAILURE(rc)) 920 1311 return rc; 921 1312 if (pThis->cbFile < 1024) 922 1313 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); 924 1315 if (RT_FAILURE(rc)) 925 1316 return rc; … … 942 1333 } 943 1334 1335 pThis->cbSize = pThis->Ftr.cSectors * VBOXDMG_SECTOR_SIZE; 1336 944 1337 /* 945 1338 * Read and parse the XML portion. … … 949 1342 if (!pszXml) 950 1343 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); 952 1345 if (RT_SUCCESS(rc)) 953 1346 { … … 956 1349 if (!pszError) 957 1350 { 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; 961 1392 } 962 1393 else … … 977 1408 978 1409 979 980 1410 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 981 static DECLCALLBACK(int) vboxdmgOpen(const char *pszFilename, unsigned fOpenFlags,982 983 1411 static DECLCALLBACK(int) dmgOpen(const char *pszFilename, unsigned fOpenFlags, 1412 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 1413 void **ppvBackendData) 984 1414 { 985 1415 /* … … 997 1427 * then hand it over to a worker function that does all the rest. 998 1428 */ 999 P VBOXDMG pThis = (PVBOXDMG)RTMemAllocZ(sizeof(*pThis));1429 PDMGIMAGE pThis = (PDMGIMAGE)RTMemAllocZ(sizeof(*pThis)); 1000 1430 if (!pThis) 1001 1431 return VERR_NO_MEMORY; 1002 pThis-> fOpenFlags = fOpenFlags;1432 pThis->uOpenFlags = fOpenFlags; 1003 1433 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); 1010 1450 if (RT_SUCCESS(rc)) 1011 1451 { … … 1025 1465 1026 1466 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */ 1027 static DECLCALLBACK(int) vboxdmgCheckIfValid(const char *pszFilename)1467 static DECLCALLBACK(int) dmgCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk) 1028 1468 { 1029 1469 /* … … 1070 1510 } 1071 1511 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 */ 1513 static 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 */ 1528 static 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 */ 1538 static 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 */ 1554 static 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 1604 out: 1605 LogFlowFunc(("returns %Rrc\n", rc)); 1606 return rc; 1607 } 1608 1609 /** @copydoc VBOXHDDBACKEND::pfnWrite */ 1610 static 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 1631 out: 1632 LogFlowFunc(("returns %Rrc\n", rc)); 1633 return rc; 1634 } 1635 1636 /** @copydoc VBOXHDDBACKEND::pfnFlush */ 1637 static 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 */ 1649 static unsigned dmgGetVersion(void *pBackendData) 1650 { 1651 LogFlowFunc(("pBackendData=%#p\n", pBackendData)); 1652 PDMGIMAGE pImage = (PDMGIMAGE)pBackendData; 1653 1654 Assert(pImage); 1655 1656 if (pImage) 1084 1657 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 */ 1663 static 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 */ 1677 static 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 */ 1701 static 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 */ 1728 static 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 1752 out: 1753 LogFlowFunc(("returns %Rrc\n", rc)); 1754 return rc; 1755 } 1756 1757 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */ 1758 static 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 */ 1785 static 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 1809 out: 1810 LogFlowFunc(("returns %Rrc\n", rc)); 1811 return rc; 1812 } 1813 1814 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */ 1815 static 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 */ 1833 static 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 */ 1851 static 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); 1119 1869 #endif 1120 1870 1871 out: 1872 LogFlowFunc(("returns %Rrc\n", rc)); 1873 return rc; 1874 } 1875 1876 /** @copydoc VBOXHDDBACKEND::pfnGetComment */ 1877 static 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 */ 1900 static 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 1919 out: 1920 LogFlowFunc(("returns %Rrc\n", rc)); 1921 return rc; 1922 } 1923 1924 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */ 1925 static 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 */ 1943 static 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 */ 1967 static 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 */ 1985 static 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 */ 2008 static 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 */ 2026 static 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 */ 2049 static 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 */ 2067 static 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 */ 2090 static 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 2104 static 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 2111 static 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 2118 static 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 2125 static 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 2132 static 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 2140 VBOXHDDBACKEND 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.