1use core::{any::Any, ffi::c_int};
2
3use alloc::{string::String, sync::Arc};
4use axerrno::{LinuxError, LinuxResult};
5use axfs::fops::DirEntry;
6use axio::PollState;
7use axsync::{Mutex, MutexGuard};
8use linux_raw_sys::general::S_IFDIR;
9
10use super::{FileLike, Kstat, get_file_like};
11
12pub struct File {
14 inner: Mutex<axfs::fops::File>,
15 path: String,
16}
17
18impl File {
19 pub fn new(inner: axfs::fops::File, path: String) -> Self {
20 Self {
21 inner: Mutex::new(inner),
22 path,
23 }
24 }
25
26 pub fn path(&self) -> &str {
28 &self.path
29 }
30
31 pub fn inner(&self) -> MutexGuard<axfs::fops::File> {
33 self.inner.lock()
34 }
35}
36
37impl FileLike for File {
38 fn read(&self, buf: &mut [u8]) -> LinuxResult<usize> {
39 Ok(self.inner().read(buf)?)
40 }
41
42 fn write(&self, buf: &[u8]) -> LinuxResult<usize> {
43 Ok(self.inner().write(buf)?)
44 }
45
46 fn stat(&self) -> LinuxResult<Kstat> {
47 let metadata = self.inner().get_attr()?;
48 let ty = metadata.file_type() as u8;
49 let perm = metadata.perm().bits() as u32;
50
51 Ok(Kstat {
52 mode: ((ty as u32) << 12) | perm,
53 size: metadata.size(),
54 blocks: metadata.blocks(),
55 blksize: 512,
56 ..Default::default()
57 })
58 }
59
60 fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
61 self
62 }
63
64 fn poll(&self) -> LinuxResult<PollState> {
65 Ok(PollState {
66 readable: true,
67 writable: true,
68 })
69 }
70
71 fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
72 Ok(())
73 }
74}
75
76pub struct Directory {
78 inner: Mutex<axfs::fops::Directory>,
79 path: String,
80 last_dirent: Mutex<Option<DirEntry>>,
81}
82
83impl Directory {
84 pub fn new(inner: axfs::fops::Directory, path: String) -> Self {
85 Self {
86 inner: Mutex::new(inner),
87 path,
88 last_dirent: Mutex::new(None),
89 }
90 }
91
92 pub fn path(&self) -> &str {
94 &self.path
95 }
96
97 pub fn inner(&self) -> MutexGuard<axfs::fops::Directory> {
99 self.inner.lock()
100 }
101
102 pub fn last_dirent(&self) -> MutexGuard<Option<DirEntry>> {
104 self.last_dirent.lock()
105 }
106}
107
108impl FileLike for Directory {
109 fn read(&self, _buf: &mut [u8]) -> LinuxResult<usize> {
110 Err(LinuxError::EBADF)
111 }
112
113 fn write(&self, _buf: &[u8]) -> LinuxResult<usize> {
114 Err(LinuxError::EBADF)
115 }
116
117 fn stat(&self) -> LinuxResult<Kstat> {
118 Ok(Kstat {
119 mode: S_IFDIR | 0o755u32, ..Default::default()
121 })
122 }
123
124 fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
125 self
126 }
127
128 fn poll(&self) -> LinuxResult<PollState> {
129 Ok(PollState {
130 readable: true,
131 writable: false,
132 })
133 }
134
135 fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult {
136 Ok(())
137 }
138
139 fn from_fd(fd: c_int) -> LinuxResult<Arc<Self>> {
140 get_file_like(fd)?
141 .into_any()
142 .downcast::<Self>()
143 .map_err(|_| LinuxError::ENOTDIR)
144 }
145}