44// file that was distributed with this source code.
55use super :: { CatResult , FdReadable , InputHandle } ;
66
7- use rustix :: io:: { read , write } ;
7+ use std :: io:: { Read , Write } ;
88use std:: os:: { fd:: AsFd , unix:: io:: AsRawFd } ;
99
1010use uucore:: pipes:: { MAX_ROOTLESS_PIPE_SIZE , might_fuse, pipe, splice, splice_exact} ;
1111
12- const BUF_SIZE : usize = 1024 * 16 ;
13-
1412/// This function is called from `write_fast()` on Linux and Android. The
1513/// function `splice()` is used to move data between two file descriptors
1614/// without copying between kernel and user spaces. This results in a large
@@ -19,14 +17,14 @@ const BUF_SIZE: usize = 1024 * 16;
1917/// The `bool` in the result value indicates if we need to fall back to normal
2018/// copying or not. False means we don't have to.
2119#[ inline]
22- pub ( super ) fn write_fast_using_splice < R : FdReadable , S : AsRawFd + AsFd > (
20+ pub ( super ) fn write_fast_using_splice < R : FdReadable , S : AsRawFd + AsFd + Write > (
2321 handle : & InputHandle < R > ,
24- write_fd : & S ,
22+ write_fd : & mut S ,
2523) -> CatResult < bool > {
2624 if splice ( & handle. reader , & write_fd, MAX_ROOTLESS_PIPE_SIZE ) . is_ok ( ) {
2725 // fcntl improves throughput
2826 // todo: avoid fcntl overhead for small input, but don't fcntl inside of the loop
29- let _ = rustix:: pipe:: fcntl_setpipe_size ( write_fd, MAX_ROOTLESS_PIPE_SIZE ) ;
27+ let _ = rustix:: pipe:: fcntl_setpipe_size ( & mut * write_fd, MAX_ROOTLESS_PIPE_SIZE ) ;
3028 loop {
3129 match splice ( & handle. reader , & write_fd, MAX_ROOTLESS_PIPE_SIZE ) {
3230 Ok ( 1 ..) => { }
@@ -46,7 +44,9 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
4644 // we can recover by copying the data that we have from the
4745 // intermediate pipe to stdout using normal read/write. Then
4846 // we tell the caller to fall back.
49- copy_exact ( & pipe_rd, write_fd, n) ?;
47+ let mut drain = Vec :: with_capacity ( n) ; // bounded by pipe size
48+ pipe_rd. take ( n as u64 ) . read_to_end ( & mut drain) ?;
49+ write_fd. write_all ( & drain) ?;
5050 return Ok ( true ) ;
5151 }
5252 }
@@ -57,24 +57,3 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
5757 Ok ( true )
5858 }
5959}
60-
61- /// Move exactly `num_bytes` bytes from `read_fd` to `write_fd`.
62- ///
63- /// Panics if not enough bytes can be read.
64- fn copy_exact ( read_fd : & impl AsFd , write_fd : & impl AsFd , num_bytes : usize ) -> std:: io:: Result < ( ) > {
65- let mut left = num_bytes;
66- let mut buf = [ 0 ; BUF_SIZE ] ;
67- while left > 0 {
68- let n = read ( read_fd, & mut buf) ?;
69- assert_ne ! ( n, 0 , "unexpected end of pipe" ) ;
70- let mut written = 0 ;
71- while written < n {
72- match write ( write_fd, & buf[ written..n] ) ? {
73- 0 => unreachable ! ( "fd should be writable" ) ,
74- w => written += w,
75- }
76- }
77- left -= n;
78- }
79- Ok ( ( ) )
80- }
0 commit comments