file.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. use super::{
  2. dentry::Dentry,
  3. inode::{Mode, WriteOffset},
  4. s_isblk, s_isdir, s_isreg,
  5. };
  6. use crate::{
  7. io::{Buffer, BufferFill, ByteBuffer, Chunks, IntoStream},
  8. kernel::{
  9. constants::{TCGETS, TCSETS, TIOCGPGRP, TIOCGWINSZ, TIOCSPGRP},
  10. mem::{paging::Page, AsMemoryBlock as _},
  11. task::Thread,
  12. terminal::{Terminal, TerminalIORequest},
  13. user::{UserPointer, UserPointerMut},
  14. CharDevice,
  15. },
  16. prelude::*,
  17. sync::CondVar,
  18. };
  19. use crate::{
  20. io::{Stream, StreamRead},
  21. kernel::constants::{
  22. EBADF, EFAULT, EINTR, EINVAL, ENOTDIR, ENOTTY, EOVERFLOW, EPIPE, ESPIPE, S_IFMT,
  23. },
  24. };
  25. use alloc::{collections::vec_deque::VecDeque, sync::Arc};
  26. use bitflags::bitflags;
  27. use core::{ops::ControlFlow, sync::atomic::Ordering};
  28. use eonix_runtime::task::Task;
  29. use eonix_sync::Mutex;
  30. use posix_types::{signal::Signal, stat::StatX};
  31. pub struct InodeFile {
  32. read: bool,
  33. write: bool,
  34. append: bool,
  35. /// Only a few modes those won't possibly change are cached here to speed up file operations.
  36. /// Specifically, `S_IFMT` masked bits.
  37. mode: Mode,
  38. cursor: Mutex<usize>,
  39. dentry: Arc<Dentry>,
  40. }
  41. pub struct PipeInner {
  42. buffer: VecDeque<u8>,
  43. read_closed: bool,
  44. write_closed: bool,
  45. }
  46. pub struct Pipe {
  47. inner: Mutex<PipeInner>,
  48. cv_read: CondVar,
  49. cv_write: CondVar,
  50. }
  51. pub struct PipeReadEnd {
  52. pipe: Arc<Pipe>,
  53. }
  54. pub struct PipeWriteEnd {
  55. pipe: Arc<Pipe>,
  56. }
  57. pub struct TerminalFile {
  58. terminal: Arc<Terminal>,
  59. }
  60. // TODO: We should use `File` as the base type, instead of `Arc<File>`
  61. // If we need shared states, like for `InodeFile`, the files themselves should
  62. // have their own shared semantics. All `File` variants will just keep the
  63. // `Clone` semantics.
  64. //
  65. // e.g. The `CharDevice` itself is stateless.
  66. pub enum File {
  67. Inode(InodeFile),
  68. PipeRead(PipeReadEnd),
  69. PipeWrite(PipeWriteEnd),
  70. TTY(TerminalFile),
  71. CharDev(Arc<CharDevice>),
  72. }
  73. pub enum SeekOption {
  74. Set(usize),
  75. Current(isize),
  76. End(isize),
  77. }
  78. bitflags! {
  79. pub struct PollEvent: u16 {
  80. const Readable = 0x0001;
  81. }
  82. }
  83. impl Drop for PipeReadEnd {
  84. fn drop(&mut self) {
  85. self.pipe.close_read();
  86. }
  87. }
  88. impl Drop for PipeWriteEnd {
  89. fn drop(&mut self) {
  90. self.pipe.close_write();
  91. }
  92. }
  93. fn send_sigpipe_to_current() {
  94. let current = Thread::current();
  95. current.raise(Signal::SIGPIPE);
  96. }
  97. impl Pipe {
  98. const PIPE_SIZE: usize = 4096;
  99. pub fn new() -> Arc<Self> {
  100. Arc::new(Self {
  101. inner: Mutex::new(PipeInner {
  102. buffer: VecDeque::with_capacity(Self::PIPE_SIZE),
  103. read_closed: false,
  104. write_closed: false,
  105. }),
  106. cv_read: CondVar::new(),
  107. cv_write: CondVar::new(),
  108. })
  109. }
  110. /// # Return
  111. /// `(read_end, write_end)`
  112. pub fn split(self: &Arc<Self>) -> (Arc<File>, Arc<File>) {
  113. (
  114. Arc::new(File::PipeRead(PipeReadEnd { pipe: self.clone() })),
  115. Arc::new(File::PipeWrite(PipeWriteEnd { pipe: self.clone() })),
  116. )
  117. }
  118. fn close_read(&self) {
  119. let mut inner = Task::block_on(self.inner.lock());
  120. if inner.read_closed {
  121. return;
  122. }
  123. inner.read_closed = true;
  124. self.cv_write.notify_all();
  125. }
  126. fn close_write(&self) {
  127. let mut inner = Task::block_on(self.inner.lock());
  128. if inner.write_closed {
  129. return;
  130. }
  131. inner.write_closed = true;
  132. self.cv_read.notify_all();
  133. }
  134. async fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  135. let mut inner = self.inner.lock().await;
  136. while !inner.write_closed && inner.buffer.is_empty() {
  137. inner = self.cv_read.wait(inner).await;
  138. if Thread::current().signal_list.has_pending_signal() {
  139. return Err(EINTR);
  140. }
  141. }
  142. let (data1, data2) = inner.buffer.as_slices();
  143. let nread = buffer.fill(data1)?.allow_partial() + buffer.fill(data2)?.allow_partial();
  144. inner.buffer.drain(..nread);
  145. self.cv_write.notify_all();
  146. Ok(nread)
  147. }
  148. async fn write_atomic(&self, data: &[u8]) -> KResult<usize> {
  149. let mut inner = self.inner.lock().await;
  150. if inner.read_closed {
  151. send_sigpipe_to_current();
  152. return Err(EPIPE);
  153. }
  154. while inner.buffer.len() + data.len() > Self::PIPE_SIZE {
  155. inner = self.cv_write.wait(inner).await;
  156. if Thread::current().signal_list.has_pending_signal() {
  157. return Err(EINTR);
  158. }
  159. if inner.read_closed {
  160. send_sigpipe_to_current();
  161. return Err(EPIPE);
  162. }
  163. }
  164. inner.buffer.extend(data);
  165. self.cv_read.notify_all();
  166. return Ok(data.len());
  167. }
  168. async fn write(&self, stream: &mut dyn Stream) -> KResult<usize> {
  169. let mut buffer = [0; Self::PIPE_SIZE];
  170. let mut total = 0;
  171. while let Some(data) = stream.poll_data(&mut buffer)? {
  172. let nwrote = self.write_atomic(data).await?;
  173. total += nwrote;
  174. if nwrote != data.len() {
  175. break;
  176. }
  177. }
  178. Ok(total)
  179. }
  180. }
  181. #[derive(Copy, Clone, Debug)]
  182. #[repr(C, packed)]
  183. struct UserDirent64 {
  184. /// Inode number
  185. d_ino: u64,
  186. /// Implementation defined. We ignore it
  187. d_off: u64,
  188. /// Length of this record
  189. d_reclen: u16,
  190. /// File type. Set to 0
  191. d_type: u8,
  192. /// Filename with a padding '\0'
  193. d_name: [u8; 0],
  194. }
  195. /// File type is at offset `d_reclen - 1`. Set it to 0
  196. #[derive(Copy, Clone, Debug)]
  197. #[repr(C, packed)]
  198. struct UserDirent {
  199. /// Inode number
  200. d_ino: u32,
  201. /// Implementation defined. We ignore it
  202. d_off: u32,
  203. /// Length of this record
  204. d_reclen: u16,
  205. /// Filename with a padding '\0'
  206. d_name: [u8; 0],
  207. }
  208. impl InodeFile {
  209. pub fn new(dentry: Arc<Dentry>, rwa: (bool, bool, bool)) -> Arc<File> {
  210. // SAFETY: `dentry` used to create `InodeFile` is valid.
  211. // SAFETY: `mode` should never change with respect to the `S_IFMT` fields.
  212. let cached_mode = dentry
  213. .get_inode()
  214. .expect("`dentry` is invalid")
  215. .mode
  216. .load(Ordering::Relaxed)
  217. & S_IFMT;
  218. Arc::new(File::Inode(InodeFile {
  219. dentry,
  220. read: rwa.0,
  221. write: rwa.1,
  222. append: rwa.2,
  223. mode: cached_mode,
  224. cursor: Mutex::new(0),
  225. }))
  226. }
  227. fn seek(&self, option: SeekOption) -> KResult<usize> {
  228. let mut cursor = Task::block_on(self.cursor.lock());
  229. let new_cursor = match option {
  230. SeekOption::Current(off) => cursor.checked_add_signed(off).ok_or(EOVERFLOW)?,
  231. SeekOption::Set(n) => n,
  232. SeekOption::End(off) => {
  233. let inode = self.dentry.get_inode()?;
  234. let size = inode.size.load(Ordering::Relaxed) as usize;
  235. size.checked_add_signed(off).ok_or(EOVERFLOW)?
  236. }
  237. };
  238. *cursor = new_cursor;
  239. Ok(new_cursor)
  240. }
  241. fn write(&self, stream: &mut dyn Stream) -> KResult<usize> {
  242. if !self.write {
  243. return Err(EBADF);
  244. }
  245. let mut cursor = Task::block_on(self.cursor.lock());
  246. if self.append {
  247. let nwrote = self.dentry.write(stream, WriteOffset::End(&mut cursor))?;
  248. Ok(nwrote)
  249. } else {
  250. let nwrote = self.dentry.write(stream, WriteOffset::Position(*cursor))?;
  251. *cursor += nwrote;
  252. Ok(nwrote)
  253. }
  254. }
  255. fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  256. if !self.read {
  257. return Err(EBADF);
  258. }
  259. let mut cursor = Task::block_on(self.cursor.lock());
  260. let nread = self.dentry.read(buffer, *cursor)?;
  261. *cursor += nread;
  262. Ok(nread)
  263. }
  264. fn getdents64(&self, buffer: &mut dyn Buffer) -> KResult<()> {
  265. let mut cursor = Task::block_on(self.cursor.lock());
  266. let nread = self.dentry.readdir(*cursor, |filename, ino| {
  267. // Filename length + 1 for padding '\0'
  268. let real_record_len = core::mem::size_of::<UserDirent64>() + filename.len() + 1;
  269. if buffer.available() < real_record_len {
  270. return Ok(ControlFlow::Break(()));
  271. }
  272. let record = UserDirent64 {
  273. d_ino: ino,
  274. d_off: 0,
  275. d_reclen: real_record_len as u16,
  276. d_type: 0,
  277. d_name: [0; 0],
  278. };
  279. buffer.copy(&record)?.ok_or(EFAULT)?;
  280. buffer.fill(filename)?.ok_or(EFAULT)?;
  281. buffer.fill(&[0])?.ok_or(EFAULT)?;
  282. Ok(ControlFlow::Continue(()))
  283. })?;
  284. *cursor += nread;
  285. Ok(())
  286. }
  287. fn getdents(&self, buffer: &mut dyn Buffer) -> KResult<()> {
  288. let mut cursor = Task::block_on(self.cursor.lock());
  289. let nread = self.dentry.readdir(*cursor, |filename, ino| {
  290. // + 1 for filename length padding '\0', + 1 for d_type.
  291. let real_record_len = core::mem::size_of::<UserDirent>() + filename.len() + 2;
  292. if buffer.available() < real_record_len {
  293. return Ok(ControlFlow::Break(()));
  294. }
  295. let record = UserDirent {
  296. d_ino: ino as u32,
  297. d_off: 0,
  298. d_reclen: real_record_len as u16,
  299. d_name: [0; 0],
  300. };
  301. buffer.copy(&record)?.ok_or(EFAULT)?;
  302. buffer.fill(filename)?.ok_or(EFAULT)?;
  303. buffer.fill(&[0, 0])?.ok_or(EFAULT)?;
  304. Ok(ControlFlow::Continue(()))
  305. })?;
  306. *cursor += nread;
  307. Ok(())
  308. }
  309. }
  310. impl TerminalFile {
  311. pub fn new(tty: Arc<Terminal>) -> Arc<File> {
  312. Arc::new(File::TTY(TerminalFile { terminal: tty }))
  313. }
  314. async fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  315. self.terminal.read(buffer).await
  316. }
  317. fn write(&self, stream: &mut dyn Stream) -> KResult<usize> {
  318. stream.read_till_end(&mut [0; 128], |data| {
  319. self.terminal.write(data);
  320. Ok(())
  321. })
  322. }
  323. async fn poll(&self, event: PollEvent) -> KResult<PollEvent> {
  324. if !event.contains(PollEvent::Readable) {
  325. unimplemented!("Poll event not supported.")
  326. }
  327. self.terminal.poll_in().await.map(|_| PollEvent::Readable)
  328. }
  329. fn ioctl(&self, request: usize, arg3: usize) -> KResult<()> {
  330. Task::block_on(self.terminal.ioctl(match request as u32 {
  331. TCGETS => TerminalIORequest::GetTermios(UserPointerMut::new_vaddr(arg3)?),
  332. TCSETS => TerminalIORequest::SetTermios(UserPointer::new_vaddr(arg3)?),
  333. TIOCGPGRP => TerminalIORequest::GetProcessGroup(UserPointerMut::new_vaddr(arg3)?),
  334. TIOCSPGRP => TerminalIORequest::SetProcessGroup(UserPointer::new_vaddr(arg3)?),
  335. TIOCGWINSZ => TerminalIORequest::GetWindowSize(UserPointerMut::new_vaddr(arg3)?),
  336. _ => return Err(EINVAL),
  337. }))
  338. }
  339. }
  340. impl File {
  341. pub async fn read(&self, buffer: &mut dyn Buffer) -> KResult<usize> {
  342. match self {
  343. File::Inode(inode) => inode.read(buffer),
  344. File::PipeRead(pipe) => pipe.pipe.read(buffer).await,
  345. File::TTY(tty) => tty.read(buffer).await,
  346. File::CharDev(device) => device.read(buffer),
  347. _ => Err(EBADF),
  348. }
  349. }
  350. // TODO
  351. // /// Read from the file into the given buffers.
  352. // ///
  353. // /// Reads are atomic, not intermingled with other reads or writes.
  354. // pub fn readv<'r, 'i, I: Iterator<Item = &'i mut dyn Buffer>>(
  355. // &'r self,
  356. // buffers: I,
  357. // ) -> KResult<usize> {
  358. // match self {
  359. // File::Inode(inode) => inode.readv(buffers),
  360. // File::PipeRead(pipe) => pipe.pipe.readv(buffers),
  361. // _ => Err(EBADF),
  362. // }
  363. // }
  364. pub async fn write(&self, stream: &mut dyn Stream) -> KResult<usize> {
  365. match self {
  366. File::Inode(inode) => inode.write(stream),
  367. File::PipeWrite(pipe) => pipe.pipe.write(stream).await,
  368. File::TTY(tty) => tty.write(stream),
  369. File::CharDev(device) => device.write(stream),
  370. _ => Err(EBADF),
  371. }
  372. }
  373. pub fn seek(&self, option: SeekOption) -> KResult<usize> {
  374. match self {
  375. File::Inode(inode) => inode.seek(option),
  376. _ => Err(ESPIPE),
  377. }
  378. }
  379. pub fn getdents(&self, buffer: &mut dyn Buffer) -> KResult<()> {
  380. match self {
  381. File::Inode(inode) => inode.getdents(buffer),
  382. _ => Err(ENOTDIR),
  383. }
  384. }
  385. pub fn getdents64(&self, buffer: &mut dyn Buffer) -> KResult<()> {
  386. match self {
  387. File::Inode(inode) => inode.getdents64(buffer),
  388. _ => Err(ENOTDIR),
  389. }
  390. }
  391. pub async fn sendfile(&self, dest_file: &Self, count: usize) -> KResult<usize> {
  392. let buffer_page = Page::alloc();
  393. // SAFETY: We are the only owner of the page.
  394. let buffer = unsafe { buffer_page.as_memblk().as_bytes_mut() };
  395. match self {
  396. File::Inode(file) if s_isblk(file.mode) || s_isreg(file.mode) => (),
  397. _ => return Err(EINVAL),
  398. }
  399. let mut nsent = 0;
  400. for (cur, len) in Chunks::new(0, count, buffer.len()) {
  401. if Thread::current().signal_list.has_pending_signal() {
  402. return if cur == 0 { Err(EINTR) } else { Ok(cur) };
  403. }
  404. let nread = self.read(&mut ByteBuffer::new(&mut buffer[..len])).await?;
  405. if nread == 0 {
  406. break;
  407. }
  408. let nwrote = dest_file.write(&mut buffer[..nread].into_stream()).await?;
  409. nsent += nwrote;
  410. if nwrote != len {
  411. break;
  412. }
  413. }
  414. Ok(nsent)
  415. }
  416. pub fn ioctl(&self, request: usize, arg3: usize) -> KResult<usize> {
  417. match self {
  418. File::TTY(tty) => tty.ioctl(request, arg3).map(|_| 0),
  419. _ => Err(ENOTTY),
  420. }
  421. }
  422. pub async fn poll(&self, event: PollEvent) -> KResult<PollEvent> {
  423. match self {
  424. File::Inode(_) => Ok(event),
  425. File::TTY(tty) => tty.poll(event).await,
  426. _ => unimplemented!("Poll event not supported."),
  427. }
  428. }
  429. pub fn statx(&self, buffer: &mut StatX, mask: u32) -> KResult<()> {
  430. match self {
  431. File::Inode(inode) => inode.dentry.statx(buffer, mask),
  432. _ => Err(EBADF),
  433. }
  434. }
  435. pub fn as_path(&self) -> Option<&Arc<Dentry>> {
  436. match self {
  437. File::Inode(inode_file) if s_isdir(inode_file.mode) => Some(&inode_file.dentry),
  438. _ => None,
  439. }
  440. }
  441. }