1 use core::cmp::Ordering;
2 use core::fmt::{self, Debug};
3 use core::hash::Hash;
4
5 use alloc::{string::String, sync::Arc};
6 use system_error::SystemError;
7
8 use crate::process::ProcessControlBlock;
9
10 use super::{fcntl::AtFlags, FileType, IndexNode, ROOT_INODE};
11
12 /// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。
13 ///
14 /// 举例:对于 /123/456/789/ 本函数返回的第一个值为123, 第二个值为456/789
15 #[allow(dead_code)]
split_path(path: &str) -> (&str, Option<&str>)16 pub fn split_path(path: &str) -> (&str, Option<&str>) {
17 let mut path_split: core::str::SplitN<&str> = path.trim_matches('/').splitn(2, "/");
18 let comp = path_split.next().unwrap_or("");
19 let rest_opt = path_split.next();
20
21 return (comp, rest_opt);
22 }
23
24 /// @brief 切分路径字符串,返回最右侧那一级的目录名和剩余的部分。
25 ///
26 /// 举例:对于 /123/456/789/ 本函数返回的第一个值为789, 第二个值为123/456
rsplit_path(path: &str) -> (&str, Option<&str>)27 pub fn rsplit_path(path: &str) -> (&str, Option<&str>) {
28 let mut path_split: core::str::RSplitN<&str> = path.trim_matches('/').rsplitn(2, "/");
29 let comp = path_split.next().unwrap_or("");
30 let rest_opt = path_split.next();
31
32 return (comp, rest_opt);
33 }
34
35 /// 根据dirfd和path,计算接下来开始lookup的inode和剩余的path
36 ///
37 /// ## 返回值
38 ///
39 /// 返回值为(需要执行lookup的inode, 剩余的path)
user_path_at( pcb: &Arc<ProcessControlBlock>, dirfd: i32, path: &str, ) -> Result<(Arc<dyn IndexNode>, String), SystemError>40 pub fn user_path_at(
41 pcb: &Arc<ProcessControlBlock>,
42 dirfd: i32,
43 path: &str,
44 ) -> Result<(Arc<dyn IndexNode>, String), SystemError> {
45 let mut inode = ROOT_INODE();
46 let ret_path;
47 // 如果path不是绝对路径,则需要拼接
48 if path.as_bytes()[0] != b'/' {
49 // 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录
50 if dirfd != AtFlags::AT_FDCWD.bits() {
51 let binding = pcb.fd_table();
52 let fd_table_guard = binding.read();
53 let file = fd_table_guard
54 .get_file_by_fd(dirfd)
55 .ok_or(SystemError::EBADF)?;
56
57 // drop guard 以避免无法调度的问题
58 drop(fd_table_guard);
59
60 // 如果dirfd不是目录,则返回错误码ENOTDIR
61 if file.file_type() != FileType::Dir {
62 return Err(SystemError::ENOTDIR);
63 }
64
65 inode = file.inode();
66 ret_path = String::from(path);
67 } else {
68 let mut cwd = pcb.basic().cwd();
69 cwd.push('/');
70 cwd.push_str(path);
71 ret_path = cwd;
72 }
73 } else {
74 ret_path = String::from(path);
75 }
76
77 return Ok((inode, ret_path));
78 }
79
80 /// Directory Name
81 /// 可以用来作为原地提取目录名及比较的
82 /// Dentry的对标(x
83 ///
84 /// 简单的生成一个新的DName,以实现简单的RCU
85 #[derive(Debug)]
86 pub struct DName(pub Arc<String>);
87
88 impl PartialEq for DName {
eq(&self, other: &Self) -> bool89 fn eq(&self, other: &Self) -> bool {
90 return *self.0 == *other.0;
91 }
92 }
93 impl Eq for DName {}
94
95 impl Hash for DName {
hash<H: core::hash::Hasher>(&self, state: &mut H)96 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
97 self.0.hash(state)
98 }
99 }
100
101 impl PartialOrd for DName {
partial_cmp(&self, other: &Self) -> Option<Ordering>102 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
103 Some(self.cmp(other))
104 }
105 }
106
107 impl Ord for DName {
cmp(&self, other: &Self) -> Ordering108 fn cmp(&self, other: &Self) -> Ordering {
109 return self.0.cmp(&other.0);
110 }
111 }
112
113 impl Default for DName {
default() -> Self114 fn default() -> Self {
115 Self(Arc::new(String::new()))
116 }
117 }
118
119 impl From<String> for DName {
from(value: String) -> Self120 fn from(value: String) -> Self {
121 Self(Arc::from(value))
122 }
123 }
124
125 impl From<&str> for DName {
from(value: &str) -> Self126 fn from(value: &str) -> Self {
127 Self(Arc::from(String::from(value)))
128 }
129 }
130
131 impl Clone for DName {
clone(&self) -> Self132 fn clone(&self) -> Self {
133 Self(self.0.clone())
134 }
135 }
136
137 impl fmt::Display for DName {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 write!(f, "{}", self.0)
140 }
141 }
142
143 impl AsRef<str> for DName {
as_ref(&self) -> &str144 fn as_ref(&self) -> &str {
145 self.0.as_str()
146 }
147 }
148