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