xref: /third_party/rust/crates/rustix/src/fs/fd.rs (revision b8a62b91)
1//! Functions which operate on file descriptors.
2
3#[cfg(not(target_os = "wasi"))]
4use crate::fs::Mode;
5use crate::io::SeekFrom;
6#[cfg(not(target_os = "wasi"))]
7use crate::process::{Gid, Uid};
8use crate::{backend, io};
9use backend::fd::{AsFd, BorrowedFd};
10
11#[cfg(not(any(target_os = "solaris", target_os = "wasi")))]
12pub use backend::fs::types::FlockOperation;
13
14#[cfg(not(any(
15    target_os = "aix",
16    target_os = "dragonfly",
17    target_os = "illumos",
18    target_os = "netbsd",
19    target_os = "openbsd",
20    target_os = "redox",
21    target_os = "solaris",
22)))]
23pub use backend::fs::types::FallocateFlags;
24
25pub use backend::fs::types::Stat;
26
27#[cfg(not(any(
28    target_os = "haiku",
29    target_os = "illumos",
30    target_os = "netbsd",
31    target_os = "redox",
32    target_os = "solaris",
33    target_os = "wasi",
34)))]
35pub use backend::fs::types::StatFs;
36
37#[cfg(not(any(
38    target_os = "haiku",
39    target_os = "illumos",
40    target_os = "redox",
41    target_os = "solaris",
42    target_os = "wasi",
43)))]
44pub use backend::fs::types::{StatVfs, StatVfsMountFlags};
45
46#[cfg(any(target_os = "android", target_os = "linux"))]
47pub use backend::fs::types::FsWord;
48
49/// Timestamps used by [`utimensat`] and [`futimens`].
50///
51/// [`utimensat`]: crate::fs::utimensat
52/// [`futimens`]: crate::fs::futimens
53// This is `repr(C)` and specifically laid out to match the representation used
54// by `utimensat` and `futimens`, which expect 2-element arrays of timestamps.
55#[repr(C)]
56#[derive(Clone, Debug)]
57pub struct Timestamps {
58    /// The timestamp of the last access to a filesystem object.
59    pub last_access: crate::fs::Timespec,
60
61    /// The timestamp of the last modification of a filesystem object.
62    pub last_modification: crate::fs::Timespec,
63}
64
65/// The filesystem magic number for procfs.
66///
67/// See [the `fstatfs` man page] for more information.
68///
69/// [the `fstatfs` man page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION
70#[cfg(any(target_os = "android", target_os = "linux"))]
71pub const PROC_SUPER_MAGIC: FsWord = backend::fs::types::PROC_SUPER_MAGIC;
72
73/// The filesystem magic number for NFS.
74///
75/// See [the `fstatfs` man page] for more information.
76///
77/// [the `fstatfs` man page]: https://man7.org/linux/man-pages/man2/fstatfs.2.html#DESCRIPTION
78#[cfg(any(target_os = "android", target_os = "linux"))]
79pub const NFS_SUPER_MAGIC: FsWord = backend::fs::types::NFS_SUPER_MAGIC;
80
81/// `lseek(fd, offset, whence)`—Repositions a file descriptor within a file.
82///
83/// # References
84///  - [POSIX]
85///  - [Linux]
86///
87/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html
88/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
89#[inline]
90#[doc(alias = "lseek")]
91pub fn seek<Fd: AsFd>(fd: Fd, pos: SeekFrom) -> io::Result<u64> {
92    backend::fs::syscalls::seek(fd.as_fd(), pos)
93}
94
95/// `lseek(fd, 0, SEEK_CUR)`—Returns the current position within a file.
96///
97/// Return the current position of the file descriptor. This is a subset of
98/// the functionality of `seek`, but this interface makes it easier for users
99/// to declare their intent not to mutate any state.
100///
101/// # References
102///  - [POSIX]
103///  - [Linux]
104///
105/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html
106/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
107#[inline]
108#[doc(alias = "lseek")]
109pub fn tell<Fd: AsFd>(fd: Fd) -> io::Result<u64> {
110    backend::fs::syscalls::tell(fd.as_fd())
111}
112
113/// `fchmod(fd)`—Sets open file or directory permissions.
114///
115/// This implementation does not support `O_PATH` file descriptors, even on
116/// platforms where the host libc emulates it.
117///
118/// # References
119///  - [POSIX]
120///  - [Linux]
121///
122/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html
123/// [Linux]: https://man7.org/linux/man-pages/man2/fchmod.2.html
124#[cfg(not(target_os = "wasi"))]
125#[inline]
126pub fn fchmod<Fd: AsFd>(fd: Fd, mode: Mode) -> io::Result<()> {
127    backend::fs::syscalls::fchmod(fd.as_fd(), mode)
128}
129
130/// `fchown(fd)`—Sets open file or directory ownership.
131///
132/// # References
133///  - [POSIX]
134///  - [Linux]
135///
136/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html
137/// [Linux]: https://man7.org/linux/man-pages/man2/fchown.2.html
138#[cfg(not(target_os = "wasi"))]
139#[inline]
140pub fn fchown<Fd: AsFd>(fd: Fd, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()> {
141    backend::fs::syscalls::fchown(fd.as_fd(), owner, group)
142}
143
144/// `fstat(fd)`—Queries metadata for an open file or directory.
145///
146/// [`Mode::from_raw_mode`] and [`FileType::from_raw_mode`] may be used to
147/// interpret the `st_mode` field.
148///
149/// # References
150///  - [POSIX]
151///  - [Linux]
152///
153/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstat.html
154/// [Linux]: https://man7.org/linux/man-pages/man2/fstat.2.html
155/// [`Mode::from_raw_mode`]: crate::fs::Mode::from_raw_mode
156/// [`FileType::from_raw_mode`]: crate::fs::FileType::from_raw_mode
157#[inline]
158pub fn fstat<Fd: AsFd>(fd: Fd) -> io::Result<Stat> {
159    backend::fs::syscalls::fstat(fd.as_fd())
160}
161
162/// `fstatfs(fd)`—Queries filesystem statistics for an open file or directory.
163///
164/// Compared to [`fstatvfs`], this function often provides more information,
165/// though it's less portable.
166///
167/// # References
168///  - [Linux]
169///
170/// [Linux]: https://man7.org/linux/man-pages/man2/fstatfs.2.html
171#[cfg(not(any(
172    target_os = "haiku",
173    target_os = "illumos",
174    target_os = "netbsd",
175    target_os = "redox",
176    target_os = "solaris",
177    target_os = "wasi",
178)))]
179#[inline]
180pub fn fstatfs<Fd: AsFd>(fd: Fd) -> io::Result<StatFs> {
181    backend::fs::syscalls::fstatfs(fd.as_fd())
182}
183
184/// `fstatvfs(fd)`—Queries filesystem statistics for an open file or
185/// directory, POSIX version.
186///
187/// Compared to [`fstatfs`], this function often provides less information,
188/// but it is more portable. But even so, filesystems are very diverse and not
189/// all the fields are meaningful for every filesystem. And `f_fsid` doesn't
190/// seem to have a clear meaning anywhere.
191///
192/// # References
193///  - [POSIX]
194///  - [Linux]
195///
196/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html
197/// [Linux]: https://man7.org/linux/man-pages/man2/fstatvfs.2.html
198#[cfg(not(any(
199    target_os = "haiku",
200    target_os = "illumos",
201    target_os = "redox",
202    target_os = "solaris",
203    target_os = "wasi",
204)))]
205#[inline]
206pub fn fstatvfs<Fd: AsFd>(fd: Fd) -> io::Result<StatVfs> {
207    backend::fs::syscalls::fstatvfs(fd.as_fd())
208}
209
210/// `futimens(fd, times)`—Sets timestamps for an open file or directory.
211///
212/// # References
213///  - [POSIX]
214///  - [Linux]
215///
216/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
217/// [Linux]: https://man7.org/linux/man-pages/man2/utimensat.2.html
218#[inline]
219pub fn futimens<Fd: AsFd>(fd: Fd, times: &Timestamps) -> io::Result<()> {
220    backend::fs::syscalls::futimens(fd.as_fd(), times)
221}
222
223/// `fallocate(fd, mode, offset, len)`—Adjusts file allocation.
224///
225/// This is a more general form of `posix_fallocate`, adding a `mode` argument
226/// which modifies the behavior. On platforms which only support
227/// `posix_fallocate` and not the more general form, no `FallocateFlags` values
228/// are defined so it will always be empty.
229///
230/// # References
231///  - [POSIX]
232///  - [Linux `fallocate`]
233///  - [Linux `posix_fallocate`]
234///
235/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html
236/// [Linux `fallocate`]: https://man7.org/linux/man-pages/man2/fallocate.2.html
237/// [Linux `posix_fallocate`]: https://man7.org/linux/man-pages/man3/posix_fallocate.3.html
238#[cfg(not(any(
239    target_os = "aix",
240    target_os = "dragonfly",
241    target_os = "illumos",
242    target_os = "netbsd",
243    target_os = "openbsd",
244    target_os = "redox",
245    target_os = "solaris",
246)))] // not implemented in libc for netbsd yet
247#[inline]
248#[doc(alias = "posix_fallocate")]
249pub fn fallocate<Fd: AsFd>(fd: Fd, mode: FallocateFlags, offset: u64, len: u64) -> io::Result<()> {
250    backend::fs::syscalls::fallocate(fd.as_fd(), mode, offset, len)
251}
252
253/// `fcntl(fd, F_GETFL) & O_ACCMODE`
254///
255/// Returns a pair of booleans indicating whether the file descriptor is
256/// readable and/or writable, respectively. This is only reliable on files; for
257/// example, it doesn't reflect whether sockets have been shut down; for
258/// general I/O handle support, use [`io::is_read_write`].
259#[inline]
260pub fn is_file_read_write<Fd: AsFd>(fd: Fd) -> io::Result<(bool, bool)> {
261    _is_file_read_write(fd.as_fd())
262}
263
264pub(crate) fn _is_file_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
265    let mode = backend::fs::syscalls::fcntl_getfl(fd)?;
266
267    // Check for `O_PATH`.
268    #[cfg(any(
269        target_os = "android",
270        target_os = "fuchsia",
271        target_os = "linux",
272        target_os = "emscripten",
273    ))]
274    if mode.contains(crate::fs::OFlags::PATH) {
275        return Ok((false, false));
276    }
277
278    // Use `RWMODE` rather than `ACCMODE` as `ACCMODE` may include `O_PATH`.
279    // We handled `O_PATH` above.
280    match mode & crate::fs::OFlags::RWMODE {
281        crate::fs::OFlags::RDONLY => Ok((true, false)),
282        crate::fs::OFlags::RDWR => Ok((true, true)),
283        crate::fs::OFlags::WRONLY => Ok((false, true)),
284        _ => unreachable!(),
285    }
286}
287
288/// `fsync(fd)`—Ensures that file data and metadata is written to the
289/// underlying storage device.
290///
291/// On iOS and macOS this isn't sufficient to ensure that data has reached
292/// persistent storage; use [`fcntl_fullfsync`] to ensure that.
293///
294/// # References
295///  - [POSIX]
296///  - [Linux]
297///
298/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html
299/// [Linux]: https://man7.org/linux/man-pages/man2/fsync.2.html
300/// [`fcntl_fullfsync`]: https://docs.rs/rustix/*/x86_64-apple-darwin/rustix/fs/fn.fcntl_fullfsync.html
301#[inline]
302pub fn fsync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
303    backend::fs::syscalls::fsync(fd.as_fd())
304}
305
306/// `fdatasync(fd)`—Ensures that file data is written to the underlying
307/// storage device.
308///
309/// # References
310///  - [POSIX]
311///  - [Linux]
312///
313/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html
314/// [Linux]: https://man7.org/linux/man-pages/man2/fdatasync.2.html
315#[cfg(not(any(
316    target_os = "dragonfly",
317    target_os = "haiku",
318    target_os = "ios",
319    target_os = "macos",
320    target_os = "redox",
321)))]
322#[inline]
323pub fn fdatasync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
324    backend::fs::syscalls::fdatasync(fd.as_fd())
325}
326
327/// `ftruncate(fd, length)`—Sets the length of a file.
328///
329/// # References
330///  - [POSIX]
331///  - [Linux]
332///
333/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
334/// [Linux]: https://man7.org/linux/man-pages/man2/ftruncate.2.html
335#[inline]
336pub fn ftruncate<Fd: AsFd>(fd: Fd, length: u64) -> io::Result<()> {
337    backend::fs::syscalls::ftruncate(fd.as_fd(), length)
338}
339
340/// `flock(fd, operation)`—Acquire or release an advisory lock on an open file.
341///
342/// # References
343///  - [Linux]
344///
345/// [Linux]: https://man7.org/linux/man-pages/man2/flock.2.html
346#[cfg(not(any(target_os = "solaris", target_os = "wasi")))]
347#[inline]
348pub fn flock<Fd: AsFd>(fd: Fd, operation: FlockOperation) -> io::Result<()> {
349    backend::fs::syscalls::flock(fd.as_fd(), operation)
350}
351