1 use core::sync::atomic::{AtomicU32, Ordering};
2
3 use alloc::{
4 collections::BTreeMap,
5 string::{String, ToString},
6 sync::{Arc, Weak},
7 vec::Vec,
8 };
9 use ida::IdAllocator;
10 use log::info;
11 use system_error::SystemError;
12 use unified_init::macros::unified_init;
13
14 use crate::{
15 driver::{
16 base::device::{
17 device_number::{DeviceNumber, Major},
18 IdTable,
19 },
20 tty::{
21 pty::unix98pty::NR_UNIX98_PTY_MAX,
22 tty_device::{PtyType, TtyDevice, TtyType},
23 },
24 },
25 filesystem::vfs::{core::do_mount_mkdir, syscall::ModeType, FileType},
26 init::initcall::INITCALL_FS,
27 libs::spinlock::{SpinLock, SpinLockGuard},
28 time::PosixTimeSpec,
29 };
30
31 use super::vfs::{
32 core::generate_inode_id, FilePrivateData, FileSystem, FsInfo, IndexNode, Metadata,
33 };
34
35 const DEV_PTYFS_MAX_NAMELEN: usize = 16;
36
37 #[allow(dead_code)]
38 const PTY_NR_LIMIT: usize = 4096;
39
40 #[derive(Debug)]
41 pub struct DevPtsFs {
42 /// 根节点
43 root_inode: Arc<LockedDevPtsFSInode>,
44 pts_ida: SpinLock<IdAllocator>,
45 pts_count: AtomicU32,
46 }
47
48 impl DevPtsFs {
new() -> Arc<Self>49 pub fn new() -> Arc<Self> {
50 let root_inode = Arc::new(LockedDevPtsFSInode::new());
51 let ret = Arc::new(Self {
52 root_inode,
53 pts_ida: SpinLock::new(IdAllocator::new(0, NR_UNIX98_PTY_MAX as usize).unwrap()),
54 pts_count: AtomicU32::new(0),
55 });
56
57 ret.root_inode.set_fs(Arc::downgrade(&ret));
58
59 ret
60 }
61
alloc_index(&self) -> Result<usize, SystemError>62 pub fn alloc_index(&self) -> Result<usize, SystemError> {
63 self.pts_ida.lock().alloc().ok_or(SystemError::ENOSPC)
64 }
65 }
66
67 impl FileSystem for DevPtsFs {
root_inode(&self) -> Arc<dyn IndexNode>68 fn root_inode(&self) -> Arc<dyn IndexNode> {
69 self.root_inode.clone()
70 }
71
info(&self) -> super::vfs::FsInfo72 fn info(&self) -> super::vfs::FsInfo {
73 return FsInfo {
74 blk_dev_id: 0,
75 max_name_len: DEV_PTYFS_MAX_NAMELEN,
76 };
77 }
78
as_any_ref(&self) -> &dyn core::any::Any79 fn as_any_ref(&self) -> &dyn core::any::Any {
80 self
81 }
82
name(&self) -> &str83 fn name(&self) -> &str {
84 "devpts"
85 }
86
super_block(&self) -> super::vfs::SuperBlock87 fn super_block(&self) -> super::vfs::SuperBlock {
88 todo!()
89 }
90 }
91
92 #[derive(Debug)]
93 pub struct LockedDevPtsFSInode {
94 inner: SpinLock<PtsDevInode>,
95 }
96
97 impl LockedDevPtsFSInode {
new() -> Self98 pub fn new() -> Self {
99 Self {
100 inner: SpinLock::new(PtsDevInode {
101 fs: Weak::new(),
102 children: Some(BTreeMap::new()),
103 metadata: Metadata {
104 dev_id: 0,
105 inode_id: generate_inode_id(),
106 size: 0,
107 blk_size: 0,
108 blocks: 0,
109 atime: PosixTimeSpec::default(),
110 mtime: PosixTimeSpec::default(),
111 ctime: PosixTimeSpec::default(),
112 file_type: FileType::Dir,
113 mode: ModeType::from_bits_truncate(0o777),
114 nlinks: 1,
115 uid: 0,
116 gid: 0,
117 raw_dev: DeviceNumber::default(),
118 },
119 }),
120 }
121 }
122
set_fs(&self, fs: Weak<DevPtsFs>)123 pub fn set_fs(&self, fs: Weak<DevPtsFs>) {
124 self.inner.lock().fs = fs;
125 }
126 }
127
128 #[derive(Debug)]
129 pub struct PtsDevInode {
130 fs: Weak<DevPtsFs>,
131 children: Option<BTreeMap<String, Arc<TtyDevice>>>,
132 metadata: Metadata,
133 }
134
135 impl PtsDevInode {
children_unchecked(&self) -> &BTreeMap<String, Arc<TtyDevice>>136 pub fn children_unchecked(&self) -> &BTreeMap<String, Arc<TtyDevice>> {
137 self.children.as_ref().unwrap()
138 }
139
children_unchecked_mut(&mut self) -> &mut BTreeMap<String, Arc<TtyDevice>>140 pub fn children_unchecked_mut(&mut self) -> &mut BTreeMap<String, Arc<TtyDevice>> {
141 self.children.as_mut().unwrap()
142 }
143 }
144
145 impl IndexNode for LockedDevPtsFSInode {
open( &self, _data: SpinLockGuard<FilePrivateData>, _mode: &super::vfs::file::FileMode, ) -> Result<(), SystemError>146 fn open(
147 &self,
148 _data: SpinLockGuard<FilePrivateData>,
149 _mode: &super::vfs::file::FileMode,
150 ) -> Result<(), SystemError> {
151 Ok(())
152 }
153
metadata(&self) -> Result<super::vfs::Metadata, SystemError>154 fn metadata(&self) -> Result<super::vfs::Metadata, SystemError> {
155 let inode = self.inner.lock();
156 let metadata = inode.metadata.clone();
157
158 return Ok(metadata);
159 }
160
close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError>161 fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
162 // TODO: 回收
163 Ok(())
164 }
165
read_at( &self, _offset: usize, _len: usize, _buf: &mut [u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize, system_error::SystemError>166 fn read_at(
167 &self,
168 _offset: usize,
169 _len: usize,
170 _buf: &mut [u8],
171 _data: SpinLockGuard<FilePrivateData>,
172 ) -> Result<usize, system_error::SystemError> {
173 todo!()
174 }
175
write_at( &self, _offset: usize, _len: usize, _buf: &[u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize, system_error::SystemError>176 fn write_at(
177 &self,
178 _offset: usize,
179 _len: usize,
180 _buf: &[u8],
181 _data: SpinLockGuard<FilePrivateData>,
182 ) -> Result<usize, system_error::SystemError> {
183 todo!()
184 }
185
fs(&self) -> alloc::sync::Arc<dyn super::vfs::FileSystem>186 fn fs(&self) -> alloc::sync::Arc<dyn super::vfs::FileSystem> {
187 self.inner.lock().fs.upgrade().unwrap()
188 }
189
as_any_ref(&self) -> &dyn core::any::Any190 fn as_any_ref(&self) -> &dyn core::any::Any {
191 todo!()
192 }
193
list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError>194 fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, system_error::SystemError> {
195 let info = self.metadata()?;
196 if info.file_type != FileType::Dir {
197 return Err(SystemError::ENOTDIR);
198 }
199
200 let mut keys: Vec<String> = Vec::new();
201 keys.push(String::from("."));
202 keys.push(String::from(".."));
203 keys.append(
204 &mut self
205 .inner
206 .lock()
207 .children_unchecked()
208 .keys()
209 .cloned()
210 .collect(),
211 );
212
213 return Ok(keys);
214 }
215
create_with_data( &self, name: &str, file_type: FileType, _mode: super::vfs::syscall::ModeType, _data: usize, ) -> Result<Arc<dyn IndexNode>, SystemError>216 fn create_with_data(
217 &self,
218 name: &str,
219 file_type: FileType,
220 _mode: super::vfs::syscall::ModeType,
221 _data: usize,
222 ) -> Result<Arc<dyn IndexNode>, SystemError> {
223 if file_type != FileType::CharDevice {
224 return Err(SystemError::ENOSYS);
225 }
226
227 let mut guard = self.inner.lock();
228
229 if guard.children_unchecked_mut().contains_key(name) {
230 return Err(SystemError::EEXIST);
231 }
232
233 let fs = guard.fs.upgrade().unwrap();
234
235 let result = TtyDevice::new(
236 name.to_string(),
237 IdTable::new(name.to_string(), None),
238 TtyType::Pty(PtyType::Pts),
239 );
240
241 let mut metadata = result.metadata()?;
242
243 metadata.mode.insert(ModeType::S_IFCHR);
244 metadata.raw_dev =
245 DeviceNumber::new(Major::UNIX98_PTY_SLAVE_MAJOR, name.parse::<u32>().unwrap());
246
247 result.set_metadata(&metadata)?;
248
249 guard
250 .children_unchecked_mut()
251 .insert(name.to_string(), result.clone());
252
253 fs.pts_count.fetch_add(1, Ordering::SeqCst);
254
255 Ok(result)
256 }
257
find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError>258 fn find(&self, name: &str) -> Result<Arc<dyn IndexNode>, SystemError> {
259 let guard = self.inner.lock();
260
261 if let Some(dev) = guard.children_unchecked().get(name) {
262 Ok(dev.clone() as Arc<dyn IndexNode>)
263 } else {
264 Err(SystemError::ENOENT)
265 }
266 }
267
unlink(&self, name: &str) -> Result<(), SystemError>268 fn unlink(&self, name: &str) -> Result<(), SystemError> {
269 let mut guard = self.inner.lock();
270 guard.children_unchecked_mut().remove(name);
271 Ok(())
272 }
273 }
274
275 #[unified_init(INITCALL_FS)]
276 #[inline(never)]
devpts_init() -> Result<(), SystemError>277 pub fn devpts_init() -> Result<(), SystemError> {
278 // 创建 devptsfs 实例
279 let ptsfs: Arc<DevPtsFs> = DevPtsFs::new();
280
281 do_mount_mkdir(ptsfs, "/dev/pts").expect("Failed to mount DevPtsFS");
282 info!("DevPtsFs mounted.");
283
284 Ok(())
285 }
286