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