Skip to content

Commit 714cbf8

Browse files
authored
Implement Apple fcntls for disabling caching (#762)
* Implement Apple fcntls for disabling caching Add `fcntl_nocache` and `fcntl_global_nocache` to wrap the Apple `F_NOCACHE` and `F_GLOBAL_NOCACHE` fcntls. Fixes #761. * Make the test file non-empty.
1 parent ecdb02e commit 714cbf8

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed

src/backend/libc/fs/syscalls.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,22 @@ pub(crate) fn fcntl_fullfsync(fd: BorrowedFd<'_>) -> io::Result<()> {
19771977
unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_FULLFSYNC)) }
19781978
}
19791979

1980+
#[cfg(apple)]
1981+
pub(crate) fn fcntl_nocache(fd: BorrowedFd, value: bool) -> io::Result<()> {
1982+
unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_NOCACHE, value as c::c_int)) }
1983+
}
1984+
1985+
#[cfg(apple)]
1986+
pub(crate) fn fcntl_global_nocache(fd: BorrowedFd, value: bool) -> io::Result<()> {
1987+
unsafe {
1988+
ret(c::fcntl(
1989+
borrowed_fd(fd),
1990+
c::F_GLOBAL_NOCACHE,
1991+
value as c::c_int,
1992+
))
1993+
}
1994+
}
1995+
19801996
/// Convert `times` from a `futimens`/`utimensat` argument into `setattrlist`
19811997
/// arguments.
19821998
#[cfg(apple)]

src/clockid.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ pub enum ClockId {
5252
/// has to fail with `INVAL` due to an unsupported clock. See
5353
/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not
5454
/// all of them are always supported.
55+
///
56+
/// [`clock_gettime`]: crate::time::clock_gettime
5557
#[cfg(apple)]
5658
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
5759
#[repr(u32)]

src/fs/fcntl_apple.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use backend::fd::AsFd;
77
/// - [Apple]
88
///
99
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
10+
#[doc(alias = "F_RDADVISE")]
1011
#[inline]
1112
pub fn fcntl_rdadvise<Fd: AsFd>(fd: Fd, offset: u64, len: u64) -> io::Result<()> {
1213
backend::fs::syscalls::fcntl_rdadvise(fd.as_fd(), offset, len)
@@ -18,7 +19,48 @@ pub fn fcntl_rdadvise<Fd: AsFd>(fd: Fd, offset: u64, len: u64) -> io::Result<()>
1819
/// - [Apple]
1920
///
2021
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
22+
#[doc(alias = "F_FULLSYNC")]
2123
#[inline]
2224
pub fn fcntl_fullfsync<Fd: AsFd>(fd: Fd) -> io::Result<()> {
2325
backend::fs::syscalls::fcntl_fullfsync(fd.as_fd())
2426
}
27+
28+
/// `fcntl(fd, F_NOCACHE, value)`—Turn data caching off or on for a file
29+
/// descriptor.
30+
///
31+
/// See [this mailing list post] for additional information about the meanings
32+
/// of `F_NOCACHE` and `F_GLOBAL_NOCACHE`.
33+
///
34+
/// [this mailing list post]: https://lists.apple.com/archives/filesystem-dev/2007/Sep/msg00010.html
35+
///
36+
/// See also [`fcntl_global_nocache`].
37+
///
38+
/// # References
39+
/// - [Apple]
40+
///
41+
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
42+
#[doc(alias = "F_NOCACHE")]
43+
#[inline]
44+
pub fn fcntl_nocache<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
45+
backend::fs::syscalls::fcntl_nocache(fd.as_fd(), value)
46+
}
47+
48+
/// `fcntl(fd, F_GLOBAL_NOCACHE, value)`—Turn data caching off or on for all
49+
/// file descriptors.
50+
///
51+
/// See [this mailing list post] for additional information about the meanings
52+
/// of `F_NOCACHE` and `F_GLOBAL_NOCACHE`.
53+
///
54+
/// [this mailing list post]: https://lists.apple.com/archives/filesystem-dev/2007/Sep/msg00010.html
55+
///
56+
/// See also [`fcntl_nocache`].
57+
///
58+
/// # References
59+
/// - [Apple]
60+
///
61+
/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html
62+
#[doc(alias = "F_GLOBAL_NOCACHE")]
63+
#[inline]
64+
pub fn fcntl_global_nocache<Fd: AsFd>(fd: Fd, value: bool) -> io::Result<()> {
65+
backend::fs::syscalls::fcntl_global_nocache(fd.as_fd(), value)
66+
}

src/fs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub use dir::{Dir, DirEntry};
8484
pub use fadvise::{fadvise, Advice};
8585
pub use fcntl::*;
8686
#[cfg(apple)]
87-
pub use fcntl_apple::{fcntl_fullfsync, fcntl_rdadvise};
87+
pub use fcntl_apple::*;
8888
#[cfg(apple)]
8989
pub use fcopyfile::*;
9090
pub use fd::*;

tests/fs/fcntl.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,32 @@ fn test_fcntl_dupfd_cloexec() {
1515
let new = rustix::fs::fcntl_dupfd_cloexec(&file, 700).unwrap();
1616
assert_eq!(new.as_fd().as_raw_fd(), 700);
1717
}
18+
19+
#[cfg(apple)]
20+
#[test]
21+
fn test_fcntl_apple() {
22+
use rustix::fs::{openat, Mode, OFlags, CWD};
23+
24+
let tmp = tempfile::tempdir().unwrap();
25+
let dir = openat(CWD, tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
26+
let foo = openat(
27+
&dir,
28+
"foo",
29+
OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC,
30+
Mode::RUSR | Mode::WUSR,
31+
)
32+
.unwrap();
33+
34+
// It appears `fsync_rdadvise` at offset 0 length 0 doesn't work if the
35+
// file has size zero, so write in some bytes.
36+
assert_eq!(
37+
rustix::io::write(&foo, b"data").expect("write"),
38+
4,
39+
"write failed"
40+
);
41+
42+
rustix::fs::fcntl_rdadvise(&foo, 0, 0).unwrap();
43+
rustix::fs::fcntl_fullfsync(&foo).unwrap();
44+
rustix::fs::fcntl_nocache(&foo, true).unwrap();
45+
rustix::fs::fcntl_global_nocache(&foo, true).unwrap();
46+
}

0 commit comments

Comments
 (0)