From d002810a47a9604f578377fead4ca2efe5eda158 Mon Sep 17 00:00:00 2001 From: Jan Verbeek Date: Fri, 27 Aug 2021 20:10:28 +0200 Subject: [PATCH] cat: Do not assume complete writes --- src/uu/cat/src/splice.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/uu/cat/src/splice.rs b/src/uu/cat/src/splice.rs index 66630060c..5ce5f2b62 100644 --- a/src/uu/cat/src/splice.rs +++ b/src/uu/cat/src/splice.rs @@ -44,21 +44,23 @@ pub(super) fn write_fast_using_splice( } } -/// Caller must ensure that `num_bytes <= BUF_SIZE`, otherwise this function -/// will panic. The way we use this function in `write_fast_using_splice` -/// above is safe because `splice` is set to write at most `BUF_SIZE` to the -/// pipe. -#[inline] +/// Move exactly `num_bytes` bytes from `read_fd` to `write_fd`. +/// +/// Panics if not enough bytes can be read. fn copy_exact(read_fd: RawFd, write_fd: RawFd, num_bytes: usize) -> nix::Result<()> { let mut left = num_bytes; let mut buf = [0; BUF_SIZE]; - loop { - let read = unistd::read(read_fd, &mut buf[..left])?; - let written = unistd::write(write_fd, &buf[..read])?; - left -= written; - if left == 0 { - break; + while left > 0 { + let read = unistd::read(read_fd, &mut buf)?; + assert_ne!(read, 0, "unexpected end of pipe"); + let mut written = 0; + while written < read { + match unistd::write(write_fd, &buf[written..read])? { + 0 => panic!(), + n => written += n, + } } + left -= read; } Ok(()) }