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