1- use  crate :: io:: { Error  as  IoError ,  Result  as  IoResult } ; 
1+ use  crate :: cmp; 
2+ use  crate :: io:: { Error  as  IoError ,  Result  as  IoResult ,  IoSlice ,  IoSliceMut } ; 
23use  crate :: time:: Duration ; 
34
45pub ( crate )  mod  alloc; 
@@ -8,13 +9,27 @@ pub(crate) mod raw;
89use  self :: raw:: * ; 
910
1011/// Usercall `read`. See the ABI documentation for more information. 
12+ /// 
13+ /// This will do a single `read` usercall and scatter the read data among 
14+ /// `bufs`. To read to a single buffer, just pass a slice of length one. 
1115#[ unstable( feature = "sgx_platform" ,  issue = "56975" ) ]  
12- pub  fn  read ( fd :  Fd ,  buf :  & mut  [ u8 ] )  -> IoResult < usize >  { 
16+ pub  fn  read ( fd :  Fd ,  bufs :  & mut  [ IoSliceMut < ' _ > ] )  -> IoResult < usize >  { 
1317    unsafe  { 
14-         let  mut  userbuf = alloc:: User :: < [ u8 ] > :: uninitialized ( buf. len ( ) ) ; 
15-         let  len = raw:: read ( fd,  userbuf. as_mut_ptr ( ) ,  userbuf. len ( ) ) . from_sgx_result ( ) ?; 
16-         userbuf[ ..len] . copy_to_enclave ( & mut  buf[ ..len] ) ; 
17-         Ok ( len) 
18+         let  total_len = bufs. iter ( ) . fold ( 0usize ,  |sum,  buf| sum. saturating_add ( buf. len ( ) ) ) ; 
19+         let  mut  userbuf = alloc:: User :: < [ u8 ] > :: uninitialized ( total_len) ; 
20+         let  ret_len = raw:: read ( fd,  userbuf. as_mut_ptr ( ) ,  userbuf. len ( ) ) . from_sgx_result ( ) ?; 
21+         let  userbuf = & userbuf[ ..ret_len] ; 
22+         let  mut  index = 0 ; 
23+         for  buf in  bufs { 
24+             let  end = cmp:: min ( index + buf. len ( ) ,  userbuf. len ( ) ) ; 
25+             if  let  Some ( buflen)  = end. checked_sub ( index)  { 
26+                 userbuf[ index..end] . copy_to_enclave ( & mut  buf[ ..buflen] ) ; 
27+                 index += buf. len ( ) ; 
28+             }  else  { 
29+                 break 
30+             } 
31+         } 
32+         Ok ( userbuf. len ( ) ) 
1833    } 
1934} 
2035
@@ -30,10 +45,24 @@ pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
3045} 
3146
3247/// Usercall `write`. See the ABI documentation for more information. 
48+ /// 
49+ /// This will do a single `write` usercall and gather the written data from 
50+ /// `bufs`. To write from a single buffer, just pass a slice of length one. 
3351#[ unstable( feature = "sgx_platform" ,  issue = "56975" ) ]  
34- pub  fn  write ( fd :  Fd ,  buf :  & [ u8 ] )  -> IoResult < usize >  { 
52+ pub  fn  write ( fd :  Fd ,  bufs :  & [ IoSlice < ' _ > ] )  -> IoResult < usize >  { 
3553    unsafe  { 
36-         let  userbuf = alloc:: User :: new_from_enclave ( buf) ; 
54+         let  total_len = bufs. iter ( ) . fold ( 0usize ,  |sum,  buf| sum. saturating_add ( buf. len ( ) ) ) ; 
55+         let  mut  userbuf = alloc:: User :: < [ u8 ] > :: uninitialized ( total_len) ; 
56+         let  mut  index = 0 ; 
57+         for  buf in  bufs { 
58+             let  end = cmp:: min ( index + buf. len ( ) ,  userbuf. len ( ) ) ; 
59+             if  let  Some ( buflen)  = end. checked_sub ( index)  { 
60+                 userbuf[ index..end] . copy_from_enclave ( & buf[ ..buflen] ) ; 
61+                 index += buf. len ( ) ; 
62+             }  else  { 
63+                 break 
64+             } 
65+         } 
3766        raw:: write ( fd,  userbuf. as_ptr ( ) ,  userbuf. len ( ) ) . from_sgx_result ( ) 
3867    } 
3968} 
0 commit comments