1use alloc::boxed::Box;
2use alloc::sync::Arc;
3use core::future::{self, Future};
4use core::mem::MaybeUninit;
5use core::task::Poll::{Pending, Ready};
6use core::time::Duration;
7
8use async_trait::async_trait;
9#[cfg(feature = "net")]
10use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
11
12use crate::arch::kernel::core_local::core_scheduler;
13use crate::errno::Errno;
14use crate::executor::block_on;
15use crate::fs::{FileAttr, SeekWhence};
16use crate::io;
17
18mod eventfd;
19#[cfg(any(feature = "net", 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 = "net", feature = "vsock"))]
28#[derive(Debug)]
29pub(crate) enum Endpoint {
30 #[cfg(feature = "net")]
31 Ip(IpEndpoint),
32 #[cfg(feature = "vsock")]
33 Vsock(socket::vsock::VsockEndpoint),
34}
35
36#[cfg(any(feature = "net", feature = "vsock"))]
37#[derive(Debug)]
38pub(crate) enum ListenEndpoint {
39 #[cfg(feature = "net")]
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, Eq, PartialEq)]
75 pub struct AccessOption: i32 {
76 const R_OK = 4;
78 const W_OK = 2;
80 const X_OK = 1;
82 const F_OK = 0;
84 }
85}
86
87impl AccessOption {
88 pub fn can_access(&self, access_permissions: AccessPermission) -> bool {
90 if self.contains(AccessOption::R_OK)
91 && !access_permissions.contains(AccessPermission::S_IRUSR)
92 && !access_permissions.contains(AccessPermission::S_IRGRP)
93 && !access_permissions.contains(AccessPermission::S_IROTH)
94 {
95 return false;
96 }
97
98 if self.contains(AccessOption::W_OK)
99 && !access_permissions.contains(AccessPermission::S_IWUSR)
100 && !access_permissions.contains(AccessPermission::S_IWGRP)
101 && !access_permissions.contains(AccessPermission::S_IWOTH)
102 {
103 return false;
104 }
105
106 if self.contains(AccessOption::X_OK)
107 && !access_permissions.contains(AccessPermission::S_IXUSR)
108 && !access_permissions.contains(AccessPermission::S_IXGRP)
109 && !access_permissions.contains(AccessPermission::S_IXOTH)
110 {
111 return false;
112 }
113
114 true
115 }
116}
117
118bitflags! {
119 #[derive(Debug, Copy, Clone, Default)]
121 pub struct StatusFlags: i32 {
122 const O_APPEND = 0o2000;
123 const O_NONBLOCK = 0o4000;
124 }
125}
126
127bitflags! {
128 #[derive(Debug, Copy, Clone, Default)]
129 pub struct PollEvent: i16 {
130 const POLLIN = 0x1;
131 const POLLPRI = 0x2;
132 const POLLOUT = 0x4;
133 const POLLERR = 0x8;
134 const POLLHUP = 0x10;
135 const POLLNVAL = 0x20;
136 const POLLRDNORM = 0x040;
137 const POLLRDBAND = 0x080;
138 const POLLWRNORM = 0x0100;
139 const POLLWRBAND = 0x0200;
140 const POLLRDHUP = 0x2000;
141 }
142}
143
144#[repr(C)]
145#[derive(Debug, Default, Copy, Clone)]
146pub struct PollFd {
147 pub fd: i32,
149 pub events: PollEvent,
151 pub revents: PollEvent,
153}
154
155bitflags! {
156 #[derive(Debug, Default, Copy, Clone)]
157 pub struct EventFlags: i16 {
158 const EFD_SEMAPHORE = 0o1;
159 const EFD_NONBLOCK = 0o4000;
160 const EFD_CLOEXEC = 0o40000;
161 }
162}
163
164bitflags! {
165 #[derive(Debug, Copy, Clone)]
166 pub struct AccessPermission: u32 {
167 const S_IFMT = 0o170_000;
168 const S_IFSOCK = 0o140_000;
169 const S_IFLNK = 0o120_000;
170 const S_IFREG = 0o100_000;
171 const S_IFBLK = 0o060_000;
172 const S_IFDIR = 0o040_000;
173 const S_IFCHR = 0o020_000;
174 const S_IFIFO = 0o010_000;
175 const S_IRUSR = 0o400;
176 const S_IWUSR = 0o200;
177 const S_IXUSR = 0o100;
178 const S_IRWXU = 0o700;
179 const S_IRGRP = 0o040;
180 const S_IWGRP = 0o020;
181 const S_IXGRP = 0o010;
182 const S_IRWXG = 0o070;
183 const S_IROTH = 0o004;
184 const S_IWOTH = 0o002;
185 const S_IXOTH = 0o001;
186 const S_IRWXO = 0o007;
187 const _ = !0;
189 }
190}
191
192impl Default for AccessPermission {
193 fn default() -> Self {
194 AccessPermission::from_bits(0o666).unwrap()
195 }
196}
197
198#[async_trait]
199pub(crate) trait ObjectInterface: Sync + Send + core::fmt::Debug {
200 async fn poll(&self, _event: PollEvent) -> io::Result<PollEvent> {
202 Ok(PollEvent::empty())
203 }
204
205 async fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
208 Err(Errno::Nosys)
209 }
210
211 async fn write(&self, _buf: &[u8]) -> io::Result<usize> {
214 Err(Errno::Nosys)
215 }
216
217 async fn lseek(&self, _offset: isize, _whence: SeekWhence) -> io::Result<isize> {
219 Err(Errno::Inval)
220 }
221
222 async fn fstat(&self) -> io::Result<FileAttr> {
224 Err(Errno::Inval)
225 }
226
227 async fn getdents(&self, _buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
231 Err(Errno::Inval)
232 }
233
234 #[cfg(any(feature = "net", feature = "vsock"))]
236 async fn accept(
237 &mut self,
238 ) -> io::Result<(Arc<async_lock::RwLock<dyn ObjectInterface>>, Endpoint)> {
239 Err(Errno::Inval)
240 }
241
242 #[cfg(any(feature = "net", feature = "vsock"))]
244 async fn connect(&mut self, _endpoint: Endpoint) -> io::Result<()> {
245 Err(Errno::Inval)
246 }
247
248 #[cfg(any(feature = "net", feature = "vsock"))]
250 async fn bind(&mut self, _name: ListenEndpoint) -> io::Result<()> {
251 Err(Errno::Inval)
252 }
253
254 #[cfg(any(feature = "net", feature = "vsock"))]
256 async fn listen(&mut self, _backlog: i32) -> io::Result<()> {
257 Err(Errno::Inval)
258 }
259
260 #[cfg(any(feature = "net", feature = "vsock"))]
262 async fn setsockopt(&self, _opt: SocketOption, _optval: bool) -> io::Result<()> {
263 Err(Errno::Notsock)
264 }
265
266 #[cfg(any(feature = "net", feature = "vsock"))]
268 async fn getsockopt(&self, _opt: SocketOption) -> io::Result<bool> {
269 Err(Errno::Notsock)
270 }
271
272 #[cfg(any(feature = "net", feature = "vsock"))]
274 async fn getsockname(&self) -> io::Result<Option<Endpoint>> {
275 Ok(None)
276 }
277
278 #[cfg(any(feature = "net", feature = "vsock"))]
280 #[allow(dead_code)]
281 async fn getpeername(&self) -> io::Result<Option<Endpoint>> {
282 Ok(None)
283 }
284
285 #[cfg(any(feature = "net", feature = "vsock"))]
287 async fn recvfrom(&self, _buffer: &mut [MaybeUninit<u8>]) -> io::Result<(usize, Endpoint)> {
288 Err(Errno::Nosys)
289 }
290
291 #[cfg(any(feature = "net", feature = "vsock"))]
299 async fn sendto(&self, _buffer: &[u8], _endpoint: Endpoint) -> io::Result<usize> {
300 Err(Errno::Nosys)
301 }
302
303 #[cfg(any(feature = "net", feature = "vsock"))]
305 async fn shutdown(&self, _how: i32) -> io::Result<()> {
306 Err(Errno::Nosys)
307 }
308
309 async fn status_flags(&self) -> io::Result<StatusFlags> {
311 Err(Errno::Nosys)
312 }
313
314 async fn set_status_flags(&mut self, _status_flags: StatusFlags) -> io::Result<()> {
316 Err(Errno::Nosys)
317 }
318
319 async fn truncate(&self, _size: usize) -> io::Result<()> {
321 Err(Errno::Nosys)
322 }
323
324 async fn chmod(&self, _access_permission: AccessPermission) -> io::Result<()> {
326 Err(Errno::Nosys)
327 }
328
329 async fn isatty(&self) -> io::Result<bool> {
331 Ok(false)
332 }
333}
334
335pub(crate) fn read(fd: FileDescriptor, buf: &mut [u8]) -> io::Result<usize> {
336 let obj = get_object(fd)?;
337
338 if buf.is_empty() {
339 return Ok(0);
340 }
341
342 block_on(async { obj.read().await.read(buf).await }, None)
343}
344
345pub(crate) fn lseek(fd: FileDescriptor, offset: isize, whence: SeekWhence) -> io::Result<isize> {
346 let obj = get_object(fd)?;
347
348 block_on(async { obj.read().await.lseek(offset, whence).await }, None)
349}
350
351pub(crate) fn chmod(fd: FileDescriptor, mode: AccessPermission) -> io::Result<()> {
352 let obj = get_object(fd)?;
353
354 block_on(async { obj.read().await.chmod(mode).await }, None)
355}
356
357pub(crate) fn write(fd: FileDescriptor, buf: &[u8]) -> io::Result<usize> {
358 let obj = get_object(fd)?;
359
360 if buf.is_empty() {
361 return Ok(0);
362 }
363
364 block_on(async { obj.read().await.write(buf).await }, None)
365}
366
367pub(crate) fn truncate(fd: FileDescriptor, length: usize) -> io::Result<()> {
368 let obj = get_object(fd)?;
369 block_on(async { obj.read().await.truncate(length).await }, None)
370}
371
372async fn poll_fds(fds: &mut [PollFd]) -> io::Result<u64> {
373 future::poll_fn(|cx| {
374 let mut counter: u64 = 0;
375
376 for i in &mut *fds {
377 let fd = i.fd;
378 i.revents = PollEvent::empty();
379 if let Ok(obj) = core_scheduler().get_object(fd) {
380 let mut pinned = core::pin::pin!(async { obj.read().await.poll(i.events).await });
381 if let Ready(Ok(e)) = pinned.as_mut().poll(cx)
382 && !e.is_empty()
383 {
384 counter += 1;
385 i.revents = e;
386 }
387 }
388 }
389
390 if counter > 0 {
391 Ready(Ok(counter))
392 } else {
393 Pending
394 }
395 })
396 .await
397}
398
399pub fn poll(fds: &mut [PollFd], timeout: Option<Duration>) -> io::Result<u64> {
406 let result = block_on(poll_fds(fds), timeout);
407 if let Err(ref e) = result
408 && timeout.is_some()
409 {
410 if *e == Errno::Again {
412 return Ok(0);
413 }
414 }
415
416 result
417}
418
419pub fn fstat(fd: FileDescriptor) -> io::Result<FileAttr> {
420 let obj = get_object(fd)?;
421 block_on(async { obj.read().await.fstat().await }, None)
422}
423
424pub fn eventfd(initval: u64, flags: EventFlags) -> io::Result<FileDescriptor> {
443 let obj = self::eventfd::EventFd::new(initval, flags);
444
445 let fd = core_scheduler().insert_object(Arc::new(async_lock::RwLock::new(obj)))?;
446
447 Ok(fd)
448}
449
450pub(crate) fn get_object(
451 fd: FileDescriptor,
452) -> io::Result<Arc<async_lock::RwLock<dyn ObjectInterface>>> {
453 core_scheduler().get_object(fd)
454}
455
456pub(crate) fn insert_object(
457 obj: Arc<async_lock::RwLock<dyn ObjectInterface>>,
458) -> io::Result<FileDescriptor> {
459 core_scheduler().insert_object(obj)
460}
461
462pub(crate) fn dup_object(fd: FileDescriptor) -> io::Result<FileDescriptor> {
467 core_scheduler().dup_object(fd)
468}
469
470pub(crate) fn dup_object2(fd1: FileDescriptor, fd2: FileDescriptor) -> io::Result<FileDescriptor> {
471 core_scheduler().dup_object2(fd1, fd2)
472}
473
474pub(crate) fn remove_object(
475 fd: FileDescriptor,
476) -> io::Result<Arc<async_lock::RwLock<dyn ObjectInterface>>> {
477 core_scheduler().remove_object(fd)
478}
479
480pub(crate) fn isatty(fd: FileDescriptor) -> io::Result<bool> {
481 let obj = get_object(fd)?;
482 block_on(async { obj.read().await.isatty().await }, None)
483}