Skip to content

Commit

Permalink
Auto merge of #397 - fiveop:asomers_master, r=@posborne
Browse files Browse the repository at this point in the history
Fix nix on FreeBSD (rebased on master)
  • Loading branch information
homu committed Aug 11, 2016
2 parents 437c8f2 + 077d979 commit 1ae7f8e
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 44 deletions.
14 changes: 12 additions & 2 deletions src/sys/socket/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,25 @@
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;

#[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
Expand All @@ -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 {
Expand Down
27 changes: 13 additions & 14 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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> {
Expand All @@ -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)
},
Expand All @@ -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);
Expand All @@ -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[..];
Expand All @@ -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()) };
Expand Down
58 changes: 31 additions & 27 deletions src/sys/socket/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand All @@ -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);
};
Expand All @@ -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) => {
Expand Down
5 changes: 4 additions & 1 deletion src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
pub fn sethostname(name: &[u8]) -> Result<()> {
// Handle some differences in type of the len arg across platforms.
cfg_if! {
if #[cfg(any(target_os = "macos", target_os = "ios"))] {
if #[cfg(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "macos", ))] {
type sethostname_len_t = c_int;
} else {
type sethostname_len_t = size_t;
Expand Down

0 comments on commit 1ae7f8e

Please sign in to comment.