diff --git a/.cirrus.yml b/.cirrus.yml index f598e2e6fb..381fb62919 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -22,6 +22,7 @@ task: - cargo test --target i686-unknown-freebsd before_cache_script: rm -rf $CARGO_HOME/registry/index +# Test OSX and iOS in a full VM task: matrix: - name: OSX x86_64 @@ -162,14 +163,12 @@ task: - name: Linux x32 env: TARGET: x86_64-unknown-linux-gnux32 - CHECK_TESTS: true - name: NetBSD x86_64 env: TARGET: x86_64-unknown-netbsd - name: Fuchsia x86_64 env: TARGET: x86_64-fuchsia - CHECK_TESTS: true container: image: rust:1.40 setup_script: @@ -177,9 +176,7 @@ task: script: - cargo +$TOOLCHAIN check --target $TARGET - cargo +$TOOLCHAIN check --target $TARGET --release - - 'if [ "$CHECK_TESTS" == true ]; then cargo +$TOOLCHAIN check --all-targets --target $TARGET; fi' - # TODO: check the tests, too. The old Travis CI setup didn't do that, so - # they don't build on all platforms. + - cargo +$TOOLCHAIN check --all-targets --target $TARGET before_cache_script: rm -rf $CARGO_HOME/registry/index # illumos toolchain isn't available via rustup until 1.50 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9636942d5f..2a46003606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - ReleaseDate ### Added +- Add new symbol for linux IP_MULTICAST_ALL + (#[]()) +- Added TIMESTAMPNS support for linux + (#[1402](https://github.com/nix-rust/nix/pull/1402)) ### Changed - Made `forkpty` unsafe, like `fork` @@ -13,6 +17,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Allow `sockaddr_ll` size, as reported by the Linux kernel, to be smaller then it's definition (#[1395](https://github.com/nix-rust/nix/pull/1395)) +- Fix spurious errors using `sendmmsg` with multiple cmsgs + (#[1414](https://github.com/nix-rust/nix/pull/1414)) ### Removed diff --git a/Cargo.toml b/Cargo.toml index 5b052473e4..f5f6dd893b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,10 +32,13 @@ targets = [ ] [dependencies] -libc = { version = "0.2.82", features = [ "extra_traits" ] } +libc = { version = "0.2.93", features = [ "extra_traits" ] } bitflags = "1.1" cfg-if = "1.0" +[target.'cfg(not(target_os = "redox"))'.dependencies] +memoffset = "0.6.3" + [target.'cfg(target_os = "dragonfly")'.build-dependencies] cc = "1" diff --git a/src/macros.rs b/src/macros.rs index feb02ea745..7d6ac8dfbf 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -203,16 +203,3 @@ macro_rules! libc_enum { } }; } - -/// A Rust version of the familiar C `offset_of` macro. It returns the byte -/// offset of `field` within struct `ty` -#[cfg(not(target_os = "redox"))] -macro_rules! offset_of { - ($ty:ty, $field:ident) => {{ - // Safe because we don't actually read from the dereferenced pointer - #[allow(unused_unsafe)] // for when the macro is used in an unsafe block - unsafe { - &(*(ptr::null() as *const $ty)).$field as *const _ as usize - } - }} -} diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 1f7f4ec68e..71b2c973c5 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -1,6 +1,7 @@ use super::sa_family_t; use crate::{Error, Result, NixPath}; use crate::errno::Errno; +use memoffset::offset_of; use std::{fmt, mem, net, ptr, slice}; use std::ffi::OsStr; use std::hash::{Hash, Hasher}; diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 2725e57c43..c04af50f73 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -5,8 +5,11 @@ use cfg_if::cfg_if; use crate::{Error, 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::{mem, ptr, slice}; use std::os::unix::io::RawFd; +#[cfg(all(target_os = "linux"))] +use crate::sys::time::TimeSpec; use crate::sys::time::TimeVal; use crate::sys::uio::IoVec; @@ -554,6 +557,11 @@ pub enum ControlMessageOwned { /// # } /// ``` ScmTimestamp(TimeVal), + /// Nanoseconds resolution timestamp + /// + /// [Further reading](https://www.kernel.org/doc/html/latest/networking/timestamping.html) + #[cfg(all(target_os = "linux"))] + ScmTimestampns(TimeSpec), #[cfg(any( target_os = "android", target_os = "ios", @@ -645,6 +653,11 @@ impl ControlMessageOwned { let tv: libc::timeval = ptr::read_unaligned(p as *const _); ControlMessageOwned::ScmTimestamp(TimeVal::from(tv)) }, + #[cfg(all(target_os = "linux"))] + (libc::SOL_SOCKET, libc::SCM_TIMESTAMPNS) => { + let ts: libc::timespec = ptr::read_unaligned(p as *const _); + ControlMessageOwned::ScmTimestampns(TimeSpec::from(ts)) + } #[cfg(any( target_os = "android", target_os = "freebsd", @@ -1101,23 +1114,22 @@ pub fn sendmmsg<'a, I, C>( let mut output = Vec::::with_capacity(reserve_items); - let mut cmsgs_buffer = vec![0u8; 0]; + let mut cmsgs_buffers = Vec::>::with_capacity(reserve_items); for d in iter { - let cmsgs_start = cmsgs_buffer.len(); - let cmsgs_required_capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum(); - let cmsgs_buffer_need_capacity = cmsgs_start + cmsgs_required_capacity; - cmsgs_buffer.resize(cmsgs_buffer_need_capacity, 0); + let capacity: usize = d.cmsgs.as_ref().iter().map(|c| c.space()).sum(); + let mut cmsgs_buffer = vec![0u8; capacity]; output.push(libc::mmsghdr { msg_hdr: pack_mhdr_to_send( - &mut cmsgs_buffer[cmsgs_start..], + &mut cmsgs_buffer, &d.iov, &d.cmsgs, d.addr.as_ref() ), msg_len: 0, }); + cmsgs_buffers.push(cmsgs_buffer); }; let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) }; diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index fd9a710c51..ff55cb0b9b 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -238,6 +238,8 @@ cfg_if! { } sockopt_impl!(Both, IpMulticastTtl, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8); sockopt_impl!(Both, IpMulticastLoop, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool); +[cfg(any(target_os = "linux", target_os = "android"))] +sockopt_impl!(Both, IpMulticastAll, libc::IPPROTO_IP, libc::IP_MULTICAST_ALL, bool); sockopt_impl!(Both, ReceiveTimeout, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal); sockopt_impl!(Both, SendTimeout, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal); sockopt_impl!(Both, Broadcast, libc::SOL_SOCKET, libc::SO_BROADCAST, bool); @@ -272,6 +274,8 @@ sockopt_impl!(Both, BindToDevice, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsStr #[cfg(any(target_os = "android", target_os = "linux"))] sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in); sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool); +#[cfg(all(target_os = "linux"))] +sockopt_impl!(Both, ReceiveTimestampns, libc::SOL_SOCKET, libc::SO_TIMESTAMPNS, bool); #[cfg(any(target_os = "android", target_os = "linux"))] sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool); #[cfg(target_os = "openbsd")] diff --git a/src/unistd.rs b/src/unistd.rs index f93c21924c..d3afeac633 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -2641,10 +2641,10 @@ impl User { libc::size_t, *mut *mut libc::passwd) -> libc::c_int { - let buflimit = 16384; + let buflimit = 1048576; let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) { Ok(Some(n)) => n as usize, - Ok(None) | Err(_) => buflimit as usize, + Ok(None) | Err(_) => 16384, }; let mut cbuf = Vec::with_capacity(bufsize); @@ -2762,10 +2762,10 @@ impl Group { libc::size_t, *mut *mut libc::group) -> libc::c_int { - let buflimit = 16384; + let buflimit = 1048576; let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) { Ok(Some(n)) => n as usize, - Ok(None) | Err(_) => buflimit as usize, + Ok(None) | Err(_) => 16384, }; let mut cbuf = Vec::with_capacity(bufsize); diff --git a/test/sys/mod.rs b/test/sys/mod.rs index 14b03784a0..4f5316ffa9 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -41,5 +41,5 @@ mod test_pthread; target_os = "netbsd", target_os = "openbsd"))] mod test_ptrace; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(target_os = "linux")] mod test_timerfd; diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 2b89a45336..32318ef0cb 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -757,6 +757,7 @@ pub fn test_af_alg_aead() { target_os = "netbsd"))] #[test] pub fn test_sendmsg_ipv4packetinfo() { + use cfg_if::cfg_if; use nix::sys::uio::IoVec; use nix::sys::socket::{socket, sendmsg, bind, AddressFamily, SockType, SockFlag, SockAddr, @@ -778,11 +779,21 @@ pub fn test_sendmsg_ipv4packetinfo() { let iov = [IoVec::from_slice(&slice)]; if let InetAddr::V4(sin) = inet_addr { - let pi = libc::in_pktinfo { - ipi_ifindex: 0, /* Unspecified interface */ - ipi_addr: libc::in_addr { s_addr: 0 }, - ipi_spec_dst: sin.sin_addr, - }; + cfg_if! { + if #[cfg(target_os = "netbsd")] { + drop(sin); + let pi = libc::in_pktinfo { + ipi_ifindex: 0, /* Unspecified interface */ + ipi_addr: libc::in_addr { s_addr: 0 }, + }; + } else { + let pi = libc::in_pktinfo { + ipi_ifindex: 0, /* Unspecified interface */ + ipi_addr: libc::in_addr { s_addr: 0 }, + ipi_spec_dst: sin.sin_addr, + }; + } + } let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)]; @@ -1472,13 +1483,13 @@ pub fn test_recv_ipv6pktinfo() { Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) => { let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); assert_eq!( - pktinfo.ipi6_ifindex, + pktinfo.ipi6_ifindex as libc::c_uint, i, "unexpected ifindex (expected {}, got {})", i, pktinfo.ipi6_ifindex ); - } + }, _ => (), } assert!(cmsgs.next().is_none(), "unexpected additional control msg"); @@ -1535,3 +1546,111 @@ pub fn test_vsock() { close(s1).unwrap(); thr.join().unwrap(); } + +// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU +// support is suspected. +#[cfg_attr(not(any(target_arch = "x86_64")), ignore)] +#[cfg(all(target_os = "linux"))] +#[test] +fn test_recvmsg_timestampns() { + use nix::sys::socket::*; + use nix::sys::uio::IoVec; + use nix::sys::time::*; + use std::time::*; + + // Set up + let message = "Ohayō!".as_bytes(); + let in_socket = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + None).unwrap(); + setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap(); + let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0); + bind(in_socket, &SockAddr::new_inet(localhost)).unwrap(); + let address = getsockname(in_socket).unwrap(); + // Get initial time + let time0 = SystemTime::now(); + // Send the message + let iov = [IoVec::from_slice(message)]; + let flags = MsgFlags::empty(); + let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); + assert_eq!(message.len(), l); + // Receive the message + let mut buffer = vec![0u8; message.len()]; + let mut cmsgspace = nix::cmsg_space!(TimeSpec); + let iov = [IoVec::from_mut_slice(&mut buffer)]; + let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap(); + let rtime = match r.cmsgs().next() { + Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime, + Some(_) => panic!("Unexpected control message"), + None => panic!("No control message") + }; + // Check the final time + let time1 = SystemTime::now(); + // the packet's received timestamp should lie in-between the two system + // times, unless the system clock was adjusted in the meantime. + let rduration = Duration::new(rtime.tv_sec() as u64, + rtime.tv_nsec() as u32); + assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration); + assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap()); + // Close socket + nix::unistd::close(in_socket).unwrap(); +} + +// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU +// support is suspected. +#[cfg_attr(not(any(target_arch = "x86_64")), ignore)] +#[cfg(all(target_os = "linux"))] +#[test] +fn test_recvmmsg_timestampns() { + use nix::sys::socket::*; + use nix::sys::uio::IoVec; + use nix::sys::time::*; + use std::time::*; + + // Set up + let message = "Ohayō!".as_bytes(); + let in_socket = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + None).unwrap(); + setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap(); + let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0); + bind(in_socket, &SockAddr::new_inet(localhost)).unwrap(); + let address = getsockname(in_socket).unwrap(); + // Get initial time + let time0 = SystemTime::now(); + // Send the message + let iov = [IoVec::from_slice(message)]; + let flags = MsgFlags::empty(); + let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap(); + assert_eq!(message.len(), l); + // Receive the message + let mut buffer = vec![0u8; message.len()]; + let mut cmsgspace = nix::cmsg_space!(TimeSpec); + let iov = [IoVec::from_mut_slice(&mut buffer)]; + let mut data = vec![ + RecvMmsgData { + iov, + cmsg_buffer: Some(&mut cmsgspace), + }, + ]; + let r = recvmmsg(in_socket, &mut data, flags, None).unwrap(); + let rtime = match r[0].cmsgs().next() { + Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime, + Some(_) => panic!("Unexpected control message"), + None => panic!("No control message") + }; + // Check the final time + let time1 = SystemTime::now(); + // the packet's received timestamp should lie in-between the two system + // times, unless the system clock was adjusted in the meantime. + let rduration = Duration::new(rtime.tv_sec() as u64, + rtime.tv_nsec() as u32); + assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration); + assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap()); + // Close socket + nix::unistd::close(in_socket).unwrap(); +} diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs index 5d1bafebe1..48d46626b6 100644 --- a/test/test_fcntl.rs +++ b/test/test_fcntl.rs @@ -81,19 +81,18 @@ fn test_readlink() { #[cfg(any(target_os = "linux", target_os = "android"))] mod linux_android { - use std::fs::File; use std::io::prelude::*; - use std::io::{BufRead, BufReader, SeekFrom}; + use std::io::SeekFrom; use std::os::unix::prelude::*; - use libc::loff_t; use nix::fcntl::*; - use nix::sys::stat::fstat; use nix::sys::uio::IoVec; use nix::unistd::{close, pipe, read, write}; - use tempfile::{tempfile, NamedTempFile}; + use tempfile::tempfile; + #[cfg(any(target_os = "linux"))] + use tempfile::NamedTempFile; use crate::*; @@ -206,6 +205,7 @@ mod linux_android { close(wr).unwrap(); } + #[cfg(any(target_os = "linux"))] #[test] fn test_fallocate() { let tmp = NamedTempFile::new().unwrap(); @@ -224,17 +224,11 @@ mod linux_android { // they run under QEMU. #[test] - #[cfg(not(any(target_arch = "aarch64", - target_arch = "arm", - target_arch = "armv7", - target_arch = "x86", - target_arch = "mips", - target_arch = "mips64", - target_arch = "mips64el", - target_arch = "powerpc64", - target_arch = "powerpc64le", - target_env = "musl")))] + #[cfg(all(target_os = "linux", not(target_env = "musl")))] fn test_ofd_write_lock() { + use nix::sys::stat::fstat; + use std::mem; + let tmp = NamedTempFile::new().unwrap(); let fd = tmp.as_raw_fd(); @@ -247,13 +241,14 @@ mod linux_android { } let inode = fstat(fd).expect("fstat failed").st_ino as usize; - let mut flock = libc::flock { - l_type: libc::F_WRLCK as libc::c_short, - l_whence: libc::SEEK_SET as libc::c_short, - l_start: 0, - l_len: 0, - l_pid: 0, + let mut flock: libc::flock = unsafe { + mem::zeroed() // required for Linux/mips }; + flock.l_type = libc::F_WRLCK as libc::c_short; + flock.l_whence = libc::SEEK_SET as libc::c_short; + flock.l_start = 0; + flock.l_len = 0; + flock.l_pid = 0; fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed"); assert_eq!( Some(("OFDLCK".to_string(), "WRITE".to_string())), @@ -266,17 +261,11 @@ mod linux_android { } #[test] - #[cfg(not(any(target_arch = "aarch64", - target_arch = "arm", - target_arch = "armv7", - target_arch = "x86", - target_arch = "mips", - target_arch = "mips64", - target_arch = "mips64el", - target_arch = "powerpc64", - target_arch = "powerpc64le", - target_env = "musl")))] + #[cfg(all(target_os = "linux", not(target_env = "musl")))] fn test_ofd_read_lock() { + use nix::sys::stat::fstat; + use std::mem; + let tmp = NamedTempFile::new().unwrap(); let fd = tmp.as_raw_fd(); @@ -289,13 +278,14 @@ mod linux_android { } let inode = fstat(fd).expect("fstat failed").st_ino as usize; - let mut flock = libc::flock { - l_type: libc::F_RDLCK as libc::c_short, - l_whence: libc::SEEK_SET as libc::c_short, - l_start: 0, - l_len: 0, - l_pid: 0, + let mut flock: libc::flock = unsafe { + mem::zeroed() // required for Linux/mips }; + flock.l_type = libc::F_RDLCK as libc::c_short; + flock.l_whence = libc::SEEK_SET as libc::c_short; + flock.l_start = 0; + flock.l_len = 0; + flock.l_pid = 0; fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed"); assert_eq!( Some(("OFDLCK".to_string(), "READ".to_string())), @@ -307,7 +297,13 @@ mod linux_android { assert_eq!(None, lock_info(inode)); } + #[cfg(all(target_os = "linux", not(target_env = "musl")))] fn lock_info(inode: usize) -> Option<(String, String)> { + use std::{ + fs::File, + io::BufReader + }; + let file = File::open("/proc/locks").expect("open /proc/locks failed"); let buf = BufReader::new(file); diff --git a/test/test_stat.rs b/test/test_stat.rs index 0b94666856..98112d6146 100644 --- a/test/test_stat.rs +++ b/test/test_stat.rs @@ -10,7 +10,9 @@ use std::time::{Duration, UNIX_EPOCH}; use std::path::Path; #[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -use libc::{S_IFMT, S_IFLNK, mode_t}; +use libc::{S_IFMT, S_IFLNK}; +#[cfg(not(target_os = "redox"))] +use libc::mode_t; #[cfg(not(target_os = "redox"))] use nix::{fcntl, Error}; @@ -69,6 +71,8 @@ fn assert_stat_results(stat_result: Result) { } #[cfg(not(any(target_os = "netbsd", target_os = "redox")))] +// (Android's st_blocks is ulonglong which is always non-negative.) +#[cfg_attr(target_os = "android", allow(unused_comparisons))] fn assert_lstat_results(stat_result: Result) { let stats = stat_result.expect("stat call failed"); assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent @@ -86,7 +90,6 @@ fn assert_lstat_results(stat_result: Result) { // st_blocks depends on whether the machine's file system uses fast // or slow symlinks, so just make sure it's not negative - // (Android's st_blocks is ulonglong which is always non-negative.) assert!(stats.st_blocks >= 0); } @@ -159,14 +162,14 @@ fn test_fchmod() { fchmod(file.as_raw_fd(), mode1).unwrap(); let file_stat1 = stat(&filename).unwrap(); - assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits()); + assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits()); let mut mode2 = Mode::empty(); mode2.insert(Mode::S_IROTH); fchmod(file.as_raw_fd(), mode2).unwrap(); let file_stat2 = stat(&filename).unwrap(); - assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits()); + assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits()); } #[test] @@ -186,7 +189,7 @@ fn test_fchmodat() { fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink).unwrap(); let file_stat1 = stat(&fullpath).unwrap(); - assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits()); + assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits()); chdir(tempdir.path()).unwrap(); @@ -195,7 +198,7 @@ fn test_fchmodat() { fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap(); let file_stat2 = stat(&fullpath).unwrap(); - assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits()); + assert_eq!(file_stat2.st_mode as mode_t & 0o7777, mode2.bits()); } /// Asserts that the atime and mtime in a file's metadata match expected values. diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 9f71016802..4acfff3792 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -23,7 +23,7 @@ use std::os::unix::prelude::*; #[cfg(not(target_os = "redox"))] use std::path::Path; use tempfile::{tempdir, tempfile}; -use libc::{_exit, off_t}; +use libc::{_exit, mode_t, off_t}; use crate::*; @@ -102,7 +102,7 @@ fn test_mkfifo() { mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap(); let stats = stat::stat(&mkfifo_fifo).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode); + let typ = stat::SFlag::from_bits_truncate(stats.st_mode as mode_t); assert!(typ == SFlag::S_IFIFO); } @@ -629,10 +629,10 @@ fn test_sysconf_unsupported() { #[test] fn test_pipe() { let (fd0, fd1) = pipe().unwrap(); - let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode); + let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode as mode_t); // S_IFIFO means it's a pipe assert_eq!(m0, SFlag::S_IFIFO); - let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode); + let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode as mode_t); assert_eq!(m1, SFlag::S_IFIFO); } @@ -926,7 +926,9 @@ fn test_linkat_follow_symlink() { let newfilestat = stat::stat(&newfilepath).unwrap(); // Check the file type of the new link - assert!((stat::SFlag::from_bits_truncate(newfilestat.st_mode) & SFlag::S_IFMT) == SFlag::S_IFREG); + assert_eq!((stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t) & SFlag::S_IFMT), + SFlag::S_IFREG + ); // Check the number of hard links to the original file assert_eq!(newfilestat.st_nlink, 2);