xref: /DragonOS/kernel/src/filesystem/vfs/utils.rs (revision 0fb515b011967be01006cf88d788793dbbce2967)
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
10bf4a4899SLoGin #[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 ///
34bf4a4899SLoGin /// 返回值为(需要执行lookup的inode, 剩余的path)
359b0abe6dSLoGin pub fn user_path_at(
369b0abe6dSLoGin     pcb: &Arc<ProcessControlBlock>,
379b0abe6dSLoGin     dirfd: i32,
38*0fb515b0SLoGin     path: &str,
399b0abe6dSLoGin ) -> Result<(Arc<dyn IndexNode>, String), SystemError> {
409b0abe6dSLoGin     let mut inode = ROOT_INODE();
41*0fb515b0SLoGin     let ret_path;
429b0abe6dSLoGin     // 如果path不是绝对路径,则需要拼接
439b0abe6dSLoGin     if path.as_bytes()[0] != b'/' {
449b0abe6dSLoGin         // 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
459b0abe6dSLoGin         if dirfd != AtFlags::AT_FDCWD.bits() {
469b0abe6dSLoGin             let binding = pcb.fd_table();
479b0abe6dSLoGin             let fd_table_guard = binding.read();
489b0abe6dSLoGin             let file = fd_table_guard
499b0abe6dSLoGin                 .get_file_by_fd(dirfd)
509b0abe6dSLoGin                 .ok_or(SystemError::EBADF)?;
519b0abe6dSLoGin 
529b0abe6dSLoGin             // drop guard 以避免无法调度的问题
539b0abe6dSLoGin             drop(fd_table_guard);
549b0abe6dSLoGin 
559b0abe6dSLoGin             let file_guard = file.lock();
569b0abe6dSLoGin             // 如果dirfd不是目录,则返回错误码ENOTDIR
579b0abe6dSLoGin             if file_guard.file_type() != FileType::Dir {
589b0abe6dSLoGin                 return Err(SystemError::ENOTDIR);
599b0abe6dSLoGin             }
609b0abe6dSLoGin 
619b0abe6dSLoGin             inode = file_guard.inode();
62*0fb515b0SLoGin             ret_path = String::from(path);
639b0abe6dSLoGin         } else {
649b0abe6dSLoGin             let mut cwd = pcb.basic().cwd();
659b0abe6dSLoGin             cwd.push('/');
66*0fb515b0SLoGin             cwd.push_str(path);
67*0fb515b0SLoGin             ret_path = cwd;
689b0abe6dSLoGin         }
69*0fb515b0SLoGin     } else {
70*0fb515b0SLoGin         ret_path = String::from(path);
719b0abe6dSLoGin     }
729b0abe6dSLoGin 
73*0fb515b0SLoGin     return Ok((inode, ret_path));
749b0abe6dSLoGin }
75