From f15530b8ed29fc17f8709cfdc2a7034c63ddc103 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 22 Mar 2024 14:50:56 -0600 Subject: [PATCH] Fix the build with the next version of libc The next version of libc includes some backwards-incompatible changes. Fixes #2342 --- Cargo.toml | 2 +- src/sys/select.rs | 5 +++-- src/unistd.rs | 35 ++++++++++++++++++++++++++++++----- test/sys/test_timer.rs | 1 - 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index adaf31f0fd..84fcb0d310 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ targets = [ ] [dependencies] -libc = { version = "0.2.153", features = ["extra_traits"] } +libc = { git = "https://github.com/rust-lang/libc", rev = "a0f5b4b21391252fe38b2df9310dc65e37b07d9f", features = ["extra_traits", "const-extern-fn"] } bitflags = "2.3.1" cfg-if = "1.0" pin-utils = { version = "0.1.0", optional = true } diff --git a/src/sys/select.rs b/src/sys/select.rs index 64a8e258cf..16b3d8ea98 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -22,7 +22,7 @@ pub struct FdSet<'fd> { fn assert_fd_valid(fd: RawFd) { assert!( - usize::try_from(fd).map_or(false, |fd| fd < FD_SETSIZE), + fd < RawFd::try_from(FD_SETSIZE).unwrap_or(RawFd::min_value()), "fd must be in the range 0..FD_SETSIZE", ); } @@ -107,10 +107,11 @@ impl<'fd> FdSet<'fd> { /// assert_eq!(fds, vec![4, 9]); /// ``` #[inline] + #[allow(clippy::unnecessary_cast)] // Not unnecessary with libc 0.2.154+ pub fn fds(&self, highest: Option) -> Fds { Fds { set: self, - range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE), + range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE as usize), } } } diff --git a/src/unistd.rs b/src/unistd.rs index 4502766c5d..47f0edd3cb 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -823,7 +823,12 @@ fn to_exec_array>(args: &[S]) -> Vec<*const c_char> { pub fn execv>(path: &CStr, argv: &[S]) -> Result { let args_p = to_exec_array(argv); - unsafe { libc::execv(path.as_ptr(), args_p.as_ptr()) }; + // SAFETY: + // The const cast looks unsafe. But it's actually fine. The problem is that POSIX requires + // "execv" and friends to take mutable pointers in their signatures, even while it prohibits + // them from actually modifying those arguments. See discussion at + // https://github.com/rust-lang/libc/issues/1272 . + unsafe { libc::execv(path.as_ptr(), args_p.as_ptr() as *const _) }; Err(Errno::last()) } @@ -849,7 +854,12 @@ pub fn execve, SE: AsRef>( let args_p = to_exec_array(args); let env_p = to_exec_array(env); - unsafe { libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) }; + // SAFETY: + // The const cast looks unsafe. But it's actually fine. The problem is that POSIX requires + // "execv" and friends to take mutable pointers in their signatures, even while it prohibits + // them from actually modifying those arguments. See discussion at + // https://github.com/rust-lang/libc/issues/1272 . + unsafe { libc::execve(path.as_ptr(), args_p.as_ptr() as *const _, env_p.as_ptr() as *const _) }; Err(Errno::last()) } @@ -870,7 +880,12 @@ pub fn execvp>( ) -> Result { let args_p = to_exec_array(args); - unsafe { libc::execvp(filename.as_ptr(), args_p.as_ptr()) }; + // SAFETY: + // The const cast looks unsafe. But it's actually fine. The problem is that POSIX requires + // "execv" and friends to take mutable pointers in their signatures, even while it prohibits + // them from actually modifying those arguments. See discussion at + // https://github.com/rust-lang/libc/issues/1272 . + unsafe { libc::execvp(filename.as_ptr(), args_p.as_ptr() as *const _) }; Err(Errno::last()) } @@ -891,8 +906,13 @@ pub fn execvpe, SE: AsRef>( let args_p = to_exec_array(args); let env_p = to_exec_array(env); + // SAFETY: + // The const cast looks unsafe. But it's actually fine. The problem is that POSIX requires + // "execv" and friends to take mutable pointers in their signatures, even while it prohibits + // them from actually modifying those arguments. See discussion at + // https://github.com/rust-lang/libc/issues/1272 . unsafe { - libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) + libc::execvpe(filename.as_ptr(), args_p.as_ptr() as *const _, env_p.as_ptr() as *const _) }; Err(Errno::last()) @@ -918,7 +938,12 @@ pub fn fexecve, SE: AsRef>( let args_p = to_exec_array(args); let env_p = to_exec_array(env); - unsafe { libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr()) }; + // SAFETY: + // The const cast looks unsafe. But it's actually fine. The problem is that POSIX requires + // "execv" and friends to take mutable pointers in their signatures, even while it prohibits + // them from actually modifying those arguments. See discussion at + // https://github.com/rust-lang/libc/issues/1272 . + unsafe { libc::fexecve(fd, args_p.as_ptr() as *const _, env_p.as_ptr() as *const _) }; Err(Errno::last()) } diff --git a/test/sys/test_timer.rs b/test/sys/test_timer.rs index ffd146867b..c18876fc78 100644 --- a/test/sys/test_timer.rs +++ b/test/sys/test_timer.rs @@ -4,7 +4,6 @@ use nix::sys::signal::{ }; use nix::sys::timer::{Expiration, Timer, TimerSetTimeFlags}; use nix::time::ClockId; -use std::convert::TryFrom; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; use std::time::{Duration, Instant};