tun_easytier/platform/posix/
fd.rs1use 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
20pub(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 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}