summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml7
-rw-r--r--CHANGELOG.md2
-rw-r--r--Cargo.toml3
-rw-r--r--src/dir.rs10
-rw-r--r--src/macros.rs13
-rw-r--r--src/sys/socket/addr.rs1
-rw-r--r--src/sys/socket/mod.rs12
-rw-r--r--src/unistd.rs8
-rw-r--r--test/sys/mod.rs2
-rw-r--r--test/sys/test_socket.rs25
-rw-r--r--test/test_fcntl.rs70
-rw-r--r--test/test_stat.rs15
-rw-r--r--test/test_unistd.rs12
13 files changed, 90 insertions, 90 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index f598e2e6..381fb629 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 93be70fe..0ead550e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,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 5eb30fe2..f5f6dd89 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,6 +36,9 @@ 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/dir.rs b/src/dir.rs
index a58af19c..7c35d70f 100644
--- a/src/dir.rs
+++ b/src/dir.rs
@@ -53,14 +53,12 @@ impl Dir {
/// Converts from a file descriptor, closing it on success or failure.
pub fn from_fd(fd: RawFd) -> Result<Self> {
- let d = unsafe { libc::fdopendir(fd) };
- if d.is_null() {
+ let d = ptr::NonNull::new(unsafe { libc::fdopendir(fd) }).ok_or_else(|| {
let e = Error::last();
unsafe { libc::close(fd) };
- return Err(e);
- };
- // Always guaranteed to be non-null by the previous check
- Ok(Dir(ptr::NonNull::new(d).unwrap()))
+ e
+ })?;
+ Ok(Dir(d))
}
/// Returns an iterator of `Result<Entry>` which rewinds when finished.
diff --git a/src/macros.rs b/src/macros.rs
index feb02ea7..7d6ac8df 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 1f7f4ec6..71b2c973 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 6e22274c..c04af50f 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -5,6 +5,7 @@ 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"))]
@@ -1113,23 +1114,22 @@ pub fn sendmmsg<'a, I, C>(
let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
- let mut cmsgs_buffer = vec![0u8; 0];
+ let mut cmsgs_buffers = Vec::<Vec<u8>>::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/unistd.rs b/src/unistd.rs
index f93c2192..d3afeac6 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 14b03784..4f5316ff 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 22ecece7..32318ef0 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");
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index 5d1bafeb..48d46626 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 0b946668..98112d61 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<FileStat>) {
}
#[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<FileStat>) {
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<FileStat>) {
// 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 9f710168..4acfff37 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);