summaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
authorPhilipp Keller <philipp.keller@gmail.com>2016-09-16 07:14:29 +0200
committerPhilipp Keller <philipp.keller@gmail.com>2016-09-16 07:14:29 +0200
commit631a27a545906f739e50393509e71fb847740c3a (patch)
tree1d3279093084c3f2b650bb3ff8b88c2df9c2d69c /src/sys
parent23a7ea64938cc73d476e42b80a243fefbe7111b2 (diff)
parent7c0570d3ad3c8e5fdd45c7de745771a6be054c3c (diff)
downloadnix-631a27a545906f739e50393509e71fb847740c3a.zip
made it running with rust 1.2, added documentation to mkstemp
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/event.rs2
-rw-r--r--src/sys/eventfd.rs26
-rw-r--r--src/sys/mman.rs2
-rw-r--r--src/sys/mod.rs3
-rw-r--r--src/sys/reboot.rs43
-rw-r--r--src/sys/select.rs1
-rw-r--r--src/sys/signal.rs254
-rw-r--r--src/sys/socket/consts.rs3
-rw-r--r--src/sys/socket/ffi.rs14
-rw-r--r--src/sys/socket/mod.rs32
-rw-r--r--src/sys/socket/sockopt.rs62
-rw-r--r--src/sys/wait.rs61
12 files changed, 338 insertions, 165 deletions
diff --git a/src/sys/event.rs b/src/sys/event.rs
index 8b112689..0e94475e 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -355,7 +355,7 @@ pub fn ev_set(ev: &mut KEvent,
filter: EventFilter,
flags: EventFlag,
fflags: FilterFlag,
- udata: i64) {
+ udata: isize) {
ev.ident = ident as uintptr_t;
ev.filter = filter;
diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs
index cd740341..e6e410ec 100644
--- a/src/sys/eventfd.rs
+++ b/src/sys/eventfd.rs
@@ -2,26 +2,16 @@ use libc;
use std::os::unix::io::RawFd;
use {Errno, Result};
-bitflags!(
- flags EventFdFlag: libc::c_int {
- const EFD_CLOEXEC = 0o2000000, // Since Linux 2.6.27
- const EFD_NONBLOCK = 0o0004000, // Since Linux 2.6.27
- const EFD_SEMAPHORE = 0o0000001, // Since Linux 2.6.30
- }
-);
-
-mod ffi {
- use libc;
-
- extern {
- pub fn eventfd(initval: libc::c_uint, flags: libc::c_int) -> libc::c_int;
+libc_bitflags! {
+ flags EfdFlags: libc::c_int {
+ const EFD_CLOEXEC, // Since Linux 2.6.27
+ const EFD_NONBLOCK, // Since Linux 2.6.27
+ const EFD_SEMAPHORE, // Since Linux 2.6.30
}
}
-pub fn eventfd(initval: usize, flags: EventFdFlag) -> Result<RawFd> {
- unsafe {
- let res = ffi::eventfd(initval as libc::c_uint, flags.bits());
+pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
+ let res = unsafe { libc::eventfd(initval, flags.bits()) };
- Errno::result(res).map(|r| r as RawFd)
- }
+ Errno::result(res).map(|r| r as RawFd)
}
diff --git a/src/sys/mman.rs b/src/sys/mman.rs
index 5bc1c82d..a1bf6134 100644
--- a/src/sys/mman.rs
+++ b/src/sys/mman.rs
@@ -131,7 +131,7 @@ mod consts {
const MAP_RENAME = libc::MAP_RENAME,
const MAP_NORESERVE = libc::MAP_NORESERVE,
const MAP_HASSEMAPHORE = libc::MAP_HASSEMAPHORE,
- #[cfg(not(target_os = "openbsd"))]
+ #[cfg(not(any(target_os = "openbsd", target_os = "netbsd")))]
const MAP_STACK = libc::MAP_STACK,
#[cfg(target_os = "netbsd")]
const MAP_WIRED = libc::MAP_WIRED,
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index 82934164..793bc70e 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -31,6 +31,9 @@ pub mod stat;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod syscall;
+#[cfg(any(target_os = "linux"))]
+pub mod reboot;
+
#[cfg(not(target_os = "ios"))]
pub mod termios;
diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs
new file mode 100644
index 00000000..94f30f62
--- /dev/null
+++ b/src/sys/reboot.rs
@@ -0,0 +1,43 @@
+//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
+
+use {Errno, Error, Result};
+use libc;
+use void::Void;
+use std::mem::drop;
+
+/// How exactly should the system be rebooted.
+///
+/// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
+/// enabling/disabling Ctrl-Alt-Delete.
+#[repr(i32)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum RebootMode {
+ RB_HALT_SYSTEM = libc::RB_HALT_SYSTEM,
+ RB_KEXEC = libc::RB_KEXEC,
+ RB_POWER_OFF = libc::RB_POWER_OFF,
+ RB_AUTOBOOT = libc::RB_AUTOBOOT,
+ // we do not support Restart2,
+ RB_SW_SUSPEND = libc::RB_SW_SUSPEND,
+}
+
+pub fn reboot(how: RebootMode) -> Result<Void> {
+ unsafe {
+ libc::reboot(how as libc::c_int)
+ };
+ Err(Error::Sys(Errno::last()))
+}
+
+/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
+///
+/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
+pub fn set_cad_enabled(enable: bool) -> Result<()> {
+ let cmd = if enable {
+ libc::RB_ENABLE_CAD
+ } else {
+ libc::RB_DISABLE_CAD
+ };
+ let res = unsafe {
+ libc::reboot(cmd)
+ };
+ Errno::result(res).map(drop)
+}
diff --git a/src/sys/select.rs b/src/sys/select.rs
index 1b47d759..28b664aa 100644
--- a/src/sys/select.rs
+++ b/src/sys/select.rs
@@ -8,6 +8,7 @@ pub const FD_SETSIZE: RawFd = 1024;
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[repr(C)]
+#[derive(Clone)]
pub struct FdSet {
bits: [i32; FD_SETSIZE as usize / 32]
}
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index 753c1562..18827332 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -2,48 +2,166 @@
// See http://rust-lang.org/COPYRIGHT.
use libc;
-use {Errno, Result};
+use {Errno, Error, Result};
use std::mem;
use std::ptr;
-pub use libc::{
+// 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
+// this is not (yet) possible.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[repr(i32)]
+pub enum Signal {
+ SIGHUP = libc::SIGHUP,
+ SIGINT = libc::SIGINT,
+ SIGQUIT = libc::SIGQUIT,
+ SIGILL = libc::SIGILL,
+ SIGTRAP = libc::SIGTRAP,
+ SIGABRT = libc::SIGABRT,
+ SIGBUS = libc::SIGBUS,
+ SIGFPE = libc::SIGFPE,
+ SIGKILL = libc::SIGKILL,
+ SIGUSR1 = libc::SIGUSR1,
+ SIGSEGV = libc::SIGSEGV,
+ SIGUSR2 = libc::SIGUSR2,
+ SIGPIPE = libc::SIGPIPE,
+ SIGALRM = libc::SIGALRM,
+ SIGTERM = libc::SIGTERM,
+ #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
+ SIGSTKFLT = libc::SIGSTKFLT,
+ SIGCHLD = libc::SIGCHLD,
+ SIGCONT = libc::SIGCONT,
+ SIGSTOP = libc::SIGSTOP,
+ SIGTSTP = libc::SIGTSTP,
+ SIGTTIN = libc::SIGTTIN,
+ SIGTTOU = libc::SIGTTOU,
+ SIGURG = libc::SIGURG,
+ SIGXCPU = libc::SIGXCPU,
+ SIGXFSZ = libc::SIGXFSZ,
+ SIGVTALRM = libc::SIGVTALRM,
+ SIGPROF = libc::SIGPROF,
+ SIGWINCH = libc::SIGWINCH,
+ SIGIO = libc::SIGIO,
+ #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
+ SIGPWR = libc::SIGPWR,
+ SIGSYS = libc::SIGSYS,
+ #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
+ SIGEMT = libc::SIGEMT,
+ #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
+ SIGINFO = libc::SIGINFO,
+}
+
+pub use self::Signal::*;
+
+#[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))]
+const SIGNALS: [Signal; 31] = [
SIGHUP,
SIGINT,
SIGQUIT,
SIGILL,
+ SIGTRAP,
SIGABRT,
+ SIGBUS,
SIGFPE,
SIGKILL,
+ SIGUSR1,
SIGSEGV,
+ SIGUSR2,
SIGPIPE,
SIGALRM,
SIGTERM,
- SIGTRAP,
- SIGIOT,
- SIGBUS,
- SIGSYS,
- SIGURG,
+ SIGSTKFLT,
+ SIGCHLD,
+ SIGCONT,
SIGSTOP,
SIGTSTP,
- SIGCONT,
- SIGCHLD,
SIGTTIN,
SIGTTOU,
- SIGIO,
+ SIGURG,
SIGXCPU,
SIGXFSZ,
SIGVTALRM,
SIGPROF,
SIGWINCH,
+ SIGIO,
+ SIGPWR,
+ SIGSYS];
+#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
+const SIGNALS: [Signal; 31] = [
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGABRT,
+ SIGBUS,
+ SIGFPE,
+ SIGKILL,
SIGUSR1,
+ SIGSEGV,
SIGUSR2,
-};
-
-// This doesn't always exist, but when it does, it's 7
-pub const SIGEMT: libc::c_int = 7;
+ SIGPIPE,
+ SIGALRM,
+ SIGTERM,
+ SIGCHLD,
+ SIGCONT,
+ SIGSTOP,
+ SIGTSTP,
+ SIGTTIN,
+ SIGTTOU,
+ SIGURG,
+ SIGXCPU,
+ SIGXFSZ,
+ SIGVTALRM,
+ SIGPROF,
+ SIGWINCH,
+ SIGIO,
+ SIGSYS,
+ SIGEMT,
+ SIGINFO];
pub const NSIG: libc::c_int = 32;
+pub struct SignalIterator {
+ next: usize,
+}
+
+impl Iterator for SignalIterator {
+ type Item = Signal;
+
+ fn next(&mut self) -> Option<Signal> {
+ if self.next < SIGNALS.len() {
+ let next_signal = SIGNALS[self.next];
+ self.next += 1;
+ Some(next_signal)
+ } else {
+ None
+ }
+ }
+}
+
+impl Signal {
+ pub fn iterator() -> SignalIterator {
+ SignalIterator{next: 0}
+ }
+
+ // We do not implement the From trait, because it is supposed to be infallible.
+ // With Rust RFC 1542 comes the appropriate trait TryFrom. Once it is
+ // implemented, we'll replace this function.
+ #[inline]
+ pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
+ match 0 < signum && signum < NSIG {
+ true => Ok(unsafe { mem::transmute(signum) }),
+ false => Err(Error::invalid_argument()),
+ }
+ }
+}
+
+pub const SIGIOT : Signal = SIGABRT;
+pub const SIGPOLL : Signal = SIGIO;
+pub const SIGUNUSED : Signal = SIGSYS;
+
bitflags!{
flags SaFlags: libc::c_int {
const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
@@ -69,7 +187,6 @@ pub struct SigSet {
sigset: libc::sigset_t
}
-pub type SigNum = libc::c_int;
impl SigSet {
pub fn all() -> SigSet {
@@ -86,40 +203,33 @@ impl SigSet {
SigSet { sigset: sigset }
}
- pub fn add(&mut self, signum: SigNum) -> Result<()> {
- let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };
-
- Errno::result(res).map(drop)
+ pub fn add(&mut self, signal: Signal) {
+ unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
- pub fn clear(&mut self) -> Result<()> {
- let res = unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
-
- Errno::result(res).map(drop)
+ pub fn clear(&mut self) {
+ unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
}
- pub fn remove(&mut self, signum: SigNum) -> Result<()> {
- let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };
-
- Errno::result(res).map(drop)
+ pub fn remove(&mut self, signal: Signal) {
+ unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
- pub fn extend(&mut self, other: &SigSet) -> Result<()> {
- for i in 1..NSIG {
- if try!(other.contains(i)) {
- try!(self.add(i));
- }
+ pub fn contains(&self, signal: Signal) -> bool {
+ let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
+
+ match res {
+ 1 => true,
+ 0 => false,
+ _ => unreachable!("unexpected value from sigismember"),
}
- Ok(())
}
- pub fn contains(&self, signum: SigNum) -> Result<bool> {
- let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };
-
- match try!(Errno::result(res)) {
- 1 => Ok(true),
- 0 => Ok(false),
- _ => unreachable!("unexpected value from sigismember"),
+ pub fn extend(&mut self, other: &SigSet) {
+ for signal in Signal::iterator() {
+ if other.contains(signal) {
+ self.add(signal);
+ }
}
}
@@ -154,11 +264,11 @@ impl SigSet {
/// Suspends execution of the calling thread until one of the signals in the
/// signal mask becomes pending, and returns the accepted signal.
- pub fn wait(&self) -> Result<SigNum> {
- let mut signum: SigNum = unsafe { mem::uninitialized() };
+ pub fn wait(&self) -> Result<Signal> {
+ let mut signum: libc::c_int = unsafe { mem::uninitialized() };
let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
- Errno::result(res).map(|_| signum)
+ Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
}
}
@@ -174,8 +284,8 @@ impl AsRef<libc::sigset_t> for SigSet {
pub enum SigHandler {
SigDfl,
SigIgn,
- Handler(extern fn(SigNum)),
- SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
+ Handler(extern fn(libc::c_int)),
+ SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
}
pub struct SigAction {
@@ -203,11 +313,11 @@ impl SigAction {
}
}
-pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
+pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
let mut oldact = mem::uninitialized::<libc::sigaction>();
let res =
- libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
+ libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
Errno::result(res).map(|_| SigAction { sigaction: oldact })
}
@@ -246,14 +356,14 @@ pub fn pthread_sigmask(how: SigFlags,
Errno::result(res).map(drop)
}
-pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
- let res = unsafe { libc::kill(pid, signum) };
+pub fn kill(pid: libc::pid_t, signal: Signal) -> Result<()> {
+ let res = unsafe { libc::kill(pid, signal as libc::c_int) };
Errno::result(res).map(drop)
}
-pub fn raise(signum: SigNum) -> Result<()> {
- let res = unsafe { libc::raise(signum) };
+pub fn raise(signal: Signal) -> Result<()> {
+ let res = unsafe { libc::raise(signal as libc::c_int) };
Errno::result(res).map(drop)
}
@@ -265,42 +375,42 @@ mod tests {
#[test]
fn test_contains() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
+ mask.add(SIGUSR1);
- assert_eq!(mask.contains(SIGUSR1), Ok(true));
- assert_eq!(mask.contains(SIGUSR2), Ok(false));
+ assert!(mask.contains(SIGUSR1));
+ assert!(!mask.contains(SIGUSR2));
let all = SigSet::all();
- assert_eq!(all.contains(SIGUSR1), Ok(true));
- assert_eq!(all.contains(SIGUSR2), Ok(true));
+ assert!(all.contains(SIGUSR1));
+ assert!(all.contains(SIGUSR2));
}
#[test]
fn test_clear() {
let mut set = SigSet::all();
- set.clear().unwrap();
- for i in 1..NSIG {
- assert_eq!(set.contains(i), Ok(false));
+ set.clear();
+ for signal in Signal::iterator() {
+ assert!(!set.contains(signal));
}
}
#[test]
fn test_extend() {
let mut one_signal = SigSet::empty();
- one_signal.add(SIGUSR1).unwrap();
+ one_signal.add(SIGUSR1);
let mut two_signals = SigSet::empty();
- two_signals.add(SIGUSR2).unwrap();
- two_signals.extend(&one_signal).unwrap();
+ two_signals.add(SIGUSR2);
+ two_signals.extend(&one_signal);
- assert_eq!(two_signals.contains(SIGUSR1), Ok(true));
- assert_eq!(two_signals.contains(SIGUSR2), Ok(true));
+ assert!(two_signals.contains(SIGUSR1));
+ assert!(two_signals.contains(SIGUSR2));
}
#[test]
fn test_thread_signal_block() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
+ mask.add(SIGUSR1);
assert!(mask.thread_block().is_ok());
}
@@ -308,18 +418,18 @@ mod tests {
#[test]
fn test_thread_signal_swap() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
+ mask.add(SIGUSR1);
mask.thread_block().unwrap();
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
let mask2 = SigSet::empty();
- mask.add(SIGUSR2).unwrap();
+ mask.add(SIGUSR2);
let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();
- assert!(oldmask.contains(SIGUSR1).unwrap());
- assert!(!oldmask.contains(SIGUSR2).unwrap());
+ assert!(oldmask.contains(SIGUSR1));
+ assert!(!oldmask.contains(SIGUSR2));
}
// TODO(#251): Re-enable after figuring out flakiness.
@@ -327,8 +437,8 @@ mod tests {
#[test]
fn test_sigwait() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
- mask.add(SIGUSR2).unwrap();
+ mask.add(SIGUSR1);
+ mask.add(SIGUSR2);
mask.thread_block().unwrap();
raise(SIGUSR1).unwrap();
diff --git a/src/sys/socket/consts.rs b/src/sys/socket/consts.rs
index ddd8f6a9..63eaf28a 100644
--- a/src/sys/socket/consts.rs
+++ b/src/sys/socket/consts.rs
@@ -59,6 +59,8 @@ mod os {
pub const SO_TIMESTAMP: c_int = 29;
pub const SO_TYPE: c_int = 3;
pub const SO_BUSY_POLL: c_int = 46;
+ #[cfg(target_os = "linux")]
+ pub const SO_ORIGINAL_DST: c_int = 80;
// Socket options for TCP sockets
pub const TCP_NODELAY: c_int = 1;
@@ -96,6 +98,7 @@ mod os {
const MSG_DONTWAIT = 0x0040,
const MSG_EOR = 0x0080,
const MSG_ERRQUEUE = 0x2000,
+ const MSG_CMSG_CLOEXEC = 0x40000000,
}
}
diff --git a/src/sys/socket/ffi.rs b/src/sys/socket/ffi.rs
index 1cbf766c..55a47eb6 100644
--- a/src/sys/socket/ffi.rs
+++ b/src/sys/socket/ffi.rs
@@ -4,8 +4,11 @@
pub use libc::{socket, listen, bind, accept, connect, setsockopt, sendto, recvfrom, getsockname, getpeername, recv, send};
use libc::{c_int, c_void, socklen_t, size_t, ssize_t};
-use sys::uio::IoVec;
+#[cfg(target_os = "macos")]
+use libc::c_uint;
+
+use sys::uio::IoVec;
#[cfg(target_os = "linux")]
pub type type_of_cmsg_len = size_t;
@@ -13,6 +16,13 @@ pub type type_of_cmsg_len = size_t;
#[cfg(not(target_os = "linux"))]
pub type type_of_cmsg_len = socklen_t;
+// OSX always aligns struct cmsghdr as if it were a 32-bit OS
+#[cfg(target_os = "macos")]
+pub type type_of_cmsg_data = c_uint;
+
+#[cfg(not(target_os = "macos"))]
+pub type type_of_cmsg_data = size_t;
+
// Private because we don't expose any external functions that operate
// directly on this type; we just use it internally at FFI boundaries.
// Note that in some cases we store pointers in *const fields that the
@@ -37,7 +47,7 @@ pub struct cmsghdr {
pub cmsg_len: type_of_cmsg_len,
pub cmsg_level: c_int,
pub cmsg_type: c_int,
- pub cmsg_data: [type_of_cmsg_len; 0]
+ pub cmsg_data: [type_of_cmsg_data; 0]
}
extern {
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs
index c96a5c8d..69f26aa0 100644
--- a/src/sys/socket/mod.rs
+++ b/src/sys/socket/mod.rs
@@ -94,7 +94,7 @@ unsafe fn copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8]) {
}
-use self::ffi::{cmsghdr, msghdr, type_of_cmsg_len};
+use self::ffi::{cmsghdr, msghdr, type_of_cmsg_len, type_of_cmsg_data};
/// A structure used to make room in a cmsghdr passed to recvmsg. The
/// size and alignment match that of a cmsghdr followed by a T, but the
@@ -169,8 +169,7 @@ impl<'a> Iterator for CmsgIterator<'a> {
(SOL_SOCKET, SCM_RIGHTS) => unsafe {
Some(ControlMessage::ScmRights(
slice::from_raw_parts(
- &cmsg.cmsg_data as *const _ as *const _,
- len / mem::size_of::<RawFd>())))
+ &cmsg.cmsg_data as *const _ as *const _, 1)))
},
(_, _) => unsafe {
Some(ControlMessage::Unknown(UnknownCmsg(
@@ -201,12 +200,8 @@ pub enum ControlMessage<'a> {
pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);
fn cmsg_align(len: usize) -> usize {
- let round_to = mem::size_of::<type_of_cmsg_len>();
- if len % round_to == 0 {
- len
- } else {
- len + round_to - (len % round_to)
- }
+ let align_bytes = mem::size_of::<type_of_cmsg_data>() - 1;
+ (len + align_bytes) & !align_bytes
}
impl<'a> ControlMessage<'a> {
@@ -217,7 +212,7 @@ impl<'a> ControlMessage<'a> {
/// The value of CMSG_LEN on this message.
fn len(&self) -> usize {
- mem::size_of::<cmsghdr>() + match *self {
+ cmsg_align(mem::size_of::<cmsghdr>()) + match *self {
ControlMessage::ScmRights(fds) => {
mem::size_of_val(fds)
},
@@ -240,7 +235,11 @@ impl<'a> ControlMessage<'a> {
cmsg_data: [],
};
copy_bytes(&cmsg, buf);
- copy_bytes(fds, buf);
+
+ let padlen = cmsg_align(mem::size_of_val(&cmsg)) -
+ mem::size_of_val(&cmsg);
+ let buf2 = &mut &mut buf[padlen..];
+ copy_bytes(fds, buf2);
},
ControlMessage::Unknown(UnknownCmsg(orig_cmsg, bytes)) => {
copy_bytes(orig_cmsg, buf);
@@ -267,10 +266,10 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
// multiple of size_t. Note also that the resulting vector claims
// to have length == capacity, so it's presently uninitialized.
let mut cmsg_buffer = unsafe {
- let mut vec = Vec::<size_t>::with_capacity(capacity / mem::size_of::<size_t>());
+ let mut vec = Vec::<u8>::with_capacity(len);
let ptr = vec.as_mut_ptr();
mem::forget(vec);
- Vec::<u8>::from_raw_parts(ptr as *mut _, capacity, capacity)
+ Vec::<u8>::from_raw_parts(ptr as *mut _, len, len)
};
{
let mut ptr = &mut cmsg_buffer[..];
@@ -290,7 +289,7 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
msg_iov: iov.as_ptr(),
msg_iovlen: iov.len() as size_t,
msg_control: cmsg_buffer.as_ptr() as *const c_void,
- msg_controllen: len as size_t,
+ msg_controllen: capacity as size_t,
msg_flags: 0,
};
let ret = unsafe { ffi::sendmsg(fd, &mhdr, flags.bits()) };
@@ -630,6 +629,11 @@ pub unsafe fn sockaddr_storage_to_addr(
consts::AF_UNIX => {
Ok(SockAddr::Unix(UnixAddr(*(addr as *const _ as *const sockaddr_un), len)))
}
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ consts::AF_NETLINK => {
+ use libc::sockaddr_nl;
+ Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
+ }
af => panic!("unexpected address family {}", af),
}
}
diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs
index 17de2d27..bf17347c 100644
--- a/src/sys/socket/sockopt.rs
+++ b/src/sys/socket/sockopt.rs
@@ -2,6 +2,8 @@ use super::{ffi, consts, GetSockOpt, SetSockOpt};
use {Errno, Result};
use sys::time::TimeVal;
use libc::{c_int, uint8_t, c_void, socklen_t};
+#[cfg(target_os = "linux")]
+use libc::sockaddr_in;
use std::mem;
use std::os::unix::io::RawFd;
@@ -47,10 +49,6 @@ macro_rules! getsockopt_impl {
// Helper to generate the sockopt accessors
macro_rules! sockopt_impl {
- (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
- sockopt_impl!(GetOnly, $name, $level, $flag, $ty, GetStruct<$ty>);
- };
-
(GetOnly, $name:ident, $level:path, $flag:path, bool) => {
sockopt_impl!(GetOnly, $name, $level, $flag, bool, GetBool);
};
@@ -63,17 +61,6 @@ macro_rules! sockopt_impl {
sockopt_impl!(GetOnly, $name, $level, $flag, usize, GetUsize);
};
- (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
- #[derive(Copy, Clone, Debug)]
- pub struct $name;
-
- getsockopt_impl!($name, $level, $flag, $ty, $getter);
- };
-
- (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
- sockopt_impl!(SetOnly, $name, $level, $flag, $ty, SetStruct<$ty>);
- };
-
(SetOnly, $name:ident, $level:path, $flag:path, bool) => {
sockopt_impl!(SetOnly, $name, $level, $flag, bool, SetBool);
};
@@ -86,31 +73,50 @@ macro_rules! sockopt_impl {
sockopt_impl!(SetOnly, $name, $level, $flag, usize, SetUsize);
};
- (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
- #[derive(Copy, Clone, Debug)]
- pub struct $name;
+ (Both, $name:ident, $level:path, $flag:path, bool) => {
+ sockopt_impl!(Both, $name, $level, $flag, bool, GetBool, SetBool);
+ };
- setsockopt_impl!($name, $level, $flag, $ty, $setter);
+ (Both, $name:ident, $level:path, $flag:path, u8) => {
+ sockopt_impl!(Both, $name, $level, $flag, u8, GetU8, SetU8);
};
- (Both, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty, $setter:ty) => {
+ (Both, $name:ident, $level:path, $flag:path, usize) => {
+ sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize);
+ };
+
+ /*
+ * Matchers with generic getter types must be placed at the end, so
+ * they'll only match _after_ specialized matchers fail
+ */
+ (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
+ sockopt_impl!(GetOnly, $name, $level, $flag, $ty, GetStruct<$ty>);
+ };
+
+ (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
#[derive(Copy, Clone, Debug)]
pub struct $name;
- setsockopt_impl!($name, $level, $flag, $ty, $setter);
getsockopt_impl!($name, $level, $flag, $ty, $getter);
};
- (Both, $name:ident, $level:path, $flag:path, bool) => {
- sockopt_impl!(Both, $name, $level, $flag, bool, GetBool, SetBool);
+ (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
+ sockopt_impl!(SetOnly, $name, $level, $flag, $ty, SetStruct<$ty>);
};
- (Both, $name:ident, $level:path, $flag:path, u8) => {
- sockopt_impl!(Both, $name, $level, $flag, u8, GetU8, SetU8);
+ (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
+ #[derive(Copy, Clone, Debug)]
+ pub struct $name;
+
+ setsockopt_impl!($name, $level, $flag, $ty, $setter);
};
- (Both, $name:ident, $level:path, $flag:path, usize) => {
- sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize);
+ (Both, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty, $setter:ty) => {
+ #[derive(Copy, Clone, Debug)]
+ pub struct $name;
+
+ setsockopt_impl!($name, $level, $flag, $ty, $setter);
+ getsockopt_impl!($name, $level, $flag, $ty, $getter);
};
(Both, $name:ident, $level:path, $flag:path, $ty:ty) => {
@@ -168,6 +174,8 @@ sockopt_impl!(GetOnly, SockType, consts::SOL_SOCKET, consts::SO_TYPE, super::Soc
target_os = "linux",
target_os = "nacl"))]
sockopt_impl!(GetOnly, AcceptConn, consts::SOL_SOCKET, consts::SO_ACCEPTCONN, bool);
+#[cfg(target_os = "linux")]
+sockopt_impl!(GetOnly, OriginalDst, consts::SOL_IP, consts::SO_ORIGINAL_DST, sockaddr_in);
/*
*
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index 3d9b3a50..259efb70 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -1,7 +1,7 @@
-use libc::{pid_t, c_int};
+use libc::{self, pid_t, c_int};
use {Errno, Result};
-use sys::signal;
+use sys::signal::Signal;
mod ffi {
use libc::{pid_t, c_int};
@@ -15,7 +15,8 @@ mod ffi {
target_os = "android")))]
bitflags!(
flags WaitPidFlag: c_int {
- const WNOHANG = 0x00000001,
+ const WNOHANG = libc::WNOHANG,
+ const WUNTRACED = libc::WUNTRACED,
}
);
@@ -23,14 +24,14 @@ bitflags!(
target_os = "android"))]
bitflags!(
flags WaitPidFlag: c_int {
- const WNOHANG = 0x00000001,
- const WUNTRACED = 0x00000002,
- const WEXITED = 0x00000004,
- const WCONTINUED = 0x00000008,
- const WNOWAIT = 0x01000000, // Don't reap, just poll status.
- const __WNOTHREAD = 0x20000000, // Don't wait on children of other threads in this group
- const __WALL = 0x40000000, // Wait on all children, regardless of type
- // const __WCLONE = 0x80000000,
+ const WNOHANG = libc::WNOHANG,
+ const WUNTRACED = libc::WUNTRACED,
+ const WEXITED = libc::WEXITED,
+ const WCONTINUED = libc::WCONTINUED,
+ const WNOWAIT = libc::WNOWAIT, // Don't reap, just poll status.
+ const __WNOTHREAD = libc::__WNOTHREAD, // Don't wait on children of other threads in this group
+ const __WALL = libc::__WALL, // Wait on all children, regardless of type
+ const __WCLONE = libc::__WCLONE,
}
);
@@ -41,8 +42,8 @@ const WSTOPPED: WaitPidFlag = WUNTRACED;
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum WaitStatus {
Exited(pid_t, i8),
- Signaled(pid_t, signal::SigNum, bool),
- Stopped(pid_t, signal::SigNum),
+ Signaled(pid_t, Signal, bool),
+ Stopped(pid_t, Signal),
Continued(pid_t),
StillAlive
}
@@ -50,7 +51,7 @@ pub enum WaitStatus {
#[cfg(any(target_os = "linux",
target_os = "android"))]
mod status {
- use sys::signal;
+ use sys::signal::Signal;
pub fn exited(status: i32) -> bool {
(status & 0x7F) == 0
@@ -64,8 +65,8 @@ mod status {
((((status & 0x7f) + 1) as i8) >> 1) > 0
}
- pub fn term_signal(status: i32) -> signal::SigNum {
- (status & 0x7f) as signal::SigNum
+ pub fn term_signal(status: i32) -> Signal {
+ Signal::from_c_int(status & 0x7f).unwrap()
}
pub fn dumped_core(status: i32) -> bool {
@@ -76,8 +77,8 @@ mod status {
(status & 0xff) == 0x7f
}
- pub fn stop_signal(status: i32) -> signal::SigNum {
- ((status & 0xFF00) >> 8) as signal::SigNum
+ pub fn stop_signal(status: i32) -> Signal {
+ Signal::from_c_int((status & 0xFF00) >> 8).unwrap()
}
pub fn continued(status: i32) -> bool {
@@ -88,7 +89,7 @@ mod status {
#[cfg(any(target_os = "macos",
target_os = "ios"))]
mod status {
- use sys::signal;
+ use sys::signal::{Signal,SIGCONT};
const WCOREFLAG: i32 = 0x80;
const WSTOPPED: i32 = 0x7f;
@@ -101,16 +102,16 @@ mod status {
((status >> 8) & 0xFF) as i8
}
- pub fn stop_signal(status: i32) -> signal::SigNum {
- (status >> 8) as signal::SigNum
+ pub fn stop_signal(status: i32) -> Signal {
+ Signal::from_c_int(status >> 8).unwrap()
}
pub fn continued(status: i32) -> bool {
- wstatus(status) == WSTOPPED && stop_signal(status) == 0x13
+ wstatus(status) == WSTOPPED && stop_signal(status) == SIGCONT
}
pub fn stopped(status: i32) -> bool {
- wstatus(status) == WSTOPPED && stop_signal(status) != 0x13
+ wstatus(status) == WSTOPPED && stop_signal(status) != SIGCONT
}
pub fn exited(status: i32) -> bool {
@@ -121,8 +122,8 @@ mod status {
wstatus(status) != WSTOPPED && wstatus(status) != 0
}
- pub fn term_signal(status: i32) -> signal::SigNum {
- wstatus(status) as signal::SigNum
+ pub fn term_signal(status: i32) -> Signal {
+ Signal::from_c_int(wstatus(status)).unwrap()
}
pub fn dumped_core(status: i32) -> bool {
@@ -135,7 +136,7 @@ mod status {
target_os = "dragonfly",
target_os = "netbsd"))]
mod status {
- use sys::signal;
+ use sys::signal::Signal;
const WCOREFLAG: i32 = 0x80;
const WSTOPPED: i32 = 0x7f;
@@ -148,16 +149,16 @@ mod status {
wstatus(status) == WSTOPPED
}
- pub fn stop_signal(status: i32) -> signal::SigNum {
- (status >> 8) as signal::SigNum
+ pub fn stop_signal(status: i32) -> Signal {
+ Signal::from_c_int(status >> 8).unwrap()
}
pub fn signaled(status: i32) -> bool {
wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
}
- pub fn term_signal(status: i32) -> signal::SigNum {
- wstatus(status) as signal::SigNum
+ pub fn term_signal(status: i32) -> Signal {
+ Signal::from_c_int(wstatus(status)).unwrap()
}
pub fn exited(status: i32) -> bool {