Skip to main content

strate_fs_abstraction/
error.rs

1//! Filesystem error types.
2//!
3//! This module defines a comprehensive error type for filesystem operations,
4//! designed to map to appropriate Windows NTSTATUS codes.
5
6pub type FsResult<T> = Result<T, FsError>;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
9pub enum FsError {
10    #[error("Buffer too small")]
11    BufferTooSmall,
12    #[error("End of file")]
13    EndOfFile,
14    #[error("Disk I/O error")]
15    DiskError,
16    #[error("Device not ready")]
17    DeviceNotReady,
18    #[error("Filesystem corrupted")]
19    Corrupted,
20    #[error("Invalid block type")]
21    InvalidBlockType,
22    #[error("Invalid magic number")]
23    InvalidMagic,
24    #[error("Unsupported version")]
25    UnsupportedVersion,
26    #[error("Invalid block address")]
27    InvalidBlockAddress,
28    #[error("Inode not found")]
29    InodeNotFound,
30    #[error("Not found")]
31    NotFound,
32    #[error("Not a directory")]
33    NotADirectory,
34    #[error("Is a directory")]
35    IsADirectory,
36    #[error("Invalid path")]
37    InvalidPath,
38    #[error("Path too long")]
39    PathTooLong,
40    #[error("Arithmetic overflow")]
41    ArithmeticOverflow,
42    #[error("Security violation")]
43    SecurityViolation,
44    #[error("Alignment error")]
45    AlignmentError,
46    #[error("Out of memory")]
47    OutOfMemory,
48    #[error("No space left")]
49    NoSpace,
50    #[error("Too many open files")]
51    TooManyOpenFiles,
52    #[error("Invalid UTF-8")]
53    InvalidUtf8,
54    #[error("Invalid UTF-16")]
55    InvalidUtf16,
56    #[error("String too long")]
57    StringTooLong,
58    #[error("Not implemented")]
59    NotImplemented,
60    #[error("Not supported")]
61    NotSupported,
62    #[error("Read-only filesystem")]
63    ReadOnly,
64    #[error("Already exists")]
65    AlreadyExists,
66    #[error("Directory not empty")]
67    NotEmpty,
68    #[error("Invalid argument")]
69    InvalidArgument,
70    #[error("Permission denied")]
71    PermissionDenied,
72    #[error("Cross-device link")]
73    CrossDeviceLink,
74    #[error("Too many symbolic links")]
75    TooManySymlinks,
76    #[error("File too large")]
77    FileTooLarge,
78    #[error("Unknown filesystem")]
79    UnknownFilesystem,
80}
81
82impl FsError {
83    /// Converts to Windows NTSTATUS code.
84    pub const fn to_ntstatus(self) -> i32 {
85        match self {
86            FsError::BufferTooSmall => 0xC0000023_u32 as i32,
87            FsError::EndOfFile => 0xC0000011_u32 as i32,
88            FsError::DiskError => 0xC000016A_u32 as i32,
89            FsError::DeviceNotReady => 0xC00000A3_u32 as i32,
90            FsError::Corrupted => 0xC0000032_u32 as i32,
91            FsError::InvalidBlockType => 0xC0000032_u32 as i32,
92            FsError::InvalidMagic => 0xC000014F_u32 as i32,
93            FsError::UnsupportedVersion => 0xC000019C_u32 as i32,
94            FsError::InvalidBlockAddress => 0xC0000015_u32 as i32,
95            FsError::InodeNotFound => 0xC000000F_u32 as i32,
96            FsError::NotFound => 0xC0000034_u32 as i32,
97            FsError::NotADirectory => 0xC0000103_u32 as i32,
98            FsError::IsADirectory => 0xC00000BA_u32 as i32,
99            FsError::InvalidPath => 0xC0000033_u32 as i32,
100            FsError::PathTooLong => 0xC0000106_u32 as i32,
101            FsError::ArithmeticOverflow => 0xC0000095_u32 as i32,
102            FsError::SecurityViolation => 0xC0000005_u32 as i32,
103            FsError::AlignmentError => 0x80000002_u32 as i32,
104            FsError::OutOfMemory => 0xC000009A_u32 as i32,
105            FsError::NoSpace => 0xC000007F_u32 as i32,
106            FsError::TooManyOpenFiles => 0xC000011F_u32 as i32,
107            FsError::InvalidUtf8 => 0xC000000D_u32 as i32,
108            FsError::InvalidUtf16 => 0xC000000D_u32 as i32,
109            FsError::StringTooLong => 0x80000005_u32 as i32,
110            FsError::NotImplemented => 0xC0000002_u32 as i32,
111            FsError::NotSupported => 0xC00000BB_u32 as i32,
112            FsError::ReadOnly => 0xC00000A2_u32 as i32,
113            FsError::AlreadyExists => 0xC0000035_u32 as i32,
114            FsError::NotEmpty => 0xC0000101_u32 as i32,
115            FsError::InvalidArgument => 0xC000000D_u32 as i32,
116            FsError::PermissionDenied => 0xC0000022_u32 as i32,
117            FsError::CrossDeviceLink => 0xC00000D4_u32 as i32,
118            FsError::TooManySymlinks => 0xC0000280_u32 as i32,
119            FsError::FileTooLarge => 0xC0000904_u32 as i32,
120            FsError::UnknownFilesystem => 0xC000014F_u32 as i32,
121        }
122    }
123
124    /// Returns `true` if this is a security-related error.
125    pub const fn is_security_error(self) -> bool {
126        matches!(
127            self,
128            FsError::ArithmeticOverflow | FsError::SecurityViolation
129        )
130    }
131
132    /// Returns `true` if this error indicates corrupted data.
133    pub const fn is_corruption_error(self) -> bool {
134        matches!(
135            self,
136            FsError::Corrupted
137                | FsError::InvalidMagic
138                | FsError::InvalidBlockAddress
139                | FsError::InvalidBlockType
140        )
141    }
142}
143
144#[cfg(feature = "syscall")]
145impl From<FsError> for strat9_syscall::error::Error {
146    /// Implements from.
147    fn from(e: FsError) -> Self {
148        use strat9_syscall::error::Error as SE;
149        match e {
150            FsError::BufferTooSmall => SE::InvalidArgument,
151            FsError::EndOfFile => SE::IoError,
152            FsError::DiskError => SE::IoError,
153            FsError::DeviceNotReady => SE::Again,
154            FsError::Corrupted | FsError::InvalidBlockType | FsError::InvalidMagic => SE::IoError,
155            FsError::UnsupportedVersion => SE::NotSupported,
156            FsError::InvalidBlockAddress => SE::InvalidArgument,
157            FsError::InodeNotFound | FsError::NotFound => SE::NotFound,
158            FsError::NotADirectory | FsError::IsADirectory => SE::InvalidArgument,
159            FsError::InvalidPath | FsError::PathTooLong => SE::InvalidArgument,
160            FsError::ArithmeticOverflow | FsError::SecurityViolation => SE::Fault,
161            FsError::AlignmentError => SE::Fault,
162            FsError::OutOfMemory => SE::OutOfMemory,
163            FsError::NoSpace => SE::NoSpace,
164            FsError::TooManyOpenFiles => SE::Again,
165            FsError::InvalidUtf8 | FsError::InvalidUtf16 | FsError::StringTooLong => {
166                SE::InvalidArgument
167            }
168            FsError::NotImplemented => SE::NotImplemented,
169            FsError::NotSupported | FsError::ReadOnly => SE::NotSupported,
170            FsError::AlreadyExists => SE::AlreadyExists,
171            FsError::NotEmpty => SE::InvalidArgument,
172            FsError::InvalidArgument => SE::InvalidArgument,
173            FsError::PermissionDenied => SE::PermissionDenied,
174            FsError::CrossDeviceLink => SE::NotSupported,
175            FsError::TooManySymlinks => SE::IoError,
176            FsError::FileTooLarge => SE::NoSpace,
177            FsError::UnknownFilesystem => SE::NotSupported,
178        }
179    }
180}