From 70f3f2da42f0f79f3f5f089ab621af7a4c89e541 Mon Sep 17 00:00:00 2001 From: mattsu Date: Wed, 30 Sep 2026 21:01:54 +0900 Subject: [PATCH 1/3] tee: exercise short writes through splice fallback --- tests/by-util/test_tee.rs | 33 ++++++++++++++++++++++++++++++++- util/build-gnu.sh | 6 ++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/by-util/test_tee.rs b/tests/by-util/test_tee.rs index f8bad5aa834..1bc256d673c 100644 --- a/tests/by-util/test_tee.rs +++ b/tests/by-util/test_tee.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore nopipe +// spell-checker:ignore nopipe EFBIG Fsize SIGXFSZ XFSZ #![allow(clippy::borrow_as_ptr)] @@ -262,6 +262,37 @@ mod linux_only { use uutests::at_and_ucmd; use uutests::new_ucmd; + #[test] + fn test_tee_append_short_write_before_file_size_error() { + use rustix::process::Resource; + use uutests::util::TestScenario; + + const FILE_LIMIT: u64 = 4137; + + let content: Vec = (0..100_000).map(|n| (n % 251) as u8).collect(); + let scene = TestScenario::new("tee"); + let at = &scene.fixtures; + at.write_bytes("input", &content); + + // Append mode prevents splice from writing to the file, naturally + // exercising write_all: the file-size limit allows a prefix, then the + // retry fails. Ignore SIGXFSZ only in the child so it reports EFBIG + // without changing signal handling in other concurrently running tests. + scene + .cmd("sh") + .args(&["-c", "trap '' XFSZ; exec \"$@\"", "sh"]) + .arg(&scene.bin_path) + .args(&["tee", "-a", "limited"]) + .set_stdin(at.open("input")) + .set_stdout(Stdio::piped()) + .limit(Resource::Fsize, FILE_LIMIT, FILE_LIMIT) + .fails_with_code(1) + .stdout_is_bytes(&content) + .stderr_is("tee: limited: File too large\n"); + + assert_eq!(at.read_bytes("limited"), content[..FILE_LIMIT as usize]); + } + fn make_broken_pipe() -> std::io::PipeWriter { let (read, write) = std::io::pipe().expect("Failed to create pipe"); // Drop the read end of the pipe diff --git a/util/build-gnu.sh b/util/build-gnu.sh index 53d3e9694d1..53ceca5a3c1 100755 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -239,6 +239,12 @@ grep -rlE '/usr/local/bin/\s?/usr/local/bin' init.cfg tests/* | xargs -r "${SED} # we should not regress our project just to match what GNU is going. # So, do some changes on the fly +# Request faults in tee's optional splice path to exercise short-write retries +# through the read/write fallback, preserving the existing trace options. +# Avoid adding the fault option again when reusing the GNU test tree. +sed -i '/ -e fault=splice /!s/ -e trace=write /&-e fault=splice /' \ + tests/tee/short-write.sh + sed -i -e "s|removed directory 'a/'|removed directory 'a'|g" tests/rm/v-slash.sh # 'rel' doesn't exist. Our implementation is giving a better message. From bb04eb08dfb0004eb248c5620761fd3e0f56aad9 Mon Sep 17 00:00:00 2001 From: mattsu <35655889+mattsu2020@users.noreply.github.com> Date: Thu, 1 Oct 2026 08:08:48 +0900 Subject: [PATCH 2/3] Update util/build-gnu.sh Co-authored-by: oech3 <79379754+oech3@users.noreply.github.com> --- util/build-gnu.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/util/build-gnu.sh b/util/build-gnu.sh index 53ceca5a3c1..a9f36709286 100755 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -242,8 +242,7 @@ grep -rlE '/usr/local/bin/\s?/usr/local/bin' init.cfg tests/* | xargs -r "${SED} # Request faults in tee's optional splice path to exercise short-write retries # through the read/write fallback, preserving the existing trace options. # Avoid adding the fault option again when reusing the GNU test tree. -sed -i '/ -e fault=splice /!s/ -e trace=write /&-e fault=splice /' \ - tests/tee/short-write.sh +sed -i "s/strace/strace -e fault=splice/" tests/tee/short-write.sh sed -i -e "s|removed directory 'a/'|removed directory 'a'|g" tests/rm/v-slash.sh From dd0f016d2cc121cc138832515287bbe50d510b7a Mon Sep 17 00:00:00 2001 From: mattsu Date: Thu, 1 Oct 2026 08:44:18 +0900 Subject: [PATCH 3/3] tee: include splice in short-write fault injection --- util/build-gnu.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/util/build-gnu.sh b/util/build-gnu.sh index a9f36709286..7b9cfbf8685 100755 --- a/util/build-gnu.sh +++ b/util/build-gnu.sh @@ -239,10 +239,11 @@ grep -rlE '/usr/local/bin/\s?/usr/local/bin' init.cfg tests/* | xargs -r "${SED} # we should not regress our project just to match what GNU is going. # So, do some changes on the fly -# Request faults in tee's optional splice path to exercise short-write retries -# through the read/write fallback, preserving the existing trace options. -# Avoid adding the fault option again when reusing the GNU test tree. -sed -i "s/strace/strace -e fault=splice/" tests/tee/short-write.sh +# strace only injects faults into traced calls. Include splice to force tee's +# stdout path to use read/write and exercise short-write retries. The +# replacement stops matching after the first edit, avoiding duplicate options. +sed -i 's/-e trace=write /-e trace=write,splice -e fault=splice /' \ + tests/tee/short-write.sh sed -i -e "s|removed directory 'a/'|removed directory 'a'|g" tests/rm/v-slash.sh