summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/tests
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/tests')
-rw-r--r--vendor/rustix/tests/backends.rs109
-rw-r--r--vendor/rustix/tests/fs/cwd.rs3
-rw-r--r--vendor/rustix/tests/fs/dir.rs37
-rw-r--r--vendor/rustix/tests/fs/fcntl.rs17
-rw-r--r--vendor/rustix/tests/fs/file.rs83
-rw-r--r--vendor/rustix/tests/fs/flock.rs34
-rw-r--r--vendor/rustix/tests/fs/futimens.rs42
-rw-r--r--vendor/rustix/tests/fs/invalid_offset.rs182
-rw-r--r--vendor/rustix/tests/fs/long_paths.rs28
-rw-r--r--vendor/rustix/tests/fs/main.rs47
-rw-r--r--vendor/rustix/tests/fs/makedev.rs10
-rw-r--r--vendor/rustix/tests/fs/mkdirat.rs33
-rw-r--r--vendor/rustix/tests/fs/mknodat.rs27
-rw-r--r--vendor/rustix/tests/fs/openat.rs33
-rw-r--r--vendor/rustix/tests/fs/openat2.rs184
-rw-r--r--vendor/rustix/tests/fs/readdir.rs68
-rw-r--r--vendor/rustix/tests/fs/renameat.rs104
-rw-r--r--vendor/rustix/tests/fs/statfs.rs49
-rw-r--r--vendor/rustix/tests/fs/utimensat.rs127
-rw-r--r--vendor/rustix/tests/fs/y2038.rs146
-rw-r--r--vendor/rustix/tests/io/dup2_to_replace_stdio.rs18
-rw-r--r--vendor/rustix/tests/io/epoll.rs103
-rw-r--r--vendor/rustix/tests/io/error.rs14
-rw-r--r--vendor/rustix/tests/io/eventfd.rs24
-rw-r--r--vendor/rustix/tests/io/from_into.rs28
-rw-r--r--vendor/rustix/tests/io/ioctl.rs14
-rw-r--r--vendor/rustix/tests/io/main.rs31
-rw-r--r--vendor/rustix/tests/io/poll.rs63
-rw-r--r--vendor/rustix/tests/io/procfs.rs8
-rw-r--r--vendor/rustix/tests/io/read_write.rs118
-rw-r--r--vendor/rustix/tests/io/seals.rs41
-rw-r--r--vendor/rustix/tests/mm/main.rs13
-rw-r--r--vendor/rustix/tests/mm/mlock.rs79
-rw-r--r--vendor/rustix/tests/mm/mmap.rs163
-rw-r--r--vendor/rustix/tests/mm/prot.rs4
-rw-r--r--vendor/rustix/tests/net/addr.rs92
-rw-r--r--vendor/rustix/tests/net/connect_bind_send.rs487
-rw-r--r--vendor/rustix/tests/net/main.rs32
-rw-r--r--vendor/rustix/tests/net/poll.rs119
-rw-r--r--vendor/rustix/tests/net/sockopt.rs158
-rw-r--r--vendor/rustix/tests/net/unix.rs147
-rw-r--r--vendor/rustix/tests/net/v4.rs86
-rw-r--r--vendor/rustix/tests/net/v6.rs95
-rw-r--r--vendor/rustix/tests/param/auxv.rs41
-rw-r--r--vendor/rustix/tests/param/main.rs14
-rw-r--r--vendor/rustix/tests/param/weak.rs201
-rw-r--r--vendor/rustix/tests/path/arg.rs167
-rw-r--r--vendor/rustix/tests/path/dec_int.rs20
-rw-r--r--vendor/rustix/tests/path/main.rs13
-rw-r--r--vendor/rustix/tests/process/cpu_set.rs14
-rw-r--r--vendor/rustix/tests/process/id.rs65
-rw-r--r--vendor/rustix/tests/process/main.rs28
-rw-r--r--vendor/rustix/tests/process/membarrier.rs40
-rw-r--r--vendor/rustix/tests/process/priority.rs83
-rw-r--r--vendor/rustix/tests/process/proc.rs5
-rw-r--r--vendor/rustix/tests/process/rlimit.rs51
-rw-r--r--vendor/rustix/tests/process/sched_yield.rs7
-rw-r--r--vendor/rustix/tests/process/uname.rs13
-rw-r--r--vendor/rustix/tests/process/wait.rs25
-rw-r--r--vendor/rustix/tests/process/weak.rs201
-rw-r--r--vendor/rustix/tests/process/working_directory.rs43
-rw-r--r--vendor/rustix/tests/rand/getrandom.rs7
-rw-r--r--vendor/rustix/tests/rand/main.rs9
-rw-r--r--vendor/rustix/tests/termios/isatty.rs69
-rw-r--r--vendor/rustix/tests/termios/main.rs10
-rw-r--r--vendor/rustix/tests/termios/ttyname.rs24
-rw-r--r--vendor/rustix/tests/thread/clocks.rs212
-rw-r--r--vendor/rustix/tests/thread/id.rs7
-rw-r--r--vendor/rustix/tests/thread/main.rs9
-rw-r--r--vendor/rustix/tests/time/dynamic_clocks.rs22
-rw-r--r--vendor/rustix/tests/time/main.rs14
-rw-r--r--vendor/rustix/tests/time/monotonic.rs45
-rw-r--r--vendor/rustix/tests/time/timerfd.rs75
-rw-r--r--vendor/rustix/tests/time/timespec.rs26
-rw-r--r--vendor/rustix/tests/time/y2038.rs77
75 files changed, 4937 insertions, 0 deletions
diff --git a/vendor/rustix/tests/backends.rs b/vendor/rustix/tests/backends.rs
new file mode 100644
index 000000000..4b88bd11c
--- /dev/null
+++ b/vendor/rustix/tests/backends.rs
@@ -0,0 +1,109 @@
+use std::process::Command;
+
+#[test]
+fn test_backends() {
+ // Pick an arbitrary platform where linux_raw is enabled by default and
+ // ensure that the use-default crate uses it.
+ #[cfg(all(target_os = "linux", target_arch = "aarch64"))]
+ {
+ assert!(
+ !has_dependency("test-crates/use-default", &[], &[], &["RUSTFLAGS"], "libc"),
+ "use-default depends on libc"
+ );
+ assert!(
+ has_dependency(
+ "test-crates/use-default",
+ &[],
+ &[],
+ &["RUSTFLAGS"],
+ "linux-raw-sys"
+ ),
+ "use-default does not depend on linux-raw-sys"
+ );
+ }
+
+ #[cfg(windows)]
+ let libc_dep = "windows-sys";
+ #[cfg(unix)]
+ let libc_dep = "libc";
+
+ // Test the use-libc crate, which enables the "use-libc" cargo feature.
+ assert!(
+ has_dependency("test-crates/use-libc", &[], &[], &["RUSTFLAGS"], libc_dep),
+ "use-libc doesn't depend on {}",
+ libc_dep
+ );
+
+ // Test the use-default crate with `--cfg=rustix_use_libc`.
+ assert!(
+ has_dependency(
+ "test-crates/use-default",
+ &[],
+ &[("RUSTFLAGS", "--cfg=rustix_use_libc")],
+ &[],
+ libc_dep
+ ),
+ "use-default with --cfg=rustix_use_libc does not depend on {}",
+ libc_dep
+ );
+ assert!(
+ !has_dependency(
+ "test-crates/use-default",
+ &[],
+ &[("RUSTFLAGS", "--cfg=rustix_use_libc")],
+ &[],
+ "linux-raw-sys"
+ ),
+ "use-default with --cfg=rustix_use_libc depends on linux-raw-sys"
+ );
+
+ // Test the use-default crate with `--features=rustix/use-libc`.
+ assert!(
+ has_dependency(
+ "test-crates/use-default",
+ &["--features=rustix/use-libc"],
+ &[],
+ &[],
+ libc_dep
+ ),
+ "use-default with --features=rustix/use-libc does not depend on {}",
+ libc_dep
+ );
+}
+
+/// Test whether the crate at directory `dir` has a dependency on `dependency`,
+/// setting the environment variables `envs` and unsetting the environment
+/// variables `remove_envs` when running `cargo`.
+fn has_dependency(
+ dir: &str,
+ args: &[&str],
+ envs: &[(&str, &str)],
+ remove_envs: &[&str],
+ dependency: &str,
+) -> bool {
+ let mut command = Command::new("cargo");
+
+ command
+ .arg("tree")
+ .arg("--quiet")
+ .arg("--edges=normal")
+ .arg(&format!("--invert={}", dependency))
+ .current_dir(dir);
+
+ command.args(args);
+ for (key, value) in envs {
+ command.env(key, value);
+ }
+ for key in remove_envs {
+ command.env_remove(key);
+ }
+
+ let child = command.output().unwrap();
+
+ // `cargo tree --invert=foo` can fail in two different ways: it exits with
+ // a non-zero status if the dependency is not present in the Cargo.toml
+ // configuration, and it exists with a zero status and prints nothing if
+ // the dependency is present but optional and not enabled. So we check for
+ // both here.
+ child.status.success() && !child.stdout.is_empty()
+}
diff --git a/vendor/rustix/tests/fs/cwd.rs b/vendor/rustix/tests/fs/cwd.rs
new file mode 100644
index 000000000..749c84f24
--- /dev/null
+++ b/vendor/rustix/tests/fs/cwd.rs
@@ -0,0 +1,3 @@
+/// Make sure we can use `cwd` in const contexts.
+#[allow(dead_code)]
+const CWD: rustix::fd::BorrowedFd<'static> = rustix::fs::cwd();
diff --git a/vendor/rustix/tests/fs/dir.rs b/vendor/rustix/tests/fs/dir.rs
new file mode 100644
index 000000000..f5120be96
--- /dev/null
+++ b/vendor/rustix/tests/fs/dir.rs
@@ -0,0 +1,37 @@
+#[test]
+fn test_dir() {
+ let t = rustix::fs::openat(
+ rustix::fs::cwd(),
+ rustix::cstr!("."),
+ rustix::fs::OFlags::RDONLY | rustix::fs::OFlags::CLOEXEC,
+ rustix::fs::Mode::empty(),
+ )
+ .unwrap();
+
+ let dir = rustix::fs::Dir::read_from(&t).unwrap();
+
+ let _file = rustix::fs::openat(
+ &t,
+ rustix::cstr!("Cargo.toml"),
+ rustix::fs::OFlags::RDONLY | rustix::fs::OFlags::CLOEXEC,
+ rustix::fs::Mode::empty(),
+ )
+ .unwrap();
+
+ let mut saw_dot = false;
+ let mut saw_dotdot = false;
+ let mut saw_cargo_toml = false;
+ for entry in dir {
+ let entry = entry.unwrap();
+ if entry.file_name() == rustix::cstr!(".") {
+ saw_dot = true;
+ } else if entry.file_name() == rustix::cstr!("..") {
+ saw_dotdot = true;
+ } else if entry.file_name() == rustix::cstr!("Cargo.toml") {
+ saw_cargo_toml = true;
+ }
+ }
+ assert!(saw_dot);
+ assert!(saw_dotdot);
+ assert!(saw_cargo_toml);
+}
diff --git a/vendor/rustix/tests/fs/fcntl.rs b/vendor/rustix/tests/fs/fcntl.rs
new file mode 100644
index 000000000..1f8b78387
--- /dev/null
+++ b/vendor/rustix/tests/fs/fcntl.rs
@@ -0,0 +1,17 @@
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[test]
+fn test_fcntl_dupfd_cloexec() {
+ use rustix::fd::AsFd;
+ use std::os::unix::io::AsRawFd;
+
+ let file = rustix::fs::openat(
+ rustix::fs::cwd(),
+ "Cargo.toml",
+ rustix::fs::OFlags::RDONLY,
+ rustix::fs::Mode::empty(),
+ )
+ .unwrap();
+
+ let new = rustix::fs::fcntl_dupfd_cloexec(&file, 700).unwrap();
+ assert_eq!(new.as_fd().as_raw_fd(), 700);
+}
diff --git a/vendor/rustix/tests/fs/file.rs b/vendor/rustix/tests/fs/file.rs
new file mode 100644
index 000000000..5c09f640d
--- /dev/null
+++ b/vendor/rustix/tests/fs/file.rs
@@ -0,0 +1,83 @@
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn test_file() {
+ #[cfg(not(target_os = "illumos"))]
+ rustix::fs::accessat(
+ rustix::fs::cwd(),
+ "Cargo.toml",
+ rustix::fs::Access::READ_OK,
+ rustix::fs::AtFlags::empty(),
+ )
+ .unwrap();
+
+ assert_eq!(
+ rustix::fs::openat(
+ rustix::fs::cwd(),
+ "Cagro.motl",
+ rustix::fs::OFlags::RDONLY,
+ rustix::fs::Mode::empty(),
+ )
+ .unwrap_err(),
+ rustix::io::Errno::NOENT
+ );
+
+ let file = rustix::fs::openat(
+ rustix::fs::cwd(),
+ "Cargo.toml",
+ rustix::fs::OFlags::RDONLY,
+ rustix::fs::Mode::empty(),
+ )
+ .unwrap();
+
+ assert_eq!(
+ rustix::fs::openat(
+ &file,
+ "Cargo.toml",
+ rustix::fs::OFlags::RDONLY,
+ rustix::fs::Mode::empty(),
+ )
+ .unwrap_err(),
+ rustix::io::Errno::NOTDIR
+ );
+
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ )))]
+ rustix::fs::fadvise(&file, 0, 10, rustix::fs::Advice::Normal).unwrap();
+
+ assert_eq!(
+ rustix::fs::fcntl_getfd(&file).unwrap(),
+ rustix::fs::FdFlags::empty()
+ );
+ assert_eq!(
+ rustix::fs::fcntl_getfl(&file).unwrap(),
+ rustix::fs::OFlags::empty()
+ );
+
+ let stat = rustix::fs::fstat(&file).unwrap();
+ assert!(stat.st_size > 0);
+ assert!(stat.st_blocks > 0);
+
+ #[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+ )))]
+ // not implemented in libc for netbsd yet
+ {
+ let statfs = rustix::fs::fstatfs(&file).unwrap();
+ assert!(statfs.f_blocks > 0);
+ }
+
+ #[cfg(feature = "net")]
+ assert_eq!(rustix::io::is_read_write(&file).unwrap(), (true, false));
+
+ assert_ne!(rustix::io::ioctl_fionread(&file).unwrap(), 0);
+}
diff --git a/vendor/rustix/tests/fs/flock.rs b/vendor/rustix/tests/fs/flock.rs
new file mode 100644
index 000000000..1b7df6ffd
--- /dev/null
+++ b/vendor/rustix/tests/fs/flock.rs
@@ -0,0 +1,34 @@
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn test_flock() {
+ use rustix::fs::{cwd, flock, openat, FlockOperation, Mode, OFlags};
+
+ let f = openat(cwd(), "Cargo.toml", OFlags::RDONLY, Mode::empty()).unwrap();
+ flock(&f, FlockOperation::LockExclusive).unwrap();
+ flock(&f, FlockOperation::Unlock).unwrap();
+ let g = openat(cwd(), "Cargo.toml", OFlags::RDONLY, Mode::empty()).unwrap();
+ flock(&g, FlockOperation::LockExclusive).unwrap();
+ flock(&g, FlockOperation::Unlock).unwrap();
+ drop(f);
+ drop(g);
+
+ let f = openat(cwd(), "Cargo.toml", OFlags::RDONLY, Mode::empty()).unwrap();
+ flock(&f, FlockOperation::LockShared).unwrap();
+ let g = openat(cwd(), "Cargo.toml", OFlags::RDONLY, Mode::empty()).unwrap();
+ flock(&g, FlockOperation::LockShared).unwrap();
+ flock(&f, FlockOperation::Unlock).unwrap();
+ flock(&g, FlockOperation::Unlock).unwrap();
+ drop(f);
+ drop(g);
+
+ let f = openat(cwd(), "Cargo.toml", OFlags::RDONLY, Mode::empty()).unwrap();
+ flock(&f, FlockOperation::LockShared).unwrap();
+ flock(&f, FlockOperation::LockExclusive).unwrap();
+ flock(&f, FlockOperation::Unlock).unwrap();
+ let g = openat(cwd(), "Cargo.toml", OFlags::RDONLY, Mode::empty()).unwrap();
+ flock(&g, FlockOperation::LockShared).unwrap();
+ flock(&g, FlockOperation::LockExclusive).unwrap();
+ flock(&g, FlockOperation::Unlock).unwrap();
+ drop(f);
+ drop(g);
+}
diff --git a/vendor/rustix/tests/fs/futimens.rs b/vendor/rustix/tests/fs/futimens.rs
new file mode 100644
index 000000000..81f8b8a27
--- /dev/null
+++ b/vendor/rustix/tests/fs/futimens.rs
@@ -0,0 +1,42 @@
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[test]
+fn test_futimens() {
+ use rustix::fs::{cwd, fstat, futimens, openat, Mode, OFlags, Timespec, Timestamps};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ let foo = openat(
+ &dir,
+ "foo",
+ OFlags::CREATE | OFlags::WRONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let times = Timestamps {
+ last_access: Timespec {
+ tv_sec: 44000,
+ tv_nsec: 45000,
+ },
+ last_modification: Timespec {
+ tv_sec: 46000,
+ tv_nsec: 47000,
+ },
+ };
+ futimens(&foo, &times).unwrap();
+
+ let after = fstat(&foo).unwrap();
+
+ assert_eq!(times.last_modification.tv_sec as u64, after.st_mtime as u64);
+ #[cfg(not(target_os = "netbsd"))]
+ assert_eq!(
+ times.last_modification.tv_nsec as u64,
+ after.st_mtime_nsec as u64
+ );
+ #[cfg(target_os = "netbsd")]
+ assert_eq!(
+ times.last_modification.tv_nsec as u64,
+ after.st_mtimensec as u64
+ );
+}
diff --git a/vendor/rustix/tests/fs/invalid_offset.rs b/vendor/rustix/tests/fs/invalid_offset.rs
new file mode 100644
index 000000000..995e302a1
--- /dev/null
+++ b/vendor/rustix/tests/fs/invalid_offset.rs
@@ -0,0 +1,182 @@
+//! Tests for extreme `u64` file offsets.
+//!
+//! POSIX-ish interfaces tend to use signed integers for file offsets, while
+//! Rust APIs tend to use `u64`. Test that extreme `u64` values in APIs that
+//! take file offsets are properly diagnosed.
+//!
+//! These tests are disabled on ios/macos since those platforms kill the
+//! process with `SIGXFSZ` instead of returning an error.
+
+#![cfg(not(any(target_os = "redox", target_os = "wasi")))]
+
+use rustix::io::SeekFrom;
+
+#[test]
+fn invalid_offset_seek() {
+ use rustix::fs::{cwd, openat, seek, Mode, OFlags};
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let file = openat(
+ &dir,
+ "foo",
+ OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ seek(&file, SeekFrom::Start(u64::MAX)).unwrap_err();
+ seek(&file, SeekFrom::Start(i64::MAX as u64 + 1)).unwrap_err();
+ seek(&file, SeekFrom::End(-1)).unwrap_err();
+ seek(&file, SeekFrom::End(i64::MIN)).unwrap_err();
+ seek(&file, SeekFrom::Current(-1)).unwrap_err();
+ seek(&file, SeekFrom::Current(i64::MIN)).unwrap_err();
+}
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+#[test]
+fn invalid_offset_fallocate() {
+ use rustix::fs::{cwd, fallocate, openat, FallocateFlags, Mode, OFlags};
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let file = openat(
+ &dir,
+ "foo",
+ OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ fallocate(&file, FallocateFlags::empty(), u64::MAX, 1).unwrap_err();
+ fallocate(&file, FallocateFlags::empty(), i64::MAX as u64 + 1, 1).unwrap_err();
+ fallocate(&file, FallocateFlags::empty(), 0, u64::MAX).unwrap_err();
+ fallocate(&file, FallocateFlags::empty(), 0, i64::MAX as u64 + 1).unwrap_err();
+}
+
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+)))]
+#[test]
+fn invalid_offset_fadvise() {
+ use rustix::fs::{cwd, fadvise, openat, Advice, Mode, OFlags};
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let file = openat(
+ &dir,
+ "foo",
+ OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ // `fadvise` never fails on invalid offsets.
+ fadvise(&file, i64::MAX as u64, i64::MAX as u64, Advice::Normal).unwrap();
+ fadvise(&file, u64::MAX, 0, Advice::Normal).unwrap();
+ fadvise(&file, i64::MAX as u64, 1, Advice::Normal).unwrap();
+ fadvise(&file, 1, i64::MAX as u64, Advice::Normal).unwrap();
+ fadvise(&file, i64::MAX as u64 + 1, 0, Advice::Normal).unwrap();
+ fadvise(&file, u64::MAX, i64::MAX as u64, Advice::Normal).unwrap();
+
+ // `fadvise` fails on invalid lengths.
+ fadvise(&file, u64::MAX, u64::MAX, Advice::Normal).unwrap_err();
+ fadvise(&file, i64::MAX as u64, u64::MAX, Advice::Normal).unwrap_err();
+ fadvise(&file, 0, u64::MAX, Advice::Normal).unwrap_err();
+ fadvise(&file, u64::MAX, i64::MAX as u64 + 1, Advice::Normal).unwrap_err();
+ fadvise(&file, i64::MAX as u64 + 1, u64::MAX, Advice::Normal).unwrap_err();
+ fadvise(&file, i64::MAX as u64, i64::MAX as u64 + 1, Advice::Normal).unwrap_err();
+ fadvise(&file, 0, i64::MAX as u64 + 1, Advice::Normal).unwrap_err();
+}
+
+#[test]
+fn invalid_offset_pread() {
+ use rustix::fs::{cwd, openat, Mode, OFlags};
+ use rustix::io::pread;
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let file = openat(
+ &dir,
+ "foo",
+ OFlags::RDWR | OFlags::TRUNC | OFlags::CREATE,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ let mut buf = [0_u8; 1];
+ pread(&file, &mut buf, u64::MAX).unwrap_err();
+ pread(&file, &mut buf, i64::MAX as u64 + 1).unwrap_err();
+}
+
+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+#[test]
+fn invalid_offset_pwrite() {
+ use rustix::fs::{cwd, openat, Mode, OFlags};
+ use rustix::io::pwrite;
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let file = openat(
+ &dir,
+ "foo",
+ OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ let buf = [0_u8; 1];
+ pwrite(&file, &buf, u64::MAX).unwrap_err();
+ pwrite(&file, &buf, i64::MAX as u64 + 1).unwrap_err();
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn invalid_offset_copy_file_range() {
+ use rustix::fs::{copy_file_range, cwd, openat, Mode, OFlags};
+ use rustix::io::write;
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let foo = openat(
+ &dir,
+ "foo",
+ OFlags::RDWR | OFlags::TRUNC | OFlags::CREATE,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+ let bar = openat(
+ &dir,
+ "bar",
+ OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+ write(&foo, b"a").unwrap();
+
+ let mut off_in = u64::MAX;
+ let mut off_out = 0;
+ copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err();
+
+ let mut off_in = i64::MAX as u64 + 1;
+ let mut off_out = 0;
+ copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err();
+
+ let mut off_in = 0;
+ let mut off_out = u64::MAX;
+ copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err();
+
+ let mut off_in = 0;
+ let mut off_out = i64::MAX as u64;
+ copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err();
+
+ let mut off_in = 0;
+ let mut off_out = i64::MAX as u64 + 1;
+ copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err();
+}
diff --git a/vendor/rustix/tests/fs/long_paths.rs b/vendor/rustix/tests/fs/long_paths.rs
new file mode 100644
index 000000000..dbc2fa6ea
--- /dev/null
+++ b/vendor/rustix/tests/fs/long_paths.rs
@@ -0,0 +1,28 @@
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[test]
+fn test_long_paths() {
+ use rustix::fs::{cwd, mkdirat, openat, Mode, OFlags};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ #[cfg(libc)]
+ const PATH_MAX: usize = libc::PATH_MAX as usize;
+ #[cfg(linux_raw)]
+ const PATH_MAX: usize = linux_raw_sys::general::PATH_MAX as usize;
+
+ mkdirat(&dir, "a", Mode::RUSR | Mode::XUSR | Mode::WUSR).unwrap();
+
+ let mut long_path = String::new();
+ for _ in 0..PATH_MAX / 5 {
+ long_path.push_str("a/../");
+ }
+
+ let mut too_long_path = String::new();
+ for _ in 0..PATH_MAX / 4 {
+ too_long_path.push_str("a/../");
+ }
+
+ let _ = openat(&dir, &long_path, OFlags::RDONLY, Mode::empty()).unwrap();
+ let _ = openat(&dir, &too_long_path, OFlags::RDONLY, Mode::empty()).unwrap_err();
+}
diff --git a/vendor/rustix/tests/fs/main.rs b/vendor/rustix/tests/fs/main.rs
new file mode 100644
index 000000000..23928a6ba
--- /dev/null
+++ b/vendor/rustix/tests/fs/main.rs
@@ -0,0 +1,47 @@
+//! Tests for [`rustix::fs`].
+
+#![cfg(feature = "fs")]
+#![cfg(not(windows))]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+#![cfg_attr(core_c_str, feature(core_c_str))]
+
+mod cwd;
+mod dir;
+mod fcntl;
+mod file;
+#[cfg(not(target_os = "wasi"))]
+mod flock;
+mod futimens;
+mod invalid_offset;
+mod long_paths;
+#[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "illumos",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+mod makedev;
+mod mkdirat;
+mod mknodat;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod openat;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod openat2;
+mod readdir;
+mod renameat;
+#[cfg(not(any(
+ target_os = "illumos",
+ target_os = "netbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+// not implemented in libc for netbsd yet
+mod statfs;
+mod utimensat;
+mod y2038;
diff --git a/vendor/rustix/tests/fs/makedev.rs b/vendor/rustix/tests/fs/makedev.rs
new file mode 100644
index 000000000..79b5199e8
--- /dev/null
+++ b/vendor/rustix/tests/fs/makedev.rs
@@ -0,0 +1,10 @@
+use rustix::fs::{major, makedev, minor};
+
+#[test]
+fn makedev_roundtrip() {
+ let maj = 0x2324_2526;
+ let min = 0x6564_6361;
+ let dev = makedev(maj, min);
+ assert_eq!(maj, major(dev));
+ assert_eq!(min, minor(dev));
+}
diff --git a/vendor/rustix/tests/fs/mkdirat.rs b/vendor/rustix/tests/fs/mkdirat.rs
new file mode 100644
index 000000000..884588037
--- /dev/null
+++ b/vendor/rustix/tests/fs/mkdirat.rs
@@ -0,0 +1,33 @@
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[test]
+fn test_mkdirat() {
+ use rustix::fs::{cwd, mkdirat, openat, statat, unlinkat, AtFlags, FileType, Mode, OFlags};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ mkdirat(&dir, "foo", Mode::RWXU).unwrap();
+ let stat = statat(&dir, "foo", AtFlags::empty()).unwrap();
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory);
+ unlinkat(&dir, "foo", AtFlags::REMOVEDIR).unwrap();
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_mkdirat_with_o_path() {
+ use rustix::fs::{cwd, mkdirat, openat, statat, unlinkat, AtFlags, FileType, Mode, OFlags};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::PATH,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ mkdirat(&dir, "foo", Mode::RWXU).unwrap();
+ let stat = statat(&dir, "foo", AtFlags::empty()).unwrap();
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Directory);
+ unlinkat(&dir, "foo", AtFlags::REMOVEDIR).unwrap();
+}
diff --git a/vendor/rustix/tests/fs/mknodat.rs b/vendor/rustix/tests/fs/mknodat.rs
new file mode 100644
index 000000000..fa1c84f69
--- /dev/null
+++ b/vendor/rustix/tests/fs/mknodat.rs
@@ -0,0 +1,27 @@
+#[cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[test]
+fn test_mknodat() {
+ use rustix::fs::{cwd, mknodat, openat, statat, unlinkat, AtFlags, FileType, Mode, OFlags};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ // Create a regular file. Not supported on FreeBSD or OpenBSD.
+ #[cfg(not(any(target_os = "freebsd", target_os = "openbsd")))]
+ {
+ mknodat(&dir, "foo", FileType::RegularFile, Mode::empty(), 0).unwrap();
+ let stat = statat(&dir, "foo", AtFlags::empty()).unwrap();
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::RegularFile);
+ unlinkat(&dir, "foo", AtFlags::empty()).unwrap();
+ }
+
+ mknodat(&dir, "foo", FileType::Fifo, Mode::empty(), 0).unwrap();
+ let stat = statat(&dir, "foo", AtFlags::empty()).unwrap();
+ assert_eq!(FileType::from_raw_mode(stat.st_mode), FileType::Fifo);
+ unlinkat(&dir, "foo", AtFlags::empty()).unwrap();
+}
diff --git a/vendor/rustix/tests/fs/openat.rs b/vendor/rustix/tests/fs/openat.rs
new file mode 100644
index 000000000..564574dc1
--- /dev/null
+++ b/vendor/rustix/tests/fs/openat.rs
@@ -0,0 +1,33 @@
+use std::fs::File;
+
+use io_lifetimes::{FromFd, IntoFd};
+use rustix::fs::{cwd, openat, Mode, OFlags};
+use std::io::Write;
+
+#[test]
+fn test_openat_tmpfile() {
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ )
+ .unwrap();
+ let f = match openat(
+ &dir,
+ ".",
+ OFlags::WRONLY | OFlags::CLOEXEC | OFlags::TMPFILE,
+ Mode::from_bits_truncate(0o644),
+ ) {
+ Ok(f) => Ok(Some(File::from_fd(f.into_fd()))),
+ // TODO: Factor out the `Err`, once we no longer support Rust 1.48.
+ Err(rustix::io::Errno::OPNOTSUPP)
+ | Err(rustix::io::Errno::ISDIR)
+ | Err(rustix::io::Errno::NOENT) => Ok(None),
+ Err(e) => Err(e),
+ };
+ if let Some(mut f) = f.unwrap() {
+ write!(f, "hello world").unwrap();
+ }
+}
diff --git a/vendor/rustix/tests/fs/openat2.rs b/vendor/rustix/tests/fs/openat2.rs
new file mode 100644
index 000000000..0b1d86fe2
--- /dev/null
+++ b/vendor/rustix/tests/fs/openat2.rs
@@ -0,0 +1,184 @@
+use rustix::fd::AsFd;
+use rustix::fs::{cwd, mkdirat, openat, openat2, symlinkat, Mode, OFlags, ResolveFlags};
+use rustix::io::OwnedFd;
+use rustix::{io, path};
+use std::os::unix::io::AsRawFd;
+
+/// Like `openat2`, but keep retrying until it fails or succeeds.
+fn openat2_more<Fd: AsFd, P: path::Arg>(
+ dirfd: Fd,
+ path: P,
+ oflags: OFlags,
+ mode: Mode,
+ resolve: ResolveFlags,
+) -> io::Result<OwnedFd> {
+ let path = path.as_cow_c_str().unwrap().into_owned();
+ loop {
+ match openat2(dirfd.as_fd(), &path, oflags, mode, resolve) {
+ Ok(file) => return Ok(file),
+ Err(io::Errno::AGAIN) => continue,
+ Err(err) => return Err(err),
+ }
+ }
+}
+
+#[test]
+fn test_openat2() {
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ // Detect whether `openat2` is available.
+ match openat2(
+ &dir,
+ ".",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ ) {
+ Ok(_file) => (),
+ Err(io::Errno::NOSYS) => return,
+ Err(_err) => return,
+ }
+
+ // Create a file.
+ let _ = openat2_more(
+ &dir,
+ "test.txt",
+ OFlags::WRONLY | OFlags::CREATE | OFlags::TRUNC | OFlags::CLOEXEC,
+ Mode::RUSR,
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+
+ // Test `NO_SYMLINKS`.
+ symlinkat("test.txt", &dir, "symlink.txt").unwrap();
+ let _ = openat2_more(
+ &dir,
+ "symlink.txt",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &dir,
+ "symlink.txt",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::NO_MAGICLINKS,
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &dir,
+ "symlink.txt",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::NO_SYMLINKS,
+ )
+ .unwrap_err();
+
+ // Test `NO_MAGICLINKS`.
+ let test = openat2_more(
+ &dir,
+ "test.txt",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &dir,
+ &format!("/proc/self/fd/{}", test.as_fd().as_raw_fd()),
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &dir,
+ &format!("/proc/self/fd/{}", test.as_fd().as_raw_fd()),
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::NO_SYMLINKS,
+ )
+ .unwrap_err();
+ let _ = openat2_more(
+ &dir,
+ &format!("/proc/self/fd/{}", test.as_fd().as_raw_fd()),
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::NO_MAGICLINKS,
+ )
+ .unwrap_err();
+
+ // Test `NO_XDEV`.
+ let root = openat2_more(
+ &dir,
+ "/",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &root,
+ "proc",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &root,
+ "proc",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::NO_XDEV,
+ )
+ .unwrap_err();
+
+ // Test `BENEATH`.
+ let _ = openat2_more(
+ &dir,
+ "..",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &dir,
+ "..",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::BENEATH,
+ )
+ .unwrap_err();
+
+ // Test `IN_ROOT`.
+ let _ = openat2_more(
+ &dir,
+ "/proc",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::empty(),
+ )
+ .unwrap();
+ let _ = openat2_more(
+ &dir,
+ "/proc",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::IN_ROOT,
+ )
+ .unwrap_err();
+ mkdirat(&dir, "proc", Mode::RUSR | Mode::XUSR).unwrap();
+ let _ = openat2_more(
+ &dir,
+ "/proc",
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ ResolveFlags::IN_ROOT,
+ )
+ .unwrap();
+}
diff --git a/vendor/rustix/tests/fs/readdir.rs b/vendor/rustix/tests/fs/readdir.rs
new file mode 100644
index 000000000..8925660a9
--- /dev/null
+++ b/vendor/rustix/tests/fs/readdir.rs
@@ -0,0 +1,68 @@
+#![cfg(not(target_os = "redox"))]
+
+use rustix::fs::{Dir, DirEntry};
+use std::collections::HashMap;
+
+#[test]
+fn dir_entries() {
+ let tmpdir = tempfile::tempdir().expect("construct tempdir");
+ let dirfd = std::fs::File::open(tmpdir.path()).expect("open tempdir as file");
+ let mut dir = Dir::read_from(dirfd).expect("construct Dir from dirfd");
+
+ let entries = read_entries(&mut dir);
+ assert_eq!(entries.len(), 0, "no files in directory");
+
+ let _f1 = std::fs::File::create(tmpdir.path().join("file1")).expect("create file1");
+
+ let entries = read_entries(&mut dir);
+ assert!(
+ entries.get("file1").is_some(),
+ "directory contains `file1`: {:?}",
+ entries
+ );
+ assert_eq!(entries.len(), 1);
+
+ let _f2 = std::fs::File::create(tmpdir.path().join("file2")).expect("create file1");
+ let entries = read_entries(&mut dir);
+ assert!(
+ entries.get("file1").is_some(),
+ "directory contains `file1`: {:?}",
+ entries
+ );
+ assert!(
+ entries.get("file2").is_some(),
+ "directory contains `file2`: {:?}",
+ entries
+ );
+ assert_eq!(entries.len(), 2);
+}
+
+fn read_entries(dir: &mut Dir) -> HashMap<String, DirEntry> {
+ dir.rewind();
+ let mut out = HashMap::new();
+ loop {
+ match dir.read() {
+ Some(e) => {
+ let e = e.expect("non-error entry");
+ let name = e.file_name().to_str().expect("utf8 filename").to_owned();
+ if name != "." && name != ".." {
+ out.insert(name, e);
+ }
+ }
+ None => break,
+ }
+ }
+ out
+}
+
+#[test]
+fn dir_from_openat() {
+ let dirfd = rustix::fs::openat(
+ rustix::fs::cwd(),
+ ".",
+ rustix::fs::OFlags::RDONLY,
+ rustix::fs::Mode::empty(),
+ )
+ .expect("open cwd as file");
+ let _dir = Dir::read_from(dirfd).expect("construct Dir from dirfd");
+}
diff --git a/vendor/rustix/tests/fs/renameat.rs b/vendor/rustix/tests/fs/renameat.rs
new file mode 100644
index 000000000..2eea2e77a
--- /dev/null
+++ b/vendor/rustix/tests/fs/renameat.rs
@@ -0,0 +1,104 @@
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use rustix::fs::Stat;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+fn same(a: &Stat, b: &Stat) -> bool {
+ a.st_ino == b.st_ino && a.st_dev == b.st_dev
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_renameat() {
+ use rustix::fs::{cwd, openat, renameat, statat, AtFlags, Mode, OFlags};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::PATH,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let _ = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
+ let before = statat(&dir, "foo", AtFlags::empty()).unwrap();
+ renameat(&dir, "foo", &dir, "bar").unwrap();
+ let renamed = statat(&dir, "bar", AtFlags::empty()).unwrap();
+ assert!(same(&before, &renamed));
+}
+
+/// Like `test_renameat` but the file already exists, so `renameat`
+/// overwrites it.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_renameat_overwrite() {
+ use rustix::fs::{cwd, openat, renameat, statat, AtFlags, Mode, OFlags};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::PATH,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let _ = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
+ let _ = openat(&dir, "bar", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
+ let before = statat(&dir, "foo", AtFlags::empty()).unwrap();
+ renameat(&dir, "foo", &dir, "bar").unwrap();
+ let renamed = statat(&dir, "bar", AtFlags::empty()).unwrap();
+ assert!(same(&before, &renamed));
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_renameat_with() {
+ use rustix::fs::{cwd, openat, renameat_with, statat, AtFlags, Mode, OFlags, RenameFlags};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::PATH,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let _ = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::empty()).unwrap();
+ let before = statat(&dir, "foo", AtFlags::empty()).unwrap();
+
+ match renameat_with(&dir, "foo", &dir, "red", RenameFlags::empty()) {
+ Ok(()) => (),
+ Err(e) if e == rustix::io::Errno::NOSYS => return,
+ Err(e) => unreachable!("unexpected error from renameat_with: {:?}", e),
+ }
+
+ let renamed = statat(&dir, "red", AtFlags::empty()).unwrap();
+ assert!(same(&before, &renamed));
+
+ let _ = openat(
+ &dir,
+ "green",
+ OFlags::CREATE | OFlags::WRONLY,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ {
+ let green = statat(&dir, "green", AtFlags::empty()).unwrap();
+
+ renameat_with(&dir, "red", &dir, "green", RenameFlags::NOREPLACE).unwrap_err();
+ let renamed = statat(&dir, "red", AtFlags::empty()).unwrap();
+ assert!(same(&before, &renamed));
+ let orig = statat(&dir, "green", AtFlags::empty()).unwrap();
+ assert!(same(&green, &orig));
+
+ renameat_with(&dir, "red", &dir, "green", RenameFlags::EXCHANGE).unwrap();
+ let renamed = statat(&dir, "red", AtFlags::empty()).unwrap();
+ assert!(same(&green, &renamed));
+ let orig = statat(&dir, "green", AtFlags::empty()).unwrap();
+ assert!(same(&before, &orig));
+ }
+}
diff --git a/vendor/rustix/tests/fs/statfs.rs b/vendor/rustix/tests/fs/statfs.rs
new file mode 100644
index 000000000..f8bf2e350
--- /dev/null
+++ b/vendor/rustix/tests/fs/statfs.rs
@@ -0,0 +1,49 @@
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_statfs_abi() {
+ use rustix::fs::{FsWord, StatFs, NFS_SUPER_MAGIC, PROC_SUPER_MAGIC};
+
+ // Ensure these all have consistent types.
+ let t: StatFs = unsafe { std::mem::zeroed() };
+ let _s: FsWord = t.f_type;
+ let _u: FsWord = PROC_SUPER_MAGIC;
+ let _v: FsWord = NFS_SUPER_MAGIC;
+
+ // Ensure that after all the platform-specific dancing we have to do, this
+ // constant comes out with the correct value.
+ #[cfg(all(libc, not(target_env = "musl")))]
+ {
+ assert_eq!(
+ i128::from(PROC_SUPER_MAGIC),
+ i128::from(libc::PROC_SUPER_MAGIC)
+ );
+ assert_eq!(
+ i128::from(NFS_SUPER_MAGIC),
+ i128::from(libc::NFS_SUPER_MAGIC)
+ );
+ }
+
+ #[cfg(linux_raw)]
+ {
+ assert_eq!(
+ i128::from(PROC_SUPER_MAGIC),
+ i128::from(linux_raw_sys::general::PROC_SUPER_MAGIC)
+ );
+ assert_eq!(
+ i128::from(NFS_SUPER_MAGIC),
+ i128::from(linux_raw_sys::general::NFS_SUPER_MAGIC)
+ );
+ }
+
+ assert_eq!(PROC_SUPER_MAGIC, 0x0000_9fa0);
+ assert_eq!(NFS_SUPER_MAGIC, 0x0000_6969);
+}
+
+#[test]
+fn test_statfs() {
+ let statfs = rustix::fs::statfs("Cargo.toml").unwrap();
+ let f_blocks = statfs.f_blocks;
+ assert_ne!(f_blocks, 0);
+ // Previously we checked f_files != 0 here, but at least btrfs doesn't set
+ // that.
+}
diff --git a/vendor/rustix/tests/fs/utimensat.rs b/vendor/rustix/tests/fs/utimensat.rs
new file mode 100644
index 000000000..f0fb7e27b
--- /dev/null
+++ b/vendor/rustix/tests/fs/utimensat.rs
@@ -0,0 +1,127 @@
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[test]
+fn test_utimensat() {
+ use rustix::fs::{cwd, openat, statat, utimensat, AtFlags, Mode, OFlags, Timespec, Timestamps};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let _ = openat(
+ &dir,
+ "foo",
+ OFlags::CREATE | OFlags::WRONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let times = Timestamps {
+ last_access: Timespec {
+ tv_sec: 44000,
+ tv_nsec: 45000,
+ },
+ last_modification: Timespec {
+ tv_sec: 46000,
+ tv_nsec: 47000,
+ },
+ };
+ utimensat(&dir, "foo", &times, AtFlags::empty()).unwrap();
+
+ let after = statat(&dir, "foo", AtFlags::empty()).unwrap();
+
+ assert_eq!(times.last_modification.tv_sec as u64, after.st_mtime as u64);
+ #[cfg(not(target_os = "netbsd"))]
+ assert_eq!(
+ times.last_modification.tv_nsec as u64,
+ after.st_mtime_nsec as u64
+ );
+ #[cfg(target_os = "netbsd")]
+ assert_eq!(
+ times.last_modification.tv_nsec as u64,
+ after.st_mtimensec as u64
+ );
+ assert!(times.last_access.tv_sec as u64 >= after.st_atime as u64);
+ #[cfg(not(target_os = "netbsd"))]
+ assert!(
+ times.last_access.tv_sec as u64 > after.st_atime as u64
+ || times.last_access.tv_nsec as u64 >= after.st_atime_nsec as u64
+ );
+ #[cfg(target_os = "netbsd")]
+ assert!(
+ times.last_access.tv_sec as u64 > after.st_atime as u64
+ || times.last_access.tv_nsec as u64 >= after.st_atimensec as u64
+ );
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[test]
+fn test_utimensat_noent() {
+ use rustix::fs::{cwd, openat, utimensat, AtFlags, Mode, OFlags, Timespec, Timestamps};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let times = Timestamps {
+ last_access: Timespec {
+ tv_sec: 44000,
+ tv_nsec: 45000,
+ },
+ last_modification: Timespec {
+ tv_sec: 46000,
+ tv_nsec: 47000,
+ },
+ };
+ assert_eq!(
+ utimensat(&dir, "foo", &times, AtFlags::empty()).unwrap_err(),
+ rustix::io::Errno::NOENT
+ );
+}
+
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#[test]
+fn test_utimensat_notdir() {
+ use rustix::fs::{cwd, openat, utimensat, AtFlags, Mode, OFlags, Timespec, Timestamps};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(
+ cwd(),
+ tmp.path(),
+ OFlags::RDONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let foo = openat(
+ &dir,
+ "foo",
+ OFlags::CREATE | OFlags::WRONLY | OFlags::CLOEXEC,
+ Mode::empty(),
+ )
+ .unwrap();
+
+ let times = Timestamps {
+ last_access: Timespec {
+ tv_sec: 44000,
+ tv_nsec: 45000,
+ },
+ last_modification: Timespec {
+ tv_sec: 46000,
+ tv_nsec: 47000,
+ },
+ };
+ assert_eq!(
+ utimensat(&foo, "bar", &times, AtFlags::empty()).unwrap_err(),
+ rustix::io::Errno::NOTDIR
+ );
+}
diff --git a/vendor/rustix/tests/fs/y2038.rs b/vendor/rustix/tests/fs/y2038.rs
new file mode 100644
index 000000000..4299d709b
--- /dev/null
+++ b/vendor/rustix/tests/fs/y2038.rs
@@ -0,0 +1,146 @@
+/// Test that we can set a file timestamp to a date past the year 2038 with
+/// `utimensat` and read it back again.
+///
+/// See tests/time/y2038.rs for more information about y2038 testing.
+#[cfg(not(all(target_env = "musl", target_pointer_width = "32")))]
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+#[cfg(not(all(target_os = "emscripten", target_pointer_width = "32")))]
+#[test]
+fn test_y2038_with_utimensat() {
+ use rustix::fs::{
+ cwd, fstat, openat, statat, utimensat, AtFlags, Mode, OFlags, Timespec, Timestamps,
+ };
+ use std::convert::TryInto;
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(&cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ let m_sec = 1_u64 << 32;
+ let m_nsec = 17_u32;
+ let a_sec = m_sec + 1;
+ let a_nsec = m_nsec + 1;
+
+ let timestamps = Timestamps {
+ last_modification: Timespec {
+ tv_sec: m_sec as _,
+ tv_nsec: m_nsec as _,
+ },
+ last_access: Timespec {
+ tv_sec: a_sec as _,
+ tv_nsec: a_nsec as _,
+ },
+ };
+ let _ = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::RUSR).unwrap();
+
+ match utimensat(&dir, "foo", &timestamps, AtFlags::empty()) {
+ Ok(()) => (),
+
+ // On 32-bit platforms, accept `EOVERFLOW`, meaning that y2038 support
+ // is not available in this version of the OS.
+ #[cfg(target_pointer_width = "32")]
+ Err(rustix::io::Errno::OVERFLOW) => return,
+
+ Err(e) => panic!("unexpected error: {:?}", e),
+ }
+
+ // Use `statat` to read back the timestamp.
+ let stat = statat(&dir, "foo", AtFlags::empty()).unwrap();
+
+ assert_eq!(
+ TryInto::<u64>::try_into(stat.st_mtime).unwrap() as u64,
+ m_sec
+ );
+ assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
+ assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() as u64 >= a_sec);
+ assert!(
+ TryInto::<u64>::try_into(stat.st_atime).unwrap() as u64 > a_sec
+ || stat.st_atime_nsec as u32 >= a_nsec
+ );
+
+ // Now test the same thing, but with `fstat`.
+ let file = openat(&dir, "foo", OFlags::RDONLY, Mode::empty()).unwrap();
+ let stat = fstat(&file).unwrap();
+
+ assert_eq!(
+ TryInto::<u64>::try_into(stat.st_mtime).unwrap() as u64,
+ m_sec
+ );
+ assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
+ assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() as u64 >= a_sec);
+ assert!(
+ TryInto::<u64>::try_into(stat.st_atime).unwrap() as u64 > a_sec
+ || stat.st_atime_nsec as u32 >= a_nsec
+ );
+}
+
+/// Test that we can set a file timestamp to a date past the year 2038 with
+/// `futimens` and read it back again.
+///
+/// See tests/time/y2038.rs for more information about y2038 testing.
+#[cfg(not(all(target_env = "musl", target_pointer_width = "32")))]
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+#[cfg(not(all(target_os = "emscripten", target_pointer_width = "32")))]
+#[test]
+fn test_y2038_with_futimens() {
+ use rustix::fs::{
+ cwd, fstat, futimens, openat, statat, AtFlags, Mode, OFlags, Timespec, Timestamps,
+ };
+ use std::convert::TryInto;
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(&cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ let m_sec = 1_u64 << 32;
+ let m_nsec = 17_u32;
+ let a_sec = m_sec + 1;
+ let a_nsec = m_nsec + 1;
+
+ let timestamps = Timestamps {
+ last_modification: Timespec {
+ tv_sec: m_sec as _,
+ tv_nsec: m_nsec as _,
+ },
+ last_access: Timespec {
+ tv_sec: a_sec as _,
+ tv_nsec: a_nsec as _,
+ },
+ };
+ let file = openat(&dir, "foo", OFlags::CREATE | OFlags::WRONLY, Mode::RUSR).unwrap();
+
+ match futimens(&file, &timestamps) {
+ Ok(()) => (),
+
+ // On 32-bit platforms, accept `EOVERFLOW`, meaning that y2038 support
+ // is not available in this version of the OS.
+ #[cfg(target_pointer_width = "32")]
+ Err(rustix::io::Errno::OVERFLOW) => return,
+
+ Err(e) => panic!("unexpected error: {:?}", e),
+ }
+
+ // Use `statat` to read back the timestamp.
+ let stat = statat(&dir, "foo", AtFlags::empty()).unwrap();
+
+ assert_eq!(TryInto::<u64>::try_into(stat.st_mtime).unwrap(), m_sec);
+ assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
+ assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() >= a_sec);
+ assert!(
+ TryInto::<u64>::try_into(stat.st_atime).unwrap() > a_sec
+ || stat.st_atime_nsec as u32 >= a_nsec
+ );
+
+ // Now test the same thing, but with `fstat`.
+ let file = openat(&dir, "foo", OFlags::RDONLY, Mode::empty()).unwrap();
+ let stat = fstat(&file).unwrap();
+
+ assert_eq!(
+ TryInto::<u64>::try_into(stat.st_mtime).unwrap() as u64,
+ m_sec
+ );
+ assert_eq!(stat.st_mtime_nsec as u32, m_nsec);
+ assert!(TryInto::<u64>::try_into(stat.st_atime).unwrap() as u64 >= a_sec);
+ assert!(
+ TryInto::<u64>::try_into(stat.st_atime).unwrap() as u64 > a_sec
+ || stat.st_atime_nsec as u32 >= a_nsec
+ );
+}
diff --git a/vendor/rustix/tests/io/dup2_to_replace_stdio.rs b/vendor/rustix/tests/io/dup2_to_replace_stdio.rs
new file mode 100644
index 000000000..b07ec17f0
--- /dev/null
+++ b/vendor/rustix/tests/io/dup2_to_replace_stdio.rs
@@ -0,0 +1,18 @@
+#![cfg(not(target_os = "wasi"))]
+
+use std::env;
+use std::process::Command;
+
+/// Use `dup2` to replace the stdin and stdout file descriptors.
+#[test]
+fn dup2_to_replace_stdio() {
+ // This test modifies the stdio file descriptors, so we run it in a
+ // separate process so that it doesn't interfere with the test harness.
+ assert!(Command::new(env::var("CARGO").unwrap())
+ .arg("run")
+ .arg("--example")
+ .arg("dup2_to_replace_stdio")
+ .status()
+ .unwrap()
+ .success());
+}
diff --git a/vendor/rustix/tests/io/epoll.rs b/vendor/rustix/tests/io/epoll.rs
new file mode 100644
index 000000000..4cfe305fe
--- /dev/null
+++ b/vendor/rustix/tests/io/epoll.rs
@@ -0,0 +1,103 @@
+#![cfg(any(target_os = "android", target_os = "linux"))]
+
+use rustix::fd::AsFd;
+use rustix::io::epoll::{self, Epoll};
+use rustix::io::{ioctl_fionbio, read, write, OwnedFd};
+use rustix::net::{
+ accept, bind_v4, connect_v4, getsockname, listen, socket, AddressFamily, Ipv4Addr, Protocol,
+ SocketAddrAny, SocketAddrV4, SocketType,
+};
+use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use std::sync::{Arc, Condvar, Mutex};
+use std::thread;
+
+const BUFFER_SIZE: usize = 20;
+
+fn server(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap();
+ bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)).unwrap();
+ listen(&listen_sock, 1).unwrap();
+
+ let who = match getsockname(&listen_sock).unwrap() {
+ SocketAddrAny::V4(addr) => addr,
+ _ => panic!(),
+ };
+
+ {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ *port = who.port();
+ cvar.notify_all();
+ }
+
+ let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::<OwnedFd>::new()).unwrap();
+
+ // Test into conversions.
+ let fd: OwnedFd = epoll.into();
+ let epoll: Epoll<epoll::Owning<OwnedFd>> = fd.into();
+ let fd: RawFd = epoll.into_raw_fd();
+ let epoll = unsafe { Epoll::<epoll::Owning<OwnedFd>>::from_raw_fd(fd) };
+
+ let raw_listen_sock = listen_sock.as_fd().as_raw_fd();
+ epoll.add(listen_sock, epoll::EventFlags::IN).unwrap();
+
+ let mut event_list = epoll::EventVec::with_capacity(4);
+ loop {
+ epoll.wait(&mut event_list, -1).unwrap();
+ for (_event_flags, target) in &event_list {
+ if target.as_raw_fd() == raw_listen_sock {
+ let conn_sock = accept(&*target).unwrap();
+ ioctl_fionbio(&conn_sock, true).unwrap();
+ epoll
+ .add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET)
+ .unwrap();
+ } else {
+ write(&*target, b"hello\n").unwrap();
+ let _ = epoll.del(target).unwrap();
+ }
+ }
+ }
+}
+
+fn client(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let port = {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ while *port == 0 {
+ port = cvar.wait(port).unwrap();
+ }
+ *port
+ };
+
+ let addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
+ let mut buffer = vec![0; BUFFER_SIZE];
+
+ for _ in 0..16 {
+ let data_socket =
+ socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap();
+ connect_v4(&data_socket, &addr).unwrap();
+
+ let nread = read(&data_socket, &mut buffer).unwrap();
+ assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello\n");
+ }
+}
+
+#[test]
+fn test_epoll() {
+ let ready = Arc::new((Mutex::new(0_u16), Condvar::new()));
+ let ready_clone = Arc::clone(&ready);
+
+ let _server = thread::Builder::new()
+ .name("server".to_string())
+ .spawn(move || {
+ server(ready);
+ })
+ .unwrap();
+ let client = thread::Builder::new()
+ .name("client".to_string())
+ .spawn(move || {
+ client(ready_clone);
+ })
+ .unwrap();
+ client.join().unwrap();
+}
diff --git a/vendor/rustix/tests/io/error.rs b/vendor/rustix/tests/io/error.rs
new file mode 100644
index 000000000..128d3b59a
--- /dev/null
+++ b/vendor/rustix/tests/io/error.rs
@@ -0,0 +1,14 @@
+#[test]
+fn test_error() {
+ assert_eq!(
+ rustix::io::Errno::INVAL,
+ rustix::io::Errno::from_raw_os_error(rustix::io::Errno::INVAL.raw_os_error())
+ );
+ #[cfg(not(windows))]
+ assert_eq!(rustix::io::Errno::INVAL.raw_os_error(), libc::EINVAL);
+ #[cfg(windows)]
+ assert_eq!(
+ rustix::io::Errno::INVAL.raw_os_error(),
+ windows_sys::Win32::Networking::WinSock::WSAEINVAL
+ );
+}
diff --git a/vendor/rustix/tests/io/eventfd.rs b/vendor/rustix/tests/io/eventfd.rs
new file mode 100644
index 000000000..11bc8ae55
--- /dev/null
+++ b/vendor/rustix/tests/io/eventfd.rs
@@ -0,0 +1,24 @@
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_eventfd() {
+ use rustix::io::{eventfd, read, write, EventfdFlags};
+ use std::mem::size_of;
+ use std::thread;
+
+ let efd = eventfd(0, EventfdFlags::CLOEXEC).unwrap();
+
+ let child = thread::spawn(move || {
+ for u in [1_u64, 3, 6, 11, 5000].iter() {
+ assert_eq!(write(&efd, &u.to_ne_bytes()).unwrap(), size_of::<u64>());
+ }
+ efd
+ });
+
+ let efd = child.join().unwrap();
+
+ let mut bytes = [0_u8; size_of::<u64>()];
+ let s = read(&efd, &mut bytes).unwrap();
+ assert_eq!(s, bytes.len());
+ let u = u64::from_ne_bytes(bytes);
+ assert_eq!(u, 5021);
+}
diff --git a/vendor/rustix/tests/io/from_into.rs b/vendor/rustix/tests/io/from_into.rs
new file mode 100644
index 000000000..94d915993
--- /dev/null
+++ b/vendor/rustix/tests/io/from_into.rs
@@ -0,0 +1,28 @@
+#[cfg(feature = "fs")]
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn test_owned() {
+ use rustix::fd::AsFd;
+ #[cfg(unix)]
+ use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
+ #[cfg(target_os = "wasi")]
+ use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd};
+
+ let file = rustix::fs::openat(
+ rustix::fs::cwd(),
+ "Cargo.toml",
+ rustix::fs::OFlags::RDONLY,
+ rustix::fs::Mode::empty(),
+ )
+ .unwrap();
+
+ let raw = file.as_raw_fd();
+ assert_eq!(raw, file.as_fd().as_raw_fd());
+
+ let inner = file.into_raw_fd();
+ assert_eq!(raw, inner);
+
+ let new = unsafe { rustix::io::OwnedFd::from_raw_fd(inner) };
+ let mut buf = [0_u8; 4];
+ let _ = rustix::io::read(&new, &mut buf).unwrap();
+}
diff --git a/vendor/rustix/tests/io/ioctl.rs b/vendor/rustix/tests/io/ioctl.rs
new file mode 100644
index 000000000..e260e4884
--- /dev/null
+++ b/vendor/rustix/tests/io/ioctl.rs
@@ -0,0 +1,14 @@
+// `is_read_write` is not yet implemented on Windows. And `ioctl_fionread`
+// on Windows doesn't work on files.
+#[cfg(not(windows))]
+#[test]
+fn test_ioctls() {
+ let file = std::fs::File::open("Cargo.toml").unwrap();
+
+ assert_eq!(rustix::io::is_read_write(&file).unwrap(), (true, false));
+
+ assert_eq!(
+ rustix::io::ioctl_fionread(&file).unwrap(),
+ file.metadata().unwrap().len()
+ );
+}
diff --git a/vendor/rustix/tests/io/main.rs b/vendor/rustix/tests/io/main.rs
new file mode 100644
index 000000000..bdd044809
--- /dev/null
+++ b/vendor/rustix/tests/io/main.rs
@@ -0,0 +1,31 @@
+//! Tests for [`rustix::io`].
+
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+#[cfg(not(windows))]
+#[cfg(not(target_os = "wasi"))]
+mod dup2_to_replace_stdio;
+#[cfg(not(feature = "rustc-dep-of-std"))] // TODO
+#[cfg(not(windows))]
+#[cfg(feature = "net")]
+#[cfg(not(target_os = "wasi"))]
+mod epoll;
+mod error;
+#[cfg(not(windows))]
+#[cfg(not(target_os = "wasi"))]
+mod eventfd;
+#[cfg(not(windows))]
+mod from_into;
+#[cfg(not(target_os = "redox"))]
+mod ioctl;
+mod poll;
+#[cfg(all(feature = "procfs", any(target_os = "android", target_os = "linux")))]
+mod procfs;
+#[cfg(not(windows))]
+#[cfg(not(target_os = "redox"))] // redox doesn't have cwd/openat
+#[cfg(not(target_os = "wasi"))] // wasi support for S_IRUSR etc. submitted to libc in #2264
+mod read_write;
+#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "android"))]
+mod seals;
diff --git a/vendor/rustix/tests/io/poll.rs b/vendor/rustix/tests/io/poll.rs
new file mode 100644
index 000000000..ff2da695b
--- /dev/null
+++ b/vendor/rustix/tests/io/poll.rs
@@ -0,0 +1,63 @@
+use rustix::fd::{AsFd, AsRawFd, FromRawFd, IntoRawFd, OwnedFd};
+#[cfg(not(windows))]
+use rustix::io::{poll, retry_on_intr};
+use rustix::io::{PollFd, PollFlags};
+
+#[cfg(not(windows))]
+#[test]
+fn test_poll() {
+ use rustix::io::{pipe, read, write};
+
+ // Create a pipe.
+ let (reader, writer) = pipe().unwrap();
+ let mut poll_fds = [PollFd::new(&reader, PollFlags::IN)];
+ assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
+
+ // `poll` should say there's nothing ready to be read from the pipe.
+ let num = retry_on_intr(|| poll(&mut poll_fds, 0)).unwrap();
+ assert_eq!(num, 0);
+ assert!(poll_fds[0].revents().is_empty());
+ assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
+
+ // Write a byte to the pipe.
+ assert_eq!(retry_on_intr(|| write(&writer, b"a")).unwrap(), 1);
+
+ // `poll` should now say there's data to be read.
+ let num = retry_on_intr(|| poll(&mut poll_fds, -1)).unwrap();
+ assert_eq!(num, 1);
+ assert_eq!(poll_fds[0].revents(), PollFlags::IN);
+ assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
+
+ let mut temp = poll_fds[0].clone();
+ assert_eq!(temp.revents(), PollFlags::IN);
+ temp.clear_revents();
+ assert!(temp.revents().is_empty());
+
+ // Read the byte from the pipe.
+ let mut buf = [b'\0'];
+ assert_eq!(retry_on_intr(|| read(&reader, &mut buf)).unwrap(), 1);
+ assert_eq!(buf[0], b'a');
+ assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
+
+ // Poll should now say there's no more data to be read.
+ let num = retry_on_intr(|| poll(&mut poll_fds, 0)).unwrap();
+ assert_eq!(num, 0);
+ assert!(poll_fds[0].revents().is_empty());
+ assert_eq!(poll_fds[0].as_fd().as_raw_fd(), reader.as_fd().as_raw_fd());
+}
+
+#[test]
+fn test_poll_fd_set_fd() {
+ // Make up some file descriptors so that we can test that set_fd works.
+ let a = unsafe { OwnedFd::from_raw_fd(777) };
+ let mut poll_fd = PollFd::new(&a, PollFlags::empty());
+ assert_eq!(poll_fd.as_fd().as_raw_fd(), 777);
+
+ let b = unsafe { OwnedFd::from_raw_fd(888) };
+ poll_fd.set_fd(&b);
+ assert_eq!(poll_fd.as_fd().as_raw_fd(), 888);
+
+ // Don't attempt to close our made-up file descriptors.
+ let _ = a.into_raw_fd();
+ let _ = b.into_raw_fd();
+}
diff --git a/vendor/rustix/tests/io/procfs.rs b/vendor/rustix/tests/io/procfs.rs
new file mode 100644
index 000000000..4c4256bd7
--- /dev/null
+++ b/vendor/rustix/tests/io/procfs.rs
@@ -0,0 +1,8 @@
+use io_lifetimes::raw::AsRawFilelike;
+
+#[test]
+fn test_proc_self() {
+ // Verify that this API works at all
+ let fd = rustix::io::proc_self_fd().unwrap();
+ assert_ne!(fd.as_raw_filelike(), 0);
+}
diff --git a/vendor/rustix/tests/io/read_write.rs b/vendor/rustix/tests/io/read_write.rs
new file mode 100644
index 000000000..65186bf21
--- /dev/null
+++ b/vendor/rustix/tests/io/read_write.rs
@@ -0,0 +1,118 @@
+#[cfg(feature = "fs")]
+use std::io::{IoSlice, IoSliceMut};
+
+#[cfg(feature = "fs")]
+#[test]
+fn test_readwrite_pv() {
+ use rustix::fs::{cwd, openat, Mode, OFlags};
+ use rustix::io::{preadv, pwritev};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let foo = openat(
+ &dir,
+ "foo",
+ OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ // For most targets, just call `pwritev`.
+ #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+ {
+ pwritev(&foo, &[IoSlice::new(b"hello")], 200).unwrap();
+ }
+ // macOS only has pwritev in newer versions; allow it to fail with `ENOSYS`.
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ {
+ match pwritev(&foo, &[IoSlice::new(b"hello")], 200) {
+ Ok(_) => (),
+ Err(rustix::io::Errno::NOSYS) => return,
+ Err(err) => Err(err).unwrap(),
+ }
+ }
+ pwritev(&foo, &[IoSlice::new(b"world")], 300).unwrap();
+ let mut buf = [0_u8; 5];
+ preadv(&foo, &mut [IoSliceMut::new(&mut buf)], 200).unwrap();
+ assert_eq!(&buf, b"hello");
+ preadv(&foo, &mut [IoSliceMut::new(&mut buf)], 300).unwrap();
+ assert_eq!(&buf, b"world");
+}
+
+#[cfg(feature = "fs")]
+#[test]
+fn test_readwrite_p() {
+ use rustix::fs::{cwd, openat, Mode, OFlags};
+ use rustix::io::{pread, pwrite};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let foo = openat(
+ &dir,
+ "foo",
+ OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ pwrite(&foo, b"hello", 200).unwrap();
+ pwrite(&foo, b"world", 300).unwrap();
+ let mut buf = [0_u8; 5];
+ pread(&foo, &mut buf, 200).unwrap();
+ assert_eq!(&buf, b"hello");
+ pread(&foo, &mut buf, 300).unwrap();
+ assert_eq!(&buf, b"world");
+}
+
+#[cfg(feature = "fs")]
+#[test]
+fn test_readwrite_v() {
+ use rustix::fs::{cwd, openat, seek, Mode, OFlags};
+ use rustix::io::{readv, writev, SeekFrom};
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let foo = openat(
+ &dir,
+ "foo",
+ OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ writev(&foo, &[IoSlice::new(b"hello")]).unwrap();
+ writev(&foo, &[IoSlice::new(b"world")]).unwrap();
+ seek(&foo, SeekFrom::Start(0)).unwrap();
+ let mut buf = [0_u8; 5];
+ readv(&foo, &mut [IoSliceMut::new(&mut buf)]).unwrap();
+ assert_eq!(&buf, b"hello");
+ readv(&foo, &mut [IoSliceMut::new(&mut buf)]).unwrap();
+ assert_eq!(&buf, b"world");
+}
+
+#[cfg(feature = "fs")]
+#[test]
+fn test_readwrite() {
+ use rustix::fs::{cwd, openat, seek, Mode, OFlags};
+ use rustix::io::{read, write};
+ use std::io::SeekFrom;
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+ let foo = openat(
+ &dir,
+ "foo",
+ OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC,
+ Mode::RUSR | Mode::WUSR,
+ )
+ .unwrap();
+
+ write(&foo, b"hello").unwrap();
+ write(&foo, b"world").unwrap();
+ seek(&foo, SeekFrom::Start(0)).unwrap();
+ let mut buf = [0_u8; 5];
+ read(&foo, &mut buf).unwrap();
+ assert_eq!(&buf, b"hello");
+ read(&foo, &mut buf).unwrap();
+ assert_eq!(&buf, b"world");
+}
diff --git a/vendor/rustix/tests/io/seals.rs b/vendor/rustix/tests/io/seals.rs
new file mode 100644
index 000000000..ff971fa75
--- /dev/null
+++ b/vendor/rustix/tests/io/seals.rs
@@ -0,0 +1,41 @@
+#[cfg(feature = "fs")]
+#[test]
+fn test_seals() {
+ use rustix::fd::FromFd;
+ use rustix::fs::{
+ fcntl_add_seals, fcntl_get_seals, ftruncate, memfd_create, MemfdFlags, SealFlags,
+ };
+ use std::fs::File;
+ use std::io::Write;
+
+ let fd = match memfd_create("test", MemfdFlags::CLOEXEC | MemfdFlags::ALLOW_SEALING) {
+ Ok(fd) => fd,
+ Err(rustix::io::Errno::NOSYS) => return,
+ Err(err) => Err(err).unwrap(),
+ };
+ let mut file = File::from_fd(fd.into());
+
+ let old = fcntl_get_seals(&file).unwrap();
+ assert_eq!(old, SealFlags::empty());
+
+ writeln!(&mut file, "Hello!").unwrap();
+
+ fcntl_add_seals(&file, SealFlags::GROW).unwrap();
+
+ let now = fcntl_get_seals(&file).unwrap();
+ assert_eq!(now, SealFlags::GROW);
+
+ // We sealed growing, so this should fail.
+ writeln!(&mut file, "World?").unwrap_err();
+
+ // We can still shrink for now.
+ ftruncate(&mut file, 1).unwrap();
+
+ fcntl_add_seals(&file, SealFlags::SHRINK).unwrap();
+
+ let now = fcntl_get_seals(&file).unwrap();
+ assert_eq!(now, SealFlags::GROW | SealFlags::SHRINK);
+
+ // We sealed shrinking, so this should fail.
+ ftruncate(&mut file, 0).unwrap_err();
+}
diff --git a/vendor/rustix/tests/mm/main.rs b/vendor/rustix/tests/mm/main.rs
new file mode 100644
index 000000000..ee746d900
--- /dev/null
+++ b/vendor/rustix/tests/mm/main.rs
@@ -0,0 +1,13 @@
+//! Tests for [`rustix::mm`].
+
+#![cfg(feature = "mm")]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+#[cfg(not(windows))]
+#[cfg(not(target_os = "wasi"))]
+mod mlock;
+#[cfg(not(windows))]
+mod mmap;
+#[cfg(not(windows))]
+mod prot;
diff --git a/vendor/rustix/tests/mm/mlock.rs b/vendor/rustix/tests/mm/mlock.rs
new file mode 100644
index 000000000..c4a1a83b5
--- /dev/null
+++ b/vendor/rustix/tests/mm/mlock.rs
@@ -0,0 +1,79 @@
+//! Tests for `mlock`.
+//!
+//! We can't easily test that it actually locks memory, but we can test that we
+//! can call it and either get success or a reasonable error message.
+
+use std::ffi::c_void;
+
+#[test]
+fn test_mlock() {
+ let mut buf = vec![0_u8; 4096];
+
+ unsafe {
+ match rustix::mm::mlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()) {
+ Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(),
+ // Tests won't always have enough memory or permissions, and that's ok.
+ Err(rustix::io::Errno::PERM) | Err(rustix::io::Errno::NOMEM) => {}
+ // But they shouldn't fail otherwise.
+ Err(other) => Err(other).unwrap(),
+ }
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_mlock_with() {
+ let mut buf = vec![0_u8; 4096];
+
+ unsafe {
+ match rustix::mm::mlock_with(
+ buf.as_mut_ptr().cast::<c_void>(),
+ buf.len(),
+ rustix::mm::MlockFlags::empty(),
+ ) {
+ Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(),
+ // Tests won't always have enough memory or permissions, and that's ok.
+ Err(rustix::io::Errno::PERM)
+ | Err(rustix::io::Errno::NOMEM)
+ | Err(rustix::io::Errno::NOSYS) => {}
+ // But they shouldn't fail otherwise.
+ Err(other) => Err(other).unwrap(),
+ }
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_mlock_with_onfault() {
+ // With glibc, `mlock2` with `MLOCK_ONFAULT` returns `EINVAL` if the
+ // `mlock2` system call returns `ENOSYS`. That's not what we want
+ // here though, because `ENOSYS` just means the OS doesn't have
+ // `mlock2`, while `EINVAL` may indicate a bug in rustix.
+ //
+ // To work around this, we use `libc::syscall` to make a `mlock2`
+ // syscall directly to test for `ENOSYS`, before running the main
+ // test below.
+ unsafe {
+ if libc::syscall(libc::SYS_mlock2, 0, 0) == -1 && libc_errno::errno().0 == libc::ENOSYS {
+ return;
+ }
+ }
+
+ let mut buf = vec![0_u8; 4096];
+
+ unsafe {
+ match rustix::mm::mlock_with(
+ buf.as_mut_ptr().cast::<c_void>(),
+ buf.len(),
+ rustix::mm::MlockFlags::ONFAULT,
+ ) {
+ Ok(()) => rustix::mm::munlock(buf.as_mut_ptr().cast::<c_void>(), buf.len()).unwrap(),
+ // Tests won't always have enough memory or permissions, and that's ok.
+ Err(rustix::io::Errno::PERM)
+ | Err(rustix::io::Errno::NOMEM)
+ | Err(rustix::io::Errno::NOSYS) => {}
+ // But they shouldn't fail otherwise.
+ Err(other) => Err(other).unwrap(),
+ }
+ }
+}
diff --git a/vendor/rustix/tests/mm/mmap.rs b/vendor/rustix/tests/mm/mmap.rs
new file mode 100644
index 000000000..6b27287d7
--- /dev/null
+++ b/vendor/rustix/tests/mm/mmap.rs
@@ -0,0 +1,163 @@
+#![cfg(not(target_os = "wasi"))]
+
+#[cfg(feature = "fs")]
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn test_mmap() {
+ use rustix::fs::{cwd, openat, Mode, OFlags};
+ use rustix::io::write;
+ use rustix::mm::{mmap, munmap, MapFlags, ProtFlags};
+ use std::ptr::null_mut;
+ use std::slice;
+
+ let tmp = tempfile::tempdir().unwrap();
+ let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
+
+ let file = openat(
+ &dir,
+ "foo",
+ OFlags::CREATE | OFlags::WRONLY | OFlags::TRUNC,
+ Mode::RUSR,
+ )
+ .unwrap();
+ write(&file, &[b'a'; 8192]).unwrap();
+ drop(file);
+
+ let file = openat(&dir, "foo", OFlags::RDONLY, Mode::empty()).unwrap();
+ unsafe {
+ let addr = mmap(
+ null_mut(),
+ 8192,
+ ProtFlags::READ,
+ MapFlags::PRIVATE,
+ &file,
+ 0,
+ )
+ .unwrap();
+ let slice = slice::from_raw_parts(addr.cast::<u8>(), 8192);
+ assert_eq!(slice, &[b'a'; 8192]);
+
+ munmap(addr, 8192).unwrap();
+ }
+
+ let file = openat(&dir, "foo", OFlags::RDONLY, Mode::empty()).unwrap();
+ unsafe {
+ assert_eq!(
+ mmap(
+ null_mut(),
+ 8192,
+ ProtFlags::READ,
+ MapFlags::PRIVATE,
+ &file,
+ u64::MAX,
+ )
+ .unwrap_err()
+ .raw_os_error(),
+ libc::EINVAL
+ );
+ }
+}
+
+#[test]
+fn test_mmap_anonymous() {
+ use rustix::mm::{mmap_anonymous, munmap, MapFlags, ProtFlags};
+ use std::ptr::null_mut;
+ use std::slice;
+
+ unsafe {
+ let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap();
+ let slice = slice::from_raw_parts(addr.cast::<u8>(), 8192);
+ assert_eq!(slice, &[b'\0'; 8192]);
+
+ munmap(addr, 8192).unwrap();
+ }
+}
+
+#[test]
+fn test_mprotect() {
+ use rustix::mm::{mmap_anonymous, mprotect, munmap, MapFlags, MprotectFlags, ProtFlags};
+ use std::ptr::null_mut;
+ use std::slice;
+
+ unsafe {
+ let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap();
+
+ mprotect(addr, 8192, MprotectFlags::empty()).unwrap();
+ mprotect(addr, 8192, MprotectFlags::READ).unwrap();
+
+ let slice = slice::from_raw_parts(addr.cast::<u8>(), 8192);
+ assert_eq!(slice, &[b'\0'; 8192]);
+
+ munmap(addr, 8192).unwrap();
+ }
+}
+
+#[test]
+fn test_mlock() {
+ use rustix::mm::{mlock, mmap_anonymous, munlock, munmap, MapFlags, ProtFlags};
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ use rustix::mm::{mlock_with, MlockFlags};
+ use std::ptr::null_mut;
+
+ unsafe {
+ let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap();
+
+ mlock(addr, 8192).unwrap();
+ munlock(addr, 8192).unwrap();
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ match mlock_with(addr, 8192, MlockFlags::empty()) {
+ Err(rustix::io::Errno::NOSYS) => (),
+ Err(err) => Err(err).unwrap(),
+ Ok(()) => munlock(addr, 8192).unwrap(),
+ }
+
+ #[cfg(linux_raw)] // libc doesn't expose `MLOCK_UNFAULT` yet.
+ {
+ match mlock_with(addr, 8192, MlockFlags::ONFAULT) {
+ Err(rustix::io::Errno::NOSYS) => (),
+ Err(err) => Err(err).unwrap(),
+ Ok(()) => munlock(addr, 8192).unwrap(),
+ }
+ munlock(addr, 8192).unwrap();
+ }
+ }
+
+ munmap(addr, 8192).unwrap();
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn test_madvise() {
+ use rustix::mm::{madvise, mmap_anonymous, munmap, Advice, MapFlags, ProtFlags};
+ use std::ptr::null_mut;
+
+ unsafe {
+ let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap();
+
+ madvise(addr, 8192, Advice::Normal).unwrap();
+ madvise(addr, 8192, Advice::DontNeed).unwrap();
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ madvise(addr, 8192, Advice::LinuxDontNeed).unwrap();
+
+ munmap(addr, 8192).unwrap();
+ }
+}
+
+#[test]
+fn test_msync() {
+ use rustix::mm::{mmap_anonymous, msync, munmap, MapFlags, MsyncFlags, ProtFlags};
+ use std::ptr::null_mut;
+
+ unsafe {
+ let addr = mmap_anonymous(null_mut(), 8192, ProtFlags::READ, MapFlags::PRIVATE).unwrap();
+
+ msync(addr, 8192, MsyncFlags::SYNC).unwrap();
+ msync(addr, 8192, MsyncFlags::ASYNC).unwrap();
+
+ munmap(addr, 8192).unwrap();
+ }
+}
diff --git a/vendor/rustix/tests/mm/prot.rs b/vendor/rustix/tests/mm/prot.rs
new file mode 100644
index 000000000..6c86a8f2a
--- /dev/null
+++ b/vendor/rustix/tests/mm/prot.rs
@@ -0,0 +1,4 @@
+#[test]
+fn test_prot_flags() {
+ assert_eq!(libc::PROT_NONE, 0);
+}
diff --git a/vendor/rustix/tests/net/addr.rs b/vendor/rustix/tests/net/addr.rs
new file mode 100644
index 000000000..124413132
--- /dev/null
+++ b/vendor/rustix/tests/net/addr.rs
@@ -0,0 +1,92 @@
+#[test]
+fn encode_decode() {
+ #[cfg(unix)]
+ use rustix::net::SocketAddrUnix;
+ use rustix::net::{
+ Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrStorage, SocketAddrV4, SocketAddrV6,
+ };
+
+ unsafe {
+ let orig = SocketAddrV4::new(Ipv4Addr::new(2, 3, 5, 6), 33);
+ let mut encoded = std::mem::MaybeUninit::<SocketAddrStorage>::uninit();
+ let len = SocketAddrAny::V4(orig).write(encoded.as_mut_ptr());
+ let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap();
+ assert_eq!(decoded, SocketAddrAny::V4(orig));
+
+ let orig = SocketAddrV6::new(Ipv6Addr::new(2, 3, 5, 6, 8, 9, 11, 12), 33, 34, 36);
+ let mut encoded = std::mem::MaybeUninit::<SocketAddrStorage>::uninit();
+ let len = SocketAddrAny::V6(orig).write(encoded.as_mut_ptr());
+ let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap();
+ assert_eq!(decoded, SocketAddrAny::V6(orig));
+
+ #[cfg(not(windows))]
+ {
+ let orig = SocketAddrUnix::new("/path/to/socket").unwrap();
+ let mut encoded = std::mem::MaybeUninit::<SocketAddrStorage>::uninit();
+ let len = SocketAddrAny::Unix(orig.clone()).write(encoded.as_mut_ptr());
+ let decoded = SocketAddrAny::read(encoded.as_ptr(), len).unwrap();
+ assert_eq!(decoded, SocketAddrAny::Unix(orig));
+ }
+ }
+}
+
+#[cfg(not(windows))]
+#[test]
+fn test_unix_addr() {
+ use rustix::cstr;
+ use rustix::net::SocketAddrUnix;
+
+ assert_eq!(
+ SocketAddrUnix::new("/").unwrap().path().unwrap(),
+ cstr!("/")
+ );
+ assert_eq!(
+ SocketAddrUnix::new("//").unwrap().path().unwrap(),
+ cstr!("//")
+ );
+ assert_eq!(
+ SocketAddrUnix::new("/foo/bar").unwrap().path().unwrap(),
+ cstr!("/foo/bar")
+ );
+ assert_eq!(
+ SocketAddrUnix::new("foo").unwrap().path().unwrap(),
+ cstr!("foo")
+ );
+ SocketAddrUnix::new("/foo\0/bar").unwrap_err();
+ assert!(SocketAddrUnix::new("").unwrap().path().is_none());
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ assert!(SocketAddrUnix::new("foo")
+ .unwrap()
+ .abstract_name()
+ .is_none());
+
+ assert_eq!(
+ SocketAddrUnix::new_abstract_name(b"test")
+ .unwrap()
+ .abstract_name()
+ .unwrap(),
+ b"test"
+ );
+ assert_eq!(
+ SocketAddrUnix::new_abstract_name(b"")
+ .unwrap()
+ .abstract_name()
+ .unwrap(),
+ b""
+ );
+ assert_eq!(
+ SocketAddrUnix::new_abstract_name(b"this\0that")
+ .unwrap()
+ .abstract_name()
+ .unwrap(),
+ b"this\0that"
+ );
+ SocketAddrUnix::new_abstract_name(&[b'a'; 500]).unwrap_err();
+ assert!(SocketAddrUnix::new_abstract_name(b"test")
+ .unwrap()
+ .path()
+ .is_none());
+ }
+}
diff --git a/vendor/rustix/tests/net/connect_bind_send.rs b/vendor/rustix/tests/net/connect_bind_send.rs
new file mode 100644
index 000000000..84720975f
--- /dev/null
+++ b/vendor/rustix/tests/net/connect_bind_send.rs
@@ -0,0 +1,487 @@
+use rustix::net::{
+ AddressFamily, Ipv6Addr, Protocol, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4,
+ SocketAddrV6, SocketType,
+};
+use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+
+/// Test `connect_any`.
+#[test]
+fn net_v4_connect_any() -> std::io::Result<()> {
+ let localhost = IpAddr::V4(Ipv4Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener =
+ rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
+
+/// Similar, but with V6.
+#[test]
+fn net_v6_connect_any() -> std::io::Result<()> {
+ let localhost = IpAddr::V6(Ipv6Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
+
+/// Test `connect` with a `SocketAddr`.
+#[test]
+fn net_v4_connect() -> std::io::Result<()> {
+ let localhost = IpAddr::V4(Ipv4Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener =
+ rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let local_addr = match local_addr {
+ SocketAddrAny::V4(v4) => SocketAddr::V4(v4),
+ other => panic!("unexpected socket address {:?}", other),
+ };
+ let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::connect(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
+
+/// Similar, but use V6.
+#[test]
+fn net_v6_connect() -> std::io::Result<()> {
+ let localhost = IpAddr::V6(Ipv6Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let local_addr = match local_addr {
+ SocketAddrAny::V6(v6) => SocketAddr::V6(v6),
+ other => panic!("unexpected socket address {:?}", other),
+ };
+ let sender = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::connect(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
+
+/// Test `bind_any`.
+#[test]
+fn net_v4_bind_any() -> std::io::Result<()> {
+ let localhost = Ipv4Addr::LOCALHOST;
+ let addr = SocketAddrAny::V4(SocketAddrV4::new(localhost, 0));
+ let listener =
+ rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::bind_any(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
+
+/// Similar, but use V6.
+#[test]
+fn net_v6_bind_any() -> std::io::Result<()> {
+ let localhost = Ipv6Addr::LOCALHOST;
+ let addr = SocketAddrAny::V6(SocketAddrV6::new(localhost, 0, 0, 0));
+ let listener = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::bind_any(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
+
+/// Test `sendto`.
+#[test]
+fn net_v4_sendto() -> std::io::Result<()> {
+ let localhost = IpAddr::V4(Ipv4Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener =
+ rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let local_addr = match local_addr {
+ SocketAddrAny::V4(v4) => SocketAddr::V4(v4),
+ other => panic!("unexpected socket address {:?}", other),
+ };
+ let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let (n, from) =
+ rustix::net::recvfrom(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+ assert!(from.is_none());
+
+ Ok(())
+}
+
+/// Similar, but with V6.
+#[test]
+fn net_v6_sendto() -> std::io::Result<()> {
+ let localhost = IpAddr::V6(Ipv6Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let local_addr = match local_addr {
+ SocketAddrAny::V6(v6) => SocketAddr::V6(v6),
+ other => panic!("unexpected socket address {:?}", other),
+ };
+ let n = rustix::net::sendto(&sender, request, SendFlags::empty(), &local_addr).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let (n, from) =
+ rustix::net::recvfrom(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+ assert!(from.is_none());
+
+ Ok(())
+}
+
+/// Test `sendto_any`.
+#[test]
+fn net_v4_sendto_any() -> std::io::Result<()> {
+ let localhost = IpAddr::V4(Ipv4Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener =
+ rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n =
+ rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let (n, from) =
+ rustix::net::recvfrom(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+ assert!(from.is_none());
+
+ Ok(())
+}
+
+/// Test `sendto_any`.
+#[test]
+fn net_v6_sendto_any() -> std::io::Result<()> {
+ let localhost = IpAddr::V6(Ipv6Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n =
+ rustix::net::sendto_any(&sender, request, SendFlags::empty(), &local_addr).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let accepted = rustix::net::accept(&listener).expect("accept");
+ let mut response = [0_u8; 128];
+ let (n, from) =
+ rustix::net::recvfrom(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+ assert!(from.is_none());
+
+ Ok(())
+}
+
+/// Test `acceptfrom`.
+#[test]
+fn net_v4_acceptfrom() -> std::io::Result<()> {
+ let localhost = IpAddr::V4(Ipv4Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener =
+ rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let (accepted, from) = rustix::net::acceptfrom(&listener).expect("accept");
+
+ assert_ne!(from.clone().unwrap(), local_addr);
+
+ let from = match from.unwrap() {
+ SocketAddrAny::V4(v4) => v4,
+ other => panic!("unexpected socket address {:?}", other),
+ };
+ let local_addr = match local_addr {
+ SocketAddrAny::V4(v4) => v4,
+ other => panic!("unexpected socket address {:?}", other),
+ };
+
+ assert_eq!(from.clone().ip(), local_addr.ip());
+ assert_ne!(from.clone().port(), local_addr.port());
+
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
+
+/// Similar, but with V6.
+#[test]
+fn net_v6_acceptfrom() -> std::io::Result<()> {
+ let localhost = IpAddr::V6(Ipv6Addr::LOCALHOST);
+ let addr = SocketAddr::new(localhost, 0);
+ let listener = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::bind(&listener, &addr).expect("bind");
+ rustix::net::listen(&listener, 1).expect("listen");
+
+ let local_addr = rustix::net::getsockname(&listener)?;
+ let sender = rustix::net::socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )?;
+ rustix::net::connect_any(&sender, &local_addr).expect("connect");
+ let request = b"Hello, World!!!";
+ let n = rustix::net::send(&sender, request, SendFlags::empty()).expect("send");
+ drop(sender);
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ let (accepted, from) = rustix::net::acceptfrom(&listener).expect("accept");
+
+ assert_ne!(from.clone().unwrap(), local_addr);
+
+ let from = match from.unwrap() {
+ SocketAddrAny::V6(v6) => v6,
+ other => panic!("unexpected socket address {:?}", other),
+ };
+ let local_addr = match local_addr {
+ SocketAddrAny::V6(v6) => v6,
+ other => panic!("unexpected socket address {:?}", other),
+ };
+
+ assert_eq!(from.clone().ip(), local_addr.ip());
+ assert_ne!(from.clone().port(), local_addr.port());
+
+ let mut response = [0_u8; 128];
+ let n = rustix::net::recv(&accepted, &mut response, RecvFlags::empty()).expect("recv");
+
+ // Not strictly required, but it makes the test simpler.
+ assert_eq!(n, request.len());
+
+ assert_eq!(request, &response[..n]);
+
+ Ok(())
+}
diff --git a/vendor/rustix/tests/net/main.rs b/vendor/rustix/tests/net/main.rs
new file mode 100644
index 000000000..0745282aa
--- /dev/null
+++ b/vendor/rustix/tests/net/main.rs
@@ -0,0 +1,32 @@
+//! Tests for [`rustix::net`].
+
+#![cfg(feature = "net")]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg(not(any(target_os = "redox", target_os = "wasi")))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+#![cfg_attr(core_c_str, feature(core_c_str))]
+
+mod addr;
+mod connect_bind_send;
+mod poll;
+mod sockopt;
+#[cfg(unix)]
+mod unix;
+mod v4;
+mod v6;
+
+/// Windows requires us to call a setup function before using any of the
+/// socket APIs.
+#[cfg(windows)]
+#[ctor::ctor]
+fn windows_startup() {
+ let _ = rustix::net::wsa_startup().unwrap();
+}
+
+/// Windows requires us to call a cleanup function after using any of the
+/// socket APIs.
+#[cfg(windows)]
+#[ctor::dtor]
+fn windows_shutdown() {
+ rustix::net::wsa_cleanup().unwrap();
+}
diff --git a/vendor/rustix/tests/net/poll.rs b/vendor/rustix/tests/net/poll.rs
new file mode 100644
index 000000000..7933983f2
--- /dev/null
+++ b/vendor/rustix/tests/net/poll.rs
@@ -0,0 +1,119 @@
+//! The same as v6.rs, but with `poll` calls.
+
+#![cfg(not(any(target_os = "redox", target_os = "wasi")))]
+
+use rustix::io::{poll, PollFd, PollFlags};
+use rustix::net::{
+ accept, bind_v6, connect_v6, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr,
+ Protocol, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV6, SocketType,
+};
+use std::sync::{Arc, Condvar, Mutex};
+use std::thread;
+
+const BUFFER_SIZE: usize = 20;
+
+fn server(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let connection_socket = socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )
+ .unwrap();
+
+ let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0);
+ bind_v6(&connection_socket, &name).unwrap();
+
+ let who = match getsockname(&connection_socket).unwrap() {
+ SocketAddrAny::V6(addr) => addr,
+ _ => panic!(),
+ };
+
+ listen(&connection_socket, 1).unwrap();
+
+ {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ *port = who.port();
+ cvar.notify_all();
+ }
+
+ let mut buffer = vec![0; BUFFER_SIZE];
+ let data_socket = accept(&connection_socket).unwrap();
+
+ let mut fds = [PollFd::new(&data_socket, PollFlags::IN)];
+ assert_eq!(poll(&mut fds, -1).unwrap(), 1);
+ assert!(fds[0].revents().intersects(PollFlags::IN));
+ assert!(!fds[0].revents().intersects(PollFlags::OUT));
+
+ let expected_nread = rustix::io::ioctl_fionread(&data_socket).unwrap();
+ let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
+ assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello, world");
+ assert_eq!(expected_nread, nread as u64);
+
+ let mut fds = [PollFd::new(&data_socket, PollFlags::OUT)];
+ assert_eq!(poll(&mut fds, -1).unwrap(), 1);
+ assert!(!fds[0].revents().intersects(PollFlags::IN));
+ assert!(fds[0].revents().intersects(PollFlags::OUT));
+
+ send(&data_socket, b"goodnight, moon", SendFlags::empty()).unwrap();
+}
+
+fn client(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let port = {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ while *port == 0 {
+ port = cvar.wait(port).unwrap();
+ }
+ *port
+ };
+
+ let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), port, 0, 0);
+ let mut buffer = vec![0; BUFFER_SIZE];
+
+ let data_socket = socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )
+ .unwrap();
+ connect_v6(&data_socket, &addr).unwrap();
+
+ let mut fds = [PollFd::new(&data_socket, PollFlags::OUT)];
+ assert_eq!(poll(&mut fds, -1).unwrap(), 1);
+ assert!(!fds[0].revents().intersects(PollFlags::IN));
+ assert!(fds[0].revents().intersects(PollFlags::OUT));
+
+ send(&data_socket, b"hello, world", SendFlags::empty()).unwrap();
+
+ let mut fds = [PollFd::new(&data_socket, PollFlags::IN)];
+ assert_eq!(poll(&mut fds, -1).unwrap(), 1);
+ assert!(fds[0].revents().intersects(PollFlags::IN));
+ assert!(!fds[0].revents().intersects(PollFlags::OUT));
+
+ let expected_nread = rustix::io::ioctl_fionread(&data_socket).unwrap();
+ let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
+ assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "goodnight, moon");
+ assert_eq!(expected_nread, nread as u64);
+}
+
+#[test]
+fn test_poll() {
+ let ready = Arc::new((Mutex::new(0_u16), Condvar::new()));
+ let ready_clone = Arc::clone(&ready);
+
+ let server = thread::Builder::new()
+ .name("server".to_string())
+ .spawn(move || {
+ server(ready);
+ })
+ .unwrap();
+ let client = thread::Builder::new()
+ .name("client".to_string())
+ .spawn(move || {
+ client(ready_clone);
+ })
+ .unwrap();
+ client.join().unwrap();
+ server.join().unwrap();
+}
diff --git a/vendor/rustix/tests/net/sockopt.rs b/vendor/rustix/tests/net/sockopt.rs
new file mode 100644
index 000000000..8e4cf52e8
--- /dev/null
+++ b/vendor/rustix/tests/net/sockopt.rs
@@ -0,0 +1,158 @@
+#[test]
+fn test_sockopts() {
+ use rustix::net::{AddressFamily, Protocol, SocketType};
+ use std::time::Duration;
+
+ let s =
+ rustix::net::socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap();
+
+ // On a new socket we shouldn't have a timeout yet.
+ assert!(
+ rustix::net::sockopt::get_socket_timeout(&s, rustix::net::sockopt::Timeout::Recv)
+ .unwrap()
+ .is_none()
+ );
+ assert_eq!(
+ rustix::net::sockopt::get_socket_type(&s).unwrap(),
+ SocketType::STREAM
+ );
+ #[cfg(not(windows))]
+ assert_eq!(
+ rustix::net::sockopt::get_socket_broadcast(&s).unwrap(),
+ false
+ );
+ // On a new socket we shouldn't have a linger yet.
+ assert!(rustix::net::sockopt::get_socket_linger(&s)
+ .unwrap()
+ .is_none());
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ assert_eq!(
+ rustix::net::sockopt::get_socket_passcred(&s).unwrap(),
+ false
+ );
+ assert_ne!(rustix::net::sockopt::get_ip_ttl(&s).unwrap(), 0);
+ assert_ne!(rustix::net::sockopt::get_ip_ttl(&s).unwrap(), 77);
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ assert_eq!(
+ rustix::net::sockopt::get_ip_multicast_loop(&s).unwrap(),
+ true
+ );
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ assert_eq!(rustix::net::sockopt::get_ip_multicast_ttl(&s).unwrap(), 1);
+ assert_eq!(rustix::net::sockopt::get_tcp_nodelay(&s).unwrap(), false);
+
+ // Set a timeout.
+ rustix::net::sockopt::set_socket_timeout(
+ &s,
+ rustix::net::sockopt::Timeout::Recv,
+ Some(Duration::new(1, 1)),
+ )
+ .unwrap();
+
+ // Check that we have a timeout of at least the time we set.
+ if cfg!(not(target_os = "freebsd")) {
+ assert!(
+ rustix::net::sockopt::get_socket_timeout(&s, rustix::net::sockopt::Timeout::Recv)
+ .unwrap()
+ .unwrap()
+ >= Duration::new(1, 1)
+ );
+ } else {
+ // On FreeBSD <= 12, it appears the system rounds the timeout down.
+ assert!(
+ rustix::net::sockopt::get_socket_timeout(&s, rustix::net::sockopt::Timeout::Recv)
+ .unwrap()
+ .unwrap()
+ >= Duration::new(1, 0)
+ );
+ }
+
+ #[cfg(not(windows))]
+ {
+ // Set the broadcast flag;
+ rustix::net::sockopt::set_socket_broadcast(&s, true).unwrap();
+
+ // Check that the broadcast flag is set. This has no effect on stream
+ // sockets, and not all platforms even remember the value.
+ #[cfg(not(any(
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ assert_eq!(
+ rustix::net::sockopt::get_socket_broadcast(&s).unwrap(),
+ true
+ );
+ }
+
+ // Set a linger.
+ rustix::net::sockopt::set_socket_linger(&s, Some(Duration::new(1, 1))).unwrap();
+
+ // Check that we have a linger of at least the time we set.
+ assert!(
+ dbg!(rustix::net::sockopt::get_socket_linger(&s)
+ .unwrap()
+ .unwrap())
+ >= Duration::new(1, 1)
+ );
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ // Set the passcred flag;
+ rustix::net::sockopt::set_socket_passcred(&s, true).unwrap();
+
+ // Check that the passcred flag is set.
+ assert_eq!(rustix::net::sockopt::get_socket_passcred(&s).unwrap(), true);
+ }
+
+ // Set the ip ttl.
+ rustix::net::sockopt::set_ip_ttl(&s, 77).unwrap();
+
+ // Check the ip ttl.
+ assert_eq!(rustix::net::sockopt::get_ip_ttl(&s).unwrap(), 77);
+
+ #[cfg(not(any(
+ windows,
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ )))]
+ {
+ // Set the multicast loop flag;
+ rustix::net::sockopt::set_ip_multicast_loop(&s, false).unwrap();
+
+ // Check that the multicast loop flag is set.
+ assert_eq!(
+ rustix::net::sockopt::get_ip_multicast_loop(&s).unwrap(),
+ false
+ );
+ }
+
+ // Set the nodelay flag;
+ rustix::net::sockopt::set_tcp_nodelay(&s, true).unwrap();
+
+ // Check that the nodelay flag is set.
+ assert_eq!(rustix::net::sockopt::get_tcp_nodelay(&s).unwrap(), true);
+}
diff --git a/vendor/rustix/tests/net/unix.rs b/vendor/rustix/tests/net/unix.rs
new file mode 100644
index 000000000..21a6542f8
--- /dev/null
+++ b/vendor/rustix/tests/net/unix.rs
@@ -0,0 +1,147 @@
+//! Test a simple Unix-domain socket server and client.
+//!
+//! The client sends lists of integers and the server sends back sums.
+
+// This test uses `AF_UNIX` with `SOCK_SEQPACKET` which is unsupported on macOS.
+#![cfg(not(any(
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+// This test uses `DecInt`.
+#![cfg(feature = "itoa")]
+#![cfg(feature = "fs")]
+
+use rustix::fs::{cwd, unlinkat, AtFlags};
+use rustix::io::{read, write};
+use rustix::net::{
+ accept, bind_unix, connect_unix, listen, socket, AddressFamily, Protocol, SocketAddrUnix,
+ SocketType,
+};
+use rustix::path::DecInt;
+use std::path::Path;
+use std::str::FromStr;
+use std::sync::{Arc, Condvar, Mutex};
+use std::thread;
+
+const BUFFER_SIZE: usize = 20;
+
+fn server(ready: Arc<(Mutex<bool>, Condvar)>, path: &Path) {
+ let connection_socket = socket(
+ AddressFamily::UNIX,
+ SocketType::SEQPACKET,
+ Protocol::default(),
+ )
+ .unwrap();
+
+ let name = SocketAddrUnix::new(path).unwrap();
+ bind_unix(&connection_socket, &name).unwrap();
+ listen(&connection_socket, 1).unwrap();
+
+ {
+ let (lock, cvar) = &*ready;
+ let mut started = lock.lock().unwrap();
+ *started = true;
+ cvar.notify_all();
+ }
+
+ let mut buffer = vec![0; BUFFER_SIZE];
+ 'exit: loop {
+ let data_socket = accept(&connection_socket).unwrap();
+ let mut sum = 0;
+ loop {
+ let nread = read(&data_socket, &mut buffer).unwrap();
+
+ if &buffer[..nread] == b"exit" {
+ break 'exit;
+ }
+ if &buffer[..nread] == b"sum" {
+ break;
+ }
+
+ sum += i32::from_str(&String::from_utf8_lossy(&buffer[..nread])).unwrap();
+ }
+
+ write(&data_socket, DecInt::new(sum).as_bytes()).unwrap();
+ }
+
+ unlinkat(cwd(), path, AtFlags::empty()).unwrap();
+}
+
+fn client(ready: Arc<(Mutex<bool>, Condvar)>, path: &Path, runs: &[(&[&str], i32)]) {
+ {
+ let (lock, cvar) = &*ready;
+ let mut started = lock.lock().unwrap();
+ while !*started {
+ started = cvar.wait(started).unwrap();
+ }
+ }
+
+ let addr = SocketAddrUnix::new(path).unwrap();
+ let mut buffer = vec![0; BUFFER_SIZE];
+
+ for (args, sum) in runs {
+ let data_socket = socket(
+ AddressFamily::UNIX,
+ SocketType::SEQPACKET,
+ Protocol::default(),
+ )
+ .unwrap();
+ connect_unix(&data_socket, &addr).unwrap();
+
+ for arg in *args {
+ write(&data_socket, arg.as_bytes()).unwrap();
+ }
+ write(&data_socket, b"sum").unwrap();
+
+ let nread = read(&data_socket, &mut buffer).unwrap();
+ assert_eq!(
+ i32::from_str(&String::from_utf8_lossy(&buffer[..nread])).unwrap(),
+ *sum
+ );
+ }
+
+ let data_socket = socket(
+ AddressFamily::UNIX,
+ SocketType::SEQPACKET,
+ Protocol::default(),
+ )
+ .unwrap();
+ connect_unix(&data_socket, &addr).unwrap();
+ write(&data_socket, b"exit").unwrap();
+}
+
+#[test]
+fn test_unix() {
+ let ready = Arc::new((Mutex::new(false), Condvar::new()));
+ let ready_clone = Arc::clone(&ready);
+
+ let tmp = tempfile::tempdir().unwrap();
+ let path = tmp.path().join("soccer");
+ let send_path = path.to_owned();
+ let server = thread::Builder::new()
+ .name("server".to_string())
+ .spawn(move || {
+ server(ready, &send_path);
+ })
+ .unwrap();
+ let send_path = path.to_owned();
+ let client = thread::Builder::new()
+ .name("client".to_string())
+ .spawn(move || {
+ client(
+ ready_clone,
+ &send_path,
+ &[
+ (&["1", "2"], 3),
+ (&["4", "77", "103"], 184),
+ (&["5", "78", "104"], 187),
+ (&[], 0),
+ ],
+ );
+ })
+ .unwrap();
+ client.join().unwrap();
+ server.join().unwrap();
+}
diff --git a/vendor/rustix/tests/net/v4.rs b/vendor/rustix/tests/net/v4.rs
new file mode 100644
index 000000000..0908057be
--- /dev/null
+++ b/vendor/rustix/tests/net/v4.rs
@@ -0,0 +1,86 @@
+//! Test a simple IPv4 socket server and client.
+//!
+//! The client send a message and the server sends one back.
+
+#![cfg(not(any(target_os = "redox", target_os = "wasi")))]
+
+use rustix::net::{
+ accept, bind_v4, connect_v4, getsockname, listen, recv, send, socket, AddressFamily, Ipv4Addr,
+ Protocol, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV4, SocketType,
+};
+use std::sync::{Arc, Condvar, Mutex};
+use std::thread;
+
+const BUFFER_SIZE: usize = 20;
+
+fn server(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let connection_socket =
+ socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap();
+
+ let name = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0);
+ bind_v4(&connection_socket, &name).unwrap();
+
+ let who = match getsockname(&connection_socket).unwrap() {
+ SocketAddrAny::V4(addr) => addr,
+ _ => panic!(),
+ };
+
+ listen(&connection_socket, 1).unwrap();
+
+ {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ *port = who.port();
+ cvar.notify_all();
+ }
+
+ let mut buffer = vec![0; BUFFER_SIZE];
+ let data_socket = accept(&connection_socket).unwrap();
+ let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
+ assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello, world");
+
+ send(&data_socket, b"goodnight, moon", SendFlags::empty()).unwrap();
+}
+
+fn client(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let port = {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ while *port == 0 {
+ port = cvar.wait(port).unwrap();
+ }
+ *port
+ };
+
+ let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), port);
+ let mut buffer = vec![0; BUFFER_SIZE];
+
+ let data_socket = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default()).unwrap();
+ connect_v4(&data_socket, &addr).unwrap();
+
+ send(&data_socket, b"hello, world", SendFlags::empty()).unwrap();
+
+ let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
+ assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "goodnight, moon");
+}
+
+#[test]
+fn test_v4() {
+ let ready = Arc::new((Mutex::new(0_u16), Condvar::new()));
+ let ready_clone = Arc::clone(&ready);
+
+ let server = thread::Builder::new()
+ .name("server".to_string())
+ .spawn(move || {
+ server(ready);
+ })
+ .unwrap();
+ let client = thread::Builder::new()
+ .name("client".to_string())
+ .spawn(move || {
+ client(ready_clone);
+ })
+ .unwrap();
+ client.join().unwrap();
+ server.join().unwrap();
+}
diff --git a/vendor/rustix/tests/net/v6.rs b/vendor/rustix/tests/net/v6.rs
new file mode 100644
index 000000000..07205be89
--- /dev/null
+++ b/vendor/rustix/tests/net/v6.rs
@@ -0,0 +1,95 @@
+//! Test a simple IPv6 socket server and client.
+//!
+//! The client send a message and the server sends one back.
+
+#![cfg(not(any(target_os = "redox", target_os = "wasi")))]
+
+use rustix::net::{
+ accept, bind_v6, connect_v6, getsockname, listen, recv, send, socket, AddressFamily, Ipv6Addr,
+ Protocol, RecvFlags, SendFlags, SocketAddrAny, SocketAddrV6, SocketType,
+};
+use std::sync::{Arc, Condvar, Mutex};
+use std::thread;
+
+const BUFFER_SIZE: usize = 20;
+
+fn server(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let connection_socket = socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )
+ .unwrap();
+
+ let name = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 0, 0, 0);
+ bind_v6(&connection_socket, &name).unwrap();
+
+ let who = match getsockname(&connection_socket).unwrap() {
+ SocketAddrAny::V6(addr) => addr,
+ _ => panic!(),
+ };
+
+ listen(&connection_socket, 1).unwrap();
+
+ {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ *port = who.port();
+ cvar.notify_all();
+ }
+
+ let mut buffer = vec![0; BUFFER_SIZE];
+ let data_socket = accept(&connection_socket).unwrap();
+ let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
+ assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "hello, world");
+
+ send(&data_socket, b"goodnight, moon", SendFlags::empty()).unwrap();
+}
+
+fn client(ready: Arc<(Mutex<u16>, Condvar)>) {
+ let port = {
+ let (lock, cvar) = &*ready;
+ let mut port = lock.lock().unwrap();
+ while *port == 0 {
+ port = cvar.wait(port).unwrap();
+ }
+ *port
+ };
+
+ let addr = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), port, 0, 0);
+ let mut buffer = vec![0; BUFFER_SIZE];
+
+ let data_socket = socket(
+ AddressFamily::INET6,
+ SocketType::STREAM,
+ Protocol::default(),
+ )
+ .unwrap();
+ connect_v6(&data_socket, &addr).unwrap();
+
+ send(&data_socket, b"hello, world", SendFlags::empty()).unwrap();
+
+ let nread = recv(&data_socket, &mut buffer, RecvFlags::empty()).unwrap();
+ assert_eq!(String::from_utf8_lossy(&buffer[..nread]), "goodnight, moon");
+}
+
+#[test]
+fn test_v6() {
+ let ready = Arc::new((Mutex::new(0_u16), Condvar::new()));
+ let ready_clone = Arc::clone(&ready);
+
+ let server = thread::Builder::new()
+ .name("server".to_string())
+ .spawn(move || {
+ server(ready);
+ })
+ .unwrap();
+ let client = thread::Builder::new()
+ .name("client".to_string())
+ .spawn(move || {
+ client(ready_clone);
+ })
+ .unwrap();
+ client.join().unwrap();
+ server.join().unwrap();
+}
diff --git a/vendor/rustix/tests/param/auxv.rs b/vendor/rustix/tests/param/auxv.rs
new file mode 100644
index 000000000..90a088101
--- /dev/null
+++ b/vendor/rustix/tests/param/auxv.rs
@@ -0,0 +1,41 @@
+#[cfg(any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+))]
+use rustix::param::linux_hwcap;
+use rustix::param::{clock_ticks_per_second, page_size};
+
+#[test]
+fn test_page_size() {
+ let size = page_size();
+ assert_ne!(size, 0);
+ assert!(size.is_power_of_two());
+ assert_eq!(size, page_size());
+ assert_eq!(size, unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize });
+}
+
+#[test]
+fn test_clock_ticks_per_second() {
+ let size = clock_ticks_per_second();
+ assert_ne!(size, 0);
+ assert_eq!(size, unsafe { libc::sysconf(libc::_SC_CLK_TCK) as u64 });
+}
+
+#[cfg(any(
+ all(target_os = "android", target_pointer_width = "64"),
+ target_os = "linux",
+))]
+#[test]
+fn test_linux_hwcap() {
+ weak!(fn getauxval(libc::c_ulong) -> libc::c_ulong);
+
+ if let Some(libc_getauxval) = getauxval.get() {
+ let (_hwcap, hwcap2) = linux_hwcap();
+
+ // GLIBC seems to return a different value than `LD_SHOW_AUXV=1` reports.
+ #[cfg(not(target_env = "gnu"))]
+ assert_eq!(_hwcap, unsafe { libc_getauxval(libc::AT_HWCAP) } as usize);
+
+ assert_eq!(hwcap2, unsafe { libc_getauxval(libc::AT_HWCAP2) } as usize);
+ }
+}
diff --git a/vendor/rustix/tests/param/main.rs b/vendor/rustix/tests/param/main.rs
new file mode 100644
index 000000000..e350a6f1f
--- /dev/null
+++ b/vendor/rustix/tests/param/main.rs
@@ -0,0 +1,14 @@
+//! Tests for [`rustix::param`].
+
+#![cfg(feature = "param")]
+#![cfg(not(windows))]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+#![cfg_attr(core_c_str, feature(core_c_str))]
+
+#[cfg(not(target_os = "wasi"))]
+#[macro_use]
+mod weak;
+
+#[cfg(not(target_os = "wasi"))]
+mod auxv;
diff --git a/vendor/rustix/tests/param/weak.rs b/vendor/rustix/tests/param/weak.rs
new file mode 100644
index 000000000..377a8a5a1
--- /dev/null
+++ b/vendor/rustix/tests/param/weak.rs
@@ -0,0 +1,201 @@
+// Implementation derived from `weak` in Rust's
+// library/std/src/sys/unix/weak.rs at revision
+// fd0cb0cdc21dd9c06025277d772108f8d42cb25f.
+
+//! Support for "weak linkage" to symbols on Unix
+//!
+//! Some I/O operations we do in libstd require newer versions of OSes but we
+//! need to maintain binary compatibility with older releases for now. In order
+//! to use the new functionality when available we use this module for
+//! detection.
+//!
+//! One option to use here is weak linkage, but that is unfortunately only
+//! really workable on Linux. Hence, use dlsym to get the symbol value at
+//! runtime. This is also done for compatibility with older versions of glibc,
+//! and to avoid creating dependencies on `GLIBC_PRIVATE` symbols. It assumes
+//! that we've been dynamically linked to the library the symbol comes from,
+//! but that is currently always the case for things like libpthread/libc.
+//!
+//! A long time ago this used weak linkage for the `__pthread_get_minstack`
+//! symbol, but that caused Debian to detect an unnecessarily strict versioned
+//! dependency on libc6 (#23628).
+
+// There are a variety of `#[cfg]`s controlling which targets are involved in
+// each instance of `weak!` and `syscall!`. Rather than trying to unify all of
+// that, we'll just allow that some unix targets don't use this module at all.
+#![allow(dead_code, unused_macros)]
+#![allow(clippy::doc_markdown)]
+
+use core::ffi::c_void;
+use core::ptr::null_mut;
+use core::sync::atomic::{self, AtomicPtr, Ordering};
+use core::{marker, mem};
+use rustix::ffi::CStr;
+
+const NULL: *mut c_void = null_mut();
+const INVALID: *mut c_void = 1 as *mut c_void;
+
+macro_rules! weak {
+ (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+ #[allow(non_upper_case_globals)]
+ static $name: $crate::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
+ $crate::weak::Weak::new(concat!(stringify!($name), '\0'));
+ )
+}
+
+pub(crate) struct Weak<F> {
+ name: &'static str,
+ addr: AtomicPtr<c_void>,
+ _marker: marker::PhantomData<F>,
+}
+
+impl<F> Weak<F> {
+ pub(crate) const fn new(name: &'static str) -> Self {
+ Self {
+ name,
+ addr: AtomicPtr::new(INVALID),
+ _marker: marker::PhantomData,
+ }
+ }
+
+ pub(crate) fn get(&self) -> Option<F> {
+ assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+ unsafe {
+ // Relaxed is fine here because we fence before reading through the
+ // pointer (see the comment below).
+ match self.addr.load(Ordering::Relaxed) {
+ INVALID => self.initialize(),
+ NULL => None,
+ addr => {
+ let func = mem::transmute_copy::<*mut c_void, F>(&addr);
+ // The caller is presumably going to read through this value
+ // (by calling the function we've dlsymed). This means we'd
+ // need to have loaded it with at least C11's consume
+ // ordering in order to be guaranteed that the data we read
+ // from the pointer isn't from before the pointer was
+ // stored. Rust has no equivalent to memory_order_consume,
+ // so we use an acquire fence (sorry, ARM).
+ //
+ // Now, in practice this likely isn't needed even on CPUs
+ // where relaxed and consume mean different things. The
+ // symbols we're loading are probably present (or not) at
+ // init, and even if they aren't the runtime dynamic loader
+ // is extremely likely have sufficient barriers internally
+ // (possibly implicitly, for example the ones provided by
+ // invoking `mprotect`).
+ //
+ // That said, none of that's *guaranteed*, and so we fence.
+ atomic::fence(Ordering::Acquire);
+ Some(func)
+ }
+ }
+ }
+ }
+
+ // Cold because it should only happen during first-time initialization.
+ #[cold]
+ unsafe fn initialize(&self) -> Option<F> {
+ let val = fetch(self.name);
+ // This synchronizes with the acquire fence in `get`.
+ self.addr.store(val, Ordering::Release);
+
+ match val {
+ NULL => None,
+ addr => Some(mem::transmute_copy::<*mut c_void, F>(&addr)),
+ }
+ }
+}
+
+unsafe fn fetch(name: &str) -> *mut c_void {
+ let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
+ Ok(c_str) => c_str,
+ Err(..) => return null_mut(),
+ };
+ libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr())
+}
+
+#[cfg(not(any(target_os = "android", target_os = "linux")))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ errno::set_errno(errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ unsafe fn $name($($arg_name:$t),*) -> $ret {
+ // This looks like a hack, but concat_idents only accepts idents
+ // (not paths).
+ use libc::*;
+
+ trait AsSyscallArg {
+ type SyscallArgType;
+ fn as_syscall_arg(self) -> Self::SyscallArgType;
+ }
+
+ // Pass pointer types as pointers, to preserve provenance.
+ impl<T> AsSyscallArg for *mut T {
+ type SyscallArgType = *mut T;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+ impl<T> AsSyscallArg for *const T {
+ type SyscallArgType = *const T;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+
+ // Pass `BorrowedFd` values as the integer value.
+ impl AsSyscallArg for $crate::fd::BorrowedFd<'_> {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType {
+ $crate::fd::AsRawFd::as_raw_fd(&self) as _
+ }
+ }
+
+ // Coerce integer values into `c_long`.
+ impl AsSyscallArg for i32 {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for u32 {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for usize {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+
+ syscall(
+ concat_idents!(SYS_, $name),
+ $($arg_name.as_syscall_arg()),*
+ ) as $ret
+ }
+ )
+}
+
+macro_rules! weakcall {
+ ($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ $vis unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
+ // interposition, but if it's not found just fail.
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ errno::set_errno(errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
diff --git a/vendor/rustix/tests/path/arg.rs b/vendor/rustix/tests/path/arg.rs
new file mode 100644
index 000000000..0eb511be1
--- /dev/null
+++ b/vendor/rustix/tests/path/arg.rs
@@ -0,0 +1,167 @@
+use rustix::ffi::{CStr, CString};
+use rustix::io;
+use rustix::path::Arg;
+#[cfg(feature = "itoa")]
+use rustix::path::DecInt;
+use std::borrow::Cow;
+use std::ffi::{OsStr, OsString};
+use std::path::{Component, Components, Iter, Path, PathBuf};
+
+#[test]
+fn test_arg() {
+ use rustix::cstr;
+ use std::borrow::Borrow;
+
+ let t: &str = "hello";
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: String = "hello".to_owned();
+ assert_eq!("hello", Arg::as_str(&t).unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: &OsStr = OsStr::new("hello");
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: OsString = OsString::from("hello".to_owned());
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: &Path = Path::new("hello");
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: PathBuf = PathBuf::from("hello".to_owned());
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: &CStr = cstr!("hello");
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: CString = cstr!("hello").to_owned();
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(
+ cstr!("hello"),
+ Borrow::borrow(&Arg::as_cow_c_str(&t).unwrap())
+ );
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Components = Path::new("hello").components();
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Component = Path::new("hello").components().next().unwrap();
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Iter = Path::new("hello").iter();
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Cow<'_, str> = Cow::Borrowed("hello");
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Cow<'_, str> = Cow::Owned("hello".to_owned());
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Cow<'_, OsStr> = Cow::Borrowed(OsStr::new("hello"));
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Cow<'_, OsStr> = Cow::Owned(OsString::from("hello".to_owned()));
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Cow<'_, CStr> = Cow::Borrowed(cstr!("hello"));
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Cow<'_, CStr> = Cow::Owned(cstr!("hello").to_owned());
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: &[u8] = b"hello";
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ let t: Vec<u8> = b"hello".to_vec();
+ assert_eq!("hello", t.as_str().unwrap());
+ assert_eq!("hello".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("hello"), Borrow::borrow(&t.into_c_str().unwrap()));
+
+ #[cfg(feature = "itoa")]
+ {
+ let t: DecInt = DecInt::new(43110);
+ assert_eq!("43110", t.as_str());
+ assert_eq!("43110".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(cstr!("43110"), Borrow::borrow(&t.as_cow_c_str().unwrap()));
+ assert_eq!(cstr!("43110"), t.as_c_str());
+ assert_eq!(cstr!("43110"), Borrow::borrow(&t.into_c_str().unwrap()));
+ }
+}
+
+#[test]
+fn test_invalid() {
+ use std::borrow::Borrow;
+
+ let t: &[u8] = b"hello\xc0world";
+ assert_eq!(t.as_str().unwrap_err(), io::Errno::INVAL);
+ assert_eq!("hello\u{fffd}world".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(
+ b"hello\xc0world\0",
+ Borrow::<CStr>::borrow(&t.as_cow_c_str().unwrap()).to_bytes_with_nul()
+ );
+ assert_eq!(
+ b"hello\xc0world\0",
+ Borrow::<CStr>::borrow(&t.into_c_str().unwrap()).to_bytes_with_nul()
+ );
+}
+
+#[test]
+fn test_embedded_nul() {
+ let t: &[u8] = b"hello\0world";
+ assert_eq!("hello\0world", t.as_str().unwrap());
+ assert_eq!("hello\0world".to_owned(), Arg::to_string_lossy(&t));
+ assert_eq!(t.as_cow_c_str().unwrap_err(), io::Errno::INVAL);
+ assert_eq!(t.into_c_str().unwrap_err(), io::Errno::INVAL);
+}
diff --git a/vendor/rustix/tests/path/dec_int.rs b/vendor/rustix/tests/path/dec_int.rs
new file mode 100644
index 000000000..6ce1a5123
--- /dev/null
+++ b/vendor/rustix/tests/path/dec_int.rs
@@ -0,0 +1,20 @@
+use rustix::path::DecInt;
+
+#[test]
+fn test_dec_int() {
+ assert_eq!(DecInt::new(0).as_ref().to_str().unwrap(), "0");
+ assert_eq!(DecInt::new(-1).as_ref().to_str().unwrap(), "-1");
+ assert_eq!(DecInt::new(789).as_ref().to_str().unwrap(), "789");
+ assert_eq!(
+ DecInt::new(i64::MIN).as_ref().to_str().unwrap(),
+ i64::MIN.to_string()
+ );
+ assert_eq!(
+ DecInt::new(i64::MAX).as_ref().to_str().unwrap(),
+ i64::MAX.to_string()
+ );
+ assert_eq!(
+ DecInt::new(u64::MAX).as_ref().to_str().unwrap(),
+ u64::MAX.to_string()
+ );
+}
diff --git a/vendor/rustix/tests/path/main.rs b/vendor/rustix/tests/path/main.rs
new file mode 100644
index 000000000..3215c7e5e
--- /dev/null
+++ b/vendor/rustix/tests/path/main.rs
@@ -0,0 +1,13 @@
+//! Tests for [`rustix::path`].
+
+#![cfg(any(feature = "fs", feature = "net"))]
+#![cfg(not(windows))]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+#![cfg_attr(core_c_str, feature(core_c_str))]
+#![cfg_attr(alloc_c_string, feature(alloc_c_string))]
+
+#[cfg(not(feature = "rustc-dep-of-std"))]
+mod arg;
+#[cfg(feature = "itoa")]
+mod dec_int;
diff --git a/vendor/rustix/tests/process/cpu_set.rs b/vendor/rustix/tests/process/cpu_set.rs
new file mode 100644
index 000000000..c4d9edf08
--- /dev/null
+++ b/vendor/rustix/tests/process/cpu_set.rs
@@ -0,0 +1,14 @@
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_cpu_set() {
+ let set = rustix::process::sched_getaffinity(None).unwrap();
+
+ let mut count = 0;
+ for i in 0..rustix::process::CpuSet::MAX_CPU {
+ if set.is_set(i) {
+ count += 1;
+ }
+ }
+
+ assert_eq!(count, set.count());
+}
diff --git a/vendor/rustix/tests/process/id.rs b/vendor/rustix/tests/process/id.rs
new file mode 100644
index 000000000..10095fa60
--- /dev/null
+++ b/vendor/rustix/tests/process/id.rs
@@ -0,0 +1,65 @@
+use rustix::process;
+
+#[test]
+fn test_getuid() {
+ assert_eq!(process::getuid(), process::getuid());
+ unsafe {
+ assert_eq!(process::getuid().as_raw(), libc::getuid());
+ assert_eq!(process::getuid().is_root(), libc::getuid() == 0);
+ }
+}
+
+#[test]
+fn test_getgid() {
+ assert_eq!(process::getgid(), process::getgid());
+ unsafe {
+ assert_eq!(process::getgid().as_raw(), libc::getgid());
+ assert_eq!(process::getgid().is_root(), libc::getgid() == 0);
+ }
+}
+
+#[test]
+fn test_geteuid() {
+ assert_eq!(process::geteuid(), process::geteuid());
+ unsafe {
+ assert_eq!(process::geteuid().as_raw(), libc::geteuid());
+ assert_eq!(process::geteuid().is_root(), libc::geteuid() == 0);
+ }
+}
+
+#[test]
+fn test_getegid() {
+ assert_eq!(process::getegid(), process::getegid());
+ unsafe {
+ assert_eq!(process::getegid().as_raw(), libc::getegid());
+ assert_eq!(process::getegid().is_root(), libc::getegid() == 0);
+ }
+}
+
+#[test]
+fn test_getpid() {
+ assert_eq!(process::getpid(), process::getpid());
+ unsafe {
+ assert_eq!(
+ process::getpid().as_raw_nonzero().get() as libc::pid_t,
+ libc::getpid()
+ );
+ assert_eq!(process::getpid().is_init(), libc::getpid() == 1);
+ }
+}
+
+#[test]
+fn test_getppid() {
+ assert_eq!(process::getppid(), process::getppid());
+ unsafe {
+ assert_eq!(
+ process::Pid::as_raw(process::getppid()) as libc::pid_t,
+ libc::getppid()
+ );
+ if let Some(ppid) = process::getppid() {
+ assert_eq!(ppid.is_init(), libc::getppid() == 1);
+ } else {
+ assert_eq!(libc::getppid(), 0);
+ }
+ }
+}
diff --git a/vendor/rustix/tests/process/main.rs b/vendor/rustix/tests/process/main.rs
new file mode 100644
index 000000000..90aa34c59
--- /dev/null
+++ b/vendor/rustix/tests/process/main.rs
@@ -0,0 +1,28 @@
+//! Tests for [`rustix::process`].
+
+#![cfg(feature = "process")]
+#![cfg(not(windows))]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+#![cfg_attr(core_c_str, feature(core_c_str))]
+
+#[cfg(not(target_os = "wasi"))]
+#[macro_use]
+mod weak;
+
+mod cpu_set;
+#[cfg(not(target_os = "wasi"))] // WASI doesn't have get[gpu]id.
+mod id;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod membarrier;
+#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))] // WASI doesn't have [gs]etpriority.
+mod priority;
+#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
+mod rlimit;
+mod sched_yield;
+#[cfg(not(target_os = "wasi"))] // WASI doesn't have uname.
+mod uname;
+#[cfg(not(target_os = "wasi"))] // WASI doesn't have waitpid.
+mod wait;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+mod working_directory;
diff --git a/vendor/rustix/tests/process/membarrier.rs b/vendor/rustix/tests/process/membarrier.rs
new file mode 100644
index 000000000..ed9b00c1a
--- /dev/null
+++ b/vendor/rustix/tests/process/membarrier.rs
@@ -0,0 +1,40 @@
+#[test]
+fn test_membarrier() {
+ use rustix::process::{membarrier, membarrier_query, MembarrierCommand, MembarrierQuery};
+
+ let query: MembarrierQuery = membarrier_query();
+
+ // Supported registration commands should succeed.
+ for cmd in [
+ MembarrierCommand::RegisterGlobalExpedited,
+ MembarrierCommand::RegisterPrivateExpedited,
+ MembarrierCommand::RegisterPrivateExpeditedSyncCore,
+ MembarrierCommand::RegisterPrivateExpeditedRseq,
+ ]
+ .iter()
+ .copied()
+ {
+ if query.contains_command(cmd) {
+ membarrier(cmd).unwrap();
+ }
+ }
+
+ // All supported commands should now succeed, and all unsupported
+ // commands should fail.
+ for cmd in [
+ MembarrierCommand::Global,
+ MembarrierCommand::GlobalExpedited,
+ MembarrierCommand::PrivateExpedited,
+ MembarrierCommand::PrivateExpeditedSyncCore,
+ MembarrierCommand::PrivateExpeditedRseq,
+ ]
+ .iter()
+ .copied()
+ {
+ if query.contains_command(cmd) {
+ membarrier(cmd).unwrap();
+ } else {
+ membarrier(cmd).unwrap_err();
+ }
+ }
+}
diff --git a/vendor/rustix/tests/process/priority.rs b/vendor/rustix/tests/process/priority.rs
new file mode 100644
index 000000000..7feb1467a
--- /dev/null
+++ b/vendor/rustix/tests/process/priority.rs
@@ -0,0 +1,83 @@
+use rustix::process::nice;
+#[cfg(not(target_os = "redox"))]
+use rustix::process::{getpriority_process, setpriority_process};
+
+#[cfg(not(target_os = "freebsd"))] // FreeBSD's nice(3) doesn't return the old value.
+#[test]
+fn test_priorities() {
+ let old = nice(0).unwrap();
+
+ #[cfg(not(target_os = "redox"))]
+ {
+ let get_prio = getpriority_process(None).unwrap();
+ assert_eq!(get_prio, old);
+ }
+
+ // Lower the priority by one.
+ let new = nice(1).unwrap();
+
+ // If the test wasn't running with the lowest priority initially, test that
+ // we were able to lower the priority.
+ if old < 19 {
+ assert_eq!(old + 1, new);
+ }
+
+ let get = nice(0).unwrap();
+ assert_eq!(new, get);
+
+ #[cfg(not(target_os = "redox"))]
+ {
+ let get_prio = getpriority_process(None).unwrap();
+ assert_eq!(get_prio, new);
+
+ setpriority_process(None, get + 1).unwrap();
+ let now = getpriority_process(None).unwrap();
+
+ // If the test wasn't running with the lowest priority initially, test
+ // that we were able to lower the priority.
+ if get < 19 {
+ assert_eq!(get + 1, now);
+ }
+ setpriority_process(None, get + 10000).unwrap();
+ let now = getpriority_process(None).unwrap();
+ // Linux's max is 19; Darwin's max is 20.
+ assert!(now >= 19 && now <= 20);
+ // Darwin appears to return `EPERM` on an out of range `nice`.
+ if let Ok(again) = nice(1) {
+ assert_eq!(now, again);
+ }
+ }
+}
+
+/// FreeBSD's `nice` doesn't return the new nice value, so use a specialized
+/// test.
+#[cfg(target_os = "freebsd")]
+#[test]
+fn test_priorities() {
+ let start = getpriority_process(None).unwrap();
+
+ let _ = nice(0).unwrap();
+
+ let now = getpriority_process(None).unwrap();
+ assert_eq!(start, now);
+
+ let _ = nice(1).unwrap();
+
+ let now = getpriority_process(None).unwrap();
+ assert_eq!(start + 1, now);
+
+ setpriority_process(None, start + 2).unwrap();
+
+ let now = getpriority_process(None).unwrap();
+ assert_eq!(start + 2, now);
+
+ setpriority_process(None, 10000).unwrap();
+
+ let now = getpriority_process(None).unwrap();
+ assert_eq!(now, 20);
+
+ let _ = nice(1).unwrap();
+
+ let now = getpriority_process(None).unwrap();
+ assert_eq!(now, 20);
+}
diff --git a/vendor/rustix/tests/process/proc.rs b/vendor/rustix/tests/process/proc.rs
new file mode 100644
index 000000000..e85d85883
--- /dev/null
+++ b/vendor/rustix/tests/process/proc.rs
@@ -0,0 +1,5 @@
+#[test]
+fn test_proc_funcs() {
+ let _maps = rustix::io::proc_self_maps().unwrap();
+ let _pagemap = rustix::io::proc_self_pagemap().unwrap();
+}
diff --git a/vendor/rustix/tests/process/rlimit.rs b/vendor/rustix/tests/process/rlimit.rs
new file mode 100644
index 000000000..b01f9204c
--- /dev/null
+++ b/vendor/rustix/tests/process/rlimit.rs
@@ -0,0 +1,51 @@
+use rustix::process::{Resource, Rlimit};
+
+#[test]
+fn test_getrlimit() {
+ let lim = rustix::process::getrlimit(Resource::Stack);
+ assert_ne!(lim.current, Some(0));
+ assert_ne!(lim.maximum, Some(0));
+}
+
+#[test]
+fn test_setrlimit() {
+ let old = rustix::process::getrlimit(Resource::Core);
+ let new = Rlimit {
+ current: Some(0),
+ maximum: Some(4096),
+ };
+ assert_ne!(old, new);
+ rustix::process::setrlimit(Resource::Core, new.clone()).unwrap();
+
+ let lim = rustix::process::getrlimit(Resource::Core);
+ assert_eq!(lim, new);
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ let new = Rlimit {
+ current: Some(0),
+ maximum: Some(0),
+ };
+
+ let first = rustix::process::getrlimit(Resource::Core);
+
+ let old = match rustix::process::prlimit(None, Resource::Core, new.clone()) {
+ Ok(rlimit) => rlimit,
+ Err(rustix::io::Errno::NOSYS) => return,
+ Err(e) => Err(e).unwrap(),
+ };
+
+ assert_eq!(first, old);
+
+ let other = Rlimit {
+ current: Some(0),
+ maximum: Some(0),
+ };
+
+ let again =
+ rustix::process::prlimit(Some(rustix::process::getpid()), Resource::Core, other)
+ .unwrap();
+
+ assert_eq!(again, new);
+ }
+}
diff --git a/vendor/rustix/tests/process/sched_yield.rs b/vendor/rustix/tests/process/sched_yield.rs
new file mode 100644
index 000000000..eacf17d5e
--- /dev/null
+++ b/vendor/rustix/tests/process/sched_yield.rs
@@ -0,0 +1,7 @@
+use rustix::process::sched_yield;
+
+#[test]
+fn test_sched_yield() {
+ // Just make sure we can call it.
+ sched_yield();
+}
diff --git a/vendor/rustix/tests/process/uname.rs b/vendor/rustix/tests/process/uname.rs
new file mode 100644
index 000000000..bc944c49e
--- /dev/null
+++ b/vendor/rustix/tests/process/uname.rs
@@ -0,0 +1,13 @@
+#[test]
+fn test_uname() {
+ let name: rustix::process::Uname = rustix::process::uname();
+
+ assert!(!name.sysname().to_bytes().is_empty());
+ assert!(!name.nodename().to_bytes().is_empty());
+ assert!(!name.release().to_bytes().is_empty());
+ assert!(!name.version().to_bytes().is_empty());
+ assert!(!name.machine().to_bytes().is_empty());
+
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ assert!(!name.domainname().to_bytes().is_empty());
+}
diff --git a/vendor/rustix/tests/process/wait.rs b/vendor/rustix/tests/process/wait.rs
new file mode 100644
index 000000000..a1f25a631
--- /dev/null
+++ b/vendor/rustix/tests/process/wait.rs
@@ -0,0 +1,25 @@
+use libc::{kill, SIGSTOP};
+use rustix::process;
+use serial_test::serial;
+use std::process::{Command, Stdio};
+
+// These tests must execute serially to prevent race condition, where
+// `test_wait` waits for the child process spawned in `test_waitpid`, causing
+// the tests to get stuck.
+
+#[test]
+#[serial]
+fn test_waitpid() {
+ let child = Command::new("yes")
+ .stdout(Stdio::null())
+ .stderr(Stdio::null())
+ .spawn()
+ .expect("failed to execute child");
+ unsafe { kill(child.id() as _, SIGSTOP) };
+
+ let pid = unsafe { process::Pid::from_raw(child.id() as _) };
+ let status = process::waitpid(pid, process::WaitOptions::UNTRACED)
+ .expect("failed to wait")
+ .unwrap();
+ assert!(status.stopped());
+}
diff --git a/vendor/rustix/tests/process/weak.rs b/vendor/rustix/tests/process/weak.rs
new file mode 100644
index 000000000..d4f00f999
--- /dev/null
+++ b/vendor/rustix/tests/process/weak.rs
@@ -0,0 +1,201 @@
+// Implementation derived from `weak` in Rust's
+// library/std/src/sys/unix/weak.rs at revision
+// fd0cb0cdc21dd9c06025277d772108f8d42cb25f.
+
+//! Support for "weak linkage" to symbols on Unix
+//!
+//! Some I/O operations we do in libstd require newer versions of OSes but we
+//! need to maintain binary compatibility with older releases for now. In order
+//! to use the new functionality when available we use this module for
+//! detection.
+//!
+//! One option to use here is weak linkage, but that is unfortunately only
+//! really workable on Linux. Hence, use dlsym to get the symbol value at
+//! runtime. This is also done for compatibility with older versions of glibc,
+//! and to avoid creating dependencies on `GLIBC_PRIVATE` symbols. It assumes
+//! that we've been dynamically linked to the library the symbol comes from,
+//! but that is currently always the case for things like libpthread/libc.
+//!
+//! A long time ago this used weak linkage for the `__pthread_get_minstack`
+//! symbol, but that caused Debian to detect an unnecessarily strict versioned
+//! dependency on libc6 (#23628).
+
+// There are a variety of `#[cfg]`s controlling which targets are involved in
+// each instance of `weak!` and `syscall!`. Rather than trying to unify all of
+// that, we'll just allow that some unix targets don't use this module at all.
+#![allow(dead_code, unused_macros)]
+#![allow(clippy::doc_markdown)]
+
+use core::ffi::c_void;
+use core::ptr::null_mut;
+use core::sync::atomic::{self, AtomicPtr, Ordering};
+use core::{marker, mem};
+use rustix::ffi::CStr;
+
+const NULL: *mut c_void = null_mut();
+const INVALID: *mut c_void = 1 as *mut c_void;
+
+macro_rules! weak {
+ (fn $name:ident($($t:ty),*) -> $ret:ty) => (
+ #[allow(non_upper_case_globals)]
+ static $name: $crate::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
+ $crate::weak::Weak::new(concat!(stringify!($name), '\0'));
+ )
+}
+
+pub(crate) struct Weak<F> {
+ name: &'static str,
+ addr: AtomicPtr<c_void>,
+ _marker: marker::PhantomData<F>,
+}
+
+impl<F> Weak<F> {
+ pub(crate) const fn new(name: &'static str) -> Self {
+ Self {
+ name,
+ addr: AtomicPtr::new(INVALID),
+ _marker: marker::PhantomData,
+ }
+ }
+
+ pub(crate) fn get(&self) -> Option<F> {
+ assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
+ unsafe {
+ // Relaxed is fine here because we fence before reading through the
+ // pointer (see the comment below).
+ match self.addr.load(Ordering::Relaxed) {
+ INVALID => self.initialize(),
+ NULL => None,
+ addr => {
+ let func = mem::transmute_copy::<*mut c_void, F>(&addr);
+ // The caller is presumably going to read through this value
+ // (by calling the function we've dlsymed). This means we'd
+ // need to have loaded it with at least C11's consume
+ // ordering in order to be guaranteed that the data we read
+ // from the pointer isn't from before the pointer was
+ // stored. Rust has no equivalent to memory_order_consume,
+ // so we use an acquire fence (sorry, ARM).
+ //
+ // Now, in practice this likely isn't needed even on CPUs
+ // where relaxed and consume mean different things. The
+ // symbols we're loading are probably present (or not) at
+ // init, and even if they aren't the runtime dynamic loader
+ // is extremely likely have sufficient barriers internally
+ // (possibly implicitly, for example the ones provided by
+ // invoking `mprotect`).
+ //
+ // That said, none of that's *guaranteed*, and so we fence.
+ atomic::fence(Ordering::Acquire);
+ Some(func)
+ }
+ }
+ }
+ }
+
+ // Cold because it should only happen during first-time initialization.
+ #[cold]
+ unsafe fn initialize(&self) -> Option<F> {
+ let val = fetch(self.name);
+ // This synchronizes with the acquire fence in `get`.
+ self.addr.store(val, Ordering::Release);
+
+ match val {
+ NULL => None,
+ addr => Some(mem::transmute_copy::<*mut c_void, F>(&addr)),
+ }
+ }
+}
+
+unsafe fn fetch(name: &str) -> *mut c_void {
+ let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
+ Ok(c_str) => c_str,
+ Err(..) => return null_mut(),
+ };
+ libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr().cast())
+}
+
+#[cfg(not(any(target_os = "android", target_os = "linux")))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ errno::set_errno(errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+macro_rules! syscall {
+ (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ unsafe fn $name($($arg_name:$t),*) -> $ret {
+ // This looks like a hack, but concat_idents only accepts idents
+ // (not paths).
+ use libc::*;
+
+ trait AsSyscallArg {
+ type SyscallArgType;
+ fn as_syscall_arg(self) -> Self::SyscallArgType;
+ }
+
+ // Pass pointer types as pointers, to preserve provenance.
+ impl<T> AsSyscallArg for *mut T {
+ type SyscallArgType = *mut T;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+ impl<T> AsSyscallArg for *const T {
+ type SyscallArgType = *const T;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self }
+ }
+
+ // Pass `BorrowedFd` values as the integer value.
+ impl AsSyscallArg for $crate::fd::BorrowedFd<'_> {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType {
+ $crate::fd::AsRawFd::as_raw_fd(&self) as _
+ }
+ }
+
+ // Coerce integer values into `c_long`.
+ impl AsSyscallArg for i32 {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for u32 {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+ impl AsSyscallArg for usize {
+ type SyscallArgType = c::c_long;
+ fn as_syscall_arg(self) -> Self::SyscallArgType { self as _ }
+ }
+
+ syscall(
+ concat_idents!(SYS_, $name),
+ $($arg_name.as_syscall_arg()),*
+ ) as $ret
+ }
+ )
+}
+
+macro_rules! weakcall {
+ ($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+ $vis unsafe fn $name($($arg_name: $t),*) -> $ret {
+ weak! { fn $name($($t),*) -> $ret }
+
+ // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
+ // interposition, but if it's not found just fail.
+ if let Some(fun) = $name.get() {
+ fun($($arg_name),*)
+ } else {
+ errno::set_errno(errno::Errno(libc::ENOSYS));
+ -1
+ }
+ }
+ )
+}
diff --git a/vendor/rustix/tests/process/working_directory.rs b/vendor/rustix/tests/process/working_directory.rs
new file mode 100644
index 000000000..1c3262bb9
--- /dev/null
+++ b/vendor/rustix/tests/process/working_directory.rs
@@ -0,0 +1,43 @@
+#![cfg(feature = "fs")]
+
+#[cfg(not(target_os = "macos"))]
+use rustix::fs::{Mode, OFlags};
+use tempfile::{tempdir, TempDir};
+
+#[allow(unused)]
+fn tmpdir() -> TempDir {
+ tempdir().expect("expected to be able to create a temporary directory")
+}
+
+/// Disable this test on macos because GHA has a weird system folder structure
+/// that makes this test fail.
+#[cfg(not(target_os = "macos"))]
+#[test]
+fn test_changing_working_directory() {
+ let tmpdir = tmpdir();
+
+ let orig_cwd = rustix::process::getcwd(Vec::new()).expect("get the cwd");
+ let orig_fd_cwd = rustix::fs::openat(rustix::fs::cwd(), ".", OFlags::RDONLY, Mode::empty())
+ .expect("get a fd for the current directory");
+
+ rustix::process::chdir(tmpdir.path()).expect("changing dir to the tmp");
+ let ch1_cwd = rustix::process::getcwd(Vec::new()).expect("get the cwd");
+
+ assert_ne!(orig_cwd, ch1_cwd, "The cwd hasn't changed!");
+ assert_eq!(
+ ch1_cwd.to_string_lossy(),
+ tmpdir.path().to_string_lossy(),
+ "The cwd is not the same as the tmpdir"
+ );
+
+ #[cfg(not(target_os = "fuchsia"))]
+ rustix::process::fchdir(orig_fd_cwd).expect("changing dir to the original");
+ #[cfg(target_os = "fushcia")]
+ rustix::process::chdir(orig_cwd).expect("changing dir to the original");
+ let ch2_cwd = rustix::process::getcwd(ch1_cwd).expect("get the cwd");
+
+ assert_eq!(
+ orig_cwd, ch2_cwd,
+ "The cwd wasn't changed back to the its original position"
+ );
+}
diff --git a/vendor/rustix/tests/rand/getrandom.rs b/vendor/rustix/tests/rand/getrandom.rs
new file mode 100644
index 000000000..ac316e447
--- /dev/null
+++ b/vendor/rustix/tests/rand/getrandom.rs
@@ -0,0 +1,7 @@
+use rustix::rand::{getrandom, GetRandomFlags};
+
+#[test]
+fn test_getrandom() {
+ let mut buf = [0_u8; 256];
+ let _ = getrandom(&mut buf, GetRandomFlags::empty());
+}
diff --git a/vendor/rustix/tests/rand/main.rs b/vendor/rustix/tests/rand/main.rs
new file mode 100644
index 000000000..9dac8027f
--- /dev/null
+++ b/vendor/rustix/tests/rand/main.rs
@@ -0,0 +1,9 @@
+//! Tests for [`rustix::rand`].
+
+#![cfg(feature = "rand")]
+#![cfg(not(windows))]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+#[cfg(any(linux_raw, all(libc, target_os = "linux")))]
+mod getrandom;
diff --git a/vendor/rustix/tests/termios/isatty.rs b/vendor/rustix/tests/termios/isatty.rs
new file mode 100644
index 000000000..5e6fae73d
--- /dev/null
+++ b/vendor/rustix/tests/termios/isatty.rs
@@ -0,0 +1,69 @@
+use rustix::fd::AsRawFd;
+use rustix::termios::{isatty, tcgetwinsize};
+use tempfile::{tempdir, TempDir};
+
+#[allow(unused)]
+fn tmpdir() -> TempDir {
+ tempdir().expect("expected to be able to create a temporary directory")
+}
+
+#[test]
+fn std_file_is_not_terminal() {
+ let tmpdir = tempfile::tempdir().unwrap();
+ assert!(!isatty(
+ &std::fs::File::create(tmpdir.path().join("file")).unwrap()
+ ));
+ assert!(!isatty(
+ &std::fs::File::open(tmpdir.path().join("file")).unwrap()
+ ));
+}
+
+#[test]
+fn stdout_stderr_terminals() {
+ // This test is flaky under qemu.
+ if std::env::vars().any(|var| var.0.starts_with("CARGO_TARGET_") && var.0.ends_with("_RUNNER"))
+ {
+ return;
+ }
+
+ // Compare `isatty` against `libc::isatty`.
+ assert_eq!(isatty(&std::io::stdout()), unsafe {
+ libc::isatty(std::io::stdout().as_raw_fd()) != 0
+ });
+ assert_eq!(isatty(&std::io::stderr()), unsafe {
+ libc::isatty(std::io::stderr().as_raw_fd()) != 0
+ });
+
+ // Compare `isatty` against `tcgetwinsize`.
+ assert_eq!(
+ isatty(&std::io::stdout()),
+ tcgetwinsize(&std::io::stdout()).is_ok()
+ );
+ assert_eq!(
+ isatty(&std::io::stderr()),
+ tcgetwinsize(&std::io::stderr()).is_ok()
+ );
+}
+
+#[test]
+fn stdio_descriptors() {
+ #[cfg(unix)]
+ use std::os::unix::io::AsRawFd;
+ #[cfg(target_os = "wasi")]
+ use std::os::wasi::io::AsRawFd;
+
+ unsafe {
+ assert_eq!(
+ rustix::io::stdin().as_raw_fd(),
+ std::io::stdin().as_raw_fd()
+ );
+ assert_eq!(
+ rustix::io::stdout().as_raw_fd(),
+ std::io::stdout().as_raw_fd()
+ );
+ assert_eq!(
+ rustix::io::stderr().as_raw_fd(),
+ std::io::stderr().as_raw_fd()
+ );
+ }
+}
diff --git a/vendor/rustix/tests/termios/main.rs b/vendor/rustix/tests/termios/main.rs
new file mode 100644
index 000000000..d9ad9338b
--- /dev/null
+++ b/vendor/rustix/tests/termios/main.rs
@@ -0,0 +1,10 @@
+//! Tests for [`rustix::termios`].
+
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+#![cfg(feature = "termios")]
+
+#[cfg(not(windows))]
+mod isatty;
+#[cfg(not(windows))]
+mod ttyname;
diff --git a/vendor/rustix/tests/termios/ttyname.rs b/vendor/rustix/tests/termios/ttyname.rs
new file mode 100644
index 000000000..636178c31
--- /dev/null
+++ b/vendor/rustix/tests/termios/ttyname.rs
@@ -0,0 +1,24 @@
+use rustix::io;
+use rustix::termios::{isatty, ttyname};
+use std::fs::File;
+
+#[test]
+fn test_ttyname_ok() {
+ let file = File::open("/dev/stdin").unwrap();
+ if isatty(&file) {
+ assert!(ttyname(&file, Vec::new())
+ .unwrap()
+ .into_string()
+ .unwrap()
+ .starts_with("/dev/"));
+ }
+}
+
+#[test]
+fn test_ttyname_not_tty() {
+ let file = File::open("Cargo.toml").unwrap();
+ assert_eq!(ttyname(&file, Vec::new()).unwrap_err(), io::Errno::NOTTY);
+
+ let file = File::open("/dev/null").unwrap();
+ assert_eq!(ttyname(&file, Vec::new()).unwrap_err(), io::Errno::NOTTY);
+}
diff --git a/vendor/rustix/tests/thread/clocks.rs b/vendor/rustix/tests/thread/clocks.rs
new file mode 100644
index 000000000..cf14df777
--- /dev/null
+++ b/vendor/rustix/tests/thread/clocks.rs
@@ -0,0 +1,212 @@
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+use rustix::thread::{clock_nanosleep_absolute, clock_nanosleep_relative, ClockId};
+#[cfg(not(target_os = "redox"))]
+use {
+ rustix::io,
+ rustix::thread::{nanosleep, NanosleepRelativeResult, Timespec},
+};
+
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn test_invalid_nanosleep() {
+ match nanosleep(&Timespec {
+ tv_sec: 0,
+ tv_nsec: 1_000_000_000,
+ }) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match nanosleep(&Timespec {
+ tv_sec: 0,
+ tv_nsec: !0,
+ }) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match nanosleep(&Timespec {
+ tv_sec: !0,
+ tv_nsec: 1_000_000_000,
+ }) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match nanosleep(&Timespec {
+ tv_sec: !0,
+ tv_nsec: !0,
+ }) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+}
+
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[test]
+fn test_invalid_nanosleep_absolute() {
+ match clock_nanosleep_absolute(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: 0,
+ tv_nsec: 1000000000,
+ },
+ ) {
+ Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match clock_nanosleep_absolute(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: 0,
+ tv_nsec: !0,
+ },
+ ) {
+ Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match clock_nanosleep_absolute(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: !0,
+ tv_nsec: 1_000_000_000,
+ },
+ ) {
+ Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match clock_nanosleep_absolute(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: !0,
+ tv_nsec: !0,
+ },
+ ) {
+ Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+}
+
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[test]
+fn test_invalid_nanosleep_relative() {
+ match clock_nanosleep_relative(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: 0,
+ tv_nsec: 1_000_000_000,
+ },
+ ) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match clock_nanosleep_relative(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: 0,
+ tv_nsec: !0,
+ },
+ ) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match clock_nanosleep_relative(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: !0,
+ tv_nsec: 1_000_000_000,
+ },
+ ) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+ match clock_nanosleep_relative(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: !0,
+ tv_nsec: !0,
+ },
+ ) {
+ NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+}
+
+#[cfg(not(target_os = "redox"))]
+#[test]
+fn test_zero_nanosleep() {
+ match nanosleep(&Timespec {
+ tv_sec: 0,
+ tv_nsec: 0,
+ }) {
+ NanosleepRelativeResult::Ok => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+}
+
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[test]
+fn test_zero_nanosleep_absolute() {
+ match clock_nanosleep_absolute(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: 0,
+ tv_nsec: 0,
+ },
+ ) {
+ Ok(()) => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+}
+
+#[cfg(not(any(
+ target_os = "emscripten",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "openbsd",
+ target_os = "redox",
+ target_os = "wasi",
+)))]
+#[test]
+fn test_zero_nanosleep_relative() {
+ match clock_nanosleep_relative(
+ ClockId::Monotonic,
+ &Timespec {
+ tv_sec: 0,
+ tv_nsec: 0,
+ },
+ ) {
+ NanosleepRelativeResult::Ok => (),
+ otherwise => panic!("unexpected resut: {:?}", otherwise),
+ }
+}
diff --git a/vendor/rustix/tests/thread/id.rs b/vendor/rustix/tests/thread/id.rs
new file mode 100644
index 000000000..7aa5abba5
--- /dev/null
+++ b/vendor/rustix/tests/thread/id.rs
@@ -0,0 +1,7 @@
+use rustix::thread;
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_gettid() {
+ assert_eq!(thread::gettid(), thread::gettid());
+}
diff --git a/vendor/rustix/tests/thread/main.rs b/vendor/rustix/tests/thread/main.rs
new file mode 100644
index 000000000..0fc9b42c4
--- /dev/null
+++ b/vendor/rustix/tests/thread/main.rs
@@ -0,0 +1,9 @@
+//! Tests for [`rustix::thread`].
+
+#![cfg(feature = "thread")]
+#![cfg(not(windows))]
+
+#[cfg(not(any(target_os = "redox")))]
+mod clocks;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod id;
diff --git a/vendor/rustix/tests/time/dynamic_clocks.rs b/vendor/rustix/tests/time/dynamic_clocks.rs
new file mode 100644
index 000000000..a7e1e6792
--- /dev/null
+++ b/vendor/rustix/tests/time/dynamic_clocks.rs
@@ -0,0 +1,22 @@
+#![cfg(not(any(target_os = "redox", target_os = "wasi")))]
+
+use rustix::fd::AsFd;
+use rustix::time::{clock_gettime_dynamic, ClockId, DynamicClockId};
+
+#[test]
+fn test_known_clocks() {
+ clock_gettime_dynamic(DynamicClockId::Known(ClockId::Realtime)).unwrap();
+ clock_gettime_dynamic(DynamicClockId::Known(ClockId::Monotonic)).unwrap();
+}
+
+#[test]
+fn test_dynamic_clocks() {
+ let file = std::fs::File::open("Cargo.toml").unwrap();
+ clock_gettime_dynamic(DynamicClockId::Dynamic(file.as_fd())).unwrap_err();
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+#[test]
+fn test_conditional_clocks() {
+ let _ = clock_gettime_dynamic(DynamicClockId::Tai);
+}
diff --git a/vendor/rustix/tests/time/main.rs b/vendor/rustix/tests/time/main.rs
new file mode 100644
index 000000000..43283bca2
--- /dev/null
+++ b/vendor/rustix/tests/time/main.rs
@@ -0,0 +1,14 @@
+//! Tests for [`rustix::time`].
+
+#![cfg(feature = "time")]
+#![cfg(not(windows))]
+#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
+#![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
+
+mod dynamic_clocks;
+#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
+mod monotonic;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+mod timerfd;
+mod timespec;
+mod y2038;
diff --git a/vendor/rustix/tests/time/monotonic.rs b/vendor/rustix/tests/time/monotonic.rs
new file mode 100644
index 000000000..89470f2b4
--- /dev/null
+++ b/vendor/rustix/tests/time/monotonic.rs
@@ -0,0 +1,45 @@
+#[cfg(feature = "thread")]
+use rustix::thread::nanosleep;
+use rustix::time::{clock_gettime, ClockId, Timespec};
+
+/// Attempt to test that the monotonic clock is monotonic. Time may or may not
+/// advance, but it shouldn't regress.
+#[test]
+fn test_monotonic_clock() {
+ let a = clock_gettime(ClockId::Monotonic);
+ let b = clock_gettime(ClockId::Monotonic);
+ if b.tv_sec == a.tv_sec {
+ assert!(b.tv_nsec >= a.tv_nsec);
+ } else {
+ assert!(b.tv_sec > a.tv_sec);
+ }
+}
+
+/// With the "thread" feature, we can sleep so that we're guaranteed that time
+/// has advanced.
+#[cfg(feature = "thread")]
+#[test]
+fn test_monotonic_clock_with_sleep_1s() {
+ let a = clock_gettime(ClockId::Monotonic);
+ let _rem = nanosleep(&Timespec {
+ tv_sec: 1,
+ tv_nsec: 0,
+ });
+ let b = clock_gettime(ClockId::Monotonic);
+ assert!(b.tv_sec > a.tv_sec);
+}
+
+/// With the "thread" feature, we can sleep so that we're guaranteed that time
+/// has advanced.
+#[cfg(feature = "thread")]
+#[test]
+fn test_monotonic_clock_with_sleep_1ms() {
+ let a = clock_gettime(ClockId::Monotonic);
+ let _rem = nanosleep(&Timespec {
+ tv_sec: 0,
+ tv_nsec: 1_000_000,
+ });
+ let b = clock_gettime(ClockId::Monotonic);
+ assert!(b.tv_sec >= a.tv_sec);
+ assert!(b.tv_sec != a.tv_sec || b.tv_nsec > a.tv_nsec);
+}
diff --git a/vendor/rustix/tests/time/timerfd.rs b/vendor/rustix/tests/time/timerfd.rs
new file mode 100644
index 000000000..6ad4dd72e
--- /dev/null
+++ b/vendor/rustix/tests/time/timerfd.rs
@@ -0,0 +1,75 @@
+use rustix::time::{
+ timerfd_create, timerfd_gettime, timerfd_settime, Itimerspec, TimerfdClockId, TimerfdFlags,
+ TimerfdTimerFlags, Timespec,
+};
+
+#[test]
+fn test_timerfd() {
+ let fd = timerfd_create(TimerfdClockId::Monotonic, TimerfdFlags::CLOEXEC).unwrap();
+
+ let set = Itimerspec {
+ it_interval: Timespec {
+ tv_sec: 0,
+ tv_nsec: 0,
+ },
+ it_value: Timespec {
+ tv_sec: 1,
+ tv_nsec: 2,
+ },
+ };
+ let _old: Itimerspec = timerfd_settime(&fd, TimerfdTimerFlags::ABSTIME, &set).unwrap();
+
+ // Wait for the timer to expire.
+ let mut buf = [0_u8; 8];
+ assert_eq!(rustix::io::read(&fd, &mut buf), Ok(8));
+ assert!(u64::from_ne_bytes(buf) >= 1);
+
+ let new = timerfd_gettime(&fd).unwrap();
+
+ // The timer counts down.
+ assert_eq!(set.it_interval.tv_sec, new.it_interval.tv_sec);
+ assert_eq!(set.it_interval.tv_nsec, new.it_interval.tv_nsec);
+ assert!(new.it_value.tv_sec <= set.it_value.tv_sec);
+ assert!(
+ new.it_value.tv_nsec < set.it_value.tv_nsec || new.it_value.tv_sec < set.it_value.tv_sec
+ );
+}
+
+/// Similar, but set an interval for a repeated timer. Don't check that the
+/// times are monotonic because that would race with the timer repeating.
+#[test]
+fn test_timerfd_with_interval() {
+ let fd = timerfd_create(TimerfdClockId::Monotonic, TimerfdFlags::CLOEXEC).unwrap();
+
+ let set = Itimerspec {
+ it_interval: Timespec {
+ tv_sec: 0,
+ tv_nsec: 6,
+ },
+ it_value: Timespec {
+ tv_sec: 1,
+ tv_nsec: 7,
+ },
+ };
+ let _old: Itimerspec = timerfd_settime(&fd, TimerfdTimerFlags::ABSTIME, &set).unwrap();
+
+ // Wait for the timer to expire.
+ let mut buf = [0_u8; 8];
+ assert_eq!(rustix::io::read(&fd, &mut buf), Ok(8));
+ assert!(u64::from_ne_bytes(buf) >= 1);
+
+ let new = timerfd_gettime(&fd).unwrap();
+
+ assert_eq!(set.it_interval.tv_sec, new.it_interval.tv_sec);
+ assert_eq!(set.it_interval.tv_nsec, new.it_interval.tv_nsec);
+
+ // Wait for the timer to expire again.
+ let mut buf = [0_u8; 8];
+ assert_eq!(rustix::io::read(&fd, &mut buf), Ok(8));
+ assert!(u64::from_ne_bytes(buf) >= 1);
+
+ let new = timerfd_gettime(&fd).unwrap();
+
+ assert_eq!(set.it_interval.tv_sec, new.it_interval.tv_sec);
+ assert_eq!(set.it_interval.tv_nsec, new.it_interval.tv_nsec);
+}
diff --git a/vendor/rustix/tests/time/timespec.rs b/vendor/rustix/tests/time/timespec.rs
new file mode 100644
index 000000000..6d892dcfe
--- /dev/null
+++ b/vendor/rustix/tests/time/timespec.rs
@@ -0,0 +1,26 @@
+#[test]
+fn test_timespec_layout() {
+ #[cfg(not(target_os = "redox"))]
+ use rustix::fs::{UTIME_NOW, UTIME_OMIT};
+ use rustix::time::{Nsecs, Secs, Timespec};
+
+ let tv_sec: Secs = 0;
+ let tv_nsec: Nsecs = 0;
+ let _ = Timespec { tv_sec, tv_nsec };
+
+ #[cfg(not(target_os = "redox"))]
+ let _ = Timespec {
+ tv_sec,
+ tv_nsec: UTIME_NOW,
+ };
+ #[cfg(not(target_os = "redox"))]
+ let _ = Timespec {
+ tv_sec,
+ tv_nsec: UTIME_OMIT,
+ };
+ let _ = Timespec { tv_sec, tv_nsec: 0 };
+ let _ = Timespec {
+ tv_sec,
+ tv_nsec: 999_999_999,
+ };
+}
diff --git a/vendor/rustix/tests/time/y2038.rs b/vendor/rustix/tests/time/y2038.rs
new file mode 100644
index 000000000..45a073d19
--- /dev/null
+++ b/vendor/rustix/tests/time/y2038.rs
@@ -0,0 +1,77 @@
+/// Test that `Timespec` and `Secs` support a 64-bit number of seconds,
+/// avoiding the y2038 bug.
+///
+/// The Rust Musl target and libc crate are currently using Musl 1.1. It is
+/// expected to update to Musl 1.2 at some point, at which point it'll gain a
+/// 64-bit `time_t`.
+///
+/// 32-bit Android is [not y2038 compatible]. In theory we could use
+/// `libc::syscall` and call the new syscalls ourselves, however that doesn't
+/// seem worth the effort on a platform that will likely never support add
+/// such support itself.
+///
+/// [not y2038 compatible]: https://android.googlesource.com/platform/bionic/+/refs/heads/master/docs/32-bit-abi.md#is-32_bit-on-lp32-y2038
+#[cfg(not(all(target_env = "musl", target_pointer_width = "32")))]
+#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
+#[cfg(not(all(target_os = "emscripten", target_pointer_width = "32")))]
+#[test]
+fn test_y2038() {
+ use rustix::time::{Secs, Timespec};
+
+ let tv_sec: i64 = 0;
+ let _ = Timespec { tv_sec, tv_nsec: 0 };
+ let _: Secs = tv_sec;
+
+ #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+ {
+ use rustix::time::Itimerspec;
+
+ let _ = Itimerspec {
+ it_interval: Timespec { tv_sec, tv_nsec: 0 },
+ it_value: Timespec { tv_sec, tv_nsec: 0 },
+ };
+ }
+}
+
+#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
+#[test]
+fn test_y2038_with_timerfd() {
+ use rustix::time::{
+ timerfd_create, timerfd_gettime, timerfd_settime, Itimerspec, TimerfdClockId, TimerfdFlags,
+ TimerfdTimerFlags, Timespec,
+ };
+
+ let fd = timerfd_create(TimerfdClockId::Monotonic, TimerfdFlags::CLOEXEC).unwrap();
+
+ let set = Itimerspec {
+ it_interval: Timespec {
+ tv_sec: (1_u64 << 32) as _,
+ tv_nsec: 20,
+ },
+ it_value: Timespec {
+ tv_sec: (1_u64 << 32) as _,
+ tv_nsec: 21,
+ },
+ };
+ let _old: Itimerspec = match timerfd_settime(&fd, TimerfdTimerFlags::ABSTIME, &set) {
+ Ok(i) => i,
+
+ // On 32-bit and mips64 platforms, accept `EOVERFLOW`, meaning that
+ // y2038 support in `timerfd` APIs is not available on this platform
+ // or this version of the platform.
+ #[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
+ Err(rustix::io::Errno::OVERFLOW) => return,
+
+ Err(e) => panic!("unexpected error: {:?}", e),
+ };
+
+ let new = timerfd_gettime(&fd).unwrap();
+
+ // The timer counts down.
+ assert_eq!(set.it_interval.tv_sec, new.it_interval.tv_sec);
+ assert_eq!(set.it_interval.tv_nsec, new.it_interval.tv_nsec);
+ assert!(new.it_value.tv_sec <= set.it_value.tv_sec);
+ assert!(
+ new.it_value.tv_nsec < set.it_value.tv_nsec || new.it_value.tv_sec < set.it_value.tv_sec
+ );
+}