file_rw.rs 19 KB

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