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 } ;
2
3
use crate :: time:: Duration ;
3
4
4
5
pub ( crate ) mod alloc;
@@ -8,13 +9,27 @@ pub(crate) mod raw;
8
9
use self :: raw:: * ;
9
10
10
11
/// 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.
11
15
#[ 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 > {
13
17
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 ( ) )
18
33
}
19
34
}
20
35
@@ -30,10 +45,24 @@ pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
30
45
}
31
46
32
47
/// 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.
33
51
#[ 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 > {
35
53
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
+ }
37
66
raw:: write ( fd, userbuf. as_ptr ( ) , userbuf. len ( ) ) . from_sgx_result ( )
38
67
}
39
68
}
0 commit comments