Coverage Report

Created: 2024-07-06 06:44

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