Coverage Report

Created: 2025-10-29 07:05

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