Skip to main content

rebecca_ntfs/
lib.rs

1//! Read-only NTFS Master File Table parsing primitives.
2//!
3//! This crate intentionally parses exported record bytes and in-memory fixtures.
4//! It does not open volumes, require elevation, or provide deletion authority.
5
6pub mod adapter;
7pub mod attribute_list;
8pub mod attrs;
9pub mod dir_index;
10pub mod fixup;
11pub mod index;
12pub mod reader;
13pub mod record;
14pub mod record_set;
15pub mod runlist;
16pub mod stream;
17
18mod parse;
19
20pub use adapter::{
21    NtfsAttributeListEntry, NtfsAttributeStream, NtfsDataRun, NtfsDirectoryEntry,
22    NtfsDirectoryEntrySource, NtfsDirectoryIndex, NtfsFileName, NtfsFileReference, NtfsIndexEntry,
23    NtfsParsedAttribute, NtfsParsedRecord,
24};
25pub use attrs::{AttributeHeader, AttributeType};
26pub use index::{
27    DirectoryEdge, DirectoryEdgeConfidence, DirectoryEdgeSequenceStatus, DirectoryEdgeSource,
28    MftIndex, MftIndexEntry, MftPathCandidate, PhysicalMetrics, PhysicalMetricsAccumulator,
29    SubtreeSummary,
30};
31pub use reader::{MftRecordBatch, MftRecordError, MftRecordReader};
32pub use record::{FileNameNamespace, ParseCaveat};
33pub use record_set::{NtfsRecordResolver, NtfsRecordSet, resolve_record_with_stream_source};
34pub use stream::{
35    NtfsStreamGeometry, NtfsStreamReadError, NtfsStreamReader, NtfsStreamSource, SparseRunPolicy,
36};
37
38pub type Result<T> = std::result::Result<T, NtfsParseError>;
39
40#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, thiserror::Error)]
41pub enum NtfsParseError {
42    #[error("record is too small: expected at least {expected} bytes, got {actual}")]
43    Truncated { expected: usize, actual: usize },
44
45    #[error("record signature is not FILE")]
46    InvalidSignature,
47
48    #[error("invalid update sequence array")]
49    InvalidUpdateSequence,
50
51    #[error(
52        "record attribute bounds are invalid: first attribute offset {first_attribute_offset}, used size {used_size}, record size {record_size}"
53    )]
54    InvalidRecordBounds {
55        first_attribute_offset: usize,
56        used_size: usize,
57        record_size: usize,
58    },
59
60    #[error("invalid attribute header at offset {offset}")]
61    InvalidAttribute { offset: usize },
62
63    #[error("attribute at offset {offset} is truncated")]
64    TruncatedAttribute { offset: usize },
65
66    #[error("resident attribute value at offset {offset} is truncated")]
67    TruncatedResidentValue { offset: usize },
68
69    #[error("file name attribute is invalid")]
70    InvalidFileName,
71
72    #[error("data run list is invalid")]
73    InvalidRunlist,
74
75    #[error("attribute list is invalid")]
76    InvalidAttributeList,
77
78    #[error("directory index is invalid")]
79    InvalidDirectoryIndex,
80}