file_rw.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. use super::FromSyscallArg;
  2. use crate::io::IntoStream;
  3. use crate::kernel::constants::{
  4. EBADF, EFAULT, EINVAL, ENOENT, ENOTDIR, SEEK_CUR, SEEK_END, SEEK_SET, S_IFBLK, S_IFCHR,
  5. };
  6. use crate::kernel::task::Thread;
  7. use crate::kernel::vfs::filearray::FD;
  8. use crate::{
  9. io::{Buffer, BufferFill},
  10. kernel::{
  11. user::{
  12. dataflow::{CheckedUserPointer, UserBuffer, UserString},
  13. UserPointer, UserPointerMut,
  14. },
  15. vfs::{
  16. dentry::Dentry,
  17. file::{PollEvent, SeekOption},
  18. },
  19. },
  20. path::Path,
  21. prelude::*,
  22. };
  23. use alloc::sync::Arc;
  24. use eonix_runtime::task::Task;
  25. use posix_types::ctypes::{Long, PtrT};
  26. use posix_types::open::{AtFlags, OpenFlags};
  27. use posix_types::signal::SigSet;
  28. use posix_types::stat::{StatX, TimeSpec};
  29. use posix_types::syscall_no::*;
  30. #[cfg(not(target_arch = "x86_64"))]
  31. use posix_types::stat::Stat;
  32. impl FromSyscallArg for OpenFlags {
  33. fn from_arg(value: usize) -> Self {
  34. OpenFlags::from_bits_retain(value as u32)
  35. }
  36. }
  37. impl FromSyscallArg for AtFlags {
  38. fn from_arg(value: usize) -> Self {
  39. AtFlags::from_bits_retain(value as u32)
  40. }
  41. }
  42. fn dentry_from(
  43. thread: &Thread,
  44. dirfd: FD,
  45. pathname: *const u8,
  46. follow_symlink: bool,
  47. ) -> KResult<Arc<Dentry>> {
  48. let path = UserString::new(pathname)?;
  49. match (path.as_cstr().to_bytes_with_nul()[0], dirfd) {
  50. (b'/', _) | (_, FD::AT_FDCWD) => {
  51. let path = Path::new(path.as_cstr().to_bytes())?;
  52. Dentry::open(&thread.fs_context, path, follow_symlink)
  53. }
  54. (0, dirfd) => {
  55. let dir_file = thread.files.get(dirfd).ok_or(EBADF)?;
  56. dir_file.as_path().ok_or(EBADF).cloned()
  57. }
  58. (_, dirfd) => {
  59. let path = Path::new(path.as_cstr().to_bytes())?;
  60. let dir_file = thread.files.get(dirfd).ok_or(EBADF)?;
  61. let dir_dentry = dir_file.as_path().ok_or(ENOTDIR)?;
  62. Dentry::open_at(&thread.fs_context, dir_dentry, path, follow_symlink)
  63. }
  64. }
  65. }
  66. #[eonix_macros::define_syscall(SYS_READ)]
  67. fn read(fd: FD, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  68. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  69. Task::block_on(thread.files.get(fd).ok_or(EBADF)?.read(&mut buffer))
  70. }
  71. #[eonix_macros::define_syscall(SYS_WRITE)]
  72. fn write(fd: FD, buffer: *const u8, count: usize) -> KResult<usize> {
  73. let buffer = CheckedUserPointer::new(buffer, count)?;
  74. let mut stream = buffer.into_stream();
  75. Task::block_on(thread.files.get(fd).ok_or(EBADF)?.write(&mut stream))
  76. }
  77. #[eonix_macros::define_syscall(SYS_OPENAT)]
  78. fn openat(dirfd: FD, pathname: *const u8, flags: OpenFlags, mode: u32) -> KResult<FD> {
  79. let dentry = dentry_from(thread, dirfd, pathname, flags.follow_symlink())?;
  80. thread.files.open(&dentry, flags, mode)
  81. }
  82. #[cfg(target_arch = "x86_64")]
  83. #[eonix_macros::define_syscall(SYS_OPEN)]
  84. fn open(path: *const u8, flags: OpenFlags, mode: u32) -> KResult<FD> {
  85. sys_openat(thread, FD::AT_FDCWD, path, flags, mode)
  86. }
  87. #[eonix_macros::define_syscall(SYS_CLOSE)]
  88. fn close(fd: FD) -> KResult<()> {
  89. thread.files.close(fd)
  90. }
  91. #[eonix_macros::define_syscall(SYS_DUP)]
  92. fn dup(fd: FD) -> KResult<FD> {
  93. thread.files.dup(fd)
  94. }
  95. #[cfg(target_arch = "x86_64")]
  96. #[eonix_macros::define_syscall(SYS_DUP2)]
  97. fn dup2(old_fd: FD, new_fd: FD) -> KResult<FD> {
  98. thread.files.dup_to(old_fd, new_fd, OpenFlags::empty())
  99. }
  100. #[eonix_macros::define_syscall(SYS_DUP3)]
  101. fn dup3(old_fd: FD, new_fd: FD, flags: OpenFlags) -> KResult<FD> {
  102. thread.files.dup_to(old_fd, new_fd, flags)
  103. }
  104. #[eonix_macros::define_syscall(SYS_PIPE2)]
  105. fn pipe2(pipe_fd: *mut [FD; 2], flags: OpenFlags) -> KResult<()> {
  106. let mut buffer = UserBuffer::new(pipe_fd as *mut u8, core::mem::size_of::<[FD; 2]>())?;
  107. let (read_fd, write_fd) = thread.files.pipe(flags)?;
  108. buffer.copy(&[read_fd, write_fd])?.ok_or(EFAULT)
  109. }
  110. #[cfg(target_arch = "x86_64")]
  111. #[eonix_macros::define_syscall(SYS_PIPE)]
  112. fn pipe(pipe_fd: *mut [FD; 2]) -> KResult<()> {
  113. sys_pipe2(thread, pipe_fd, OpenFlags::empty())
  114. }
  115. #[cfg(target_arch = "x86_64")]
  116. #[eonix_macros::define_syscall(SYS_GETDENTS)]
  117. fn getdents(fd: FD, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  118. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  119. thread.files.get(fd).ok_or(EBADF)?.getdents(&mut buffer)?;
  120. Ok(buffer.wrote())
  121. }
  122. #[eonix_macros::define_syscall(SYS_GETDENTS64)]
  123. fn getdents64(fd: FD, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  124. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  125. thread.files.get(fd).ok_or(EBADF)?.getdents64(&mut buffer)?;
  126. Ok(buffer.wrote())
  127. }
  128. #[cfg(not(target_arch = "x86_64"))]
  129. #[eonix_macros::define_syscall(SYS_NEWFSTATAT)]
  130. fn newfstatat(dirfd: FD, pathname: *const u8, statbuf: *mut Stat, flags: AtFlags) -> KResult<()> {
  131. let dentry = if flags.at_empty_path() {
  132. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  133. file.as_path().ok_or(EBADF)?.clone()
  134. } else {
  135. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  136. };
  137. let statbuf = UserPointerMut::new(statbuf)?;
  138. let mut statx = StatX::default();
  139. dentry.statx(&mut statx, u32::MAX)?;
  140. statbuf.write(statx.into())?;
  141. Ok(())
  142. }
  143. #[eonix_macros::define_syscall(SYS_STATX)]
  144. fn statx(
  145. dirfd: FD,
  146. pathname: *const u8,
  147. flags: AtFlags,
  148. mask: u32,
  149. buffer: *mut StatX,
  150. ) -> KResult<()> {
  151. if !flags.statx_default_sync() {
  152. unimplemented!("statx with no default sync flags: {:?}", flags);
  153. }
  154. let mut statx = StatX::default();
  155. let buffer = UserPointerMut::new(buffer)?;
  156. let dentry = if flags.at_empty_path() {
  157. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  158. file.as_path().ok_or(EBADF)?.clone()
  159. } else {
  160. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  161. };
  162. dentry.statx(&mut statx, mask)?;
  163. buffer.write(statx)?;
  164. Ok(())
  165. }
  166. #[eonix_macros::define_syscall(SYS_MKDIRAT)]
  167. fn mkdirat(dirfd: FD, pathname: *const u8, mode: u32) -> KResult<()> {
  168. let umask = *thread.fs_context.umask.lock();
  169. let mode = mode & !umask & 0o777;
  170. let dentry = dentry_from(thread, dirfd, pathname, true)?;
  171. dentry.mkdir(mode)
  172. }
  173. #[cfg(target_arch = "x86_64")]
  174. #[eonix_macros::define_syscall(SYS_MKDIR)]
  175. fn mkdir(pathname: *const u8, mode: u32) -> KResult<()> {
  176. sys_mkdirat(thread, FD::AT_FDCWD, pathname, mode)
  177. }
  178. #[cfg(target_arch = "x86_64")]
  179. #[eonix_macros::define_syscall(SYS_TRUNCATE)]
  180. fn truncate(pathname: *const u8, length: usize) -> KResult<()> {
  181. let path = UserString::new(pathname)?;
  182. let path = Path::new(path.as_cstr().to_bytes())?;
  183. let dentry = Dentry::open(&thread.fs_context, path, true)?;
  184. dentry.truncate(length)
  185. }
  186. #[eonix_macros::define_syscall(SYS_UNLINKAT)]
  187. fn unlinkat(dirfd: FD, pathname: *const u8) -> KResult<()> {
  188. dentry_from(thread, dirfd, pathname, false)?.unlink()
  189. }
  190. #[cfg(target_arch = "x86_64")]
  191. #[eonix_macros::define_syscall(SYS_UNLINK)]
  192. fn unlink(pathname: *const u8) -> KResult<()> {
  193. sys_unlinkat(thread, FD::AT_FDCWD, pathname)
  194. }
  195. #[eonix_macros::define_syscall(SYS_SYMLINKAT)]
  196. fn symlinkat(target: *const u8, dirfd: FD, linkpath: *const u8) -> KResult<()> {
  197. let target = UserString::new(target)?;
  198. let dentry = dentry_from(thread, dirfd, linkpath, false)?;
  199. dentry.symlink(target.as_cstr().to_bytes())
  200. }
  201. #[cfg(target_arch = "x86_64")]
  202. #[eonix_macros::define_syscall(SYS_SYMLINK)]
  203. fn symlink(target: *const u8, linkpath: *const u8) -> KResult<()> {
  204. sys_symlinkat(thread, target, FD::AT_FDCWD, linkpath)
  205. }
  206. #[eonix_macros::define_syscall(SYS_MKNODAT)]
  207. fn mknodat(dirfd: FD, pathname: *const u8, mode: u32, dev: u32) -> KResult<()> {
  208. let dentry = dentry_from(thread, dirfd, pathname, true)?;
  209. let umask = *thread.fs_context.umask.lock();
  210. let mode = mode & ((!umask & 0o777) | (S_IFBLK | S_IFCHR));
  211. dentry.mknod(mode, dev)
  212. }
  213. #[cfg(target_arch = "x86_64")]
  214. #[eonix_macros::define_syscall(SYS_MKNOD)]
  215. fn mknod(pathname: *const u8, mode: u32, dev: u32) -> KResult<()> {
  216. sys_mknodat(thread, FD::AT_FDCWD, pathname, mode, dev)
  217. }
  218. #[eonix_macros::define_syscall(SYS_READLINKAT)]
  219. fn readlinkat(dirfd: FD, pathname: *const u8, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  220. let dentry = dentry_from(thread, dirfd, pathname, false)?;
  221. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  222. dentry.readlink(&mut buffer)
  223. }
  224. #[cfg(target_arch = "x86_64")]
  225. #[eonix_macros::define_syscall(SYS_READLINK)]
  226. fn readlink(pathname: *const u8, buffer: *mut u8, bufsize: usize) -> KResult<usize> {
  227. sys_readlinkat(thread, FD::AT_FDCWD, pathname, buffer, bufsize)
  228. }
  229. fn do_lseek(thread: &Thread, fd: FD, offset: u64, whence: u32) -> KResult<u64> {
  230. let file = thread.files.get(fd).ok_or(EBADF)?;
  231. Ok(match whence {
  232. SEEK_SET => file.seek(SeekOption::Set(offset as usize))?,
  233. SEEK_CUR => file.seek(SeekOption::Current(offset as isize))?,
  234. SEEK_END => file.seek(SeekOption::End(offset as isize))?,
  235. _ => return Err(EINVAL),
  236. } as u64)
  237. }
  238. #[cfg(not(target_arch = "x86_64"))]
  239. #[eonix_macros::define_syscall(SYS_LSEEK)]
  240. fn lseek(fd: FD, offset: u64, whence: u32) -> KResult<u64> {
  241. do_lseek(thread, fd, offset, whence)
  242. }
  243. #[cfg(target_arch = "x86_64")]
  244. #[eonix_macros::define_syscall(SYS_LLSEEK)]
  245. fn llseek(fd: FD, offset_high: u32, offset_low: u32, result: *mut u64, whence: u32) -> KResult<()> {
  246. let mut result = UserBuffer::new(result as *mut u8, core::mem::size_of::<u64>())?;
  247. let offset = ((offset_high as u64) << 32) | (offset_low as u64);
  248. let new_offset = do_lseek(thread, fd, offset, whence)?;
  249. result.copy(&new_offset)?.ok_or(EFAULT)
  250. }
  251. #[repr(C)]
  252. #[derive(Clone, Copy)]
  253. struct IoVec {
  254. base: PtrT,
  255. len: Long,
  256. }
  257. #[eonix_macros::define_syscall(SYS_READV)]
  258. fn readv(fd: FD, iov_user: *const IoVec, iovcnt: u32) -> KResult<usize> {
  259. let file = thread.files.get(fd).ok_or(EBADF)?;
  260. let mut iov_user = UserPointer::new(iov_user)?;
  261. let iov_buffers = (0..iovcnt)
  262. .map(|_| {
  263. let iov_result = iov_user.read()?;
  264. iov_user = iov_user.offset(1)?;
  265. Ok(iov_result)
  266. })
  267. .filter_map(|iov_result| match iov_result {
  268. Err(err) => Some(Err(err)),
  269. Ok(IoVec {
  270. len: Long::ZERO, ..
  271. }) => None,
  272. Ok(IoVec { base, len }) => Some(UserBuffer::new(base.addr() as *mut u8, len.get())),
  273. })
  274. .collect::<KResult<Vec<_>>>()?;
  275. let mut tot = 0usize;
  276. for mut buffer in iov_buffers.into_iter() {
  277. // TODO!!!: `readv`
  278. let nread = Task::block_on(file.read(&mut buffer))?;
  279. tot += nread;
  280. if nread != buffer.total() {
  281. break;
  282. }
  283. }
  284. Ok(tot)
  285. }
  286. #[eonix_macros::define_syscall(SYS_WRITEV)]
  287. fn writev(fd: FD, iov_user: *const IoVec, iovcnt: u32) -> KResult<usize> {
  288. let file = thread.files.get(fd).ok_or(EBADF)?;
  289. let mut iov_user = UserPointer::new(iov_user)?;
  290. let iov_streams = (0..iovcnt)
  291. .map(|_| {
  292. let iov_result = iov_user.read()?;
  293. iov_user = iov_user.offset(1)?;
  294. Ok(iov_result)
  295. })
  296. .filter_map(|iov_result| match iov_result {
  297. Err(err) => Some(Err(err)),
  298. Ok(IoVec {
  299. len: Long::ZERO, ..
  300. }) => None,
  301. Ok(IoVec { base, len }) => Some(
  302. CheckedUserPointer::new(base.addr() as *mut u8, len.get())
  303. .map(|ptr| ptr.into_stream()),
  304. ),
  305. })
  306. .collect::<KResult<Vec<_>>>()?;
  307. let mut tot = 0usize;
  308. for mut stream in iov_streams.into_iter() {
  309. let nread = Task::block_on(file.write(&mut stream))?;
  310. tot += nread;
  311. if nread == 0 || !stream.is_drained() {
  312. break;
  313. }
  314. }
  315. Ok(tot)
  316. }
  317. #[cfg(target_arch = "x86_64")]
  318. #[eonix_macros::define_syscall(SYS_ACCESS)]
  319. fn access(pathname: *const u8, _mode: u32) -> KResult<()> {
  320. let path = UserString::new(pathname)?;
  321. let path = Path::new(path.as_cstr().to_bytes())?;
  322. let dentry = Dentry::open(&thread.fs_context, path, true)?;
  323. if !dentry.is_valid() {
  324. return Err(ENOENT);
  325. }
  326. // TODO: check permission
  327. // match mode {
  328. // F_OK => todo!(),
  329. // R_OK => todo!(),
  330. // W_OK => todo!(),
  331. // X_OK => todo!(),
  332. // _ => Err(EINVAL),
  333. // }
  334. Ok(())
  335. }
  336. #[eonix_macros::define_syscall(SYS_SENDFILE64)]
  337. fn sendfile64(out_fd: FD, in_fd: FD, offset: *mut u8, count: usize) -> KResult<usize> {
  338. let in_file = thread.files.get(in_fd).ok_or(EBADF)?;
  339. let out_file = thread.files.get(out_fd).ok_or(EBADF)?;
  340. if !offset.is_null() {
  341. unimplemented!("sendfile64 with offset");
  342. }
  343. Task::block_on(in_file.sendfile(&out_file, count))
  344. }
  345. #[eonix_macros::define_syscall(SYS_IOCTL)]
  346. fn ioctl(fd: FD, request: usize, arg3: usize) -> KResult<usize> {
  347. let file = thread.files.get(fd).ok_or(EBADF)?;
  348. file.ioctl(request, arg3)
  349. }
  350. #[eonix_macros::define_syscall(SYS_FCNTL64)]
  351. fn fcntl64(fd: FD, cmd: u32, arg: usize) -> KResult<usize> {
  352. thread.files.fcntl(fd, cmd, arg)
  353. }
  354. #[repr(C)]
  355. #[derive(Debug, Clone, Copy)]
  356. struct UserPollFd {
  357. fd: FD,
  358. events: u16,
  359. revents: u16,
  360. }
  361. fn do_poll(thread: &Thread, fds: *mut UserPollFd, nfds: u32, _timeout: u32) -> KResult<u32> {
  362. match nfds {
  363. 0 => Ok(0),
  364. 2.. => unimplemented!("Poll with {} fds", nfds),
  365. 1 => {
  366. // TODO!!: Poll with timeout
  367. // if timeout != u32::MAX {
  368. // unimplemented!("Poll with timeout {}", timeout);
  369. // }
  370. let fds = UserPointerMut::new(fds)?;
  371. let mut fd = fds.read()?;
  372. let file = thread.files.get(fd.fd).ok_or(EBADF)?;
  373. fd.revents = Task::block_on(file.poll(PollEvent::from_bits_retain(fd.events)))?.bits();
  374. fds.write(fd)?;
  375. Ok(1)
  376. }
  377. }
  378. }
  379. #[eonix_macros::define_syscall(SYS_PPOLL)]
  380. fn ppoll(
  381. fds: *mut UserPollFd,
  382. nfds: u32,
  383. _timeout_ptr: *const TimeSpec,
  384. _sigmask: *const SigSet,
  385. ) -> KResult<u32> {
  386. // TODO: Implement ppoll with signal mask and timeout
  387. do_poll(thread, fds, nfds, 0)
  388. }
  389. #[cfg(target_arch = "x86_64")]
  390. #[eonix_macros::define_syscall(SYS_POLL)]
  391. fn poll(fds: *mut UserPollFd, nfds: u32, timeout: u32) -> KResult<u32> {
  392. do_poll(thread, fds, nfds, timeout)
  393. }
  394. #[eonix_macros::define_syscall(SYS_FCHOWNAT)]
  395. fn fchownat(dirfd: FD, pathname: *const u8, uid: u32, gid: u32, flags: AtFlags) -> KResult<()> {
  396. let dentry = dentry_from(thread, dirfd, pathname, !flags.no_follow())?;
  397. if !dentry.is_valid() {
  398. return Err(ENOENT);
  399. }
  400. dentry.chown(uid, gid)
  401. }
  402. #[eonix_macros::define_syscall(SYS_FCHMODAT)]
  403. fn fchmodat(dirfd: FD, pathname: *const u8, mode: u32, flags: AtFlags) -> KResult<()> {
  404. let dentry = if flags.at_empty_path() {
  405. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  406. file.as_path().ok_or(EBADF)?.clone()
  407. } else {
  408. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  409. };
  410. if !dentry.is_valid() {
  411. return Err(ENOENT);
  412. }
  413. dentry.chmod(mode)
  414. }
  415. #[eonix_macros::define_syscall(SYS_FCHMOD)]
  416. fn chmod(pathname: *const u8, mode: u32) -> KResult<()> {
  417. sys_fchmodat(thread, FD::AT_FDCWD, pathname, mode, AtFlags::empty())
  418. }
  419. #[eonix_macros::define_syscall(SYS_UTIMENSAT)]
  420. fn utimensat(
  421. dirfd: FD,
  422. pathname: *const u8,
  423. times: *const TimeSpec,
  424. flags: AtFlags,
  425. ) -> KResult<()> {
  426. let dentry = if flags.at_empty_path() {
  427. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  428. file.as_path().ok_or(EBADF)?.clone()
  429. } else {
  430. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  431. };
  432. if !dentry.is_valid() {
  433. return Err(ENOENT);
  434. }
  435. let _times = if times.is_null() {
  436. [TimeSpec::default(), TimeSpec::default()]
  437. } else {
  438. let times = UserPointer::new(times)?;
  439. [times.read()?, times.offset(1)?.read()?]
  440. };
  441. // TODO: Implement utimensat
  442. // dentry.utimens(&times)
  443. Ok(())
  444. }
  445. pub fn keep_alive() {}