diff --git a/src/uucore/src/lib/features/buf_copy.rs b/src/uucore/src/lib/features/buf_copy.rs index bff94e94e38..da2eda56adb 100644 --- a/src/uucore/src/lib/features/buf_copy.rs +++ b/src/uucore/src/lib/features/buf_copy.rs @@ -51,20 +51,6 @@ mod tests { .unwrap() } - #[cfg(any(target_os = "linux", target_os = "android"))] - #[test] - fn test_copy_exact() { - let (mut pipe_read, mut pipe_write) = pipes::pipe().unwrap(); - let data = b"Hello, world!"; - let n = pipe_write.write(data).unwrap(); - assert_eq!(n, data.len()); - let mut buf = [0; 1024]; - let n = copy_exact(&pipe_read, &pipe_write, data.len()).unwrap(); - let n2 = pipe_read.read(&mut buf).unwrap(); - assert_eq!(n, n2); - assert_eq!(&buf[..n], data); - } - #[test] #[cfg(unix)] fn test_copy_stream() { diff --git a/src/uucore/src/lib/features/buf_copy/linux.rs b/src/uucore/src/lib/features/buf_copy/linux.rs index 9fd5cf75b24..02fea00cd4c 100644 --- a/src/uucore/src/lib/features/buf_copy/linux.rs +++ b/src/uucore/src/lib/features/buf_copy/linux.rs @@ -28,8 +28,6 @@ pub trait FdWritable: Write + AsFd + AsRawFd {} impl FdWritable for T where T: Write + AsFd + AsRawFd {} -const BUF_SIZE: usize = 1024 * 16; - /// Conversion from a `rustix::io::Errno` into our `Error` which implements `UError`. impl From for Error { fn from(error: rustix::io::Errno) -> Self { @@ -55,7 +53,7 @@ where { // If we're on Linux or Android, try to use the splice() system call // for faster writing. If it works, we're done. - if !splice_write(src, &dest.as_fd())? { + if !splice_write(src, dest)? { return Ok(()); } @@ -78,17 +76,17 @@ where /// - `source` - source handle /// - `dest` - destination handle #[inline] -pub(crate) fn splice_write(source: &R, dest: &S) -> UResult +pub(crate) fn splice_write(source: &R, dest: &mut S) -> UResult where R: Read + AsFd + AsRawFd, - S: AsRawFd + AsFd, + S: AsRawFd + AsFd + Write, { - let (pipe_rd, pipe_wr) = pipe()?; + let (pipe_rd, pipe_wr) = pipe()?; // todo: bypass this if input or output is pipe. We use this mostly for stream. // improve throughput // no need to increase pipe size of input fd since // - sender with splice probably increased size already // - sender without splice is bottleneck - let _ = rustix::pipe::fcntl_setpipe_size(dest, MAX_ROOTLESS_PIPE_SIZE); + let _ = rustix::pipe::fcntl_setpipe_size(&mut *dest, MAX_ROOTLESS_PIPE_SIZE); loop { match splice(&source, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) { @@ -100,7 +98,9 @@ where // we can recover by copying the data that we have from the // intermediate pipe to stdout using normal read/write. Then // we tell the caller to fall back. - copy_exact(&pipe_rd, dest, n)?; + let mut drain = Vec::with_capacity(n); // bounded by pipe size + pipe_rd.take(n as u64).read_to_end(&mut drain)?; + dest.write_all(&drain)?; return Ok(true); } } @@ -108,28 +108,3 @@ where } } } - -/// Move exactly `num_bytes` bytes from `read_fd` to `write_fd` using the `read` -/// and `write` calls. -#[cfg(any(target_os = "linux", target_os = "android"))] -pub(crate) fn copy_exact( - read_fd: &impl AsFd, - write_fd: &impl AsFd, - num_bytes: usize, -) -> std::io::Result { - let mut left = num_bytes; - let mut buf = [0; BUF_SIZE]; - let mut total_written = 0; - while left > 0 { - let n_read = rustix::io::read(read_fd, &mut buf)?; - assert_ne!(n_read, 0, "unexpected end of pipe"); - let mut written = 0; - while written < n_read { - let n = rustix::io::write(write_fd, &buf[written..n_read])?; - written += n; - } - total_written += written; - left -= n_read; - } - Ok(total_written) -}