Changeset 69861 in vbox
- Timestamp:
- Nov 28, 2017 7:01:35 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119307
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/formats/ntfs.h
r69849 r69861 40 40 41 41 42 /** @} */ 43 42 /** @name NTFS_MFT_IDX_XXX - Predefined MFT indexes. 43 * @{ */ 44 #define NTFS_MFT_IDX_MFT 0 /**< The MFT itself. */ 45 #define NTFS_MFT_IDX_MFT_MIRROR 1 /**< Mirror MFT (partial?). */ 46 #define NTFS_MFT_IDX_LOG_FILE 2 /**< Journalling log. */ 47 #define NTFS_MFT_IDX_VOLUME 3 /**< Volume attributes. */ 48 #define NTFS_MFT_IDX_ATTRIB_DEF 4 /**< Attribute definitions. */ 49 #define NTFS_MFT_IDX_ROOT 5 /**< The root directory. */ 50 #define NTFS_MFT_IDX_BITMAP 6 /**< Allocation bitmap. */ 51 #define NTFS_MFT_IDX_BOOT 7 /**< The boot sector. */ 52 #define NTFS_MFT_IDX_BAD_CLUSTER 8 /**< Bad cluster table. */ 53 #define NTFS_MFT_IDX_SECURITY 9 /**< Shared security descriptors (w2k and later). */ 54 #define NTFS_MFT_IDX_UP_CASE 10 /**< Unicode upper case table. */ 55 #define NTFS_MFT_IDX_EXTEND 11 /**< Directory containing further system files. */ 56 #define NTFS_MFT_IDX_FIRST_USER 16 /**< The first user file. */ 57 /** @} */ 58 59 /** 60 * NTFS MFT record reference. 61 */ 62 typedef union NTFSMFTREF 63 { 64 /** unsigned 64-bit view. */ 65 uint64_t u64; 66 /** unsigned 32-bit view. */ 67 uint32_t au32[2]; 68 /** unsigned 16-bit view. */ 69 uint16_t au16[4]; 70 71 /** Structured view. */ 72 struct 73 { 74 /** Index of the master file table record. */ 75 uint64_t idxMft : 48; 76 /** MFT record reuse sequence number (for catching dangling references). */ 77 uint64_t uRecReuseSeqNo : 16; 78 } RT_UNION_NM(s); 79 } NTFSMFTREF; 80 AssertCompileSize(NTFSMFTREF, 8); 81 /** Pointer to a NTFS MFT record reference. */ 82 typedef NTFSMFTREF *PNTFSMFTREF; 83 /** Pointer to a const NTFS MFT record reference. */ 84 typedef NTFSMFTREF const *PCNTFSMFTREF; 85 86 /** @name NTFSMFTREF_GET_IDX 87 * Gets the MFT index number from a MFT reference. */ 88 /** @name NTFSMFTREF_GET_SEQ 89 * Gets the MFT reuse sequence number from a MFT reference. */ 90 /** @name NTFSMFTREF_SET_IDX 91 * Sets the MFT index number of a MFT reference. */ 92 /** @name NTFSMFTREF_SET_SEQ 93 * Sets the MFT reuse sequence number of a MFT reference. */ 94 /** @name NTFSMFTREF_SET 95 * Sets the values of a MFT reference. */ 96 #ifdef RT_LITTLE_ENDIAN 97 # define NTFSMFTREF_GET_IDX(a_pMftRef) ((a_pMftRef)->RT_UNION_NM(s.)idxMft) 98 # define NTFSMFTREF_GET_SEQ(a_pMftRef) ((a_pMftRef)->RT_UNION_NM(s.)uRecReuseSeqNo) 99 # define NTFSMFTREF_SET_SEQ(a_pMftRef, a_uValue) do { (a_pMftRef)->RT_UNION_NM(s.)uRecReuseSeqNo = (a_uValue); } while (0) 100 # define NTFSMFTREF_SET_IDX(a_pMftRef, a_uValue) do { (a_pMftRef)->RT_UNION_NM(s.)idxMft = (a_uValue); } while (0) 101 # define NTFSMFTREF_SET(a_pMftRef, a_idx, a_uSeq) \ 102 do { \ 103 (a_pMftRef)->RT_UNION_NM(s.)idxMft = (a_idx); \ 104 (a_pMftRef)->RT_UNION_NM(s.)uRecReuseSeqNo = (a_uSeq); \ 105 } while (0) 106 #else 107 # define NTFSMFTREF_GET_IDX(a_pMftRef) (RT_LE2H_U64((a_pMftRef)->u64) & UINT64_C(0x0000ffffffffffff)) 108 # define NTFSMFTREF_GET_SEQ(a_pMftRef) RT_LE2H_U16((uint16_t)(a_pMftRef)->u64) 109 # define NTFSMFTREF_SET_SEQ(a_pMftRef, a_uValue) do { (a_pMftRef)->au16[3] = RT_H2LE_U16(a_uValue); } while (0) 110 # define NTFSMFTREF_SET_IDX(a_pMftRef, a_uValue) \ 111 do { \ 112 (a_pMftRef)->au32[0] = RT_H2LE_U32((uint32_t)(a_uValue)); \ 113 (a_pMftRef)->au16[2] = RT_H2LE_U16((uint16_t)((a_uValue) >> 32)); \ 114 } while (0) 115 # define NTFSMFTREF_SET(a_pMftRef, a_idx, a_uSeq) \ 116 do { \ 117 (a_pMftRef)->au32[0] = RT_H2LE_U32((uint32_t)(a_idx)); \ 118 (a_pMftRef)->au16[2] = RT_H2LE_U16((uint16_t)((a_idx) >> 32)); \ 119 (a_pMftRef)->au16[3] = RT_H2LE_U16((uint16_t)(a_uSeq)); \ 120 } while (0) 44 121 #endif 45 122 46 123 124 /** 125 * NTFS record header. 126 */ 127 typedef struct NTFSRECHDR 128 { 129 /** Magic number (usually ASCII). */ 130 uint32_t uMagic; 131 /** Offset of the update sequence array from the start of the record. */ 132 uint16_t offUpdateSeqArray; 133 /** Number of entries in the update sequence array. (uint16_t sized entries) */ 134 uint16_t cUpdateSeqEntries; 135 } NTFSRECHDR; 136 AssertCompileSize(NTFSRECHDR, 8); 137 /** Pointer to a NTFS record header. */ 138 typedef NTFSRECHDR *PNTFSRECHDR; 139 /** Pointer to a const NTFS record header. */ 140 typedef NTFSRECHDR const *PCNTFSRECHDR; 141 142 143 /** 144 * NTFS file record (in the MFT). 145 */ 146 typedef struct NTFSRECFILE 147 { 148 /** 0x00: Header with NTFSREC_MAGIC_FILE. */ 149 NTFSRECHDR Hdr; 150 /** 0x08: Log file sequence number. */ 151 uint64_t uLsn; 152 /** 0x10: MFT record reuse sequence number (for dangling MFT references). */ 153 uint16_t uRecReuseSeqNo; 154 /** 0x12: Number of hard links. */ 155 uint16_t cLinks; 156 /** 0x14: Offset of the first attribute (relative to start of record). */ 157 uint16_t offFirstAttrib; 158 /** 0x16: Record flags (NTFSRECFILE_F_XXX). */ 159 uint16_t fFlags; 160 /** 0x18: Number of byte in use in this MFT record. */ 161 uint32_t cbRecUsed; 162 /** 0x1c: The MFT record size. */ 163 uint32_t cbRecSize; 164 /** 0x20: Reference to the base MFT record. */ 165 NTFSMFTREF BaseMftRec; 166 /** 0x28: Next attribute instance number. */ 167 uint16_t idNextAttrib; 168 /** 0x2a: Padding if NTFS 3.1+, update sequence array if older. */ 169 uint16_t uPaddingOrUsa; 170 /** 0x2c: MFT index of this record. */ 171 uint32_t idxMftSelf; 172 } NTFSRECFILE; 173 AssertCompileSize(NTFSRECFILE, 0x30); 174 /** Pointer to a NTFS file record. */ 175 typedef NTFSRECFILE *PNTFSRECFILE; 176 /** Pointer to a const NTFS file record. */ 177 typedef NTFSRECFILE const *PCNTFSRECFILE; 178 179 180 /** NTFS 'FILE' record magic value. */ 181 #define NTFSREC_MAGIC_FILE RT_H2LE_U32_C(UINT32_C(0x454c4946)) 182 183 /** @name NTFSRECFILE_F_XXX - NTFSRECFILE::fFlags. 184 * @{ */ 185 /** MFT record is in use. */ 186 #define NTFSRECFILE_F_IN_USE RT_H2LE_U16_C(UINT16_C(0x0001)) 187 /** Directory record. */ 188 #define NTFSRECFILE_F_DIRECTORY RT_H2LE_U16_C(UINT16_C(0x0002)) 189 /** @} */ 190 191 192 /** @name NTFS_AT_XXX - Attribute types 193 * @{ */ 194 #define NTFS_AT_UNUSED RT_H2LE_U32_C(UINT32_C(0x00000000)) 195 /** NTFSATSTDINFO */ 196 #define NTFS_AT_STANDARD_INFORMATION RT_H2LE_U32_C(UINT32_C(0x00000010)) 197 #define NTFS_AT_ATTRIBUTE_LIST RT_H2LE_U32_C(UINT32_C(0x00000020)) 198 /** PCNTFSATFILENAME */ 199 #define NTFS_AT_FILENAME RT_H2LE_U32_C(UINT32_C(0x00000030)) 200 #define NTFS_AT_OBJECT_ID RT_H2LE_U32_C(UINT32_C(0x00000040)) 201 #define NTFS_AT_SECURITY_DESCRIPTOR RT_H2LE_U32_C(UINT32_C(0x00000050)) 202 #define NTFS_AT_VOLUME_NAME RT_H2LE_U32_C(UINT32_C(0x00000060)) 203 #define NTFS_AT_VOLUME_INFORMATION RT_H2LE_U32_C(UINT32_C(0x00000070)) 204 #define NTFS_AT_DATA RT_H2LE_U32_C(UINT32_C(0x00000080)) 205 #define NTFS_AT_INDEX_ROOT RT_H2LE_U32_C(UINT32_C(0x00000090)) 206 #define NTFS_AT_INDEX_ALLOCATION RT_H2LE_U32_C(UINT32_C(0x000000a0)) 207 #define NTFS_AT_BITMAP RT_H2LE_U32_C(UINT32_C(0x000000b0)) 208 #define NTFS_AT_REPARSE_POINT RT_H2LE_U32_C(UINT32_C(0x000000c0)) 209 #define NTFS_AT_EA_INFORMATION RT_H2LE_U32_C(UINT32_C(0x000000d0)) 210 #define NTFS_AT_EA RT_H2LE_U32_C(UINT32_C(0x000000e0)) 211 #define NTFS_AT_PROPERTY_SET RT_H2LE_U32_C(UINT32_C(0x000000f0)) 212 #define NTFS_AT_LOGGED_UTILITY_STREAM RT_H2LE_U32_C(UINT32_C(0x00000100)) 213 #define NTFS_AT_FIRST_USER_DEFINED RT_H2LE_U32_C(UINT32_C(0x00001000)) 214 #define NTFS_AT_END RT_H2LE_U32_C(UINT32_C(0xffffffff)) 215 /** @} */ 216 217 /** @name NTFS_AF_XXX - Attribute flags. 218 * @{ */ 219 #define NTFS_AF_COMPR_FMT_NONE UINT16_C(0x0000) 220 #define NTFS_AF_COMPR_FMT_LZNT1 UINT16_C(0x0001) /**< See RtlCompressBuffer / COMPRESSION_FORMAT_LZNT1. */ 221 #define NTFS_AF_COMPR_FMT_XPRESS UINT16_C(0x0002) /**< See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */ 222 #define NTFS_AF_COMPR_FMT_XPRESS_HUFF UINT16_C(0x0003) /**< See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */ 223 #define NTFS_AF_COMPR_FMT_MASK UINT16_C(0x00ff) 224 #define NTFS_AF_ENCRYPTED UINT16_C(0x4000) 225 #define NTFS_AF_SPARSE UINT16_C(0x8000) 226 /** @} */ 227 228 /** 229 * NTFS attribute header. 230 * 231 * This has three forms: 232 * - Resident 233 * - Non-resident, no compression 234 * - Non-resident, compressed. 235 * 236 * Each form translates to a different header size. 237 */ 238 typedef struct NTFSATTRIBHDR 239 { 240 /** 0x00: Attribute type (NTFS_AT_XXX). */ 241 uint32_t uAttrType; 242 /** 0x04: Length of this attribute (resident part). */ 243 uint32_t cbAttrib; 244 /** 0x08: Set (1) if non-resident attribute, 0 if resident. */ 245 uint8_t fNonResident; 246 /** 0x09: Attribute name length (can be zero). */ 247 uint8_t cwcName; 248 /** 0x0a: Offset of the name string (relative to the start of this header). */ 249 uint16_t offName; 250 /** 0x0c: NTFS_AF_XXX. */ 251 uint16_t fFlags; 252 /** 0x0e: Attribute instance number. Unique within the MFT record. */ 253 uint16_t idAttrib; 254 /** 0x10: Data depending on the fNonResident member value. */ 255 union 256 { 257 /** Resident attributes. */ 258 struct 259 { 260 /** 0x10: Attribute value length. */ 261 uint32_t cbValue; 262 /** 0x14: Offset of the value (relative to the start of this header). */ 263 uint16_t offValue; 264 /** 0x16: NTFS_RES_AF_XXX. */ 265 uint8_t fFlags; 266 /** 0x17: Reserved. */ 267 uint8_t bReserved; 268 } Res; 269 270 /** Non-resident attributes. */ 271 struct 272 { 273 /** 0x10: The first virtual cluster containing data. */ 274 int64_t iVcnFirst; 275 /** 0x18: The last virtual cluster containing data (inclusive). */ 276 int64_t iVcnLast; 277 /** 0x20: Offset of the mapping pair program. This program gives us a mapping 278 * between VNC and LCN for the attribute value. */ 279 uint16_t offMappingPairs; 280 /** 0x22: Power of two compression unit size in clusters (cbCluster << uCompessionUnit). 281 * Zero means uncompressed. */ 282 uint8_t uCompressionUnit; 283 /** 0x23: Reserved */ 284 uint8_t abReserved[5]; 285 /** 0x28: Allocated size. */ 286 int64_t cbAllocated; 287 /** 0x30: Initialized size. */ 288 int64_t cbInitialized; 289 /** 0x38: Compressed size if compressed, otherwise absent. */ 290 int64_t cbCompressed; 291 } NonRes; 292 } RT_UNION_NM(u); 293 } NTFSATTRIBHDR; 294 AssertCompileSize(NTFSATTRIBHDR, 0x40); 295 AssertCompileMemberOffset(NTFSATTRIBHDR, RT_UNION_NM(u.) Res, 0x10); 296 AssertCompileMemberOffset(NTFSATTRIBHDR, RT_UNION_NM(u.) Res.bReserved, 0x17); 297 AssertCompileMemberOffset(NTFSATTRIBHDR, RT_UNION_NM(u.) NonRes, 0x10); 298 AssertCompileMemberOffset(NTFSATTRIBHDR, RT_UNION_NM(u.) NonRes.cbCompressed, 0x38); 299 /** Pointer to a NTFS attribute header. */ 300 typedef NTFSATTRIBHDR *PNTFSATTRIBHDR; 301 /** Pointer to a const NTFS attribute header. */ 302 typedef NTFSATTRIBHDR const *PCNTFSATTRIBHDR; 303 304 /** @name NTFSATTRIBHDR_SIZE_XXX - Attribute header sizes. 305 * @{ */ 306 /** Attribute header size for resident values. */ 307 #define NTFSATTRIBHDR_SIZE_RESIDENT (0x18) 308 /** Attribute header size for uncompressed non-resident values. */ 309 #define NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED (0x38) 310 /** Attribute header size for compressed non-resident values. */ 311 #define NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED (0x40) 312 /** @} */ 313 314 /** 315 * NTFS standard file info attribute (NTFS_AT_STANDARD_INFORMATION). 316 */ 317 typedef struct NTFSATSTDINFO 318 { 319 /** 0x00: Creation timestamp. */ 320 int64_t iCreationTime; 321 /** 0x08: Last data modification timestamp. */ 322 int64_t iLastDataModTime; 323 /** 0x10: Last MFT record modification timestamp. */ 324 int64_t iLastMftModTime; 325 /** 0x18: Last access timestamp. */ 326 int64_t iLastAccessTime; 327 /** 0x20: File attributes. */ 328 uint32_t fFileAttribs; 329 /** 0x24: Maximum number of file versions allowed. 330 * @note NTFS 3.x, padding in 1.2 */ 331 uint32_t cMaxFileVersions; 332 /** 0x28: Current file version number. 333 * @note NTFS 3.x, padding in 1.2 */ 334 uint32_t uFileVersion; 335 /** 0x2c: Class ID (whatever that is). 336 * @note NTFS 3.x, padding in 1.2 */ 337 uint32_t idClass; 338 /** 0x30: Owner ID. 339 * Translated via $Q index in NTFS_MFT_IDX_EXTENDED/$Quota. 340 * @note NTFS 3.x, not present in 1.2 */ 341 uint32_t idOwner; 342 /** 0x34: Security ID. Translated via $SII index and $SDS data stream in 343 * NTFS_MFT_IDX_SECURITY. 344 * @note NTFS 3.x, not present in 1.2 */ 345 uint32_t idSecurity; 346 /** 0x38: Total quota charged for this file. 347 * @note NTFS 3.x, not present in 1.2 */ 348 uint64_t cbQuotaChared; 349 /** 0x40: Last update sequence number, index into $UsnJrnl. 350 * @note NTFS 3.x, not present in 1.2 */ 351 uint64_t idxUpdateSequence; 352 } NTFSATSTDINFO; 353 AssertCompileSize(NTFSATSTDINFO, 0x48); 354 /** Pointer to NTFS standard file info. */ 355 typedef NTFSATSTDINFO *PNTFSATSTDINFO; 356 /** Pointer to const NTFS standard file info. */ 357 typedef NTFSATSTDINFO const *PCNTFSATSTDINFO; 358 359 /** The size of NTFSATSTDINFO in NTFS v1.2 and earlier. */ 360 #define NTFSATSTDINFO_SIZE_NTFS_V12 (0x30) 361 362 /** @name NTFS_FA_XXX - NTFS file attributes. 363 * @{ */ 364 #define NTFS_FA_READONLY UINT32_C(0x00000001) 365 #define NTFS_FA_HIDDEN UINT32_C(0x00000002) 366 #define NTFS_FA_SYSTEM UINT32_C(0x00000004) 367 #define NTFS_FA_DIRECTORY UINT32_C(0x00000010) 368 #define NTFS_FA_ARCHIVE UINT32_C(0x00000020) 369 #define NTFS_FA_DEVICE UINT32_C(0x00000040) 370 #define NTFS_FA_NORMAL UINT32_C(0x00000080) 371 #define NTFS_FA_TEMPORARY UINT32_C(0x00000100) 372 #define NTFS_FA_SPARSE_FILE UINT32_C(0x00000200) 373 #define NTFS_FA_REPARSE_POINT UINT32_C(0x00000400) 374 #define NTFS_FA_COMPRESSED UINT32_C(0x00000800) 375 #define NTFS_FA_OFFLINE UINT32_C(0x00001000) 376 #define NTFS_FA_NOT_CONTENT_INDEXED UINT32_C(0x00002000) 377 #define NTFS_FA_ENCRYPTED UINT32_C(0x00004000) 378 #define NTFS_FA_VALID_FLAGS UINT32_C(0x00007fb7) 379 #define NTFS_FA_VALID_SET_FLAGS UINT32_C(0x000031a7) 380 #define NTFS_FA_DUP_FILE_NAME_INDEX_PRESENT UINT32_C(0x10000000) /**< ?? */ 381 #define NTFS_FA_DUP_VIEW_INDEX_PRESENT UINT32_C(0x20000000) /**< ?? */ 382 /** @} */ 383 384 385 386 /** 387 * NTFS filename attribute (NTFS_AT_FILENAME). 388 */ 389 typedef struct NTFSATFILENAME 390 { 391 /** 0x00: The parent directory MFT record. */ 392 NTFSMFTREF ParentDirMftRec; 393 /** 0x08: Creation timestamp. */ 394 int64_t iCreationTime; 395 /** 0x10: Last data modification timestamp. */ 396 int64_t iLastDataModTime; 397 /** 0x18: Last MFT record modification timestamp. */ 398 int64_t iLastMftModTime; 399 /** 0x20: Last access timestamp. */ 400 int64_t iLastAccessTime; 401 /** 0x28: Allocated disk space for the unnamed data attribute. */ 402 int64_t cbAllocated; 403 /** 0x30: Actual size of unnamed data attribute. */ 404 int64_t cbData; 405 /** 0x38: File attributes. */ 406 uint32_t fFileAttribs; 407 union 408 { 409 /** 0x3c: Packed EA length. */ 410 uint16_t cbPackedEas; 411 /** 0x3c: Reparse tag, if no EAs. */ 412 uint32_t uReparseTag; 413 }; 414 /** 0x40: Filename length in unicode chars. */ 415 uint8_t cwcFilename; 416 /** 0x41: Filename type (NTFS_FILENAME_T_XXX). */ 417 uint8_t fFilenameType; 418 /** 0x42: The filename. */ 419 RTUTF16 wszFilename[RT_FLEXIBLE_ARRAY]; 420 } NTFSATFILENAME; 421 AssertCompileMemberOffset(NTFSATFILENAME, cbData, 0x30); 422 AssertCompileMemberOffset(NTFSATFILENAME, cbPackedEas, 0x3c); 423 AssertCompileMemberOffset(NTFSATFILENAME, uReparseTag, 0x3c); 424 AssertCompileMemberOffset(NTFSATFILENAME, wszFilename, 0x42); 425 /** Pointer to a NTFS filename attribute. */ 426 typedef NTFSATFILENAME *PNTFSATFILENAME; 427 /** Pointer to a const NTFS filename attribute. */ 428 typedef NTFSATFILENAME const *PCNTFSATFILENAME; 429 430 /** @name NTFS_FILENAME_T_XXX - filename types 431 * @{ */ 432 #define NTFS_FILENAME_T_POSIX 0 433 #define NTFS_FILENAME_T_WINDOWS 1 434 #define NTFS_FILENAME_T_DOS 2 435 #define NTFS_FILENAME_T_WINDOWS_AND_DSO 3 436 /** @} */ 437 438 /** @} */ 439 440 #endif 441 -
trunk/src/VBox/Runtime/common/fs/ext2vfs.cpp
r69845 r69861 238 238 { 239 239 AssertPtrReturn(phVfs, VERR_INVALID_POINTER); 240 AssertReturn(!(fMntFlags & RTVFSMNT_F_VALID_MASK), VERR_INVALID_FLAGS);240 AssertReturn(!(fMntFlags & ~RTVFSMNT_F_VALID_MASK), VERR_INVALID_FLAGS); 241 241 AssertReturn(!fExtFlags, VERR_INVALID_FLAGS); 242 242 -
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 -
trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp
r69844 r69861 3008 3008 if (RT_SUCCESS(rc)) 3009 3009 { 3010 if (pPath->cComponents > 0) 3010 /* 3011 * Tranverse the path, resolving the parent node. 3012 * We'll do the symbolic link checking here with help of pfnOpen. 3013 */ 3014 RTVFSDIRINTERNAL *pVfsParentDir; 3015 rc = rtVfsDirTraverseToParent(pThis, pPath, (fFlags & RTPATH_F_NO_SYMLINKS) | RTPATH_F_ON_LINK, &pVfsParentDir); 3016 if (RT_SUCCESS(rc)) 3011 3017 { 3012 RTVFSDIRINTERNAL *pVfsParentDir; 3013 rc = rtVfsDirTraverseToParent(pThis, pPath, fFlags, &pVfsParentDir); 3014 if (RT_SUCCESS(rc)) 3018 /* 3019 * Do the opening. Loop if we need to follow symbolic links. 3020 */ 3021 uint32_t fObjFlags = RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_CREATE_NOTHING; 3022 for (uint32_t cLoops = 1;; cLoops++) 3015 3023 { 3016 /* 3017 * Call the query method on the parent directory. 3018 */ 3019 /** @todo symlink race condition here :/ */ 3024 /* If we end with a directory slash, adjust open flags. */ 3025 if (pPath->fDirSlash) 3026 { 3027 fObjFlags &= ~RTVFSOBJ_F_OPEN_ANY | RTVFSOBJ_F_OPEN_DIRECTORY; 3028 if ((fObjFlags & RTVFSOBJ_F_CREATE_MASK) != RTVFSOBJ_F_CREATE_DIRECTORY) 3029 fObjFlags = (fObjFlags & ~RTVFSOBJ_F_CREATE_MASK) | RTVFSOBJ_F_CREATE_NOTHING; 3030 } 3031 if (fObjFlags & RTPATH_F_FOLLOW_LINK) 3032 fObjFlags |= RTVFSOBJ_F_OPEN_SYMLINK; 3033 3034 /* Do the querying. If pfnQueryEntryInfo is available, we use it first, 3035 falling back on pfnOpen in case of symbolic links that needs following. */ 3020 3036 const char *pszEntryName = &pPath->szPath[pPath->aoffComponents[pPath->cComponents - 1]]; 3021 RTVfsLockAcquireRead(pVfsParentDir->Base.hLock); 3022 rc = pVfsParentDir->pOps->pfnQueryEntryInfo(pVfsParentDir->Base.pvThis, pszEntryName, pObjInfo, enmAddAttr); 3023 RTVfsLockReleaseRead(pVfsParentDir->Base.hLock); 3024 3025 RTVfsDirRelease(pVfsParentDir); 3037 if (pVfsParentDir->pOps->pfnQueryEntryInfo) 3038 { 3039 RTVfsLockAcquireRead(pVfsParentDir->Base.hLock); 3040 rc = pVfsParentDir->pOps->pfnQueryEntryInfo(pVfsParentDir->Base.pvThis, pszEntryName, pObjInfo, enmAddAttr); 3041 RTVfsLockReleaseRead(pVfsParentDir->Base.hLock); 3042 if (RT_FAILURE(rc)) 3043 break; 3044 if ( !RTFS_IS_SYMLINK(pObjInfo->Attr.fMode) 3045 || !(fFlags & RTPATH_F_FOLLOW_LINK)) 3046 { 3047 if ( (fObjFlags & RTVFSOBJ_F_OPEN_MASK) != RTVFSOBJ_F_OPEN_ANY 3048 && RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode)) 3049 rc = VERR_NOT_A_DIRECTORY; 3050 break; 3051 } 3052 } 3053 3054 RTVFSOBJ hVfsObj; 3055 RTVfsLockAcquireWrite(pVfsParentDir->Base.hLock); 3056 rc = pVfsParentDir->pOps->pfnOpen(pVfsParentDir->Base.pvThis, pszEntryName, 3057 RTFILE_O_ACCESS_ATTR_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, 3058 fObjFlags, &hVfsObj); 3059 RTVfsLockReleaseWrite(pVfsParentDir->Base.hLock); 3060 if (RT_FAILURE(rc)) 3061 break; 3062 3063 /* If we don't follow links or this wasn't a link we just have to do the query and we're done. */ 3064 if ( !(fObjFlags & RTPATH_F_FOLLOW_LINK) 3065 || RTVfsObjGetType(hVfsObj) != RTVFSOBJTYPE_SYMLINK) 3066 { 3067 rc = RTVfsObjQueryInfo(hVfsObj, pObjInfo, enmAddAttr); 3068 RTVfsObjRelease(hVfsObj); 3069 break; 3070 } 3071 3072 /* Follow symbolic link. */ 3073 if (cLoops < RTVFS_MAX_LINKS) 3074 rc = rtVfsDirFollowSymlinkObjToParent(&pVfsParentDir, hVfsObj, pPath, fObjFlags & RTPATH_F_MASK); 3075 else 3076 rc = VERR_TOO_MANY_SYMLINKS; 3077 RTVfsObjRelease(hVfsObj); 3078 if (RT_FAILURE(rc)) 3079 break; 3026 3080 } 3027 else 3028 rc = VERR_INVALID_PARAMETER; 3029 } 3030 /* 3031 * The path boils down to '.' so just query the directory. 3032 */ 3033 else 3034 { 3035 RTVfsLockAcquireRead(pThis->Base.hLock); 3036 rc = pThis->Base.pOps->pfnQueryInfo(pThis->Base.pvThis, pObjInfo, enmAddAttr); 3037 RTVfsLockReleaseRead(pThis->Base.hLock); 3081 3082 RTVfsDirRelease(pVfsParentDir); 3038 3083 } 3039 3084 RTVfsParsePathFree(pPath); -
trunk/src/VBox/Runtime/common/vfs/vfsmount.cpp
r69853 r69861 35 35 #include <iprt/assert.h> 36 36 #include <iprt/err.h> 37 #include <iprt/file.h> 37 38 #include <iprt/fsvfs.h> 38 39 #include <iprt/mem.h> 39 40 #include <iprt/log.h> 40 41 #include <iprt/string.h> 42 #include <iprt/vfslowlevel.h> 41 43 42 44 #include <iprt/formats/fat.h> … … 422 424 423 425 if (rtVfsMountIsNtfs(&pBuf->Bootsector)) 424 return RT ERRINFO_LOG_SET(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT, "NTFS not yet supported");426 return RTFsNtfsVolOpen(hVfsFileIn, fFlags, 0 /*fNtfsFlags*/, phVfs, pErrInfo); 425 427 426 428 if (rtVfsMountIsHpfs(&pBuf->Bootsector, hVfsFileIn, pBuf2)) … … 462 464 } 463 465 466 467 /** 468 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnValidate} 469 */ 470 static DECLCALLBACK(int) rtVfsChainMountVol_Validate(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec, 471 PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError, PRTERRINFO pErrInfo) 472 { 473 RT_NOREF(pProviderReg); 474 475 /* 476 * Basic checks. 477 */ 478 if (pElement->enmTypeIn != RTVFSOBJTYPE_FILE) 479 return pElement->enmTypeIn == RTVFSOBJTYPE_INVALID ? VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT : VERR_VFS_CHAIN_TAKES_FILE; 480 if ( pElement->enmType != RTVFSOBJTYPE_VFS 481 && pElement->enmType != RTVFSOBJTYPE_DIR) 482 return VERR_VFS_CHAIN_ONLY_DIR_OR_VFS; 483 if (pElement->cArgs > 1) 484 return VERR_VFS_CHAIN_AT_MOST_ONE_ARG; 485 486 /* 487 * Parse the flag if present, save in pElement->uProvider. 488 */ 489 bool fReadOnly = (pSpec->fOpenFile & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ; 490 if (pElement->cArgs > 0) 491 { 492 const char *psz = pElement->paArgs[0].psz; 493 if (*psz) 494 { 495 if (!strcmp(psz, "ro")) 496 fReadOnly = true; 497 else if (!strcmp(psz, "rw")) 498 fReadOnly = false; 499 else 500 { 501 *poffError = pElement->paArgs[0].offSpec; 502 return RTErrInfoSet(pErrInfo, VERR_VFS_CHAIN_INVALID_ARGUMENT, "Expected 'ro' or 'rw' as argument"); 503 } 504 } 505 } 506 507 pElement->uProvider = fReadOnly ? RTVFSMNT_F_READ_ONLY : 0; 508 return VINF_SUCCESS; 509 } 510 511 512 /** 513 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnInstantiate} 514 */ 515 static DECLCALLBACK(int) rtVfsChainMountVol_Instantiate(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec, 516 PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj, 517 PRTVFSOBJ phVfsObj, uint32_t *poffError, PRTERRINFO pErrInfo) 518 { 519 RT_NOREF(pProviderReg, pSpec, poffError); 520 521 int rc; 522 RTVFSFILE hVfsFileIn = RTVfsObjToFile(hPrevVfsObj); 523 if (hVfsFileIn != NIL_RTVFSFILE) 524 { 525 RTVFS hVfs; 526 rc = RTVfsMountVol(hVfsFileIn, (uint32_t)pElement->uProvider, &hVfs, pErrInfo); 527 RTVfsFileRelease(hVfsFileIn); 528 if (RT_SUCCESS(rc)) 529 { 530 *phVfsObj = RTVfsObjFromVfs(hVfs); 531 RTVfsRelease(hVfs); 532 if (*phVfsObj != NIL_RTVFSOBJ) 533 return VINF_SUCCESS; 534 rc = VERR_VFS_CHAIN_CAST_FAILED; 535 } 536 } 537 else 538 rc = VERR_VFS_CHAIN_CAST_FAILED; 539 return rc; 540 } 541 542 543 /** 544 * @interface_method_impl{RTVFSCHAINELEMENTREG,pfnCanReuseElement} 545 */ 546 static DECLCALLBACK(bool) rtVfsChainMountVol_CanReuseElement(PCRTVFSCHAINELEMENTREG pProviderReg, 547 PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement, 548 PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement) 549 { 550 RT_NOREF(pProviderReg, pSpec, pReuseSpec); 551 if ( pElement->paArgs[0].uProvider == pReuseElement->paArgs[0].uProvider 552 || !pReuseElement->paArgs[0].uProvider) 553 return true; 554 return false; 555 } 556 557 558 /** VFS chain element 'file'. */ 559 static RTVFSCHAINELEMENTREG g_rtVfsChainMountVolReg = 560 { 561 /* uVersion = */ RTVFSCHAINELEMENTREG_VERSION, 562 /* fReserved = */ 0, 563 /* pszName = */ "mount", 564 /* ListEntry = */ { NULL, NULL }, 565 /* pszHelp = */ "Open a file system, requires a file object on the left side.\n" 566 "First argument is an optional 'ro' (read-only) or 'rw' (read-write) flag.\n", 567 /* pfnValidate = */ rtVfsChainMountVol_Validate, 568 /* pfnInstantiate = */ rtVfsChainMountVol_Instantiate, 569 /* pfnCanReuseElement = */ rtVfsChainMountVol_CanReuseElement, 570 /* uEndMarker = */ RTVFSCHAINELEMENTREG_VERSION 571 }; 572 573 RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(&g_rtVfsChainMountVolReg, rtVfsChainMountVolReg); 574
Note:
See TracChangeset
for help on using the changeset viewer.