filearray.rs 8.7 KB

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