file.rs 16 KB

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