1 //! Functions which operate on file descriptors.
2
3 #[cfg(not(target_os = "wasi"))]
4 use crate::fs::Mode;
5 use crate::io::SeekFrom;
6 #[cfg(not(target_os = "wasi"))]
7 use crate::process::{Gid, Uid};
8 use crate::{backend, io};
9 use backend::fd::{AsFd, BorrowedFd};
10
11 #[cfg(not(any(target_os = "solaris", target_os = "wasi")))]
12 pub 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 )))]
23 pub use backend::fs::types::FallocateFlags;
24
25 pub 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 )))]
35 pub 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 )))]
44 pub use backend::fs::types::{StatVfs, StatVfsMountFlags};
45
46 #[cfg(any(target_os = "android", target_os = "linux"))]
47 pub 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)]
57 pub 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"))]
71 pub 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"))]
79 pub 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")]
seek<Fd: AsFd>(fd: Fd, pos: SeekFrom) -> io::Result<u64>91 pub 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")]
tell<Fd: AsFd>(fd: Fd) -> io::Result<u64>109 pub 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]
fchmod<Fd: AsFd>(fd: Fd, mode: Mode) -> io::Result<()>126 pub 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]
fchown<Fd: AsFd>(fd: Fd, owner: Option<Uid>, group: Option<Gid>) -> io::Result<()>140 pub 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]
fstat<Fd: AsFd>(fd: Fd) -> io::Result<Stat>158 pub 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]
fstatfs<Fd: AsFd>(fd: Fd) -> io::Result<StatFs>180 pub 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]
fstatvfs<Fd: AsFd>(fd: Fd) -> io::Result<StatVfs>206 pub 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]
futimens<Fd: AsFd>(fd: Fd, times: &Timestamps) -> io::Result<()>219 pub 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")]
fallocate<Fd: AsFd>(fd: Fd, mode: FallocateFlags, offset: u64, len: u64) -> io::Result<()>249 pub 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]
is_file_read_write<Fd: AsFd>(fd: Fd) -> io::Result<(bool, bool)>260 pub fn is_file_read_write<Fd: AsFd>(fd: Fd) -> io::Result<(bool, bool)> {
261 _is_file_read_write(fd.as_fd())
262 }
263
_is_file_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)>264 pub(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]
fsync<Fd: AsFd>(fd: Fd) -> io::Result<()>302 pub 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]
fdatasync<Fd: AsFd>(fd: Fd) -> io::Result<()>323 pub 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]
ftruncate<Fd: AsFd>(fd: Fd, length: u64) -> io::Result<()>336 pub 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]
flock<Fd: AsFd>(fd: Fd, operation: FlockOperation) -> io::Result<()>348 pub fn flock<Fd: AsFd>(fd: Fd, operation: FlockOperation) -> io::Result<()> {
349 backend::fs::syscalls::flock(fd.as_fd(), operation)
350 }
351