xref: /DragonOS/kernel/src/filesystem/vfs/utils.rs (revision 9b0abe6da72176086c3188e0599fda950562668f)
1*9b0abe6dSLoGin use alloc::{string::String, sync::Arc};
2*9b0abe6dSLoGin 
3*9b0abe6dSLoGin use crate::{process::ProcessControlBlock, syscall::SystemError};
4*9b0abe6dSLoGin 
5*9b0abe6dSLoGin use super::{fcntl::AtFlags, FileType, IndexNode, ROOT_INODE};
6*9b0abe6dSLoGin 
7004e86ffSlogin /// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。
8004e86ffSlogin ///
9004e86ffSlogin /// 举例:对于 /123/456/789/   本函数返回的第一个值为123, 第二个值为456/789
10004e86ffSlogin pub fn split_path(path: &str) -> (&str, Option<&str>) {
11004e86ffSlogin     let mut path_split: core::str::SplitN<&str> = path.trim_matches('/').splitn(2, "/");
12004e86ffSlogin     let comp = path_split.next().unwrap_or("");
13004e86ffSlogin     let rest_opt = path_split.next();
14004e86ffSlogin 
15004e86ffSlogin     return (comp, rest_opt);
16004e86ffSlogin }
17004e86ffSlogin 
18004e86ffSlogin /// @brief 切分路径字符串,返回最右侧那一级的目录名和剩余的部分。
19004e86ffSlogin ///
20004e86ffSlogin /// 举例:对于 /123/456/789/   本函数返回的第一个值为789, 第二个值为123/456
21004e86ffSlogin pub fn rsplit_path(path: &str) -> (&str, Option<&str>) {
22004e86ffSlogin     let mut path_split: core::str::RSplitN<&str> = path.trim_matches('/').rsplitn(2, "/");
23004e86ffSlogin     let comp = path_split.next().unwrap_or("");
24004e86ffSlogin     let rest_opt = path_split.next();
25004e86ffSlogin 
26004e86ffSlogin     return (comp, rest_opt);
27004e86ffSlogin }
28*9b0abe6dSLoGin 
29*9b0abe6dSLoGin /// 根据dirfd和path,计算接下来开始lookup的inode和剩余的path
30*9b0abe6dSLoGin ///
31*9b0abe6dSLoGin /// ## 返回值
32*9b0abe6dSLoGin ///
33*9b0abe6dSLoGin /// 返回值为(需要lookup的inode, 剩余的path)
34*9b0abe6dSLoGin pub fn user_path_at(
35*9b0abe6dSLoGin     pcb: &Arc<ProcessControlBlock>,
36*9b0abe6dSLoGin     dirfd: i32,
37*9b0abe6dSLoGin     mut path: String,
38*9b0abe6dSLoGin ) -> Result<(Arc<dyn IndexNode>, String), SystemError> {
39*9b0abe6dSLoGin     let mut inode = ROOT_INODE();
40*9b0abe6dSLoGin     // 如果path不是绝对路径,则需要拼接
41*9b0abe6dSLoGin     if path.as_bytes()[0] != b'/' {
42*9b0abe6dSLoGin         // 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
43*9b0abe6dSLoGin         if dirfd != AtFlags::AT_FDCWD.bits() {
44*9b0abe6dSLoGin             let binding = pcb.fd_table();
45*9b0abe6dSLoGin             let fd_table_guard = binding.read();
46*9b0abe6dSLoGin             let file = fd_table_guard
47*9b0abe6dSLoGin                 .get_file_by_fd(dirfd)
48*9b0abe6dSLoGin                 .ok_or(SystemError::EBADF)?;
49*9b0abe6dSLoGin 
50*9b0abe6dSLoGin             // drop guard 以避免无法调度的问题
51*9b0abe6dSLoGin             drop(fd_table_guard);
52*9b0abe6dSLoGin 
53*9b0abe6dSLoGin             let file_guard = file.lock();
54*9b0abe6dSLoGin             // 如果dirfd不是目录,则返回错误码ENOTDIR
55*9b0abe6dSLoGin             if file_guard.file_type() != FileType::Dir {
56*9b0abe6dSLoGin                 return Err(SystemError::ENOTDIR);
57*9b0abe6dSLoGin             }
58*9b0abe6dSLoGin 
59*9b0abe6dSLoGin             inode = file_guard.inode();
60*9b0abe6dSLoGin         } else {
61*9b0abe6dSLoGin             let mut cwd = pcb.basic().cwd();
62*9b0abe6dSLoGin             cwd.push('/');
63*9b0abe6dSLoGin             cwd.push_str(path.as_str());
64*9b0abe6dSLoGin             path = cwd;
65*9b0abe6dSLoGin         }
66*9b0abe6dSLoGin     }
67*9b0abe6dSLoGin 
68*9b0abe6dSLoGin     return Ok((inode, path));
69*9b0abe6dSLoGin }
70