xref: /DragonOS/kernel/src/filesystem/vfs/open.rs (revision 0fb515b011967be01006cf88d788793dbbce2967)
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