diff options
Diffstat (limited to 'vendor/nix/test')
42 files changed, 0 insertions, 10024 deletions
diff --git a/vendor/nix/test/common/mod.rs b/vendor/nix/test/common/mod.rs deleted file mode 100644 index bb056aab8..000000000 --- a/vendor/nix/test/common/mod.rs +++ /dev/null @@ -1,149 +0,0 @@ -use cfg_if::cfg_if; - -#[macro_export] -macro_rules! skip { - ($($reason: expr),+) => { - use ::std::io::{self, Write}; - - let stderr = io::stderr(); - let mut handle = stderr.lock(); - writeln!(handle, $($reason),+).unwrap(); - return; - } -} - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - #[macro_export] macro_rules! require_capability { - ($name:expr, $capname:ident) => { - use ::caps::{Capability, CapSet, has_cap}; - - if !has_cap(None, CapSet::Effective, Capability::$capname) - .unwrap() - { - skip!("{} requires capability {}. Skipping test.", $name, Capability::$capname); - } - } - } - } else if #[cfg(not(target_os = "redox"))] { - #[macro_export] macro_rules! require_capability { - ($name:expr, $capname:ident) => {} - } - } -} - -/// Skip the test if we don't have the ability to mount file systems. -#[cfg(target_os = "freebsd")] -#[macro_export] -macro_rules! require_mount { - ($name:expr) => { - use ::sysctl::{CtlValue, Sysctl}; - use nix::unistd::Uid; - - let ctl = ::sysctl::Ctl::new("vfs.usermount").unwrap(); - if !Uid::current().is_root() && CtlValue::Int(0) == ctl.value().unwrap() - { - skip!( - "{} requires the ability to mount file systems. Skipping test.", - $name - ); - } - }; -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -#[macro_export] -macro_rules! skip_if_cirrus { - ($reason:expr) => { - if std::env::var_os("CIRRUS_CI").is_some() { - skip!("{}", $reason); - } - }; -} - -#[cfg(target_os = "freebsd")] -#[macro_export] -macro_rules! skip_if_jailed { - ($name:expr) => { - use ::sysctl::{CtlValue, Sysctl}; - - let ctl = ::sysctl::Ctl::new("security.jail.jailed").unwrap(); - if let CtlValue::Int(1) = ctl.value().unwrap() { - skip!("{} cannot run in a jail. Skipping test.", $name); - } - }; -} - -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -#[macro_export] -macro_rules! skip_if_not_root { - ($name:expr) => { - use nix::unistd::Uid; - - if !Uid::current().is_root() { - skip!("{} requires root privileges. Skipping test.", $name); - } - }; -} - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - #[macro_export] macro_rules! skip_if_seccomp { - ($name:expr) => { - if let Ok(s) = std::fs::read_to_string("/proc/self/status") { - for l in s.lines() { - let mut fields = l.split_whitespace(); - if fields.next() == Some("Seccomp:") && - fields.next() != Some("0") - { - skip!("{} cannot be run in Seccomp mode. Skipping test.", - stringify!($name)); - } - } - } - } - } - } else if #[cfg(not(target_os = "redox"))] { - #[macro_export] macro_rules! skip_if_seccomp { - ($name:expr) => {} - } - } -} - -cfg_if! { - if #[cfg(target_os = "linux")] { - #[macro_export] macro_rules! require_kernel_version { - ($name:expr, $version_requirement:expr) => { - use semver::{Version, VersionReq}; - - let version_requirement = VersionReq::parse($version_requirement) - .expect("Bad match_version provided"); - - let uname = nix::sys::utsname::uname().unwrap(); - println!("{}", uname.sysname().to_str().unwrap()); - println!("{}", uname.nodename().to_str().unwrap()); - println!("{}", uname.release().to_str().unwrap()); - println!("{}", uname.version().to_str().unwrap()); - println!("{}", uname.machine().to_str().unwrap()); - - // Fix stuff that the semver parser can't handle - let fixed_release = &uname.release().to_str().unwrap().to_string() - // Fedora 33 reports version as 4.18.el8_2.x86_64 or - // 5.18.200-fc33.x86_64. Remove the underscore. - .replace("_", "-") - // Cirrus-CI reports version as 4.19.112+ . Remove the + - .replace("+", ""); - let mut version = Version::parse(fixed_release).unwrap(); - - //Keep only numeric parts - version.pre = semver::Prerelease::EMPTY; - version.build = semver::BuildMetadata::EMPTY; - - if !version_requirement.matches(&version) { - skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`", - stringify!($name), version, version_requirement); - } - } - } - } -} diff --git a/vendor/nix/test/sys/mod.rs b/vendor/nix/test/sys/mod.rs deleted file mode 100644 index 20312120a..000000000 --- a/vendor/nix/test/sys/mod.rs +++ /dev/null @@ -1,60 +0,0 @@ -mod test_signal; - -// NOTE: DragonFly lacks a kernel-level implementation of Posix AIO as of -// this writing. There is an user-level implementation, but whether aio -// works or not heavily depends on which pthread implementation is chosen -// by the user at link time. For this reason we do not want to run aio test -// cases on DragonFly. -#[cfg(any( - target_os = "freebsd", - target_os = "ios", - all(target_os = "linux", not(target_env = "uclibc")), - target_os = "macos", - target_os = "netbsd" -))] -mod test_aio; -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -mod test_ioctl; -#[cfg(not(target_os = "redox"))] -mod test_mman; -#[cfg(not(target_os = "redox"))] -mod test_select; -#[cfg(target_os = "linux")] -mod test_signalfd; -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -mod test_socket; -#[cfg(not(any(target_os = "redox")))] -mod test_sockopt; -mod test_stat; -#[cfg(any(target_os = "android", target_os = "linux"))] -mod test_sysinfo; -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -mod test_termios; -mod test_uio; -mod test_wait; - -#[cfg(any(target_os = "android", target_os = "linux"))] -mod test_epoll; -#[cfg(target_os = "linux")] -mod test_inotify; -mod test_pthread; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" -))] -mod test_ptrace; -#[cfg(any(target_os = "android", target_os = "linux"))] -mod test_timerfd; diff --git a/vendor/nix/test/sys/test_aio.rs b/vendor/nix/test/sys/test_aio.rs deleted file mode 100644 index 84086f80c..000000000 --- a/vendor/nix/test/sys/test_aio.rs +++ /dev/null @@ -1,626 +0,0 @@ -use std::{ - io::{Read, Seek, Write}, - ops::Deref, - os::unix::io::AsRawFd, - pin::Pin, - sync::atomic::{AtomicBool, Ordering}, - thread, time, -}; - -use libc::c_int; -use nix::{ - errno::*, - sys::{ - aio::*, - signal::{ - sigaction, SaFlags, SigAction, SigHandler, SigSet, SigevNotify, - Signal, - }, - time::{TimeSpec, TimeValLike}, - }, -}; -use tempfile::tempfile; - -lazy_static! { - pub static ref SIGNALED: AtomicBool = AtomicBool::new(false); -} - -extern "C" fn sigfunc(_: c_int) { - SIGNALED.store(true, Ordering::Relaxed); -} - -// Helper that polls an AioCb for completion or error -macro_rules! poll_aio { - ($aiocb: expr) => { - loop { - let err = $aiocb.as_mut().error(); - if err != Err(Errno::EINPROGRESS) { - break err; - }; - thread::sleep(time::Duration::from_millis(10)); - } - }; -} - -mod aio_fsync { - use super::*; - - #[test] - fn test_accessors() { - let aiocb = AioFsync::new( - 1001, - AioFsyncMode::O_SYNC, - 42, - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 99, - }, - ); - assert_eq!(1001, aiocb.fd()); - assert_eq!(AioFsyncMode::O_SYNC, aiocb.mode()); - assert_eq!(42, aiocb.priority()); - let sev = aiocb.sigevent().sigevent(); - assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo); - assert_eq!(99, sev.sigev_value.sival_ptr as i64); - } - - /// `AioFsync::submit` should not modify the `AioCb` object if - /// `libc::aio_fsync` returns an error - // Skip on Linux, because Linux's AIO implementation can't detect errors - // synchronously - #[test] - #[cfg(any(target_os = "freebsd", target_os = "macos"))] - fn error() { - use std::mem; - - const INITIAL: &[u8] = b"abcdef123456"; - // Create an invalid AioFsyncMode - let mode = unsafe { mem::transmute(666) }; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiof = Box::pin(AioFsync::new( - f.as_raw_fd(), - mode, - 0, - SigevNotify::SigevNone, - )); - let err = aiof.as_mut().submit(); - err.expect_err("assertion failed"); - } - - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn ok() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let fd = f.as_raw_fd(); - let mut aiof = Box::pin(AioFsync::new( - fd, - AioFsyncMode::O_SYNC, - 0, - SigevNotify::SigevNone, - )); - aiof.as_mut().submit().unwrap(); - poll_aio!(&mut aiof).unwrap(); - aiof.as_mut().aio_return().unwrap(); - } -} - -mod aio_read { - use super::*; - - #[test] - fn test_accessors() { - let mut rbuf = vec![0; 4]; - let aiocb = AioRead::new( - 1001, - 2, //offset - &mut rbuf, - 42, //priority - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 99, - }, - ); - assert_eq!(1001, aiocb.fd()); - assert_eq!(4, aiocb.nbytes()); - assert_eq!(2, aiocb.offset()); - assert_eq!(42, aiocb.priority()); - let sev = aiocb.sigevent().sigevent(); - assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo); - assert_eq!(99, sev.sigev_value.sival_ptr as i64); - } - - // Tests AioWrite.cancel. We aren't trying to test the OS's implementation, - // only our bindings. So it's sufficient to check that cancel - // returned any AioCancelStat value. - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn cancel() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let fd = f.as_raw_fd(); - let mut aior = - Box::pin(AioRead::new(fd, 2, &mut rbuf, 0, SigevNotify::SigevNone)); - aior.as_mut().submit().unwrap(); - - aior.as_mut().cancel().unwrap(); - - // Wait for aiow to complete, but don't care whether it succeeded - let _ = poll_aio!(&mut aior); - let _ = aior.as_mut().aio_return(); - } - - /// `AioRead::submit` should not modify the `AioCb` object if - /// `libc::aio_read` returns an error - // Skip on Linux, because Linux's AIO implementation can't detect errors - // synchronously - #[test] - #[cfg(any(target_os = "freebsd", target_os = "macos"))] - fn error() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aior = Box::pin(AioRead::new( - f.as_raw_fd(), - -1, //an invalid offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - )); - aior.as_mut().submit().expect_err("assertion failed"); - } - - // Test a simple aio operation with no completion notification. We must - // poll for completion - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn ok() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - const EXPECT: &[u8] = b"cdef"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - { - let fd = f.as_raw_fd(); - let mut aior = Box::pin(AioRead::new( - fd, - 2, - &mut rbuf, - 0, - SigevNotify::SigevNone, - )); - aior.as_mut().submit().unwrap(); - - let err = poll_aio!(&mut aior); - assert_eq!(err, Ok(())); - assert_eq!(aior.as_mut().aio_return().unwrap(), EXPECT.len()); - } - assert_eq!(EXPECT, rbuf.deref().deref()); - } - - // Like ok, but allocates the structure on the stack. - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn on_stack() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf = vec![0; 4]; - const EXPECT: &[u8] = b"cdef"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - { - let fd = f.as_raw_fd(); - let mut aior = - AioRead::new(fd, 2, &mut rbuf, 0, SigevNotify::SigevNone); - let mut aior = unsafe { Pin::new_unchecked(&mut aior) }; - aior.as_mut().submit().unwrap(); - - let err = poll_aio!(&mut aior); - assert_eq!(err, Ok(())); - assert_eq!(aior.as_mut().aio_return().unwrap(), EXPECT.len()); - } - assert_eq!(EXPECT, rbuf.deref().deref()); - } -} - -#[cfg(target_os = "freebsd")] -#[cfg(fbsd14)] -mod aio_readv { - use std::io::IoSliceMut; - - use super::*; - - #[test] - fn test_accessors() { - let mut rbuf0 = vec![0; 4]; - let mut rbuf1 = vec![0; 8]; - let mut rbufs = - [IoSliceMut::new(&mut rbuf0), IoSliceMut::new(&mut rbuf1)]; - let aiocb = AioReadv::new( - 1001, - 2, //offset - &mut rbufs, - 42, //priority - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 99, - }, - ); - assert_eq!(1001, aiocb.fd()); - assert_eq!(2, aiocb.iovlen()); - assert_eq!(2, aiocb.offset()); - assert_eq!(42, aiocb.priority()); - let sev = aiocb.sigevent().sigevent(); - assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo); - assert_eq!(99, sev.sigev_value.sival_ptr as i64); - } - - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn ok() { - const INITIAL: &[u8] = b"abcdef123456"; - let mut rbuf0 = vec![0; 4]; - let mut rbuf1 = vec![0; 2]; - let mut rbufs = - [IoSliceMut::new(&mut rbuf0), IoSliceMut::new(&mut rbuf1)]; - const EXPECT0: &[u8] = b"cdef"; - const EXPECT1: &[u8] = b"12"; - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - { - let fd = f.as_raw_fd(); - let mut aior = Box::pin(AioReadv::new( - fd, - 2, - &mut rbufs, - 0, - SigevNotify::SigevNone, - )); - aior.as_mut().submit().unwrap(); - - let err = poll_aio!(&mut aior); - assert_eq!(err, Ok(())); - assert_eq!( - aior.as_mut().aio_return().unwrap(), - EXPECT0.len() + EXPECT1.len() - ); - } - assert_eq!(&EXPECT0, &rbuf0); - assert_eq!(&EXPECT1, &rbuf1); - } -} - -mod aio_write { - use super::*; - - #[test] - fn test_accessors() { - let wbuf = vec![0; 4]; - let aiocb = AioWrite::new( - 1001, - 2, //offset - &wbuf, - 42, //priority - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 99, - }, - ); - assert_eq!(1001, aiocb.fd()); - assert_eq!(4, aiocb.nbytes()); - assert_eq!(2, aiocb.offset()); - assert_eq!(42, aiocb.priority()); - let sev = aiocb.sigevent().sigevent(); - assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo); - assert_eq!(99, sev.sigev_value.sival_ptr as i64); - } - - // Tests AioWrite.cancel. We aren't trying to test the OS's implementation, - // only our bindings. So it's sufficient to check that cancel - // returned any AioCancelStat value. - #[test] - #[cfg_attr(target_env = "musl", ignore)] - fn cancel() { - let wbuf: &[u8] = b"CDEF"; - - let f = tempfile().unwrap(); - let mut aiow = Box::pin(AioWrite::new( - f.as_raw_fd(), - 0, - wbuf, - 0, - SigevNotify::SigevNone, - )); - aiow.as_mut().submit().unwrap(); - let err = aiow.as_mut().error(); - assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS)); - - aiow.as_mut().cancel().unwrap(); - - // Wait for aiow to complete, but don't care whether it succeeded - let _ = poll_aio!(&mut aiow); - let _ = aiow.as_mut().aio_return(); - } - - // Test a simple aio operation with no completion notification. We must - // poll for completion. - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn ok() { - const INITIAL: &[u8] = b"abcdef123456"; - let wbuf = "CDEF".to_string().into_bytes(); - let mut rbuf = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiow = Box::pin(AioWrite::new( - f.as_raw_fd(), - 2, - &wbuf, - 0, - SigevNotify::SigevNone, - )); - aiow.as_mut().submit().unwrap(); - - let err = poll_aio!(&mut aiow); - assert_eq!(err, Ok(())); - assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len()); - - f.rewind().unwrap(); - let len = f.read_to_end(&mut rbuf).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf, EXPECT); - } - - // Like ok, but allocates the structure on the stack. - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn on_stack() { - const INITIAL: &[u8] = b"abcdef123456"; - let wbuf = "CDEF".to_string().into_bytes(); - let mut rbuf = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiow = AioWrite::new( - f.as_raw_fd(), - 2, //offset - &wbuf, - 0, //priority - SigevNotify::SigevNone, - ); - let mut aiow = unsafe { Pin::new_unchecked(&mut aiow) }; - aiow.as_mut().submit().unwrap(); - - let err = poll_aio!(&mut aiow); - assert_eq!(err, Ok(())); - assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len()); - - f.rewind().unwrap(); - let len = f.read_to_end(&mut rbuf).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf, EXPECT); - } - - /// `AioWrite::write` should not modify the `AioCb` object if - /// `libc::aio_write` returns an error. - // Skip on Linux, because Linux's AIO implementation can't detect errors - // synchronously - #[test] - #[cfg(any(target_os = "freebsd", target_os = "macos"))] - fn error() { - let wbuf = "CDEF".to_string().into_bytes(); - let mut aiow = Box::pin(AioWrite::new( - 666, // An invalid file descriptor - 0, //offset - &wbuf, - 0, //priority - SigevNotify::SigevNone, - )); - aiow.as_mut().submit().expect_err("assertion failed"); - // Dropping the AioWrite at this point should not panic - } -} - -#[cfg(target_os = "freebsd")] -#[cfg(fbsd14)] -mod aio_writev { - use std::io::IoSlice; - - use super::*; - - #[test] - fn test_accessors() { - let wbuf0 = vec![0; 4]; - let wbuf1 = vec![0; 8]; - let wbufs = [IoSlice::new(&wbuf0), IoSlice::new(&wbuf1)]; - let aiocb = AioWritev::new( - 1001, - 2, //offset - &wbufs, - 42, //priority - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 99, - }, - ); - assert_eq!(1001, aiocb.fd()); - assert_eq!(2, aiocb.iovlen()); - assert_eq!(2, aiocb.offset()); - assert_eq!(42, aiocb.priority()); - let sev = aiocb.sigevent().sigevent(); - assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo); - assert_eq!(99, sev.sigev_value.sival_ptr as i64); - } - - // Test a simple aio operation with no completion notification. We must - // poll for completion. - #[test] - #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)] - fn ok() { - const INITIAL: &[u8] = b"abcdef123456"; - let wbuf0 = b"BC"; - let wbuf1 = b"DEF"; - let wbufs = [IoSlice::new(wbuf0), IoSlice::new(wbuf1)]; - let wlen = wbuf0.len() + wbuf1.len(); - let mut rbuf = Vec::new(); - const EXPECT: &[u8] = b"aBCDEF123456"; - - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiow = Box::pin(AioWritev::new( - f.as_raw_fd(), - 1, - &wbufs, - 0, - SigevNotify::SigevNone, - )); - aiow.as_mut().submit().unwrap(); - - let err = poll_aio!(&mut aiow); - assert_eq!(err, Ok(())); - assert_eq!(aiow.as_mut().aio_return().unwrap(), wlen); - - f.rewind().unwrap(); - let len = f.read_to_end(&mut rbuf).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf, EXPECT); - } -} - -// Test an aio operation with completion delivered by a signal -#[test] -#[cfg_attr( - any( - all(target_env = "musl", target_arch = "x86_64"), - target_arch = "mips", - target_arch = "mips64" - ), - ignore -)] -fn sigev_signal() { - let _m = crate::SIGNAL_MTX.lock(); - let sa = SigAction::new( - SigHandler::Handler(sigfunc), - SaFlags::SA_RESETHAND, - SigSet::empty(), - ); - SIGNALED.store(false, Ordering::Relaxed); - unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap(); - - const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEF"; - let mut rbuf = Vec::new(); - const EXPECT: &[u8] = b"abCDEF123456"; - - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - let mut aiow = Box::pin(AioWrite::new( - f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevSignal { - signal: Signal::SIGUSR2, - si_value: 0, //TODO: validate in sigfunc - }, - )); - aiow.as_mut().submit().unwrap(); - while !SIGNALED.load(Ordering::Relaxed) { - thread::sleep(time::Duration::from_millis(10)); - } - - assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len()); - f.rewind().unwrap(); - let len = f.read_to_end(&mut rbuf).unwrap(); - assert_eq!(len, EXPECT.len()); - assert_eq!(rbuf, EXPECT); -} - -// Tests using aio_cancel_all for all outstanding IOs. -#[test] -#[cfg_attr(target_env = "musl", ignore)] -fn test_aio_cancel_all() { - let wbuf: &[u8] = b"CDEF"; - - let f = tempfile().unwrap(); - let mut aiocb = Box::pin(AioWrite::new( - f.as_raw_fd(), - 0, //offset - wbuf, - 0, //priority - SigevNotify::SigevNone, - )); - aiocb.as_mut().submit().unwrap(); - let err = aiocb.as_mut().error(); - assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS)); - - aio_cancel_all(f.as_raw_fd()).unwrap(); - - // Wait for aiocb to complete, but don't care whether it succeeded - let _ = poll_aio!(&mut aiocb); - let _ = aiocb.as_mut().aio_return(); -} - -#[test] -// On Cirrus on Linux, this test fails due to a glibc bug. -// https://github.com/nix-rust/nix/issues/1099 -#[cfg_attr(target_os = "linux", ignore)] -// On Cirrus, aio_suspend is failing with EINVAL -// https://github.com/nix-rust/nix/issues/1361 -#[cfg_attr(target_os = "macos", ignore)] -fn test_aio_suspend() { - const INITIAL: &[u8] = b"abcdef123456"; - const WBUF: &[u8] = b"CDEFG"; - let timeout = TimeSpec::seconds(10); - let mut rbuf = vec![0; 4]; - let rlen = rbuf.len(); - let mut f = tempfile().unwrap(); - f.write_all(INITIAL).unwrap(); - - let mut wcb = Box::pin(AioWrite::new( - f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevNone, - )); - - let mut rcb = Box::pin(AioRead::new( - f.as_raw_fd(), - 8, //offset - &mut rbuf, - 0, //priority - SigevNotify::SigevNone, - )); - wcb.as_mut().submit().unwrap(); - rcb.as_mut().submit().unwrap(); - loop { - { - let cbbuf = [ - &*wcb as &dyn AsRef<libc::aiocb>, - &*rcb as &dyn AsRef<libc::aiocb>, - ]; - let r = aio_suspend(&cbbuf[..], Some(timeout)); - match r { - Err(Errno::EINTR) => continue, - Err(e) => panic!("aio_suspend returned {:?}", e), - Ok(_) => (), - }; - } - if rcb.as_mut().error() != Err(Errno::EINPROGRESS) - && wcb.as_mut().error() != Err(Errno::EINPROGRESS) - { - break; - } - } - - assert_eq!(wcb.as_mut().aio_return().unwrap(), WBUF.len()); - assert_eq!(rcb.as_mut().aio_return().unwrap(), rlen); -} diff --git a/vendor/nix/test/sys/test_aio_drop.rs b/vendor/nix/test/sys/test_aio_drop.rs deleted file mode 100644 index bbe6623fd..000000000 --- a/vendor/nix/test/sys/test_aio_drop.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Test dropping an AioCb that hasn't yet finished. -// This must happen in its own process, because on OSX this test seems to hose -// the AIO subsystem and causes subsequent tests to fail -#[test] -#[should_panic(expected = "Dropped an in-progress AioCb")] -#[cfg(all( - not(target_env = "musl"), - not(target_env = "uclibc"), - any( - target_os = "linux", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd" - ) -))] -fn test_drop() { - use nix::sys::aio::*; - use nix::sys::signal::*; - use std::os::unix::io::AsRawFd; - use tempfile::tempfile; - - const WBUF: &[u8] = b"CDEF"; - - let f = tempfile().unwrap(); - f.set_len(6).unwrap(); - let mut aiocb = Box::pin(AioWrite::new( - f.as_raw_fd(), - 2, //offset - WBUF, - 0, //priority - SigevNotify::SigevNone, - )); - aiocb.as_mut().submit().unwrap(); -} diff --git a/vendor/nix/test/sys/test_epoll.rs b/vendor/nix/test/sys/test_epoll.rs deleted file mode 100644 index 915691595..000000000 --- a/vendor/nix/test/sys/test_epoll.rs +++ /dev/null @@ -1,24 +0,0 @@ -use nix::errno::Errno; -use nix::sys::epoll::{epoll_create1, epoll_ctl}; -use nix::sys::epoll::{EpollCreateFlags, EpollEvent, EpollFlags, EpollOp}; - -#[test] -pub fn test_epoll_errno() { - let efd = epoll_create1(EpollCreateFlags::empty()).unwrap(); - let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None); - result.expect_err("assertion failed"); - assert_eq!(result.unwrap_err(), Errno::ENOENT); - - let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None); - result.expect_err("assertion failed"); - assert_eq!(result.unwrap_err(), Errno::EINVAL); -} - -#[test] -pub fn test_epoll_ctl() { - let efd = epoll_create1(EpollCreateFlags::empty()).unwrap(); - let mut event = - EpollEvent::new(EpollFlags::EPOLLIN | EpollFlags::EPOLLERR, 1); - epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, &mut event).unwrap(); - epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None).unwrap(); -} diff --git a/vendor/nix/test/sys/test_inotify.rs b/vendor/nix/test/sys/test_inotify.rs deleted file mode 100644 index bb5851a90..000000000 --- a/vendor/nix/test/sys/test_inotify.rs +++ /dev/null @@ -1,65 +0,0 @@ -use nix::errno::Errno; -use nix::sys::inotify::{AddWatchFlags, InitFlags, Inotify}; -use std::ffi::OsString; -use std::fs::{rename, File}; - -#[test] -pub fn test_inotify() { - let instance = Inotify::init(InitFlags::IN_NONBLOCK).unwrap(); - let tempdir = tempfile::tempdir().unwrap(); - - instance - .add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS) - .unwrap(); - - let events = instance.read_events(); - assert_eq!(events.unwrap_err(), Errno::EAGAIN); - - File::create(tempdir.path().join("test")).unwrap(); - - let events = instance.read_events().unwrap(); - assert_eq!(events[0].name, Some(OsString::from("test"))); -} - -#[test] -pub fn test_inotify_multi_events() { - let instance = Inotify::init(InitFlags::IN_NONBLOCK).unwrap(); - let tempdir = tempfile::tempdir().unwrap(); - - instance - .add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS) - .unwrap(); - - let events = instance.read_events(); - assert_eq!(events.unwrap_err(), Errno::EAGAIN); - - File::create(tempdir.path().join("test")).unwrap(); - rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap(); - - // Now there should be 5 events in queue: - // - IN_CREATE on test - // - IN_OPEN on test - // - IN_CLOSE_WRITE on test - // - IN_MOVED_FROM on test with a cookie - // - IN_MOVED_TO on test2 with the same cookie - - let events = instance.read_events().unwrap(); - assert_eq!(events.len(), 5); - - assert_eq!(events[0].mask, AddWatchFlags::IN_CREATE); - assert_eq!(events[0].name, Some(OsString::from("test"))); - - assert_eq!(events[1].mask, AddWatchFlags::IN_OPEN); - assert_eq!(events[1].name, Some(OsString::from("test"))); - - assert_eq!(events[2].mask, AddWatchFlags::IN_CLOSE_WRITE); - assert_eq!(events[2].name, Some(OsString::from("test"))); - - assert_eq!(events[3].mask, AddWatchFlags::IN_MOVED_FROM); - assert_eq!(events[3].name, Some(OsString::from("test"))); - - assert_eq!(events[4].mask, AddWatchFlags::IN_MOVED_TO); - assert_eq!(events[4].name, Some(OsString::from("test2"))); - - assert_eq!(events[3].cookie, events[4].cookie); -} diff --git a/vendor/nix/test/sys/test_ioctl.rs b/vendor/nix/test/sys/test_ioctl.rs deleted file mode 100644 index 40f60cfdb..000000000 --- a/vendor/nix/test/sys/test_ioctl.rs +++ /dev/null @@ -1,376 +0,0 @@ -#![allow(dead_code)] - -// Simple tests to ensure macro generated fns compile -ioctl_none_bad!(do_bad, 0x1234); -ioctl_read_bad!(do_bad_read, 0x1234, u16); -ioctl_write_int_bad!(do_bad_write_int, 0x1234); -ioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8); -ioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32); -ioctl_none!(do_none, 0, 0); -ioctl_read!(read_test, 0, 0, u32); -ioctl_write_int!(write_ptr_int, 0, 0); -ioctl_write_ptr!(write_ptr_u8, 0, 0, u8); -ioctl_write_ptr!(write_ptr_u32, 0, 0, u32); -ioctl_write_ptr!(write_ptr_u64, 0, 0, u64); -ioctl_readwrite!(readwrite_test, 0, 0, u64); -ioctl_read_buf!(readbuf_test, 0, 0, u32); -const SPI_IOC_MAGIC: u8 = b'k'; -const SPI_IOC_MESSAGE: u8 = 0; -ioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8); -ioctl_write_buf!(writebuf_test_u8, 0, 0, u8); -ioctl_write_buf!(writebuf_test_u32, 0, 0, u32); -ioctl_write_buf!(writebuf_test_u64, 0, 0, u64); -ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32); - -// See C code for source of values for op calculations (does NOT work for mips/powerpc): -// https://gist.github.com/posborne/83ea6880770a1aef332e -// -// TODO: Need a way to compute these constants at test time. Using precomputed -// values is fragile and needs to be maintained. - -#[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" - )) { - assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A); - assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF); - } else { - assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A); - assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF); - } - } - - // 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" - )) { - assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A); - assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A); - } else { - assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A); - assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A); - } - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_write_64() { - if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) { - assert_eq!( - request_code_write!(b'z', 10, 1u64 << 32) as u32, - 0x8000_7A0A - ); - } else { - assert_eq!( - request_code_write!(b'z', 10, 1u64 << 32) as u32, - 0x4000_7A0A - ); - } - } - - // 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" - )) { - assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A); - assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A); - } else { - assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A); - assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A); - } - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_64() { - if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) { - assert_eq!( - request_code_read!(b'z', 10, 1u64 << 32) as u32, - 0x4000_7A0A - ); - } else { - assert_eq!( - request_code_read!(b'z', 10, 1u64 << 32) as u32, - 0x8000_7A0A - ); - } - } - - // 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); - assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_write_64() { - assert_eq!( - request_code_readwrite!(b'z', 10, 1u64 << 32) as u32, - 0xC000_7A0A - ); - } -} - -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd" -))] -mod bsd { - #[test] - fn test_op_none() { - assert_eq!(request_code_none!(b'q', 10), 0x2000_710A); - assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF); - } - - #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] - #[test] - fn test_op_write_int() { - assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604); - assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002); - } - - #[test] - fn test_op_write() { - assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A); - assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_write_64() { - assert_eq!(request_code_write!(b'z', 10, 1u64 << 32), 0x8000_7A0A); - } - - #[test] - fn test_op_read() { - assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A); - assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_64() { - assert_eq!(request_code_read!(b'z', 10, 1u64 << 32), 0x4000_7A0A); - } - - #[test] - fn test_op_read_write() { - assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A); - assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_op_read_write_64() { - assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32), 0xC000_7A0A); - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -mod linux_ioctls { - use std::mem; - use std::os::unix::io::AsRawFd; - - use libc::{termios, TCGETS, TCSBRK, TCSETS, TIOCNXCL}; - use tempfile::tempfile; - - use nix::errno::Errno; - - ioctl_none_bad!(tiocnxcl, TIOCNXCL); - #[test] - fn test_ioctl_none_bad() { - let file = tempfile().unwrap(); - let res = unsafe { tiocnxcl(file.as_raw_fd()) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_read_bad!(tcgets, TCGETS, termios); - #[test] - fn test_ioctl_read_bad() { - let file = tempfile().unwrap(); - let mut termios = unsafe { mem::zeroed() }; - let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_write_int_bad!(tcsbrk, TCSBRK); - #[test] - fn test_ioctl_write_int_bad() { - let file = tempfile().unwrap(); - let res = unsafe { tcsbrk(file.as_raw_fd(), 0) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_write_ptr_bad!(tcsets, TCSETS, termios); - #[test] - fn test_ioctl_write_ptr_bad() { - let file = tempfile().unwrap(); - let termios: termios = unsafe { mem::zeroed() }; - let res = unsafe { tcsets(file.as_raw_fd(), &termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - // FIXME: Find a suitable example for `ioctl_readwrite_bad` - - // From linux/videodev2.h - ioctl_none!(log_status, b'V', 70); - #[test] - fn test_ioctl_none() { - let file = tempfile().unwrap(); - let res = unsafe { log_status(file.as_raw_fd()) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - #[repr(C)] - pub struct v4l2_audio { - index: u32, - name: [u8; 32], - capability: u32, - mode: u32, - reserved: [u32; 2], - } - - // From linux/videodev2.h - ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio); - #[test] - fn test_ioctl_write_ptr() { - let file = tempfile().unwrap(); - let data: v4l2_audio = unsafe { mem::zeroed() }; - let res = unsafe { s_audio(file.as_raw_fd(), &data) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // From linux/net/bluetooth/hci_sock.h - const HCI_IOC_MAGIC: u8 = b'H'; - const HCI_IOC_HCIDEVUP: u8 = 201; - ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP); - #[test] - fn test_ioctl_write_int() { - let file = tempfile().unwrap(); - let res = unsafe { hcidevup(file.as_raw_fd(), 0) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // From linux/videodev2.h - ioctl_read!(g_audio, b'V', 33, v4l2_audio); - #[test] - fn test_ioctl_read() { - let file = tempfile().unwrap(); - let mut data: v4l2_audio = unsafe { mem::zeroed() }; - let res = unsafe { g_audio(file.as_raw_fd(), &mut data) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // From linux/videodev2.h - ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio); - #[test] - fn test_ioctl_readwrite() { - let file = tempfile().unwrap(); - let mut data: v4l2_audio = unsafe { mem::zeroed() }; - let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // FIXME: Find a suitable example for `ioctl_read_buf`. - - #[repr(C)] - pub struct spi_ioc_transfer { - tx_buf: u64, - rx_buf: u64, - len: u32, - speed_hz: u32, - delay_usecs: u16, - bits_per_word: u8, - cs_change: u8, - tx_nbits: u8, - rx_nbits: u8, - pad: u16, - } - - // From linux/spi/spidev.h - ioctl_write_buf!( - spi_ioc_message, - super::SPI_IOC_MAGIC, - super::SPI_IOC_MESSAGE, - spi_ioc_transfer - ); - #[test] - fn test_ioctl_write_buf() { - let file = tempfile().unwrap(); - let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() }; - let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) }; - assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS)); - } - - // FIXME: Find a suitable example for `ioctl_readwrite_buf`. -} - -#[cfg(target_os = "freebsd")] -mod freebsd_ioctls { - use std::mem; - use std::os::unix::io::AsRawFd; - - use libc::termios; - use tempfile::tempfile; - - use nix::errno::Errno; - - // From sys/sys/ttycom.h - const TTY_IOC_MAGIC: u8 = b't'; - const TTY_IOC_TYPE_NXCL: u8 = 14; - const TTY_IOC_TYPE_GETA: u8 = 19; - const TTY_IOC_TYPE_SETA: u8 = 20; - - ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL); - #[test] - fn test_ioctl_none() { - let file = tempfile().unwrap(); - let res = unsafe { tiocnxcl(file.as_raw_fd()) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios); - #[test] - fn test_ioctl_read() { - let file = tempfile().unwrap(); - let mut termios = unsafe { mem::zeroed() }; - let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } - - ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios); - #[test] - fn test_ioctl_write_ptr() { - let file = tempfile().unwrap(); - let termios: termios = unsafe { mem::zeroed() }; - let res = unsafe { tiocseta(file.as_raw_fd(), &termios) }; - assert_eq!(res, Err(Errno::ENOTTY)); - } -} diff --git a/vendor/nix/test/sys/test_mman.rs b/vendor/nix/test/sys/test_mman.rs deleted file mode 100644 index e748427bc..000000000 --- a/vendor/nix/test/sys/test_mman.rs +++ /dev/null @@ -1,122 +0,0 @@ -use nix::sys::mman::{mmap, MapFlags, ProtFlags}; -use std::num::NonZeroUsize; - -#[test] -fn test_mmap_anonymous() { - unsafe { - let ptr = mmap( - None, - NonZeroUsize::new(1).unwrap(), - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, - -1, - 0, - ) - .unwrap() as *mut u8; - assert_eq!(*ptr, 0x00u8); - *ptr = 0xffu8; - assert_eq!(*ptr, 0xffu8); - } -} - -#[test] -#[cfg(any(target_os = "linux", target_os = "netbsd"))] -fn test_mremap_grow() { - use nix::libc::{c_void, size_t}; - use nix::sys::mman::{mremap, MRemapFlags}; - - const ONE_K: size_t = 1024; - let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap(); - - let slice: &mut [u8] = unsafe { - let mem = mmap( - None, - one_k_non_zero, - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, - -1, - 0, - ) - .unwrap(); - std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K) - }; - assert_eq!(slice[ONE_K - 1], 0x00); - slice[ONE_K - 1] = 0xFF; - assert_eq!(slice[ONE_K - 1], 0xFF); - - let slice: &mut [u8] = unsafe { - #[cfg(target_os = "linux")] - let mem = mremap( - slice.as_mut_ptr() as *mut c_void, - ONE_K, - 10 * ONE_K, - MRemapFlags::MREMAP_MAYMOVE, - None, - ) - .unwrap(); - #[cfg(target_os = "netbsd")] - let mem = mremap( - slice.as_mut_ptr() as *mut c_void, - ONE_K, - 10 * ONE_K, - MRemapFlags::MAP_REMAPDUP, - None, - ) - .unwrap(); - std::slice::from_raw_parts_mut(mem as *mut u8, 10 * ONE_K) - }; - - // The first KB should still have the old data in it. - assert_eq!(slice[ONE_K - 1], 0xFF); - - // The additional range should be zero-init'd and accessible. - assert_eq!(slice[10 * ONE_K - 1], 0x00); - slice[10 * ONE_K - 1] = 0xFF; - assert_eq!(slice[10 * ONE_K - 1], 0xFF); -} - -#[test] -#[cfg(any(target_os = "linux", target_os = "netbsd"))] -// Segfaults for unknown reasons under QEMU for 32-bit targets -#[cfg_attr(all(target_pointer_width = "32", qemu), ignore)] -fn test_mremap_shrink() { - use nix::libc::{c_void, size_t}; - use nix::sys::mman::{mremap, MRemapFlags}; - use std::num::NonZeroUsize; - - const ONE_K: size_t = 1024; - let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap(); - let slice: &mut [u8] = unsafe { - let mem = mmap( - None, - ten_one_k, - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, - -1, - 0, - ) - .unwrap(); - std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K) - }; - assert_eq!(slice[ONE_K - 1], 0x00); - slice[ONE_K - 1] = 0xFF; - assert_eq!(slice[ONE_K - 1], 0xFF); - - let slice: &mut [u8] = unsafe { - let mem = mremap( - slice.as_mut_ptr() as *mut c_void, - ten_one_k.into(), - ONE_K, - MRemapFlags::empty(), - None, - ) - .unwrap(); - // Since we didn't supply MREMAP_MAYMOVE, the address should be the - // same. - assert_eq!(mem, slice.as_mut_ptr() as *mut c_void); - std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K) - }; - - // The first KB should still be accessible and have the old data in it. - assert_eq!(slice[ONE_K - 1], 0xFF); -} diff --git a/vendor/nix/test/sys/test_pthread.rs b/vendor/nix/test/sys/test_pthread.rs deleted file mode 100644 index ce048bae6..000000000 --- a/vendor/nix/test/sys/test_pthread.rs +++ /dev/null @@ -1,22 +0,0 @@ -use nix::sys::pthread::*; - -#[cfg(any(target_env = "musl", target_os = "redox"))] -#[test] -fn test_pthread_self() { - let tid = pthread_self(); - assert!(!tid.is_null()); -} - -#[cfg(not(any(target_env = "musl", target_os = "redox")))] -#[test] -fn test_pthread_self() { - let tid = pthread_self(); - assert_ne!(tid, 0); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_pthread_kill_none() { - pthread_kill(pthread_self(), None) - .expect("Should be able to send signal to my thread."); -} diff --git a/vendor/nix/test/sys/test_ptrace.rs b/vendor/nix/test/sys/test_ptrace.rs deleted file mode 100644 index 530560fe1..000000000 --- a/vendor/nix/test/sys/test_ptrace.rs +++ /dev/null @@ -1,275 +0,0 @@ -#[cfg(all( - target_os = "linux", - any(target_arch = "x86_64", target_arch = "x86"), - target_env = "gnu" -))] -use memoffset::offset_of; -use nix::errno::Errno; -use nix::sys::ptrace; -#[cfg(any(target_os = "android", target_os = "linux"))] -use nix::sys::ptrace::Options; -use nix::unistd::getpid; - -#[cfg(any(target_os = "android", target_os = "linux"))] -use std::mem; - -use crate::*; - -#[test] -fn test_ptrace() { - // Just make sure ptrace can be called at all, for now. - // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS - require_capability!("test_ptrace", CAP_SYS_PTRACE); - let err = ptrace::attach(getpid()).unwrap_err(); - assert!( - err == Errno::EPERM || err == Errno::EINVAL || err == Errno::ENOSYS - ); -} - -// Just make sure ptrace_setoptions can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_setoptions() { - require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE); - let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD) - .unwrap_err(); - assert_ne!(err, Errno::EOPNOTSUPP); -} - -// Just make sure ptrace_getevent can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_getevent() { - require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE); - let err = ptrace::getevent(getpid()).unwrap_err(); - assert_ne!(err, Errno::EOPNOTSUPP); -} - -// Just make sure ptrace_getsiginfo can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_getsiginfo() { - require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE); - if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) { - panic!("ptrace_getsiginfo returns Errno::EOPNOTSUPP!"); - } -} - -// Just make sure ptrace_setsiginfo can be called at all, for now. -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptrace_setsiginfo() { - require_capability!("test_ptrace_setsiginfo", CAP_SYS_PTRACE); - let siginfo = unsafe { mem::zeroed() }; - if let Err(Errno::EOPNOTSUPP) = ptrace::setsiginfo(getpid(), &siginfo) { - panic!("ptrace_setsiginfo returns Errno::EOPNOTSUPP!"); - } -} - -#[test] -fn test_ptrace_cont() { - use nix::sys::ptrace; - use nix::sys::signal::{raise, Signal}; - use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; - use nix::unistd::fork; - use nix::unistd::ForkResult::*; - - require_capability!("test_ptrace_cont", CAP_SYS_PTRACE); - - let _m = crate::FORK_MTX.lock(); - - // FIXME: qemu-user doesn't implement ptrace on all architectures - // and returns ENOSYS in this case. - // We (ab)use this behavior to detect the affected platforms - // and skip the test then. - // On valid platforms the ptrace call should return Errno::EPERM, this - // is already tested by `test_ptrace`. - let err = ptrace::attach(getpid()).unwrap_err(); - if err == Errno::ENOSYS { - return; - } - - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => { - ptrace::traceme().unwrap(); - // As recommended by ptrace(2), raise SIGTRAP to pause the child - // until the parent is ready to continue - loop { - raise(Signal::SIGTRAP).unwrap(); - } - } - Parent { child } => { - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)) - ); - ptrace::cont(child, None).unwrap(); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)) - ); - ptrace::cont(child, Some(Signal::SIGKILL)).unwrap(); - match waitpid(child, None) { - Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) - if pid == child => - { - // FIXME It's been observed on some systems (apple) the - // tracee may not be killed but remain as a zombie process - // affecting other wait based tests. Add an extra kill just - // to make sure there are no zombies. - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() { - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - } - } - _ => panic!("The process should have been killed"), - } - } - } -} - -#[cfg(target_os = "linux")] -#[test] -fn test_ptrace_interrupt() { - use nix::sys::ptrace; - use nix::sys::signal::Signal; - use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus}; - use nix::unistd::fork; - use nix::unistd::ForkResult::*; - use std::thread::sleep; - use std::time::Duration; - - require_capability!("test_ptrace_interrupt", CAP_SYS_PTRACE); - - let _m = crate::FORK_MTX.lock(); - - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => loop { - sleep(Duration::from_millis(1000)); - }, - Parent { child } => { - ptrace::seize(child, ptrace::Options::PTRACE_O_TRACESYSGOOD) - .unwrap(); - ptrace::interrupt(child).unwrap(); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::PtraceEvent(child, Signal::SIGTRAP, 128)) - ); - ptrace::syscall(child, None).unwrap(); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::PtraceSyscall(child)) - ); - ptrace::detach(child, Some(Signal::SIGKILL)).unwrap(); - match waitpid(child, None) { - Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) - if pid == child => - { - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() { - let _ = waitpid(child, Some(WaitPidFlag::WNOHANG)); - } - } - _ => panic!("The process should have been killed"), - } - } - } -} - -// ptrace::{setoptions, getregs} are only available in these platforms -#[cfg(all( - target_os = "linux", - any(target_arch = "x86_64", target_arch = "x86"), - target_env = "gnu" -))] -#[test] -fn test_ptrace_syscall() { - use nix::sys::ptrace; - use nix::sys::signal::kill; - use nix::sys::signal::Signal; - use nix::sys::wait::{waitpid, WaitStatus}; - use nix::unistd::fork; - use nix::unistd::getpid; - use nix::unistd::ForkResult::*; - - require_capability!("test_ptrace_syscall", CAP_SYS_PTRACE); - - let _m = crate::FORK_MTX.lock(); - - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => { - ptrace::traceme().unwrap(); - // first sigstop until parent is ready to continue - let pid = getpid(); - kill(pid, Signal::SIGSTOP).unwrap(); - kill(pid, Signal::SIGTERM).unwrap(); - unsafe { - ::libc::_exit(0); - } - } - - Parent { child } => { - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::Stopped(child, Signal::SIGSTOP)) - ); - - // set this option to recognize syscall-stops - ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD) - .unwrap(); - - #[cfg(target_arch = "x86_64")] - let get_syscall_id = - || ptrace::getregs(child).unwrap().orig_rax as libc::c_long; - - #[cfg(target_arch = "x86")] - let get_syscall_id = - || ptrace::getregs(child).unwrap().orig_eax as libc::c_long; - - // this duplicates `get_syscall_id` for the purpose of testing `ptrace::read_user`. - #[cfg(target_arch = "x86_64")] - let rax_offset = offset_of!(libc::user_regs_struct, orig_rax); - #[cfg(target_arch = "x86")] - let rax_offset = offset_of!(libc::user_regs_struct, orig_eax); - - let get_syscall_from_user_area = || { - // Find the offset of `user.regs.rax` (or `user.regs.eax` for x86) - let rax_offset = offset_of!(libc::user, regs) + rax_offset; - ptrace::read_user(child, rax_offset as _).unwrap() - as libc::c_long - }; - - // kill entry - ptrace::syscall(child, None).unwrap(); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::PtraceSyscall(child)) - ); - assert_eq!(get_syscall_id(), ::libc::SYS_kill); - assert_eq!(get_syscall_from_user_area(), ::libc::SYS_kill); - - // kill exit - ptrace::syscall(child, None).unwrap(); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::PtraceSyscall(child)) - ); - assert_eq!(get_syscall_id(), ::libc::SYS_kill); - assert_eq!(get_syscall_from_user_area(), ::libc::SYS_kill); - - // receive signal - ptrace::syscall(child, None).unwrap(); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::Stopped(child, Signal::SIGTERM)) - ); - - // inject signal - ptrace::syscall(child, Signal::SIGTERM).unwrap(); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::Signaled(child, Signal::SIGTERM, false)) - ); - } - } -} diff --git a/vendor/nix/test/sys/test_select.rs b/vendor/nix/test/sys/test_select.rs deleted file mode 100644 index 40bda4d90..000000000 --- a/vendor/nix/test/sys/test_select.rs +++ /dev/null @@ -1,81 +0,0 @@ -use nix::sys::select::*; -use nix::sys::signal::SigSet; -use nix::sys::time::{TimeSpec, TimeValLike}; -use nix::unistd::{pipe, write}; - -#[test] -pub fn test_pselect() { - let _mtx = crate::SIGNAL_MTX.lock(); - - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - - let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); - - let timeout = TimeSpec::seconds(10); - let sigmask = SigSet::empty(); - assert_eq!( - 1, - pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap() - ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); -} - -#[test] -pub fn test_pselect_nfds2() { - let (r1, w1) = pipe().unwrap(); - write(w1, b"hi!").unwrap(); - let (r2, _w2) = pipe().unwrap(); - - let mut fd_set = FdSet::new(); - fd_set.insert(r1); - fd_set.insert(r2); - - let timeout = TimeSpec::seconds(10); - assert_eq!( - 1, - pselect( - ::std::cmp::max(r1, r2) + 1, - &mut fd_set, - None, - None, - &timeout, - None - ) - .unwrap() - ); - assert!(fd_set.contains(r1)); - assert!(!fd_set.contains(r2)); -} - -macro_rules! generate_fdset_bad_fd_tests { - ($fd:expr, $($method:ident),* $(,)?) => { - $( - #[test] - #[should_panic] - fn $method() { - FdSet::new().$method($fd); - } - )* - } -} - -mod test_fdset_negative_fd { - use super::*; - generate_fdset_bad_fd_tests!(-1, insert, remove, contains); -} - -mod test_fdset_too_large_fd { - use super::*; - use std::convert::TryInto; - generate_fdset_bad_fd_tests!( - FD_SETSIZE.try_into().unwrap(), - insert, - remove, - contains, - ); -} diff --git a/vendor/nix/test/sys/test_signal.rs b/vendor/nix/test/sys/test_signal.rs deleted file mode 100644 index 3ad14f40c..000000000 --- a/vendor/nix/test/sys/test_signal.rs +++ /dev/null @@ -1,147 +0,0 @@ -#[cfg(not(target_os = "redox"))] -use nix::errno::Errno; -use nix::sys::signal::*; -use nix::unistd::*; -use std::convert::TryFrom; -use std::sync::atomic::{AtomicBool, Ordering}; - -#[test] -fn test_kill_none() { - kill(getpid(), None).expect("Should be able to send signal to myself."); -} - -#[test] -#[cfg(not(target_os = "fuchsia"))] -fn test_killpg_none() { - killpg(getpgrp(), None) - .expect("Should be able to send signal to my process group."); -} - -#[test] -fn test_old_sigaction_flags() { - let _m = crate::SIGNAL_MTX.lock(); - - extern "C" fn handler(_: ::libc::c_int) {} - let act = SigAction::new( - SigHandler::Handler(handler), - SaFlags::empty(), - SigSet::empty(), - ); - let oact = unsafe { sigaction(SIGINT, &act) }.unwrap(); - let _flags = oact.flags(); - let oact = unsafe { sigaction(SIGINT, &act) }.unwrap(); - let _flags = oact.flags(); -} - -#[test] -fn test_sigprocmask_noop() { - sigprocmask(SigmaskHow::SIG_BLOCK, None, None) - .expect("this should be an effective noop"); -} - -#[test] -fn test_sigprocmask() { - let _m = crate::SIGNAL_MTX.lock(); - - // This needs to be a signal that rust doesn't use in the test harness. - const SIGNAL: Signal = Signal::SIGCHLD; - - let mut old_signal_set = SigSet::empty(); - sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set)) - .expect("expect to be able to retrieve old signals"); - - // Make sure the old set doesn't contain the signal, otherwise the following - // test don't make sense. - assert!( - !old_signal_set.contains(SIGNAL), - "the {:?} signal is already blocked, please change to a \ - different one", - SIGNAL - ); - - // Now block the signal. - let mut signal_set = SigSet::empty(); - signal_set.add(SIGNAL); - sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None) - .expect("expect to be able to block signals"); - - // And test it again, to make sure the change was effective. - old_signal_set.clear(); - sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set)) - .expect("expect to be able to retrieve old signals"); - assert!( - old_signal_set.contains(SIGNAL), - "expected the {:?} to be blocked", - SIGNAL - ); - - // Reset the signal. - sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None) - .expect("expect to be able to block signals"); -} - -lazy_static! { - static ref SIGNALED: AtomicBool = AtomicBool::new(false); -} - -extern "C" fn test_sigaction_handler(signal: libc::c_int) { - let signal = Signal::try_from(signal).unwrap(); - SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed); -} - -#[cfg(not(target_os = "redox"))] -extern "C" fn test_sigaction_action( - _: libc::c_int, - _: *mut libc::siginfo_t, - _: *mut libc::c_void, -) { -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_signal_sigaction() { - let _m = crate::SIGNAL_MTX.lock(); - - let action_handler = SigHandler::SigAction(test_sigaction_action); - assert_eq!( - unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), - Errno::ENOTSUP - ); -} - -#[test] -fn test_signal() { - let _m = crate::SIGNAL_MTX.lock(); - - unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap(); - raise(Signal::SIGINT).unwrap(); - assert_eq!( - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), - SigHandler::SigIgn - ); - - let handler = SigHandler::Handler(test_sigaction_handler); - assert_eq!( - unsafe { signal(Signal::SIGINT, handler) }.unwrap(), - SigHandler::SigDfl - ); - raise(Signal::SIGINT).unwrap(); - assert!(SIGNALED.load(Ordering::Relaxed)); - - #[cfg(not(any(target_os = "illumos", target_os = "solaris")))] - assert_eq!( - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), - handler - ); - - // System V based OSes (e.g. illumos and Solaris) always resets the - // disposition to SIG_DFL prior to calling the signal handler - #[cfg(any(target_os = "illumos", target_os = "solaris"))] - assert_eq!( - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), - SigHandler::SigDfl - ); - - // Restore default signal handler - unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(); -} diff --git a/vendor/nix/test/sys/test_signalfd.rs b/vendor/nix/test/sys/test_signalfd.rs deleted file mode 100644 index 87153c957..000000000 --- a/vendor/nix/test/sys/test_signalfd.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::convert::TryFrom; - -#[test] -fn test_signalfd() { - use nix::sys::signal::{self, raise, SigSet, Signal}; - use nix::sys::signalfd::SignalFd; - - // Grab the mutex for altering signals so we don't interfere with other tests. - let _m = crate::SIGNAL_MTX.lock(); - - // Block the SIGUSR1 signal from automatic processing for this thread - let mut mask = SigSet::empty(); - mask.add(signal::SIGUSR1); - mask.thread_block().unwrap(); - - let mut fd = SignalFd::new(&mask).unwrap(); - - // Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill` - // because `kill` with `getpid` isn't correct during multi-threaded execution like during a - // cargo test session. Instead use `raise` which does the correct thing by default. - raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed"); - - // And now catch that same signal. - let res = fd.read_signal().unwrap().unwrap(); - let signo = Signal::try_from(res.ssi_signo as i32).unwrap(); - assert_eq!(signo, signal::SIGUSR1); -} diff --git a/vendor/nix/test/sys/test_socket.rs b/vendor/nix/test/sys/test_socket.rs deleted file mode 100644 index 5adc77ed6..000000000 --- a/vendor/nix/test/sys/test_socket.rs +++ /dev/null @@ -1,2628 +0,0 @@ -#[cfg(any(target_os = "linux", target_os = "android"))] -use crate::*; -use libc::{c_char, sockaddr_storage}; -#[allow(deprecated)] -use nix::sys::socket::InetAddr; -use nix::sys::socket::{ - getsockname, sockaddr, sockaddr_in6, AddressFamily, UnixAddr, -}; -use std::collections::hash_map::DefaultHasher; -use std::hash::{Hash, Hasher}; -use std::mem::{self, MaybeUninit}; -use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; -use std::os::unix::io::RawFd; -use std::path::Path; -use std::slice; -use std::str::FromStr; - -#[allow(deprecated)] -#[test] -pub fn test_inetv4_addr_to_sock_addr() { - let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap(); - let addr = InetAddr::from_std(&actual); - - match addr { - InetAddr::V4(addr) => { - let ip: u32 = 0x7f00_0001; - let port: u16 = 3000; - let saddr = addr.sin_addr.s_addr; - - assert_eq!(saddr, ip.to_be()); - assert_eq!(addr.sin_port, port.to_be()); - } - _ => panic!("nope"), - } - - assert_eq!(addr.to_string(), "127.0.0.1:3000"); - - let inet = addr.to_std(); - assert_eq!(actual, inet); -} - -#[allow(deprecated)] -#[test] -pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() { - use nix::sys::socket::{sockaddr_storage_to_addr, SockAddr}; - - let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap(); - let addr = InetAddr::from_std(&actual); - let sockaddr = SockAddr::new_inet(addr); - - let (storage, ffi_size) = { - let mut storage = MaybeUninit::<sockaddr_storage>::zeroed(); - let storage_ptr = storage.as_mut_ptr().cast::<sockaddr>(); - let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair(); - assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize); - unsafe { - storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1); - (storage.assume_init(), ffi_size) - } - }; - - let from_storage = - sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap(); - assert_eq!(from_storage, sockaddr); - let from_storage = - sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()) - .unwrap(); - assert_eq!(from_storage, sockaddr); -} - -#[cfg(any(target_os = "linux"))] -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_timestamping() { - use nix::sys::socket::{ - recvmsg, sendmsg, setsockopt, socket, sockopt::Timestamping, - ControlMessageOwned, MsgFlags, SockFlag, SockType, SockaddrIn, - TimestampingFlag, - }; - use std::io::{IoSlice, IoSliceMut}; - - let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap(); - - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - nix::sys::socket::bind(rsock, &sock_addr).unwrap(); - - setsockopt(rsock, Timestamping, &TimestampingFlag::all()).unwrap(); - - let sbuf = [0u8; 2048]; - let mut rbuf = [0u8; 2048]; - let flags = MsgFlags::empty(); - let iov1 = [IoSlice::new(&sbuf)]; - let mut iov2 = [IoSliceMut::new(&mut rbuf)]; - - let mut cmsg = cmsg_space!(nix::sys::socket::Timestamps); - sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap(); - let recv = recvmsg::<()>(rsock, &mut iov2, Some(&mut cmsg), flags).unwrap(); - - let mut ts = None; - for c in recv.cmsgs() { - if let ControlMessageOwned::ScmTimestampsns(timestamps) = c { - ts = Some(timestamps.system); - } - } - let ts = ts.expect("ScmTimestampns is present"); - let sys_time = - ::nix::time::clock_gettime(::nix::time::ClockId::CLOCK_REALTIME) - .unwrap(); - let diff = if ts > sys_time { - ts - sys_time - } else { - sys_time - ts - }; - assert!(std::time::Duration::from(diff).as_secs() < 60); -} - -#[allow(deprecated)] -#[test] -pub fn test_inetv6_addr_roundtrip_sockaddr_storage_to_addr() { - use nix::sys::socket::{sockaddr_storage_to_addr, SockAddr}; - - let port: u16 = 3000; - let flowinfo: u32 = 1; - let scope_id: u32 = 2; - let ip: Ipv6Addr = "fe80::1".parse().unwrap(); - - let actual = - SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id)); - let addr = InetAddr::from_std(&actual); - let sockaddr = SockAddr::new_inet(addr); - - let (storage, ffi_size) = { - let mut storage = MaybeUninit::<sockaddr_storage>::zeroed(); - let storage_ptr = storage.as_mut_ptr().cast::<sockaddr_in6>(); - let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair(); - assert_eq!(mem::size_of::<sockaddr_in6>(), ffi_size as usize); - unsafe { - storage_ptr.copy_from_nonoverlapping( - (ffi_ptr as *const sockaddr).cast::<sockaddr_in6>(), - 1, - ); - (storage.assume_init(), ffi_size) - } - }; - - let from_storage = - sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap(); - assert_eq!(from_storage, sockaddr); - let from_storage = - sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>()) - .unwrap(); - assert_eq!(from_storage, sockaddr); -} - -#[test] -pub fn test_path_to_sock_addr() { - let path = "/foo/bar"; - let actual = Path::new(path); - let addr = UnixAddr::new(actual).unwrap(); - - let expect: &[c_char] = unsafe { - slice::from_raw_parts(path.as_ptr() as *const c_char, path.len()) - }; - assert_eq!(unsafe { &(*addr.as_ptr()).sun_path[..8] }, expect); - - assert_eq!(addr.path(), Some(actual)); -} - -fn calculate_hash<T: Hash>(t: &T) -> u64 { - let mut s = DefaultHasher::new(); - t.hash(&mut s); - s.finish() -} - -#[test] -pub fn test_addr_equality_path() { - let path = "/foo/bar"; - let actual = Path::new(path); - let addr1 = UnixAddr::new(actual).unwrap(); - let mut addr2 = addr1; - - unsafe { (*addr2.as_mut_ptr()).sun_path[10] = 127 }; - - assert_eq!(addr1, addr2); - assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_abstract_sun_path_too_long() { - let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough"); - let addr = UnixAddr::new_abstract(name.as_bytes()); - addr.expect_err("assertion failed"); -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_addr_equality_abstract() { - let name = String::from("nix\0abstract\0test"); - let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap(); - let mut addr2 = addr1; - - assert_eq!(addr1, addr2); - assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2)); - - unsafe { (*addr2.as_mut_ptr()).sun_path[17] = 127 }; - assert_ne!(addr1, addr2); - assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2)); -} - -// Test getting/setting abstract addresses (without unix socket creation) -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_abstract_uds_addr() { - let empty = String::new(); - let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap(); - let sun_path: [u8; 0] = []; - assert_eq!(addr.as_abstract(), Some(&sun_path[..])); - - let name = String::from("nix\0abstract\0test"); - let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap(); - let sun_path = [ - 110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, - 115, 116, - ]; - assert_eq!(addr.as_abstract(), Some(&sun_path[..])); - assert_eq!(addr.path(), None); - - // Internally, name is null-prefixed (abstract namespace) - assert_eq!(unsafe { (*addr.as_ptr()).sun_path[0] }, 0); -} - -// Test getting an unnamed address (without unix socket creation) -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_unnamed_uds_addr() { - use crate::nix::sys::socket::SockaddrLike; - - let addr = UnixAddr::new_unnamed(); - - assert!(addr.is_unnamed()); - assert_eq!(addr.len(), 2); - assert!(addr.path().is_none()); - assert_eq!(addr.path_len(), 0); - - assert!(addr.as_abstract().is_none()); -} - -#[test] -pub fn test_getsockname() { - use nix::sys::socket::bind; - use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType}; - - let tempdir = tempfile::tempdir().unwrap(); - let sockname = tempdir.path().join("sock"); - let sock = socket( - AddressFamily::Unix, - SockType::Stream, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - let sockaddr = UnixAddr::new(&sockname).unwrap(); - bind(sock, &sockaddr).expect("bind failed"); - assert_eq!(sockaddr, getsockname(sock).expect("getsockname failed")); -} - -#[test] -pub fn test_socketpair() { - use nix::sys::socket::{socketpair, AddressFamily, SockFlag, SockType}; - use nix::unistd::{read, write}; - - let (fd1, fd2) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - write(fd1, b"hello").unwrap(); - let mut buf = [0; 5]; - read(fd2, &mut buf).unwrap(); - - assert_eq!(&buf[..], b"hello"); -} - -#[test] -pub fn test_std_conversions() { - use nix::sys::socket::*; - - let std_sa = SocketAddrV4::from_str("127.0.0.1:6789").unwrap(); - let sock_addr = SockaddrIn::from(std_sa); - assert_eq!(std_sa, sock_addr.into()); - - let std_sa = SocketAddrV6::from_str("[::1]:6000").unwrap(); - let sock_addr: SockaddrIn6 = SockaddrIn6::from(std_sa); - assert_eq!(std_sa, sock_addr.into()); -} - -mod recvfrom { - use super::*; - use nix::sys::socket::*; - use nix::{errno::Errno, Result}; - use std::thread; - - const MSG: &[u8] = b"Hello, World!"; - - fn sendrecv<Fs, Fr>( - rsock: RawFd, - ssock: RawFd, - f_send: Fs, - mut f_recv: Fr, - ) -> Option<SockaddrStorage> - where - Fs: Fn(RawFd, &[u8], MsgFlags) -> Result<usize> + Send + 'static, - Fr: FnMut(usize, Option<SockaddrStorage>), - { - let mut buf: [u8; 13] = [0u8; 13]; - let mut l = 0; - let mut from = None; - - let send_thread = thread::spawn(move || { - let mut l = 0; - while l < std::mem::size_of_val(MSG) { - l += f_send(ssock, &MSG[l..], MsgFlags::empty()).unwrap(); - } - }); - - while l < std::mem::size_of_val(MSG) { - let (len, from_) = recvfrom(rsock, &mut buf[l..]).unwrap(); - f_recv(len, from_); - from = from_; - l += len; - } - assert_eq!(&buf, MSG); - send_thread.join().unwrap(); - from - } - - #[test] - pub fn stream() { - let (fd2, fd1) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - // Ignore from for stream sockets - let _ = sendrecv(fd1, fd2, send, |_, _| {}); - } - - #[test] - pub fn udp() { - let std_sa = SocketAddrV4::from_str("127.0.0.1:6789").unwrap(); - let sock_addr = SockaddrIn::from(std_sa); - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - let from = sendrecv( - rsock, - ssock, - move |s, m, flags| sendto(s, m, &sock_addr, flags), - |_, _| {}, - ); - // UDP sockets should set the from address - assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap()); - } - - #[cfg(target_os = "linux")] - mod udp_offload { - use super::*; - use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment}; - use std::io::IoSlice; - - #[test] - // Disable the test under emulation because it fails in Cirrus-CI. Lack - // of QEMU support is suspected. - #[cfg_attr(qemu, ignore)] - pub fn gso() { - require_kernel_version!(udp_offload::gso, ">= 4.18"); - - // In this test, we send the data and provide a GSO segment size. - // Since we are sending the buffer of size 13, six UDP packets - // with size 2 and two UDP packet with size 1 will be sent. - let segment_size: u16 = 2; - - let sock_addr = SockaddrIn::new(127, 0, 0, 1, 6791); - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - - setsockopt(rsock, UdpGsoSegment, &(segment_size as _)) - .expect("setsockopt UDP_SEGMENT failed"); - - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - - let mut num_packets_received: i32 = 0; - - sendrecv( - rsock, - ssock, - move |s, m, flags| { - let iov = [IoSlice::new(m)]; - let cmsg = ControlMessage::UdpGsoSegments(&segment_size); - sendmsg(s, &iov, &[cmsg], flags, Some(&sock_addr)) - }, - { - let num_packets_received_ref = &mut num_packets_received; - - move |len, _| { - // check that we receive UDP packets with payload size - // less or equal to segment size - assert!(len <= segment_size as usize); - *num_packets_received_ref += 1; - } - }, - ); - - // Buffer size is 13, we will receive six packets of size 2, - // and one packet of size 1. - assert_eq!(7, num_packets_received); - } - - #[test] - // Disable the test on emulated platforms because it fails in Cirrus-CI. - // Lack of QEMU support is suspected. - #[cfg_attr(qemu, ignore)] - pub fn gro() { - require_kernel_version!(udp_offload::gro, ">= 5.3"); - - // It's hard to guarantee receiving GRO packets. Just checking - // that `setsockopt` doesn't fail with error - - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - - setsockopt(rsock, UdpGroSegment, &true) - .expect("setsockopt UDP_GRO failed"); - } - } - - #[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - ))] - #[test] - pub fn udp_sendmmsg() { - use std::io::IoSlice; - - let std_sa = SocketAddrV4::from_str("127.0.0.1:6793").unwrap(); - let std_sa2 = SocketAddrV4::from_str("127.0.0.1:6794").unwrap(); - let sock_addr = SockaddrIn::from(std_sa); - let sock_addr2 = SockaddrIn::from(std_sa2); - - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - - let from = sendrecv( - rsock, - ssock, - move |s, m, flags| { - let batch_size = 15; - let mut iovs = Vec::with_capacity(1 + batch_size); - let mut addrs = Vec::with_capacity(1 + batch_size); - let mut data = MultiHeaders::preallocate(1 + batch_size, None); - let iov = IoSlice::new(m); - // first chunk: - iovs.push([iov]); - addrs.push(Some(sock_addr)); - - for _ in 0..batch_size { - iovs.push([iov]); - addrs.push(Some(sock_addr2)); - } - - let res = sendmmsg(s, &mut data, &iovs, addrs, [], flags)?; - let mut sent_messages = 0; - let mut sent_bytes = 0; - for item in res { - sent_messages += 1; - sent_bytes += item.bytes; - } - // - assert_eq!(sent_messages, iovs.len()); - assert_eq!(sent_bytes, sent_messages * m.len()); - Ok(sent_messages) - }, - |_, _| {}, - ); - // UDP sockets should set the from address - assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap()); - } - - #[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - ))] - #[test] - pub fn udp_recvmmsg() { - use nix::sys::socket::{recvmmsg, MsgFlags}; - use std::io::IoSliceMut; - - const NUM_MESSAGES_SENT: usize = 2; - const DATA: [u8; 2] = [1, 2]; - - let inet_addr = SocketAddrV4::from_str("127.0.0.1:6798").unwrap(); - let sock_addr = SockaddrIn::from(inet_addr); - - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - - let send_thread = thread::spawn(move || { - for _ in 0..NUM_MESSAGES_SENT { - sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()) - .unwrap(); - } - }); - - let mut msgs = std::collections::LinkedList::new(); - - // Buffers to receive exactly `NUM_MESSAGES_SENT` messages - let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT]; - msgs.extend( - receive_buffers - .iter_mut() - .map(|buf| [IoSliceMut::new(&mut buf[..])]), - ); - - let mut data = - MultiHeaders::<SockaddrIn>::preallocate(msgs.len(), None); - - let res: Vec<RecvMsg<SockaddrIn>> = - recvmmsg(rsock, &mut data, msgs.iter(), MsgFlags::empty(), None) - .expect("recvmmsg") - .collect(); - assert_eq!(res.len(), DATA.len()); - - for RecvMsg { address, bytes, .. } in res.into_iter() { - assert_eq!(AddressFamily::Inet, address.unwrap().family().unwrap()); - assert_eq!(DATA.len(), bytes); - } - - for buf in &receive_buffers { - assert_eq!(&buf[..DATA.len()], DATA); - } - - send_thread.join().unwrap(); - } - - #[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - ))] - #[test] - pub fn udp_recvmmsg_dontwait_short_read() { - use nix::sys::socket::{recvmmsg, MsgFlags}; - use std::io::IoSliceMut; - - const NUM_MESSAGES_SENT: usize = 2; - const DATA: [u8; 4] = [1, 2, 3, 4]; - - let inet_addr = SocketAddrV4::from_str("127.0.0.1:6799").unwrap(); - let sock_addr = SockaddrIn::from(inet_addr); - - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - bind(rsock, &sock_addr).unwrap(); - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - - let send_thread = thread::spawn(move || { - for _ in 0..NUM_MESSAGES_SENT { - sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()) - .unwrap(); - } - }); - // Ensure we've sent all the messages before continuing so `recvmmsg` - // will return right away - send_thread.join().unwrap(); - - let mut msgs = std::collections::LinkedList::new(); - - // Buffers to receive >`NUM_MESSAGES_SENT` messages to ensure `recvmmsg` - // will return when there are fewer than requested messages in the - // kernel buffers when using `MSG_DONTWAIT`. - let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2]; - msgs.extend( - receive_buffers - .iter_mut() - .map(|buf| [IoSliceMut::new(&mut buf[..])]), - ); - - let mut data = MultiHeaders::<SockaddrIn>::preallocate( - NUM_MESSAGES_SENT + 2, - None, - ); - - let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg( - rsock, - &mut data, - msgs.iter(), - MsgFlags::MSG_DONTWAIT, - None, - ) - .expect("recvmmsg") - .collect(); - assert_eq!(res.len(), NUM_MESSAGES_SENT); - - for RecvMsg { address, bytes, .. } in res.into_iter() { - assert_eq!(AddressFamily::Inet, address.unwrap().family().unwrap()); - assert_eq!(DATA.len(), bytes); - } - - for buf in &receive_buffers[..NUM_MESSAGES_SENT] { - assert_eq!(&buf[..DATA.len()], DATA); - } - } - - #[test] - pub fn udp_inet6() { - let addr = std::net::Ipv6Addr::from_str("::1").unwrap(); - let rport = 6789; - let rstd_sa = SocketAddrV6::new(addr, rport, 0, 0); - let raddr = SockaddrIn6::from(rstd_sa); - let sport = 6790; - let sstd_sa = SocketAddrV6::new(addr, sport, 0, 0); - let saddr = SockaddrIn6::from(sstd_sa); - let rsock = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("receive socket failed"); - match bind(rsock, &raddr) { - Err(Errno::EADDRNOTAVAIL) => { - println!("IPv6 not available, skipping test."); - return; - } - Err(e) => panic!("bind: {}", e), - Ok(()) => (), - } - let ssock = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - bind(ssock, &saddr).unwrap(); - let from = sendrecv( - rsock, - ssock, - move |s, m, flags| sendto(s, m, &raddr, flags), - |_, _| {}, - ); - assert_eq!(AddressFamily::Inet6, from.unwrap().family().unwrap()); - let osent_addr = from.unwrap(); - let sent_addr = osent_addr.as_sockaddr_in6().unwrap(); - assert_eq!(sent_addr.ip(), addr); - assert_eq!(sent_addr.port(), sport); - } -} - -// Test error handling of our recvmsg wrapper -#[test] -pub fn test_recvmsg_ebadf() { - use nix::errno::Errno; - use nix::sys::socket::{recvmsg, MsgFlags}; - use std::io::IoSliceMut; - - let mut buf = [0u8; 5]; - let mut iov = [IoSliceMut::new(&mut buf[..])]; - - let fd = -1; // Bad file descriptor - let r = recvmsg::<()>(fd, &mut iov, None, MsgFlags::empty()); - - assert_eq!(r.err().unwrap(), Errno::EBADF); -} - -// Disable the test on emulated platforms due to a bug in QEMU versions < -// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808 -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_scm_rights() { - use nix::sys::socket::{ - recvmsg, sendmsg, socketpair, AddressFamily, ControlMessage, - ControlMessageOwned, MsgFlags, SockFlag, SockType, - }; - use nix::unistd::{close, pipe, read, write}; - use std::io::{IoSlice, IoSliceMut}; - - let (fd1, fd2) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - let (r, w) = pipe().unwrap(); - let mut received_r: Option<RawFd> = None; - - { - let iov = [IoSlice::new(b"hello")]; - let fds = [r]; - let cmsg = ControlMessage::ScmRights(&fds); - assert_eq!( - sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), - 5 - ); - close(r).unwrap(); - close(fd1).unwrap(); - } - - { - let mut buf = [0u8; 5]; - - let mut iov = [IoSliceMut::new(&mut buf[..])]; - let mut cmsgspace = cmsg_space!([RawFd; 1]); - let msg = recvmsg::<()>( - fd2, - &mut iov, - Some(&mut cmsgspace), - MsgFlags::empty(), - ) - .unwrap(); - - for cmsg in msg.cmsgs() { - if let ControlMessageOwned::ScmRights(fd) = cmsg { - assert_eq!(received_r, None); - assert_eq!(fd.len(), 1); - received_r = Some(fd[0]); - } else { - panic!("unexpected cmsg"); - } - } - assert_eq!(msg.bytes, 5); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - close(fd2).unwrap(); - } - - let received_r = received_r.expect("Did not receive passed fd"); - // Ensure that the received file descriptor works - write(w, b"world").unwrap(); - let mut buf = [0u8; 5]; - read(received_r, &mut buf).unwrap(); - assert_eq!(&buf[..], b"world"); - close(received_r).unwrap(); - close(w).unwrap(); -} - -// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross -#[cfg(any(target_os = "linux", target_os = "android"))] -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_af_alg_cipher() { - use nix::sys::socket::sockopt::AlgSetKey; - use nix::sys::socket::{ - accept, bind, sendmsg, setsockopt, socket, AddressFamily, AlgAddr, - ControlMessage, MsgFlags, SockFlag, SockType, - }; - use nix::unistd::read; - use std::io::IoSlice; - - skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352"); - // Travis's seccomp profile blocks AF_ALG - // https://docs.docker.com/engine/security/seccomp/ - skip_if_seccomp!(test_af_alg_cipher); - - let alg_type = "skcipher"; - let alg_name = "ctr-aes-aesni"; - // 256-bits secret key - let key = vec![0u8; 32]; - // 16-bytes IV - let iv_len = 16; - let iv = vec![1u8; iv_len]; - // 256-bytes plain payload - let payload_len = 256; - let payload = vec![2u8; payload_len]; - - let sock = socket( - AddressFamily::Alg, - SockType::SeqPacket, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - let sockaddr = AlgAddr::new(alg_type, alg_name); - bind(sock, &sockaddr).expect("bind failed"); - - assert_eq!(sockaddr.alg_name().to_string_lossy(), alg_name); - assert_eq!(sockaddr.alg_type().to_string_lossy(), alg_type); - - setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt"); - let session_socket = accept(sock).expect("accept failed"); - - let msgs = [ - ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT), - ControlMessage::AlgSetIv(iv.as_slice()), - ]; - let iov = IoSlice::new(&payload); - sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None) - .expect("sendmsg encrypt"); - - // allocate buffer for encrypted data - let mut encrypted = vec![0u8; payload_len]; - let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt"); - assert_eq!(num_bytes, payload_len); - - let iov = IoSlice::new(&encrypted); - - let iv = vec![1u8; iv_len]; - - let msgs = [ - ControlMessage::AlgSetOp(&libc::ALG_OP_DECRYPT), - ControlMessage::AlgSetIv(iv.as_slice()), - ]; - sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None) - .expect("sendmsg decrypt"); - - // allocate buffer for decrypted data - let mut decrypted = vec![0u8; payload_len]; - let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt"); - - assert_eq!(num_bytes, payload_len); - assert_eq!(decrypted, payload); -} - -// Disable the test on emulated platforms due to not enabled support of AF_ALG -// in QEMU from rust cross -#[cfg(any(target_os = "linux", target_os = "android"))] -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_af_alg_aead() { - use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT}; - use nix::fcntl::{fcntl, FcntlArg, OFlag}; - use nix::sys::socket::sockopt::{AlgSetAeadAuthSize, AlgSetKey}; - use nix::sys::socket::{ - accept, bind, sendmsg, setsockopt, socket, AddressFamily, AlgAddr, - ControlMessage, MsgFlags, SockFlag, SockType, - }; - use nix::unistd::{close, read}; - use std::io::IoSlice; - - skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1352"); - // Travis's seccomp profile blocks AF_ALG - // https://docs.docker.com/engine/security/seccomp/ - skip_if_seccomp!(test_af_alg_aead); - - let auth_size = 4usize; - let assoc_size = 16u32; - - let alg_type = "aead"; - let alg_name = "gcm(aes)"; - // 256-bits secret key - let key = vec![0u8; 32]; - // 12-bytes IV - let iv_len = 12; - let iv = vec![1u8; iv_len]; - // 256-bytes plain payload - let payload_len = 256; - let mut payload = - vec![2u8; payload_len + (assoc_size as usize) + auth_size]; - - for i in 0..assoc_size { - payload[i as usize] = 10; - } - - let len = payload.len(); - - for i in 0..auth_size { - payload[len - 1 - i] = 0; - } - - let sock = socket( - AddressFamily::Alg, - SockType::SeqPacket, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - let sockaddr = AlgAddr::new(alg_type, alg_name); - bind(sock, &sockaddr).expect("bind failed"); - - setsockopt(sock, AlgSetAeadAuthSize, &auth_size) - .expect("setsockopt AlgSetAeadAuthSize"); - setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt AlgSetKey"); - let session_socket = accept(sock).expect("accept failed"); - - let msgs = [ - ControlMessage::AlgSetOp(&ALG_OP_ENCRYPT), - ControlMessage::AlgSetIv(iv.as_slice()), - ControlMessage::AlgSetAeadAssoclen(&assoc_size), - ]; - - let iov = IoSlice::new(&payload); - sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None) - .expect("sendmsg encrypt"); - - // allocate buffer for encrypted data - let mut encrypted = - vec![0u8; (assoc_size as usize) + payload_len + auth_size]; - let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt"); - assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize)); - close(session_socket).expect("close"); - - for i in 0..assoc_size { - encrypted[i as usize] = 10; - } - - let iov = IoSlice::new(&encrypted); - - let iv = vec![1u8; iv_len]; - - let session_socket = accept(sock).expect("accept failed"); - - let msgs = [ - ControlMessage::AlgSetOp(&ALG_OP_DECRYPT), - ControlMessage::AlgSetIv(iv.as_slice()), - ControlMessage::AlgSetAeadAssoclen(&assoc_size), - ]; - sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None) - .expect("sendmsg decrypt"); - - // allocate buffer for decrypted data - let mut decrypted = - vec![0u8; payload_len + (assoc_size as usize) + auth_size]; - // Starting with kernel 4.9, the interface changed slightly such that the - // authentication tag memory is only needed in the output buffer for encryption - // and in the input buffer for decryption. - // Do not block on read, as we may have fewer bytes than buffer size - fcntl(session_socket, FcntlArg::F_SETFL(OFlag::O_NONBLOCK)) - .expect("fcntl non_blocking"); - let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt"); - - assert!(num_bytes >= payload_len + (assoc_size as usize)); - assert_eq!( - decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))], - payload[(assoc_size as usize)..payload_len + (assoc_size as usize)] - ); -} - -// Verify `ControlMessage::Ipv4PacketInfo` for `sendmsg`. -// This creates a (udp) socket bound to localhost, then sends a message to -// itself but uses Ipv4PacketInfo to force the source address to be localhost. -// -// This would be a more interesting test if we could assume that the test host -// has more than one IP address (since we could select a different address to -// test from). -#[cfg(any(target_os = "linux", target_os = "macos", target_os = "netbsd"))] -#[test] -pub fn test_sendmsg_ipv4packetinfo() { - use cfg_if::cfg_if; - use nix::sys::socket::{ - bind, sendmsg, socket, AddressFamily, ControlMessage, MsgFlags, - SockFlag, SockType, SockaddrIn, - }; - use std::io::IoSlice; - - let sock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - let sock_addr = SockaddrIn::new(127, 0, 0, 1, 4000); - - bind(sock, &sock_addr).expect("bind failed"); - - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - - cfg_if! { - if #[cfg(target_os = "netbsd")] { - 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: sock_addr.as_ref().sin_addr, - }; - } - } - - let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)]; - - sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr)) - .expect("sendmsg"); -} - -// Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`. -// This creates a (udp) socket bound to ip6-localhost, then sends a message to -// itself but uses Ipv6PacketInfo to force the source address to be -// ip6-localhost. -// -// This would be a more interesting test if we could assume that the test host -// has more than one IP address (since we could select a different address to -// test from). -#[cfg(any( - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "freebsd" -))] -#[test] -pub fn test_sendmsg_ipv6packetinfo() { - use nix::errno::Errno; - use nix::sys::socket::{ - bind, sendmsg, socket, AddressFamily, ControlMessage, MsgFlags, - SockFlag, SockType, SockaddrIn6, - }; - use std::io::IoSlice; - - let sock = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - let std_sa = SocketAddrV6::from_str("[::1]:6000").unwrap(); - let sock_addr: SockaddrIn6 = SockaddrIn6::from(std_sa); - - if let Err(Errno::EADDRNOTAVAIL) = bind(sock, &sock_addr) { - println!("IPv6 not available, skipping test."); - return; - } - - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - - let pi = libc::in6_pktinfo { - ipi6_ifindex: 0, /* Unspecified interface */ - ipi6_addr: sock_addr.as_ref().sin6_addr, - }; - - let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)]; - - sendmsg::<SockaddrIn6>( - sock, - &iov, - &cmsg, - MsgFlags::empty(), - Some(&sock_addr), - ) - .expect("sendmsg"); -} - -// Verify that ControlMessage::Ipv4SendSrcAddr works for sendmsg. This -// creates a UDP socket bound to all local interfaces (0.0.0.0). It then -// sends message to itself at 127.0.0.1 while explicitly specifying -// 127.0.0.1 as the source address through an Ipv4SendSrcAddr -// (IP_SENDSRCADDR) control message. -// -// Note that binding to 0.0.0.0 is *required* on FreeBSD; sendmsg -// returns EINVAL otherwise. (See FreeBSD's ip(4) man page.) -#[cfg(any( - target_os = "netbsd", - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", -))] -#[test] -pub fn test_sendmsg_ipv4sendsrcaddr() { - use nix::sys::socket::{ - bind, sendmsg, socket, AddressFamily, ControlMessage, MsgFlags, - SockFlag, SockType, SockaddrIn, - }; - use std::io::IoSlice; - - let sock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - let unspec_sock_addr = SockaddrIn::new(0, 0, 0, 0, 0); - bind(sock, &unspec_sock_addr).expect("bind failed"); - let bound_sock_addr: SockaddrIn = getsockname(sock).unwrap(); - let localhost_sock_addr: SockaddrIn = - SockaddrIn::new(127, 0, 0, 1, bound_sock_addr.port()); - - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - let cmsg = [ControlMessage::Ipv4SendSrcAddr( - &localhost_sock_addr.as_ref().sin_addr, - )]; - - sendmsg( - sock, - &iov, - &cmsg, - MsgFlags::empty(), - Some(&localhost_sock_addr), - ) - .expect("sendmsg"); -} - -/// Tests that passing multiple fds using a single `ControlMessage` works. -// Disable the test on emulated platforms due to a bug in QEMU versions < -// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808 -#[cfg_attr(qemu, ignore)] -#[test] -fn test_scm_rights_single_cmsg_multiple_fds() { - use nix::sys::socket::{ - recvmsg, sendmsg, ControlMessage, ControlMessageOwned, MsgFlags, - }; - use std::io::{IoSlice, IoSliceMut}; - use std::os::unix::io::{AsRawFd, RawFd}; - use std::os::unix::net::UnixDatagram; - use std::thread; - - let (send, receive) = UnixDatagram::pair().unwrap(); - let thread = thread::spawn(move || { - let mut buf = [0u8; 8]; - let mut iovec = [IoSliceMut::new(&mut buf)]; - - let mut space = cmsg_space!([RawFd; 2]); - let msg = recvmsg::<()>( - receive.as_raw_fd(), - &mut iovec, - Some(&mut space), - MsgFlags::empty(), - ) - .unwrap(); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - - let mut cmsgs = msg.cmsgs(); - match cmsgs.next() { - Some(ControlMessageOwned::ScmRights(fds)) => { - assert_eq!( - fds.len(), - 2, - "unexpected fd count (expected 2 fds, got {})", - fds.len() - ); - } - _ => panic!(), - } - assert!(cmsgs.next().is_none(), "unexpected control msg"); - - assert_eq!(msg.bytes, 8); - assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]); - }); - - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout - let cmsg = [ControlMessage::ScmRights(&fds)]; - sendmsg::<()>(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None) - .unwrap(); - thread.join().unwrap(); -} - -// Verify `sendmsg` builds a valid `msghdr` when passing an empty -// `cmsgs` argument. This should result in a msghdr with a nullptr -// msg_control field and a msg_controllen of 0 when calling into the -// raw `sendmsg`. -#[test] -pub fn test_sendmsg_empty_cmsgs() { - use nix::sys::socket::{ - recvmsg, sendmsg, socketpair, AddressFamily, MsgFlags, SockFlag, - SockType, - }; - use nix::unistd::close; - use std::io::{IoSlice, IoSliceMut}; - - let (fd1, fd2) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - - { - let iov = [IoSlice::new(b"hello")]; - assert_eq!( - sendmsg::<()>(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), - 5 - ); - close(fd1).unwrap(); - } - - { - let mut buf = [0u8; 5]; - let mut iov = [IoSliceMut::new(&mut buf[..])]; - - let mut cmsgspace = cmsg_space!([RawFd; 1]); - let msg = recvmsg::<()>( - fd2, - &mut iov, - Some(&mut cmsgspace), - MsgFlags::empty(), - ) - .unwrap(); - - for _ in msg.cmsgs() { - panic!("unexpected cmsg"); - } - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - assert_eq!(msg.bytes, 5); - close(fd2).unwrap(); - } -} - -#[cfg(any( - target_os = "android", - target_os = "linux", - target_os = "freebsd", - target_os = "dragonfly", -))] -#[test] -fn test_scm_credentials() { - use nix::sys::socket::{ - recvmsg, sendmsg, socketpair, AddressFamily, ControlMessage, - ControlMessageOwned, MsgFlags, SockFlag, SockType, UnixCredentials, - }; - #[cfg(any(target_os = "android", target_os = "linux"))] - use nix::sys::socket::{setsockopt, sockopt::PassCred}; - use nix::unistd::{close, getgid, getpid, getuid}; - use std::io::{IoSlice, IoSliceMut}; - - let (send, recv) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - #[cfg(any(target_os = "android", target_os = "linux"))] - setsockopt(recv, PassCred, &true).unwrap(); - - { - let iov = [IoSlice::new(b"hello")]; - #[cfg(any(target_os = "android", target_os = "linux"))] - let cred = UnixCredentials::new(); - #[cfg(any(target_os = "android", target_os = "linux"))] - let cmsg = ControlMessage::ScmCredentials(&cred); - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - let cmsg = ControlMessage::ScmCreds; - assert_eq!( - sendmsg::<()>(send, &iov, &[cmsg], MsgFlags::empty(), None) - .unwrap(), - 5 - ); - close(send).unwrap(); - } - - { - let mut buf = [0u8; 5]; - let mut iov = [IoSliceMut::new(&mut buf[..])]; - - let mut cmsgspace = cmsg_space!(UnixCredentials); - let msg = recvmsg::<()>( - recv, - &mut iov, - Some(&mut cmsgspace), - MsgFlags::empty(), - ) - .unwrap(); - let mut received_cred = None; - - for cmsg in msg.cmsgs() { - let cred = match cmsg { - #[cfg(any(target_os = "android", target_os = "linux"))] - ControlMessageOwned::ScmCredentials(cred) => cred, - #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] - ControlMessageOwned::ScmCreds(cred) => cred, - other => panic!("unexpected cmsg {:?}", other), - }; - assert!(received_cred.is_none()); - assert_eq!(cred.pid(), getpid().as_raw()); - assert_eq!(cred.uid(), getuid().as_raw()); - assert_eq!(cred.gid(), getgid().as_raw()); - received_cred = Some(cred); - } - received_cred.expect("no creds received"); - assert_eq!(msg.bytes, 5); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - close(recv).unwrap(); - } -} - -/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single -/// `sendmsg` call. -#[cfg(any(target_os = "android", target_os = "linux"))] -// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation -// see https://bugs.launchpad.net/qemu/+bug/1781280 -#[cfg_attr(qemu, ignore)] -#[test] -fn test_scm_credentials_and_rights() { - let space = cmsg_space!(libc::ucred, RawFd); - test_impl_scm_credentials_and_rights(space); -} - -/// Ensure that passing a an oversized control message buffer to recvmsg -/// still works. -#[cfg(any(target_os = "android", target_os = "linux"))] -// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation -// see https://bugs.launchpad.net/qemu/+bug/1781280 -#[cfg_attr(qemu, ignore)] -#[test] -fn test_too_large_cmsgspace() { - let space = vec![0u8; 1024]; - test_impl_scm_credentials_and_rights(space); -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) { - use libc::ucred; - use nix::sys::socket::sockopt::PassCred; - use nix::sys::socket::{ - recvmsg, sendmsg, setsockopt, socketpair, ControlMessage, - ControlMessageOwned, MsgFlags, SockFlag, SockType, - }; - use nix::unistd::{close, getgid, getpid, getuid, pipe, write}; - use std::io::{IoSlice, IoSliceMut}; - - let (send, recv) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - setsockopt(recv, PassCred, &true).unwrap(); - - let (r, w) = pipe().unwrap(); - let mut received_r: Option<RawFd> = None; - - { - let iov = [IoSlice::new(b"hello")]; - let cred = ucred { - pid: getpid().as_raw(), - uid: getuid().as_raw(), - gid: getgid().as_raw(), - } - .into(); - let fds = [r]; - let cmsgs = [ - ControlMessage::ScmCredentials(&cred), - ControlMessage::ScmRights(&fds), - ]; - assert_eq!( - sendmsg::<()>(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(), - 5 - ); - close(r).unwrap(); - close(send).unwrap(); - } - - { - let mut buf = [0u8; 5]; - let mut iov = [IoSliceMut::new(&mut buf[..])]; - let msg = - recvmsg::<()>(recv, &mut iov, Some(&mut space), MsgFlags::empty()) - .unwrap(); - let mut received_cred = None; - - assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs"); - - for cmsg in msg.cmsgs() { - match cmsg { - ControlMessageOwned::ScmRights(fds) => { - assert_eq!(received_r, None, "already received fd"); - assert_eq!(fds.len(), 1); - received_r = Some(fds[0]); - } - ControlMessageOwned::ScmCredentials(cred) => { - assert!(received_cred.is_none()); - assert_eq!(cred.pid(), getpid().as_raw()); - assert_eq!(cred.uid(), getuid().as_raw()); - assert_eq!(cred.gid(), getgid().as_raw()); - received_cred = Some(cred); - } - _ => panic!("unexpected cmsg"), - } - } - received_cred.expect("no creds received"); - assert_eq!(msg.bytes, 5); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - close(recv).unwrap(); - } - - let received_r = received_r.expect("Did not receive passed fd"); - // Ensure that the received file descriptor works - write(w, b"world").unwrap(); - let mut buf = [0u8; 5]; - read(received_r, &mut buf).unwrap(); - assert_eq!(&buf[..], b"world"); - close(received_r).unwrap(); - close(w).unwrap(); -} - -// Test creating and using named unix domain sockets -#[test] -pub fn test_named_unixdomain() { - use nix::sys::socket::{accept, bind, connect, listen, socket, UnixAddr}; - use nix::sys::socket::{SockFlag, SockType}; - use nix::unistd::{close, read, write}; - use std::thread; - - let tempdir = tempfile::tempdir().unwrap(); - let sockname = tempdir.path().join("sock"); - let s1 = socket( - AddressFamily::Unix, - SockType::Stream, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - let sockaddr = UnixAddr::new(&sockname).unwrap(); - bind(s1, &sockaddr).expect("bind failed"); - listen(s1, 10).expect("listen failed"); - - let thr = thread::spawn(move || { - let s2 = socket( - AddressFamily::Unix, - SockType::Stream, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - connect(s2, &sockaddr).expect("connect failed"); - write(s2, b"hello").expect("write failed"); - close(s2).unwrap(); - }); - - let s3 = accept(s1).expect("accept failed"); - - let mut buf = [0; 5]; - read(s3, &mut buf).unwrap(); - close(s3).unwrap(); - close(s1).unwrap(); - thr.join().unwrap(); - - assert_eq!(&buf[..], b"hello"); -} - -// Test using unnamed unix domain addresses -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_unnamed_unixdomain() { - use nix::sys::socket::{getsockname, socketpair}; - use nix::sys::socket::{SockFlag, SockType}; - use nix::unistd::close; - - let (fd_1, fd_2) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .expect("socketpair failed"); - - let addr_1: UnixAddr = getsockname(fd_1).expect("getsockname failed"); - assert!(addr_1.is_unnamed()); - - close(fd_1).unwrap(); - close(fd_2).unwrap(); -} - -// Test creating and using unnamed unix domain addresses for autobinding sockets -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -pub fn test_unnamed_unixdomain_autobind() { - use nix::sys::socket::{bind, getsockname, socket}; - use nix::sys::socket::{SockFlag, SockType}; - use nix::unistd::close; - - let fd = socket( - AddressFamily::Unix, - SockType::Stream, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - // unix(7): "If a bind(2) call specifies addrlen as `sizeof(sa_family_t)`, or [...], then the - // socket is autobound to an abstract address" - bind(fd, &UnixAddr::new_unnamed()).expect("bind failed"); - - let addr: UnixAddr = getsockname(fd).expect("getsockname failed"); - let addr = addr.as_abstract().unwrap(); - - // changed from 8 to 5 bytes in Linux 2.3.15, and rust's minimum supported Linux version is 3.2 - // (as of 2022-11) - assert_eq!(addr.len(), 5); - - close(fd).unwrap(); -} - -// Test creating and using named system control sockets -#[cfg(any(target_os = "macos", target_os = "ios"))] -#[test] -pub fn test_syscontrol() { - use nix::errno::Errno; - use nix::sys::socket::{ - socket, SockFlag, SockProtocol, SockType, SysControlAddr, - }; - - let fd = socket( - AddressFamily::System, - SockType::Datagram, - SockFlag::empty(), - SockProtocol::KextControl, - ) - .expect("socket failed"); - SysControlAddr::from_name(fd, "com.apple.net.utun_control", 0) - .expect("resolving sys_control name failed"); - assert_eq!( - SysControlAddr::from_name(fd, "foo.bar.lol", 0).err(), - Some(Errno::ENOENT) - ); - - // requires root privileges - // connect(fd, &sockaddr).expect("connect failed"); -} - -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -fn loopback_address( - family: AddressFamily, -) -> Option<nix::ifaddrs::InterfaceAddress> { - use nix::ifaddrs::getifaddrs; - use nix::net::if_::*; - use nix::sys::socket::SockaddrLike; - use std::io; - use std::io::Write; - - let mut addrs = match getifaddrs() { - Ok(iter) => iter, - Err(e) => { - let stdioerr = io::stderr(); - let mut handle = stdioerr.lock(); - writeln!(handle, "getifaddrs: {:?}", e).unwrap(); - return None; - } - }; - // return first address matching family - addrs.find(|ifaddr| { - ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) - && ifaddr.address.as_ref().and_then(SockaddrLike::family) - == Some(family) - }) -} - -#[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", -))] -// qemu doesn't seem to be emulating this correctly in these architectures -#[cfg_attr( - all( - qemu, - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc64", - ) - ), - ignore -)] -#[test] -pub fn test_recv_ipv4pktinfo() { - use nix::net::if_::*; - use nix::sys::socket::sockopt::Ipv4PacketInfo; - use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn}; - use nix::sys::socket::{getsockname, setsockopt, socket}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use std::io::{IoSlice, IoSliceMut}; - - let lo_ifaddr = loopback_address(AddressFamily::Inet); - let (lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => ( - ifaddr.interface_name, - ifaddr.address.expect("Expect IPv4 address on interface"), - ), - None => return, - }; - let receive = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa: SockaddrIn = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - - let send = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)) - .expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let mut iovec = [IoSliceMut::new(&mut buf)]; - - let mut space = cmsg_space!(libc::in_pktinfo); - let msg = recvmsg::<()>( - receive, - &mut iovec, - Some(&mut space), - MsgFlags::empty(), - ) - .expect("recvmsg failed"); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - - let mut cmsgs = msg.cmsgs(); - if let Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) = cmsgs.next() - { - let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); - assert_eq!( - pktinfo.ipi_ifindex as libc::c_uint, i, - "unexpected ifindex (expected {}, got {})", - i, pktinfo.ipi_ifindex - ); - } - assert!(cmsgs.next().is_none(), "unexpected additional control msg"); - assert_eq!(msg.bytes, 8); - assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]); - } -} - -#[cfg(any( - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -// qemu doesn't seem to be emulating this correctly in these architectures -#[cfg_attr( - all( - qemu, - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc64", - ) - ), - ignore -)] -#[test] -pub fn test_recvif() { - use nix::net::if_::*; - use nix::sys::socket::sockopt::{Ipv4RecvDstAddr, Ipv4RecvIf}; - use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn}; - use nix::sys::socket::{getsockname, setsockopt, socket}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use std::io::{IoSlice, IoSliceMut}; - - let lo_ifaddr = loopback_address(AddressFamily::Inet); - let (lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => ( - ifaddr.interface_name, - ifaddr.address.expect("Expect IPv4 address on interface"), - ), - None => return, - }; - let receive = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa: SockaddrIn = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv4RecvIf, &true) - .expect("setsockopt IP_RECVIF failed"); - setsockopt(receive, Ipv4RecvDstAddr, &true) - .expect("setsockopt IP_RECVDSTADDR failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - - let send = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)) - .expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let mut iovec = [IoSliceMut::new(&mut buf)]; - let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr); - let msg = recvmsg::<()>( - receive, - &mut iovec, - Some(&mut space), - MsgFlags::empty(), - ) - .expect("recvmsg failed"); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs"); - - let mut rx_recvif = false; - let mut rx_recvdstaddr = false; - for cmsg in msg.cmsgs() { - match cmsg { - ControlMessageOwned::Ipv4RecvIf(dl) => { - rx_recvif = true; - let i = if_nametoindex(lo_name.as_bytes()) - .expect("if_nametoindex"); - assert_eq!( - dl.sdl_index as libc::c_uint, i, - "unexpected ifindex (expected {}, got {})", - i, dl.sdl_index - ); - } - ControlMessageOwned::Ipv4RecvDstAddr(addr) => { - rx_recvdstaddr = true; - if let Some(sin) = lo.as_sockaddr_in() { - assert_eq!(sin.as_ref().sin_addr.s_addr, - addr.s_addr, - "unexpected destination address (expected {}, got {})", - sin.as_ref().sin_addr.s_addr, - addr.s_addr); - } else { - panic!("unexpected Sockaddr"); - } - } - _ => panic!("unexpected additional control msg"), - } - } - assert!(rx_recvif); - assert!(rx_recvdstaddr); - assert_eq!(msg.bytes, 8); - assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]); - } -} - -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_recvif_ipv4() { - use nix::sys::socket::sockopt::Ipv4OrigDstAddr; - use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn}; - use nix::sys::socket::{getsockname, setsockopt, socket}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use std::io::{IoSlice, IoSliceMut}; - - let lo_ifaddr = loopback_address(AddressFamily::Inet); - let (_lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => ( - ifaddr.interface_name, - ifaddr.address.expect("Expect IPv4 address on interface"), - ), - None => return, - }; - let receive = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa: SockaddrIn = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv4OrigDstAddr, &true) - .expect("setsockopt IP_ORIGDSTADDR failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - - let send = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)) - .expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let mut iovec = [IoSliceMut::new(&mut buf)]; - let mut space = cmsg_space!(libc::sockaddr_in); - let msg = recvmsg::<()>( - receive, - &mut iovec, - Some(&mut space), - MsgFlags::empty(), - ) - .expect("recvmsg failed"); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - assert_eq!(msg.cmsgs().count(), 1, "expected 1 cmsgs"); - - let mut rx_recvorigdstaddr = false; - for cmsg in msg.cmsgs() { - match cmsg { - ControlMessageOwned::Ipv4OrigDstAddr(addr) => { - rx_recvorigdstaddr = true; - if let Some(sin) = lo.as_sockaddr_in() { - assert_eq!(sin.as_ref().sin_addr.s_addr, - addr.sin_addr.s_addr, - "unexpected destination address (expected {}, got {})", - sin.as_ref().sin_addr.s_addr, - addr.sin_addr.s_addr); - } else { - panic!("unexpected Sockaddr"); - } - } - _ => panic!("unexpected additional control msg"), - } - } - assert!(rx_recvorigdstaddr); - assert_eq!(msg.bytes, 8); - assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]); - } -} - -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] -#[cfg_attr(qemu, ignore)] -#[test] -pub fn test_recvif_ipv6() { - use nix::sys::socket::sockopt::Ipv6OrigDstAddr; - use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn6}; - use nix::sys::socket::{getsockname, setsockopt, socket}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use std::io::{IoSlice, IoSliceMut}; - - let lo_ifaddr = loopback_address(AddressFamily::Inet6); - let (_lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => ( - ifaddr.interface_name, - ifaddr.address.expect("Expect IPv6 address on interface"), - ), - None => return, - }; - let receive = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa: SockaddrIn6 = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv6OrigDstAddr, &true) - .expect("setsockopt IP_ORIGDSTADDR failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - - let send = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)) - .expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let mut iovec = [IoSliceMut::new(&mut buf)]; - let mut space = cmsg_space!(libc::sockaddr_in6); - let msg = recvmsg::<()>( - receive, - &mut iovec, - Some(&mut space), - MsgFlags::empty(), - ) - .expect("recvmsg failed"); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - assert_eq!(msg.cmsgs().count(), 1, "expected 1 cmsgs"); - - let mut rx_recvorigdstaddr = false; - for cmsg in msg.cmsgs() { - match cmsg { - ControlMessageOwned::Ipv6OrigDstAddr(addr) => { - rx_recvorigdstaddr = true; - if let Some(sin) = lo.as_sockaddr_in6() { - assert_eq!(sin.as_ref().sin6_addr.s6_addr, - addr.sin6_addr.s6_addr, - "unexpected destination address (expected {:?}, got {:?})", - sin.as_ref().sin6_addr.s6_addr, - addr.sin6_addr.s6_addr); - } else { - panic!("unexpected Sockaddr"); - } - } - _ => panic!("unexpected additional control msg"), - } - } - assert!(rx_recvorigdstaddr); - assert_eq!(msg.bytes, 8); - assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]); - } -} - -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -// qemu doesn't seem to be emulating this correctly in these architectures -#[cfg_attr( - all( - qemu, - any( - target_arch = "mips", - target_arch = "mips64", - target_arch = "powerpc64", - ) - ), - ignore -)] -#[test] -pub fn test_recv_ipv6pktinfo() { - use nix::net::if_::*; - use nix::sys::socket::sockopt::Ipv6RecvPacketInfo; - use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn6}; - use nix::sys::socket::{getsockname, setsockopt, socket}; - use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags}; - use std::io::{IoSlice, IoSliceMut}; - - let lo_ifaddr = loopback_address(AddressFamily::Inet6); - let (lo_name, lo) = match lo_ifaddr { - Some(ifaddr) => ( - ifaddr.interface_name, - ifaddr.address.expect("Expect IPv6 address on interface"), - ), - None => return, - }; - let receive = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("receive socket failed"); - bind(receive, &lo).expect("bind failed"); - let sa: SockaddrIn6 = getsockname(receive).expect("getsockname failed"); - setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed"); - - { - let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let iov = [IoSlice::new(&slice)]; - - let send = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)) - .expect("sendmsg failed"); - } - - { - let mut buf = [0u8; 8]; - let mut iovec = [IoSliceMut::new(&mut buf)]; - - let mut space = cmsg_space!(libc::in6_pktinfo); - let msg = recvmsg::<()>( - receive, - &mut iovec, - Some(&mut space), - MsgFlags::empty(), - ) - .expect("recvmsg failed"); - assert!(!msg - .flags - .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)); - - let mut cmsgs = msg.cmsgs(); - if let Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) = cmsgs.next() - { - let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); - assert_eq!( - 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"); - assert_eq!(msg.bytes, 8); - assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]); - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[cfg_attr(graviton, ignore = "Not supported by the CI environment")] -#[test] -pub fn test_vsock() { - use nix::errno::Errno; - use nix::sys::socket::{ - bind, connect, listen, socket, AddressFamily, SockFlag, SockType, - VsockAddr, - }; - use nix::unistd::close; - use std::thread; - - let port: u32 = 3000; - - let s1 = socket( - AddressFamily::Vsock, - SockType::Stream, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - // VMADDR_CID_HYPERVISOR is reserved, so we expect an EADDRNOTAVAIL error. - let sockaddr_hv = VsockAddr::new(libc::VMADDR_CID_HYPERVISOR, port); - assert_eq!(bind(s1, &sockaddr_hv).err(), Some(Errno::EADDRNOTAVAIL)); - - let sockaddr_any = VsockAddr::new(libc::VMADDR_CID_ANY, port); - assert_eq!(bind(s1, &sockaddr_any), Ok(())); - listen(s1, 10).expect("listen failed"); - - let thr = thread::spawn(move || { - let cid: u32 = libc::VMADDR_CID_HOST; - - let s2 = socket( - AddressFamily::Vsock, - SockType::Stream, - SockFlag::empty(), - None, - ) - .expect("socket failed"); - - let sockaddr_host = VsockAddr::new(cid, port); - - // The current implementation does not support loopback devices, so, - // for now, we expect a failure on the connect. - assert_ne!(connect(s2, &sockaddr_host), Ok(())); - - close(s2).unwrap(); - }); - - 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(qemu, ignore)] -#[cfg(all(target_os = "linux"))] -#[test] -fn test_recvmsg_timestampns() { - use nix::sys::socket::*; - use nix::sys::time::*; - use std::io::{IoSlice, IoSliceMut}; - 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 = SockaddrIn::new(127, 0, 0, 1, 0); - bind(in_socket, &localhost).unwrap(); - let address: SockaddrIn = getsockname(in_socket).unwrap(); - // Get initial time - let time0 = SystemTime::now(); - // Send the message - let iov = [IoSlice::new(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 mut iov = [IoSliceMut::new(&mut buffer)]; - let r = recvmsg::<()>(in_socket, &mut 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(qemu, ignore)] -#[cfg(all(target_os = "linux"))] -#[test] -fn test_recvmmsg_timestampns() { - use nix::sys::socket::*; - use nix::sys::time::*; - use std::io::{IoSlice, IoSliceMut}; - 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 = SockaddrIn::from_str("127.0.0.1:0").unwrap(); - bind(in_socket, &localhost).unwrap(); - let address: SockaddrIn = getsockname(in_socket).unwrap(); - // Get initial time - let time0 = SystemTime::now(); - // Send the message - let iov = [IoSlice::new(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 cmsgspace = nix::cmsg_space!(TimeSpec); - let iov = vec![[IoSliceMut::new(&mut buffer)]]; - let mut data = MultiHeaders::preallocate(1, Some(cmsgspace)); - let r: Vec<RecvMsg<()>> = - recvmmsg(in_socket, &mut data, iov.iter(), flags, None) - .unwrap() - .collect(); - 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(); -} - -// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack -// of QEMU support is suspected. -#[cfg_attr(qemu, ignore)] -#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))] -#[test] -fn test_recvmsg_rxq_ovfl() { - use nix::sys::socket::sockopt::{RcvBuf, RxqOvfl}; - use nix::sys::socket::*; - use nix::Error; - use std::io::{IoSlice, IoSliceMut}; - - let message = [0u8; 2048]; - let bufsize = message.len() * 2; - - let in_socket = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - let out_socket = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - - let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap(); - bind(in_socket, &localhost).unwrap(); - - let address: SockaddrIn = getsockname(in_socket).unwrap(); - connect(out_socket, &address).unwrap(); - - // Set SO_RXQ_OVFL flag. - setsockopt(in_socket, RxqOvfl, &1).unwrap(); - - // Set the receiver buffer size to hold only 2 messages. - setsockopt(in_socket, RcvBuf, &bufsize).unwrap(); - - let mut drop_counter = 0; - - for _ in 0..2 { - let iov = [IoSlice::new(&message)]; - let flags = MsgFlags::empty(); - - // Send the 3 messages (the receiver buffer can only hold 2 messages) - // to create an overflow. - for _ in 0..3 { - let l = - sendmsg(out_socket, &iov, &[], flags, Some(&address)).unwrap(); - assert_eq!(message.len(), l); - } - - // Receive the message and check the drop counter if any. - loop { - let mut buffer = vec![0u8; message.len()]; - let mut cmsgspace = nix::cmsg_space!(u32); - - let mut iov = [IoSliceMut::new(&mut buffer)]; - - match recvmsg::<()>( - in_socket, - &mut iov, - Some(&mut cmsgspace), - MsgFlags::MSG_DONTWAIT, - ) { - Ok(r) => { - drop_counter = match r.cmsgs().next() { - Some(ControlMessageOwned::RxqOvfl(drop_counter)) => { - drop_counter - } - Some(_) => panic!("Unexpected control message"), - None => 0, - }; - } - Err(Error::EAGAIN) => { - break; - } - _ => { - panic!("unknown recvmsg() error"); - } - } - } - } - - // One packet lost. - assert_eq!(drop_counter, 1); - - // Close sockets - nix::unistd::close(in_socket).unwrap(); - nix::unistd::close(out_socket).unwrap(); -} - -#[cfg(any(target_os = "linux", target_os = "android",))] -mod linux_errqueue { - use super::FromStr; - use nix::sys::socket::*; - - // Send a UDP datagram to a bogus destination address and observe an ICMP error (v4). - // - // Disable the test on QEMU because QEMU emulation of IP_RECVERR is broken (as documented on PR - // #1514). - #[cfg_attr(qemu, ignore)] - #[test] - fn test_recverr_v4() { - #[repr(u8)] - enum IcmpTypes { - DestUnreach = 3, // ICMP_DEST_UNREACH - } - #[repr(u8)] - enum IcmpUnreachCodes { - PortUnreach = 3, // ICMP_PORT_UNREACH - } - - test_recverr_impl::<sockaddr_in, _, _>( - "127.0.0.1:6800", - AddressFamily::Inet, - sockopt::Ipv4RecvErr, - libc::SO_EE_ORIGIN_ICMP, - IcmpTypes::DestUnreach as u8, - IcmpUnreachCodes::PortUnreach as u8, - // Closure handles protocol-specific testing and returns generic sock_extended_err for - // protocol-independent test impl. - |cmsg| { - if let ControlMessageOwned::Ipv4RecvErr(ext_err, err_addr) = - cmsg - { - if let Some(origin) = err_addr { - // Validate that our network error originated from 127.0.0.1:0. - assert_eq!(origin.sin_family, AddressFamily::Inet as _); - assert_eq!( - origin.sin_addr.s_addr, - u32::from_be(0x7f000001) - ); - assert_eq!(origin.sin_port, 0); - } else { - panic!("Expected some error origin"); - } - *ext_err - } else { - panic!("Unexpected control message {:?}", cmsg); - } - }, - ) - } - - // Essentially the same test as v4. - // - // Disable the test on QEMU because QEMU emulation of IPV6_RECVERR is broken (as documented on - // PR #1514). - #[cfg_attr(qemu, ignore)] - #[test] - fn test_recverr_v6() { - #[repr(u8)] - enum IcmpV6Types { - DestUnreach = 1, // ICMPV6_DEST_UNREACH - } - #[repr(u8)] - enum IcmpV6UnreachCodes { - PortUnreach = 4, // ICMPV6_PORT_UNREACH - } - - test_recverr_impl::<sockaddr_in6, _, _>( - "[::1]:6801", - AddressFamily::Inet6, - sockopt::Ipv6RecvErr, - libc::SO_EE_ORIGIN_ICMP6, - IcmpV6Types::DestUnreach as u8, - IcmpV6UnreachCodes::PortUnreach as u8, - // Closure handles protocol-specific testing and returns generic sock_extended_err for - // protocol-independent test impl. - |cmsg| { - if let ControlMessageOwned::Ipv6RecvErr(ext_err, err_addr) = - cmsg - { - if let Some(origin) = err_addr { - // Validate that our network error originated from localhost:0. - assert_eq!( - origin.sin6_family, - AddressFamily::Inet6 as _ - ); - assert_eq!( - origin.sin6_addr.s6_addr, - std::net::Ipv6Addr::LOCALHOST.octets() - ); - assert_eq!(origin.sin6_port, 0); - } else { - panic!("Expected some error origin"); - } - *ext_err - } else { - panic!("Unexpected control message {:?}", cmsg); - } - }, - ) - } - - fn test_recverr_impl<SA, OPT, TESTF>( - sa: &str, - af: AddressFamily, - opt: OPT, - ee_origin: u8, - ee_type: u8, - ee_code: u8, - testf: TESTF, - ) where - OPT: SetSockOpt<Val = bool>, - TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err, - { - use nix::errno::Errno; - use std::io::IoSliceMut; - - const MESSAGE_CONTENTS: &str = "ABCDEF"; - let std_sa = std::net::SocketAddr::from_str(sa).unwrap(); - let sock_addr = SockaddrStorage::from(std_sa); - let sock = socket(af, SockType::Datagram, SockFlag::SOCK_CLOEXEC, None) - .unwrap(); - setsockopt(sock, opt, &true).unwrap(); - if let Err(e) = sendto( - sock, - MESSAGE_CONTENTS.as_bytes(), - &sock_addr, - MsgFlags::empty(), - ) { - assert_eq!(e, Errno::EADDRNOTAVAIL); - println!("{:?} not available, skipping test.", af); - return; - } - - let mut buf = [0u8; 8]; - let mut iovec = [IoSliceMut::new(&mut buf)]; - let mut cspace = cmsg_space!(libc::sock_extended_err, SA); - - let msg = recvmsg( - sock, - &mut iovec, - Some(&mut cspace), - MsgFlags::MSG_ERRQUEUE, - ) - .unwrap(); - // The sent message / destination associated with the error is returned: - assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len()); - // recvmsg(2): "The original destination address of the datagram that caused the error is - // supplied via msg_name;" however, this is not literally true. E.g., an earlier version - // of this test used 0.0.0.0 (::0) as the destination address, which was mutated into - // 127.0.0.1 (::1). - assert_eq!(msg.address, Some(sock_addr)); - - // Check for expected control message. - let ext_err = match msg.cmsgs().next() { - Some(cmsg) => testf(&cmsg), - None => panic!("No control message"), - }; - - assert_eq!(ext_err.ee_errno, libc::ECONNREFUSED as u32); - assert_eq!(ext_err.ee_origin, ee_origin); - // ip(7): ee_type and ee_code are set from the type and code fields of the ICMP (ICMPv6) - // header. - assert_eq!(ext_err.ee_type, ee_type); - assert_eq!(ext_err.ee_code, ee_code); - // ip(7): ee_info contains the discovered MTU for EMSGSIZE errors. - assert_eq!(ext_err.ee_info, 0); - - let bytes = msg.bytes; - assert_eq!(&buf[..bytes], MESSAGE_CONTENTS.as_bytes()); - } -} - -// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack -// of QEMU support is suspected. -#[cfg_attr(qemu, ignore)] -#[cfg(target_os = "linux")] -#[test] -pub fn test_txtime() { - use nix::sys::socket::{ - bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage, - MsgFlags, SockFlag, SockType, SockaddrIn, - }; - use nix::sys::time::TimeValLike; - use nix::time::{clock_gettime, ClockId}; - - require_kernel_version!(test_txtime, ">= 5.8"); - - let sock_addr = SockaddrIn::from_str("127.0.0.1:6802").unwrap(); - - let ssock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .expect("send socket failed"); - - let txtime_cfg = libc::sock_txtime { - clockid: libc::CLOCK_MONOTONIC, - flags: 0, - }; - setsockopt(ssock, sockopt::TxTime, &txtime_cfg).unwrap(); - - let rsock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - bind(rsock, &sock_addr).unwrap(); - - let sbuf = [0u8; 2048]; - let iov1 = [std::io::IoSlice::new(&sbuf)]; - - let now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap(); - let delay = std::time::Duration::from_secs(1).into(); - let txtime = (now + delay).num_nanoseconds() as u64; - - let cmsg = ControlMessage::TxTime(&txtime); - sendmsg(ssock, &iov1, &[cmsg], MsgFlags::empty(), Some(&sock_addr)) - .unwrap(); - - let mut rbuf = [0u8; 2048]; - let mut iov2 = [std::io::IoSliceMut::new(&mut rbuf)]; - recvmsg::<()>(rsock, &mut iov2, None, MsgFlags::empty()).unwrap(); -} diff --git a/vendor/nix/test/sys/test_sockopt.rs b/vendor/nix/test/sys/test_sockopt.rs deleted file mode 100644 index 34bef945e..000000000 --- a/vendor/nix/test/sys/test_sockopt.rs +++ /dev/null @@ -1,431 +0,0 @@ -#[cfg(any(target_os = "android", target_os = "linux"))] -use crate::*; -use nix::sys::socket::{ - getsockopt, setsockopt, socket, sockopt, AddressFamily, SockFlag, - SockProtocol, SockType, -}; -use rand::{thread_rng, Rng}; - -// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not. -#[cfg(any(target_os = "dragonfly", target_os = "freebsd",))] -#[test] -pub fn test_local_peercred_seqpacket() { - use nix::{ - sys::socket::socketpair, - unistd::{Gid, Uid}, - }; - - let (fd1, _fd2) = socketpair( - AddressFamily::Unix, - SockType::SeqPacket, - None, - SockFlag::empty(), - ) - .unwrap(); - let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap(); - assert_eq!(xucred.version(), 0); - assert_eq!(Uid::from_raw(xucred.uid()), Uid::current()); - assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current()); -} - -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "macos", - target_os = "ios" -))] -#[test] -pub fn test_local_peercred_stream() { - use nix::{ - sys::socket::socketpair, - unistd::{Gid, Uid}, - }; - - let (fd1, _fd2) = socketpair( - AddressFamily::Unix, - SockType::Stream, - None, - SockFlag::empty(), - ) - .unwrap(); - let xucred = getsockopt(fd1, sockopt::LocalPeerCred).unwrap(); - assert_eq!(xucred.version(), 0); - assert_eq!(Uid::from_raw(xucred.uid()), Uid::current()); - assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current()); -} - -#[cfg(target_os = "linux")] -#[test] -fn is_so_mark_functional() { - use nix::sys::socket::sockopt; - - require_capability!("is_so_mark_functional", CAP_NET_ADMIN); - - let s = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - None, - ) - .unwrap(); - setsockopt(s, sockopt::Mark, &1337).unwrap(); - let mark = getsockopt(s, sockopt::Mark).unwrap(); - assert_eq!(mark, 1337); -} - -#[test] -fn test_so_buf() { - let fd = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - SockProtocol::Udp, - ) - .unwrap(); - let bufsize: usize = thread_rng().gen_range(4096..131_072); - setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap(); - let actual = getsockopt(fd, sockopt::SndBuf).unwrap(); - assert!(actual >= bufsize); - setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap(); - let actual = getsockopt(fd, sockopt::RcvBuf).unwrap(); - assert!(actual >= bufsize); -} - -#[test] -fn test_so_tcp_maxseg() { - use nix::sys::socket::{accept, bind, connect, listen, SockaddrIn}; - use nix::unistd::{close, write}; - use std::net::SocketAddrV4; - use std::str::FromStr; - - let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap(); - let sock_addr = SockaddrIn::from(std_sa); - - let rsock = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - bind(rsock, &sock_addr).unwrap(); - listen(rsock, 10).unwrap(); - let initial = getsockopt(rsock, sockopt::TcpMaxSeg).unwrap(); - // Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some - // platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger - // than 700 - cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - let segsize: u32 = 873; - assert!(initial < segsize); - setsockopt(rsock, sockopt::TcpMaxSeg, &segsize).unwrap(); - } else { - assert!(initial < 700); - } - } - - // Connect and check the MSS that was advertised - let ssock = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - connect(ssock, &sock_addr).unwrap(); - let rsess = accept(rsock).unwrap(); - write(rsess, b"hello").unwrap(); - let actual = getsockopt(ssock, sockopt::TcpMaxSeg).unwrap(); - // Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max - // TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary. - cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - assert!((segsize - 100) <= actual); - assert!(actual <= segsize); - } else { - assert!(initial < actual); - assert!(536 < actual); - } - } - close(rsock).unwrap(); - 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 believed 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. -// So the syscall doesn't work properly unless the kernel is also emulated. -#[test] -#[cfg(all( - any(target_arch = "x86", target_arch = "x86_64"), - any(target_os = "freebsd", target_os = "linux") -))] -fn test_tcp_congestion() { - use std::ffi::OsString; - - let fd = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - None, - ) - .unwrap(); - - let val = getsockopt(fd, sockopt::TcpCongestion).unwrap(); - setsockopt(fd, sockopt::TcpCongestion, &val).unwrap(); - - setsockopt( - fd, - sockopt::TcpCongestion, - &OsString::from("tcp_congestion_does_not_exist"), - ) - .unwrap_err(); - - assert_eq!(getsockopt(fd, sockopt::TcpCongestion).unwrap(), val); -} - -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_bindtodevice() { - skip_if_not_root!("test_bindtodevice"); - - let fd = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - None, - ) - .unwrap(); - - let val = getsockopt(fd, sockopt::BindToDevice).unwrap(); - setsockopt(fd, sockopt::BindToDevice, &val).unwrap(); - - assert_eq!(getsockopt(fd, sockopt::BindToDevice).unwrap(), val); -} - -#[test] -fn test_so_tcp_keepalive() { - let fd = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - setsockopt(fd, sockopt::KeepAlive, &true).unwrap(); - assert!(getsockopt(fd, sockopt::KeepAlive).unwrap()); - - #[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux" - ))] - { - let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap(); - setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap(); - assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1); - - let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap(); - setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap(); - assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1); - - let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap(); - setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap(); - assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1); - } -} - -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -#[cfg_attr(qemu, ignore)] -fn test_get_mtu() { - use nix::sys::socket::{bind, connect, SockaddrIn}; - use std::net::SocketAddrV4; - use std::str::FromStr; - - let std_sa = SocketAddrV4::from_str("127.0.0.1:4001").unwrap(); - let std_sb = SocketAddrV4::from_str("127.0.0.1:4002").unwrap(); - - let usock = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - SockProtocol::Udp, - ) - .unwrap(); - - // Bind and initiate connection - bind(usock, &SockaddrIn::from(std_sa)).unwrap(); - connect(usock, &SockaddrIn::from(std_sb)).unwrap(); - - // Loopback connections have 2^16 - the maximum - MTU - assert_eq!(getsockopt(usock, sockopt::IpMtu), Ok(u16::MAX as i32)) -} - -#[test] -#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))] -fn test_ttl_opts() { - let fd4 = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - setsockopt(fd4, sockopt::Ipv4Ttl, &1) - .expect("setting ipv4ttl on an inet socket should succeed"); - let fd6 = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - setsockopt(fd6, sockopt::Ipv6Ttl, &1) - .expect("setting ipv6ttl on an inet6 socket should succeed"); -} - -#[test] -#[cfg(any(target_os = "ios", target_os = "macos"))] -fn test_dontfrag_opts() { - let fd4 = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - setsockopt(fd4, sockopt::IpDontFrag, &true) - .expect("setting IP_DONTFRAG on an inet stream socket should succeed"); - setsockopt(fd4, sockopt::IpDontFrag, &false).expect( - "unsetting IP_DONTFRAG on an inet stream socket should succeed", - ); - let fd4d = socket( - AddressFamily::Inet, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - setsockopt(fd4d, sockopt::IpDontFrag, &true).expect( - "setting IP_DONTFRAG on an inet datagram socket should succeed", - ); - setsockopt(fd4d, sockopt::IpDontFrag, &false).expect( - "unsetting IP_DONTFRAG on an inet datagram socket should succeed", - ); -} - -#[test] -#[cfg(any( - target_os = "android", - target_os = "ios", - target_os = "linux", - target_os = "macos", -))] -// Disable the test under emulation because it fails in Cirrus-CI. Lack -// of QEMU support is suspected. -#[cfg_attr(qemu, ignore)] -fn test_v6dontfrag_opts() { - let fd6 = socket( - AddressFamily::Inet6, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - setsockopt(fd6, sockopt::Ipv6DontFrag, &true).expect( - "setting IPV6_DONTFRAG on an inet6 stream socket should succeed", - ); - setsockopt(fd6, sockopt::Ipv6DontFrag, &false).expect( - "unsetting IPV6_DONTFRAG on an inet6 stream socket should succeed", - ); - let fd6d = socket( - AddressFamily::Inet6, - SockType::Datagram, - SockFlag::empty(), - None, - ) - .unwrap(); - setsockopt(fd6d, sockopt::Ipv6DontFrag, &true).expect( - "setting IPV6_DONTFRAG on an inet6 datagram socket should succeed", - ); - setsockopt(fd6d, sockopt::Ipv6DontFrag, &false).expect( - "unsetting IPV6_DONTFRAG on an inet6 datagram socket should succeed", - ); -} - -#[test] -#[cfg(target_os = "linux")] -fn test_so_priority() { - let fd = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - let priority = 3; - setsockopt(fd, sockopt::Priority, &priority).unwrap(); - assert_eq!(getsockopt(fd, sockopt::Priority).unwrap(), priority); -} - -#[test] -#[cfg(target_os = "linux")] -fn test_ip_tos() { - let fd = socket( - AddressFamily::Inet, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - let tos = 0x80; // CS4 - setsockopt(fd, sockopt::IpTos, &tos).unwrap(); - assert_eq!(getsockopt(fd, sockopt::IpTos).unwrap(), tos); -} - -#[test] -#[cfg(target_os = "linux")] -// Disable the test under emulation because it fails in Cirrus-CI. Lack -// of QEMU support is suspected. -#[cfg_attr(qemu, ignore)] -fn test_ipv6_tclass() { - let fd = socket( - AddressFamily::Inet6, - SockType::Stream, - SockFlag::empty(), - SockProtocol::Tcp, - ) - .unwrap(); - let class = 0x80; // CS4 - setsockopt(fd, sockopt::Ipv6TClass, &class).unwrap(); - assert_eq!(getsockopt(fd, sockopt::Ipv6TClass).unwrap(), class); -} diff --git a/vendor/nix/test/sys/test_stat.rs b/vendor/nix/test/sys/test_stat.rs deleted file mode 100644 index 426b4b658..000000000 --- a/vendor/nix/test/sys/test_stat.rs +++ /dev/null @@ -1,29 +0,0 @@ -// 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/vendor/nix/test/sys/test_sysinfo.rs b/vendor/nix/test/sys/test_sysinfo.rs deleted file mode 100644 index 2897366ef..000000000 --- a/vendor/nix/test/sys/test_sysinfo.rs +++ /dev/null @@ -1,20 +0,0 @@ -use nix::sys::sysinfo::*; - -#[test] -fn sysinfo_works() { - let info = sysinfo().unwrap(); - - let (l1, l5, l15) = info.load_average(); - assert!(l1 >= 0.0); - assert!(l5 >= 0.0); - assert!(l15 >= 0.0); - - info.uptime(); // just test Duration construction - - assert!( - info.swap_free() <= info.swap_total(), - "more swap available than installed (free: {}, total: {})", - info.swap_free(), - info.swap_total() - ); -} diff --git a/vendor/nix/test/sys/test_termios.rs b/vendor/nix/test/sys/test_termios.rs deleted file mode 100644 index aaf00084f..000000000 --- a/vendor/nix/test/sys/test_termios.rs +++ /dev/null @@ -1,136 +0,0 @@ -use std::os::unix::prelude::*; -use tempfile::tempfile; - -use nix::errno::Errno; -use nix::fcntl; -use nix::pty::openpty; -use nix::sys::termios::{self, tcgetattr, LocalFlags, OutputFlags}; -use nix::unistd::{close, read, write}; - -/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s -fn write_all(f: RawFd, buf: &[u8]) { - let mut len = 0; - while len < buf.len() { - len += write(f, &buf[len..]).unwrap(); - } -} - -// Test tcgetattr on a terminal -#[test] -fn test_tcgetattr_pty() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock(); - - let pty = openpty(None, None).expect("openpty failed"); - termios::tcgetattr(pty.slave).unwrap(); - close(pty.master).expect("closing the master failed"); - close(pty.slave).expect("closing the slave failed"); -} - -// Test tcgetattr on something that isn't a terminal -#[test] -fn test_tcgetattr_enotty() { - let file = tempfile().unwrap(); - assert_eq!( - termios::tcgetattr(file.as_raw_fd()).err(), - Some(Errno::ENOTTY) - ); -} - -// Test tcgetattr on an invalid file descriptor -#[test] -fn test_tcgetattr_ebadf() { - assert_eq!(termios::tcgetattr(-1).err(), Some(Errno::EBADF)); -} - -// Test modifying output flags -#[test] -fn test_output_flags() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock(); - - // Open one pty to get attributes for the second one - let mut termios = { - let pty = openpty(None, None).expect("openpty failed"); - assert!(pty.master > 0); - assert!(pty.slave > 0); - let termios = tcgetattr(pty.slave).expect("tcgetattr failed"); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - termios - }; - - // Make sure postprocessing '\r' isn't specified by default or this test is useless. - assert!(!termios - .output_flags - .contains(OutputFlags::OPOST | OutputFlags::OCRNL)); - - // Specify that '\r' characters should be transformed to '\n' - // OPOST is specified to enable post-processing - termios - .output_flags - .insert(OutputFlags::OPOST | OutputFlags::OCRNL); - - // Open a pty - let pty = openpty(None, &termios).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Write into the master - let string = "foofoofoo\r"; - write_all(pty.master, string.as_bytes()); - - // Read from the slave verifying that the output has been properly transformed - let mut buf = [0u8; 10]; - crate::read_exact(pty.slave, &mut buf); - let transformed_string = "foofoofoo\n"; - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - assert_eq!(&buf, transformed_string.as_bytes()); -} - -// Test modifying local flags -#[test] -fn test_local_flags() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock(); - - // Open one pty to get attributes for the second one - let mut termios = { - let pty = openpty(None, None).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - let termios = tcgetattr(pty.slave).unwrap(); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - termios - }; - - // Make sure echo is specified by default or this test is useless. - assert!(termios.local_flags.contains(LocalFlags::ECHO)); - - // Disable local echo - termios.local_flags.remove(LocalFlags::ECHO); - - // Open a new pty with our modified termios settings - let pty = openpty(None, &termios).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Set the master is in nonblocking mode or reading will never return. - let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap(); - let new_flags = - fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK; - fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap(); - - // Write into the master - let string = "foofoofoo\r"; - write_all(pty.master, string.as_bytes()); - - // Try to read from the master, which should not have anything as echoing was disabled. - let mut buf = [0u8; 10]; - let read = read(pty.master, &mut buf).unwrap_err(); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - assert_eq!(read, Errno::EAGAIN); -} diff --git a/vendor/nix/test/sys/test_timerfd.rs b/vendor/nix/test/sys/test_timerfd.rs deleted file mode 100644 index 08e292106..000000000 --- a/vendor/nix/test/sys/test_timerfd.rs +++ /dev/null @@ -1,69 +0,0 @@ -use nix::sys::time::{TimeSpec, TimeValLike}; -use nix::sys::timerfd::{ - ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags, -}; -use std::time::Instant; - -#[test] -pub fn test_timerfd_oneshot() { - let timer = - TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap(); - - let before = Instant::now(); - - timer - .set( - Expiration::OneShot(TimeSpec::seconds(1)), - TimerSetTimeFlags::empty(), - ) - .unwrap(); - - timer.wait().unwrap(); - - let millis = before.elapsed().as_millis(); - assert!(millis > 900); -} - -#[test] -pub fn test_timerfd_interval() { - let timer = - TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap(); - - let before = Instant::now(); - timer - .set( - Expiration::IntervalDelayed( - TimeSpec::seconds(1), - TimeSpec::seconds(2), - ), - TimerSetTimeFlags::empty(), - ) - .unwrap(); - - timer.wait().unwrap(); - - let start_delay = before.elapsed().as_millis(); - assert!(start_delay > 900); - - timer.wait().unwrap(); - - let interval_delay = before.elapsed().as_millis(); - assert!(interval_delay > 2900); -} - -#[test] -pub fn test_timerfd_unset() { - let timer = - TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap(); - - timer - .set( - Expiration::OneShot(TimeSpec::seconds(1)), - TimerSetTimeFlags::empty(), - ) - .unwrap(); - - timer.unset().unwrap(); - - assert!(timer.get().unwrap().is_none()); -} diff --git a/vendor/nix/test/sys/test_uio.rs b/vendor/nix/test/sys/test_uio.rs deleted file mode 100644 index 0f4b8a656..000000000 --- a/vendor/nix/test/sys/test_uio.rs +++ /dev/null @@ -1,270 +0,0 @@ -use nix::sys::uio::*; -use nix::unistd::*; -use rand::distributions::Alphanumeric; -use rand::{thread_rng, Rng}; -use std::fs::OpenOptions; -use std::io::IoSlice; -use std::os::unix::io::AsRawFd; -use std::{cmp, iter}; - -#[cfg(not(target_os = "redox"))] -use std::io::IoSliceMut; - -use tempfile::tempdir; -#[cfg(not(target_os = "redox"))] -use tempfile::tempfile; - -#[test] -fn test_writev() { - let mut to_write = Vec::with_capacity(16 * 128); - for _ in 0..16 { - let s: String = thread_rng() - .sample_iter(&Alphanumeric) - .map(char::from) - .take(128) - .collect(); - let b = s.as_bytes(); - to_write.extend(b.iter().cloned()); - } - // Allocate and fill iovecs - let mut iovecs = Vec::new(); - let mut consumed = 0; - while consumed < to_write.len() { - let left = to_write.len() - consumed; - let slice_len = if left <= 64 { - left - } else { - thread_rng().gen_range(64..cmp::min(256, left)) - }; - let b = &to_write[consumed..consumed + slice_len]; - iovecs.push(IoSlice::new(b)); - consumed += slice_len; - } - let pipe_res = pipe(); - let (reader, writer) = pipe_res.expect("Couldn't create pipe"); - // FileDesc will close its filedesc (reader). - let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect(); - // Blocking io, should write all data. - let write_res = writev(writer, &iovecs); - let written = write_res.expect("couldn't write"); - // Check whether we written all data - assert_eq!(to_write.len(), written); - let read_res = read(reader, &mut read_buf[..]); - let read = read_res.expect("couldn't read"); - // Check we have read as much as we written - assert_eq!(read, written); - // Check equality of written and read data - assert_eq!(&to_write, &read_buf); - close(writer).expect("closed writer"); - close(reader).expect("closed reader"); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_readv() { - let s: String = thread_rng() - .sample_iter(&Alphanumeric) - .map(char::from) - .take(128) - .collect(); - let to_write = s.as_bytes().to_vec(); - let mut storage = Vec::new(); - let mut allocated = 0; - while allocated < to_write.len() { - let left = to_write.len() - allocated; - let vec_len = if left <= 64 { - left - } else { - thread_rng().gen_range(64..cmp::min(256, left)) - }; - let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect(); - storage.push(v); - allocated += vec_len; - } - let mut iovecs = Vec::with_capacity(storage.len()); - for v in &mut storage { - iovecs.push(IoSliceMut::new(&mut v[..])); - } - let (reader, writer) = pipe().expect("couldn't create pipe"); - // Blocking io, should write all data. - write(writer, &to_write).expect("write failed"); - let read = readv(reader, &mut iovecs[..]).expect("read failed"); - // Check whether we've read all data - assert_eq!(to_write.len(), read); - // Cccumulate data from iovecs - let mut read_buf = Vec::with_capacity(to_write.len()); - for iovec in &iovecs { - read_buf.extend(iovec.iter().cloned()); - } - // Check whether iovecs contain all written data - assert_eq!(read_buf.len(), to_write.len()); - // Check equality of written and read data - assert_eq!(&read_buf, &to_write); - close(reader).expect("couldn't close reader"); - close(writer).expect("couldn't close writer"); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_pwrite() { - use std::io::Read; - - let mut file = tempfile().unwrap(); - let buf = [1u8; 8]; - assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8)); - let mut file_content = Vec::new(); - file.read_to_end(&mut file_content).unwrap(); - let mut expected = vec![0u8; 8]; - expected.extend(vec![1; 8]); - assert_eq!(file_content, expected); -} - -#[test] -fn test_pread() { - use std::io::Write; - - let tempdir = tempdir().unwrap(); - - let path = tempdir.path().join("pread_test_file"); - let mut file = OpenOptions::new() - .write(true) - .read(true) - .create(true) - .truncate(true) - .open(path) - .unwrap(); - let file_content: Vec<u8> = (0..64).collect(); - file.write_all(&file_content).unwrap(); - - let mut buf = [0u8; 16]; - assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16)); - let expected: Vec<_> = (16..32).collect(); - assert_eq!(&buf[..], &expected[..]); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_pwritev() { - use std::io::Read; - - let to_write: Vec<u8> = (0..128).collect(); - let expected: Vec<u8> = [vec![0; 100], to_write.clone()].concat(); - - let iovecs = [ - IoSlice::new(&to_write[0..17]), - IoSlice::new(&to_write[17..64]), - IoSlice::new(&to_write[64..128]), - ]; - - let tempdir = tempdir().unwrap(); - - // pwritev them into a temporary file - let path = tempdir.path().join("pwritev_test_file"); - let mut file = OpenOptions::new() - .write(true) - .read(true) - .create(true) - .truncate(true) - .open(path) - .unwrap(); - - let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap(); - assert_eq!(written, to_write.len()); - - // Read the data back and make sure it matches - let mut contents = Vec::new(); - file.read_to_end(&mut contents).unwrap(); - assert_eq!(contents, expected); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_preadv() { - use std::io::Write; - - let to_write: Vec<u8> = (0..200).collect(); - let expected: Vec<u8> = (100..200).collect(); - - let tempdir = tempdir().unwrap(); - - let path = tempdir.path().join("preadv_test_file"); - - let mut file = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .truncate(true) - .open(path) - .unwrap(); - file.write_all(&to_write).unwrap(); - - let mut buffers: Vec<Vec<u8>> = vec![vec![0; 24], vec![0; 1], vec![0; 75]]; - - { - // Borrow the buffers into IoVecs and preadv into them - let mut iovecs: Vec<_> = buffers - .iter_mut() - .map(|buf| IoSliceMut::new(&mut buf[..])) - .collect(); - assert_eq!(Ok(100), preadv(file.as_raw_fd(), &mut iovecs, 100)); - } - - let all = buffers.concat(); - assert_eq!(all, expected); -} - -#[test] -#[cfg(all(target_os = "linux", not(target_env = "uclibc")))] -// uclibc doesn't implement process_vm_readv -// qemu-user doesn't implement process_vm_readv/writev on most arches -#[cfg_attr(qemu, ignore)] -fn test_process_vm_readv() { - use crate::*; - use nix::sys::signal::*; - use nix::sys::wait::*; - use nix::unistd::ForkResult::*; - - require_capability!("test_process_vm_readv", CAP_SYS_PTRACE); - let _m = crate::FORK_MTX.lock(); - - // Pre-allocate memory in the child, since allocation isn't safe - // post-fork (~= async-signal-safe) - let mut vector = vec![1u8, 2, 3, 4, 5]; - - let (r, w) = pipe().unwrap(); - match unsafe { fork() }.expect("Error: Fork Failed") { - Parent { child } => { - close(w).unwrap(); - // wait for child - read(r, &mut [0u8]).unwrap(); - close(r).unwrap(); - - let ptr = vector.as_ptr() as usize; - let remote_iov = RemoteIoVec { base: ptr, len: 5 }; - let mut buf = vec![0u8; 5]; - - let ret = process_vm_readv( - child, - &mut [IoSliceMut::new(&mut buf)], - &[remote_iov], - ); - - kill(child, SIGTERM).unwrap(); - waitpid(child, None).unwrap(); - - assert_eq!(Ok(5), ret); - assert_eq!(20u8, buf.iter().sum()); - } - Child => { - let _ = close(r); - for i in &mut vector { - *i += 1; - } - let _ = write(w, b"\0"); - let _ = close(w); - loop { - pause(); - } - } - } -} diff --git a/vendor/nix/test/sys/test_wait.rs b/vendor/nix/test/sys/test_wait.rs deleted file mode 100644 index d472f1ec1..000000000 --- a/vendor/nix/test/sys/test_wait.rs +++ /dev/null @@ -1,257 +0,0 @@ -use libc::_exit; -use nix::errno::Errno; -use nix::sys::signal::*; -use nix::sys::wait::*; -use nix::unistd::ForkResult::*; -use nix::unistd::*; - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_wait_signal() { - let _m = crate::FORK_MTX.lock(); - - // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe. - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => { - pause(); - unsafe { _exit(123) } - } - Parent { child } => { - kill(child, Some(SIGKILL)).expect("Error: Kill Failed"); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::Signaled(child, SIGKILL, false)) - ); - } - } -} - -#[test] -#[cfg(any( - target_os = "android", - target_os = "freebsd", - //target_os = "haiku", - all(target_os = "linux", not(target_env = "uclibc")), -))] -#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] -fn test_waitid_signal() { - let _m = crate::FORK_MTX.lock(); - - // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe. - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => { - pause(); - unsafe { _exit(123) } - } - Parent { child } => { - kill(child, Some(SIGKILL)).expect("Error: Kill Failed"); - assert_eq!( - waitid(Id::Pid(child), WaitPidFlag::WEXITED), - Ok(WaitStatus::Signaled(child, SIGKILL, false)), - ); - } - } -} - -#[test] -fn test_wait_exit() { - let _m = crate::FORK_MTX.lock(); - - // Safe: Child only calls `_exit`, which is async-signal-safe. - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => unsafe { - _exit(12); - }, - Parent { child } => { - assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12))); - } - } -} - -#[cfg(not(target_os = "haiku"))] -#[test] -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "haiku", - all(target_os = "linux", not(target_env = "uclibc")), -))] -#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] -fn test_waitid_exit() { - let _m = crate::FORK_MTX.lock(); - - // Safe: Child only calls `_exit`, which is async-signal-safe. - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => unsafe { - _exit(12); - }, - Parent { child } => { - assert_eq!( - waitid(Id::Pid(child), WaitPidFlag::WEXITED), - Ok(WaitStatus::Exited(child, 12)), - ); - } - } -} - -#[test] -fn test_waitstatus_from_raw() { - let pid = Pid::from_raw(1); - assert_eq!( - WaitStatus::from_raw(pid, 0x0002), - Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)) - ); - assert_eq!( - WaitStatus::from_raw(pid, 0x0200), - Ok(WaitStatus::Exited(pid, 2)) - ); - assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Errno::EINVAL)); -} - -#[test] -fn test_waitstatus_pid() { - let _m = crate::FORK_MTX.lock(); - - match unsafe { fork() }.unwrap() { - Child => unsafe { _exit(0) }, - Parent { child } => { - let status = waitpid(child, None).unwrap(); - assert_eq!(status.pid(), Some(child)); - } - } -} - -#[test] -#[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "haiku", - all(target_os = "linux", not(target_env = "uclibc")), -))] -fn test_waitid_pid() { - let _m = crate::FORK_MTX.lock(); - - match unsafe { fork() }.unwrap() { - Child => unsafe { _exit(0) }, - Parent { child } => { - let status = waitid(Id::Pid(child), WaitPidFlag::WEXITED).unwrap(); - assert_eq!(status.pid(), Some(child)); - } - } -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -// FIXME: qemu-user doesn't implement ptrace on most arches -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -mod ptrace { - use crate::*; - use libc::_exit; - use nix::sys::ptrace::{self, Event, Options}; - use nix::sys::signal::*; - use nix::sys::wait::*; - use nix::unistd::ForkResult::*; - use nix::unistd::*; - - fn ptrace_child() -> ! { - ptrace::traceme().unwrap(); - // As recommended by ptrace(2), raise SIGTRAP to pause the child - // until the parent is ready to continue - raise(SIGTRAP).unwrap(); - unsafe { _exit(0) } - } - - fn ptrace_wait_parent(child: Pid) { - // Wait for the raised SIGTRAP - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::Stopped(child, SIGTRAP)) - ); - // We want to test a syscall stop and a PTRACE_EVENT stop - ptrace::setoptions( - child, - Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT, - ) - .expect("setoptions failed"); - - // First, stop on the next system call, which will be exit() - ptrace::syscall(child, None).expect("syscall failed"); - assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child))); - // Then get the ptrace event for the process exiting - ptrace::cont(child, None).expect("cont failed"); - assert_eq!( - waitpid(child, None), - Ok(WaitStatus::PtraceEvent( - child, - SIGTRAP, - Event::PTRACE_EVENT_EXIT as i32 - )) - ); - // Finally get the normal wait() result, now that the process has exited - ptrace::cont(child, None).expect("cont failed"); - assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0))); - } - - #[cfg(not(target_env = "uclibc"))] - fn ptrace_waitid_parent(child: Pid) { - // Wait for the raised SIGTRAP - // - // Unlike waitpid(), waitid() can distinguish trap events from regular - // stop events, so unlike ptrace_wait_parent(), we get a PtraceEvent here - assert_eq!( - waitid(Id::Pid(child), WaitPidFlag::WEXITED), - Ok(WaitStatus::PtraceEvent(child, SIGTRAP, 0)), - ); - // We want to test a syscall stop and a PTRACE_EVENT stop - ptrace::setoptions( - child, - Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT, - ) - .expect("setopts failed"); - - // First, stop on the next system call, which will be exit() - ptrace::syscall(child, None).expect("syscall failed"); - assert_eq!( - waitid(Id::Pid(child), WaitPidFlag::WEXITED), - Ok(WaitStatus::PtraceSyscall(child)), - ); - // Then get the ptrace event for the process exiting - ptrace::cont(child, None).expect("cont failed"); - assert_eq!( - waitid(Id::Pid(child), WaitPidFlag::WEXITED), - Ok(WaitStatus::PtraceEvent( - child, - SIGTRAP, - Event::PTRACE_EVENT_EXIT as i32 - )), - ); - // Finally get the normal wait() result, now that the process has exited - ptrace::cont(child, None).expect("cont failed"); - assert_eq!( - waitid(Id::Pid(child), WaitPidFlag::WEXITED), - Ok(WaitStatus::Exited(child, 0)), - ); - } - - #[test] - fn test_wait_ptrace() { - require_capability!("test_wait_ptrace", CAP_SYS_PTRACE); - let _m = crate::FORK_MTX.lock(); - - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => ptrace_child(), - Parent { child } => ptrace_wait_parent(child), - } - } - - #[test] - #[cfg(not(target_env = "uclibc"))] - fn test_waitid_ptrace() { - require_capability!("test_waitid_ptrace", CAP_SYS_PTRACE); - let _m = crate::FORK_MTX.lock(); - - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => ptrace_child(), - Parent { child } => ptrace_waitid_parent(child), - } - } -} diff --git a/vendor/nix/test/test.rs b/vendor/nix/test/test.rs deleted file mode 100644 index 6b42aad95..000000000 --- a/vendor/nix/test/test.rs +++ /dev/null @@ -1,124 +0,0 @@ -#[macro_use] -extern crate cfg_if; -#[cfg_attr(not(any(target_os = "redox", target_os = "haiku")), macro_use)] -extern crate nix; -#[macro_use] -extern crate lazy_static; - -mod common; -mod sys; -#[cfg(not(target_os = "redox"))] -mod test_dir; -mod test_fcntl; -#[cfg(any(target_os = "android", target_os = "linux"))] -mod test_kmod; -#[cfg(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "fushsia", - target_os = "linux", - target_os = "netbsd" -))] -mod test_mq; -#[cfg(not(target_os = "redox"))] -mod test_net; -mod test_nix_path; -#[cfg(target_os = "freebsd")] -mod test_nmount; -mod test_poll; -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -mod test_pty; -mod test_resource; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - all(target_os = "freebsd", fbsd14), - target_os = "linux" -))] -mod test_sched; -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "linux", - target_os = "macos" -))] -mod test_sendfile; -mod test_stat; -mod test_time; -#[cfg(all( - any( - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd" - ), - feature = "time", - feature = "signal" -))] -mod test_timer; -mod test_unistd; - -use nix::unistd::{chdir, getcwd, read}; -use parking_lot::{Mutex, RwLock, RwLockWriteGuard}; -use std::os::unix::io::RawFd; -use std::path::PathBuf; - -/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s -fn read_exact(f: RawFd, buf: &mut [u8]) { - let mut len = 0; - while len < buf.len() { - // get_mut would be better than split_at_mut, but it requires nightly - let (_, remaining) = buf.split_at_mut(len); - len += read(f, remaining).unwrap(); - } -} - -lazy_static! { - /// Any test that changes the process's current working directory must grab - /// the RwLock exclusively. Any process that cares about the current - /// working directory must grab it shared. - pub static ref CWD_LOCK: RwLock<()> = RwLock::new(()); - /// Any test that creates child processes must grab this mutex, regardless - /// of what it does with those children. - pub static ref FORK_MTX: Mutex<()> = Mutex::new(()); - /// Any test that changes the process's supplementary groups must grab this - /// mutex - pub static ref GROUPS_MTX: Mutex<()> = Mutex::new(()); - /// Any tests that loads or unloads kernel modules must grab this mutex - pub static ref KMOD_MTX: Mutex<()> = Mutex::new(()); - /// Any test that calls ptsname(3) must grab this mutex. - pub static ref PTSNAME_MTX: Mutex<()> = Mutex::new(()); - /// Any test that alters signal handling must grab this mutex. - pub static ref SIGNAL_MTX: Mutex<()> = Mutex::new(()); -} - -/// RAII object that restores a test's original directory on drop -struct DirRestore<'a> { - d: PathBuf, - _g: RwLockWriteGuard<'a, ()>, -} - -impl<'a> DirRestore<'a> { - fn new() -> Self { - let guard = crate::CWD_LOCK.write(); - DirRestore { - _g: guard, - d: getcwd().unwrap(), - } - } -} - -impl<'a> Drop for DirRestore<'a> { - fn drop(&mut self) { - let r = chdir(&self.d); - if std::thread::panicking() { - r.unwrap(); - } - } -} diff --git a/vendor/nix/test/test_clearenv.rs b/vendor/nix/test/test_clearenv.rs deleted file mode 100644 index 28a776804..000000000 --- a/vendor/nix/test/test_clearenv.rs +++ /dev/null @@ -1,9 +0,0 @@ -use std::env; - -#[test] -fn clearenv() { - env::set_var("FOO", "BAR"); - unsafe { nix::env::clearenv() }.unwrap(); - assert_eq!(env::var("FOO").unwrap_err(), env::VarError::NotPresent); - assert_eq!(env::vars().count(), 0); -} diff --git a/vendor/nix/test/test_dir.rs b/vendor/nix/test/test_dir.rs deleted file mode 100644 index 2af4aa5c0..000000000 --- a/vendor/nix/test/test_dir.rs +++ /dev/null @@ -1,65 +0,0 @@ -use nix::dir::{Dir, Type}; -use nix::fcntl::OFlag; -use nix::sys::stat::Mode; -use std::fs::File; -use tempfile::tempdir; - -#[cfg(test)] -fn flags() -> OFlag { - #[cfg(target_os = "illumos")] - let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC; - - #[cfg(not(target_os = "illumos"))] - let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_DIRECTORY; - - f -} - -#[test] -#[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(); - 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())); - let entry_names: Vec<_> = entries - .iter() - .map(|e| e.file_name().to_str().unwrap().to_owned()) - .collect(); - assert_eq!(&entry_names[..], &[".", "..", "bar", "foo"]); - - // Check file types. The system is allowed to return DT_UNKNOWN (aka None here) but if it does - // return a type, ensure it's correct. - assert!(&[Some(Type::Directory), None].contains(&entries[0].file_type())); // .: dir - assert!(&[Some(Type::Directory), None].contains(&entries[1].file_type())); // ..: dir - assert!(&[Some(Type::Symlink), None].contains(&entries[2].file_type())); // bar: symlink - assert!(&[Some(Type::File), None].contains(&entries[3].file_type())); // foo: regular file -} - -#[test] -fn rewind() { - let tmp = tempdir().unwrap(); - let mut dir = Dir::open(tmp.path(), flags(), Mode::empty()).unwrap(); - let entries1: Vec<_> = dir - .iter() - .map(|e| e.unwrap().file_name().to_owned()) - .collect(); - let entries2: Vec<_> = dir - .iter() - .map(|e| e.unwrap().file_name().to_owned()) - .collect(); - let entries3: Vec<_> = dir - .into_iter() - .map(|e| e.unwrap().file_name().to_owned()) - .collect(); - assert_eq!(entries1, entries2); - assert_eq!(entries2, entries3); -} - -#[cfg(not(target_os = "haiku"))] -#[test] -fn ebadf() { - assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::EBADF); -} diff --git a/vendor/nix/test/test_fcntl.rs b/vendor/nix/test/test_fcntl.rs deleted file mode 100644 index e51044a06..000000000 --- a/vendor/nix/test/test_fcntl.rs +++ /dev/null @@ -1,565 +0,0 @@ -#[cfg(not(target_os = "redox"))] -use nix::errno::*; -#[cfg(not(target_os = "redox"))] -use nix::fcntl::{open, readlink, OFlag}; -#[cfg(not(target_os = "redox"))] -use nix::fcntl::{openat, readlinkat, renameat}; -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -use nix::fcntl::{renameat2, RenameFlags}; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::Mode; -#[cfg(not(target_os = "redox"))] -use nix::unistd::{close, read}; -#[cfg(not(target_os = "redox"))] -use std::fs::File; -#[cfg(not(target_os = "redox"))] -use std::io::prelude::*; -#[cfg(not(target_os = "redox"))] -use std::os::unix::fs; -#[cfg(not(target_os = "redox"))] -use tempfile::{self, NamedTempFile}; - -#[test] -#[cfg(not(target_os = "redox"))] -// QEMU does not handle openat well enough to satisfy this test -// https://gitlab.com/qemu-project/qemu/-/issues/829 -#[cfg_attr(qemu, ignore)] -fn test_openat() { - const CONTENTS: &[u8] = b"abcd"; - let mut tmp = NamedTempFile::new().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let dirfd = - open(tmp.path().parent().unwrap(), OFlag::empty(), Mode::empty()) - .unwrap(); - let fd = openat( - dirfd, - tmp.path().file_name().unwrap(), - OFlag::O_RDONLY, - Mode::empty(), - ) - .unwrap(); - - let mut buf = [0u8; 1024]; - assert_eq!(4, read(fd, &mut buf).unwrap()); - assert_eq!(CONTENTS, &buf[0..4]); - - close(fd).unwrap(); - close(dirfd).unwrap(); -} - -#[test] -#[cfg(not(target_os = "redox"))] -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(); - 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(); - assert_eq!( - renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(), - Errno::ENOENT - ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); - assert!(new_dir.path().join("new").exists()); -} - -#[test] -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -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(); - let new_dir = tempfile::tempdir().unwrap(); - let new_dirfd = - open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap(); - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::empty(), - ) - .unwrap(); - assert_eq!( - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::empty() - ) - .unwrap_err(), - Errno::ENOENT - ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); - assert!(new_dir.path().join("new").exists()); -} - -#[test] -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -fn test_renameat2_exchange() { - 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"); - { - let mut old_f = File::create(&old_path).unwrap(); - old_f.write_all(b"old").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"); - { - let mut new_f = File::create(&new_path).unwrap(); - new_f.write_all(b"new").unwrap(); - } - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::RENAME_EXCHANGE, - ) - .unwrap(); - let mut buf = String::new(); - let mut new_f = File::open(&new_path).unwrap(); - new_f.read_to_string(&mut buf).unwrap(); - assert_eq!(buf, "old"); - buf = "".to_string(); - let mut old_f = File::open(&old_path).unwrap(); - old_f.read_to_string(&mut buf).unwrap(); - assert_eq!(buf, "new"); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); -} - -#[test] -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any( - target_arch = "x86_64", - target_arch = "x32", - target_arch = "powerpc", - target_arch = "s390x" - ) -))] -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(); - 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(); - assert_eq!( - renameat2( - Some(old_dirfd), - "old", - Some(new_dirfd), - "new", - RenameFlags::RENAME_NOREPLACE - ) - .unwrap_err(), - Errno::EEXIST - ); - close(old_dirfd).unwrap(); - close(new_dirfd).unwrap(); - assert!(new_dir.path().join("new").exists()); - assert!(old_dir.path().join("old").exists()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_readlink() { - let tempdir = tempfile::tempdir().unwrap(); - 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(); - let expected_dir = src.to_str().unwrap(); - - assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir); - assert_eq!( - readlinkat(dirfd, "b").unwrap().to_str().unwrap(), - expected_dir - ); -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod linux_android { - use libc::loff_t; - use std::io::prelude::*; - use std::io::IoSlice; - use std::os::unix::prelude::*; - - use nix::fcntl::*; - use nix::unistd::{close, pipe, read, write}; - - use tempfile::tempfile; - #[cfg(any(target_os = "linux"))] - use tempfile::NamedTempFile; - - use crate::*; - - /// This test creates a temporary file containing the contents - /// 'foobarbaz' and uses the `copy_file_range` call to transfer - /// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The - /// resulting file is read and should contain the contents `bar`. - /// The from_offset should be updated by the call to reflect - /// the 3 bytes read (6). - #[test] - // QEMU does not support copy_file_range. Skip under qemu - #[cfg_attr(qemu, ignore)] - fn test_copy_file_range() { - const CONTENTS: &[u8] = b"foobarbaz"; - - let mut tmp1 = tempfile().unwrap(); - let mut tmp2 = tempfile().unwrap(); - - tmp1.write_all(CONTENTS).unwrap(); - tmp1.flush().unwrap(); - - let mut from_offset: i64 = 3; - copy_file_range( - tmp1.as_raw_fd(), - Some(&mut from_offset), - tmp2.as_raw_fd(), - None, - 3, - ) - .unwrap(); - - let mut res: String = String::new(); - tmp2.rewind().unwrap(); - tmp2.read_to_string(&mut res).unwrap(); - - assert_eq!(res, String::from("bar")); - assert_eq!(from_offset, 6); - } - - #[test] - fn test_splice() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let (rd, wr) = pipe().unwrap(); - let mut offset: loff_t = 5; - let res = splice( - tmp.as_raw_fd(), - Some(&mut offset), - wr, - None, - 2, - SpliceFFlags::empty(), - ) - .unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); - assert_eq!(b"f1", &buf[0..2]); - assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); - } - - #[test] - fn test_tee() { - let (rd1, wr1) = pipe().unwrap(); - let (rd2, wr2) = pipe().unwrap(); - - write(wr1, b"abc").unwrap(); - let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - - // Check the tee'd bytes are at rd2. - assert_eq!(2, read(rd2, &mut buf).unwrap()); - assert_eq!(b"ab", &buf[0..2]); - - // Check all the bytes are still at rd1. - assert_eq!(3, read(rd1, &mut buf).unwrap()); - assert_eq!(b"abc", &buf[0..3]); - - close(rd1).unwrap(); - close(wr1).unwrap(); - close(rd2).unwrap(); - close(wr2).unwrap(); - } - - #[test] - fn test_vmsplice() { - let (rd, wr) = pipe().unwrap(); - - let buf1 = b"abcdef"; - let buf2 = b"defghi"; - let iovecs = vec![IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])]; - - let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap(); - - assert_eq!(6, res); - - // Check the bytes can be read at rd. - let mut buf = [0u8; 32]; - assert_eq!(6, read(rd, &mut buf).unwrap()); - assert_eq!(b"abcdef", &buf[0..6]); - - close(rd).unwrap(); - close(wr).unwrap(); - } - - #[cfg(any(target_os = "linux"))] - #[test] - fn test_fallocate() { - let tmp = NamedTempFile::new().unwrap(); - - let fd = tmp.as_raw_fd(); - fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap(); - - // Check if we read exactly 100 bytes - let mut buf = [0u8; 200]; - assert_eq!(100, read(fd, &mut buf).unwrap()); - } - - // The tests below are disabled for the listed targets - // due to OFD locks not being available in the kernel/libc - // versions used in the CI environment, probably because - // they run under QEMU. - - #[test] - #[cfg(all(target_os = "linux", not(target_env = "musl")))] - #[cfg_attr(target_env = "uclibc", ignore)] // uclibc doesn't support OFD locks, but the test should still compile - fn test_ofd_write_lock() { - use nix::sys::stat::fstat; - use std::mem; - - let tmp = NamedTempFile::new().unwrap(); - - let fd = tmp.as_raw_fd(); - let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap(); - if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC { - // OverlayFS is a union file system. It returns one inode value in - // stat(2), but a different one shows up in /proc/locks. So we must - // skip the test. - skip!("/proc/locks does not work on overlayfs"); - } - let inode = fstat(fd).expect("fstat failed").st_ino as usize; - - 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())), - lock_info(inode) - ); - - flock.l_type = libc::F_UNLCK as libc::c_short; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed"); - assert_eq!(None, lock_info(inode)); - } - - #[test] - #[cfg(all(target_os = "linux", not(target_env = "musl")))] - #[cfg_attr(target_env = "uclibc", ignore)] // uclibc doesn't support OFD locks, but the test should still compile - fn test_ofd_read_lock() { - use nix::sys::stat::fstat; - use std::mem; - - let tmp = NamedTempFile::new().unwrap(); - - let fd = tmp.as_raw_fd(); - let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap(); - if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC { - // OverlayFS is a union file system. It returns one inode value in - // stat(2), but a different one shows up in /proc/locks. So we must - // skip the test. - skip!("/proc/locks does not work on overlayfs"); - } - let inode = fstat(fd).expect("fstat failed").st_ino as usize; - - 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())), - lock_info(inode) - ); - - flock.l_type = libc::F_UNLCK as libc::c_short; - fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed"); - 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); - - for line in buf.lines() { - let line = line.unwrap(); - let parts: Vec<_> = line.split_whitespace().collect(); - let lock_type = parts[1]; - let lock_access = parts[3]; - let ino_parts: Vec<_> = parts[5].split(':').collect(); - let ino: usize = ino_parts[2].parse().unwrap(); - if ino == inode { - return Some((lock_type.to_string(), lock_access.to_string())); - } - } - None - } -} - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "wasi", - target_env = "uclibc", - target_os = "freebsd" -))] -mod test_posix_fadvise { - - use nix::errno::Errno; - use nix::fcntl::*; - use nix::unistd::pipe; - use std::os::unix::io::{AsRawFd, RawFd}; - use tempfile::NamedTempFile; - - #[test] - fn test_success() { - let tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); - posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED) - .expect("posix_fadvise failed"); - } - - #[test] - fn test_errno() { - let (rd, _wr) = pipe().unwrap(); - let res = posix_fadvise( - rd as RawFd, - 0, - 100, - PosixFadviseAdvice::POSIX_FADV_WILLNEED, - ); - assert_eq!(res, Err(Errno::ESPIPE)); - } -} - -#[cfg(any( - target_os = "linux", - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "fuchsia", - target_os = "wasi", - target_os = "freebsd" -))] -mod test_posix_fallocate { - - use nix::errno::Errno; - use nix::fcntl::*; - use nix::unistd::pipe; - use std::{ - io::Read, - os::unix::io::{AsRawFd, RawFd}, - }; - use tempfile::NamedTempFile; - - #[test] - fn success() { - const LEN: usize = 100; - let mut tmp = NamedTempFile::new().unwrap(); - let fd = tmp.as_raw_fd(); - let res = posix_fallocate(fd, 0, LEN as libc::off_t); - match res { - Ok(_) => { - let mut data = [1u8; LEN]; - 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. - } - _ => res.unwrap(), - } - } - - #[test] - fn errno() { - let (rd, _wr) = pipe().unwrap(); - let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err(); - match err { - Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (), - errno => panic!("unexpected errno {}", errno,), - } - } -} diff --git a/vendor/nix/test/test_kmod/hello_mod/Makefile b/vendor/nix/test/test_kmod/hello_mod/Makefile deleted file mode 100644 index 74c99b77e..000000000 --- a/vendor/nix/test/test_kmod/hello_mod/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-m += hello.o - -all: - make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules - -clean: - make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean diff --git a/vendor/nix/test/test_kmod/mod.rs b/vendor/nix/test/test_kmod/mod.rs deleted file mode 100644 index 6f9aaa897..000000000 --- a/vendor/nix/test/test_kmod/mod.rs +++ /dev/null @@ -1,188 +0,0 @@ -use crate::*; -use std::fs::copy; -use std::path::PathBuf; -use std::process::Command; -use tempfile::{tempdir, TempDir}; - -fn compile_kernel_module() -> (PathBuf, String, TempDir) { - let _m = crate::FORK_MTX.lock(); - - let tmp_dir = - tempdir().expect("unable to create temporary build directory"); - - copy( - "test/test_kmod/hello_mod/hello.c", - 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"); - - let status = Command::new("make") - .current_dir(tmp_dir.path()) - .status() - .expect("failed to run make"); - - assert!(status.success()); - - // Return the relative path of the build kernel module - (tmp_dir.path().join("hello.ko"), "hello".to_owned(), tmp_dir) -} - -use nix::errno::Errno; -use nix::kmod::{delete_module, DeleteModuleFlags}; -use nix::kmod::{finit_module, init_module, ModuleInitFlags}; -use std::ffi::CString; -use std::fs::File; -use std::io::Read; - -#[test] -fn test_finit_and_delete_module() { - require_capability!("test_finit_and_delete_module", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock(); - let _m1 = crate::CWD_LOCK.read(); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let f = File::open(kmod_path).expect("unable to open kernel module"); - finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()) - .expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ) - .expect("unable to unload kernel module"); -} - -#[test] -fn test_finit_and_delete_module_with_params() { - require_capability!( - "test_finit_and_delete_module_with_params", - CAP_SYS_MODULE - ); - let _m0 = crate::KMOD_MTX.lock(); - let _m1 = crate::CWD_LOCK.read(); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let f = File::open(kmod_path).expect("unable to open kernel module"); - finit_module( - &f, - &CString::new("who=Rust number=2018").unwrap(), - ModuleInitFlags::empty(), - ) - .expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ) - .expect("unable to unload kernel module"); -} - -#[test] -fn test_init_and_delete_module() { - require_capability!("test_init_and_delete_module", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock(); - let _m1 = crate::CWD_LOCK.read(); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let mut f = File::open(kmod_path).expect("unable to open kernel module"); - let mut contents: Vec<u8> = Vec::new(); - f.read_to_end(&mut contents) - .expect("unable to read kernel module content to buffer"); - init_module(&contents, &CString::new("").unwrap()) - .expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ) - .expect("unable to unload kernel module"); -} - -#[test] -fn test_init_and_delete_module_with_params() { - require_capability!( - "test_init_and_delete_module_with_params", - CAP_SYS_MODULE - ); - let _m0 = crate::KMOD_MTX.lock(); - let _m1 = crate::CWD_LOCK.read(); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let mut f = File::open(kmod_path).expect("unable to open kernel module"); - let mut contents: Vec<u8> = Vec::new(); - f.read_to_end(&mut contents) - .expect("unable to read kernel module content to buffer"); - init_module(&contents, &CString::new("who=Nix number=2015").unwrap()) - .expect("unable to load kernel module"); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ) - .expect("unable to unload kernel module"); -} - -#[test] -fn test_finit_module_invalid() { - require_capability!("test_finit_module_invalid", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock(); - let _m1 = crate::CWD_LOCK.read(); - - let kmod_path = "/dev/zero"; - - let f = File::open(kmod_path).expect("unable to open kernel module"); - let result = - finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()); - - assert_eq!(result.unwrap_err(), Errno::EINVAL); -} - -#[test] -fn test_finit_module_twice_and_delete_module() { - require_capability!( - "test_finit_module_twice_and_delete_module", - CAP_SYS_MODULE - ); - let _m0 = crate::KMOD_MTX.lock(); - let _m1 = crate::CWD_LOCK.read(); - - let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module(); - - let f = File::open(kmod_path).expect("unable to open kernel module"); - finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()) - .expect("unable to load kernel module"); - - let result = - finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty()); - - assert_eq!(result.unwrap_err(), Errno::EEXIST); - - delete_module( - &CString::new(kmod_name).unwrap(), - DeleteModuleFlags::empty(), - ) - .expect("unable to unload kernel module"); -} - -#[test] -fn test_delete_module_not_loaded() { - require_capability!("test_delete_module_not_loaded", CAP_SYS_MODULE); - let _m0 = crate::KMOD_MTX.lock(); - let _m1 = crate::CWD_LOCK.read(); - - let result = delete_module( - &CString::new("hello").unwrap(), - DeleteModuleFlags::empty(), - ); - - assert_eq!(result.unwrap_err(), Errno::ENOENT); -} diff --git a/vendor/nix/test/test_mount.rs b/vendor/nix/test/test_mount.rs deleted file mode 100644 index 2fd612e35..000000000 --- a/vendor/nix/test/test_mount.rs +++ /dev/null @@ -1,271 +0,0 @@ -mod common; - -// Implementation note: to allow unprivileged users to run it, this test makes -// use of user and mount namespaces. On systems that allow unprivileged user -// namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run -// without root. - -#[cfg(target_os = "linux")] -mod test_mount { - use std::fs::{self, File}; - use std::io::{self, Read, Write}; - use std::os::unix::fs::OpenOptionsExt; - use std::os::unix::fs::PermissionsExt; - use std::process::{self, Command}; - - use libc::{EACCES, EROFS}; - - use nix::errno::Errno; - use nix::mount::{mount, umount, MsFlags}; - use nix::sched::{unshare, CloneFlags}; - use nix::sys::stat::{self, Mode}; - use nix::unistd::getuid; - - static SCRIPT_CONTENTS: &[u8] = b"#!/bin/sh -exit 23"; - - const EXPECTED_STATUS: i32 = 23; - - const NONE: Option<&'static [u8]> = None; - #[allow(clippy::bind_instead_of_map)] // False positive - pub fn test_mount_tmpfs_without_flags_allows_rwx() { - let tempdir = tempfile::tempdir().unwrap(); - - mount( - NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), - MsFlags::empty(), - NONE, - ) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - let test_path = tempdir.path().join("test"); - - // Verify write. - fs::OpenOptions::new() - .create(true) - .write(true) - .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits()) - .open(&test_path) - .or_else(|e| { - if Errno::from_i32(e.raw_os_error().unwrap()) - == Errno::EOVERFLOW - { - // Skip tests on certain Linux kernels which have a bug - // regarding tmpfs in namespaces. - // Ubuntu 14.04 and 16.04 are known to be affected; 16.10 is - // not. There is no legitimate reason for open(2) to return - // EOVERFLOW here. - // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1659087 - let stderr = io::stderr(); - let mut handle = stderr.lock(); - writeln!( - handle, - "Buggy Linux kernel detected. Skipping test." - ) - .unwrap(); - process::exit(0); - } else { - panic!("open failed: {}", e); - } - }) - .and_then(|mut f| f.write(SCRIPT_CONTENTS)) - .unwrap_or_else(|e| panic!("write failed: {}", e)); - - // Verify read. - let mut buf = Vec::new(); - File::open(&test_path) - .and_then(|mut f| f.read_to_end(&mut buf)) - .unwrap_or_else(|e| panic!("read failed: {}", e)); - assert_eq!(buf, SCRIPT_CONTENTS); - - // Verify execute. - assert_eq!( - EXPECTED_STATUS, - Command::new(&test_path) - .status() - .unwrap_or_else(|e| panic!("exec failed: {}", e)) - .code() - .unwrap_or_else(|| panic!("child killed by signal")) - ); - - umount(tempdir.path()) - .unwrap_or_else(|e| panic!("umount failed: {}", e)); - } - - pub fn test_mount_rdonly_disallows_write() { - let tempdir = tempfile::tempdir().unwrap(); - - mount( - NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), - MsFlags::MS_RDONLY, - NONE, - ) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - // EROFS: Read-only file system - 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)); - } - - pub fn test_mount_noexec_disallows_exec() { - let tempdir = tempfile::tempdir().unwrap(); - - mount( - NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), - MsFlags::MS_NOEXEC, - NONE, - ) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - let test_path = tempdir.path().join("test"); - - fs::OpenOptions::new() - .create(true) - .write(true) - .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits()) - .open(&test_path) - .and_then(|mut f| f.write(SCRIPT_CONTENTS)) - .unwrap_or_else(|e| panic!("write failed: {}", e)); - - // Verify that we cannot execute despite a+x permissions being set. - let mode = stat::Mode::from_bits_truncate( - fs::metadata(&test_path) - .map(|md| md.permissions().mode()) - .unwrap_or_else(|e| panic!("metadata failed: {}", e)), - ); - - assert!( - mode.contains(Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IXOTH), - "{:?} did not have execute permissions", - &test_path - ); - - // EACCES: Permission denied - 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)); - } - - pub fn test_mount_bind() { - let tempdir = tempfile::tempdir().unwrap(); - let file_name = "test"; - - { - let mount_point = tempfile::tempdir().unwrap(); - - mount( - Some(tempdir.path()), - mount_point.path(), - NONE, - MsFlags::MS_BIND, - NONE, - ) - .unwrap_or_else(|e| panic!("mount failed: {}", e)); - - fs::OpenOptions::new() - .create(true) - .write(true) - .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits()) - .open(mount_point.path().join(file_name)) - .and_then(|mut f| f.write(SCRIPT_CONTENTS)) - .unwrap_or_else(|e| panic!("write failed: {}", e)); - - umount(mount_point.path()) - .unwrap_or_else(|e| panic!("umount failed: {}", e)); - } - - // Verify the file written in the mount shows up in source directory, even - // after unmounting. - - let mut buf = Vec::new(); - File::open(tempdir.path().join(file_name)) - .and_then(|mut f| f.read_to_end(&mut buf)) - .unwrap_or_else(|e| panic!("read failed: {}", e)); - assert_eq!(buf, SCRIPT_CONTENTS); - } - - pub fn setup_namespaces() { - // Hold on to the uid in the parent namespace. - let uid = getuid(); - - unshare(CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_NEWUSER).unwrap_or_else(|e| { - let stderr = io::stderr(); - let mut handle = stderr.lock(); - writeln!(handle, - "unshare failed: {}. Are unprivileged user namespaces available?", - e).unwrap(); - writeln!(handle, "mount is not being tested").unwrap(); - // Exit with success because not all systems support unprivileged user namespaces, and - // that's not what we're testing for. - process::exit(0); - }); - - // Map user as uid 1000. - fs::OpenOptions::new() - .write(true) - .open("/proc/self/uid_map") - .and_then(|mut f| f.write(format!("1000 {} 1\n", uid).as_bytes())) - .unwrap_or_else(|e| panic!("could not write uid map: {}", e)); - } -} - -// Test runner - -/// Mimic normal test output (hackishly). -#[cfg(target_os = "linux")] -macro_rules! run_tests { - ( $($test_fn:ident),* ) => {{ - println!(); - - $( - print!("test test_mount::{} ... ", stringify!($test_fn)); - $test_fn(); - println!("ok"); - )* - - println!(); - }} -} - -#[cfg(target_os = "linux")] -fn main() { - use test_mount::{ - setup_namespaces, test_mount_bind, test_mount_noexec_disallows_exec, - test_mount_rdonly_disallows_write, - test_mount_tmpfs_without_flags_allows_rwx, - }; - skip_if_cirrus!("Fails for an unknown reason Cirrus CI. Bug #1351"); - setup_namespaces(); - - run_tests!( - test_mount_tmpfs_without_flags_allows_rwx, - test_mount_rdonly_disallows_write, - test_mount_noexec_disallows_exec, - test_mount_bind - ); -} - -#[cfg(not(target_os = "linux"))] -fn main() {} diff --git a/vendor/nix/test/test_mq.rs b/vendor/nix/test/test_mq.rs deleted file mode 100644 index 7b48e7ac7..000000000 --- a/vendor/nix/test/test_mq.rs +++ /dev/null @@ -1,190 +0,0 @@ -use cfg_if::cfg_if; -use std::ffi::CString; -use std::str; - -use nix::errno::Errno; -use nix::mqueue::{mq_attr_member_t, mq_close, mq_open, mq_receive, mq_send}; -use nix::mqueue::{MQ_OFlag, MqAttr}; -use nix::sys::stat::Mode; - -// Defined as a macro such that the error source is reported as the caller's location. -macro_rules! assert_attr_eq { - ($read_attr:ident, $initial_attr:ident) => { - cfg_if! { - if #[cfg(any(target_os = "dragonfly", target_os = "netbsd"))] { - // NetBSD (and others which inherit its implementation) include other flags - // in read_attr, such as those specified by oflag. Just make sure at least - // the correct bits are set. - assert_eq!($read_attr.flags() & $initial_attr.flags(), $initial_attr.flags()); - assert_eq!($read_attr.maxmsg(), $initial_attr.maxmsg()); - assert_eq!($read_attr.msgsize(), $initial_attr.msgsize()); - assert_eq!($read_attr.curmsgs(), $initial_attr.curmsgs()); - } else { - assert_eq!($read_attr, $initial_attr); - } - } - } -} - -#[test] -fn test_mq_send_and_receive() { - const MSG_SIZE: mq_attr_member_t = 32; - let attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap(); - - let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r0 = mq_open(mq_name, oflag0, mode, Some(&attr)); - if let Err(Errno::ENOSYS) = r0 { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd0 = r0.unwrap(); - let msg_to_send = "msg_1"; - mq_send(&mqd0, msg_to_send.as_bytes(), 1).unwrap(); - - let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY; - let mqd1 = mq_open(mq_name, oflag1, mode, Some(&attr)).unwrap(); - let mut buf = [0u8; 32]; - let mut prio = 0u32; - let len = mq_receive(&mqd1, &mut buf, &mut prio).unwrap(); - assert_eq!(prio, 1); - - mq_close(mqd1).unwrap(); - mq_close(mqd0).unwrap(); - assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap()); -} - -#[test] -fn test_mq_getattr() { - use nix::mqueue::mq_getattr; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - - let read_attr = mq_getattr(&mqd).unwrap(); - assert_attr_eq!(read_attr, initial_attr); - mq_close(mqd).unwrap(); -} - -// FIXME: Fix failures for mips in QEMU -#[test] -#[cfg_attr( - all(qemu, any(target_arch = "mips", target_arch = "mips64")), - ignore -)] -fn test_mq_setattr() { - use nix::mqueue::{mq_getattr, mq_setattr}; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - - let new_attr = MqAttr::new(0, 20, MSG_SIZE * 2, 100); - let old_attr = mq_setattr(&mqd, &new_attr).unwrap(); - assert_attr_eq!(old_attr, initial_attr); - - // No changes here because according to the Linux man page only - // O_NONBLOCK can be set (see tests below) - #[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] - { - let new_attr_get = mq_getattr(&mqd).unwrap(); - assert_ne!(new_attr_get, new_attr); - } - - let new_attr_non_blocking = MqAttr::new( - MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, - 10, - MSG_SIZE, - 0, - ); - mq_setattr(&mqd, &new_attr_non_blocking).unwrap(); - let new_attr_get = mq_getattr(&mqd).unwrap(); - - // now the O_NONBLOCK flag has been set - #[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] - { - assert_ne!(new_attr_get, initial_attr); - } - assert_attr_eq!(new_attr_get, new_attr_non_blocking); - mq_close(mqd).unwrap(); -} - -// FIXME: Fix failures for mips in QEMU -#[test] -#[cfg_attr( - all(qemu, any(target_arch = "mips", target_arch = "mips64")), - ignore -)] -fn test_mq_set_nonblocking() { - use nix::mqueue::{mq_getattr, mq_remove_nonblock, mq_set_nonblock}; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - mq_set_nonblock(&mqd).unwrap(); - let new_attr = mq_getattr(&mqd); - let o_nonblock_bits = MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t; - assert_eq!(new_attr.unwrap().flags() & o_nonblock_bits, o_nonblock_bits); - mq_remove_nonblock(&mqd).unwrap(); - let new_attr = mq_getattr(&mqd); - assert_eq!(new_attr.unwrap().flags() & o_nonblock_bits, 0); - mq_close(mqd).unwrap(); -} - -#[test] -fn test_mq_unlink() { - use nix::mqueue::mq_unlink; - const MSG_SIZE: mq_attr_member_t = 32; - let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap(); - #[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] - let mq_name_not_opened = - &CString::new(b"/mq_unlink_test".as_ref()).unwrap(); - let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY; - let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH; - let r = mq_open(mq_name_opened, oflag, mode, Some(&initial_attr)); - if let Err(Errno::ENOSYS) = r { - println!("message queues not supported or module not loaded?"); - return; - }; - let mqd = r.unwrap(); - - let res_unlink = mq_unlink(mq_name_opened); - assert_eq!(res_unlink, Ok(())); - - // NetBSD (and others which inherit its implementation) defer removing the message - // queue name until all references are closed, whereas Linux and others remove the - // message queue name immediately. - #[cfg(not(any(target_os = "dragonfly", target_os = "netbsd")))] - { - let res_unlink_not_opened = mq_unlink(mq_name_not_opened); - assert_eq!(res_unlink_not_opened, Err(Errno::ENOENT)); - } - - mq_close(mqd).unwrap(); - let res_unlink_after_close = mq_unlink(mq_name_opened); - assert_eq!(res_unlink_after_close, Err(Errno::ENOENT)); -} diff --git a/vendor/nix/test/test_net.rs b/vendor/nix/test/test_net.rs deleted file mode 100644 index c44655a4c..000000000 --- a/vendor/nix/test/test_net.rs +++ /dev/null @@ -1,19 +0,0 @@ -use nix::net::if_::*; - -#[cfg(any(target_os = "android", target_os = "linux"))] -const LOOPBACK: &[u8] = b"lo"; - -#[cfg(not(any( - target_os = "android", - target_os = "linux", - target_os = "haiku" -)))] -const LOOPBACK: &[u8] = b"lo0"; - -#[cfg(target_os = "haiku")] -const LOOPBACK: &[u8] = b"loop"; - -#[test] -fn test_if_nametoindex() { - if_nametoindex(LOOPBACK).expect("assertion failed"); -} diff --git a/vendor/nix/test/test_nix_path.rs b/vendor/nix/test/test_nix_path.rs deleted file mode 100644 index 8b1378917..000000000 --- a/vendor/nix/test/test_nix_path.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/vendor/nix/test/test_nmount.rs b/vendor/nix/test/test_nmount.rs deleted file mode 100644 index dec806a55..000000000 --- a/vendor/nix/test/test_nmount.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::*; -use nix::{ - errno::Errno, - mount::{unmount, MntFlags, Nmount}, -}; -use std::{ffi::CString, fs::File, path::Path}; -use tempfile::tempdir; - -#[test] -fn ok() { - require_mount!("nullfs"); - - let mountpoint = tempdir().unwrap(); - let target = tempdir().unwrap(); - let _sentry = File::create(target.path().join("sentry")).unwrap(); - - let fstype = CString::new("fstype").unwrap(); - let nullfs = CString::new("nullfs").unwrap(); - Nmount::new() - .str_opt(&fstype, &nullfs) - .str_opt_owned("fspath", mountpoint.path().to_str().unwrap()) - .str_opt_owned("target", target.path().to_str().unwrap()) - .nmount(MntFlags::empty()) - .unwrap(); - - // Now check that the sentry is visible through the mountpoint - let exists = Path::exists(&mountpoint.path().join("sentry")); - - // Cleanup the mountpoint before asserting - unmount(mountpoint.path(), MntFlags::empty()).unwrap(); - - assert!(exists); -} - -#[test] -fn bad_fstype() { - let mountpoint = tempdir().unwrap(); - let target = tempdir().unwrap(); - let _sentry = File::create(target.path().join("sentry")).unwrap(); - - let e = Nmount::new() - .str_opt_owned("fspath", mountpoint.path().to_str().unwrap()) - .str_opt_owned("target", target.path().to_str().unwrap()) - .nmount(MntFlags::empty()) - .unwrap_err(); - - assert_eq!(e.error(), Errno::EINVAL); - assert_eq!(e.errmsg(), Some("Invalid fstype")); -} diff --git a/vendor/nix/test/test_poll.rs b/vendor/nix/test/test_poll.rs deleted file mode 100644 index 53964e26b..000000000 --- a/vendor/nix/test/test_poll.rs +++ /dev/null @@ -1,84 +0,0 @@ -use nix::{ - errno::Errno, - poll::{poll, PollFd, PollFlags}, - unistd::{pipe, write}, -}; - -macro_rules! loop_while_eintr { - ($poll_expr: expr) => { - loop { - match $poll_expr { - Ok(nfds) => break nfds, - Err(Errno::EINTR) => (), - Err(e) => panic!("{}", e), - } - } - }; -} - -#[test] -fn test_poll() { - let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(r, PollFlags::POLLIN)]; - - // Poll an idle pipe. Should timeout - let nfds = loop_while_eintr!(poll(&mut fds, 100)); - assert_eq!(nfds, 0); - assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - - write(w, b".").unwrap(); - - // Poll a readable pipe. Should return an event. - let nfds = poll(&mut fds, 100).unwrap(); - assert_eq!(nfds, 1); - assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN)); -} - -// ppoll(2) is the same as poll except for how it handles timeouts and signals. -// Repeating the test for poll(2) should be sufficient to check that our -// bindings are correct. -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux" -))] -#[test] -fn test_ppoll() { - use nix::poll::ppoll; - use nix::sys::signal::SigSet; - use nix::sys::time::{TimeSpec, TimeValLike}; - - let timeout = TimeSpec::milliseconds(1); - let (r, w) = pipe().unwrap(); - let mut fds = [PollFd::new(r, PollFlags::POLLIN)]; - - // Poll an idle pipe. Should timeout - let sigset = SigSet::empty(); - let nfds = loop_while_eintr!(ppoll(&mut fds, Some(timeout), Some(sigset))); - assert_eq!(nfds, 0); - assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN)); - - write(w, b".").unwrap(); - - // Poll a readable pipe. Should return an event. - let nfds = ppoll(&mut fds, Some(timeout), None).unwrap(); - assert_eq!(nfds, 1); - assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN)); -} - -#[test] -fn test_pollfd_fd() { - use std::os::unix::io::AsRawFd; - - let pfd = PollFd::new(0x1234, PollFlags::empty()); - assert_eq!(pfd.as_raw_fd(), 0x1234); -} - -#[test] -fn test_pollfd_events() { - let mut pfd = PollFd::new(-1, PollFlags::POLLIN); - assert_eq!(pfd.events(), PollFlags::POLLIN); - pfd.set_events(PollFlags::POLLOUT); - assert_eq!(pfd.events(), PollFlags::POLLOUT); -} diff --git a/vendor/nix/test/test_pty.rs b/vendor/nix/test/test_pty.rs deleted file mode 100644 index 5c27e2d63..000000000 --- a/vendor/nix/test/test_pty.rs +++ /dev/null @@ -1,313 +0,0 @@ -use std::fs::File; -use std::io::{Read, Write}; -use std::os::unix::prelude::*; -use std::path::Path; -use tempfile::tempfile; - -use libc::{_exit, STDOUT_FILENO}; -use nix::fcntl::{open, OFlag}; -use nix::pty::*; -use nix::sys::stat; -use nix::sys::termios::*; -use nix::unistd::{close, pause, write}; - -/// Regression test for Issue #659 -/// This is the correct way to explicitly close a `PtyMaster` -#[test] -fn test_explicit_close() { - let mut f = { - let m = posix_openpt(OFlag::O_RDWR).unwrap(); - close(m.into_raw_fd()).unwrap(); - tempfile().unwrap() - }; - // This should work. But if there's been a double close, then it will - // return EBADF - f.write_all(b"whatever").unwrap(); -} - -/// Test equivalence of `ptsname` and `ptsname_r` -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_equivalence() { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name = unsafe { ptsname(&master_fd) }.unwrap(); - let slave_name_r = ptsname_r(&master_fd).unwrap(); - assert_eq!(slave_name, slave_name_r); -} - -/// Test data copying of `ptsname` -// TODO need to run in a subprocess, since ptsname is non-reentrant -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_copy() { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap(); - let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap(); - assert_eq!(slave_name1, slave_name2); - // Also make sure that the string was actually copied and they point to different parts of - // memory. - assert_ne!(slave_name1.as_ptr(), slave_name2.as_ptr()); -} - -/// Test data copying of `ptsname_r` -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_r_copy() { - // Open a new PTTY master - let master_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = ptsname_r(&master_fd).unwrap(); - let slave_name2 = ptsname_r(&master_fd).unwrap(); - assert_eq!(slave_name1, slave_name2); - assert_ne!(slave_name1.as_ptr(), slave_name2.as_ptr()); -} - -/// Test that `ptsname` returns different names for different devices -#[test] -#[cfg(any(target_os = "android", target_os = "linux"))] -fn test_ptsname_unique() { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master1_fd.as_raw_fd() > 0); - - // Open a second PTTY master - let master2_fd = posix_openpt(OFlag::O_RDWR).unwrap(); - assert!(master2_fd.as_raw_fd() > 0); - - // Get the name of the slave - let slave_name1 = unsafe { ptsname(&master1_fd) }.unwrap(); - let slave_name2 = unsafe { ptsname(&master2_fd) }.unwrap(); - assert_ne!(slave_name1, slave_name2); -} - -/// Common setup for testing PTTY pairs -fn open_ptty_pair() -> (PtyMaster, File) { - let _m = crate::PTSNAME_MTX.lock(); - - // Open a new PTTY master - let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed"); - - // Allow a slave to be generated for it - grantpt(&master).expect("grantpt failed"); - unlockpt(&master).expect("unlockpt failed"); - - // Get the name of the slave - let slave_name = unsafe { ptsname(&master) }.expect("ptsname failed"); - - // Open the slave device - let slave_fd = - open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()) - .unwrap(); - - #[cfg(target_os = "illumos")] - // TODO: rewrite using ioctl! - #[allow(clippy::comparison_chain)] - { - use libc::{ioctl, I_FIND, I_PUSH}; - - // On illumos systems, as per pts(7D), one must push STREAMS modules - // after opening a device path returned from ptsname(). - let ptem = b"ptem\0"; - let ldterm = b"ldterm\0"; - let r = unsafe { ioctl(slave_fd, I_FIND, ldterm.as_ptr()) }; - if r < 0 { - panic!("I_FIND failure"); - } else if r == 0 { - if unsafe { ioctl(slave_fd, I_PUSH, ptem.as_ptr()) } < 0 { - panic!("I_PUSH ptem failure"); - } - if unsafe { ioctl(slave_fd, I_PUSH, ldterm.as_ptr()) } < 0 { - panic!("I_PUSH ldterm failure"); - } - } - } - - let slave = unsafe { File::from_raw_fd(slave_fd) }; - - (master, slave) -} - -/// Test opening a master/slave PTTY pair -/// -/// This uses a common `open_ptty_pair` because much of these functions aren't useful by -/// themselves. So for this test we perform the basic act of getting a file handle for a -/// master/slave PTTY pair, then just sanity-check the raw values. -#[test] -fn test_open_ptty_pair() { - let (master, slave) = open_ptty_pair(); - assert!(master.as_raw_fd() > 0); - assert!(slave.as_raw_fd() > 0); -} - -/// Put the terminal in raw mode. -fn make_raw(fd: RawFd) { - let mut termios = tcgetattr(fd).unwrap(); - cfmakeraw(&mut termios); - tcsetattr(fd, SetArg::TCSANOW, &termios).unwrap(); -} - -/// Test `io::Read` on the PTTY master -#[test] -fn test_read_ptty_pair() { - let (mut master, mut slave) = open_ptty_pair(); - make_raw(slave.as_raw_fd()); - - let mut buf = [0u8; 5]; - slave.write_all(b"hello").unwrap(); - master.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"hello"); - - let mut master = &master; - slave.write_all(b"hello").unwrap(); - master.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"hello"); -} - -/// Test `io::Write` on the PTTY master -#[test] -fn test_write_ptty_pair() { - let (mut master, mut slave) = open_ptty_pair(); - make_raw(slave.as_raw_fd()); - - let mut buf = [0u8; 5]; - master.write_all(b"adios").unwrap(); - slave.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"adios"); - - let mut master = &master; - master.write_all(b"adios").unwrap(); - slave.read_exact(&mut buf).unwrap(); - assert_eq!(&buf, b"adios"); -} - -#[test] -fn test_openpty() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock(); - - let pty = openpty(None, None).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Writing to one should be readable on the other one - let string = "foofoofoo\n"; - let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); - crate::read_exact(pty.slave, &mut buf); - - assert_eq!(&buf, string.as_bytes()); - - // Read the echo as well - let echoed_string = "foofoofoo\r\n"; - let mut buf = [0u8; 11]; - crate::read_exact(pty.master, &mut buf); - assert_eq!(&buf, echoed_string.as_bytes()); - - let string2 = "barbarbarbar\n"; - let echoed_string2 = "barbarbarbar\r\n"; - let mut buf = [0u8; 14]; - write(pty.slave, string2.as_bytes()).unwrap(); - crate::read_exact(pty.master, &mut buf); - - assert_eq!(&buf, echoed_string2.as_bytes()); - - close(pty.master).unwrap(); - close(pty.slave).unwrap(); -} - -#[test] -fn test_openpty_with_termios() { - // openpty uses ptname(3) internally - let _m = crate::PTSNAME_MTX.lock(); - - // Open one pty to get attributes for the second one - let mut termios = { - let pty = openpty(None, None).unwrap(); - assert!(pty.master > 0); - assert!(pty.slave > 0); - let termios = tcgetattr(pty.slave).unwrap(); - close(pty.master).unwrap(); - close(pty.slave).unwrap(); - termios - }; - // Make sure newlines are not transformed so the data is preserved when sent. - termios.output_flags.remove(OutputFlags::ONLCR); - - let pty = openpty(None, &termios).unwrap(); - // Must be valid file descriptors - assert!(pty.master > 0); - assert!(pty.slave > 0); - - // Writing to one should be readable on the other one - let string = "foofoofoo\n"; - let mut buf = [0u8; 10]; - write(pty.master, string.as_bytes()).unwrap(); - crate::read_exact(pty.slave, &mut buf); - - assert_eq!(&buf, string.as_bytes()); - - // read the echo as well - let echoed_string = "foofoofoo\n"; - crate::read_exact(pty.master, &mut buf); - assert_eq!(&buf, echoed_string.as_bytes()); - - let string2 = "barbarbarbar\n"; - let echoed_string2 = "barbarbarbar\n"; - let mut buf = [0u8; 13]; - write(pty.slave, string2.as_bytes()).unwrap(); - crate::read_exact(pty.master, &mut buf); - - assert_eq!(&buf, echoed_string2.as_bytes()); - - close(pty.master).unwrap(); - close(pty.slave).unwrap(); -} - -#[test] -fn test_forkpty() { - use nix::sys::signal::*; - use nix::sys::wait::wait; - use nix::unistd::ForkResult::*; - // forkpty calls openpty which uses ptname(3) internally. - let _m0 = crate::PTSNAME_MTX.lock(); - // forkpty spawns a child process - let _m1 = crate::FORK_MTX.lock(); - - let string = "naninani\n"; - let echoed_string = "naninani\r\n"; - let pty = unsafe { forkpty(None, None).unwrap() }; - match pty.fork_result { - Child => { - write(STDOUT_FILENO, string.as_bytes()).unwrap(); - pause(); // we need the child to stay alive until the parent calls read - unsafe { - _exit(0); - } - } - Parent { child } => { - let mut buf = [0u8; 10]; - assert!(child.as_raw() > 0); - crate::read_exact(pty.master, &mut buf); - kill(child, SIGTERM).unwrap(); - wait().unwrap(); // keep other tests using generic wait from getting our child - assert_eq!(&buf, echoed_string.as_bytes()); - close(pty.master).unwrap(); - } - } -} diff --git a/vendor/nix/test/test_ptymaster_drop.rs b/vendor/nix/test/test_ptymaster_drop.rs deleted file mode 100644 index ffbaa5697..000000000 --- a/vendor/nix/test/test_ptymaster_drop.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -mod t { - use nix::fcntl::OFlag; - use nix::pty::*; - use nix::unistd::close; - use std::os::unix::io::AsRawFd; - - /// Regression test for Issue #659 - /// - /// `PtyMaster` should panic rather than double close the file descriptor - /// This must run in its own test process because it deliberately creates a - /// race condition. - #[test] - #[should_panic(expected = "Closing an invalid file descriptor!")] - fn test_double_close() { - let m = posix_openpt(OFlag::O_RDWR).unwrap(); - close(m.as_raw_fd()).unwrap(); - drop(m); // should panic here - } -} diff --git a/vendor/nix/test/test_resource.rs b/vendor/nix/test/test_resource.rs deleted file mode 100644 index 2ab581ba2..000000000 --- a/vendor/nix/test/test_resource.rs +++ /dev/null @@ -1,34 +0,0 @@ -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "illumos", - target_os = "haiku" -)))] -use nix::sys::resource::{getrlimit, setrlimit, Resource}; - -/// Tests the RLIMIT_NOFILE functionality of getrlimit(), where the resource RLIMIT_NOFILE refers -/// to the maximum file descriptor number that can be opened by the process (aka the maximum number -/// of file descriptors that the process can open, since Linux 4.5). -/// -/// We first fetch the existing file descriptor maximum values using getrlimit(), then edit the -/// soft limit to make sure it has a new and distinct value to the hard limit. We then setrlimit() -/// to put the new soft limit in effect, and then getrlimit() once more to ensure the limits have -/// been updated. -#[test] -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "illumos", - target_os = "haiku" -)))] -pub fn test_resource_limits_nofile() { - let (mut soft_limit, hard_limit) = - getrlimit(Resource::RLIMIT_NOFILE).unwrap(); - - soft_limit -= 1; - assert_ne!(soft_limit, hard_limit); - setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); - - let (new_soft_limit, _) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); - assert_eq!(new_soft_limit, soft_limit); -} diff --git a/vendor/nix/test/test_sched.rs b/vendor/nix/test/test_sched.rs deleted file mode 100644 index c52616b8b..000000000 --- a/vendor/nix/test/test_sched.rs +++ /dev/null @@ -1,39 +0,0 @@ -use nix::sched::{sched_getaffinity, sched_getcpu, sched_setaffinity, CpuSet}; -use nix::unistd::Pid; - -#[test] -fn test_sched_affinity() { - // If pid is zero, then the mask of the calling process is returned. - let initial_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap(); - let mut at_least_one_cpu = false; - let mut last_valid_cpu = 0; - for field in 0..CpuSet::count() { - if initial_affinity.is_set(field).unwrap() { - at_least_one_cpu = true; - last_valid_cpu = field; - } - } - assert!(at_least_one_cpu); - - // Now restrict the running CPU - let mut new_affinity = CpuSet::new(); - new_affinity.set(last_valid_cpu).unwrap(); - sched_setaffinity(Pid::from_raw(0), &new_affinity).unwrap(); - - // And now re-check the affinity which should be only the one we set. - let updated_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap(); - for field in 0..CpuSet::count() { - // Should be set only for the CPU we set previously - assert_eq!( - updated_affinity.is_set(field).unwrap(), - field == last_valid_cpu - ) - } - - // Now check that we're also currently running on the CPU in question. - let cur_cpu = sched_getcpu().unwrap(); - assert_eq!(cur_cpu, last_valid_cpu); - - // Finally, reset the initial CPU set - sched_setaffinity(Pid::from_raw(0), &initial_affinity).unwrap(); -} diff --git a/vendor/nix/test/test_sendfile.rs b/vendor/nix/test/test_sendfile.rs deleted file mode 100644 index f73a3b56c..000000000 --- a/vendor/nix/test/test_sendfile.rs +++ /dev/null @@ -1,208 +0,0 @@ -use std::io::prelude::*; -use std::os::unix::prelude::*; - -use libc::off_t; -use nix::sys::sendfile::*; -use tempfile::tempfile; - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - use nix::unistd::{close, pipe, read}; - } else if #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos"))] { - use std::net::Shutdown; - use std::os::unix::net::UnixStream; - } -} - -#[cfg(any(target_os = "android", target_os = "linux"))] -#[test] -fn test_sendfile_linux() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let (rd, wr) = pipe().unwrap(); - let mut offset: off_t = 5; - let res = sendfile(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); - assert_eq!(b"f1", &buf[0..2]); - assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); -} - -#[cfg(target_os = "linux")] -#[test] -fn test_sendfile64_linux() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - - let (rd, wr) = pipe().unwrap(); - let mut offset: libc::off64_t = 5; - let res = sendfile64(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap(); - - assert_eq!(2, res); - - let mut buf = [0u8; 1024]; - assert_eq!(2, read(rd, &mut buf).unwrap()); - assert_eq!(b"f1", &buf[0..2]); - assert_eq!(7, offset); - - close(rd).unwrap(); - close(wr).unwrap(); -} - -#[cfg(target_os = "freebsd")] -#[test] -fn test_sendfile_freebsd() { - // Declare the content - let header_strings = - vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"]; - let body = "Xabcdef123456"; - let body_offset = 1; - let trailer_strings = vec!["\n", "Served by Make Believe\n"]; - - // Write the body to a file - let mut tmp = tempfile().unwrap(); - tmp.write_all(body.as_bytes()).unwrap(); - - // Prepare headers and trailers for sendfile - let headers: Vec<&[u8]> = - header_strings.iter().map(|s| s.as_bytes()).collect(); - let trailers: Vec<&[u8]> = - trailer_strings.iter().map(|s| s.as_bytes()).collect(); - - // Prepare socket pair - let (mut rd, wr) = UnixStream::pair().unwrap(); - - // Call the test method - let (res, bytes_written) = sendfile( - tmp.as_raw_fd(), - wr.as_raw_fd(), - body_offset as off_t, - None, - Some(headers.as_slice()), - Some(trailers.as_slice()), - SfFlags::empty(), - 0, - ); - assert!(res.is_ok()); - wr.shutdown(Shutdown::Both).unwrap(); - - // Prepare the expected result - let expected_string = header_strings.concat() - + &body[body_offset..] - + &trailer_strings.concat(); - - // Verify the message that was sent - assert_eq!(bytes_written as usize, expected_string.as_bytes().len()); - - let mut read_string = String::new(); - let bytes_read = rd.read_to_string(&mut read_string).unwrap(); - assert_eq!(bytes_written as usize, bytes_read); - assert_eq!(expected_string, read_string); -} - -#[cfg(target_os = "dragonfly")] -#[test] -fn test_sendfile_dragonfly() { - // Declare the content - let header_strings = - vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"]; - let body = "Xabcdef123456"; - let body_offset = 1; - let trailer_strings = vec!["\n", "Served by Make Believe\n"]; - - // Write the body to a file - let mut tmp = tempfile().unwrap(); - tmp.write_all(body.as_bytes()).unwrap(); - - // Prepare headers and trailers for sendfile - let headers: Vec<&[u8]> = - header_strings.iter().map(|s| s.as_bytes()).collect(); - let trailers: Vec<&[u8]> = - trailer_strings.iter().map(|s| s.as_bytes()).collect(); - - // Prepare socket pair - let (mut rd, wr) = UnixStream::pair().unwrap(); - - // Call the test method - let (res, bytes_written) = sendfile( - tmp.as_raw_fd(), - wr.as_raw_fd(), - body_offset as off_t, - None, - Some(headers.as_slice()), - Some(trailers.as_slice()), - ); - assert!(res.is_ok()); - wr.shutdown(Shutdown::Both).unwrap(); - - // Prepare the expected result - let expected_string = header_strings.concat() - + &body[body_offset..] - + &trailer_strings.concat(); - - // Verify the message that was sent - assert_eq!(bytes_written as usize, expected_string.as_bytes().len()); - - let mut read_string = String::new(); - let bytes_read = rd.read_to_string(&mut read_string).unwrap(); - assert_eq!(bytes_written as usize, bytes_read); - assert_eq!(expected_string, read_string); -} - -#[cfg(any(target_os = "ios", target_os = "macos"))] -#[test] -fn test_sendfile_darwin() { - // Declare the content - let header_strings = - vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"]; - let body = "Xabcdef123456"; - let body_offset = 1; - let trailer_strings = vec!["\n", "Served by Make Believe\n"]; - - // Write the body to a file - let mut tmp = tempfile().unwrap(); - tmp.write_all(body.as_bytes()).unwrap(); - - // Prepare headers and trailers for sendfile - let headers: Vec<&[u8]> = - header_strings.iter().map(|s| s.as_bytes()).collect(); - let trailers: Vec<&[u8]> = - trailer_strings.iter().map(|s| s.as_bytes()).collect(); - - // Prepare socket pair - let (mut rd, wr) = UnixStream::pair().unwrap(); - - // Call the test method - let (res, bytes_written) = sendfile( - tmp.as_raw_fd(), - wr.as_raw_fd(), - body_offset as off_t, - None, - Some(headers.as_slice()), - Some(trailers.as_slice()), - ); - assert!(res.is_ok()); - wr.shutdown(Shutdown::Both).unwrap(); - - // Prepare the expected result - let expected_string = header_strings.concat() - + &body[body_offset..] - + &trailer_strings.concat(); - - // Verify the message that was sent - assert_eq!(bytes_written as usize, expected_string.as_bytes().len()); - - let mut read_string = String::new(); - let bytes_read = rd.read_to_string(&mut read_string).unwrap(); - assert_eq!(bytes_written as usize, bytes_read); - assert_eq!(expected_string, read_string); -} diff --git a/vendor/nix/test/test_stat.rs b/vendor/nix/test/test_stat.rs deleted file mode 100644 index 55f15c077..000000000 --- a/vendor/nix/test/test_stat.rs +++ /dev/null @@ -1,421 +0,0 @@ -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use std::fs; -use std::fs::File; -#[cfg(not(target_os = "redox"))] -use std::os::unix::fs::symlink; -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use std::os::unix::fs::PermissionsExt; -use std::os::unix::prelude::AsRawFd; -#[cfg(not(target_os = "redox"))] -use std::path::Path; -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use std::time::{Duration, UNIX_EPOCH}; - -use libc::mode_t; -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -use libc::{S_IFLNK, S_IFMT}; - -#[cfg(not(target_os = "redox"))] -use nix::errno::Errno; -#[cfg(not(target_os = "redox"))] -use nix::fcntl; -#[cfg(any( - target_os = "linux", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd" -))] -use nix::sys::stat::lutimes; -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use nix::sys::stat::utimensat; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::FchmodatFlags; -use nix::sys::stat::Mode; -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use nix::sys::stat::UtimensatFlags; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::{self}; -use nix::sys::stat::{fchmod, stat}; -#[cfg(not(target_os = "redox"))] -use nix::sys::stat::{fchmodat, mkdirat}; -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use nix::sys::stat::{futimens, utimes}; - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -use nix::sys::stat::FileStat; - -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use nix::sys::time::{TimeSpec, TimeVal, TimeValLike}; -#[cfg(not(target_os = "redox"))] -use nix::unistd::chdir; - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -use nix::Result; - -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn assert_stat_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 - assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent - assert!(stats.st_mode > 0); // must be positive integer - assert_eq!(stats.st_nlink, 1); // there links created, must be 1 - assert_eq!(stats.st_size, 0); // size is 0 because we did not write anything to the file - assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent - assert!(stats.st_blocks <= 16); // Up to 16 blocks can be allocated for a blank file -} - -#[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))] -#[allow(clippy::absurd_extreme_comparisons)] // Not absurd on all OSes -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 - assert!(stats.st_ino > 0); // inode is positive integer, exact number machine dependent - assert!(stats.st_mode > 0); // must be positive integer - - // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t - // (u16 on Android), and that will be a compile error. - // On other platforms they are the same (either both are u16 or u32). - assert_eq!( - (stats.st_mode as usize) & (S_IFMT as usize), - S_IFLNK as usize - ); // should be a link - assert_eq!(stats.st_nlink, 1); // there links created, must be 1 - assert!(stats.st_size > 0); // size is > 0 because it points to another file - assert!(stats.st_blksize > 0); // must be positive integer, exact number machine dependent - - // st_blocks depends on whether the machine's file system uses fast - // or slow symlinks, so just make sure it's not negative - assert!(stats.st_blocks >= 0); -} - -#[test] -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn test_stat_and_fstat() { - use nix::sys::stat::fstat; - - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("foo.txt"); - let file = File::create(&filename).unwrap(); - - let stat_result = stat(&filename); - assert_stat_results(stat_result); - - let fstat_result = fstat(file.as_raw_fd()); - assert_stat_results(fstat_result); -} - -#[test] -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn test_fstatat() { - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("foo.txt"); - File::create(&filename).unwrap(); - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()); - - let result = - stat::fstatat(dirfd.unwrap(), &filename, fcntl::AtFlags::empty()); - assert_stat_results(result); -} - -#[test] -#[cfg(not(any(target_os = "netbsd", target_os = "redox")))] -fn test_stat_fstat_lstat() { - use nix::sys::stat::{fstat, lstat}; - - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("bar.txt"); - let linkname = tempdir.path().join("barlink"); - - File::create(&filename).unwrap(); - symlink("bar.txt", &linkname).unwrap(); - let link = File::open(&linkname).unwrap(); - - // should be the same result as calling stat, - // since it's a regular file - let stat_result = stat(&filename); - assert_stat_results(stat_result); - - let lstat_result = lstat(&linkname); - assert_lstat_results(lstat_result); - - let fstat_result = fstat(link.as_raw_fd()); - assert_stat_results(fstat_result); -} - -#[test] -fn test_fchmod() { - let tempdir = tempfile::tempdir().unwrap(); - let filename = tempdir.path().join("foo.txt"); - let file = File::create(&filename).unwrap(); - - let mut mode1 = Mode::empty(); - mode1.insert(Mode::S_IRUSR); - mode1.insert(Mode::S_IWUSR); - fchmod(file.as_raw_fd(), mode1).unwrap(); - - let file_stat1 = stat(&filename).unwrap(); - 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 as mode_t & 0o7777, mode2.bits()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_fchmodat() { - let _dr = crate::DirRestore::new(); - let tempdir = tempfile::tempdir().unwrap(); - let filename = "foo.txt"; - let fullpath = tempdir.path().join(filename); - File::create(&fullpath).unwrap(); - - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - - let mut mode1 = Mode::empty(); - mode1.insert(Mode::S_IRUSR); - mode1.insert(Mode::S_IWUSR); - fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink) - .unwrap(); - - let file_stat1 = stat(&fullpath).unwrap(); - assert_eq!(file_stat1.st_mode as mode_t & 0o7777, mode1.bits()); - - chdir(tempdir.path()).unwrap(); - - let mut mode2 = Mode::empty(); - mode2.insert(Mode::S_IROTH); - fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap(); - - let file_stat2 = stat(&fullpath).unwrap(); - 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. -/// -/// The atime and mtime are expressed with a resolution of seconds because some file systems -/// (like macOS's HFS+) do not have higher granularity. -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn assert_times_eq( - exp_atime_sec: u64, - exp_mtime_sec: u64, - attr: &fs::Metadata, -) { - assert_eq!( - Duration::new(exp_atime_sec, 0), - attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap() - ); - assert_eq!( - Duration::new(exp_mtime_sec, 0), - attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap() - ); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_utimes() { - let tempdir = tempfile::tempdir().unwrap(); - let fullpath = tempdir.path().join("file"); - drop(File::create(&fullpath).unwrap()); - - utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550)) - .unwrap(); - assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap()); -} - -#[test] -#[cfg(any( - target_os = "linux", - target_os = "ios", - target_os = "macos", - target_os = "freebsd", - target_os = "netbsd" -))] -fn test_lutimes() { - let tempdir = tempfile::tempdir().unwrap(); - let target = tempdir.path().join("target"); - let fullpath = tempdir.path().join("symlink"); - drop(File::create(&target).unwrap()); - symlink(&target, &fullpath).unwrap(); - - let exp_target_metadata = fs::symlink_metadata(&target).unwrap(); - lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230)) - .unwrap(); - assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap()); - - let target_metadata = fs::symlink_metadata(&target).unwrap(); - assert_eq!( - exp_target_metadata.accessed().unwrap(), - target_metadata.accessed().unwrap(), - "atime of symlink target was unexpectedly modified" - ); - assert_eq!( - exp_target_metadata.modified().unwrap(), - target_metadata.modified().unwrap(), - "mtime of symlink target was unexpectedly modified" - ); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_futimens() { - let tempdir = tempfile::tempdir().unwrap(); - let fullpath = tempdir.path().join("file"); - drop(File::create(&fullpath).unwrap()); - - let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - - futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap(); - assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap()); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_utimensat() { - let _dr = crate::DirRestore::new(); - let tempdir = tempfile::tempdir().unwrap(); - let filename = "foo.txt"; - let fullpath = tempdir.path().join(filename); - drop(File::create(&fullpath).unwrap()); - - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - - utimensat( - Some(dirfd), - filename, - &TimeSpec::seconds(12345), - &TimeSpec::seconds(678), - UtimensatFlags::FollowSymlink, - ) - .unwrap(); - assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap()); - - chdir(tempdir.path()).unwrap(); - - utimensat( - None, - filename, - &TimeSpec::seconds(500), - &TimeSpec::seconds(800), - UtimensatFlags::FollowSymlink, - ) - .unwrap(); - assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkdirat_success_path() { - let tempdir = tempfile::tempdir().unwrap(); - let filename = "example_subdir"; - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed"); - assert!(Path::exists(&tempdir.path().join(filename))); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_mkdirat_success_mode() { - let expected_bits = - stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits(); - let tempdir = tempfile::tempdir().unwrap(); - let filename = "example_subdir"; - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed"); - let permissions = fs::metadata(tempdir.path().join(filename)) - .unwrap() - .permissions(); - let mode = permissions.mode(); - assert_eq!(mode as mode_t, expected_bits) -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkdirat_fail() { - let tempdir = tempfile::tempdir().unwrap(); - let not_dir_filename = "example_not_dir"; - let filename = "example_subdir_dir"; - let dirfd = fcntl::open( - &tempdir.path().join(not_dir_filename), - fcntl::OFlag::O_CREAT, - stat::Mode::empty(), - ) - .unwrap(); - let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err(); - assert_eq!(result, Errno::ENOTDIR); -} - -#[test] -#[cfg(not(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "ios", - target_os = "macos", - target_os = "haiku", - target_os = "redox" -)))] -fn test_mknod() { - use stat::{lstat, mknod, SFlag}; - - let file_name = "test_file"; - let tempdir = tempfile::tempdir().unwrap(); - let target = tempdir.path().join(file_name); - mknod(&target, SFlag::S_IFREG, Mode::S_IRWXU, 0).unwrap(); - let mode = lstat(&target).unwrap().st_mode as mode_t; - assert_eq!(mode & libc::S_IFREG, libc::S_IFREG); - assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU); -} - -#[test] -#[cfg(not(any( - target_os = "dragonfly", - target_os = "freebsd", - target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "haiku", - target_os = "redox" -)))] -fn test_mknodat() { - use fcntl::{AtFlags, OFlag}; - use nix::dir::Dir; - use stat::{fstatat, mknodat, SFlag}; - - let file_name = "test_file"; - let tempdir = tempfile::tempdir().unwrap(); - let target_dir = - Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap(); - mknodat( - target_dir.as_raw_fd(), - file_name, - SFlag::S_IFREG, - Mode::S_IRWXU, - 0, - ) - .unwrap(); - let mode = fstatat( - target_dir.as_raw_fd(), - file_name, - AtFlags::AT_SYMLINK_NOFOLLOW, - ) - .unwrap() - .st_mode as mode_t; - assert_eq!(mode & libc::S_IFREG, libc::S_IFREG); - assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU); -} diff --git a/vendor/nix/test/test_time.rs b/vendor/nix/test/test_time.rs deleted file mode 100644 index 5f76e61a2..000000000 --- a/vendor/nix/test/test_time.rs +++ /dev/null @@ -1,59 +0,0 @@ -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -use nix::time::clock_getcpuclockid; -use nix::time::{clock_gettime, ClockId}; - -#[cfg(not(target_os = "redox"))] -#[test] -pub fn test_clock_getres() { - nix::time::clock_getres(ClockId::CLOCK_REALTIME).expect("assertion failed"); -} - -#[test] -pub fn test_clock_gettime() { - clock_gettime(ClockId::CLOCK_REALTIME).expect("assertion failed"); -} - -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -#[test] -pub fn test_clock_getcpuclockid() { - let clock_id = clock_getcpuclockid(nix::unistd::Pid::this()).unwrap(); - clock_gettime(clock_id).unwrap(); -} - -#[cfg(not(target_os = "redox"))] -#[test] -pub fn test_clock_id_res() { - ClockId::CLOCK_REALTIME.res().unwrap(); -} - -#[test] -pub fn test_clock_id_now() { - ClockId::CLOCK_REALTIME.now().unwrap(); -} - -#[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "linux", - target_os = "android", - target_os = "emscripten", -))] -#[test] -pub fn test_clock_id_pid_cpu_clock_id() { - ClockId::pid_cpu_clock_id(nix::unistd::Pid::this()) - .map(ClockId::now) - .unwrap() - .unwrap(); -} diff --git a/vendor/nix/test/test_timer.rs b/vendor/nix/test/test_timer.rs deleted file mode 100644 index ffd146867..000000000 --- a/vendor/nix/test/test_timer.rs +++ /dev/null @@ -1,102 +0,0 @@ -use nix::sys::signal::{ - sigaction, SaFlags, SigAction, SigEvent, SigHandler, SigSet, SigevNotify, - Signal, -}; -use nix::sys::timer::{Expiration, Timer, TimerSetTimeFlags}; -use nix::time::ClockId; -use std::convert::TryFrom; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::thread; -use std::time::{Duration, Instant}; - -const SIG: Signal = Signal::SIGALRM; -static ALARM_CALLED: AtomicBool = AtomicBool::new(false); - -pub extern "C" fn handle_sigalarm(raw_signal: libc::c_int) { - let signal = Signal::try_from(raw_signal).unwrap(); - if signal == SIG { - ALARM_CALLED.store(true, Ordering::Release); - } -} - -#[test] -fn alarm_fires() { - // Avoid interfering with other signal using tests by taking a mutex shared - // among other tests in this crate. - let _m = crate::SIGNAL_MTX.lock(); - const TIMER_PERIOD: Duration = Duration::from_millis(100); - - // - // Setup - // - - // Create a handler for the test signal, `SIG`. The handler is responsible - // for flipping `ALARM_CALLED`. - let handler = SigHandler::Handler(handle_sigalarm); - let signal_action = - SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty()); - let old_handler = unsafe { - sigaction(SIG, &signal_action) - .expect("unable to set signal handler for alarm") - }; - - // Create the timer. We use the monotonic clock here, though any would do - // really. The timer is set to fire every 250 milliseconds with no delay for - // the initial firing. - let clockid = ClockId::CLOCK_MONOTONIC; - let sigevent = SigEvent::new(SigevNotify::SigevSignal { - signal: SIG, - si_value: 0, - }); - let mut timer = - Timer::new(clockid, sigevent).expect("failed to create timer"); - let expiration = Expiration::Interval(TIMER_PERIOD.into()); - let flags = TimerSetTimeFlags::empty(); - timer.set(expiration, flags).expect("could not set timer"); - - // - // Test - // - - // Determine that there's still an expiration tracked by the - // timer. Depending on when this runs either an `Expiration::Interval` or - // `Expiration::IntervalDelayed` will be present. That is, if the timer has - // not fired yet we'll get our original `expiration`, else the one that - // represents a delay to the next expiration. We're only interested in the - // timer still being extant. - match timer.get() { - Ok(Some(exp)) => assert!(matches!( - exp, - Expiration::Interval(..) | Expiration::IntervalDelayed(..) - )), - _ => panic!("timer lost its expiration"), - } - - // Wait for 2 firings of the alarm before checking that it has fired and - // been handled at least the once. If we wait for 3 seconds and the handler - // is never called something has gone sideways and the test fails. - let starttime = Instant::now(); - loop { - thread::sleep(2 * TIMER_PERIOD); - if ALARM_CALLED.load(Ordering::Acquire) { - break; - } - if starttime.elapsed() > Duration::from_secs(3) { - panic!("Timeout waiting for SIGALRM"); - } - } - - // Cleanup: - // 1) deregister the OS's timer. - // 2) Wait for a full timer period, since POSIX does not require that - // disabling the timer will clear pending signals, and on NetBSD at least - // it does not. - // 2) Replace the old signal handler now that we've completed the test. If - // the test fails this process panics, so the fact we might not get here - // is okay. - drop(timer); - thread::sleep(TIMER_PERIOD); - unsafe { - sigaction(SIG, &old_handler).expect("unable to reset signal handler"); - } -} diff --git a/vendor/nix/test/test_unistd.rs b/vendor/nix/test/test_unistd.rs deleted file mode 100644 index 9e20f977e..000000000 --- a/vendor/nix/test/test_unistd.rs +++ /dev/null @@ -1,1407 +0,0 @@ -use libc::{_exit, mode_t, off_t}; -use nix::errno::Errno; -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -use nix::fcntl::readlink; -use nix::fcntl::OFlag; -#[cfg(not(target_os = "redox"))] -use nix::fcntl::{self, open}; -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt}; -#[cfg(not(target_os = "redox"))] -use nix::sys::signal::{ - sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, -}; -use nix::sys::stat::{self, Mode, SFlag}; -use nix::sys::wait::*; -use nix::unistd::ForkResult::*; -use nix::unistd::*; -use std::env; -#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] -use std::ffi::CString; -#[cfg(not(target_os = "redox"))] -use std::fs::DirBuilder; -use std::fs::{self, File}; -use std::io::Write; -use std::os::unix::prelude::*; -#[cfg(not(any( - target_os = "fuchsia", - target_os = "redox", - target_os = "haiku" -)))] -use std::path::Path; -use tempfile::{tempdir, tempfile}; - -use crate::*; - -#[test] -#[cfg(not(any(target_os = "netbsd")))] -fn test_fork_and_waitpid() { - let _m = crate::FORK_MTX.lock(); - - // Safe: Child only calls `_exit`, which is signal-safe - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => unsafe { _exit(0) }, - Parent { child } => { - // assert that child was created and pid > 0 - let child_raw: ::libc::pid_t = child.into(); - assert!(child_raw > 0); - let wait_status = waitpid(child, None); - match wait_status { - // assert that waitpid returned correct status and the pid is the one of the child - Ok(WaitStatus::Exited(pid_t, _)) => assert_eq!(pid_t, child), - - // panic, must never happen - s @ Ok(_) => { - panic!("Child exited {:?}, should never happen", s) - } - - // panic, waitpid should never fail - Err(s) => panic!("Error: waitpid returned Err({:?}", s), - } - } - } -} - -#[test] -fn test_wait() { - // Grab FORK_MTX so wait doesn't reap a different test's child process - let _m = crate::FORK_MTX.lock(); - - // Safe: Child only calls `_exit`, which is signal-safe - match unsafe { fork() }.expect("Error: Fork Failed") { - Child => unsafe { _exit(0) }, - Parent { child } => { - let wait_status = wait(); - - // just assert that (any) one child returns with WaitStatus::Exited - assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0))); - } - } -} - -#[test] -fn test_mkstemp() { - let mut path = env::temp_dir(); - path.push("nix_tempfile.XXXXXX"); - - let result = mkstemp(&path); - match result { - Ok((fd, path)) => { - close(fd).unwrap(); - unlink(path.as_path()).unwrap(); - } - Err(e) => panic!("mkstemp failed: {}", e), - } -} - -#[test] -fn test_mkstemp_directory() { - // mkstemp should fail if a directory is given - mkstemp(&env::temp_dir()).expect_err("assertion failed"); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkfifo() { - let tempdir = tempdir().unwrap(); - let mkfifo_fifo = tempdir.path().join("mkfifo_fifo"); - - mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap(); - - let stats = stat::stat(&mkfifo_fifo).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode as mode_t); - assert_eq!(typ, SFlag::S_IFIFO); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_mkfifo_directory() { - // mkfifo should fail if a directory is given - mkfifo(&env::temp_dir(), Mode::S_IRUSR).expect_err("assertion failed"); -} - -#[test] -#[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "redox", - target_os = "haiku" -)))] -fn test_mkfifoat_none() { - let _m = crate::CWD_LOCK.read(); - - let tempdir = tempdir().unwrap(); - let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo"); - - mkfifoat(None, &mkfifoat_fifo, Mode::S_IRUSR).unwrap(); - - let stats = stat::stat(&mkfifoat_fifo).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode); - assert_eq!(typ, SFlag::S_IFIFO); -} - -#[test] -#[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "redox", - target_os = "haiku" -)))] -fn test_mkfifoat() { - use nix::fcntl; - - let tempdir = tempdir().unwrap(); - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let mkfifoat_name = "mkfifoat_name"; - - mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap(); - - let stats = - stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap(); - let typ = stat::SFlag::from_bits_truncate(stats.st_mode); - assert_eq!(typ, SFlag::S_IFIFO); -} - -#[test] -#[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "redox", - target_os = "haiku" -)))] -fn test_mkfifoat_directory_none() { - let _m = crate::CWD_LOCK.read(); - - // mkfifoat should fail if a directory is given - mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR) - .expect_err("assertion failed"); -} - -#[test] -#[cfg(not(any( - target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "redox", - target_os = "haiku" -)))] -fn test_mkfifoat_directory() { - // mkfifoat should fail if a directory is given - let tempdir = tempdir().unwrap(); - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let mkfifoat_dir = "mkfifoat_dir"; - stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap(); - - mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR) - .expect_err("assertion failed"); -} - -#[test] -fn test_getpid() { - let pid: ::libc::pid_t = getpid().into(); - let ppid: ::libc::pid_t = getppid().into(); - assert!(pid > 0); - assert!(ppid > 0); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_getsid() { - let none_sid: ::libc::pid_t = getsid(None).unwrap().into(); - let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into(); - assert!(none_sid > 0); - assert_eq!(none_sid, pid_sid); -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -mod linux_android { - use nix::unistd::gettid; - - #[test] - fn test_gettid() { - let tid: ::libc::pid_t = gettid().into(); - assert!(tid > 0); - } -} - -#[test] -// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms -#[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -fn test_setgroups() { - // Skip this test when not run as root as `setgroups()` requires root. - skip_if_not_root!("test_setgroups"); - - let _m = crate::GROUPS_MTX.lock(); - - // Save the existing groups - let old_groups = getgroups().unwrap(); - - // Set some new made up groups - let groups = [Gid::from_raw(123), Gid::from_raw(456)]; - setgroups(&groups).unwrap(); - - let new_groups = getgroups().unwrap(); - assert_eq!(new_groups, groups); - - // Revert back to the old groups - setgroups(&old_groups).unwrap(); -} - -#[test] -// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms -#[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku", - target_os = "illumos" -)))] -fn test_initgroups() { - // Skip this test when not run as root as `initgroups()` and `setgroups()` - // require root. - skip_if_not_root!("test_initgroups"); - - let _m = crate::GROUPS_MTX.lock(); - - // Save the existing groups - let old_groups = getgroups().unwrap(); - - // It doesn't matter if the root user is not called "root" or if a user - // called "root" doesn't exist. We are just checking that the extra, - // made-up group, `123`, is set. - // FIXME: Test the other half of initgroups' functionality: whether the - // groups that the user belongs to are also set. - let user = CString::new("root").unwrap(); - let group = Gid::from_raw(123); - let group_list = getgrouplist(&user, group).unwrap(); - assert!(group_list.contains(&group)); - - initgroups(&user, group).unwrap(); - - let new_groups = getgroups().unwrap(); - assert_eq!(new_groups, group_list); - - // Revert back to the old groups - setgroups(&old_groups).unwrap(); -} - -#[cfg(not(any(target_os = "fuchsia", target_os = "redox")))] -macro_rules! execve_test_factory ( - ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => ( - - #[cfg(test)] - mod $test_name { - use std::ffi::CStr; - use super::*; - - const EMPTY: &'static [u8] = b"\0"; - const DASH_C: &'static [u8] = b"-c\0"; - const BIGARG: &'static [u8] = b"echo nix!!! && echo foo=$foo && echo baz=$baz\0"; - const FOO: &'static [u8] = b"foo=bar\0"; - const BAZ: &'static [u8] = b"baz=quux\0"; - - fn syscall_cstr_ref() -> Result<std::convert::Infallible, nix::Error> { - $syscall( - $exe, - $(CString::new($pathname).unwrap().as_c_str(), )* - &[CStr::from_bytes_with_nul(EMPTY).unwrap(), - CStr::from_bytes_with_nul(DASH_C).unwrap(), - CStr::from_bytes_with_nul(BIGARG).unwrap()], - &[CStr::from_bytes_with_nul(FOO).unwrap(), - CStr::from_bytes_with_nul(BAZ).unwrap()] - $(, $flags)*) - } - - fn syscall_cstring() -> Result<std::convert::Infallible, nix::Error> { - $syscall( - $exe, - $(CString::new($pathname).unwrap().as_c_str(), )* - &[CString::from(CStr::from_bytes_with_nul(EMPTY).unwrap()), - CString::from(CStr::from_bytes_with_nul(DASH_C).unwrap()), - CString::from(CStr::from_bytes_with_nul(BIGARG).unwrap())], - &[CString::from(CStr::from_bytes_with_nul(FOO).unwrap()), - CString::from(CStr::from_bytes_with_nul(BAZ).unwrap())] - $(, $flags)*) - } - - fn common_test(syscall: fn() -> Result<std::convert::Infallible, nix::Error>) { - if "execveat" == stringify!($syscall) { - // Though undocumented, Docker's default seccomp profile seems to - // block this syscall. https://github.com/nix-rust/nix/issues/1122 - skip_if_seccomp!($test_name); - } - - let m = crate::FORK_MTX.lock(); - // The `exec`d process will write to `writer`, and we'll read that - // data from `reader`. - let (reader, writer) = pipe().unwrap(); - - // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function. - // NOTE: Technically, this makes the macro unsafe to use because you could pass anything. - // The tests make sure not to do that, though. - match unsafe{fork()}.unwrap() { - Child => { - // Make `writer` be the stdout of the new process. - dup2(writer, 1).unwrap(); - let r = syscall(); - let _ = std::io::stderr() - .write_all(format!("{:?}", r).as_bytes()); - // Should only get here in event of error - unsafe{ _exit(1) }; - }, - Parent { child } => { - // Wait for the child to exit. - let ws = waitpid(child, None); - drop(m); - assert_eq!(ws, Ok(WaitStatus::Exited(child, 0))); - // Read 1024 bytes. - let mut buf = [0u8; 1024]; - read(reader, &mut buf).unwrap(); - // It should contain the things we printed using `/bin/sh`. - let string = String::from_utf8_lossy(&buf); - assert!(string.contains("nix!!!")); - assert!(string.contains("foo=bar")); - assert!(string.contains("baz=quux")); - } - } - } - - // These tests frequently fail on musl, probably due to - // https://github.com/nix-rust/nix/issues/555 - #[cfg_attr(target_env = "musl", ignore)] - #[test] - fn test_cstr_ref() { - common_test(syscall_cstr_ref); - } - - // These tests frequently fail on musl, probably due to - // https://github.com/nix-rust/nix/issues/555 - #[cfg_attr(target_env = "musl", ignore)] - #[test] - fn test_cstring() { - common_test(syscall_cstring); - } - } - - ) -); - -cfg_if! { - if #[cfg(target_os = "android")] { - execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str()); - execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd()); - } else if #[cfg(any(target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux"))] { - // These tests frequently fail on musl, probably due to - // https://github.com/nix-rust/nix/issues/555 - execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str()); - execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd()); - } else if #[cfg(any(target_os = "illumos", - target_os = "ios", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] { - execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str()); - // No fexecve() on ios, macos, NetBSD, OpenBSD. - } -} - -#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))] -execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap()); - -cfg_if! { - if #[cfg(target_os = "android")] { - use nix::fcntl::AtFlags; - execve_test_factory!(test_execveat_empty, execveat, - File::open("/system/bin/sh").unwrap().into_raw_fd(), - "", AtFlags::AT_EMPTY_PATH); - execve_test_factory!(test_execveat_relative, execveat, - File::open("/system/bin/").unwrap().into_raw_fd(), - "./sh", AtFlags::empty()); - execve_test_factory!(test_execveat_absolute, execveat, - File::open("/").unwrap().into_raw_fd(), - "/system/bin/sh", AtFlags::empty()); - } else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] { - use nix::fcntl::AtFlags; - execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(), - "", AtFlags::AT_EMPTY_PATH); - execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap().into_raw_fd(), - "./sh", AtFlags::empty()); - execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(), - "/bin/sh", AtFlags::empty()); - } -} - -#[test] -#[cfg(not(target_os = "fuchsia"))] -fn test_fchdir() { - // fchdir changes the process's cwd - let _dr = crate::DirRestore::new(); - - let tmpdir = tempdir().unwrap(); - let tmpdir_path = tmpdir.path().canonicalize().unwrap(); - let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd(); - - fchdir(tmpdir_fd).expect("assertion failed"); - assert_eq!(getcwd().unwrap(), tmpdir_path); - - close(tmpdir_fd).expect("assertion failed"); -} - -#[test] -fn test_getcwd() { - // chdir changes the process's cwd - let _dr = crate::DirRestore::new(); - - let tmpdir = tempdir().unwrap(); - let tmpdir_path = tmpdir.path().canonicalize().unwrap(); - chdir(&tmpdir_path).expect("assertion failed"); - assert_eq!(getcwd().unwrap(), tmpdir_path); - - // make path 500 chars longer so that buffer doubling in getcwd - // kicks in. Note: One path cannot be longer than 255 bytes - // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually - // 4096 on linux, 1024 on macos) - let mut inner_tmp_dir = tmpdir_path; - for _ in 0..5 { - let newdir = "a".repeat(100); - inner_tmp_dir.push(newdir); - mkdir(inner_tmp_dir.as_path(), Mode::S_IRWXU) - .expect("assertion failed"); - } - chdir(inner_tmp_dir.as_path()).expect("assertion failed"); - assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path()); -} - -#[test] -fn test_chown() { - // Testing for anything other than our own UID/GID is hard. - let uid = Some(getuid()); - let gid = Some(getgid()); - - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - { - File::create(&path).unwrap(); - } - - chown(&path, uid, gid).unwrap(); - chown(&path, uid, None).unwrap(); - chown(&path, None, gid).unwrap(); - - fs::remove_file(&path).unwrap(); - chown(&path, uid, gid).unwrap_err(); -} - -#[test] -fn test_fchown() { - // Testing for anything other than our own UID/GID is hard. - let uid = Some(getuid()); - let gid = Some(getgid()); - - let path = tempfile().unwrap(); - let fd = path.as_raw_fd(); - - fchown(fd, uid, gid).unwrap(); - fchown(fd, uid, None).unwrap(); - fchown(fd, None, gid).unwrap(); - fchown(999999999, uid, gid).unwrap_err(); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_fchownat() { - let _dr = crate::DirRestore::new(); - // Testing for anything other than our own UID/GID is hard. - let uid = Some(getuid()); - let gid = Some(getgid()); - - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - { - File::create(&path).unwrap(); - } - - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - - fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink) - .unwrap(); - - chdir(tempdir.path()).unwrap(); - fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap(); - - fs::remove_file(&path).unwrap(); - fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err(); -} - -#[test] -fn test_lseek() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - let tmpfd = tmp.into_raw_fd(); - - let offset: off_t = 5; - lseek(tmpfd, offset, Whence::SeekSet).unwrap(); - - let mut buf = [0u8; 7]; - crate::read_exact(tmpfd, &mut buf); - assert_eq!(b"f123456", &buf); - - close(tmpfd).unwrap(); -} - -#[cfg(any(target_os = "linux", target_os = "android"))] -#[test] -fn test_lseek64() { - const CONTENTS: &[u8] = b"abcdef123456"; - let mut tmp = tempfile().unwrap(); - tmp.write_all(CONTENTS).unwrap(); - let tmpfd = tmp.into_raw_fd(); - - lseek64(tmpfd, 5, Whence::SeekSet).unwrap(); - - let mut buf = [0u8; 7]; - crate::read_exact(tmpfd, &mut buf); - assert_eq!(b"f123456", &buf); - - close(tmpfd).unwrap(); -} - -cfg_if! { - if #[cfg(any(target_os = "android", target_os = "linux"))] { - macro_rules! require_acct{ - () => { - require_capability!("test_acct", CAP_SYS_PACCT); - } - } - } else if #[cfg(target_os = "freebsd")] { - macro_rules! require_acct{ - () => { - skip_if_not_root!("test_acct"); - skip_if_jailed!("test_acct"); - } - } - } else if #[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "haiku")))] { - macro_rules! require_acct{ - () => { - skip_if_not_root!("test_acct"); - } - } - } -} - -#[test] -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -fn test_acct() { - use std::process::Command; - use std::{thread, time}; - use tempfile::NamedTempFile; - - let _m = crate::FORK_MTX.lock(); - require_acct!(); - - let file = NamedTempFile::new().unwrap(); - let path = file.path().to_str().unwrap(); - - acct::enable(path).unwrap(); - - loop { - Command::new("echo").arg("Hello world").output().unwrap(); - let len = fs::metadata(path).unwrap().len(); - if len > 0 { - break; - } - thread::sleep(time::Duration::from_millis(10)); - } - acct::disable().unwrap(); -} - -#[test] -fn test_fpathconf_limited() { - let f = tempfile().unwrap(); - // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test - let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX); - assert!( - path_max - .expect("fpathconf failed") - .expect("PATH_MAX is unlimited") - > 0 - ); -} - -#[test] -fn test_pathconf_limited() { - // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test - let path_max = pathconf("/", PathconfVar::PATH_MAX); - assert!( - path_max - .expect("pathconf failed") - .expect("PATH_MAX is unlimited") - > 0 - ); -} - -#[test] -fn test_sysconf_limited() { - // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test - let open_max = sysconf(SysconfVar::OPEN_MAX); - assert!( - open_max - .expect("sysconf failed") - .expect("OPEN_MAX is unlimited") - > 0 - ); -} - -#[cfg(target_os = "freebsd")] -#[test] -fn test_sysconf_unsupported() { - // I know of no sysconf variables that are unsupported everywhere, but - // _XOPEN_CRYPT is unsupported on FreeBSD 11.0, which is one of the platforms - // we test. - let open_max = sysconf(SysconfVar::_XOPEN_CRYPT); - assert!(open_max.expect("sysconf failed").is_none()) -} - -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "openbsd" -))] -#[test] -fn test_getresuid() { - let resuids = getresuid().unwrap(); - assert_ne!(resuids.real.as_raw(), libc::uid_t::MAX); - assert_ne!(resuids.effective.as_raw(), libc::uid_t::MAX); - assert_ne!(resuids.saved.as_raw(), libc::uid_t::MAX); -} - -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "linux", - target_os = "openbsd" -))] -#[test] -fn test_getresgid() { - let resgids = getresgid().unwrap(); - assert_ne!(resgids.real.as_raw(), libc::gid_t::MAX); - assert_ne!(resgids.effective.as_raw(), libc::gid_t::MAX); - assert_ne!(resgids.saved.as_raw(), libc::gid_t::MAX); -} - -// Test that we can create a pair of pipes. No need to verify that they pass -// data; that's the domain of the OS, not nix. -#[test] -fn test_pipe() { - let (fd0, fd1) = pipe().unwrap(); - 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 as mode_t, - ); - assert_eq!(m1, SFlag::S_IFIFO); -} - -// pipe2(2) is the same as pipe(2), except it allows setting some flags. Check -// that we can set a flag. -#[cfg(any( - target_os = "android", - target_os = "dragonfly", - target_os = "emscripten", - target_os = "freebsd", - target_os = "illumos", - target_os = "linux", - target_os = "netbsd", - target_os = "openbsd", - target_os = "redox", - target_os = "solaris" -))] -#[test] -fn test_pipe2() { - use nix::fcntl::{fcntl, FcntlArg, FdFlag}; - - let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap(); - let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap()); - assert!(f0.contains(FdFlag::FD_CLOEXEC)); - let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap()); - assert!(f1.contains(FdFlag::FD_CLOEXEC)); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -fn test_truncate() { - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - - { - let mut tmp = File::create(&path).unwrap(); - const CONTENTS: &[u8] = b"12345678"; - tmp.write_all(CONTENTS).unwrap(); - } - - truncate(&path, 4).unwrap(); - - let metadata = fs::metadata(&path).unwrap(); - assert_eq!(4, metadata.len()); -} - -#[test] -fn test_ftruncate() { - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("file"); - - let tmpfd = { - let mut tmp = File::create(&path).unwrap(); - const CONTENTS: &[u8] = b"12345678"; - tmp.write_all(CONTENTS).unwrap(); - tmp.into_raw_fd() - }; - - ftruncate(tmpfd, 2).unwrap(); - close(tmpfd).unwrap(); - - let metadata = fs::metadata(&path).unwrap(); - assert_eq!(2, metadata.len()); -} - -// Used in `test_alarm`. -#[cfg(not(target_os = "redox"))] -static mut ALARM_CALLED: bool = false; - -// Used in `test_alarm`. -#[cfg(not(target_os = "redox"))] -pub extern "C" fn alarm_signal_handler(raw_signal: libc::c_int) { - assert_eq!( - raw_signal, - libc::SIGALRM, - "unexpected signal: {}", - raw_signal - ); - unsafe { ALARM_CALLED = true }; -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_alarm() { - use std::{ - thread, - time::{Duration, Instant}, - }; - - // Maybe other tests that fork interfere with this one? - let _m = crate::SIGNAL_MTX.lock(); - - let handler = SigHandler::Handler(alarm_signal_handler); - let signal_action = - SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty()); - let old_handler = unsafe { - sigaction(Signal::SIGALRM, &signal_action) - .expect("unable to set signal handler for alarm") - }; - - // Set an alarm. - assert_eq!(alarm::set(60), None); - - // Overwriting an alarm should return the old alarm. - assert_eq!(alarm::set(1), Some(60)); - - // We should be woken up after 1 second by the alarm, so we'll sleep for 3 - // seconds to be sure. - let starttime = Instant::now(); - loop { - thread::sleep(Duration::from_millis(100)); - if unsafe { ALARM_CALLED } { - break; - } - if starttime.elapsed() > Duration::from_secs(3) { - panic!("Timeout waiting for SIGALRM"); - } - } - - // Reset the signal. - unsafe { - sigaction(Signal::SIGALRM, &old_handler) - .expect("unable to set signal handler for alarm"); - } -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_canceling_alarm() { - let _m = crate::SIGNAL_MTX.lock(); - - assert_eq!(alarm::cancel(), None); - - assert_eq!(alarm::set(60), None); - assert_eq!(alarm::cancel(), Some(60)); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_symlinkat() { - let _m = crate::CWD_LOCK.read(); - - let tempdir = tempdir().unwrap(); - - let target = tempdir.path().join("a"); - let linkpath = tempdir.path().join("b"); - symlinkat(&target, None, &linkpath).unwrap(); - assert_eq!( - readlink(&linkpath).unwrap().to_str().unwrap(), - target.to_str().unwrap() - ); - - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let target = "c"; - let linkpath = "d"; - symlinkat(target, Some(dirfd), linkpath).unwrap(); - assert_eq!( - readlink(&tempdir.path().join(linkpath)) - .unwrap() - .to_str() - .unwrap(), - target - ); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_linkat_file() { - let tempdir = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir.path().join(oldfilename); - - let newfilename = "bar.txt"; - let newfilepath = tempdir.path().join(newfilename); - - // Create file - File::create(oldfilepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - - // Attempt hard link file at relative path - linkat( - Some(dirfd), - oldfilename, - Some(dirfd), - newfilename, - LinkatFlags::SymlinkFollow, - ) - .unwrap(); - assert!(newfilepath.exists()); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_linkat_olddirfd_none() { - let _dr = crate::DirRestore::new(); - - let tempdir_oldfile = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir_oldfile.path().join(oldfilename); - - let tempdir_newfile = tempdir().unwrap(); - let newfilename = "bar.txt"; - let newfilepath = tempdir_newfile.path().join(newfilename); - - // Create file - 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(); - - // Attempt hard link file using curent working directory as relative path for old file path - chdir(tempdir_oldfile.path()).unwrap(); - linkat( - None, - oldfilename, - Some(dirfd), - newfilename, - LinkatFlags::SymlinkFollow, - ) - .unwrap(); - assert!(newfilepath.exists()); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_linkat_newdirfd_none() { - let _dr = crate::DirRestore::new(); - - let tempdir_oldfile = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir_oldfile.path().join(oldfilename); - - let tempdir_newfile = tempdir().unwrap(); - let newfilename = "bar.txt"; - let newfilepath = tempdir_newfile.path().join(newfilename); - - // Create file - 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(); - - // Attempt hard link file using current working directory as relative path for new file path - chdir(tempdir_newfile.path()).unwrap(); - linkat( - Some(dirfd), - oldfilename, - None, - newfilename, - LinkatFlags::SymlinkFollow, - ) - .unwrap(); - assert!(newfilepath.exists()); -} - -#[test] -#[cfg(not(any( - target_os = "ios", - target_os = "macos", - target_os = "redox", - target_os = "haiku" -)))] -fn test_linkat_no_follow_symlink() { - let _m = crate::CWD_LOCK.read(); - - let tempdir = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir.path().join(oldfilename); - - let symoldfilename = "symfoo.txt"; - let symoldfilepath = tempdir.path().join(symoldfilename); - - let newfilename = "nofollowsymbar.txt"; - let newfilepath = tempdir.path().join(newfilename); - - // Create file - File::create(&oldfilepath).unwrap(); - - // Create symlink to file - symlinkat(&oldfilepath, None, &symoldfilepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - - // Attempt link symlink of file at relative path - linkat( - Some(dirfd), - symoldfilename, - Some(dirfd), - newfilename, - LinkatFlags::NoSymlinkFollow, - ) - .unwrap(); - - // Assert newfile is actually a symlink to oldfile. - assert_eq!( - readlink(&newfilepath).unwrap().to_str().unwrap(), - oldfilepath.to_str().unwrap() - ); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "haiku")))] -fn test_linkat_follow_symlink() { - let _m = crate::CWD_LOCK.read(); - - let tempdir = tempdir().unwrap(); - let oldfilename = "foo.txt"; - let oldfilepath = tempdir.path().join(oldfilename); - - let symoldfilename = "symfoo.txt"; - let symoldfilepath = tempdir.path().join(symoldfilename); - - let newfilename = "nofollowsymbar.txt"; - let newfilepath = tempdir.path().join(newfilename); - - // Create file - File::create(&oldfilepath).unwrap(); - - // Create symlink to file - symlinkat(&oldfilepath, None, &symoldfilepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - - // Attempt link target of symlink of file at relative path - linkat( - Some(dirfd), - symoldfilename, - Some(dirfd), - newfilename, - LinkatFlags::SymlinkFollow, - ) - .unwrap(); - - let newfilestat = stat::stat(&newfilepath).unwrap(); - - // Check the file type of the new link - 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); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_unlinkat_dir_noremovedir() { - let tempdir = tempdir().unwrap(); - let dirname = "foo_dir"; - let dirpath = tempdir.path().join(dirname); - - // Create dir - 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(); - - // Attempt unlink dir at relative path without proper flag - let err_result = - unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err(); - assert!(err_result == Errno::EISDIR || err_result == Errno::EPERM); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_unlinkat_dir_removedir() { - let tempdir = tempdir().unwrap(); - let dirname = "foo_dir"; - let dirpath = tempdir.path().join(dirname); - - // Create dir - 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(); - - // Attempt unlink dir at relative path with proper flag - unlinkat(Some(dirfd), dirname, UnlinkatFlags::RemoveDir).unwrap(); - assert!(!dirpath.exists()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_unlinkat_file() { - let tempdir = tempdir().unwrap(); - let filename = "foo.txt"; - let filepath = tempdir.path().join(filename); - - // Create file - File::create(&filepath).unwrap(); - - // Get file descriptor for base directory - let dirfd = - fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()) - .unwrap(); - - // Attempt unlink file at relative path - unlinkat(Some(dirfd), filename, UnlinkatFlags::NoRemoveDir).unwrap(); - assert!(!filepath.exists()); -} - -#[test] -fn test_access_not_existing() { - let tempdir = tempdir().unwrap(); - let dir = tempdir.path().join("does_not_exist.txt"); - assert_eq!( - access(&dir, AccessFlags::F_OK).err().unwrap(), - Errno::ENOENT - ); -} - -#[test] -fn test_access_file_exists() { - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("does_exist.txt"); - let _file = File::create(path.clone()).unwrap(); - access(&path, AccessFlags::R_OK | AccessFlags::W_OK) - .expect("assertion failed"); -} - -//Clippy false positive https://github.com/rust-lang/rust-clippy/issues/9111 -#[allow(clippy::needless_borrow)] -#[cfg(not(target_os = "redox"))] -#[test] -fn test_user_into_passwd() { - // get the UID of the "nobody" user - #[cfg(not(target_os = "haiku"))] - let test_username = "nobody"; - // "nobody" unavailable on haiku - #[cfg(target_os = "haiku")] - let test_username = "user"; - - let nobody = User::from_name(test_username).unwrap().unwrap(); - let pwd: libc::passwd = nobody.into(); - let _: User = (&pwd).into(); -} - -/// Tests setting the filesystem UID with `setfsuid`. -#[cfg(any(target_os = "linux", target_os = "android"))] -#[test] -fn test_setfsuid() { - use std::os::unix::fs::PermissionsExt; - use std::{fs, io, thread}; - require_capability!("test_setfsuid", CAP_SETUID); - - // get the UID of the "nobody" user - let nobody = User::from_name("nobody").unwrap().unwrap(); - - // create a temporary file with permissions '-rw-r-----' - let file = tempfile::NamedTempFile::new_in("/var/tmp").unwrap(); - let temp_path = file.into_temp_path(); - let temp_path_2 = temp_path.to_path_buf(); - let mut permissions = fs::metadata(&temp_path).unwrap().permissions(); - permissions.set_mode(0o640); - - // spawn a new thread where to test setfsuid - thread::spawn(move || { - // set filesystem UID - let fuid = setfsuid(nobody.uid); - // trying to open the temporary file should fail with EACCES - let res = fs::File::open(&temp_path); - let err = res.expect_err("assertion failed"); - assert_eq!(err.kind(), io::ErrorKind::PermissionDenied); - - // assert fuid actually changes - let prev_fuid = setfsuid(Uid::from_raw(-1i32 as u32)); - assert_ne!(prev_fuid, fuid); - }) - .join() - .unwrap(); - - // open the temporary file with the current thread filesystem UID - fs::File::open(temp_path_2).unwrap(); -} - -#[test] -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -fn test_ttyname() { - let fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed"); - assert!(fd.as_raw_fd() > 0); - - // on linux, we can just call ttyname on the pty master directly, but - // apparently osx requires that ttyname is called on a slave pty (can't - // find this documented anywhere, but it seems to empirically be the case) - grantpt(&fd).expect("grantpt failed"); - unlockpt(&fd).expect("unlockpt failed"); - let sname = unsafe { ptsname(&fd) }.expect("ptsname failed"); - let fds = open(Path::new(&sname), OFlag::O_RDWR, stat::Mode::empty()) - .expect("open failed"); - assert!(fds > 0); - - let name = ttyname(fds).expect("ttyname failed"); - assert!(name.starts_with("/dev")); -} - -#[test] -#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] -fn test_ttyname_not_pty() { - let fd = File::open("/dev/zero").unwrap(); - assert!(fd.as_raw_fd() > 0); - assert_eq!(ttyname(fd.as_raw_fd()), Err(Errno::ENOTTY)); -} - -#[test] -#[cfg(not(any( - target_os = "redox", - target_os = "fuchsia", - target_os = "haiku" -)))] -fn test_ttyname_invalid_fd() { - assert_eq!(ttyname(-1), Err(Errno::EBADF)); -} - -#[test] -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly", -))] -fn test_getpeereid() { - use std::os::unix::net::UnixStream; - let (sock_a, sock_b) = UnixStream::pair().unwrap(); - - let (uid_a, gid_a) = getpeereid(sock_a.as_raw_fd()).unwrap(); - let (uid_b, gid_b) = getpeereid(sock_b.as_raw_fd()).unwrap(); - - let uid = geteuid(); - let gid = getegid(); - - assert_eq!(uid, uid_a); - assert_eq!(gid, gid_a); - assert_eq!(uid_a, uid_b); - assert_eq!(gid_a, gid_b); -} - -#[test] -#[cfg(any( - target_os = "macos", - target_os = "ios", - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly", -))] -fn test_getpeereid_invalid_fd() { - // getpeereid is not POSIX, so error codes are inconsistent between different Unices. - getpeereid(-1).expect_err("assertion failed"); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_faccessat_none_not_existing() { - use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); - let dir = tempdir.path().join("does_not_exist.txt"); - assert_eq!( - faccessat(None, &dir, AccessFlags::F_OK, AtFlags::empty()) - .err() - .unwrap(), - Errno::ENOENT - ); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_faccessat_not_existing() { - use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let not_exist_file = "does_not_exist.txt"; - assert_eq!( - faccessat( - Some(dirfd), - not_exist_file, - AccessFlags::F_OK, - AtFlags::empty(), - ) - .err() - .unwrap(), - Errno::ENOENT - ); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_faccessat_none_file_exists() { - use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); - let path = tempdir.path().join("does_exist.txt"); - let _file = File::create(path.clone()).unwrap(); - assert!(faccessat( - None, - &path, - AccessFlags::R_OK | AccessFlags::W_OK, - AtFlags::empty(), - ) - .is_ok()); -} - -#[test] -#[cfg(not(target_os = "redox"))] -fn test_faccessat_file_exists() { - use nix::fcntl::AtFlags; - let tempdir = tempfile::tempdir().unwrap(); - let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); - let exist_file = "does_exist.txt"; - let path = tempdir.path().join(exist_file); - let _file = File::create(path.clone()).unwrap(); - assert!(faccessat( - Some(dirfd), - &path, - AccessFlags::R_OK | AccessFlags::W_OK, - AtFlags::empty(), - ) - .is_ok()); -} - -#[test] -#[cfg(any( - all(target_os = "linux", not(target_env = "uclibc")), - target_os = "freebsd", - target_os = "dragonfly" -))] -fn test_eaccess_not_existing() { - let tempdir = tempdir().unwrap(); - let dir = tempdir.path().join("does_not_exist.txt"); - assert_eq!( - eaccess(&dir, AccessFlags::F_OK).err().unwrap(), - Errno::ENOENT - ); -} - -#[test] -#[cfg(any( - all(target_os = "linux", not(target_env = "uclibc")), - target_os = "freebsd", - target_os = "dragonfly" -))] -fn test_eaccess_file_exists() { - let tempdir = tempdir().unwrap(); - let path = tempdir.path().join("does_exist.txt"); - let _file = File::create(path.clone()).unwrap(); - eaccess(&path, AccessFlags::R_OK | AccessFlags::W_OK) - .expect("assertion failed"); -} |