-use crate::io::{Error as IoError, Result as IoResult};
+use crate::cmp;
+use crate::io::{Error as IoError, Result as IoResult, IoSlice, IoSliceMut};
use crate::time::Duration;
pub(crate) mod alloc;
use self::raw::*;
/// Usercall `read`. See the ABI documentation for more information.
+///
+/// This will do a single `read` usercall and scatter the read data among
+/// `bufs`. To read to a single buffer, just pass a slice of length one.
#[unstable(feature = "sgx_platform", issue = "56975")]
-pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
+pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
unsafe {
- let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
- let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
- userbuf[..len].copy_to_enclave(&mut buf[..len]);
- Ok(len)
+ let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
+ let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
+ let ret_len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
+ let userbuf = &userbuf[..ret_len];
+ let mut index = 0;
+ for buf in bufs {
+ let end = cmp::min(index + buf.len(), userbuf.len());
+ if let Some(buflen) = end.checked_sub(index) {
+ userbuf[index..end].copy_to_enclave(&mut buf[..buflen]);
+ index += buf.len();
+ } else {
+ break
+ }
+ }
+ Ok(userbuf.len())
}
}
}
/// Usercall `write`. See the ABI documentation for more information.
+///
+/// This will do a single `write` usercall and gather the written data from
+/// `bufs`. To write from a single buffer, just pass a slice of length one.
#[unstable(feature = "sgx_platform", issue = "56975")]
-pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
+pub fn write(fd: Fd, bufs: &[IoSlice<'_>]) -> IoResult<usize> {
unsafe {
- let userbuf = alloc::User::new_from_enclave(buf);
+ let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
+ let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
+ let mut index = 0;
+ for buf in bufs {
+ let end = cmp::min(index + buf.len(), userbuf.len());
+ if let Some(buflen) = end.checked_sub(index) {
+ userbuf[index..end].copy_from_enclave(&buf[..buflen]);
+ index += buf.len();
+ } else {
+ break
+ }
+ }
raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
}
}
use fortanix_sgx_abi::Fd;
-use crate::io;
+use crate::io::{self, IoSlice, IoSliceMut};
use crate::mem;
use crate::sys::{AsInner, FromInner, IntoInner};
use super::abi::usercalls;
}
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
- usercalls::read(self.fd, buf)
+ usercalls::read(self.fd, &mut [IoSliceMut::new(buf)])
+ }
+
+ pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+ usercalls::read(self.fd, bufs)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
- usercalls::write(self.fd, buf)
+ usercalls::write(self.fd, &[IoSlice::new(buf)])
+ }
+
+ pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+ usercalls::write(self.fd, bufs)
}
pub fn flush(&self) -> io::Result<()> {
}
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
- io::default_read_vectored(|b| self.read(b), bufs)
+ self.inner.inner.read_vectored(bufs)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
}
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
- io::default_write_vectored(|b| self.write(b), bufs)
+ self.inner.inner.write_vectored(bufs)
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {