| #![unstable(reason = "not public", issue = "none", feature = "fd")] | |
| use crate::cmp; | |
| use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, SeekFrom}; | |
| use crate::os::hermit::hermit_abi; | |
| use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; | |
| use crate::sys::{AsInner, FromInner, IntoInner, cvt, unsupported}; | |
| const fn max_iov() -> usize { | |
| hermit_abi::IOV_MAX | |
| } | |
| #[derive(Debug)] | |
| pub struct FileDesc { | |
| fd: OwnedFd, | |
| } | |
| impl FileDesc { | |
| pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { | |
| let result = | |
| cvt(unsafe { hermit_abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?; | |
| Ok(result as usize) | |
| } | |
| pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { | |
| // SAFETY: The `read` syscall does not read from the buffer, so it is | |
| // safe to use `&mut [MaybeUninit<u8>]`. | |
| let result = cvt(unsafe { | |
| hermit_abi::read( | |
| self.fd.as_raw_fd(), | |
| buf.as_mut().as_mut_ptr() as *mut u8, | |
| buf.capacity(), | |
| ) | |
| })?; | |
| // SAFETY: Exactly `result` bytes have been filled. | |
| unsafe { buf.advance(result as usize) }; | |
| Ok(()) | |
| } | |
| pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { | |
| let ret = cvt(unsafe { | |
| hermit_abi::readv( | |
| self.as_raw_fd(), | |
| bufs.as_mut_ptr() as *mut hermit_abi::iovec as *const hermit_abi::iovec, | |
| cmp::min(bufs.len(), max_iov()), | |
| ) | |
| })?; | |
| Ok(ret as usize) | |
| } | |
| #[inline] | |
| pub fn is_read_vectored(&self) -> bool { | |
| true | |
| } | |
| pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { | |
| let mut me = self; | |
| (&mut me).read_to_end(buf) | |
| } | |
| pub fn write(&self, buf: &[u8]) -> io::Result<usize> { | |
| let result = | |
| cvt(unsafe { hermit_abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?; | |
| Ok(result as usize) | |
| } | |
| pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { | |
| let ret = cvt(unsafe { | |
| hermit_abi::writev( | |
| self.as_raw_fd(), | |
| bufs.as_ptr() as *const hermit_abi::iovec, | |
| cmp::min(bufs.len(), max_iov()), | |
| ) | |
| })?; | |
| Ok(ret as usize) | |
| } | |
| #[inline] | |
| pub fn is_write_vectored(&self) -> bool { | |
| true | |
| } | |
| pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> { | |
| let (whence, pos) = match pos { | |
| // Casting to `i64` is fine, too large values will end up as | |
| // negative which will cause an error in `lseek`. | |
| SeekFrom::Start(off) => (hermit_abi::SEEK_SET, off as i64), | |
| SeekFrom::End(off) => (hermit_abi::SEEK_END, off), | |
| SeekFrom::Current(off) => (hermit_abi::SEEK_CUR, off), | |
| }; | |
| let n = cvt(unsafe { hermit_abi::lseek(self.as_raw_fd(), pos as isize, whence) })?; | |
| Ok(n as u64) | |
| } | |
| pub fn tell(&self) -> io::Result<u64> { | |
| self.seek(SeekFrom::Current(0)) | |
| } | |
| pub fn duplicate(&self) -> io::Result<FileDesc> { | |
| self.duplicate_path(&[]) | |
| } | |
| pub fn duplicate_path(&self, _path: &[u8]) -> io::Result<FileDesc> { | |
| unsupported() | |
| } | |
| pub fn nonblocking(&self) -> io::Result<bool> { | |
| Ok(false) | |
| } | |
| pub fn set_cloexec(&self) -> io::Result<()> { | |
| unsupported() | |
| } | |
| pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { | |
| unsupported() | |
| } | |
| pub fn fstat(&self, stat: *mut hermit_abi::stat) -> io::Result<()> { | |
| cvt(unsafe { hermit_abi::fstat(self.fd.as_raw_fd(), stat) })?; | |
| Ok(()) | |
| } | |
| } | |
| impl<'a> Read for &'a FileDesc { | |
| fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
| (**self).read(buf) | |
| } | |
| } | |
| impl IntoInner<OwnedFd> for FileDesc { | |
| fn into_inner(self) -> OwnedFd { | |
| self.fd | |
| } | |
| } | |
| impl FromInner<OwnedFd> for FileDesc { | |
| fn from_inner(owned_fd: OwnedFd) -> Self { | |
| Self { fd: owned_fd } | |
| } | |
| } | |
| impl FromRawFd for FileDesc { | |
| unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { | |
| let fd = unsafe { OwnedFd::from_raw_fd(raw_fd) }; | |
| Self { fd } | |
| } | |
| } | |
| impl AsInner<OwnedFd> for FileDesc { | |
| #[inline] | |
| fn as_inner(&self) -> &OwnedFd { | |
| &self.fd | |
| } | |
| } | |
| impl AsFd for FileDesc { | |
| fn as_fd(&self) -> BorrowedFd<'_> { | |
| self.fd.as_fd() | |
| } | |
| } | |
| impl AsRawFd for FileDesc { | |
| #[inline] | |
| fn as_raw_fd(&self) -> RawFd { | |
| self.fd.as_raw_fd() | |
| } | |
| } | |
| impl IntoRawFd for FileDesc { | |
| fn into_raw_fd(self) -> RawFd { | |
| self.fd.into_raw_fd() | |
| } | |
| } |