1*004e86ffSlogin use core::mem::MaybeUninit; 2*004e86ffSlogin 3*004e86ffSlogin use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec}; 4*004e86ffSlogin 5*004e86ffSlogin use crate::{ 6*004e86ffSlogin arch::asm::current::current_pcb, 7*004e86ffSlogin filesystem::procfs::ProcfsFilePrivateData, 8*004e86ffSlogin include::bindings::bindings::{ 9*004e86ffSlogin process_control_block, EINVAL, ENOBUFS, EOVERFLOW, EPERM, ESPIPE, 10*004e86ffSlogin }, 11*004e86ffSlogin io::SeekFrom, 12*004e86ffSlogin kerror, 13*004e86ffSlogin }; 14*004e86ffSlogin 15*004e86ffSlogin use super::{Dirent, FileType, IndexNode, Metadata}; 16*004e86ffSlogin 17*004e86ffSlogin /// 文件私有信息的枚举类型 18*004e86ffSlogin #[derive(Debug, Clone)] 19*004e86ffSlogin pub enum FilePrivateData { 20*004e86ffSlogin // procfs文件私有信息 21*004e86ffSlogin Procfs(ProcfsFilePrivateData), 22*004e86ffSlogin // 不需要文件私有信息 23*004e86ffSlogin Unused, 24*004e86ffSlogin } 25*004e86ffSlogin 26*004e86ffSlogin impl Default for FilePrivateData { 27*004e86ffSlogin fn default() -> Self { 28*004e86ffSlogin return Self::Unused; 29*004e86ffSlogin } 30*004e86ffSlogin } 31*004e86ffSlogin 32*004e86ffSlogin bitflags! { 33*004e86ffSlogin /// @brief 文件打开模式 34*004e86ffSlogin /// 其中,低2bit组合而成的数字的值,用于表示访问权限。其他的bit,才支持通过按位或的方式来表示参数 35*004e86ffSlogin /// 36*004e86ffSlogin /// 与Linux 5.19.10的uapi/asm-generic/fcntl.h相同 37*004e86ffSlogin /// https://opengrok.ringotek.cn/xref/linux-5.19.10/tools/include/uapi/asm-generic/fcntl.h#19 38*004e86ffSlogin pub struct FileMode: u32{ 39*004e86ffSlogin /* File access modes for `open' and `fcntl'. */ 40*004e86ffSlogin /// Open Read-only 41*004e86ffSlogin const O_RDONLY = 0; 42*004e86ffSlogin /// Open Write-only 43*004e86ffSlogin const O_WRONLY = 1; 44*004e86ffSlogin /// Open read/write 45*004e86ffSlogin const O_RDWR = 2; 46*004e86ffSlogin /// Mask for file access modes 47*004e86ffSlogin const O_ACCMODE = 00000003; 48*004e86ffSlogin 49*004e86ffSlogin /* Bits OR'd into the second argument to open. */ 50*004e86ffSlogin /// Create file if it does not exist 51*004e86ffSlogin const O_CREAT = 00000100; 52*004e86ffSlogin /// Fail if file already exists 53*004e86ffSlogin const O_EXCL = 00000200; 54*004e86ffSlogin /// Do not assign controlling terminal 55*004e86ffSlogin const O_NOCTTY = 00000400; 56*004e86ffSlogin /// 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空 57*004e86ffSlogin const O_TRUNC = 00001000; 58*004e86ffSlogin /// 文件指针会被移动到文件末尾 59*004e86ffSlogin const O_APPEND = 00002000; 60*004e86ffSlogin /// 非阻塞式IO模式 61*004e86ffSlogin const O_NONBLOCK = 00004000; 62*004e86ffSlogin /// used to be O_SYNC, see below 63*004e86ffSlogin const O_DSYNC = 00010000; 64*004e86ffSlogin /// fcntl, for BSD compatibility 65*004e86ffSlogin const FASYNC = 00020000; 66*004e86ffSlogin /* direct disk access hint */ 67*004e86ffSlogin const O_DIRECT = 00040000; 68*004e86ffSlogin const O_LARGEFILE = 00100000; 69*004e86ffSlogin /// 打开的必须是一个目录 70*004e86ffSlogin const O_DIRECTORY = 00200000; 71*004e86ffSlogin /// Do not follow symbolic links 72*004e86ffSlogin const O_NOFOLLOW = 00400000; 73*004e86ffSlogin const O_NOATIME = 01000000; 74*004e86ffSlogin /// set close_on_exec 75*004e86ffSlogin const O_CLOEXEC = 02000000; 76*004e86ffSlogin } 77*004e86ffSlogin } 78*004e86ffSlogin 79*004e86ffSlogin /// @brief 抽象文件结构体 80*004e86ffSlogin #[derive(Debug, Clone)] 81*004e86ffSlogin pub struct File { 82*004e86ffSlogin inode: Arc<dyn IndexNode>, 83*004e86ffSlogin /// 对于文件,表示字节偏移量;对于文件夹,表示当前操作的子目录项偏移量 84*004e86ffSlogin offset: usize, 85*004e86ffSlogin /// 文件的打开模式 86*004e86ffSlogin mode: FileMode, 87*004e86ffSlogin /// 文件类型 88*004e86ffSlogin file_type: FileType, 89*004e86ffSlogin /// readdir时候用的,暂存的本次循环中,所有子目录项的名字的数组 90*004e86ffSlogin readdir_subdirs_name: Vec<String>, 91*004e86ffSlogin pub private_data: FilePrivateData, 92*004e86ffSlogin } 93*004e86ffSlogin 94*004e86ffSlogin impl File { 95*004e86ffSlogin /// @brief 创建一个新的文件对象 96*004e86ffSlogin /// 97*004e86ffSlogin /// @param inode 文件对象对应的inode 98*004e86ffSlogin /// @param mode 文件的打开模式 99*004e86ffSlogin pub fn new(inode: Arc<dyn IndexNode>, mode: FileMode) -> Result<Self, i32> { 100*004e86ffSlogin let file_type: FileType = inode.metadata()?.file_type; 101*004e86ffSlogin let mut f = File { 102*004e86ffSlogin inode, 103*004e86ffSlogin offset: 0, 104*004e86ffSlogin mode, 105*004e86ffSlogin file_type, 106*004e86ffSlogin readdir_subdirs_name: Vec::new(), 107*004e86ffSlogin private_data: FilePrivateData::default(), 108*004e86ffSlogin }; 109*004e86ffSlogin // kdebug!("inode:{:?}",f.inode); 110*004e86ffSlogin f.inode.open(&mut f.private_data)?; 111*004e86ffSlogin return Ok(f); 112*004e86ffSlogin } 113*004e86ffSlogin 114*004e86ffSlogin /// @brief 从文件中读取指定的字节数到buffer中 115*004e86ffSlogin /// 116*004e86ffSlogin /// @param len 要读取的字节数 117*004e86ffSlogin /// @param buf 目标buffer 118*004e86ffSlogin /// 119*004e86ffSlogin /// @return Ok(usize) 成功读取的字节数 120*004e86ffSlogin /// @return Err(i32) 错误码 121*004e86ffSlogin pub fn read(&mut self, len: usize, buf: &mut [u8]) -> Result<usize, i32> { 122*004e86ffSlogin // 先检查本文件在权限等规则下,是否可读取。 123*004e86ffSlogin self.readable()?; 124*004e86ffSlogin 125*004e86ffSlogin if buf.len() < len { 126*004e86ffSlogin return Err(-(ENOBUFS as i32)); 127*004e86ffSlogin } 128*004e86ffSlogin 129*004e86ffSlogin let len = self 130*004e86ffSlogin .inode 131*004e86ffSlogin .read_at(self.offset, len, buf, &mut self.private_data)?; 132*004e86ffSlogin self.offset += len; 133*004e86ffSlogin return Ok(len); 134*004e86ffSlogin } 135*004e86ffSlogin 136*004e86ffSlogin /// @brief 从buffer向文件写入指定的字节数的数据 137*004e86ffSlogin /// 138*004e86ffSlogin /// @param len 要写入的字节数 139*004e86ffSlogin /// @param buf 源数据buffer 140*004e86ffSlogin /// 141*004e86ffSlogin /// @return Ok(usize) 成功写入的字节数 142*004e86ffSlogin /// @return Err(i32) 错误码 143*004e86ffSlogin pub fn write(&mut self, len: usize, buf: &[u8]) -> Result<usize, i32> { 144*004e86ffSlogin // 先检查本文件在权限等规则下,是否可写入。 145*004e86ffSlogin self.writeable()?; 146*004e86ffSlogin if buf.len() < len { 147*004e86ffSlogin return Err(-(ENOBUFS as i32)); 148*004e86ffSlogin } 149*004e86ffSlogin let len = self 150*004e86ffSlogin .inode 151*004e86ffSlogin .write_at(self.offset, len, buf, &mut FilePrivateData::Unused)?; 152*004e86ffSlogin self.offset += len; 153*004e86ffSlogin return Ok(len); 154*004e86ffSlogin } 155*004e86ffSlogin 156*004e86ffSlogin /// @brief 获取文件的元数据 157*004e86ffSlogin pub fn metadata(&self) -> Result<Metadata, i32> { 158*004e86ffSlogin return self.inode.metadata(); 159*004e86ffSlogin } 160*004e86ffSlogin 161*004e86ffSlogin /// @brief 根据inode号获取子目录项的名字 162*004e86ffSlogin pub fn get_entry_name(&self, ino: usize) -> Result<String, i32> { 163*004e86ffSlogin return self.inode.get_entry_name(ino); 164*004e86ffSlogin } 165*004e86ffSlogin 166*004e86ffSlogin /// @brief 调整文件操作指针的位置 167*004e86ffSlogin /// 168*004e86ffSlogin /// @param origin 调整的起始位置 169*004e86ffSlogin pub fn lseek(&mut self, origin: SeekFrom) -> Result<usize, i32> { 170*004e86ffSlogin if self.inode.metadata().unwrap().file_type == FileType::Pipe { 171*004e86ffSlogin return Err(-(ESPIPE as i32)); 172*004e86ffSlogin } 173*004e86ffSlogin let pos: i64; 174*004e86ffSlogin match origin { 175*004e86ffSlogin SeekFrom::SeekSet(offset) => { 176*004e86ffSlogin pos = offset; 177*004e86ffSlogin } 178*004e86ffSlogin SeekFrom::SeekCurrent(offset) => { 179*004e86ffSlogin pos = self.offset as i64 + offset; 180*004e86ffSlogin } 181*004e86ffSlogin SeekFrom::SeekEnd(offset) => { 182*004e86ffSlogin let metadata = self.metadata()?; 183*004e86ffSlogin pos = metadata.size + offset; 184*004e86ffSlogin } 185*004e86ffSlogin SeekFrom::Invalid => { 186*004e86ffSlogin return Err(-(EINVAL as i32)); 187*004e86ffSlogin } 188*004e86ffSlogin } 189*004e86ffSlogin 190*004e86ffSlogin if pos < 0 || pos > self.metadata()?.size { 191*004e86ffSlogin return Err(-(EOVERFLOW as i32)); 192*004e86ffSlogin } 193*004e86ffSlogin self.offset = pos as usize; 194*004e86ffSlogin return Ok(self.offset); 195*004e86ffSlogin } 196*004e86ffSlogin 197*004e86ffSlogin /// @brief 判断当前文件是否可读 198*004e86ffSlogin #[inline] 199*004e86ffSlogin pub fn readable(&self) -> Result<(), i32> { 200*004e86ffSlogin // 暂时认为只要不是write only, 就可读 201*004e86ffSlogin if self.mode == FileMode::O_WRONLY { 202*004e86ffSlogin return Err(-(EPERM as i32)); 203*004e86ffSlogin } 204*004e86ffSlogin 205*004e86ffSlogin return Ok(()); 206*004e86ffSlogin } 207*004e86ffSlogin 208*004e86ffSlogin /// @brief 判断当前文件是否可写 209*004e86ffSlogin #[inline] 210*004e86ffSlogin pub fn writeable(&self) -> Result<(), i32> { 211*004e86ffSlogin // 暂时认为只要不是read only, 就可写 212*004e86ffSlogin if self.mode == FileMode::O_RDONLY { 213*004e86ffSlogin return Err(-(EPERM as i32)); 214*004e86ffSlogin } 215*004e86ffSlogin 216*004e86ffSlogin return Ok(()); 217*004e86ffSlogin } 218*004e86ffSlogin 219*004e86ffSlogin /// @biref 充填dirent结构体 220*004e86ffSlogin /// @return 返回dirent结构体的大小 221*004e86ffSlogin pub fn readdir(&mut self, dirent: &mut Dirent) -> Result<u64, i32> { 222*004e86ffSlogin let inode: &Arc<dyn IndexNode> = &self.inode; 223*004e86ffSlogin 224*004e86ffSlogin // 如果偏移量为0 225*004e86ffSlogin if self.offset == 0 { 226*004e86ffSlogin self.readdir_subdirs_name = inode.list()?; 227*004e86ffSlogin self.readdir_subdirs_name.sort(); 228*004e86ffSlogin } 229*004e86ffSlogin 230*004e86ffSlogin // kdebug!("sub_entries={sub_entries:?}"); 231*004e86ffSlogin if self.readdir_subdirs_name.is_empty() { 232*004e86ffSlogin self.offset = 0; 233*004e86ffSlogin return Ok(0); 234*004e86ffSlogin } 235*004e86ffSlogin let name: String = self.readdir_subdirs_name.remove(0); 236*004e86ffSlogin let sub_inode: Arc<dyn IndexNode> = match inode.find(&name) { 237*004e86ffSlogin Ok(i) => i, 238*004e86ffSlogin Err(e) => { 239*004e86ffSlogin kerror!("Readdir error: Failed to find sub inode, file={self:?}"); 240*004e86ffSlogin return Err(e); 241*004e86ffSlogin } 242*004e86ffSlogin }; 243*004e86ffSlogin 244*004e86ffSlogin let name_bytes: &[u8] = name.as_bytes(); 245*004e86ffSlogin 246*004e86ffSlogin self.offset += 1; 247*004e86ffSlogin dirent.d_ino = sub_inode.metadata().unwrap().inode_id as u64; 248*004e86ffSlogin dirent.d_off = 0; 249*004e86ffSlogin dirent.d_reclen = 0; 250*004e86ffSlogin dirent.d_type = sub_inode.metadata().unwrap().file_type.get_file_type_num() as u8; 251*004e86ffSlogin // 根据posix的规定,dirent中的d_name是一个不定长的数组,因此需要unsafe来拷贝数据 252*004e86ffSlogin unsafe { 253*004e86ffSlogin let ptr = &mut dirent.d_name as *mut u8; 254*004e86ffSlogin let buf: &mut [u8] = 255*004e86ffSlogin ::core::slice::from_raw_parts_mut::<'static, u8>(ptr, name_bytes.len()); 256*004e86ffSlogin buf.copy_from_slice(name_bytes); 257*004e86ffSlogin } 258*004e86ffSlogin 259*004e86ffSlogin // 计算dirent结构体的大小 260*004e86ffSlogin return Ok((name_bytes.len() + ::core::mem::size_of::<Dirent>() 261*004e86ffSlogin - ::core::mem::size_of_val(&dirent.d_name)) as u64); 262*004e86ffSlogin } 263*004e86ffSlogin pub fn inode(&self) -> Arc<dyn IndexNode> { 264*004e86ffSlogin return self.inode.clone(); 265*004e86ffSlogin } 266*004e86ffSlogin } 267*004e86ffSlogin 268*004e86ffSlogin impl Drop for File { 269*004e86ffSlogin fn drop(&mut self) { 270*004e86ffSlogin let r: Result<(), i32> = self.inode.close(&mut self.private_data); 271*004e86ffSlogin // 打印错误信息 272*004e86ffSlogin if r.is_err() { 273*004e86ffSlogin kerror!( 274*004e86ffSlogin "pid: {} failed to close file: {:?}, errno={}", 275*004e86ffSlogin current_pcb().pid, 276*004e86ffSlogin self, 277*004e86ffSlogin r.unwrap_err() 278*004e86ffSlogin ); 279*004e86ffSlogin } 280*004e86ffSlogin } 281*004e86ffSlogin } 282*004e86ffSlogin 283*004e86ffSlogin /// @brief pcb里面的文件描述符数组 284*004e86ffSlogin #[derive(Debug, Clone)] 285*004e86ffSlogin pub struct FileDescriptorVec { 286*004e86ffSlogin /// 当前进程打开的文件描述符 287*004e86ffSlogin pub fds: [Option<Box<File>>; FileDescriptorVec::PROCESS_MAX_FD], 288*004e86ffSlogin } 289*004e86ffSlogin 290*004e86ffSlogin impl FileDescriptorVec { 291*004e86ffSlogin pub const PROCESS_MAX_FD: usize = 32; 292*004e86ffSlogin 293*004e86ffSlogin pub fn new() -> Box<FileDescriptorVec> { 294*004e86ffSlogin // 先声明一个未初始化的数组 295*004e86ffSlogin let mut data: [MaybeUninit<Option<Box<File>>>; FileDescriptorVec::PROCESS_MAX_FD] = 296*004e86ffSlogin unsafe { MaybeUninit::uninit().assume_init() }; 297*004e86ffSlogin 298*004e86ffSlogin // 逐个把每个元素初始化为None 299*004e86ffSlogin for i in 0..FileDescriptorVec::PROCESS_MAX_FD { 300*004e86ffSlogin data[i] = MaybeUninit::new(None); 301*004e86ffSlogin } 302*004e86ffSlogin // 由于一切都初始化完毕,因此将未初始化的类型强制转换为已经初始化的类型 303*004e86ffSlogin let data: [Option<Box<File>>; FileDescriptorVec::PROCESS_MAX_FD] = unsafe { 304*004e86ffSlogin core::mem::transmute::<_, [Option<Box<File>>; FileDescriptorVec::PROCESS_MAX_FD]>(data) 305*004e86ffSlogin }; 306*004e86ffSlogin 307*004e86ffSlogin // 初始化文件描述符数组结构体 308*004e86ffSlogin return Box::new(FileDescriptorVec { fds: data }); 309*004e86ffSlogin } 310*004e86ffSlogin 311*004e86ffSlogin /// @brief 从pcb的fds字段,获取文件描述符数组的可变引用 312*004e86ffSlogin #[inline] 313*004e86ffSlogin pub fn from_pcb(pcb: &'static process_control_block) -> Option<&'static mut FileDescriptorVec> { 314*004e86ffSlogin return unsafe { (pcb.fds as usize as *mut FileDescriptorVec).as_mut() }; 315*004e86ffSlogin } 316*004e86ffSlogin 317*004e86ffSlogin /// @brief 判断文件描述符序号是否合法 318*004e86ffSlogin /// 319*004e86ffSlogin /// @return true 合法 320*004e86ffSlogin /// 321*004e86ffSlogin /// @return false 不合法 322*004e86ffSlogin #[inline] 323*004e86ffSlogin pub fn validate_fd(fd: i32) -> bool { 324*004e86ffSlogin if fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD { 325*004e86ffSlogin return false; 326*004e86ffSlogin } else { 327*004e86ffSlogin return true; 328*004e86ffSlogin } 329*004e86ffSlogin } 330*004e86ffSlogin } 331