tun_easytier/platform/posix/
fd.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 crate::error::{Error, Result};
16use libc::{self, fcntl, F_GETFL, F_SETFL, O_NONBLOCK};
17use std::io;
18use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
19
20/// POSIX file descriptor support for `io` traits.
21pub(crate) struct Fd {
22    pub(crate) inner: RawFd,
23    close_fd_on_drop: bool,
24}
25
26impl Fd {
27    pub fn new(value: RawFd, close_fd_on_drop: bool) -> Result<Self> {
28        if value < 0 {
29            return Err(Error::InvalidDescriptor);
30        }
31        Ok(Fd {
32            inner: value,
33            close_fd_on_drop,
34        })
35    }
36
37    /// Enable non-blocking mode
38    pub fn set_nonblock(&self) -> io::Result<()> {
39        match unsafe { fcntl(self.inner, F_SETFL, fcntl(self.inner, F_GETFL) | O_NONBLOCK) } {
40            0 => Ok(()),
41            _ => Err(io::Error::last_os_error()),
42        }
43    }
44
45    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
46        let fd = self.as_raw_fd();
47        let amount = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, buf.len()) };
48        if amount < 0 {
49            return Err(io::Error::last_os_error());
50        }
51        Ok(amount as usize)
52    }
53
54    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
55        let fd = self.as_raw_fd();
56        let amount = unsafe { libc::write(fd, buf.as_ptr() as *const _, buf.len()) };
57        if amount < 0 {
58            return Err(io::Error::last_os_error());
59        }
60        Ok(amount as usize)
61    }
62}
63
64impl AsRawFd for Fd {
65    fn as_raw_fd(&self) -> RawFd {
66        self.inner
67    }
68}
69
70impl IntoRawFd for Fd {
71    fn into_raw_fd(mut self) -> RawFd {
72        let fd = self.inner;
73        self.inner = -1;
74        fd
75    }
76}
77
78impl Drop for Fd {
79    fn drop(&mut self) {
80        if self.close_fd_on_drop && self.inner >= 0 {
81            unsafe { libc::close(self.inner) };
82        }
83    }
84}