1use num_enum::{IntoPrimitive, TryFromPrimitive};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive, IntoPrimitive, thiserror::Error)]
9#[must_use]
10#[repr(i64)]
11pub enum SyscallError {
12 #[error("Operation not permitted")]
13 PermissionDenied = -1,
14 #[error("No such file or directory")]
15 NotFound = -2,
16 #[error("No such process")]
17 NoSuchProcess = -3,
18 #[error("Interrupted system call")]
19 Interrupted = -4,
20 #[error("Input/output error")]
21 IoError = -5,
22 #[error("Argument list too long")]
23 ArgumentListTooLong = -7,
24 #[error("Exec format error")]
25 ExecFormatError = -8,
26 #[error("Bad file descriptor")]
27 BadHandle = -9,
28 #[error("No child processes")]
29 NoChildren = -10,
30 #[error("Resource temporarily unavailable")]
31 Again = -11,
32 #[error("Cannot allocate memory")]
33 OutOfMemory = -12,
34 #[error("Permission denied")]
35 AccessDenied = -13,
36 #[error("Bad address")]
37 Fault = -14,
38 #[error("File exists")]
39 AlreadyExists = -17,
40 #[error("Invalid argument")]
41 InvalidArgument = -22,
42 #[error("Not a typewriter")]
43 NotATty = -25,
44 #[error("Not a directory")]
45 NotADirectory = -20,
46 #[error("Is a directory")]
47 IsADirectory = -21,
48 #[error("No space left on device")]
49 NoSpace = -28,
50 #[error("Broken pipe")]
51 Pipe = -32,
52 #[error("Result too large")]
53 Range = -34,
54 #[error("File name too long")]
55 NameTooLong = -36,
56 #[error("Function not implemented")]
57 NotImplemented = -38,
58 #[error("Directory not empty")]
59 NotEmpty = -39,
60 #[error("Not supported")]
61 NotSupported = -52,
62 #[error("Message too long")]
63 MessageSize = -90,
64 #[error("No buffer space available")]
65 QueueFull = -105,
66 #[error("Connection timed out")]
67 TimedOut = -110,
68}
69
70impl SyscallError {
71 #[inline]
73 pub fn to_raw(self) -> u64 {
74 (self as i64) as u64
75 }
76
77 pub fn from_code(code: i64) -> Self {
79 Self::try_from(code).unwrap_or(SyscallError::InvalidArgument)
80 }
81
82 #[inline]
84 pub fn is_retryable(self) -> bool {
85 matches!(self, SyscallError::Interrupted | SyscallError::Again)
86 }
87
88 #[inline]
90 pub fn name(self) -> &'static str {
91 match self {
92 SyscallError::PermissionDenied => "EPERM",
93 SyscallError::NotFound => "ENOENT",
94 SyscallError::NoSuchProcess => "ESRCH",
95 SyscallError::Interrupted => "EINTR",
96 SyscallError::IoError => "EIO",
97 SyscallError::ArgumentListTooLong => "E2BIG",
98 SyscallError::ExecFormatError => "ENOEXEC",
99 SyscallError::BadHandle => "EBADF",
100 SyscallError::NoChildren => "ECHILD",
101 SyscallError::Again => "EAGAIN",
102 SyscallError::OutOfMemory => "ENOMEM",
103 SyscallError::AccessDenied => "EACCES",
104 SyscallError::Fault => "EFAULT",
105 SyscallError::AlreadyExists => "EEXIST",
106 SyscallError::InvalidArgument => "EINVAL",
107 SyscallError::NotADirectory => "ENOTDIR",
108 SyscallError::IsADirectory => "EISDIR",
109 SyscallError::NotATty => "ENOTTY",
110 SyscallError::NoSpace => "ENOSPC",
111 SyscallError::Pipe => "EPIPE",
112 SyscallError::Range => "ERANGE",
113 SyscallError::NameTooLong => "ENAMETOOLONG",
114 SyscallError::NotImplemented => "ENOSYS",
115 SyscallError::NotEmpty => "ENOTEMPTY",
116 SyscallError::NotSupported => "ENOTSUP",
117 SyscallError::MessageSize => "EMSGSIZE",
118 SyscallError::QueueFull => "ENOBUFS",
119 SyscallError::TimedOut => "ETIMEDOUT",
120 }
121 }
122}
123
124impl From<core::str::Utf8Error> for SyscallError {
127 #[inline]
129 fn from(_: core::str::Utf8Error) -> Self {
130 SyscallError::InvalidArgument
131 }
132}
133
134impl From<crate::ostd::util::Error> for SyscallError {
135 fn from(err: crate::ostd::util::Error) -> Self {
137 use crate::ostd::util::Error;
138 match err {
139 Error::OutOfMemory => SyscallError::OutOfMemory,
140 Error::InvalidArgument => SyscallError::InvalidArgument,
141 Error::NotFound => SyscallError::NotFound,
142 Error::AlreadyExists => SyscallError::AlreadyExists,
143 Error::PermissionDenied => SyscallError::PermissionDenied,
144 Error::Busy => SyscallError::Again,
145 Error::PageFault => SyscallError::Fault,
146 Error::ArchError(_) => SyscallError::IoError,
147 }
148 }
149}
150
151impl From<crate::ostd::mm::MapError> for SyscallError {
152 fn from(err: crate::ostd::mm::MapError) -> Self {
154 use crate::ostd::mm::MapError;
155 match err {
156 MapError::OutOfBounds => SyscallError::InvalidArgument,
157 MapError::NotOwner => SyscallError::PermissionDenied,
158 MapError::AlreadyMapped => SyscallError::AlreadyExists,
159 MapError::InvalidAddress => SyscallError::InvalidArgument,
160 MapError::OutOfMemory => SyscallError::OutOfMemory,
161 MapError::ArchError(_) => SyscallError::IoError,
162 }
163 }
164}
165
166impl From<crate::hardware::storage::virtio_block::BlockError> for SyscallError {
167 fn from(err: crate::hardware::storage::virtio_block::BlockError) -> Self {
169 use crate::hardware::storage::virtio_block::BlockError;
170 match err {
171 BlockError::IoError => SyscallError::IoError,
172 BlockError::InvalidSector => SyscallError::InvalidArgument,
173 BlockError::BufferTooSmall => SyscallError::InvalidArgument,
174 BlockError::NotReady => SyscallError::Again,
175 }
176 }
177}
178
179impl From<crate::ipc::port::IpcError> for SyscallError {
180 fn from(err: crate::ipc::port::IpcError) -> Self {
182 use crate::ipc::port::IpcError;
183 match err {
184 IpcError::PortNotFound => SyscallError::NotFound,
185 IpcError::NotOwner => SyscallError::PermissionDenied,
186 IpcError::PortDestroyed => SyscallError::Pipe,
187 IpcError::WouldBlock => SyscallError::Again,
188 IpcError::Interrupted => SyscallError::Interrupted,
189 }
190 }
191}
192
193impl From<net_core::NetError> for SyscallError {
194 fn from(err: net_core::NetError) -> Self {
196 use net_core::NetError;
197 match err {
198 NetError::NoPacket => SyscallError::Again,
199 NetError::TxQueueFull => SyscallError::QueueFull,
200 NetError::BufferTooSmall => SyscallError::InvalidArgument,
201 NetError::NotReady => SyscallError::Again,
202 NetError::LinkDown => SyscallError::IoError,
203 NetError::DeviceNotFound => SyscallError::NotImplemented,
204 }
205 }
206}
207
208impl From<crate::ipc::channel::ChannelError> for SyscallError {
209 fn from(err: crate::ipc::channel::ChannelError) -> Self {
211 use crate::ipc::channel::ChannelError;
212 match err {
213 ChannelError::WouldBlock => SyscallError::Again,
214 ChannelError::Disconnected => SyscallError::Pipe,
215 ChannelError::Interrupted => SyscallError::Interrupted,
216 }
217 }
218}