file_rw.rs 11 KB

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