summaryrefslogtreecommitdiff
path: root/test/sys
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-07-05 15:49:18 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-07-05 15:49:18 +0000
commit90b1c17a5e01768e9396e8801b36b2ce5f025187 (patch)
treee9e8f65d3a048a3e69f8047df3ca2da2a653e67b /test/sys
parente0577cc89059267e996027f45578f09f34b7347b (diff)
parent5d6dc265b313aa45868cedc972a4b18114972da9 (diff)
downloadnix-90b1c17a5e01768e9396e8801b36b2ce5f025187.zip
Merge #918
918: Fix passing multiple file descriptors / control messages via sendmsg r=asomers a=jonas-schievink Fixes #464 Closes #874 because it's incorporated here Closes #756 because it adds the test from that issue (with fixes) Co-authored-by: alecmocatta <alec@mocatta.net>
Diffstat (limited to 'test/sys')
-rw-r--r--test/sys/test_socket.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index a997fbca..35e3bf90 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -167,6 +167,51 @@ pub fn test_scm_rights() {
close(w).unwrap();
}
+/// Tests that passing multiple fds using a single `ControlMessage` works.
+#[test]
+fn test_scm_rights_single_cmsg_multiple_fds() {
+ use std::os::unix::net::UnixDatagram;
+ use std::os::unix::io::{RawFd, AsRawFd};
+ use std::thread;
+ use nix::sys::socket::{CmsgSpace, ControlMessage, MsgFlags, sendmsg, recvmsg};
+ use nix::sys::uio::IoVec;
+ use libc;
+
+ let (send, receive) = UnixDatagram::pair().unwrap();
+ let thread = thread::spawn(move || {
+ let mut buf = [0u8; 8];
+ let iovec = [IoVec::from_mut_slice(&mut buf)];
+ let mut space = CmsgSpace::<[RawFd; 2]>::new();
+ let msg = recvmsg(
+ receive.as_raw_fd(),
+ &iovec,
+ Some(&mut space),
+ MsgFlags::empty()
+ ).unwrap();
+ assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
+
+ let mut cmsgs = msg.cmsgs();
+ match cmsgs.next() {
+ Some(ControlMessage::ScmRights(fds)) => {
+ assert_eq!(fds.len(), 2,
+ "unexpected fd count (expected 2 fds, got {})",
+ fds.len());
+ },
+ _ => panic!(),
+ }
+ assert!(cmsgs.next().is_none(), "unexpected control msg");
+
+ assert_eq!(iovec[0].as_slice(), [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8]);
+ });
+
+ let slice = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8];
+ let iov = [IoVec::from_slice(&slice)];
+ let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout
+ let cmsg = [ControlMessage::ScmRights(&fds)];
+ sendmsg(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap();
+ thread.join().unwrap();
+}
+
// Verify `sendmsg` builds a valid `msghdr` when passing an empty
// `cmsgs` argument. This should result in a msghdr with a nullptr
// msg_control field and a msg_controllen of 0 when calling into the