]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/vxworks/fd.rs
Fix font color for help button in ayu and dark themes
[rust.git] / library / std / src / sys / vxworks / fd.rs
1 #![unstable(reason = "not public", issue = "none", feature = "fd")]
2
3 use crate::cmp;
4 use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
5 use crate::mem;
6 use crate::sys::cvt;
7 use crate::sys_common::AsInner;
8
9 use libc::{self, c_int, c_void, ssize_t};
10
11 #[derive(Debug)]
12 pub struct FileDesc {
13     fd: c_int,
14 }
15
16 // The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
17 // with the man page quoting that if the count of bytes to read is
18 // greater than `SSIZE_MAX` the result is "unspecified".
19 const READ_LIMIT: usize = ssize_t::MAX as usize;
20
21 impl FileDesc {
22     pub fn new(fd: c_int) -> FileDesc {
23         FileDesc { fd: fd }
24     }
25
26     pub fn raw(&self) -> c_int {
27         self.fd
28     }
29
30     /// Extracts the actual file descriptor without closing it.
31     pub fn into_raw(self) -> c_int {
32         let fd = self.fd;
33         mem::forget(self);
34         fd
35     }
36
37     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
38         let ret = cvt(unsafe {
39             libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
40         })?;
41         Ok(ret as usize)
42     }
43
44     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
45         let ret = cvt(unsafe {
46             libc::readv(
47                 self.fd,
48                 bufs.as_ptr() as *const libc::iovec,
49                 cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
50             )
51         })?;
52         Ok(ret as usize)
53     }
54
55     #[inline]
56     fn is_read_vectored(&self) -> bool {
57         true
58     }
59
60     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
61         let mut me = self;
62         (&mut me).read_to_end(buf)
63     }
64
65     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
66         unsafe fn cvt_pread(
67             fd: c_int,
68             buf: *mut c_void,
69             count: usize,
70             offset: i64,
71         ) -> io::Result<isize> {
72             use libc::pread;
73             cvt(pread(fd, buf, count, offset))
74         }
75
76         unsafe {
77             cvt_pread(
78                 self.fd,
79                 buf.as_mut_ptr() as *mut c_void,
80                 cmp::min(buf.len(), READ_LIMIT),
81                 offset as i64,
82             )
83             .map(|n| n as usize)
84         }
85     }
86
87     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
88         let ret = cvt(unsafe {
89             libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
90         })?;
91         Ok(ret as usize)
92     }
93
94     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
95         let ret = cvt(unsafe {
96             libc::writev(
97                 self.fd,
98                 bufs.as_ptr() as *const libc::iovec,
99                 cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
100             )
101         })?;
102         Ok(ret as usize)
103     }
104
105     #[inline]
106     pub fn is_write_vectored(&self) -> bool {
107         true
108     }
109
110     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
111         unsafe fn cvt_pwrite(
112             fd: c_int,
113             buf: *const c_void,
114             count: usize,
115             offset: i64,
116         ) -> io::Result<isize> {
117             use libc::pwrite;
118             cvt(pwrite(fd, buf, count, offset))
119         }
120
121         unsafe {
122             cvt_pwrite(
123                 self.fd,
124                 buf.as_ptr() as *const c_void,
125                 cmp::min(buf.len(), READ_LIMIT),
126                 offset as i64,
127             )
128             .map(|n| n as usize)
129         }
130     }
131
132     pub fn get_cloexec(&self) -> io::Result<bool> {
133         unsafe { Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
134     }
135
136     pub fn set_cloexec(&self) -> io::Result<()> {
137         unsafe {
138             let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
139             let new = previous | libc::FD_CLOEXEC;
140             if new != previous {
141                 cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
142             }
143             Ok(())
144         }
145     }
146
147     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
148         unsafe {
149             let v = nonblocking as c_int;
150             cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
151             Ok(())
152         }
153     }
154
155     // refer to pxPipeDrv library documentation.
156     // VxWorks uses fcntl to set O_NONBLOCK to the pipes
157     pub fn set_nonblocking_pipe(&self, nonblocking: bool) -> io::Result<()> {
158         unsafe {
159             let mut flags = cvt(libc::fcntl(self.fd, libc::F_GETFL, 0))?;
160             flags = if nonblocking { flags | libc::O_NONBLOCK } else { flags & !libc::O_NONBLOCK };
161             cvt(libc::fcntl(self.fd, libc::F_SETFL, flags))?;
162             Ok(())
163         }
164     }
165
166     pub fn duplicate(&self) -> io::Result<FileDesc> {
167         let fd = self.raw();
168         match cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, 0) }) {
169             Ok(newfd) => Ok(FileDesc::new(newfd)),
170             Err(e) => return Err(e),
171         }
172     }
173 }
174
175 impl<'a> Read for &'a FileDesc {
176     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
177         (**self).read(buf)
178     }
179
180     #[inline]
181     unsafe fn initializer(&self) -> Initializer {
182         Initializer::nop()
183     }
184 }
185
186 impl AsInner<c_int> for FileDesc {
187     fn as_inner(&self) -> &c_int {
188         &self.fd
189     }
190 }
191
192 impl Drop for FileDesc {
193     fn drop(&mut self) {
194         // Note that errors are ignored when closing a file descriptor. The
195         // reason for this is that if an error occurs we don't actually know if
196         // the file descriptor was closed or not, and if we retried (for
197         // something like EINTR), we might close another valid file descriptor
198         // (opened after we closed ours.
199         let _ = unsafe { libc::close(self.fd) };
200     }
201 }