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