xref: /DragonOS/kernel/src/filesystem/vfs/utils.rs (revision 1074eb34e784aa2adfc5b9e0d89fa4b7e6ea03ef)
1*1074eb34SSamuel Dai use core::cmp::Ordering;
2*1074eb34SSamuel Dai use core::fmt::Debug;
3*1074eb34SSamuel Dai use core::hash::Hash;
4*1074eb34SSamuel Dai 
5*1074eb34SSamuel Dai use alloc::string::ToString;
69b0abe6dSLoGin use alloc::{string::String, sync::Arc};
791e9d4abSLoGin use system_error::SystemError;
89b0abe6dSLoGin 
991e9d4abSLoGin use crate::process::ProcessControlBlock;
109b0abe6dSLoGin 
119b0abe6dSLoGin use super::{fcntl::AtFlags, FileType, IndexNode, ROOT_INODE};
129b0abe6dSLoGin 
13004e86ffSlogin /// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。
14004e86ffSlogin ///
15004e86ffSlogin /// 举例:对于 /123/456/789/   本函数返回的第一个值为123, 第二个值为456/789
16bf4a4899SLoGin #[allow(dead_code)]
17004e86ffSlogin pub fn split_path(path: &str) -> (&str, Option<&str>) {
18004e86ffSlogin     let mut path_split: core::str::SplitN<&str> = path.trim_matches('/').splitn(2, "/");
19004e86ffSlogin     let comp = path_split.next().unwrap_or("");
20004e86ffSlogin     let rest_opt = path_split.next();
21004e86ffSlogin 
22004e86ffSlogin     return (comp, rest_opt);
23004e86ffSlogin }
24004e86ffSlogin 
25004e86ffSlogin /// @brief 切分路径字符串,返回最右侧那一级的目录名和剩余的部分。
26004e86ffSlogin ///
27004e86ffSlogin /// 举例:对于 /123/456/789/   本函数返回的第一个值为789, 第二个值为123/456
28004e86ffSlogin pub fn rsplit_path(path: &str) -> (&str, Option<&str>) {
29004e86ffSlogin     let mut path_split: core::str::RSplitN<&str> = path.trim_matches('/').rsplitn(2, "/");
30004e86ffSlogin     let comp = path_split.next().unwrap_or("");
31004e86ffSlogin     let rest_opt = path_split.next();
32004e86ffSlogin 
33004e86ffSlogin     return (comp, rest_opt);
34004e86ffSlogin }
359b0abe6dSLoGin 
369b0abe6dSLoGin /// 根据dirfd和path,计算接下来开始lookup的inode和剩余的path
379b0abe6dSLoGin ///
389b0abe6dSLoGin /// ## 返回值
399b0abe6dSLoGin ///
40bf4a4899SLoGin /// 返回值为(需要执行lookup的inode, 剩余的path)
419b0abe6dSLoGin pub fn user_path_at(
429b0abe6dSLoGin     pcb: &Arc<ProcessControlBlock>,
439b0abe6dSLoGin     dirfd: i32,
440fb515b0SLoGin     path: &str,
459b0abe6dSLoGin ) -> Result<(Arc<dyn IndexNode>, String), SystemError> {
469b0abe6dSLoGin     let mut inode = ROOT_INODE();
470fb515b0SLoGin     let ret_path;
489b0abe6dSLoGin     // 如果path不是绝对路径,则需要拼接
499b0abe6dSLoGin     if path.as_bytes()[0] != b'/' {
509b0abe6dSLoGin         // 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
519b0abe6dSLoGin         if dirfd != AtFlags::AT_FDCWD.bits() {
529b0abe6dSLoGin             let binding = pcb.fd_table();
539b0abe6dSLoGin             let fd_table_guard = binding.read();
549b0abe6dSLoGin             let file = fd_table_guard
559b0abe6dSLoGin                 .get_file_by_fd(dirfd)
569b0abe6dSLoGin                 .ok_or(SystemError::EBADF)?;
579b0abe6dSLoGin 
589b0abe6dSLoGin             // drop guard 以避免无法调度的问题
599b0abe6dSLoGin             drop(fd_table_guard);
609b0abe6dSLoGin 
619b0abe6dSLoGin             // 如果dirfd不是目录,则返回错误码ENOTDIR
62dfe53cf0SGnoCiYeH             if file.file_type() != FileType::Dir {
639b0abe6dSLoGin                 return Err(SystemError::ENOTDIR);
649b0abe6dSLoGin             }
659b0abe6dSLoGin 
66dfe53cf0SGnoCiYeH             inode = file.inode();
670fb515b0SLoGin             ret_path = String::from(path);
689b0abe6dSLoGin         } else {
699b0abe6dSLoGin             let mut cwd = pcb.basic().cwd();
709b0abe6dSLoGin             cwd.push('/');
710fb515b0SLoGin             cwd.push_str(path);
720fb515b0SLoGin             ret_path = cwd;
739b0abe6dSLoGin         }
740fb515b0SLoGin     } else {
750fb515b0SLoGin         ret_path = String::from(path);
769b0abe6dSLoGin     }
779b0abe6dSLoGin 
780fb515b0SLoGin     return Ok((inode, ret_path));
799b0abe6dSLoGin }
80*1074eb34SSamuel Dai 
81*1074eb34SSamuel Dai /// Directory Name
82*1074eb34SSamuel Dai /// 可以用来作为原地提取目录名及比较的
83*1074eb34SSamuel Dai /// Dentry的对标(x
84*1074eb34SSamuel Dai ///
85*1074eb34SSamuel Dai /// 简单的生成一个新的DName,以实现简单的RCU
86*1074eb34SSamuel Dai #[derive(Debug)]
87*1074eb34SSamuel Dai pub struct DName(pub Arc<String>);
88*1074eb34SSamuel Dai 
89*1074eb34SSamuel Dai impl PartialEq for DName {
90*1074eb34SSamuel Dai     fn eq(&self, other: &Self) -> bool {
91*1074eb34SSamuel Dai         return *self.0 == *other.0;
92*1074eb34SSamuel Dai     }
93*1074eb34SSamuel Dai }
94*1074eb34SSamuel Dai impl Eq for DName {}
95*1074eb34SSamuel Dai 
96*1074eb34SSamuel Dai impl Hash for DName {
97*1074eb34SSamuel Dai     fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
98*1074eb34SSamuel Dai         self.0.hash(state)
99*1074eb34SSamuel Dai     }
100*1074eb34SSamuel Dai }
101*1074eb34SSamuel Dai 
102*1074eb34SSamuel Dai impl PartialOrd for DName {
103*1074eb34SSamuel Dai     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
104*1074eb34SSamuel Dai         Some(self.cmp(other))
105*1074eb34SSamuel Dai     }
106*1074eb34SSamuel Dai }
107*1074eb34SSamuel Dai 
108*1074eb34SSamuel Dai impl Ord for DName {
109*1074eb34SSamuel Dai     fn cmp(&self, other: &Self) -> Ordering {
110*1074eb34SSamuel Dai         return self.0.cmp(&other.0);
111*1074eb34SSamuel Dai     }
112*1074eb34SSamuel Dai }
113*1074eb34SSamuel Dai 
114*1074eb34SSamuel Dai impl Default for DName {
115*1074eb34SSamuel Dai     fn default() -> Self {
116*1074eb34SSamuel Dai         Self(Arc::new(String::new()))
117*1074eb34SSamuel Dai     }
118*1074eb34SSamuel Dai }
119*1074eb34SSamuel Dai 
120*1074eb34SSamuel Dai impl From<String> for DName {
121*1074eb34SSamuel Dai     fn from(value: String) -> Self {
122*1074eb34SSamuel Dai         Self(Arc::from(value))
123*1074eb34SSamuel Dai     }
124*1074eb34SSamuel Dai }
125*1074eb34SSamuel Dai 
126*1074eb34SSamuel Dai impl From<&str> for DName {
127*1074eb34SSamuel Dai     fn from(value: &str) -> Self {
128*1074eb34SSamuel Dai         Self(Arc::from(String::from(value)))
129*1074eb34SSamuel Dai     }
130*1074eb34SSamuel Dai }
131*1074eb34SSamuel Dai 
132*1074eb34SSamuel Dai impl Clone for DName {
133*1074eb34SSamuel Dai     fn clone(&self) -> Self {
134*1074eb34SSamuel Dai         Self(self.0.clone())
135*1074eb34SSamuel Dai     }
136*1074eb34SSamuel Dai }
137*1074eb34SSamuel Dai 
138*1074eb34SSamuel Dai impl ToString for DName {
139*1074eb34SSamuel Dai     fn to_string(&self) -> String {
140*1074eb34SSamuel Dai         (*self.0).clone()
141*1074eb34SSamuel Dai     }
142*1074eb34SSamuel Dai }
143*1074eb34SSamuel Dai 
144*1074eb34SSamuel Dai impl AsRef<str> for DName {
145*1074eb34SSamuel Dai     fn as_ref(&self) -> &str {
146*1074eb34SSamuel Dai         self.0.as_str()
147*1074eb34SSamuel Dai     }
148*1074eb34SSamuel Dai }
149