file_rw.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. use super::{FromSyscallArg, User};
  2. use crate::io::IntoStream;
  3. use crate::kernel::constants::{
  4. EBADF, EFAULT, EINVAL, ENOENT, ENOSYS, ENOTDIR, SEEK_CUR, SEEK_END, SEEK_SET, S_IFBLK, S_IFCHR,
  5. };
  6. use crate::kernel::syscall::UserMut;
  7. use crate::kernel::task::Thread;
  8. use crate::kernel::timer::sleep;
  9. use crate::kernel::vfs::filearray::FD;
  10. use crate::{
  11. io::{Buffer, BufferFill},
  12. kernel::{
  13. user::{CheckedUserPointer, UserBuffer, UserPointer, UserPointerMut, UserString},
  14. vfs::{
  15. dentry::Dentry,
  16. file::{PollEvent, SeekOption},
  17. },
  18. },
  19. path::Path,
  20. prelude::*,
  21. };
  22. use alloc::sync::Arc;
  23. use core::time::Duration;
  24. use posix_types::ctypes::{Long, PtrT};
  25. use posix_types::namei::RenameFlags;
  26. use posix_types::open::{AtFlags, OpenFlags};
  27. use posix_types::poll::FDSet;
  28. use posix_types::signal::{SigSet, Signal};
  29. use posix_types::stat::Stat;
  30. use posix_types::stat::{StatX, TimeSpec};
  31. use posix_types::syscall_no::*;
  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: User<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. async fn read(fd: FD, buffer: UserMut<u8>, bufsize: usize) -> KResult<usize> {
  68. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  69. thread
  70. .files
  71. .get(fd)
  72. .ok_or(EBADF)?
  73. .read(&mut buffer, None)
  74. .await
  75. }
  76. #[eonix_macros::define_syscall(SYS_PREAD64)]
  77. async fn pread64(fd: FD, buffer: UserMut<u8>, bufsize: usize, offset: usize) -> KResult<usize> {
  78. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  79. thread
  80. .files
  81. .get(fd)
  82. .ok_or(EBADF)?
  83. .read(&mut buffer, Some(offset))
  84. .await
  85. }
  86. #[eonix_macros::define_syscall(SYS_WRITE)]
  87. async fn write(fd: FD, buffer: User<u8>, count: usize) -> KResult<usize> {
  88. let buffer = CheckedUserPointer::new(buffer, count)?;
  89. let mut stream = buffer.into_stream();
  90. thread
  91. .files
  92. .get(fd)
  93. .ok_or(EBADF)?
  94. .write(&mut stream, None)
  95. .await
  96. }
  97. #[eonix_macros::define_syscall(SYS_PWRITE64)]
  98. async fn pwrite64(fd: FD, buffer: User<u8>, count: usize, offset: usize) -> KResult<usize> {
  99. let buffer = CheckedUserPointer::new(buffer, count)?;
  100. let mut stream = buffer.into_stream();
  101. thread
  102. .files
  103. .get(fd)
  104. .ok_or(EBADF)?
  105. .write(&mut stream, Some(offset))
  106. .await
  107. }
  108. #[eonix_macros::define_syscall(SYS_OPENAT)]
  109. async fn openat(dirfd: FD, pathname: User<u8>, flags: OpenFlags, mode: u32) -> KResult<FD> {
  110. let dentry = dentry_from(thread, dirfd, pathname, flags.follow_symlink())?;
  111. thread.files.open(&dentry, flags, mode)
  112. }
  113. #[cfg(target_arch = "x86_64")]
  114. #[eonix_macros::define_syscall(SYS_OPEN)]
  115. async fn open(path: User<u8>, flags: OpenFlags, mode: u32) -> KResult<FD> {
  116. sys_openat(thread, FD::AT_FDCWD, path, flags, mode).await
  117. }
  118. #[eonix_macros::define_syscall(SYS_CLOSE)]
  119. async fn close(fd: FD) -> KResult<()> {
  120. thread.files.close(fd)
  121. }
  122. #[eonix_macros::define_syscall(SYS_DUP)]
  123. async fn dup(fd: FD) -> KResult<FD> {
  124. thread.files.dup(fd)
  125. }
  126. #[cfg(target_arch = "x86_64")]
  127. #[eonix_macros::define_syscall(SYS_DUP2)]
  128. async fn dup2(old_fd: FD, new_fd: FD) -> KResult<FD> {
  129. thread.files.dup_to(old_fd, new_fd, OpenFlags::empty())
  130. }
  131. #[eonix_macros::define_syscall(SYS_DUP3)]
  132. async fn dup3(old_fd: FD, new_fd: FD, flags: OpenFlags) -> KResult<FD> {
  133. thread.files.dup_to(old_fd, new_fd, flags)
  134. }
  135. #[eonix_macros::define_syscall(SYS_PIPE2)]
  136. async fn pipe2(pipe_fd: UserMut<[FD; 2]>, flags: OpenFlags) -> KResult<()> {
  137. let mut buffer = UserBuffer::new(pipe_fd.cast(), core::mem::size_of::<[FD; 2]>())?;
  138. let (read_fd, write_fd) = thread.files.pipe(flags)?;
  139. buffer.copy(&[read_fd, write_fd])?.ok_or(EFAULT)
  140. }
  141. #[cfg(target_arch = "x86_64")]
  142. #[eonix_macros::define_syscall(SYS_PIPE)]
  143. async fn pipe(pipe_fd: UserMut<[FD; 2]>) -> KResult<()> {
  144. sys_pipe2(thread, pipe_fd, OpenFlags::empty()).await
  145. }
  146. #[cfg(target_arch = "x86_64")]
  147. #[eonix_macros::define_syscall(SYS_GETDENTS)]
  148. async fn getdents(fd: FD, buffer: UserMut<u8>, bufsize: usize) -> KResult<usize> {
  149. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  150. thread.files.get(fd).ok_or(EBADF)?.getdents(&mut buffer)?;
  151. Ok(buffer.wrote())
  152. }
  153. #[eonix_macros::define_syscall(SYS_GETDENTS64)]
  154. async fn getdents64(fd: FD, buffer: UserMut<u8>, bufsize: usize) -> KResult<usize> {
  155. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  156. thread
  157. .files
  158. .get(fd)
  159. .ok_or(EBADF)?
  160. .getdents64(&mut buffer)
  161. .await?;
  162. Ok(buffer.wrote())
  163. }
  164. #[cfg_attr(
  165. not(target_arch = "x86_64"),
  166. eonix_macros::define_syscall(SYS_NEWFSTATAT)
  167. )]
  168. #[cfg_attr(target_arch = "x86_64", eonix_macros::define_syscall(SYS_FSTATAT64))]
  169. async fn newfstatat(
  170. dirfd: FD,
  171. pathname: User<u8>,
  172. statbuf: UserMut<Stat>,
  173. flags: AtFlags,
  174. ) -> KResult<()> {
  175. let dentry = if flags.at_empty_path() {
  176. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  177. file.as_path().ok_or(EBADF)?.clone()
  178. } else {
  179. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  180. };
  181. let statbuf = UserPointerMut::new(statbuf)?;
  182. let mut statx = StatX::default();
  183. dentry.statx(&mut statx, u32::MAX)?;
  184. statbuf.write(statx.into())?;
  185. Ok(())
  186. }
  187. #[cfg_attr(
  188. not(target_arch = "x86_64"),
  189. eonix_macros::define_syscall(SYS_NEWFSTAT)
  190. )]
  191. #[cfg_attr(target_arch = "x86_64", eonix_macros::define_syscall(SYS_FSTAT64))]
  192. async fn newfstat(fd: FD, statbuf: UserMut<Stat>) -> KResult<()> {
  193. sys_newfstatat(thread, fd, User::null(), statbuf, AtFlags::AT_EMPTY_PATH).await
  194. }
  195. #[eonix_macros::define_syscall(SYS_STATX)]
  196. async fn statx(
  197. dirfd: FD,
  198. pathname: User<u8>,
  199. flags: AtFlags,
  200. mask: u32,
  201. buffer: UserMut<StatX>,
  202. ) -> KResult<()> {
  203. if !flags.statx_default_sync() {
  204. unimplemented!("statx with no default sync flags: {:?}", flags);
  205. }
  206. let mut statx = StatX::default();
  207. let buffer = UserPointerMut::new(buffer)?;
  208. let dentry = if flags.at_empty_path() {
  209. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  210. file.as_path().ok_or(EBADF)?.clone()
  211. } else {
  212. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  213. };
  214. dentry.statx(&mut statx, mask)?;
  215. buffer.write(statx)?;
  216. Ok(())
  217. }
  218. #[eonix_macros::define_syscall(SYS_MKDIRAT)]
  219. async fn mkdirat(dirfd: FD, pathname: User<u8>, mode: u32) -> KResult<()> {
  220. let umask = *thread.fs_context.umask.lock();
  221. let mode = mode & !umask & 0o777;
  222. let dentry = dentry_from(thread, dirfd, pathname, true)?;
  223. dentry.mkdir(mode)
  224. }
  225. #[cfg(target_arch = "x86_64")]
  226. #[eonix_macros::define_syscall(SYS_MKDIR)]
  227. async fn mkdir(pathname: User<u8>, mode: u32) -> KResult<()> {
  228. sys_mkdirat(thread, FD::AT_FDCWD, pathname, mode).await
  229. }
  230. #[eonix_macros::define_syscall(SYS_FTRUNCATE64)]
  231. async fn truncate64(fd: FD, length: usize) -> KResult<()> {
  232. let file = thread.files.get(fd).ok_or(EBADF)?;
  233. file.as_path().ok_or(EBADF)?.truncate(length)
  234. }
  235. #[cfg(target_arch = "x86_64")]
  236. #[eonix_macros::define_syscall(SYS_TRUNCATE)]
  237. async fn truncate(pathname: User<u8>, length: usize) -> KResult<()> {
  238. let path = UserString::new(pathname)?;
  239. let path = Path::new(path.as_cstr().to_bytes())?;
  240. let dentry = Dentry::open(&thread.fs_context, path, true)?;
  241. dentry.truncate(length)
  242. }
  243. #[eonix_macros::define_syscall(SYS_UNLINKAT)]
  244. async fn unlinkat(dirfd: FD, pathname: User<u8>) -> KResult<()> {
  245. dentry_from(thread, dirfd, pathname, false)?.unlink()
  246. }
  247. #[cfg(target_arch = "x86_64")]
  248. #[eonix_macros::define_syscall(SYS_UNLINK)]
  249. async fn unlink(pathname: User<u8>) -> KResult<()> {
  250. sys_unlinkat(thread, FD::AT_FDCWD, pathname)
  251. }
  252. #[eonix_macros::define_syscall(SYS_SYMLINKAT)]
  253. async fn symlinkat(target: User<u8>, dirfd: FD, linkpath: User<u8>) -> KResult<()> {
  254. let target = UserString::new(target)?;
  255. let dentry = dentry_from(thread, dirfd, linkpath, false)?;
  256. dentry.symlink(target.as_cstr().to_bytes())
  257. }
  258. #[cfg(target_arch = "x86_64")]
  259. #[eonix_macros::define_syscall(SYS_SYMLINK)]
  260. async fn symlink(target: User<u8>, linkpath: User<u8>) -> KResult<()> {
  261. sys_symlinkat(thread, target, FD::AT_FDCWD, linkpath)
  262. }
  263. #[eonix_macros::define_syscall(SYS_MKNODAT)]
  264. async fn mknodat(dirfd: FD, pathname: User<u8>, mode: u32, dev: u32) -> KResult<()> {
  265. let dentry = dentry_from(thread, dirfd, pathname, true)?;
  266. let umask = *thread.fs_context.umask.lock();
  267. let mode = mode & ((!umask & 0o777) | (S_IFBLK | S_IFCHR));
  268. dentry.mknod(mode, dev)
  269. }
  270. #[cfg(target_arch = "x86_64")]
  271. #[eonix_macros::define_syscall(SYS_MKNOD)]
  272. async fn mknod(pathname: User<u8>, mode: u32, dev: u32) -> KResult<()> {
  273. sys_mknodat(thread, FD::AT_FDCWD, pathname, mode, dev).await
  274. }
  275. #[eonix_macros::define_syscall(SYS_READLINKAT)]
  276. async fn readlinkat(
  277. dirfd: FD,
  278. pathname: User<u8>,
  279. buffer: UserMut<u8>,
  280. bufsize: usize,
  281. ) -> KResult<usize> {
  282. let dentry = dentry_from(thread, dirfd, pathname, false)?;
  283. let mut buffer = UserBuffer::new(buffer, bufsize)?;
  284. dentry.readlink(&mut buffer)
  285. }
  286. #[cfg(target_arch = "x86_64")]
  287. #[eonix_macros::define_syscall(SYS_READLINK)]
  288. async fn readlink(pathname: User<u8>, buffer: UserMut<u8>, bufsize: usize) -> KResult<usize> {
  289. sys_readlinkat(thread, FD::AT_FDCWD, pathname, buffer, bufsize).await
  290. }
  291. async fn do_lseek(thread: &Thread, fd: FD, offset: u64, whence: u32) -> KResult<u64> {
  292. let file = thread.files.get(fd).ok_or(EBADF)?;
  293. Ok(match whence {
  294. SEEK_SET => file.seek(SeekOption::Set(offset as usize)).await?,
  295. SEEK_CUR => file.seek(SeekOption::Current(offset as isize)).await?,
  296. SEEK_END => file.seek(SeekOption::End(offset as isize)).await?,
  297. _ => return Err(EINVAL),
  298. } as u64)
  299. }
  300. #[cfg(not(target_arch = "x86_64"))]
  301. #[eonix_macros::define_syscall(SYS_LSEEK)]
  302. async fn lseek(fd: FD, offset: u64, whence: u32) -> KResult<u64> {
  303. do_lseek(thread, fd, offset, whence).await
  304. }
  305. #[cfg(target_arch = "x86_64")]
  306. #[eonix_macros::define_syscall(SYS_LLSEEK)]
  307. fn llseek(
  308. fd: FD,
  309. offset_high: u32,
  310. offset_low: u32,
  311. result: UserMut<u64>,
  312. whence: u32,
  313. ) -> KResult<()> {
  314. let mut result = UserBuffer::new(result.cast(), core::mem::size_of::<u64>())?;
  315. let offset = ((offset_high as u64) << 32) | (offset_low as u64);
  316. let new_offset = do_lseek(thread, fd, offset, whence).await?;
  317. result.copy(&new_offset)?.ok_or(EFAULT)
  318. }
  319. #[repr(C)]
  320. #[derive(Clone, Copy)]
  321. struct IoVec {
  322. base: PtrT,
  323. len: Long,
  324. }
  325. #[eonix_macros::define_syscall(SYS_READV)]
  326. async fn readv(fd: FD, iov_user: User<IoVec>, iovcnt: u32) -> KResult<usize> {
  327. let file = thread.files.get(fd).ok_or(EBADF)?;
  328. let mut iov_user = UserPointer::new(iov_user)?;
  329. let iov_buffers = (0..iovcnt)
  330. .map(|_| {
  331. let iov_result = iov_user.read()?;
  332. iov_user = iov_user.offset(1)?;
  333. Ok(iov_result)
  334. })
  335. .filter_map(|iov_result| match iov_result {
  336. Err(err) => Some(Err(err)),
  337. Ok(IoVec {
  338. len: Long::ZERO, ..
  339. }) => None,
  340. Ok(IoVec { base, len }) => {
  341. Some(UserBuffer::new(UserMut::with_addr(base.addr()), len.get()))
  342. }
  343. })
  344. .collect::<KResult<Vec<_>>>()?;
  345. let mut tot = 0usize;
  346. for mut buffer in iov_buffers.into_iter() {
  347. // TODO!!!: `readv`
  348. let nread = file.read(&mut buffer, None).await?;
  349. tot += nread;
  350. if nread != buffer.total() {
  351. break;
  352. }
  353. }
  354. Ok(tot)
  355. }
  356. #[eonix_macros::define_syscall(SYS_WRITEV)]
  357. async fn writev(fd: FD, iov_user: User<IoVec>, iovcnt: u32) -> KResult<usize> {
  358. let file = thread.files.get(fd).ok_or(EBADF)?;
  359. let mut iov_user = UserPointer::new(iov_user)?;
  360. let iov_streams = (0..iovcnt)
  361. .map(|_| {
  362. let iov_result = iov_user.read()?;
  363. iov_user = iov_user.offset(1)?;
  364. Ok(iov_result)
  365. })
  366. .filter_map(|iov_result| match iov_result {
  367. Err(err) => Some(Err(err)),
  368. Ok(IoVec {
  369. len: Long::ZERO, ..
  370. }) => None,
  371. Ok(IoVec { base, len }) => Some(
  372. CheckedUserPointer::new(User::with_addr(base.addr()), len.get())
  373. .map(|ptr| ptr.into_stream()),
  374. ),
  375. })
  376. .collect::<KResult<Vec<_>>>()?;
  377. let mut tot = 0usize;
  378. for mut stream in iov_streams.into_iter() {
  379. let nread = file.write(&mut stream, None).await?;
  380. tot += nread;
  381. if nread == 0 || !stream.is_drained() {
  382. break;
  383. }
  384. }
  385. Ok(tot)
  386. }
  387. #[eonix_macros::define_syscall(SYS_FACCESSAT)]
  388. async fn faccessat(dirfd: FD, pathname: User<u8>, _mode: u32, flags: AtFlags) -> KResult<()> {
  389. let dentry = if flags.at_empty_path() {
  390. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  391. file.as_path().ok_or(EBADF)?.clone()
  392. } else {
  393. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  394. };
  395. if !dentry.is_valid() {
  396. return Err(ENOENT);
  397. }
  398. // TODO: check permission
  399. // match mode {
  400. // F_OK => todo!(),
  401. // R_OK => todo!(),
  402. // W_OK => todo!(),
  403. // X_OK => todo!(),
  404. // _ => Err(EINVAL),
  405. // }
  406. Ok(())
  407. }
  408. #[cfg(target_arch = "x86_64")]
  409. #[eonix_macros::define_syscall(SYS_ACCESS)]
  410. async fn access(pathname: User<u8>, mode: u32) -> KResult<()> {
  411. sys_faccessat(thread, FD::AT_FDCWD, pathname, mode, AtFlags::empty()).await
  412. }
  413. #[eonix_macros::define_syscall(SYS_SENDFILE64)]
  414. async fn sendfile64(out_fd: FD, in_fd: FD, offset: UserMut<u8>, count: usize) -> KResult<usize> {
  415. let in_file = thread.files.get(in_fd).ok_or(EBADF)?;
  416. let out_file = thread.files.get(out_fd).ok_or(EBADF)?;
  417. if !offset.is_null() {
  418. unimplemented!("sendfile64 with offset");
  419. }
  420. in_file.sendfile(&out_file, count).await
  421. }
  422. #[eonix_macros::define_syscall(SYS_IOCTL)]
  423. async fn ioctl(fd: FD, request: usize, arg3: usize) -> KResult<usize> {
  424. let file = thread.files.get(fd).ok_or(EBADF)?;
  425. file.ioctl(request, arg3).await
  426. }
  427. #[eonix_macros::define_syscall(SYS_FCNTL64)]
  428. async fn fcntl64(fd: FD, cmd: u32, arg: usize) -> KResult<usize> {
  429. thread.files.fcntl(fd, cmd, arg)
  430. }
  431. #[repr(C)]
  432. #[derive(Debug, Clone, Copy)]
  433. struct UserPollFd {
  434. fd: FD,
  435. events: u16,
  436. revents: u16,
  437. }
  438. async fn do_poll(
  439. thread: &Thread,
  440. fds: UserMut<UserPollFd>,
  441. nfds: u32,
  442. _timeout: u32,
  443. ) -> KResult<u32> {
  444. match nfds {
  445. 0 => Ok(0),
  446. 2.. => unimplemented!("Poll with {} fds", nfds),
  447. 1 => {
  448. // TODO!!: Poll with timeout
  449. // if timeout != u32::MAX {
  450. // unimplemented!("Poll with timeout {}", timeout);
  451. // }
  452. let fds = UserPointerMut::new(fds)?;
  453. let mut fd = fds.read()?;
  454. let file = thread.files.get(fd.fd).ok_or(EBADF)?;
  455. fd.revents = file
  456. .poll(PollEvent::from_bits_retain(fd.events))
  457. .await?
  458. .bits();
  459. fds.write(fd)?;
  460. Ok(1)
  461. }
  462. }
  463. }
  464. #[eonix_macros::define_syscall(SYS_PPOLL)]
  465. async fn ppoll(
  466. fds: UserMut<UserPollFd>,
  467. nfds: u32,
  468. _timeout_ptr: User<TimeSpec>,
  469. _sigmask: User<SigSet>,
  470. ) -> KResult<u32> {
  471. // TODO: Implement ppoll with signal mask and timeout
  472. do_poll(thread, fds, nfds, 0).await
  473. }
  474. #[eonix_macros::define_syscall(SYS_PSELECT6)]
  475. async fn pselect6(
  476. nfds: u32,
  477. _readfds: UserMut<FDSet>,
  478. _writefds: UserMut<FDSet>,
  479. _exceptfds: UserMut<FDSet>,
  480. timeout: UserMut<TimeSpec>,
  481. _sigmask: User<()>,
  482. ) -> KResult<usize> {
  483. // According to [pthread6(2)](https://linux.die.net/man/2/pselect6):
  484. // Some code calls select() with all three sets empty, nfds zero, and
  485. // a non-NULL timeout as a fairly portable way to sleep with subsecond precision.
  486. if nfds != 0 {
  487. thread.raise(Signal::SIGSYS);
  488. return Err(ENOSYS);
  489. }
  490. let timeout = UserPointerMut::new(timeout)?;
  491. // Read here to check for invalid pointers.
  492. let _timeout_value = timeout.read()?;
  493. sleep(Duration::from_millis(10)).await;
  494. timeout.write(TimeSpec {
  495. tv_sec: 0,
  496. tv_nsec: 0,
  497. })?;
  498. Ok(0)
  499. }
  500. #[cfg(target_arch = "x86_64")]
  501. #[eonix_macros::define_syscall(SYS_POLL)]
  502. async fn poll(fds: UserMut<UserPollFd>, nfds: u32, timeout: u32) -> KResult<u32> {
  503. do_poll(thread, fds, nfds, timeout).await
  504. }
  505. #[eonix_macros::define_syscall(SYS_FCHOWNAT)]
  506. async fn fchownat(
  507. dirfd: FD,
  508. pathname: User<u8>,
  509. uid: u32,
  510. gid: u32,
  511. flags: AtFlags,
  512. ) -> KResult<()> {
  513. let dentry = dentry_from(thread, dirfd, pathname, !flags.no_follow())?;
  514. if !dentry.is_valid() {
  515. return Err(ENOENT);
  516. }
  517. dentry.chown(uid, gid)
  518. }
  519. #[eonix_macros::define_syscall(SYS_FCHMODAT)]
  520. async fn fchmodat(dirfd: FD, pathname: User<u8>, mode: u32, flags: AtFlags) -> KResult<()> {
  521. let dentry = if flags.at_empty_path() {
  522. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  523. file.as_path().ok_or(EBADF)?.clone()
  524. } else {
  525. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  526. };
  527. if !dentry.is_valid() {
  528. return Err(ENOENT);
  529. }
  530. dentry.chmod(mode)
  531. }
  532. #[eonix_macros::define_syscall(SYS_FCHMOD)]
  533. async fn chmod(pathname: User<u8>, mode: u32) -> KResult<()> {
  534. sys_fchmodat(thread, FD::AT_FDCWD, pathname, mode, AtFlags::empty()).await
  535. }
  536. #[eonix_macros::define_syscall(SYS_UTIMENSAT)]
  537. async fn utimensat(
  538. dirfd: FD,
  539. pathname: User<u8>,
  540. times: User<TimeSpec>,
  541. flags: AtFlags,
  542. ) -> KResult<()> {
  543. let dentry = if flags.at_empty_path() {
  544. let file = thread.files.get(dirfd).ok_or(EBADF)?;
  545. file.as_path().ok_or(EBADF)?.clone()
  546. } else {
  547. dentry_from(thread, dirfd, pathname, !flags.no_follow())?
  548. };
  549. if !dentry.is_valid() {
  550. return Err(ENOENT);
  551. }
  552. let _times = if times.is_null() {
  553. [TimeSpec::default(), TimeSpec::default()]
  554. } else {
  555. let times = UserPointer::new(times)?;
  556. [times.read()?, times.offset(1)?.read()?]
  557. };
  558. // TODO: Implement utimensat
  559. // dentry.utimens(&times)
  560. Ok(())
  561. }
  562. #[eonix_macros::define_syscall(SYS_RENAMEAT2)]
  563. async fn renameat2(
  564. old_dirfd: FD,
  565. old_pathname: User<u8>,
  566. new_dirfd: FD,
  567. new_pathname: User<u8>,
  568. flags: u32,
  569. ) -> KResult<()> {
  570. let flags = RenameFlags::from_bits(flags).ok_or(EINVAL)?;
  571. // The two flags RENAME_NOREPLACE and RENAME_EXCHANGE are mutually exclusive.
  572. if flags.contains(RenameFlags::RENAME_NOREPLACE | RenameFlags::RENAME_EXCHANGE) {
  573. Err(EINVAL)?;
  574. }
  575. let old_dentry = dentry_from(thread, old_dirfd, old_pathname, false)?;
  576. let new_dentry = dentry_from(thread, new_dirfd, new_pathname, false)?;
  577. old_dentry.rename(&new_dentry, flags)
  578. }
  579. #[cfg(target_arch = "x86_64")]
  580. #[eonix_macros::define_syscall(SYS_RENAME)]
  581. async fn rename(old_pathname: User<u8>, new_pathname: User<u8>) -> KResult<()> {
  582. sys_renameat2(
  583. thread,
  584. FD::AT_FDCWD,
  585. old_pathname,
  586. FD::AT_FDCWD,
  587. new_pathname,
  588. 0,
  589. )
  590. .await
  591. }
  592. pub fn keep_alive() {}