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