1 #![unstable(reason = "not public", issue = "none", feature = "fd")]
4 use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
7 use crate::sys_common::AsInner;
9 use libc::{self, c_int, c_void, ssize_t};
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;
22 pub fn new(fd: c_int) -> FileDesc {
26 pub fn raw(&self) -> c_int {
30 /// Extracts the actual file descriptor without closing it.
31 pub fn into_raw(self) -> c_int {
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))
44 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
45 let ret = cvt(unsafe {
48 bufs.as_ptr() as *const libc::iovec,
49 cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
56 fn is_read_vectored(&self) -> bool {
60 pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
62 (&mut me).read_to_end(buf)
65 pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
71 ) -> io::Result<isize> {
73 cvt(pread(fd, buf, count, offset))
79 buf.as_mut_ptr() as *mut c_void,
80 cmp::min(buf.len(), READ_LIMIT),
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))
94 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
95 let ret = cvt(unsafe {
98 bufs.as_ptr() as *const libc::iovec,
99 cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
106 pub fn is_write_vectored(&self) -> bool {
110 pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
111 unsafe fn cvt_pwrite(
116 ) -> io::Result<isize> {
118 cvt(pwrite(fd, buf, count, offset))
124 buf.as_ptr() as *const c_void,
125 cmp::min(buf.len(), READ_LIMIT),
132 pub fn get_cloexec(&self) -> io::Result<bool> {
133 unsafe { Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
136 pub fn set_cloexec(&self) -> io::Result<()> {
138 let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
139 let new = previous | libc::FD_CLOEXEC;
141 cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
147 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
149 let v = nonblocking as c_int;
150 cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
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<()> {
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))?;
166 pub fn duplicate(&self) -> io::Result<FileDesc> {
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),
175 impl<'a> Read for &'a FileDesc {
176 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
181 unsafe fn initializer(&self) -> Initializer {
186 impl AsInner<c_int> for FileDesc {
187 fn as_inner(&self) -> &c_int {
192 impl Drop for FileDesc {
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) };