1dfe53cf0SGnoCiYeH use core::sync::atomic::{AtomicUsize, Ordering}; 2dfe53cf0SGnoCiYeH 340609970SGnoCiYeH use alloc::{ 440609970SGnoCiYeH string::String, 540609970SGnoCiYeH sync::{Arc, Weak}, 640609970SGnoCiYeH vec::Vec, 740609970SGnoCiYeH }; 82eab6dd7S曾俊 use log::error; 991e9d4abSLoGin use system_error::SystemError; 10004e86ffSlogin 11004e86ffSlogin use crate::{ 12b087521eSChiichen driver::{ 13b087521eSChiichen base::{block::SeekFrom, device::DevicePrivateData}, 1452da9a59SGnoCiYeH tty::tty_device::TtyFilePrivateData, 15b087521eSChiichen }, 16b087521eSChiichen filesystem::procfs::ProcfsFilePrivateData, 175e948c56SGnoCiYeH ipc::pipe::{LockedPipeInode, PipeFsPrivateData}, 18dfe53cf0SGnoCiYeH libs::{rwlock::RwLock, spinlock::SpinLock}, 1940609970SGnoCiYeH net::{ 2040609970SGnoCiYeH event_poll::{EPollItem, EPollPrivateData, EventPoll}, 2140609970SGnoCiYeH socket::SocketInode, 2240609970SGnoCiYeH }, 231496ba7bSLoGin process::ProcessManager, 24004e86ffSlogin }; 25004e86ffSlogin 262dbef785SGnoCiYeH use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData}; 27004e86ffSlogin 28004e86ffSlogin /// 文件私有信息的枚举类型 29004e86ffSlogin #[derive(Debug, Clone)] 30bf4a4899SLoGin #[allow(dead_code)] 31004e86ffSlogin pub enum FilePrivateData { 32876cb89eSGnoCiYeH /// 管道文件私有信息 33876cb89eSGnoCiYeH Pipefs(PipeFsPrivateData), 340d48c3c9Slogin /// procfs文件私有信息 35004e86ffSlogin Procfs(ProcfsFilePrivateData), 36b087521eSChiichen /// 设备文件的私有信息 37b087521eSChiichen DevFS(DevicePrivateData), 38b087521eSChiichen /// tty设备文件的私有信息 390d48c3c9Slogin Tty(TtyFilePrivateData), 4040609970SGnoCiYeH /// epoll私有信息 4140609970SGnoCiYeH EPoll(EPollPrivateData), 420d48c3c9Slogin /// 不需要文件私有信息 43004e86ffSlogin Unused, 44004e86ffSlogin } 45004e86ffSlogin 46004e86ffSlogin impl Default for FilePrivateData { 47004e86ffSlogin fn default() -> Self { 48004e86ffSlogin return Self::Unused; 49004e86ffSlogin } 50004e86ffSlogin } 51004e86ffSlogin 525e948c56SGnoCiYeH impl FilePrivateData { 535e948c56SGnoCiYeH pub fn update_mode(&mut self, mode: FileMode) { 545e948c56SGnoCiYeH if let FilePrivateData::Pipefs(pdata) = self { 555e948c56SGnoCiYeH pdata.set_mode(mode); 565e948c56SGnoCiYeH } 575e948c56SGnoCiYeH } 585e948c56SGnoCiYeH } 595e948c56SGnoCiYeH 60004e86ffSlogin bitflags! { 61004e86ffSlogin /// @brief 文件打开模式 62004e86ffSlogin /// 其中,低2bit组合而成的数字的值,用于表示访问权限。其他的bit,才支持通过按位或的方式来表示参数 63004e86ffSlogin /// 64004e86ffSlogin /// 与Linux 5.19.10的uapi/asm-generic/fcntl.h相同 65e7071df6SLoGin /// https://code.dragonos.org.cn/xref/linux-5.19.10/tools/include/uapi/asm-generic/fcntl.h#19 66b5b571e0SLoGin #[allow(clippy::bad_bit_mask)] 67004e86ffSlogin pub struct FileMode: u32{ 68004e86ffSlogin /* File access modes for `open' and `fcntl'. */ 69004e86ffSlogin /// Open Read-only 7084407d36Slogin const O_RDONLY = 0o0; 71004e86ffSlogin /// Open Write-only 7284407d36Slogin const O_WRONLY = 0o1; 73004e86ffSlogin /// Open read/write 7484407d36Slogin const O_RDWR = 0o2; 75004e86ffSlogin /// Mask for file access modes 7684407d36Slogin const O_ACCMODE = 0o00000003; 77004e86ffSlogin 78004e86ffSlogin /* Bits OR'd into the second argument to open. */ 79004e86ffSlogin /// Create file if it does not exist 8084407d36Slogin const O_CREAT = 0o00000100; 81004e86ffSlogin /// Fail if file already exists 8284407d36Slogin const O_EXCL = 0o00000200; 83004e86ffSlogin /// Do not assign controlling terminal 8484407d36Slogin const O_NOCTTY = 0o00000400; 85004e86ffSlogin /// 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空 8684407d36Slogin const O_TRUNC = 0o00001000; 87004e86ffSlogin /// 文件指针会被移动到文件末尾 8884407d36Slogin const O_APPEND = 0o00002000; 89004e86ffSlogin /// 非阻塞式IO模式 9084407d36Slogin const O_NONBLOCK = 0o00004000; 9120e3152eSlogin /// 每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新 9284407d36Slogin const O_DSYNC = 0o00010000; 93004e86ffSlogin /// fcntl, for BSD compatibility 9484407d36Slogin const FASYNC = 0o00020000; 95004e86ffSlogin /* direct disk access hint */ 9684407d36Slogin const O_DIRECT = 0o00040000; 9784407d36Slogin const O_LARGEFILE = 0o00100000; 98004e86ffSlogin /// 打开的必须是一个目录 9984407d36Slogin const O_DIRECTORY = 0o00200000; 100004e86ffSlogin /// Do not follow symbolic links 10184407d36Slogin const O_NOFOLLOW = 0o00400000; 10284407d36Slogin const O_NOATIME = 0o01000000; 103004e86ffSlogin /// set close_on_exec 10484407d36Slogin const O_CLOEXEC = 0o02000000; 10520e3152eSlogin /// 每次write都等到物理I/O完成,包括write引起的文件属性的更新 10620e3152eSlogin const O_SYNC = 0o04000000; 1070fb515b0SLoGin 1080fb515b0SLoGin const O_PATH = 0o10000000; 1090fb515b0SLoGin 1100fb515b0SLoGin const O_PATH_FLAGS = Self::O_DIRECTORY.bits|Self::O_NOFOLLOW.bits|Self::O_CLOEXEC.bits|Self::O_PATH.bits; 111004e86ffSlogin } 112004e86ffSlogin } 113004e86ffSlogin 11420e3152eSlogin impl FileMode { 11520e3152eSlogin /// @brief 获取文件的访问模式的值 11620e3152eSlogin #[inline] 11720e3152eSlogin pub fn accmode(&self) -> u32 { 11820e3152eSlogin return self.bits() & FileMode::O_ACCMODE.bits(); 11920e3152eSlogin } 12020e3152eSlogin } 121004e86ffSlogin /// @brief 抽象文件结构体 12264aea4b3SGou Ngai #[derive(Debug)] 123004e86ffSlogin pub struct File { 124004e86ffSlogin inode: Arc<dyn IndexNode>, 125004e86ffSlogin /// 对于文件,表示字节偏移量;对于文件夹,表示当前操作的子目录项偏移量 126dfe53cf0SGnoCiYeH offset: AtomicUsize, 127004e86ffSlogin /// 文件的打开模式 128dfe53cf0SGnoCiYeH mode: RwLock<FileMode>, 129004e86ffSlogin /// 文件类型 130004e86ffSlogin file_type: FileType, 131004e86ffSlogin /// readdir时候用的,暂存的本次循环中,所有子目录项的名字的数组 132dfe53cf0SGnoCiYeH readdir_subdirs_name: SpinLock<Vec<String>>, 133dfe53cf0SGnoCiYeH pub private_data: SpinLock<FilePrivateData>, 134004e86ffSlogin } 135004e86ffSlogin 136004e86ffSlogin impl File { 137004e86ffSlogin /// @brief 创建一个新的文件对象 138004e86ffSlogin /// 139004e86ffSlogin /// @param inode 文件对象对应的inode 140004e86ffSlogin /// @param mode 文件的打开模式 141676b8ef6SMork pub fn new(inode: Arc<dyn IndexNode>, mode: FileMode) -> Result<Self, SystemError> { 1422dbef785SGnoCiYeH let mut inode = inode; 1432dbef785SGnoCiYeH let file_type = inode.metadata()?.file_type; 144b5b571e0SLoGin if file_type == FileType::Pipe { 1452dbef785SGnoCiYeH if let Some(SpecialNodeData::Pipe(pipe_inode)) = inode.special_node() { 1462dbef785SGnoCiYeH inode = pipe_inode; 1472dbef785SGnoCiYeH } 1482dbef785SGnoCiYeH } 1492dbef785SGnoCiYeH 150dfe53cf0SGnoCiYeH let f = File { 151004e86ffSlogin inode, 152dfe53cf0SGnoCiYeH offset: AtomicUsize::new(0), 153dfe53cf0SGnoCiYeH mode: RwLock::new(mode), 154004e86ffSlogin file_type, 155dfe53cf0SGnoCiYeH readdir_subdirs_name: SpinLock::new(Vec::default()), 156dfe53cf0SGnoCiYeH private_data: SpinLock::new(FilePrivateData::default()), 157004e86ffSlogin }; 158dfe53cf0SGnoCiYeH f.inode.open(f.private_data.lock(), &mode)?; 15940314b30SXiaoye Zheng 160004e86ffSlogin return Ok(f); 161004e86ffSlogin } 162004e86ffSlogin 163004e86ffSlogin /// @brief 从文件中读取指定的字节数到buffer中 164004e86ffSlogin /// 165004e86ffSlogin /// @param len 要读取的字节数 166004e86ffSlogin /// @param buf 目标buffer 167004e86ffSlogin /// 168004e86ffSlogin /// @return Ok(usize) 成功读取的字节数 169676b8ef6SMork /// @return Err(SystemError) 错误码 170dfe53cf0SGnoCiYeH pub fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> { 171dfe53cf0SGnoCiYeH self.do_read( 172dfe53cf0SGnoCiYeH self.offset.load(core::sync::atomic::Ordering::SeqCst), 173dfe53cf0SGnoCiYeH len, 174dfe53cf0SGnoCiYeH buf, 175dfe53cf0SGnoCiYeH true, 176dfe53cf0SGnoCiYeH ) 177004e86ffSlogin } 178004e86ffSlogin 179004e86ffSlogin /// @brief 从buffer向文件写入指定的字节数的数据 180004e86ffSlogin /// 181004e86ffSlogin /// @param len 要写入的字节数 182004e86ffSlogin /// @param buf 源数据buffer 183004e86ffSlogin /// 184004e86ffSlogin /// @return Ok(usize) 成功写入的字节数 185676b8ef6SMork /// @return Err(SystemError) 错误码 186dfe53cf0SGnoCiYeH pub fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError> { 187dfe53cf0SGnoCiYeH self.do_write( 188dfe53cf0SGnoCiYeH self.offset.load(core::sync::atomic::Ordering::SeqCst), 189dfe53cf0SGnoCiYeH len, 190dfe53cf0SGnoCiYeH buf, 191dfe53cf0SGnoCiYeH true, 192dfe53cf0SGnoCiYeH ) 19327b967a3S裕依 } 19427b967a3S裕依 19527b967a3S裕依 /// ## 从文件中指定的偏移处读取指定的字节数到buf中 19627b967a3S裕依 /// 19727b967a3S裕依 /// ### 参数 19827b967a3S裕依 /// - `offset`: 文件偏移量 19927b967a3S裕依 /// - `len`: 要读取的字节数 20027b967a3S裕依 /// - `buf`: 读出缓冲区 20127b967a3S裕依 /// 20227b967a3S裕依 /// ### 返回值 20327b967a3S裕依 /// - `Ok(usize)`: 成功读取的字节数 204dfe53cf0SGnoCiYeH pub fn pread(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> { 20527b967a3S裕依 self.do_read(offset, len, buf, false) 20627b967a3S裕依 } 20727b967a3S裕依 20827b967a3S裕依 /// ## 从buf向文件中指定的偏移处写入指定的字节数的数据 20927b967a3S裕依 /// 21027b967a3S裕依 /// ### 参数 21127b967a3S裕依 /// - `offset`: 文件偏移量 21227b967a3S裕依 /// - `len`: 要写入的字节数 21327b967a3S裕依 /// - `buf`: 写入缓冲区 21427b967a3S裕依 /// 21527b967a3S裕依 /// ### 返回值 21627b967a3S裕依 /// - `Ok(usize)`: 成功写入的字节数 217dfe53cf0SGnoCiYeH pub fn pwrite(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> { 21827b967a3S裕依 self.do_write(offset, len, buf, false) 21927b967a3S裕依 } 22027b967a3S裕依 22127b967a3S裕依 fn do_read( 222dfe53cf0SGnoCiYeH &self, 22327b967a3S裕依 offset: usize, 22427b967a3S裕依 len: usize, 22527b967a3S裕依 buf: &mut [u8], 22627b967a3S裕依 update_offset: bool, 22727b967a3S裕依 ) -> Result<usize, SystemError> { 22827b967a3S裕依 // 先检查本文件在权限等规则下,是否可读取。 22927b967a3S裕依 self.readable()?; 23027b967a3S裕依 if buf.len() < len { 23127b967a3S裕依 return Err(SystemError::ENOBUFS); 23227b967a3S裕依 } 23327b967a3S裕依 23427b967a3S裕依 let len = self 23527b967a3S裕依 .inode 236dfe53cf0SGnoCiYeH .read_at(offset, len, buf, self.private_data.lock())?; 23727b967a3S裕依 23827b967a3S裕依 if update_offset { 239dfe53cf0SGnoCiYeH self.offset 240dfe53cf0SGnoCiYeH .fetch_add(len, core::sync::atomic::Ordering::SeqCst); 24127b967a3S裕依 } 24227b967a3S裕依 24327b967a3S裕依 Ok(len) 24427b967a3S裕依 } 24527b967a3S裕依 24627b967a3S裕依 fn do_write( 247dfe53cf0SGnoCiYeH &self, 24827b967a3S裕依 offset: usize, 24927b967a3S裕依 len: usize, 25027b967a3S裕依 buf: &[u8], 25127b967a3S裕依 update_offset: bool, 25227b967a3S裕依 ) -> Result<usize, SystemError> { 253004e86ffSlogin // 先检查本文件在权限等规则下,是否可写入。 254004e86ffSlogin self.writeable()?; 255004e86ffSlogin if buf.len() < len { 256676b8ef6SMork return Err(SystemError::ENOBUFS); 257004e86ffSlogin } 2586d81180bSLoGin 2596d81180bSLoGin // 如果文件指针已经超过了文件大小,则需要扩展文件大小 26027b967a3S裕依 if offset > self.inode.metadata()?.size as usize { 26127b967a3S裕依 self.inode.resize(offset)?; 2626d81180bSLoGin } 263004e86ffSlogin let len = self 264004e86ffSlogin .inode 265dfe53cf0SGnoCiYeH .write_at(offset, len, buf, self.private_data.lock())?; 26627b967a3S裕依 26727b967a3S裕依 if update_offset { 268dfe53cf0SGnoCiYeH self.offset 269dfe53cf0SGnoCiYeH .fetch_add(len, core::sync::atomic::Ordering::SeqCst); 27027b967a3S裕依 } 27127b967a3S裕依 27227b967a3S裕依 Ok(len) 273004e86ffSlogin } 274004e86ffSlogin 275004e86ffSlogin /// @brief 获取文件的元数据 276676b8ef6SMork pub fn metadata(&self) -> Result<Metadata, SystemError> { 277004e86ffSlogin return self.inode.metadata(); 278004e86ffSlogin } 279004e86ffSlogin 280004e86ffSlogin /// @brief 根据inode号获取子目录项的名字 281bf4a4899SLoGin #[allow(dead_code)] 2826b4e7a29SLoGin pub fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> { 283004e86ffSlogin return self.inode.get_entry_name(ino); 284004e86ffSlogin } 285004e86ffSlogin 286004e86ffSlogin /// @brief 调整文件操作指针的位置 287004e86ffSlogin /// 288004e86ffSlogin /// @param origin 调整的起始位置 289dfe53cf0SGnoCiYeH pub fn lseek(&self, origin: SeekFrom) -> Result<usize, SystemError> { 29040fe15e0SLoGin let file_type = self.inode.metadata()?.file_type; 291bfafc102Slogin match file_type { 292bfafc102Slogin FileType::Pipe | FileType::CharDevice => { 293676b8ef6SMork return Err(SystemError::ESPIPE); 294004e86ffSlogin } 295bfafc102Slogin _ => {} 296bfafc102Slogin } 297bfafc102Slogin 298b5b571e0SLoGin let pos: i64 = match origin { 299b5b571e0SLoGin SeekFrom::SeekSet(offset) => offset, 300dfe53cf0SGnoCiYeH SeekFrom::SeekCurrent(offset) => self.offset.load(Ordering::SeqCst) as i64 + offset, 301004e86ffSlogin SeekFrom::SeekEnd(offset) => { 302004e86ffSlogin let metadata = self.metadata()?; 303b5b571e0SLoGin metadata.size + offset 304004e86ffSlogin } 305004e86ffSlogin SeekFrom::Invalid => { 306676b8ef6SMork return Err(SystemError::EINVAL); 307004e86ffSlogin } 308b5b571e0SLoGin }; 3096d81180bSLoGin // 根据linux man page, lseek允许超出文件末尾,并且不改变文件大小 3106d81180bSLoGin // 当pos超出文件末尾时,read返回0。直到开始写入数据时,才会改变文件大小 3116d81180bSLoGin if pos < 0 { 312676b8ef6SMork return Err(SystemError::EOVERFLOW); 313004e86ffSlogin } 314dfe53cf0SGnoCiYeH self.offset.store(pos as usize, Ordering::SeqCst); 315dfe53cf0SGnoCiYeH return Ok(pos as usize); 316004e86ffSlogin } 317004e86ffSlogin 318004e86ffSlogin /// @brief 判断当前文件是否可读 319004e86ffSlogin #[inline] 320676b8ef6SMork pub fn readable(&self) -> Result<(), SystemError> { 321004e86ffSlogin // 暂时认为只要不是write only, 就可读 322dfe53cf0SGnoCiYeH if *self.mode.read() == FileMode::O_WRONLY { 323676b8ef6SMork return Err(SystemError::EPERM); 324004e86ffSlogin } 325004e86ffSlogin 326004e86ffSlogin return Ok(()); 327004e86ffSlogin } 328004e86ffSlogin 329004e86ffSlogin /// @brief 判断当前文件是否可写 330004e86ffSlogin #[inline] 331676b8ef6SMork pub fn writeable(&self) -> Result<(), SystemError> { 332004e86ffSlogin // 暂时认为只要不是read only, 就可写 333dfe53cf0SGnoCiYeH if *self.mode.read() == FileMode::O_RDONLY { 334676b8ef6SMork return Err(SystemError::EPERM); 335004e86ffSlogin } 336004e86ffSlogin 337004e86ffSlogin return Ok(()); 338004e86ffSlogin } 339004e86ffSlogin 340004e86ffSlogin /// @biref 充填dirent结构体 341004e86ffSlogin /// @return 返回dirent结构体的大小 342dfe53cf0SGnoCiYeH pub fn readdir(&self, dirent: &mut Dirent) -> Result<u64, SystemError> { 343004e86ffSlogin let inode: &Arc<dyn IndexNode> = &self.inode; 344dfe53cf0SGnoCiYeH let mut readdir_subdirs_name = self.readdir_subdirs_name.lock(); 345dfe53cf0SGnoCiYeH let offset = self.offset.load(Ordering::SeqCst); 346004e86ffSlogin // 如果偏移量为0 347dfe53cf0SGnoCiYeH if offset == 0 { 3481effcfe5SGnoCiYeH // 通过list更新readdir_subdirs_name 349dfe53cf0SGnoCiYeH *readdir_subdirs_name = inode.list()?; 350dfe53cf0SGnoCiYeH readdir_subdirs_name.sort(); 351004e86ffSlogin } 3522eab6dd7S曾俊 // debug!("sub_entries={sub_entries:?}"); 3531effcfe5SGnoCiYeH 3541effcfe5SGnoCiYeH // 已经读到末尾 355dfe53cf0SGnoCiYeH if offset == readdir_subdirs_name.len() { 356dfe53cf0SGnoCiYeH self.offset.store(0, Ordering::SeqCst); 357004e86ffSlogin return Ok(0); 358004e86ffSlogin } 359dfe53cf0SGnoCiYeH let name = &readdir_subdirs_name[offset]; 360b5b571e0SLoGin let sub_inode: Arc<dyn IndexNode> = match inode.find(name) { 361004e86ffSlogin Ok(i) => i, 362004e86ffSlogin Err(e) => { 3632eab6dd7S曾俊 error!( 36406d5e247SLoGin "Readdir error: Failed to find sub inode:{name:?}, file={self:?}, error={e:?}" 36506d5e247SLoGin ); 366004e86ffSlogin return Err(e); 367004e86ffSlogin } 368004e86ffSlogin }; 369004e86ffSlogin 370004e86ffSlogin let name_bytes: &[u8] = name.as_bytes(); 371004e86ffSlogin 372004e86ffSlogin // 根据posix的规定,dirent中的d_name是一个不定长的数组,因此需要unsafe来拷贝数据 373004e86ffSlogin unsafe { 374004e86ffSlogin let ptr = &mut dirent.d_name as *mut u8; 3751effcfe5SGnoCiYeH 376004e86ffSlogin let buf: &mut [u8] = 3771effcfe5SGnoCiYeH ::core::slice::from_raw_parts_mut::<'static, u8>(ptr, name_bytes.len() + 1); 3781effcfe5SGnoCiYeH buf[0..name_bytes.len()].copy_from_slice(name_bytes); 3791effcfe5SGnoCiYeH buf[name_bytes.len()] = 0; 380004e86ffSlogin } 381004e86ffSlogin 382dfe53cf0SGnoCiYeH self.offset.fetch_add(1, Ordering::SeqCst); 3831effcfe5SGnoCiYeH dirent.d_ino = sub_inode.metadata().unwrap().inode_id.into() as u64; 3841effcfe5SGnoCiYeH dirent.d_type = sub_inode.metadata().unwrap().file_type.get_file_type_num() as u8; 3851effcfe5SGnoCiYeH 386004e86ffSlogin // 计算dirent结构体的大小 387bb0e4d41SGnoCiYeH let size = (name_bytes.len() + ::core::mem::size_of::<Dirent>() 388bb0e4d41SGnoCiYeH - ::core::mem::size_of_val(&dirent.d_name)) as u64; 389bb0e4d41SGnoCiYeH 390bb0e4d41SGnoCiYeH dirent.d_reclen = size as u16; 391bb0e4d41SGnoCiYeH dirent.d_off += dirent.d_reclen as i64; 392bb0e4d41SGnoCiYeH 393bb0e4d41SGnoCiYeH return Ok(size); 394004e86ffSlogin } 39564aea4b3SGou Ngai 396004e86ffSlogin pub fn inode(&self) -> Arc<dyn IndexNode> { 397004e86ffSlogin return self.inode.clone(); 398004e86ffSlogin } 39964aea4b3SGou Ngai 40064aea4b3SGou Ngai /// @brief 尝试克隆一个文件 40164aea4b3SGou Ngai /// 4021496ba7bSLoGin /// @return Option<File> 克隆后的文件结构体。如果克隆失败,返回None 4031496ba7bSLoGin pub fn try_clone(&self) -> Option<File> { 404dfe53cf0SGnoCiYeH let res = Self { 40564aea4b3SGou Ngai inode: self.inode.clone(), 406dfe53cf0SGnoCiYeH offset: AtomicUsize::new(self.offset.load(Ordering::SeqCst)), 407dfe53cf0SGnoCiYeH mode: RwLock::new(self.mode()), 408b5b571e0SLoGin file_type: self.file_type, 409dfe53cf0SGnoCiYeH readdir_subdirs_name: SpinLock::new(self.readdir_subdirs_name.lock().clone()), 410dfe53cf0SGnoCiYeH private_data: SpinLock::new(self.private_data.lock().clone()), 4111496ba7bSLoGin }; 41264aea4b3SGou Ngai // 调用inode的open方法,让inode知道有新的文件打开了这个inode 413dfe53cf0SGnoCiYeH if self 414dfe53cf0SGnoCiYeH .inode 415dfe53cf0SGnoCiYeH .open(res.private_data.lock(), &res.mode()) 416dfe53cf0SGnoCiYeH .is_err() 417dfe53cf0SGnoCiYeH { 41864aea4b3SGou Ngai return None; 41964aea4b3SGou Ngai } 42064aea4b3SGou Ngai 42164aea4b3SGou Ngai return Some(res); 42264aea4b3SGou Ngai } 423cde5492fSlogin 424cde5492fSlogin /// @brief 获取文件的类型 425cde5492fSlogin #[inline] 426cde5492fSlogin pub fn file_type(&self) -> FileType { 427cde5492fSlogin return self.file_type; 428cde5492fSlogin } 4296d81180bSLoGin 4306d81180bSLoGin /// @brief 获取文件的打开模式 4316d81180bSLoGin #[inline] 4326d81180bSLoGin pub fn mode(&self) -> FileMode { 433dfe53cf0SGnoCiYeH return *self.mode.read(); 4346d81180bSLoGin } 4356d81180bSLoGin 4366d81180bSLoGin /// 获取文件是否在execve时关闭 4376d81180bSLoGin #[inline] 4386d81180bSLoGin pub fn close_on_exec(&self) -> bool { 439dfe53cf0SGnoCiYeH return self.mode().contains(FileMode::O_CLOEXEC); 4406d81180bSLoGin } 4416d81180bSLoGin 4426d81180bSLoGin /// 设置文件是否在execve时关闭 4436d81180bSLoGin #[inline] 444dfe53cf0SGnoCiYeH pub fn set_close_on_exec(&self, close_on_exec: bool) { 445dfe53cf0SGnoCiYeH let mut mode_guard = self.mode.write(); 4466d81180bSLoGin if close_on_exec { 447dfe53cf0SGnoCiYeH mode_guard.insert(FileMode::O_CLOEXEC); 4486d81180bSLoGin } else { 449dfe53cf0SGnoCiYeH mode_guard.remove(FileMode::O_CLOEXEC); 4506d81180bSLoGin } 4516d81180bSLoGin } 4526d81180bSLoGin 453dfe53cf0SGnoCiYeH pub fn set_mode(&self, mode: FileMode) -> Result<(), SystemError> { 4546d81180bSLoGin // todo: 是否需要调用inode的open方法,以更新private data(假如它与mode有关的话)? 4556d81180bSLoGin // 也许需要加个更好的设计,让inode知晓文件的打开模式发生了变化,让它自己决定是否需要更新private data 4566d81180bSLoGin 4576d81180bSLoGin // 直接修改文件的打开模式 458dfe53cf0SGnoCiYeH *self.mode.write() = mode; 459dfe53cf0SGnoCiYeH self.private_data.lock().update_mode(mode); 4606d81180bSLoGin return Ok(()); 4616d81180bSLoGin } 4626d81180bSLoGin 4636d81180bSLoGin /// @brief 重新设置文件的大小 4646d81180bSLoGin /// 4656d81180bSLoGin /// 如果文件大小增加,则文件内容不变,但是文件的空洞部分会被填充为0 4666d81180bSLoGin /// 如果文件大小减小,则文件内容会被截断 4676d81180bSLoGin /// 4686d81180bSLoGin /// @return 成功:Ok() 4696d81180bSLoGin /// 失败:Err(错误码) 4701496ba7bSLoGin pub fn ftruncate(&self, len: usize) -> Result<(), SystemError> { 4716d81180bSLoGin // 如果文件不可写,返回错误 4726d81180bSLoGin self.writeable()?; 4736d81180bSLoGin 4746d81180bSLoGin // 调用inode的truncate方法 4756d81180bSLoGin self.inode.resize(len)?; 4766d81180bSLoGin return Ok(()); 4776d81180bSLoGin } 47840609970SGnoCiYeH 47940609970SGnoCiYeH /// ## 向该文件添加一个EPollItem对象 48040609970SGnoCiYeH /// 48140609970SGnoCiYeH /// 在文件状态发生变化时,需要向epoll通知 482dfe53cf0SGnoCiYeH pub fn add_epoll(&self, epitem: Arc<EPollItem>) -> Result<(), SystemError> { 48340609970SGnoCiYeH match self.file_type { 48440609970SGnoCiYeH FileType::Socket => { 48540609970SGnoCiYeH let inode = self.inode.downcast_ref::<SocketInode>().unwrap(); 48640609970SGnoCiYeH let mut socket = inode.inner(); 48740609970SGnoCiYeH 48840609970SGnoCiYeH return socket.add_epoll(epitem); 48940609970SGnoCiYeH } 4905e948c56SGnoCiYeH FileType::Pipe => { 4915e948c56SGnoCiYeH let inode = self.inode.downcast_ref::<LockedPipeInode>().unwrap(); 4925e948c56SGnoCiYeH return inode.inner().lock().add_epoll(epitem); 4935e948c56SGnoCiYeH } 49452bcb59eSGnoCiYeH _ => { 49552bcb59eSGnoCiYeH let r = self.inode.ioctl( 49652bcb59eSGnoCiYeH EventPoll::ADD_EPOLLITEM, 49752bcb59eSGnoCiYeH &epitem as *const Arc<EPollItem> as usize, 498dfe53cf0SGnoCiYeH &self.private_data.lock(), 49952bcb59eSGnoCiYeH ); 50052bcb59eSGnoCiYeH if r.is_err() { 50152bcb59eSGnoCiYeH return Err(SystemError::ENOSYS); 50252bcb59eSGnoCiYeH } 50352bcb59eSGnoCiYeH 50452bcb59eSGnoCiYeH Ok(()) 50552bcb59eSGnoCiYeH } 50640609970SGnoCiYeH } 50740609970SGnoCiYeH } 50840609970SGnoCiYeH 50940609970SGnoCiYeH /// ## 删除一个绑定的epoll 510dfe53cf0SGnoCiYeH pub fn remove_epoll(&self, epoll: &Weak<SpinLock<EventPoll>>) -> Result<(), SystemError> { 51140609970SGnoCiYeH match self.file_type { 51240609970SGnoCiYeH FileType::Socket => { 51340609970SGnoCiYeH let inode = self.inode.downcast_ref::<SocketInode>().unwrap(); 51440609970SGnoCiYeH let mut socket = inode.inner(); 51540609970SGnoCiYeH 51640609970SGnoCiYeH return socket.remove_epoll(epoll); 51740609970SGnoCiYeH } 5181074eb34SSamuel Dai _ => return Err(SystemError::ENOSYS), 51940609970SGnoCiYeH } 52040609970SGnoCiYeH } 52140609970SGnoCiYeH 52240609970SGnoCiYeH pub fn poll(&self) -> Result<usize, SystemError> { 523dfe53cf0SGnoCiYeH self.inode.poll(&self.private_data.lock()) 52440609970SGnoCiYeH } 525004e86ffSlogin } 526004e86ffSlogin 527004e86ffSlogin impl Drop for File { 528004e86ffSlogin fn drop(&mut self) { 529dfe53cf0SGnoCiYeH let r: Result<(), SystemError> = self.inode.close(self.private_data.lock()); 530004e86ffSlogin // 打印错误信息 531004e86ffSlogin if r.is_err() { 5322eab6dd7S曾俊 error!( 5331496ba7bSLoGin "pid: {:?} failed to close file: {:?}, errno={:?}", 5341496ba7bSLoGin ProcessManager::current_pcb().pid(), 535004e86ffSlogin self, 5368d72b68dSJomo r.as_ref().unwrap_err() 537004e86ffSlogin ); 538004e86ffSlogin } 539004e86ffSlogin } 540004e86ffSlogin } 541004e86ffSlogin 542004e86ffSlogin /// @brief pcb里面的文件描述符数组 54364aea4b3SGou Ngai #[derive(Debug)] 544004e86ffSlogin pub struct FileDescriptorVec { 545004e86ffSlogin /// 当前进程打开的文件描述符 546dfe53cf0SGnoCiYeH fds: Vec<Option<Arc<File>>>, 547004e86ffSlogin } 548004e86ffSlogin 549004e86ffSlogin impl FileDescriptorVec { 5500d9b7d92SLoGin pub const PROCESS_MAX_FD: usize = 1024; 551004e86ffSlogin 5524fda81ceSLoGin #[inline(never)] 5531496ba7bSLoGin pub fn new() -> FileDescriptorVec { 5544fda81ceSLoGin let mut data = Vec::with_capacity(FileDescriptorVec::PROCESS_MAX_FD); 5554fda81ceSLoGin data.resize(FileDescriptorVec::PROCESS_MAX_FD, None); 556004e86ffSlogin 557004e86ffSlogin // 初始化文件描述符数组结构体 5581496ba7bSLoGin return FileDescriptorVec { fds: data }; 559004e86ffSlogin } 560004e86ffSlogin 56164aea4b3SGou Ngai /// @brief 克隆一个文件描述符数组 56264aea4b3SGou Ngai /// 5631496ba7bSLoGin /// @return FileDescriptorVec 克隆后的文件描述符数组 5641496ba7bSLoGin pub fn clone(&self) -> FileDescriptorVec { 5651496ba7bSLoGin let mut res = FileDescriptorVec::new(); 56664aea4b3SGou Ngai for i in 0..FileDescriptorVec::PROCESS_MAX_FD { 56764aea4b3SGou Ngai if let Some(file) = &self.fds[i] { 568dfe53cf0SGnoCiYeH if let Some(file) = file.try_clone() { 569dfe53cf0SGnoCiYeH res.fds[i] = Some(Arc::new(file)); 5701496ba7bSLoGin } 57164aea4b3SGou Ngai } 57264aea4b3SGou Ngai } 57364aea4b3SGou Ngai return res; 57464aea4b3SGou Ngai } 57564aea4b3SGou Ngai 576*3d4cd853Sdonjuanplatinum /// 返回 `已经打开的` 文件描述符的数量 577*3d4cd853Sdonjuanplatinum pub fn fd_open_count(&self) -> usize { 578*3d4cd853Sdonjuanplatinum let mut size = 0; 579*3d4cd853Sdonjuanplatinum for fd in &self.fds { 580*3d4cd853Sdonjuanplatinum if fd.is_some() { 581*3d4cd853Sdonjuanplatinum size += 1; 582*3d4cd853Sdonjuanplatinum } 583*3d4cd853Sdonjuanplatinum } 584*3d4cd853Sdonjuanplatinum return size; 585*3d4cd853Sdonjuanplatinum } 586*3d4cd853Sdonjuanplatinum 587004e86ffSlogin /// @brief 判断文件描述符序号是否合法 588004e86ffSlogin /// 589004e86ffSlogin /// @return true 合法 590004e86ffSlogin /// 591004e86ffSlogin /// @return false 不合法 592004e86ffSlogin #[inline] 593004e86ffSlogin pub fn validate_fd(fd: i32) -> bool { 594b5b571e0SLoGin return !(fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD); 595004e86ffSlogin } 5961496ba7bSLoGin 5971496ba7bSLoGin /// 申请文件描述符,并把文件对象存入其中。 5981496ba7bSLoGin /// 5991496ba7bSLoGin /// ## 参数 6001496ba7bSLoGin /// 6011496ba7bSLoGin /// - `file` 要存放的文件对象 6021496ba7bSLoGin /// - `fd` 如果为Some(i32),表示指定要申请这个文件描述符,如果这个文件描述符已经被使用,那么返回EBADF 6031496ba7bSLoGin /// 6041496ba7bSLoGin /// ## 返回值 6051496ba7bSLoGin /// 6061496ba7bSLoGin /// - `Ok(i32)` 申请成功,返回申请到的文件描述符 6071496ba7bSLoGin /// - `Err(SystemError)` 申请失败,返回错误码,并且,file对象将被drop掉 6081496ba7bSLoGin pub fn alloc_fd(&mut self, file: File, fd: Option<i32>) -> Result<i32, SystemError> { 609b5b571e0SLoGin if let Some(new_fd) = fd { 6101496ba7bSLoGin let x = &mut self.fds[new_fd as usize]; 6111496ba7bSLoGin if x.is_none() { 612dfe53cf0SGnoCiYeH *x = Some(Arc::new(file)); 6131496ba7bSLoGin return Ok(new_fd); 6141496ba7bSLoGin } else { 6151496ba7bSLoGin return Err(SystemError::EBADF); 6161496ba7bSLoGin } 6171496ba7bSLoGin } else { 6181496ba7bSLoGin // 没有指定要申请的文件描述符编号 6191496ba7bSLoGin for i in 0..FileDescriptorVec::PROCESS_MAX_FD { 6201496ba7bSLoGin if self.fds[i].is_none() { 621dfe53cf0SGnoCiYeH self.fds[i] = Some(Arc::new(file)); 6221496ba7bSLoGin return Ok(i as i32); 6231496ba7bSLoGin } 6241496ba7bSLoGin } 6251496ba7bSLoGin return Err(SystemError::EMFILE); 6261496ba7bSLoGin } 6271496ba7bSLoGin } 6281496ba7bSLoGin 6291496ba7bSLoGin /// 根据文件描述符序号,获取文件结构体的Arc指针 6301496ba7bSLoGin /// 6311496ba7bSLoGin /// ## 参数 6321496ba7bSLoGin /// 6331496ba7bSLoGin /// - `fd` 文件描述符序号 634dfe53cf0SGnoCiYeH pub fn get_file_by_fd(&self, fd: i32) -> Option<Arc<File>> { 6351496ba7bSLoGin if !FileDescriptorVec::validate_fd(fd) { 6361496ba7bSLoGin return None; 6371496ba7bSLoGin } 6386046f775S裕依 self.fds[fd as usize].clone() 6391496ba7bSLoGin } 6401496ba7bSLoGin 6411496ba7bSLoGin /// 释放文件描述符,同时关闭文件。 6421496ba7bSLoGin /// 6431496ba7bSLoGin /// ## 参数 6441496ba7bSLoGin /// 6451496ba7bSLoGin /// - `fd` 文件描述符序号 6461496ba7bSLoGin pub fn drop_fd(&mut self, fd: i32) -> Result<(), SystemError> { 64771474bc6SLoGin self.get_file_by_fd(fd).ok_or(SystemError::EBADF)?; 6481496ba7bSLoGin 6491496ba7bSLoGin // 把文件描述符数组对应位置设置为空 6501496ba7bSLoGin let file = self.fds[fd as usize].take().unwrap(); 65134e6d6c8Syuyi2439 6521496ba7bSLoGin assert!(Arc::strong_count(&file) == 1); 6531496ba7bSLoGin return Ok(()); 6541496ba7bSLoGin } 655876cb89eSGnoCiYeH 656bf4a4899SLoGin #[allow(dead_code)] 657876cb89eSGnoCiYeH pub fn iter(&self) -> FileDescriptorIterator { 658876cb89eSGnoCiYeH return FileDescriptorIterator::new(self); 659876cb89eSGnoCiYeH } 660876cb89eSGnoCiYeH 661876cb89eSGnoCiYeH pub fn close_on_exec(&mut self) { 662876cb89eSGnoCiYeH for i in 0..FileDescriptorVec::PROCESS_MAX_FD { 663876cb89eSGnoCiYeH if let Some(file) = &self.fds[i] { 664dfe53cf0SGnoCiYeH let to_drop = file.close_on_exec(); 665876cb89eSGnoCiYeH if to_drop { 6664ad52e57S裕依2439 if let Err(r) = self.drop_fd(i as i32) { 6672eab6dd7S曾俊 error!( 668876cb89eSGnoCiYeH "Failed to close file: pid = {:?}, fd = {}, error = {:?}", 669876cb89eSGnoCiYeH ProcessManager::current_pcb().pid(), 670876cb89eSGnoCiYeH i, 671876cb89eSGnoCiYeH r 672876cb89eSGnoCiYeH ); 673876cb89eSGnoCiYeH } 674876cb89eSGnoCiYeH } 675876cb89eSGnoCiYeH } 676876cb89eSGnoCiYeH } 677876cb89eSGnoCiYeH } 678876cb89eSGnoCiYeH } 679876cb89eSGnoCiYeH 680876cb89eSGnoCiYeH #[derive(Debug)] 681876cb89eSGnoCiYeH pub struct FileDescriptorIterator<'a> { 682876cb89eSGnoCiYeH fds: &'a FileDescriptorVec, 683876cb89eSGnoCiYeH index: usize, 684876cb89eSGnoCiYeH } 685876cb89eSGnoCiYeH 686876cb89eSGnoCiYeH impl<'a> FileDescriptorIterator<'a> { 687876cb89eSGnoCiYeH pub fn new(fds: &'a FileDescriptorVec) -> Self { 688876cb89eSGnoCiYeH return Self { fds, index: 0 }; 689876cb89eSGnoCiYeH } 690876cb89eSGnoCiYeH } 691876cb89eSGnoCiYeH 692876cb89eSGnoCiYeH impl<'a> Iterator for FileDescriptorIterator<'a> { 693dfe53cf0SGnoCiYeH type Item = (i32, Arc<File>); 694876cb89eSGnoCiYeH 695876cb89eSGnoCiYeH fn next(&mut self) -> Option<Self::Item> { 696876cb89eSGnoCiYeH while self.index < FileDescriptorVec::PROCESS_MAX_FD { 697876cb89eSGnoCiYeH let fd = self.index as i32; 698876cb89eSGnoCiYeH self.index += 1; 699876cb89eSGnoCiYeH if let Some(file) = self.fds.get_file_by_fd(fd) { 700876cb89eSGnoCiYeH return Some((fd, file)); 701876cb89eSGnoCiYeH } 702876cb89eSGnoCiYeH } 703876cb89eSGnoCiYeH return None; 704876cb89eSGnoCiYeH } 705004e86ffSlogin } 706