]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/sys/sgx/abi/usercalls/mod.rs
Format libstd/sys with rustfmt
[rust.git] / src / libstd / sys / sgx / abi / usercalls / mod.rs
index 0abfc26bced0025d4188ef341c8302d773295e9e..ae803ee47a6cb1717bd7439a6cc80322b28557ad 100644 (file)
@@ -1,4 +1,5 @@
-use crate::io::{Error as IoError, Result as IoResult};
+use crate::cmp;
+use crate::io::{Error as IoError, IoSlice, IoSliceMut, Result as IoResult};
 use crate::time::Duration;
 
 pub(crate) mod alloc;
@@ -8,13 +9,27 @@
 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())
     }
 }
 
@@ -30,10 +45,24 @@ pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
 }
 
 /// 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()
     }
 }
@@ -61,11 +90,8 @@ pub fn bind_stream(addr: &str) -> IoResult<(Fd, String)> {
     unsafe {
         let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
         let mut local = alloc::User::<ByteBuffer>::uninitialized();
-        let fd = raw::bind_stream(
-            addr_user.as_ptr(),
-            addr_user.len(),
-            local.as_raw_mut_ptr()
-        ).from_sgx_result()?;
+        let fd = raw::bind_stream(addr_user.as_ptr(), addr_user.len(), local.as_raw_mut_ptr())
+            .from_sgx_result()?;
         let local = string_from_bytebuffer(&local, "bind_stream", "local_addr");
         Ok((fd, local))
     }
@@ -77,13 +103,10 @@ pub fn accept_stream(fd: Fd) -> IoResult<(Fd, String, String)> {
     unsafe {
         let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
         let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
-                                                               // without forcing coercion?
+        // without forcing coercion?
         let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
-        let fd = raw::accept_stream(
-            fd,
-            local.as_raw_mut_ptr(),
-            peer.as_raw_mut_ptr()
-        ).from_sgx_result()?;
+        let fd = raw::accept_stream(fd, local.as_raw_mut_ptr(), peer.as_raw_mut_ptr())
+            .from_sgx_result()?;
         let local = string_from_bytebuffer(&local, "accept_stream", "local_addr");
         let peer = string_from_bytebuffer(&peer, "accept_stream", "peer_addr");
         Ok((fd, local, peer))
@@ -97,14 +120,15 @@ pub fn connect_stream(addr: &str) -> IoResult<(Fd, String, String)> {
         let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
         let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
         let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
-                                                               // without forcing coercion?
+        // without forcing coercion?
         let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
         let fd = raw::connect_stream(
             addr_user.as_ptr(),
             addr_user.len(),
             local.as_raw_mut_ptr(),
-            peer.as_raw_mut_ptr()
-        ).from_sgx_result()?;
+            peer.as_raw_mut_ptr(),
+        )
+        .from_sgx_result()?;
         let local = string_from_bytebuffer(&local, "connect_stream", "local_addr");
         let peer = string_from_bytebuffer(&peer, "connect_stream", "peer_addr");
         Ok((fd, local, peer))
@@ -154,25 +178,25 @@ pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> {
 
 fn check_os_error(err: Result) -> i32 {
     // FIXME: not sure how to make sure all variants of Error are covered
-    if err == Error::NotFound as _ ||
-       err == Error::PermissionDenied as _ ||
-       err == Error::ConnectionRefused as _ ||
-       err == Error::ConnectionReset as _ ||
-       err == Error::ConnectionAborted as _ ||
-       err == Error::NotConnected as _ ||
-       err == Error::AddrInUse as _ ||
-       err == Error::AddrNotAvailable as _ ||
-       err == Error::BrokenPipe as _ ||
-       err == Error::AlreadyExists as _ ||
-       err == Error::WouldBlock as _ ||
-       err == Error::InvalidInput as _ ||
-       err == Error::InvalidData as _ ||
-       err == Error::TimedOut as _ ||
-       err == Error::WriteZero as _ ||
-       err == Error::Interrupted as _ ||
-       err == Error::Other as _ ||
-       err == Error::UnexpectedEof as _ ||
-       ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&err)
+    if err == Error::NotFound as _
+        || err == Error::PermissionDenied as _
+        || err == Error::ConnectionRefused as _
+        || err == Error::ConnectionReset as _
+        || err == Error::ConnectionAborted as _
+        || err == Error::NotConnected as _
+        || err == Error::AddrInUse as _
+        || err == Error::AddrNotAvailable as _
+        || err == Error::BrokenPipe as _
+        || err == Error::AlreadyExists as _
+        || err == Error::WouldBlock as _
+        || err == Error::InvalidInput as _
+        || err == Error::InvalidData as _
+        || err == Error::TimedOut as _
+        || err == Error::WriteZero as _
+        || err == Error::Interrupted as _
+        || err == Error::Other as _
+        || err == Error::UnexpectedEof as _
+        || ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&err)
     {
         err
     } else {