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