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("No buffer space available")]
61 QueueFull = -105,
62 #[error("Connection timed out")]
63 TimedOut = -110,
64}
65
66impl SyscallError {
67 #[inline]
69 pub fn to_raw(self) -> u64 {
70 (self as i64) as u64
71 }
72
73 pub fn from_code(code: i64) -> Self {
75 Self::try_from(code).unwrap_or(SyscallError::InvalidArgument)
76 }
77
78 #[inline]
80 pub fn is_retryable(self) -> bool {
81 matches!(self, SyscallError::Interrupted | SyscallError::Again)
82 }
83
84 #[inline]
86 pub fn name(self) -> &'static str {
87 match self {
88 SyscallError::PermissionDenied => "EPERM",
89 SyscallError::NotFound => "ENOENT",
90 SyscallError::Interrupted => "EINTR",
91 SyscallError::IoError => "EIO",
92 SyscallError::ArgumentListTooLong => "E2BIG",
93 SyscallError::ExecFormatError => "ENOEXEC",
94 SyscallError::BadHandle => "EBADF",
95 SyscallError::NoChildren => "ECHILD",
96 SyscallError::Again => "EAGAIN",
97 SyscallError::OutOfMemory => "ENOMEM",
98 SyscallError::AccessDenied => "EACCES",
99 SyscallError::Fault => "EFAULT",
100 SyscallError::AlreadyExists => "EEXIST",
101 SyscallError::InvalidArgument => "EINVAL",
102 SyscallError::NotADirectory => "ENOTDIR",
103 SyscallError::IsADirectory => "EISDIR",
104 SyscallError::NotATty => "ENOTTY",
105 SyscallError::NoSpace => "ENOSPC",
106 SyscallError::Pipe => "EPIPE",
107 SyscallError::Range => "ERANGE",
108 SyscallError::NameTooLong => "ENAMETOOLONG",
109 SyscallError::NotImplemented => "ENOSYS",
110 SyscallError::NotEmpty => "ENOTEMPTY",
111 SyscallError::NotSupported => "ENOTSUP",
112 SyscallError::QueueFull => "ENOBUFS",
113 SyscallError::TimedOut => "ETIMEDOUT",
114 }
115 }
116}
117
118impl From<core::str::Utf8Error> for SyscallError {
121 #[inline]
123 fn from(_: core::str::Utf8Error) -> Self {
124 SyscallError::InvalidArgument
125 }
126}
127
128impl From<crate::ostd::util::Error> for SyscallError {
129 fn from(err: crate::ostd::util::Error) -> Self {
131 use crate::ostd::util::Error;
132 match err {
133 Error::OutOfMemory => SyscallError::OutOfMemory,
134 Error::InvalidArgument => SyscallError::InvalidArgument,
135 Error::NotFound => SyscallError::NotFound,
136 Error::AlreadyExists => SyscallError::AlreadyExists,
137 Error::PermissionDenied => SyscallError::PermissionDenied,
138 Error::Busy => SyscallError::Again,
139 Error::PageFault => SyscallError::Fault,
140 Error::ArchError(_) => SyscallError::IoError,
141 }
142 }
143}
144
145impl From<crate::ostd::mm::MapError> for SyscallError {
146 fn from(err: crate::ostd::mm::MapError) -> Self {
148 use crate::ostd::mm::MapError;
149 match err {
150 MapError::OutOfBounds => SyscallError::InvalidArgument,
151 MapError::NotOwner => SyscallError::PermissionDenied,
152 MapError::AlreadyMapped => SyscallError::AlreadyExists,
153 MapError::InvalidAddress => SyscallError::InvalidArgument,
154 MapError::OutOfMemory => SyscallError::OutOfMemory,
155 MapError::ArchError(_) => SyscallError::IoError,
156 }
157 }
158}
159
160impl From<crate::hardware::storage::virtio_block::BlockError> for SyscallError {
161 fn from(err: crate::hardware::storage::virtio_block::BlockError) -> Self {
163 use crate::hardware::storage::virtio_block::BlockError;
164 match err {
165 BlockError::IoError => SyscallError::IoError,
166 BlockError::InvalidSector => SyscallError::InvalidArgument,
167 BlockError::BufferTooSmall => SyscallError::InvalidArgument,
168 BlockError::NotReady => SyscallError::Again,
169 }
170 }
171}
172
173impl From<crate::ipc::port::IpcError> for SyscallError {
174 fn from(err: crate::ipc::port::IpcError) -> Self {
176 use crate::ipc::port::IpcError;
177 match err {
178 IpcError::PortNotFound => SyscallError::NotFound,
179 IpcError::NotOwner => SyscallError::PermissionDenied,
180 IpcError::PortDestroyed => SyscallError::Pipe,
181 }
182 }
183}
184
185impl From<net_core::NetError> for SyscallError {
186 fn from(err: net_core::NetError) -> Self {
188 use net_core::NetError;
189 match err {
190 NetError::NoPacket => SyscallError::Again,
191 NetError::TxQueueFull => SyscallError::QueueFull,
192 NetError::BufferTooSmall => SyscallError::InvalidArgument,
193 NetError::NotReady => SyscallError::Again,
194 NetError::LinkDown => SyscallError::IoError,
195 NetError::DeviceNotFound => SyscallError::NotImplemented,
196 }
197 }
198}
199
200impl From<crate::ipc::channel::ChannelError> for SyscallError {
201 fn from(err: crate::ipc::channel::ChannelError) -> Self {
203 use crate::ipc::channel::ChannelError;
204 match err {
205 ChannelError::WouldBlock => SyscallError::Again,
206 ChannelError::Disconnected => SyscallError::Pipe,
207 }
208 }
209}