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