1 use alloc::{string::String, sync::Arc}; 2 use system_error::SystemError; 3 4 use crate::process::ProcessControlBlock; 5 6 use super::{fcntl::AtFlags, FileType, IndexNode, ROOT_INODE}; 7 8 /// @brief 切分路径字符串,返回最左侧那一级的目录名和剩余的部分。 9 /// 10 /// 举例:对于 /123/456/789/ 本函数返回的第一个值为123, 第二个值为456/789 11 #[allow(dead_code)] 12 pub fn split_path(path: &str) -> (&str, Option<&str>) { 13 let mut path_split: core::str::SplitN<&str> = path.trim_matches('/').splitn(2, "/"); 14 let comp = path_split.next().unwrap_or(""); 15 let rest_opt = path_split.next(); 16 17 return (comp, rest_opt); 18 } 19 20 /// @brief 切分路径字符串,返回最右侧那一级的目录名和剩余的部分。 21 /// 22 /// 举例:对于 /123/456/789/ 本函数返回的第一个值为789, 第二个值为123/456 23 pub fn rsplit_path(path: &str) -> (&str, Option<&str>) { 24 let mut path_split: core::str::RSplitN<&str> = path.trim_matches('/').rsplitn(2, "/"); 25 let comp = path_split.next().unwrap_or(""); 26 let rest_opt = path_split.next(); 27 28 return (comp, rest_opt); 29 } 30 31 /// 根据dirfd和path,计算接下来开始lookup的inode和剩余的path 32 /// 33 /// ## 返回值 34 /// 35 /// 返回值为(需要执行lookup的inode, 剩余的path) 36 pub fn user_path_at( 37 pcb: &Arc<ProcessControlBlock>, 38 dirfd: i32, 39 path: &str, 40 ) -> Result<(Arc<dyn IndexNode>, String), SystemError> { 41 let mut inode = ROOT_INODE(); 42 let ret_path; 43 // 如果path不是绝对路径,则需要拼接 44 if path.as_bytes()[0] != b'/' { 45 // 如果dirfd不是AT_FDCWD,则需要检查dirfd是否是目录 46 if dirfd != AtFlags::AT_FDCWD.bits() { 47 let binding = pcb.fd_table(); 48 let fd_table_guard = binding.read(); 49 let file = fd_table_guard 50 .get_file_by_fd(dirfd) 51 .ok_or(SystemError::EBADF)?; 52 53 // drop guard 以避免无法调度的问题 54 drop(fd_table_guard); 55 56 // 如果dirfd不是目录,则返回错误码ENOTDIR 57 if file.file_type() != FileType::Dir { 58 return Err(SystemError::ENOTDIR); 59 } 60 61 inode = file.inode(); 62 ret_path = String::from(path); 63 } else { 64 let mut cwd = pcb.basic().cwd(); 65 cwd.push('/'); 66 cwd.push_str(path); 67 ret_path = cwd; 68 } 69 } else { 70 ret_path = String::from(path); 71 } 72 73 return Ok((inode, ret_path)); 74 } 75