From 2b7f92a43a7b30e2e2b8f9023e75f1a5d971992a Mon Sep 17 00:00:00 2001 From: James Peach Date: Sun, 1 May 2016 17:56:48 -0700 Subject: Support sockaddr_nl in sockaddr_storage_to_addr(). Add support for converting AF_NETLINK sockaddr_nl addresses to Sockaddr::Netlink(). This lets socket::recvmsg() work on netlink sockets. --- src/sys/socket/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/sys') diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index c96a5c8d..0846eaf5 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -630,6 +630,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), } } -- cgit v1.2.3 From 39545809e40f335d3d79e8832a6d255d8d27b45f Mon Sep 17 00:00:00 2001 From: Justin Latimer Date: Fri, 29 Apr 2016 03:54:50 +0000 Subject: Add SO_ORIGINAL_DST --- src/sys/socket/consts.rs | 2 ++ src/sys/socket/sockopt.rs | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'src/sys') diff --git a/src/sys/socket/consts.rs b/src/sys/socket/consts.rs index ddd8f6a9..aeeea5c3 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; diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 17de2d27..8f30d628 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; @@ -168,6 +170,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); /* * -- cgit v1.2.3 From c1334f5068b9c404be64325bbf90c0b7ff4c00d0 Mon Sep 17 00:00:00 2001 From: Philipp Matthias Schaefer Date: Mon, 25 Apr 2016 13:07:13 +0200 Subject: Add missing signals. --- src/sys/signal.rs | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'src/sys') diff --git a/src/sys/signal.rs b/src/sys/signal.rs index 753c1562..a881a51e 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -11,36 +11,47 @@ pub use libc::{ SIGINT, SIGQUIT, SIGILL, + SIGTRAP, SIGABRT, + SIGBUS, SIGFPE, SIGKILL, + SIGUSR1, SIGSEGV, + SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, - SIGTRAP, - SIGIOT, - SIGBUS, - SIGSYS, - SIGURG, + SIGCHLD, + SIGCONT, SIGSTOP, SIGTSTP, - SIGCONT, - SIGCHLD, SIGTTIN, SIGTTOU, - SIGIO, + SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, - SIGUSR1, - SIGUSR2, + SIGIO, + SIGSYS, }; -// This doesn't always exist, but when it does, it's 7 -pub const SIGEMT: libc::c_int = 7; +#[cfg(target_os = "macos")] +pub use libc::{ + SIGEMT, + SIGINFO, +}; + +#[cfg(not(target_os = "macos"))] +pub use libc::{ + SIGPWR, + SIGSTKFLT, + SIGIOT, // Alias for SIGABRT + SIGPOLL, // Alias for SIGIO + SIGUNUSED, // Alias for 31 +}; pub const NSIG: libc::c_int = 32; -- cgit v1.2.3 From a355db493aace202aff68c189a10d27e00d96d38 Mon Sep 17 00:00:00 2001 From: Nik Klassen Date: Fri, 10 Jun 2016 14:23:46 -0400 Subject: Add missing wait flag WUNTRACED for non-Linux systems --- src/sys/wait.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/sys') diff --git a/src/sys/wait.rs b/src/sys/wait.rs index 3d9b3a50..f09eb0e3 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -16,6 +16,7 @@ mod ffi { bitflags!( flags WaitPidFlag: c_int { const WNOHANG = 0x00000001, + const WUNTRACED = 0x00000002, } ); -- cgit v1.2.3 From 5c7b3c14953881eec113513e1a4881daf960a98c Mon Sep 17 00:00:00 2001 From: Philipp Matthias Schaefer Date: Mon, 25 Apr 2016 13:03:05 +0200 Subject: Convert signal constants to enumeration. --- src/sys/signal.rs | 249 ++++++++++++++++++++++++++++++++++++++---------------- src/sys/wait.rs | 40 ++++----- 2 files changed, 194 insertions(+), 95 deletions(-) (limited to 'src/sys') diff --git a/src/sys/signal.rs b/src/sys/signal.rs index a881a51e..2214d4b9 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -2,11 +2,60 @@ // 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(not(target_os = "macos"))] + 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(not(target_os = "macos"))] + SIGPWR = libc::SIGPWR, + SIGSYS = libc::SIGSYS, + #[cfg(target_os = "macos")] + SIGEMT = libc::SIGEMT, + #[cfg(target_os = "macos")] + SIGINFO = libc::SIGINFO, +} + +pub use self::Signal::*; + +#[cfg(not(target_os = "macos"))] +const SIGNALS: [Signal; 31] = [ SIGHUP, SIGINT, SIGQUIT, @@ -22,6 +71,7 @@ pub use libc::{ SIGPIPE, SIGALRM, SIGTERM, + SIGSTKFLT, SIGCHLD, SIGCONT, SIGSTOP, @@ -35,26 +85,83 @@ pub use libc::{ SIGPROF, SIGWINCH, SIGIO, - SIGSYS, -}; - + SIGPWR, + SIGSYS]; #[cfg(target_os = "macos")] -pub use libc::{ +const SIGNALS: [Signal; 31] = [ + SIGHUP, + SIGINT, + SIGQUIT, + SIGILL, + SIGTRAP, + SIGABRT, + SIGBUS, + SIGFPE, + SIGKILL, + SIGUSR1, + SIGSEGV, + SIGUSR2, + SIGPIPE, + SIGALRM, + SIGTERM, + SIGCHLD, + SIGCONT, + SIGSTOP, + SIGTSTP, + SIGTTIN, + SIGTTOU, + SIGURG, + SIGXCPU, + SIGXFSZ, + SIGVTALRM, + SIGPROF, + SIGWINCH, + SIGIO, + SIGSYS, SIGEMT, - SIGINFO, -}; - -#[cfg(not(target_os = "macos"))] -pub use libc::{ - SIGPWR, - SIGSTKFLT, - SIGIOT, // Alias for SIGABRT - SIGPOLL, // Alias for SIGIO - SIGUNUSED, // Alias for 31 -}; + 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 { + 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 { + 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, @@ -80,7 +187,6 @@ pub struct SigSet { sigset: libc::sigset_t } -pub type SigNum = libc::c_int; impl SigSet { pub fn all() -> SigSet { @@ -97,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 { - 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); + } } } @@ -165,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 { - let mut signum: SigNum = unsafe { mem::uninitialized() }; + pub fn wait(&self) -> Result { + 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()) } } @@ -185,8 +284,8 @@ impl AsRef 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 { @@ -214,11 +313,11 @@ impl SigAction { } } -pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result { +pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result { let mut oldact = mem::uninitialized::(); 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 }) } @@ -257,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) } @@ -276,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()); } @@ -319,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. @@ -338,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/wait.rs b/src/sys/wait.rs index 3d9b3a50..80a8acaa 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -1,7 +1,7 @@ use libc::{pid_t, c_int}; use {Errno, Result}; -use sys::signal; +use sys::signal::Signal; mod ffi { use libc::{pid_t, c_int}; @@ -41,8 +41,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 +50,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 +64,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 +76,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 +88,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 +101,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 +121,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 +135,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 +148,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 { -- cgit v1.2.3 From 8fb0c51e59d31429ffa871a28028876792cdd9c4 Mon Sep 17 00:00:00 2001 From: Nik Klassen Date: Wed, 22 Jun 2016 15:00:20 -0400 Subject: Replace wait constants with libc constants --- src/sys/wait.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/sys') diff --git a/src/sys/wait.rs b/src/sys/wait.rs index f09eb0e3..20247533 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -1,4 +1,4 @@ -use libc::{pid_t, c_int}; +use libc::{self, pid_t, c_int}; use {Errno, Result}; use sys::signal; @@ -15,8 +15,8 @@ mod ffi { target_os = "android")))] bitflags!( flags WaitPidFlag: c_int { - const WNOHANG = 0x00000001, - const WUNTRACED = 0x00000002, + const WNOHANG = libc::WNOHANG, + const WUNTRACED = libc::WUNTRACED, } ); @@ -24,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, } ); -- cgit v1.2.3 From c9d92f154278da7b1e39c44a4621f509a34b4f97 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 3 Jul 2016 15:32:28 +0100 Subject: eventfd: Follow nix conventions This commit revamps to eventfd to follow nix conventions: - drop in-crate FFI definitions - rename EventFdFlag to EfdFlags Additionally, it changes the initval argument to be a libc::c_uint, matching the actual type. --- src/sys/eventfd.rs | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'src/sys') 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 { - unsafe { - let res = ffi::eventfd(initval as libc::c_uint, flags.bits()); +pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result { + let res = unsafe { libc::eventfd(initval, flags.bits()) }; - Errno::result(res).map(|r| r as RawFd) - } + Errno::result(res).map(|r| r as RawFd) } -- cgit v1.2.3 From f3d7b013be7f5ae948045cdee6accd7a64e8ae4c Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 11 Jul 2016 19:01:15 +0300 Subject: Add the initial implementation of reboot() --- src/sys/mod.rs | 3 +++ src/sys/reboot.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/sys/reboot.rs (limited to 'src/sys') diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 82934164..b59ca9b1 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", target_os = "android"))] +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..d537401f --- /dev/null +++ b/src/sys/reboot.rs @@ -0,0 +1,36 @@ +use {Errno, Error, Result}; +use libc::c_int; +use void::Void; +use std::mem::drop; + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum RebootMode { + Halt = 0xcdef0123, + kexec = 0x45584543, + PowerOff = 0x4321fedc, + Restart = 0x1234567, + // we do not support Restart2, + Suspend = 0xd000fce1, +} + +pub fn reboot(how: RebootMode) -> Result { + unsafe { + ext::reboot(how as c_int) + }; + Err(Error::Sys(Errno::last())) +} + +#[allow(overflowing_literals)] +pub fn set_cad_enabled(enable: bool) -> Result<()> { + let res = unsafe { + ext::reboot(if enable { 0x89abcdef } else { 0 }) + }; + Errno::result(res).map(drop) +} + +mod ext { + use libc::c_int; + extern { + pub fn reboot(cmd: c_int) -> c_int; + } +} -- cgit v1.2.3 From 91b29abf648a53a16280c7c6d7547f30b8268a87 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 11 Jul 2016 20:37:23 +0300 Subject: Add some basic docs for reboot::set_cad_enabled() --- src/sys/reboot.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index d537401f..eedbf5ae 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -20,6 +20,10 @@ pub fn reboot(how: RebootMode) -> Result { 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. #[allow(overflowing_literals)] pub fn set_cad_enabled(enable: bool) -> Result<()> { let res = unsafe { -- cgit v1.2.3 From c63f89cb47405329260c36ec905e7cfa92d239a0 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Mon, 11 Jul 2016 21:28:06 +0300 Subject: Ignore the overflow for constants Force using the constants even on x86 where they do not fit into isize (c_int) --- src/sys/reboot.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index eedbf5ae..10abef91 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -3,6 +3,7 @@ use libc::c_int; use void::Void; use std::mem::drop; +#[allow(overflowing_literals)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum RebootMode { Halt = 0xcdef0123, -- cgit v1.2.3 From bf796cce6e73f6e5518c76e013ded7518ff14a61 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Wed, 13 Jul 2016 10:26:31 +0300 Subject: Stop targeting Android --- src/sys/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/sys') diff --git a/src/sys/mod.rs b/src/sys/mod.rs index b59ca9b1..793bc70e 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -31,7 +31,7 @@ pub mod stat; #[cfg(any(target_os = "linux", target_os = "android"))] pub mod syscall; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "linux"))] pub mod reboot; #[cfg(not(target_os = "ios"))] -- cgit v1.2.3 From b19afe56ab55cc2aa3d7e7937d33e4525d860e29 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Wed, 13 Jul 2016 10:38:59 +0300 Subject: Use libc's declarations --- src/sys/reboot.rs | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index 10abef91..82a31380 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -1,41 +1,37 @@ use {Errno, Error, Result}; -use libc::c_int; +use libc; use void::Void; use std::mem::drop; -#[allow(overflowing_literals)] +#[repr(i32)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum RebootMode { - Halt = 0xcdef0123, - kexec = 0x45584543, - PowerOff = 0x4321fedc, - Restart = 0x1234567, + Halt = libc::RB_HALT_SYSTEM, + kexec = libc::RB_KEXEC, + PowerOff = libc::RB_POWER_OFF, + Restart = libc::RB_AUTOBOOT, // we do not support Restart2, - Suspend = 0xd000fce1, + Suspend = libc::RB_SW_SUSPEND, } pub fn reboot(how: RebootMode) -> Result { unsafe { - ext::reboot(how as c_int) + 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. -#[allow(overflowing_literals)] pub fn set_cad_enabled(enable: bool) -> Result<()> { + let cmd = if enable { + libc::RB_ENABLE_CAD + } else { + libc::RB_DISABLE_CAD + }; let res = unsafe { - ext::reboot(if enable { 0x89abcdef } else { 0 }) + libc::reboot(cmd) }; Errno::result(res).map(drop) } - -mod ext { - use libc::c_int; - extern { - pub fn reboot(cmd: c_int) -> c_int; - } -} -- cgit v1.2.3 From 012c6623c9c50aca91b81e6d30800613f515f898 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Wed, 13 Jul 2016 21:06:39 +0300 Subject: Manually match on RebootMode::* --- src/sys/reboot.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index 82a31380..45f9ec98 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -3,20 +3,27 @@ use libc; use void::Void; use std::mem::drop; -#[repr(i32)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum RebootMode { - Halt = libc::RB_HALT_SYSTEM, - kexec = libc::RB_KEXEC, - PowerOff = libc::RB_POWER_OFF, - Restart = libc::RB_AUTOBOOT, + Halt, + kexec, + PowerOff, + Restart, // we do not support Restart2, - Suspend = libc::RB_SW_SUSPEND, + Suspend, } pub fn reboot(how: RebootMode) -> Result { + let cmd = match how { + RebootMode::Halt => libc::RB_HALT_SYSTEM, + RebootMode::kexec => libc::RB_KEXEC, + RebootMode::PowerOff => libc::RB_POWER_OFF, + RebootMode::Restart => libc::RB_AUTOBOOT, + // we do not support Restart2, + RebootMode::Suspend => libc::RB_SW_SUSPEND, + }; unsafe { - libc::reboot(how as libc::c_int) + libc::reboot(cmd) }; Err(Error::Sys(Errno::last())) } -- cgit v1.2.3 From cce6bce7fc85d8c44a101ae164a4604ab5adf6d4 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Thu, 14 Jul 2016 00:40:17 +0300 Subject: Switch Clone and Copy --- src/sys/reboot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index 45f9ec98..0f9d5e88 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -3,7 +3,7 @@ use libc; use void::Void; use std::mem::drop; -#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum RebootMode { Halt, kexec, -- cgit v1.2.3 From f682458c829e6d715cabd9e8ef6730ff05567966 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Thu, 14 Jul 2016 00:51:52 +0300 Subject: Add some documentation --- src/sys/reboot.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index 0f9d5e88..81502d01 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -1,8 +1,14 @@ +//! 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. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum RebootMode { Halt, -- cgit v1.2.3 From 8f6b162fb189d092afc7e6a6162e00d5d5332f4a Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Thu, 14 Jul 2016 14:54:21 +0300 Subject: Revert "Manually match on RebootMode::*" This reverts commit 012c6623c9c50aca91b81e6d30800613f515f898. --- src/sys/reboot.rs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index 81502d01..d593ee78 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -9,27 +9,20 @@ use std::mem::drop; /// /// 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 { - Halt, - kexec, - PowerOff, - Restart, + Halt = libc::RB_HALT_SYSTEM, + kexec = libc::RB_KEXEC, + PowerOff = libc::RB_POWER_OFF, + Restart = libc::RB_AUTOBOOT, // we do not support Restart2, - Suspend, + Suspend = libc::RB_SW_SUSPEND, } pub fn reboot(how: RebootMode) -> Result { - let cmd = match how { - RebootMode::Halt => libc::RB_HALT_SYSTEM, - RebootMode::kexec => libc::RB_KEXEC, - RebootMode::PowerOff => libc::RB_POWER_OFF, - RebootMode::Restart => libc::RB_AUTOBOOT, - // we do not support Restart2, - RebootMode::Suspend => libc::RB_SW_SUSPEND, - }; unsafe { - libc::reboot(cmd) + libc::reboot(how as libc::c_int) }; Err(Error::Sys(Errno::last())) } -- cgit v1.2.3 From 215f3872b1ead677e5f942f86e334db5f01a4eb3 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Thu, 14 Jul 2016 14:56:21 +0300 Subject: Name enum variants after the libc constants --- src/sys/reboot.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/sys') diff --git a/src/sys/reboot.rs b/src/sys/reboot.rs index d593ee78..94f30f62 100644 --- a/src/sys/reboot.rs +++ b/src/sys/reboot.rs @@ -12,12 +12,12 @@ use std::mem::drop; #[repr(i32)] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum RebootMode { - Halt = libc::RB_HALT_SYSTEM, - kexec = libc::RB_KEXEC, - PowerOff = libc::RB_POWER_OFF, - Restart = libc::RB_AUTOBOOT, + 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, - Suspend = libc::RB_SW_SUSPEND, + RB_SW_SUSPEND = libc::RB_SW_SUSPEND, } pub fn reboot(how: RebootMode) -> Result { -- cgit v1.2.3 From c4ae567db9be37fa572e9f90f2d8e1110565742a Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 18 Jul 2016 22:25:25 +0200 Subject: Fix NetBSD build --- src/sys/event.rs | 2 +- src/sys/mman.rs | 2 +- src/sys/signal.rs | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/sys') 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/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/signal.rs b/src/sys/signal.rs index 2214d4b9..18827332 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -28,7 +28,7 @@ pub enum Signal { SIGPIPE = libc::SIGPIPE, SIGALRM = libc::SIGALRM, SIGTERM = libc::SIGTERM, - #[cfg(not(target_os = "macos"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] SIGSTKFLT = libc::SIGSTKFLT, SIGCHLD = libc::SIGCHLD, SIGCONT = libc::SIGCONT, @@ -43,18 +43,18 @@ pub enum Signal { SIGPROF = libc::SIGPROF, SIGWINCH = libc::SIGWINCH, SIGIO = libc::SIGIO, - #[cfg(not(target_os = "macos"))] + #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] SIGPWR = libc::SIGPWR, SIGSYS = libc::SIGSYS, - #[cfg(target_os = "macos")] + #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))] SIGEMT = libc::SIGEMT, - #[cfg(target_os = "macos")] + #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))] SIGINFO = libc::SIGINFO, } pub use self::Signal::*; -#[cfg(not(target_os = "macos"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] const SIGNALS: [Signal; 31] = [ SIGHUP, SIGINT, @@ -87,7 +87,7 @@ const SIGNALS: [Signal; 31] = [ SIGIO, SIGPWR, SIGSYS]; -#[cfg(target_os = "macos")] +#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))] const SIGNALS: [Signal; 31] = [ SIGHUP, SIGINT, -- cgit v1.2.3 From 36789c78a726d9ccf2f3b2fa2eccdfb78b28c664 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Mon, 25 Jul 2016 02:42:07 +0000 Subject: Fix the sockopt_impl matcher rule order. Rules for generic types were located above rules for specific types, so the rules for specific types never got matched. This caused the sys::socket::sockopt::test::can_get_listen_on_tcp_socket test to fail on FreeBSD. The solution is to put all of the generic rules at the bottom. --- src/sys/socket/sockopt.rs | 58 +++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'src/sys') diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 8f30d628..bf17347c 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -49,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); }; @@ -65,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); }; @@ -88,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) => { -- cgit v1.2.3 From 077d979acb57ecbd1dbe4c1a4b7b1449aa5a14d2 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Wed, 3 Aug 2016 22:11:05 -0600 Subject: Fix nix on FreeBSD amd64 On Linux, the cmsg_len field of struct cmsghdr has type size_t, but it has size socklen_t on POSIX-compliant operating systems. So on POSIX-compliant 64-bit operating systems, struct cmsghdr has padding gaps that aren't present on Linux. Most of the issues fixed by this commit related to those gaps. src/sys/socket/ffi.rs Fix the type of the cmsg_data field so the struct layout will be correct. src/sys/socket/mod.rs In CmsgIterator.next, only return a single file descriptor. sendmsg(2) can only stuff a single file descriptor into each cmsg. In cmsg_align, fix the rounding calculation, and eliminate a division instruction. Add a missing cmsg_align call in ControlMessage.len In ControlMessage.encode_into, add any necessary padding bytes between the cmsghdr and the data. In sendmsg, fix some len<->capacity confusion. --- src/sys/socket/ffi.rs | 14 ++++++++++++-- src/sys/socket/mod.rs | 27 +++++++++++++-------------- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'src/sys') 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 0846eaf5..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::()))) + &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::(); - if len % round_to == 0 { - len - } else { - len + round_to - (len % round_to) - } + let align_bytes = mem::size_of::() - 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::() + match *self { + cmsg_align(mem::size_of::()) + 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::::with_capacity(capacity / mem::size_of::()); + let mut vec = Vec::::with_capacity(len); let ptr = vec.as_mut_ptr(); mem::forget(vec); - Vec::::from_raw_parts(ptr as *mut _, capacity, capacity) + Vec::::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()) }; -- cgit v1.2.3 From aa426634ad2a1c94df8367ce1a8a6ba7a1ac62b6 Mon Sep 17 00:00:00 2001 From: Murarth Date: Thu, 25 Aug 2016 14:10:59 -0700 Subject: Implement `Clone` for `FdSet` on Mac/iOS --- src/sys/select.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/sys') 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] } -- cgit v1.2.3 From 0f9cc0589c7b31d3e7dd789834d128b1e5508c53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 9 Sep 2016 18:11:01 +0300 Subject: Add MSG_CMSG_CLOEXEC to MsgFlags on Linux Fixes #421. --- src/sys/socket/consts.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/sys') diff --git a/src/sys/socket/consts.rs b/src/sys/socket/consts.rs index aeeea5c3..63eaf28a 100644 --- a/src/sys/socket/consts.rs +++ b/src/sys/socket/consts.rs @@ -98,6 +98,7 @@ mod os { const MSG_DONTWAIT = 0x0040, const MSG_EOR = 0x0080, const MSG_ERRQUEUE = 0x2000, + const MSG_CMSG_CLOEXEC = 0x40000000, } } -- cgit v1.2.3