1use core::fmt;
4
5#[derive(Debug)]
7pub enum NtfsError {
8 InvalidBootSignature {
10 found: u16,
12 },
13 InvalidOemId,
15 InvalidSectorSize {
17 found: u16,
19 },
20 InvalidSectorsPerCluster {
22 found: u8,
24 },
25 InvalidVolumeGeometry,
27 InvalidMftMagic,
29 InvalidIndexMagic,
31 InvalidFixup,
33 FixupMismatch {
35 expected: u16,
37 found: u16,
39 },
40 InvalidRecordSize,
42 MftRecordOutOfBounds {
44 index: u64,
46 },
47 StaleFileReference {
49 index: u64,
51 expected: u16,
53 found: u16,
55 },
56 AttributeNotFound {
58 attr_type: u32,
60 },
61 InvalidAttribute,
63 InvalidDataRun,
65 InvalidFileName,
67 InvalidUpcaseTable,
69 InvalidIndexEntry,
71 NotAFile,
73 NotADirectory,
75 EntryNotFound,
77 InvalidPath,
79 UnsupportedCompression,
81 UnsupportedEncryption,
83 UnexpectedEndOfData,
85 Io(hadris_io::Error),
87}
88
89impl fmt::Display for NtfsError {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 match self {
92 Self::InvalidBootSignature { found } => {
93 write!(
94 f,
95 "invalid boot signature: expected 0xAA55, found {found:#06x}"
96 )
97 }
98 Self::InvalidOemId => write!(f, "invalid OEM ID (expected \"NTFS \")"),
99 Self::InvalidSectorSize { found } => {
100 write!(f, "invalid NTFS sector size: {found}")
101 }
102 Self::InvalidSectorsPerCluster { found } => {
103 write!(f, "invalid NTFS sectors per cluster: {found}")
104 }
105 Self::InvalidVolumeGeometry => write!(f, "invalid NTFS volume geometry"),
106 Self::InvalidMftMagic => write!(f, "invalid MFT record magic (expected \"FILE\")"),
107 Self::InvalidIndexMagic => {
108 write!(f, "invalid index record magic (expected \"INDX\")")
109 }
110 Self::InvalidFixup => write!(f, "invalid or corrupt update sequence array"),
111 Self::FixupMismatch { expected, found } => {
112 write!(
113 f,
114 "fixup mismatch: expected {expected:#06x}, found {found:#06x}"
115 )
116 }
117 Self::InvalidRecordSize => write!(f, "invalid record size in boot sector"),
118 Self::MftRecordOutOfBounds { index } => {
119 write!(f, "MFT record index {index} is out of bounds")
120 }
121 Self::StaleFileReference {
122 index,
123 expected,
124 found,
125 } => write!(
126 f,
127 "stale reference to MFT record {index}: expected sequence {expected}, found {found}"
128 ),
129 Self::AttributeNotFound { attr_type } => {
130 write!(f, "attribute type {attr_type:#06x} not found")
131 }
132 Self::InvalidAttribute => write!(f, "malformed attribute header or value"),
133 Self::InvalidDataRun => write!(f, "malformed non-resident attribute data run"),
134 Self::InvalidFileName => write!(f, "could not decode UTF-16LE filename"),
135 Self::InvalidUpcaseTable => write!(f, "missing or malformed NTFS $UpCase table"),
136 Self::InvalidIndexEntry => write!(f, "malformed index entry"),
137 Self::NotAFile => write!(f, "entry is not a file"),
138 Self::NotADirectory => write!(f, "entry is not a directory"),
139 Self::EntryNotFound => write!(f, "entry not found in directory"),
140 Self::InvalidPath => write!(f, "path is invalid (empty or malformed)"),
141 Self::UnsupportedCompression => {
142 write!(f, "compressed data streams are not supported")
143 }
144 Self::UnsupportedEncryption => {
145 write!(f, "encrypted data streams are not supported")
146 }
147 Self::UnexpectedEndOfData => write!(f, "unexpected end of data runs"),
148 Self::Io(e) => write!(f, "I/O error: {e:?}"),
149 }
150 }
151}
152
153#[cfg(feature = "std")]
154impl std::error::Error for NtfsError {}
155
156impl<E: hadris_io::IoError> From<hadris_io::Error<E>> for NtfsError {
157 fn from(e: hadris_io::Error<E>) -> Self {
158 Self::Io(e.erase())
159 }
160}
161
162pub type Result<T> = core::result::Result<T, NtfsError>;