ntfsmft

package
v0.0.27 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

README

NTFS MFT integration tests

On Windows, raw-MFT integration tests lazily create one disposable, 2 GiB expandable NTFS VHD on R:. They run against that clean volume, then detach and delete it at package teardown. This requires an Administrator token and an unused R: drive letter. If VHD provisioning is unavailable, only those raw integration tests are skipped; parser and other unit tests still run.

To run against an already-mounted real NTFS drive instead, set RSHELL_NTFSDU_TEST_ROOT to a directory on that drive. The tests create and remove only their own temporary subdirectories; they do not attach, detach, or delete the caller's drive.

$env:RSHELL_NTFSDU_TEST_ROOT = 'R:\'
go test -count=1 -v ./builtins/internal/ntfsmft

The default VHD is clean and small, so every full-MFT scan is fast and its contents are controlled by the test. A real drive validates the same raw-device path against existing host data, but its MFT may be much larger and its scan time varies with the drive's file population.

Documentation

Overview

Package ntfsmft computes disk usage for a target directory on an NTFS volume by reading the raw $MFT.

The volume I/O and scan orchestration are Windows-only (see du_windows.go); this file holds the pure $MFT record/attribute parser, which has no platform dependencies (stdlib only) so it can be unit-tested and fuzzed on any OS.

Scan pipeline (see Scan in du_windows.go for section markers):

  • Setup: open \\.\<drive>:, resolve the target and its immediate children (resolveScopeIndices) to MFT indices via the Windows API (CreateFile, GetFileInformationByHandle, FindFirstFile). Exclusion paths are resolved to indices before the MFT walks so out-of-scope subtrees short-circuit cheaply.

  • Pass 1 (modeAll, one full MFT stream): build dirParent (directory → parent idx), plus extSize and extParents per file base. Extension records are folded into this pass so their $DATA sizes and spillover $FILE_NAME parents are not rescanned. The bulk walk does not decode UTF-16 names.

  • Map dirs to size accumulators (mapDirsToSizeAccumulators): assign each directory to the running total pass 2 accumulates its subtree bytes into. TreeDepth <= 1 (fast path) precomputes dirBucket via walkUp from target and its immediate children so pass 2 attributes a file in O(1); TreeDepth >= 2 (general path) retains dirParent and the in-tree anchor totals for per-file chain walks in pass 2.

  • Pass 2 (modeFileBaseOnly, or modeAll when TreeDepth >= 2): tally in-use file base records into per-child / subtree totals; optional top-N files, extension aggregation, and find predicates run inline in this callback. The general path opportunistically decodes names only for dirs at depth ≤ TreeDepth.

  • Post-scan: assemble the optional Result.Tree; resolve top-file paths via OpenFileByID (bounded, not part of the MFT stream).

  • Pipelined ReadFile (double-buffered) overlaps disk I/O with parsing.

  • parseMode header-only early exit skips the attribute walk on records a pass cannot use (see modeAll / modeFileBaseOnly below).

  • No per-file info map: pass 2 unions base + extension parents and adds directly into totals. No per-file slice allocation on the hot path.

Requires Administrator privileges (\\.\C: open).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MFTIndex

func MFTIndex(ref uint64) uint64

MFTIndex masks the lower 48 bits of an MFT file reference. The upper 16 are the sequence number; we don't need them for disk-usage tally because we always cross-reference by record index, not sequence-stamped reference.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL