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