filearray.rs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. use super::{
  2. file::{File, InodeFile, TerminalFile},
  3. inode::Mode,
  4. s_ischr, Spin,
  5. };
  6. use crate::kernel::{
  7. constants::{
  8. EBADF, EISDIR, ENOTDIR, F_DUPFD, F_DUPFD_CLOEXEC, F_GETFD, F_GETFL, F_SETFD, F_SETFL,
  9. },
  10. syscall::{FromSyscallArg, SyscallRetVal},
  11. };
  12. use crate::{
  13. kernel::{
  14. console::get_console,
  15. constants::ENXIO,
  16. vfs::{dentry::Dentry, file::Pipe, s_isdir, s_isreg},
  17. CharDevice,
  18. },
  19. prelude::*,
  20. };
  21. use alloc::{
  22. collections::btree_map::{BTreeMap, Entry},
  23. sync::Arc,
  24. };
  25. use core::sync::atomic::Ordering;
  26. use itertools::{
  27. FoldWhile::{Continue, Done},
  28. Itertools,
  29. };
  30. use posix_types::open::{FDFlags, OpenFlags};
  31. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
  32. pub struct FD(u32);
  33. #[derive(Clone)]
  34. struct OpenFile {
  35. flags: FDFlags,
  36. file: Arc<File>,
  37. }
  38. #[derive(Clone)]
  39. struct FileArrayInner {
  40. files: BTreeMap<FD, OpenFile>,
  41. fd_min_avail: FD,
  42. }
  43. pub struct FileArray {
  44. inner: Spin<FileArrayInner>,
  45. }
  46. impl OpenFile {
  47. pub fn close_on_exec(&self) -> bool {
  48. self.flags.contains(FDFlags::FD_CLOEXEC)
  49. }
  50. }
  51. impl FileArray {
  52. pub fn new() -> Arc<Self> {
  53. Arc::new(FileArray {
  54. inner: Spin::new(FileArrayInner {
  55. files: BTreeMap::new(),
  56. fd_min_avail: FD(0),
  57. }),
  58. })
  59. }
  60. #[allow(dead_code)]
  61. pub fn new_shared(other: &Arc<Self>) -> Arc<Self> {
  62. other.clone()
  63. }
  64. pub fn new_cloned(other: &Self) -> Arc<Self> {
  65. Arc::new(Self {
  66. inner: Spin::new(other.inner.lock().clone()),
  67. })
  68. }
  69. /// Acquires the file array lock.
  70. pub fn get(&self, fd: FD) -> Option<Arc<File>> {
  71. self.inner.lock().get(fd)
  72. }
  73. pub fn close_all(&self) {
  74. let _old_files = {
  75. let mut inner = self.inner.lock();
  76. inner.fd_min_avail = FD(0);
  77. core::mem::take(&mut inner.files)
  78. };
  79. }
  80. pub fn close(&self, fd: FD) -> KResult<()> {
  81. let _file = {
  82. let mut inner = self.inner.lock();
  83. let file = inner.files.remove(&fd).ok_or(EBADF)?;
  84. inner.release_fd(fd);
  85. file
  86. };
  87. Ok(())
  88. }
  89. pub fn on_exec(&self) -> () {
  90. let mut inner = self.inner.lock();
  91. // TODO: This is not efficient. We should avoid cloning.
  92. let fds_to_close = inner
  93. .files
  94. .iter()
  95. .filter(|(_, ofile)| ofile.close_on_exec())
  96. .map(|(&fd, _)| fd)
  97. .collect::<Vec<_>>();
  98. inner.files.retain(|_, ofile| !ofile.close_on_exec());
  99. fds_to_close.into_iter().for_each(|fd| inner.release_fd(fd));
  100. }
  101. }
  102. impl FileArray {
  103. pub fn dup(&self, old_fd: FD) -> KResult<FD> {
  104. let mut inner = self.inner.lock();
  105. let old_file = inner.files.get(&old_fd).ok_or(EBADF)?;
  106. let new_file_data = old_file.file.clone();
  107. let new_file_flags = old_file.flags;
  108. let new_fd = inner.next_fd();
  109. inner.do_insert(new_fd, new_file_flags, new_file_data);
  110. Ok(new_fd)
  111. }
  112. pub fn dup_to(&self, old_fd: FD, new_fd: FD, flags: OpenFlags) -> KResult<FD> {
  113. let fdflags = flags.as_fd_flags();
  114. let mut inner = self.inner.lock();
  115. let old_file = inner.files.get(&old_fd).ok_or(EBADF)?;
  116. let new_file_data = old_file.file.clone();
  117. match inner.files.entry(new_fd) {
  118. Entry::Vacant(_) => {}
  119. Entry::Occupied(entry) => {
  120. let new_file = entry.into_mut();
  121. let mut file_swap = new_file_data;
  122. new_file.flags = fdflags;
  123. core::mem::swap(&mut file_swap, &mut new_file.file);
  124. drop(inner);
  125. return Ok(new_fd);
  126. }
  127. }
  128. assert_eq!(new_fd, inner.allocate_fd(new_fd));
  129. inner.do_insert(new_fd, fdflags, new_file_data);
  130. Ok(new_fd)
  131. }
  132. /// # Return
  133. /// `(read_fd, write_fd)`
  134. pub fn pipe(&self, flags: OpenFlags) -> KResult<(FD, FD)> {
  135. let mut inner = self.inner.lock();
  136. let read_fd = inner.next_fd();
  137. let write_fd = inner.next_fd();
  138. let fdflag = flags.as_fd_flags();
  139. let (read_end, write_end) = Pipe::new(flags);
  140. inner.do_insert(read_fd, fdflag, read_end);
  141. inner.do_insert(write_fd, fdflag, write_end);
  142. Ok((read_fd, write_fd))
  143. }
  144. pub fn open(&self, dentry: &Arc<Dentry>, flags: OpenFlags, mode: Mode) -> KResult<FD> {
  145. dentry.open_check(flags, mode)?;
  146. let fdflag = flags.as_fd_flags();
  147. let inode = dentry.get_inode()?;
  148. let filemode = inode.mode.load(Ordering::Relaxed);
  149. if flags.directory() {
  150. if !s_isdir(filemode) {
  151. return Err(ENOTDIR);
  152. }
  153. } else {
  154. if s_isdir(filemode) && flags.write() {
  155. return Err(EISDIR);
  156. }
  157. }
  158. if flags.truncate() && flags.write() && s_isreg(filemode) {
  159. inode.truncate(0)?;
  160. }
  161. let file = if s_ischr(filemode) {
  162. let device = CharDevice::get(inode.devid()?).ok_or(ENXIO)?;
  163. device.open(flags)?
  164. } else {
  165. InodeFile::new(dentry.clone(), flags)
  166. };
  167. let mut inner = self.inner.lock();
  168. let fd = inner.next_fd();
  169. inner.do_insert(fd, fdflag, file);
  170. Ok(fd)
  171. }
  172. pub fn fcntl(&self, fd: FD, cmd: u32, arg: usize) -> KResult<usize> {
  173. let mut inner = self.inner.lock();
  174. let ofile = inner.files.get_mut(&fd).ok_or(EBADF)?;
  175. match cmd {
  176. F_DUPFD | F_DUPFD_CLOEXEC => {
  177. let cloexec = cmd == F_DUPFD_CLOEXEC || ofile.flags.close_on_exec();
  178. let flags = cloexec
  179. .then_some(FDFlags::FD_CLOEXEC)
  180. .unwrap_or(FDFlags::empty());
  181. let new_file_data = ofile.file.clone();
  182. let new_fd = inner.allocate_fd(FD(arg as u32));
  183. inner.do_insert(new_fd, flags, new_file_data);
  184. Ok(new_fd.0 as usize)
  185. }
  186. F_GETFD => Ok(ofile.flags.bits() as usize),
  187. F_SETFD => {
  188. ofile.flags = FDFlags::from_bits_truncate(arg as u32);
  189. Ok(0)
  190. }
  191. F_GETFL => Ok(ofile.file.get_flags().bits() as usize),
  192. F_SETFL => {
  193. ofile
  194. .file
  195. .set_flags(OpenFlags::from_bits_retain(arg as u32));
  196. Ok(0)
  197. }
  198. _ => unimplemented!("fcntl: cmd={}", cmd),
  199. }
  200. }
  201. /// Only used for init process.
  202. pub fn open_console(&self) {
  203. let mut inner = self.inner.lock();
  204. let (stdin, stdout, stderr) = (inner.next_fd(), inner.next_fd(), inner.next_fd());
  205. let console_terminal = get_console().expect("No console terminal");
  206. inner.do_insert(
  207. stdin,
  208. FDFlags::FD_CLOEXEC,
  209. TerminalFile::new(console_terminal.clone(), OpenFlags::empty()),
  210. );
  211. inner.do_insert(
  212. stdout,
  213. FDFlags::FD_CLOEXEC,
  214. TerminalFile::new(console_terminal.clone(), OpenFlags::empty()),
  215. );
  216. inner.do_insert(
  217. stderr,
  218. FDFlags::FD_CLOEXEC,
  219. TerminalFile::new(console_terminal.clone(), OpenFlags::empty()),
  220. );
  221. }
  222. }
  223. impl FileArrayInner {
  224. fn get(&mut self, fd: FD) -> Option<Arc<File>> {
  225. self.files.get(&fd).map(|f| f.file.clone())
  226. }
  227. fn find_available(&mut self, from: FD) -> FD {
  228. self.files
  229. .range(&from..)
  230. .fold_while(from, |current, (&key, _)| {
  231. if current == key {
  232. Continue(FD(current.0 + 1))
  233. } else {
  234. Done(current)
  235. }
  236. })
  237. .into_inner()
  238. }
  239. /// Allocate a new file descriptor starting from `from`.
  240. ///
  241. /// Returned file descriptor should be used immediately.
  242. ///
  243. fn allocate_fd(&mut self, from: FD) -> FD {
  244. let from = FD::max(from, self.fd_min_avail);
  245. if from == self.fd_min_avail {
  246. let next_min_avail = self.find_available(FD(from.0 + 1));
  247. let allocated = self.fd_min_avail;
  248. self.fd_min_avail = next_min_avail;
  249. allocated
  250. } else {
  251. self.find_available(from)
  252. }
  253. }
  254. fn release_fd(&mut self, fd: FD) {
  255. if fd < self.fd_min_avail {
  256. self.fd_min_avail = fd;
  257. }
  258. }
  259. fn next_fd(&mut self) -> FD {
  260. self.allocate_fd(self.fd_min_avail)
  261. }
  262. /// Insert a file description to the file array.
  263. fn do_insert(&mut self, fd: FD, flags: FDFlags, file: Arc<File>) {
  264. assert!(self.files.insert(fd, OpenFile { flags, file }).is_none());
  265. }
  266. }
  267. impl FD {
  268. pub const AT_FDCWD: FD = FD(-100i32 as u32);
  269. }
  270. impl core::fmt::Debug for FD {
  271. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  272. match self {
  273. &Self::AT_FDCWD => f.write_str("FD(AT_FDCWD)"),
  274. FD(no) => f.debug_tuple("FD").field(&no).finish(),
  275. }
  276. }
  277. }
  278. impl FromSyscallArg for FD {
  279. fn from_arg(value: usize) -> Self {
  280. Self(value as u32)
  281. }
  282. }
  283. impl SyscallRetVal for FD {
  284. fn into_retval(self) -> Option<usize> {
  285. Some(self.0 as usize)
  286. }
  287. }