summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md8
-rw-r--r--RELEASE_PROCEDURE.md9
-rw-r--r--src/fcntl.rs7
-rw-r--r--src/features.rs3
-rw-r--r--src/lib.rs62
-rw-r--r--src/mqueue.rs1
-rw-r--r--src/net/mod.rs1
-rw-r--r--src/poll.rs2
-rw-r--r--src/pty.rs4
-rw-r--r--src/sched.rs3
-rw-r--r--src/sys/aio.rs8
-rw-r--r--src/sys/epoll.rs5
-rw-r--r--src/sys/event.rs3
-rw-r--r--src/sys/mman.rs8
-rw-r--r--src/sys/mod.rs53
-rw-r--r--src/sys/ptrace.rs4
-rw-r--r--src/sys/quota.rs4
-rw-r--r--src/sys/select.rs4
-rw-r--r--src/sys/signal.rs6
-rw-r--r--src/sys/socket/addr.rs71
-rw-r--r--src/sys/socket/mod.rs7
-rw-r--r--src/sys/statvfs.rs8
-rw-r--r--src/sys/termios.rs19
-rw-r--r--src/sys/time.rs16
-rw-r--r--src/sys/uio.rs3
-rw-r--r--src/sys/utsname.rs1
-rw-r--r--src/sys/wait.rs4
-rw-r--r--src/ucontext.rs1
-rw-r--r--src/unistd.rs105
-rw-r--r--test/test_unistd.rs59
30 files changed, 340 insertions, 149 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ffc1b560..e434e5c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,10 +6,18 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Added
+- Added `getsid` in `::nix::unistd`
+ ([#850](https://github.com/nix-rust/nix/pull/850))
+
+- Added `alarm`. ([#830](https://github.com/nix-rust/nix/pull/830))
### Changed
+- Display and Debug for SysControlAddr now includes all fields.
+ ([#837](https://github.com/nix-rust/nix/pull/837))
### Fixed
+- Properly exposed 460800 and 921600 baud rates on NetBSD
+ ([#837](https://github.com/nix-rust/nix/pull/837))
### Removed
diff --git a/RELEASE_PROCEDURE.md b/RELEASE_PROCEDURE.md
index 25ba11d6..4946539a 100644
--- a/RELEASE_PROCEDURE.md
+++ b/RELEASE_PROCEDURE.md
@@ -30,12 +30,11 @@ The release is prepared as follows:
# After Release
-After the release a commit with the following changes is added to the master
-branch.
+After the release make a pull request with the following changes:
-- Add a new Unreleased section header to CHANGELOG.md.
+- Add a new Unreleased section header to `CHANGELOG.md`.
- In `Cargo.toml`, update the version to the nextversion, e.g.
`v0.8.4`.
- In `Cargo.toml`, revert the libc dependency to its git master branch.
-- Commit with a message like "Bump to v0.8.4"
-- Make a pull request.
+- Make a commit of the above changes with a message like "[skip ci] Bump to v0.8.4"
+ - This skips continuous integration testing on the build bots and Travis CI
diff --git a/src/fcntl.rs b/src/fcntl.rs
index fa96491f..58de3b31 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -205,6 +205,7 @@ libc_bitflags!(
}
);
+#[allow(missing_debug_implementations)]
pub enum FcntlArg<'a> {
F_DUPFD(RawFd),
F_DUPFD_CLOEXEC(RawFd),
@@ -230,7 +231,7 @@ pub enum FcntlArg<'a> {
#[cfg(any(target_os = "linux", target_os = "android"))]
F_GETPIPE_SZ,
#[cfg(any(target_os = "linux", target_os = "android"))]
- F_SETPIPE_SZ(libc::c_int),
+ F_SETPIPE_SZ(c_int),
// TODO: Rest of flags
}
@@ -267,6 +268,8 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
Errno::result(res)
}
+#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub enum FlockArg {
LockShared,
LockExclusive,
@@ -343,7 +346,7 @@ pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<
#[cfg(any(target_os = "linux"))]
libc_bitflags!(
/// Mode argument flags for fallocate determining operation performed on a given range.
- pub struct FallocateFlags: libc::c_int {
+ pub struct FallocateFlags: c_int {
/// File size is not changed.
///
/// offset + len can be greater than file size.
diff --git a/src/features.rs b/src/features.rs
index 1448fdd0..7797aa46 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -1,3 +1,4 @@
+//! Feature tests for OS functionality
pub use self::os::*;
#[cfg(any(target_os = "linux", target_os = "android"))]
@@ -82,6 +83,7 @@ mod os {
}
}
+ /// Check if the OS supports atomic close-on-exec for sockets
pub fn socket_atomic_cloexec() -> bool {
kernel_version() >= VERS_2_6_27
}
@@ -94,6 +96,7 @@ mod os {
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly", target_os = "ios", target_os = "openbsd", target_os = "netbsd"))]
mod os {
+ /// Check if the OS supports atomic close-on-exec for sockets
pub fn socket_atomic_cloexec() -> bool {
false
}
diff --git a/src/lib.rs b/src/lib.rs
index 5aaebc40..3873f4a1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,61 +10,61 @@
#![allow(dead_code)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
+#![deny(unused)]
+#![deny(unstable_features)]
+#![deny(missing_copy_implementations)]
+#![deny(missing_debug_implementations)]
+// External crates
extern crate bytes;
#[macro_use]
extern crate bitflags;
-
#[macro_use]
extern crate cfg_if;
extern crate void;
-#[macro_use] mod macros;
-
+// Re-exported external crates
pub extern crate libc;
-use errno::Errno;
+// Private internal modules
+#[macro_use] mod macros;
+// Public crates
pub mod errno;
+#[deny(missing_docs)]
pub mod features;
pub mod fcntl;
-
+#[deny(missing_docs)]
+#[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
+pub mod ifaddrs;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod mount;
-
#[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "fushsia",
target_os = "linux",
target_os = "netbsd"))]
pub mod mqueue;
-
-pub mod pty;
-
-pub mod poll;
-
+#[deny(missing_docs)]
pub mod net;
-
-#[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "ios",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
-pub mod ifaddrs;
-
+#[deny(missing_docs)]
+pub mod poll;
+#[deny(missing_docs)]
+pub mod pty;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;
-
pub mod sys;
-
// 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")))]
pub mod ucontext;
-
pub mod unistd;
/*
@@ -73,14 +73,14 @@ pub mod unistd;
*
*/
-use libc::c_char;
-use std::{ptr, result};
+use libc::{c_char, PATH_MAX};
+
+use std::{error, fmt, ptr, result};
use std::ffi::{CStr, OsStr};
-use std::path::{Path, PathBuf};
use std::os::unix::ffi::OsStrExt;
-use std::fmt;
-use std::error;
-use libc::PATH_MAX;
+use std::path::{Path, PathBuf};
+
+use errno::Errno;
/// Nix Result Type
pub type Result<T> = result::Result<T, Error>;
@@ -94,7 +94,7 @@ pub type Result<T> = result::Result<T, Error>;
/// implementing other common traits.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
- Sys(errno::Errno),
+ Sys(Errno),
InvalidPath,
/// The operation involved a conversion to Rust's native String type, which failed because the
/// string did not contain all valid UTF-8.
diff --git a/src/mqueue.rs b/src/mqueue.rs
index b9db3bab..0c6990f6 100644
--- a/src/mqueue.rs
+++ b/src/mqueue.rs
@@ -30,6 +30,7 @@ libc_bitflags!{
#[repr(C)]
#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct MqAttr {
mq_attr: libc::mq_attr,
}
diff --git a/src/net/mod.rs b/src/net/mod.rs
index eca5cfbb..079fcfde 100644
--- a/src/net/mod.rs
+++ b/src/net/mod.rs
@@ -1,3 +1,4 @@
+//! Functionality involving network interfaces
// To avoid clashing with the keyword "if", we use "if_" as the module name.
// The original header is called "net/if.h".
pub mod if_;
diff --git a/src/poll.rs b/src/poll.rs
index 78229a5b..f3046ff3 100644
--- a/src/poll.rs
+++ b/src/poll.rs
@@ -1,3 +1,4 @@
+//! Wait for events to trigger on specific file descriptors
#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
use sys::time::TimeSpec;
#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
@@ -18,6 +19,7 @@ use errno::Errno;
/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
#[repr(C)]
#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct PollFd {
pollfd: libc::pollfd,
}
diff --git a/src/pty.rs b/src/pty.rs
index ea0e543d..ec250aa7 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -17,8 +17,12 @@ use errno::Errno;
///
/// This is returned by `openpty`. Note that this type does *not* implement `Drop`, so the user
/// must manually close the file descriptors.
+#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct OpenptyResult {
+ /// The master port in a virtual pty pair
pub master: RawFd,
+ /// The slave port in a virtual pty pair
pub slave: RawFd,
}
diff --git a/src/sched.rs b/src/sched.rs
index 9de1bd10..f8f3a68a 100644
--- a/src/sched.rs
+++ b/src/sched.rs
@@ -9,7 +9,7 @@ use ::unistd::Pid;
// For some functions taking with a parameter of type CloneFlags,
// only a subset of these flags have an effect.
libc_bitflags!{
- pub struct CloneFlags: libc::c_int {
+ pub struct CloneFlags: c_int {
CLONE_VM;
CLONE_FS;
CLONE_FILES;
@@ -40,6 +40,7 @@ pub type CloneCb<'a> = Box<FnMut() -> isize + 'a>;
#[repr(C)]
#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct CpuSet {
cpu_set: libc::cpu_set_t,
}
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index d5561e9c..fe8e9ed2 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -295,7 +295,7 @@ impl<'a> AioCb<'a> {
aiocb: a,
mutable: true,
in_progress: false,
- buffer: Buffer::Phantom(PhantomData)
+ buffer: Buffer::Phantom(PhantomData),
}
}
@@ -379,7 +379,7 @@ impl<'a> AioCb<'a> {
aiocb: a,
mutable: false,
in_progress: false,
- buffer: Buffer::Bytes(buf2)
+ buffer: Buffer::Bytes(buf2),
}
}
@@ -464,7 +464,7 @@ impl<'a> AioCb<'a> {
aiocb: a,
mutable: true,
in_progress: false,
- buffer: Buffer::BytesMut(buf2)
+ buffer: Buffer::BytesMut(buf2),
}
}
@@ -619,7 +619,7 @@ impl<'a> AioCb<'a> {
aiocb: a,
mutable: false,
in_progress: false,
- buffer: Buffer::None
+ buffer: Buffer::None,
}
}
diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs
index c6c2eab3..3ed1dd72 100644
--- a/src/sys/epoll.rs
+++ b/src/sys/epoll.rs
@@ -7,7 +7,7 @@ use std::mem;
use ::Error;
libc_bitflags!(
- pub struct EpollFlags: libc::c_int {
+ pub struct EpollFlags: c_int {
EPOLLIN;
EPOLLPRI;
EPOLLOUT;
@@ -42,6 +42,7 @@ libc_bitflags!{
}
}
+#[allow(missing_debug_implementations)]
#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
@@ -58,7 +59,7 @@ impl EpollEvent {
}
pub fn events(&self) -> EpollFlags {
- EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
+ EpollFlags::from_bits(self.event.events as c_int).unwrap()
}
pub fn data(&self) -> u64 {
diff --git a/src/sys/event.rs b/src/sys/event.rs
index 4d5d1880..3a6c528d 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -14,6 +14,7 @@ use std::mem;
// Redefine kevent in terms of programmer-friendly enums and bitfields.
#[derive(Clone, Copy)]
#[repr(C)]
+#[allow(missing_debug_implementations)]
pub struct KEvent {
kevent: libc::kevent,
}
@@ -24,7 +25,7 @@ pub struct KEvent {
type type_of_udata = *mut libc::c_void;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos"))]
-type type_of_data = libc::intptr_t;
+type type_of_data = intptr_t;
#[cfg(any(target_os = "netbsd"))]
type type_of_udata = intptr_t;
#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
diff --git a/src/sys/mman.rs b/src/sys/mman.rs
index 65f6c59d..9d1f88df 100644
--- a/src/sys/mman.rs
+++ b/src/sys/mman.rs
@@ -1,13 +1,17 @@
-use {Error, Result, NixPath};
+use {Error, Result};
+#[cfg(not(target_os = "android"))]
+use NixPath;
use errno::Errno;
+#[cfg(not(target_os = "android"))]
use fcntl::OFlag;
use libc::{self, c_int, c_void, size_t, off_t};
+#[cfg(not(target_os = "android"))]
use sys::stat::Mode;
use std::os::unix::io::RawFd;
libc_bitflags!{
/// Desired memory protection of a memory mapping.
- pub struct ProtFlags: libc::c_int {
+ pub struct ProtFlags: c_int {
/// Pages cannot be accessed.
PROT_NONE;
/// Pages can be read.
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index a94b8a06..55c3d5d2 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -20,48 +20,39 @@ pub mod event;
#[cfg(target_os = "linux")]
pub mod eventfd;
-#[cfg(target_os = "linux")]
-pub mod memfd;
-
#[macro_use]
pub mod ioctl;
-// TODO: Add support for dragonfly, freebsd, and ios/macos.
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod sendfile;
+#[cfg(target_os = "linux")]
+pub mod memfd;
-pub mod signal;
+pub mod mman;
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod signalfd;
+pub mod pthread;
-pub mod socket;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub mod ptrace;
-pub mod stat;
+#[cfg(target_os = "linux")]
+pub mod quota;
#[cfg(any(target_os = "linux"))]
pub mod reboot;
-pub mod termios;
-
-pub mod utsname;
-
-pub mod wait;
-
-pub mod mman;
+pub mod select;
-pub mod uio;
+// TODO: Add support for dragonfly, freebsd, and ios/macos.
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub mod sendfile;
-pub mod time;
+pub mod signal;
#[cfg(any(target_os = "android", target_os = "linux"))]
-pub mod ptrace;
-
-pub mod select;
+pub mod signalfd;
-#[cfg(target_os = "linux")]
-pub mod quota;
+pub mod socket;
+pub mod stat;
#[cfg(all(target_os = "linux",
any(target_arch = "x86",
@@ -70,7 +61,6 @@ pub mod quota;
)]
pub mod statfs;
-
#[cfg(all(any(target_os = "linux",
target_os = "macos"),
any(target_arch = "x86",
@@ -78,4 +68,13 @@ pub mod statfs;
target_arch = "arm")),
)]
pub mod statvfs;
-pub mod pthread;
+
+pub mod termios;
+
+pub mod time;
+
+pub mod uio;
+
+pub mod utsname;
+
+pub mod wait;
diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs
index 59ceb378..4fb4f5b5 100644
--- a/src/sys/ptrace.rs
+++ b/src/sys/ptrace.rs
@@ -178,7 +178,7 @@ pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
let res = unsafe {
libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
libc::pid_t::from(pid),
- ptr::null_mut::<libc::c_void>(),
+ ptr::null_mut::<c_void>(),
options.bits() as *mut c_void)
};
Errno::result(res).map(|_| ())
@@ -200,7 +200,7 @@ pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
Errno::clear();
libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
libc::pid_t::from(pid),
- ptr::null_mut::<libc::c_void>(),
+ ptr::null_mut::<c_void>(),
sig as *const _ as *const c_void)
};
match Errno::result(ret) {
diff --git a/src/sys/quota.rs b/src/sys/quota.rs
index a85d9e30..b4cac1dc 100644
--- a/src/sys/quota.rs
+++ b/src/sys/quota.rs
@@ -33,9 +33,6 @@ libc_enum!{
Q_SYNC,
Q_QUOTAON,
Q_QUOTAOFF,
- Q_GETFMT,
- Q_GETINFO,
- Q_SETINFO,
Q_GETQUOTA,
Q_SETQUOTA,
}
@@ -100,6 +97,7 @@ libc_bitflags!(
// FIXME: Change to repr(transparent)
#[repr(C)]
#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct Dqblk(libc::dqblk);
impl Default for Dqblk {
diff --git a/src/sys/select.rs b/src/sys/select.rs
index 6fe176ae..33d3e638 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -10,6 +10,8 @@ pub use libc::FD_SETSIZE;
// FIXME: Change to repr(transparent) once it's stable
#[repr(C)]
+#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct FdSet(libc::fd_set);
impl FdSet {
@@ -56,7 +58,7 @@ impl FdSet {
///
/// [`select`]: fn.select.html
pub fn highest(&mut self) -> Option<RawFd> {
- for i in (0..libc::FD_SETSIZE).rev() {
+ for i in (0..FD_SETSIZE).rev() {
let i = i as RawFd;
if unsafe { libc::FD_ISSET(i, self as *mut _ as *mut libc::fd_set) } {
return Some(i)
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index f533b1b2..10798ba1 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -163,6 +163,8 @@ const SIGNALS: [Signal; 31] = [
pub const NSIG: libc::c_int = 32;
+#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct SignalIterator {
next: usize,
}
@@ -255,6 +257,7 @@ libc_enum! {
}
#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct SigSet {
sigset: libc::sigset_t
}
@@ -359,6 +362,8 @@ pub enum SigHandler {
SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
}
+#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct SigAction {
sigaction: libc::sigaction
}
@@ -528,6 +533,7 @@ mod sigevent {
/// Used to request asynchronous notification of the completion of certain
/// events, such as POSIX AIO and timers.
#[repr(C)]
+ #[derive(Clone, Copy)]
pub struct SigEvent {
sigevent: libc::sigevent
}
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index 823f8df5..25114dd2 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -215,7 +215,7 @@ impl AddressFamily {
/// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
/// the `sa_family` field of a `sockaddr`.
///
- /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
+ /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
/// and System. Returns None for unsupported or unknown address families.
pub fn from_i32(family: i32) -> Option<AddressFamily> {
match family {
@@ -392,7 +392,7 @@ impl fmt::Debug for InetAddr {
* ===== IpAddr =====
*
*/
-
+#[derive(Clone, Copy)]
pub enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
@@ -813,7 +813,7 @@ impl SockAddr {
NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
#[cfg(any(target_os = "ios", target_os = "macos"))]
Some(AddressFamily::System) => Some(SockAddr::SysControl(
- SysControlAddr(*(addr as *const sys_control::sockaddr_ctl)))),
+ SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
#[cfg(any(target_os = "android", target_os = "linux"))]
Some(AddressFamily::Packet) => Some(SockAddr::Link(
LinkAddr(*(addr as *const libc::sockaddr_ll)))),
@@ -839,11 +839,11 @@ impl SockAddr {
}
/// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
- ///
+ ///
/// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
- /// Returns a reference to the underlying data type (as a sockaddr reference) along
- /// with the size of the actual data type. sockaddr is commonly used as a proxy for
- /// a superclass as C doesn't support inheritance, so many functions that take
+ /// Returns a reference to the underlying data type (as a sockaddr reference) along
+ /// with the size of the actual data type. sockaddr is commonly used as a proxy for
+ /// a superclass as C doesn't support inheritance, so many functions that take
/// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
match *self {
@@ -853,7 +853,7 @@ impl SockAddr {
#[cfg(any(target_os = "android", target_os = "linux"))]
SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
#[cfg(any(target_os = "ios", target_os = "macos"))]
- SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<sys_control::sockaddr_ctl>() as libc::socklen_t),
+ SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t),
#[cfg(any(target_os = "android", target_os = "linux"))]
SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t),
#[cfg(any(target_os = "dragonfly",
@@ -951,7 +951,7 @@ impl fmt::Display for SockAddr {
#[cfg(any(target_os = "android", target_os = "linux"))]
pub mod netlink {
- use ::sys::socket::addr::{AddressFamily};
+ use ::sys::socket::addr::AddressFamily;
use libc::{sa_family_t, sockaddr_nl};
use std::{fmt, mem};
use std::hash::{Hash, Hasher};
@@ -1012,7 +1012,7 @@ pub mod netlink {
#[cfg(any(target_os = "ios", target_os = "macos"))]
pub mod sys_control {
- use ::sys::socket::addr::{AddressFamily};
+ use ::sys::socket::addr::AddressFamily;
use libc::{self, c_uchar, uint16_t, uint32_t};
use std::{fmt, mem};
use std::hash::{Hash, Hasher};
@@ -1031,21 +1031,10 @@ pub mod sys_control {
ioctl!(readwrite ctl_info with CTL_IOC_MAGIC, CTL_IOC_INFO; ctl_ioc_info);
- #[repr(C)]
- #[derive(Copy, Clone)]
- pub struct sockaddr_ctl {
- pub sc_len: c_uchar,
- pub sc_family: c_uchar,
- pub ss_sysaddr: uint16_t,
- pub sc_id: uint32_t,
- pub sc_unit: uint32_t,
- pub sc_reserved: [uint32_t; 5],
- }
-
#[derive(Copy, Clone)]
- pub struct SysControlAddr(pub sockaddr_ctl);
+ #[repr(C)]
+ pub struct SysControlAddr(pub libc::sockaddr_ctl);
- // , PartialEq, Eq, Debug, Hash
impl PartialEq for SysControlAddr {
fn eq(&self, other: &Self) -> bool {
let (inner, other) = (self.0, other.0);
@@ -1066,8 +1055,8 @@ pub mod sys_control {
impl SysControlAddr {
pub fn new(id: u32, unit: u32) -> SysControlAddr {
- let addr = sockaddr_ctl {
- sc_len: mem::size_of::<sockaddr_ctl>() as c_uchar,
+ let addr = libc::sockaddr_ctl {
+ sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
sc_family: AddressFamily::System as c_uchar,
ss_sysaddr: libc::AF_SYS_CONTROL as uint16_t,
sc_id: id,
@@ -1103,13 +1092,19 @@ pub mod sys_control {
impl fmt::Display for SysControlAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "id: {} unit: {}", self.id(), self.unit())
+ fmt::Debug::fmt(self, f)
}
}
impl fmt::Debug for SysControlAddr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Display::fmt(self, f)
+ f.debug_struct("SysControlAddr")
+ .field("sc_len", &self.0.sc_len)
+ .field("sc_family", &self.0.sc_family)
+ .field("ss_sysaddr", &self.0.ss_sysaddr)
+ .field("sc_id", &self.0.sc_id)
+ .field("sc_unit", &self.0.sc_unit)
+ .finish()
}
}
}
@@ -1173,9 +1168,9 @@ mod datalink {
impl PartialEq for LinkAddr {
fn eq(&self, other: &Self) -> bool {
let (a, b) = (self.0, other.0);
- (a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype,
+ (a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype,
a.sll_pkttype, a.sll_halen, a.sll_addr) ==
- (b.sll_family, b.sll_protocol, b.sll_ifindex, b.sll_hatype,
+ (b.sll_family, b.sll_protocol, b.sll_ifindex, b.sll_hatype,
b.sll_pkttype, b.sll_halen, b.sll_addr)
}
}
@@ -1183,7 +1178,7 @@ mod datalink {
impl hash::Hash for LinkAddr {
fn hash<H: hash::Hasher>(&self, s: &mut H) {
let a = self.0;
- (a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype,
+ (a.sll_family, a.sll_protocol, a.sll_ifindex, a.sll_hatype,
a.sll_pkttype, a.sll_halen, a.sll_addr).hash(s);
}
}
@@ -1300,18 +1295,18 @@ mod datalink {
target_os = "openbsd"))]
fn eq(&self, other: &Self) -> bool {
let (a, b) = (self.0, other.0);
- (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
+ (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
a.sdl_nlen, a.sdl_alen, a.sdl_slen, &a.sdl_data[..]) ==
- (b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type,
+ (b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type,
b.sdl_nlen, b.sdl_alen, b.sdl_slen, &b.sdl_data[..])
}
-
+
#[cfg(target_os = "dragonfly")]
fn eq(&self, other: &Self) -> bool {
let (a, b) = (self.0, other.0);
- (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen,
+ (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen,
a.sdl_alen, a.sdl_slen, a.sdl_data, a.sdl_rcf, a.sdl_route) ==
- (b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type, b.sdl_nlen,
+ (b.sdl_len, b.sdl_family, b.sdl_index, b.sdl_type, b.sdl_nlen,
b.sdl_alen, b.sdl_slen, b.sdl_data, b.sdl_rcf, b.sdl_route)
}
}
@@ -1324,14 +1319,14 @@ mod datalink {
target_os = "openbsd"))]
fn hash<H: hash::Hasher>(&self, s: &mut H) {
let a = self.0;
- (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
+ (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type,
a.sdl_nlen, a.sdl_alen, a.sdl_slen, &a.sdl_data[..]).hash(s);
}
#[cfg(target_os = "dragonfly")]
fn hash<H: hash::Hasher>(&self, s: &mut H) {
let a = self.0;
- (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen,
+ (a.sdl_len, a.sdl_family, a.sdl_index, a.sdl_type, a.sdl_nlen,
a.sdl_alen, a.sdl_slen, a.sdl_data, a.sdl_rcf, a.sdl_route).hash(s);
}
}
@@ -1398,7 +1393,7 @@ mod tests {
let sock_addr = _sock_addr.unwrap();
assert_eq!(sock_addr.family(), AddressFamily::Link);
-
+
match sock_addr {
SockAddr::Link(ether_addr) => {
assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index 7c62c739..beef3db8 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -117,7 +117,7 @@ libc_bitflags!{
libc_bitflags!{
/// Flags for send/recv and their relatives
- pub struct MsgFlags: libc::c_int {
+ pub struct MsgFlags: c_int {
/// Sends or requests out-of-band data on sockets that support this notion
/// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
/// support out-of-band data.
@@ -320,6 +320,7 @@ cfg_if! {
/// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
/// ```
#[repr(C)]
+#[allow(missing_debug_implementations)]
pub struct CmsgSpace<T> {
_hdr: cmsghdr,
_pad: [align_of_cmsg_data; 0],
@@ -335,6 +336,7 @@ impl<T> CmsgSpace<T> {
}
}
+#[allow(missing_debug_implementations)]
pub struct RecvMsg<'a> {
// The number of bytes received.
pub bytes: usize,
@@ -354,6 +356,7 @@ impl<'a> RecvMsg<'a> {
}
}
+#[allow(missing_debug_implementations)]
pub struct CmsgIterator<'a> {
buf: &'a [u8],
next: usize,
@@ -420,6 +423,7 @@ impl<'a> Iterator for CmsgIterator<'a> {
/// A type-safe wrapper around a single control message. More types may
/// be added to this enum; do not exhaustively pattern-match it.
/// [Further reading](http://man7.org/linux/man-pages/man3/cmsg.3.html)
+#[allow(missing_debug_implementations)]
pub enum ControlMessage<'a> {
/// A message of type `SCM_RIGHTS`, containing an array of file
/// descriptors passed between processes.
@@ -501,6 +505,7 @@ pub enum ControlMessage<'a> {
// An opaque structure used to prevent cmsghdr from being a public type
#[doc(hidden)]
+#[allow(missing_debug_implementations)]
pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);
// Round `len` up to meet the platform's required alignment for
diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs
index fbd0570e..41ca44f2 100644
--- a/src/sys/statvfs.rs
+++ b/src/sys/statvfs.rs
@@ -57,16 +57,18 @@ libc_bitflags!(
/// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
// FIXME: Replace with repr(transparent)
#[repr(C)]
+#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct Statvfs(libc::statvfs);
impl Statvfs {
/// get the file system block size
- pub fn block_size(&self) -> libc::c_ulong {
+ pub fn block_size(&self) -> c_ulong {
self.0.f_bsize
}
/// Get the fundamental file system block size
- pub fn fragment_size(&self) -> libc::c_ulong {
+ pub fn fragment_size(&self) -> c_ulong {
self.0.f_frsize
}
@@ -113,7 +115,7 @@ impl Statvfs {
}
/// Get the maximum filename length
- pub fn name_max(&self) -> libc::c_ulong {
+ pub fn name_max(&self) -> c_ulong {
self.0.f_namemax
}
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index 962377d5..356c7769 100644
--- a/src/sys/termios.rs
+++ b/src/sys/termios.rs
@@ -177,6 +177,7 @@ use ::unistd::Pid;
/// standard fields. The only safe way to obtain an instance of this struct is to extract it from
/// an open port using `tcgetattr()`.
#[derive(Clone)]
+#[allow(missing_debug_implementations)]
pub struct Termios {
inner: RefCell<libc::termios>,
/// Input mode flags (see `termios.c_iflag` documentation)
@@ -188,7 +189,7 @@ pub struct Termios {
/// Local mode flags (see `termios.c_lflag` documentation)
pub local_flags: LocalFlags,
/// Control characters (see `termios.c_cc` documentation)
- pub control_chars: [libc::cc_t; libc::NCCS],
+ pub control_chars: [libc::cc_t; NCCS],
}
impl Termios {
@@ -344,18 +345,18 @@ libc_enum!{
B115200,
B230400,
#[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- taget_os = "netbsd"))]
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd"))]
B460800,
#[cfg(any(target_os = "android", target_os = "linux"))]
B500000,
#[cfg(any(target_os = "android", target_os = "linux"))]
B576000,
#[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- taget_os = "netbsd"))]
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd"))]
B921600,
#[cfg(any(target_os = "android", target_os = "linux"))]
B1000000,
@@ -443,7 +444,7 @@ impl From<libc::speed_t> for BaudRate {
#[cfg(any(target_os = "android",
target_os = "freebsd",
target_os = "linux",
- taget_os = "netbsd"))]
+ target_os = "netbsd"))]
B460800 => BaudRate::B460800,
#[cfg(any(target_os = "android", target_os = "linux"))]
B500000 => BaudRate::B500000,
@@ -452,7 +453,7 @@ impl From<libc::speed_t> for BaudRate {
#[cfg(any(target_os = "android",
target_os = "freebsd",
target_os = "linux",
- taget_os = "netbsd"))]
+ target_os = "netbsd"))]
B921600 => BaudRate::B921600,
#[cfg(any(target_os = "android", target_os = "linux"))]
B1000000 => BaudRate::B1000000,
diff --git a/src/sys/time.rs b/src/sys/time.rs
index 0d977045..51286a06 100644
--- a/src/sys/time.rs
+++ b/src/sys/time.rs
@@ -74,7 +74,7 @@ impl fmt::Debug for TimeSpec {
}
}
-impl cmp::PartialEq for TimeSpec {
+impl PartialEq for TimeSpec {
// The implementation of cmp is simplified by assuming that the struct is
// normalized. That is, tv_nsec must always be within [0, 1_000_000_000)
fn eq(&self, other: &TimeSpec) -> bool {
@@ -82,9 +82,9 @@ impl cmp::PartialEq for TimeSpec {
}
}
-impl cmp::Eq for TimeSpec {}
+impl Eq for TimeSpec {}
-impl cmp::Ord for TimeSpec {
+impl Ord for TimeSpec {
// The implementation of cmp is simplified by assuming that the struct is
// normalized. That is, tv_nsec must always be within [0, 1_000_000_000)
fn cmp(&self, other: &TimeSpec) -> cmp::Ordering {
@@ -96,7 +96,7 @@ impl cmp::Ord for TimeSpec {
}
}
-impl cmp::PartialOrd for TimeSpec {
+impl PartialOrd for TimeSpec {
fn partial_cmp(&self, other: &TimeSpec) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
@@ -285,7 +285,7 @@ impl fmt::Debug for TimeVal {
}
}
-impl cmp::PartialEq for TimeVal {
+impl PartialEq for TimeVal {
// The implementation of cmp is simplified by assuming that the struct is
// normalized. That is, tv_usec must always be within [0, 1_000_000)
fn eq(&self, other: &TimeVal) -> bool {
@@ -293,9 +293,9 @@ impl cmp::PartialEq for TimeVal {
}
}
-impl cmp::Eq for TimeVal {}
+impl Eq for TimeVal {}
-impl cmp::Ord for TimeVal {
+impl Ord for TimeVal {
// The implementation of cmp is simplified by assuming that the struct is
// normalized. That is, tv_usec must always be within [0, 1_000_000)
fn cmp(&self, other: &TimeVal) -> cmp::Ordering {
@@ -307,7 +307,7 @@ impl cmp::Ord for TimeVal {
}
}
-impl cmp::PartialOrd for TimeVal {
+impl PartialOrd for TimeVal {
fn partial_cmp(&self, other: &TimeVal) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 7447f3ff..5713f63c 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -67,6 +67,8 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
/// and [`process_vm_writev`](fn.process_vm_writev.html).
#[cfg(target_os = "linux")]
#[repr(C)]
+#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct RemoteIoVec {
/// The starting address of this slice (`iov_base`).
pub base: usize,
@@ -137,6 +139,7 @@ pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remo
}
#[repr(C)]
+#[allow(missing_debug_implementations)]
pub struct IoVec<T>(libc::iovec, PhantomData<T>);
impl<T> IoVec<T> {
diff --git a/src/sys/utsname.rs b/src/sys/utsname.rs
index afec3e20..e33d0739 100644
--- a/src/sys/utsname.rs
+++ b/src/sys/utsname.rs
@@ -5,6 +5,7 @@ use std::str::from_utf8_unchecked;
#[repr(C)]
#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct UtsName(libc::utsname);
impl UtsName {
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index 53c6a5f2..038354b1 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -141,6 +141,7 @@ fn stop_signal(status: i32) -> Result<Signal> {
Signal::from_c_int(unsafe { libc::WSTOPSIG(status) })
}
+#[cfg(any(target_os = "android", target_os = "linux"))]
fn syscall_stop(status: i32) -> bool {
// From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
// of delivering SIGTRAP | 0x80 as the signal number for syscall
@@ -149,6 +150,7 @@ fn syscall_stop(status: i32) -> bool {
unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 }
}
+#[cfg(any(target_os = "android", target_os = "linux"))]
fn stop_additional(status: i32) -> c_int {
(status >> 16) as c_int
}
@@ -182,7 +184,7 @@ impl WaitStatus {
WaitStatus::Signaled(pid, try!(term_signal(status)), dumped_core(status))
} else if stopped(status) {
cfg_if! {
- if #[cfg(any(target_os = "linux", target_os = "android"))] {
+ if #[cfg(any(target_os = "android", target_os = "linux"))] {
fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
let status_additional = stop_additional(status);
Ok(if syscall_stop(status) {
diff --git a/src/ucontext.rs b/src/ucontext.rs
index da5a5b13..c94464d5 100644
--- a/src/ucontext.rs
+++ b/src/ucontext.rs
@@ -7,6 +7,7 @@ use std::mem;
use sys::signal::SigSet;
#[derive(Clone, Copy)]
+#[allow(missing_debug_implementations)]
pub struct UContext {
context: libc::ucontext_t,
}
diff --git a/src/unistd.rs b/src/unistd.rs
index 0f47a7fc..8022aa0b 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -10,7 +10,7 @@ use std::{fmt, mem, ptr};
use std::ffi::{CString, CStr, OsString, OsStr};
use std::os::unix::ffi::{OsStringExt, OsStrExt};
use std::os::unix::io::RawFd;
-use std::path::{PathBuf};
+use std::path::PathBuf;
use void::Void;
use sys::stat::Mode;
@@ -143,7 +143,7 @@ impl fmt::Display for Pid {
/// When `fork` is called, the process continues execution in the parent process
/// and in the new child. This return type can be examined to determine whether
/// you are now executing in the parent process or in the child.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub enum ForkResult {
Parent { child: Pid },
Child,
@@ -264,6 +264,17 @@ pub fn setsid() -> Result<Pid> {
Errno::result(unsafe { libc::setsid() }).map(Pid)
}
+/// Get the process group ID of a session leader
+/// [getsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
+///
+/// Obtain the process group ID of the process that is the session leader of the process specified
+/// by pid. If pid is zero, it specifies the calling process.
+#[inline]
+pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
+ let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
+ Errno::result(res).map(Pid)
+}
+
/// Get the terminal foreground process group (see
/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
@@ -503,14 +514,14 @@ pub fn getcwd() -> Result<PathBuf> {
let mut buf = Vec::with_capacity(512);
loop {
unsafe {
- let ptr = buf.as_mut_ptr() as *mut libc::c_char;
+ let ptr = buf.as_mut_ptr() as *mut c_char;
// The buffer must be large enough to store the absolute pathname plus
// a terminating null byte, or else null is returned.
// To safely handle this we start with a reasonable size (512 bytes)
// and double the buffer size upon every error
if !libc::getcwd(ptr, buf.capacity()).is_null() {
- let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
+ let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len();
buf.set_len(len);
buf.shrink_to_fit();
return Ok(PathBuf::from(OsString::from_vec(buf)));
@@ -822,6 +833,7 @@ pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
/// [`lseek`]: ./fn.lseek.html
/// [`lseek64`]: ./fn.lseek64.html
#[repr(i32)]
+#[derive(Clone, Copy, Debug)]
pub enum Whence {
/// Specify an offset relative to the start of the file.
SeekSet = libc::SEEK_SET,
@@ -852,10 +864,10 @@ pub enum Whence {
/// Move the read/write file offset.
///
/// See also [lseek(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
-pub fn lseek(fd: RawFd, offset: libc::off_t, whence: Whence) -> Result<libc::off_t> {
+pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
let res = unsafe { libc::lseek(fd, offset, whence as i32) };
- Errno::result(res).map(|r| r as libc::off_t)
+ Errno::result(res).map(|r| r as off_t)
}
#[cfg(any(target_os = "linux", target_os = "android"))]
@@ -1324,12 +1336,91 @@ pub fn pause() {
unsafe { libc::pause() };
}
+pub mod alarm {
+ //! Alarm signal scheduling.
+ //!
+ //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has
+ //! elapsed, which has to be caught, because the default action for the
+ //! signal is to terminate the program. This signal also can't be ignored
+ //! because the system calls like `pause` will not be interrupted, see the
+ //! second example below.
+ //!
+ //! # Examples
+ //!
+ //! Canceling an alarm:
+ //!
+ //! ```
+ //! use nix::unistd::alarm;
+ //!
+ //! // Set an alarm for 60 seconds from now.
+ //! alarm::set(60);
+ //!
+ //! // Cancel the above set alarm, which returns the number of seconds left
+ //! // of the previously set alarm.
+ //! assert_eq!(alarm::cancel(), Some(60));
+ //! ```
+ //!
+ //! Scheduling an alarm and waiting for the signal:
+ //!
+ //! ```
+ //! use std::time::{Duration, Instant};
+ //!
+ //! use nix::unistd::{alarm, pause};
+ //! use nix::sys::signal::*;
+ //!
+ //! // We need to setup an empty signal handler to catch the alarm signal,
+ //! // otherwise the program will be terminated once the signal is delivered.
+ //! extern fn signal_handler(_: nix::libc::c_int) { }
+ //! unsafe { sigaction(Signal::SIGALRM, &SigAction::new(SigHandler::Handler(signal_handler), SaFlags::empty(), SigSet::empty())); }
+ //!
+ //! // Set an alarm for 1 second from now.
+ //! alarm::set(1);
+ //!
+ //! let start = Instant::now();
+ //! // Pause the process until the alarm signal is received.
+ //! pause();
+ //!
+ //! assert!(start.elapsed() >= Duration::from_secs(1));
+ //! ```
+ //!
+ //! # References
+ //!
+ //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
+
+ use libc;
+
+ /// Schedule an alarm signal.
+ ///
+ /// This will cause the system to generate a `SIGALRM` signal for the
+ /// process after the specified number of seconds have elapsed.
+ ///
+ /// Returns the leftover time of a previously set alarm if there was one.
+ pub fn set(secs: libc::c_uint) -> Option<libc::c_uint> {
+ assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`");
+ alarm(secs)
+ }
+
+ /// Cancel an previously set alarm signal.
+ ///
+ /// Returns the leftover time of a previously set alarm if there was one.
+ pub fn cancel() -> Option<libc::c_uint> {
+ alarm(0)
+ }
+
+ fn alarm(secs: libc::c_uint) -> Option<libc::c_uint> {
+ match unsafe { libc::alarm(secs) } {
+ 0 => None,
+ secs => Some(secs),
+ }
+ }
+}
+
/// Suspend execution for an interval of time
///
/// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
// Per POSIX, does not fail
#[inline]
-pub fn sleep(seconds: libc::c_uint) -> c_uint {
+pub fn sleep(seconds: c_uint) -> c_uint {
unsafe { libc::sleep(seconds) }
}
diff --git a/test/test_unistd.rs b/test/test_unistd.rs
index e15fec17..fe33b1d0 100644
--- a/test/test_unistd.rs
+++ b/test/test_unistd.rs
@@ -3,6 +3,7 @@ extern crate tempdir;
use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag};
use nix::unistd::*;
use nix::unistd::ForkResult::*;
+use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
use nix::sys::wait::*;
use nix::sys::stat::{self, Mode, SFlag};
use std::{self, env, iter};
@@ -12,7 +13,7 @@ use std::io::Write;
use std::os::unix::prelude::*;
use tempfile::tempfile;
use tempdir::TempDir;
-use libc::{_exit, off_t};
+use libc::{self, _exit, off_t};
#[test]
fn test_fork_and_waitpid() {
@@ -107,6 +108,14 @@ fn test_getpid() {
assert!(ppid > 0);
}
+#[test]
+fn test_getsid() {
+ let none_sid: ::libc::pid_t = getsid(None).unwrap().into();
+ let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into();
+ assert!(none_sid > 0);
+ assert!(none_sid == pid_sid);
+}
+
#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux_android {
use nix::unistd::gettid;
@@ -400,3 +409,51 @@ fn test_pipe2() {
let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
assert!(f1.contains(FdFlag::FD_CLOEXEC));
}
+
+// Used in `test_alarm`.
+static mut ALARM_CALLED: bool = false;
+
+// Used in `test_alarm`.
+pub extern fn alarm_signal_handler(raw_signal: libc::c_int) {
+ assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal);
+ unsafe { ALARM_CALLED = true };
+}
+
+#[test]
+fn test_alarm() {
+ let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+
+ let handler = SigHandler::Handler(alarm_signal_handler);
+ let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
+ let old_handler = unsafe {
+ sigaction(Signal::SIGALRM, &signal_action)
+ .expect("unable to set signal handler for alarm")
+ };
+
+ // Set an alarm.
+ assert_eq!(alarm::set(60), None);
+
+ // Overwriting an alarm should return the old alarm.
+ assert_eq!(alarm::set(1), Some(60));
+
+ // We should be woken up after 1 second by the alarm, so we'll sleep for 2
+ // seconds to be sure.
+ sleep(2);
+ assert_eq!(unsafe { ALARM_CALLED }, true, "expected our alarm signal handler to be called");
+
+ // Reset the signal.
+ unsafe {
+ sigaction(Signal::SIGALRM, &old_handler)
+ .expect("unable to set signal handler for alarm");
+ }
+}
+
+#[test]
+fn test_canceling_alarm() {
+ let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+
+ assert_eq!(alarm::cancel(), None);
+
+ assert_eq!(alarm::set(60), None);
+ assert_eq!(alarm::cancel(), Some(60));
+}