From a170d4dfee0468227aa961646fc72a20c2352627 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 12:16:39 -0600 Subject: [PATCH 01/10] Fix the test_fcntl::test_posix_fallocate::success test with recent ZFS POSIX 1003.1-2024 Issue 8 changed the error code for this operation, and recent ZFS versions have followed suit. So the test should accept either the old error code (EINVAL) or the new one (ENOTSUP). https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_fallocate.html --- test/test_fcntl.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 76c3b9f2dc..693935894e 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -541,13 +541,14 @@ mod test_posix_fallocate { assert_eq!(tmp.read(&mut data).expect("read failure"), LEN); assert_eq!(&data[..], &[0u8; LEN][..]); } - Err(Errno::EINVAL) => { - // POSIX requires posix_fallocate to return EINVAL both for - // invalid arguments (i.e. len < 0) and if the operation is not - // supported by the file system. - // There's no way to tell for sure whether the file system - // supports posix_fallocate, so we must pass the test if it - // returns EINVAL. + Err(Errno::ENOTSUP) | Err(Errno::EINVAL) => { + // POSIX 1003.1-2024 Issue 8 specified ENOTSUP for "the file + // system does not support this operation", so Nix should accept + // that error code and pass the test. + // But older POSIX required posix_fallocate to return EINVAL + // both for invalid arguments (i.e. len < 0) and if the + // operation is not supported by the file system. So we must + // also pass the test if it returns EINVAL. } _ => res.unwrap(), } From bd9a6fb52e436503840bb06ab8e61bccf0aa7f18 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 12:31:33 -0600 Subject: [PATCH 02/10] Clippy cleanup: mismatched_lifetime_syntaxes --- src/dir.rs | 4 ++-- src/sys/eventfd.rs | 2 +- src/sys/select.rs | 2 +- src/sys/socket/mod.rs | 2 +- src/sys/termios.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dir.rs b/src/dir.rs index b514212e60..a24bc76bb8 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -119,7 +119,7 @@ impl Dir { } /// Returns an iterator of `Result` which rewinds when finished. - pub fn iter(&mut self) -> Iter { + pub fn iter(&mut self) -> Iter<'_> { Iter(self) } } @@ -133,7 +133,7 @@ impl Dir { unsafe impl Send for Dir {} impl std::os::fd::AsFd for Dir { - fn as_fd(&self) -> std::os::fd::BorrowedFd { + fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> { let raw_fd = self.as_raw_fd(); // SAFETY: diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs index 382a72e75c..8d6e48c80b 100644 --- a/src/sys/eventfd.rs +++ b/src/sys/eventfd.rs @@ -101,7 +101,7 @@ impl EventFd { } } impl AsFd for EventFd { - fn as_fd(&self) -> BorrowedFd { + fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } diff --git a/src/sys/select.rs b/src/sys/select.rs index 29f6bd25a4..b15fab886d 100644 --- a/src/sys/select.rs +++ b/src/sys/select.rs @@ -107,7 +107,7 @@ impl<'fd> FdSet<'fd> { /// assert_eq!(fds, vec![4, 9]); /// ``` #[inline] - pub fn fds(&self, highest: Option) -> Fds { + pub fn fds(&self, highest: Option) -> Fds<'_, '_> { Fds { set: self, range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE), diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 1b38646eed..30c4e0a082 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -701,7 +701,7 @@ impl RecvMsg<'_, '_, S> { /// Iterate over the valid control messages pointed to by this msghdr. If /// allocated space for CMSGs was too small it is not safe to iterate, /// instead return an `Error::ENOBUFS` error. - pub fn cmsgs(&self) -> Result { + pub fn cmsgs(&self) -> Result> { if self.mhdr.msg_flags & MSG_CTRUNC == MSG_CTRUNC { return Err(Errno::ENOBUFS); diff --git a/src/sys/termios.rs b/src/sys/termios.rs index b2415c0aff..bff981fad5 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -178,7 +178,7 @@ impl Termios { /// /// This is not part of `nix`'s public API because it requires additional work to maintain type /// safety. - pub(crate) fn get_libc_termios(&self) -> Ref { + pub(crate) fn get_libc_termios(&self) -> Ref<'_, libc::termios> { { let mut termios = self.inner.borrow_mut(); termios.c_iflag = self.input_flags.bits(); From fbfb43359108a3d04ee2e76024ed4dba011f233d Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 13:26:47 -0600 Subject: [PATCH 03/10] fixup to Clippy cleanup: mismatched_lifetime_syntaxes --- src/sys/socket/sockopt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index a821f5cb36..8e00488617 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -1955,7 +1955,7 @@ pub struct SetOsString<'a> { #[cfg(any(target_os = "freebsd", linux_android, target_os = "illumos"))] impl<'a> Set<'a, OsString> for SetOsString<'a> { - fn new(val: &OsString) -> SetOsString { + fn new(val: &OsString) -> SetOsString<'_> { SetOsString { val: val.as_os_str(), } From a16a9f86f6b64a9809dbef8918ff986c32738e06 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 13:29:50 -0600 Subject: [PATCH 04/10] Remove the `PartialEq` and `Eq` implementations from `SigHandler` Because it never worked reliably anyway. See https://doc.rust-lang.org/nightly/core/ptr/fn.fn_addr_eq.html for more info. Alternatively, we could only remove `Eq` and leave `PartialEq`. We would be able to guarantee equality or inequality in most cases, but would be unable to prove that different handler functions are actually different. I think users would find that confusing. Reported by: Clippy (unpredictable_function_pointer_comparisons) --- changelog/2642.removed.md | 8 ++++++++ src/sys/signal.rs | 2 +- test/sys/test_signal.rs | 31 +++++++++++-------------------- 3 files changed, 20 insertions(+), 21 deletions(-) create mode 100644 changelog/2642.removed.md diff --git a/changelog/2642.removed.md b/changelog/2642.removed.md new file mode 100644 index 0000000000..908cd69605 --- /dev/null +++ b/changelog/2642.removed.md @@ -0,0 +1,8 @@ +Removed `Eq` and `PartialEq` implementations from `SigHandler`, because they +never worked reliably. The suggested alternative is `matches!`. For example: +``` +let h: SigHandler = ... +if matches!(h, SigHandler::SigIgn) { + ... +} +``` diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 2b0c779b03..f987ca1093 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -753,7 +753,7 @@ impl<'a> IntoIterator for &'a SigSet { } /// A signal handler. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[derive(Clone, Copy, Debug, Hash)] pub enum SigHandler { /// Default signal handling. SigDfl, diff --git a/test/sys/test_signal.rs b/test/sys/test_signal.rs index cd4bc3d9b9..49e5089cb2 100644 --- a/test/sys/test_signal.rs +++ b/test/sys/test_signal.rs @@ -112,32 +112,23 @@ fn test_signal() { unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap(); raise(Signal::SIGINT).unwrap(); - assert_eq!( - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), - SigHandler::SigIgn - ); + let h = unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(); + assert!(matches!(h, SigHandler::SigIgn)); let handler = SigHandler::Handler(test_sigaction_handler); - assert_eq!( - unsafe { signal(Signal::SIGINT, handler) }.unwrap(), - SigHandler::SigDfl - ); + let h = unsafe { signal(Signal::SIGINT, handler) }.unwrap(); + assert!(matches!(h, SigHandler::SigDfl)); raise(Signal::SIGINT).unwrap(); assert!(SIGNALED.load(Ordering::Relaxed)); + let h = unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(); #[cfg(not(solarish))] - assert_eq!( - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), - handler - ); + assert!(matches!(h, SigHandler::Handler(_))); // System V based OSes (e.g. illumos and Solaris) always resets the // disposition to SIG_DFL prior to calling the signal handler #[cfg(solarish)] - assert_eq!( - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), - SigHandler::SigDfl - ); + assert!(matches!(h, SigHandler::SigDfl)); // Restore default signal handler unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(); @@ -307,7 +298,7 @@ fn test_sigaction() { action_sig.flags(), SaFlags::SA_ONSTACK | SaFlags::SA_RESTART ); - assert_eq!(action_sig.handler(), handler_sig); + assert!(matches!(action_sig.handler(), SigHandler::Handler(_))); mask = action_sig.mask(); assert!(mask.contains(SIGUSR1)); @@ -315,13 +306,13 @@ fn test_sigaction() { let handler_act = SigHandler::SigAction(test_sigaction_action); let action_act = SigAction::new(handler_act, flags, mask); - assert_eq!(action_act.handler(), handler_act); + assert!(matches!(action_act.handler(), SigHandler::SigAction(_))); let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask); - assert_eq!(action_dfl.handler(), SigHandler::SigDfl); + assert!(matches!(action_dfl.handler(), SigHandler::SigDfl)); let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask); - assert_eq!(action_ign.handler(), SigHandler::SigIgn); + assert!(matches!(action_ign.handler(), SigHandler::SigIgn)); }) .join() .unwrap(); From 99a3ea35dcda63994f8e3552f5e5077b81f48a69 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 13:39:50 -0600 Subject: [PATCH 05/10] Fix rustdoc::redundant_explicit_links warning on nightly --- src/fcntl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fcntl.rs b/src/fcntl.rs index 13ee1919ca..d4441dea91 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -745,7 +745,7 @@ pub enum FcntlArg<'a> { F_SETFL(OFlag), // O_NONBLOCK /// Set or clear a file segment lock F_SETLK(&'a libc::flock), - /// Like [`F_SETLK`](FcntlArg::F_SETLK) except that if a shared or exclusive lock is blocked by + /// Like [`F_SETLK`] except that if a shared or exclusive lock is blocked by /// other locks, the process waits until the request can be satisfied. F_SETLKW(&'a libc::flock), /// Get the first lock that blocks the lock description From d7e3c1c621a18b8e9e823b02c6104bc51f84cc01 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 13:54:45 -0600 Subject: [PATCH 06/10] Clippy::doc_overindented_list_items Fix the lint in one file, but suppress it in src/sys/aio.rs, where the docstrings are nicely formated for reading in either plain text or html. --- src/sys/aio.rs | 11 +++++++---- src/sys/signal.rs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/sys/aio.rs b/src/sys/aio.rs index 39cd15cc75..ecb89ad31a 100644 --- a/src/sys/aio.rs +++ b/src/sys/aio.rs @@ -23,6 +23,7 @@ //! [`cancel`](trait.Aio.html#method.cancel) or //! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may //! not support this for all filesystems and devices. +#![allow(clippy::doc_overindented_list_items)] // It looks better this way #[cfg(target_os = "freebsd")] use std::io::{IoSlice, IoSliceMut}; use std::{ @@ -572,8 +573,9 @@ impl<'a> AioRead<'a> { /// * `fd`: File descriptor to read from /// * `offs`: File offset /// * `buf`: A memory buffer. It must outlive the `AioRead`. - /// * `prio`: If POSIX Prioritized IO is supported, then the operation - /// will be prioritized at the process's priority level minus `prio` + /// * `prio`: If POSIX Prioritized IO is supported, then the + /// operation will be prioritized at the process's + /// priority level minus `prio`. /// * `sigev_notify`: Determines how you will be notified of event completion. pub fn new( fd: BorrowedFd<'a>, @@ -802,8 +804,9 @@ impl<'a> AioWrite<'a> { /// * `fd`: File descriptor to write to /// * `offs`: File offset /// * `buf`: A memory buffer. It must outlive the `AioWrite`. - /// * `prio`: If POSIX Prioritized IO is supported, then the operation - /// will be prioritized at the process's priority level minus `prio` + /// * `prio`: If POSIX Prioritized IO is supported, then the + /// operation will be prioritized at the process's + /// priority level minus `prio` /// * `sigev_notify`: Determines how you will be notified of event completion. pub fn new( fd: BorrowedFd<'a>, diff --git a/src/sys/signal.rs b/src/sys/signal.rs index f987ca1093..3e08da5557 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -1035,7 +1035,7 @@ pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut Si /// - If less than `-1`, the signal is sent to all processes whose /// process group ID is equal to the absolute value of `pid`. /// * `signal` - Signal to send. If `None`, error checking is performed -/// but no signal is actually sent. +/// but no signal is actually sent. /// /// See Also /// [`kill(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html) From b56d9e940b6b8cce437e4aebdaab6d6f443a5b01 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 13:59:39 -0600 Subject: [PATCH 07/10] fixup to Clippy cleanup: mismatched_lifetime_syntaxes --- src/mqueue.rs | 2 +- src/sys/fanotify.rs | 4 ++-- src/sys/signalfd.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mqueue.rs b/src/mqueue.rs index eea45be7a7..7684d56858 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -315,7 +315,7 @@ pub fn mq_remove_nonblock(mqd: &MqdT) -> Result { #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "dragonfly"))] impl AsFd for MqdT { /// Borrow the underlying message queue descriptor. - fn as_fd(&self) -> BorrowedFd { + fn as_fd(&self) -> BorrowedFd<'_> { // SAFETY: [MqdT] will only contain a valid fd by construction. unsafe { BorrowedFd::borrow_raw(self.0) } } diff --git a/src/sys/fanotify.rs b/src/sys/fanotify.rs index fd3089f702..0b5e43f30d 100644 --- a/src/sys/fanotify.rs +++ b/src/sys/fanotify.rs @@ -229,7 +229,7 @@ impl FanotifyEvent { /// The file descriptor of the event. If the value is `None` when reading /// from the fanotify group, this event is to notify that a group queue /// overflow occured. - pub fn fd(&self) -> Option { + pub fn fd(&self) -> Option> { if self.0.fd == libc::FAN_NOFD { None } else { @@ -443,4 +443,4 @@ impl Fanotify { fd } } -} \ No newline at end of file +} diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index 3614881252..8224c3228e 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -146,7 +146,7 @@ impl SignalFd { } impl AsFd for SignalFd { - fn as_fd(&self) -> BorrowedFd { + fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } From 16df853aaa492ce93ea905a53acd8241c39a6ecf Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 14 Jun 2025 14:02:26 -0600 Subject: [PATCH 08/10] fixup to Fix rustdoc::redundant_explicit_links warning on nightly --- src/fcntl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fcntl.rs b/src/fcntl.rs index d4441dea91..6504c1dcf2 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -753,7 +753,7 @@ pub enum FcntlArg<'a> { /// Acquire or release an open file description lock #[cfg(linux_android)] F_OFD_SETLK(&'a libc::flock), - /// Like [`F_OFD_SETLK`](FcntlArg::F_OFD_SETLK) except that if a conflicting lock is held on + /// Like [`F_OFD_SETLK`] except that if a conflicting lock is held on /// the file, then wait for that lock to be released. #[cfg(linux_android)] F_OFD_SETLKW(&'a libc::flock), From 9c3d4efbd6d49d5742f23d3668860c0122598dc6 Mon Sep 17 00:00:00 2001 From: Steve Lau Date: Tue, 17 Jun 2025 09:25:09 +0800 Subject: [PATCH 09/10] clippy fix: mismatched-lifetime-syntaxes --- src/sys/aio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sys/aio.rs b/src/sys/aio.rs index ecb89ad31a..a5f368637a 100644 --- a/src/sys/aio.rs +++ b/src/sys/aio.rs @@ -314,7 +314,7 @@ pub trait Aio { fn error(self: Pin<&mut Self>) -> Result<()>; /// Returns the underlying file descriptor associated with the operation. - fn fd(&self) -> BorrowedFd; + fn fd(&self) -> BorrowedFd<'_>; /// Does this operation currently have any in-kernel state? /// From 19b23ac8cd980ea2022a57e6f7604fdd2dde1e30 Mon Sep 17 00:00:00 2001 From: Steve Lau Date: Tue, 17 Jun 2025 10:10:04 +0800 Subject: [PATCH 10/10] chore: pin libc to 0.2.172 to avoid the broken timespec --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9970f121cb..18aa5afcfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ targets = [ ] [dependencies] -libc = { version = "0.2.171", features = ["extra_traits"] } +libc = { version = "=0.2.172", features = ["extra_traits"] } bitflags = "2.3.3" cfg-if = "1.0" pin-utils = { version = "0.1.0", optional = true }