diff --git a/.cirrus.yml b/.cirrus.yml index 8d6e121020..c94d4b9ec1 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -116,7 +116,7 @@ task: - curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs - sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN - . $HOME/.cargo/env - - cargo install cross + - cargo install cross --version 0.2.1 # cross 0.2.2 bumped the MSRV to 1.58.1 - cp Cargo.lock.msrv Cargo.lock << : *TEST before_cache_script: rm -rf $CARGO_HOME/registry/index @@ -244,11 +244,9 @@ task: BUILD: check name: Redox x86_64 env: - TARGET: x86_64-unknown-redox - # Redox requires a nightly compiler. - # If stuff breaks, change nightly to the date at - # https://gitlab.redox-os.org/redox-os/redox/-/blob/master/rust-toolchain - TOOLCHAIN: nightly-2021-06-15 + TARGET: x86_64-unknown-redox + # Redox's MSRV policy is unclear. Until they define it, use nightly. + TOOLCHAIN: nightly setup_script: - rustup target add $TARGET - rustup toolchain install $TOOLCHAIN --profile minimal --target $TARGET diff --git a/CHANGELOG.md b/CHANGELOG.md index 77d5b2a326..a7b24ff211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). +## [0.23.2] - 2022-12-03 +### Added + +### Changed + +### Fixed + +- `InetAddr::from_std` now sets the `sin_len`/`sin6_len` fields on the BSDs. + (#[1642](https://github.com/nix-rust/nix/pull/1642)) +- Fix microsecond calculation for `TimeSpec`. + ([#1801](https://github.com/nix-rust/nix/pull/1801)) +- Fix `User::from_name` and `Group::from_name` panicking + when given a name containing a nul. + ([#1815](https://github.com/nix-rust/nix/pull/1815)) +- Fix `User::from_uid` and `User::from_name` crash on Android platform. + ([#1824](https://github.com/nix-rust/nix/pull/1824)) +- Fix UB with `sys::socket::sockopt::SockType` using `SOCK_PACKET`. + ([#1821](https://github.com/nix-rust/nix/pull/1821)) + +### Removed + ## [0.23.1] - 2021-12-16 ### Added diff --git a/Cargo.toml b/Cargo.toml index d2ca8ee804..f3e3df3df7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "nix" description = "Rust friendly bindings to *nix APIs" edition = "2018" -version = "0.23.1" +version = "0.23.2" rust-version = "1.46" authors = ["The nix-rust Project Developers"] repository = "https://github.com/nix-rust/nix" @@ -26,7 +26,7 @@ targets = [ ] [dependencies] -libc = { version = "0.2.102", features = [ "extra_traits" ] } +libc = { version = "0.2.121", features = [ "extra_traits" ] } bitflags = "1.1" cfg-if = "1.0" diff --git a/release.toml b/release.toml index df2c9da45d..23488fbfa5 100644 --- a/release.toml +++ b/release.toml @@ -1,4 +1,3 @@ -no-dev-version = true pre-release-replacements = [ { file="CHANGELOG.md", search="Unreleased", replace="{{version}}" }, { file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}" } diff --git a/src/dir.rs b/src/dir.rs index ed70a458ac..b27fb70425 100644 --- a/src/dir.rs +++ b/src/dir.rs @@ -186,6 +186,8 @@ pub enum Type { impl Entry { /// Returns the inode number (`d_ino`) of the underlying `dirent`. + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", @@ -212,6 +214,8 @@ impl Entry { target_os = "macos", target_os = "solaris")))] #[allow(clippy::useless_conversion)] // Not useless on all OSes + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] pub fn ino(&self) -> u64 { u64::from(self.0.d_fileno) } diff --git a/src/errno.rs b/src/errno.rs index 3da246e823..d5f644305b 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -43,9 +43,7 @@ fn clear() { /// Returns the platform-specific value of errno pub fn errno() -> i32 { - unsafe { - (*errno_location()) as i32 - } + unsafe { *errno_location() } } impl Errno { diff --git a/src/macros.rs b/src/macros.rs index 3ccbfdd43b..b73f666c48 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -5,7 +5,7 @@ /// The `libc` crate must be in scope with the name `libc`. /// /// # Example -/// ``` +/// ```ignore /// libc_bitflags!{ /// pub struct ProtFlags: libc::c_int { /// PROT_NONE; @@ -25,7 +25,7 @@ /// various flags have different types, so we cast the broken ones to the right /// type. /// -/// ``` +/// ```ignore /// libc_bitflags!{ /// pub struct SaFlags: libc::c_ulong { /// SA_NOCLDSTOP as libc::c_ulong; @@ -66,7 +66,7 @@ macro_rules! libc_bitflags { /// The `libc` crate must be in scope with the name `libc`. /// /// # Example -/// ``` +/// ```ignore /// libc_enum!{ /// pub enum ProtFlags { /// PROT_NONE, @@ -80,6 +80,9 @@ macro_rules! libc_bitflags { /// } /// } /// ``` +// Some targets don't use all rules. +#[allow(unknown_lints)] +#[allow(unused_macro_rules)] macro_rules! libc_enum { // Exit rule. (@make_enum diff --git a/src/sys/event.rs b/src/sys/event.rs index c648f5ebc8..660a5357c2 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -114,6 +114,9 @@ libc_bitflags!{ target_os = "ios", target_os = "macos", target_os = "netbsd", target_os = "openbsd"))] EV_RECEIPT; + // Removed in 0.24 by 84e3c56bcc144fb4964caa69fb1dddeccb35be82, + // but leaving around in older versions. + #[allow(deprecated)] EV_SYSFLAGS; } } diff --git a/src/sys/pthread.rs b/src/sys/pthread.rs index d42e45d13d..1636ba8f03 100644 --- a/src/sys/pthread.rs +++ b/src/sys/pthread.rs @@ -27,6 +27,7 @@ pub fn pthread_self() -> Pthread { /// won't send any signal. /// /// [`pthread_kill(3)`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html +#[allow(clippy::not_unsafe_ptr_arg_deref)] #[cfg(not(target_os = "redox"))] pub fn pthread_kill>>(thread: Pthread, signal: T) -> Result<()> { let sig = match signal.into() { diff --git a/src/sys/ptrace/bsd.rs b/src/sys/ptrace/bsd.rs index a62881ef34..68cb2309c0 100644 --- a/src/sys/ptrace/bsd.rs +++ b/src/sys/ptrace/bsd.rs @@ -162,6 +162,9 @@ pub fn step>>(pid: Pid, sig: T) -> Result<()> { } /// Reads a word from a processes memory at the given address +// Technically, ptrace doesn't dereference the pointer. It passes it directly +// to the kernel. +#[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn read(pid: Pid, addr: AddressType) -> Result { unsafe { // Traditionally there was a difference between reading data or @@ -171,6 +174,9 @@ pub fn read(pid: Pid, addr: AddressType) -> Result { } /// Writes a word into the processes memory at the given address +// Technically, ptrace doesn't dereference the pointer. It passes it directly +// to the kernel. +#[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn write(pid: Pid, addr: AddressType, data: c_int) -> Result<()> { unsafe { ptrace_other(Request::PT_WRITE_D, pid, addr, data).map(drop) } } diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 61bdc74aef..ee0f7dc594 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -589,21 +589,12 @@ impl SigAction { /// is the `SigAction` variant). `mask` specifies other signals to block during execution of /// the signal-catching function. pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction { - #[cfg(target_os = "redox")] - unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) { - (*p).sa_handler = match handler { - SigHandler::SigDfl => libc::SIG_DFL, - SigHandler::SigIgn => libc::SIG_IGN, - SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize, - }; - } - - #[cfg(not(target_os = "redox"))] unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) { (*p).sa_sigaction = match handler { SigHandler::SigDfl => libc::SIG_DFL, SigHandler::SigIgn => libc::SIG_IGN, SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize, + #[cfg(not(target_os = "redox"))] SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize, }; } @@ -635,11 +626,11 @@ impl SigAction { } /// Returns the action's handler. - #[cfg(not(target_os = "redox"))] pub fn handler(&self) -> SigHandler { match self.sigaction.sa_sigaction { libc::SIG_DFL => SigHandler::SigDfl, libc::SIG_IGN => SigHandler::SigIgn, + #[cfg(not(target_os = "redox"))] p if self.flags().contains(SaFlags::SA_SIGINFO) => SigHandler::SigAction( // Safe for one of two reasons: @@ -667,27 +658,6 @@ impl SigAction { as extern fn(libc::c_int)), } } - - /// Returns the action's handler. - #[cfg(target_os = "redox")] - pub fn handler(&self) -> SigHandler { - match self.sigaction.sa_handler { - libc::SIG_DFL => SigHandler::SigDfl, - libc::SIG_IGN => SigHandler::SigIgn, - p => SigHandler::Handler( - // Safe for one of two reasons: - // * The SigHandler was created by SigHandler::new, in which - // case the pointer is correct, or - // * The SigHandler was created by signal or sigaction, which - // are unsafe functions, so the caller should've somehow - // ensured that it is correctly initialized. - unsafe{ - *(&p as *const usize - as *const extern fn(libc::c_int)) - } - as extern fn(libc::c_int)), - } - } } /// Changes the action taken by a process on receipt of a specific signal. diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index b119642b3f..4ef435d041 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -275,6 +275,11 @@ impl InetAddr { match *std { net::SocketAddr::V4(ref addr) => { InetAddr::V4(libc::sockaddr_in { + #[cfg(any(target_os = "dragonfly", target_os = "freebsd", + target_os = "haiku", target_os = "hermit", + target_os = "ios", target_os = "macos", + target_os = "netbsd", target_os = "openbsd"))] + sin_len: mem::size_of::() as u8, sin_family: AddressFamily::Inet as sa_family_t, sin_port: addr.port().to_be(), // network byte order sin_addr: Ipv4Addr::from_std(addr.ip()).0, @@ -283,6 +288,11 @@ impl InetAddr { } net::SocketAddr::V6(ref addr) => { InetAddr::V6(libc::sockaddr_in6 { + #[cfg(any(target_os = "dragonfly", target_os = "freebsd", + target_os = "haiku", target_os = "hermit", + target_os = "ios", target_os = "macos", + target_os = "netbsd", target_os = "openbsd"))] + sin6_len: mem::size_of::() as u8, sin6_family: AddressFamily::Inet6 as sa_family_t, sin6_port: addr.port().to_be(), // network byte order sin6_addr: Ipv6Addr::from_std(addr.ip()).0, @@ -1175,12 +1185,12 @@ mod datalink { /// Physical-layer address (MAC) pub fn addr(&self) -> [u8; 6] { [ - self.0.sll_addr[0] as u8, - self.0.sll_addr[1] as u8, - self.0.sll_addr[2] as u8, - self.0.sll_addr[3] as u8, - self.0.sll_addr[4] as u8, - self.0.sll_addr[5] as u8, + self.0.sll_addr[0], + self.0.sll_addr[1], + self.0.sll_addr[2], + self.0.sll_addr[3], + self.0.sll_addr[4], + self.0.sll_addr[5], ] } } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 97eea3dcb1..49f11e4517 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -6,6 +6,7 @@ use crate::{Result, errno::Errno}; use libc::{self, c_void, c_int, iovec, socklen_t, size_t, CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN}; use memoffset::offset_of; +use std::convert::TryFrom; use std::{mem, ptr, slice}; use std::os::unix::io::RawFd; #[cfg(all(target_os = "linux"))] @@ -91,6 +92,24 @@ pub enum SockType { /// guarantee ordering. Rdm = libc::SOCK_RDM, } +// The TryFrom impl could've been derived using libc_enum!. But for +// backwards-compatibility with Nix-0.25.0 we manually implement it, so as to +// keep the old variant names. +impl TryFrom for SockType { + type Error = crate::Error; + + fn try_from(x: i32) -> Result { + match x { + libc::SOCK_STREAM => Ok(Self::Stream), + libc::SOCK_DGRAM => Ok(Self::Datagram), + libc::SOCK_SEQPACKET => Ok(Self::SeqPacket), + libc::SOCK_RAW => Ok(Self::Raw), + #[cfg(not(any(target_os = "haiku")))] + libc::SOCK_RDM => Ok(Self::Rdm), + _ => Err(Errno::EINVAL) + } + } +} /// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html) /// to specify the protocol to use. @@ -679,6 +698,8 @@ impl ControlMessageOwned { unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned { let p = CMSG_DATA(header); + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] let len = header as *const _ as usize + header.cmsg_len as usize - p as usize; match (header.cmsg_level, header.cmsg_type) { @@ -1158,7 +1179,7 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage], // because subsequent code will not clear the padding bytes. let mut cmsg_buffer = vec![0u8; capacity]; - let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], &iov, &cmsgs, addr); + let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], iov, cmsgs, addr); let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) }; @@ -1339,7 +1360,7 @@ pub fn recvmmsg<'a, I>( } ); - (msg_controllen as usize, &mut d.cmsg_buffer) + (msg_controllen, &mut d.cmsg_buffer) }).collect(); let timeout = if let Some(mut t) = timeout { @@ -1358,6 +1379,8 @@ pub fn recvmmsg<'a, I>( .zip(addresses.iter().map(|addr| unsafe{addr.assume_init()})) .zip(results.into_iter()) .map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| { + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] unsafe { read_mhdr( mmsghdr.msg_hdr, @@ -1371,13 +1394,15 @@ pub fn recvmmsg<'a, I>( .collect()) } -unsafe fn read_mhdr<'a, 'b>( +unsafe fn read_mhdr<'a>( mhdr: msghdr, r: isize, msg_controllen: usize, address: sockaddr_storage, - cmsg_buffer: &'a mut Option<&'b mut Vec> -) -> RecvMsg<'b> { + cmsg_buffer: &mut Option<&'a mut Vec> +) -> RecvMsg<'a> { + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] let cmsghdr = { if mhdr.msg_controllen > 0 { // got control message(s) @@ -1519,7 +1544,7 @@ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>], let mut address = mem::MaybeUninit::uninit(); let (msg_controllen, mut mhdr) = unsafe { - pack_mhdr_to_receive(&iov, &mut cmsg_buffer, address.as_mut_ptr()) + pack_mhdr_to_receive(iov, &mut cmsg_buffer, address.as_mut_ptr()) }; let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) }; @@ -1819,14 +1844,14 @@ pub fn sockaddr_storage_to_addr( match c_int::from(addr.ss_family) { libc::AF_INET => { - assert!(len as usize >= mem::size_of::()); + assert!(len >= mem::size_of::()); let sin = unsafe { *(addr as *const sockaddr_storage as *const sockaddr_in) }; Ok(SockAddr::Inet(InetAddr::V4(sin))) } libc::AF_INET6 => { - assert!(len as usize >= mem::size_of::()); + assert!(len >= mem::size_of::()); let sin6 = unsafe { *(addr as *const _ as *const sockaddr_in6) }; diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index fcb4be81be..efb9c54500 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -5,6 +5,7 @@ use crate::Result; use crate::errno::Errno; use crate::sys::time::TimeVal; use libc::{self, c_int, c_void, socklen_t}; +use std::convert::TryFrom; use std::mem::{ self, MaybeUninit @@ -96,7 +97,10 @@ macro_rules! getsockopt_impl { getter.ffi_len()); Errno::result(res)?; - Ok(getter.assume_init()) + match <$ty>::try_from(getter.assume_init()) { + Err(_) => Err(Errno::EINVAL), + Ok(r) => Ok(r) + } } } } @@ -128,6 +132,9 @@ macro_rules! getsockopt_impl { /// * `$ty:ty`: type of the value that will be get/set. /// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`. /// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`. +// Some targets don't use all rules. +#[allow(unknown_lints)] +#[allow(unused_macro_rules)] macro_rules! sockopt_impl { ($(#[$attr:meta])* $name:ident, GetOnly, $level:expr, $flag:path, bool) => { sockopt_impl!($(#[$attr])* @@ -413,7 +420,7 @@ sockopt_impl!( SndBufForce, SetOnly, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize); sockopt_impl!( /// Gets the socket type as an integer. - SockType, GetOnly, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType); + SockType, GetOnly, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType, GetStruct); sockopt_impl!( /// Returns a value indicating whether or not this socket has been marked to /// accept connections with `listen(2)`. @@ -718,7 +725,7 @@ struct SetBool { impl<'a> Set<'a, bool> for SetBool { fn new(val: &'a bool) -> SetBool { - SetBool { val: if *val { 1 } else { 0 } } + SetBool { val: i32::from(*val) } } fn ffi_ptr(&self) -> *const c_void { @@ -765,7 +772,7 @@ struct SetU8 { impl<'a> Set<'a, u8> for SetU8 { fn new(val: &'a u8) -> SetU8 { - SetU8 { val: *val as u8 } + SetU8 { val: *val } } fn ffi_ptr(&self) -> *const c_void { diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs index 829be57f63..18f0820ea9 100644 --- a/src/sys/statfs.rs +++ b/src/sys/statfs.rs @@ -564,6 +564,8 @@ mod test { assert_fs_equals(fs, vfs); } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] fn assert_fs_equals(fs: Statfs, vfs: Statvfs) { assert_eq!(fs.files() as u64, vfs.files() as u64); assert_eq!(fs.blocks() as u64, vfs.blocks() as u64); @@ -611,6 +613,8 @@ mod test { assert_fs_equals_strict(fs.unwrap(), vfs.unwrap()) } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) { assert_eq!(fs.files_free() as u64, vfs.files_free() as u64); assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64); diff --git a/src/sys/sysinfo.rs b/src/sys/sysinfo.rs index dc943c1adc..56d8e0a3db 100644 --- a/src/sys/sysinfo.rs +++ b/src/sys/sysinfo.rs @@ -30,6 +30,8 @@ impl SysInfo { } /// Returns the time since system boot. + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] pub fn uptime(&self) -> Duration { // Truncate negative values to 0 Duration::from_secs(cmp::max(self.0.uptime, 0) as u64) @@ -64,6 +66,8 @@ impl SysInfo { self.scale_mem(self.0.freeram) } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] fn scale_mem(&self, units: mem_blocks_t) -> u64 { units as u64 * self.0.mem_unit as u64 } diff --git a/src/sys/termios.rs b/src/sys/termios.rs index 01d4608039..dcc7b2b8a3 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -804,6 +804,8 @@ cfg_if!{ /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)). /// /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure. + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] pub fn cfgetispeed(termios: &Termios) -> u32 { let inner_termios = termios.get_libc_termios(); unsafe { libc::cfgetispeed(&*inner_termios) as u32 } @@ -813,6 +815,8 @@ cfg_if!{ /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)). /// /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure. + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] pub fn cfgetospeed(termios: &Termios) -> u32 { let inner_termios = termios.get_libc_termios(); unsafe { libc::cfgetospeed(&*inner_termios) as u32 } diff --git a/src/sys/time.rs b/src/sys/time.rs index ac4247180d..6cf567ec36 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -5,6 +5,10 @@ use libc::{timespec, timeval}; #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 pub use libc::{time_t, suseconds_t}; +pub(crate) const TIMESPEC_ZERO: libc::timespec = unsafe { + std::mem::transmute([0u8; std::mem::size_of::()]) +}; + pub trait TimeValLike: Sized { #[inline] fn zero() -> Self { @@ -119,11 +123,15 @@ impl PartialOrd for TimeSpec { impl TimeValLike for TimeSpec { #[inline] + #[cfg_attr(target_env = "musl", allow(deprecated))] + // https://github.com/rust-lang/libc/issues/1848 fn seconds(seconds: i64) -> TimeSpec { - assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS, + assert!((TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&seconds), "TimeSpec out of bounds; seconds={}", seconds); - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 }) + let mut ts = TIMESPEC_ZERO; + ts.tv_sec = seconds as time_t; + ts.tv_nsec = 0; + TimeSpec(ts) } #[inline] @@ -145,15 +153,20 @@ impl TimeValLike for TimeSpec { /// Makes a new `TimeSpec` with given number of nanoseconds. #[inline] + #[cfg_attr(target_env = "musl", allow(deprecated))] + // https://github.com/rust-lang/libc/issues/1848 fn nanoseconds(nanoseconds: i64) -> TimeSpec { let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC); - assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS, + assert!((TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&secs), "TimeSpec out of bounds"); - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec {tv_sec: secs as time_t, - tv_nsec: nanos as timespec_tv_nsec_t }) + let mut ts = TIMESPEC_ZERO; + ts.tv_sec = secs as time_t; + ts.tv_nsec = nanos as timespec_tv_nsec_t; + TimeSpec(ts) } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] fn num_seconds(&self) -> i64 { if self.tv_sec() < 0 && self.tv_nsec() > 0 { (self.tv_sec() + 1) as i64 @@ -167,9 +180,11 @@ impl TimeValLike for TimeSpec { } fn num_microseconds(&self) -> i64 { - self.num_nanoseconds() / 1_000_000_000 + self.num_nanoseconds() / 1_000 } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] fn num_nanoseconds(&self) -> i64 { let secs = self.num_seconds() * 1_000_000_000; let nsec = self.nanos_mod_sec(); @@ -195,12 +210,13 @@ impl TimeSpec { self.0.tv_nsec } + #[cfg_attr(target_env = "musl", allow(deprecated))] + // https://github.com/rust-lang/libc/issues/1848 pub const fn from_duration(duration: Duration) -> Self { - #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec { - tv_sec: duration.as_secs() as time_t, - tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t - }) + let mut ts = TIMESPEC_ZERO; + ts.tv_sec = duration.as_secs() as time_t; + ts.tv_nsec = duration.subsec_nanos() as timespec_tv_nsec_t; + TimeSpec(ts) } pub const fn from_timespec(timespec: timespec) -> Self { @@ -333,7 +349,7 @@ impl PartialOrd for TimeVal { impl TimeValLike for TimeVal { #[inline] fn seconds(seconds: i64) -> TimeVal { - assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS, + assert!((TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&seconds), "TimeVal out of bounds; seconds={}", seconds); #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 }) @@ -351,7 +367,7 @@ impl TimeValLike for TimeVal { #[inline] fn microseconds(microseconds: i64) -> TimeVal { let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC); - assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, + assert!((TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&secs), "TimeVal out of bounds"); #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 TimeVal(timeval {tv_sec: secs as time_t, @@ -364,13 +380,15 @@ impl TimeValLike for TimeVal { fn nanoseconds(nanoseconds: i64) -> TimeVal { let microseconds = nanoseconds / 1000; let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC); - assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS, + assert!((TV_MIN_SECONDS..=TV_MAX_SECONDS).contains(&secs), "TimeVal out of bounds"); #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 TimeVal(timeval {tv_sec: secs as time_t, tv_usec: micros as suseconds_t }) } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] fn num_seconds(&self) -> i64 { if self.tv_sec() < 0 && self.tv_usec() > 0 { (self.tv_sec() + 1) as i64 @@ -383,6 +401,8 @@ impl TimeValLike for TimeVal { self.num_microseconds() / 1_000 } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] fn num_microseconds(&self) -> i64 { let secs = self.num_seconds() * 1_000_000; let usec = self.micros_mod_sec(); diff --git a/src/sys/timerfd.rs b/src/sys/timerfd.rs index 705a3c4d65..4df3c34866 100644 --- a/src/sys/timerfd.rs +++ b/src/sys/timerfd.rs @@ -28,7 +28,7 @@ //! // We wait for the timer to expire. //! timer.wait().unwrap(); //! ``` -use crate::sys::time::TimeSpec; +use crate::sys::time::{TIMESPEC_ZERO, TimeSpec}; use crate::unistd::read; use crate::{errno::Errno, Result}; use bitflags::bitflags; @@ -90,14 +90,8 @@ struct TimerSpec(libc::itimerspec); impl TimerSpec { pub const fn none() -> Self { Self(libc::itimerspec { - it_interval: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, - it_value: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, + it_interval: TIMESPEC_ZERO, + it_value: TIMESPEC_ZERO, }) } } @@ -112,10 +106,7 @@ impl From for TimerSpec { fn from(expiration: Expiration) -> TimerSpec { match expiration { Expiration::OneShot(t) => TimerSpec(libc::itimerspec { - it_interval: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, + it_interval: TIMESPEC_ZERO, it_value: *t.as_ref(), }), Expiration::IntervalDelayed(start, interval) => TimerSpec(libc::itimerspec { @@ -138,6 +129,7 @@ impl From for Expiration { libc::timespec { tv_sec: 0, tv_nsec: 0, + .. }, it_value: ts, }) => Expiration::OneShot(ts.into()), @@ -157,7 +149,7 @@ impl From for Expiration { /// An enumeration allowing the definition of the expiration time of an alarm, /// recurring or not. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum Expiration { OneShot(TimeSpec), IntervalDelayed(TimeSpec, TimeSpec), diff --git a/src/sys/uio.rs b/src/sys/uio.rs index 3abcde24fe..a65a6f10c8 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -189,7 +189,7 @@ impl IoVec { unsafe { slice::from_raw_parts( self.0.iov_base as *const u8, - self.0.iov_len as usize) + self.0.iov_len) } } } diff --git a/src/unistd.rs b/src/unistd.rs index 2c89d77240..23bed1cbbb 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -2052,7 +2052,7 @@ pub enum SysconfVar { /// Unless otherwise noted, the maximum length, in bytes, of a utility's /// input line (either standard input or another file), when the utility is /// described as processing text files. The length includes room for the - /// trailing . + /// trailing newline. #[cfg(not(target_os = "redox"))] LINE_MAX = libc::_SC_LINE_MAX, /// Maximum length of a login name. @@ -2625,7 +2625,7 @@ pub fn access(path: &P, amode: AccessFlags) -> Result<()> { /// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only /// contains ASCII. #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct User { /// Username pub name: String, @@ -2670,32 +2670,32 @@ impl From<&libc::passwd> for User { fn from(pw: &libc::passwd) -> User { unsafe { User { - name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(), - passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(), + name: if pw.pw_name.is_null() { Default::default() } else { CStr::from_ptr(pw.pw_name).to_string_lossy().into_owned() }, + passwd: if pw.pw_passwd.is_null() { Default::default() } else { CString::new(CStr::from_ptr(pw.pw_passwd).to_bytes()).unwrap() }, #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] - gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(), - dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())), - shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())), - uid: Uid::from_raw((*pw).pw_uid), - gid: Gid::from_raw((*pw).pw_gid), + gecos: if pw.pw_gecos.is_null() { Default::default() } else { CString::new(CStr::from_ptr(pw.pw_gecos).to_bytes()).unwrap() }, + dir: if pw.pw_dir.is_null() { Default::default() } else { PathBuf::from(OsStr::from_bytes(CStr::from_ptr(pw.pw_dir).to_bytes())) }, + shell: if pw.pw_shell.is_null() { Default::default() } else { PathBuf::from(OsStr::from_bytes(CStr::from_ptr(pw.pw_shell).to_bytes())) }, + uid: Uid::from_raw(pw.pw_uid), + gid: Gid::from_raw(pw.pw_gid), #[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "illumos", target_os = "linux", target_os = "solaris")))] - class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(), + class: CString::new(CStr::from_ptr(pw.pw_class).to_bytes()).unwrap(), #[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "illumos", target_os = "linux", target_os = "solaris")))] - change: (*pw).pw_change, + change: pw.pw_change, #[cfg(not(any(target_os = "android", target_os = "fuchsia", target_os = "illumos", target_os = "linux", target_os = "solaris")))] - expire: (*pw).pw_expire + expire: pw.pw_expire } } } @@ -2823,7 +2823,10 @@ impl User { /// assert!(res.name == "root"); /// ``` pub fn from_name(name: &str) -> Result> { - let name = CString::new(name).unwrap(); + let name = match CString::new(name) { + Ok(c_str) => c_str, + Err(_nul_error) => return Ok(None), + }; User::from_anything(|pwd, cbuf, cap, res| { unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) } }) @@ -2832,7 +2835,7 @@ impl User { /// Representation of a Group, based on `libc::group` #[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct Group { /// Group name pub name: String, @@ -2849,10 +2852,10 @@ impl From<&libc::group> for Group { fn from(gr: &libc::group) -> Group { unsafe { Group { - name: CStr::from_ptr((*gr).gr_name).to_string_lossy().into_owned(), - passwd: CString::new(CStr::from_ptr((*gr).gr_passwd).to_bytes()).unwrap(), - gid: Gid::from_raw((*gr).gr_gid), - mem: Group::members((*gr).gr_mem) + name: CStr::from_ptr(gr.gr_name).to_string_lossy().into_owned(), + passwd: CString::new(CStr::from_ptr(gr.gr_passwd).to_bytes()).unwrap(), + gid: Gid::from_raw(gr.gr_gid), + mem: Group::members(gr.gr_mem) } } } @@ -2948,7 +2951,10 @@ impl Group { /// assert!(res.name == "root"); /// ``` pub fn from_name(name: &str) -> Result> { - let name = CString::new(name).unwrap(); + let name = match CString::new(name) { + Ok(c_str) => c_str, + Err(_nul_error) => return Ok(None), + }; Group::from_anything(|grp, cbuf, cap, res| { unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) } }) diff --git a/test/sys/test_ioctl.rs b/test/sys/test_ioctl.rs index 236d24268a..f34296f9ee 100644 --- a/test/sys/test_ioctl.rs +++ b/test/sys/test_ioctl.rs @@ -30,6 +30,8 @@ ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32); #[cfg(any(target_os = "linux", target_os = "android"))] mod linux { + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] #[test] fn test_op_none() { if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){ @@ -41,6 +43,8 @@ mod linux { } } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] #[test] fn test_op_write() { if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){ @@ -65,6 +69,8 @@ mod linux { } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] #[test] fn test_op_read() { if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){ @@ -88,6 +94,8 @@ mod linux { } } + // The cast is not unnecessary on all platforms. + #[allow(clippy::unnecessary_cast)] #[test] fn test_op_read_write() { assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A); diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs index 01920fd40a..0a8761e07d 100644 --- a/test/sys/test_sockopt.rs +++ b/test/sys/test_sockopt.rs @@ -121,6 +121,33 @@ fn test_so_tcp_maxseg() { close(ssock).unwrap(); } +#[test] +fn test_so_type() { + let sockfd = socket( + AddressFamily::Inet, + SockType::Stream, + SockFlag::empty(), + None, + ) + .unwrap(); + + assert_eq!(Ok(SockType::Stream), getsockopt(sockfd, sockopt::SockType)); +} + +/// getsockopt(_, sockopt::SockType) should gracefully handle unknown socket +/// types. Regression test for https://github.com/nix-rust/nix/issues/1819 +#[cfg(any(target_os = "android", target_os = "linux",))] +#[test] +fn test_so_type_unknown() { + use nix::errno::Errno; + + require_capability!("test_so_type", CAP_NET_RAW); + let sockfd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) }; + assert!(sockfd >= 0, "Error opening socket: {}", nix::Error::last()); + + assert_eq!(Err(Errno::EINVAL), getsockopt(sockfd, sockopt::SockType)); +} + // The CI doesn't supported getsockopt and setsockopt on emulated processors. // It's beleived that a QEMU issue, the tests run ok on a fully emulated system. // Current CI just run the binary with QEMU but the Kernel remains the same as the host. diff --git a/test/sys/test_stat.rs b/test/sys/test_stat.rs new file mode 100644 index 0000000000..426b4b6588 --- /dev/null +++ b/test/sys/test_stat.rs @@ -0,0 +1,29 @@ +// The conversion is not useless on all platforms. +#[allow(clippy::useless_conversion)] +#[cfg(target_os = "freebsd")] +#[test] +fn test_chflags() { + use nix::{ + sys::stat::{fstat, FileFlag}, + unistd::chflags, + }; + use std::os::unix::io::AsRawFd; + use tempfile::NamedTempFile; + + let f = NamedTempFile::new().unwrap(); + + let initial = FileFlag::from_bits_truncate( + fstat(f.as_raw_fd()).unwrap().st_flags.into(), + ); + // UF_OFFLINE is preserved by all FreeBSD file systems, but not interpreted + // in any way, so it's handy for testing. + let commanded = initial ^ FileFlag::UF_OFFLINE; + + chflags(f.path(), commanded).unwrap(); + + let changed = FileFlag::from_bits_truncate( + fstat(f.as_raw_fd()).unwrap().st_flags.into(), + ); + + assert_eq!(commanded, changed); +} diff --git a/test/sys/test_timerfd.rs b/test/sys/test_timerfd.rs index 24fb2ac002..e546d790e7 100644 --- a/test/sys/test_timerfd.rs +++ b/test/sys/test_timerfd.rs @@ -57,5 +57,5 @@ pub fn test_timerfd_unset() { timer.unset().unwrap(); - assert!(timer.get().unwrap() == None); + assert!(timer.get().unwrap().is_none()); } diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs index c63b58103c..99dad0cad6 100644 --- a/test/sys/test_uio.rs +++ b/test/sys/test_uio.rs @@ -47,7 +47,7 @@ fn test_writev() { let read_res = read(reader, &mut read_buf[..]); // Successful read assert!(read_res.is_ok()); - let read = read_res.ok().unwrap() as usize; + let read = read_res.ok().unwrap(); // Check we have read as much as we written assert_eq!(read, written); // Check equality of written and read data @@ -249,7 +249,7 @@ fn test_process_vm_readv() { } let _ = write(w, b"\0"); let _ = close(w); - loop { let _ = pause(); } + loop { pause(); } }, } } diff --git a/test/test_dir.rs b/test/test_dir.rs index 2940b6eafb..8cbb8ff5d3 100644 --- a/test/test_dir.rs +++ b/test/test_dir.rs @@ -20,8 +20,8 @@ fn flags() -> OFlag { #[allow(clippy::unnecessary_sort_by)] // False positive fn read() { let tmp = tempdir().unwrap(); - File::create(&tmp.path().join("foo")).unwrap(); - ::std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap(); + File::create(tmp.path().join("foo")).unwrap(); + std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap(); let mut dir = Dir::open(tmp.path(), flags(), Mode::empty()).unwrap(); let mut entries: Vec<_> = dir.iter().map(|e| e.unwrap()).collect(); entries.sort_by(|a, b| a.file_name().cmp(b.file_name())); diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index db2acfbf52..b7d50a4096 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -57,7 +57,7 @@ fn test_renameat() { let old_dir = tempfile::tempdir().unwrap(); let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); let old_path = old_dir.path().join("old"); - File::create(&old_path).unwrap(); + File::create(old_path).unwrap(); let new_dir = tempfile::tempdir().unwrap(); let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap(); @@ -83,7 +83,7 @@ fn test_renameat2_behaves_like_renameat_with_no_flags() { let old_dir = tempfile::tempdir().unwrap(); let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); let old_path = old_dir.path().join("old"); - File::create(&old_path).unwrap(); + File::create(old_path).unwrap(); let new_dir = tempfile::tempdir().unwrap(); let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); renameat2( @@ -171,11 +171,11 @@ fn test_renameat2_noreplace() { let old_dir = tempfile::tempdir().unwrap(); let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); let old_path = old_dir.path().join("old"); - File::create(&old_path).unwrap(); + File::create(old_path).unwrap(); let new_dir = tempfile::tempdir().unwrap(); let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); let new_path = new_dir.path().join("new"); - File::create(&new_path).unwrap(); + File::create(new_path).unwrap(); assert_eq!( renameat2( Some(old_dirfd), @@ -201,10 +201,8 @@ fn test_readlink() { let src = tempdir.path().join("a"); let dst = tempdir.path().join("b"); println!("a: {:?}, b: {:?}", &src, &dst); - fs::symlink(&src.as_path(), &dst.as_path()).unwrap(); - let dirfd = open(tempdir.path(), - OFlag::empty(), - Mode::empty()).unwrap(); + fs::symlink(src.as_path(), dst.as_path()).unwrap(); + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); let expected_dir = src.to_str().unwrap(); assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir); diff --git a/test/test_kmod/mod.rs b/test/test_kmod/mod.rs index 8eef5384a3..246aec66b4 100644 --- a/test/test_kmod/mod.rs +++ b/test/test_kmod/mod.rs @@ -11,12 +11,14 @@ fn compile_kernel_module() -> (PathBuf, String, TempDir) { copy( "test/test_kmod/hello_mod/hello.c", - &tmp_dir.path().join("hello.c"), - ).expect("unable to copy hello.c to temporary build directory"); + tmp_dir.path().join("hello.c"), + ) + .expect("unable to copy hello.c to temporary build directory"); copy( "test/test_kmod/hello_mod/Makefile", - &tmp_dir.path().join("Makefile"), - ).expect("unable to copy Makefile to temporary build directory"); + tmp_dir.path().join("Makefile"), + ) + .expect("unable to copy Makefile to temporary build directory"); let status = Command::new("make") .current_dir(tmp_dir.path()) diff --git a/test/test_mount.rs b/test/test_mount.rs index 44287f975f..0767185f5a 100644 --- a/test/test_mount.rs +++ b/test/test_mount.rs @@ -95,8 +95,13 @@ exit 23"; .unwrap_or_else(|e| panic!("mount failed: {}", e)); // EROFS: Read-only file system - assert_eq!(EROFS as i32, - File::create(tempdir.path().join("test")).unwrap_err().raw_os_error().unwrap()); + assert_eq!( + EROFS, + File::create(tempdir.path().join("test")) + .unwrap_err() + .raw_os_error() + .unwrap() + ); umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); } @@ -133,8 +138,14 @@ exit 23"; &test_path); // EACCES: Permission denied - assert_eq!(EACCES as i32, - Command::new(&test_path).status().unwrap_err().raw_os_error().unwrap()); + assert_eq!( + EACCES, + Command::new(&test_path) + .status() + .unwrap_err() + .raw_os_error() + .unwrap() + ); umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); } diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 61062ad229..f5942030c5 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -820,7 +820,7 @@ fn test_linkat_file() { let newfilepath = tempdir.path().join(newfilename); // Create file - File::create(&oldfilepath).unwrap(); + File::create(oldfilepath).unwrap(); // Get file descriptor for base directory let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); @@ -844,7 +844,7 @@ fn test_linkat_olddirfd_none() { let newfilepath = tempdir_newfile.path().join(newfilename); // Create file - File::create(&oldfilepath).unwrap(); + File::create(oldfilepath).unwrap(); // Get file descriptor for base directory of new file let dirfd = fcntl::open(tempdir_newfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); @@ -869,7 +869,7 @@ fn test_linkat_newdirfd_none() { let newfilepath = tempdir_newfile.path().join(newfilename); // Create file - File::create(&oldfilepath).unwrap(); + File::create(oldfilepath).unwrap(); // Get file descriptor for base directory of old file let dirfd = fcntl::open(tempdir_oldfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); @@ -963,7 +963,7 @@ fn test_unlinkat_dir_noremovedir() { let dirpath = tempdir.path().join(dirname); // Create dir - DirBuilder::new().recursive(true).create(&dirpath).unwrap(); + DirBuilder::new().recursive(true).create(dirpath).unwrap(); // Get file descriptor for base directory let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap(); @@ -1049,7 +1049,7 @@ fn test_setfsuid() { let file = tempfile::NamedTempFile::new_in("/var/tmp").unwrap(); let temp_path = file.into_temp_path(); dbg!(&temp_path); - let temp_path_2 = (&temp_path).to_path_buf(); + let temp_path_2 = temp_path.to_path_buf(); let mut permissions = fs::metadata(&temp_path).unwrap().permissions(); permissions.set_mode(0o640); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy