open.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. use alloc::sync::Arc;
  2. use crate::{
  3. driver::base::block::SeekFrom,
  4. process::ProcessManager,
  5. syscall::{user_access::check_and_clone_cstr, SystemError},
  6. };
  7. use super::{
  8. fcntl::AtFlags,
  9. file::{File, FileMode},
  10. syscall::{ModeType, OpenHow, OpenHowResolve},
  11. utils::{rsplit_path, user_path_at},
  12. FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
  13. };
  14. pub(super) fn do_faccessat(
  15. dirfd: i32,
  16. path: *const u8,
  17. mode: ModeType,
  18. flags: u32,
  19. ) -> Result<usize, SystemError> {
  20. if (mode.bits() & (!ModeType::S_IRWXO.bits())) != 0 {
  21. return Err(SystemError::EINVAL);
  22. }
  23. if (flags
  24. & (!((AtFlags::AT_EACCESS | AtFlags::AT_SYMLINK_NOFOLLOW | AtFlags::AT_EMPTY_PATH).bits()
  25. as u32)))
  26. != 0
  27. {
  28. return Err(SystemError::EINVAL);
  29. }
  30. // let follow_symlink = flags & AtFlags::AT_SYMLINK_NOFOLLOW.bits() as u32 == 0;
  31. let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
  32. if path.len() == 0 {
  33. return Err(SystemError::EINVAL);
  34. }
  35. let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;
  36. // 如果找不到文件,则返回错误码ENOENT
  37. let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
  38. // todo: 接着完善(可以借鉴linux 6.1.9的do_faccessat)
  39. return Ok(0);
  40. }
  41. pub fn do_fchmodat(dirfd: i32, path: *const u8, _mode: ModeType) -> Result<usize, SystemError> {
  42. let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
  43. if path.len() == 0 {
  44. return Err(SystemError::EINVAL);
  45. }
  46. let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;
  47. // 如果找不到文件,则返回错误码ENOENT
  48. let _inode = inode.lookup_follow_symlink(path.as_str(), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
  49. kwarn!("do_fchmodat: not implemented yet\n");
  50. // todo: 真正去改变文件的权限
  51. return Ok(0);
  52. }
  53. pub(super) fn do_sys_open(
  54. dfd: i32,
  55. path: &str,
  56. o_flags: FileMode,
  57. mode: ModeType,
  58. follow_symlink: bool,
  59. ) -> Result<usize, SystemError> {
  60. let how = OpenHow::new(o_flags, mode, OpenHowResolve::empty());
  61. return do_sys_openat2(dfd, path, how, follow_symlink);
  62. }
  63. fn do_sys_openat2(
  64. dirfd: i32,
  65. path: &str,
  66. how: OpenHow,
  67. follow_symlink: bool,
  68. ) -> Result<usize, SystemError> {
  69. // kdebug!("open: path: {}, mode: {:?}", path, mode);
  70. // 文件名过长
  71. if path.len() > MAX_PATHLEN as usize {
  72. return Err(SystemError::ENAMETOOLONG);
  73. }
  74. let (inode_begin, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, path)?;
  75. let inode: Result<Arc<dyn IndexNode>, SystemError> = inode_begin.lookup_follow_symlink(
  76. &path,
  77. if follow_symlink {
  78. VFS_MAX_FOLLOW_SYMLINK_TIMES
  79. } else {
  80. 0
  81. },
  82. );
  83. let inode: Arc<dyn IndexNode> = if inode.is_err() {
  84. let errno = inode.unwrap_err();
  85. // 文件不存在,且需要创建
  86. if how.o_flags.contains(FileMode::O_CREAT)
  87. && !how.o_flags.contains(FileMode::O_DIRECTORY)
  88. && errno == SystemError::ENOENT
  89. {
  90. let (filename, parent_path) = rsplit_path(&path);
  91. // 查找父目录
  92. let parent_inode: Arc<dyn IndexNode> =
  93. ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
  94. // 创建文件
  95. let inode: Arc<dyn IndexNode> = parent_inode.create(
  96. filename,
  97. FileType::File,
  98. ModeType::from_bits_truncate(0o755),
  99. )?;
  100. inode
  101. } else {
  102. // 不需要创建文件,因此返回错误码
  103. return Err(errno);
  104. }
  105. } else {
  106. inode.unwrap()
  107. };
  108. let file_type: FileType = inode.metadata()?.file_type;
  109. // 如果要打开的是文件夹,而目标不是文件夹
  110. if how.o_flags.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
  111. return Err(SystemError::ENOTDIR);
  112. }
  113. // 创建文件对象
  114. let mut file: File = File::new(inode, how.o_flags)?;
  115. // 打开模式为“追加”
  116. if how.o_flags.contains(FileMode::O_APPEND) {
  117. file.lseek(SeekFrom::SeekEnd(0))?;
  118. }
  119. // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
  120. if how.o_flags.contains(FileMode::O_TRUNC)
  121. && (how.o_flags.contains(FileMode::O_RDWR) || how.o_flags.contains(FileMode::O_WRONLY))
  122. && file_type == FileType::File
  123. {
  124. file.ftruncate(0)?;
  125. }
  126. // 把文件对象存入pcb
  127. let r = ProcessManager::current_pcb()
  128. .fd_table()
  129. .write()
  130. .alloc_fd(file, None)
  131. .map(|fd| fd as usize);
  132. return r;
  133. }