xref: /DragonOS/kernel/src/filesystem/vfs/utils.rs (revision bf4a48994a2b284ee34aa49a66b4dec1b6ebc07c)
19b0abe6dSLoGin use alloc::{string::String, sync::Arc};
29b0abe6dSLoGin 
39b0abe6dSLoGin use crate::{process::ProcessControlBlock, syscall::SystemError};
49b0abe6dSLoGin 
59b0abe6dSLoGin use super::{fcntl::AtFlags, FileType, IndexNode, ROOT_INODE};
69b0abe6dSLoGin 
7004e86ffSlogin /// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。
8004e86ffSlogin ///
9004e86ffSlogin /// 举例:对于 /123/456/789/   本函数返回的第一个值为123, 第二个值为456/789
10*bf4a4899SLoGin #[allow(dead_code)]
11004e86ffSlogin pub fn split_path(path: &str) -> (&str, Option<&str>) {
12004e86ffSlogin     let mut path_split: core::str::SplitN<&str> = path.trim_matches('/').splitn(2, "/");
13004e86ffSlogin     let comp = path_split.next().unwrap_or("");
14004e86ffSlogin     let rest_opt = path_split.next();
15004e86ffSlogin 
16004e86ffSlogin     return (comp, rest_opt);
17004e86ffSlogin }
18004e86ffSlogin 
19004e86ffSlogin /// @brief 切分路径字符串,返回最右侧那一级的目录名和剩余的部分。
20004e86ffSlogin ///
21004e86ffSlogin /// 举例:对于 /123/456/789/   本函数返回的第一个值为789, 第二个值为123/456
22004e86ffSlogin pub fn rsplit_path(path: &str) -> (&str, Option<&str>) {
23004e86ffSlogin     let mut path_split: core::str::RSplitN<&str> = path.trim_matches('/').rsplitn(2, "/");
24004e86ffSlogin     let comp = path_split.next().unwrap_or("");
25004e86ffSlogin     let rest_opt = path_split.next();
26004e86ffSlogin 
27004e86ffSlogin     return (comp, rest_opt);
28004e86ffSlogin }
299b0abe6dSLoGin 
309b0abe6dSLoGin /// 根据dirfd和path,计算接下来开始lookup的inode和剩余的path
319b0abe6dSLoGin ///
329b0abe6dSLoGin /// ## 返回值
339b0abe6dSLoGin ///
34*bf4a4899SLoGin /// 返回值为(需要执行lookup的inode, 剩余的path)
359b0abe6dSLoGin pub fn user_path_at(
369b0abe6dSLoGin     pcb: &Arc<ProcessControlBlock>,
379b0abe6dSLoGin     dirfd: i32,
389b0abe6dSLoGin     mut path: String,
399b0abe6dSLoGin ) -> Result<(Arc<dyn IndexNode>, String), SystemError> {
409b0abe6dSLoGin     let mut inode = ROOT_INODE();
419b0abe6dSLoGin     // 如果path不是绝对路径,则需要拼接
429b0abe6dSLoGin     if path.as_bytes()[0] != b'/' {
439b0abe6dSLoGin         // 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
449b0abe6dSLoGin         if dirfd != AtFlags::AT_FDCWD.bits() {
459b0abe6dSLoGin             let binding = pcb.fd_table();
469b0abe6dSLoGin             let fd_table_guard = binding.read();
479b0abe6dSLoGin             let file = fd_table_guard
489b0abe6dSLoGin                 .get_file_by_fd(dirfd)
499b0abe6dSLoGin                 .ok_or(SystemError::EBADF)?;
509b0abe6dSLoGin 
519b0abe6dSLoGin             // drop guard 以避免无法调度的问题
529b0abe6dSLoGin             drop(fd_table_guard);
539b0abe6dSLoGin 
549b0abe6dSLoGin             let file_guard = file.lock();
559b0abe6dSLoGin             // 如果dirfd不是目录,则返回错误码ENOTDIR
569b0abe6dSLoGin             if file_guard.file_type() != FileType::Dir {
579b0abe6dSLoGin                 return Err(SystemError::ENOTDIR);
589b0abe6dSLoGin             }
599b0abe6dSLoGin 
609b0abe6dSLoGin             inode = file_guard.inode();
619b0abe6dSLoGin         } else {
629b0abe6dSLoGin             let mut cwd = pcb.basic().cwd();
639b0abe6dSLoGin             cwd.push('/');
649b0abe6dSLoGin             cwd.push_str(path.as_str());
659b0abe6dSLoGin             path = cwd;
669b0abe6dSLoGin         }
679b0abe6dSLoGin     }
689b0abe6dSLoGin 
699b0abe6dSLoGin     return Ok((inode, path));
709b0abe6dSLoGin }
71