file_rw.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. use core::mem::MaybeUninit;
  2. use bindings::{
  3. statx, AT_FDCWD, AT_STATX_SYNC_AS_STAT, AT_STATX_SYNC_TYPE, AT_SYMLINK_NOFOLLOW, EBADF, EFAULT,
  4. EINVAL, ENOENT, SEEK_CUR, SEEK_END, SEEK_SET, S_IFBLK, S_IFCHR,
  5. };
  6. use eonix_runtime::task::Task;
  7. use crate::{
  8. io::{Buffer, BufferFill},
  9. kernel::{
  10. constants::AT_EMPTY_PATH,
  11. task::Thread,
  12. user::{
  13. dataflow::{CheckedUserPointer, UserBuffer, UserString},
  14. UserPointer, UserPointerMut,
  15. },
  16. vfs::{
  17. dentry::Dentry,
  18. file::{PollEvent, SeekOption},
  19. filearray::FileArray,
  20. FsContext,
  21. },
  22. },
  23. path::Path,
  24. prelude::*,
  25. };
  26. use super::{define_syscall32, register_syscall};
  27. fn do_read(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  28. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  29. let files = FileArray::get_current();
  30. Task::block_on(files.get(fd).ok_or(EBADF)?.read(&mut buffer))
  31. }
  32. fn do_write(fd: u32, buffer: *const u8, count: usize) -> KResult<usize> {
  33. let data = unsafe { core::slice::from_raw_parts(buffer, count) };
  34. let files = FileArray::get_current();
  35. Task::block_on(files.get(fd).ok_or(EBADF)?.write(data))
  36. }
  37. fn do_open(path: *const u8, flags: u32, mode: u32) -> KResult<u32> {
  38. let path = UserString::new(path)?;
  39. let path = Path::new(path.as_cstr().to_bytes())?;
  40. let files = FileArray::get_current();
  41. let context = FsContext::get_current();
  42. let mode = mode & !*context.umask.lock();
  43. files.open(&context, path, flags, mode)
  44. }
  45. fn do_close(fd: u32) -> KResult<()> {
  46. let files = FileArray::get_current();
  47. files.close(fd)
  48. }
  49. fn do_dup(fd: u32) -> KResult<u32> {
  50. let files = FileArray::get_current();
  51. files.dup(fd)
  52. }
  53. fn do_dup2(old_fd: u32, new_fd: u32) -> KResult<u32> {
  54. let files = FileArray::get_current();
  55. files.dup_to(old_fd, new_fd, 0)
  56. }
  57. fn do_pipe2(pipe_fd: *mut [u32; 2], flags: u32) -> KResult<()> {
  58. let mut buffer = UserBuffer::new(pipe_fd as *mut u8, core::mem::size_of::<[u32; 2]>())?;
  59. let files = FileArray::get_current();
  60. let (read_fd, write_fd) = files.pipe(flags)?;
  61. buffer.copy(&[read_fd, write_fd])?.ok_or(EFAULT)
  62. }
  63. fn do_pipe(pipe_fd: *mut [u32; 2]) -> KResult<()> {
  64. do_pipe2(pipe_fd, 0)
  65. }
  66. fn do_getdents(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  67. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  68. let files = FileArray::get_current();
  69. files.get(fd).ok_or(EBADF)?.getdents(&mut buffer)?;
  70. Ok(buffer.wrote())
  71. }
  72. fn do_getdents64(fd: u32, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  73. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  74. let files = FileArray::get_current();
  75. files.get(fd).ok_or(EBADF)?.getdents64(&mut buffer)?;
  76. Ok(buffer.wrote())
  77. }
  78. fn do_statx(dirfd: u32, path: *const u8, flags: u32, mask: u32, buffer: *mut u8) -> KResult<()> {
  79. if (flags & AT_STATX_SYNC_TYPE) != AT_STATX_SYNC_AS_STAT {
  80. unimplemented!("AT_STATX_SYNC_TYPE={:x}", flags & AT_STATX_SYNC_TYPE);
  81. }
  82. let mut stat: statx = unsafe { MaybeUninit::zeroed().assume_init() };
  83. let mut buffer = UserBuffer::new(buffer, core::mem::size_of::<statx>())?;
  84. if (flags & AT_EMPTY_PATH) != 0 {
  85. let file = FileArray::get_current().get(dirfd).ok_or(EBADF)?;
  86. file.statx(&mut stat, mask)?;
  87. } else {
  88. let path = UserString::new(path)?;
  89. let path = Path::new(path.as_cstr().to_bytes())?;
  90. let file;
  91. if dirfd != AT_FDCWD as u32 && !path.is_absolute() {
  92. let at = FileArray::get_current().get(dirfd).ok_or(EBADF)?;
  93. file = Dentry::open_at(
  94. &FsContext::get_current(),
  95. at.as_path().ok_or(EBADF)?,
  96. path,
  97. (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW,
  98. )?;
  99. } else {
  100. file = Dentry::open(
  101. &FsContext::get_current(),
  102. path,
  103. (flags & AT_SYMLINK_NOFOLLOW) != AT_SYMLINK_NOFOLLOW,
  104. )?;
  105. }
  106. file.statx(&mut stat, mask)?;
  107. }
  108. buffer.copy(&stat)?.ok_or(EFAULT)
  109. }
  110. fn do_mkdir(pathname: *const u8, mode: u32) -> KResult<()> {
  111. let path = UserString::new(pathname)?;
  112. let path = Path::new(path.as_cstr().to_bytes())?;
  113. let context = FsContext::get_current();
  114. let mode = mode & !*context.umask.lock() & 0o777;
  115. let dentry = Dentry::open(&context, path, true)?;
  116. dentry.mkdir(mode)
  117. }
  118. fn do_truncate(pathname: *const u8, length: usize) -> KResult<()> {
  119. let path = UserString::new(pathname)?;
  120. let path = Path::new(path.as_cstr().to_bytes())?;
  121. let dentry = Dentry::open(&FsContext::get_current(), path, true)?;
  122. dentry.truncate(length)
  123. }
  124. fn do_unlink(pathname: *const u8) -> KResult<()> {
  125. let path = UserString::new(pathname)?;
  126. let path = Path::new(path.as_cstr().to_bytes())?;
  127. let dentry = Dentry::open(&FsContext::get_current(), path, false)?;
  128. dentry.unlink()
  129. }
  130. fn do_symlink(target: *const u8, linkpath: *const u8) -> KResult<()> {
  131. let target = UserString::new(target)?;
  132. let linkpath = UserString::new(linkpath)?;
  133. let linkpath = Path::new(linkpath.as_cstr().to_bytes())?;
  134. let dentry = Dentry::open(&FsContext::get_current(), linkpath, false)?;
  135. dentry.symlink(target.as_cstr().to_bytes())
  136. }
  137. fn do_mknod(pathname: *const u8, mode: u32, dev: u32) -> KResult<()> {
  138. let path = UserString::new(pathname)?;
  139. let path = Path::new(path.as_cstr().to_bytes())?;
  140. let context = FsContext::get_current();
  141. let mode = mode & ((!*context.umask.lock() & 0o777) | (S_IFBLK | S_IFCHR));
  142. let dentry = Dentry::open(&context, path, true)?;
  143. dentry.mknod(mode, dev)
  144. }
  145. fn do_readlink(pathname: *const u8, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  146. let path = UserString::new(pathname)?;
  147. let path = Path::new(path.as_cstr().to_bytes())?;
  148. let dentry = Dentry::open(&FsContext::get_current(), path, false)?;
  149. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  150. dentry.readlink(&mut buffer)
  151. }
  152. fn do_llseek(
  153. fd: u32,
  154. offset_high: u32,
  155. offset_low: u32,
  156. result: *mut u64,
  157. whence: u32,
  158. ) -> KResult<()> {
  159. let mut result = UserBuffer::new(result as *mut u8, core::mem::size_of::<u64>())?;
  160. let files = FileArray::get_current();
  161. let file = files.get(fd).ok_or(EBADF)?;
  162. let offset = ((offset_high as u64) << 32) | offset_low as u64;
  163. let new_offset = match whence {
  164. SEEK_SET => file.seek(SeekOption::Set(offset as usize))?,
  165. SEEK_CUR => file.seek(SeekOption::Current(offset as isize))?,
  166. SEEK_END => file.seek(SeekOption::End(offset as isize))?,
  167. _ => return Err(EINVAL),
  168. } as u64;
  169. result.copy(&new_offset)?.ok_or(EFAULT)
  170. }
  171. #[repr(C)]
  172. #[derive(Default, Clone, Copy)]
  173. struct IoVec32 {
  174. base: u32,
  175. len: u32,
  176. }
  177. fn do_readv(fd: u32, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
  178. let files = FileArray::get_current();
  179. let file = files.get(fd).ok_or(EBADF)?;
  180. let mut iov_user = UserPointer::new(iov_user as *mut IoVec32)?;
  181. let iov_buffers = (0..iovcnt)
  182. .map(|_| {
  183. let iov_result = iov_user.read()?;
  184. iov_user = iov_user.offset(1)?;
  185. Ok(iov_result)
  186. })
  187. .filter_map(|iov_result| match iov_result {
  188. Err(err) => Some(Err(err)),
  189. Ok(IoVec32 { len: 0, .. }) => None,
  190. Ok(IoVec32 { base, len }) => Some(UserBuffer::new(base as *mut u8, len as usize)),
  191. })
  192. .collect::<KResult<Vec<_>>>()?;
  193. let mut tot = 0usize;
  194. for mut buffer in iov_buffers.into_iter() {
  195. // TODO!!!: `readv`
  196. let nread = Task::block_on(file.read(&mut buffer))?;
  197. tot += nread;
  198. if nread != buffer.total() {
  199. break;
  200. }
  201. }
  202. Ok(tot)
  203. }
  204. fn do_writev(fd: u32, iov_user: *const u8, iovcnt: u32) -> KResult<usize> {
  205. let files = FileArray::get_current();
  206. let file = files.get(fd).ok_or(EBADF)?;
  207. // TODO: Rewrite this with `UserPointer`.
  208. let iov_user =
  209. CheckedUserPointer::new(iov_user, iovcnt as usize * core::mem::size_of::<IoVec32>())?;
  210. let mut iov_user_copied: Vec<IoVec32> = vec![];
  211. iov_user_copied.resize(iovcnt as usize, IoVec32::default());
  212. iov_user.read(
  213. iov_user_copied.as_mut_ptr() as *mut (),
  214. iov_user_copied.len() * core::mem::size_of::<IoVec32>(),
  215. )?;
  216. let iov_blocks = iov_user_copied
  217. .into_iter()
  218. .filter(|iov| iov.len != 0)
  219. .map(|iov| CheckedUserPointer::new(iov.base as *mut u8, iov.len as usize))
  220. .collect::<KResult<Vec<_>>>()?;
  221. let mut tot = 0usize;
  222. for block in iov_blocks.into_iter() {
  223. // TODO!!!: atomic `writev`
  224. // TODO!!!!!: copy from user
  225. let slice = block.as_slice();
  226. let nread = Task::block_on(file.write(slice))?;
  227. tot += nread;
  228. if nread == 0 || nread != slice.len() {
  229. break;
  230. }
  231. }
  232. Ok(tot)
  233. }
  234. fn do_access(pathname: *const u8, _mode: u32) -> KResult<()> {
  235. let path = UserString::new(pathname)?;
  236. let path = Path::new(path.as_cstr().to_bytes())?;
  237. let dentry = Dentry::open(&FsContext::get_current(), path, true)?;
  238. if !dentry.is_valid() {
  239. return Err(ENOENT);
  240. }
  241. // TODO: check permission
  242. // match mode {
  243. // F_OK => todo!(),
  244. // R_OK => todo!(),
  245. // W_OK => todo!(),
  246. // X_OK => todo!(),
  247. // _ => Err(EINVAL),
  248. // }
  249. Ok(())
  250. }
  251. fn do_sendfile64(out_fd: u32, in_fd: u32, offset: *mut u8, count: usize) -> KResult<usize> {
  252. let files = FileArray::get_current();
  253. let in_file = files.get(in_fd).ok_or(EBADF)?;
  254. let out_file = files.get(out_fd).ok_or(EBADF)?;
  255. if !offset.is_null() {
  256. unimplemented!("sendfile64 with offset");
  257. }
  258. Task::block_on(in_file.sendfile(&out_file, count))
  259. }
  260. fn do_ioctl(fd: u32, request: usize, arg3: usize) -> KResult<usize> {
  261. let files = FileArray::get_current();
  262. let file = files.get(fd).ok_or(EBADF)?;
  263. file.ioctl(request, arg3)
  264. }
  265. fn do_fcntl64(fd: u32, cmd: u32, arg: usize) -> KResult<usize> {
  266. FileArray::get_current().fcntl(fd, cmd, arg)
  267. }
  268. #[repr(C)]
  269. #[derive(Debug, Clone, Copy)]
  270. struct UserPollFd {
  271. fd: u32,
  272. events: u16,
  273. revents: u16,
  274. }
  275. fn do_poll(fds: *mut UserPollFd, nfds: u32, _timeout: u32) -> KResult<u32> {
  276. match nfds {
  277. 0 => Ok(0),
  278. 2.. => unimplemented!("Poll with {} fds", nfds),
  279. 1 => {
  280. // TODO!!: Poll with timeout
  281. // if timeout != u32::MAX {
  282. // unimplemented!("Poll with timeout {}", timeout);
  283. // }
  284. let fds = UserPointerMut::new(fds)?;
  285. let mut fd = fds.read()?;
  286. let file = Thread::current().files.get(fd.fd).ok_or(EBADF)?;
  287. fd.revents = Task::block_on(file.poll(PollEvent::from_bits_retain(fd.events)))?.bits();
  288. fds.write(fd)?;
  289. Ok(1)
  290. }
  291. }
  292. }
  293. define_syscall32!(sys_read, do_read, fd: u32, buffer: *mut u8, bufsize: usize);
  294. define_syscall32!(sys_write, do_write, fd: u32, buffer: *const u8, count: usize);
  295. define_syscall32!(sys_open, do_open, path: *const u8, flags: u32, mode: u32);
  296. define_syscall32!(sys_close, do_close, fd: u32);
  297. define_syscall32!(sys_dup, do_dup, fd: u32);
  298. define_syscall32!(sys_dup2, do_dup2, old_fd: u32, new_fd: u32);
  299. define_syscall32!(sys_pipe, do_pipe, pipe_fd: *mut [u32; 2]);
  300. define_syscall32!(sys_pipe2, do_pipe2, pipe_fd: *mut [u32; 2], flags: u32);
  301. define_syscall32!(sys_getdents, do_getdents, fd: u32, buffer: *mut u8, bufsize: usize);
  302. define_syscall32!(sys_getdents64, do_getdents64, fd: u32, buffer: *mut u8, bufsize: usize);
  303. define_syscall32!(sys_statx, do_statx, fd: u32, path: *const u8, flags: u32, mask: u32, buffer: *mut u8);
  304. define_syscall32!(sys_mkdir, do_mkdir, pathname: *const u8, mode: u32);
  305. define_syscall32!(sys_truncate, do_truncate, pathname: *const u8, length: usize);
  306. define_syscall32!(sys_unlink, do_unlink, pathname: *const u8);
  307. define_syscall32!(sys_symlink, do_symlink, target: *const u8, linkpath: *const u8);
  308. define_syscall32!(sys_readlink, do_readlink, pathname: *const u8, buffer: *mut u8, bufsize: usize);
  309. define_syscall32!(sys_llseek, do_llseek, fd: u32, offset_high: u32, offset_low: u32, result: *mut u64, whence: u32);
  310. define_syscall32!(sys_mknod, do_mknod, pathname: *const u8, mode: u32, dev: u32);
  311. define_syscall32!(sys_readv, do_readv, fd: u32, iov_user: *const IoVec32, iovcnt: u32);
  312. define_syscall32!(sys_writev, do_writev, fd: u32, iov_user: *const u8, iovcnt: u32);
  313. define_syscall32!(sys_access, do_access, pathname: *const u8, mode: u32);
  314. define_syscall32!(sys_sendfile64, do_sendfile64, out_fd: u32, in_fd: u32, offset: *mut u8, count: usize);
  315. define_syscall32!(sys_ioctl, do_ioctl, fd: u32, request: usize, arg3: usize);
  316. define_syscall32!(sys_fcntl64, do_fcntl64, fd: u32, cmd: u32, arg: usize);
  317. define_syscall32!(sys_poll, do_poll, fds: *mut UserPollFd, nfds: u32, timeout: u32);
  318. pub(super) fn register() {
  319. register_syscall!(0x03, read);
  320. register_syscall!(0x04, write);
  321. register_syscall!(0x05, open);
  322. register_syscall!(0x06, close);
  323. register_syscall!(0x0a, unlink);
  324. register_syscall!(0x0e, mknod);
  325. register_syscall!(0x21, access);
  326. register_syscall!(0x27, mkdir);
  327. register_syscall!(0x29, dup);
  328. register_syscall!(0x2a, pipe);
  329. register_syscall!(0x36, ioctl);
  330. register_syscall!(0x3f, dup2);
  331. register_syscall!(0x53, symlink);
  332. register_syscall!(0x55, readlink);
  333. register_syscall!(0x5c, truncate);
  334. register_syscall!(0x8c, llseek);
  335. register_syscall!(0x8d, getdents);
  336. register_syscall!(0x91, readv);
  337. register_syscall!(0x92, writev);
  338. register_syscall!(0xa8, poll);
  339. register_syscall!(0xdc, getdents64);
  340. register_syscall!(0xdd, fcntl64);
  341. register_syscall!(0xef, sendfile64);
  342. register_syscall!(0x14b, pipe2);
  343. register_syscall!(0x17f, statx);
  344. }