VirtualBox

Ignore:
Timestamp:
Nov 28, 2017 7:01:35 PM (7 years ago)
Author:
vboxsync
Message:

iprt/formats/ntfs: updates

File:
1 edited

Legend:

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

    r69849 r69861  
    3333
    3434#include <iprt/asm.h>
     35#include <iprt/avl.h>
    3536#include <iprt/assert.h>
    3637#include <iprt/file.h>
     
    4647*   Structures and Typedefs                                                                                                      *
    4748*********************************************************************************************************************************/
     49/** Pointer to the instance data for a NTFS volume. */
     50typedef struct RTFSNTFSVOL *PRTFSNTFSVOL;
     51/** Pointer to a NTFS MFT record. */
     52typedef struct RTFSNTFSMFTREC *PRTFSNTFSMFTREC;
     53
     54/**
     55 * NTFS MFT record.
     56 */
     57typedef struct RTFSNTFSMFTREC
     58{
     59    /** MFT record number as key. */
     60    AVLU64NODECORE      Core;
     61    /** Pointer to the next MFT record if chained. */
     62    PRTFSNTFSMFTREC     pNext;
     63    /** Pointer back to the volume. */
     64    PRTFSNTFSVOL        pVol;
     65    /** The disk offset of this MFT entry. */
     66    uint64_t            offDisk;
     67    union
     68    {
     69        /** Generic pointer. */
     70        uint8_t        *pbRec;
     71        /** Pointer to the file record. */
     72        PNTFSRECFILE    pFileRec;
     73    } RT_UNION_NM(u);
     74
     75    /** Reference counter. */
     76    uint32_t volatile   cRefs;
     77
     78    // ....
     79} RTFSNTFSMFTREC;
    4880
    4981/**
     
    91123    uint64_t        uSerialNo;
    92124
     125    /** Pointer to the MFT record for the MFT. */
     126    PRTFSNTFSMFTREC pMft;
     127
     128    /** Root of the MFT record tree (RTFSNTFSMFTREC). */
     129    AVLU64TREE      MftRoot;
    93130} RTFSNTFSVOL;
    94 /** Pointer to the instance data for a NTFS volume. */
    95 typedef RTFSNTFSVOL *PRTFSNTFSVOL;
     131
     132
     133static PRTFSNTFSMFTREC rtFsNtfsMftRec_New(PRTFSNTFSVOL pVol, uint64_t idMft)
     134{
     135    PRTFSNTFSMFTREC pRec = (PRTFSNTFSMFTREC)RTMemAllocZ(sizeof(*pRec));
     136    if (pRec)
     137    {
     138        pRec->pbRec = (uint8_t *)RTMemAllocZ(pVol->cbMftRecord);
     139        if (pRec->pbRec)
     140        {
     141            pRec->Core.Key = idMft;
     142            pRec->pNext    = NULL;
     143            pRec->offDisk  = UINT64_MAX / 2;
     144            pRec->pVol     = pVol;
     145            pRec->cRefs    = 1;
     146            return pRec;
     147        }
     148    }
     149    return NULL;
     150}
     151
     152
     153static uint32_t rtFsNtfsMftRec_Destroy(PRTFSNTFSMFTREC pThis)
     154{
     155    RTMemFree(pThis->pbRec);
     156    pThis->pbRec = NULL;
     157
     158    PAVLU64NODECORE pRemoved = RTAvlU64Remove(&pThis->pVol->MftRoot, pThis->Core.Key);
     159    Assert(pRemoved == &pThis->Core); NOREF(pRemoved);
     160
     161    pThis->pVol = NULL;
     162    RTMemFree(pThis);
     163
     164    return 0;
     165}
     166
     167
     168static uint32_t rtFsNtfsMftRec_Retain(PRTFSNTFSMFTREC pThis)
     169{
     170    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
     171    Assert(cRefs < 64);
     172    return cRefs;
     173}
     174
     175
     176static uint32_t rtFsNtfsMftRec_Release(PRTFSNTFSMFTREC pThis)
     177{
     178    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
     179    Assert(cRefs < 64);
     180    if (cRefs != 0)
     181        return cRefs;
     182    return rtFsNtfsMftRec_Destroy(pThis);
     183}
     184
     185
     186#ifdef LOG_ENABLED
     187/**
     188 * Logs the MFT record
     189 *
     190 * @param   pRec        The MFT record to log.
     191 */
     192static void rtfsNtfsMftRec_Log(PRTFSNTFSMFTREC pRec)
     193{
     194    if (LogIs2Enabled())
     195    {
     196        PCNTFSRECFILE  pFileRec = pRec->pFileRec;
     197        Log2(("NTFS: MFT #%#RX64 at %#RX64\n", pRec->Core.Key, pRec->offDisk));
     198        if (pFileRec->Hdr.uMagic == NTFSREC_MAGIC_FILE)
     199        {
     200            size_t const          cbRec = pRec->pVol->cbMftRecord;
     201            uint8_t const * const pbRec = pRec->pbRec;
     202
     203            Log2(("NTFS: FILE record: \n"));
     204            Log2(("NTFS:   UpdateSeqArray  %#x L %#x\n", RT_LE2H_U16(pFileRec->Hdr.offUpdateSeqArray), RT_LE2H_U16(pFileRec->Hdr.cUpdateSeqEntries) ));
     205            Log2(("NTFS:   uLsn            %#RX64\n", RT_LE2H_U64(pFileRec->uLsn)));
     206            Log2(("NTFS:   uRecReuseSeqNo  %#RX16\n", RT_LE2H_U16(pFileRec->uRecReuseSeqNo)));
     207            Log2(("NTFS:   cLinks          %#RX16\n", RT_LE2H_U16(pFileRec->cLinks)));
     208            Log2(("NTFS:   offFirstAttrib  %#RX16\n", RT_LE2H_U16(pFileRec->offFirstAttrib)));
     209            Log2(("NTFS:   fFlags          %#RX16%s%s\n", RT_LE2H_U16(pFileRec->fFlags),
     210                  RT_LE2H_U16(pFileRec->fFlags) & NTFSRECFILE_F_IN_USE    ? " in-use"    : "",
     211                  RT_LE2H_U16(pFileRec->fFlags) & NTFSRECFILE_F_DIRECTORY ? " directory" : ""));
     212            Log2(("NTFS:   cbRecUsed       %#RX32\n", RT_LE2H_U32(pFileRec->cbRecUsed)));
     213            Log2(("NTFS:   BaseMftRec      %#RX64, sqn %#x\n",
     214                  NTFSMFTREF_GET_IDX(&pFileRec->BaseMftRec), NTFSMFTREF_GET_SEQ(&pFileRec->BaseMftRec)));
     215            Log2(("NTFS:   idNextAttrib    %#RX16\n", RT_LE2H_U16(pFileRec->idNextAttrib)));
     216            if (   RT_LE2H_U16(pFileRec->offFirstAttrib)         >= sizeof(*pFileRec)
     217                && (   RT_LE2H_U16(pFileRec->Hdr.offUpdateSeqArray) >= sizeof(*pFileRec)
     218                    || pFileRec->Hdr.offUpdateSeqArray == 0))
     219            {
     220                Log2(("NTFS:   uPaddingOrUsa   %#RX16\n", pFileRec->uPaddingOrUsa));
     221                Log2(("NTFS:   idxMftSelf      %#RX32\n", RT_LE2H_U32(pFileRec->idxMftSelf)));
     222            }
     223
     224            uint32_t offRec = pFileRec->offFirstAttrib;
     225            size_t   cbRecUsed = RT_MIN(cbRec, pFileRec->cbRecUsed);
     226            while (offRec + NTFSATTRIBHDR_SIZE_RESIDENT <= cbRecUsed)
     227            {
     228                PCNTFSATTRIBHDR pHdr     = (PCNTFSATTRIBHDR)&pbRec[offRec];
     229                uint32_t const  cbAttrib = RT_LE2H_U32(pHdr->cbAttrib);
     230                Log2(("NTFS:   @%#05x: Attrib record: %#x LB %#x, instance #%#x, fFlags=%#RX16, %s\n", offRec,
     231                      RT_LE2H_U32(pHdr->uAttrType), cbAttrib, RT_LE2H_U16(pHdr->idAttrib), RT_LE2H_U16(pHdr->fFlags),
     232                      pHdr->fNonResident == 0 ? "resident" : pHdr->fNonResident == 1 ? "non-resident" : "bad-resident-flag"));
     233                if (pHdr->offName && pHdr->cwcName)
     234                {
     235                    if (offRec + RT_LE2H_U16(pHdr->offName) + pHdr->cwcName * sizeof(RTUTF16) <= cbRec)
     236                        Log2(("NTFS:     Name %.*ls\n", pHdr->cwcName,&pbRec[offRec + RT_LE2H_U16(pHdr->offName)]));
     237                    else
     238                        Log2(("NTFS:     Name <!out of bounds!> %#x L %#x\n", RT_LE2H_U16(pHdr->offName), pHdr->cwcName));
     239                }
     240                switch (pHdr->uAttrType)
     241                {
     242                    case NTFS_AT_UNUSED:                    Log2(("NTFS:     Type: UNUSED\n")); break;
     243                    case NTFS_AT_STANDARD_INFORMATION:      Log2(("NTFS:     Type: STANDARD_INFORMATION\n")); break;
     244                    case NTFS_AT_ATTRIBUTE_LIST:            Log2(("NTFS:     Type: ATTRIBUTE_LIST\n")); break;
     245                    case NTFS_AT_FILENAME:                  Log2(("NTFS:     Type: FILENAME\n")); break;
     246                    case NTFS_AT_OBJECT_ID:                 Log2(("NTFS:     Type: OBJECT_ID\n")); break;
     247                    case NTFS_AT_SECURITY_DESCRIPTOR:       Log2(("NTFS:     Type: SECURITY_DESCRIPTOR\n")); break;
     248                    case NTFS_AT_VOLUME_NAME:               Log2(("NTFS:     Type: VOLUME_NAME\n")); break;
     249                    case NTFS_AT_VOLUME_INFORMATION:        Log2(("NTFS:     Type: VOLUME_INFORMATION\n")); break;
     250                    case NTFS_AT_DATA:                      Log2(("NTFS:     Type: DATA\n")); break;
     251                    case NTFS_AT_INDEX_ROOT:                Log2(("NTFS:     Type: INDEX_ROOT\n")); break;
     252                    case NTFS_AT_INDEX_ALLOCATION:          Log2(("NTFS:     Type: INDEX_ALLOCATION\n")); break;
     253                    case NTFS_AT_BITMAP:                    Log2(("NTFS:     Type: BITMAP\n")); break;
     254                    case NTFS_AT_REPARSE_POINT:             Log2(("NTFS:     Type: REPARSE_POINT\n")); break;
     255                    case NTFS_AT_EA_INFORMATION:            Log2(("NTFS:     Type: EA_INFORMATION\n")); break;
     256                    case NTFS_AT_EA:                        Log2(("NTFS:     Type: EA\n")); break;
     257                    case NTFS_AT_PROPERTY_SET:              Log2(("NTFS:     Type: PROPERTY_SET\n")); break;
     258                    case NTFS_AT_LOGGED_UTILITY_STREAM:     Log2(("NTFS:     Type: LOGGED_UTILITY_STREAM\n")); break;
     259                    default:
     260                        if (RT_LE2H_U32(pHdr->uAttrType) >= RT_LE2H_U32_C(NTFS_AT_FIRST_USER_DEFINED))
     261                            Log2(("NTFS:     Type: unknown user defined - %#x!\n", RT_LE2H_U32(pHdr->uAttrType)));
     262                        else
     263                            Log2(("NTFS:     Type: unknown - %#x!\n", RT_LE2H_U32(pHdr->uAttrType)));
     264                        break;
     265                }
     266
     267                size_t const cbMaxAttrib = cbRec - offRec;
     268                if (!pHdr->fNonResident)
     269                {
     270                    uint16_t const offValue = RT_LE2H_U16(pHdr->Res.offValue);
     271                    uint32_t const cbValue  = RT_LE2H_U32(pHdr->Res.cbValue);
     272                    Log2(("NTFS:     Value: %#x LB %#x, fFlags=%#x bReserved=%#x\n",
     273                          offValue, cbValue, pHdr->Res.fFlags, pHdr->Res.bReserved));
     274                    if (   offValue < cbMaxAttrib
     275                        && cbValue  < cbMaxAttrib
     276                        && offValue + cbValue <= cbMaxAttrib)
     277                    {
     278                        uint8_t const *pbValue = &pbRec[offRec + offValue];
     279                        RTTIMESPEC     Spec;
     280                        char           sz[80];
     281                        switch (pHdr->uAttrType)
     282                        {
     283                            case NTFS_AT_STANDARD_INFORMATION:
     284                            {
     285                                PCNTFSATSTDINFO pInfo = (PCNTFSATSTDINFO)pbValue;
     286                                if (cbValue >= NTFSATSTDINFO_SIZE_NTFS_V12)
     287                                {
     288                                    Log2(("NTFS:     iCreationTime      %#RX64 %s\n", RT_LE2H_U64(pInfo->iCreationTime),
     289                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iCreationTime)), sz, sizeof(sz)) ));
     290                                    Log2(("NTFS:     iLastDataModTime   %#RX64 %s\n", RT_LE2H_U64(pInfo->iLastDataModTime),
     291                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iLastDataModTime)), sz, sizeof(sz)) ));
     292                                    Log2(("NTFS:     iLastMftModTime    %#RX64 %s\n", RT_LE2H_U64(pInfo->iLastMftModTime),
     293                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iLastMftModTime)), sz, sizeof(sz)) ));
     294                                    Log2(("NTFS:     iLastAccessTime    %#RX64 %s\n", RT_LE2H_U64(pInfo->iLastAccessTime),
     295                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iLastAccessTime)), sz, sizeof(sz)) ));
     296                                    Log2(("NTFS:     fFileAttribs       %#RX32\n", RT_LE2H_U32(pInfo->fFileAttribs) ));
     297                                    Log2(("NTFS:     cMaxFileVersions   %#RX32\n", RT_LE2H_U32(pInfo->cMaxFileVersions) ));
     298                                    Log2(("NTFS:     uFileVersion       %#RX32\n", RT_LE2H_U32(pInfo->uFileVersion) ));
     299                                }
     300                                else
     301                                    Log2(("NTFS:     Error! cbValue=%#x is smaller than expected (%#x) for NTFSATSTDINFO!\n",
     302                                          cbValue, NTFSATSTDINFO_SIZE_NTFS_V12));
     303                                if (cbValue >= sizeof(*pInfo))
     304                                {
     305                                    Log2(("NTFS:     idClass            %#RX32\n", RT_LE2H_U32(pInfo->idClass) ));
     306                                    Log2(("NTFS:     idOwner            %#RX32\n", RT_LE2H_U32(pInfo->idOwner) ));
     307                                    Log2(("NTFS:     idSecurity         %#RX32\n", RT_LE2H_U32(pInfo->idSecurity) ));
     308                                    Log2(("NTFS:     cbQuotaChared      %#RX64\n", RT_LE2H_U64(pInfo->cbQuotaChared) ));
     309                                    Log2(("NTFS:     idxUpdateSequence  %#RX64\n", RT_LE2H_U64(pInfo->idxUpdateSequence) ));
     310                                }
     311                                if (cbValue > sizeof(*pInfo))
     312                                    Log2(("NTFS:     Undefined data: %.*Rhxs\n", cbValue - sizeof(*pInfo), &pbValue[sizeof(*pInfo)]));
     313                                break;
     314                            }
     315
     316                            //case NTFS_AT_ATTRIBUTE_LIST:
     317
     318                            case NTFS_AT_FILENAME:
     319                            {
     320                                PCNTFSATFILENAME pInfo = (PCNTFSATFILENAME)pbValue;
     321                                if (cbValue >= RT_OFFSETOF(NTFSATFILENAME, wszFilename))
     322                                {
     323                                    Log2(("NTFS:     ParentDirMftRec    %#RX64, sqn %#x\n",
     324                                          NTFSMFTREF_GET_IDX(&pInfo->ParentDirMftRec), NTFSMFTREF_GET_SEQ(&pInfo->ParentDirMftRec) ));
     325                                    Log2(("NTFS:     iCreationTime      %#RX64 %s\n", RT_LE2H_U64(pInfo->iCreationTime),
     326                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iCreationTime)), sz, sizeof(sz)) ));
     327                                    Log2(("NTFS:     iLastDataModTime   %#RX64 %s\n", RT_LE2H_U64(pInfo->iLastDataModTime),
     328                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iLastDataModTime)), sz, sizeof(sz)) ));
     329                                    Log2(("NTFS:     iLastMftModTime    %#RX64 %s\n", RT_LE2H_U64(pInfo->iLastMftModTime),
     330                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iLastMftModTime)), sz, sizeof(sz)) ));
     331                                    Log2(("NTFS:     iLastAccessTime    %#RX64 %s\n", RT_LE2H_U64(pInfo->iLastAccessTime),
     332                                          RTTimeSpecToString(RTTimeSpecSetNtTime(&Spec, RT_LE2H_U64(pInfo->iLastAccessTime)), sz, sizeof(sz)) ));
     333                                    Log2(("NTFS:     cbAllocated        %#RX64 (%Rhcb)\n",
     334                                          RT_LE2H_U64(pInfo->cbAllocated), RT_LE2H_U64(pInfo->cbAllocated)));
     335                                    Log2(("NTFS:     cbData             %#RX64 (%Rhcb)\n",
     336                                          RT_LE2H_U64(pInfo->cbData), RT_LE2H_U64(pInfo->cbData)));
     337                                    Log2(("NTFS:     fFileAttribs       %#RX32\n", RT_LE2H_U32(pInfo->fFileAttribs) ));
     338                                    if (RT_LE2H_U32(pInfo->fFileAttribs) & NTFS_FA_REPARSE_POINT)
     339                                        Log2(("NTFS:     uReparseTag        %#RX32\n", RT_LE2H_U32(pInfo->uReparseTag) ));
     340                                    else
     341                                        Log2(("NTFS:     cbPackedEas        %#RX16\n", RT_LE2H_U16(pInfo->cbPackedEas) ));
     342                                    Log2(("NTFS:     cwcFilename        %#x\n", pInfo->cwcFilename));
     343                                    Log2(("NTFS:     fFilenameType      %#x\n", pInfo->fFilenameType));
     344                                    if (cbValue >= RT_UOFFSETOF(NTFSATFILENAME, wszFilename))
     345                                        Log2(("NTFS:     wszFilename       '%.*ls'\n", pInfo->cwcFilename, pInfo->wszFilename ));
     346                                    else
     347                                        Log2(("NTFS:     Error! Truncated filename!!\n"));
     348                                }
     349                                else
     350                                    Log2(("NTFS:     Error! cbValue=%#x is smaller than expected (%#x) for NTFSATFILENAME!\n",
     351                                          cbValue, RT_OFFSETOF(NTFSATFILENAME, wszFilename) ));
     352                                break;
     353                            }
     354
     355                            //case NTFS_AT_OBJECT_ID:
     356                            //case NTFS_AT_SECURITY_DESCRIPTOR:
     357                            //case NTFS_AT_VOLUME_NAME:
     358                            //case NTFS_AT_VOLUME_INFORMATION:
     359                            //case NTFS_AT_DATA:
     360                            //case NTFS_AT_INDEX_ROOT:
     361                            //case NTFS_AT_INDEX_ALLOCATION:
     362                            //case NTFS_AT_BITMAP:
     363                            //case NTFS_AT_REPARSE_POINT:
     364                            //case NTFS_AT_EA_INFORMATION:
     365                            //case NTFS_AT_EA:
     366                            //case NTFS_AT_PROPERTY_SET:
     367                            //case NTFS_AT_LOGGED_UTILITY_STREAM:
     368
     369                            default:
     370                                if (cbValue <= 24)
     371                                    Log2(("NTFS:     %.*Rhxs\n", cbValue, pbValue));
     372                                else
     373                                    Log2(("%.*Rhxd\n", cbValue, pbValue));
     374                                break;
     375                        }
     376
     377                    }
     378                    else
     379                        Log2(("NTFS:     !Value is out of bounds!\n"));
     380                }
     381                else if (RT_MAX(cbAttrib, NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED) <= cbMaxAttrib)
     382                {
     383                    Log2(("NTFS:     VNC range          %#RX64 .. %#RX64 (%#RX64 clusters)\n",
     384                          RT_LE2H_U64(pHdr->NonRes.iVcnFirst), RT_LE2H_U64(pHdr->NonRes.iVcnLast),
     385                          RT_LE2H_U64(pHdr->NonRes.iVcnLast) - RT_LE2H_U64(pHdr->NonRes.iVcnFirst) + 1));
     386                    Log2(("NTFS:     cbAllocated        %#RX64 (%Rhcb)\n",
     387                          RT_LE2H_U64(pHdr->NonRes.cbAllocated), RT_LE2H_U64(pHdr->NonRes.cbAllocated)));
     388                    Log2(("NTFS:     cbInitialized      %#RX64 (%Rhcb)\n",
     389                          RT_LE2H_U64(pHdr->NonRes.cbInitialized), RT_LE2H_U64(pHdr->NonRes.cbInitialized)));
     390                    uint16_t const offMappingPairs = RT_LE2H_U16(pHdr->NonRes.offMappingPairs);
     391                    Log2(("NTFS:     offMappingPairs    %#RX16\n", offMappingPairs));
     392                    if (   pHdr->NonRes.abReserved[0] || pHdr->NonRes.abReserved[1]
     393                        || pHdr->NonRes.abReserved[2] || pHdr->NonRes.abReserved[3] || pHdr->NonRes.abReserved[4] )
     394                        Log2(("NTFS:     abReserved         %.7Rhxs\n", pHdr->NonRes.abReserved));
     395                    if (pHdr->NonRes.uCompressionUnit != 0)
     396                        Log2(("NTFS:     Compression unit   2^%u clusters\n", pHdr->NonRes.uCompressionUnit));
     397
     398                    if (   NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED <= cbMaxAttrib
     399                        && NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED <= cbAttrib
     400                        && (   offMappingPairs >= NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED
     401                            || offMappingPairs <  NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED))
     402                        Log2(("NTFS:     cbCompressed       %#RX64 (%Rhcb)\n",
     403                              RT_LE2H_U64(pHdr->NonRes.cbCompressed), RT_LE2H_U64(pHdr->NonRes.cbCompressed)));
     404                    else if (pHdr->NonRes.uCompressionUnit != 0 && pHdr->NonRes.uCompressionUnit != 64)
     405                        Log2(("NTFS:     !Error! Compressed attrib fields are out of bound!\n"));
     406
     407                    if (   offMappingPairs < cbAttrib
     408                        && offMappingPairs >= NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED)
     409                    {
     410                        uint8_t const *pbPairs    = &pbRec[offRec + offMappingPairs];
     411                        uint32_t const cbMaxPairs = cbAttrib - offMappingPairs;
     412                        int64_t iVnc = pHdr->NonRes.iVcnFirst;
     413                        Log2(("NTFS:     Mapping Pairs: %.*Rhxsd\n", cbMaxPairs, pbPairs));
     414                        if (!iVnc && !*pbPairs)
     415                            Log2(("NTFS:         [0]: Empty\n", cbMaxPairs, pbPairs));
     416                        else
     417                        {
     418                            if (iVnc != 0)
     419                                Log2(("NTFS:         [0]: VCN=%#012RX64 L %#012RX64 - not mapped\n", 0, iVnc));
     420                            int64_t  iLnc     = 0;
     421                            uint32_t iPair    = 0;
     422                            uint32_t offPairs = 0;
     423                            while (offPairs < cbMaxPairs)
     424                            {
     425                                /* First byte: 4-bit length of each of the pair values */
     426                                uint8_t const bLengths = pbPairs[offPairs];
     427                                if (!bLengths)
     428                                    break;
     429                                uint8_t const cbRun    = (bLengths & 0x0f) + (bLengths >> 4);
     430                                if (offPairs + cbRun > cbMaxPairs)
     431                                {
     432                                    Log2(("NTFS:         [%d]: run overrun! cbRun=%#x bLengths=%#x offPairs=%#x cbMaxPairs=%#x\n",
     433                                          iPair, cbRun, bLengths, offPairs, cbMaxPairs));
     434                                    break;
     435                                }
     436
     437                                /* Value 1: Number of (virtual) clusters in this run. */
     438                                int64_t cClustersInRun;
     439                                uint8_t cbNum = (bLengths & 0xf);
     440                                if (cbNum)
     441                                {
     442                                    int8_t const *pbNum = (int8_t const *)&pbPairs[offPairs + cbNum]; /* last byte */
     443                                    cClustersInRun = *pbNum--;
     444                                    while (cbNum-- > 1)
     445                                        cClustersInRun = (cClustersInRun << 8) + *pbNum--;
     446                                }
     447                                else
     448                                    cClustersInRun = -1;
     449
     450                                /* Value 2: The logical cluster delta to get to the first cluster in the run. */
     451                                cbNum = bLengths >> 4;
     452                                if (cbNum)
     453                                {
     454                                    int8_t const *pbNum  = (int8_t const *)&pbPairs[offPairs + cbNum + (bLengths & 0xf)]; /* last byte */
     455                                    int64_t cLcnDelta = *pbNum--;
     456                                    while (cbNum-- > 1)
     457                                        cLcnDelta = (cLcnDelta << 8) + *pbNum--;
     458                                    iLnc += cLcnDelta;
     459                                    Log2(("NTFS:         [%d]: VNC=%#012RX64 L %#012RX64 => LNC=%#012RX64\n",
     460                                          iPair, iVnc, cClustersInRun, iLnc));
     461                                }
     462                                else
     463                                    Log2(("NTFS:         [%d]: VNC=%#012RX64 L %#012RX64 => HOLE\n",
     464                                          iPair, iVnc, cClustersInRun));
     465
     466                                /* Advance. */
     467                                iVnc     += cClustersInRun;
     468                                offPairs += 1 + cbRun;
     469                                iPair++;
     470                            }
     471                        }
     472                    }
     473                    else if (   cbAttrib != NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED
     474                             && cbAttrib != NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED)
     475                    {
     476                        Log2(("NTFS:     Warning! Odd non-resident attribute size: %#x!\n", cbAttrib));
     477                        if (cbAttrib >= NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED)
     478                            Log2(("NTFS:     @%05x: %.*Rhxs!\n", offRec + NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED,
     479                                  cbAttrib - NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED,
     480                                  &pbRec[offRec + NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED]));
     481                    }
     482                }
     483                else
     484                    Log2(("NTFS:     !Attrib header is out of bound!\n"));
     485
     486                /* Advance. */
     487                offRec += RT_MAX(cbAttrib, NTFSATTRIBHDR_SIZE_RESIDENT);
     488            }
     489
     490            /* Anything left? */
     491            if (offRec < cbRecUsed)
     492                Log2(("NTFS:   @%#05x: Tail: %.*Rhxs\n", offRec, cbRecUsed - offRec, &pbRec[offRec]));
     493        }
     494        else
     495            Log2(("NTFS:   Unknown record type: %.4Rhxs\n", pFileRec));
     496    }
     497}
     498#endif /* LOG_ENABLED */
    96499
    97500
     
    165568    /** @todo read MFT, find bitmap allocation, implement
    166569     *        rtFsNtfsVol_QueryRangeState. */
     570
     571    PRTFSNTFSMFTREC pRec = rtFsNtfsMftRec_New(pThis, 0);
     572    AssertReturn(pRec, VERR_NO_MEMORY);
     573    pThis->pMft = pRec;
     574
     575    int rc = RTVfsFileReadAt(pThis->hVfsBacking, pThis->uLcnMft << pThis->cClusterShift, pRec->pbRec, pThis->cbMftRecord, NULL);
     576    if (RT_FAILURE(rc))
     577        return RTERRINFO_LOG_SET(pErrInfo, rc, "Error reading MFT record #0");
     578#ifdef LOG_ENABLED
     579    rtfsNtfsMftRec_Log(pRec);
     580#endif
     581
     582    //Log(("MFT#0:\n%.*Rhxd\n", pThis->cbMftRecord, pRec->pbRec));
     583
    167584    return VINF_SUCCESS;
    168585}
     
    189606     */
    190607    PFATBOOTSECTOR pBootSector = (PFATBOOTSECTOR)pvBuf;
    191     int rc = RTVfsFileRead(pThis->hVfsBacking, pBootSector, sizeof(*pBootSector), NULL);
     608    int rc = RTVfsFileReadAt(pThis->hVfsBacking, 0, pBootSector, sizeof(*pBootSector), NULL);
    192609    if (RT_FAILURE(rc))
    193610        return RTERRINFO_LOG_SET(pErrInfo, rc, "Error reading boot sector");
     
    287704        pThis->cbMftRecord = UINT32_C(1) << -pBootSector->Bpb.Ntfs.cClustersPerMftRecord;
    288705    Log2(("NTFS BPB: cbMftRecord=%#x\n", pThis->cbMftRecord));
     706    if (   pThis->cbMftRecord > _32K
     707        || pThis->cbMftRecord < 256)
     708        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT,
     709                                   "Unsupported NTFS MFT record size: %#x", pThis->cbMftRecord);
    289710
    290711    /* NTFS BPB: Index block size */
     
    319740{
    320741    AssertPtrReturn(phVfs, VERR_INVALID_POINTER);
    321     AssertReturn(!(fMntFlags & RTVFSMNT_F_VALID_MASK), VERR_INVALID_FLAGS);
     742    AssertReturn(!(fMntFlags & ~RTVFSMNT_F_VALID_MASK), VERR_INVALID_FLAGS);
    322743    AssertReturn(!fNtfsFlags, VERR_INVALID_FLAGS);
    323744
     
    476897RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainNtfsVolReg, rtVfsChainNtfsVolReg);
    477898
    478 
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