summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nix/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:43:14 +0000
commit8dd16259287f58f9273002717ec4d27e97127719 (patch)
tree3863e62a53829a84037444beab3abd4ed9dfc7d0 /third_party/rust/nix/test
parentReleasing progress-linux version 126.0.1-1~progress7.99u1. (diff)
downloadfirefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz
firefox-8dd16259287f58f9273002717ec4d27e97127719.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/nix/test')
-rw-r--r--third_party/rust/nix/test/common/mod.rs10
-rw-r--r--third_party/rust/nix/test/sys/mod.rs54
-rw-r--r--third_party/rust/nix/test/sys/test_aio.rs66
-rw-r--r--third_party/rust/nix/test/sys/test_aio_drop.rs3
-rw-r--r--third_party/rust/nix/test/sys/test_event.rs41
-rw-r--r--third_party/rust/nix/test/sys/test_fanotify.rs149
-rw-r--r--third_party/rust/nix/test/sys/test_ioctl.rs33
-rw-r--r--third_party/rust/nix/test/sys/test_mman.rs55
-rw-r--r--third_party/rust/nix/test/sys/test_ptrace.rs12
-rw-r--r--third_party/rust/nix/test/sys/test_resource.rs (renamed from third_party/rust/nix/test/test_resource.rs)33
-rw-r--r--third_party/rust/nix/test/sys/test_select.rs247
-rw-r--r--third_party/rust/nix/test/sys/test_signal.rs320
-rw-r--r--third_party/rust/nix/test/sys/test_signalfd.rs63
-rw-r--r--third_party/rust/nix/test/sys/test_socket.rs474
-rw-r--r--third_party/rust/nix/test/sys/test_sockopt.rs454
-rw-r--r--third_party/rust/nix/test/sys/test_statfs.rs99
-rw-r--r--third_party/rust/nix/test/sys/test_statvfs.rs13
-rw-r--r--third_party/rust/nix/test/sys/test_termios.rs13
-rw-r--r--third_party/rust/nix/test/sys/test_time.rs91
-rw-r--r--third_party/rust/nix/test/sys/test_timer.rs (renamed from third_party/rust/nix/test/test_timer.rs)0
-rw-r--r--third_party/rust/nix/test/sys/test_uio.rs36
-rw-r--r--third_party/rust/nix/test/sys/test_utsname.rs17
-rw-r--r--third_party/rust/nix/test/sys/test_wait.rs16
-rw-r--r--third_party/rust/nix/test/test.rs32
-rw-r--r--third_party/rust/nix/test/test_dir.rs4
-rw-r--r--third_party/rust/nix/test/test_errno.rs16
-rw-r--r--third_party/rust/nix/test/test_fcntl.rs182
-rw-r--r--third_party/rust/nix/test/test_mount.rs390
-rw-r--r--third_party/rust/nix/test/test_mq.rs20
-rw-r--r--third_party/rust/nix/test/test_net.rs8
-rw-r--r--third_party/rust/nix/test/test_poll.rs31
-rw-r--r--third_party/rust/nix/test/test_pty.rs24
-rw-r--r--third_party/rust/nix/test/test_sendfile.rs90
-rw-r--r--third_party/rust/nix/test/test_stat.rs104
-rw-r--r--third_party/rust/nix/test/test_time.rs49
-rw-r--r--third_party/rust/nix/test/test_unistd.rs260
36 files changed, 2681 insertions, 828 deletions
diff --git a/third_party/rust/nix/test/common/mod.rs b/third_party/rust/nix/test/common/mod.rs
index bb056aab87..db4aed2598 100644
--- a/third_party/rust/nix/test/common/mod.rs
+++ b/third_party/rust/nix/test/common/mod.rs
@@ -2,18 +2,18 @@ use cfg_if::cfg_if;
#[macro_export]
macro_rules! skip {
- ($($reason: expr),+) => {
+ ($($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"))] {
+ if #[cfg(linux_android)] {
#[macro_export] macro_rules! require_capability {
($name:expr, $capname:ident) => {
use ::caps::{Capability, CapSet, has_cap};
@@ -51,7 +51,7 @@ macro_rules! require_mount {
};
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[macro_export]
macro_rules! skip_if_cirrus {
($reason:expr) => {
@@ -87,7 +87,7 @@ macro_rules! skip_if_not_root {
}
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
#[macro_export] macro_rules! skip_if_seccomp {
($name:expr) => {
if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
diff --git a/third_party/rust/nix/test/sys/mod.rs b/third_party/rust/nix/test/sys/mod.rs
index 20312120a6..fb3f6be0e5 100644
--- a/third_party/rust/nix/test/sys/mod.rs
+++ b/third_party/rust/nix/test/sys/mod.rs
@@ -7,16 +7,16 @@ mod test_signal;
// cases on DragonFly.
#[cfg(any(
target_os = "freebsd",
- target_os = "ios",
+ apple_targets,
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"
+ target_os = "haiku",
+ target_os = "hurd"
)))]
mod test_ioctl;
#[cfg(not(target_os = "redox"))]
@@ -30,7 +30,7 @@ mod test_socket;
#[cfg(not(any(target_os = "redox")))]
mod test_sockopt;
mod test_stat;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_sysinfo;
#[cfg(not(any(
target_os = "redox",
@@ -41,20 +41,44 @@ mod test_termios;
mod test_uio;
mod test_wait;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_epoll;
#[cfg(target_os = "linux")]
+mod test_fanotify;
+#[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"
-))]
+
+#[cfg(any(linux_android, freebsdlike, netbsdlike, apple_targets))]
mod test_ptrace;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_timerfd;
+
+#[cfg(all(
+ any(
+ target_os = "freebsd",
+ solarish,
+ target_os = "linux",
+ target_os = "netbsd"
+ ),
+ feature = "time",
+ feature = "signal"
+))]
+mod test_timer;
+
+#[cfg(bsd)]
+mod test_event;
+mod test_statvfs;
+mod test_time;
+mod test_utsname;
+
+#[cfg(any(linux_android, freebsdlike, apple_targets, target_os = "openbsd"))]
+mod test_statfs;
+
+#[cfg(not(any(
+ target_os = "redox",
+ target_os = "fuchsia",
+ solarish,
+ target_os = "haiku"
+)))]
+mod test_resource;
diff --git a/third_party/rust/nix/test/sys/test_aio.rs b/third_party/rust/nix/test/sys/test_aio.rs
index 5035b5a08f..ba5ad02ec3 100644
--- a/third_party/rust/nix/test/sys/test_aio.rs
+++ b/third_party/rust/nix/test/sys/test_aio.rs
@@ -67,7 +67,7 @@ mod aio_fsync {
// Skip on Linux, because Linux's AIO implementation can't detect errors
// synchronously
#[test]
- #[cfg(any(target_os = "freebsd", target_os = "macos"))]
+ #[cfg(any(target_os = "freebsd", apple_targets))]
fn error() {
use std::mem;
@@ -157,7 +157,7 @@ mod aio_read {
// Skip on Linux, because Linux's AIO implementation can't detect errors
// synchronously
#[test]
- #[cfg(any(target_os = "freebsd", target_os = "macos"))]
+ #[cfg(any(target_os = "freebsd", apple_targets))]
fn error() {
const INITIAL: &[u8] = b"abcdef123456";
let mut rbuf = vec![0; 4];
@@ -411,7 +411,7 @@ mod aio_write {
// Skip on Linux, because Linux's AIO implementation can't detect errors
// synchronously
#[test]
- #[cfg(any(target_os = "freebsd", target_os = "macos"))]
+ #[cfg(any(target_os = "freebsd", apple_targets))]
fn error() {
let wbuf = "CDEF".to_string().into_bytes();
let mut aiow = Box::pin(AioWrite::new(
@@ -498,7 +498,9 @@ mod aio_writev {
any(
all(target_env = "musl", target_arch = "x86_64"),
target_arch = "mips",
- target_arch = "mips64"
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
),
ignore
)]
@@ -567,12 +569,6 @@ fn test_aio_cancel_all() {
}
#[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";
@@ -622,3 +618,53 @@ fn test_aio_suspend() {
assert_eq!(wcb.as_mut().aio_return().unwrap(), WBUF.len());
assert_eq!(rcb.as_mut().aio_return().unwrap(), rlen);
}
+
+/// aio_suspend relies on casting Rust Aio* struct pointers to libc::aiocb
+/// pointers. This test ensures that such casts are valid.
+#[test]
+fn casting() {
+ let sev = SigevNotify::SigevNone;
+ let aiof = AioFsync::new(666, AioFsyncMode::O_SYNC, 0, sev);
+ assert_eq!(
+ aiof.as_ref() as *const libc::aiocb,
+ &aiof as *const AioFsync as *const libc::aiocb
+ );
+
+ let mut rbuf = [];
+ let aior = AioRead::new(666, 0, &mut rbuf, 0, sev);
+ assert_eq!(
+ aior.as_ref() as *const libc::aiocb,
+ &aior as *const AioRead as *const libc::aiocb
+ );
+
+ let wbuf = [];
+ let aiow = AioWrite::new(666, 0, &wbuf, 0, sev);
+ assert_eq!(
+ aiow.as_ref() as *const libc::aiocb,
+ &aiow as *const AioWrite as *const libc::aiocb
+ );
+}
+
+#[cfg(target_os = "freebsd")]
+#[test]
+fn casting_vectored() {
+ use std::io::{IoSlice, IoSliceMut};
+
+ let sev = SigevNotify::SigevNone;
+
+ let mut rbuf = [];
+ let mut rbufs = [IoSliceMut::new(&mut rbuf)];
+ let aiorv = AioReadv::new(666, 0, &mut rbufs[..], 0, sev);
+ assert_eq!(
+ aiorv.as_ref() as *const libc::aiocb,
+ &aiorv as *const AioReadv as *const libc::aiocb
+ );
+
+ let wbuf = [];
+ let wbufs = [IoSlice::new(&wbuf)];
+ let aiowv = AioWritev::new(666, 0, &wbufs, 0, sev);
+ assert_eq!(
+ aiowv.as_ref() as *const libc::aiocb,
+ &aiowv as *const AioWritev as *const libc::aiocb
+ );
+}
diff --git a/third_party/rust/nix/test/sys/test_aio_drop.rs b/third_party/rust/nix/test/sys/test_aio_drop.rs
index bbe6623fd7..54106dd168 100644
--- a/third_party/rust/nix/test/sys/test_aio_drop.rs
+++ b/third_party/rust/nix/test/sys/test_aio_drop.rs
@@ -8,8 +8,7 @@
not(target_env = "uclibc"),
any(
target_os = "linux",
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
)
diff --git a/third_party/rust/nix/test/sys/test_event.rs b/third_party/rust/nix/test/sys/test_event.rs
new file mode 100644
index 0000000000..a10b1e5d12
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_event.rs
@@ -0,0 +1,41 @@
+use libc::intptr_t;
+use nix::sys::event::{EventFilter, EventFlag, FilterFlag, KEvent};
+
+#[test]
+fn test_struct_kevent() {
+ use std::mem;
+
+ let udata: intptr_t = 12345;
+ let data: intptr_t = 0x1337;
+
+ let actual = KEvent::new(
+ 0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ data,
+ udata,
+ );
+ assert_eq!(0xdead_beef, actual.ident());
+ assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
+ assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
+ assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
+ assert_eq!(data, actual.data());
+ assert_eq!(udata, actual.udata());
+ assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
+}
+
+#[test]
+fn test_kevent_filter() {
+ let udata: intptr_t = 12345;
+
+ let actual = KEvent::new(
+ 0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ 0x1337,
+ udata,
+ );
+ assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
+}
diff --git a/third_party/rust/nix/test/sys/test_fanotify.rs b/third_party/rust/nix/test/sys/test_fanotify.rs
new file mode 100644
index 0000000000..20226c272a
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_fanotify.rs
@@ -0,0 +1,149 @@
+use crate::*;
+use nix::sys::fanotify::{
+ EventFFlags, Fanotify, FanotifyResponse, InitFlags, MarkFlags, MaskFlags,
+ Response,
+};
+use std::fs::{read_link, File, OpenOptions};
+use std::io::ErrorKind;
+use std::io::{Read, Write};
+use std::os::fd::AsRawFd;
+use std::thread;
+
+#[test]
+/// Run fanotify tests sequentially to avoid tmp files races
+pub fn test_fanotify() {
+ require_capability!("test_fanotify", CAP_SYS_ADMIN);
+
+ test_fanotify_notifications();
+ test_fanotify_responses();
+}
+
+fn test_fanotify_notifications() {
+ let group =
+ Fanotify::init(InitFlags::FAN_CLASS_NOTIF, EventFFlags::O_RDONLY)
+ .unwrap();
+ let tempdir = tempfile::tempdir().unwrap();
+ let tempfile = tempdir.path().join("test");
+ OpenOptions::new()
+ .write(true)
+ .create_new(true)
+ .open(&tempfile)
+ .unwrap();
+
+ group
+ .mark(
+ MarkFlags::FAN_MARK_ADD,
+ MaskFlags::FAN_OPEN | MaskFlags::FAN_MODIFY | MaskFlags::FAN_CLOSE,
+ None,
+ Some(&tempfile),
+ )
+ .unwrap();
+
+ // modify test file
+ {
+ let mut f = OpenOptions::new().write(true).open(&tempfile).unwrap();
+ f.write_all(b"hello").unwrap();
+ }
+
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(
+ event.mask(),
+ MaskFlags::FAN_OPEN
+ | MaskFlags::FAN_MODIFY
+ | MaskFlags::FAN_CLOSE_WRITE
+ );
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+
+ // read test file
+ {
+ let mut f = File::open(&tempfile).unwrap();
+ let mut s = String::new();
+ f.read_to_string(&mut s).unwrap();
+ }
+
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(
+ event.mask(),
+ MaskFlags::FAN_OPEN | MaskFlags::FAN_CLOSE_NOWRITE
+ );
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+}
+
+fn test_fanotify_responses() {
+ let group =
+ Fanotify::init(InitFlags::FAN_CLASS_CONTENT, EventFFlags::O_RDONLY)
+ .unwrap();
+ let tempdir = tempfile::tempdir().unwrap();
+ let tempfile = tempdir.path().join("test");
+ OpenOptions::new()
+ .write(true)
+ .create_new(true)
+ .open(&tempfile)
+ .unwrap();
+
+ group
+ .mark(
+ MarkFlags::FAN_MARK_ADD,
+ MaskFlags::FAN_OPEN_PERM,
+ None,
+ Some(&tempfile),
+ )
+ .unwrap();
+
+ let file_thread = thread::spawn({
+ let tempfile = tempfile.clone();
+
+ move || {
+ // first open, should fail
+ let Err(e) = File::open(&tempfile) else {
+ panic!("The first open should fail");
+ };
+ assert_eq!(e.kind(), ErrorKind::PermissionDenied);
+
+ // second open, should succeed
+ File::open(&tempfile).unwrap();
+ }
+ });
+
+ // Deny the first open try
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(event.mask(), MaskFlags::FAN_OPEN_PERM);
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+ group
+ .write_response(FanotifyResponse::new(*fd, Response::FAN_DENY))
+ .unwrap();
+
+ // Allow the second open try
+ let mut events = group.read_events().unwrap();
+ assert_eq!(events.len(), 1, "should have read exactly one event");
+ let event = events.pop().unwrap();
+ assert!(event.check_version());
+ assert_eq!(event.mask(), MaskFlags::FAN_OPEN_PERM);
+ let fd_opt = event.fd();
+ let fd = fd_opt.as_ref().unwrap();
+ let path = read_link(format!("/proc/self/fd/{}", fd.as_raw_fd())).unwrap();
+ assert_eq!(path, tempfile);
+ group
+ .write_response(FanotifyResponse::new(*fd, Response::FAN_ALLOW))
+ .unwrap();
+
+ file_thread.join().unwrap();
+}
diff --git a/third_party/rust/nix/test/sys/test_ioctl.rs b/third_party/rust/nix/test/sys/test_ioctl.rs
index 40f60cfdbc..08843bf61c 100644
--- a/third_party/rust/nix/test/sys/test_ioctl.rs
+++ b/third_party/rust/nix/test/sys/test_ioctl.rs
@@ -28,7 +28,7 @@ ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
// 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"))]
+#[cfg(linux_android)]
mod linux {
// The cast is not unnecessary on all platforms.
#[allow(clippy::unnecessary_cast)]
@@ -36,7 +36,9 @@ mod linux {
fn test_op_none() {
if cfg!(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64"
)) {
@@ -54,7 +56,9 @@ mod linux {
fn test_op_write() {
if cfg!(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64"
)) {
@@ -69,7 +73,11 @@ mod linux {
#[cfg(target_pointer_width = "64")]
#[test]
fn test_op_write_64() {
- if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) {
+ if cfg!(any(
+ target_arch = "mips64",
+ target_arch = "mips64r6",
+ target_arch = "powerpc64"
+ )) {
assert_eq!(
request_code_write!(b'z', 10, 1u64 << 32) as u32,
0x8000_7A0A
@@ -88,7 +96,9 @@ mod linux {
fn test_op_read() {
if cfg!(any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64"
)) {
@@ -103,7 +113,11 @@ mod linux {
#[cfg(target_pointer_width = "64")]
#[test]
fn test_op_read_64() {
- if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) {
+ if cfg!(any(
+ target_arch = "mips64",
+ target_arch = "mips64r6",
+ target_arch = "powerpc64"
+ )) {
assert_eq!(
request_code_read!(b'z', 10, 1u64 << 32) as u32,
0x4000_7A0A
@@ -134,14 +148,7 @@ mod linux {
}
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"
-))]
+#[cfg(bsd)]
mod bsd {
#[test]
fn test_op_none() {
@@ -149,7 +156,7 @@ mod bsd {
assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
}
- #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+ #[cfg(freebsdlike)]
#[test]
fn test_op_write_int() {
assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
@@ -193,7 +200,7 @@ mod bsd {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod linux_ioctls {
use std::mem;
use std::os::unix::io::AsRawFd;
diff --git a/third_party/rust/nix/test/sys/test_mman.rs b/third_party/rust/nix/test/sys/test_mman.rs
index b4674e53fa..3689f642be 100644
--- a/third_party/rust/nix/test/sys/test_mman.rs
+++ b/third_party/rust/nix/test/sys/test_mman.rs
@@ -1,44 +1,44 @@
-use nix::sys::mman::{mmap, MapFlags, ProtFlags};
-use std::{num::NonZeroUsize, os::unix::io::BorrowedFd};
+#![allow(clippy::redundant_slicing)]
+
+use nix::sys::mman::{mmap_anonymous, MapFlags, ProtFlags};
+use std::num::NonZeroUsize;
#[test]
fn test_mmap_anonymous() {
unsafe {
- let ptr = mmap::<BorrowedFd>(
+ let mut ptr = mmap_anonymous(
None,
NonZeroUsize::new(1).unwrap(),
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS,
- None,
- 0,
+ MapFlags::MAP_PRIVATE,
)
- .unwrap() as *mut u8;
- assert_eq!(*ptr, 0x00u8);
- *ptr = 0xffu8;
- assert_eq!(*ptr, 0xffu8);
+ .unwrap()
+ .cast::<u8>();
+ assert_eq!(*ptr.as_ref(), 0x00u8);
+ *ptr.as_mut() = 0xffu8;
+ assert_eq!(*ptr.as_ref(), 0xffu8);
}
}
#[test]
#[cfg(any(target_os = "linux", target_os = "netbsd"))]
fn test_mremap_grow() {
- use nix::libc::{c_void, size_t};
+ use nix::libc::size_t;
use nix::sys::mman::{mremap, MRemapFlags};
+ use std::ptr::NonNull;
const ONE_K: size_t = 1024;
let one_k_non_zero = NonZeroUsize::new(ONE_K).unwrap();
let slice: &mut [u8] = unsafe {
- let mem = mmap::<BorrowedFd>(
+ let mem = mmap_anonymous(
None,
one_k_non_zero,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
- None,
- 0,
+ MapFlags::MAP_PRIVATE,
)
.unwrap();
- std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
+ std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
};
assert_eq!(slice[ONE_K - 1], 0x00);
slice[ONE_K - 1] = 0xFF;
@@ -47,7 +47,7 @@ fn test_mremap_grow() {
let slice: &mut [u8] = unsafe {
#[cfg(target_os = "linux")]
let mem = mremap(
- slice.as_mut_ptr() as *mut c_void,
+ NonNull::from(&mut slice[..]).cast(),
ONE_K,
10 * ONE_K,
MRemapFlags::MREMAP_MAYMOVE,
@@ -56,14 +56,14 @@ fn test_mremap_grow() {
.unwrap();
#[cfg(target_os = "netbsd")]
let mem = mremap(
- slice.as_mut_ptr() as *mut c_void,
+ NonNull::from(&mut slice[..]).cast(),
ONE_K,
10 * ONE_K,
MRemapFlags::MAP_REMAPDUP,
None,
)
.unwrap();
- std::slice::from_raw_parts_mut(mem as *mut u8, 10 * ONE_K)
+ std::slice::from_raw_parts_mut(mem.cast().as_ptr(), 10 * ONE_K)
};
// The first KB should still have the old data in it.
@@ -80,23 +80,22 @@ fn test_mremap_grow() {
// 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::libc::size_t;
use nix::sys::mman::{mremap, MRemapFlags};
use std::num::NonZeroUsize;
+ use std::ptr::NonNull;
const ONE_K: size_t = 1024;
let ten_one_k = NonZeroUsize::new(10 * ONE_K).unwrap();
let slice: &mut [u8] = unsafe {
- let mem = mmap::<BorrowedFd>(
+ let mem = mmap_anonymous(
None,
ten_one_k,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
- MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
- None,
- 0,
+ MapFlags::MAP_PRIVATE,
)
.unwrap();
- std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
+ std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
};
assert_eq!(slice[ONE_K - 1], 0x00);
slice[ONE_K - 1] = 0xFF;
@@ -104,7 +103,7 @@ fn test_mremap_shrink() {
let slice: &mut [u8] = unsafe {
let mem = mremap(
- slice.as_mut_ptr() as *mut c_void,
+ NonNull::from(&mut slice[..]).cast(),
ten_one_k.into(),
ONE_K,
MRemapFlags::empty(),
@@ -113,8 +112,8 @@ fn test_mremap_shrink() {
.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)
+ assert_eq!(mem.as_ptr(), NonNull::from(&mut slice[..]).cast().as_ptr());
+ std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
};
// The first KB should still be accessible and have the old data in it.
diff --git a/third_party/rust/nix/test/sys/test_ptrace.rs b/third_party/rust/nix/test/sys/test_ptrace.rs
index 530560fe17..246b35445d 100644
--- a/third_party/rust/nix/test/sys/test_ptrace.rs
+++ b/third_party/rust/nix/test/sys/test_ptrace.rs
@@ -6,11 +6,11 @@
use memoffset::offset_of;
use nix::errno::Errno;
use nix::sys::ptrace;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use nix::sys::ptrace::Options;
use nix::unistd::getpid;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use std::mem;
use crate::*;
@@ -28,7 +28,7 @@ fn test_ptrace() {
// Just make sure ptrace_setoptions can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_setoptions() {
require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE);
let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD)
@@ -38,7 +38,7 @@ fn test_ptrace_setoptions() {
// Just make sure ptrace_getevent can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_getevent() {
require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE);
let err = ptrace::getevent(getpid()).unwrap_err();
@@ -47,7 +47,7 @@ fn test_ptrace_getevent() {
// Just make sure ptrace_getsiginfo can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_getsiginfo() {
require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE);
if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) {
@@ -57,7 +57,7 @@ fn test_ptrace_getsiginfo() {
// Just make sure ptrace_setsiginfo can be called at all, for now.
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptrace_setsiginfo() {
require_capability!("test_ptrace_setsiginfo", CAP_SYS_PTRACE);
let siginfo = unsafe { mem::zeroed() };
diff --git a/third_party/rust/nix/test/test_resource.rs b/third_party/rust/nix/test/sys/test_resource.rs
index 2ab581ba29..8b12a9495b 100644
--- a/third_party/rust/nix/test/test_resource.rs
+++ b/third_party/rust/nix/test/sys/test_resource.rs
@@ -1,10 +1,5 @@
-#[cfg(not(any(
- target_os = "redox",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "haiku"
-)))]
use nix::sys::resource::{getrlimit, setrlimit, Resource};
+use nix::sys::resource::{getrusage, UsageWho};
/// 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
@@ -15,12 +10,6 @@ use nix::sys::resource::{getrlimit, setrlimit, Resource};
/// 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();
@@ -32,3 +21,23 @@ pub fn test_resource_limits_nofile() {
let (new_soft_limit, _) = getrlimit(Resource::RLIMIT_NOFILE).unwrap();
assert_eq!(new_soft_limit, soft_limit);
}
+
+#[test]
+pub fn test_self_cpu_time() {
+ // Make sure some CPU time is used.
+ let mut numbers: Vec<i32> = (1..1_000_000).collect();
+ numbers.iter_mut().for_each(|item| *item *= 2);
+
+ // FIXME: this is here to help ensure the compiler does not optimize the whole
+ // thing away. Replace the assert with test::black_box once stabilized.
+ assert_eq!(numbers[100..200].iter().sum::<i32>(), 30_100);
+
+ let usage = getrusage(UsageWho::RUSAGE_SELF)
+ .expect("Failed to call getrusage for SELF");
+ let rusage = usage.as_ref();
+
+ let user = usage.user_time();
+ assert!(user.tv_sec() > 0 || user.tv_usec() > 0);
+ assert_eq!(user.tv_sec(), rusage.ru_utime.tv_sec);
+ assert_eq!(user.tv_usec(), rusage.ru_utime.tv_usec);
+}
diff --git a/third_party/rust/nix/test/sys/test_select.rs b/third_party/rust/nix/test/sys/test_select.rs
index 79f75de3b4..e39a31923a 100644
--- a/third_party/rust/nix/test/sys/test_select.rs
+++ b/third_party/rust/nix/test/sys/test_select.rs
@@ -1,22 +1,20 @@
use nix::sys::select::*;
use nix::sys::signal::SigSet;
-use nix::sys::time::{TimeSpec, TimeValLike};
+use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
use nix::unistd::{pipe, write};
-use std::os::unix::io::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
+use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
#[test]
pub fn test_pselect() {
let _mtx = crate::SIGNAL_MTX.lock();
let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
+ write(&w1, b"hi!").unwrap();
let (r2, _w2) = pipe().unwrap();
- let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
let mut fd_set = FdSet::new();
- fd_set.insert(&r1);
- fd_set.insert(&r2);
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
let timeout = TimeSpec::seconds(10);
let sigmask = SigSet::empty();
@@ -24,21 +22,19 @@ pub fn test_pselect() {
1,
pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
);
- assert!(fd_set.contains(&r1));
- assert!(!fd_set.contains(&r2));
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
}
#[test]
pub fn test_pselect_nfds2() {
let (r1, w1) = pipe().unwrap();
- write(w1, b"hi!").unwrap();
- let r1 = unsafe { OwnedFd::from_raw_fd(r1) };
+ write(&w1, b"hi!").unwrap();
let (r2, _w2) = pipe().unwrap();
- let r2 = unsafe { OwnedFd::from_raw_fd(r2) };
let mut fd_set = FdSet::new();
- fd_set.insert(&r1);
- fd_set.insert(&r2);
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
let timeout = TimeSpec::seconds(10);
assert_eq!(
@@ -53,8 +49,8 @@ pub fn test_pselect_nfds2() {
)
.unwrap()
);
- assert!(fd_set.contains(&r1));
- assert!(!fd_set.contains(&r2));
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
}
macro_rules! generate_fdset_bad_fd_tests {
@@ -64,7 +60,7 @@ macro_rules! generate_fdset_bad_fd_tests {
#[should_panic]
fn $method() {
let bad_fd = unsafe{BorrowedFd::borrow_raw($fd)};
- FdSet::new().$method(&bad_fd);
+ FdSet::new().$method(bad_fd);
}
)*
}
@@ -72,7 +68,6 @@ macro_rules! generate_fdset_bad_fd_tests {
mod test_fdset_too_large_fd {
use super::*;
- use std::convert::TryInto;
generate_fdset_bad_fd_tests!(
FD_SETSIZE.try_into().unwrap(),
insert,
@@ -80,3 +75,219 @@ mod test_fdset_too_large_fd {
contains,
);
}
+
+#[test]
+fn fdset_insert() {
+ let mut fd_set = FdSet::new();
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+
+ let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
+ fd_set.insert(fd_seven);
+
+ assert!(fd_set.contains(fd_seven));
+}
+
+#[test]
+fn fdset_remove() {
+ let mut fd_set = FdSet::new();
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+
+ let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
+ fd_set.insert(fd_seven);
+ fd_set.remove(fd_seven);
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+}
+
+#[test]
+#[allow(non_snake_case)]
+fn fdset_clear() {
+ let mut fd_set = FdSet::new();
+ let fd_one = unsafe { BorrowedFd::borrow_raw(1) };
+ let fd_FD_SETSIZE_divided_by_two =
+ unsafe { BorrowedFd::borrow_raw((FD_SETSIZE / 2) as RawFd) };
+ let fd_FD_SETSIZE_minus_one =
+ unsafe { BorrowedFd::borrow_raw((FD_SETSIZE - 1) as RawFd) };
+ fd_set.insert(fd_one);
+ fd_set.insert(fd_FD_SETSIZE_divided_by_two);
+ fd_set.insert(fd_FD_SETSIZE_minus_one);
+
+ fd_set.clear();
+
+ for i in 0..FD_SETSIZE {
+ let borrowed_i = unsafe { BorrowedFd::borrow_raw(i as RawFd) };
+ assert!(!fd_set.contains(borrowed_i));
+ }
+}
+
+#[test]
+fn fdset_highest() {
+ let mut set = FdSet::new();
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ None
+ );
+ let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
+ let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
+ set.insert(fd_zero);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(0)
+ );
+ set.insert(fd_ninety);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(90)
+ );
+ set.remove(fd_zero);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(90)
+ );
+ set.remove(fd_ninety);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ None
+ );
+
+ let fd_four = unsafe { BorrowedFd::borrow_raw(4) };
+ let fd_five = unsafe { BorrowedFd::borrow_raw(5) };
+ let fd_seven = unsafe { BorrowedFd::borrow_raw(7) };
+ set.insert(fd_four);
+ set.insert(fd_five);
+ set.insert(fd_seven);
+ assert_eq!(
+ set.highest().map(|borrowed_fd| borrowed_fd.as_raw_fd()),
+ Some(7)
+ );
+}
+
+#[test]
+fn fdset_fds() {
+ let mut set = FdSet::new();
+ let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
+ let fd_ninety = unsafe { BorrowedFd::borrow_raw(90) };
+ assert_eq!(
+ set.fds(None)
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![]
+ );
+ set.insert(fd_zero);
+ assert_eq!(
+ set.fds(None)
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0]
+ );
+ set.insert(fd_ninety);
+ assert_eq!(
+ set.fds(None)
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0, 90]
+ );
+
+ // highest limit
+ assert_eq!(
+ set.fds(Some(89))
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0]
+ );
+ assert_eq!(
+ set.fds(Some(90))
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .collect::<Vec<_>>(),
+ vec![0, 90]
+ );
+}
+
+#[test]
+fn test_select() {
+ let (r1, w1) = pipe().unwrap();
+ let (r2, _w2) = pipe().unwrap();
+
+ write(&w1, b"hi!").unwrap();
+ let mut fd_set = FdSet::new();
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
+
+ let mut timeout = TimeVal::seconds(10);
+ assert_eq!(
+ 1,
+ select(None, &mut fd_set, None, None, &mut timeout).unwrap()
+ );
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
+}
+
+#[test]
+fn test_select_nfds() {
+ let (r1, w1) = pipe().unwrap();
+ let (r2, _w2) = pipe().unwrap();
+
+ write(&w1, b"hi!").unwrap();
+ let mut fd_set = FdSet::new();
+ fd_set.insert(r1.as_fd());
+ fd_set.insert(r2.as_fd());
+
+ let mut timeout = TimeVal::seconds(10);
+ {
+ assert_eq!(
+ 1,
+ select(
+ Some(
+ fd_set
+ .highest()
+ .map(|borrowed_fd| borrowed_fd.as_raw_fd())
+ .unwrap()
+ + 1
+ ),
+ &mut fd_set,
+ None,
+ None,
+ &mut timeout
+ )
+ .unwrap()
+ );
+ }
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
+}
+
+#[test]
+fn test_select_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.as_fd());
+ fd_set.insert(r2.as_fd());
+
+ let mut timeout = TimeVal::seconds(10);
+ assert_eq!(
+ 1,
+ select(
+ std::cmp::max(r1.as_raw_fd(), r2.as_raw_fd()) + 1,
+ &mut fd_set,
+ None,
+ None,
+ &mut timeout
+ )
+ .unwrap()
+ );
+ assert!(fd_set.contains(r1.as_fd()));
+ assert!(!fd_set.contains(r2.as_fd()));
+}
diff --git a/third_party/rust/nix/test/sys/test_signal.rs b/third_party/rust/nix/test/sys/test_signal.rs
index ca25ff9ab0..bf607497be 100644
--- a/third_party/rust/nix/test/sys/test_signal.rs
+++ b/third_party/rust/nix/test/sys/test_signal.rs
@@ -1,9 +1,10 @@
-#[cfg(not(target_os = "redox"))]
use nix::errno::Errno;
use nix::sys::signal::*;
use nix::unistd::*;
-use std::convert::TryFrom;
+use std::hash::{Hash, Hasher};
use std::sync::atomic::{AtomicBool, Ordering};
+#[cfg(not(target_os = "redox"))]
+use std::thread;
#[test]
fn test_kill_none() {
@@ -124,7 +125,7 @@ fn test_signal() {
raise(Signal::SIGINT).unwrap();
assert!(SIGNALED.load(Ordering::Relaxed));
- #[cfg(not(any(target_os = "illumos", target_os = "solaris")))]
+ #[cfg(not(solarish))]
assert_eq!(
unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(),
handler
@@ -132,7 +133,7 @@ fn test_signal() {
// 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"))]
+ #[cfg(solarish)]
assert_eq!(
unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(),
SigHandler::SigDfl
@@ -141,3 +142,314 @@ fn test_signal() {
// Restore default signal handler
unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
}
+
+#[test]
+fn test_contains() {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ assert!(mask.contains(SIGUSR1));
+ assert!(!mask.contains(SIGUSR2));
+
+ let all = SigSet::all();
+ assert!(all.contains(SIGUSR1));
+ assert!(all.contains(SIGUSR2));
+}
+
+#[test]
+fn test_clear() {
+ let mut set = SigSet::all();
+ set.clear();
+ for signal in Signal::iterator() {
+ assert!(!set.contains(signal));
+ }
+}
+
+#[test]
+fn test_from_str_round_trips() {
+ for signal in Signal::iterator() {
+ assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
+ assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
+ }
+}
+
+#[test]
+fn test_from_str_invalid_value() {
+ let errval = Err(Errno::EINVAL);
+ assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
+ assert_eq!("kill".parse::<Signal>(), errval);
+ assert_eq!("9".parse::<Signal>(), errval);
+}
+
+#[test]
+fn test_extend() {
+ let mut one_signal = SigSet::empty();
+ one_signal.add(SIGUSR1);
+
+ let mut two_signals = SigSet::empty();
+ two_signals.add(SIGUSR2);
+ two_signals.extend(&one_signal);
+
+ assert!(two_signals.contains(SIGUSR1));
+ assert!(two_signals.contains(SIGUSR2));
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_set_mask() {
+ thread::spawn(|| {
+ let prev_mask = SigSet::thread_get_mask()
+ .expect("Failed to get existing signal mask!");
+
+ let mut test_mask = prev_mask;
+ test_mask.add(SIGUSR1);
+
+ test_mask.thread_set_mask().expect("assertion failed");
+ let new_mask =
+ SigSet::thread_get_mask().expect("Failed to get new mask!");
+
+ assert!(new_mask.contains(SIGUSR1));
+ assert!(!new_mask.contains(SIGUSR2));
+
+ prev_mask
+ .thread_set_mask()
+ .expect("Failed to revert signal mask!");
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_block() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ mask.thread_block().expect("assertion failed");
+
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_unblock() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ mask.thread_unblock().expect("assertion failed");
+
+ assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_thread_signal_swap() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+ mask.thread_block().unwrap();
+
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
+
+ let mut mask2 = SigSet::empty();
+ mask2.add(SIGUSR2);
+
+ let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap();
+
+ assert!(oldmask.contains(SIGUSR1));
+ assert!(!oldmask.contains(SIGUSR2));
+
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+fn test_from_and_into_iterator() {
+ let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
+ let signals = sigset.into_iter().collect::<Vec<Signal>>();
+ assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_sigaction() {
+ thread::spawn(|| {
+ extern "C" fn test_sigaction_handler(_: libc::c_int) {}
+ extern "C" fn test_sigaction_action(
+ _: libc::c_int,
+ _: *mut libc::siginfo_t,
+ _: *mut libc::c_void,
+ ) {
+ }
+
+ let handler_sig = SigHandler::Handler(test_sigaction_handler);
+
+ let flags =
+ SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO;
+
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+
+ let action_sig = SigAction::new(handler_sig, flags, mask);
+
+ assert_eq!(
+ action_sig.flags(),
+ SaFlags::SA_ONSTACK | SaFlags::SA_RESTART
+ );
+ assert_eq!(action_sig.handler(), handler_sig);
+
+ mask = action_sig.mask();
+ assert!(mask.contains(SIGUSR1));
+ assert!(!mask.contains(SIGUSR2));
+
+ let handler_act = SigHandler::SigAction(test_sigaction_action);
+ let action_act = SigAction::new(handler_act, flags, mask);
+ assert_eq!(action_act.handler(), handler_act);
+
+ let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
+ assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
+
+ let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
+ assert_eq!(action_ign.handler(), SigHandler::SigIgn);
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+#[cfg(not(target_os = "redox"))]
+fn test_sigwait() {
+ thread::spawn(|| {
+ let mut mask = SigSet::empty();
+ mask.add(SIGUSR1);
+ mask.add(SIGUSR2);
+ mask.thread_block().unwrap();
+
+ raise(SIGUSR1).unwrap();
+ assert_eq!(mask.wait().unwrap(), SIGUSR1);
+ })
+ .join()
+ .unwrap();
+}
+
+#[cfg(any(
+ bsd,
+ linux_android,
+ solarish,
+ target_os = "haiku",
+ target_os = "hurd",
+ target_os = "aix",
+ target_os = "fushsia"
+))]
+#[test]
+fn test_sigsuspend() {
+ // This test change signal handler
+ let _m = crate::SIGNAL_MTX.lock();
+ static SIGNAL_RECIEVED: AtomicBool = AtomicBool::new(false);
+ extern "C" fn test_sigsuspend_handler(_: libc::c_int) {
+ assert!(!SIGNAL_RECIEVED.swap(true, Ordering::SeqCst));
+ }
+ thread::spawn(|| {
+ const SIGNAL: Signal = Signal::SIGUSR1;
+
+ // Add signal mask to this thread
+ let mut signal_set = SigSet::empty();
+ signal_set.add(SIGNAL);
+ signal_set.thread_block().unwrap();
+
+ // Set signal handler and save old one.
+ let act = SigAction::new(
+ SigHandler::Handler(test_sigsuspend_handler),
+ SaFlags::empty(),
+ SigSet::empty(),
+ );
+ let old_act = unsafe { sigaction(SIGNAL, &act) }
+ .expect("expect to be able to set new action and get old action");
+
+ raise(SIGNAL).expect("expect be able to send signal");
+ // Now `SIGNAL` was sended but it is blocked.
+ let mut not_wait_set = SigSet::all();
+ not_wait_set.remove(SIGNAL);
+ // signal handler must run in SigSet::suspend()
+ assert!(!SIGNAL_RECIEVED.load(Ordering::SeqCst));
+ not_wait_set.suspend().unwrap();
+ assert!(SIGNAL_RECIEVED.load(Ordering::SeqCst));
+
+ // Restore the signal handler.
+ unsafe { sigaction(SIGNAL, &old_act) }
+ .expect("expect to be able to restore old action ");
+ })
+ .join()
+ .unwrap();
+}
+
+#[test]
+fn test_from_sigset_t_unchecked() {
+ let src_set = SigSet::empty();
+ let set = unsafe { SigSet::from_sigset_t_unchecked(*src_set.as_ref()) };
+
+ for signal in Signal::iterator() {
+ assert!(!set.contains(signal));
+ }
+
+ let src_set = SigSet::all();
+ let set = unsafe { SigSet::from_sigset_t_unchecked(*src_set.as_ref()) };
+
+ for signal in Signal::iterator() {
+ assert!(set.contains(signal));
+ }
+}
+
+#[test]
+fn test_eq_empty() {
+ let set0 = SigSet::empty();
+ let set1 = SigSet::empty();
+ assert_eq!(set0, set1);
+}
+
+#[test]
+fn test_eq_all() {
+ let set0 = SigSet::all();
+ let set1 = SigSet::all();
+ assert_eq!(set0, set1);
+}
+
+#[test]
+fn test_hash_empty() {
+ use std::collections::hash_map::DefaultHasher;
+
+ let set0 = SigSet::empty();
+ let mut h0 = DefaultHasher::new();
+ set0.hash(&mut h0);
+
+ let set1 = SigSet::empty();
+ let mut h1 = DefaultHasher::new();
+ set1.hash(&mut h1);
+
+ assert_eq!(h0.finish(), h1.finish());
+}
+
+#[test]
+fn test_hash_all() {
+ use std::collections::hash_map::DefaultHasher;
+
+ let set0 = SigSet::all();
+ let mut h0 = DefaultHasher::new();
+ set0.hash(&mut h0);
+
+ let set1 = SigSet::all();
+ let mut h1 = DefaultHasher::new();
+ set1.hash(&mut h1);
+
+ assert_eq!(h0.finish(), h1.finish());
+}
diff --git a/third_party/rust/nix/test/sys/test_signalfd.rs b/third_party/rust/nix/test/sys/test_signalfd.rs
index 87153c9572..4e0971aba7 100644
--- a/third_party/rust/nix/test/sys/test_signalfd.rs
+++ b/third_party/rust/nix/test/sys/test_signalfd.rs
@@ -1,6 +1,40 @@
use std::convert::TryFrom;
#[test]
+fn create_signalfd() {
+ use nix::sys::{signal::SigSet, signalfd::SignalFd};
+
+ let mask = SigSet::empty();
+ SignalFd::new(&mask).unwrap();
+}
+
+#[test]
+fn create_signalfd_with_opts() {
+ use nix::sys::{
+ signal::SigSet,
+ signalfd::{SfdFlags, SignalFd},
+ };
+
+ let mask = SigSet::empty();
+ SignalFd::with_flags(&mask, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK)
+ .unwrap();
+}
+
+#[test]
+fn read_empty_signalfd() {
+ use nix::sys::{
+ signal::SigSet,
+ signalfd::{SfdFlags, SignalFd},
+ };
+
+ let mask = SigSet::empty();
+ let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
+
+ let res = fd.read_signal();
+ assert!(res.unwrap().is_none());
+}
+
+#[test]
fn test_signalfd() {
use nix::sys::signal::{self, raise, SigSet, Signal};
use nix::sys::signalfd::SignalFd;
@@ -25,3 +59,32 @@ fn test_signalfd() {
let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
assert_eq!(signo, signal::SIGUSR1);
}
+
+/// Update the signal mask of an already existing signalfd.
+#[test]
+fn test_signalfd_setmask() {
+ 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();
+
+ let mut fd = SignalFd::new(&mask).unwrap();
+
+ mask.add(signal::SIGUSR1);
+ mask.thread_block().unwrap();
+ fd.set_mask(&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/third_party/rust/nix/test/sys/test_socket.rs b/third_party/rust/nix/test/sys/test_socket.rs
index ed1686e87d..90b8a6f528 100644
--- a/third_party/rust/nix/test/sys/test_socket.rs
+++ b/third_party/rust/nix/test/sys/test_socket.rs
@@ -1,4 +1,4 @@
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
use crate::*;
use libc::c_char;
use nix::sys::socket::{getsockname, AddressFamily, UnixAddr};
@@ -21,7 +21,7 @@ pub fn test_timestamping() {
};
use std::io::{IoSlice, IoSliceMut};
- let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6797").unwrap();
let ssock = socket(
AddressFamily::Inet,
@@ -72,15 +72,134 @@ pub fn test_timestamping() {
assert!(std::time::Duration::from(diff).as_secs() < 60);
}
+#[cfg(target_os = "freebsd")]
+#[test]
+pub fn test_timestamping_realtime() {
+ use nix::sys::socket::{
+ recvmsg, sendmsg, setsockopt, socket, sockopt::ReceiveTimestamp,
+ sockopt::TsClock, ControlMessageOwned, MsgFlags, SockFlag, SockType,
+ SockaddrIn, SocketTimestamp,
+ };
+ use std::io::{IoSlice, IoSliceMut};
+
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6792").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.as_raw_fd(), &sock_addr).unwrap();
+
+ setsockopt(&rsock, ReceiveTimestamp, &true).unwrap();
+ setsockopt(&rsock, TsClock, &SocketTimestamp::SO_TS_REALTIME).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::time::TimeVal);
+ sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
+ let recv =
+ recvmsg::<()>(rsock.as_raw_fd(), &mut iov2, Some(&mut cmsg), flags)
+ .unwrap();
+
+ let mut ts = None;
+ for c in recv.cmsgs() {
+ if let ControlMessageOwned::ScmRealtime(timeval) = c {
+ ts = Some(timeval);
+ }
+ }
+ let ts = ts.expect("ScmRealtime 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);
+}
+
+#[cfg(target_os = "freebsd")]
+#[test]
+pub fn test_timestamping_monotonic() {
+ use nix::sys::socket::{
+ recvmsg, sendmsg, setsockopt, socket, sockopt::ReceiveTimestamp,
+ sockopt::TsClock, ControlMessageOwned, MsgFlags, SockFlag, SockType,
+ SockaddrIn, SocketTimestamp,
+ };
+ use std::io::{IoSlice, IoSliceMut};
+
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6803").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.as_raw_fd(), &sock_addr).unwrap();
+
+ setsockopt(&rsock, ReceiveTimestamp, &true).unwrap();
+ setsockopt(&rsock, TsClock, &SocketTimestamp::SO_TS_MONOTONIC).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::time::TimeVal);
+ sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
+ let recv =
+ recvmsg::<()>(rsock.as_raw_fd(), &mut iov2, Some(&mut cmsg), flags)
+ .unwrap();
+
+ let mut ts = None;
+ for c in recv.cmsgs() {
+ if let ControlMessageOwned::ScmMonotonic(timeval) = c {
+ ts = Some(timeval);
+ }
+ }
+ let ts = ts.expect("ScmMonotonic is present");
+ let sys_time =
+ ::nix::time::clock_gettime(::nix::time::ClockId::CLOCK_MONOTONIC)
+ .unwrap();
+ let diff = sys_time - ts; // Monotonic clock sys_time must be greater
+ assert!(std::time::Duration::from(diff).as_secs() < 60);
+}
+
#[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())
- };
+ let expect: &[c_char] =
+ unsafe { slice::from_raw_parts(path.as_ptr().cast(), path.len()) };
assert_eq!(unsafe { &(*addr.as_ptr()).sun_path[..8] }, expect);
assert_eq!(addr.path(), Some(actual));
@@ -105,7 +224,7 @@ pub fn test_addr_equality_path() {
assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[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");
@@ -113,7 +232,7 @@ pub fn test_abstract_sun_path_too_long() {
addr.expect_err("assertion failed");
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_addr_equality_abstract() {
let name = String::from("nix\0abstract\0test");
@@ -129,7 +248,7 @@ pub fn test_addr_equality_abstract() {
}
// Test getting/setting abstract addresses (without unix socket creation)
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_abstract_uds_addr() {
let empty = String::new();
@@ -151,7 +270,7 @@ pub fn test_abstract_uds_addr() {
}
// Test getting an unnamed address (without unix socket creation)
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_unnamed_uds_addr() {
use crate::nix::sys::socket::SockaddrLike;
@@ -200,7 +319,7 @@ pub fn test_socketpair() {
SockFlag::empty(),
)
.unwrap();
- write(fd1.as_raw_fd(), b"hello").unwrap();
+ write(&fd1, b"hello").unwrap();
let mut buf = [0; 5];
read(fd2.as_raw_fd(), &mut buf).unwrap();
@@ -315,7 +434,7 @@ mod recvfrom {
#[test]
pub fn udp() {
- let std_sa = SocketAddrV4::from_str("127.0.0.1:6789").unwrap();
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:6795").unwrap();
let sock_addr = SockaddrIn::from(std_sa);
let rsock = socket(
AddressFamily::Inet,
@@ -437,12 +556,7 @@ mod recvfrom {
}
}
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[test]
pub fn udp_sendmmsg() {
use std::io::IoSlice;
@@ -504,12 +618,7 @@ mod recvfrom {
assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap());
}
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[test]
pub fn udp_recvmmsg() {
use nix::sys::socket::{recvmmsg, MsgFlags};
@@ -565,7 +674,7 @@ mod recvfrom {
let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(
rsock.as_raw_fd(),
&mut data,
- msgs.iter(),
+ msgs.iter_mut(),
MsgFlags::empty(),
None,
)
@@ -585,12 +694,7 @@ mod recvfrom {
send_thread.join().unwrap();
}
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "freebsd",
- target_os = "netbsd",
- ))]
+ #[cfg(any(linux_android, target_os = "freebsd", target_os = "netbsd"))]
#[test]
pub fn udp_recvmmsg_dontwait_short_read() {
use nix::sys::socket::{recvmmsg, MsgFlags};
@@ -653,7 +757,7 @@ mod recvfrom {
let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(
rsock.as_raw_fd(),
&mut data,
- msgs.iter(),
+ msgs.iter_mut(),
MsgFlags::MSG_DONTWAIT,
None,
)
@@ -674,10 +778,10 @@ mod recvfrom {
#[test]
pub fn udp_inet6() {
let addr = std::net::Ipv6Addr::from_str("::1").unwrap();
- let rport = 6789;
+ let rport = 6796;
let rstd_sa = SocketAddrV6::new(addr, rport, 0, 0);
let raddr = SockaddrIn6::from(rstd_sa);
- let sport = 6790;
+ let sport = 6798;
let sstd_sa = SocketAddrV6::new(addr, sport, 0, 0);
let saddr = SockaddrIn6::from(sstd_sa);
let rsock = socket(
@@ -757,7 +861,7 @@ pub fn test_scm_rights() {
{
let iov = [IoSlice::new(b"hello")];
- let fds = [r];
+ let fds = [r.as_raw_fd()];
let cmsg = ControlMessage::ScmRights(&fds);
assert_eq!(
sendmsg::<()>(
@@ -770,7 +874,6 @@ pub fn test_scm_rights() {
.unwrap(),
5
);
- close(r).unwrap();
}
{
@@ -803,16 +906,15 @@ pub fn test_scm_rights() {
let received_r = received_r.expect("Did not receive passed fd");
// Ensure that the received file descriptor works
- write(w.as_raw_fd(), b"world").unwrap();
+ write(&w, b"world").unwrap();
let mut buf = [0u8; 5];
read(received_r.as_raw_fd(), &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(linux_android)]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_cipher() {
@@ -905,7 +1007,7 @@ pub fn test_af_alg_cipher() {
// 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(linux_android)]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_aead() {
@@ -1039,7 +1141,7 @@ pub fn test_af_alg_aead() {
// 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"))]
+#[cfg(any(target_os = "linux", apple_targets, target_os = "netbsd"))]
#[test]
pub fn test_sendmsg_ipv4packetinfo() {
use cfg_if::cfg_if;
@@ -1101,7 +1203,7 @@ pub fn test_sendmsg_ipv4packetinfo() {
// test from).
#[cfg(any(
target_os = "linux",
- target_os = "macos",
+ apple_targets,
target_os = "netbsd",
target_os = "freebsd"
))]
@@ -1158,12 +1260,7 @@ pub fn test_sendmsg_ipv6packetinfo() {
//
// 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",
-))]
+#[cfg(any(freebsdlike, netbsdlike))]
#[test]
pub fn test_sendmsg_ipv4sendsrcaddr() {
use nix::sys::socket::{
@@ -1302,7 +1399,7 @@ pub fn test_sendmsg_empty_cmsgs() {
)
.unwrap();
- for _ in msg.cmsgs() {
+ if msg.cmsgs().next().is_some() {
panic!("unexpected cmsg");
}
assert!(!msg
@@ -1312,19 +1409,14 @@ pub fn test_sendmsg_empty_cmsgs() {
}
}
-#[cfg(any(
- target_os = "android",
- target_os = "linux",
- target_os = "freebsd",
- target_os = "dragonfly",
-))]
+#[cfg(any(linux_android, freebsdlike))]
#[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"))]
+ #[cfg(linux_android)]
use nix::sys::socket::{setsockopt, sockopt::PassCred};
use nix::unistd::{getgid, getpid, getuid};
use std::io::{IoSlice, IoSliceMut};
@@ -1336,16 +1428,16 @@ fn test_scm_credentials() {
SockFlag::empty(),
)
.unwrap();
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
setsockopt(&recv, PassCred, &true).unwrap();
{
let iov = [IoSlice::new(b"hello")];
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
let cred = UnixCredentials::new();
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
let cmsg = ControlMessage::ScmCredentials(&cred);
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
let cmsg = ControlMessage::ScmCreds;
assert_eq!(
sendmsg::<()>(
@@ -1376,9 +1468,9 @@ fn test_scm_credentials() {
for cmsg in msg.cmsgs() {
let cred = match cmsg {
- #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[cfg(linux_android)]
ControlMessageOwned::ScmCredentials(cred) => cred,
- #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[cfg(freebsdlike)]
ControlMessageOwned::ScmCreds(cred) => cred,
other => panic!("unexpected cmsg {other:?}"),
};
@@ -1398,7 +1490,7 @@ fn test_scm_credentials() {
/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
/// `sendmsg` call.
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
#[cfg_attr(qemu, ignore)]
@@ -1410,7 +1502,7 @@ fn test_scm_credentials_and_rights() {
/// Ensure that passing a an oversized control message buffer to recvmsg
/// still works.
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
#[cfg_attr(qemu, ignore)]
@@ -1420,7 +1512,7 @@ fn test_too_large_cmsgspace() {
test_impl_scm_credentials_and_rights(space);
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
use libc::ucred;
use nix::sys::socket::sockopt::PassCred;
@@ -1451,7 +1543,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
gid: getgid().as_raw(),
}
.into();
- let fds = [r];
+ let fds = [r.as_raw_fd()];
let cmsgs = [
ControlMessage::ScmCredentials(&cred),
ControlMessage::ScmRights(&fds),
@@ -1467,7 +1559,6 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
.unwrap(),
5
);
- close(r).unwrap();
}
{
@@ -1510,18 +1601,19 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
let received_r = received_r.expect("Did not receive passed fd");
// Ensure that the received file descriptor works
- write(w.as_raw_fd(), b"world").unwrap();
+ write(&w, b"world").unwrap();
let mut buf = [0u8; 5];
read(received_r.as_raw_fd(), &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::{
+ accept, bind, connect, listen, socket, Backlog, UnixAddr,
+ };
use nix::sys::socket::{SockFlag, SockType};
use nix::unistd::{read, write};
use std::thread;
@@ -1537,7 +1629,7 @@ pub fn test_named_unixdomain() {
.expect("socket failed");
let sockaddr = UnixAddr::new(&sockname).unwrap();
bind(s1.as_raw_fd(), &sockaddr).expect("bind failed");
- listen(&s1, 10).expect("listen failed");
+ listen(&s1, Backlog::new(10).unwrap()).expect("listen failed");
let thr = thread::spawn(move || {
let s2 = socket(
@@ -1548,7 +1640,7 @@ pub fn test_named_unixdomain() {
)
.expect("socket failed");
connect(s2.as_raw_fd(), &sockaddr).expect("connect failed");
- write(s2.as_raw_fd(), b"hello").expect("write failed");
+ write(&s2, b"hello").expect("write failed");
});
let s3 = accept(s1.as_raw_fd()).expect("accept failed");
@@ -1560,8 +1652,16 @@ pub fn test_named_unixdomain() {
assert_eq!(&buf[..], b"hello");
}
+#[test]
+pub fn test_listen_wrongbacklog() {
+ use nix::sys::socket::Backlog;
+
+ assert!(Backlog::new(libc::SOMAXCONN + 1).is_err());
+ assert!(Backlog::new(-2).is_err());
+}
+
// Test using unnamed unix domain addresses
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_unnamed_unixdomain() {
use nix::sys::socket::{getsockname, socketpair};
@@ -1581,7 +1681,7 @@ pub fn test_unnamed_unixdomain() {
}
// Test creating and using unnamed unix domain addresses for autobinding sockets
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_unnamed_unixdomain_autobind() {
use nix::sys::socket::{bind, getsockname, socket};
@@ -1609,7 +1709,7 @@ pub fn test_unnamed_unixdomain_autobind() {
}
// Test creating and using named system control sockets
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(apple_targets)]
#[test]
pub fn test_syscontrol() {
use nix::errno::Errno;
@@ -1635,15 +1735,7 @@ pub fn test_syscontrol() {
// connect(fd.as_raw_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",
-))]
+#[cfg(any(bsd, linux_android))]
fn loopback_address(
family: AddressFamily,
) -> Option<nix::ifaddrs::InterfaceAddress> {
@@ -1670,20 +1762,16 @@ fn loopback_address(
})
}
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
-))]
+#[cfg(any(linux_android, apple_targets, 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 = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc64",
)
),
@@ -1765,20 +1853,16 @@ pub fn test_recv_ipv4pktinfo() {
}
}
-#[cfg(any(
- target_os = "freebsd",
- target_os = "ios",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(bsd)]
// qemu doesn't seem to be emulating this correctly in these architectures
#[cfg_attr(
all(
qemu,
any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc64",
)
),
@@ -1883,7 +1967,7 @@ pub fn test_recvif() {
}
}
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_recvif_ipv4() {
@@ -1969,7 +2053,7 @@ pub fn test_recvif_ipv4() {
}
}
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_recvif_ipv6() {
@@ -2055,22 +2139,16 @@ pub fn test_recvif_ipv6() {
}
}
-#[cfg(any(
- target_os = "android",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
-))]
+#[cfg(any(linux_android, target_os = "freebsd", apple_targets, netbsdlike))]
// qemu doesn't seem to be emulating this correctly in these architectures
#[cfg_attr(
all(
qemu,
any(
target_arch = "mips",
+ target_arch = "mips32r6",
target_arch = "mips64",
+ target_arch = "mips64r6",
target_arch = "powerpc64",
)
),
@@ -2152,7 +2230,7 @@ pub fn test_recv_ipv6pktinfo() {
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
pub fn test_vsock() {
use nix::sys::socket::SockaddrLike;
@@ -2192,7 +2270,7 @@ pub fn test_vsock() {
assert_eq!(addr3.as_ref().svm_port, addr1.port());
}
-#[cfg(target_os = "macos")]
+#[cfg(apple_targets)]
#[test]
pub fn test_vsock() {
use nix::sys::socket::SockaddrLike;
@@ -2329,12 +2407,17 @@ fn test_recvmmsg_timestampns() {
// 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 iov = vec![[IoSliceMut::new(&mut buffer)]];
let mut data = MultiHeaders::preallocate(1, Some(cmsgspace));
- let r: Vec<RecvMsg<()>> =
- recvmmsg(in_socket.as_raw_fd(), &mut data, iov.iter(), flags, None)
- .unwrap()
- .collect();
+ let r: Vec<RecvMsg<()>> = recvmmsg(
+ in_socket.as_raw_fd(),
+ &mut data,
+ iov.iter_mut(),
+ flags,
+ None,
+ )
+ .unwrap()
+ .collect();
let rtime = match r[0].cmsgs().next() {
Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
Some(_) => panic!("Unexpected control message"),
@@ -2353,7 +2436,7 @@ fn test_recvmmsg_timestampns() {
// 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"))]
+#[cfg(any(linux_android, target_os = "fuchsia"))]
#[test]
fn test_recvmsg_rxq_ovfl() {
use nix::sys::socket::sockopt::{RcvBuf, RxqOvfl};
@@ -2447,7 +2530,7 @@ fn test_recvmsg_rxq_ovfl() {
assert_eq!(drop_counter, 1);
}
-#[cfg(any(target_os = "linux", target_os = "android",))]
+#[cfg(linux_android)]
mod linux_errqueue {
use super::FromStr;
use nix::sys::socket::*;
@@ -2685,3 +2768,160 @@ pub fn test_txtime() {
recvmsg::<()>(rsock.as_raw_fd(), &mut iov2, None, MsgFlags::empty())
.unwrap();
}
+
+// cfg needed for capability check.
+#[cfg(linux_android)]
+#[test]
+fn test_icmp_protocol() {
+ use nix::sys::socket::{
+ sendto, socket, AddressFamily, MsgFlags, SockFlag, SockProtocol,
+ SockType, SockaddrIn,
+ };
+
+ require_capability!("test_icmp_protocol", CAP_NET_RAW);
+
+ let owned_fd = socket(
+ AddressFamily::Inet,
+ SockType::Raw,
+ SockFlag::empty(),
+ SockProtocol::Icmp,
+ )
+ .unwrap();
+
+ // Send a minimal ICMP packet with no payload.
+ let packet = [
+ 0x08, // Type
+ 0x00, // Code
+ 0x84, 0x85, // Checksum
+ 0x73, 0x8a, // ID
+ 0x00, 0x00, // Sequence Number
+ ];
+
+ let dest_addr = SockaddrIn::new(127, 0, 0, 1, 0);
+ sendto(owned_fd.as_raw_fd(), &packet, &dest_addr, MsgFlags::empty())
+ .unwrap();
+}
+
+// test contains both recvmmsg and timestaping which is linux only
+// there are existing tests for recvmmsg only in tests/
+#[cfg_attr(qemu, ignore)]
+#[cfg(target_os = "linux")]
+#[test]
+fn test_recvmm2() -> nix::Result<()> {
+ use nix::sys::{
+ socket::{
+ bind, recvmmsg, sendmsg, setsockopt, socket, sockopt::Timestamping,
+ AddressFamily, ControlMessageOwned, MsgFlags, MultiHeaders,
+ SockFlag, SockType, SockaddrIn, TimestampingFlag, Timestamps,
+ },
+ time::TimeSpec,
+ };
+ use std::io::{IoSlice, IoSliceMut};
+ use std::os::unix::io::AsRawFd;
+ use std::str::FromStr;
+
+ let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
+
+ let ssock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )?;
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::SOCK_NONBLOCK,
+ None,
+ )?;
+
+ bind(rsock.as_raw_fd(), &sock_addr)?;
+
+ setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?;
+
+ let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
+
+ let mut recv_buf = vec![0; 1024];
+
+ let mut recv_iovs = Vec::new();
+ let mut pkt_iovs = Vec::new();
+
+ for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() {
+ pkt_iovs.push(IoSliceMut::new(chunk));
+ if ix % 2 == 1 {
+ recv_iovs.push(pkt_iovs);
+ pkt_iovs = Vec::new();
+ }
+ }
+ drop(pkt_iovs);
+
+ let flags = MsgFlags::empty();
+ let iov1 = [IoSlice::new(&sbuf)];
+
+ let cmsg = cmsg_space!(Timestamps);
+ sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
+
+ let mut data = MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
+
+ let t = TimeSpec::from_duration(std::time::Duration::from_secs(10));
+
+ let recv = recvmmsg(
+ rsock.as_raw_fd(),
+ &mut data,
+ recv_iovs.iter_mut(),
+ flags,
+ Some(t),
+ )?;
+
+ for rmsg in recv {
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ let mut saw_time = false;
+ let mut recvd = 0;
+ for cmsg in rmsg.cmsgs() {
+ if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
+ let ts = timestamps.system;
+
+ let sys_time = nix::time::clock_gettime(
+ nix::time::ClockId::CLOCK_REALTIME,
+ )?;
+ let diff = if ts > sys_time {
+ ts - sys_time
+ } else {
+ sys_time - ts
+ };
+ assert!(std::time::Duration::from(diff).as_secs() < 60);
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ {
+ saw_time = true;
+ }
+ }
+ }
+
+ #[cfg(not(any(qemu, target_arch = "aarch64")))]
+ assert!(saw_time);
+
+ for iov in rmsg.iovs() {
+ recvd += iov.len();
+ }
+ assert_eq!(recvd, 400);
+ }
+
+ Ok(())
+}
+
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn can_use_cmsg_space() {
+ let _ = cmsg_space!(u8);
+}
+
+#[cfg(not(any(linux_android, target_os = "redox", target_os = "haiku")))]
+#[test]
+fn can_open_routing_socket() {
+ use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType};
+
+ let _ =
+ socket(AddressFamily::Route, SockType::Raw, SockFlag::empty(), None)
+ .expect("Failed to open routing socket");
+}
diff --git a/third_party/rust/nix/test/sys/test_sockopt.rs b/third_party/rust/nix/test/sys/test_sockopt.rs
index 0e34917325..a99d4e39ed 100644
--- a/third_party/rust/nix/test/sys/test_sockopt.rs
+++ b/third_party/rust/nix/test/sys/test_sockopt.rs
@@ -1,14 +1,14 @@
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
use crate::*;
use nix::sys::socket::{
getsockopt, setsockopt, socket, sockopt, AddressFamily, SockFlag,
SockProtocol, SockType,
};
use rand::{thread_rng, Rng};
-use std::os::unix::io::AsRawFd;
+use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd};
// NB: FreeBSD supports LOCAL_PEERCRED for SOCK_SEQPACKET, but OSX does not.
-#[cfg(any(target_os = "dragonfly", target_os = "freebsd",))]
+#[cfg(freebsdlike)]
#[test]
pub fn test_local_peercred_seqpacket() {
use nix::{
@@ -29,12 +29,7 @@ pub fn test_local_peercred_seqpacket() {
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
}
-#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "ios"
-))]
+#[cfg(any(freebsdlike, apple_targets))]
#[test]
pub fn test_local_peercred_stream() {
use nix::{
@@ -55,7 +50,7 @@ pub fn test_local_peercred_stream() {
assert_eq!(Gid::from_raw(xucred.groups()[0]), Gid::current());
}
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
#[test]
pub fn test_local_peer_pid() {
use nix::sys::socket::socketpair;
@@ -108,15 +103,42 @@ fn test_so_buf() {
assert!(actual >= bufsize);
}
+#[cfg(target_os = "freebsd")]
+#[test]
+fn test_so_listen_q_limit() {
+ use nix::sys::socket::{bind, listen, Backlog, SockaddrIn};
+ use std::net::SocketAddrV4;
+ use std::str::FromStr;
+
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:4004").unwrap();
+ let sock_addr = SockaddrIn::from(std_sa);
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ bind(rsock.as_raw_fd(), &sock_addr).unwrap();
+ let pre_limit = getsockopt(&rsock, sockopt::ListenQLimit).unwrap();
+ assert_eq!(pre_limit, 0);
+ listen(&rsock, Backlog::new(42).unwrap()).unwrap();
+ let post_limit = getsockopt(&rsock, sockopt::ListenQLimit).unwrap();
+ assert_eq!(post_limit, 42);
+}
+
#[test]
fn test_so_tcp_maxseg() {
- use nix::sys::socket::{accept, bind, connect, listen, SockaddrIn};
+ use nix::sys::socket::{
+ accept, bind, connect, getsockname, listen, Backlog, SockaddrIn,
+ };
use nix::unistd::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 std_sa = SocketAddrV4::from_str("127.0.0.1:0").unwrap();
+ let mut sock_addr = SockaddrIn::from(std_sa);
let rsock = socket(
AddressFamily::Inet,
@@ -126,13 +148,14 @@ fn test_so_tcp_maxseg() {
)
.unwrap();
bind(rsock.as_raw_fd(), &sock_addr).unwrap();
- listen(&rsock, 10).unwrap();
+ sock_addr = getsockname(rsock.as_raw_fd()).unwrap();
+ listen(&rsock, Backlog::new(10).unwrap()).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"))] {
+ if #[cfg(linux_android)] {
let segsize: u32 = 873;
assert!(initial < segsize);
setsockopt(&rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
@@ -151,12 +174,13 @@ fn test_so_tcp_maxseg() {
.unwrap();
connect(ssock.as_raw_fd(), &sock_addr).unwrap();
let rsess = accept(rsock.as_raw_fd()).unwrap();
- write(rsess, b"hello").unwrap();
+ let rsess = unsafe { OwnedFd::from_raw_fd(rsess) };
+ 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"))] {
+ if #[cfg(linux_android)] {
assert!((segsize - 100) <= actual);
assert!(actual <= segsize);
} else {
@@ -181,11 +205,10 @@ fn test_so_type() {
/// 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",))]
+#[cfg(linux_android)]
#[test]
fn test_so_type_unknown() {
use nix::errno::Errno;
- use std::os::unix::io::{FromRawFd, OwnedFd};
require_capability!("test_so_type", CAP_NET_RAW);
let raw_fd = unsafe { libc::socket(libc::AF_PACKET, libc::SOCK_PACKET, 0) };
@@ -229,7 +252,7 @@ fn test_tcp_congestion() {
}
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_bindtodevice() {
skip_if_not_root!("test_bindtodevice");
@@ -259,12 +282,7 @@ fn test_so_tcp_keepalive() {
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"
- ))]
+ #[cfg(any(linux_android, freebsdlike))]
{
let x = getsockopt(&fd, sockopt::TcpKeepIdle).unwrap();
setsockopt(&fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
@@ -281,14 +299,14 @@ fn test_so_tcp_keepalive() {
}
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[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_sa = SocketAddrV4::from_str("127.0.0.1:0").unwrap();
let std_sb = SocketAddrV4::from_str("127.0.0.1:4002").unwrap();
let usock = socket(
@@ -308,7 +326,7 @@ fn test_get_mtu() {
}
#[test]
-#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
fn test_ttl_opts() {
let fd4 = socket(
AddressFamily::Inet,
@@ -331,7 +349,48 @@ fn test_ttl_opts() {
}
#[test]
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(any(linux_android, target_os = "freebsd"))]
+fn test_multicast_ttl_opts_ipv4() {
+ let fd4 = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd4, sockopt::IpMulticastTtl, &2)
+ .expect("setting ipmulticastttl on an inet socket should succeed");
+}
+
+#[test]
+#[cfg(linux_android)]
+fn test_multicast_ttl_opts_ipv6() {
+ let fd6 = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd6, sockopt::IpMulticastTtl, &2)
+ .expect("setting ipmulticastttl on an inet6 socket should succeed");
+}
+
+#[test]
+fn test_ipv6_multicast_hops() {
+ let fd6 = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd6, sockopt::Ipv6MulticastHops, &7)
+ .expect("setting ipv6multicasthops on an inet6 socket should succeed");
+}
+
+#[test]
+#[cfg(apple_targets)]
fn test_dontfrag_opts() {
let fd4 = socket(
AddressFamily::Inet,
@@ -361,12 +420,7 @@ fn test_dontfrag_opts() {
}
#[test]
-#[cfg(any(
- target_os = "android",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
-))]
+#[cfg(any(linux_android, apple_targets))]
// Disable the test under emulation because it fails in Cirrus-CI. Lack
// of QEMU support is suspected.
#[cfg_attr(qemu, ignore)]
@@ -446,3 +500,331 @@ fn test_ipv6_tclass() {
setsockopt(&fd, sockopt::Ipv6TClass, &class).unwrap();
assert_eq!(getsockopt(&fd, sockopt::Ipv6TClass).unwrap(), class);
}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_receive_timestamp() {
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+ assert!(getsockopt(&fd, sockopt::ReceiveTimestamp).unwrap());
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_realtime_micro() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(
+ &fd,
+ sockopt::TsClock,
+ &SocketTimestamp::SO_TS_REALTIME_MICRO,
+ )
+ .unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_REALTIME_MICRO
+ );
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_bintime() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(&fd, sockopt::TsClock, &SocketTimestamp::SO_TS_BINTIME).unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_BINTIME
+ );
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_realtime() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(&fd, sockopt::TsClock, &SocketTimestamp::SO_TS_REALTIME)
+ .unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_REALTIME
+ );
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_ts_clock_monotonic() {
+ use nix::sys::socket::SocketTimestamp;
+
+ let fd = socket(
+ AddressFamily::Inet6,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+
+ // FreeBSD setsockopt docs say to set SO_TS_CLOCK after setting SO_TIMESTAMP.
+ setsockopt(&fd, sockopt::ReceiveTimestamp, &true).unwrap();
+
+ setsockopt(&fd, sockopt::TsClock, &SocketTimestamp::SO_TS_MONOTONIC)
+ .unwrap();
+ assert_eq!(
+ getsockopt(&fd, sockopt::TsClock).unwrap(),
+ SocketTimestamp::SO_TS_MONOTONIC
+ );
+}
+
+#[test]
+#[cfg(linux_android)]
+// Disable the test under emulation because it fails with ENOPROTOOPT in CI
+// on cross target. Lack of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
+fn test_ip_bind_address_no_port() {
+ let fd = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ setsockopt(&fd, sockopt::IpBindAddressNoPort, &true).expect(
+ "setting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ );
+ assert!(getsockopt(&fd, sockopt::IpBindAddressNoPort).expect(
+ "getting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ ));
+ setsockopt(&fd, sockopt::IpBindAddressNoPort, &false).expect(
+ "unsetting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ );
+ assert!(!getsockopt(&fd, sockopt::IpBindAddressNoPort).expect(
+ "getting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed",
+ ));
+}
+
+#[test]
+#[cfg(linux_android)]
+fn test_tcp_fast_open_connect() {
+ let fd = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ setsockopt(&fd, sockopt::TcpFastOpenConnect, &true).expect(
+ "setting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ );
+ assert!(getsockopt(&fd, sockopt::TcpFastOpenConnect).expect(
+ "getting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ ));
+ setsockopt(&fd, sockopt::TcpFastOpenConnect, &false).expect(
+ "unsetting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ );
+ assert!(!getsockopt(&fd, sockopt::TcpFastOpenConnect).expect(
+ "getting TCP_FASTOPEN_CONNECT on an inet stream socket should succeed",
+ ));
+}
+
+#[cfg(linux_android)]
+#[test]
+fn can_get_peercred_on_unix_socket() {
+ use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType};
+
+ let (a, b) = socketpair(
+ AddressFamily::Unix,
+ SockType::Stream,
+ None,
+ SockFlag::empty(),
+ )
+ .unwrap();
+ let a_cred = getsockopt(&a, sockopt::PeerCredentials).unwrap();
+ let b_cred = getsockopt(&b, sockopt::PeerCredentials).unwrap();
+ assert_eq!(a_cred, b_cred);
+ assert_ne!(a_cred.pid(), 0);
+}
+
+#[test]
+fn is_socket_type_unix() {
+ use nix::sys::socket::{socketpair, sockopt, SockFlag, SockType};
+
+ let (a, _b) = socketpair(
+ AddressFamily::Unix,
+ SockType::Stream,
+ None,
+ SockFlag::empty(),
+ )
+ .unwrap();
+ let a_type = getsockopt(&a, sockopt::SockType).unwrap();
+ assert_eq!(a_type, SockType::Stream);
+}
+
+#[test]
+fn is_socket_type_dgram() {
+ use nix::sys::socket::{
+ getsockopt, sockopt, AddressFamily, SockFlag, SockType,
+ };
+
+ let s = socket(
+ AddressFamily::Inet,
+ SockType::Datagram,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ let s_type = getsockopt(&s, sockopt::SockType).unwrap();
+ assert_eq!(s_type, SockType::Datagram);
+}
+
+#[cfg(any(target_os = "freebsd", target_os = "linux"))]
+#[test]
+fn can_get_listen_on_tcp_socket() {
+ use nix::sys::socket::{
+ getsockopt, listen, socket, sockopt, AddressFamily, Backlog, SockFlag,
+ SockType,
+ };
+
+ let s = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ None,
+ )
+ .unwrap();
+ let s_listening = getsockopt(&s, sockopt::AcceptConn).unwrap();
+ assert!(!s_listening);
+ listen(&s, Backlog::new(10).unwrap()).unwrap();
+ let s_listening2 = getsockopt(&s, sockopt::AcceptConn).unwrap();
+ assert!(s_listening2);
+}
+
+#[cfg(target_os = "linux")]
+// Some architectures running under cross don't support `setsockopt(SOL_TCP, TCP_ULP)`
+// because the cross image is based on Ubuntu 16.04 which predates TCP ULP support
+// (it was added in kernel v4.13 released in 2017). For these architectures,
+// the `setsockopt(SOL_TCP, TCP_ULP, "tls", sizeof("tls"))` call succeeds
+// but the subsequent `setsockopt(SOL_TLS, TLS_TX, ...)` call fails with `ENOPROTOOPT`.
+// It's as if the first `setsockopt` call enabled some other option, not `TCP_ULP`.
+// For example, `strace` says:
+//
+// [pid 813] setsockopt(4, SOL_TCP, 0x1f /* TCP_??? */, [7564404], 4) = 0
+//
+// It's not clear why `setsockopt(SOL_TCP, TCP_ULP)` succeeds if the container image libc doesn't support it,
+// but in any case we can't run the test on such an architecture, so skip it.
+#[cfg_attr(qemu, ignore)]
+#[test]
+fn test_ktls() {
+ use nix::sys::socket::{
+ accept, bind, connect, getsockname, listen, Backlog, SockaddrIn,
+ };
+ use std::net::SocketAddrV4;
+ use std::str::FromStr;
+
+ let std_sa = SocketAddrV4::from_str("127.0.0.1:0").unwrap();
+ let mut sock_addr = SockaddrIn::from(std_sa);
+
+ let rsock = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ bind(rsock.as_raw_fd(), &sock_addr).unwrap();
+ sock_addr = getsockname(rsock.as_raw_fd()).unwrap();
+ listen(&rsock, Backlog::new(10).unwrap()).unwrap();
+
+ let ssock = socket(
+ AddressFamily::Inet,
+ SockType::Stream,
+ SockFlag::empty(),
+ SockProtocol::Tcp,
+ )
+ .unwrap();
+ connect(ssock.as_raw_fd(), &sock_addr).unwrap();
+
+ let _rsess = accept(rsock.as_raw_fd()).unwrap();
+
+ match setsockopt(&ssock, sockopt::TcpUlp::default(), b"tls") {
+ Ok(()) => (),
+
+ // TLS ULP is not enabled, so we can't test kTLS.
+ Err(nix::Error::ENOENT) => skip!("TLS ULP is not enabled"),
+
+ Err(err) => panic!("{err:?}"),
+ }
+
+ // In real life we would do a TLS handshake and extract the protocol version and secrets.
+ // For this test we just make some up.
+
+ let tx = sockopt::TlsCryptoInfo::Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128 {
+ info: libc::tls_crypto_info {
+ version: libc::TLS_1_2_VERSION,
+ cipher_type: libc::TLS_CIPHER_AES_GCM_128,
+ },
+ iv: *b"\x04\x05\x06\x07\x08\x09\x0a\x0b",
+ key: *b"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ salt: *b"\x00\x01\x02\x03",
+ rec_seq: *b"\x00\x00\x00\x00\x00\x00\x00\x00",
+ });
+ setsockopt(&ssock, sockopt::TcpTlsTx, &tx)
+ .expect("setting TLS_TX after enabling TLS ULP should succeed");
+
+ let rx = sockopt::TlsCryptoInfo::Aes128Gcm(libc::tls12_crypto_info_aes_gcm_128 {
+ info: libc::tls_crypto_info {
+ version: libc::TLS_1_2_VERSION,
+ cipher_type: libc::TLS_CIPHER_AES_GCM_128,
+ },
+ iv: *b"\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb",
+ key: *b"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
+ salt: *b"\xf0\xf1\xf2\xf3",
+ rec_seq: *b"\x00\x00\x00\x00\x00\x00\x00\x00",
+ });
+ match setsockopt(&ssock, sockopt::TcpTlsRx, &rx) {
+ Ok(()) => (),
+ Err(nix::Error::ENOPROTOOPT) => {
+ // TLS_TX was added in v4.13 and TLS_RX in v4.17, so we appear to be between that range.
+ // It's good enough that TLS_TX worked, so let the test succeed.
+ }
+ Err(err) => panic!("{err:?}"),
+ }
+}
diff --git a/third_party/rust/nix/test/sys/test_statfs.rs b/third_party/rust/nix/test/sys/test_statfs.rs
new file mode 100644
index 0000000000..66b3f2ce96
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_statfs.rs
@@ -0,0 +1,99 @@
+use nix::sys::statfs::*;
+use nix::sys::statvfs::*;
+use std::fs::File;
+use std::path::Path;
+
+fn check_fstatfs(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes()).unwrap();
+ let file = File::open(path).unwrap();
+ let fs = fstatfs(&file).unwrap();
+ assert_fs_equals(fs, vfs);
+}
+
+fn check_statfs(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes()).unwrap();
+ let fs = statfs(path.as_bytes()).unwrap();
+ assert_fs_equals(fs, vfs);
+}
+
+fn check_fstatfs_strict(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes());
+ let file = File::open(path).unwrap();
+ let fs = fstatfs(&file);
+ assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
+}
+
+fn check_statfs_strict(path: &str) {
+ if !Path::new(path).exists() {
+ return;
+ }
+ let vfs = statvfs(path.as_bytes());
+ let fs = statfs(path.as_bytes());
+ assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
+}
+
+// The cast is not unnecessary on all platforms.
+#[allow(clippy::unnecessary_cast)]
+fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
+ assert_eq!(fs.files() as u64, vfs.files() as u64);
+ assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
+ assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
+}
+
+#[test]
+fn statfs_call() {
+ check_statfs("/tmp");
+ check_statfs("/dev");
+ check_statfs("/run");
+ check_statfs("/");
+}
+
+#[test]
+fn fstatfs_call() {
+ check_fstatfs("/tmp");
+ check_fstatfs("/dev");
+ check_fstatfs("/run");
+ check_fstatfs("/");
+}
+
+// This test is ignored because files_free/blocks_free can change after statvfs call and before
+// statfs call.
+#[test]
+#[ignore]
+fn statfs_call_strict() {
+ check_statfs_strict("/tmp");
+ check_statfs_strict("/dev");
+ check_statfs_strict("/run");
+ check_statfs_strict("/");
+}
+
+// This test is ignored because files_free/blocks_free can change after statvfs call and before
+// fstatfs call.
+#[test]
+#[ignore]
+fn fstatfs_call_strict() {
+ check_fstatfs_strict("/tmp");
+ check_fstatfs_strict("/dev");
+ check_fstatfs_strict("/run");
+ check_fstatfs_strict("/");
+}
+
+// The cast is not unnecessary on all platforms.
+#[allow(clippy::unnecessary_cast)]
+fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
+ assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
+ assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
+ assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
+ assert_eq!(fs.files() as u64, vfs.files() as u64);
+ assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
+ assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
+}
diff --git a/third_party/rust/nix/test/sys/test_statvfs.rs b/third_party/rust/nix/test/sys/test_statvfs.rs
new file mode 100644
index 0000000000..5c80965253
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_statvfs.rs
@@ -0,0 +1,13 @@
+use nix::sys::statvfs::*;
+use std::fs::File;
+
+#[test]
+fn statvfs_call() {
+ statvfs(&b"/"[..]).unwrap();
+}
+
+#[test]
+fn fstatvfs_call() {
+ let root = File::open("/").unwrap();
+ fstatvfs(&root).unwrap();
+}
diff --git a/third_party/rust/nix/test/sys/test_termios.rs b/third_party/rust/nix/test/sys/test_termios.rs
index 83919378a7..35cc7ab739 100644
--- a/third_party/rust/nix/test/sys/test_termios.rs
+++ b/third_party/rust/nix/test/sys/test_termios.rs
@@ -4,17 +4,26 @@ use tempfile::tempfile;
use nix::errno::Errno;
use nix::fcntl;
use nix::pty::openpty;
-use nix::sys::termios::{self, tcgetattr, LocalFlags, OutputFlags};
+use nix::sys::termios::{self, tcgetattr, BaudRate, LocalFlags, OutputFlags};
use nix::unistd::{read, write};
/// Helper function analogous to `std::io::Write::write_all`, but for `Fd`s
fn write_all<Fd: AsFd>(f: Fd, buf: &[u8]) {
let mut len = 0;
while len < buf.len() {
- len += write(f.as_fd().as_raw_fd(), &buf[len..]).unwrap();
+ len += write(f.as_fd(), &buf[len..]).unwrap();
}
}
+#[test]
+fn test_baudrate_try_from() {
+ assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
+ #[cfg(not(target_os = "haiku"))]
+ BaudRate::try_from(999999999).expect_err("assertion failed");
+ #[cfg(target_os = "haiku")]
+ BaudRate::try_from(99).expect_err("assertion failed");
+}
+
// Test tcgetattr on a terminal
#[test]
fn test_tcgetattr_pty() {
diff --git a/third_party/rust/nix/test/sys/test_time.rs b/third_party/rust/nix/test/sys/test_time.rs
new file mode 100644
index 0000000000..0510225a92
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_time.rs
@@ -0,0 +1,91 @@
+use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
+use std::time::Duration;
+
+#[test]
+pub fn test_timespec() {
+ assert_ne!(TimeSpec::seconds(1), TimeSpec::zero());
+ assert_eq!(
+ TimeSpec::seconds(1) + TimeSpec::seconds(2),
+ TimeSpec::seconds(3)
+ );
+ assert_eq!(
+ TimeSpec::minutes(3) + TimeSpec::seconds(2),
+ TimeSpec::seconds(182)
+ );
+}
+
+#[test]
+pub fn test_timespec_from() {
+ let duration = Duration::new(123, 123_456_789);
+ let timespec = TimeSpec::nanoseconds(123_123_456_789);
+
+ assert_eq!(TimeSpec::from(duration), timespec);
+ assert_eq!(Duration::from(timespec), duration);
+}
+
+#[test]
+pub fn test_timespec_neg() {
+ let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
+ let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123);
+
+ assert_eq!(a, -b);
+}
+
+#[test]
+pub fn test_timespec_ord() {
+ assert_eq!(TimeSpec::seconds(1), TimeSpec::nanoseconds(1_000_000_000));
+ assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001));
+ assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999));
+ assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999));
+ assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001));
+}
+
+#[test]
+pub fn test_timespec_fmt() {
+ assert_eq!(TimeSpec::zero().to_string(), "0 seconds");
+ assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds");
+ assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds");
+ assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds");
+ assert_eq!(TimeSpec::nanoseconds(42).to_string(), "0.000000042 seconds");
+ assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds");
+}
+
+#[test]
+pub fn test_timeval() {
+ assert_ne!(TimeVal::seconds(1), TimeVal::zero());
+ assert_eq!(
+ TimeVal::seconds(1) + TimeVal::seconds(2),
+ TimeVal::seconds(3)
+ );
+ assert_eq!(
+ TimeVal::minutes(3) + TimeVal::seconds(2),
+ TimeVal::seconds(182)
+ );
+}
+
+#[test]
+pub fn test_timeval_ord() {
+ assert_eq!(TimeVal::seconds(1), TimeVal::microseconds(1_000_000));
+ assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001));
+ assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999));
+ assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999));
+ assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001));
+}
+
+#[test]
+pub fn test_timeval_neg() {
+ let a = TimeVal::seconds(1) + TimeVal::microseconds(123);
+ let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123);
+
+ assert_eq!(a, -b);
+}
+
+#[test]
+pub fn test_timeval_fmt() {
+ assert_eq!(TimeVal::zero().to_string(), "0 seconds");
+ assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds");
+ assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds");
+ assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds");
+ assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds");
+ assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds");
+}
diff --git a/third_party/rust/nix/test/test_timer.rs b/third_party/rust/nix/test/sys/test_timer.rs
index ffd146867b..ffd146867b 100644
--- a/third_party/rust/nix/test/test_timer.rs
+++ b/third_party/rust/nix/test/sys/test_timer.rs
diff --git a/third_party/rust/nix/test/sys/test_uio.rs b/third_party/rust/nix/test/sys/test_uio.rs
index fc09465f19..d035a7bb04 100644
--- a/third_party/rust/nix/test/sys/test_uio.rs
+++ b/third_party/rust/nix/test/sys/test_uio.rs
@@ -4,7 +4,7 @@ use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use std::fs::OpenOptions;
use std::io::IoSlice;
-use std::os::unix::io::{FromRawFd, OwnedFd};
+use std::os::unix::io::AsRawFd;
use std::{cmp, iter};
#[cfg(not(target_os = "redox"))]
@@ -44,22 +44,17 @@ fn test_writev() {
// FileDesc will close its filedesc (reader).
let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
- // Temporary workaround to cope with the existing RawFd pipe(2), should be
- // removed when pipe(2) becomes I/O-safe.
- let writer = unsafe { OwnedFd::from_raw_fd(writer) };
-
// 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_res = read(reader.as_raw_fd(), &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(reader).expect("closed reader");
}
#[test]
@@ -92,10 +87,6 @@ fn test_readv() {
// Blocking io, should write all data.
write(writer, &to_write).expect("write failed");
- // Temporary workaround to cope with the existing RawFd pipe(2), should be
- // removed when pipe(2) becomes I/O-safe.
- let reader = unsafe { OwnedFd::from_raw_fd(reader) };
-
let read = readv(&reader, &mut iovecs[..]).expect("read failed");
// Check whether we've read all data
assert_eq!(to_write.len(), read);
@@ -108,7 +99,6 @@ fn test_readv() {
assert_eq!(read_buf.len(), to_write.len());
// Check equality of written and read data
assert_eq!(&read_buf, &to_write);
- close(writer).expect("couldn't close writer");
}
#[test]
@@ -150,7 +140,11 @@ fn test_pread() {
}
#[test]
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+#[cfg(not(any(
+ target_os = "redox",
+ target_os = "haiku",
+ target_os = "solaris"
+)))]
fn test_pwritev() {
use std::io::Read;
@@ -185,7 +179,11 @@ fn test_pwritev() {
}
#[test]
-#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+#[cfg(not(any(
+ target_os = "redox",
+ target_os = "haiku",
+ target_os = "solaris"
+)))]
fn test_preadv() {
use std::io::Write;
@@ -230,6 +228,7 @@ fn test_process_vm_readv() {
use nix::sys::signal::*;
use nix::sys::wait::*;
use nix::unistd::ForkResult::*;
+ use std::os::unix::io::AsRawFd;
require_capability!("test_process_vm_readv", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock();
@@ -241,10 +240,10 @@ fn test_process_vm_readv() {
let (r, w) = pipe().unwrap();
match unsafe { fork() }.expect("Error: Fork Failed") {
Parent { child } => {
- close(w).unwrap();
+ drop(w);
// wait for child
- read(r, &mut [0u8]).unwrap();
- close(r).unwrap();
+ read(r.as_raw_fd(), &mut [0u8]).unwrap();
+ drop(r);
let ptr = vector.as_ptr() as usize;
let remote_iov = RemoteIoVec { base: ptr, len: 5 };
@@ -263,12 +262,11 @@ fn test_process_vm_readv() {
assert_eq!(20u8, buf.iter().sum());
}
Child => {
- let _ = close(r);
+ drop(r);
for i in &mut vector {
*i += 1;
}
let _ = write(w, b"\0");
- let _ = close(w);
loop {
pause();
}
diff --git a/third_party/rust/nix/test/sys/test_utsname.rs b/third_party/rust/nix/test/sys/test_utsname.rs
new file mode 100644
index 0000000000..8f84ac074f
--- /dev/null
+++ b/third_party/rust/nix/test/sys/test_utsname.rs
@@ -0,0 +1,17 @@
+#[cfg(target_os = "linux")]
+#[test]
+pub fn test_uname_linux() {
+ assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "Linux");
+}
+
+#[cfg(apple_targets)]
+#[test]
+pub fn test_uname_darwin() {
+ assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "Darwin");
+}
+
+#[cfg(target_os = "freebsd")]
+#[test]
+pub fn test_uname_freebsd() {
+ assert_eq!(nix::sys::utsname::uname().unwrap().sysname(), "FreeBSD");
+}
diff --git a/third_party/rust/nix/test/sys/test_wait.rs b/third_party/rust/nix/test/sys/test_wait.rs
index d472f1ec19..365b0165f8 100644
--- a/third_party/rust/nix/test/sys/test_wait.rs
+++ b/third_party/rust/nix/test/sys/test_wait.rs
@@ -33,7 +33,12 @@ fn test_wait_signal() {
//target_os = "haiku",
all(target_os = "linux", not(target_env = "uclibc")),
))]
-#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+#[cfg(not(any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+)))]
fn test_waitid_signal() {
let _m = crate::FORK_MTX.lock();
@@ -76,7 +81,12 @@ fn test_wait_exit() {
target_os = "haiku",
all(target_os = "linux", not(target_env = "uclibc")),
))]
-#[cfg(not(any(target_arch = "mips", target_arch = "mips64")))]
+#[cfg(not(any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+)))]
fn test_waitid_exit() {
let _m = crate::FORK_MTX.lock();
@@ -140,7 +150,7 @@ fn test_waitid_pid() {
}
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
// FIXME: qemu-user doesn't implement ptrace on most arches
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod ptrace {
diff --git a/third_party/rust/nix/test/test.rs b/third_party/rust/nix/test/test.rs
index 7e73bb3056..c7231426c2 100644
--- a/third_party/rust/nix/test/test.rs
+++ b/third_party/rust/nix/test/test.rs
@@ -7,12 +7,14 @@ mod common;
mod sys;
#[cfg(not(target_os = "redox"))]
mod test_dir;
+mod test_errno;
mod test_fcntl;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
mod test_kmod;
+#[cfg(target_os = "linux")]
+mod test_mount;
#[cfg(any(
- target_os = "dragonfly",
- target_os = "freebsd",
+ freebsdlike,
target_os = "fushsia",
target_os = "linux",
target_os = "netbsd"
@@ -30,36 +32,16 @@ mod test_poll;
target_os = "haiku"
)))]
mod test_pty;
-mod test_resource;
#[cfg(any(
- target_os = "android",
+ linux_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"
-))]
+#[cfg(any(linux_android, freebsdlike, apple_targets, solarish))]
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};
diff --git a/third_party/rust/nix/test/test_dir.rs b/third_party/rust/nix/test/test_dir.rs
index 2af4aa5c0a..24ecd6963e 100644
--- a/third_party/rust/nix/test/test_dir.rs
+++ b/third_party/rust/nix/test/test_dir.rs
@@ -6,10 +6,10 @@ use tempfile::tempdir;
#[cfg(test)]
fn flags() -> OFlag {
- #[cfg(target_os = "illumos")]
+ #[cfg(solarish)]
let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC;
- #[cfg(not(target_os = "illumos"))]
+ #[cfg(not(solarish))]
let f = OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_DIRECTORY;
f
diff --git a/third_party/rust/nix/test/test_errno.rs b/third_party/rust/nix/test/test_errno.rs
new file mode 100644
index 0000000000..750fc924ff
--- /dev/null
+++ b/third_party/rust/nix/test/test_errno.rs
@@ -0,0 +1,16 @@
+use nix::errno::Errno;
+
+#[test]
+fn errno_set_and_read() {
+ Errno::ENFILE.set();
+ assert_eq!(Errno::last(), Errno::ENFILE);
+}
+
+#[test]
+fn errno_set_and_clear() {
+ Errno::ENFILE.set();
+ assert_eq!(Errno::last(), Errno::ENFILE);
+
+ Errno::clear();
+ assert_eq!(Errno::last(), Errno::from_raw(0));
+}
diff --git a/third_party/rust/nix/test/test_fcntl.rs b/third_party/rust/nix/test/test_fcntl.rs
index 5fef04ba9b..6572e8af8d 100644
--- a/third_party/rust/nix/test/test_fcntl.rs
+++ b/third_party/rust/nix/test/test_fcntl.rs
@@ -42,7 +42,7 @@ fn test_openat() {
open(tmp.path().parent().unwrap(), OFlag::empty(), Mode::empty())
.unwrap();
let fd = openat(
- dirfd,
+ Some(dirfd),
tmp.path().file_name().unwrap(),
OFlag::O_RDONLY,
Mode::empty(),
@@ -222,7 +222,7 @@ fn test_readlink() {
assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir);
assert_eq!(
- readlinkat(dirfd, "b").unwrap().to_str().unwrap(),
+ readlinkat(Some(dirfd), "b").unwrap().to_str().unwrap(),
expected_dir
);
}
@@ -234,10 +234,9 @@ fn test_readlink() {
/// The from_offset should be updated by the call to reflect
/// the 3 bytes read (6).
#[cfg(any(
- target_os = "linux",
+ linux_android,
// Not available until FreeBSD 13.0
all(target_os = "freebsd", fbsd14),
- target_os = "android"
))]
#[test]
// QEMU does not support copy_file_range. Skip under qemu
@@ -272,7 +271,7 @@ fn test_copy_file_range() {
assert_eq!(from_offset, 6);
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
mod linux_android {
use libc::loff_t;
use std::io::prelude::*;
@@ -280,7 +279,7 @@ mod linux_android {
use std::os::unix::prelude::*;
use nix::fcntl::*;
- use nix::unistd::{close, pipe, read, write};
+ use nix::unistd::{pipe, read, write};
use tempfile::tempfile;
#[cfg(target_os = "linux")]
@@ -299,7 +298,7 @@ mod linux_android {
let res = splice(
tmp.as_raw_fd(),
Some(&mut offset),
- wr,
+ wr.as_raw_fd(),
None,
2,
SpliceFFlags::empty(),
@@ -309,12 +308,9 @@ mod linux_android {
assert_eq!(2, res);
let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
+ assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"f1", &buf[0..2]);
assert_eq!(7, offset);
-
- close(rd).unwrap();
- close(wr).unwrap();
}
#[test]
@@ -323,24 +319,21 @@ mod linux_android {
let (rd2, wr2) = pipe().unwrap();
write(wr1, b"abc").unwrap();
- let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap();
+ let res =
+ tee(rd1.as_raw_fd(), wr2.as_raw_fd(), 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!(2, read(rd2.as_raw_fd(), &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!(3, read(rd1.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"abc", &buf[0..3]);
-
- close(rd1).unwrap();
- close(wr1).unwrap();
- close(rd2).unwrap();
- close(wr2).unwrap();
}
#[test]
@@ -351,17 +344,15 @@ mod linux_android {
let buf2 = b"defghi";
let iovecs = [IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])];
- let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
+ let res = vmsplice(wr.as_raw_fd(), &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!(6, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"abcdef", &buf[0..6]);
-
- close(rd).unwrap();
- close(wr).unwrap();
}
#[cfg(target_os = "linux")]
@@ -481,8 +472,7 @@ mod linux_android {
}
#[cfg(any(
- target_os = "linux",
- target_os = "android",
+ linux_android,
target_os = "emscripten",
target_os = "fuchsia",
target_os = "wasi",
@@ -494,7 +484,7 @@ mod test_posix_fadvise {
use nix::errno::Errno;
use nix::fcntl::*;
use nix::unistd::pipe;
- use std::os::unix::io::{AsRawFd, RawFd};
+ use std::os::unix::io::AsRawFd;
use tempfile::NamedTempFile;
#[test]
@@ -509,7 +499,7 @@ mod test_posix_fadvise {
fn test_errno() {
let (rd, _wr) = pipe().unwrap();
let res = posix_fadvise(
- rd as RawFd,
+ rd.as_raw_fd(),
0,
100,
PosixFadviseAdvice::POSIX_FADV_WILLNEED,
@@ -519,23 +509,18 @@ mod test_posix_fadvise {
}
#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "dragonfly",
+ linux_android,
+ freebsdlike,
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 std::{io::Read, os::unix::io::AsRawFd};
use tempfile::NamedTempFile;
#[test]
@@ -565,10 +550,133 @@ mod test_posix_fallocate {
#[test]
fn errno() {
let (rd, _wr) = pipe().unwrap();
- let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
+ let err = posix_fallocate(rd.as_raw_fd(), 0, 100).unwrap_err();
match err {
Errno::EINVAL | Errno::ENODEV | Errno::ESPIPE | Errno::EBADF => (),
errno => panic!("unexpected errno {errno}",),
}
}
}
+
+#[cfg(any(target_os = "dragonfly", target_os = "netbsd", apple_targets))]
+#[test]
+fn test_f_get_path() {
+ use nix::fcntl::*;
+ use std::{os::unix::io::AsRawFd, path::PathBuf};
+
+ let tmp = NamedTempFile::new().unwrap();
+ let fd = tmp.as_raw_fd();
+ let mut path = PathBuf::new();
+ let res =
+ fcntl(fd, FcntlArg::F_GETPATH(&mut path)).expect("get path failed");
+ assert_ne!(res, -1);
+ assert_eq!(
+ path.as_path().canonicalize().unwrap(),
+ tmp.path().canonicalize().unwrap()
+ );
+}
+
+#[cfg(apple_targets)]
+#[test]
+fn test_f_get_path_nofirmlink() {
+ use nix::fcntl::*;
+ use std::{os::unix::io::AsRawFd, path::PathBuf};
+
+ let tmp = NamedTempFile::new().unwrap();
+ let fd = tmp.as_raw_fd();
+ let mut path = PathBuf::new();
+ let res = fcntl(fd, FcntlArg::F_GETPATH_NOFIRMLINK(&mut path))
+ .expect("get path failed");
+ let mut tmpstr = String::from("/System/Volumes/Data");
+ tmpstr.push_str(
+ &tmp.path()
+ .canonicalize()
+ .unwrap()
+ .into_os_string()
+ .into_string()
+ .unwrap(),
+ );
+ assert_ne!(res, -1);
+ assert_eq!(
+ path.as_path()
+ .canonicalize()
+ .unwrap()
+ .into_os_string()
+ .into_string()
+ .unwrap(),
+ tmpstr
+ );
+}
+
+#[cfg(all(target_os = "freebsd", target_arch = "x86_64"))]
+#[test]
+fn test_f_kinfo() {
+ use nix::fcntl::*;
+ use std::{os::unix::io::AsRawFd, path::PathBuf};
+
+ let tmp = NamedTempFile::new().unwrap();
+ // With TMPDIR set with UFS, the vnode name is not entered
+ // into the name cache thus path is always empty.
+ // Therefore, we reopen the tempfile a second time for the test
+ // to pass.
+ let tmp2 = File::open(tmp.path()).unwrap();
+ let fd = tmp2.as_raw_fd();
+ let mut path = PathBuf::new();
+ let res = fcntl(fd, FcntlArg::F_KINFO(&mut path)).expect("get path failed");
+ assert_ne!(res, -1);
+ assert_eq!(path, tmp.path());
+}
+
+/// Test `Flock` and associated functions.
+///
+#[cfg(not(any(target_os = "redox", target_os = "solaris")))]
+mod test_flock {
+ use nix::fcntl::*;
+ use tempfile::NamedTempFile;
+
+ /// Verify that `Flock::lock()` correctly obtains a lock, and subsequently unlocks upon drop.
+ #[test]
+ fn verify_lock_and_drop() {
+ // Get 2 `File` handles to same underlying file.
+ let file1 = NamedTempFile::new().unwrap();
+ let file2 = file1.reopen().unwrap();
+ let file1 = file1.into_file();
+
+ // Lock first handle
+ let lock1 = Flock::lock(file1, FlockArg::LockExclusive).unwrap();
+
+ // Attempt to lock second handle
+ let file2 = match Flock::lock(file2, FlockArg::LockExclusiveNonblock) {
+ Ok(_) => panic!("Expected second exclusive lock to fail."),
+ Err((f, _)) => f,
+ };
+
+ // Drop first lock
+ std::mem::drop(lock1);
+
+ // Attempt to lock second handle again (but successfully)
+ if Flock::lock(file2, FlockArg::LockExclusiveNonblock).is_err() {
+ panic!("Expected locking to be successful.");
+ }
+ }
+
+ /// Verify that `Flock::unlock()` correctly obtains unlocks.
+ #[test]
+ fn verify_unlock() {
+ // Get 2 `File` handles to same underlying file.
+ let file1 = NamedTempFile::new().unwrap();
+ let file2 = file1.reopen().unwrap();
+ let file1 = file1.into_file();
+
+ // Lock first handle
+ let lock1 = Flock::lock(file1, FlockArg::LockExclusive).unwrap();
+
+ // Unlock and retain file so any erroneous flocks also remain present.
+ let _file1 = lock1.unlock().unwrap();
+
+ // Attempt to lock second handle.
+ if Flock::lock(file2, FlockArg::LockExclusiveNonblock).is_err() {
+ panic!("Expected locking to be successful.");
+ }
+ }
+}
diff --git a/third_party/rust/nix/test/test_mount.rs b/third_party/rust/nix/test/test_mount.rs
index 5cf00408e8..a4f0903dba 100644
--- a/third_party/rust/nix/test/test_mount.rs
+++ b/third_party/rust/nix/test/test_mount.rs
@@ -1,267 +1,183 @@
-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
+use std::fs::{self, File};
+use std::io::{Read, Write};
+use std::os::unix::fs::OpenOptionsExt;
+use std::os::unix::fs::PermissionsExt;
+use std::process::Command;
+
+use libc::{EACCES, EROFS};
+
+use nix::mount::{mount, umount, MsFlags};
+use nix::sys::stat::{self, Mode};
+
+use crate::*;
+
+static SCRIPT_CONTENTS: &[u8] = b"#!/bin/sh
exit 23";
- const EXPECTED_STATUS: i32 = 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();
+const NONE: Option<&'static [u8]> = None;
- mount(
- NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::empty(),
- NONE,
- )
- .unwrap_or_else(|e| panic!("mount failed: {e}"));
+#[test]
+fn test_mount_tmpfs_without_flags_allows_rwx() {
+ require_capability!(
+ "test_mount_tmpfs_without_flags_allows_rwx",
+ CAP_SYS_ADMIN
+ );
+ 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)
+ .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"))
+ );
- let test_path = tempdir.path().join("test");
+ umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
+}
- // 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}"));
+#[test]
+fn test_mount_rdonly_disallows_write() {
+ require_capability!("test_mount_rdonly_disallows_write", CAP_SYS_ADMIN);
+ 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()
+ );
- // 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}"));
- }
+ umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
+}
- pub fn test_mount_rdonly_disallows_write() {
- let tempdir = tempfile::tempdir().unwrap();
+#[test]
+fn test_mount_noexec_disallows_exec() {
+ require_capability!("test_mount_noexec_disallows_exec", CAP_SYS_ADMIN);
+ 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}")),
+ );
- mount(
- NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::MS_RDONLY,
- NONE,
- )
- .unwrap_or_else(|e| panic!("mount 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()
+ );
- // 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}"));
+}
- umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {e}"));
- }
+#[test]
+fn test_mount_bind() {
+ require_capability!("test_mount_bind", CAP_SYS_ADMIN);
+ let tempdir = tempfile::tempdir().unwrap();
+ let file_name = "test";
- pub fn test_mount_noexec_disallows_exec() {
- let tempdir = tempfile::tempdir().unwrap();
+ {
+ let mount_point = tempfile::tempdir().unwrap();
mount(
+ Some(tempdir.path()),
+ mount_point.path(),
NONE,
- tempdir.path(),
- Some(b"tmpfs".as_ref()),
- MsFlags::MS_NOEXEC,
+ MsFlags::MS_BIND,
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)
+ .open(mount_point.path().join(file_name))
.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}"));
+ umount(mount_point.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);
- }
+ // Verify the file written in the mount shows up in source directory, even
+ // after unmounting.
- 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: {e}. Are unprivileged user namespaces available?").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 {uid} 1\n").as_bytes()))
- .unwrap_or_else(|e| panic!("could not write uid map: {e}"));
- }
+ 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);
}
-
-// 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/third_party/rust/nix/test/test_mq.rs b/third_party/rust/nix/test/test_mq.rs
index 1fd8929c17..874a72b44d 100644
--- a/third_party/rust/nix/test/test_mq.rs
+++ b/third_party/rust/nix/test/test_mq.rs
@@ -112,7 +112,15 @@ fn test_mq_getattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg_attr(
- all(qemu, any(target_arch = "mips", target_arch = "mips64")),
+ all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+ )
+ ),
ignore
)]
fn test_mq_setattr() {
@@ -162,7 +170,15 @@ fn test_mq_setattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg_attr(
- all(qemu, any(target_arch = "mips", target_arch = "mips64")),
+ all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips32r6",
+ target_arch = "mips64",
+ target_arch = "mips64r6"
+ )
+ ),
ignore
)]
fn test_mq_set_nonblocking() {
diff --git a/third_party/rust/nix/test/test_net.rs b/third_party/rust/nix/test/test_net.rs
index c44655a4c9..faba8503fe 100644
--- a/third_party/rust/nix/test/test_net.rs
+++ b/third_party/rust/nix/test/test_net.rs
@@ -1,13 +1,9 @@
use nix::net::if_::*;
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
const LOOPBACK: &[u8] = b"lo";
-#[cfg(not(any(
- target_os = "android",
- target_os = "linux",
- target_os = "haiku"
-)))]
+#[cfg(not(any(linux_android, target_os = "haiku")))]
const LOOPBACK: &[u8] = b"lo0";
#[cfg(target_os = "haiku")]
diff --git a/third_party/rust/nix/test/test_poll.rs b/third_party/rust/nix/test/test_poll.rs
index 045ccd3df1..fcb325494e 100644
--- a/third_party/rust/nix/test/test_poll.rs
+++ b/third_party/rust/nix/test/test_poll.rs
@@ -1,9 +1,9 @@
use nix::{
errno::Errno,
- poll::{poll, PollFd, PollFlags},
- unistd::{close, pipe, write},
+ poll::{poll, PollFd, PollFlags, PollTimeout},
+ unistd::{pipe, write},
};
-use std::os::unix::io::{BorrowedFd, FromRawFd, OwnedFd};
+use std::os::unix::io::{AsFd, BorrowedFd};
macro_rules! loop_while_eintr {
($poll_expr: expr) => {
@@ -20,32 +20,25 @@ macro_rules! loop_while_eintr {
#[test]
fn test_poll() {
let (r, w) = pipe().unwrap();
- let r = unsafe { OwnedFd::from_raw_fd(r) };
- let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
+ let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)];
// Poll an idle pipe. Should timeout
- let nfds = loop_while_eintr!(poll(&mut fds, 100));
+ let nfds = loop_while_eintr!(poll(&mut fds, PollTimeout::from(100u8)));
assert_eq!(nfds, 0);
assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- write(w, b".").unwrap();
+ write(&w, b".").unwrap();
// Poll a readable pipe. Should return an event.
- let nfds = poll(&mut fds, 100).unwrap();
+ let nfds = poll(&mut fds, PollTimeout::from(100u8)).unwrap();
assert_eq!(nfds, 1);
assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- close(w).unwrap();
}
// 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"
-))]
+#[cfg(any(linux_android, freebsdlike))]
#[test]
fn test_ppoll() {
use nix::poll::ppoll;
@@ -54,8 +47,7 @@ fn test_ppoll() {
let timeout = TimeSpec::milliseconds(1);
let (r, w) = pipe().unwrap();
- let r = unsafe { OwnedFd::from_raw_fd(r) };
- let mut fds = [PollFd::new(&r, PollFlags::POLLIN)];
+ let mut fds = [PollFd::new(r.as_fd(), PollFlags::POLLIN)];
// Poll an idle pipe. Should timeout
let sigset = SigSet::empty();
@@ -63,19 +55,18 @@ fn test_ppoll() {
assert_eq!(nfds, 0);
assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- write(w, b".").unwrap();
+ 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));
- close(w).unwrap();
}
#[test]
fn test_pollfd_events() {
let fd_zero = unsafe { BorrowedFd::borrow_raw(0) };
- let mut pfd = PollFd::new(&fd_zero, PollFlags::POLLIN);
+ let mut pfd = PollFd::new(fd_zero.as_fd(), PollFlags::POLLIN);
assert_eq!(pfd.events(), PollFlags::POLLIN);
pfd.set_events(PollFlags::POLLOUT);
assert_eq!(pfd.events(), PollFlags::POLLOUT);
diff --git a/third_party/rust/nix/test/test_pty.rs b/third_party/rust/nix/test/test_pty.rs
index 4cc6620c3c..368ec129b0 100644
--- a/third_party/rust/nix/test/test_pty.rs
+++ b/third_party/rust/nix/test/test_pty.rs
@@ -1,9 +1,9 @@
use std::fs::File;
-use std::io::{Read, Write};
+use std::io::{stdout, Read, Write};
use std::os::unix::prelude::*;
use std::path::Path;
-use libc::{_exit, STDOUT_FILENO};
+use libc::_exit;
use nix::fcntl::{open, OFlag};
use nix::pty::*;
use nix::sys::stat;
@@ -12,7 +12,7 @@ use nix::unistd::{pause, write};
/// Test equivalence of `ptsname` and `ptsname_r`
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptsname_equivalence() {
let _m = crate::PTSNAME_MTX.lock();
@@ -29,7 +29,7 @@ fn test_ptsname_equivalence() {
/// 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"))]
+#[cfg(linux_android)]
fn test_ptsname_copy() {
let _m = crate::PTSNAME_MTX.lock();
@@ -47,7 +47,7 @@ fn test_ptsname_copy() {
/// Test data copying of `ptsname_r`
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptsname_r_copy() {
// Open a new PTTY master
let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
@@ -61,7 +61,7 @@ fn test_ptsname_r_copy() {
/// Test that `ptsname` returns different names for different devices
#[test]
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
fn test_ptsname_unique() {
let _m = crate::PTSNAME_MTX.lock();
@@ -96,7 +96,7 @@ fn open_ptty_pair() -> (PtyMaster, File) {
open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty())
.unwrap();
- #[cfg(target_os = "illumos")]
+ #[cfg(solarish)]
// TODO: rewrite using ioctl!
#[allow(clippy::comparison_chain)]
{
@@ -185,7 +185,7 @@ fn test_openpty() {
// Writing to one should be readable on the other one
let string = "foofoofoo\n";
let mut buf = [0u8; 10];
- write(pty.master.as_raw_fd(), string.as_bytes()).unwrap();
+ write(&pty.master, string.as_bytes()).unwrap();
crate::read_exact(&pty.slave, &mut buf);
assert_eq!(&buf, string.as_bytes());
@@ -199,7 +199,7 @@ fn test_openpty() {
let string2 = "barbarbarbar\n";
let echoed_string2 = "barbarbarbar\r\n";
let mut buf = [0u8; 14];
- write(pty.slave.as_raw_fd(), string2.as_bytes()).unwrap();
+ write(&pty.slave, string2.as_bytes()).unwrap();
crate::read_exact(&pty.master, &mut buf);
assert_eq!(&buf, echoed_string2.as_bytes());
@@ -224,7 +224,7 @@ fn test_openpty_with_termios() {
// Writing to one should be readable on the other one
let string = "foofoofoo\n";
let mut buf = [0u8; 10];
- write(pty.master.as_raw_fd(), string.as_bytes()).unwrap();
+ write(&pty.master, string.as_bytes()).unwrap();
crate::read_exact(&pty.slave, &mut buf);
assert_eq!(&buf, string.as_bytes());
@@ -237,7 +237,7 @@ fn test_openpty_with_termios() {
let string2 = "barbarbarbar\n";
let echoed_string2 = "barbarbarbar\n";
let mut buf = [0u8; 13];
- write(pty.slave.as_raw_fd(), string2.as_bytes()).unwrap();
+ write(&pty.slave, string2.as_bytes()).unwrap();
crate::read_exact(&pty.master, &mut buf);
assert_eq!(&buf, echoed_string2.as_bytes());
@@ -258,7 +258,7 @@ fn test_forkpty() {
let pty = unsafe { forkpty(None, None).unwrap() };
match pty.fork_result {
Child => {
- write(STDOUT_FILENO, string.as_bytes()).unwrap();
+ write(stdout(), string.as_bytes()).unwrap();
pause(); // we need the child to stay alive until the parent calls read
unsafe {
_exit(0);
diff --git a/third_party/rust/nix/test/test_sendfile.rs b/third_party/rust/nix/test/test_sendfile.rs
index b85e030fd3..6333bf8662 100644
--- a/third_party/rust/nix/test/test_sendfile.rs
+++ b/third_party/rust/nix/test/test_sendfile.rs
@@ -1,21 +1,20 @@
use std::io::prelude::*;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-use std::os::unix::io::{FromRawFd, OwnedFd};
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"))] {
+ if #[cfg(linux_android)] {
+ use nix::unistd::{pipe, read};
+ use std::os::unix::io::AsRawFd;
+ } else if #[cfg(any(freebsdlike, apple_targets, solarish))] {
use std::net::Shutdown;
use std::os::unix::net::UnixStream;
}
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg(linux_android)]
#[test]
fn test_sendfile_linux() {
const CONTENTS: &[u8] = b"abcdef123456";
@@ -24,21 +23,14 @@ fn test_sendfile_linux() {
let (rd, wr) = pipe().unwrap();
let mut offset: off_t = 5;
- // The construct of this `OwnedFd` is a temporary workaround, when `pipe(2)`
- // becomes I/O-safe:
- // pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error>
- // then it is no longer needed.
- let wr = unsafe { OwnedFd::from_raw_fd(wr) };
let res = sendfile(&wr, &tmp, Some(&mut offset), 2).unwrap();
assert_eq!(2, res);
let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
+ assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"f1", &buf[0..2]);
assert_eq!(7, offset);
-
- close(rd).unwrap();
}
#[cfg(target_os = "linux")]
@@ -50,21 +42,14 @@ fn test_sendfile64_linux() {
let (rd, wr) = pipe().unwrap();
let mut offset: libc::off64_t = 5;
- // The construct of this `OwnedFd` is a temporary workaround, when `pipe(2)`
- // becomes I/O-safe:
- // pub fn pipe() -> std::result::Result<(OwnedFd, OwnedFd), Error>
- // then it is no longer needed.
- let wr = unsafe { OwnedFd::from_raw_fd(wr) };
let res = sendfile64(&wr, &tmp, Some(&mut offset), 2).unwrap();
assert_eq!(2, res);
let mut buf = [0u8; 1024];
- assert_eq!(2, read(rd, &mut buf).unwrap());
+ assert_eq!(2, read(rd.as_raw_fd(), &mut buf).unwrap());
assert_eq!(b"f1", &buf[0..2]);
assert_eq!(7, offset);
-
- close(rd).unwrap();
}
#[cfg(target_os = "freebsd")]
@@ -167,7 +152,7 @@ fn test_sendfile_dragonfly() {
assert_eq!(expected_string, read_string);
}
-#[cfg(any(target_os = "ios", target_os = "macos"))]
+#[cfg(apple_targets)]
#[test]
fn test_sendfile_darwin() {
// Declare the content
@@ -215,3 +200,62 @@ fn test_sendfile_darwin() {
assert_eq!(bytes_written as usize, bytes_read);
assert_eq!(expected_string, read_string);
}
+
+#[cfg(solarish)]
+#[test]
+fn test_sendfilev() {
+ use std::os::fd::AsFd;
+ // Declare the content
+ let header_strings =
+ ["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
+ let body = "Xabcdef123456";
+ let body_offset = 1usize;
+ let trailer_strings = ["\n", "Served by Make Believe\n"];
+
+ // Write data to files
+ let mut header_data = tempfile().unwrap();
+ header_data
+ .write_all(header_strings.concat().as_bytes())
+ .unwrap();
+ let mut body_data = tempfile().unwrap();
+ body_data.write_all(body.as_bytes()).unwrap();
+ let mut trailer_data = tempfile().unwrap();
+ trailer_data
+ .write_all(trailer_strings.concat().as_bytes())
+ .unwrap();
+ let (mut rd, wr) = UnixStream::pair().unwrap();
+ let vec: &[SendfileVec] = &[
+ SendfileVec::new(
+ header_data.as_fd(),
+ 0,
+ header_strings.iter().map(|s| s.len()).sum(),
+ ),
+ SendfileVec::new(
+ body_data.as_fd(),
+ body_offset as off_t,
+ body.len() - body_offset,
+ ),
+ SendfileVec::new(
+ trailer_data.as_fd(),
+ 0,
+ trailer_strings.iter().map(|s| s.len()).sum(),
+ ),
+ ];
+
+ let (res, bytes_written) = sendfilev(&wr, vec);
+ 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, 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, bytes_read);
+ assert_eq!(expected_string, read_string);
+}
diff --git a/third_party/rust/nix/test/test_stat.rs b/third_party/rust/nix/test/test_stat.rs
index 55f15c0771..386f1084cc 100644
--- a/third_party/rust/nix/test/test_stat.rs
+++ b/third_party/rust/nix/test/test_stat.rs
@@ -21,8 +21,7 @@ use nix::errno::Errno;
use nix::fcntl;
#[cfg(any(
target_os = "linux",
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
@@ -117,7 +116,7 @@ fn test_fstatat() {
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty());
let result =
- stat::fstatat(dirfd.unwrap(), &filename, fcntl::AtFlags::empty());
+ stat::fstatat(Some(dirfd.unwrap()), &filename, fcntl::AtFlags::empty());
assert_stat_results(result);
}
@@ -235,8 +234,7 @@ fn test_utimes() {
#[test]
#[cfg(any(
target_os = "linux",
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "freebsd",
target_os = "netbsd"
))]
@@ -323,7 +321,7 @@ fn test_mkdirat_success_path() {
let dirfd =
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
.unwrap();
- mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed");
+ mkdirat(Some(dirfd), filename, Mode::S_IRWXU).expect("mkdirat failed");
assert!(Path::exists(&tempdir.path().join(filename)));
}
@@ -337,7 +335,7 @@ fn test_mkdirat_success_mode() {
let dirfd =
fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty())
.unwrap();
- mkdirat(dirfd, filename, Mode::S_IRWXU).expect("mkdirat failed");
+ mkdirat(Some(dirfd), filename, Mode::S_IRWXU).expect("mkdirat failed");
let permissions = fs::metadata(tempdir.path().join(filename))
.unwrap()
.permissions();
@@ -357,16 +355,14 @@ fn test_mkdirat_fail() {
stat::Mode::empty(),
)
.unwrap();
- let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
+ let result = mkdirat(Some(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",
+ freebsdlike,
+ apple_targets,
target_os = "haiku",
target_os = "redox"
)))]
@@ -384,11 +380,9 @@ fn test_mknod() {
#[test]
#[cfg(not(any(
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "ios",
- target_os = "macos",
+ solarish,
+ freebsdlike,
+ apple_targets,
target_os = "haiku",
target_os = "redox"
)))]
@@ -402,7 +396,7 @@ fn test_mknodat() {
let target_dir =
Dir::open(tempdir.path(), OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap();
mknodat(
- target_dir.as_raw_fd(),
+ Some(target_dir.as_raw_fd()),
file_name,
SFlag::S_IFREG,
Mode::S_IRWXU,
@@ -410,7 +404,7 @@ fn test_mknodat() {
)
.unwrap();
let mode = fstatat(
- target_dir.as_raw_fd(),
+ Some(target_dir.as_raw_fd()),
file_name,
AtFlags::AT_SYMLINK_NOFOLLOW,
)
@@ -419,3 +413,75 @@ fn test_mknodat() {
assert_eq!(mode & libc::S_IFREG, libc::S_IFREG);
assert_eq!(mode & libc::S_IRWXU, libc::S_IRWXU);
}
+
+#[test]
+#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+fn test_futimens_unchanged() {
+ 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();
+
+ let old_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let old_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+
+ futimens(fd, &TimeSpec::UTIME_OMIT, &TimeSpec::UTIME_OMIT).unwrap();
+
+ let new_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let new_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+ assert_eq!(old_atime, new_atime);
+ assert_eq!(old_mtime, new_mtime);
+}
+
+#[test]
+#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
+fn test_utimensat_unchanged() {
+ 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();
+
+ let old_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let old_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+ utimensat(
+ Some(dirfd),
+ filename,
+ &TimeSpec::UTIME_OMIT,
+ &TimeSpec::UTIME_OMIT,
+ UtimensatFlags::NoFollowSymlink,
+ )
+ .unwrap();
+ let new_atime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .accessed()
+ .unwrap();
+ let new_mtime = fs::metadata(fullpath.as_path())
+ .unwrap()
+ .modified()
+ .unwrap();
+ assert_eq!(old_atime, new_atime);
+ assert_eq!(old_mtime, new_mtime);
+}
diff --git a/third_party/rust/nix/test/test_time.rs b/third_party/rust/nix/test/test_time.rs
index 5f76e61a2d..64c8161dbf 100644
--- a/third_party/rust/nix/test/test_time.rs
+++ b/third_party/rust/nix/test/test_time.rs
@@ -1,10 +1,4 @@
-#[cfg(any(
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "linux",
- target_os = "android",
- target_os = "emscripten",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
use nix::time::clock_getcpuclockid;
use nix::time::{clock_gettime, ClockId};
@@ -19,13 +13,7 @@ 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",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
#[test]
pub fn test_clock_getcpuclockid() {
let clock_id = clock_getcpuclockid(nix::unistd::Pid::this()).unwrap();
@@ -43,13 +31,7 @@ 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",
-))]
+#[cfg(any(freebsdlike, linux_android, target_os = "emscripten"))]
#[test]
pub fn test_clock_id_pid_cpu_clock_id() {
ClockId::pid_cpu_clock_id(nix::unistd::Pid::this())
@@ -57,3 +39,28 @@ pub fn test_clock_id_pid_cpu_clock_id() {
.unwrap()
.unwrap();
}
+
+#[cfg(any(
+ linux_android,
+ solarish,
+ freebsdlike,
+ target_os = "netbsd",
+ target_os = "hurd",
+ target_os = "aix"
+))]
+#[test]
+pub fn test_clock_nanosleep() {
+ use nix::{
+ sys::time::{TimeSpec, TimeValLike},
+ time::{clock_nanosleep, ClockNanosleepFlags},
+ };
+
+ let sleep_time = TimeSpec::microseconds(1);
+ let res = clock_nanosleep(
+ ClockId::CLOCK_MONOTONIC,
+ ClockNanosleepFlags::empty(),
+ &sleep_time,
+ );
+ let expected = TimeSpec::microseconds(0);
+ assert_eq!(res, Ok(expected));
+}
diff --git a/third_party/rust/nix/test/test_unistd.rs b/third_party/rust/nix/test/test_unistd.rs
index 10284e4127..aa2e5e56d7 100644
--- a/third_party/rust/nix/test/test_unistd.rs
+++ b/third_party/rust/nix/test/test_unistd.rs
@@ -67,6 +67,37 @@ fn test_fork_and_waitpid() {
}
#[test]
+#[cfg(target_os = "freebsd")]
+fn test_rfork_and_waitpid() {
+ let _m = crate::FORK_MTX.lock();
+
+ // Safe: Child only calls `_exit`, which is signal-safe
+ match unsafe { rfork(RforkFlags::RFPROC | RforkFlags::RFTHREAD) }
+ .expect("Error: Rfork 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 {s:?}, should never happen")
+ }
+
+ // 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();
@@ -126,8 +157,7 @@ fn test_mkfifo_directory() {
#[test]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -147,8 +177,7 @@ fn test_mkfifoat_none() {
#[test]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -163,15 +192,15 @@ fn test_mkfifoat() {
mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap();
let stats =
- stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap();
+ stat::fstatat(Some(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",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -186,8 +215,7 @@ fn test_mkfifoat_directory_none() {
#[test]
#[cfg(not(any(
- target_os = "macos",
- target_os = "ios",
+ apple_targets,
target_os = "android",
target_os = "redox",
target_os = "haiku"
@@ -197,7 +225,7 @@ fn test_mkfifoat_directory() {
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();
+ stat::mkdirat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).unwrap();
mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR)
.expect_err("assertion failed");
@@ -220,7 +248,7 @@ fn test_getsid() {
assert_eq!(none_sid, pid_sid);
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
mod linux_android {
use nix::unistd::gettid;
@@ -234,8 +262,7 @@ mod linux_android {
#[test]
// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "redox",
target_os = "fuchsia",
target_os = "haiku"
@@ -263,12 +290,11 @@ fn test_setgroups() {
#[test]
// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
+ apple_targets,
target_os = "redox",
target_os = "fuchsia",
target_os = "haiku",
- target_os = "illumos"
+ solarish
)))]
fn test_initgroups() {
// Skip this test when not run as root as `initgroups()` and `setgroups()`
@@ -356,7 +382,7 @@ macro_rules! execve_test_factory (
match unsafe{fork()}.unwrap() {
Child => {
// Make `writer` be the stdout of the new process.
- dup2(writer, 1).unwrap();
+ dup2(writer.as_raw_fd(), 1).unwrap();
let r = syscall();
let _ = std::io::stderr()
.write_all(format!("{:?}", r).as_bytes());
@@ -370,7 +396,7 @@ macro_rules! execve_test_factory (
assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
// Read 1024 bytes.
let mut buf = [0u8; 1024];
- read(reader, &mut buf).unwrap();
+ read(reader.as_raw_fd(), &mut buf).unwrap();
// It should contain the things we printed using `/bin/sh`.
let string = String::from_utf8_lossy(&buf);
assert!(string.contains("nix!!!"));
@@ -404,46 +430,44 @@ 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"))] {
+ } else if #[cfg(any(freebsdlike, target_os = "linux", target_os = "hurd"))] {
// 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"))] {
+ } else if #[cfg(any(solarish, apple_targets, netbsdlike))] {
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"))]
+#[cfg(any(
+ target_os = "haiku",
+ target_os = "hurd",
+ 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(),
+ Some(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(),
+ Some(File::open("/system/bin/").unwrap().into_raw_fd()),
"./sh", AtFlags::empty());
execve_test_factory!(test_execveat_absolute, execveat,
- File::open("/").unwrap().into_raw_fd(),
+ Some(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(),
+ execve_test_factory!(test_execveat_empty, execveat, Some(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(),
+ execve_test_factory!(test_execveat_relative, execveat, Some(File::open("/bin/").unwrap().into_raw_fd()),
"./sh", AtFlags::empty());
- execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
+ execve_test_factory!(test_execveat_absolute, execveat, Some(File::open("/").unwrap().into_raw_fd()),
"/bin/sh", AtFlags::empty());
}
}
@@ -527,6 +551,8 @@ fn test_fchown() {
#[test]
#[cfg(not(target_os = "redox"))]
fn test_fchownat() {
+ use nix::fcntl::AtFlags;
+
let _dr = crate::DirRestore::new();
// Testing for anything other than our own UID/GID is hard.
let uid = Some(getuid());
@@ -540,14 +566,13 @@ fn test_fchownat() {
let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
- fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink)
- .unwrap();
+ fchownat(Some(dirfd), "file", uid, gid, AtFlags::empty()).unwrap();
chdir(tempdir.path()).unwrap();
- fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
+ fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap();
fs::remove_file(&path).unwrap();
- fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err();
+ fchownat(None, "file", uid, gid, AtFlags::empty()).unwrap_err();
}
#[test]
@@ -564,7 +589,7 @@ fn test_lseek() {
assert_eq!(b"f123456", &buf);
}
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[test]
fn test_lseek64() {
const CONTENTS: &[u8] = b"abcdef123456";
@@ -579,7 +604,7 @@ fn test_lseek64() {
}
cfg_if! {
- if #[cfg(any(target_os = "android", target_os = "linux"))] {
+ if #[cfg(linux_android)] {
macro_rules! require_acct{
() => {
require_capability!("test_acct", CAP_SYS_PACCT);
@@ -631,11 +656,12 @@ fn test_acct() {
acct::disable().unwrap();
}
+#[cfg_attr(target_os = "hurd", ignore)]
#[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);
+ // PATH_MAX is limited on most platforms, so it makes a good test
+ let path_max = fpathconf(f, PathconfVar::PATH_MAX);
assert!(
path_max
.expect("fpathconf failed")
@@ -644,9 +670,10 @@ fn test_fpathconf_limited() {
);
}
+#[cfg_attr(target_os = "hurd", ignore)]
#[test]
fn test_pathconf_limited() {
- // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
+ // PATH_MAX is limited on most platforms, so it makes a good test
let path_max = pathconf("/", PathconfVar::PATH_MAX);
assert!(
path_max
@@ -656,9 +683,10 @@ fn test_pathconf_limited() {
);
}
+#[cfg_attr(target_os = "hurd", ignore)]
#[test]
fn test_sysconf_limited() {
- // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test
+ // OPEN_MAX is limited on most platforms, so it makes a good test
let open_max = sysconf(SysconfVar::OPEN_MAX);
assert!(
open_max
@@ -678,13 +706,7 @@ fn test_sysconf_unsupported() {
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"
-))]
+#[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
#[test]
fn test_getresuid() {
let resuids = getresuid().unwrap();
@@ -693,13 +715,7 @@ fn test_getresuid() {
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"
-))]
+#[cfg(any(linux_android, freebsdlike, target_os = "openbsd"))]
#[test]
fn test_getresgid() {
let resgids = getresgid().unwrap();
@@ -714,12 +730,12 @@ fn test_getresgid() {
fn test_pipe() {
let (fd0, fd1) = pipe().unwrap();
let m0 = stat::SFlag::from_bits_truncate(
- stat::fstat(fd0).unwrap().st_mode as mode_t,
+ stat::fstat(fd0.as_raw_fd()).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,
+ stat::fstat(fd1.as_raw_fd()).unwrap().st_mode as mode_t,
);
assert_eq!(m1, SFlag::S_IFIFO);
}
@@ -727,25 +743,25 @@ fn test_pipe() {
// 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",
+ linux_android,
+ freebsdlike,
+ solarish,
+ netbsdlike,
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());
+ let f0 = FdFlag::from_bits_truncate(
+ fcntl(fd0.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
+ );
assert!(f0.contains(FdFlag::FD_CLOEXEC));
- let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
+ let f1 = FdFlag::from_bits_truncate(
+ fcntl(fd1.as_raw_fd(), FcntlArg::F_GETFD).unwrap(),
+ );
assert!(f1.contains(FdFlag::FD_CLOEXEC));
}
@@ -881,6 +897,8 @@ fn test_symlinkat() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_file() {
+ use nix::fcntl::AtFlags;
+
let tempdir = tempdir().unwrap();
let oldfilename = "foo.txt";
let oldfilepath = tempdir.path().join(oldfilename);
@@ -902,7 +920,7 @@ fn test_linkat_file() {
oldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
@@ -911,6 +929,8 @@ fn test_linkat_file() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_olddirfd_none() {
+ use nix::fcntl::AtFlags;
+
let _dr = crate::DirRestore::new();
let tempdir_oldfile = tempdir().unwrap();
@@ -939,7 +959,7 @@ fn test_linkat_olddirfd_none() {
oldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
@@ -948,6 +968,8 @@ fn test_linkat_olddirfd_none() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_newdirfd_none() {
+ use nix::fcntl::AtFlags;
+
let _dr = crate::DirRestore::new();
let tempdir_oldfile = tempdir().unwrap();
@@ -976,20 +998,17 @@ fn test_linkat_newdirfd_none() {
oldfilename,
None,
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
assert!(newfilepath.exists());
}
#[test]
-#[cfg(not(any(
- target_os = "ios",
- target_os = "macos",
- target_os = "redox",
- target_os = "haiku"
-)))]
+#[cfg(not(any(apple_targets, target_os = "redox", target_os = "haiku")))]
fn test_linkat_no_follow_symlink() {
+ use nix::fcntl::AtFlags;
+
let _m = crate::CWD_LOCK.read();
let tempdir = tempdir().unwrap();
@@ -1019,7 +1038,7 @@ fn test_linkat_no_follow_symlink() {
symoldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::NoSymlinkFollow,
+ AtFlags::empty(),
)
.unwrap();
@@ -1033,6 +1052,8 @@ fn test_linkat_no_follow_symlink() {
#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_linkat_follow_symlink() {
+ use nix::fcntl::AtFlags;
+
let _m = crate::CWD_LOCK.read();
let tempdir = tempdir().unwrap();
@@ -1062,7 +1083,7 @@ fn test_linkat_follow_symlink() {
symoldfilename,
Some(dirfd),
newfilename,
- LinkatFlags::SymlinkFollow,
+ AtFlags::AT_SYMLINK_FOLLOW,
)
.unwrap();
@@ -1070,8 +1091,8 @@ fn test_linkat_follow_symlink() {
// Check the file type of the new link
assert_eq!(
- (stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t)
- & SFlag::S_IFMT),
+ stat::SFlag::from_bits_truncate(newfilestat.st_mode as mode_t)
+ & SFlag::S_IFMT,
SFlag::S_IFREG
);
@@ -1159,8 +1180,6 @@ fn test_access_file_exists() {
.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() {
@@ -1177,7 +1196,7 @@ fn test_user_into_passwd() {
}
/// Tests setting the filesystem UID with `setfsuid`.
-#[cfg(any(target_os = "linux", target_os = "android"))]
+#[cfg(linux_android)]
#[test]
fn test_setfsuid() {
use std::os::unix::fs::PermissionsExt;
@@ -1230,9 +1249,11 @@ fn test_ttyname() {
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())
+ let fds = fs::OpenOptions::new()
+ .read(true)
+ .write(true)
+ .open(Path::new(&sname))
.expect("open failed");
- assert!(fds > 0);
let name = ttyname(fds).expect("ttyname failed");
assert!(name.starts_with("/dev"));
@@ -1242,35 +1263,17 @@ fn test_ttyname() {
#[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));
+ assert_eq!(ttyname(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",
-))]
+#[cfg(bsd)]
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_a, gid_a) = getpeereid(sock_a).unwrap();
+ let (uid_b, gid_b) = getpeereid(sock_b).unwrap();
let uid = geteuid();
let gid = getegid();
@@ -1282,20 +1285,6 @@ fn test_getpeereid() {
}
#[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;
@@ -1364,11 +1353,7 @@ fn test_faccessat_file_exists() {
}
#[test]
-#[cfg(any(
- all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
+#[cfg(any(all(target_os = "linux", not(target_env = "uclibc")), freebsdlike))]
fn test_eaccess_not_existing() {
let tempdir = tempdir().unwrap();
let dir = tempdir.path().join("does_not_exist.txt");
@@ -1379,11 +1364,7 @@ fn test_eaccess_not_existing() {
}
#[test]
-#[cfg(any(
- all(target_os = "linux", not(target_env = "uclibc")),
- target_os = "freebsd",
- target_os = "dragonfly"
-))]
+#[cfg(any(all(target_os = "linux", not(target_env = "uclibc")), freebsdlike))]
fn test_eaccess_file_exists() {
let tempdir = tempdir().unwrap();
let path = tempdir.path().join("does_exist.txt");
@@ -1391,3 +1372,14 @@ fn test_eaccess_file_exists() {
eaccess(&path, AccessFlags::R_OK | AccessFlags::W_OK)
.expect("assertion failed");
}
+
+#[test]
+#[cfg(bsd)]
+fn test_group_from() {
+ let group = Group::from_name("wheel").unwrap().unwrap();
+ assert!(group.name == "wheel");
+ let group_id = group.gid;
+ let group = Group::from_gid(group_id).unwrap().unwrap();
+ assert_eq!(group.gid, group_id);
+ assert_eq!(group.name, "wheel");
+}