From 9d6bdcb1107a594667b84bfe55ad87b7dde804d0 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 3 Sep 2024 21:56:16 +0100 Subject: [PATCH 1/3] fcntl: adding macOs F_RDADVISE flag Hints to prefetch blocks of the file into memory when possible. Can be useful to process large files. --- src/fcntl.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/fcntl.rs b/src/fcntl.rs index a5dca8a539..49fa29a01e 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -2,6 +2,8 @@ use crate::errno::Errno; #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] use core::slice; +#[cfg(apple_targets)] +use libc::off_t; use libc::{c_int, c_uint, size_t, ssize_t}; #[cfg(any( target_os = "netbsd", @@ -797,6 +799,9 @@ pub enum FcntlArg<'a> { /// Return the full path without firmlinks of the fd. #[cfg(apple_targets)] F_GETPATH_NOFIRMLINK(&'a mut PathBuf), + /// Issue an advisory read async with no copy to user + #[cfg(apple_targets)] + F_RDADVISE(off_t, c_int), // TODO: Rest of flags } @@ -905,6 +910,14 @@ pub fn fcntl(fd: Fd, arg: FcntlArg) -> Result { *path = PathBuf::from(OsString::from(optr.to_str().unwrap())); return Ok(ok_res) }, + #[cfg(apple_targets)] + F_RDADVISE(offset, count) => { + let rad = libc::radvisory { + ra_offset: offset, + ra_count: count, + }; + libc::fcntl(fd, libc::F_RDADVISE, &rad) + } } }; From 5639670ff304238c0488b394911f740b80b79328 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 3 Sep 2024 22:07:23 +0100 Subject: [PATCH 2/3] add changelog entry --- changelog/2480.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/2480.added.md diff --git a/changelog/2480.added.md b/changelog/2480.added.md new file mode 100644 index 0000000000..d0f1d59271 --- /dev/null +++ b/changelog/2480.added.md @@ -0,0 +1 @@ +Add fcntl constant `F_RDADVISE` for Apple target From bf5ef1194ddff8bf98d6e05190849e9d79c538ca Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 4 Sep 2024 05:46:18 +0100 Subject: [PATCH 3/3] testing --- changelog/2113.added.md | 2 +- src/fcntl.rs | 10 ++-------- test/test_fcntl.rs | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/changelog/2113.added.md b/changelog/2113.added.md index be654b5dd5..48ca3ac465 100644 --- a/changelog/2113.added.md +++ b/changelog/2113.added.md @@ -1 +1 @@ -Add socket option `IPV6_PKTINFO` for BSDs/Linux/Android, also `IPV6_RECVPKTINFO` for DragonFlyBSD \ No newline at end of file +Add socket option `IPV6_PKTINFO` for BSDs/Linux/Android, also `IPV6_RECVPKTINFO` for DragonFlyBSD diff --git a/src/fcntl.rs b/src/fcntl.rs index 49fa29a01e..515b45b4d0 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -2,8 +2,6 @@ use crate::errno::Errno; #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] use core::slice; -#[cfg(apple_targets)] -use libc::off_t; use libc::{c_int, c_uint, size_t, ssize_t}; #[cfg(any( target_os = "netbsd", @@ -801,7 +799,7 @@ pub enum FcntlArg<'a> { F_GETPATH_NOFIRMLINK(&'a mut PathBuf), /// Issue an advisory read async with no copy to user #[cfg(apple_targets)] - F_RDADVISE(off_t, c_int), + F_RDADVISE(libc::radvisory), // TODO: Rest of flags } @@ -911,11 +909,7 @@ pub fn fcntl(fd: Fd, arg: FcntlArg) -> Result { return Ok(ok_res) }, #[cfg(apple_targets)] - F_RDADVISE(offset, count) => { - let rad = libc::radvisory { - ra_offset: offset, - ra_count: count, - }; + F_RDADVISE(rad) => { libc::fcntl(fd, libc::F_RDADVISE, &rad) } } diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index d49f49670f..f8eddd3cde 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -732,3 +732,23 @@ mod test_flock { .expect_err("Should not have been able to lock the file"); } } + +#[cfg(apple_targets)] +#[test] +fn test_f_rdadvise() { + use nix::fcntl::*; + + let contents = vec![1; 1024]; + let mut buf = [0; 1024]; + let mut tmp = NamedTempFile::new().unwrap(); + tmp.write_all(&contents).unwrap(); + let fd = open(tmp.path(), OFlag::empty(), Mode::empty()).unwrap(); + let rad = libc::radvisory { + ra_offset: 0, + ra_count: contents.len() as _, + }; + let res = fcntl(&tmp, FcntlArg::F_RDADVISE(rad)).expect("rdadivse failed"); + assert_ne!(res, -1); + assert_eq!(contents.len(), read(&fd, &mut buf).unwrap()); + assert_eq!(contents, &buf[0..contents.len()]); +}