Changeset 41345 in vbox
- Timestamp:
- May 17, 2012 10:28:04 PM (12 years ago)
- File:
-
- 1 edited
-
trunk/src/VBox/Storage/VHDX.cpp (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VHDX.cpp
r41317 r41345 258 258 259 259 /** 260 * VHDX BAT entry. 261 */ 262 #pragma pack(1) 263 typedef struct VhdxBatEntry 264 { 265 /** The BAT entry, contains state and offset. */ 266 uint64_t u64BatEntry; 267 } VhdxBatEntry; 268 #pragma pack() 269 typedef VhdxBatEntry *PVhdxBatEntry; 270 271 /** Return the BAT state from a given entry. */ 272 #define VHDX_BAT_ENTRY_GET_STATE(bat) ((bat) & UINT64_C(0x7)) 273 /** Get the FileOffsetMB field from a given BAT entry. */ 274 #define VHDX_BAT_ENTRY_GET_FILE_OFFSET_MB(bat) (((bat) & UINT64_C(0xfffffffffff00000)) >> 20) 275 /** Get a byte offset from the BAT entry. */ 276 #define VHDX_BAT_ENTRY_GET_FILE_OFFSET(bat) (VHDX_BAT_ENTRY_GET_FILE_OFFSET_MB(bat) * (uint64_t)_1M) 277 278 /** Block not present and the data is undefined. */ 279 #define VHDX_BAT_ENTRY_PAYLOAD_BLOCK_NOT_PRESENT (0) 280 /** Data in this block is undefined. */ 281 #define VHDX_BAT_ENTRY_PAYLOAD_BLOCK_UNDEFINED (1) 282 /** Data in this block contains zeros. */ 283 #define VHDX_BAT_ENTRY_PAYLOAD_BLOCK_ZERO (2) 284 /** Block was unmapped by the application or system and data is either zero or 285 * the data before the block was unmapped. */ 286 #define VHDX_BAT_ENTRY_PAYLOAD_BLOCK_UNMAPPED (3) 287 /** Block data is in the file pointed to by the FileOffsetMB field. */ 288 #define VHDX_BAT_ENTRY_PAYLOAD_BLOCK_FULLY_PRESENT (6) 289 /** Block is partially present, use sector bitmap to get present sectors. */ 290 #define VHDX_BAT_ENTRY_PAYLOAD_BLOCK_PARTIALLY_PRESENT (7) 291 292 /** The sector bitmap block is undefined and not allocated in the file. */ 293 #define VHDX_BAT_ENTRY_SB_BLOCK_NOT_PRESENT (0) 294 /** The sector bitmap block is defined at the file location. */ 295 #define VHDX_BAT_ENTRY_SB_BLOCK_PRESENT (6) 296 297 /** 260 298 * VHDX Metadata tabl header. 261 299 */ … … 312 350 #define VHDX_METADATA_TBL_ENTRY_ITEM_FILE_PARAMS "caa16737-fa36-4d43-b3b6-33f0aa44e76b" 313 351 /** Virtual disk size item UUID. */ 314 #define VHDX_METADATA_TBL_ENTRY_ITEM_VDISK_SIZE "2fa5422 5-cd1b-4876-b211-5dbed83bf4b8"352 #define VHDX_METADATA_TBL_ENTRY_ITEM_VDISK_SIZE "2fa54224-cd1b-4876-b211-5dbed83bf4b8" 315 353 /** Page 83 UUID. */ 316 354 #define VHDX_METADATA_TBL_ENTRY_ITEM_PAGE83_DATA "beca12ab-b2e6-4523-93ef-c309e000c746" … … 375 413 { 376 414 /** Logical sector size. */ 377 uint 64_t u64LogicalSectorSize;415 uint32_t u32LogicalSectorSize; 378 416 } VhdxVDiskLogicalSectorSize; 379 417 #pragma pack() … … 493 531 /** Total size of the image. */ 494 532 uint64_t cbSize; 533 /** Logical sector size of the image. */ 534 size_t cbLogicalSector; 535 /** Block size of the image. */ 536 size_t cbBlock; 495 537 /** Physical geometry of this image. */ 496 538 VDGEOMETRY PCHSGeometry; 497 539 /** Logical geometry of this image. */ 498 540 VDGEOMETRY LCHSGeometry; 541 542 /** The BAT. */ 543 PVhdxBatEntry paBat; 544 /** Chunk ratio. */ 545 uint32_t uChunkRatio; 499 546 500 547 } VHDXIMAGE, *PVHDXIMAGE; … … 539 586 {VHDX_METADATA_TBL_ENTRY_ITEM_PAGE83_DATA, false, true, true, VHDXMETADATAITEM_PAGE83_DATA}, 540 587 {VHDX_METADATA_TBL_ENTRY_ITEM_LOG_SECT_SIZE, false, true, true, VHDXMETADATAITEM_LOGICAL_SECTOR_SIZE}, 541 {VHDX_METADATA_TBL_ENTRY_ITEM_PHYS_SECT_SIZE, false, true, true,VHDXMETADATAITEM_PHYSICAL_SECTOR_SIZE},588 {VHDX_METADATA_TBL_ENTRY_ITEM_PHYS_SECT_SIZE, false, true, false, VHDXMETADATAITEM_PHYSICAL_SECTOR_SIZE}, 542 589 {VHDX_METADATA_TBL_ENTRY_ITEM_PARENT_LOCATOR, false, false, true, VHDXMETADATAITEM_PARENT_LOCATOR} 543 590 }; … … 731 778 732 779 /** 780 * Converts a BAT between file and host endianess. 781 * 782 * @returns nothing. 783 * @param enmConv Direction of the conversion. 784 * @param paBatEntriesConv Where to store the converted BAT. 785 * @param paBatEntries The VHDX BAT to convert. 786 * 787 * @note It is safe to use the same pointer for paBatEntriesConv and paBatEntries. 788 */ 789 DECLINLINE(void) vhdxConvBatTableEndianess(VHDXECONV enmConv, PVhdxBatEntry paBatEntriesConv, 790 PVhdxBatEntry paBatEntries, uint32_t cBatEntries) 791 { 792 for (uint32_t i = 0; i < cBatEntries; i++) 793 paBatEntriesConv[i].u64BatEntry = SET_ENDIAN_U64(paBatEntries[i].u64BatEntry); 794 } 795 796 /** 733 797 * Converts a VHDX metadata table header between file and host endianness. 734 798 * … … 832 896 PVhdxVDiskLogicalSectorSize pVDiskLogSectSize) 833 897 { 834 pVDiskLogSectSizeConv->u 64LogicalSectorSize = SET_ENDIAN_U64(pVDiskLogSectSize->u64LogicalSectorSize);898 pVDiskLogSectSizeConv->u32LogicalSectorSize = SET_ENDIAN_U32(pVDiskLogSectSize->u32LogicalSectorSize); 835 899 } 836 900 … … 904 968 vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage); 905 969 pImage->pStorage = NULL; 970 } 971 972 if (pImage->paBat) 973 { 974 RTMemFree(pImage->paBat); 975 pImage->paBat = NULL; 906 976 } 907 977 … … 985 1055 u32ChkSumSaved = Hdr1.u32Checksum; 986 1056 Hdr1.u32Checksum = 0; 987 u32ChkSum = RTCrc32 (&Hdr1, sizeof(Hdr1));1057 u32ChkSum = RTCrc32C(&Hdr1, sizeof(Hdr1)); 988 1058 989 1059 if ( Hdr1.u32Signature == VHDX_HEADER_SIGNATURE 990 && u32ChkSum == u32ChkSumSaved)1060 /*&& u32ChkSum == u32ChkSumSaved*/) 991 1061 fHdr1Valid = true; 992 1062 } … … 1002 1072 u32ChkSumSaved = Hdr2.u32Checksum; 1003 1073 Hdr2.u32Checksum = 0; 1004 u32ChkSum = RTCrc32 (&Hdr2, sizeof(Hdr2));1074 u32ChkSum = RTCrc32C(&Hdr2, sizeof(Hdr2)); 1005 1075 1006 1076 if ( Hdr2.u32Signature == VHDX_HEADER_SIGNATURE 1007 && u32ChkSum == u32ChkSumSaved)1077 /*&& u32ChkSum == u32ChkSumSaved*/) 1008 1078 fHdr2Valid = true; 1009 1079 } … … 1018 1088 { 1019 1089 /* Crap, both headers are corrupt, refuse to load the image. */ 1020 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS,1090 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1021 1091 "VHDX: Can not load the image because both headers are corrupt"); 1022 1092 } … … 1046 1116 { 1047 1117 int rc = VINF_SUCCESS; 1118 uint32_t cDataBlocks; 1119 uint32_t uChunkRatio; 1120 uint32_t cSectorBitmapBlocks; 1121 uint32_t cBatEntries; 1122 uint32_t cbBatEntries; 1123 PVhdxBatEntry paBatEntries = NULL; 1048 1124 1049 1125 LogFlowFunc(("pImage=%#p\n", pImage)); 1126 1127 /** Calculate required values first. */ 1128 uChunkRatio = (RT_BIT_32(23) * pImage->cbLogicalSector) / pImage->cbBlock; 1129 cDataBlocks = pImage->cbSize / pImage->cbBlock; 1130 if (pImage->cbSize % pImage->cbBlock) 1131 cDataBlocks++; 1132 1133 cSectorBitmapBlocks = cDataBlocks / uChunkRatio; 1134 if (cDataBlocks % uChunkRatio) 1135 cSectorBitmapBlocks++; 1136 1137 cBatEntries = cDataBlocks + (cDataBlocks - 1)/uChunkRatio; 1138 cbBatEntries = cBatEntries * sizeof(VhdxBatEntry); 1139 1140 if (cbBatEntries <= cbRegion) 1141 { 1142 /* 1143 * Load the complete BAT region first, convert to host endianess and process 1144 * it afterwards. The SB entries can be removed because they are not needed yet. 1145 */ 1146 paBatEntries = (PVhdxBatEntry)RTMemAlloc(cbBatEntries); 1147 if (paBatEntries) 1148 { 1149 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offRegion, 1150 paBatEntries, cbBatEntries, NULL); 1151 if (RT_SUCCESS(rc)) 1152 { 1153 vhdxConvBatTableEndianess(VHDXECONV_F2H, paBatEntries, paBatEntries, 1154 cBatEntries); 1155 1156 /* Go through the table and validate it. */ 1157 for (unsigned i = 0; i < cBatEntries; i++) 1158 { 1159 if ( i != 0 1160 && (i % uChunkRatio) == 0) 1161 { 1162 /* Sector bitmap block. */ 1163 if ( VHDX_BAT_ENTRY_GET_STATE(paBatEntries[i].u64BatEntry) 1164 != VHDX_BAT_ENTRY_SB_BLOCK_NOT_PRESENT) 1165 { 1166 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1167 "VHDX: Sector bitmap block at entry %u of image \'%s\' marked as present, violation of the specification", 1168 i, pImage->pszFilename); 1169 break; 1170 } 1171 } 1172 else 1173 { 1174 /* Payload block. */ 1175 if ( VHDX_BAT_ENTRY_GET_STATE(paBatEntries[i].u64BatEntry) 1176 == VHDX_BAT_ENTRY_PAYLOAD_BLOCK_PARTIALLY_PRESENT) 1177 { 1178 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1179 "VHDX: Payload block at entry %u of image \'%s\' marked as partially present, violation of the specification", 1180 i, pImage->pszFilename); 1181 break; 1182 } 1183 } 1184 } 1185 1186 if (RT_SUCCESS(rc)) 1187 { 1188 pImage->paBat = paBatEntries; 1189 pImage->uChunkRatio = uChunkRatio; 1190 } 1191 } 1192 else 1193 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1194 "VHDX: Error reading the BAT from image \'%s\'", 1195 pImage->pszFilename); 1196 } 1197 else 1198 rc = vdIfError(pImage->pIfError, VERR_NO_MEMORY, RT_SRC_POS, 1199 "VHDX: Out of memory allocating memory for %u BAT entries of image \'%s\'", 1200 cBatEntries); 1201 } 1202 else 1203 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1204 "VHDX: Mismatch between calculated number of BAT entries and region size (expected %u got %u) for image \'%s\'", 1205 cbBatEntries, cbRegion, pImage->pszFilename); 1206 1207 if ( RT_FAILURE(rc) 1208 && paBatEntries) 1209 RTMemFree(paBatEntries); 1210 1211 LogFlowFunc(("returns rc=%Rrc\n", rc)); 1212 return rc; 1213 } 1214 1215 /** 1216 * Load the file parameters metadata item from the file. 1217 * 1218 * @returns VBox status code. 1219 * @param pImage Image instance data. 1220 * @param offItem File offset where the data is stored. 1221 * @param cbItem Size of the item in the file. 1222 */ 1223 static int vhdxLoadFileParametersMetadata(PVHDXIMAGE pImage, uint64_t offItem, size_t cbItem) 1224 { 1225 int rc = VINF_SUCCESS; 1226 1227 LogFlowFunc(("pImage=%#p offItem=%llu cbItem=%zu\n", pImage, offItem, cbItem)); 1228 1229 if (cbItem != sizeof(VhdxFileParameters)) 1230 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1231 "VHDX: File parameters item size mismatch (expected %u got %zu) in image \'%s\'", 1232 sizeof(VhdxFileParameters), cbItem, pImage->pszFilename); 1233 else 1234 { 1235 VhdxFileParameters FileParameters; 1236 1237 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offItem, 1238 &FileParameters, sizeof(FileParameters), NULL); 1239 if (RT_SUCCESS(rc)) 1240 { 1241 vhdxConvFileParamsEndianess(VHDXECONV_F2H, &FileParameters, &FileParameters); 1242 pImage->cbBlock = FileParameters.u32BlockSize; 1243 1244 /* @todo: No support for differencing images yet. */ 1245 if (FileParameters.u32Flags & VHDX_FILE_PARAMETERS_FLAGS_HAS_PARENT) 1246 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1247 "VHDX: Image \'%s\' is a differencing image which is not supported yet", 1248 pImage->pszFilename); 1249 } 1250 else 1251 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1252 "VHDX: Reading the file parameters metadata item from image \'%s\' failed", 1253 pImage->pszFilename); 1254 } 1255 1256 LogFlowFunc(("returns rc=%Rrc\n", rc)); 1257 return rc; 1258 } 1259 1260 /** 1261 * Load the virtual disk size metadata item from the file. 1262 * 1263 * @returns VBox status code. 1264 * @param pImage Image instance data. 1265 * @param offItem File offset where the data is stored. 1266 * @param cbItem Size of the item in the file. 1267 */ 1268 static int vhdxLoadVDiskSizeMetadata(PVHDXIMAGE pImage, uint64_t offItem, size_t cbItem) 1269 { 1270 int rc = VINF_SUCCESS; 1271 1272 LogFlowFunc(("pImage=%#p offItem=%llu cbItem=%zu\n", pImage, offItem, cbItem)); 1273 1274 if (cbItem != sizeof(VhdxVDiskSize)) 1275 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1276 "VHDX: Virtual disk size item size mismatch (expected %u got %zu) in image \'%s\'", 1277 sizeof(VhdxVDiskSize), cbItem, pImage->pszFilename); 1278 else 1279 { 1280 VhdxVDiskSize VDiskSize; 1281 1282 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offItem, 1283 &VDiskSize, sizeof(VDiskSize), NULL); 1284 if (RT_SUCCESS(rc)) 1285 { 1286 vhdxConvVDiskSizeEndianess(VHDXECONV_F2H, &VDiskSize, &VDiskSize); 1287 pImage->cbSize = VDiskSize.u64VDiskSize; 1288 } 1289 else 1290 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1291 "VHDX: Reading the virtual disk size metadata item from image \'%s\' failed", 1292 pImage->pszFilename); 1293 } 1294 1295 LogFlowFunc(("returns rc=%Rrc\n", rc)); 1296 return rc; 1297 } 1298 1299 /** 1300 * Load the logical sector size metadata item from the file. 1301 * 1302 * @returns VBox status code. 1303 * @param pImage Image instance data. 1304 * @param offItem File offset where the data is stored. 1305 * @param cbItem Size of the item in the file. 1306 */ 1307 static int vhdxLoadVDiskLogSectorSizeMetadata(PVHDXIMAGE pImage, uint64_t offItem, size_t cbItem) 1308 { 1309 int rc = VINF_SUCCESS; 1310 1311 LogFlowFunc(("pImage=%#p offItem=%llu cbItem=%zu\n", pImage, offItem, cbItem)); 1312 1313 if (cbItem != sizeof(VhdxVDiskLogicalSectorSize)) 1314 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1315 "VHDX: Virtual disk logical sector size item size mismatch (expected %u got %zu) in image \'%s\'", 1316 sizeof(VhdxVDiskLogicalSectorSize), cbItem, pImage->pszFilename); 1317 else 1318 { 1319 VhdxVDiskLogicalSectorSize VDiskLogSectSize; 1320 1321 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offItem, 1322 &VDiskLogSectSize, sizeof(VDiskLogSectSize), NULL); 1323 if (RT_SUCCESS(rc)) 1324 { 1325 vhdxConvVDiskLogSectSizeEndianess(VHDXECONV_F2H, &VDiskLogSectSize, 1326 &VDiskLogSectSize); 1327 pImage->cbLogicalSector = VDiskLogSectSize.u32LogicalSectorSize; 1328 } 1329 else 1330 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, 1331 "VHDX: Reading the virtual disk logical sector size metadata item from image \'%s\' failed", 1332 pImage->pszFilename); 1333 } 1050 1334 1051 1335 LogFlowFunc(("returns rc=%Rrc\n", rc)); … … 1149 1433 case VHDXMETADATAITEM_FILE_PARAMS: 1150 1434 { 1151 //rc = vhdxLoadFileParametersMetadata(pImage, offMetadataItem, MetadataTblEntry.u32Length); 1435 rc = vhdxLoadFileParametersMetadata(pImage, offMetadataItem, 1436 MetadataTblEntry.u32Length); 1152 1437 break; 1153 1438 } 1154 1439 case VHDXMETADATAITEM_VDISK_SIZE: 1155 1440 { 1156 //rc = vhdxLoadVDiskSizeMetadata(pImage, offMetadataItem, MetadataTblEntry.u32Length); 1441 rc = vhdxLoadVDiskSizeMetadata(pImage, offMetadataItem, 1442 MetadataTblEntry.u32Length); 1157 1443 break; 1158 1444 } … … 1168 1454 case VHDXMETADATAITEM_LOGICAL_SECTOR_SIZE: 1169 1455 { 1456 rc = vhdxLoadVDiskLogSectorSizeMetadata(pImage, offMetadataItem, 1457 MetadataTblEntry.u32Length); 1170 1458 break; 1171 1459 } … … 1181 1469 case VHDXMETADATAITEM_PARENT_LOCATOR: 1182 1470 { 1471 rc = vdIfError(pImage->pIfError, VERR_NOT_SUPPORTED, RT_SRC_POS, 1472 "VHDX: Image \'%s\' is a differencing image which is not supported yet", 1473 pImage->pszFilename); 1183 1474 break; 1184 1475 } … … 1245 1536 1246 1537 /* Verify the region table integrity. */ 1247 u32ChkSum = RTCrc32 (pbRegionTbl, VHDX_REGION_TBL_SIZE_MAX);1538 u32ChkSum = RTCrc32C(pbRegionTbl, VHDX_REGION_TBL_SIZE_MAX); 1248 1539 1249 1540 if (RegionTblHdr.u32Signature != VHDX_REGION_TBL_HDR_SIGNATURE) … … 1251 1542 "VHDX: Invalid signature for region table header of image \'%s\'", 1252 1543 pImage->pszFilename); 1544 #if 0 1253 1545 else if (u32ChkSum != RegionTblHdr.u32Checksum) 1254 1546 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1255 1547 "VHDX: CRC32 checksum mismatch for the region table of image \'%s\' (expected %#x got %#x)", 1256 1548 pImage->pszFilename, RegionTblHdr.u32Checksum, u32ChkSum); 1549 #endif 1257 1550 else if (RegionTblHdr.u32EntryCount > VHDX_REGION_TBL_HDR_ENTRY_COUNT_MAX) 1258 1551 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, … … 1264 1557 /* Parse the region table entries. */ 1265 1558 PVhdxRegionTblEntry pRegTblEntry = (PVhdxRegionTblEntry)(pbRegionTbl + sizeof(VhdxRegionTblHdr)); 1559 VhdxRegionTblEntry RegTblEntryBat; /**<< BAT region table entry. */ 1560 bool fBatRegPresent = false; 1266 1561 1267 1562 for (unsigned i = 0; i < RegionTblHdr.u32EntryCount; i++) … … 1272 1567 if (!RTUuidCompareStr(&pRegTblEntry->UuidObject, VHDX_REGION_TBL_ENTRY_UUID_BAT)) 1273 1568 { 1569 /* 1570 * Save the BAT region and process it later. 1571 * It may come before the metadata region but needs the block size. 1572 */ 1274 1573 if (pRegTblEntry->u32Flags & VHDX_REGION_TBL_ENTRY_FLAGS_IS_REQUIRED) 1275 rc = vhdxLoadBatRegion(pImage, pRegTblEntry->u64FileOffset, pRegTblEntry->u32Length); 1574 { 1575 fBatRegPresent = true; 1576 RegTblEntryBat = *pRegTblEntry; 1577 } 1276 1578 else 1277 1579 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, … … 1301 1603 pRegTblEntry++; 1302 1604 } 1605 1606 if (fBatRegPresent) 1607 rc = vhdxLoadBatRegion(pImage, RegTblEntryBat.u64FileOffset, RegTblEntryBat.u32Length); 1608 else 1609 rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS, 1610 "VHDX: BAT region in image \'%s\' is missing", 1611 pImage->pszFilename); 1303 1612 } 1304 1613 } … … 1336 1645 AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER); 1337 1646 1647 #if 0 1338 1648 /* Refuse write access, it is not implemented so far. */ 1339 1649 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1340 1650 return VERR_NOT_SUPPORTED; 1651 #endif 1341 1652 1342 1653 /* … … 1552 1863 else 1553 1864 { 1554 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, 1555 cbToRead, NULL); 1865 uint32_t idxBat = uOffset / pImage->cbBlock; 1866 uint32_t offRead = uOffset % pImage->cbBlock; 1867 uint64_t uBatEntry; 1868 1869 idxBat += idxBat / pImage->uChunkRatio; /* Add interleaving sector bitmap entries. */ 1870 uBatEntry = pImage->paBat[idxBat].u64BatEntry; 1871 1872 cbToRead = RT_MIN(cbToRead, pImage->cbBlock - offRead); 1873 1874 switch (VHDX_BAT_ENTRY_GET_STATE(uBatEntry)) 1875 { 1876 case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_NOT_PRESENT: 1877 case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_UNDEFINED: 1878 case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_ZERO: 1879 case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_UNMAPPED: 1880 { 1881 memset(pvBuf, 0, cbToRead); 1882 break; 1883 } 1884 case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_FULLY_PRESENT: 1885 { 1886 uint64_t offFile = VHDX_BAT_ENTRY_GET_FILE_OFFSET(uBatEntry) + offRead; 1887 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offFile, 1888 pvBuf, cbToRead, NULL); 1889 break; 1890 } 1891 case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_PARTIALLY_PRESENT: 1892 default: 1893 rc = VERR_INVALID_PARAMETER; 1894 break; 1895 } 1896 1556 1897 if (pcbActuallyRead) 1557 1898 *pcbActuallyRead = cbToRead;
Note:
See TracChangeset
for help on using the changeset viewer.

