diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index be47e5c28..46c0d7195 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -496,11 +496,16 @@ fn write_fast(handle: &mut InputHandle) -> CatResult<()> { // If we're not on Linux or Android, or the splice() call failed, // fall back on slower writing. let mut buf = [0; 1024 * 64]; - while let Ok(n) = handle.reader.read(&mut buf) { - if n == 0 { - break; + loop { + match handle.reader.read(&mut buf) { + Ok(n) => { + if n == 0 { + break; + } + stdout_lock.write_all(&buf[..n])?; + } + Err(e) => return Err(e.into()), } - stdout_lock.write_all(&buf[..n])?; } // If the splice() call failed and there has been some data written to diff --git a/tests/by-util/test_cat.rs b/tests/by-util/test_cat.rs index 9fca79753..6433e726b 100644 --- a/tests/by-util/test_cat.rs +++ b/tests/by-util/test_cat.rs @@ -713,6 +713,26 @@ fn test_u_ignored() { } } +#[test] +#[cfg(unix)] +fn test_write_fast_read_error() { + use std::os::unix::fs::PermissionsExt; + + let (at, mut ucmd) = at_and_ucmd!(); + + // Create a file with content + at.write("foo", "content"); + + // Remove read permissions to cause a read error + let file_path = at.plus_as_string("foo"); + let mut perms = std::fs::metadata(&file_path).unwrap().permissions(); + perms.set_mode(0o000); // No permissions + std::fs::set_permissions(&file_path, perms).unwrap(); + + // Test that cat fails with permission denied + ucmd.arg("foo").fails().stderr_contains("Permission denied"); +} + #[test] #[cfg(target_os = "linux")] fn test_appending_same_input_output() {