tun_sync/platform/posix/
split.rs

1//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyleft (ↄ) meh. <meh@schizofreni.co> | http://meh.schizofreni.co
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14
15use std::io::{self, Read, Write};
16use std::mem;
17use std::os::unix::io::{AsRawFd, RawFd};
18use std::sync::Arc;
19
20use crate::platform::posix::Fd;
21use libc;
22
23/// Read-only end for a file descriptor.
24pub struct Reader(pub(crate) Arc<Fd>);
25
26/// Write-only end for a file descriptor.
27pub struct Writer(pub(crate) Arc<Fd>);
28
29impl Read for Reader {
30    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
31        unsafe {
32            let amount = libc::read(self.0.as_raw_fd(), buf.as_mut_ptr() as *mut _, buf.len());
33
34            if amount < 0 {
35                return Err(io::Error::last_os_error());
36            }
37
38            Ok(amount as usize)
39        }
40    }
41
42    fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
43        unsafe {
44            let mut msg: libc::msghdr = mem::zeroed();
45            // msg.msg_name: NULL
46            // msg.msg_namelen: 0
47            msg.msg_iov = bufs.as_mut_ptr().cast();
48            msg.msg_iovlen = bufs.len().min(libc::c_int::MAX as usize) as _;
49
50            let n = libc::recvmsg(self.0.as_raw_fd(), &mut msg, 0);
51            if n < 0 {
52                return Err(io::Error::last_os_error());
53            }
54
55            Ok(n as usize)
56        }
57    }
58}
59
60impl Write for Writer {
61    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
62        unsafe {
63            let amount = libc::write(self.0.as_raw_fd(), buf.as_ptr() as *const _, buf.len());
64
65            if amount < 0 {
66                return Err(io::Error::last_os_error());
67            }
68
69            Ok(amount as usize)
70        }
71    }
72
73    fn flush(&mut self) -> io::Result<()> {
74        Ok(())
75    }
76
77    fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
78        unsafe {
79            let mut msg: libc::msghdr = mem::zeroed();
80            // msg.msg_name = NULL
81            // msg.msg_namelen = 0
82            msg.msg_iov = bufs.as_ptr() as *mut _;
83            msg.msg_iovlen = bufs.len().min(libc::c_int::MAX as usize) as _;
84
85            let n = libc::sendmsg(self.0.as_raw_fd(), &msg, 0);
86            if n < 0 {
87                return Err(io::Error::last_os_error());
88            }
89
90            Ok(n as usize)
91        }
92    }
93}
94
95impl AsRawFd for Reader {
96    fn as_raw_fd(&self) -> RawFd {
97        self.0.as_raw_fd()
98    }
99}
100
101impl AsRawFd for Writer {
102    fn as_raw_fd(&self) -> RawFd {
103        self.0.as_raw_fd()
104    }
105}