@@ -24,9 +24,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
2424 let matches = uucore:: clap_localization:: handle_clap_result ( uu_app ( ) , args) ?;
2525
2626 #[ allow( clippy:: unwrap_used, reason = "clap provides 'y' by default" ) ]
27- let buffer = args_into_buffer ( matches. get_many :: < OsString > ( "STRING" ) . unwrap ( ) ) ?;
28-
29- match exec ( buffer) {
27+ let mut buffer = args_into_buffer ( matches. get_many :: < OsString > ( "STRING" ) . unwrap ( ) ) ?;
28+ repeat_content_to_capacity ( & mut buffer ) ;
29+ match exec ( & buffer) {
3030 Ok ( ( ) ) => Ok ( ( ) ) ,
3131 // On Windows, silently handle broken pipe since there's no SIGPIPE
3232 #[ cfg( windows) ]
@@ -96,51 +96,42 @@ fn repeat_content_to_capacity(buf: &mut Vec<u8>) {
9696}
9797
9898#[ cfg( not( any( target_os = "linux" , target_os = "android" ) ) ) ]
99- pub fn exec ( mut bytes : Vec < u8 > ) -> io:: Result < ( ) > {
100- repeat_content_to_capacity ( & mut bytes) ;
101- let bytes = bytes. as_slice ( ) ;
99+ pub fn exec ( bytes : & [ u8 ] ) -> io:: Result < ( ) > {
102100 let mut stdout = io:: stdout ( ) . lock ( ) ;
103101 loop {
104102 stdout. write_all ( bytes) ?;
105103 }
106104}
107105
108106#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
109- pub fn exec ( mut bytes : Vec < u8 > ) -> io:: Result < ( ) > {
107+ pub fn exec ( bytes : & [ u8 ] ) -> io:: Result < ( ) > {
110108 use uucore:: io:: RawWriter ;
111109 use uucore:: pipes:: { pipe, splice, tee} ;
112110
113- let safe_partial_send = rustix:: pipe:: PIPE_BUF . is_multiple_of ( bytes. len ( ) ) ;
114- repeat_content_to_capacity ( & mut bytes) ;
115- let bytes = bytes. as_slice ( ) ;
116111 let stdout = rustix:: stdio:: stdout ( ) ;
117112 // improve throughput
118113 let _ = rustix:: pipe:: fcntl_setpipe_size ( stdout, MAX_ROOTLESS_PIPE_SIZE ) ;
119114 // don't show any error from fast-path and fallback to write for proper message
115+ // tee() cannot control offset. We can do tee only if original bytes.len() is multiple of PIPE_BUF,
116+ // but it is slower than mixing splice even it reduces syscalls...
120117 if let Ok ( ( p_read, mut p_write) ) = pipe :: < true > ( )
121118 && p_write. write_all ( bytes) . is_ok ( )
119+ && let Ok ( ( broker_read, broker_write) ) = pipe :: < true > ( )
122120 {
123- // tee() cannot control offset. But omit splice if it is possible
124- if safe_partial_send {
125- // fails if stdout is not a pipe
126- while tee ( & p_read, & stdout, MAX_ROOTLESS_PIPE_SIZE ) . is_ok ( ) { }
127- }
128- if let Ok ( ( broker_read, broker_write) ) = pipe :: < true > ( ) {
129- ' splice: while let Ok ( mut remain) = tee ( & p_read, & broker_write, MAX_ROOTLESS_PIPE_SIZE )
130- {
131- debug_assert ! ( remain == bytes. len( ) , "splice() should cleanup pipe" ) ;
132- while remain > 0 {
133- if let Ok ( s) = splice ( & broker_read, & stdout, remain) {
134- remain -= s;
135- } else {
136- // avoid output breakage with reduced remain even if it would not happen
137- RawWriter ( stdout) . write_all ( & bytes[ bytes. len ( ) - remain..] ) ?;
138- break ' splice;
139- }
121+ ' splice: while let Ok ( mut remain) = tee ( & p_read, & broker_write, MAX_ROOTLESS_PIPE_SIZE ) {
122+ debug_assert ! ( remain == bytes. len( ) , "splice() should cleanup pipe" ) ;
123+ while remain > 0 {
124+ if let Ok ( s) = splice ( & broker_read, & stdout, remain) {
125+ remain -= s;
126+ } else {
127+ // avoid output breakage with reduced remain even if it would not happen
128+ RawWriter ( stdout) . write_all ( & bytes[ bytes. len ( ) - remain..] ) ?;
129+ break ' splice;
140130 }
141131 }
142132 }
143133 }
134+
144135 // fallback
145136 let mut stdout = RawWriter ( stdout) ;
146137 loop {
0 commit comments