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