summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml12
-rw-r--r--src/lib.rs2
-rw-r--r--src/sys/aio.rs4
-rw-r--r--src/sys/mod.rs9
-rw-r--r--src/sys/pthread.rs3
-rw-r--r--src/sys/resource.rs34
-rw-r--r--src/sys/select.rs7
-rw-r--r--src/sys/sendfile.rs2
-rw-r--r--src/sys/signal.rs146
-rw-r--r--src/sys/stat.rs1
-rw-r--r--src/sys/statfs.rs54
-rw-r--r--src/sys/uio.rs25
-rw-r--r--src/sys/utsname.rs8
-rw-r--r--src/sys/wait.rs20
14 files changed, 292 insertions, 35 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index bc8f21de..29175a27 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -2,6 +2,9 @@ cargo_cache:
folder: $CARGO_HOME/registry
fingerprint_script: cat Cargo.lock || echo ""
+env:
+ RUSTFLAGS: -D warnings
+ RUSTDOCFLAGS: -D warnings
# 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
@@ -17,9 +20,11 @@ task:
amd64_test_script:
- . $HOME/.cargo/env
- cargo test
+ - cargo doc --no-deps
i386_test_script:
- . $HOME/.cargo/env
- cargo test --target i686-unknown-freebsd
+ - cargo doc --no-deps --target i686-unknown-freebsd
before_cache_script: rm -rf $CARGO_HOME/registry/index
# Test OSX and iOS in a full VM
@@ -48,7 +53,7 @@ task:
RUST_TEST_THREADS: 1 # QEMU works best with 1 thread
HOME: /tmp/home
PATH: $HOME/.cargo/bin:$PATH
- RUSTFLAGS: --cfg qemu
+ RUSTFLAGS: --cfg qemu -D warnings
matrix:
- name: Linux arm gnueabi
env:
@@ -93,6 +98,7 @@ task:
- . $HOME/.cargo/env || true
- cross build --target $TARGET
- cross test --target $TARGET
+ - cross doc --no-deps --target $TARGET
before_cache_script: rm -rf $CARGO_HOME/registry/index
# Tasks for Linux native builds
@@ -107,7 +113,7 @@ task:
arm_container:
image: rust:1.46
env:
- RUSTFLAGS: --cfg graviton
+ RUSTFLAGS: --cfg graviton -D warnings
TARGET: aarch64-unknown-linux-gnu
- name: Linux x86_64
container:
@@ -125,6 +131,7 @@ task:
script:
- cargo build --target $TARGET --all-targets
- cargo test --target $TARGET
+ - cargo doc --no-deps --target $TARGET
before_cache_script: rm -rf $CARGO_HOME/registry/index
# Tasks for cross-compiling, but no testing
@@ -210,6 +217,7 @@ task:
script:
- cargo +$TOOLCHAIN check --target $TARGET
- cargo +$TOOLCHAIN check --all-targets --target $TARGET
+ - cargo +$TOOLCHAIN doc --no-deps --target $TARGET
before_cache_script: rm -rf $CARGO_HOME/registry/index
# Test that we can build with the lowest version of all dependencies.
diff --git a/src/lib.rs b/src/lib.rs
index 1ae63810..7a64b97a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,7 +11,7 @@
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]
-#![deny(missing_docs)]
+#![warn(missing_docs)]
// Re-exported external crates
pub use libc;
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index ae08a1fc..fcee28c5 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -62,9 +62,9 @@ libc_enum! {
pub enum LioOpcode {
/// No operation
LIO_NOP,
- /// Write data as if by a call to [`aio_write`]
+ /// Write data as if by a call to [`AioCb::write`]
LIO_WRITE,
- /// Write data as if by a call to [`aio_read`]
+ /// Write data as if by a call to [`AioCb::read`]
LIO_READ,
}
}
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 2f356801..5d9821a7 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -49,7 +49,6 @@ pub mod mman;
#[allow(missing_docs)]
pub mod personality;
-#[allow(missing_docs)]
pub mod pthread;
#[cfg(any(target_os = "android",
@@ -70,11 +69,9 @@ pub mod quota;
pub mod reboot;
#[cfg(not(any(target_os = "redox", target_os = "fuchsia", target_os = "illumos")))]
-#[allow(missing_docs)]
pub mod resource;
#[cfg(not(target_os = "redox"))]
-#[allow(missing_docs)]
pub mod select;
#[cfg(any(target_os = "android",
@@ -82,10 +79,8 @@ pub mod select;
target_os = "ios",
target_os = "linux",
target_os = "macos"))]
-#[allow(missing_docs)]
pub mod sendfile;
-#[allow(missing_docs)]
pub mod signal;
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -107,7 +102,6 @@ pub mod stat;
target_os = "macos",
target_os = "openbsd"
))]
-#[allow(missing_docs)]
pub mod statfs;
pub mod statvfs;
@@ -122,13 +116,10 @@ pub mod termios;
#[allow(missing_docs)]
pub mod time;
-#[allow(missing_docs)]
pub mod uio;
-#[allow(missing_docs)]
pub mod utsname;
-#[allow(missing_docs)]
pub mod wait;
#[cfg(any(target_os = "android", target_os = "linux"))]
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..c3bf29e8 100644
--- a/src/sys/resource.rs
+++ b/src/sys/resource.rs
@@ -50,54 +50,88 @@ libc_enum! {
#[non_exhaustive]
pub enum Resource {
#[cfg(not(any(target_os = "netbsd", target_os = "freebsd")))]
+ /// 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 89bcc1a2..ffcbf4a0 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -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
///
-/// 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.
+/// # Arguments
+///
+/// * `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,13 +914,14 @@ 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.
@@ -835,22 +929,35 @@ pub type type_of_thread_id = libc::pid_t;
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 +1039,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/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..16c16e65 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) };
@@ -60,6 +65,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 +78,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 +179,17 @@ pub fn process_vm_readv(
Errno::result(res).map(|r| r as usize)
}
+/// A vector of buffers.
+///
+/// Vectored I/O methods like [`pwritev`] and [`preadv`] 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 +211,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 +221,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)
}