utils.rs 2.4 KB

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