Skip to content

Commit bc98b99

Browse files
committed
1 parent 17f87d4 commit bc98b99

File tree

5 files changed

+45
-21
lines changed

5 files changed

+45
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6666
([#623](https://github.com/nix-rust/nix/pull/623))
6767
- Multiple constants related to the termios API have now been properly defined for
6868
all supported platforms. ([#527](https://github.com/nix-rust/nix/pull/527))
69+
- Fixed field types of `sys::socket::ffi::{msghdr, cmsghdr}` on
70+
non-Linux platforms. ([#](https://...))
6971

7072
## [0.8.1] 2017-04-16
7173

nix-test/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ pub fn assert_size_of<T>(name: &str) {
3636
assert!(expect > 0, "undefined type {}", name);
3737

3838
if mem::size_of::<T>() != expect {
39-
panic!("incorrectly sized type; expect={}; actual={}",
40-
expect, mem::size_of::<T>());
39+
panic!("incorrectly sized type; type={} expect={}; actual={}",
40+
name, expect, mem::size_of::<T>());
4141
}
4242
}
4343
}

nix-test/src/sizes.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ size_of(const char* type) {
2424

2525
// sys/socket
2626
SIZE_OF_S(sockaddr_storage);
27+
SIZE_OF_S(msghdr);
28+
SIZE_OF_S(cmsghdr);
2729

2830
// sys/uio
2931
SIZE_OF_S(iovec);

src/sys/socket/ffi.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
pub use libc::{socket, listen, bind, accept, connect, setsockopt, sendto, recvfrom, getsockname, getpeername, recv, send};
55

6-
use libc::{c_int, c_void, socklen_t, size_t, ssize_t};
6+
use libc::{c_int, c_void, socklen_t, ssize_t};
7+
8+
#[cfg(not(target_os = "macos"))]
9+
use libc::size_t;
710

811
#[cfg(target_os = "macos")]
912
use libc::c_uint;
@@ -18,10 +21,22 @@ pub type type_of_cmsg_len = socklen_t;
1821

1922
// OSX always aligns struct cmsghdr as if it were a 32-bit OS
2023
#[cfg(target_os = "macos")]
21-
pub type type_of_cmsg_data = c_uint;
24+
pub type align_of_cmsg_data = c_uint;
2225

2326
#[cfg(not(target_os = "macos"))]
24-
pub type type_of_cmsg_data = size_t;
27+
pub type align_of_cmsg_data = size_t;
28+
29+
#[cfg(target_os = "linux")]
30+
pub type type_of_msgiov_len = size_t;
31+
32+
#[cfg(not(target_os = "linux"))]
33+
pub type type_of_msgiov_len = c_int;
34+
35+
#[cfg(target_os = "linux")]
36+
pub type type_of_msg_controllen = size_t;
37+
38+
#[cfg(not(target_os = "linux"))]
39+
pub type type_of_msg_controllen = socklen_t;
2540

2641
// Private because we don't expose any external functions that operate
2742
// directly on this type; we just use it internally at FFI boundaries.
@@ -33,9 +48,9 @@ pub struct msghdr<'a> {
3348
pub msg_name: *const c_void,
3449
pub msg_namelen: socklen_t,
3550
pub msg_iov: *const IoVec<&'a [u8]>,
36-
pub msg_iovlen: size_t,
51+
pub msg_iovlen: type_of_msgiov_len,
3752
pub msg_control: *const c_void,
38-
pub msg_controllen: size_t,
53+
pub msg_controllen: type_of_msg_controllen,
3954
pub msg_flags: c_int,
4055
}
4156

@@ -47,7 +62,6 @@ pub struct cmsghdr {
4762
pub cmsg_len: type_of_cmsg_len,
4863
pub cmsg_level: c_int,
4964
pub cmsg_type: c_int,
50-
pub cmsg_data: [type_of_cmsg_data; 0]
5165
}
5266

5367
extern {

src/sys/socket/mod.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ unsafe fn copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8]) {
8585
}
8686

8787

88-
use self::ffi::{cmsghdr, msghdr, type_of_cmsg_len, type_of_cmsg_data};
88+
use self::ffi::{cmsghdr, msghdr, type_of_cmsg_len, align_of_cmsg_data,
89+
type_of_msgiov_len, type_of_msg_controllen};
8990

9091
/// A structure used to make room in a cmsghdr passed to recvmsg. The
9192
/// size and alignment match that of a cmsghdr followed by a T, but the
@@ -95,8 +96,11 @@ use self::ffi::{cmsghdr, msghdr, type_of_cmsg_len, type_of_cmsg_data};
9596
/// To make room for multiple messages, nest the type parameter with
9697
/// tuples, e.g.
9798
/// `let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();`
99+
#[repr(C)]
98100
pub struct CmsgSpace<T> {
99101
_hdr: cmsghdr,
102+
#[cfg(not(target_os = "macos"))]
103+
_pad: [align_of_cmsg_data; 0],
100104
_data: T,
101105
}
102106

@@ -156,17 +160,18 @@ impl<'a> Iterator for CmsgIterator<'a> {
156160
}
157161
self.0 = &buf[cmsg_align(cmsg_len)..];
158162

163+
let cmsg_data = &buf[cmsg_align(sizeof_cmsghdr)..];
159164
match (cmsg.cmsg_level, cmsg.cmsg_type) {
160165
(SOL_SOCKET, SCM_RIGHTS) => unsafe {
161166
Some(ControlMessage::ScmRights(
162167
slice::from_raw_parts(
163-
&cmsg.cmsg_data as *const _ as *const _, 1)))
168+
cmsg_data.as_ptr() as *const _, 1)))
164169
},
165170
(_, _) => unsafe {
166171
Some(ControlMessage::Unknown(UnknownCmsg(
167172
&cmsg,
168173
slice::from_raw_parts(
169-
&cmsg.cmsg_data as *const _ as *const _,
174+
cmsg_data.as_ptr() as *const _,
170175
len))))
171176
}
172177
}
@@ -191,7 +196,7 @@ pub enum ControlMessage<'a> {
191196
pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);
192197

193198
fn cmsg_align(len: usize) -> usize {
194-
let align_bytes = mem::size_of::<type_of_cmsg_data>() - 1;
199+
let align_bytes = mem::size_of::<align_of_cmsg_data>() - 1;
195200
(len + align_bytes) & !align_bytes
196201
}
197202

@@ -213,8 +218,8 @@ impl<'a> ControlMessage<'a> {
213218
}
214219
}
215220

216-
// Unsafe: start and end of buffer must be size_t-aligned (that is,
217-
// cmsg_align'd). Updates the provided slice; panics if the buffer
221+
// Unsafe: start and end of buffer must be cmsg_align'd.
222+
// Updates the provided slice; panics if the buffer
218223
// is too small.
219224
unsafe fn encode_into<'b>(&self, buf: &mut &'b mut [u8]) {
220225
match *self {
@@ -223,7 +228,6 @@ impl<'a> ControlMessage<'a> {
223228
cmsg_len: self.len() as type_of_cmsg_len,
224229
cmsg_level: SOL_SOCKET,
225230
cmsg_type: SCM_RIGHTS,
226-
cmsg_data: [],
227231
};
228232
copy_bytes(&cmsg, buf);
229233

@@ -287,9 +291,9 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
287291
msg_name: name as *const c_void,
288292
msg_namelen: namelen,
289293
msg_iov: iov.as_ptr(),
290-
msg_iovlen: iov.len() as size_t,
294+
msg_iovlen: iov.len() as type_of_msgiov_len,
291295
msg_control: cmsg_ptr,
292-
msg_controllen: capacity as size_t,
296+
msg_controllen: capacity as type_of_msg_controllen,
293297
msg_flags: 0,
294298
};
295299
let ret = unsafe { ffi::sendmsg(fd, &mhdr, flags.bits()) };
@@ -310,9 +314,9 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
310314
msg_name: &mut address as *const _ as *const c_void,
311315
msg_namelen: mem::size_of::<sockaddr_storage>() as socklen_t,
312316
msg_iov: iov.as_ptr() as *const IoVec<&[u8]>, // safe cast to add const-ness
313-
msg_iovlen: iov.len() as size_t,
317+
msg_iovlen: iov.len() as type_of_msgiov_len,
314318
msg_control: msg_control as *const c_void,
315-
msg_controllen: msg_controllen as size_t,
319+
msg_controllen: msg_controllen as type_of_msg_controllen,
316320
msg_flags: 0,
317321
};
318322
let ret = unsafe { ffi::recvmsg(fd, &mut mhdr, flags.bits()) };
@@ -692,6 +696,8 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
692696

693697
#[test]
694698
pub fn test_struct_sizes() {
695-
use nixtest;
696-
nixtest::assert_size_of::<sockaddr_storage>("sockaddr_storage");
699+
use nixtest::assert_size_of;
700+
assert_size_of::<sockaddr_storage>("sockaddr_storage");
701+
assert_size_of::<msghdr>("msghdr");
702+
assert_size_of::<cmsghdr>("cmsghdr");
697703
}

0 commit comments

Comments
 (0)