1b8a62b91Sopenharmony_ci//! POSIX-style `*at` functions.
2b8a62b91Sopenharmony_ci//!
3b8a62b91Sopenharmony_ci//! The `dirfd` argument to these functions may be a file descriptor for a
4b8a62b91Sopenharmony_ci//! directory, or the special value returned by [`cwd`].
5b8a62b91Sopenharmony_ci//!
6b8a62b91Sopenharmony_ci//! [`cwd`]: crate::fs::cwd
7b8a62b91Sopenharmony_ci
8b8a62b91Sopenharmony_ciuse crate::fd::OwnedFd;
9b8a62b91Sopenharmony_ciuse crate::ffi::{CStr, CString};
10b8a62b91Sopenharmony_ci#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
11b8a62b91Sopenharmony_ciuse crate::fs::Access;
12b8a62b91Sopenharmony_ci#[cfg(any(target_os = "ios", target_os = "macos"))]
13b8a62b91Sopenharmony_ciuse crate::fs::CloneFlags;
14b8a62b91Sopenharmony_ci#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
15b8a62b91Sopenharmony_ciuse crate::fs::FileType;
16b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
17b8a62b91Sopenharmony_ciuse crate::fs::RenameFlags;
18b8a62b91Sopenharmony_ciuse crate::fs::{AtFlags, Mode, OFlags, Stat, Timestamps};
19b8a62b91Sopenharmony_ciuse crate::path::SMALL_PATH_BUFFER_SIZE;
20b8a62b91Sopenharmony_ci#[cfg(not(target_os = "wasi"))]
21b8a62b91Sopenharmony_ciuse crate::process::{Gid, Uid};
22b8a62b91Sopenharmony_ciuse crate::{backend, io, path};
23b8a62b91Sopenharmony_ciuse alloc::vec::Vec;
24b8a62b91Sopenharmony_ciuse backend::fd::{AsFd, BorrowedFd};
25b8a62b91Sopenharmony_ciuse backend::time::types::Nsecs;
26b8a62b91Sopenharmony_ci
27b8a62b91Sopenharmony_cipub use backend::fs::types::{Dev, RawMode};
28b8a62b91Sopenharmony_ci
29b8a62b91Sopenharmony_ci/// `UTIME_NOW` for use with [`utimensat`].
30b8a62b91Sopenharmony_ci///
31b8a62b91Sopenharmony_ci/// [`utimensat`]: crate::fs::utimensat
32b8a62b91Sopenharmony_ci#[cfg(not(target_os = "redox"))]
33b8a62b91Sopenharmony_cipub const UTIME_NOW: Nsecs = backend::fs::types::UTIME_NOW as Nsecs;
34b8a62b91Sopenharmony_ci
35b8a62b91Sopenharmony_ci/// `UTIME_OMIT` for use with [`utimensat`].
36b8a62b91Sopenharmony_ci///
37b8a62b91Sopenharmony_ci/// [`utimensat`]: crate::fs::utimensat
38b8a62b91Sopenharmony_ci#[cfg(not(target_os = "redox"))]
39b8a62b91Sopenharmony_cipub const UTIME_OMIT: Nsecs = backend::fs::types::UTIME_OMIT as Nsecs;
40b8a62b91Sopenharmony_ci
41b8a62b91Sopenharmony_ci/// `openat(dirfd, path, oflags, mode)`—Opens a file.
42b8a62b91Sopenharmony_ci///
43b8a62b91Sopenharmony_ci/// POSIX guarantees that `openat` will use the lowest unused file descriptor,
44b8a62b91Sopenharmony_ci/// however it is not safe in general to rely on this, as file descriptors may
45b8a62b91Sopenharmony_ci/// be unexpectedly allocated on other threads or in libraries.
46b8a62b91Sopenharmony_ci///
47b8a62b91Sopenharmony_ci/// The `Mode` argument is only significant when creating a file.
48b8a62b91Sopenharmony_ci///
49b8a62b91Sopenharmony_ci/// # References
50b8a62b91Sopenharmony_ci///  - [POSIX]
51b8a62b91Sopenharmony_ci///  - [Linux]
52b8a62b91Sopenharmony_ci///
53b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/openat.html
54b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/open.2.html
55b8a62b91Sopenharmony_ci#[inline]
56b8a62b91Sopenharmony_cipub fn openat<P: path::Arg, Fd: AsFd>(
57b8a62b91Sopenharmony_ci    dirfd: Fd,
58b8a62b91Sopenharmony_ci    path: P,
59b8a62b91Sopenharmony_ci    oflags: OFlags,
60b8a62b91Sopenharmony_ci    create_mode: Mode,
61b8a62b91Sopenharmony_ci) -> io::Result<OwnedFd> {
62b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| {
63b8a62b91Sopenharmony_ci        backend::fs::syscalls::openat(dirfd.as_fd(), path, oflags, create_mode)
64b8a62b91Sopenharmony_ci    })
65b8a62b91Sopenharmony_ci}
66b8a62b91Sopenharmony_ci
67b8a62b91Sopenharmony_ci/// `readlinkat(fd, path)`—Reads the contents of a symlink.
68b8a62b91Sopenharmony_ci///
69b8a62b91Sopenharmony_ci/// If `reuse` is non-empty, reuse its buffer to store the result if possible.
70b8a62b91Sopenharmony_ci///
71b8a62b91Sopenharmony_ci/// # References
72b8a62b91Sopenharmony_ci///  - [POSIX]
73b8a62b91Sopenharmony_ci///  - [Linux]
74b8a62b91Sopenharmony_ci///
75b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlinkat.html
76b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/readlinkat.2.html
77b8a62b91Sopenharmony_ci#[inline]
78b8a62b91Sopenharmony_cipub fn readlinkat<P: path::Arg, Fd: AsFd, B: Into<Vec<u8>>>(
79b8a62b91Sopenharmony_ci    dirfd: Fd,
80b8a62b91Sopenharmony_ci    path: P,
81b8a62b91Sopenharmony_ci    reuse: B,
82b8a62b91Sopenharmony_ci) -> io::Result<CString> {
83b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| _readlinkat(dirfd.as_fd(), path, reuse.into()))
84b8a62b91Sopenharmony_ci}
85b8a62b91Sopenharmony_ci
86b8a62b91Sopenharmony_cifn _readlinkat(dirfd: BorrowedFd<'_>, path: &CStr, mut buffer: Vec<u8>) -> io::Result<CString> {
87b8a62b91Sopenharmony_ci    // This code would benefit from having a better way to read into
88b8a62b91Sopenharmony_ci    // uninitialized memory, but that requires `unsafe`.
89b8a62b91Sopenharmony_ci    buffer.clear();
90b8a62b91Sopenharmony_ci    buffer.reserve(SMALL_PATH_BUFFER_SIZE);
91b8a62b91Sopenharmony_ci    buffer.resize(buffer.capacity(), 0_u8);
92b8a62b91Sopenharmony_ci
93b8a62b91Sopenharmony_ci    loop {
94b8a62b91Sopenharmony_ci        let nread = backend::fs::syscalls::readlinkat(dirfd.as_fd(), path, &mut buffer)?;
95b8a62b91Sopenharmony_ci
96b8a62b91Sopenharmony_ci        let nread = nread as usize;
97b8a62b91Sopenharmony_ci        assert!(nread <= buffer.len());
98b8a62b91Sopenharmony_ci        if nread < buffer.len() {
99b8a62b91Sopenharmony_ci            buffer.resize(nread, 0_u8);
100b8a62b91Sopenharmony_ci            return Ok(CString::new(buffer).unwrap());
101b8a62b91Sopenharmony_ci        }
102b8a62b91Sopenharmony_ci        buffer.reserve(1); // use `Vec` reallocation strategy to grow capacity exponentially
103b8a62b91Sopenharmony_ci        buffer.resize(buffer.capacity(), 0_u8);
104b8a62b91Sopenharmony_ci    }
105b8a62b91Sopenharmony_ci}
106b8a62b91Sopenharmony_ci
107b8a62b91Sopenharmony_ci/// `mkdirat(fd, path, mode)`—Creates a directory.
108b8a62b91Sopenharmony_ci///
109b8a62b91Sopenharmony_ci/// # References
110b8a62b91Sopenharmony_ci///  - [POSIX]
111b8a62b91Sopenharmony_ci///  - [Linux]
112b8a62b91Sopenharmony_ci///
113b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdirat.html
114b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/mkdirat.2.html
115b8a62b91Sopenharmony_ci#[inline]
116b8a62b91Sopenharmony_cipub fn mkdirat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, mode: Mode) -> io::Result<()> {
117b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| backend::fs::syscalls::mkdirat(dirfd.as_fd(), path, mode))
118b8a62b91Sopenharmony_ci}
119b8a62b91Sopenharmony_ci
120b8a62b91Sopenharmony_ci/// `linkat(old_dirfd, old_path, new_dirfd, new_path, flags)`—Creates a hard
121b8a62b91Sopenharmony_ci/// link.
122b8a62b91Sopenharmony_ci///
123b8a62b91Sopenharmony_ci/// # References
124b8a62b91Sopenharmony_ci///  - [POSIX]
125b8a62b91Sopenharmony_ci///  - [Linux]
126b8a62b91Sopenharmony_ci///
127b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html
128b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/linkat.2.html
129b8a62b91Sopenharmony_ci#[inline]
130b8a62b91Sopenharmony_cipub fn linkat<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
131b8a62b91Sopenharmony_ci    old_dirfd: PFd,
132b8a62b91Sopenharmony_ci    old_path: P,
133b8a62b91Sopenharmony_ci    new_dirfd: QFd,
134b8a62b91Sopenharmony_ci    new_path: Q,
135b8a62b91Sopenharmony_ci    flags: AtFlags,
136b8a62b91Sopenharmony_ci) -> io::Result<()> {
137b8a62b91Sopenharmony_ci    old_path.into_with_c_str(|old_path| {
138b8a62b91Sopenharmony_ci        new_path.into_with_c_str(|new_path| {
139b8a62b91Sopenharmony_ci            backend::fs::syscalls::linkat(
140b8a62b91Sopenharmony_ci                old_dirfd.as_fd(),
141b8a62b91Sopenharmony_ci                old_path,
142b8a62b91Sopenharmony_ci                new_dirfd.as_fd(),
143b8a62b91Sopenharmony_ci                new_path,
144b8a62b91Sopenharmony_ci                flags,
145b8a62b91Sopenharmony_ci            )
146b8a62b91Sopenharmony_ci        })
147b8a62b91Sopenharmony_ci    })
148b8a62b91Sopenharmony_ci}
149b8a62b91Sopenharmony_ci
150b8a62b91Sopenharmony_ci/// `unlinkat(fd, path, flags)`—Unlinks a file or remove a directory.
151b8a62b91Sopenharmony_ci///
152b8a62b91Sopenharmony_ci/// With the [`REMOVEDIR`] flag, this removes a directory. This is in place
153b8a62b91Sopenharmony_ci/// of a `rmdirat` function.
154b8a62b91Sopenharmony_ci///
155b8a62b91Sopenharmony_ci/// # References
156b8a62b91Sopenharmony_ci///  - [POSIX]
157b8a62b91Sopenharmony_ci///  - [Linux]
158b8a62b91Sopenharmony_ci///
159b8a62b91Sopenharmony_ci/// [`REMOVEDIR`]: AtFlags::REMOVEDIR
160b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html
161b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/unlinkat.2.html
162b8a62b91Sopenharmony_ci#[inline]
163b8a62b91Sopenharmony_cipub fn unlinkat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, flags: AtFlags) -> io::Result<()> {
164b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| backend::fs::syscalls::unlinkat(dirfd.as_fd(), path, flags))
165b8a62b91Sopenharmony_ci}
166b8a62b91Sopenharmony_ci
167b8a62b91Sopenharmony_ci/// `renameat(old_dirfd, old_path, new_dirfd, new_path)`—Renames a file or
168b8a62b91Sopenharmony_ci/// directory.
169b8a62b91Sopenharmony_ci///
170b8a62b91Sopenharmony_ci/// # References
171b8a62b91Sopenharmony_ci///  - [POSIX]
172b8a62b91Sopenharmony_ci///  - [Linux]
173b8a62b91Sopenharmony_ci///
174b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/renameat.html
175b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/renameat.2.html
176b8a62b91Sopenharmony_ci#[inline]
177b8a62b91Sopenharmony_cipub fn renameat<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
178b8a62b91Sopenharmony_ci    old_dirfd: PFd,
179b8a62b91Sopenharmony_ci    old_path: P,
180b8a62b91Sopenharmony_ci    new_dirfd: QFd,
181b8a62b91Sopenharmony_ci    new_path: Q,
182b8a62b91Sopenharmony_ci) -> io::Result<()> {
183b8a62b91Sopenharmony_ci    old_path.into_with_c_str(|old_path| {
184b8a62b91Sopenharmony_ci        new_path.into_with_c_str(|new_path| {
185b8a62b91Sopenharmony_ci            backend::fs::syscalls::renameat(
186b8a62b91Sopenharmony_ci                old_dirfd.as_fd(),
187b8a62b91Sopenharmony_ci                old_path,
188b8a62b91Sopenharmony_ci                new_dirfd.as_fd(),
189b8a62b91Sopenharmony_ci                new_path,
190b8a62b91Sopenharmony_ci            )
191b8a62b91Sopenharmony_ci        })
192b8a62b91Sopenharmony_ci    })
193b8a62b91Sopenharmony_ci}
194b8a62b91Sopenharmony_ci
195b8a62b91Sopenharmony_ci/// `renameat2(old_dirfd, old_path, new_dirfd, new_path, flags)`—Renames a
196b8a62b91Sopenharmony_ci/// file or directory.
197b8a62b91Sopenharmony_ci///
198b8a62b91Sopenharmony_ci/// # References
199b8a62b91Sopenharmony_ci///  - [Linux]
200b8a62b91Sopenharmony_ci///
201b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/renameat2.2.html
202b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
203b8a62b91Sopenharmony_ci#[inline]
204b8a62b91Sopenharmony_ci#[doc(alias = "renameat2")]
205b8a62b91Sopenharmony_cipub fn renameat_with<P: path::Arg, Q: path::Arg, PFd: AsFd, QFd: AsFd>(
206b8a62b91Sopenharmony_ci    old_dirfd: PFd,
207b8a62b91Sopenharmony_ci    old_path: P,
208b8a62b91Sopenharmony_ci    new_dirfd: QFd,
209b8a62b91Sopenharmony_ci    new_path: Q,
210b8a62b91Sopenharmony_ci    flags: RenameFlags,
211b8a62b91Sopenharmony_ci) -> io::Result<()> {
212b8a62b91Sopenharmony_ci    old_path.into_with_c_str(|old_path| {
213b8a62b91Sopenharmony_ci        new_path.into_with_c_str(|new_path| {
214b8a62b91Sopenharmony_ci            backend::fs::syscalls::renameat2(
215b8a62b91Sopenharmony_ci                old_dirfd.as_fd(),
216b8a62b91Sopenharmony_ci                old_path,
217b8a62b91Sopenharmony_ci                new_dirfd.as_fd(),
218b8a62b91Sopenharmony_ci                new_path,
219b8a62b91Sopenharmony_ci                flags,
220b8a62b91Sopenharmony_ci            )
221b8a62b91Sopenharmony_ci        })
222b8a62b91Sopenharmony_ci    })
223b8a62b91Sopenharmony_ci}
224b8a62b91Sopenharmony_ci
225b8a62b91Sopenharmony_ci/// `symlinkat(old_path, new_dirfd, new_path)`—Creates a symlink.
226b8a62b91Sopenharmony_ci///
227b8a62b91Sopenharmony_ci/// # References
228b8a62b91Sopenharmony_ci///  - [POSIX]
229b8a62b91Sopenharmony_ci///  - [Linux]
230b8a62b91Sopenharmony_ci///
231b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html
232b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/symlinkat.2.html
233b8a62b91Sopenharmony_ci#[inline]
234b8a62b91Sopenharmony_cipub fn symlinkat<P: path::Arg, Q: path::Arg, Fd: AsFd>(
235b8a62b91Sopenharmony_ci    old_path: P,
236b8a62b91Sopenharmony_ci    new_dirfd: Fd,
237b8a62b91Sopenharmony_ci    new_path: Q,
238b8a62b91Sopenharmony_ci) -> io::Result<()> {
239b8a62b91Sopenharmony_ci    old_path.into_with_c_str(|old_path| {
240b8a62b91Sopenharmony_ci        new_path.into_with_c_str(|new_path| {
241b8a62b91Sopenharmony_ci            backend::fs::syscalls::symlinkat(old_path, new_dirfd.as_fd(), new_path)
242b8a62b91Sopenharmony_ci        })
243b8a62b91Sopenharmony_ci    })
244b8a62b91Sopenharmony_ci}
245b8a62b91Sopenharmony_ci
246b8a62b91Sopenharmony_ci/// `fstatat(dirfd, path, flags)`—Queries metadata for a file or directory.
247b8a62b91Sopenharmony_ci///
248b8a62b91Sopenharmony_ci/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
249b8a62b91Sopenharmony_ci/// interpret the `st_mode` field.
250b8a62b91Sopenharmony_ci///
251b8a62b91Sopenharmony_ci/// # References
252b8a62b91Sopenharmony_ci///  - [POSIX]
253b8a62b91Sopenharmony_ci///  - [Linux]
254b8a62b91Sopenharmony_ci///
255b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatat.html
256b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/fstatat.2.html
257b8a62b91Sopenharmony_ci/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode
258b8a62b91Sopenharmony_ci/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
259b8a62b91Sopenharmony_ci#[inline]
260b8a62b91Sopenharmony_ci#[doc(alias = "fstatat")]
261b8a62b91Sopenharmony_cipub fn statat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, flags: AtFlags) -> io::Result<Stat> {
262b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| backend::fs::syscalls::statat(dirfd.as_fd(), path, flags))
263b8a62b91Sopenharmony_ci}
264b8a62b91Sopenharmony_ci
265b8a62b91Sopenharmony_ci/// `faccessat(dirfd, path, access, flags)`—Tests permissions for a file or
266b8a62b91Sopenharmony_ci/// directory.
267b8a62b91Sopenharmony_ci///
268b8a62b91Sopenharmony_ci/// # References
269b8a62b91Sopenharmony_ci///  - [POSIX]
270b8a62b91Sopenharmony_ci///  - [Linux]
271b8a62b91Sopenharmony_ci///
272b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html
273b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/faccessat.2.html
274b8a62b91Sopenharmony_ci#[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
275b8a62b91Sopenharmony_ci#[inline]
276b8a62b91Sopenharmony_ci#[doc(alias = "faccessat")]
277b8a62b91Sopenharmony_cipub fn accessat<P: path::Arg, Fd: AsFd>(
278b8a62b91Sopenharmony_ci    dirfd: Fd,
279b8a62b91Sopenharmony_ci    path: P,
280b8a62b91Sopenharmony_ci    access: Access,
281b8a62b91Sopenharmony_ci    flags: AtFlags,
282b8a62b91Sopenharmony_ci) -> io::Result<()> {
283b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| backend::fs::syscalls::accessat(dirfd.as_fd(), path, access, flags))
284b8a62b91Sopenharmony_ci}
285b8a62b91Sopenharmony_ci
286b8a62b91Sopenharmony_ci/// `utimensat(dirfd, path, times, flags)`—Sets file or directory timestamps.
287b8a62b91Sopenharmony_ci///
288b8a62b91Sopenharmony_ci/// # References
289b8a62b91Sopenharmony_ci///  - [POSIX]
290b8a62b91Sopenharmony_ci///  - [Linux]
291b8a62b91Sopenharmony_ci///
292b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimensat.html
293b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/utimensat.2.html
294b8a62b91Sopenharmony_ci#[inline]
295b8a62b91Sopenharmony_cipub fn utimensat<P: path::Arg, Fd: AsFd>(
296b8a62b91Sopenharmony_ci    dirfd: Fd,
297b8a62b91Sopenharmony_ci    path: P,
298b8a62b91Sopenharmony_ci    times: &Timestamps,
299b8a62b91Sopenharmony_ci    flags: AtFlags,
300b8a62b91Sopenharmony_ci) -> io::Result<()> {
301b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| backend::fs::syscalls::utimensat(dirfd.as_fd(), path, times, flags))
302b8a62b91Sopenharmony_ci}
303b8a62b91Sopenharmony_ci
304b8a62b91Sopenharmony_ci/// `fchmodat(dirfd, path, mode, 0)`—Sets file or directory permissions.
305b8a62b91Sopenharmony_ci///
306b8a62b91Sopenharmony_ci/// The flags argument is fixed to 0, so `AT_SYMLINK_NOFOLLOW` is not
307b8a62b91Sopenharmony_ci/// supported. <details>Platform support for this flag varies widely.</details>
308b8a62b91Sopenharmony_ci///
309b8a62b91Sopenharmony_ci/// This implementation does not support `O_PATH` file descriptors, even on
310b8a62b91Sopenharmony_ci/// platforms where the host libc emulates it.
311b8a62b91Sopenharmony_ci///
312b8a62b91Sopenharmony_ci/// # References
313b8a62b91Sopenharmony_ci///  - [POSIX]
314b8a62b91Sopenharmony_ci///  - [Linux]
315b8a62b91Sopenharmony_ci///
316b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html
317b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/fchmodat.2.html
318b8a62b91Sopenharmony_ci#[cfg(not(target_os = "wasi"))]
319b8a62b91Sopenharmony_ci#[inline]
320b8a62b91Sopenharmony_ci#[doc(alias = "fchmodat")]
321b8a62b91Sopenharmony_cipub fn chmodat<P: path::Arg, Fd: AsFd>(dirfd: Fd, path: P, mode: Mode) -> io::Result<()> {
322b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| backend::fs::syscalls::chmodat(dirfd.as_fd(), path, mode))
323b8a62b91Sopenharmony_ci}
324b8a62b91Sopenharmony_ci
325b8a62b91Sopenharmony_ci/// `fclonefileat(src, dst_dir, dst, flags)`—Efficiently copies between files.
326b8a62b91Sopenharmony_ci///
327b8a62b91Sopenharmony_ci/// # References
328b8a62b91Sopenharmony_ci///  - [Apple]
329b8a62b91Sopenharmony_ci///
330b8a62b91Sopenharmony_ci/// [Apple]: https://opensource.apple.com/source/xnu/xnu-3789.21.4/bsd/man/man2/clonefile.2.auto.html
331b8a62b91Sopenharmony_ci#[cfg(any(target_os = "ios", target_os = "macos"))]
332b8a62b91Sopenharmony_ci#[inline]
333b8a62b91Sopenharmony_cipub fn fclonefileat<Fd: AsFd, DstFd: AsFd, P: path::Arg>(
334b8a62b91Sopenharmony_ci    src: Fd,
335b8a62b91Sopenharmony_ci    dst_dir: DstFd,
336b8a62b91Sopenharmony_ci    dst: P,
337b8a62b91Sopenharmony_ci    flags: CloneFlags,
338b8a62b91Sopenharmony_ci) -> io::Result<()> {
339b8a62b91Sopenharmony_ci    dst.into_with_c_str(|dst| {
340b8a62b91Sopenharmony_ci        backend::fs::syscalls::fclonefileat(src.as_fd(), dst_dir.as_fd(), dst, flags)
341b8a62b91Sopenharmony_ci    })
342b8a62b91Sopenharmony_ci}
343b8a62b91Sopenharmony_ci
344b8a62b91Sopenharmony_ci/// `mknodat(dirfd, path, mode, dev)`—Creates special or normal files.
345b8a62b91Sopenharmony_ci///
346b8a62b91Sopenharmony_ci/// # References
347b8a62b91Sopenharmony_ci///  - [POSIX]
348b8a62b91Sopenharmony_ci///  - [Linux]
349b8a62b91Sopenharmony_ci///
350b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mknodat.html
351b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/mknodat.2.html
352b8a62b91Sopenharmony_ci#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
353b8a62b91Sopenharmony_ci#[inline]
354b8a62b91Sopenharmony_cipub fn mknodat<P: path::Arg, Fd: AsFd>(
355b8a62b91Sopenharmony_ci    dirfd: Fd,
356b8a62b91Sopenharmony_ci    path: P,
357b8a62b91Sopenharmony_ci    file_type: FileType,
358b8a62b91Sopenharmony_ci    mode: Mode,
359b8a62b91Sopenharmony_ci    dev: Dev,
360b8a62b91Sopenharmony_ci) -> io::Result<()> {
361b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| {
362b8a62b91Sopenharmony_ci        backend::fs::syscalls::mknodat(dirfd.as_fd(), path, file_type, mode, dev)
363b8a62b91Sopenharmony_ci    })
364b8a62b91Sopenharmony_ci}
365b8a62b91Sopenharmony_ci
366b8a62b91Sopenharmony_ci/// `fchownat(dirfd, path, owner, group, flags)`—Sets file or directory
367b8a62b91Sopenharmony_ci/// ownership.
368b8a62b91Sopenharmony_ci///
369b8a62b91Sopenharmony_ci/// # References
370b8a62b91Sopenharmony_ci///  - [POSIX]
371b8a62b91Sopenharmony_ci///  - [Linux]
372b8a62b91Sopenharmony_ci///
373b8a62b91Sopenharmony_ci/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html
374b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/fchownat.2.html
375b8a62b91Sopenharmony_ci#[cfg(not(target_os = "wasi"))]
376b8a62b91Sopenharmony_ci#[inline]
377b8a62b91Sopenharmony_ci#[doc(alias = "fchownat")]
378b8a62b91Sopenharmony_cipub fn chownat<P: path::Arg, Fd: AsFd>(
379b8a62b91Sopenharmony_ci    dirfd: Fd,
380b8a62b91Sopenharmony_ci    path: P,
381b8a62b91Sopenharmony_ci    owner: Option<Uid>,
382b8a62b91Sopenharmony_ci    group: Option<Gid>,
383b8a62b91Sopenharmony_ci    flags: AtFlags,
384b8a62b91Sopenharmony_ci) -> io::Result<()> {
385b8a62b91Sopenharmony_ci    path.into_with_c_str(|path| {
386b8a62b91Sopenharmony_ci        backend::fs::syscalls::chownat(dirfd.as_fd(), path, owner, group, flags)
387b8a62b91Sopenharmony_ci    })
388b8a62b91Sopenharmony_ci}
389