Skip to main content

ntfs_core/
error.rs

1//! Crate-wide error type.
2
3/// Errors produced while parsing NTFS structures.
4#[derive(Debug, thiserror::Error)]
5pub enum NtfsError {
6    /// The input slice was shorter than the structure requires.
7    #[error("input too short for {what}: need {need} bytes, got {got}")]
8    TooShort {
9        what: &'static str,
10        need: usize,
11        got: usize,
12    },
13
14    /// The OEM ID at offset 3 was not `b"NTFS    "`.
15    #[error("not an NTFS volume: OEM ID is {0:x?}, expected \"NTFS    \"")]
16    BadOemId([u8; 8]),
17
18    /// Bytes-per-sector is not a power of two in the range 256..=4096.
19    #[error("invalid bytes-per-sector: {0} (must be a power of two in 256..=4096)")]
20    BadBytesPerSector(u16),
21
22    /// Sectors-per-cluster is zero or not a power of two.
23    #[error("invalid sectors-per-cluster encoding: {0:#04x}")]
24    BadSectorsPerCluster(u8),
25
26    /// The clusters-per-file-record-segment byte encodes an out-of-range size.
27    #[error("invalid MFT record size encoding: byte {0:#04x}")]
28    BadRecordSize(u8),
29
30    /// The clusters-per-index-buffer byte encodes an out-of-range size.
31    #[error("invalid index record size encoding: byte {0:#04x}")]
32    BadIndexRecordSize(u8),
33
34    /// An MFT record's signature was neither `FILE` nor `BAAD`.
35    #[error("bad MFT record signature: {0:x?} (expected \"FILE\" or \"BAAD\")")]
36    BadRecordSignature([u8; 4]),
37
38    /// An update-sequence fixup did not match the Update Sequence Number — the
39    /// record was torn across a sector boundary, or has been tampered with.
40    #[error("fixup mismatch in sector {sector}: expected USN {expected:#06x}, found {found:#06x}")]
41    FixupMismatch {
42        sector: usize,
43        expected: u16,
44        found: u16,
45    },
46
47    /// The update sequence array is malformed (offset/count out of bounds).
48    #[error("malformed update sequence array: {0}")]
49    BadUpdateSequence(&'static str),
50
51    /// An attribute is corrupt or would read out of bounds — rejected rather
52    /// than trusted (defends against crafted records).
53    #[error("corrupt attribute at offset {offset}: {detail}")]
54    BadAttribute { offset: usize, detail: &'static str },
55
56    /// A data runlist is malformed (bad field size, truncated, or overflowing).
57    #[error("malformed runlist: {0}")]
58    BadRunlist(&'static str),
59
60    /// A directory index node or entry is malformed.
61    #[error("malformed index: {0}")]
62    BadIndex(&'static str),
63
64    /// LZNT1-compressed data is malformed.
65    #[error("malformed compressed data: {0}")]
66    BadCompression(&'static str),
67
68    /// An `$ATTRIBUTE_LIST` entry is malformed.
69    #[error("malformed attribute list: {0}")]
70    BadAttributeList(&'static str),
71
72    /// A path component was not found.
73    #[error("path not found: {0}")]
74    NotFound(String),
75
76    /// A path component that should be a directory is not one.
77    #[error("not a directory: {0}")]
78    NotADirectory(String),
79
80    /// A structure declared a size that would require an unreasonable
81    /// allocation — refused rather than attempted (defends against crafted
82    /// sizes / allocation bombs).
83    #[error("refusing to allocate {bytes} bytes")]
84    TooLarge { bytes: u64 },
85
86    /// An underlying I/O error.
87    #[error("I/O error: {0}")]
88    Io(#[from] std::io::Error),
89}
90
91/// Convenience alias.
92pub type Result<T> = std::result::Result<T, NtfsError>;