Changeset 69609 in vbox for trunk/src/VBox/Runtime/common/dvm
- Timestamp:
- Nov 7, 2017 6:59:38 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 118969
- Location:
- trunk/src/VBox/Runtime/common/dvm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dvm/dvm.cpp
r69111 r69609 101 101 * Supported volume formats. 102 102 */ 103 static PCRTDVMFMTOPS g_aDvmFmts[] =103 static PCRTDVMFMTOPS const g_aDvmFmts[] = 104 104 { 105 105 &g_rtDvmFmtMbr, … … 113 113 * This is indexed by RTDVMVOLTYPE. 114 114 */ 115 static const char * g_apcszDvmVolTypes[] =115 static const char * const g_apszDvmVolTypes[] = 116 116 { 117 117 "Invalid", … … 130 130 "Solaris" 131 131 }; 132 AssertCompile(RT_ELEMENTS(g_apszDvmVolTypes) == RTDVMVOLTYPE_END); 133 132 134 133 135 /** … … 139 141 * @param phVol Where to store the generic volume handle on success. 140 142 */ 141 static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, 142 PRTDVMVOLUME phVol) 143 { 144 int rc = VINF_SUCCESS; 145 PRTDVMVOLUMEINTERNAL pVol = NULL; 146 147 pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL)); 143 static int rtDvmVolumeCreate(PRTDVMINTERNAL pThis, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUME phVol) 144 { 145 PRTDVMVOLUMEINTERNAL pVol = (PRTDVMVOLUMEINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEINTERNAL)); 148 146 if (pVol) 149 147 { … … 154 152 155 153 *phVol = pVol; 156 } 157 else 158 rc = VERR_NO_MEMORY; 159 160 return rc; 154 return VINF_SUCCESS; 155 } 156 return VERR_NO_MEMORY; 161 157 } 162 158 … … 184 180 } 185 181 186 RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, PFNDVMREAD pfnRead, 187 PFNDVMWRITE pfnWrite, uint64_t cbDisk, 188 uint64_t cbSector, uint32_t fFlags, void *pvUser) 189 { 190 int rc = VINF_SUCCESS;191 PRTDVMINTERNAL pThis;192 193 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_MASK),194 ("Invalid flags given %#x\n", fFlags),195 VERR_INVALID_PARAMETER);196 197 pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL));198 if (pThis)199 {200 pThis->u32Magic = RTDVM_MAGIC;201 pThis->DvmDisk.cbDisk = cbDisk;202 pThis->DvmDisk.cbSector = cbSector;203 pThis->DvmDisk.pvUser = pvUser;204 pThis->DvmDisk.pfnRead = pfnRead; 205 pThis->DvmDisk.pfnWrite = pfnWrite;206 pThis->pDvmFmtOps = NULL;207 pThis->hVolMgrFmt = NIL_RTDVMFMT;208 pThis->fFlags = fFlags;209 pThis->cRefs = 1;210 RTListInit(&pThis->VolumeList); 211 *phVolMgr = pThis;212 }213 else182 183 RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, RTVFSFILE hVfsFile, uint32_t cbSector, uint32_t fFlags) 184 { 185 AssertMsgReturn(!(fFlags & ~DVM_FLAGS_VALID_MASK), ("Invalid flags given %#x\n", fFlags), VERR_INVALID_FLAGS); 186 uint32_t cRefs = RTVfsFileRetain(hVfsFile); 187 AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE); 188 189 uint64_t cbDisk; 190 int rc = RTVfsFileGetSize(hVfsFile, &cbDisk); 191 if (RT_SUCCESS(rc)) 192 { 193 PRTDVMINTERNAL pThis = (PRTDVMINTERNAL)RTMemAllocZ(sizeof(RTDVMINTERNAL)); 194 if (pThis) 195 { 196 pThis->u32Magic = RTDVM_MAGIC; 197 pThis->DvmDisk.cbDisk = cbDisk; 198 pThis->DvmDisk.cbSector = cbSector; 199 pThis->DvmDisk.hVfsFile = hVfsFile; 200 201 pThis->pDvmFmtOps = NULL; 202 pThis->hVolMgrFmt = NIL_RTDVMFMT; 203 pThis->fFlags = fFlags; 204 pThis->cRefs = 1; 205 RTListInit(&pThis->VolumeList); 206 207 *phVolMgr = pThis; 208 return VINF_SUCCESS; 209 } 214 210 rc = VERR_NO_MEMORY; 215 211 } 212 RTVfsFileRelease(hVfsFile); 216 213 return rc; 217 214 } 215 218 216 219 217 RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr) … … 235 233 static void rtDvmDestroy(PRTDVMINTERNAL pThis) 236 234 { 235 pThis->u32Magic = RTDVM_MAGIC_DEAD; 236 237 237 if (pThis->hVolMgrFmt != NIL_RTDVMFMT) 238 238 { … … 242 242 pThis->pDvmFmtOps->pfnClose(pThis->hVolMgrFmt); 243 243 pThis->hVolMgrFmt = NIL_RTDVMFMT; 244 } 245 246 pThis->DvmDisk.cbDisk = 0; 247 pThis->DvmDisk.pvUser = NULL; 248 pThis->DvmDisk.pfnRead = NULL; 249 pThis->DvmDisk.pfnWrite = NULL; 250 pThis->u32Magic = RTDVM_MAGIC_DEAD; 244 pThis->pDvmFmtOps = NULL; 245 } 246 247 pThis->DvmDisk.cbDisk = 0; 248 pThis->DvmDisk.cbSector = 0; 249 if (pThis->DvmDisk.hVfsFile != NIL_RTVFSFILE) 250 { 251 RTVfsFileRelease(pThis->DvmDisk.hVfsFile); 252 pThis->DvmDisk.hVfsFile = NIL_RTVFSFILE; 253 } 251 254 RTMemFree(pThis); 252 255 } … … 269 272 RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr) 270 273 { 271 int rc = VINF_SUCCESS; 272 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED; 274 PRTDVMINTERNAL pThis = hVolMgr; 275 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 276 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE); 277 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER); 278 279 Assert(!pThis->pDvmFmtOps); 280 281 /* 282 * Let each format backend have a go at the disk, pick the one which scores the highest. 283 */ 284 int rc = VINF_SUCCESS; 285 uint32_t uScoreMax = RTDVM_MATCH_SCORE_UNSUPPORTED; 273 286 PCRTDVMFMTOPS pDvmFmtOpsMatch = NULL; 274 PRTDVMINTERNAL pThis = hVolMgr;275 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);276 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);277 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_INVALID_HANDLE);278 279 Assert(!pThis->pDvmFmtOps);280 281 287 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++) 282 288 { 283 uint32_t uScore ;289 uint32_t uScore = 0; 284 290 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i]; 285 291 286 292 rc = pDvmFmtOps->pfnProbe(&pThis->DvmDisk, &uScore); 287 if ( RT_SUCCESS(rc) 288 && uScore > uScoreMax) 293 if (RT_SUCCESS(rc)) 289 294 { 290 pDvmFmtOpsMatch = pDvmFmtOps; 291 uScoreMax = uScore; 292 } 293 else if (RT_FAILURE(rc)) 294 break; 295 } 296 297 if (RT_SUCCESS(rc)) 298 { 299 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED) 300 { 301 AssertPtr(pDvmFmtOpsMatch); 302 303 /* Open the format. */ 304 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt); 305 if (RT_SUCCESS(rc)) 295 if (uScore > uScoreMax) 306 296 { 307 uint32_t cVols; 308 309 pThis->pDvmFmtOps = pDvmFmtOpsMatch; 310 311 cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt); 312 313 /* Construct volume list. */ 314 if (cVols) 315 { 316 PRTDVMVOLUMEINTERNAL pVol = NULL; 317 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT; 318 319 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt); 320 if (RT_SUCCESS(rc)) 321 { 322 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 323 if (RT_FAILURE(rc)) 324 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 325 } 326 327 if (RT_SUCCESS(rc)) 328 { 329 cVols--; 330 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 331 332 while ( cVols > 0 333 && RT_SUCCESS(rc)) 334 { 335 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt); 336 if (RT_SUCCESS(rc)) 337 { 338 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 339 if (RT_FAILURE(rc)) 340 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 341 else 342 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 343 cVols--; 344 } 345 } 346 } 347 348 if (RT_FAILURE(rc)) 349 { 350 /* Remove all entries. */ 351 PRTDVMVOLUMEINTERNAL pItNext, pIt; 352 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode) 353 { 354 RTListNodeRemove(&pIt->VolumeNode); 355 rtDvmVolumeDestroy(pIt); 356 } 357 } 358 } 297 pDvmFmtOpsMatch = pDvmFmtOps; 298 uScoreMax = uScore; 359 299 } 360 300 } 361 301 else 362 rc = VERR_NOT_SUPPORTED; 363 } 364 302 return rc; 303 } 304 if (uScoreMax > RTDVM_MATCH_SCORE_UNSUPPORTED) 305 { 306 AssertPtr(pDvmFmtOpsMatch); 307 308 /* 309 * Open the format. 310 */ 311 rc = pDvmFmtOpsMatch->pfnOpen(&pThis->DvmDisk, &pThis->hVolMgrFmt); 312 if (RT_SUCCESS(rc)) 313 { 314 pThis->pDvmFmtOps = pDvmFmtOpsMatch; 315 316 /* 317 * Construct volume list (we're done if none). 318 */ 319 uint32_t cVols = pThis->pDvmFmtOps->pfnGetValidVolumes(pThis->hVolMgrFmt); 320 if (cVols == 0) 321 return VINF_SUCCESS; 322 323 /* First volume. */ 324 RTDVMVOLUMEFMT hVolFmt = NIL_RTDVMVOLUMEFMT; 325 rc = pThis->pDvmFmtOps->pfnQueryFirstVolume(pThis->hVolMgrFmt, &hVolFmt); 326 if (RT_SUCCESS(rc)) 327 { 328 for (;;) 329 { 330 PRTDVMVOLUMEINTERNAL pVol = NULL; 331 rc = rtDvmVolumeCreate(pThis, hVolFmt, &pVol); 332 if (RT_FAILURE(rc)) 333 { 334 pThis->pDvmFmtOps->pfnVolumeClose(hVolFmt); 335 break; 336 } 337 RTListAppend(&pThis->VolumeList, &pVol->VolumeNode); 338 339 /* Done?*/ 340 cVols--; 341 if (cVols < 1) 342 return VINF_SUCCESS; 343 344 /* Next volume. */ 345 rc = pThis->pDvmFmtOps->pfnQueryNextVolume(pThis->hVolMgrFmt, pVol->hVolFmt, &hVolFmt); 346 if (RT_FAILURE(rc)) 347 break; 348 } 349 350 /* Bail out. */ 351 PRTDVMVOLUMEINTERNAL pItNext, pIt; 352 RTListForEachSafe(&pThis->VolumeList, pIt, pItNext, RTDVMVOLUMEINTERNAL, VolumeNode) 353 { 354 RTListNodeRemove(&pIt->VolumeNode); 355 rtDvmVolumeDestroy(pIt); 356 } 357 } 358 359 /** @todo shouldn't we close the format too here? */ 360 } 361 } 362 else 363 rc = VERR_NOT_SUPPORTED; 365 364 return rc; 366 365 } … … 368 367 RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt) 369 368 { 370 int rc = VERR_NOT_SUPPORTED;371 369 PRTDVMINTERNAL pThis = hVolMgr; 372 370 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 373 371 AssertPtrReturn(pszFmt, VERR_INVALID_POINTER); 374 372 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE); 375 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_ INVALID_HANDLE);373 AssertReturn(pThis->hVolMgrFmt == NIL_RTDVMFMT, VERR_WRONG_ORDER); 376 374 377 375 for (unsigned i = 0; i < RT_ELEMENTS(g_aDvmFmts); i++) 378 376 { 379 377 PCRTDVMFMTOPS pDvmFmtOps = g_aDvmFmts[i]; 380 381 378 if (!RTStrCmp(pDvmFmtOps->pcszFmt, pszFmt)) 382 379 { 383 rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt);380 int rc = pDvmFmtOps->pfnInitialize(&pThis->DvmDisk, &pThis->hVolMgrFmt); 384 381 if (RT_SUCCESS(rc)) 385 382 pThis->pDvmFmtOps = pDvmFmtOps; 386 387 break; 383 return rc; 388 384 } 389 385 } 390 391 return rc; 386 return VERR_NOT_SUPPORTED; 392 387 } 393 388 … … 444 439 RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext) 445 440 { 446 int rc = VERR_DVM_MAP_NO_VOLUME;447 441 PRTDVMINTERNAL pThis = hVolMgr; 448 442 PRTDVMVOLUMEINTERNAL pVol = hVol; … … 454 448 AssertPtrReturn(phVolNext, VERR_INVALID_POINTER); 455 449 456 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol,457 450 int rc = VERR_DVM_MAP_NO_VOLUME; 451 PRTDVMVOLUMEINTERNAL pVolNext = RTListGetNext(&pThis->VolumeList, pVol, RTDVMVOLUMEINTERNAL, VolumeNode); 458 452 if (pVolNext) 459 453 { … … 466 460 } 467 461 468 RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, 469 bool *pfAllocated) 470 { 471 int rc = VINF_SUCCESS; 472 PRTDVMINTERNAL pThis = hVolMgr; 462 RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, bool *pfAllocated) 463 { 464 PRTDVMINTERNAL pThis = hVolMgr; 473 465 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 474 466 AssertPtrReturn(pfAllocated, VERR_INVALID_POINTER); 475 467 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE); 476 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE); 477 AssertReturn(off + cb <= pThis->DvmDisk.cbDisk * pThis->DvmDisk.cbSector, 478 VERR_INVALID_PARAMETER); 468 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_WRONG_ORDER); 469 AssertMsgReturn( off <= pThis->DvmDisk.cbDisk 470 || cb <= pThis->DvmDisk.cbDisk 471 || off + cb <= pThis->DvmDisk.cbDisk, 472 ("off=%#RX64 cb=%#RX64 cbDisk=%#RX64\n", off, cb, pThis->DvmDisk.cbDisk), 473 VERR_OUT_OF_RANGE); 479 474 480 475 /* Check whether the range is inuse by the volume manager metadata first. */ 481 rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated);476 int rc = pThis->pDvmFmtOps->pfnQueryRangeUse(pThis->hVolMgrFmt, off, cb, pfAllocated); 482 477 if (RT_FAILURE(rc)) 483 478 return rc; … … 513 508 { 514 509 bool fVolAllocated = true; 515 516 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, 517 &fVolAllocated); 510 rc = pVol->pfnQueryBlockStatus(pVol->pvUser, offVol, cbIntersect, &fVolAllocated); 518 511 if (RT_FAILURE(rc)) 519 512 break; 520 elseif (fVolAllocated)513 if (fVolAllocated) 521 514 { 522 515 fAllocated = true; … … 657 650 AssertReturn(enmVolType >= RTDVMVOLTYPE_INVALID && enmVolType < RTDVMVOLTYPE_END, NULL); 658 651 659 return g_apcszDvmVolTypes[enmVolType]; 660 } 652 return g_apszDvmVolTypes[enmVolType]; 653 } 654 -
trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp
r69111 r69609 415 415 if (pThis->DiskLabel.aPartitions[i].cSectors) 416 416 { 417 rc = rtDvmFmtBsdLblVolumeCreate(pThis, &pThis->DiskLabel.aPartitions[i], 418 i, phVolFmt); 417 rc = rtDvmFmtBsdLblVolumeCreate(pThis, &pThis->DiskLabel.aPartitions[i], i, phVolFmt); 419 418 break; 420 419 } -
trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp
r69111 r69609 48 48 * GPT on disk header. 49 49 */ 50 typedef struct GPTHDR 51 { 52 /** 0x00: Signature ("EFI PART"). */ 53 char abSignature[8]; 54 /** 0x08: Revision. */ 55 uint32_t u32Revision; 56 /** 0x0c: Header size. */ 57 uint32_t cbHeader; 58 /** 0x10: CRC of header. */ 59 uint32_t u32Crc; 60 } GPTHDR; 61 /** Pointer to a GPT header. */ 62 typedef struct GPTHDR *PGPTHDR; 63 AssertCompileSize(GPTHDR, 20); 64 65 /** 66 * Complete GPT table header for revision 1.0. 67 */ 50 68 #pragma pack(1) 51 typedef struct GptHdr 52 { 53 /** Signature ("EFI PART"). */ 54 char abSignature[8]; 55 /** Revision. */ 56 uint32_t u32Revision; 57 /** Header size. */ 58 uint32_t cbHeader; 59 /** CRC of header. */ 60 uint32_t u32Crc; 61 } GptHdr; 62 /** Pointer to a GPT header. */ 63 typedef struct GptHdr *PGptHdr; 69 typedef struct GPTHDRREV1 70 { 71 /** 0x00: Header. */ 72 GPTHDR Hdr; 73 /** 0x14: Reserved. */ 74 uint32_t u32Reserved; 75 /** 0x18: Current LBA. */ 76 uint64_t u64LbaCurrent; 77 /** 0x20: Backup LBA. */ 78 uint64_t u64LbaBackup; 79 /** 0x28:First usable LBA for partitions. */ 80 uint64_t u64LbaFirstPartition; 81 /** 0x30: Last usable LBA for partitions. */ 82 uint64_t u64LbaLastPartition; 83 /** 0x38: Disk UUID. */ 84 RTUUID DiskUuid; 85 /** 0x48: LBA of first partition entry. */ 86 uint64_t u64LbaPartitionEntries; 87 /** 0x50: Number of partition entries. */ 88 uint32_t cPartitionEntries; 89 /** 0x54: Partition entry size. */ 90 uint32_t cbPartitionEntry; 91 /** 0x58: CRC of partition entries. */ 92 uint32_t u32CrcPartitionEntries; 93 } GPTHDRREV1; 94 /** Pointer to a revision 1.0 GPT header. */ 95 typedef GPTHDRREV1 *PGPTHDRREV1; 64 96 #pragma pack() 65 AssertCompileSize(GptHdr, 20); 66 67 /** 68 * Complete GPT table header for revision 1.0. 69 */ 70 #pragma pack(1) 71 typedef struct GptHdrRev1 72 { 73 /** Header. */ 74 GptHdr Hdr; 75 /** Reserved. */ 76 uint32_t u32Reserved; 77 /** Current LBA. */ 78 uint64_t u64LbaCurrent; 79 /** Backup LBA. */ 80 uint64_t u64LbaBackup; 81 /** First usable LBA for partitions. */ 82 uint64_t u64LbaFirstPartition; 83 /** Last usable LBA for partitions. */ 84 uint64_t u64LbaLastPartition; 85 /** Disk UUID. */ 86 RTUUID DiskUuid; 87 /** LBA of first partition entry. */ 88 uint64_t u64LbaPartitionEntries; 89 /** Number of partition entries. */ 90 uint32_t cPartitionEntries; 91 /** Partition entry size. */ 92 uint32_t cbPartitionEntry; 93 /** CRC of partition entries. */ 94 uint32_t u32CrcPartitionEntries; 95 } GptHdrRev1; 96 /** Pointer to a revision 1.0 GPT header. */ 97 typedef GptHdrRev1 *PGptHdrRev1; 98 #pragma pack() 99 AssertCompileSize(GptHdrRev1, 92); 97 AssertCompileSize(GPTHDRREV1, 92); 100 98 101 99 /** 102 100 * GPT partition table entry. 103 101 */ 104 #pragma pack(1) 105 typedef struct GptEntry 106 { 107 /** Partition type UUID. */ 102 typedef struct GPTENTRY 103 { 104 /** 0x00: Partition type UUID. */ 108 105 RTUUID UuidType; 109 /** Partition UUID. */106 /** 0x10: Partition UUID. */ 110 107 RTUUID UuidPartition; 111 /** First LBA. */108 /** 0x20: First LBA. */ 112 109 uint64_t u64LbaFirst; 113 /** Last LBA. */110 /** 0x28: Last LBA. */ 114 111 uint64_t u64LbaLast; 115 /** Attribute flags. */112 /** 0x30: Attribute flags. */ 116 113 uint64_t u64Flags; 117 /** Partition name (UTF-16LE code units). */114 /** 0x38: Partition name (UTF-16LE code units). */ 118 115 RTUTF16 aPartitionName[36]; 119 } G ptEntry;116 } GPTENTRY; 120 117 /** Pointer to a GPT entry. */ 121 typedef struct GptEntry *PGptEntry; 122 #pragma pack() 123 AssertCompileSize(GptEntry, 128); 118 typedef struct GPTENTRY *PGPTENTRY; 119 AssertCompileSize(GPTENTRY, 128); 124 120 125 121 /** Partition flags - System partition. */ … … 140 136 PCRTDVMDISK pDisk; 141 137 /** GPT header. */ 142 G ptHdrRev1 HdrRev1;138 GPTHDRREV1 HdrRev1; 143 139 /** GPT array. */ 144 PG ptEntrypaGptEntries;140 PGPTENTRY paGptEntries; 145 141 /** Number of occupied partition entries. */ 146 142 uint32_t cPartitions; … … 163 159 uint64_t cbVolume; 164 160 /** Pointer to the GPT entry in the array. */ 165 PG ptEntrypGptEntry;161 PGPTENTRY pGptEntry; 166 162 } RTDVMVOLUMEFMTINTERNAL; 167 163 /** Pointer to an MBR volume. */ … … 232 228 { 233 229 int rc = VINF_SUCCESS; 234 G ptHdrHdr;230 GPTHDR Hdr; 235 231 236 232 *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED; … … 239 235 { 240 236 /* Read from the disk and check for the signature. */ 241 rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &Hdr, sizeof(G ptHdr));237 rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &Hdr, sizeof(GPTHDR)); 242 238 if ( RT_SUCCESS(rc) 243 239 && !strncmp(&Hdr.abSignature[0], RTDVM_GPT_SIGNATURE, RT_ELEMENTS(Hdr.abSignature)) 244 240 && RT_LE2H_U32(Hdr.u32Revision) == 0x00010000 245 && RT_LE2H_U32(Hdr.cbHeader) == sizeof(G ptHdrRev1))241 && RT_LE2H_U32(Hdr.cbHeader) == sizeof(GPTHDRREV1)) 246 242 *puScore = RTDVM_MATCH_SCORE_PERFECT; 247 243 } … … 278 274 pThis->HdrRev1.u32CrcPartitionEntries = RT_LE2H_U32(pThis->HdrRev1.u32CrcPartitionEntries); 279 275 280 if (pThis->HdrRev1.cbPartitionEntry == sizeof(G ptEntry))276 if (pThis->HdrRev1.cbPartitionEntry == sizeof(GPTENTRY)) 281 277 { 282 pThis->paGptEntries = (PG ptEntry)RTMemAllocZ(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry);278 pThis->paGptEntries = (PGPTENTRY)RTMemAllocZ(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry); 283 279 if (pThis->paGptEntries) 284 280 { … … 381 377 * @param phVolFmt Where to store the volume data on success. 382 378 */ 383 static int rtDvmFmtMbrVolumeCreate(PRTDVMFMTINTERNAL pThis, PG ptEntrypGptEntry,379 static int rtDvmFmtMbrVolumeCreate(PRTDVMFMTINTERNAL pThis, PGPTENTRY pGptEntry, 384 380 uint32_t idx, PRTDVMVOLUMEFMT phVolFmt) 385 381 { … … 405 401 static DECLCALLBACK(int) rtDvmFmtGptQueryFirstVolume(RTDVMFMT hVolMgrFmt, PRTDVMVOLUMEFMT phVolFmt) 406 402 { 407 int rc = VINF_SUCCESS;408 403 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 409 404 410 405 if (pThis->cPartitions != 0) 411 406 { 412 PG ptEntrypGptEntry = &pThis->paGptEntries[0];407 PGPTENTRY pGptEntry = &pThis->paGptEntries[0]; 413 408 414 409 /* Search for the first non empty entry. */ … … 416 411 { 417 412 if (!RTUuidIsNull(&pGptEntry->UuidType)) 418 { 419 rc = rtDvmFmtMbrVolumeCreate(pThis, pGptEntry, i, phVolFmt); 420 break; 421 } 413 return rtDvmFmtMbrVolumeCreate(pThis, pGptEntry, i, phVolFmt); 422 414 pGptEntry++; 423 415 } 416 AssertFailed(); 424 417 } 425 else 426 rc = VERR_DVM_MAP_EMPTY; 427 428 return rc; 418 return VERR_DVM_MAP_EMPTY; 429 419 } 430 420 431 421 static DECLCALLBACK(int) rtDvmFmtGptQueryNextVolume(RTDVMFMT hVolMgrFmt, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUMEFMT phVolFmtNext) 432 422 { 433 int rc = VERR_DVM_MAP_NO_VOLUME;434 423 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 435 424 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 436 PG ptEntrypGptEntry = pVol->pGptEntry + 1;425 PGPTENTRY pGptEntry = pVol->pGptEntry + 1; 437 426 438 427 for (unsigned i = pVol->idxEntry + 1; i < pThis->HdrRev1.cPartitionEntries; i++) 439 428 { 440 429 if (!RTUuidIsNull(&pGptEntry->UuidType)) 441 { 442 rc = rtDvmFmtMbrVolumeCreate(pThis, pGptEntry, i, phVolFmtNext); 443 break; 444 } 430 return rtDvmFmtMbrVolumeCreate(pThis, pGptEntry, i, phVolFmtNext); 445 431 pGptEntry++; 446 432 } 447 433 448 return rc;434 return VERR_DVM_MAP_NO_VOLUME; 449 435 } 450 436 … … 471 457 { 472 458 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 473 int rc = VINF_SUCCESS;474 459 475 460 *ppszVolName = NULL; 476 rc = RTUtf16ToUtf8Ex(&pVol->pGptEntry->aPartitionName[0], RT_ELEMENTS(pVol->pGptEntry->aPartitionName), 477 ppszVolName, 0, NULL); 478 479 return rc; 461 return RTUtf16ToUtf8Ex(&pVol->pGptEntry->aPartitionName[0], RT_ELEMENTS(pVol->pGptEntry->aPartitionName), 462 ppszVolName, 0, NULL); 480 463 } 481 464 482 465 static DECLCALLBACK(RTDVMVOLTYPE) rtDvmFmtGptVolumeGetType(RTDVMVOLUMEFMT hVolFmt) 483 466 { 484 RTDVMVOLTYPE enmVolType = RTDVMVOLTYPE_UNKNOWN;485 467 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 486 468 487 469 for (unsigned i = 0; i < RT_ELEMENTS(g_aPartType2DvmVolTypes); i++) 488 470 if (!RTUuidCompareStr(&pVol->pGptEntry->UuidType, g_aPartType2DvmVolTypes[i].pcszUuid)) 489 { 490 enmVolType = g_aPartType2DvmVolTypes[i].enmVolType; 491 break; 492 } 493 494 return enmVolType; 471 return g_aPartType2DvmVolTypes[i].enmVolType; 472 473 return RTDVMVOLTYPE_UNKNOWN; 495 474 } 496 475 … … 506 485 uint64_t *pcbIntersect) 507 486 { 508 bool fIntersect = false;509 487 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 510 488 511 489 if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart)) 512 490 { 513 fIntersect = true;514 491 *poffVol = offStart - pVol->offStart; 515 492 *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart); 493 return true; 516 494 } 517 518 return fIntersect; 495 return false; 519 496 } 520 497 -
trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp
r69111 r69609 29 29 * Header Files * 30 30 *********************************************************************************************************************************/ 31 #define LOG_GROUP RTLOGGROUP_FS /** @todo fix log group */ 31 32 #include <iprt/types.h> 32 33 #include <iprt/assert.h> … … 40 41 #include <iprt/vfslowlevel.h> 41 42 #include <iprt/poll.h> 43 #include <iprt/log.h> 42 44 #include "internal/dvm.h" 43 45 … … 59 61 /** Pointer to a the internal data of a DVM volume file. */ 60 62 typedef RTVFSDVMFILE *PRTVFSDVMFILE; 63 64 /** 65 * A volume manager VFS for use in chains (thing pseudo/devfs). 66 */ 67 typedef struct RTDVMVFSVOL 68 { 69 /** The volume manager. */ 70 RTDVM hVolMgr; 71 /** Whether to close it on success. */ 72 bool fCloseDvm; 73 /** Whether the access is read-only. */ 74 bool fReadOnly; 75 /** Number of volumes. */ 76 uint32_t cVolumes; 77 } RTDVMVFSVOL; 78 /** Poitner to a volume manager VFS. */ 79 typedef RTDVMVFSVOL *PRTDVMVFSVOL; 80 81 /** 82 * The volume manager VFS root dir data. 83 */ 84 typedef struct RTDVMVFSROOTDIR 85 { 86 /** Pointer to the VFS volume. */ 87 PRTDVMVFSVOL pVfsVol; 88 /** The current directory offset. */ 89 uint32_t offDir; 90 } RTDVMVFSROOTDIR; 91 /** Poitner to a volume manager VFS root dir. */ 92 typedef RTDVMVFSROOTDIR *PRTDVMVFSROOTDIR; 61 93 62 94 … … 413 445 } 414 446 447 448 449 450 /** 451 * @interface_method_impl{RTVFSOBJOPS::Obj,pfnClose} 452 */ 453 static DECLCALLBACK(int) rtDvmVfsVol_Close(void *pvThis) 454 { 455 PRTDVMVFSVOL pThis = (PRTDVMVFSVOL)pvThis; 456 LogFlow(("rtDvmVfsVol_Close(%p)\n", pThis)); 457 458 if ( pThis->fCloseDvm 459 && pThis->hVolMgr != NIL_RTDVM ) 460 RTDvmRelease(pThis->hVolMgr); 461 pThis->hVolMgr = NIL_RTDVM; 462 463 return VINF_SUCCESS; 464 } 465 466 467 /** 468 * @interface_method_impl{RTVFSOBJOPS::Obj,pfnQueryInfo} 469 */ 470 static DECLCALLBACK(int) rtDvmVfsVol_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 471 { 472 RT_NOREF(pvThis, pObjInfo, enmAddAttr); 473 return VERR_WRONG_TYPE; 474 } 475 476 477 /** 478 * @interface_method_impl{RTVFSOPS,pfnOpenRoot} 479 */ 480 static DECLCALLBACK(int) rtDvmVfsVol_OpenRoot(void *pvThis, PRTVFSDIR phVfsDir) 481 { 482 //PRTDVMVFSVOL pThis = (PRTDVMVFSVOL)pvThis; 483 484 //rtDvmDirShrd_Retain(pThis->pRootDir); /* consumed by the next call */ 485 //return rtDvmDir_NewWithShared(pThis, pThis->pRootDir, phVfsDir); 486 RT_NOREF(pvThis, phVfsDir); 487 return VERR_NOT_IMPLEMENTED; 488 } 489 490 491 /** 492 * @interface_method_impl{RTVFSOPS,pfnIsRangeInUse} 493 */ 494 static DECLCALLBACK(int) rtDvmVfsVol_IsRangeInUse(void *pvThis, RTFOFF off, size_t cb, bool *pfUsed) 495 { 496 RT_NOREF(pvThis, off, cb, pfUsed); 497 return VERR_NOT_IMPLEMENTED; 498 } 499 500 501 DECL_HIDDEN_CONST(const RTVFSOPS) g_rtDvmVfsVolOps = 502 { 503 { /* Obj */ 504 RTVFSOBJOPS_VERSION, 505 RTVFSOBJTYPE_VFS, 506 "DvmVol", 507 rtDvmVfsVol_Close, 508 rtDvmVfsVol_QueryInfo, 509 RTVFSOBJOPS_VERSION 510 }, 511 RTVFSOPS_VERSION, 512 0 /* fFeatures */, 513 rtDvmVfsVol_OpenRoot, 514 rtDvmVfsVol_IsRangeInUse, 515 RTVFSOPS_VERSION 516 }; 517 518 519 520 /** 521 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate} 522 */ 523 static DECLCALLBACK(int) rtDvmVfsChain_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec, 524 PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError, PRTERRINFO pErrInfo) 525 { 526 RT_NOREF(pProviderReg, pSpec); 527 528 /* 529 * Basic checks. 530 */ 531 if (pElement->enmTypeIn != RTVFSOBJTYPE_FILE) 532 return pElement->enmTypeIn == RTVFSOBJTYPE_INVALID ? VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT : VERR_VFS_CHAIN_TAKES_FILE; 533 if (pElement->enmType != RTVFSOBJTYPE_VFS) 534 return VERR_VFS_CHAIN_ONLY_VFS; 535 536 if (pElement->cArgs > 1) 537 return VERR_VFS_CHAIN_AT_MOST_ONE_ARG; 538 539 /* 540 * Parse the flag if present, save in pElement->uProvider. 541 */ 542 /** @todo allow specifying sector size */ 543 bool fReadOnly = (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ; 544 if (pElement->cArgs > 0) 545 { 546 const char *psz = pElement->paArgs[0].psz; 547 if (*psz) 548 { 549 if ( !strcmp(psz, "ro") 550 || !strcmp(psz, "r")) 551 fReadOnly = true; 552 else if (!strcmp(psz, "rw")) 553 fReadOnly = false; 554 else 555 { 556 *poffError = pElement->paArgs[0].offSpec; 557 return RTErrInfoSet(pErrInfo, VERR_VFS_CHAIN_INVALID_ARGUMENT, "Expected 'ro' or 'rw' as argument"); 558 } 559 } 560 } 561 562 pElement->uProvider = fReadOnly; 563 return VINF_SUCCESS; 564 } 565 566 567 /** 568 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate} 569 */ 570 static DECLCALLBACK(int) rtDvmVfsChain_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec, 571 PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj, 572 PRTVFSOBJ phVfsObj, uint32_t *poffError, PRTERRINFO pErrInfo) 573 { 574 RT_NOREF(pProviderReg, pSpec, poffError, pErrInfo); 575 AssertReturn(hPrevVfsObj != NIL_RTVFSOBJ, VERR_VFS_CHAIN_IPE); 576 577 /* 578 * Instantiate the volume manager and open the map stuff. 579 */ 580 RTVFSFILE hPrevVfsFile = RTVfsObjToFile(hPrevVfsObj); 581 AssertReturn(hPrevVfsFile != NIL_RTVFSFILE, VERR_VFS_CHAIN_CAST_FAILED); 582 583 RTDVM hVolMgr; 584 int rc = RTDvmCreate(&hVolMgr, hPrevVfsFile, 512, 0 /*fFlags*/); 585 RTVfsFileRelease(hPrevVfsFile); 586 if (RT_SUCCESS(rc)) 587 { 588 rc = RTDvmMapOpen(hVolMgr); 589 if (RT_SUCCESS(rc)) 590 { 591 /* 592 * Create a VFS instance for the volume manager. 593 */ 594 RTVFS hVfs = NIL_RTVFS; 595 PRTDVMVFSVOL pThis = NULL; 596 int rc = RTVfsNew(&g_rtDvmVfsVolOps, sizeof(RTDVMVFSVOL), NIL_RTVFS, RTVFSLOCK_CREATE_RW, &hVfs, (void **)&pThis); 597 if (RT_SUCCESS(rc)) 598 { 599 pThis->hVolMgr = hVolMgr; 600 pThis->fCloseDvm = true; 601 pThis->fReadOnly = pElement->uProvider == (uint64_t)true; 602 pThis->cVolumes = RTDvmMapGetValidVolumes(hVolMgr); 603 604 *phVfsObj = RTVfsObjFromVfs(hVfs); 605 RTVfsRelease(hVfs); 606 return *phVfsObj != NIL_RTVFSOBJ ? VINF_SUCCESS : VERR_VFS_CHAIN_CAST_FAILED; 607 } 608 } 609 else 610 rc = RTErrInfoSetF(pErrInfo, rc, "RTDvmMapOpen failed: %Rrc", rc); 611 RTDvmRelease(hVolMgr); 612 } 613 else 614 rc = RTErrInfoSetF(pErrInfo, rc, "RTDvmCreate failed: %Rrc", rc); 615 return rc; 616 } 617 618 619 /** 620 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement} 621 */ 622 static DECLCALLBACK(bool) rtDvmVfsChain_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg, 623 PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement, 624 PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement) 625 { 626 RT_NOREF(pProviderReg, pSpec, pElement, pReuseSpec, pReuseElement); 627 return false; 628 } 629 630 631 /** VFS chain element 'file'. */ 632 static RTVFSCHAINELEMENTREG g_rtVfsChainIsoFsVolReg = 633 { 634 /* uVersion = */ RTVFSCHAINELEMENTREG_VERSION, 635 /* fReserved = */ 0, 636 /* pszName = */ "dvm", 637 /* ListEntry = */ { NULL, NULL }, 638 /* pszHelp = */ "Opens a container image using the VD API.\n", 639 /* pfnValidate = */ rtDvmVfsChain_Validate, 640 /* pfnInstantiate = */ rtDvmVfsChain_Instantiate, 641 /* pfnCanReuseElement = */ rtDvmVfsChain_CanReuseElement, 642 /* uEndMarker = */ RTVFSCHAINELEMENTREG_VERSION 643 }; 644 645 RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainIsoFsVolReg, rtVfsChainIsoFsVolReg); 646
Note:
See TracChangeset
for help on using the changeset viewer.