1004e86ffSlogin pub mod core; 26d81180bSLoGin pub mod fcntl; 3004e86ffSlogin pub mod file; 4004e86ffSlogin pub mod mount; 59b0abe6dSLoGin pub mod open; 6cde5492fSlogin pub mod syscall; 71074eb34SSamuel Dai pub mod utils; 8004e86ffSlogin 96b4e7a29SLoGin use ::core::{any::Any, fmt::Debug, sync::atomic::AtomicUsize}; 10004e86ffSlogin use alloc::{string::String, sync::Arc, vec::Vec}; 11dfe53cf0SGnoCiYeH use intertrait::CastFromSync; 1291e9d4abSLoGin use system_error::SystemError; 13004e86ffSlogin 142dbef785SGnoCiYeH use crate::{ 15c566df45SLoGin driver::base::{ 16c566df45SLoGin block::block_device::BlockDevice, char::CharDevice, device::device_number::DeviceNumber, 17c566df45SLoGin }, 182dbef785SGnoCiYeH ipc::pipe::LockedPipeInode, 19dfe53cf0SGnoCiYeH libs::{ 20dfe53cf0SGnoCiYeH casting::DowncastArc, 21dfe53cf0SGnoCiYeH spinlock::{SpinLock, SpinLockGuard}, 22dfe53cf0SGnoCiYeH }, 23*cf7f801eSMemoryShore mm::{fault::PageFaultMessage, VmFaultReason}, 246fc066acSJomo time::PosixTimeSpec, 252dbef785SGnoCiYeH }; 26004e86ffSlogin 27*cf7f801eSMemoryShore use self::{ 28*cf7f801eSMemoryShore core::generate_inode_id, 29*cf7f801eSMemoryShore file::{FileMode, PageCache}, 30*cf7f801eSMemoryShore syscall::ModeType, 31*cf7f801eSMemoryShore utils::DName, 32*cf7f801eSMemoryShore }; 33004e86ffSlogin pub use self::{core::ROOT_INODE, file::FilePrivateData, mount::MountFS}; 34004e86ffSlogin 35004e86ffSlogin /// vfs容许的最大的路径名称长度 36ab5c8ca4Slogin pub const MAX_PATHLEN: usize = 1024; 37004e86ffSlogin 386b4e7a29SLoGin // 定义inode号 396b4e7a29SLoGin int_like!(InodeId, AtomicInodeId, usize, AtomicUsize); 40004e86ffSlogin 41004e86ffSlogin /// 文件的类型 42004e86ffSlogin #[derive(Debug, Clone, Copy, PartialEq, Eq)] 43004e86ffSlogin pub enum FileType { 44004e86ffSlogin /// 文件 45004e86ffSlogin File, 46004e86ffSlogin /// 文件夹 47004e86ffSlogin Dir, 48004e86ffSlogin /// 块设备 49004e86ffSlogin BlockDevice, 50004e86ffSlogin /// 字符设备 51004e86ffSlogin CharDevice, 5202343d0bSLoGin /// 帧缓冲设备 5302343d0bSLoGin FramebufferDevice, 5440314b30SXiaoye Zheng /// kvm设备 5540314b30SXiaoye Zheng KvmDevice, 56004e86ffSlogin /// 管道文件 57004e86ffSlogin Pipe, 58004e86ffSlogin /// 符号链接 59004e86ffSlogin SymLink, 60cde5492fSlogin /// 套接字 61cde5492fSlogin Socket, 62004e86ffSlogin } 63004e86ffSlogin 64bf4a4899SLoGin #[allow(dead_code)] 652dbef785SGnoCiYeH #[derive(Debug, Clone)] 662dbef785SGnoCiYeH pub enum SpecialNodeData { 672dbef785SGnoCiYeH /// 管道文件 682dbef785SGnoCiYeH Pipe(Arc<LockedPipeInode>), 692dbef785SGnoCiYeH /// 字符设备 702dbef785SGnoCiYeH CharDevice(Arc<dyn CharDevice>), 712dbef785SGnoCiYeH /// 块设备 722dbef785SGnoCiYeH BlockDevice(Arc<dyn BlockDevice>), 732dbef785SGnoCiYeH } 742dbef785SGnoCiYeH 75004e86ffSlogin /* these are defined by POSIX and also present in glibc's dirent.h */ 76004e86ffSlogin /// 完整含义请见 http://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html 77bf4a4899SLoGin #[allow(dead_code)] 78004e86ffSlogin pub const DT_UNKNOWN: u16 = 0; 79004e86ffSlogin /// 命名管道,或者FIFO 80004e86ffSlogin pub const DT_FIFO: u16 = 1; 81004e86ffSlogin // 字符设备 82004e86ffSlogin pub const DT_CHR: u16 = 2; 83004e86ffSlogin // 目录 84004e86ffSlogin pub const DT_DIR: u16 = 4; 85004e86ffSlogin // 块设备 86004e86ffSlogin pub const DT_BLK: u16 = 6; 87004e86ffSlogin // 常规文件 88004e86ffSlogin pub const DT_REG: u16 = 8; 89004e86ffSlogin // 符号链接 90004e86ffSlogin pub const DT_LNK: u16 = 10; 91004e86ffSlogin // 是一个socket 92004e86ffSlogin pub const DT_SOCK: u16 = 12; 93004e86ffSlogin // 这个是抄Linux的,还不知道含义 94bf4a4899SLoGin #[allow(dead_code)] 95004e86ffSlogin pub const DT_WHT: u16 = 14; 96bf4a4899SLoGin #[allow(dead_code)] 97004e86ffSlogin pub const DT_MAX: u16 = 16; 98004e86ffSlogin 99a03c4f9dSLoGin /// vfs容许的最大的符号链接跳转次数 100a03c4f9dSLoGin pub const VFS_MAX_FOLLOW_SYMLINK_TIMES: usize = 8; 101a03c4f9dSLoGin 102004e86ffSlogin impl FileType { get_file_type_num(&self) -> u16103004e86ffSlogin pub fn get_file_type_num(&self) -> u16 { 104004e86ffSlogin return match self { 105004e86ffSlogin FileType::File => DT_REG, 106004e86ffSlogin FileType::Dir => DT_DIR, 107004e86ffSlogin FileType::BlockDevice => DT_BLK, 108004e86ffSlogin FileType::CharDevice => DT_CHR, 10940314b30SXiaoye Zheng FileType::KvmDevice => DT_CHR, 110004e86ffSlogin FileType::Pipe => DT_FIFO, 111004e86ffSlogin FileType::SymLink => DT_LNK, 112cde5492fSlogin FileType::Socket => DT_SOCK, 11302343d0bSLoGin FileType::FramebufferDevice => DT_CHR, 114004e86ffSlogin }; 115004e86ffSlogin } 116004e86ffSlogin } 117004e86ffSlogin 118cde5492fSlogin bitflags! { 119004e86ffSlogin /// @brief inode的状态(由poll方法返回) 120cde5492fSlogin pub struct PollStatus: u8 { 121cde5492fSlogin const WRITE = 1u8 << 0; 122cde5492fSlogin const READ = 1u8 << 1; 123cde5492fSlogin const ERROR = 1u8 << 2; 124004e86ffSlogin } 125004e86ffSlogin } 126004e86ffSlogin 127dfe53cf0SGnoCiYeH pub trait IndexNode: Any + Sync + Send + Debug + CastFromSync { 128004e86ffSlogin /// @brief 打开文件 129004e86ffSlogin /// 130004e86ffSlogin /// @return 成功:Ok() 131004e86ffSlogin /// 失败:Err(错误码) open( &self, _data: SpinLockGuard<FilePrivateData>, _mode: &FileMode, ) -> Result<(), SystemError>132dfe53cf0SGnoCiYeH fn open( 133dfe53cf0SGnoCiYeH &self, 134dfe53cf0SGnoCiYeH _data: SpinLockGuard<FilePrivateData>, 135dfe53cf0SGnoCiYeH _mode: &FileMode, 136dfe53cf0SGnoCiYeH ) -> Result<(), SystemError> { 137004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 1381074eb34SSamuel Dai return Err(SystemError::ENOSYS); 139004e86ffSlogin } 140004e86ffSlogin 141004e86ffSlogin /// @brief 关闭文件 142004e86ffSlogin /// 143004e86ffSlogin /// @return 成功:Ok() 144004e86ffSlogin /// 失败:Err(错误码) close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError>145dfe53cf0SGnoCiYeH fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> { 146004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 1471074eb34SSamuel Dai return Err(SystemError::ENOSYS); 148004e86ffSlogin } 149004e86ffSlogin 150004e86ffSlogin /// @brief 在inode的指定偏移量开始,读取指定大小的数据 151004e86ffSlogin /// 152004e86ffSlogin /// @param offset 起始位置在Inode中的偏移量 153004e86ffSlogin /// @param len 要读取的字节数 154004e86ffSlogin /// @param buf 缓冲区. 请注意,必须满足@buf.len()>=@len 155004e86ffSlogin /// @param _data 各文件系统系统所需私有信息 156004e86ffSlogin /// 157004e86ffSlogin /// @return 成功:Ok(读取的字节数) 158004e86ffSlogin /// 失败:Err(Posix错误码) read_at( &self, offset: usize, len: usize, buf: &mut [u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize, SystemError>159004e86ffSlogin fn read_at( 160004e86ffSlogin &self, 161004e86ffSlogin offset: usize, 162004e86ffSlogin len: usize, 163004e86ffSlogin buf: &mut [u8], 164dfe53cf0SGnoCiYeH _data: SpinLockGuard<FilePrivateData>, 165676b8ef6SMork ) -> Result<usize, SystemError>; 166004e86ffSlogin 167004e86ffSlogin /// @brief 在inode的指定偏移量开始,写入指定大小的数据(从buf的第0byte开始写入) 168004e86ffSlogin /// 169004e86ffSlogin /// @param offset 起始位置在Inode中的偏移量 170004e86ffSlogin /// @param len 要写入的字节数 171004e86ffSlogin /// @param buf 缓冲区. 请注意,必须满足@buf.len()>=@len 172004e86ffSlogin /// @param _data 各文件系统系统所需私有信息 173004e86ffSlogin /// 174004e86ffSlogin /// @return 成功:Ok(写入的字节数) 175004e86ffSlogin /// 失败:Err(Posix错误码) write_at( &self, offset: usize, len: usize, buf: &[u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize, SystemError>176004e86ffSlogin fn write_at( 177004e86ffSlogin &self, 178004e86ffSlogin offset: usize, 179004e86ffSlogin len: usize, 180004e86ffSlogin buf: &[u8], 181dfe53cf0SGnoCiYeH _data: SpinLockGuard<FilePrivateData>, 182676b8ef6SMork ) -> Result<usize, SystemError>; 183004e86ffSlogin 184004e86ffSlogin /// @brief 获取当前inode的状态。 185004e86ffSlogin /// 186004e86ffSlogin /// @return PollStatus结构体 poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError>1875e948c56SGnoCiYeH fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> { 18840609970SGnoCiYeH // 若文件系统没有实现此方法,则返回“不支持” 1891074eb34SSamuel Dai return Err(SystemError::ENOSYS); 19040609970SGnoCiYeH } 191004e86ffSlogin 192004e86ffSlogin /// @brief 获取inode的元数据 193004e86ffSlogin /// 194004e86ffSlogin /// @return 成功:Ok(inode的元数据) 195004e86ffSlogin /// 失败:Err(错误码) metadata(&self) -> Result<Metadata, SystemError>196676b8ef6SMork fn metadata(&self) -> Result<Metadata, SystemError> { 197004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 1981074eb34SSamuel Dai return Err(SystemError::ENOSYS); 199004e86ffSlogin } 200004e86ffSlogin 201004e86ffSlogin /// @brief 设置inode的元数据 202004e86ffSlogin /// 203004e86ffSlogin /// @return 成功:Ok() 204004e86ffSlogin /// 失败:Err(错误码) set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError>205676b8ef6SMork fn set_metadata(&self, _metadata: &Metadata) -> Result<(), SystemError> { 206004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 2071074eb34SSamuel Dai return Err(SystemError::ENOSYS); 208004e86ffSlogin } 209004e86ffSlogin 210004e86ffSlogin /// @brief 重新设置文件的大小 211004e86ffSlogin /// 2126d81180bSLoGin /// 如果文件大小增加,则文件内容不变,但是文件的空洞部分会被填充为0 2136d81180bSLoGin /// 如果文件大小减小,则文件内容会被截断 2146d81180bSLoGin /// 215004e86ffSlogin /// @return 成功:Ok() 216004e86ffSlogin /// 失败:Err(错误码) resize(&self, _len: usize) -> Result<(), SystemError>217676b8ef6SMork fn resize(&self, _len: usize) -> Result<(), SystemError> { 218004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 2191074eb34SSamuel Dai return Err(SystemError::ENOSYS); 220004e86ffSlogin } 221004e86ffSlogin 222004e86ffSlogin /// @brief 在当前目录下创建一个新的inode 223004e86ffSlogin /// 224004e86ffSlogin /// @param name 目录项的名字 225004e86ffSlogin /// @param file_type 文件类型 226004e86ffSlogin /// @param mode 权限 227004e86ffSlogin /// 228004e86ffSlogin /// @return 创建成功:返回Ok(新的inode的Arc指针) 229004e86ffSlogin /// @return 创建失败:返回Err(错误码) create( &self, name: &str, file_type: FileType, mode: ModeType, ) -> Result<Arc<dyn IndexNode>, SystemError>230004e86ffSlogin fn create( 231004e86ffSlogin &self, 232004e86ffSlogin name: &str, 233004e86ffSlogin file_type: FileType, 2346b4e7a29SLoGin mode: ModeType, 235676b8ef6SMork ) -> Result<Arc<dyn IndexNode>, SystemError> { 2361074eb34SSamuel Dai // 若文件系统没有实现此方法,则默认调用其create_with_data方法。如果仍未实现,则会得到一个Err(-ENOSYS)的返回值 237004e86ffSlogin return self.create_with_data(name, file_type, mode, 0); 238004e86ffSlogin } 239004e86ffSlogin 240004e86ffSlogin /// @brief 在当前目录下创建一个新的inode,并传入一个简单的data字段,方便进行初始化。 241004e86ffSlogin /// 242004e86ffSlogin /// @param name 目录项的名字 243004e86ffSlogin /// @param file_type 文件类型 244004e86ffSlogin /// @param mode 权限 245004e86ffSlogin /// @param data 用于初始化该inode的数据。(为0则表示忽略此字段)对于不同的文件系统来说,代表的含义可能不同。 246004e86ffSlogin /// 247004e86ffSlogin /// @return 创建成功:返回Ok(新的inode的Arc指针) 248004e86ffSlogin /// @return 创建失败:返回Err(错误码) create_with_data( &self, _name: &str, _file_type: FileType, _mode: ModeType, _data: usize, ) -> Result<Arc<dyn IndexNode>, SystemError>249004e86ffSlogin fn create_with_data( 250004e86ffSlogin &self, 251004e86ffSlogin _name: &str, 252004e86ffSlogin _file_type: FileType, 2536b4e7a29SLoGin _mode: ModeType, 254004e86ffSlogin _data: usize, 255676b8ef6SMork ) -> Result<Arc<dyn IndexNode>, SystemError> { 256004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 2571074eb34SSamuel Dai return Err(SystemError::ENOSYS); 258004e86ffSlogin } 259004e86ffSlogin 260004e86ffSlogin /// @brief 在当前目录下,创建一个名为Name的硬链接,指向另一个IndexNode 261004e86ffSlogin /// 262004e86ffSlogin /// @param name 硬链接的名称 263004e86ffSlogin /// @param other 要被指向的IndexNode的Arc指针 264004e86ffSlogin /// 265004e86ffSlogin /// @return 成功:Ok() 266004e86ffSlogin /// 失败:Err(错误码) link(&self, _name: &str, _other: &Arc<dyn IndexNode>) -> Result<(), SystemError>267676b8ef6SMork fn link(&self, _name: &str, _other: &Arc<dyn IndexNode>) -> Result<(), SystemError> { 268004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 2691074eb34SSamuel Dai return Err(SystemError::ENOSYS); 270004e86ffSlogin } 271004e86ffSlogin 272004e86ffSlogin /// @brief 在当前目录下,删除一个名为Name的硬链接 273004e86ffSlogin /// 274004e86ffSlogin /// @param name 硬链接的名称 275004e86ffSlogin /// 276004e86ffSlogin /// @return 成功:Ok() 277004e86ffSlogin /// 失败:Err(错误码) unlink(&self, _name: &str) -> Result<(), SystemError>278676b8ef6SMork fn unlink(&self, _name: &str) -> Result<(), SystemError> { 279004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 2801074eb34SSamuel Dai return Err(SystemError::ENOSYS); 281004e86ffSlogin } 282004e86ffSlogin 283004e86ffSlogin /// @brief 删除文件夹 284004e86ffSlogin /// 285004e86ffSlogin /// @param name 文件夹名称 286004e86ffSlogin /// 287004e86ffSlogin /// @return 成功 Ok(()) 288004e86ffSlogin /// @return 失败 Err(错误码) rmdir(&self, _name: &str) -> Result<(), SystemError>289676b8ef6SMork fn rmdir(&self, _name: &str) -> Result<(), SystemError> { 2901074eb34SSamuel Dai return Err(SystemError::ENOSYS); 291004e86ffSlogin } 292004e86ffSlogin 2931074eb34SSamuel Dai /// 将指定的`old_name`子目录项移动到target目录下, 并予以`new_name`。 294004e86ffSlogin /// 2951074eb34SSamuel Dai /// # Behavior 2961074eb34SSamuel Dai /// 如果old_name所指向的inode与target的相同,那么则直接**执行重命名的操作**。 move_to( &self, _old_name: &str, _target: &Arc<dyn IndexNode>, _new_name: &str, ) -> Result<(), SystemError>2979e481b3bSTTaq fn move_to( 298004e86ffSlogin &self, 299004e86ffSlogin _old_name: &str, 300004e86ffSlogin _target: &Arc<dyn IndexNode>, 301004e86ffSlogin _new_name: &str, 302676b8ef6SMork ) -> Result<(), SystemError> { 303004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 3041074eb34SSamuel Dai return Err(SystemError::ENOSYS); 3059e481b3bSTTaq } 3069e481b3bSTTaq 307004e86ffSlogin /// @brief 寻找一个名为Name的inode 308004e86ffSlogin /// 309004e86ffSlogin /// @param name 要寻找的inode的名称 310004e86ffSlogin /// 311004e86ffSlogin /// @return 成功:Ok() 312004e86ffSlogin /// 失败:Err(错误码) find(&self, _name: &str) -> Result<Arc<dyn IndexNode>, SystemError>313676b8ef6SMork fn find(&self, _name: &str) -> Result<Arc<dyn IndexNode>, SystemError> { 314004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 3151074eb34SSamuel Dai return Err(SystemError::ENOSYS); 316004e86ffSlogin } 317004e86ffSlogin 318004e86ffSlogin /// @brief 根据inode号,获取子目录项的名字 319004e86ffSlogin /// 320004e86ffSlogin /// @param ino inode号 321004e86ffSlogin /// 322004e86ffSlogin /// @return 成功:Ok() 323004e86ffSlogin /// 失败:Err(错误码) get_entry_name(&self, _ino: InodeId) -> Result<String, SystemError>324676b8ef6SMork fn get_entry_name(&self, _ino: InodeId) -> Result<String, SystemError> { 325004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 3261074eb34SSamuel Dai return Err(SystemError::ENOSYS); 327004e86ffSlogin } 328004e86ffSlogin 329004e86ffSlogin /// @brief 根据inode号,获取子目录项的名字和元数据 330004e86ffSlogin /// 331004e86ffSlogin /// @param ino inode号 332004e86ffSlogin /// 333004e86ffSlogin /// @return 成功:Ok(String, Metadata) 334004e86ffSlogin /// 失败:Err(错误码) get_entry_name_and_metadata(&self, ino: InodeId) -> Result<(String, Metadata), SystemError>335676b8ef6SMork fn get_entry_name_and_metadata(&self, ino: InodeId) -> Result<(String, Metadata), SystemError> { 336004e86ffSlogin // 如果有条件,请在文件系统中使用高效的方式实现本接口,而不是依赖这个低效率的默认实现。 337004e86ffSlogin let name = self.get_entry_name(ino)?; 338004e86ffSlogin let entry = self.find(&name)?; 339004e86ffSlogin return Ok((name, entry.metadata()?)); 340004e86ffSlogin } 341004e86ffSlogin 342004e86ffSlogin /// @brief io control接口 343004e86ffSlogin /// 344004e86ffSlogin /// @param cmd 命令 345004e86ffSlogin /// @param data 数据 346004e86ffSlogin /// 347004e86ffSlogin /// @return 成功:Ok() 348004e86ffSlogin /// 失败:Err(错误码) ioctl( &self, _cmd: u32, _data: usize, _private_data: &FilePrivateData, ) -> Result<usize, SystemError>34952da9a59SGnoCiYeH fn ioctl( 35052da9a59SGnoCiYeH &self, 35152da9a59SGnoCiYeH _cmd: u32, 35252da9a59SGnoCiYeH _data: usize, 35352da9a59SGnoCiYeH _private_data: &FilePrivateData, 35452da9a59SGnoCiYeH ) -> Result<usize, SystemError> { 355004e86ffSlogin // 若文件系统没有实现此方法,则返回“不支持” 3561074eb34SSamuel Dai return Err(SystemError::ENOSYS); 357004e86ffSlogin } 358004e86ffSlogin kernel_ioctl( &self, _arg: Arc<dyn crate::net::event_poll::KernelIoctlData>, _data: &FilePrivateData, ) -> Result<usize, SystemError>359415e14e9Slaokengwt fn kernel_ioctl( 360415e14e9Slaokengwt &self, 361415e14e9Slaokengwt _arg: Arc<dyn crate::net::event_poll::KernelIoctlData>, 362415e14e9Slaokengwt _data: &FilePrivateData, 363415e14e9Slaokengwt ) -> Result<usize, SystemError> { 364415e14e9Slaokengwt return Err(SystemError::ENOSYS); 365415e14e9Slaokengwt } 366415e14e9Slaokengwt 367004e86ffSlogin /// @brief 获取inode所在的文件系统的指针 fs(&self) -> Arc<dyn FileSystem>368004e86ffSlogin fn fs(&self) -> Arc<dyn FileSystem>; 369004e86ffSlogin 370004e86ffSlogin /// @brief 本函数用于实现动态转换。 371004e86ffSlogin /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self as_any_ref(&self) -> &dyn Any372004e86ffSlogin fn as_any_ref(&self) -> &dyn Any; 373004e86ffSlogin 374004e86ffSlogin /// @brief 列出当前inode下的所有目录项的名字 list(&self) -> Result<Vec<String>, SystemError>375676b8ef6SMork fn list(&self) -> Result<Vec<String>, SystemError>; 376004e86ffSlogin 3771074eb34SSamuel Dai /// # mount - 挂载文件系统 3781074eb34SSamuel Dai /// 3791074eb34SSamuel Dai /// 将给定的文件系统挂载到当前的文件系统节点上。 3801074eb34SSamuel Dai /// 3811074eb34SSamuel Dai /// 该函数是`MountFS`结构体的实例方法,用于将一个新的文件系统挂载到调用它的`MountFS`实例上。 3821074eb34SSamuel Dai /// 3831074eb34SSamuel Dai /// ## 参数 3841074eb34SSamuel Dai /// 3851074eb34SSamuel Dai /// - `fs`: `Arc<dyn FileSystem>` - 要挂载的文件系统的共享引用。 3861074eb34SSamuel Dai /// 3871074eb34SSamuel Dai /// ## 返回值 3881074eb34SSamuel Dai /// 3891074eb34SSamuel Dai /// - `Ok(Arc<MountFS>)`: 新的挂载文件系统的共享引用。 3901074eb34SSamuel Dai /// - `Err(SystemError)`: 挂载过程中出现的错误。 3911074eb34SSamuel Dai /// 3921074eb34SSamuel Dai /// ## 错误处理 3931074eb34SSamuel Dai /// 3941074eb34SSamuel Dai /// - 如果文件系统不是目录类型,则返回`SystemError::ENOTDIR`错误。 3951074eb34SSamuel Dai /// - 如果当前路径已经是挂载点,则返回`SystemError::EBUSY`错误。 3961074eb34SSamuel Dai /// 3971074eb34SSamuel Dai /// ## 副作用 3981074eb34SSamuel Dai /// 3991074eb34SSamuel Dai /// - 该函数会在`MountFS`实例上创建一个新的挂载点。 4001074eb34SSamuel Dai /// - 该函数会在全局的挂载列表中记录新的挂载关系。 mount(&self, _fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError>401676b8ef6SMork fn mount(&self, _fs: Arc<dyn FileSystem>) -> Result<Arc<MountFS>, SystemError> { 4021074eb34SSamuel Dai return Err(SystemError::ENOSYS); 4031074eb34SSamuel Dai } 4041074eb34SSamuel Dai 4051074eb34SSamuel Dai /// # mount_from - 从给定的目录挂载已有挂载信息的文件系统 4061074eb34SSamuel Dai /// 4071074eb34SSamuel Dai /// 这个函数将一个已有挂载信息的文件系统从给定的目录挂载到当前目录。 4081074eb34SSamuel Dai /// 4091074eb34SSamuel Dai /// ## 参数 4101074eb34SSamuel Dai /// 4111074eb34SSamuel Dai /// - `from`: Arc<dyn IndexNode> - 要挂载的目录的引用。 4121074eb34SSamuel Dai /// 4131074eb34SSamuel Dai /// ## 返回值 4141074eb34SSamuel Dai /// 4151074eb34SSamuel Dai /// - Ok(Arc<MountFS>): 挂载的新文件系统的引用。 4161074eb34SSamuel Dai /// - Err(SystemError): 如果发生错误,返回系统错误。 4171074eb34SSamuel Dai /// 4181074eb34SSamuel Dai /// ## 错误处理 4191074eb34SSamuel Dai /// 4201074eb34SSamuel Dai /// - 如果给定的目录不是目录类型,返回`SystemError::ENOTDIR`。 4211074eb34SSamuel Dai /// - 如果当前目录已经是挂载点的根目录,返回`SystemError::EBUSY`。 4221074eb34SSamuel Dai /// 4231074eb34SSamuel Dai /// ## 副作用 4241074eb34SSamuel Dai /// 4251074eb34SSamuel Dai /// - 系统初始化用,其他情况不应调用此函数 mount_from(&self, _des: Arc<dyn IndexNode>) -> Result<Arc<MountFS>, SystemError>4261074eb34SSamuel Dai fn mount_from(&self, _des: Arc<dyn IndexNode>) -> Result<Arc<MountFS>, SystemError> { 4271074eb34SSamuel Dai return Err(SystemError::ENOSYS); 4281074eb34SSamuel Dai } 4291074eb34SSamuel Dai 4301074eb34SSamuel Dai /// # umount - 卸载当前Inode下的文件系统 4311074eb34SSamuel Dai /// 4321074eb34SSamuel Dai /// 该函数是特定于`MountFS`实现的,其他文件系统不应实现此函数。 4331074eb34SSamuel Dai /// 4341074eb34SSamuel Dai /// ## 参数 4351074eb34SSamuel Dai /// 4361074eb34SSamuel Dai /// 无 4371074eb34SSamuel Dai /// 4381074eb34SSamuel Dai /// ## 返回值 4391074eb34SSamuel Dai /// 4401074eb34SSamuel Dai /// - Ok(Arc<MountFS>): 卸载的文件系统的引用。 4411074eb34SSamuel Dai /// - Err(SystemError): 如果发生错误,返回系统错误。 4421074eb34SSamuel Dai /// 4431074eb34SSamuel Dai /// ## 行为 4441074eb34SSamuel Dai /// 4451074eb34SSamuel Dai /// - 查找路径 4461074eb34SSamuel Dai /// - 定位到父文件系统的挂载点 4471074eb34SSamuel Dai /// - 将挂载点与子文件系统的根进行叠加 4481074eb34SSamuel Dai /// - 判断是否为子文件系统的根 4491074eb34SSamuel Dai /// - 调用父文件系统挂载点的`_umount`方法进行卸载 umount(&self) -> Result<Arc<MountFS>, SystemError>4501074eb34SSamuel Dai fn umount(&self) -> Result<Arc<MountFS>, SystemError> { 4511074eb34SSamuel Dai return Err(SystemError::ENOSYS); 4521074eb34SSamuel Dai } 4531074eb34SSamuel Dai 4541074eb34SSamuel Dai /// # absolute_path 获取目录项绝对路径 4551074eb34SSamuel Dai /// 4561074eb34SSamuel Dai /// ## 参数 4571074eb34SSamuel Dai /// 4581074eb34SSamuel Dai /// 无 4591074eb34SSamuel Dai /// 4601074eb34SSamuel Dai /// ## 返回值 4611074eb34SSamuel Dai /// 4621074eb34SSamuel Dai /// - Ok(String): 路径 4631074eb34SSamuel Dai /// - Err(SystemError): 文件系统不支持dname parent api 4641074eb34SSamuel Dai /// 4651074eb34SSamuel Dai /// ## Behavior 4661074eb34SSamuel Dai /// 4671074eb34SSamuel Dai /// 该函数只能被MountFS实现,其他文件系统不应实现这个函数 4681074eb34SSamuel Dai /// 4691074eb34SSamuel Dai /// # Performance 4701074eb34SSamuel Dai /// 4711074eb34SSamuel Dai /// 这是一个O(n)的路径查询,并且在未实现DName缓存的文件系统中,性能极差; 4721074eb34SSamuel Dai /// 即使实现了DName也尽量不要用。 absolute_path(&self) -> Result<String, SystemError>4731074eb34SSamuel Dai fn absolute_path(&self) -> Result<String, SystemError> { 4741074eb34SSamuel Dai return Err(SystemError::ENOSYS); 475004e86ffSlogin } 476004e86ffSlogin 477004e86ffSlogin /// @brief 截断当前inode到指定的长度。如果当前文件长度小于len,则不操作。 478004e86ffSlogin /// 479004e86ffSlogin /// @param len 要被截断到的目标长度 truncate(&self, _len: usize) -> Result<(), SystemError>480676b8ef6SMork fn truncate(&self, _len: usize) -> Result<(), SystemError> { 4811074eb34SSamuel Dai return Err(SystemError::ENOSYS); 482004e86ffSlogin } 48320e3152eSlogin 48420e3152eSlogin /// @brief 将当前inode的内容同步到具体设备上 sync(&self) -> Result<(), SystemError>48520e3152eSlogin fn sync(&self) -> Result<(), SystemError> { 48620e3152eSlogin return Ok(()); 48720e3152eSlogin } 4882dbef785SGnoCiYeH 4892dbef785SGnoCiYeH /// ## 创建一个特殊文件节点 4902dbef785SGnoCiYeH /// - _filename: 文件名 4912dbef785SGnoCiYeH /// - _mode: 权限信息 mknod( &self, _filename: &str, _mode: ModeType, _dev_t: DeviceNumber, ) -> Result<Arc<dyn IndexNode>, SystemError>4922dbef785SGnoCiYeH fn mknod( 4932dbef785SGnoCiYeH &self, 4942dbef785SGnoCiYeH _filename: &str, 4952dbef785SGnoCiYeH _mode: ModeType, 4962dbef785SGnoCiYeH _dev_t: DeviceNumber, 4972dbef785SGnoCiYeH ) -> Result<Arc<dyn IndexNode>, SystemError> { 4981074eb34SSamuel Dai return Err(SystemError::ENOSYS); 4991074eb34SSamuel Dai } 5001074eb34SSamuel Dai 5011074eb34SSamuel Dai /// # mkdir - 新建名称为`name`的目录项 5021074eb34SSamuel Dai /// 5031074eb34SSamuel Dai /// 当目录下已有名称为`name`的文件夹时,返回该目录项的引用;否则新建`name`文件夹,并返回该引用。 5041074eb34SSamuel Dai /// 5051074eb34SSamuel Dai /// 该函数会检查`name`目录是否已存在,如果存在但类型不为文件夹,则会返回`EEXIST`错误。 5061074eb34SSamuel Dai /// 5071074eb34SSamuel Dai /// # 参数 5081074eb34SSamuel Dai /// 5091074eb34SSamuel Dai /// - `name`: &str - 要新建的目录项的名称。 5101074eb34SSamuel Dai /// - `mode`: ModeType - 设置目录项的权限模式。 5111074eb34SSamuel Dai /// 5121074eb34SSamuel Dai /// # 返回值 5131074eb34SSamuel Dai /// 5141074eb34SSamuel Dai /// - `Ok(Arc<dyn IndexNode>)`: 成功时返回`name`目录项的共享引用。 5151074eb34SSamuel Dai /// - `Err(SystemError)`: 出错时返回错误信息。 mkdir(&self, name: &str, mode: ModeType) -> Result<Arc<dyn IndexNode>, SystemError>5161074eb34SSamuel Dai fn mkdir(&self, name: &str, mode: ModeType) -> Result<Arc<dyn IndexNode>, SystemError> { 5171074eb34SSamuel Dai match self.find(name) { 5181074eb34SSamuel Dai Ok(inode) => { 5191074eb34SSamuel Dai if inode.metadata()?.file_type == FileType::Dir { 5201074eb34SSamuel Dai Ok(inode) 5211074eb34SSamuel Dai } else { 5221074eb34SSamuel Dai Err(SystemError::EEXIST) 5231074eb34SSamuel Dai } 5241074eb34SSamuel Dai } 5251074eb34SSamuel Dai Err(SystemError::ENOENT) => self.create(name, FileType::Dir, mode), 5261074eb34SSamuel Dai Err(err) => Err(err), 5271074eb34SSamuel Dai } 5282dbef785SGnoCiYeH } 5292dbef785SGnoCiYeH 5302dbef785SGnoCiYeH /// ## 返回特殊文件的inode special_node(&self) -> Option<SpecialNodeData>5312dbef785SGnoCiYeH fn special_node(&self) -> Option<SpecialNodeData> { 5322dbef785SGnoCiYeH None 5332dbef785SGnoCiYeH } 5341074eb34SSamuel Dai 5351074eb34SSamuel Dai /// # dname - 返回目录名 5361074eb34SSamuel Dai /// 5371074eb34SSamuel Dai /// 此函数用于返回一个目录名。 5381074eb34SSamuel Dai /// 5391074eb34SSamuel Dai /// ## 参数 5401074eb34SSamuel Dai /// 5411074eb34SSamuel Dai /// 无 5421074eb34SSamuel Dai /// 5431074eb34SSamuel Dai /// ## 返回值 5441074eb34SSamuel Dai /// - Ok(DName): 成功时返回一个目录名。 5451074eb34SSamuel Dai /// - Err(SystemError): 如果系统不支持此操作,则返回一个系统错误。 dname(&self) -> Result<DName, SystemError>5461074eb34SSamuel Dai fn dname(&self) -> Result<DName, SystemError> { 5471074eb34SSamuel Dai return Err(SystemError::ENOSYS); 5481074eb34SSamuel Dai } 5491074eb34SSamuel Dai 5501074eb34SSamuel Dai /// # parent - 返回父目录的引用 5511074eb34SSamuel Dai /// 5521074eb34SSamuel Dai /// 当该目录是当前文件系统的根目录时,返回自身的引用。 5531074eb34SSamuel Dai /// 5541074eb34SSamuel Dai /// ## 参数 5551074eb34SSamuel Dai /// 5561074eb34SSamuel Dai /// 无 5571074eb34SSamuel Dai /// 5581074eb34SSamuel Dai /// ## 返回值 5591074eb34SSamuel Dai /// 5601074eb34SSamuel Dai /// - Ok(Arc<dyn IndexNode>): A reference to the parent directory 5611074eb34SSamuel Dai /// - Err(SystemError): If there is an error in finding the parent directory parent(&self) -> Result<Arc<dyn IndexNode>, SystemError>5621074eb34SSamuel Dai fn parent(&self) -> Result<Arc<dyn IndexNode>, SystemError> { 5631074eb34SSamuel Dai return self.find(".."); 5641074eb34SSamuel Dai } 565*cf7f801eSMemoryShore page_cache(&self) -> Option<Arc<PageCache>>566*cf7f801eSMemoryShore fn page_cache(&self) -> Option<Arc<PageCache>> { 567*cf7f801eSMemoryShore log::error!( 568*cf7f801eSMemoryShore "function page_cache() has not yet been implemented for inode:{}", 569*cf7f801eSMemoryShore crate::libs::name::get_type_name(&self) 570*cf7f801eSMemoryShore ); 571*cf7f801eSMemoryShore None 572*cf7f801eSMemoryShore } 573004e86ffSlogin } 574004e86ffSlogin 575cde5492fSlogin impl DowncastArc for dyn IndexNode { as_any_arc(self: Arc<Self>) -> Arc<dyn Any>576cde5492fSlogin fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> { 577cde5492fSlogin self 578cde5492fSlogin } 579cde5492fSlogin } 580cde5492fSlogin 581004e86ffSlogin impl dyn IndexNode { 582004e86ffSlogin /// @brief 将当前Inode转换为一个具体的结构体(类型由T指定) 583004e86ffSlogin /// 如果类型正确,则返回Some,否则返回None downcast_ref<T: IndexNode>(&self) -> Option<&T>584004e86ffSlogin pub fn downcast_ref<T: IndexNode>(&self) -> Option<&T> { 585004e86ffSlogin return self.as_any_ref().downcast_ref::<T>(); 586004e86ffSlogin } 587004e86ffSlogin 588004e86ffSlogin /// @brief 查找文件(不考虑符号链接) 589004e86ffSlogin /// 590004e86ffSlogin /// @param path 文件路径 591004e86ffSlogin /// 592004e86ffSlogin /// @return Ok(Arc<dyn IndexNode>) 要寻找的目录项的inode 593676b8ef6SMork /// @return Err(SystemError) 错误码 lookup(&self, path: &str) -> Result<Arc<dyn IndexNode>, SystemError>594676b8ef6SMork pub fn lookup(&self, path: &str) -> Result<Arc<dyn IndexNode>, SystemError> { 595004e86ffSlogin return self.lookup_follow_symlink(path, 0); 596004e86ffSlogin } 597004e86ffSlogin 598004e86ffSlogin /// @brief 查找文件(考虑符号链接) 599004e86ffSlogin /// 600004e86ffSlogin /// @param path 文件路径 601004e86ffSlogin /// @param max_follow_times 最大经过的符号链接的大小 602004e86ffSlogin /// 603004e86ffSlogin /// @return Ok(Arc<dyn IndexNode>) 要寻找的目录项的inode 604676b8ef6SMork /// @return Err(SystemError) 错误码 lookup_follow_symlink( &self, path: &str, max_follow_times: usize, ) -> Result<Arc<dyn IndexNode>, SystemError>605004e86ffSlogin pub fn lookup_follow_symlink( 606004e86ffSlogin &self, 607004e86ffSlogin path: &str, 608004e86ffSlogin max_follow_times: usize, 609676b8ef6SMork ) -> Result<Arc<dyn IndexNode>, SystemError> { 610004e86ffSlogin if self.metadata()?.file_type != FileType::Dir { 611676b8ef6SMork return Err(SystemError::ENOTDIR); 612004e86ffSlogin } 613004e86ffSlogin 614004e86ffSlogin // 处理绝对路径 615004e86ffSlogin // result: 上一个被找到的inode 616004e86ffSlogin // rest_path: 还没有查找的路径 617004e86ffSlogin let (mut result, mut rest_path) = if let Some(rest) = path.strip_prefix('/') { 618004e86ffSlogin (ROOT_INODE().clone(), String::from(rest)) 619004e86ffSlogin } else { 620004e86ffSlogin // 是相对路径 621004e86ffSlogin (self.find(".")?, String::from(path)) 622004e86ffSlogin }; 623004e86ffSlogin 624004e86ffSlogin // 逐级查找文件 625004e86ffSlogin while !rest_path.is_empty() { 626004e86ffSlogin // 当前这一级不是文件夹 627004e86ffSlogin if result.metadata()?.file_type != FileType::Dir { 628676b8ef6SMork return Err(SystemError::ENOTDIR); 629004e86ffSlogin } 630004e86ffSlogin 631004e86ffSlogin let name; 632004e86ffSlogin 633004e86ffSlogin // 寻找“/” 634004e86ffSlogin match rest_path.find('/') { 635004e86ffSlogin Some(pos) => { 636004e86ffSlogin // 找到了,设置下一个要查找的名字 637004e86ffSlogin name = String::from(&rest_path[0..pos]); 638004e86ffSlogin // 剩余的路径字符串 639004e86ffSlogin rest_path = String::from(&rest_path[pos + 1..]); 640004e86ffSlogin } 641004e86ffSlogin None => { 642004e86ffSlogin name = rest_path; 643004e86ffSlogin rest_path = String::new(); 644004e86ffSlogin } 645004e86ffSlogin } 646004e86ffSlogin 647004e86ffSlogin // 遇到连续多个"/"的情况 648004e86ffSlogin if name.is_empty() { 649004e86ffSlogin continue; 650004e86ffSlogin } 651004e86ffSlogin 652004e86ffSlogin let inode = result.find(&name)?; 653004e86ffSlogin 654004e86ffSlogin // 处理符号链接的问题 655004e86ffSlogin if inode.metadata()?.file_type == FileType::SymLink && max_follow_times > 0 { 656004e86ffSlogin let mut content = [0u8; 256]; 657004e86ffSlogin // 读取符号链接 658dfe53cf0SGnoCiYeH let len = inode.read_at( 659dfe53cf0SGnoCiYeH 0, 660dfe53cf0SGnoCiYeH 256, 661dfe53cf0SGnoCiYeH &mut content, 662dfe53cf0SGnoCiYeH SpinLock::new(FilePrivateData::Unused).lock(), 663dfe53cf0SGnoCiYeH )?; 664004e86ffSlogin 665004e86ffSlogin // 将读到的数据转换为utf8字符串(先转为str,再转为String) 666004e86ffSlogin let link_path = String::from( 667676b8ef6SMork ::core::str::from_utf8(&content[..len]).map_err(|_| SystemError::ENOTDIR)?, 668004e86ffSlogin ); 669004e86ffSlogin 670004e86ffSlogin let new_path = link_path + "/" + &rest_path; 671004e86ffSlogin // 继续查找符号链接 672004e86ffSlogin return result.lookup_follow_symlink(&new_path, max_follow_times - 1); 673004e86ffSlogin } else { 674004e86ffSlogin result = inode; 675004e86ffSlogin } 676004e86ffSlogin } 677004e86ffSlogin 678004e86ffSlogin return Ok(result); 679004e86ffSlogin } 680004e86ffSlogin } 681004e86ffSlogin 682004e86ffSlogin /// IndexNode的元数据 683004e86ffSlogin /// 684004e86ffSlogin /// 对应Posix2008中的sys/stat.h中的定义 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html 685004e86ffSlogin #[derive(Debug, PartialEq, Eq, Clone)] 686004e86ffSlogin pub struct Metadata { 687004e86ffSlogin /// 当前inode所在的文件系统的设备号 688004e86ffSlogin pub dev_id: usize, 689004e86ffSlogin 690004e86ffSlogin /// inode号 691004e86ffSlogin pub inode_id: InodeId, 692004e86ffSlogin 693004e86ffSlogin /// Inode的大小 694004e86ffSlogin /// 文件:文件大小(单位:字节) 695004e86ffSlogin /// 目录:目录项中的文件、文件夹数量 696004e86ffSlogin pub size: i64, 697004e86ffSlogin 698004e86ffSlogin /// Inode所在的文件系统中,每个块的大小 699004e86ffSlogin pub blk_size: usize, 700004e86ffSlogin 701004e86ffSlogin /// Inode所占的块的数目 702004e86ffSlogin pub blocks: usize, 703004e86ffSlogin 704004e86ffSlogin /// inode最后一次被访问的时间 7056fc066acSJomo pub atime: PosixTimeSpec, 706004e86ffSlogin 707004e86ffSlogin /// inode最后一次修改的时间 7086fc066acSJomo pub mtime: PosixTimeSpec, 709004e86ffSlogin 710004e86ffSlogin /// inode的创建时间 7116fc066acSJomo pub ctime: PosixTimeSpec, 712004e86ffSlogin 713004e86ffSlogin /// 文件类型 714004e86ffSlogin pub file_type: FileType, 715004e86ffSlogin 716004e86ffSlogin /// 权限 7176b4e7a29SLoGin pub mode: ModeType, 718004e86ffSlogin 719004e86ffSlogin /// 硬链接的数量 720004e86ffSlogin pub nlinks: usize, 721004e86ffSlogin 722004e86ffSlogin /// User ID 723004e86ffSlogin pub uid: usize, 724004e86ffSlogin 725004e86ffSlogin /// Group ID 726004e86ffSlogin pub gid: usize, 727004e86ffSlogin 728004e86ffSlogin /// 文件指向的设备的id(对于设备文件系统来说) 72902343d0bSLoGin pub raw_dev: DeviceNumber, 730004e86ffSlogin } 731004e86ffSlogin 732cde5492fSlogin impl Default for Metadata { default() -> Self733cde5492fSlogin fn default() -> Self { 734cde5492fSlogin return Self { 735cde5492fSlogin dev_id: 0, 7366b4e7a29SLoGin inode_id: InodeId::new(0), 737cde5492fSlogin size: 0, 738cde5492fSlogin blk_size: 0, 739cde5492fSlogin blocks: 0, 7406fc066acSJomo atime: PosixTimeSpec::default(), 7416fc066acSJomo mtime: PosixTimeSpec::default(), 7426fc066acSJomo ctime: PosixTimeSpec::default(), 743cde5492fSlogin file_type: FileType::File, 7446b4e7a29SLoGin mode: ModeType::empty(), 745cde5492fSlogin nlinks: 1, 746cde5492fSlogin uid: 0, 747cde5492fSlogin gid: 0, 74802343d0bSLoGin raw_dev: DeviceNumber::default(), 749cde5492fSlogin }; 750cde5492fSlogin } 751cde5492fSlogin } 752cde5492fSlogin 753597ecc08STTaq #[derive(Debug, Clone)] 754597ecc08STTaq pub struct SuperBlock { 755597ecc08STTaq // type of filesystem 756597ecc08STTaq pub magic: Magic, 757597ecc08STTaq // optimal transfer block size 758597ecc08STTaq pub bsize: u64, 759597ecc08STTaq // total data blocks in filesystem 760597ecc08STTaq pub blocks: u64, 761597ecc08STTaq // free block in system 762597ecc08STTaq pub bfree: u64, 763597ecc08STTaq // 可供非特权用户使用的空闲块 764597ecc08STTaq pub bavail: u64, 765597ecc08STTaq // total inodes in filesystem 766597ecc08STTaq pub files: u64, 767597ecc08STTaq // free inodes in filesystem 768597ecc08STTaq pub ffree: u64, 769597ecc08STTaq // filesysytem id 770597ecc08STTaq pub fsid: u64, 771597ecc08STTaq // Max length of filename 772597ecc08STTaq pub namelen: u64, 773597ecc08STTaq // fragment size 774597ecc08STTaq pub frsize: u64, 775597ecc08STTaq // mount flags of filesystem 776597ecc08STTaq pub flags: u64, 777597ecc08STTaq } 778597ecc08STTaq 779597ecc08STTaq impl SuperBlock { new(magic: Magic, bsize: u64, namelen: u64) -> Self780597ecc08STTaq pub fn new(magic: Magic, bsize: u64, namelen: u64) -> Self { 781597ecc08STTaq Self { 782597ecc08STTaq magic, 783597ecc08STTaq bsize, 784597ecc08STTaq blocks: 0, 785597ecc08STTaq bfree: 0, 786597ecc08STTaq bavail: 0, 787597ecc08STTaq files: 0, 788597ecc08STTaq ffree: 0, 789597ecc08STTaq fsid: 0, 790597ecc08STTaq namelen, 791597ecc08STTaq frsize: 0, 792597ecc08STTaq flags: 0, 793597ecc08STTaq } 794597ecc08STTaq } 795597ecc08STTaq } 796597ecc08STTaq bitflags! { 797597ecc08STTaq pub struct Magic: u64 { 798597ecc08STTaq const DEVFS_MAGIC = 0x1373; 799597ecc08STTaq const FAT_MAGIC = 0xf2f52011; 800597ecc08STTaq const KER_MAGIC = 0x3153464b; 801597ecc08STTaq const PROC_MAGIC = 0x9fa0; 802597ecc08STTaq const RAMFS_MAGIC = 0x858458f6; 803597ecc08STTaq const MOUNT_MAGIC = 61267; 804597ecc08STTaq } 805597ecc08STTaq } 806597ecc08STTaq 807004e86ffSlogin /// @brief 所有文件系统都应该实现的trait 808004e86ffSlogin pub trait FileSystem: Any + Sync + Send + Debug { 809004e86ffSlogin /// @brief 获取当前文件系统的root inode的指针 root_inode(&self) -> Arc<dyn IndexNode>810004e86ffSlogin fn root_inode(&self) -> Arc<dyn IndexNode>; 811004e86ffSlogin 812004e86ffSlogin /// @brief 获取当前文件系统的信息 info(&self) -> FsInfo813004e86ffSlogin fn info(&self) -> FsInfo; 814004e86ffSlogin 815004e86ffSlogin /// @brief 本函数用于实现动态转换。 816004e86ffSlogin /// 具体的文件系统在实现本函数时,最简单的方式就是:直接返回self as_any_ref(&self) -> &dyn Any817004e86ffSlogin fn as_any_ref(&self) -> &dyn Any; 8181d37ca6dSDonkey Kane name(&self) -> &str8191d37ca6dSDonkey Kane fn name(&self) -> &str; 820597ecc08STTaq super_block(&self) -> SuperBlock821597ecc08STTaq fn super_block(&self) -> SuperBlock; 822*cf7f801eSMemoryShore fault(&self, _pfm: &mut PageFaultMessage) -> VmFaultReason823*cf7f801eSMemoryShore unsafe fn fault(&self, _pfm: &mut PageFaultMessage) -> VmFaultReason { 824*cf7f801eSMemoryShore panic!( 825*cf7f801eSMemoryShore "fault() has not yet been implemented for filesystem: {}", 826*cf7f801eSMemoryShore crate::libs::name::get_type_name(&self) 827*cf7f801eSMemoryShore ) 828*cf7f801eSMemoryShore } 829*cf7f801eSMemoryShore map_pages( &self, _pfm: &mut PageFaultMessage, _start_pgoff: usize, _end_pgoff: usize, ) -> VmFaultReason830*cf7f801eSMemoryShore unsafe fn map_pages( 831*cf7f801eSMemoryShore &self, 832*cf7f801eSMemoryShore _pfm: &mut PageFaultMessage, 833*cf7f801eSMemoryShore _start_pgoff: usize, 834*cf7f801eSMemoryShore _end_pgoff: usize, 835*cf7f801eSMemoryShore ) -> VmFaultReason { 836*cf7f801eSMemoryShore panic!( 837*cf7f801eSMemoryShore "map_pages() has not yet been implemented for filesystem: {}", 838*cf7f801eSMemoryShore crate::libs::name::get_type_name(&self) 839*cf7f801eSMemoryShore ) 840*cf7f801eSMemoryShore } 841004e86ffSlogin } 842004e86ffSlogin 84306d5e247SLoGin impl DowncastArc for dyn FileSystem { as_any_arc(self: Arc<Self>) -> Arc<dyn Any>84406d5e247SLoGin fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> { 84506d5e247SLoGin self 84606d5e247SLoGin } 84706d5e247SLoGin } 84806d5e247SLoGin 849004e86ffSlogin #[derive(Debug)] 850004e86ffSlogin pub struct FsInfo { 851004e86ffSlogin /// 文件系统所在的块设备的id 852004e86ffSlogin pub blk_dev_id: usize, 853004e86ffSlogin /// 文件名的最大长度 854004e86ffSlogin pub max_name_len: usize, 855004e86ffSlogin } 856004e86ffSlogin 857004e86ffSlogin /// @brief 858004e86ffSlogin #[repr(C)] 859004e86ffSlogin #[derive(Debug)] 860004e86ffSlogin pub struct Dirent { 861004e86ffSlogin d_ino: u64, // 文件序列号 862004e86ffSlogin d_off: i64, // dir偏移量 863004e86ffSlogin d_reclen: u16, // 目录下的记录数 864004e86ffSlogin d_type: u8, // entry的类型 865004e86ffSlogin d_name: u8, // 文件entry的名字(是一个零长数组), 本字段仅用于占位 866004e86ffSlogin } 86720e3152eSlogin 86820e3152eSlogin impl Metadata { new(file_type: FileType, mode: ModeType) -> Self8696b4e7a29SLoGin pub fn new(file_type: FileType, mode: ModeType) -> Self { 87020e3152eSlogin Metadata { 87120e3152eSlogin dev_id: 0, 87220e3152eSlogin inode_id: generate_inode_id(), 87320e3152eSlogin size: 0, 87420e3152eSlogin blk_size: 0, 87520e3152eSlogin blocks: 0, 8766fc066acSJomo atime: PosixTimeSpec::default(), 8776fc066acSJomo mtime: PosixTimeSpec::default(), 8786fc066acSJomo ctime: PosixTimeSpec::default(), 87920e3152eSlogin file_type, 88020e3152eSlogin mode, 88120e3152eSlogin nlinks: 1, 88220e3152eSlogin uid: 0, 88320e3152eSlogin gid: 0, 88402343d0bSLoGin raw_dev: DeviceNumber::default(), 88520e3152eSlogin } 88620e3152eSlogin } 88720e3152eSlogin } 8881d37ca6dSDonkey Kane pub struct FileSystemMaker { 8891d37ca6dSDonkey Kane function: &'static FileSystemNewFunction, 8901d37ca6dSDonkey Kane name: &'static str, 8911d37ca6dSDonkey Kane } 8921d37ca6dSDonkey Kane 8931d37ca6dSDonkey Kane impl FileSystemMaker { new( name: &'static str, function: &'static FileSystemNewFunction, ) -> FileSystemMaker8941d37ca6dSDonkey Kane pub const fn new( 8951d37ca6dSDonkey Kane name: &'static str, 8961d37ca6dSDonkey Kane function: &'static FileSystemNewFunction, 8971d37ca6dSDonkey Kane ) -> FileSystemMaker { 8981d37ca6dSDonkey Kane FileSystemMaker { function, name } 8991d37ca6dSDonkey Kane } 9001d37ca6dSDonkey Kane call(&self) -> Result<Arc<dyn FileSystem>, SystemError>9011d37ca6dSDonkey Kane pub fn call(&self) -> Result<Arc<dyn FileSystem>, SystemError> { 9021d37ca6dSDonkey Kane (self.function)() 9031d37ca6dSDonkey Kane } 9041d37ca6dSDonkey Kane } 9051d37ca6dSDonkey Kane 9061d37ca6dSDonkey Kane pub type FileSystemNewFunction = fn() -> Result<Arc<dyn FileSystem>, SystemError>; 9071d37ca6dSDonkey Kane 9081d37ca6dSDonkey Kane #[macro_export] 9091d37ca6dSDonkey Kane macro_rules! define_filesystem_maker_slice { 9101d37ca6dSDonkey Kane ($name:ident) => { 9111d37ca6dSDonkey Kane #[::linkme::distributed_slice] 9121d37ca6dSDonkey Kane pub static $name: [FileSystemMaker] = [..]; 9131d37ca6dSDonkey Kane }; 9141d37ca6dSDonkey Kane () => { 9150897bd8eSLoGin compile_error!("define_filesystem_maker_slice! requires at least one argument: slice_name"); 9161d37ca6dSDonkey Kane }; 9171d37ca6dSDonkey Kane } 9181d37ca6dSDonkey Kane 9191d37ca6dSDonkey Kane /// 调用指定数组中的所有初始化器 9201d37ca6dSDonkey Kane #[macro_export] 9211d37ca6dSDonkey Kane macro_rules! producefs { 9221d37ca6dSDonkey Kane ($initializer_slice:ident,$filesystem:ident) => { 9231d37ca6dSDonkey Kane match $initializer_slice.iter().find(|&m| m.name == $filesystem) { 9241d37ca6dSDonkey Kane Some(maker) => maker.call(), 9251d37ca6dSDonkey Kane None => { 9262eab6dd7S曾俊 log::error!("mismatch filesystem type : {}", $filesystem); 9271d37ca6dSDonkey Kane Err(SystemError::EINVAL) 9281d37ca6dSDonkey Kane } 9291d37ca6dSDonkey Kane } 9301d37ca6dSDonkey Kane }; 9311d37ca6dSDonkey Kane } 9321d37ca6dSDonkey Kane 9331d37ca6dSDonkey Kane define_filesystem_maker_slice!(FSMAKER); 934