summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml114
-rw-r--r--CHANGELOG.md8
-rw-r--r--Cargo.toml2
-rw-r--r--Cross.toml5
-rw-r--r--README.md5
-rw-r--r--bors.toml4
-rw-r--r--src/env.rs1
-rw-r--r--src/lib.rs23
-rw-r--r--src/mount/bsd.rs1
-rw-r--r--src/mount/mod.rs3
-rw-r--r--src/sched.rs55
-rw-r--r--src/sys/aio.rs4
-rw-r--r--src/sys/mman.rs8
-rw-r--r--src/sys/mod.rs17
-rw-r--r--src/sys/pthread.rs3
-rw-r--r--src/sys/resource.rs40
-rw-r--r--src/sys/select.rs7
-rw-r--r--src/sys/sendfile.rs2
-rw-r--r--src/sys/signal.rs149
-rw-r--r--src/sys/socket/mod.rs11
-rw-r--r--src/sys/socket/sockopt.rs4
-rw-r--r--src/sys/stat.rs1
-rw-r--r--src/sys/statfs.rs54
-rw-r--r--src/sys/uio.rs37
-rw-r--r--src/sys/utsname.rs8
-rw-r--r--src/sys/wait.rs20
-rw-r--r--src/unistd.rs2
-rw-r--r--test/common/mod.rs6
-rw-r--r--test/sys/test_ptrace.rs16
-rw-r--r--test/sys/test_socket.rs83
-rw-r--r--test/sys/test_sockopt.rs2
-rw-r--r--test/sys/test_uio.rs6
-rw-r--r--test/sys/test_wait.rs2
-rw-r--r--test/test_fcntl.rs10
-rw-r--r--test/test_kmod/mod.rs16
-rw-r--r--test/test_mq.rs12
-rw-r--r--test/test_unistd.rs4
37 files changed, 576 insertions, 169 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 3a74a4a4..f4cf98da 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -2,27 +2,53 @@ cargo_cache:
folder: $CARGO_HOME/registry
fingerprint_script: cat Cargo.lock || echo ""
+env:
+ # Build by default; don't just check
+ BUILD: build
+ RUSTFLAGS: -D warnings
+ RUSTDOCFLAGS: -D warnings
+ TOOL: cargo
+ # The MSRV
+ TOOLCHAIN: 1.46.0
+ ZFLAGS:
+
+# Tests that don't require executing the build binaries
+build: &BUILD
+ build_script:
+ - . $HOME/.cargo/env || true
+ - $TOOL +$TOOLCHAIN $BUILD $ZFLAGS --target $TARGET --all-targets
+ - $TOOL +$TOOLCHAIN doc $ZFLAGS --no-deps --target $TARGET
+
+# Tests that do require executing the binaries
+test: &TEST
+ << : *BUILD
+ test_script:
+ - . $HOME/.cargo/env || true
+ - $TOOL +$TOOLCHAIN test --target $TARGET
+
# Test FreeBSD in a full VM. Test the i686 target too, in the
# same VM. The binary will be built in 32-bit mode, but will execute on a
# 64-bit kernel and in a 64-bit environment. Our tests don't execute any of
# the system's binaries, so the environment shouldn't matter.
task:
name: FreeBSD amd64 & i686
+ env:
+ TARGET: x86_64-unknown-freebsd
freebsd_instance:
image: freebsd-11-4-release-amd64
setup_script:
- fetch https://sh.rustup.rs -o rustup.sh
- - sh rustup.sh -y --profile=minimal --default-toolchain 1.46.0
+ - sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN
- $HOME/.cargo/bin/rustup target add i686-unknown-freebsd
- amd64_test_script:
- - . $HOME/.cargo/env
- - cargo test
+ << : *TEST
i386_test_script:
- . $HOME/.cargo/env
+ - cargo build --target i686-unknown-freebsd
+ - cargo doc --no-deps --target i686-unknown-freebsd
- cargo test --target i686-unknown-freebsd
before_cache_script: rm -rf $CARGO_HOME/registry/index
-# Test OSX and iOS in a full VM
+# Test OSX in a full VM
task:
matrix:
- name: OSX x86_64
@@ -32,13 +58,9 @@ task:
image: catalina-xcode
setup_script:
- curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs
- - sh rustup.sh -y --profile=minimal --default-toolchain 1.46.0
- - . $HOME/.cargo/env
- - cargo install cross
- script:
+ - sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN
- . $HOME/.cargo/env
- - cross build --target $TARGET
- - cross test --target $TARGET
+ << : *TEST
before_cache_script: rm -rf $CARGO_HOME/registry/index
# Use cross for QEMU-based testing
@@ -48,10 +70,9 @@ task:
RUST_TEST_THREADS: 1 # QEMU works best with 1 thread
HOME: /tmp/home
PATH: $HOME/.cargo/bin:$PATH
+ RUSTFLAGS: --cfg qemu -D warnings
+ TOOL: cross
matrix:
- - name: Linux aarch64
- env:
- TARGET: aarch64-unknown-linux-gnu
- name: Linux arm gnueabi
env:
TARGET: arm-unknown-linux-gnueabi
@@ -88,38 +109,40 @@ task:
setup_script:
- mkdir /tmp/home
- curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs
- - sh rustup.sh -y --profile=minimal --default-toolchain 1.46.0
+ - sh rustup.sh -y --profile=minimal --default-toolchain $TOOLCHAIN
- . $HOME/.cargo/env
- cargo install cross
- script:
- - . $HOME/.cargo/env || true
- - cross build --target $TARGET
- - cross test --target $TARGET
+ << : *TEST
before_cache_script: rm -rf $CARGO_HOME/registry/index
-# Tasks for Linux amd64 builds
+# Tasks for Linux native builds
task:
matrix:
- name: Rust Stable
+ container:
+ image: rust:latest
env:
TARGET: x86_64-unknown-linux-gnu
- TOOLCHAIN: stable
+ TOOLCHAIN:
+ - name: Linux aarch64
+ arm_container:
+ image: rust:1.46
+ env:
+ RUSTFLAGS: --cfg graviton -D warnings
+ TARGET: aarch64-unknown-linux-gnu
- name: Linux x86_64
+ container:
+ image: rust:1.46
env:
TARGET: x86_64-unknown-linux-gnu
- TOOLCHAIN: 1.46.0
- name: Linux x86_64 musl
+ container:
+ image: rust:1.46
env:
TARGET: x86_64-unknown-linux-musl
- TOOLCHAIN: 1.46.0
- container:
- image: rust:1.46
setup_script:
- - rustup toolchain install $TOOLCHAIN
- - rustup target add --toolchain $TOOLCHAIN $TARGET
- script:
- - cargo +$TOOLCHAIN build --target $TARGET --all-targets
- - cargo +$TOOLCHAIN test --target $TARGET
+ - rustup target add $TARGET
+ << : *TEST
before_cache_script: rm -rf $CARGO_HOME/registry/index
# Tasks for cross-compiling, but no testing
@@ -127,7 +150,7 @@ task:
container:
image: rust:1.46
env:
- TOOLCHAIN: 1.46.0
+ BUILD: check
matrix:
# Cross claims to support Android, but when it tries to run Nix's tests it
# reports undefined symbol references.
@@ -166,8 +189,7 @@ task:
TARGET: aarch64-apple-ios
# Rustup only supports cross-building from arbitrary hosts for iOS at
# 1.49.0 and above. Below that it's possible to cross-build from an OSX
- # host, but OSX VMs
- # are more expensive than Linux VMs.
+ # host, but OSX VMs are more expensive than Linux VMs.
TOOLCHAIN: 1.49.0
- name: iOS x86_64
env:
@@ -202,9 +224,27 @@ task:
setup_script:
- rustup target add $TARGET
- rustup toolchain install $TOOLCHAIN --profile minimal --target $TARGET
- script:
- - cargo +$TOOLCHAIN check --target $TARGET
- - cargo +$TOOLCHAIN check --all-targets --target $TARGET
+ << : *BUILD
+ before_cache_script: rm -rf $CARGO_HOME/registry/index
+
+# Rust Tier 3 targets can't use Rustup
+task:
+ container:
+ image: rustlang/rust:nightly
+ env:
+ BUILD: check
+ TOOLCHAIN: nightly
+ ZFLAGS: -Zbuild-std
+ matrix:
+ - name: DragonFly BSD x86_64
+ env:
+ TARGET: x86_64-unknown-dragonfly
+ - name: OpenBSD x86_64
+ env:
+ TARGET: x86_64-unknown-openbsd
+ setup_script:
+ - rustup component add rust-src
+ << : *BUILD
before_cache_script: rm -rf $CARGO_HOME/registry/index
# Test that we can build with the lowest version of all dependencies.
@@ -212,6 +252,8 @@ task:
# rand, can't build with their own minimal dependencies.
task:
name: Minver
+ env:
+ TOOLCHAIN: nightly
container:
image: rustlang/rust:nightly
setup_script:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d01351f4..8865c59f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1335](https://github.com/nix-rust/nix/pull/1335))
- Exposed `SockAddr::from_raw_sockaddr`
(#[1447](https://github.com/nix-rust/nix/pull/1447))
+- Added `TcpRepair`
+ (#[1503](https://github.com/nix-rust/nix/pull/1503))
+- Enabled `pwritev` and `preadv` for more operating systems.
+ (#[1511](https://github.com/nix-rust/nix/pull/1511))
- Added support for `TCP_MAXSEG` TCP Maximum Segment Size socket options
(#[1292](https://github.com/nix-rust/nix/pull/1292))
@@ -76,6 +80,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Removed a couple of termios constants on redox that were never actually
supported.
(#[1483](https://github.com/nix-rust/nix/pull/1483))
+
- Removed `nix::sys::signal::NSIG`. It was of dubious utility, and not correct
for all platforms.
(#[1484](https://github.com/nix-rust/nix/pull/1484))
@@ -87,6 +92,9 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Deprecated `SockAddr/InetAddr::to_str` in favor of `ToString::to_string`
(#[1495](https://github.com/nix-rust/nix/pull/1495))
+- Removed `SigevNotify` on OpenBSD and Redox.
+ (#[1511](https://github.com/nix-rust/nix/pull/1511))
+
## [0.22.0] - 9 July 2021
### Added
- Added `if_nameindex` (#[1445](https://github.com/nix-rust/nix/pull/1445))
diff --git a/Cargo.toml b/Cargo.toml
index 9e48fc0c..fe0d3b52 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,7 +25,7 @@ targets = [
]
[dependencies]
-libc = { git = "https://github.com/rust-lang/libc", rev = "f5e31f208", features = [ "extra_traits" ] }
+libc = { git = "https://github.com/rust-lang/libc", rev = "621a95373", features = [ "extra_traits" ] }
bitflags = "1.3.1"
cfg-if = "1.0"
diff --git a/Cross.toml b/Cross.toml
index 7c536dc5..acd94f30 100644
--- a/Cross.toml
+++ b/Cross.toml
@@ -1,2 +1,5 @@
[build.env]
-passthrough = ["RUST_TEST_THREADS"]
+passthrough = [
+ "RUSTFLAGS",
+ "RUST_TEST_THREADS"
+]
diff --git a/README.md b/README.md
index 5c900a44..296f83fb 100644
--- a/README.md
+++ b/README.md
@@ -74,12 +74,15 @@ Tier 2:
* s390x-unknown-linux-gnu
* x86_64-apple-ios
* x86_64-linux-android
+ * x86_64-unknown-illumos
* x86_64-unknown-netbsd
Tier 3:
* x86_64-fuchsia
- * x86_64-unknown-redox
+ * x86_64-unknown-dragonfly
* x86_64-unknown-linux-gnux32
+ * x86_64-unknown-openbsd
+ * x86_64-unknown-redox
## Usage
diff --git a/bors.toml b/bors.toml
index 1e2ad980..03810b7e 100644
--- a/bors.toml
+++ b/bors.toml
@@ -4,6 +4,7 @@ status = [
"Android armv7",
"Android i686",
"Android x86_64",
+ "DragonFly BSD x86_64",
"FreeBSD amd64 & i686",
"Fuchsia x86_64",
"Linux MIPS",
@@ -25,12 +26,13 @@ status = [
"Linux x86_64",
"Minver",
"NetBSD x86_64",
+ "OpenBSD x86_64",
"OSX x86_64",
"Redox x86_64",
"Rust Stable",
"iOS aarch64",
"iOS x86_64",
- "illumos",
+ "Illumos",
]
# Set bors's timeout to 1 hour
diff --git a/src/env.rs b/src/env.rs
index 613b0cd8..54d75959 100644
--- a/src/env.rs
+++ b/src/env.rs
@@ -1,3 +1,4 @@
+//! Environment variables
use cfg_if::cfg_if;
use std::fmt;
diff --git a/src/lib.rs b/src/lib.rs
index 3b534a58..7a64b97a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,15 +5,13 @@
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
-// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
-// warnings even though the macro expands into something with allow(dead_code)
-#![allow(dead_code)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]
+#![warn(missing_docs)]
// Re-exported external crates
pub use libc;
@@ -23,13 +21,14 @@ pub use libc;
// Public crates
#[cfg(not(target_os = "redox"))]
+#[allow(missing_docs)]
pub mod dir;
pub mod env;
+#[allow(missing_docs)]
pub mod errno;
-#[deny(missing_docs)]
pub mod features;
+#[allow(missing_docs)]
pub mod fcntl;
-#[deny(missing_docs)]
#[cfg(any(target_os = "android",
target_os = "dragonfly",
target_os = "freebsd",
@@ -42,6 +41,7 @@ pub mod fcntl;
pub mod ifaddrs;
#[cfg(any(target_os = "android",
target_os = "linux"))]
+#[allow(missing_docs)]
pub mod kmod;
#[cfg(any(target_os = "android",
target_os = "freebsd",
@@ -52,23 +52,24 @@ pub mod mount;
target_os = "fushsia",
target_os = "linux",
target_os = "netbsd"))]
+#[allow(missing_docs)]
pub mod mqueue;
-#[deny(missing_docs)]
#[cfg(not(target_os = "redox"))]
pub mod net;
-#[deny(missing_docs)]
pub mod poll;
-#[deny(missing_docs)]
#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
pub mod pty;
pub mod sched;
pub mod sys;
+#[allow(missing_docs)]
pub mod time;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
any(target_arch = "x86", target_arch = "x86_64")))]
+#[allow(missing_docs)]
pub mod ucontext;
+#[allow(missing_docs)]
pub mod unistd;
/*
@@ -101,11 +102,17 @@ pub type Result<T> = result::Result<T, Errno>;
/// ones.
pub type Error = Errno;
+/// Common trait used to represent file system paths by many Nix functions.
pub trait NixPath {
+ /// Is the path empty?
fn is_empty(&self) -> bool;
+ /// Length of the path in bytes
fn len(&self) -> usize;
+ /// Execute a function with this path as a `CStr`.
+ ///
+ /// Mostly used internally by Nix.
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
where F: FnOnce(&CStr) -> T;
}
diff --git a/src/mount/bsd.rs b/src/mount/bsd.rs
index f0a9443a..9913fc20 100644
--- a/src/mount/bsd.rs
+++ b/src/mount/bsd.rs
@@ -347,6 +347,7 @@ impl<'a> Nmount<'a> {
self
}
+ /// Create a new `Nmount` struct with no options
pub fn new() -> Self {
Self::default()
}
diff --git a/src/mount/mod.rs b/src/mount/mod.rs
index 8538bf3d..00303b6a 100644
--- a/src/mount/mod.rs
+++ b/src/mount/mod.rs
@@ -1,7 +1,10 @@
+//! Mount file systems
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(missing_docs)]
mod linux;
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(missing_docs)]
pub use self::linux::*;
#[cfg(any(target_os = "dragonfly",
diff --git a/src/sched.rs b/src/sched.rs
index 575bf24b..69436fdf 100644
--- a/src/sched.rs
+++ b/src/sched.rs
@@ -1,3 +1,7 @@
+//! Execution scheduling
+//!
+//! See Also
+//! [sched.h](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html)
use crate::{Errno, Result};
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -16,33 +20,70 @@ mod sched_linux_like {
// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
libc_bitflags! {
+ /// Options for use with [`clone`]
pub struct CloneFlags: c_int {
+ /// The calling process and the child process run in the same
+ /// memory space.
CLONE_VM;
+ /// The caller and the child process share the same filesystem
+ /// information.
CLONE_FS;
+ /// The calling process and the child process share the same file
+ /// descriptor table.
CLONE_FILES;
+ /// The calling process and the child process share the same table
+ /// of signal handlers.
CLONE_SIGHAND;
+ /// If the calling process is being traced, then trace the child
+ /// also.
CLONE_PTRACE;
+ /// The execution of the calling process is suspended until the
+ /// child releases its virtual memory resources via a call to
+ /// execve(2) or _exit(2) (as with vfork(2)).
CLONE_VFORK;
+ /// The parent of the new child (as returned by getppid(2))
+ /// will be the same as that of the calling process.
CLONE_PARENT;
+ /// The child is placed in the same thread group as the calling
+ /// process.
CLONE_THREAD;
+ /// The cloned child is started in a new mount namespace.
CLONE_NEWNS;
+ /// The child and the calling process share a single list of System
+ /// V semaphore adjustment values
CLONE_SYSVSEM;
- CLONE_SETTLS;
- CLONE_PARENT_SETTID;
- CLONE_CHILD_CLEARTID;
+ // Not supported by Nix due to lack of varargs support in Rust FFI
+ // CLONE_SETTLS;
+ // Not supported by Nix due to lack of varargs support in Rust FFI
+ // CLONE_PARENT_SETTID;
+ // Not supported by Nix due to lack of varargs support in Rust FFI
+ // CLONE_CHILD_CLEARTID;
+ /// Unused since Linux 2.6.2
+ #[deprecated(since = "0.23.0", note = "Deprecated by Linux 2.6.2")]
CLONE_DETACHED;
+ /// A tracing process cannot force `CLONE_PTRACE` on this child
+ /// process.
CLONE_UNTRACED;
- CLONE_CHILD_SETTID;
+ // Not supported by Nix due to lack of varargs support in Rust FFI
+ // CLONE_CHILD_SETTID;
+ /// Create the process in a new cgroup namespace.
CLONE_NEWCGROUP;
+ /// Create the process in a new UTS namespace.
CLONE_NEWUTS;
+ /// Create the process in a new IPC namespace.
CLONE_NEWIPC;
+ /// Create the process in a new user namespace.
CLONE_NEWUSER;
+ /// Create the process in a new PID namespace.
CLONE_NEWPID;
+ /// Create the process in a new network namespace.
CLONE_NEWNET;
+ /// The new process shares an I/O context with the calling process.
CLONE_IO;
}
}
+ /// Type for the function executed by [`clone`].
pub type CloneCb<'a> = Box<dyn FnMut() -> isize + 'a>;
/// CpuSet represent a bit-mask of CPUs.
@@ -212,12 +253,18 @@ mod sched_linux_like {
Errno::result(res).map(Pid::from_raw)
}
+ /// disassociate parts of the process execution context
+ ///
+ /// See also [unshare(2)](https://man7.org/linux/man-pages/man2/unshare.2.html)
pub fn unshare(flags: CloneFlags) -> Result<()> {
let res = unsafe { libc::unshare(flags.bits()) };
Errno::result(res).map(drop)
}
+ /// reassociate thread with a namespace
+ ///
+ /// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html)
pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
let res = unsafe { libc::setns(fd, nstype.bits()) };
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index 71a2184d..fcee28c5 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -60,8 +60,11 @@ libc_enum! {
#[repr(i32)]
#[non_exhaustive]
pub enum LioOpcode {
+ /// No operation
LIO_NOP,
+ /// Write data as if by a call to [`AioCb::write`]
LIO_WRITE,
+ /// Write data as if by a call to [`AioCb::read`]
LIO_READ,
}
}
@@ -840,6 +843,7 @@ unsafe impl<'a> Sync for LioCb<'a> {}
#[cfg(not(any(target_os = "ios", target_os = "macos")))]
impl<'a> LioCb<'a> {
+ /// Are no [`AioCb`]s contained?
pub fn is_empty(&self) -> bool {
self.aiocbs.is_empty()
}
diff --git a/src/sys/mman.rs b/src/sys/mman.rs
index a8d6d7c9..33ac21de 100644
--- a/src/sys/mman.rs
+++ b/src/sys/mman.rs
@@ -65,8 +65,8 @@ libc_bitflags!{
MAP_LOCKED;
/// Do not reserve swap space for this mapping.
///
- /// This was removed in FreeBSD 11.
- #[cfg(not(target_os = "freebsd"))]
+ /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
+ #[cfg(not(any(target_os = "dragonfly", target_os = "freebsd")))]
MAP_NORESERVE;
/// Populate page tables for a mapping.
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -122,8 +122,8 @@ libc_bitflags!{
MAP_NOSYNC;
/// Rename private pages to a file.
///
- /// This was removed in FreeBSD 11.
- #[cfg(any(target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd"))]
+ /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
+ #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
MAP_RENAME;
/// Region may contain semaphores.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index cffefdc3..5d9821a7 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -1,3 +1,4 @@
+//! Mostly platform-specific functionality
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
@@ -7,6 +8,7 @@
pub mod aio;
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(missing_docs)]
pub mod epoll;
#[cfg(any(target_os = "dragonfly",
@@ -15,9 +17,11 @@ pub mod epoll;
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
+#[allow(missing_docs)]
pub mod event;
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(missing_docs)]
pub mod eventfd;
#[cfg(any(target_os = "android",
@@ -34,12 +38,15 @@ pub mod eventfd;
pub mod ioctl;
#[cfg(target_os = "linux")]
+#[allow(missing_docs)]
pub mod memfd;
#[cfg(not(target_os = "redox"))]
+#[allow(missing_docs)]
pub mod mman;
#[cfg(target_os = "linux")]
+#[allow(missing_docs)]
pub mod personality;
pub mod pthread;
@@ -51,12 +58,14 @@ pub mod pthread;
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd"))]
+#[allow(missing_docs)]
pub mod ptrace;
#[cfg(target_os = "linux")]
pub mod quota;
#[cfg(any(target_os = "linux"))]
+#[allow(missing_docs)]
pub mod reboot;
#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))]
@@ -75,11 +84,14 @@ pub mod sendfile;
pub mod signal;
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(missing_docs)]
pub mod signalfd;
#[cfg(not(target_os = "redox"))]
+#[allow(missing_docs)]
pub mod socket;
+#[allow(missing_docs)]
pub mod stat;
#[cfg(any(target_os = "android",
@@ -95,10 +107,13 @@ pub mod statfs;
pub mod statvfs;
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(missing_docs)]
pub mod sysinfo;
+#[allow(missing_docs)]
pub mod termios;
+#[allow(missing_docs)]
pub mod time;
pub mod uio;
@@ -108,7 +123,9 @@ pub mod utsname;
pub mod wait;
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[allow(missing_docs)]
pub mod inotify;
#[cfg(target_os = "linux")]
+#[allow(missing_docs)]
pub mod timerfd;
diff --git a/src/sys/pthread.rs b/src/sys/pthread.rs
index 9163c8d1..d42e45d1 100644
--- a/src/sys/pthread.rs
+++ b/src/sys/pthread.rs
@@ -1,3 +1,5 @@
+//! Low level threading primitives
+
#[cfg(not(target_os = "redox"))]
use crate::errno::Errno;
#[cfg(not(target_os = "redox"))]
@@ -6,6 +8,7 @@ use crate::Result;
use crate::sys::signal::Signal;
use libc::{self, pthread_t};
+/// Identifies an individual thread.
pub type Pthread = pthread_t;
/// Obtain ID of the calling thread (see
diff --git a/src/sys/resource.rs b/src/sys/resource.rs
index 8f71375b..dd7f8c5c 100644
--- a/src/sys/resource.rs
+++ b/src/sys/resource.rs
@@ -49,55 +49,93 @@ libc_enum! {
), repr(i32))]
#[non_exhaustive]
pub enum Resource {
- #[cfg(not(any(target_os = "netbsd", target_os = "freebsd")))]
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd"
+ )))]
+ /// The maximum amount (in bytes) of virtual memory the process is
+ /// allowed to map.
RLIMIT_AS,
+ /// The largest size (in bytes) core(5) file that may be created.
RLIMIT_CORE,
+ /// The maximum amount of cpu time (in seconds) to be used by each
+ /// process.
RLIMIT_CPU,
+ /// The maximum size (in bytes) of the data segment for a process
RLIMIT_DATA,
+ /// The largest size (in bytes) file that may be created.
RLIMIT_FSIZE,
+ /// The maximum number of open files for this process.
RLIMIT_NOFILE,
+ /// The maximum size (in bytes) of the stack segment for a process.
RLIMIT_STACK,
#[cfg(target_os = "freebsd")]
+ /// The maximum number of kqueues this user id is allowed to create.
RLIMIT_KQUEUES,
#[cfg(any(target_os = "android", target_os = "linux"))]
+ /// A limit on the combined number of flock locks and fcntl leases that
+ /// this process may establish.
RLIMIT_LOCKS,
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
+ /// The maximum size (in bytes) which a process may lock into memory
+ /// using the mlock(2) system call.
RLIMIT_MEMLOCK,
#[cfg(any(target_os = "android", target_os = "linux"))]
+ /// A limit on the number of bytes that can be allocated for POSIX
+ /// message queues for the real user ID of the calling process.
RLIMIT_MSGQUEUE,
#[cfg(any(target_os = "android", target_os = "linux"))]
+ /// A ceiling to which the process's nice value can be raised using
+ /// setpriority or nice.
RLIMIT_NICE,
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
+ /// The maximum number of simultaneous processes for this user id.
RLIMIT_NPROC,
#[cfg(target_os = "freebsd")]
+ /// The maximum number of pseudo-terminals this user id is allowed to
+ /// create.
RLIMIT_NPTS,
#[cfg(any(target_os = "android", target_os = "freebsd", target_os = "openbsd", target_os = "linux"))]
+ /// When there is memory pressure and swap is available, prioritize
+ /// eviction of a process' resident pages beyond this amount (in bytes).
RLIMIT_RSS,
#[cfg(any(target_os = "android", target_os = "linux"))]
+ /// A ceiling on the real-time priority that may be set for this process
+ /// using sched_setscheduler and sched_set‐ param.
RLIMIT_RTPRIO,
#[cfg(any(target_os = "linux"))]
+ /// A limit (in microseconds) on the amount of CPU time that a process
+ /// scheduled under a real-time scheduling policy may con‐ sume without
+ /// making a blocking system call.
RLIMIT_RTTIME,
#[cfg(any(target_os = "android", target_os = "linux"))]
+ /// A limit on the number of signals that may be queued for the real
+ /// user ID of the calling process.
RLIMIT_SIGPENDING,
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ /// The maximum size (in bytes) of socket buffer usage for this user.
RLIMIT_SBSIZE,
#[cfg(target_os = "freebsd")]
+ /// The maximum size (in bytes) of the swap space that may be reserved
+ /// or used by all of this user id's processes.
RLIMIT_SWAP,
#[cfg(target_os = "freebsd")]
+ /// An alias for RLIMIT_AS.
RLIMIT_VMEM,
}
}
diff --git a/src/sys/select.rs b/src/sys/select.rs
index a8035f79..0a0e830d 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -1,3 +1,4 @@
+//! Portably monitor a group of file descriptors for readiness.
use std::iter::FusedIterator;
use std::mem;
use std::ops::Range;
@@ -11,11 +12,13 @@ use crate::sys::time::{TimeSpec, TimeVal};
pub use libc::FD_SETSIZE;
+/// Contains a set of file descriptors used by [`select`]
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct FdSet(libc::fd_set);
impl FdSet {
+ /// Create an empty `FdSet`
pub fn new() -> FdSet {
let mut fdset = mem::MaybeUninit::uninit();
unsafe {
@@ -24,18 +27,22 @@ impl FdSet {
}
}
+ /// Add a file descriptor to an `FdSet`
pub fn insert(&mut self, fd: RawFd) {
unsafe { libc::FD_SET(fd, &mut self.0) };
}
+ /// Remove a file descriptor from an `FdSet`
pub fn remove(&mut self, fd: RawFd) {
unsafe { libc::FD_CLR(fd, &mut self.0) };
}
+ /// Test an `FdSet` for the presence of a certain file descriptor.
pub fn contains(&self, fd: RawFd) -> bool {
unsafe { libc::FD_ISSET(fd, &self.0) }
}
+ /// Remove all file descriptors from this `FdSet`.
pub fn clear(&mut self) {
unsafe { libc::FD_ZERO(&mut self.0) };
}
diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs
index a12c0411..7a210c6f 100644
--- a/src/sys/sendfile.rs
+++ b/src/sys/sendfile.rs
@@ -1,3 +1,5 @@
+//! Send data from a file to a socket, bypassing userland.
+
use cfg_if::cfg_if;
use std::os::unix::io::RawFd;
use std::ptr;
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index 95663687..1011930f 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -1,7 +1,7 @@
// Portions of this file are Copyright 2014 The Rust Project Developers.
// See https://www.rust-lang.org/policies/licenses.
-///! Operating system signals.
+//! Operating system signals.
use crate::{Error, Result};
use crate::errno::Errno;
@@ -17,6 +17,7 @@ use std::ptr;
pub use self::sigevent::*;
libc_enum!{
+ /// Types of operating system signals
// Currently there is only one definition of c_int in libc, as well as only one
// type for signal constants.
// We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
@@ -24,50 +25,83 @@ libc_enum!{
#[repr(i32)]
#[non_exhaustive]
pub enum Signal {
+ /// Hangup
SIGHUP,
+ /// Interrupt
SIGINT,
+ /// Quit
SIGQUIT,
+ /// Illegal instruction (not reset when caught)
SIGILL,
+ /// Trace trap (not reset when caught)
SIGTRAP,
+ /// Abort
SIGABRT,
+ /// Bus error
SIGBUS,
+ /// Floating point exception
SIGFPE,
+ /// Kill (cannot be caught or ignored)
SIGKILL,
+ /// User defined signal 1
SIGUSR1,
+ /// Segmentation violation
SIGSEGV,
+ /// User defined signal 2
SIGUSR2,
+ /// Write on a pipe with no one to read it
SIGPIPE,
+ /// Alarm clock
SIGALRM,
+ /// Software termination signal from kill
SIGTERM,
+ /// Stack fault (obsolete)
#[cfg(all(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux"),
not(any(target_arch = "mips", target_arch = "mips64",
target_arch = "sparc64"))))]
SIGSTKFLT,
+ /// To parent on child stop or exit
SIGCHLD,
+ /// Continue a stopped process
SIGCONT,
+ /// Sendable stop signal not from tty
SIGSTOP,
+ /// Stop signal from tty
SIGTSTP,
+ /// To readers pgrp upon background tty read
SIGTTIN,
+ /// Like TTIN if (tp->t_local&LTOSTOP)
SIGTTOU,
+ /// Urgent condition on IO channel
SIGURG,
+ /// Exceeded CPU time limit
SIGXCPU,
+ /// Exceeded file size limit
SIGXFSZ,
+ /// Virtual time alarm
SIGVTALRM,
+ /// Profiling time alarm
SIGPROF,
+ /// Window size changes
SIGWINCH,
+ /// Input/output possible signal
SIGIO,
#[cfg(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux"))]
+ /// Power failure imminent.
SIGPWR,
+ /// Bad system call
SIGSYS,
#[cfg(not(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux",
target_os = "redox")))]
+ /// Emulator trap
SIGEMT,
#[cfg(not(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux",
target_os = "redox")))]
+ /// Information request
SIGINFO,
}
impl TryFrom<i32>
@@ -336,6 +370,7 @@ const SIGNALS: [Signal; 31] = [
SIGINFO];
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+/// Iterate through all signals defined by this operating system
pub struct SignalIterator {
next: usize,
}
@@ -355,13 +390,17 @@ impl Iterator for SignalIterator {
}
impl Signal {
+ /// Iterate through all signals defined by this OS
pub const fn iterator() -> SignalIterator {
SignalIterator{next: 0}
}
}
+/// Alias for [`SIGABRT`]
pub const SIGIOT : Signal = SIGABRT;
+/// Alias for [`SIGIO`]
pub const SIGPOLL : Signal = SIGIO;
+/// Alias for [`SIGSYS`]
pub const SIGUNUSED : Signal = SIGSYS;
#[cfg(not(target_os = "redox"))]
@@ -370,27 +409,48 @@ type SaFlags_t = libc::c_int;
type SaFlags_t = libc::c_ulong;
libc_bitflags!{
+ /// Controls the behavior of a [`SigAction`]
pub struct SaFlags: SaFlags_t {
+ /// When catching a [`Signal::SIGCHLD`] signal, the signal will be
+ /// generated only when a child process exits, not when a child process
+ /// stops.
SA_NOCLDSTOP;
+ /// When catching a [`Signal::SIGCHLD`] signal, the system will not
+ /// create zombie processes when children of the calling process exit.
SA_NOCLDWAIT;
+ /// Further occurrences of the delivered signal are not masked during
+ /// the execution of the handler.
SA_NODEFER;
+ /// The system will deliver the signal to the process on a signal stack,
+ /// specified by each thread with sigaltstack(2).
SA_ONSTACK;
+ /// The handler is reset back to the default at the moment the signal is
+ /// delivered.
SA_RESETHAND;
+ /// Requests that certain system calls restart if interrupted by this
+ /// signal. See the man page for complete details.
SA_RESTART;
+ /// This flag is controlled internally by Nix.
SA_SIGINFO;
}
}
libc_enum! {
+ /// Specifies how certain functions should manipulate a signal mask
#[repr(i32)]
#[non_exhaustive]
pub enum SigmaskHow {
+ /// The new mask is the union of the current mask and the specified set.
SIG_BLOCK,
+ /// The new mask is the intersection of the current mask and the
+ /// complement of the specified set.
SIG_UNBLOCK,
+ /// The current mask is replaced by the specified set.
SIG_SETMASK,
}
}
+/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SigSet {
sigset: libc::sigset_t
@@ -398,6 +458,7 @@ pub struct SigSet {
impl SigSet {
+ /// Initialize to include all signals.
pub fn all() -> SigSet {
let mut sigset = mem::MaybeUninit::uninit();
let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
@@ -405,6 +466,7 @@ impl SigSet {
unsafe{ SigSet { sigset: sigset.assume_init() } }
}
+ /// Initialize to include nothing.
pub fn empty() -> SigSet {
let mut sigset = mem::MaybeUninit::uninit();
let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
@@ -412,18 +474,22 @@ impl SigSet {
unsafe{ SigSet { sigset: sigset.assume_init() } }
}
+ /// Add the specified signal to the set.
pub fn add(&mut self, signal: Signal) {
unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
+ /// Remove all signals from this set.
pub fn clear(&mut self) {
unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
}
+ /// Remove the specified signal from this set.
pub fn remove(&mut self, signal: Signal) {
unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
+ /// Return whether this set includes the specified signal.
pub fn contains(&self, signal: Signal) -> bool {
let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
@@ -434,6 +500,8 @@ impl SigSet {
}
}
+ /// Merge all of `other`'s signals into this set.
+ // TODO: use libc::sigorset on supported operating systems.
pub fn extend(&mut self, other: &SigSet) {
for signal in Signal::iterator() {
if other.contains(signal) {
@@ -787,6 +855,24 @@ pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut Si
Errno::result(res).map(drop)
}
+/// Send a signal to a process
+///
+/// # Arguments
+///
+/// * `pid` - Specifies which processes should receive the signal.
+/// - If positive, specifies an individual process
+/// - If zero, the signal will be sent to all processes whose group
+/// ID is equal to the process group ID of the sender. This is a
+/// variant of [`killpg`].
+/// - If `-1` and the process has super-user privileges, the signal
+/// is sent to all processes exclusing system processes.
+/// - If less than `-1`, the signal is sent to all processes whose
+/// process group ID is equal to the absolute value of `pid`.
+/// * `signal` - Signal to send. If 0, error checking if performed but no
+/// signal is actually sent.
+///
+/// See Also
+/// [`kill(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html)
pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
let res = unsafe { libc::kill(pid.into(),
match signal.into() {
@@ -797,12 +883,16 @@ pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
Errno::result(res).map(drop)
}
-/// Send a signal to a process group [(see
-/// killpg(3))](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
+/// Send a signal to a process group
+///
+/// # Arguments
///
-/// If `pgrp` less then or equal 1, the behavior is platform-specific.
-/// If `signal` is `None`, `killpg` will only preform error checking and won't
-/// send any signal.
+/// * `pgrp` - Process group to signal. If less then or equal 1, the behavior
+/// is platform-specific.
+/// * `signal` - Signal to send. If `None`, `killpg` will only preform error
+/// checking and won't send any signal.
+///
+/// See Also [killpg(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
#[cfg(not(target_os = "fuchsia"))]
pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
let res = unsafe { libc::killpg(pgrp.into(),
@@ -814,6 +904,9 @@ pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
Errno::result(res).map(drop)
}
+/// Send a signal to the current thread
+///
+/// See Also [raise(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html)
pub fn raise(signal: Signal) -> Result<()> {
let res = unsafe { libc::raise(signal as libc::c_int) };
@@ -821,36 +914,51 @@ pub fn raise(signal: Signal) -> Result<()> {
}
+/// Identifies a thread for [`SigevNotify::SigevThreadId`]
#[cfg(target_os = "freebsd")]
pub type type_of_thread_id = libc::lwpid_t;
+/// Identifies a thread for [`SigevNotify::SigevThreadId`]
#[cfg(target_os = "linux")]
pub type type_of_thread_id = libc::pid_t;
-/// Used to request asynchronous notification of certain events, for example,
-/// with POSIX AIO, POSIX message queues, and POSIX timers.
+/// Specifies the notification method used by a [`SigEvent`]
// sigval is actually a union of a int and a void*. But it's never really used
// as a pointer, because neither libc nor the kernel ever dereference it. nix
// therefore presents it as an intptr_t, which is how kevent uses it.
+#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum SigevNotify {
/// No notification will be delivered
SigevNone,
- /// The signal given by `signal` will be delivered to the process. The
- /// value in `si_value` will be present in the `si_value` field of the
- /// `siginfo_t` structure of the queued signal.
- SigevSignal { signal: Signal, si_value: libc::intptr_t },
+ /// Notify by delivering a signal to the process.
+ SigevSignal {
+ /// Signal to deliver
+ signal: Signal,
+ /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
+ /// structure of the queued signal.
+ si_value: libc::intptr_t
+ },
// Note: SIGEV_THREAD is not implemented because libc::sigevent does not
// expose a way to set the union members needed by SIGEV_THREAD.
- /// A new `kevent` is posted to the kqueue `kq`. The `kevent`'s `udata`
- /// field will contain the value in `udata`.
+ /// Notify by delivering an event to a kqueue.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
- SigevKevent { kq: RawFd, udata: libc::intptr_t },
- /// The signal `signal` is queued to the thread whose LWP ID is given in
- /// `thread_id`. The value stored in `si_value` will be present in the
- /// `si_value` of the `siginfo_t` structure of the queued signal.
+ SigevKevent {
+ /// File descriptor of the kqueue to notify.
+ kq: RawFd,
+ /// Will be contained in the kevent's `udata` field.
+ udata: libc::intptr_t
+ },
+ /// Notify by delivering a signal to a thread.
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
- SigevThreadId { signal: Signal, thread_id: type_of_thread_id,
- si_value: libc::intptr_t },
+ SigevThreadId {
+ /// Signal to send
+ signal: Signal,
+ /// LWP ID of the thread to notify
+ thread_id: type_of_thread_id,
+ /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
+ /// structure of the queued signal.
+ si_value: libc::intptr_t
+ },
}
#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
@@ -932,6 +1040,7 @@ mod sigevent {
fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
}
+ /// Return a copy of the inner structure
pub fn sigevent(&self) -> libc::sigevent {
self.sigevent
}
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index f701a731..33585bb9 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -526,15 +526,12 @@ impl<'a> Iterator for CmsgIterator<'a> {
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ControlMessageOwned {
- /// Received version of
- /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights]
+ /// Received version of [`ControlMessage::ScmRights`]
ScmRights(Vec<RawFd>),
- /// Received version of
- /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
+ /// Received version of [`ControlMessage::ScmCredentials`]
#[cfg(any(target_os = "android", target_os = "linux"))]
ScmCredentials(UnixCredentials),
- /// Received version of
- /// [`ControlMessage::ScmCreds`][#enum.ControlMessage.html#variant.ScmCreds]
+ /// Received version of [`ControlMessage::ScmCreds`]
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
ScmCreds(UnixCredentials),
/// A message of type `SCM_TIMESTAMP`, containing the time the
@@ -808,7 +805,7 @@ pub enum ControlMessage<'a> {
///
/// Credentials are always overwritten by the kernel, so this variant does have
/// any data, unlike the receive-side
- /// [`ControlMessageOwned::ScmCreds`][#enum.ControlMessageOwned.html#variant.ScmCreds].
+ /// [`ControlMessageOwned::ScmCreds`].
///
/// For further information, please refer to the
/// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index 90f3cb3d..67f5f71e 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -274,6 +274,10 @@ cfg_if! {
}
#[cfg(not(target_os = "openbsd"))]
sockopt_impl!(Both, TcpKeepCount, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
+#[cfg(any(target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"))]
+sockopt_impl!(Both, TcpRepair, libc::IPPROTO_TCP, libc::TCP_REPAIR, u32);
#[cfg(not(target_os = "openbsd"))]
sockopt_impl!(Both, TcpKeepInterval, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
#[cfg(any(target_os = "fuchsia", target_os = "linux"))]
diff --git a/src/sys/stat.rs b/src/sys/stat.rs
index ed62b12d..c8f10419 100644
--- a/src/sys/stat.rs
+++ b/src/sys/stat.rs
@@ -256,6 +256,7 @@ pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
}
/// Flags for `utimensat` function.
+// TODO: replace with fcntl::AtFlags
#[derive(Clone, Copy, Debug)]
pub enum UtimensatFlags {
FollowSymlink,
diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs
index 27b72592..829be57f 100644
--- a/src/sys/statfs.rs
+++ b/src/sys/statfs.rs
@@ -1,3 +1,6 @@
+//! Get filesystem statistics, non-portably
+//!
+//! See [`statvfs`](crate::sys::statvfs) for a portable alternative.
use std::fmt::{self, Debug};
use std::mem;
use std::os::unix::io::AsRawFd;
@@ -6,11 +9,14 @@ use std::ffi::CStr;
use crate::{NixPath, Result, errno::Errno};
+/// Identifies a mounted file system
#[cfg(target_os = "android")]
pub type fsid_t = libc::__fsid_t;
+/// Identifies a mounted file system
#[cfg(not(target_os = "android"))]
pub type fsid_t = libc::fsid_t;
+/// Describes a mounted file system
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Statfs(libc::statfs);
@@ -26,6 +32,7 @@ type fs_type_t = libc::c_ulong;
#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
type fs_type_t = libc::__fsword_t;
+/// Describes the file system type as known by the operating system.
#[cfg(any(
target_os = "freebsd",
target_os = "android",
@@ -36,63 +43,94 @@ type fs_type_t = libc::__fsword_t;
#[derive(Eq, Copy, Clone, PartialEq, Debug)]
pub struct FsType(pub fs_type_t);
+// These constants are defined without documentation in the Linux headers, so we
+// can't very well document them here.
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[allow(missing_docs)]
pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
@@ -451,6 +489,14 @@ impl Debug for Statfs {
}
}
+/// Describes a mounted file system.
+///
+/// The result is OS-dependent. For a portabable alternative, see
+/// [`statvfs`](crate::sys::statvfs::statvfs).
+///
+/// # Arguments
+///
+/// `path` - Path to any file within the file system to describe
pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
unsafe {
let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
@@ -459,6 +505,14 @@ pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
}
}
+/// Describes a mounted file system.
+///
+/// The result is OS-dependent. For a portabable alternative, see
+/// [`fstatvfs`](crate::sys::statvfs::fstatvfs).
+///
+/// # Arguments
+///
+/// `fd` - File descriptor of any open file within the file system to describe
pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
unsafe {
let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 48a0efd8..3abcde24 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -1,5 +1,4 @@
-// Silence invalid warnings due to rust-lang/rust#16719
-#![allow(improper_ctypes)]
+//! Vectored I/O
use crate::Result;
use crate::errno::Errno;
@@ -7,12 +6,18 @@ use libc::{self, c_int, c_void, size_t, off_t};
use std::marker::PhantomData;
use std::os::unix::io::RawFd;
+/// Low-level vectored write to a raw file descriptor
+///
+/// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html)
pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result<usize> {
let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
Errno::result(res).map(|r| r as usize)
}
+/// Low-level vectored read from a raw file descriptor
+///
+/// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html)
pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
@@ -25,11 +30,7 @@ pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
/// or an error occurs. The file offset is not changed.
///
/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
+#[cfg(not(target_os = "redox"))]
pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
offset: off_t) -> Result<usize> {
let res = unsafe {
@@ -46,11 +47,7 @@ pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
/// changed.
///
/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "openbsd"))]
+#[cfg(not(target_os = "redox"))]
pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>],
offset: off_t) -> Result<usize> {
let res = unsafe {
@@ -60,6 +57,10 @@ pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>],
Errno::result(res).map(|r| r as usize)
}
+/// Low-level write to a file, with specified offset.
+///
+/// See also [pwrite(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html)
+// TODO: move to unistd
pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
let res = unsafe {
libc::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t,
@@ -69,6 +70,10 @@ pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
Errno::result(res).map(|r| r as usize)
}
+/// Low-level write to a file, with specified offset.
+///
+/// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html)
+// TODO: move to unistd
pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
let res = unsafe {
libc::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t,
@@ -166,11 +171,17 @@ pub fn process_vm_readv(
Errno::result(res).map(|r| r as usize)
}
+/// A vector of buffers.
+///
+/// Vectored I/O methods like [`writev`] and [`readv`] use this structure for
+/// both reading and writing. Each `IoVec` specifies the base address and
+/// length of an area in memory.
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct IoVec<T>(pub(crate) libc::iovec, PhantomData<T>);
impl<T> IoVec<T> {
+ /// View the `IoVec` as a Rust slice.
#[inline]
pub fn as_slice(&self) -> &[u8] {
use std::slice;
@@ -192,6 +203,7 @@ impl<'a> IoVec<&'a [u8]> {
}, PhantomData)
}
+ /// Create an `IoVec` from a Rust slice.
pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> {
IoVec(libc::iovec {
iov_base: buf.as_ptr() as *mut c_void,
@@ -201,6 +213,7 @@ impl<'a> IoVec<&'a [u8]> {
}
impl<'a> IoVec<&'a mut [u8]> {
+ /// Create an `IoVec` from a mutable Rust slice.
pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> {
IoVec(libc::iovec {
iov_base: buf.as_ptr() as *mut c_void,
diff --git a/src/sys/utsname.rs b/src/sys/utsname.rs
index bf1a814d..98edee04 100644
--- a/src/sys/utsname.rs
+++ b/src/sys/utsname.rs
@@ -1,34 +1,42 @@
+//! Get system identification
use std::mem;
use libc::{self, c_char};
use std::ffi::CStr;
use std::str::from_utf8_unchecked;
+/// Describes the running system. Return type of [`uname`].
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct UtsName(libc::utsname);
impl UtsName {
+ /// Name of the operating system implementation
pub fn sysname(&self) -> &str {
to_str(&(&self.0.sysname as *const c_char ) as *const *const c_char)
}
+ /// Network name of this machine.
pub fn nodename(&self) -> &str {
to_str(&(&self.0.nodename as *const c_char ) as *const *const c_char)
}
+ /// Release level of the operating system.
pub fn release(&self) -> &str {
to_str(&(&self.0.release as *const c_char ) as *const *const c_char)
}
+ /// Version level of the operating system.
pub fn version(&self) -> &str {
to_str(&(&self.0.version as *const c_char ) as *const *const c_char)
}
+ /// Machine hardware platform.
pub fn machine(&self) -> &str {
to_str(&(&self.0.machine as *const c_char ) as *const *const c_char)
}
}
+/// Get system identification
pub fn uname() -> UtsName {
unsafe {
let mut ret = mem::MaybeUninit::uninit();
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index 6c5c0f0e..ee49e37d 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -1,3 +1,4 @@
+//! Wait for a process to change status
use crate::errno::Errno;
use crate::sys::signal::Signal;
use crate::unistd::Pid;
@@ -7,9 +8,17 @@ use libc::{self, c_int};
use std::convert::TryFrom;
libc_bitflags!(
+ /// Controls the behavior of [`waitpid`].
pub struct WaitPidFlag: c_int {
+ /// Do not block when there are no processes wishing to report status.
WNOHANG;
+ /// Report the status of selected processes which are stopped due to a
+ /// [`SIGTTIN`](crate::sys::signal::Signal::SIGTTIN),
+ /// [`SIGTTOU`](crate::sys::signal::Signal::SIGTTOU),
+ /// [`SIGTSTP`](crate::sys::signal::Signal::SIGTSTP), or
+ /// [`SIGSTOP`](crate::sys::signal::Signal::SIGSTOP) signal.
WUNTRACED;
+ /// Report the status of selected processes which have terminated.
#[cfg(any(target_os = "android",
target_os = "freebsd",
target_os = "haiku",
@@ -19,7 +28,11 @@ libc_bitflags!(
target_os = "macos",
target_os = "netbsd"))]
WEXITED;
+ /// Report the status of selected processes that have continued from a
+ /// job control stop by receiving a
+ /// [`SIGCONT`](crate::sys::signal::Signal::SIGCONT) signal.
WCONTINUED;
+ /// An alias for WUNTRACED.
#[cfg(any(target_os = "android",
target_os = "freebsd",
target_os = "haiku",
@@ -45,6 +58,7 @@ libc_bitflags!(
/// Wait on all children, regardless of type
#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
__WALL;
+ /// Wait for "clone" children only.
#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
__WCLONE;
}
@@ -213,6 +227,9 @@ impl WaitStatus {
}
}
+/// Wait for a process to change status
+///
+/// See also [waitpid(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html)
pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
use self::WaitStatus::*;
@@ -237,6 +254,9 @@ pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Re
}
}
+/// Wait for any child process to change status or a signal is received.
+///
+/// See also [wait(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html)
pub fn wait() -> Result<WaitStatus> {
waitpid(None, None)
}
diff --git a/src/unistd.rs b/src/unistd.rs
index e42f83a5..25b20051 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -2742,7 +2742,7 @@ impl From<User> for libc::passwd {
pw_age: CString::new("").unwrap().into_raw(),
#[cfg(target_os = "illumos")]
pw_comment: CString::new("").unwrap().into_raw(),
- #[cfg(target_os = "freebsd")]
+ #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
pw_fields: 0,
}
}
diff --git a/test/common/mod.rs b/test/common/mod.rs
index cdc32582..84a0b4fa 100644
--- a/test/common/mod.rs
+++ b/test/common/mod.rs
@@ -14,19 +14,19 @@ use cfg_if::cfg_if;
cfg_if! {
if #[cfg(any(target_os = "android", target_os = "linux"))] {
#[macro_export] macro_rules! require_capability {
- ($capname:ident) => {
+ ($name:expr, $capname:ident) => {
use ::caps::{Capability, CapSet, has_cap};
if !has_cap(None, CapSet::Effective, Capability::$capname)
.unwrap()
{
- skip!("Insufficient capabilities. Skipping test.");
+ skip!("{} requires capability {}. Skipping test.", $name, Capability::$capname);
}
}
}
} else if #[cfg(not(target_os = "redox"))] {
#[macro_export] macro_rules! require_capability {
- ($capname:ident) => {}
+ ($name:expr, $capname:ident) => {}
}
}
}
diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs
index ceb39b9b..1c72e7c2 100644
--- a/test/sys/test_ptrace.rs
+++ b/test/sys/test_ptrace.rs
@@ -13,7 +13,7 @@ use crate::*;
fn test_ptrace() {
// Just make sure ptrace can be called at all, for now.
// FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace", CAP_SYS_PTRACE);
let err = ptrace::attach(getpid()).unwrap_err();
assert!(err == Errno::EPERM || err == Errno::EINVAL ||
err == Errno::ENOSYS);
@@ -23,7 +23,7 @@ fn test_ptrace() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_setoptions() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_setoptions", CAP_SYS_PTRACE);
let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
assert!(err != Errno::EOPNOTSUPP);
}
@@ -32,7 +32,7 @@ fn test_ptrace_setoptions() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_getevent() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_getevent", CAP_SYS_PTRACE);
let err = ptrace::getevent(getpid()).unwrap_err();
assert!(err != Errno::EOPNOTSUPP);
}
@@ -41,7 +41,7 @@ fn test_ptrace_getevent() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_getsiginfo() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_getsiginfo", CAP_SYS_PTRACE);
if let Err(Errno::EOPNOTSUPP) = ptrace::getsiginfo(getpid()) {
panic!("ptrace_getsiginfo returns Errno::EOPNOTSUPP!");
}
@@ -51,7 +51,7 @@ fn test_ptrace_getsiginfo() {
#[test]
#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_setsiginfo() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_setsiginfo", CAP_SYS_PTRACE);
let siginfo = unsafe { mem::zeroed() };
if let Err(Errno::EOPNOTSUPP) = ptrace::setsiginfo(getpid(), &siginfo) {
panic!("ptrace_setsiginfo returns Errno::EOPNOTSUPP!");
@@ -67,7 +67,7 @@ fn test_ptrace_cont() {
use nix::unistd::fork;
use nix::unistd::ForkResult::*;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_cont", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
@@ -125,7 +125,7 @@ fn test_ptrace_interrupt() {
use std::thread::sleep;
use std::time::Duration;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_interrupt", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
@@ -171,7 +171,7 @@ fn test_ptrace_syscall() {
use nix::unistd::getpid;
use nix::unistd::ForkResult::*;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_ptrace_syscall", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 92bb30e0..aceffccb 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -288,9 +288,9 @@ mod recvfrom {
use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment};
#[test]
- // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
- // support is suspected.
- #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+ // Disable the test under emulation because it fails in Cirrus-CI. Lack
+ // of QEMU support is suspected.
+ #[cfg_attr(qemu, ignore)]
pub fn gso() {
require_kernel_version!(udp_offload::gso, ">= 4.18");
@@ -342,9 +342,9 @@ mod recvfrom {
}
#[test]
- // Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
- // support is suspected.
- #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+ // Disable the test on emulated platforms because it fails in Cirrus-CI.
+ // Lack of QEMU support is suspected.
+ #[cfg_attr(qemu, ignore)]
pub fn gro() {
require_kernel_version!(udp_offload::gro, ">= 5.3");
@@ -583,7 +583,7 @@ pub fn test_recvmsg_ebadf() {
// Disable the test on emulated platforms due to a bug in QEMU versions <
// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_scm_rights() {
use nix::sys::uio::IoVec;
@@ -637,8 +637,8 @@ pub fn test_scm_rights() {
}
// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
#[cfg(any(target_os = "linux", target_os= "android"))]
+#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_cipher() {
use libc;
@@ -705,9 +705,10 @@ pub fn test_af_alg_cipher() {
assert_eq!(decrypted, payload);
}
-// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
+// Disable the test on emulated platforms due to not enabled support of AF_ALG
+// in QEMU from rust cross
#[cfg(any(target_os = "linux", target_os= "android"))]
+#[cfg_attr(qemu, ignore)]
#[test]
pub fn test_af_alg_aead() {
use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT};
@@ -910,7 +911,7 @@ pub fn test_sendmsg_ipv6packetinfo() {
/// Tests that passing multiple fds using a single `ControlMessage` works.
// Disable the test on emulated platforms due to a bug in QEMU versions <
// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
fn test_scm_rights_single_cmsg_multiple_fds() {
use std::os::unix::net::UnixDatagram;
@@ -1057,9 +1058,9 @@ fn test_scm_credentials() {
/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
/// `sendmsg` call.
#[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
+// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
fn test_scm_credentials_and_rights() {
use libc;
@@ -1071,9 +1072,9 @@ fn test_scm_credentials_and_rights() {
/// Ensure that passing a an oversized control message buffer to recvmsg
/// still works.
#[cfg(any(target_os = "android", target_os = "linux"))]
-// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
+// qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
// see https://bugs.launchpad.net/qemu/+bug/1781280
-#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
+#[cfg_attr(qemu, ignore)]
#[test]
fn test_too_large_cmsgspace() {
let space = vec![0u8; 1024];
@@ -1262,10 +1263,13 @@ fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddr
target_os = "netbsd",
))]
// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
+#[cfg_attr(all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ )
), ignore)]
#[test]
pub fn test_recv_ipv4pktinfo() {
@@ -1352,10 +1356,13 @@ pub fn test_recv_ipv4pktinfo() {
target_os = "openbsd",
))]
// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
+#[cfg_attr(all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ )
), ignore)]
#[test]
pub fn test_recvif() {
@@ -1463,10 +1470,13 @@ pub fn test_recvif() {
target_os = "openbsd",
))]
// qemu doesn't seem to be emulating this correctly in these architectures
-#[cfg_attr(any(
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64",
+#[cfg_attr(all(
+ qemu,
+ any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ )
), ignore)]
#[test]
pub fn test_recv_ipv6pktinfo() {
@@ -1544,6 +1554,7 @@ pub fn test_recv_ipv6pktinfo() {
}
#[cfg(any(target_os = "android", target_os = "linux"))]
+#[cfg_attr(graviton, ignore = "Not supported by the CI environment")]
#[test]
pub fn test_vsock() {
use libc;
@@ -1588,9 +1599,9 @@ pub fn test_vsock() {
thr.join().unwrap();
}
-// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
-// support is suspected.
-#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
#[cfg(all(target_os = "linux"))]
#[test]
fn test_recvmsg_timestampns() {
@@ -1639,9 +1650,9 @@ fn test_recvmsg_timestampns() {
nix::unistd::close(in_socket).unwrap();
}
-// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
-// support is suspected.
-#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
#[cfg(all(target_os = "linux"))]
#[test]
fn test_recvmmsg_timestampns() {
@@ -1696,9 +1707,9 @@ fn test_recvmmsg_timestampns() {
nix::unistd::close(in_socket).unwrap();
}
-// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack of QEMU
-// support is suspected.
-#[cfg_attr(not(any(target_arch = "x86_64")), ignore)]
+// Disable the test on emulated platforms because it fails in Cirrus-CI. Lack
+// of QEMU support is suspected.
+#[cfg_attr(qemu, ignore)]
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
#[test]
fn test_recvmsg_rxq_ovfl() {
diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs
index 72c9a315..45e969f4 100644
--- a/test/sys/test_sockopt.rs
+++ b/test/sys/test_sockopt.rs
@@ -49,7 +49,7 @@ pub fn test_local_peercred_stream() {
fn is_so_mark_functional() {
use nix::sys::socket::sockopt;
- require_capability!(CAP_NET_ADMIN);
+ require_capability!("is_so_mark_functional", CAP_NET_ADMIN);
let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
setsockopt(s, sockopt::Mark, &1337).unwrap();
diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs
index 9dd4f01d..8f8ba5e4 100644
--- a/test/sys/test_uio.rs
+++ b/test/sys/test_uio.rs
@@ -205,15 +205,15 @@ fn test_preadv() {
#[test]
#[cfg(target_os = "linux")]
-// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
-#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
+// qemu-user doesn't implement process_vm_readv/writev on most arches
+#[cfg_attr(qemu, ignore)]
fn test_process_vm_readv() {
use nix::unistd::ForkResult::*;
use nix::sys::signal::*;
use nix::sys::wait::*;
use crate::*;
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_process_vm_readv", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
// Pre-allocate memory in the child, since allocation isn't safe
diff --git a/test/sys/test_wait.rs b/test/sys/test_wait.rs
index 2d26fb8e..4a5b9661 100644
--- a/test/sys/test_wait.rs
+++ b/test/sys/test_wait.rs
@@ -96,7 +96,7 @@ mod ptrace {
#[test]
fn test_wait_ptrace() {
- require_capability!(CAP_SYS_PTRACE);
+ require_capability!("test_wait_ptrace", CAP_SYS_PTRACE);
let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
match unsafe{fork()}.expect("Error: Fork Failed") {
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index e74a8598..c19a1b0a 100644
--- a/test/test_fcntl.rs
+++ b/test/test_fcntl.rs
@@ -236,14 +236,8 @@ mod linux_android {
/// The from_offset should be updated by the call to reflect
/// the 3 bytes read (6).
#[test]
- // QEMU does not support copy_file_range. Skip platforms that use QEMU in CI
- #[cfg_attr(all(target_os = "linux", any(
- target_arch = "aarch64",
- target_arch = "arm",
- target_arch = "mips",
- target_arch = "mips64",
- target_arch = "powerpc64"
- )), ignore)]
+ // QEMU does not support copy_file_range. Skip under qemu
+ #[cfg_attr(qemu, ignore)]
fn test_copy_file_range() {
const CONTENTS: &[u8] = b"foobarbaz";
diff --git a/test/test_kmod/mod.rs b/test/test_kmod/mod.rs
index 76263305..e53e7a9e 100644
--- a/test/test_kmod/mod.rs
+++ b/test/test_kmod/mod.rs
@@ -41,7 +41,7 @@ use std::io::Read;
#[test]
fn test_finit_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_finit_and_delete_module", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -58,8 +58,8 @@ fn test_finit_and_delete_module() {
}
#[test]
-fn test_finit_and_delete_modul_with_params() {
- require_capability!(CAP_SYS_MODULE);
+fn test_finit_and_delete_module_with_params() {
+ require_capability!("test_finit_and_delete_module_with_params", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -80,7 +80,7 @@ fn test_finit_and_delete_modul_with_params() {
#[test]
fn test_init_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_init_and_delete_module", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -100,7 +100,7 @@ fn test_init_and_delete_module() {
#[test]
fn test_init_and_delete_module_with_params() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_init_and_delete_module_with_params", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -121,7 +121,7 @@ fn test_init_and_delete_module_with_params() {
#[test]
fn test_finit_module_invalid() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_finit_module_invalid", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -135,7 +135,7 @@ fn test_finit_module_invalid() {
#[test]
fn test_finit_module_twice_and_delete_module() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_finit_module_twice_and_delete_module", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
@@ -157,7 +157,7 @@ fn test_finit_module_twice_and_delete_module() {
#[test]
fn test_delete_module_not_loaded() {
- require_capability!(CAP_SYS_MODULE);
+ require_capability!("test_delete_module_not_loaded", CAP_SYS_MODULE);
let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
diff --git a/test/test_mq.rs b/test/test_mq.rs
index d0826923..430df5dd 100644
--- a/test/test_mq.rs
+++ b/test/test_mq.rs
@@ -60,7 +60,11 @@ fn test_mq_getattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
+#[cfg_attr(all(
+ qemu,
+ any(target_arch = "mips", target_arch = "mips64")
+ ), ignore
+)]
fn test_mq_setattr() {
use nix::mqueue::{mq_getattr, mq_setattr};
const MSG_SIZE: mq_attr_member_t = 32;
@@ -97,7 +101,11 @@ fn test_mq_setattr() {
// FIXME: Fix failures for mips in QEMU
#[test]
#[cfg(not(any(target_os = "netbsd")))]
-#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
+#[cfg_attr(all(
+ qemu,
+ any(target_arch = "mips", target_arch = "mips64")
+ ), ignore
+)]
fn test_mq_set_nonblocking() {
use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
const MSG_SIZE: mq_attr_member_t = 32;
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index 37e7a9b3..cb23ba75 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -549,7 +549,7 @@ cfg_if!{
if #[cfg(any(target_os = "android", target_os = "linux"))] {
macro_rules! require_acct{
() => {
- require_capability!(CAP_SYS_PACCT);
+ require_capability!("test_acct", CAP_SYS_PACCT);
}
}
} else if #[cfg(target_os = "freebsd")] {
@@ -1040,7 +1040,7 @@ fn test_user_into_passwd() {
fn test_setfsuid() {
use std::os::unix::fs::PermissionsExt;
use std::{fs, io, thread};
- require_capability!(CAP_SETUID);
+ require_capability!("test_setfsuid", CAP_SETUID);
// get the UID of the "nobody" user
let nobody = User::from_name("nobody").unwrap().unwrap();