1use alloc::boxed::Box;
2use alloc::sync::Arc;
3use alloc::vec::Vec;
4use core::future::{self, Future};
5use core::mem::MaybeUninit;
6use core::task::Poll::{Pending, Ready};
7use core::time::Duration;
8
9use async_trait::async_trait;
10#[cfg(any(feature = "tcp", feature = "udp"))]
11use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
12
13use crate::arch::kernel::core_local::core_scheduler;
14use crate::executor::block_on;
15use crate::fs::{DirectoryEntry, FileAttr, SeekWhence};
16use crate::io;
17
18mod eventfd;
19#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
20pub(crate) mod socket;
21pub(crate) mod stdio;
22
23pub(crate) const STDIN_FILENO: FileDescriptor = 0;
24pub(crate) const STDOUT_FILENO: FileDescriptor = 1;
25pub(crate) const STDERR_FILENO: FileDescriptor = 2;
26
27#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
28#[derive(Debug)]
29pub(crate) enum Endpoint {
30 #[cfg(any(feature = "tcp", feature = "udp"))]
31 Ip(IpEndpoint),
32 #[cfg(feature = "vsock")]
33 Vsock(socket::vsock::VsockEndpoint),
34}
35
36#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
37#[derive(Debug)]
38pub(crate) enum ListenEndpoint {
39 #[cfg(any(feature = "tcp", feature = "udp"))]
40 Ip(IpListenEndpoint),
41 #[cfg(feature = "vsock")]
42 Vsock(socket::vsock::VsockListenEndpoint),
43}
44
45#[allow(dead_code)]
46#[derive(Debug, PartialEq)]
47pub(crate) enum SocketOption {
48 TcpNoDelay,
49}
50
51pub(crate) type FileDescriptor = i32;
52
53bitflags! {
54 #[derive(Debug, Copy, Clone, Default)]
56 pub struct OpenOption: i32 {
57 const O_RDONLY = 0o0000;
58 const O_WRONLY = 0o0001;
59 const O_RDWR = 0o0002;
60 const O_CREAT = 0o0100;
61 const O_EXCL = 0o0200;
62 const O_TRUNC = 0o1000;
63 const O_APPEND = StatusFlags::O_APPEND.bits();
64 const O_NONBLOCK = StatusFlags::O_NONBLOCK.bits();
65 const O_DIRECT = 0o40000;
66 const O_DIRECTORY = 0o200_000;
67 const O_CLOEXEC = 0o2_000_000;
69 }
70}
71
72bitflags! {
73 #[derive(Debug, Copy, Clone, Default)]
75 pub struct StatusFlags: i32 {
76 const O_APPEND = 0o2000;
77 const O_NONBLOCK = 0o4000;
78 }
79}
80
81bitflags! {
82 #[derive(Debug, Copy, Clone, Default)]
83 pub struct PollEvent: i16 {
84 const POLLIN = 0x1;
85 const POLLPRI = 0x2;
86 const POLLOUT = 0x4;
87 const POLLERR = 0x8;
88 const POLLHUP = 0x10;
89 const POLLNVAL = 0x20;
90 const POLLRDNORM = 0x040;
91 const POLLRDBAND = 0x080;
92 const POLLWRNORM = 0x0100;
93 const POLLWRBAND = 0x0200;
94 const POLLRDHUP = 0x2000;
95 }
96}
97
98#[repr(C)]
99#[derive(Debug, Default, Copy, Clone)]
100pub struct PollFd {
101 pub fd: i32,
103 pub events: PollEvent,
105 pub revents: PollEvent,
107}
108
109bitflags! {
110 #[derive(Debug, Default, Copy, Clone)]
111 pub struct EventFlags: i16 {
112 const EFD_SEMAPHORE = 0o1;
113 const EFD_NONBLOCK = 0o4000;
114 const EFD_CLOEXEC = 0o40000;
115 }
116}
117
118bitflags! {
119 #[derive(Debug, Copy, Clone)]
120 pub struct AccessPermission: u32 {
121 const S_IFMT = 0o170_000;
122 const S_IFSOCK = 0o140_000;
123 const S_IFLNK = 0o120_000;
124 const S_IFREG = 0o100_000;
125 const S_IFBLK = 0o060_000;
126 const S_IFDIR = 0o040_000;
127 const S_IFCHR = 0o020_000;
128 const S_IFIFO = 0o010_000;
129 const S_IRUSR = 0o400;
130 const S_IWUSR = 0o200;
131 const S_IXUSR = 0o100;
132 const S_IRWXU = 0o700;
133 const S_IRGRP = 0o040;
134 const S_IWGRP = 0o020;
135 const S_IXGRP = 0o010;
136 const S_IRWXG = 0o070;
137 const S_IROTH = 0o004;
138 const S_IWOTH = 0o002;
139 const S_IXOTH = 0o001;
140 const S_IRWXO = 0o007;
141 const _ = !0;
143 }
144}
145
146impl Default for AccessPermission {
147 fn default() -> Self {
148 AccessPermission::from_bits(0o666).unwrap()
149 }
150}
151
152#[async_trait]
153pub(crate) trait ObjectInterface: Sync + Send + core::fmt::Debug {
154 async fn poll(&self, _event: PollEvent) -> io::Result<PollEvent> {
156 Ok(PollEvent::empty())
157 }
158
159 async fn read(&self, _buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
162 Err(io::Error::ENOSYS)
163 }
164
165 async fn write(&self, _buf: &[u8]) -> io::Result<usize> {
168 Err(io::Error::ENOSYS)
169 }
170
171 async fn lseek(&self, _offset: isize, _whence: SeekWhence) -> io::Result<isize> {
173 Err(io::Error::EINVAL)
174 }
175
176 async fn fstat(&self) -> io::Result<FileAttr> {
178 Err(io::Error::EINVAL)
179 }
180
181 async fn readdir(&self) -> io::Result<Vec<DirectoryEntry>> {
185 Err(io::Error::EINVAL)
186 }
187
188 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
190 async fn accept(&self) -> io::Result<(Arc<dyn ObjectInterface>, Endpoint)> {
191 Err(io::Error::EINVAL)
192 }
193
194 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
196 async fn connect(&self, _endpoint: Endpoint) -> io::Result<()> {
197 Err(io::Error::EINVAL)
198 }
199
200 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
202 async fn bind(&self, _name: ListenEndpoint) -> io::Result<()> {
203 Err(io::Error::EINVAL)
204 }
205
206 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
208 async fn listen(&self, _backlog: i32) -> io::Result<()> {
209 Err(io::Error::EINVAL)
210 }
211
212 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
214 async fn setsockopt(&self, _opt: SocketOption, _optval: bool) -> io::Result<()> {
215 Err(io::Error::ENOTSOCK)
216 }
217
218 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
220 async fn getsockopt(&self, _opt: SocketOption) -> io::Result<bool> {
221 Err(io::Error::ENOTSOCK)
222 }
223
224 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
226 async fn getsockname(&self) -> io::Result<Option<Endpoint>> {
227 Ok(None)
228 }
229
230 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
232 #[allow(dead_code)]
233 async fn getpeername(&self) -> io::Result<Option<Endpoint>> {
234 Ok(None)
235 }
236
237 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
239 async fn recvfrom(&self, _buffer: &mut [MaybeUninit<u8>]) -> io::Result<(usize, Endpoint)> {
240 Err(io::Error::ENOSYS)
241 }
242
243 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
251 async fn sendto(&self, _buffer: &[u8], _endpoint: Endpoint) -> io::Result<usize> {
252 Err(io::Error::ENOSYS)
253 }
254
255 #[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
257 async fn shutdown(&self, _how: i32) -> io::Result<()> {
258 Err(io::Error::ENOSYS)
259 }
260
261 async fn status_flags(&self) -> io::Result<StatusFlags> {
263 Err(io::Error::ENOSYS)
264 }
265
266 async fn set_status_flags(&self, _status_flags: StatusFlags) -> io::Result<()> {
268 Err(io::Error::ENOSYS)
269 }
270
271 async fn isatty(&self) -> io::Result<bool> {
273 Ok(false)
274 }
275
276 #[cfg(any(feature = "tcp", feature = "udp"))]
278 async fn inet_domain(&self) -> io::Result<i32> {
279 Err(io::Error::EINVAL)
280 }
281}
282
283pub(crate) fn read(fd: FileDescriptor, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
284 let obj = get_object(fd)?;
285
286 if buf.is_empty() {
287 return Ok(0);
288 }
289
290 block_on(obj.read(buf), None)
291}
292
293pub(crate) fn lseek(fd: FileDescriptor, offset: isize, whence: SeekWhence) -> io::Result<isize> {
294 let obj = get_object(fd)?;
295
296 block_on(obj.lseek(offset, whence), None)
297}
298
299pub(crate) fn write(fd: FileDescriptor, buf: &[u8]) -> io::Result<usize> {
300 let obj = get_object(fd)?;
301
302 if buf.is_empty() {
303 return Ok(0);
304 }
305
306 block_on(obj.write(buf), None)
307}
308
309async fn poll_fds(fds: &mut [PollFd]) -> io::Result<u64> {
310 future::poll_fn(|cx| {
311 let mut counter: u64 = 0;
312
313 for i in &mut *fds {
314 let fd = i.fd;
315 i.revents = PollEvent::empty();
316 let mut pinned_obj = core::pin::pin!(core_scheduler().get_object(fd));
317 if let Ready(Ok(obj)) = pinned_obj.as_mut().poll(cx) {
318 let mut pinned = core::pin::pin!(obj.poll(i.events));
319 if let Ready(Ok(e)) = pinned.as_mut().poll(cx) {
320 if !e.is_empty() {
321 counter += 1;
322 i.revents = e;
323 }
324 }
325 }
326 }
327
328 if counter > 0 {
329 Ready(Ok(counter))
330 } else {
331 Pending
332 }
333 })
334 .await
335}
336
337pub fn poll(fds: &mut [PollFd], timeout: Option<Duration>) -> io::Result<u64> {
344 let result = block_on(poll_fds(fds), timeout);
345 if let Err(ref e) = result {
346 if timeout.is_some() {
347 if *e == io::Error::EAGAIN {
349 return Ok(0);
350 }
351 }
352 }
353
354 result
355}
356
357pub fn fstat(fd: FileDescriptor) -> io::Result<FileAttr> {
358 let obj = get_object(fd)?;
359 block_on(obj.fstat(), None)
360}
361
362pub fn eventfd(initval: u64, flags: EventFlags) -> io::Result<FileDescriptor> {
381 let obj = self::eventfd::EventFd::new(initval, flags);
382
383 let fd = block_on(core_scheduler().insert_object(Arc::new(obj)), None)?;
384
385 Ok(fd)
386}
387
388pub(crate) fn get_object(fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
389 block_on(core_scheduler().get_object(fd), None)
390}
391
392pub(crate) fn insert_object(obj: Arc<dyn ObjectInterface>) -> io::Result<FileDescriptor> {
393 block_on(core_scheduler().insert_object(obj), None)
394}
395
396pub(crate) fn dup_object(fd: FileDescriptor) -> io::Result<FileDescriptor> {
401 block_on(core_scheduler().dup_object(fd), None)
402}
403
404pub(crate) fn dup_object2(fd1: FileDescriptor, fd2: FileDescriptor) -> io::Result<FileDescriptor> {
405 block_on(core_scheduler().dup_object2(fd1, fd2), None)
406}
407
408pub(crate) fn remove_object(fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
409 block_on(core_scheduler().remove_object(fd), None)
410}
411
412pub(crate) fn isatty(fd: FileDescriptor) -> io::Result<bool> {
413 let obj = get_object(fd)?;
414 block_on(obj.isatty(), None)
415}