Skip to content

Commit ed75b24

Browse files
committed
1 parent 64815c6 commit ed75b24

File tree

5 files changed

+44
-21
lines changed

5 files changed

+44
-21
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6262
only available on x86, x86-64, and ARM, and also not on Android.
6363
- Fixed `sys::socket::sendmsg` with zero entry `cmsgs` parameter.
6464
([#623](https://github.com/nix-rust/nix/pull/623))
65+
- Fixed field types of `sys::socket::ffi::{msghdr, cmsghdr}` on
66+
non-Linux platforms. ([#](https://...))
6567

6668
## [0.8.1] 2017-04-16
6769

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: 18 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
@@ -97,6 +98,8 @@ use self::ffi::{cmsghdr, msghdr, type_of_cmsg_len, type_of_cmsg_data};
9798
/// `let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();`
9899
pub struct CmsgSpace<T> {
99100
_hdr: cmsghdr,
101+
#[cfg(not(target_os = "macos"))]
102+
_pad: [align_of_cmsg_data; 0],
100103
_data: T,
101104
}
102105

@@ -156,17 +159,18 @@ impl<'a> Iterator for CmsgIterator<'a> {
156159
}
157160
self.0 = &buf[cmsg_align(cmsg_len)..];
158161

162+
let cmsg_data = &buf[cmsg_align(sizeof_cmsghdr)..];
159163
match (cmsg.cmsg_level, cmsg.cmsg_type) {
160164
(SOL_SOCKET, SCM_RIGHTS) => unsafe {
161165
Some(ControlMessage::ScmRights(
162166
slice::from_raw_parts(
163-
&cmsg.cmsg_data as *const _ as *const _, 1)))
167+
cmsg_data.as_ptr() as *const _, 1)))
164168
},
165169
(_, _) => unsafe {
166170
Some(ControlMessage::Unknown(UnknownCmsg(
167171
&cmsg,
168172
slice::from_raw_parts(
169-
&cmsg.cmsg_data as *const _ as *const _,
173+
cmsg_data.as_ptr() as *const _,
170174
len))))
171175
}
172176
}
@@ -191,7 +195,7 @@ pub enum ControlMessage<'a> {
191195
pub struct UnknownCmsg<'a>(&'a cmsghdr, &'a [u8]);
192196

193197
fn cmsg_align(len: usize) -> usize {
194-
let align_bytes = mem::size_of::<type_of_cmsg_data>() - 1;
198+
let align_bytes = mem::size_of::<align_of_cmsg_data>() - 1;
195199
(len + align_bytes) & !align_bytes
196200
}
197201

@@ -213,8 +217,8 @@ impl<'a> ControlMessage<'a> {
213217
}
214218
}
215219

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
220+
// Unsafe: start and end of buffer must be cmsg_align'd.
221+
// Updates the provided slice; panics if the buffer
218222
// is too small.
219223
unsafe fn encode_into<'b>(&self, buf: &mut &'b mut [u8]) {
220224
match *self {
@@ -223,7 +227,6 @@ impl<'a> ControlMessage<'a> {
223227
cmsg_len: self.len() as type_of_cmsg_len,
224228
cmsg_level: SOL_SOCKET,
225229
cmsg_type: SCM_RIGHTS,
226-
cmsg_data: [],
227230
};
228231
copy_bytes(&cmsg, buf);
229232

@@ -287,9 +290,9 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
287290
msg_name: name as *const c_void,
288291
msg_namelen: namelen,
289292
msg_iov: iov.as_ptr(),
290-
msg_iovlen: iov.len() as size_t,
293+
msg_iovlen: iov.len() as type_of_msgiov_len,
291294
msg_control: cmsg_ptr,
292-
msg_controllen: capacity as size_t,
295+
msg_controllen: capacity as type_of_msg_controllen,
293296
msg_flags: 0,
294297
};
295298
let ret = unsafe { ffi::sendmsg(fd, &mhdr, flags.bits()) };
@@ -310,9 +313,9 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
310313
msg_name: &mut address as *const _ as *const c_void,
311314
msg_namelen: mem::size_of::<sockaddr_storage>() as socklen_t,
312315
msg_iov: iov.as_ptr() as *const IoVec<&[u8]>, // safe cast to add const-ness
313-
msg_iovlen: iov.len() as size_t,
316+
msg_iovlen: iov.len() as type_of_msgiov_len,
314317
msg_control: msg_control as *const c_void,
315-
msg_controllen: msg_controllen as size_t,
318+
msg_controllen: msg_controllen as type_of_msg_controllen,
316319
msg_flags: 0,
317320
};
318321
let ret = unsafe { ffi::recvmsg(fd, &mut mhdr, flags.bits()) };
@@ -692,6 +695,8 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
692695

693696
#[test]
694697
pub fn test_struct_sizes() {
695-
use nixtest;
696-
nixtest::assert_size_of::<sockaddr_storage>("sockaddr_storage");
698+
use nixtest::assert_size_of;
699+
assert_size_of::<sockaddr_storage>("sockaddr_storage");
700+
assert_size_of::<msghdr>("msghdr");
701+
assert_size_of::<cmsghdr>("cmsghdr");
697702
}

0 commit comments

Comments
 (0)