From 6900638ac6a84a9cd4313df93ef3502dcfa30dd2 Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Wed, 16 Feb 2022 21:32:38 -0500 Subject: [PATCH] dd: don't error when outfile is /dev/null Prevent `dd` from terminating with an error when given the command-line argument `of=/dev/null`. This commit allows the call to `File::set_len()` to result in an error without causing the process to terminate prematurely. --- src/uu/dd/src/dd.rs | 11 +++++++++-- tests/by-util/test_dd.rs | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index b38671a9a..1ce64bb78 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -521,10 +521,17 @@ impl OutputTrait for Output { let mut dst = open_dst(Path::new(&fname), &cflags, &oflags) .map_err_context(|| format!("failed to open {}", fname.quote()))?; + // Seek to the index in the output file, truncating if requested. + // + // Calling `set_len()` may result in an error (for + // example, when calling it on `/dev/null`), but we don't + // want to terminate the process when that happens. + // Instead, we suppress the error by calling + // `Result::ok()`. This matches the behavior of GNU `dd` + // when given the command-line argument `of=/dev/null`. let i = seek.unwrap_or(0).try_into().unwrap(); if !cflags.notrunc { - dst.set_len(i) - .map_err_context(|| "failed to truncate output file".to_string())?; + dst.set_len(i).ok(); } dst.seek(io::SeekFrom::Start(i)) .map_err_context(|| "failed to seek in output file".to_string())?; diff --git a/tests/by-util/test_dd.rs b/tests/by-util/test_dd.rs index 7a52488eb..04f5490ec 100644 --- a/tests/by-util/test_dd.rs +++ b/tests/by-util/test_dd.rs @@ -1095,3 +1095,10 @@ fn test_truncated_record() { .stdout_is("ac") .stderr_is("0+1 records in\n0+1 records out\n2 truncated records\n"); } + +/// Test that the output file can be `/dev/null`. +#[cfg(unix)] +#[test] +fn test_outfile_dev_null() { + new_ucmd!().arg("of=/dev/null").succeeds().no_stdout(); +}