Changeset 69861 in vbox for trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp
- Timestamp:
- Nov 28, 2017 7:01:35 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp
r69849 r69861 33 33 34 34 #include <iprt/asm.h> 35 #include <iprt/avl.h> 35 36 #include <iprt/assert.h> 36 37 #include <iprt/file.h> … … 46 47 * Structures and Typedefs * 47 48 *********************************************************************************************************************************/ 49 /** Pointer to the instance data for a NTFS volume. */ 50 typedef struct RTFSNTFSVOL *PRTFSNTFSVOL; 51 /** Pointer to a NTFS MFT record. */ 52 typedef struct RTFSNTFSMFTREC *PRTFSNTFSMFTREC; 53 54 /** 55 * NTFS MFT record. 56 */ 57 typedef 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; 48 80 49 81 /** … … 91 123 uint64_t uSerialNo; 92 124 125 /** Pointer to the MFT record for the MFT. */ 126 PRTFSNTFSMFTREC pMft; 127 128 /** Root of the MFT record tree (RTFSNTFSMFTREC). */ 129 AVLU64TREE MftRoot; 93 130 } RTFSNTFSVOL; 94 /** Pointer to the instance data for a NTFS volume. */ 95 typedef RTFSNTFSVOL *PRTFSNTFSVOL; 131 132 133 static 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 153 static 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 168 static uint32_t rtFsNtfsMftRec_Retain(PRTFSNTFSMFTREC pThis) 169 { 170 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs); 171 Assert(cRefs < 64); 172 return cRefs; 173 } 174 175 176 static 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 */ 192 static 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 */ 96 499 97 500 … … 165 568 /** @todo read MFT, find bitmap allocation, implement 166 569 * 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 167 584 return VINF_SUCCESS; 168 585 } … … 189 606 */ 190 607 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); 192 609 if (RT_FAILURE(rc)) 193 610 return RTERRINFO_LOG_SET(pErrInfo, rc, "Error reading boot sector"); … … 287 704 pThis->cbMftRecord = UINT32_C(1) << -pBootSector->Bpb.Ntfs.cClustersPerMftRecord; 288 705 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); 289 710 290 711 /* NTFS BPB: Index block size */ … … 319 740 { 320 741 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); 322 743 AssertReturn(!fNtfsFlags, VERR_INVALID_FLAGS); 323 744 … … 476 897 RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainNtfsVolReg, rtVfsChainNtfsVolReg); 477 898 478
Note:
See TracChangeset
for help on using the changeset viewer.