VirtualBox

Changeset 41345 in vbox


Ignore:
Timestamp:
May 17, 2012 10:28:04 PM (12 years ago)
Author:
vboxsync
Message:

Storage/VHDX: Working readonly access (checksum verification disabled because CRC-32C is used instead of the standard CRC-32 implemented in IPRT)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/VHDX.cpp

    r41317 r41345  
    258258
    259259/**
     260 * VHDX BAT entry.
     261 */
     262#pragma pack(1)
     263typedef struct VhdxBatEntry
     264{
     265    /** The BAT entry, contains state and offset. */
     266    uint64_t    u64BatEntry;
     267} VhdxBatEntry;
     268#pragma pack()
     269typedef 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/**
    260298 * VHDX Metadata tabl header.
    261299 */
     
    312350#define VHDX_METADATA_TBL_ENTRY_ITEM_FILE_PARAMS    "caa16737-fa36-4d43-b3b6-33f0aa44e76b"
    313351/** Virtual disk size item UUID. */
    314 #define VHDX_METADATA_TBL_ENTRY_ITEM_VDISK_SIZE     "2fa54225-cd1b-4876-b211-5dbed83bf4b8"
     352#define VHDX_METADATA_TBL_ENTRY_ITEM_VDISK_SIZE     "2fa54224-cd1b-4876-b211-5dbed83bf4b8"
    315353/** Page 83 UUID. */
    316354#define VHDX_METADATA_TBL_ENTRY_ITEM_PAGE83_DATA    "beca12ab-b2e6-4523-93ef-c309e000c746"
     
    375413{
    376414    /** Logical sector size. */
    377     uint64_t    u64LogicalSectorSize;
     415    uint32_t    u32LogicalSectorSize;
    378416} VhdxVDiskLogicalSectorSize;
    379417#pragma pack()
     
    493531    /** Total size of the image. */
    494532    uint64_t             cbSize;
     533    /** Logical sector size of the image. */
     534    size_t               cbLogicalSector;
     535    /** Block size of the image. */
     536    size_t               cbBlock;
    495537    /** Physical geometry of this image. */
    496538    VDGEOMETRY           PCHSGeometry;
    497539    /** Logical geometry of this image. */
    498540    VDGEOMETRY           LCHSGeometry;
     541
     542    /** The BAT. */
     543    PVhdxBatEntry        paBat;
     544    /** Chunk ratio. */
     545    uint32_t             uChunkRatio;
    499546
    500547} VHDXIMAGE, *PVHDXIMAGE;
     
    539586    {VHDX_METADATA_TBL_ENTRY_ITEM_PAGE83_DATA,    false,   true,     true,        VHDXMETADATAITEM_PAGE83_DATA},
    540587    {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},
    542589    {VHDX_METADATA_TBL_ENTRY_ITEM_PARENT_LOCATOR, false,   false,    true,        VHDXMETADATAITEM_PARENT_LOCATOR}
    543590};
     
    731778
    732779/**
     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 */
     789DECLINLINE(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/**
    733797 * Converts a VHDX metadata table header between file and host endianness.
    734798 *
     
    832896                                                   PVhdxVDiskLogicalSectorSize pVDiskLogSectSize)
    833897{
    834     pVDiskLogSectSizeConv->u64LogicalSectorSize = SET_ENDIAN_U64(pVDiskLogSectSize->u64LogicalSectorSize);
     898    pVDiskLogSectSizeConv->u32LogicalSectorSize = SET_ENDIAN_U32(pVDiskLogSectSize->u32LogicalSectorSize);
    835899}
    836900
     
    904968            vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage);
    905969            pImage->pStorage = NULL;
     970        }
     971
     972        if (pImage->paBat)
     973        {
     974            RTMemFree(pImage->paBat);
     975            pImage->paBat = NULL;
    906976        }
    907977
     
    9851055        u32ChkSumSaved = Hdr1.u32Checksum;
    9861056        Hdr1.u32Checksum = 0;
    987         u32ChkSum = RTCrc32(&Hdr1, sizeof(Hdr1));
     1057        u32ChkSum = RTCrc32C(&Hdr1, sizeof(Hdr1));
    9881058
    9891059        if (   Hdr1.u32Signature == VHDX_HEADER_SIGNATURE
    990             && u32ChkSum == u32ChkSumSaved)
     1060            /*&& u32ChkSum == u32ChkSumSaved*/)
    9911061            fHdr1Valid = true;
    9921062    }
     
    10021072        u32ChkSumSaved = Hdr2.u32Checksum;
    10031073        Hdr2.u32Checksum = 0;
    1004         u32ChkSum = RTCrc32(&Hdr2, sizeof(Hdr2));
     1074        u32ChkSum = RTCrc32C(&Hdr2, sizeof(Hdr2));
    10051075
    10061076        if (   Hdr2.u32Signature == VHDX_HEADER_SIGNATURE
    1007             && u32ChkSum == u32ChkSumSaved)
     1077            /*&& u32ChkSum == u32ChkSumSaved*/)
    10081078            fHdr2Valid = true;
    10091079    }
     
    10181088    {
    10191089        /* 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,
    10211091                       "VHDX: Can not load the image because both headers are corrupt");
    10221092    }
     
    10461116{
    10471117    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;
    10481124
    10491125    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 */
     1223static 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 */
     1268static 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 */
     1307static 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    }
    10501334
    10511335    LogFlowFunc(("returns rc=%Rrc\n", rc));
     
    11491433                    case VHDXMETADATAITEM_FILE_PARAMS:
    11501434                    {
    1151                         //rc = vhdxLoadFileParametersMetadata(pImage, offMetadataItem, MetadataTblEntry.u32Length);
     1435                        rc = vhdxLoadFileParametersMetadata(pImage, offMetadataItem,
     1436                                                            MetadataTblEntry.u32Length);
    11521437                        break;
    11531438                    }
    11541439                    case VHDXMETADATAITEM_VDISK_SIZE:
    11551440                    {
    1156                         //rc = vhdxLoadVDiskSizeMetadata(pImage, offMetadataItem, MetadataTblEntry.u32Length);
     1441                        rc = vhdxLoadVDiskSizeMetadata(pImage, offMetadataItem,
     1442                                                       MetadataTblEntry.u32Length);
    11571443                        break;
    11581444                    }
     
    11681454                    case VHDXMETADATAITEM_LOGICAL_SECTOR_SIZE:
    11691455                    {
     1456                        rc = vhdxLoadVDiskLogSectorSizeMetadata(pImage, offMetadataItem,
     1457                                                                MetadataTblEntry.u32Length);
    11701458                        break;
    11711459                    }
     
    11811469                    case VHDXMETADATAITEM_PARENT_LOCATOR:
    11821470                    {
     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);
    11831474                        break;
    11841475                    }
     
    12451536
    12461537            /* Verify the region table integrity. */
    1247             u32ChkSum = RTCrc32(pbRegionTbl, VHDX_REGION_TBL_SIZE_MAX);
     1538            u32ChkSum = RTCrc32C(pbRegionTbl, VHDX_REGION_TBL_SIZE_MAX);
    12481539
    12491540            if (RegionTblHdr.u32Signature != VHDX_REGION_TBL_HDR_SIGNATURE)
     
    12511542                               "VHDX: Invalid signature for region table header of image \'%s\'",
    12521543                               pImage->pszFilename);
     1544#if 0
    12531545            else if (u32ChkSum != RegionTblHdr.u32Checksum)
    12541546                rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS,
    12551547                               "VHDX: CRC32 checksum mismatch for the region table of image \'%s\' (expected %#x got %#x)",
    12561548                               pImage->pszFilename, RegionTblHdr.u32Checksum, u32ChkSum);
     1549#endif
    12571550            else if (RegionTblHdr.u32EntryCount > VHDX_REGION_TBL_HDR_ENTRY_COUNT_MAX)
    12581551                rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS,
     
    12641557                /* Parse the region table entries. */
    12651558                PVhdxRegionTblEntry pRegTblEntry = (PVhdxRegionTblEntry)(pbRegionTbl + sizeof(VhdxRegionTblHdr));
     1559                VhdxRegionTblEntry RegTblEntryBat; /**<< BAT region table entry. */
     1560                bool fBatRegPresent = false;
    12661561
    12671562                for (unsigned i = 0; i < RegionTblHdr.u32EntryCount; i++)
     
    12721567                    if (!RTUuidCompareStr(&pRegTblEntry->UuidObject, VHDX_REGION_TBL_ENTRY_UUID_BAT))
    12731568                    {
     1569                        /*
     1570                         * Save the BAT region and process it later.
     1571                         * It may come before the metadata region but needs the block size.
     1572                         */
    12741573                        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                        }
    12761578                        else
    12771579                            rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS,
     
    13011603                    pRegTblEntry++;
    13021604                }
     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);
    13031612            }
    13041613        }
     
    13361645    AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
    13371646
     1647#if 0
    13381648    /* Refuse write access, it is not implemented so far. */
    13391649    if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY))
    13401650        return VERR_NOT_SUPPORTED;
     1651#endif
    13411652
    13421653    /*
     
    15521863    else
    15531864    {
    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
    15561897        if (pcbActuallyRead)
    15571898            *pcbActuallyRead = cbToRead;
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