1use alloc::boxed::Box;
2use alloc::sync::Arc;
3use core::future::{self, Future};
4use core::mem::MaybeUninit;
5use core::pin::pin;
6use core::task::Poll::{Pending, Ready};
7use core::time::Duration;
8
9use async_trait::async_trait;
10#[cfg(feature = "net")]
11use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
12
13use crate::arch::kernel::core_local::core_scheduler;
14use crate::errno::Errno;
15use crate::executor::block_on;
16use crate::fs::{FileAttr, SeekWhence};
17use crate::io;
18
19mod eventfd;
20#[cfg(any(feature = "net", feature = "virtio-vsock"))]
21pub(crate) mod socket;
22pub(crate) mod stdio;
23
24pub(crate) const STDIN_FILENO: RawFd = 0;
25pub(crate) const STDOUT_FILENO: RawFd = 1;
26pub(crate) const STDERR_FILENO: RawFd = 2;
27
28#[cfg(any(feature = "net", feature = "virtio-vsock"))]
29#[derive(Debug)]
30pub(crate) enum Endpoint {
31 #[cfg(feature = "net")]
32 Ip(IpEndpoint),
33 #[cfg(feature = "virtio-vsock")]
34 Vsock(socket::vsock::VsockEndpoint),
35}
36
37#[cfg(any(feature = "net", feature = "virtio-vsock"))]
38#[derive(Debug)]
39pub(crate) enum ListenEndpoint {
40 #[cfg(feature = "net")]
41 Ip(IpListenEndpoint),
42 #[cfg(feature = "virtio-vsock")]
43 Vsock(socket::vsock::VsockListenEndpoint),
44}
45
46#[allow(dead_code)]
47#[derive(Debug, PartialEq)]
48pub(crate) enum SocketOption {
49 TcpNoDelay,
50}
51
52pub(crate) type RawFd = i32;
53
54bitflags! {
55 #[derive(Debug, Copy, Clone, Default)]
57 pub struct OpenOption: i32 {
58 const O_RDONLY = 0o0000;
59 const O_WRONLY = 0o0001;
60 const O_RDWR = 0o0002;
61 const O_CREAT = 0o0100;
62 const O_EXCL = 0o0200;
63 const O_TRUNC = 0o1000;
64 const O_APPEND = StatusFlags::O_APPEND.bits();
65 const O_NONBLOCK = StatusFlags::O_NONBLOCK.bits();
66 const O_DIRECT = 0o40000;
67 const O_DIRECTORY = 0o200_000;
68 const O_CLOEXEC = 0o2_000_000;
70 }
71}
72
73bitflags! {
74 #[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
76 pub struct AccessOption: i32 {
77 const R_OK = 4;
79 const W_OK = 2;
81 const X_OK = 1;
83 const F_OK = 0;
85 }
86}
87
88impl AccessOption {
89 pub fn can_access(&self, access_permissions: AccessPermission) -> bool {
91 if self.contains(AccessOption::R_OK)
92 && !access_permissions.contains(AccessPermission::S_IRUSR)
93 && !access_permissions.contains(AccessPermission::S_IRGRP)
94 && !access_permissions.contains(AccessPermission::S_IROTH)
95 {
96 return false;
97 }
98
99 if self.contains(AccessOption::W_OK)
100 && !access_permissions.contains(AccessPermission::S_IWUSR)
101 && !access_permissions.contains(AccessPermission::S_IWGRP)
102 && !access_permissions.contains(AccessPermission::S_IWOTH)
103 {
104 return false;
105 }
106
107 if self.contains(AccessOption::X_OK)
108 && !access_permissions.contains(AccessPermission::S_IXUSR)
109 && !access_permissions.contains(AccessPermission::S_IXGRP)
110 && !access_permissions.contains(AccessPermission::S_IXOTH)
111 {
112 return false;
113 }
114
115 true
116 }
117}
118
119bitflags! {
120 #[derive(Debug, Copy, Clone, Default)]
122 pub struct StatusFlags: i32 {
123 const O_APPEND = 0o2000;
124 const O_NONBLOCK = 0o4000;
125 }
126}
127
128bitflags! {
129 #[derive(Debug, Copy, Clone, Default)]
130 pub struct PollEvent: i16 {
131 const POLLIN = 0x1;
132 const POLLPRI = 0x2;
133 const POLLOUT = 0x4;
134 const POLLERR = 0x8;
135 const POLLHUP = 0x10;
136 const POLLNVAL = 0x20;
137 const POLLRDNORM = 0x040;
138 const POLLRDBAND = 0x080;
139 const POLLWRNORM = 0x0100;
140 const POLLWRBAND = 0x0200;
141 const POLLRDHUP = 0x2000;
142 }
143}
144
145#[repr(C)]
146#[derive(Debug, Default, Copy, Clone)]
147pub struct PollFd {
148 pub fd: i32,
150 pub events: PollEvent,
152 pub revents: PollEvent,
154}
155
156bitflags! {
157 #[derive(Debug, Default, Copy, Clone)]
158 pub struct EventFlags: i16 {
159 const EFD_SEMAPHORE = 0o1;
160 const EFD_NONBLOCK = 0o4000;
161 const EFD_CLOEXEC = 0o40000;
162 }
163}
164
165bitflags! {
166 #[derive(Debug, Copy, Clone)]
167 pub struct AccessPermission: u32 {
168 const S_IFMT = 0o170_000;
169 const S_IFSOCK = 0o140_000;
170 const S_IFLNK = 0o120_000;
171 const S_IFREG = 0o100_000;
172 const S_IFBLK = 0o060_000;
173 const S_IFDIR = 0o040_000;
174 const S_IFCHR = 0o020_000;
175 const S_IFIFO = 0o010_000;
176 const S_IRUSR = 0o400;
177 const S_IWUSR = 0o200;
178 const S_IXUSR = 0o100;
179 const S_IRWXU = 0o700;
180 const S_IRGRP = 0o040;
181 const S_IWGRP = 0o020;
182 const S_IXGRP = 0o010;
183 const S_IRWXG = 0o070;
184 const S_IROTH = 0o004;
185 const S_IWOTH = 0o002;
186 const S_IXOTH = 0o001;
187 const S_IRWXO = 0o007;
188 const _ = !0;
190 }
191}
192
193impl Default for AccessPermission {
194 fn default() -> Self {
195 AccessPermission::from_bits(0o666).unwrap()
196 }
197}
198
199#[async_trait]
200pub(crate) trait ObjectInterface: Sync + Send {
201 async fn poll(&self, _event: PollEvent) -> io::Result<PollEvent> {
203 Ok(PollEvent::empty())
204 }
205
206 async fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
209 Err(Errno::Nosys)
210 }
211
212 async fn write(&self, _buf: &[u8]) -> io::Result<usize> {
215 Err(Errno::Nosys)
216 }
217
218 async fn lseek(&self, _offset: isize, _whence: SeekWhence) -> io::Result<isize> {
220 Err(Errno::Inval)
221 }
222
223 async fn fstat(&self) -> io::Result<FileAttr> {
225 Err(Errno::Inval)
226 }
227
228 async fn getdents(&self, _buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
232 Err(Errno::Inval)
233 }
234
235 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
237 async fn accept(
238 &mut self,
239 ) -> io::Result<(Arc<async_lock::RwLock<dyn ObjectInterface>>, Endpoint)> {
240 Err(Errno::Inval)
241 }
242
243 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
245 async fn connect(&mut self, _endpoint: Endpoint) -> io::Result<()> {
246 Err(Errno::Inval)
247 }
248
249 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
251 async fn bind(&mut self, _name: ListenEndpoint) -> io::Result<()> {
252 Err(Errno::Inval)
253 }
254
255 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
257 async fn listen(&mut self, _backlog: i32) -> io::Result<()> {
258 Err(Errno::Inval)
259 }
260
261 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
263 async fn setsockopt(&self, _opt: SocketOption, _optval: bool) -> io::Result<()> {
264 Err(Errno::Notsock)
265 }
266
267 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
269 async fn getsockopt(&self, _opt: SocketOption) -> io::Result<bool> {
270 Err(Errno::Notsock)
271 }
272
273 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
275 async fn getsockname(&self) -> io::Result<Option<Endpoint>> {
276 Ok(None)
277 }
278
279 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
281 #[allow(dead_code)]
282 async fn getpeername(&self) -> io::Result<Option<Endpoint>> {
283 Ok(None)
284 }
285
286 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
288 async fn recvfrom(&self, _buffer: &mut [MaybeUninit<u8>]) -> io::Result<(usize, Endpoint)> {
289 Err(Errno::Nosys)
290 }
291
292 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
300 async fn sendto(&self, _buffer: &[u8], _endpoint: Endpoint) -> io::Result<usize> {
301 Err(Errno::Nosys)
302 }
303
304 #[cfg(any(feature = "net", feature = "virtio-vsock"))]
306 async fn shutdown(&self, _how: i32) -> io::Result<()> {
307 Err(Errno::Nosys)
308 }
309
310 async fn status_flags(&self) -> io::Result<StatusFlags> {
312 Err(Errno::Nosys)
313 }
314
315 async fn set_status_flags(&mut self, _status_flags: StatusFlags) -> io::Result<()> {
317 Err(Errno::Nosys)
318 }
319
320 async fn truncate(&self, _size: usize) -> io::Result<()> {
322 Err(Errno::Nosys)
323 }
324
325 async fn chmod(&self, _access_permission: AccessPermission) -> io::Result<()> {
327 Err(Errno::Nosys)
328 }
329
330 async fn isatty(&self) -> io::Result<bool> {
332 Ok(false)
333 }
334}
335
336pub(crate) fn read(fd: RawFd, buf: &mut [u8]) -> io::Result<usize> {
337 let obj = get_object(fd)?;
338
339 if buf.is_empty() {
340 return Ok(0);
341 }
342
343 block_on(async { obj.read().await.read(buf).await }, None)
344}
345
346pub(crate) fn lseek(fd: RawFd, offset: isize, whence: SeekWhence) -> io::Result<isize> {
347 let obj = get_object(fd)?;
348
349 block_on(async { obj.read().await.lseek(offset, whence).await }, None)
350}
351
352pub(crate) fn chmod(fd: RawFd, mode: AccessPermission) -> io::Result<()> {
353 let obj = get_object(fd)?;
354
355 block_on(async { obj.read().await.chmod(mode).await }, None)
356}
357
358pub(crate) fn write(fd: RawFd, buf: &[u8]) -> io::Result<usize> {
359 let obj = get_object(fd)?;
360
361 if buf.is_empty() {
362 return Ok(0);
363 }
364
365 block_on(async { obj.read().await.write(buf).await }, None)
366}
367
368pub(crate) fn truncate(fd: RawFd, length: usize) -> io::Result<()> {
369 let obj = get_object(fd)?;
370 block_on(async { obj.read().await.truncate(length).await }, None)
371}
372
373async fn poll_fds(fds: &mut [PollFd]) -> io::Result<u64> {
374 future::poll_fn(|cx| {
375 let mut counter: u64 = 0;
376
377 for poll_fd in &mut *fds {
378 let fd = poll_fd.fd;
379 poll_fd.revents = PollEvent::empty();
380 let Ok(obj) = core_scheduler().get_object(fd) else {
381 continue;
382 };
383
384 let mut pinned = pin!(async { obj.read().await.poll(poll_fd.events).await });
385 if let Ready(Ok(e)) = pinned.as_mut().poll(cx)
386 && !e.is_empty()
387 {
388 counter += 1;
389 poll_fd.revents = e;
390 }
391 }
392
393 if counter > 0 {
394 Ready(Ok(counter))
395 } else {
396 Pending
397 }
398 })
399 .await
400}
401
402pub fn poll(fds: &mut [PollFd], timeout: Option<Duration>) -> io::Result<u64> {
409 let result = block_on(poll_fds(fds), timeout);
410 if let Err(ref e) = result
411 && timeout.is_some()
412 {
413 if *e == Errno::Again {
415 return Ok(0);
416 }
417 }
418
419 result
420}
421
422pub fn fstat(fd: RawFd) -> io::Result<FileAttr> {
423 let obj = get_object(fd)?;
424 block_on(async { obj.read().await.fstat().await }, None)
425}
426
427pub fn eventfd(initval: u64, flags: EventFlags) -> io::Result<RawFd> {
446 let obj = self::eventfd::EventFd::new(initval, flags);
447
448 let fd = core_scheduler().insert_object(Arc::new(async_lock::RwLock::new(obj)))?;
449
450 Ok(fd)
451}
452
453pub(crate) fn get_object(fd: RawFd) -> io::Result<Arc<async_lock::RwLock<dyn ObjectInterface>>> {
454 core_scheduler().get_object(fd)
455}
456
457pub(crate) fn insert_object(
458 obj: Arc<async_lock::RwLock<dyn ObjectInterface>>,
459) -> io::Result<RawFd> {
460 core_scheduler().insert_object(obj)
461}
462
463pub(crate) fn dup_object(fd: RawFd) -> io::Result<RawFd> {
468 core_scheduler().dup_object(fd)
469}
470
471pub(crate) fn dup_object2(fd1: RawFd, fd2: RawFd) -> io::Result<RawFd> {
472 core_scheduler().dup_object2(fd1, fd2)
473}
474
475pub(crate) fn remove_object(fd: RawFd) -> io::Result<Arc<async_lock::RwLock<dyn ObjectInterface>>> {
476 core_scheduler().remove_object(fd)
477}
478
479pub(crate) fn isatty(fd: RawFd) -> io::Result<bool> {
480 let obj = get_object(fd)?;
481 block_on(async { obj.read().await.isatty().await }, None)
482}