1*0fb515b0SLoGin use alloc::sync::Arc; 2*0fb515b0SLoGin 3bf4a4899SLoGin use crate::{ 4*0fb515b0SLoGin driver::base::block::SeekFrom, 5bf4a4899SLoGin process::ProcessManager, 6bf4a4899SLoGin syscall::{user_access::check_and_clone_cstr, SystemError}, 7bf4a4899SLoGin }; 89b0abe6dSLoGin 9bf4a4899SLoGin use super::{ 10*0fb515b0SLoGin fcntl::AtFlags, 11*0fb515b0SLoGin file::{File, FileMode}, 12*0fb515b0SLoGin syscall::{ModeType, OpenHow, OpenHowResolve}, 13*0fb515b0SLoGin utils::{rsplit_path, user_path_at}, 14*0fb515b0SLoGin FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES, 15bf4a4899SLoGin }; 169b0abe6dSLoGin 179b0abe6dSLoGin pub(super) fn do_faccessat( 18bf4a4899SLoGin dirfd: i32, 19bf4a4899SLoGin path: *const u8, 209b0abe6dSLoGin mode: ModeType, 219b0abe6dSLoGin flags: u32, 229b0abe6dSLoGin ) -> Result<usize, SystemError> { 23bf4a4899SLoGin if (mode.bits() & (!ModeType::S_IRWXO.bits())) != 0 { 249b0abe6dSLoGin return Err(SystemError::EINVAL); 259b0abe6dSLoGin } 269b0abe6dSLoGin 279b0abe6dSLoGin if (flags 289b0abe6dSLoGin & (!((AtFlags::AT_EACCESS | AtFlags::AT_SYMLINK_NOFOLLOW | AtFlags::AT_EMPTY_PATH).bits() 299b0abe6dSLoGin as u32))) 309b0abe6dSLoGin != 0 319b0abe6dSLoGin { 329b0abe6dSLoGin return Err(SystemError::EINVAL); 339b0abe6dSLoGin } 349b0abe6dSLoGin 359b0abe6dSLoGin // let follow_symlink = flags & AtFlags::AT_SYMLINK_NOFOLLOW.bits() as u32 == 0; 369b0abe6dSLoGin 37bf4a4899SLoGin let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 38bf4a4899SLoGin 39bf4a4899SLoGin if path.len() == 0 { 40bf4a4899SLoGin return Err(SystemError::EINVAL); 41bf4a4899SLoGin } 42bf4a4899SLoGin 43*0fb515b0SLoGin let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?; 44bf4a4899SLoGin 45bf4a4899SLoGin // 如果找不到文件,则返回错误码ENOENT 46bf4a4899SLoGin let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 47bf4a4899SLoGin 489b0abe6dSLoGin // todo: 接着完善(可以借鉴linux 6.1.9的do_faccessat) 499b0abe6dSLoGin return Ok(0); 509b0abe6dSLoGin } 51bf4a4899SLoGin 52bf4a4899SLoGin pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize, SystemError> { 53bf4a4899SLoGin let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 54bf4a4899SLoGin 55bf4a4899SLoGin if path.len() == 0 { 56bf4a4899SLoGin return Err(SystemError::EINVAL); 57bf4a4899SLoGin } 58bf4a4899SLoGin 59*0fb515b0SLoGin let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?; 60bf4a4899SLoGin 61bf4a4899SLoGin // 如果找不到文件,则返回错误码ENOENT 62bf4a4899SLoGin let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 63bf4a4899SLoGin 64bf4a4899SLoGin kwarn!("do_fchmodat: not implemented yet\n"); 65bf4a4899SLoGin // todo: 真正去改变文件的权限 66bf4a4899SLoGin 67bf4a4899SLoGin return Ok(0); 68bf4a4899SLoGin } 69*0fb515b0SLoGin 70*0fb515b0SLoGin pub(super) fn do_sys_open( 71*0fb515b0SLoGin dfd: i32, 72*0fb515b0SLoGin path: &str, 73*0fb515b0SLoGin o_flags: FileMode, 74*0fb515b0SLoGin mode: ModeType, 75*0fb515b0SLoGin follow_symlink: bool, 76*0fb515b0SLoGin ) -> Result<usize, SystemError> { 77*0fb515b0SLoGin let how = OpenHow::new(o_flags, mode, OpenHowResolve::empty()); 78*0fb515b0SLoGin return do_sys_openat2(dfd, path, how, follow_symlink); 79*0fb515b0SLoGin } 80*0fb515b0SLoGin 81*0fb515b0SLoGin fn do_sys_openat2( 82*0fb515b0SLoGin dirfd: i32, 83*0fb515b0SLoGin path: &str, 84*0fb515b0SLoGin how: OpenHow, 85*0fb515b0SLoGin follow_symlink: bool, 86*0fb515b0SLoGin ) -> Result<usize, SystemError> { 87*0fb515b0SLoGin // kdebug!("open: path: {}, mode: {:?}", path, mode); 88*0fb515b0SLoGin // 文件名过长 89*0fb515b0SLoGin if path.len() > MAX_PATHLEN as usize { 90*0fb515b0SLoGin return Err(SystemError::ENAMETOOLONG); 91*0fb515b0SLoGin } 92*0fb515b0SLoGin let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?; 93*0fb515b0SLoGin let inode: Result<Arc<dyn IndexNode>, SystemError> = inode_begin.lookup_follow_symlink( 94*0fb515b0SLoGin &path, 95*0fb515b0SLoGin if follow_symlink { 96*0fb515b0SLoGin VFS_MAX_FOLLOW_SYMLINK_TIMES 97*0fb515b0SLoGin } else { 98*0fb515b0SLoGin 0 99*0fb515b0SLoGin }, 100*0fb515b0SLoGin ); 101*0fb515b0SLoGin 102*0fb515b0SLoGin let inode: Arc<dyn IndexNode> = if inode.is_err() { 103*0fb515b0SLoGin let errno = inode.unwrap_err(); 104*0fb515b0SLoGin // 文件不存在,且需要创建 105*0fb515b0SLoGin if how.o_flags.contains(FileMode::O_CREAT) 106*0fb515b0SLoGin && !how.o_flags.contains(FileMode::O_DIRECTORY) 107*0fb515b0SLoGin && errno == SystemError::ENOENT 108*0fb515b0SLoGin { 109*0fb515b0SLoGin let (filename, parent_path) = rsplit_path(&path); 110*0fb515b0SLoGin // 查找父目录 111*0fb515b0SLoGin let parent_inode: Arc<dyn IndexNode> = 112*0fb515b0SLoGin ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; 113*0fb515b0SLoGin // 创建文件 114*0fb515b0SLoGin let inode: Arc<dyn IndexNode> = parent_inode.create( 115*0fb515b0SLoGin filename, 116*0fb515b0SLoGin FileType::File, 117*0fb515b0SLoGin ModeType::from_bits_truncate(0o755), 118*0fb515b0SLoGin )?; 119*0fb515b0SLoGin inode 120*0fb515b0SLoGin } else { 121*0fb515b0SLoGin // 不需要创建文件,因此返回错误码 122*0fb515b0SLoGin return Err(errno); 123*0fb515b0SLoGin } 124*0fb515b0SLoGin } else { 125*0fb515b0SLoGin inode.unwrap() 126*0fb515b0SLoGin }; 127*0fb515b0SLoGin 128*0fb515b0SLoGin let file_type: FileType = inode.metadata()?.file_type; 129*0fb515b0SLoGin // 如果要打开的是文件夹,而目标不是文件夹 130*0fb515b0SLoGin if how.o_flags.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir { 131*0fb515b0SLoGin return Err(SystemError::ENOTDIR); 132*0fb515b0SLoGin } 133*0fb515b0SLoGin 134*0fb515b0SLoGin // 创建文件对象 135*0fb515b0SLoGin 136*0fb515b0SLoGin let mut file: File = File::new(inode, how.o_flags)?; 137*0fb515b0SLoGin 138*0fb515b0SLoGin // 打开模式为“追加” 139*0fb515b0SLoGin if how.o_flags.contains(FileMode::O_APPEND) { 140*0fb515b0SLoGin file.lseek(SeekFrom::SeekEnd(0))?; 141*0fb515b0SLoGin } 142*0fb515b0SLoGin 143*0fb515b0SLoGin // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件 144*0fb515b0SLoGin if how.o_flags.contains(FileMode::O_TRUNC) 145*0fb515b0SLoGin && (how.o_flags.contains(FileMode::O_RDWR) || how.o_flags.contains(FileMode::O_WRONLY)) 146*0fb515b0SLoGin && file_type == FileType::File 147*0fb515b0SLoGin { 148*0fb515b0SLoGin file.ftruncate(0)?; 149*0fb515b0SLoGin } 150*0fb515b0SLoGin // 把文件对象存入pcb 151*0fb515b0SLoGin let r = ProcessManager::current_pcb() 152*0fb515b0SLoGin .fd_table() 153*0fb515b0SLoGin .write() 154*0fb515b0SLoGin .alloc_fd(file, None) 155*0fb515b0SLoGin .map(|fd| fd as usize); 156*0fb515b0SLoGin 157*0fb515b0SLoGin return r; 158*0fb515b0SLoGin } 159