Skip to content

Commit 45fdf3b

Browse files
githubrobbiclaude
andcommitted
fix(mft): restore OFFLINE sort + custom format for parity (5/6 drives pass)
Commit 90ee522 removed all sort_directory_children() calls to match C++ LIVE behavior, but this broke OFFLINE mode (0/6 drives passing). OFFLINE paths need sorting for deterministic output since MFT dump parsing order differs from live IOCP traversal. Changes: - Restore sort_directory_children() before compute_tree_metrics() in all 3 OFFLINE code paths: builder.rs, persistence.rs, merge.rs - Add --format custom to verify_parity.rs to match C++ baseline footer Verified: D, E, G, M, S all SORTED MATCH. F is known deferred (Bug 3). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 90ee522 commit 45fdf3b

File tree

4 files changed

+18
-1
lines changed

4 files changed

+18
-1
lines changed

crates/uffs-mft/src/index/builder.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,15 @@ impl MftIndex {
465465
tracing::debug!("[TRIP] MftIndex::from_parsed_records -> Phase 2: ExtensionIndex::build");
466466
index.extension_index = Some(ExtensionIndex::build(&index));
467467

468-
// 2. Compute tree metrics for directory statistics (Phase 5)
468+
// 2. Sort directory children for deterministic OFFLINE output (Phase 4)
469+
// CRITICAL: OFFLINE path (from_parsed_records) requires sorted children
470+
// for deterministic CSV output order. LIVE paths (to_index.rs) do NOT
471+
// sort to match C++ behavior (reverse MFT parse order).
472+
tracing::debug!("[TRIP] MftIndex::from_parsed_records -> Phase 4: sort_directory_children");
473+
index.sort_directory_children();
474+
475+
// 3. Compute tree metrics for directory statistics (Phase 5)
476+
// Must run AFTER sorting in OFFLINE path for deterministic results.
469477
tracing::debug!("[TRIP] MftIndex::from_parsed_records -> Phase 5: compute_tree_metrics");
470478
index.compute_tree_metrics();
471479

crates/uffs-mft/src/index/merge.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ impl MftIndex {
5454
debug!("🔨 Building extension index...");
5555
self.extension_index = Some(ExtensionIndex::build(self));
5656

57+
debug!("🔨 Sorting directory children...");
58+
self.sort_directory_children();
59+
5760
debug!("🔨 Computing tree metrics...");
5861
self.compute_tree_metrics();
5962

crates/uffs-mft/src/reader/persistence.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,10 @@ impl MftReader {
609609
}
610610
}
611611

612+
// Sort directory children for deterministic output
613+
// CRITICAL for OFFLINE path: ensures consistent ordering across runs
614+
index.sort_directory_children();
615+
612616
// Compute tree metrics
613617
index.compute_tree_metrics();
614618

scripts/verify_parity.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,8 @@ fn regenerate_rust_output(
994994
drive_letter,
995995
"--tz-offset",
996996
&tz_str,
997+
"--format",
998+
"custom", // Match C++ baseline footer format
997999
"--out",
9981000
&rust_output.to_string_lossy(),
9991001
])

0 commit comments

Comments
 (0)