1
1
use crate :: mft:: fast_fixup:: FixupStats ;
2
2
use crate :: mft:: fast_fixup:: apply_fixups_parallel;
3
+ use crate :: mft:: mft_record_iter:: MftRecordIter ;
3
4
use bytes:: Bytes ;
4
5
use eyre:: Context ;
5
6
use std:: fmt:: Debug ;
@@ -10,8 +11,8 @@ use std::time::Instant;
10
11
use thousands:: Separable ;
11
12
use tracing:: debug;
12
13
use tracing:: instrument;
13
- use uom:: si:: f64:: Information ;
14
14
use uom:: si:: information:: byte;
15
+ use uom:: si:: usize:: Information ;
15
16
16
17
pub struct MftFile {
17
18
bytes : Bytes ,
@@ -33,17 +34,18 @@ impl Deref for MftFile {
33
34
}
34
35
impl MftFile {
35
36
pub fn size ( & self ) -> Information {
36
- Information :: new :: < byte > ( self . bytes . len ( ) as f64 )
37
+ Information :: new :: < byte > ( self . bytes . len ( ) )
37
38
}
38
39
pub fn entry_size ( & self ) -> Information {
39
40
if self . len ( ) < 0x20 {
40
- return Information :: new :: < byte > ( 1024.0 ) ;
41
+ return Information :: new :: < byte > ( 1024 ) ;
41
42
}
42
- let size = u32:: from_le_bytes ( [ self [ 0x1C ] , self [ 0x1D ] , self [ 0x1E ] , self [ 0x1F ] ] ) ;
43
+ let size = u32:: from_le_bytes ( [ self [ 0x1C ] , self [ 0x1D ] , self [ 0x1E ] , self [ 0x1F ] ] ) as usize ;
43
44
if size == 0 {
44
- Information :: new :: < byte > ( 1024.0 )
45
+ // Information::new::<byte>(1024)
46
+ panic ! ( "MFT entry size field is zero (invalid/unknown)" ) ;
45
47
} else {
46
- Information :: new :: < byte > ( size as f64 )
48
+ Information :: new :: < byte > ( size)
47
49
}
48
50
}
49
51
pub fn entry_count ( & self ) -> usize {
@@ -64,20 +66,22 @@ impl MftFile {
64
66
debug ! ( "Opened MFT file: {}" , mft_file_path. display( ) ) ;
65
67
66
68
// Determine file size
67
- let file_size_bytes = file
68
- . metadata ( )
69
- . wrap_err_with ( || format ! ( "Failed to get metadata for {}" , mft_file_path. display( ) ) ) ?
70
- . len ( ) as usize ;
71
- let mft_file_size = Information :: new :: < byte > ( file_size_bytes as f64 ) ;
72
- if file_size_bytes < 1024 {
69
+ let mft_file_size = Information :: new :: < byte > (
70
+ file. metadata ( )
71
+ . wrap_err_with ( || {
72
+ format ! ( "Failed to get metadata for {}" , mft_file_path. display( ) )
73
+ } ) ?
74
+ . len ( ) as usize ,
75
+ ) ;
76
+ if mft_file_size < Information :: new :: < byte > ( 1024 ) {
73
77
eyre:: bail!( "MFT file too small: {}" , mft_file_path. display( ) ) ;
74
78
}
75
79
76
80
// Read all bytes
77
81
debug ! ( "Reading cached bytes: {}" , mft_file_size. get_human( ) ) ;
78
82
let read_start = Instant :: now ( ) ;
79
83
let bytes = {
80
- let mut buf = Vec :: with_capacity ( file_size_bytes ) ;
84
+ let mut buf = Vec :: with_capacity ( mft_file_size . get :: < byte > ( ) ) ;
81
85
let mut reader = std:: io:: BufReader :: new ( & file) ;
82
86
reader
83
87
. read_to_end ( & mut buf)
@@ -133,4 +137,15 @@ impl MftFile {
133
137
bytes : Bytes :: from ( raw) ,
134
138
} )
135
139
}
140
+
141
+ /// Iterate over fixed-size records contained in this MFT file.
142
+ ///
143
+ /// This creates zero-copy `MftRecord` instances by slicing the shared
144
+ /// `Bytes` buffer. No signature validation is performed.
145
+ /// The caller is responsible for ensuring fixups were already applied
146
+ /// (handled by `MftFile::from_bytes`/`from_path`).
147
+ #[ inline]
148
+ pub fn iter_records ( & self ) -> MftRecordIter {
149
+ MftRecordIter :: new ( self . bytes . clone ( ) , self . entry_size ( ) )
150
+ }
136
151
}
0 commit comments