From 68c230b37e82c6e714cbd7b5b1b9c3785fda2438 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 3 Oct 2023 10:16:32 +0100 Subject: [PATCH] fcntl add F_GETPATH support for apple/netbsd/dragonfly (#2142) * fcntl add F_GETPATH support for apple/netbsd * changes from review * CHANGELOG entry --------- Co-authored-by: SteveLauC --- CHANGELOG.md | 3 +++ src/fcntl.rs | 25 +++++++++++++++++++++++++ test/test_fcntl.rs | 23 +++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f73e2a0e78..aaab7b2d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,9 @@ This project adheres to [Semantic Versioning](https://semver.org/). - Added `Icmp` and `IcmpV6` to `SockProtocol`. (#[2103](https://github.com/nix-rust/nix/pull/2103)) +- Added `F_GETPATH` FcntlFlags entry on Apple/NetBSD/DragonflyBSD for `::nix::fcntl`. + ([#2142](https://github.com/nix-rust/nix/pull/2142)) + - Added `Ipv6HopLimit` to `::nix::sys::socket::ControlMessage` for Linux, MacOS, FreeBSD, DragonflyBSD, Android, iOS and Haiku. ([#2074](https://github.com/nix-rust/nix/pull/2074)) diff --git a/src/fcntl.rs b/src/fcntl.rs index 1ee8c96352..a711a41170 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -1,11 +1,25 @@ use crate::errno::Errno; use libc::{self, c_int, c_uint, size_t, ssize_t}; +#[cfg(any( + target_os = "netbsd", + target_os = "macos", + target_os = "ios", + target_os = "dragonfly", +))] +use std::ffi::CStr; use std::ffi::OsString; #[cfg(not(target_os = "redox"))] use std::os::raw; use std::os::unix::ffi::OsStringExt; use std::os::unix::io::RawFd; // For splice and copy_file_range +#[cfg(any( + target_os = "netbsd", + target_os = "macos", + target_os = "ios", + target_os = "dragonfly", +))] +use std::path::PathBuf; #[cfg(any( target_os = "android", target_os = "freebsd", @@ -489,6 +503,8 @@ pub enum FcntlArg<'a> { F_GETPIPE_SZ, #[cfg(any(target_os = "linux", target_os = "android"))] F_SETPIPE_SZ(c_int), + #[cfg(any(target_os = "netbsd", target_os = "dragonfly", target_os = "macos", target_os = "ios"))] + F_GETPATH(&'a mut PathBuf), // TODO: Rest of flags } @@ -549,6 +565,15 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result { F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ), #[cfg(any(target_os = "linux", target_os = "android"))] F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size), + #[cfg(any(target_os = "dragonfly", target_os = "netbsd", target_os = "macos", target_os = "ios"))] + F_GETPATH(path) => { + let mut buffer = vec![0; libc::PATH_MAX as usize]; + let res = libc::fcntl(fd, libc::F_GETPATH, buffer.as_mut_ptr()); + let ok_res = Errno::result(res)?; + let optr = CStr::from_bytes_until_nul(&buffer).unwrap(); + *path = PathBuf::from(OsString::from(optr.to_str().unwrap())); + return Ok(ok_res) + }, } }; diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 45698490b6..0faf39d237 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -561,3 +561,26 @@ mod test_posix_fallocate { } } } + +#[cfg(any( + target_os = "dragonfly", + target_os = "netbsd", + target_os = "macos", + target_os = "ios" +))] +#[test] +fn test_f_get_path() { + use nix::fcntl::*; + use std::{os::unix::io::AsRawFd, path::PathBuf}; + + let tmp = NamedTempFile::new().unwrap(); + let fd = tmp.as_raw_fd(); + let mut path = PathBuf::new(); + let res = + fcntl(fd, FcntlArg::F_GETPATH(&mut path)).expect("get path failed"); + assert_ne!(res, -1); + assert_eq!( + path.as_path().canonicalize().unwrap(), + tmp.path().canonicalize().unwrap() + ); +}