diff --git a/ci/docker/x86_64-rumprun-netbsd/runtest.rs b/ci/docker/x86_64-rumprun-netbsd/runtest.rs index 94b5946080b69..7e96fbfab442d 100644 --- a/ci/docker/x86_64-rumprun-netbsd/runtest.rs +++ b/ci/docker/x86_64-rumprun-netbsd/runtest.rs @@ -47,7 +47,8 @@ fn find_ok(input: &mut Read, tx: mpsc::Sender<()>) { for line in BufReader::new(input).lines() { let line = line.unwrap(); println!("{}", line); - if line.starts_with("PASSED ") && line.contains(" tests") { + if (line.starts_with("PASSED ") && line.contains(" tests")) || + line.starts_with("test result: ok"){ tx.send(()).unwrap(); } } diff --git a/ci/ios/deploy_and_run_on_ios_simulator.rs b/ci/ios/deploy_and_run_on_ios_simulator.rs index 95df52d76d593..2075be6d62007 100644 --- a/ci/ios/deploy_and_run_on_ios_simulator.rs +++ b/ci/ios/deploy_and_run_on_ios_simulator.rs @@ -129,8 +129,11 @@ fn run_app_on_simulator() { let stdout = String::from_utf8_lossy(&output.stdout); let passed = stdout.lines() - .find(|l| l.contains("PASSED")) - .map(|l| l.contains("tests")) + .find(|l| + (l.contains("PASSED") && + l.contains("tests")) || + l.contains("test result: ok") + ) .unwrap_or(false); println!("Shutting down simulator"); diff --git a/ci/run.sh b/ci/run.sh index 853b7c10537ff..1fb5e127a254e 100755 --- a/ci/run.sh +++ b/ci/run.sh @@ -77,7 +77,7 @@ if [ "$QEMU" != "" ]; then -net user \ -nographic \ -vga none 2>&1 | tee "${CARGO_TARGET_DIR}/out.log" - exec grep "^PASSED .* tests" "${CARGO_TARGET_DIR}/out.log" + exec egrep "^(PASSED)|(test result: ok)" "${CARGO_TARGET_DIR}/out.log" fi # FIXME: x86_64-unknown-linux-gnux32 fail to compile without --release diff --git a/ci/runtest-android.rs b/ci/runtest-android.rs index a68b854cf68a0..18d39bfdfe89c 100644 --- a/ci/runtest-android.rs +++ b/ci/runtest-android.rs @@ -38,8 +38,10 @@ fn main() { String::from_utf8_lossy(&output.stderr)); let stdout = String::from_utf8_lossy(&output.stdout); - let mut lines = stdout.lines().filter(|l| l.starts_with("PASSED ")); - if !lines.any(|l| l.contains(" tests")) { + let passed = stdout.lines().find(|l| + (l.starts_with("PASSED ") && l.contains(" tests")) || + l.starts_with("test result: ok") + ).unwrap_or_else(|| { panic!("failed to find successful test run"); - } + }); } diff --git a/ci/test-runner-linux b/ci/test-runner-linux index 5f1fb237c28ea..569fa0077006f 100755 --- a/ci/test-runner-linux +++ b/ci/test-runner-linux @@ -5,7 +5,18 @@ set -e arch=$1 prog=$2 +# Skip cmsg test on linux-s390x +# https://github.com/rust-lang/libc/issues/1240 +if [ "$arch" = "s390x" ]; then + progbasename=`basename $prog` + if [ "${progbasename%%-*}" = "cmsg" ]; then + exit 0 + fi +fi + cd /qemu/init +echo "#!/bin/sh\n/prog --color=never" > run_prog.sh +chmod +x run_prog.sh cp -f $2 prog find . | cpio --create --format='newc' --quiet | gzip > ../initrd.gz cd .. @@ -15,9 +26,9 @@ timeout 30s qemu-system-$arch \ -nographic \ -kernel kernel \ -initrd initrd.gz \ - -append init=/prog > output || true + -append init=/run_prog.sh > output || true # remove kernel messages tr -d '\r' < output | egrep -v '^\[' -grep PASSED output > /dev/null +egrep "(PASSED)|(test result: ok)" output > /dev/null diff --git a/libc-test/Cargo.toml b/libc-test/Cargo.toml index f8bd11b5edc90..7eecc4994cabe 100644 --- a/libc-test/Cargo.toml +++ b/libc-test/Cargo.toml @@ -9,6 +9,7 @@ path = ".." default-features = false [build-dependencies] +cc = "1.0" ctest = "0.2.8" [features] @@ -27,3 +28,7 @@ name = "linux-fcntl" path = "test/linux_fcntl.rs" harness = false +[[test]] +name = "cmsg" +path = "test/cmsg.rs" +harness = true diff --git a/libc-test/build.rs b/libc-test/build.rs index d81a54d716224..eab5b762f0db2 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1,10 +1,21 @@ #![deny(warnings)] +extern crate cc; extern crate ctest; use std::env; -fn main() { +#[cfg(unix)] +fn do_cc() { + cc::Build::new() + .file("src/cmsg.c") + .compile("cmsg"); +} +#[cfg(not(unix))] +fn do_cc() { +} + +fn do_ctest() { let target = env::var("TARGET").unwrap(); let aarch64 = target.contains("aarch64"); let i686 = target.contains("i686"); @@ -975,3 +986,8 @@ fn main() { } cfg.generate("../src/lib.rs", "linux_fcntl.rs"); } + +fn main() { + do_cc(); + do_ctest(); +} diff --git a/libc-test/src/cmsg.c b/libc-test/src/cmsg.c new file mode 100644 index 0000000000000..a8b1c371736c8 --- /dev/null +++ b/libc-test/src/cmsg.c @@ -0,0 +1,28 @@ +#include +#include + +// Since the cmsg(3) macros are macros instead of functions, they aren't +// available to FFI. libc must reimplement them, which is error-prone. This +// file provides FFI access to the actual macros so they can be tested against +// the Rust reimplementations. + +struct cmsghdr *cmsg_firsthdr(struct msghdr *msgh) { + return CMSG_FIRSTHDR(msgh); +} + +struct cmsghdr *cmsg_nxthdr(struct msghdr *msgh, struct cmsghdr *cmsg) { + return CMSG_NXTHDR(msgh, cmsg); +} + +size_t cmsg_space(size_t length) { + return CMSG_SPACE(length); +} + +size_t cmsg_len(size_t length) { + return CMSG_LEN(length); +} + +unsigned char *cmsg_data(struct cmsghdr *cmsg) { + return CMSG_DATA(cmsg); +} + diff --git a/libc-test/test/cmsg.rs b/libc-test/test/cmsg.rs new file mode 100644 index 0000000000000..c9eecb628d975 --- /dev/null +++ b/libc-test/test/cmsg.rs @@ -0,0 +1,99 @@ +//! Compare libc's CMSG(3) family of functions against the actual C macros, for +//! various inputs. + +extern crate libc; + +#[cfg(unix)] +mod t { + +use libc::{self, c_uchar, c_uint, c_void, cmsghdr, msghdr}; +use std::mem; + +extern { + pub fn cmsg_firsthdr(msgh: *const msghdr) -> *mut cmsghdr; + pub fn cmsg_nxthdr(mhdr: *const msghdr, + cmsg: *const cmsghdr) -> *mut cmsghdr; + pub fn cmsg_space(length: c_uint) -> usize; + pub fn cmsg_len(length: c_uint) -> usize; + pub fn cmsg_data(cmsg: *const cmsghdr) -> *mut c_uchar; +} + +#[test] +fn test_cmsg_data() { + for l in 0..128 { + let pcmsghdr = l as *const cmsghdr; + unsafe { + assert_eq!(libc::CMSG_DATA(pcmsghdr), cmsg_data(pcmsghdr)); + } + } +} + +#[test] +fn test_cmsg_firsthdr() { + let mut mhdr: msghdr = unsafe{mem::zeroed()}; + mhdr.msg_control = 0xdeadbeef as *mut c_void; + let pmhdr = &mhdr as *const msghdr; + for l in 0..128 { + mhdr.msg_controllen = l; + unsafe { + assert_eq!(libc::CMSG_FIRSTHDR(pmhdr), cmsg_firsthdr(pmhdr)); + } + } +} + +#[test] +fn test_cmsg_len() { + for l in 0..128 { + unsafe { + assert_eq!(libc::CMSG_LEN(l) as usize, cmsg_len(l)); + } + } +} + +// Skip on sparc64 +// https://github.com/rust-lang/libc/issues/1239 +#[cfg(not(target_arch = "sparc64"))] +#[test] +fn test_cmsg_nxthdr() { + use std::ptr; + + let mut buffer = [0u8; 256]; + let mut mhdr: msghdr = unsafe{mem::zeroed()}; + let pmhdr = &mhdr as *const msghdr; + for start_ofs in 0..64 { + let pcmsghdr = &mut buffer[start_ofs] as *mut u8 as *mut cmsghdr; + mhdr.msg_control = pcmsghdr as *mut c_void; + mhdr.msg_controllen = (160 - start_ofs) as _; + for cmsg_len in 0..64 { + for next_cmsg_len in 0..32 { + for i in buffer[start_ofs..].iter_mut() { + *i = 0; + } + unsafe { + (*pcmsghdr).cmsg_len = cmsg_len; + let libc_next = libc::CMSG_NXTHDR(pmhdr, pcmsghdr); + let next = cmsg_nxthdr(pmhdr, pcmsghdr); + assert_eq!(libc_next, next); + + if libc_next != ptr::null_mut() { + (*libc_next).cmsg_len = next_cmsg_len; + let libc_next = libc::CMSG_NXTHDR(pmhdr, pcmsghdr); + let next = cmsg_nxthdr(pmhdr, pcmsghdr); + assert_eq!(libc_next, next); + } + } + } + } + } +} + +#[test] +fn test_cmsg_space() { + unsafe { + for l in 0..128 { + assert_eq!(libc::CMSG_SPACE(l) as usize, cmsg_space(l)); + } + } +} + +} diff --git a/src/unix/bsd/apple/mod.rs b/src/unix/bsd/apple/mod.rs index 59394c6bcaf1b..85332180e015d 100644 --- a/src/unix/bsd/apple/mod.rs +++ b/src/unix/bsd/apple/mod.rs @@ -2777,11 +2777,10 @@ f! { return ::CMSG_FIRSTHDR(mhdr); }; let cmsg_len = (*cmsg).cmsg_len as usize; - let next = cmsg as usize + __DARWIN_ALIGN32(cmsg_len as usize) - + __DARWIN_ALIGN32(mem::size_of::<::cmsghdr>()); + let next = cmsg as usize + __DARWIN_ALIGN32(cmsg_len as usize); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; - if next > max { + if next + __DARWIN_ALIGN32(mem::size_of::<::cmsghdr>()) > max { 0 as *mut ::cmsghdr } else { next as *mut ::cmsghdr @@ -2800,7 +2799,7 @@ f! { } pub fn CMSG_LEN(length: ::c_uint) -> ::c_uint { - __DARWIN_ALIGN32(mem::size_of::<::cmsghdr>() + length as usize) + (__DARWIN_ALIGN32(mem::size_of::<::cmsghdr>()) + length as usize) as ::c_uint } diff --git a/src/unix/notbsd/android/mod.rs b/src/unix/notbsd/android/mod.rs index 0e2eebf056e39..f768ce1283e0e 100644 --- a/src/unix/notbsd/android/mod.rs +++ b/src/unix/notbsd/android/mod.rs @@ -1688,6 +1688,20 @@ pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002; pub const ENOATTR: ::c_int = ::ENODATA; f! { + pub fn CMSG_NXTHDR(mhdr: *const msghdr, + cmsg: *const cmsghdr) -> *mut cmsghdr { + let next = (cmsg as usize + + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) + as *mut cmsghdr; + let max = (*mhdr).msg_control as usize + + (*mhdr).msg_controllen as usize; + if (next.offset(1)) as usize > max { + 0 as *mut cmsghdr + } else { + next as *mut cmsghdr + } + } + pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = 0; diff --git a/src/unix/notbsd/emscripten.rs b/src/unix/notbsd/emscripten.rs index 9bf2026b22e4d..2685e769fc1d6 100644 --- a/src/unix/notbsd/emscripten.rs +++ b/src/unix/notbsd/emscripten.rs @@ -1515,6 +1515,23 @@ pub const ARPD_FLUSH: ::c_ushort = 0x03; pub const ATF_MAGIC: ::c_int = 0x80; f! { + pub fn CMSG_NXTHDR(mhdr: *const msghdr, + cmsg: *const cmsghdr) -> *mut cmsghdr { + if ((*cmsg).cmsg_len as usize) < mem::size_of::() { + return 0 as *mut cmsghdr; + }; + let next = (cmsg as usize + + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) + as *mut cmsghdr; + let max = (*mhdr).msg_control as usize + + (*mhdr).msg_controllen as usize; + if (next.offset(1)) as usize > max { + 0 as *mut cmsghdr + } else { + next as *mut cmsghdr + } + } + pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; diff --git a/src/unix/notbsd/linux/mod.rs b/src/unix/notbsd/linux/mod.rs index e1a24dcd3c0b8..034db9bc85482 100644 --- a/src/unix/notbsd/linux/mod.rs +++ b/src/unix/notbsd/linux/mod.rs @@ -1897,6 +1897,25 @@ pub const SOF_TIMESTAMPING_SYS_HARDWARE: ::c_uint = 1 << 5; pub const SOF_TIMESTAMPING_RAW_HARDWARE: ::c_uint = 1 << 6; f! { + pub fn CMSG_NXTHDR(mhdr: *const msghdr, + cmsg: *const cmsghdr) -> *mut cmsghdr { + if ((*cmsg).cmsg_len as usize) < mem::size_of::() { + return 0 as *mut cmsghdr; + }; + let next = (cmsg as usize + + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) + as *mut cmsghdr; + let max = (*mhdr).msg_control as usize + + (*mhdr).msg_controllen as usize; + if (next.offset(1)) as usize > max || + next as usize + super::CMSG_ALIGN((*next).cmsg_len as usize) > max + { + 0 as *mut cmsghdr + } else { + next as *mut cmsghdr + } + } + pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; diff --git a/src/unix/notbsd/mod.rs b/src/unix/notbsd/mod.rs index 51414e688d73d..3698590ad4525 100644 --- a/src/unix/notbsd/mod.rs +++ b/src/unix/notbsd/mod.rs @@ -1114,6 +1114,10 @@ pub const ARPHRD_IEEE802154: u16 = 804; pub const ARPHRD_VOID: u16 = 0xFFFF; pub const ARPHRD_NONE: u16 = 0xFFFE; +fn CMSG_ALIGN(len: usize) -> usize { + len + mem::size_of::() - 1 & !(mem::size_of::() - 1) +} + f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { @@ -1123,33 +1127,17 @@ f! { } } - pub fn CMSG_NXTHDR(mhdr: *const msghdr, - cmsg: *const cmsghdr) -> *mut cmsghdr { - if cmsg.is_null() { - return CMSG_FIRSTHDR(mhdr); - }; - let pad = mem::align_of::() - 1; - let next = cmsg as usize + (*cmsg).cmsg_len as usize + pad & !pad; - let max = (*mhdr).msg_control as usize - + (*mhdr).msg_controllen as usize; - if next < max { - next as *mut cmsghdr - } else { - 0 as *mut cmsghdr - } - } - pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut ::c_uchar { cmsg.offset(1) as *mut ::c_uchar } pub fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { - let pad = mem::align_of::() as ::c_uint - 1; - mem::size_of::() as ::c_uint + ((length + pad) & !pad) + (CMSG_ALIGN(length as usize) + CMSG_ALIGN(mem::size_of::())) + as ::c_uint } pub fn CMSG_LEN(length: ::c_uint) -> ::c_uint { - mem::size_of::() as ::c_uint + length + CMSG_ALIGN(mem::size_of::()) as ::c_uint + length } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () {