From 6b6bd31ee5effa13bdd8710a00c6a9cf7eb534d8 Mon Sep 17 00:00:00 2001 From: Toggy Smith Date: Sat, 11 Jul 2026 15:56:37 +0100 Subject: [PATCH 1/2] fix: panics on redirect to /dev/full This fixes several panics that would occur when the stdout was redirected to /dev/full. This also introduces a new macro for this purpose, named `safe_println!()`, that does not panic in this situation, which can presumably be reused elsewhere this issue may reoccur in the future. --- src/cmp.rs | 3 ++- src/diff.rs | 2 +- src/macros.rs | 12 ++++++++++++ src/main.rs | 8 ++++---- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/cmp.rs b/src/cmp.rs index 0175466e..50a5325a 100644 --- a/src/cmp.rs +++ b/src/cmp.rs @@ -4,6 +4,7 @@ // files that was distributed with this source code. use crate::utils::format_failure_to_read_input_file; +use crate::safe_println; use std::env::{self, ArgsOs}; use std::ffi::OsString; use std::io::{BufRead, BufReader, BufWriter, Read, Write}; @@ -721,7 +722,7 @@ fn report_difference( format_visible_byte(to_byte) ); } - println!(); + safe_println!(); } #[cfg(test)] diff --git a/src/diff.rs b/src/diff.rs index f4c0614c..c0e5b8f5 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -91,7 +91,7 @@ pub fn main(opts: Peekable) -> ExitCode { params.to.to_string_lossy() ); } else { - io::stdout().write_all(&result).unwrap(); + let _ = io::stdout().write_all(&result); } if result.is_empty() { maybe_report_identical_files(); diff --git a/src/macros.rs b/src/macros.rs index 90a4eaaf..18bef119 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -23,3 +23,15 @@ macro_rules! assert_diff_eq { assert_eq!(actual, $expected); }}; } + +/// A safe version of println!() that does not panic if stdout is redirected to /dev/full +#[macro_export] +macro_rules! safe_println { + () => { + let _ = ::std::io::Write::write_all(&mut ::std::io::stdout(), b"\n"); + }; + ($($arg:tt)*) => { + let _ = ::std::io::Write::write_fmt(&mut ::std::io::stdout(), format_args!($($arg)*)) + .and_then(|_| ::std::io::Write::write_all(&mut ::std::io::stdout(), b"\n")); + }; +} diff --git a/src/main.rs b/src/main.rs index d0adb692..13efd173 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,10 +40,10 @@ fn name(binary_path: &Path) -> &OsStr { const VERSION: &str = env!("CARGO_PKG_VERSION"); fn usage(name: &str) { - println!("{name} {VERSION} (multi-call binary)\n"); - println!("Usage: {name} [function [arguments...]]\n"); - println!("Currently defined functions:\n"); - println!(" cmp, diff\n"); + safe_println!("{name} {VERSION} (multi-call binary)\n"); + safe_println!("Usage: {name} [function [arguments...]]\n"); + safe_println!("Currently defined functions:\n"); + safe_println!(" cmp, diff\n"); } fn second_arg_error(name: &OsStr) -> ! { From 6e4e3592ba9bbb0be6c856bdd061390d44f655de Mon Sep 17 00:00:00 2001 From: Toggy Smith Date: Sat, 11 Jul 2026 16:00:35 +0100 Subject: [PATCH 2/2] refactor: run cargo fmt --- src/cmp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmp.rs b/src/cmp.rs index 50a5325a..50c01632 100644 --- a/src/cmp.rs +++ b/src/cmp.rs @@ -3,8 +3,8 @@ // For the full copyright and license information, please view the LICENSE-* // files that was distributed with this source code. -use crate::utils::format_failure_to_read_input_file; use crate::safe_println; +use crate::utils::format_failure_to_read_input_file; use std::env::{self, ArgsOs}; use std::ffi::OsString; use std::io::{BufRead, BufReader, BufWriter, Read, Write};