xref: /DragonOS/kernel/src/filesystem/vfs/file.rs (revision cf7f801e1d50ee5b04cb728e4251a57f4183bfbc)
1 use core::sync::atomic::{AtomicUsize, Ordering};
2 
3 use alloc::{
4     string::String,
5     sync::{Arc, Weak},
6     vec::Vec,
7 };
8 use log::error;
9 use system_error::SystemError;
10 use xarray::XArray;
11 
12 use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
13 use crate::filesystem::eventfd::EventFdInode;
14 use crate::{
15     arch::MMArch,
16     driver::{
17         base::{block::SeekFrom, device::DevicePrivateData},
18         tty::tty_device::TtyFilePrivateData,
19     },
20     filesystem::procfs::ProcfsFilePrivateData,
21     ipc::pipe::{LockedPipeInode, PipeFsPrivateData},
22     libs::{rwlock::RwLock, spinlock::SpinLock},
23     mm::{page::Page, MemoryManagementArch},
24     net::{
25         event_poll::{EPollItem, EPollPrivateData, EventPoll},
26         socket::SocketInode,
27     },
28     process::{cred::Cred, ProcessManager},
29 };
30 
31 /// 文件私有信息的枚举类型
32 #[derive(Debug, Clone)]
33 #[allow(dead_code)]
34 pub enum FilePrivateData {
35     /// 管道文件私有信息
36     Pipefs(PipeFsPrivateData),
37     /// procfs文件私有信息
38     Procfs(ProcfsFilePrivateData),
39     /// 设备文件的私有信息
40     DevFS(DevicePrivateData),
41     /// tty设备文件的私有信息
42     Tty(TtyFilePrivateData),
43     /// epoll私有信息
44     EPoll(EPollPrivateData),
45     /// 不需要文件私有信息
46     Unused,
47 }
48 
49 impl Default for FilePrivateData {
50     fn default() -> Self {
51         return Self::Unused;
52     }
53 }
54 
55 impl FilePrivateData {
56     pub fn update_mode(&mut self, mode: FileMode) {
57         if let FilePrivateData::Pipefs(pdata) = self {
58             pdata.set_mode(mode);
59         }
60     }
61 }
62 
63 bitflags! {
64     /// @brief 文件打开模式
65     /// 其中,低2bit组合而成的数字的值,用于表示访问权限。其他的bit,才支持通过按位或的方式来表示参数
66     ///
67     /// 与Linux 5.19.10的uapi/asm-generic/fcntl.h相同
68     /// https://code.dragonos.org.cn/xref/linux-5.19.10/tools/include/uapi/asm-generic/fcntl.h#19
69     #[allow(clippy::bad_bit_mask)]
70     pub struct FileMode: u32{
71         /* File access modes for `open' and `fcntl'.  */
72         /// Open Read-only
73         const O_RDONLY = 0o0;
74         /// Open Write-only
75         const O_WRONLY = 0o1;
76         /// Open read/write
77         const O_RDWR = 0o2;
78         /// Mask for file access modes
79         const O_ACCMODE = 0o00000003;
80 
81         /* Bits OR'd into the second argument to open.  */
82         /// Create file if it does not exist
83         const O_CREAT = 0o00000100;
84         /// Fail if file already exists
85         const O_EXCL = 0o00000200;
86         /// Do not assign controlling terminal
87         const O_NOCTTY = 0o00000400;
88         /// 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空
89         const O_TRUNC = 0o00001000;
90         /// 文件指针会被移动到文件末尾
91         const O_APPEND = 0o00002000;
92         /// 非阻塞式IO模式
93         const O_NONBLOCK = 0o00004000;
94         /// 每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新
95         const O_DSYNC = 0o00010000;
96         /// fcntl, for BSD compatibility
97         const FASYNC = 0o00020000;
98         /* direct disk access hint */
99         const O_DIRECT = 0o00040000;
100         const O_LARGEFILE = 0o00100000;
101         /// 打开的必须是一个目录
102         const O_DIRECTORY = 0o00200000;
103         /// Do not follow symbolic links
104         const O_NOFOLLOW = 0o00400000;
105         const O_NOATIME = 0o01000000;
106         /// set close_on_exec
107         const O_CLOEXEC = 0o02000000;
108         /// 每次write都等到物理I/O完成,包括write引起的文件属性的更新
109         const O_SYNC = 0o04000000;
110 
111         const O_PATH = 0o10000000;
112 
113         const O_PATH_FLAGS = Self::O_DIRECTORY.bits|Self::O_NOFOLLOW.bits|Self::O_CLOEXEC.bits|Self::O_PATH.bits;
114     }
115 }
116 
117 impl FileMode {
118     /// @brief 获取文件的访问模式的值
119     #[inline]
120     pub fn accmode(&self) -> u32 {
121         return self.bits() & FileMode::O_ACCMODE.bits();
122     }
123 }
124 
125 /// 页面缓存
126 pub struct PageCache {
127     xarray: SpinLock<XArray<Arc<Page>>>,
128     inode: Option<Weak<dyn IndexNode>>,
129 }
130 
131 impl core::fmt::Debug for PageCache {
132     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
133         f.debug_struct("PageCache")
134             .field(
135                 "xarray",
136                 &self
137                     .xarray
138                     .lock()
139                     .range(0..((MMArch::PAGE_ADDRESS_SIZE >> MMArch::PAGE_SHIFT) as u64))
140                     .map(|(_, r)| (*r).clone())
141                     .collect::<Vec<Arc<Page>>>(),
142             )
143             .finish()
144     }
145 }
146 
147 impl PageCache {
148     pub fn new(inode: Option<Weak<dyn IndexNode>>) -> Arc<PageCache> {
149         let page_cache = Self {
150             xarray: SpinLock::new(XArray::new()),
151             inode,
152         };
153         Arc::new(page_cache)
154     }
155 
156     pub fn inode(&self) -> Option<Weak<dyn IndexNode>> {
157         self.inode.clone()
158     }
159 
160     pub fn add_page(&self, offset: usize, page: &Arc<Page>) {
161         let mut guard = self.xarray.lock();
162         let mut cursor = guard.cursor_mut(offset as u64);
163         cursor.store(page.clone());
164     }
165 
166     pub fn get_page(&self, offset: usize) -> Option<Arc<Page>> {
167         let mut guard = self.xarray.lock();
168         let mut cursor = guard.cursor_mut(offset as u64);
169         let page = cursor.load().map(|r| (*r).clone());
170         page
171     }
172 
173     pub fn remove_page(&self, offset: usize) {
174         let mut guard = self.xarray.lock();
175         let mut cursor = guard.cursor_mut(offset as u64);
176         cursor.remove();
177     }
178 
179     pub fn set_inode(&mut self, inode: Weak<dyn IndexNode>) {
180         self.inode = Some(inode)
181     }
182 }
183 
184 /// @brief 抽象文件结构体
185 #[derive(Debug)]
186 pub struct File {
187     inode: Arc<dyn IndexNode>,
188     /// 对于文件,表示字节偏移量;对于文件夹,表示当前操作的子目录项偏移量
189     offset: AtomicUsize,
190     /// 文件的打开模式
191     mode: RwLock<FileMode>,
192     /// 文件类型
193     file_type: FileType,
194     /// readdir时候用的,暂存的本次循环中,所有子目录项的名字的数组
195     readdir_subdirs_name: SpinLock<Vec<String>>,
196     pub private_data: SpinLock<FilePrivateData>,
197     /// 文件的凭证
198     cred: Cred,
199 }
200 
201 impl File {
202     /// @brief 创建一个新的文件对象
203     ///
204     /// @param inode 文件对象对应的inode
205     /// @param mode 文件的打开模式
206     pub fn new(inode: Arc<dyn IndexNode>, mode: FileMode) -> Result<Self, SystemError> {
207         let mut inode = inode;
208         let file_type = inode.metadata()?.file_type;
209         if file_type == FileType::Pipe {
210             if let Some(SpecialNodeData::Pipe(pipe_inode)) = inode.special_node() {
211                 inode = pipe_inode;
212             }
213         }
214 
215         let f = File {
216             inode,
217             offset: AtomicUsize::new(0),
218             mode: RwLock::new(mode),
219             file_type,
220             readdir_subdirs_name: SpinLock::new(Vec::default()),
221             private_data: SpinLock::new(FilePrivateData::default()),
222             cred: ProcessManager::current_pcb().cred(),
223         };
224         f.inode.open(f.private_data.lock(), &mode)?;
225 
226         return Ok(f);
227     }
228 
229     /// @brief 从文件中读取指定的字节数到buffer中
230     ///
231     /// @param len 要读取的字节数
232     /// @param buf 目标buffer
233     ///
234     /// @return Ok(usize) 成功读取的字节数
235     /// @return Err(SystemError) 错误码
236     pub fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
237         self.do_read(
238             self.offset.load(core::sync::atomic::Ordering::SeqCst),
239             len,
240             buf,
241             true,
242         )
243     }
244 
245     /// @brief 从buffer向文件写入指定的字节数的数据
246     ///
247     /// @param len 要写入的字节数
248     /// @param buf 源数据buffer
249     ///
250     /// @return Ok(usize) 成功写入的字节数
251     /// @return Err(SystemError) 错误码
252     pub fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
253         self.do_write(
254             self.offset.load(core::sync::atomic::Ordering::SeqCst),
255             len,
256             buf,
257             true,
258         )
259     }
260 
261     /// ## 从文件中指定的偏移处读取指定的字节数到buf中
262     ///
263     /// ### 参数
264     /// - `offset`: 文件偏移量
265     /// - `len`: 要读取的字节数
266     /// - `buf`: 读出缓冲区
267     ///
268     /// ### 返回值
269     /// - `Ok(usize)`: 成功读取的字节数
270     pub fn pread(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> {
271         self.do_read(offset, len, buf, false)
272     }
273 
274     /// ## 从buf向文件中指定的偏移处写入指定的字节数的数据
275     ///
276     /// ### 参数
277     /// - `offset`: 文件偏移量
278     /// - `len`: 要写入的字节数
279     /// - `buf`: 写入缓冲区
280     ///
281     /// ### 返回值
282     /// - `Ok(usize)`: 成功写入的字节数
283     pub fn pwrite(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> {
284         self.do_write(offset, len, buf, false)
285     }
286 
287     fn do_read(
288         &self,
289         offset: usize,
290         len: usize,
291         buf: &mut [u8],
292         update_offset: bool,
293     ) -> Result<usize, SystemError> {
294         // 先检查本文件在权限等规则下,是否可读取。
295         self.readable()?;
296         if buf.len() < len {
297             return Err(SystemError::ENOBUFS);
298         }
299 
300         let len = self
301             .inode
302             .read_at(offset, len, buf, self.private_data.lock())
303             .map_err(|e| {
304                 if e == SystemError::ERESTARTSYS {
305                     SystemError::EINTR
306                 } else {
307                     e
308                 }
309             })?;
310 
311         if update_offset {
312             self.offset
313                 .fetch_add(len, core::sync::atomic::Ordering::SeqCst);
314         }
315 
316         Ok(len)
317     }
318 
319     fn do_write(
320         &self,
321         offset: usize,
322         len: usize,
323         buf: &[u8],
324         update_offset: bool,
325     ) -> Result<usize, SystemError> {
326         // 先检查本文件在权限等规则下,是否可写入。
327         self.writeable()?;
328         if buf.len() < len {
329             return Err(SystemError::ENOBUFS);
330         }
331 
332         // 如果文件指针已经超过了文件大小,则需要扩展文件大小
333         if offset > self.inode.metadata()?.size as usize {
334             self.inode.resize(offset).map_err(|e| {
335                 if e == SystemError::ERESTARTSYS {
336                     SystemError::EINTR
337                 } else {
338                     e
339                 }
340             })?;
341         }
342         let len = self
343             .inode
344             .write_at(offset, len, buf, self.private_data.lock())
345             .map_err(|e| {
346                 if e == SystemError::ERESTARTSYS {
347                     SystemError::EINTR
348                 } else {
349                     e
350                 }
351             })?;
352 
353         if update_offset {
354             self.offset
355                 .fetch_add(len, core::sync::atomic::Ordering::SeqCst);
356         }
357 
358         Ok(len)
359     }
360 
361     /// @brief 获取文件的元数据
362     pub fn metadata(&self) -> Result<Metadata, SystemError> {
363         return self.inode.metadata();
364     }
365 
366     /// @brief 根据inode号获取子目录项的名字
367     #[allow(dead_code)]
368     pub fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> {
369         return self.inode.get_entry_name(ino);
370     }
371 
372     /// @brief 调整文件操作指针的位置
373     ///
374     /// @param origin 调整的起始位置
375     pub fn lseek(&self, origin: SeekFrom) -> Result<usize, SystemError> {
376         let file_type = self.inode.metadata()?.file_type;
377         match file_type {
378             FileType::Pipe | FileType::CharDevice => {
379                 return Err(SystemError::ESPIPE);
380             }
381             _ => {}
382         }
383 
384         let pos: i64 = match origin {
385             SeekFrom::SeekSet(offset) => offset,
386             SeekFrom::SeekCurrent(offset) => self.offset.load(Ordering::SeqCst) as i64 + offset,
387             SeekFrom::SeekEnd(offset) => {
388                 let metadata = self.metadata()?;
389                 metadata.size + offset
390             }
391             SeekFrom::Invalid => {
392                 return Err(SystemError::EINVAL);
393             }
394         };
395         // 根据linux man page, lseek允许超出文件末尾,并且不改变文件大小
396         // 当pos超出文件末尾时,read返回0。直到开始写入数据时,才会改变文件大小
397         if pos < 0 {
398             return Err(SystemError::EOVERFLOW);
399         }
400         self.offset.store(pos as usize, Ordering::SeqCst);
401         return Ok(pos as usize);
402     }
403 
404     /// @brief 判断当前文件是否可读
405     #[inline]
406     pub fn readable(&self) -> Result<(), SystemError> {
407         // 暂时认为只要不是write only, 就可读
408         if *self.mode.read() == FileMode::O_WRONLY {
409             return Err(SystemError::EPERM);
410         }
411 
412         return Ok(());
413     }
414 
415     /// @brief 判断当前文件是否可写
416     #[inline]
417     pub fn writeable(&self) -> Result<(), SystemError> {
418         // 暂时认为只要不是read only, 就可写
419         if *self.mode.read() == FileMode::O_RDONLY {
420             return Err(SystemError::EPERM);
421         }
422 
423         return Ok(());
424     }
425 
426     /// @biref 充填dirent结构体
427     /// @return 返回dirent结构体的大小
428     pub fn readdir(&self, dirent: &mut Dirent) -> Result<u64, SystemError> {
429         let inode: &Arc<dyn IndexNode> = &self.inode;
430         let mut readdir_subdirs_name = self.readdir_subdirs_name.lock();
431         let offset = self.offset.load(Ordering::SeqCst);
432         // 如果偏移量为0
433         if offset == 0 {
434             // 通过list更新readdir_subdirs_name
435             *readdir_subdirs_name = inode.list()?;
436             readdir_subdirs_name.sort();
437         }
438         // debug!("sub_entries={sub_entries:?}");
439 
440         // 已经读到末尾
441         if offset == readdir_subdirs_name.len() {
442             self.offset.store(0, Ordering::SeqCst);
443             return Ok(0);
444         }
445         let name = &readdir_subdirs_name[offset];
446         let sub_inode: Arc<dyn IndexNode> = match inode.find(name) {
447             Ok(i) => i,
448             Err(e) => {
449                 error!(
450                     "Readdir error: Failed to find sub inode:{name:?}, file={self:?}, error={e:?}"
451                 );
452                 return Err(e);
453             }
454         };
455 
456         let name_bytes: &[u8] = name.as_bytes();
457 
458         // 根据posix的规定,dirent中的d_name是一个不定长的数组,因此需要unsafe来拷贝数据
459         unsafe {
460             let ptr = &mut dirent.d_name as *mut u8;
461 
462             let buf: &mut [u8] =
463                 ::core::slice::from_raw_parts_mut::<'static, u8>(ptr, name_bytes.len() + 1);
464             buf[0..name_bytes.len()].copy_from_slice(name_bytes);
465             buf[name_bytes.len()] = 0;
466         }
467 
468         self.offset.fetch_add(1, Ordering::SeqCst);
469         dirent.d_ino = sub_inode.metadata().unwrap().inode_id.into() as u64;
470         dirent.d_type = sub_inode.metadata().unwrap().file_type.get_file_type_num() as u8;
471 
472         // 计算dirent结构体的大小
473         let size = (name_bytes.len() + ::core::mem::size_of::<Dirent>()
474             - ::core::mem::size_of_val(&dirent.d_name)) as u64;
475 
476         dirent.d_reclen = size as u16;
477         dirent.d_off += dirent.d_reclen as i64;
478 
479         return Ok(size);
480     }
481 
482     pub fn inode(&self) -> Arc<dyn IndexNode> {
483         return self.inode.clone();
484     }
485 
486     /// @brief 尝试克隆一个文件
487     ///
488     /// @return Option<File> 克隆后的文件结构体。如果克隆失败,返回None
489     pub fn try_clone(&self) -> Option<File> {
490         let res = Self {
491             inode: self.inode.clone(),
492             offset: AtomicUsize::new(self.offset.load(Ordering::SeqCst)),
493             mode: RwLock::new(self.mode()),
494             file_type: self.file_type,
495             readdir_subdirs_name: SpinLock::new(self.readdir_subdirs_name.lock().clone()),
496             private_data: SpinLock::new(self.private_data.lock().clone()),
497             cred: self.cred.clone(),
498         };
499         // 调用inode的open方法,让inode知道有新的文件打开了这个inode
500         if self
501             .inode
502             .open(res.private_data.lock(), &res.mode())
503             .is_err()
504         {
505             return None;
506         }
507 
508         return Some(res);
509     }
510 
511     /// @brief 获取文件的类型
512     #[inline]
513     pub fn file_type(&self) -> FileType {
514         return self.file_type;
515     }
516 
517     /// @brief 获取文件的打开模式
518     #[inline]
519     pub fn mode(&self) -> FileMode {
520         return *self.mode.read();
521     }
522 
523     /// 获取文件是否在execve时关闭
524     #[inline]
525     pub fn close_on_exec(&self) -> bool {
526         return self.mode().contains(FileMode::O_CLOEXEC);
527     }
528 
529     /// 设置文件是否在execve时关闭
530     #[inline]
531     pub fn set_close_on_exec(&self, close_on_exec: bool) {
532         let mut mode_guard = self.mode.write();
533         if close_on_exec {
534             mode_guard.insert(FileMode::O_CLOEXEC);
535         } else {
536             mode_guard.remove(FileMode::O_CLOEXEC);
537         }
538     }
539 
540     pub fn set_mode(&self, mode: FileMode) -> Result<(), SystemError> {
541         // todo: 是否需要调用inode的open方法,以更新private data(假如它与mode有关的话)?
542         // 也许需要加个更好的设计,让inode知晓文件的打开模式发生了变化,让它自己决定是否需要更新private data
543 
544         // 直接修改文件的打开模式
545         *self.mode.write() = mode;
546         self.private_data.lock().update_mode(mode);
547         return Ok(());
548     }
549 
550     /// @brief 重新设置文件的大小
551     ///
552     /// 如果文件大小增加,则文件内容不变,但是文件的空洞部分会被填充为0
553     /// 如果文件大小减小,则文件内容会被截断
554     ///
555     /// @return 成功:Ok()
556     ///         失败:Err(错误码)
557     pub fn ftruncate(&self, len: usize) -> Result<(), SystemError> {
558         // 如果文件不可写,返回错误
559         self.writeable()?;
560 
561         // 调用inode的truncate方法
562         self.inode.resize(len)?;
563         return Ok(());
564     }
565 
566     /// ## 向该文件添加一个EPollItem对象
567     ///
568     /// 在文件状态发生变化时,需要向epoll通知
569     pub fn add_epoll(&self, epitem: Arc<EPollItem>) -> Result<(), SystemError> {
570         match self.file_type {
571             FileType::Socket => {
572                 let inode = self.inode.downcast_ref::<SocketInode>().unwrap();
573                 let mut socket = inode.inner();
574 
575                 return socket.add_epoll(epitem);
576             }
577             FileType::Pipe => {
578                 let inode = self.inode.downcast_ref::<LockedPipeInode>().unwrap();
579                 return inode.inner().lock().add_epoll(epitem);
580             }
581             _ => {
582                 let r = self.inode.kernel_ioctl(epitem, &self.private_data.lock());
583                 if r.is_err() {
584                     return Err(SystemError::ENOSYS);
585                 }
586 
587                 Ok(())
588             }
589         }
590     }
591 
592     /// ## 删除一个绑定的epoll
593     pub fn remove_epoll(&self, epoll: &Weak<SpinLock<EventPoll>>) -> Result<(), SystemError> {
594         match self.file_type {
595             FileType::Socket => {
596                 let inode = self.inode.downcast_ref::<SocketInode>().unwrap();
597                 let mut socket = inode.inner();
598 
599                 socket.remove_epoll(epoll)
600             }
601             FileType::Pipe => {
602                 let inode = self.inode.downcast_ref::<LockedPipeInode>().unwrap();
603                 inode.inner().lock().remove_epoll(epoll)
604             }
605             _ => {
606                 let inode = self
607                     .inode
608                     .downcast_ref::<EventFdInode>()
609                     .ok_or(SystemError::ENOSYS)?;
610                 inode.remove_epoll(epoll)
611             }
612         }
613     }
614 
615     pub fn poll(&self) -> Result<usize, SystemError> {
616         self.inode.poll(&self.private_data.lock())
617     }
618 }
619 
620 impl Drop for File {
621     fn drop(&mut self) {
622         let r: Result<(), SystemError> = self.inode.close(self.private_data.lock());
623         // 打印错误信息
624         if r.is_err() {
625             error!(
626                 "pid: {:?} failed to close file: {:?}, errno={:?}",
627                 ProcessManager::current_pcb().pid(),
628                 self,
629                 r.as_ref().unwrap_err()
630             );
631         }
632     }
633 }
634 
635 /// @brief pcb里面的文件描述符数组
636 #[derive(Debug)]
637 pub struct FileDescriptorVec {
638     /// 当前进程打开的文件描述符
639     fds: Vec<Option<Arc<File>>>,
640 }
641 impl Default for FileDescriptorVec {
642     fn default() -> Self {
643         Self::new()
644     }
645 }
646 impl FileDescriptorVec {
647     pub const PROCESS_MAX_FD: usize = 1024;
648 
649     #[inline(never)]
650     pub fn new() -> FileDescriptorVec {
651         let mut data = Vec::with_capacity(FileDescriptorVec::PROCESS_MAX_FD);
652         data.resize(FileDescriptorVec::PROCESS_MAX_FD, None);
653 
654         // 初始化文件描述符数组结构体
655         return FileDescriptorVec { fds: data };
656     }
657 
658     /// @brief 克隆一个文件描述符数组
659     ///
660     /// @return FileDescriptorVec 克隆后的文件描述符数组
661     pub fn clone(&self) -> FileDescriptorVec {
662         let mut res = FileDescriptorVec::new();
663         for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
664             if let Some(file) = &self.fds[i] {
665                 if let Some(file) = file.try_clone() {
666                     res.fds[i] = Some(Arc::new(file));
667                 }
668             }
669         }
670         return res;
671     }
672 
673     /// 返回 `已经打开的` 文件描述符的数量
674     pub fn fd_open_count(&self) -> usize {
675         let mut size = 0;
676         for fd in &self.fds {
677             if fd.is_some() {
678                 size += 1;
679             }
680         }
681         return size;
682     }
683 
684     /// @brief 判断文件描述符序号是否合法
685     ///
686     /// @return true 合法
687     ///
688     /// @return false 不合法
689     #[inline]
690     pub fn validate_fd(fd: i32) -> bool {
691         return !(fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD);
692     }
693 
694     /// 申请文件描述符,并把文件对象存入其中。
695     ///
696     /// ## 参数
697     ///
698     /// - `file` 要存放的文件对象
699     /// - `fd` 如果为Some(i32),表示指定要申请这个文件描述符,如果这个文件描述符已经被使用,那么返回EBADF
700     ///
701     /// ## 返回值
702     ///
703     /// - `Ok(i32)` 申请成功,返回申请到的文件描述符
704     /// - `Err(SystemError)` 申请失败,返回错误码,并且,file对象将被drop掉
705     pub fn alloc_fd(&mut self, file: File, fd: Option<i32>) -> Result<i32, SystemError> {
706         if let Some(new_fd) = fd {
707             let x = &mut self.fds[new_fd as usize];
708             if x.is_none() {
709                 *x = Some(Arc::new(file));
710                 return Ok(new_fd);
711             } else {
712                 return Err(SystemError::EBADF);
713             }
714         } else {
715             // 没有指定要申请的文件描述符编号
716             for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
717                 if self.fds[i].is_none() {
718                     self.fds[i] = Some(Arc::new(file));
719                     return Ok(i as i32);
720                 }
721             }
722             return Err(SystemError::EMFILE);
723         }
724     }
725 
726     /// 根据文件描述符序号,获取文件结构体的Arc指针
727     ///
728     /// ## 参数
729     ///
730     /// - `fd` 文件描述符序号
731     pub fn get_file_by_fd(&self, fd: i32) -> Option<Arc<File>> {
732         if !FileDescriptorVec::validate_fd(fd) {
733             return None;
734         }
735         self.fds[fd as usize].clone()
736     }
737 
738     /// 释放文件描述符,同时关闭文件。
739     ///
740     /// ## 参数
741     ///
742     /// - `fd` 文件描述符序号
743     pub fn drop_fd(&mut self, fd: i32) -> Result<Arc<File>, SystemError> {
744         self.get_file_by_fd(fd).ok_or(SystemError::EBADF)?;
745 
746         // 把文件描述符数组对应位置设置为空
747         let file = self.fds[fd as usize].take().unwrap();
748 
749         return Ok(file);
750     }
751 
752     #[allow(dead_code)]
753     pub fn iter(&self) -> FileDescriptorIterator {
754         return FileDescriptorIterator::new(self);
755     }
756 
757     pub fn close_on_exec(&mut self) {
758         for i in 0..FileDescriptorVec::PROCESS_MAX_FD {
759             if let Some(file) = &self.fds[i] {
760                 let to_drop = file.close_on_exec();
761                 if to_drop {
762                     if let Err(r) = self.drop_fd(i as i32) {
763                         error!(
764                             "Failed to close file: pid = {:?}, fd = {}, error = {:?}",
765                             ProcessManager::current_pcb().pid(),
766                             i,
767                             r
768                         );
769                     }
770                 }
771             }
772         }
773     }
774 }
775 
776 #[derive(Debug)]
777 pub struct FileDescriptorIterator<'a> {
778     fds: &'a FileDescriptorVec,
779     index: usize,
780 }
781 
782 impl<'a> FileDescriptorIterator<'a> {
783     pub fn new(fds: &'a FileDescriptorVec) -> Self {
784         return Self { fds, index: 0 };
785     }
786 }
787 
788 impl<'a> Iterator for FileDescriptorIterator<'a> {
789     type Item = (i32, Arc<File>);
790 
791     fn next(&mut self) -> Option<Self::Item> {
792         while self.index < FileDescriptorVec::PROCESS_MAX_FD {
793             let fd = self.index as i32;
794             self.index += 1;
795             if let Some(file) = self.fds.get_file_by_fd(fd) {
796                 return Some((fd, file));
797             }
798         }
799         return None;
800     }
801 }
802