1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
//! Functions which operate on file descriptors.
use crate::{imp, io};
#[cfg(not(any(target_os = "netbsd", target_os = "openbsd", target_os = "redox")))]
use imp::fs::FallocateFlags;
use imp::fs::Stat;
#[cfg(not(any(target_os = "netbsd", target_os = "redox", target_os = "wasi")))]
// not implemented in libc for netbsd yet
use imp::fs::StatFs;
#[cfg(not(target_os = "wasi"))]
use imp::fs::{FlockOperation, Mode};
use imp::time::Timespec;
use io_lifetimes::{AsFd, BorrowedFd};
use std::io::SeekFrom;
/// `lseek(fd, offset, whence)`—Repositions a file descriptor within a file.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html
/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
#[inline]
pub fn seek<Fd: AsFd>(fd: &Fd, pos: SeekFrom) -> io::Result<u64> {
let fd = fd.as_fd();
imp::syscalls::seek(fd, pos)
}
/// `lseek(fd, 0, SEEK_CUR)`—Returns the current position within a file.
///
/// Return the current position of the file descriptor. This is a subset of
/// the functionality of `seek`, but this interface makes it easier for users
/// to declare their intent not to mutate any state.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html
/// [Linux]: https://man7.org/linux/man-pages/man2/lseek.2.html
#[inline]
pub fn tell<Fd: AsFd>(fd: &Fd) -> io::Result<u64> {
let fd = fd.as_fd();
imp::syscalls::tell(fd)
}
/// `fchmod(fd)`—Sets open file or directory permissions.
///
/// Note that this implementation does not support `O_PATH` file descriptors,
/// even on platforms where the host libc emulates it.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fchmod.2.html
#[cfg(not(target_os = "wasi"))]
#[inline]
pub fn fchmod<Fd: AsFd>(fd: &Fd, mode: Mode) -> io::Result<()> {
let fd = fd.as_fd();
imp::syscalls::fchmod(fd, mode)
}
/// `fstat(fd)`—Queries metadata for an open file or directory.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstat.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fstat.2.html
#[inline]
pub fn fstat<Fd: AsFd>(fd: &Fd) -> io::Result<Stat> {
let fd = fd.as_fd();
imp::syscalls::fstat(fd)
}
/// `fstatfs(fd)`—Queries filesystem statistics for an open file or directory.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/fstatfs.2.html
#[cfg(not(any(target_os = "netbsd", target_os = "redox", target_os = "wasi")))] // not implemented in libc for netbsd yet
#[inline]
pub fn fstatfs<Fd: AsFd>(fd: &Fd) -> io::Result<StatFs> {
let fd = fd.as_fd();
imp::syscalls::fstatfs(fd)
}
/// `futimens(fd, times)`—Sets timestamps for an open file or directory.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
/// [Linux]: https://man7.org/linux/man-pages/man2/futimens.2.html
#[inline]
pub fn futimens<Fd: AsFd>(fd: &Fd, times: &[Timespec; 2]) -> io::Result<()> {
let fd = fd.as_fd();
imp::syscalls::futimens(fd, times)
}
/// `fallocate(fd, mode, offset, len)`—Adjusts file allocation.
///
/// This is a more general form of `posix_fallocate`, adding a `mode` argument
/// which modifies the behavior. On platforms which only support
/// `posix_fallocate` and not the more general form, no `FallocateFlags` values
/// are defined so it will always be empty.
///
/// # References
/// - [POSIX]
/// - [Linux `fallocate`]
/// - [Linux `posix_fallocate`]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html
/// [Linux `fallocate`]: https://man7.org/linux/man-pages/man2/fallocate.2.html
/// [Linux `posix_fallocate`]: https://man7.org/linux/man-pages/man3/posix_fallocate.3.html
#[cfg(not(any(target_os = "netbsd", target_os = "openbsd", target_os = "redox")))] // not implemented in libc for netbsd yet
#[inline]
#[doc(alias = "posix_fallocate")]
pub fn fallocate<Fd: AsFd>(fd: &Fd, mode: FallocateFlags, offset: u64, len: u64) -> io::Result<()> {
let fd = fd.as_fd();
imp::syscalls::fallocate(fd, mode, offset, len)
}
/// `fcntl(fd, F_GETFL) & O_ACCMODE`
///
/// Returns a pair of booleans indicating whether the file descriptor is
/// readable and/or writeable, respectively. This is only reliable on files;
/// for example, it doesn't reflect whether sockets have been shut down; for
/// general I/O handle support, use [`io::is_read_write`].
#[inline]
pub fn is_file_read_write<Fd: AsFd>(fd: &Fd) -> io::Result<(bool, bool)> {
let fd = fd.as_fd();
_is_file_read_write(fd)
}
pub(crate) fn _is_file_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
let mode = imp::syscalls::fcntl_getfl(fd)?;
// Check for `O_PATH`.
#[cfg(any(
target_os = "android",
target_os = "fuchsia",
target_os = "linux",
target_os = "emscripten"
))]
if mode.contains(crate::fs::OFlags::PATH) {
return Ok((false, false));
}
// Use `RWMODE` rather than `ACCMODE` as `ACCMODE` may include `O_PATH`.
// We handled `O_PATH` above.
match mode & crate::fs::OFlags::RWMODE {
crate::fs::OFlags::RDONLY => Ok((true, false)),
crate::fs::OFlags::RDWR => Ok((true, true)),
crate::fs::OFlags::WRONLY => Ok((false, true)),
_ => unreachable!(),
}
}
/// `fsync(fd)`—Ensures that file data and metadata is written to the
/// underlying storage device.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fsync.2.html
#[inline]
pub fn fsync<Fd: AsFd>(fd: &Fd) -> io::Result<()> {
let fd = fd.as_fd();
imp::syscalls::fsync(fd)
}
/// `fdatasync(fd)`—Ensures that file data is written to the underlying
/// storage device.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html
/// [Linux]: https://man7.org/linux/man-pages/man2/fdatasync.2.html
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
#[inline]
pub fn fdatasync<Fd: AsFd>(fd: &Fd) -> io::Result<()> {
let fd = fd.as_fd();
imp::syscalls::fdatasync(fd)
}
/// `ftruncate(fd, length)`—Sets the length of a file.
///
/// # References
/// - [POSIX]
/// - [Linux]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
/// [Linux]: https://man7.org/linux/man-pages/man2/ftruncate.2.html
#[inline]
pub fn ftruncate<Fd: AsFd>(fd: &Fd, length: u64) -> io::Result<()> {
let fd = fd.as_fd();
imp::syscalls::ftruncate(fd, length)
}
/// `flock(fd, operation)`—Acquire or release an advisory lock on an open file.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/flock.2.html
#[cfg(not(target_os = "wasi"))]
#[inline]
pub fn flock<Fd: AsFd>(fd: &Fd, operation: FlockOperation) -> io::Result<()> {
let fd = fd.as_fd();
imp::syscalls::flock(fd, operation)
}