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