VirtualBox

Changeset 69910 in vbox for trunk/src/VBox/Runtime/common/fs


Ignore:
Timestamp:
Dec 3, 2017 5:06:56 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119388
Message:

IPRT/ntfsvfs.cpp: More on the subject of directories (indexes).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp

    r69903 r69910  
    265265    /** The MFT record size. */
    266266    uint32_t        cbMftRecord;
    267     /** The index record size. */
    268     uint32_t        cbIndexRecord;
     267    /** The default index (B-tree) node size. */
     268    uint32_t        cbDefaultIndexNode;
    269269
    270270    /** The volume serial number. */
     
    306306*********************************************************************************************************************************/
    307307static uint32_t rtFsNtfsCore_Release(PRTFSNTFSCORE pThis);
     308#ifdef LOG_ENABLED
     309static void     rtFsNtfsVol_LogIndexRoot(PCNTFSATINDEXROOT pIdxRoot, uint32_t cbIdxRoot);
     310#endif
    308311
    309312
     
    580583                            //case NTFS_AT_VOLUME_INFORMATION:
    581584                            //case NTFS_AT_DATA:
    582                             //case NTFS_AT_INDEX_ROOT:
     585
     586                            case NTFS_AT_INDEX_ROOT:
     587                                rtFsNtfsVol_LogIndexRoot((PCNTFSATINDEXROOT)pbValue, cbValue);
     588                                break;
     589
    583590                            //case NTFS_AT_INDEX_ALLOCATION:
    584591                            //case NTFS_AT_BITMAP:
     
    637644                        uint32_t const cbMaxPairs = cbAttrib - offMappingPairs;
    638645                        int64_t iVnc = pHdr->u.NonRes.iVcnFirst;
    639                         Log2(("NTFS:     Mapping Pairs: %.*Rhxsd\n", cbMaxPairs, pbPairs));
     646                        if (cbMaxPairs < 48)
     647                            Log2(("NTFS:     Mapping Pairs: cbMaxPairs=%#x %.*Rhxs\n", cbMaxPairs, cbMaxPairs, pbPairs));
     648                        else
     649                            Log2(("NTFS:     Mapping Pairs: cbMaxPairs=%#x\n%.*Rhxd\n", cbMaxPairs, cbMaxPairs, pbPairs));
    640650                        if (!iVnc && !*pbPairs)
    641651                            Log2(("NTFS:         [0]: Empty\n"));
     
    643653                        {
    644654                            if (iVnc != 0)
    645                                 Log2(("NTFS:         [0]: VCN=%#012RX64 L %#012RX64 - not mapped\n", 0, iVnc));
     655                                Log2(("NTFS:         [00/0x000]: VCN=%#012RX64 L %#012RX64 - not mapped\n", 0, iVnc));
    646656                            int64_t  iLnc     = 0;
    647657                            uint32_t iPair    = 0;
     
    656666                                if (offPairs + cbRun > cbMaxPairs)
    657667                                {
    658                                     Log2(("NTFS:         [%d]: run overrun! cbRun=%#x bLengths=%#x offPairs=%#x cbMaxPairs=%#x\n",
    659                                           iPair, cbRun, bLengths, offPairs, cbMaxPairs));
     668                                    Log2(("NTFS:         [%02d/%#05x]: run overrun! cbRun=%#x bLengths=%#x offPairs=%#x cbMaxPairs=%#x\n",
     669                                          iPair, offPairs, cbRun, bLengths, offPairs, cbMaxPairs));
    660670                                    break;
    661671                                }
     672                                //Log2(("NTFS:         @%#05x: %.*Rhxs\n", offPairs, cbRun + 1, &pbPairs[offPairs]));
    662673
    663674                                /* Value 1: Number of (virtual) clusters in this run. */
     
    683694                                        cLcnDelta = (cLcnDelta << 8) + *pbNum--;
    684695                                    iLnc += cLcnDelta;
    685                                     Log2(("NTFS:         [%d]: VNC=%#012RX64 L %#012RX64 => LNC=%#012RX64\n",
    686                                           iPair, iVnc, cClustersInRun, iLnc));
     696                                    Log2(("NTFS:         [%02d/%#05x]: VNC=%#012RX64 L %#012RX64 => LNC=%#012RX64\n",
     697                                          iPair, offPairs, iVnc, cClustersInRun, iLnc));
    687698                                }
    688699                                else
    689                                     Log2(("NTFS:         [%d]: VNC=%#012RX64 L %#012RX64 => HOLE\n",
    690                                           iPair, iVnc, cClustersInRun));
     700                                    Log2(("NTFS:         [%02d/%#05x]: VNC=%#012RX64 L %#012RX64 => HOLE\n",
     701                                          iPair, offPairs, iVnc, cClustersInRun));
    691702
    692703                                /* Advance. */
     
    12401251                    {
    12411252                        rc = RTVfsFileReadAt(pVol->hVfsBacking, pTable->paExtents[iExtent].off + off, pvBuf, cbThisRead, NULL);
     1253                        Log4(("NTFS: Volume read: @%#RX64 LB %#zx -> %Rrc\n", pTable->paExtents[iExtent].off + off, cbThisRead, rc));
    12421254                        if (RT_FAILURE(rc))
    12431255                            break;
     
    12841296
    12851297/**
     1298 *
     1299 * @returns
     1300 * @param   pRecHdr             .
     1301 * @param   cbRec               .
     1302 * @param   fRelaxedUsa         .
     1303 * @param   pErrInfo            .
     1304 *
     1305 * @see https://msdn.microsoft.com/en-us/library/bb470212%28v=vs.85%29.aspx
     1306 */
     1307static int rtFsNtfsRec_DoMultiSectorFixups(PNTFSRECHDR pRecHdr, uint32_t cbRec, bool fRelaxedUsa, PRTERRINFO pErrInfo)
     1308{
     1309    /*
     1310     * Do sanity checking.
     1311     */
     1312    uint16_t offUpdateSeqArray = RT_LE2H_U16(pRecHdr->offUpdateSeqArray);
     1313    uint16_t cUpdateSeqEntries = RT_LE2H_U16(pRecHdr->cUpdateSeqEntries);
     1314    if (   !(cbRec & (NTFS_MULTI_SECTOR_STRIDE - 1))
     1315        && !(offUpdateSeqArray & 1) /* two byte aligned */
     1316        && cUpdateSeqEntries == 1 + cbRec / NTFS_MULTI_SECTOR_STRIDE
     1317        && offUpdateSeqArray + (uint32_t)cUpdateSeqEntries * 2U < NTFS_MULTI_SECTOR_STRIDE - 2U)
     1318    {
     1319        uint16_t const *pauUsa = (uint16_t const *)((uint8_t *)pRecHdr + offUpdateSeqArray);
     1320
     1321        /*
     1322         * The first update seqence array entry is the value stored at
     1323         * the fixup locations at the end of the blocks.  We read this
     1324         * and check each of the blocks.
     1325         */
     1326        uint16_t const uCheck = *pauUsa++;
     1327        cUpdateSeqEntries--;
     1328        for (uint16_t iBlock = 0; iBlock < cUpdateSeqEntries; iBlock++)
     1329        {
     1330            uint16_t const *puBlockCheck = (uint16_t const *)((uint8_t *)pRecHdr + (iBlock + 1) * NTFS_MULTI_SECTOR_STRIDE - 2U);
     1331            if (*puBlockCheck == uCheck)
     1332            { /* likely */ }
     1333            else if (!fRelaxedUsa)
     1334                return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_OFFSET,
     1335                                               "Multisector transfer error: block #%u ends with %#x instead of %#x (fixup: %#x)",
     1336                                               iBlock, RT_LE2H_U16(*puBlockCheck), RT_LE2H_U16(uCheck), RT_LE2H_U16(pauUsa[iBlock]) );
     1337            else
     1338            {
     1339                Log(("NTFS: Multisector transfer warning: block #%u ends with %#x instead of %#x (fixup: %#x)\n",
     1340                     iBlock, RT_LE2H_U16(*puBlockCheck), RT_LE2H_U16(uCheck), RT_LE2H_U16(pauUsa[iBlock]) ));
     1341                return VINF_SUCCESS;
     1342            }
     1343        }
     1344
     1345        /*
     1346         * Apply the fixups.
     1347         * Note! We advanced pauUsa above, so it's now at the fixup values.
     1348         */
     1349        for (uint16_t iBlock = 0; iBlock < cUpdateSeqEntries; iBlock++)
     1350        {
     1351            uint16_t *puFixup = (uint16_t *)((uint8_t *)pRecHdr + (iBlock + 1) * NTFS_MULTI_SECTOR_STRIDE - 2U);
     1352            *puFixup = pauUsa[iBlock];
     1353        }
     1354        return VINF_SUCCESS;
     1355    }
     1356    if (fRelaxedUsa)
     1357    {
     1358        Log(("NTFS: Ignoring bogus multisector update sequence: cbRec=%#x uMagic=%#RX32 offUpdateSeqArray=%#x cUpdateSeqEntries=%#x\n",
     1359             cbRec, RT_LE2H_U32(pRecHdr->uMagic), offUpdateSeqArray, cUpdateSeqEntries ));
     1360        return VINF_SUCCESS;
     1361    }
     1362    return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_OFFSET,
     1363                                   "Bogus multisector update sequence: cbRec=%#x uMagic=%#RX32 offUpdateSeqArray=%#x cUpdateSeqEntries=%#x",
     1364                                   cbRec, RT_LE2H_U32(pRecHdr->uMagic), offUpdateSeqArray, cUpdateSeqEntries);
     1365}
     1366
     1367
     1368/**
    12861369 * Allocate and parse an MFT record, returning a core object structure.
    12871370 *
     
    12891372 * @param   pThis               The NTFS volume instance.
    12901373 * @param   idxMft              The index of the MTF record.
     1374 * @param   fRelaxedUsa         Relaxed update sequence checking. Won't fail if
     1375 *                              checks doesn't work or not present.
    12911376 * @param   ppCore              Where to return the core object structure.
    12921377 * @param   pErrInfo            Where to return error details.  Optional.
    12931378 */
    1294 static int rtFsNtfsVol_NewCoreForMftIdx(PRTFSNTFSVOL pThis, uint64_t idxMft, PRTFSNTFSCORE *ppCore, PRTERRINFO pErrInfo)
     1379static int rtFsNtfsVol_NewCoreForMftIdx(PRTFSNTFSVOL pThis, uint64_t idxMft, bool fRelaxedUsa,
     1380                                        PRTFSNTFSCORE *ppCore, PRTERRINFO pErrInfo)
    12951381{
    12961382    *ppCore = NULL;
     
    13031389    uint64_t offRec = idxMft * pThis->cbMftRecord;
    13041390    int rc = rtFsNtfsAttr_Read(pThis->pMftData, offRec, pRec->pbRec, pThis->cbMftRecord);
     1391    if (RT_SUCCESS(rc))
     1392        rc = rtFsNtfsRec_DoMultiSectorFixups(&pRec->pFileRec->Hdr, pThis->cbMftRecord, fRelaxedUsa, pErrInfo);
    13051393    if (RT_SUCCESS(rc))
    13061394    {
     
    14691557 */
    14701558
     1559#ifdef LOG_ENABLED
     1560
     1561/**
     1562 * Logs an index header and all the entries.
     1563 *
     1564 * @param   pIdxHdr     The index header.
     1565 * @param   cbIndex     The number of valid bytes starting with the header.
     1566 * @param   offIndex    The offset of the index header into the parent
     1567 *                      structure.
     1568 * @param   pszPrefix   The log prefix.
     1569 * @param   uIdxType    The index type.
     1570 */
     1571static void rtFsNtfsVol_LogIndexHdrAndEntries(PCNTFSINDEXHDR pIdxHdr, uint32_t cbIndex, uint32_t offIndex,
     1572                                              const char *pszPrefix, uint32_t uIdxType)
     1573{
     1574    if (!LogIs2Enabled())
     1575        return;
     1576
     1577    /*
     1578     * Do the header.
     1579     */
     1580    if (cbIndex <= sizeof(*pIdxHdr))
     1581    {
     1582        Log2(("NTFS: %s: Error! Not enough space for the index header! cbIndex=%#x, index head needs %#x\n",
     1583              pszPrefix, cbIndex, sizeof(*pIdxHdr)));
     1584        return;
     1585    }
     1586
     1587    Log2(("NTFS: %s:    offFirstEntry %#x%s\n", pszPrefix, RT_LE2H_U32(pIdxHdr->offFirstEntry),
     1588          RT_LE2H_U32(pIdxHdr->offFirstEntry) >= cbIndex ? " !out-of-bounds!" : ""));
     1589    Log2(("NTFS: %s:           cbUsed %#x%s\n", pszPrefix, RT_LE2H_U32(pIdxHdr->cbUsed),
     1590          RT_LE2H_U32(pIdxHdr->cbUsed) > cbIndex ? " !out-of-bounds!" : ""));
     1591    Log2(("NTFS: %s:      cbAllocated %#x%s\n", pszPrefix, RT_LE2H_U32(pIdxHdr->cbAllocated),
     1592          RT_LE2H_U32(pIdxHdr->cbAllocated) > cbIndex ? " !out-of-bounds!" : ""));
     1593    Log2(("NTFS: %s:           fFlags %#x (%s%s)\n", pszPrefix, pIdxHdr->fFlags,
     1594          pIdxHdr->fFlags & NTFSINDEXHDR_F_INTERNAL ? "internal" : "leaf",
     1595          pIdxHdr->fFlags & ~NTFSINDEXHDR_F_INTERNAL ? " !!unknown-flags!!" : ""));
     1596    if (pIdxHdr->abReserved[0]) Log2(("NTFS: %s:    abReserved[0] %#x\n", pszPrefix, pIdxHdr->abReserved[0]));
     1597    if (pIdxHdr->abReserved[1]) Log2(("NTFS: %s:    abReserved[0] %#x\n", pszPrefix, pIdxHdr->abReserved[1]));
     1598    if (pIdxHdr->abReserved[2]) Log2(("NTFS: %s:    abReserved[0] %#x\n", pszPrefix, pIdxHdr->abReserved[2]));
     1599
     1600    /*
     1601     * The entries.
     1602     */
     1603    bool        fSeenEnd    = false;
     1604    uint32_t    iEntry      = 0;
     1605    uint32_t    offCurEntry = RT_LE2H_U32(pIdxHdr->offFirstEntry);
     1606    while (offCurEntry < cbIndex)
     1607    {
     1608        if (offCurEntry + sizeof(NTFSIDXENTRYHDR) > cbIndex)
     1609        {
     1610            Log2(("NTFS:    Entry[%#04x]:  Out of bounds: %#x LB %#x, max %#x\n",
     1611                  iEntry, offCurEntry, sizeof(NTFSIDXENTRYHDR), cbIndex));
     1612            break;
     1613        }
     1614        PCNTFSIDXENTRYHDR pEntryHdr = (PCNTFSIDXENTRYHDR)((uint8_t const *)pIdxHdr + offCurEntry);
     1615        Log2(("NTFS:    [%#04x]: @%#05x/@%#05x cbEntry=%#x cbKey=%#x fFlags=%#x (%s%s%s)\n",
     1616              iEntry, offCurEntry, offCurEntry + offIndex, RT_LE2H_U16(pEntryHdr->cbEntry), RT_LE2H_U16(pEntryHdr->cbKey),
     1617              RT_LE2H_U16(pEntryHdr->fFlags),
     1618              pEntryHdr->fFlags & NTFSIDXENTRYHDR_F_INTERNAL ? "internal" : "leaf",
     1619              pEntryHdr->fFlags & NTFSIDXENTRYHDR_F_END ? " end" : "",
     1620              pEntryHdr->fFlags & ~(NTFSIDXENTRYHDR_F_INTERNAL | NTFSIDXENTRYHDR_F_END) ? " !unknown!" : ""));
     1621        if (uIdxType == NTFSATINDEXROOT_TYPE_DIR)
     1622            Log2(("NTFS:             FileMftRec %#RX64 sqn %#x\n",
     1623                  NTFSMFTREF_GET_IDX(&pEntryHdr->u.FileMftRec), NTFSMFTREF_GET_SEQ(&pEntryHdr->u.FileMftRec) ));
     1624        else
     1625            Log2(("NTFS:             offData=%#x cbData=%#x uReserved=%#x\n",
     1626                  RT_LE2H_U16(pEntryHdr->u.View.offData), RT_LE2H_U16(pEntryHdr->u.View.cbData),
     1627                  RT_LE2H_U32(pEntryHdr->u.View.uReserved) ));
     1628        if (pEntryHdr->fFlags & NTFSIDXENTRYHDR_F_INTERNAL)
     1629            Log2(("NTFS:             Subnode=%#RX64\n", RT_LE2H_U64(NTFSIDXENTRYHDR_GET_SUBNODE(pEntryHdr)) ));
     1630
     1631        if (   RT_LE2H_U16(pEntryHdr->cbKey) >= sizeof(NTFSATFILENAME)
     1632            && uIdxType == NTFSATINDEXROOT_TYPE_DIR)
     1633        {
     1634            PCNTFSATFILENAME pFilename = (PCNTFSATFILENAME)(pEntryHdr + 1);
     1635            Log2(("NTFS:             Filename=%.*ls\n", pFilename->cwcFilename, pFilename->wszFilename));
     1636        }
     1637
     1638
     1639        /* next */
     1640        iEntry++;
     1641        offCurEntry += RT_LE2H_U16(pEntryHdr->cbEntry);
     1642        fSeenEnd = RT_BOOL(pEntryHdr->fFlags & NTFSIDXENTRYHDR_F_END);
     1643        if (fSeenEnd || RT_LE2H_U16(pEntryHdr->cbEntry) < sizeof(*pEntryHdr))
     1644            break;
     1645    }
     1646    if (!fSeenEnd)
     1647        Log2(("NTFS: %s: Warning! Missing NTFSIDXENTRYHDR_F_END node!\n", pszPrefix));
     1648}
     1649
     1650static void rtFsNtfsVol_LogIndexNode(PCNTFSATINDEXALLOC pIdxNode, uint32_t cbIdxNode, uint32_t uType)
     1651{
     1652    if (!LogIs2Enabled())
     1653        return;
     1654    if (cbIdxNode < sizeof(*pIdxNode))
     1655        Log2(("NTFS: Index Node: Error! Too small! cbIdxNode=%#x, index node needs %#x\n", cbIdxNode, sizeof(*pIdxNode)));
     1656    else
     1657    {
     1658        Log2(("NTFS: Index Node:            uMagic %#x\n", RT_LE2H_U32(pIdxNode->RecHdr.uMagic)));
     1659        Log2(("NTFS: Index Node:    UpdateSeqArray %#x L %#x\n",
     1660              RT_LE2H_U16(pIdxNode->RecHdr.offUpdateSeqArray), RT_LE2H_U16(pIdxNode->RecHdr.cUpdateSeqEntries) ));
     1661        Log2(("NTFS: Index Node:              uLsn %#RX64\n", RT_LE2H_U64(pIdxNode->uLsn) ));
     1662        Log2(("NTFS: Index Node:      iSelfAddress %#RX64\n", RT_LE2H_U64(pIdxNode->iSelfAddress) ));
     1663        if (pIdxNode->RecHdr.uMagic == NTFSREC_MAGIC_INDEX_ALLOC)
     1664            rtFsNtfsVol_LogIndexHdrAndEntries(&pIdxNode->Hdr, cbIdxNode - RT_UOFFSETOF(NTFSATINDEXALLOC, Hdr),
     1665                                              RT_UOFFSETOF(NTFSATINDEXALLOC, Hdr), "Index Node Hdr", uType);
     1666        else
     1667            Log2(("NTFS: Index Node: !Error! Invalid magic!\n"));
     1668    }
     1669}
     1670
     1671
     1672/**
     1673 * Logs a index root structure and what follows (index header + entries).
     1674 *
     1675 * @param   pIdxRoot    The index root.
     1676 * @param   cbIdxRoot   Number of valid bytes starting with @a pIdxRoot.
     1677 */
     1678static void rtFsNtfsVol_LogIndexRoot(PCNTFSATINDEXROOT pIdxRoot, uint32_t cbIdxRoot)
     1679{
     1680    if (!LogIs2Enabled())
     1681        return;
     1682    if (cbIdxRoot < sizeof(*pIdxRoot))
     1683        Log2(("NTFS: Index Root: Error! Too small! cbIndex=%#x, index head needs %#x\n", cbIdxRoot, sizeof(*pIdxRoot)));
     1684    else
     1685    {
     1686        Log2(("NTFS: Index Root:              cbIdxRoot %#x\n", cbIdxRoot));
     1687        Log2(("NTFS: Index Root:                  uType %#x %s\n", RT_LE2H_U32(pIdxRoot->uType),
     1688              pIdxRoot->uType == NTFSATINDEXROOT_TYPE_VIEW ? "view"
     1689              : pIdxRoot->uType == NTFSATINDEXROOT_TYPE_DIR ? "directory" : "!unknown!"));
     1690        Log2(("NTFS: Index Root:        uCollationRules %#x %s\n", RT_LE2H_U32(pIdxRoot->uCollationRules),
     1691              pIdxRoot->uCollationRules == NTFS_COLLATION_BINARY ? "binary"
     1692              : pIdxRoot->uCollationRules == NTFS_COLLATION_FILENAME ? "filename"
     1693              : pIdxRoot->uCollationRules == NTFS_COLLATION_UNICODE_STRING ? "unicode-string"
     1694              : pIdxRoot->uCollationRules == NTFS_COLLATION_UINT32 ? "uint32"
     1695              : pIdxRoot->uCollationRules == NTFS_COLLATION_SID ? "sid"
     1696              : pIdxRoot->uCollationRules == NTFS_COLLATION_UINT32_PAIR ? "uint32-pair"
     1697              : pIdxRoot->uCollationRules == NTFS_COLLATION_UINT32_SEQ ? "uint32-sequence" : "!unknown!"));
     1698        Log2(("NTFS: Index Root:            cbIndexNode %#x\n", RT_LE2H_U32(pIdxRoot->cbIndexNode) ));
     1699        Log2(("NTFS: Index Root: cAddressesPerIndexNode %#x => cbNodeAddressingUnit=%#x\n",
     1700              pIdxRoot->cAddressesPerIndexNode, RT_LE2H_U32(pIdxRoot->cbIndexNode) / RT_MAX(1, pIdxRoot->cAddressesPerIndexNode) ));
     1701        if (pIdxRoot->abReserved[0]) Log2(("NTFS: Index Root:          abReserved[0] %#x\n", pIdxRoot->abReserved[0]));
     1702        if (pIdxRoot->abReserved[1]) Log2(("NTFS: Index Root:          abReserved[1] %#x\n", pIdxRoot->abReserved[1]));
     1703        if (pIdxRoot->abReserved[2]) Log2(("NTFS: Index Root:          abReserved[2] %#x\n", pIdxRoot->abReserved[2]));
     1704
     1705        rtFsNtfsVol_LogIndexHdrAndEntries(&pIdxRoot->Hdr, cbIdxRoot - RT_UOFFSETOF(NTFSATINDEXROOT, Hdr),
     1706                                          RT_UOFFSETOF(NTFSATINDEXROOT, Hdr), "Index Root Hdr", pIdxRoot->uType);
     1707    }
     1708}
     1709
     1710#endif /* LOG_ENABLED */
     1711
    14711712
    14721713static int rtFsNtfsVol_NewSharedDirFromCore(PRTFSNTFSVOL pThis, PRTFSNTFSCORE pCore, PRTFSNTFSDIRSHRD *ppSharedDir,
     
    14781719     * Look for the index root and do some quick checks of it first.
    14791720     */
    1480     PRTFSNTFSATTR pRootAttr = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME,
    1481                                                                       NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ROOT);
     1721    PRTFSNTFSATTR pRootAttr = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_INDEX_ROOT,
     1722                                                                   RT_STR_TUPLE(NTFS_DIR_ATTRIBUTE_NAME));
    14821723    if (!pRootAttr)
    14831724        return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "%s: Found no INDEX_ROOT attribute named $I30", pszWhat);
    14841725    if (pRootAttr->pAttrHdr->fNonResident)
    14851726        return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "%s: INDEX_ROOT is is not resident", pszWhat);
    1486 
     1727    if (pRootAttr->cbResident < sizeof(NTFSATINDEXROOT))
     1728        return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "%s: INDEX_ROOT is too small: %#x, min %#x ",
     1729                                       pRootAttr->cbResident, sizeof(pRootAttr->cbResident));
     1730
     1731    PCNTFSATINDEXROOT pIdxRoot = (PCNTFSATINDEXROOT)NTFSATTRIBHDR_GET_RES_VALUE_PTR(pRootAttr->pAttrHdr);
     1732#ifdef LOG_ENABLED
     1733    rtFsNtfsVol_LogIndexRoot(pIdxRoot, pRootAttr->cbResident);
     1734#endif
     1735    NOREF(pIdxRoot);
     1736//    if (pIdxRoot->uType)
     1737//    {
     1738//    }
    14871739
    14881740#if 1 /* later */
     
    14921744     *
    14931745     */
    1494     PRTFSNTFSATTR pAllocAttr  = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME,
    1495                                                                       NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ALLOCATION);
    1496     PRTFSNTFSATTR pBitmapAttr = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME,
    1497                                                                       NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_BITMAP);
     1746    PRTFSNTFSATTR pIndexAlloc  = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_INDEX_ALLOCATION,
     1747                                                                      RT_STR_TUPLE(NTFS_DIR_ATTRIBUTE_NAME));
     1748    PRTFSNTFSATTR pIndexBitmap = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_BITMAP,
     1749                                                                      RT_STR_TUPLE(NTFS_DIR_ATTRIBUTE_NAME));
    14981750#endif
    14991751    return VINF_SUCCESS;
     
    17812033     */
    17822034    PRTFSNTFSCORE pCore;
    1783     int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_ROOT, &pCore, pErrInfo);
     2035    int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_ROOT, false /*fRelaxedUsa*/, &pCore, pErrInfo); // DON'T COMMIT
    17842036    if (RT_SUCCESS(rc))
    17852037    {
     
    18052057            else
    18062058            {
    1807                 PRTFSNTFSATTR pIndexRoot   = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME,
    1808                                                                                   NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ROOT);
    1809                 PRTFSNTFSATTR pIndexAlloc  = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME,
    1810                                                                                   NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ALLOCATION);
    1811                 PRTFSNTFSATTR pIndexBitmap = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME,
    1812                                                                                   NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_BITMAP);
     2059                PRTFSNTFSATTR pIndexRoot   = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_INDEX_ROOT,
     2060                                                                                  RT_STR_TUPLE(NTFS_DIR_ATTRIBUTE_NAME));
     2061                PRTFSNTFSATTR pIndexAlloc  = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_INDEX_ALLOCATION,
     2062                                                                                  RT_STR_TUPLE(NTFS_DIR_ATTRIBUTE_NAME));
     2063                PRTFSNTFSATTR pIndexBitmap = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_BITMAP,
     2064                                                                                  RT_STR_TUPLE(NTFS_DIR_ATTRIBUTE_NAME));
    18132065                if (!pIndexRoot)
    18142066                    rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "RootDir: Found no INDEX_ROOT attribute named $I30");
     
    18572109{
    18582110    PRTFSNTFSCORE pCore;
    1859     int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_UP_CASE, &pCore, pErrInfo);
     2111    int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_UP_CASE, false /*fRelaxedUsa*/, &pCore, pErrInfo);
    18602112    if (RT_SUCCESS(rc))
    18612113    {
     
    19792231{
    19802232    PRTFSNTFSCORE pCore;
    1981     int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_BITMAP, &pCore, pErrInfo);
     2233    int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_BITMAP, false /*fRelaxedUsa*/, &pCore, pErrInfo);
    19822234    if (RT_SUCCESS(rc))
    19832235    {
     
    21022354{
    21032355    PRTFSNTFSCORE pCore;
    2104     int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_VOLUME, &pCore, pErrInfo);
     2356    int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_VOLUME, false /*fRelaxedUsa*/, &pCore, pErrInfo);
    21052357    if (RT_SUCCESS(rc))
    21062358    {
     
    21842436    AssertReturn(pRec, VERR_NO_MEMORY);
    21852437
     2438#if 0 && defined(LOG_ENABLED)
     2439    for (uint32_t i = 0; i < 128; i++)
     2440    {
     2441        uint64_t const offDisk = (pThis->uLcnMft << pThis->cClusterShift) + i * pThis->cbMftRecord;
     2442        int rc = RTVfsFileReadAt(pThis->hVfsBacking, offDisk, pRec->pbRec, pThis->cbMftRecord, NULL);
     2443        if (RT_SUCCESS(rc))
     2444        {
     2445            pRec->TreeNode.Key = i;
     2446            rtfsNtfsMftRec_Log(pRec, pThis->cbMftRecord);
     2447            pRec->TreeNode.Key = 0;
     2448        }
     2449    }
     2450#endif
     2451
    21862452    uint64_t const offDisk = pThis->uLcnMft << pThis->cClusterShift;
    21872453    int rc = RTVfsFileReadAt(pThis->hVfsBacking, offDisk, pRec->pbRec, pThis->cbMftRecord, NULL);
    21882454    if (RT_SUCCESS(rc))
    21892455    {
     2456        rc = rtFsNtfsRec_DoMultiSectorFixups(&pRec->pFileRec->Hdr, pThis->cbMftRecord, true, pErrInfo);
     2457        if (RT_SUCCESS(rc))
     2458        {
    21902459#ifdef LOG_ENABLED
    2191         rtfsNtfsMftRec_Log(pRec, pThis->cbMftRecord);
     2460            rtfsNtfsMftRec_Log(pRec, pThis->cbMftRecord);
    21922461#endif
    2193         rc = rtFsNtfsVol_ParseMft(pThis, pRec, pErrInfo);
     2462            rc = rtFsNtfsVol_ParseMft(pThis, pRec, pErrInfo);
     2463        }
    21942464        if (RT_SUCCESS(rc))
    21952465        {
     
    23982668                                   "Unsupported NTFS MFT record size: %#x", pThis->cbMftRecord);
    23992669
    2400     /* NTFS BPB: Index block size */
    2401     if (pBootSector->Bpb.Ntfs.cClusterPerIndexBlock >= 0)
    2402     {
    2403         if (   !RT_IS_POWER_OF_TWO((uint32_t)pBootSector->Bpb.Ntfs.cClusterPerIndexBlock)
    2404             || pBootSector->Bpb.Ntfs.cClusterPerIndexBlock == 0)
     2670    /* NTFS BPB: Default index node size */
     2671    if (pBootSector->Bpb.Ntfs.cClustersPerIndexNode >= 0)
     2672    {
     2673        if (   !RT_IS_POWER_OF_TWO((uint32_t)pBootSector->Bpb.Ntfs.cClustersPerIndexNode)
     2674            || pBootSector->Bpb.Ntfs.cClustersPerIndexNode == 0)
    24052675            return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
    2406                                        "NTFS clusters-per-index-block is zero or not a power of two: %#x",
    2407                                         pBootSector->Bpb.Ntfs.cClusterPerIndexBlock);
    2408         pThis->cbIndexRecord = (uint32_t)pBootSector->Bpb.Ntfs.cClusterPerIndexBlock << pThis->cClusterShift;
    2409         Assert(pThis->cbIndexRecord == pBootSector->Bpb.Ntfs.cClusterPerIndexBlock * pThis->cbCluster);
    2410     }
    2411     else if (   pBootSector->Bpb.Ntfs.cClusterPerIndexBlock < -32
    2412              || pBootSector->Bpb.Ntfs.cClusterPerIndexBlock > -9)
     2676                                       "NTFS default clusters-per-index-tree-node is zero or not a power of two: %#x",
     2677                                        pBootSector->Bpb.Ntfs.cClustersPerIndexNode);
     2678        pThis->cbDefaultIndexNode = (uint32_t)pBootSector->Bpb.Ntfs.cClustersPerIndexNode << pThis->cClusterShift;
     2679        Assert(pThis->cbDefaultIndexNode == pBootSector->Bpb.Ntfs.cClustersPerIndexNode * pThis->cbCluster);
     2680    }
     2681    else if (   pBootSector->Bpb.Ntfs.cClustersPerIndexNode < -32
     2682             || pBootSector->Bpb.Ntfs.cClustersPerIndexNode > -9)
    24132683        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
    2414                                    "NTFS clusters-per-index-block is out of shift range: %d",
    2415                                     pBootSector->Bpb.Ntfs.cClusterPerIndexBlock);
     2684                                   "NTFS default clusters-per-index-tree-node is out of shift range: %d",
     2685                                    pBootSector->Bpb.Ntfs.cClustersPerIndexNode);
    24162686    else
    2417         pThis->cbIndexRecord = UINT32_C(1) << -pBootSector->Bpb.Ntfs.cClustersPerMftRecord;
    2418     Log2(("NTFS BPB: cbIndexRecord=%#x\n", pThis->cbIndexRecord));
     2687        pThis->cbDefaultIndexNode = UINT32_C(1) << -pBootSector->Bpb.Ntfs.cClustersPerMftRecord;
     2688    Log2(("NTFS BPB: cbDefaultIndexNode=%#x\n", pThis->cbDefaultIndexNode));
    24192689
    24202690    pThis->uSerialNo = RT_LE2H_U64(pBootSector->Bpb.Ntfs.uSerialNumber);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette