1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

cat: Fix reporting "input file is output file" error when outputting to an input file (#8025)

* cat: Check if a file can be overwritten safely in Unix

* cat: Check if a file can be overwritten safely in Windows

* cat: Test writing read-write file that is input and output

* cat: Unit test `is_appending` function

* cat: Unit test `is_unsafe_overwrite` function

* cat: Comment why a few function calls could return Err

* cat: Remove obvious comments from test
This commit is contained in:
Teemu Pätsi 2025-06-06 13:01:31 +03:00 committed by GitHub
parent 9e21259e2d
commit 4d40671d79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 253 additions and 43 deletions

View file

@ -9,6 +9,7 @@ use rlimit::Resource;
#[cfg(unix)]
use std::fs::File;
use std::fs::OpenOptions;
use std::fs::read_to_string;
use std::process::Stdio;
use uutests::at_and_ucmd;
use uutests::new_ucmd;
@ -637,6 +638,57 @@ fn test_write_to_self() {
);
}
/// Test derived from the following GNU test in `tests/cat/cat-self.sh`:
///
/// `cat fxy2 fy 1<>fxy2`
// TODO: make this work on windows
#[test]
#[cfg(unix)]
fn test_successful_write_to_read_write_self() {
let (at, mut ucmd) = at_and_ucmd!();
at.write("fy", "y");
at.write("fxy2", "x");
// Open `rw_file` as both stdin and stdout (read/write)
let fxy2_file_path = at.plus("fxy2");
let fxy2_file = OpenOptions::new()
.read(true)
.write(true)
.open(&fxy2_file_path)
.unwrap();
ucmd.args(&["fxy2", "fy"]).set_stdout(fxy2_file).succeeds();
// The contents of `fxy2` and `fy` files should be merged
let fxy2_contents = read_to_string(fxy2_file_path).unwrap();
assert_eq!(fxy2_contents, "xy");
}
/// Test derived from the following GNU test in `tests/cat/cat-self.sh`:
///
/// `cat fx fx3 1<>fx3`
#[test]
fn test_failed_write_to_read_write_self() {
let (at, mut ucmd) = at_and_ucmd!();
at.write("fx", "g");
at.write("fx3", "bold");
// Open `rw_file` as both stdin and stdout (read/write)
let fx3_file_path = at.plus("fx3");
let fx3_file = OpenOptions::new()
.read(true)
.write(true)
.open(&fx3_file_path)
.unwrap();
ucmd.args(&["fx", "fx3"])
.set_stdout(fx3_file)
.fails_with_code(1)
.stderr_only("cat: fx3: input file is output file\n");
// The contents of `fx` should have overwritten the beginning of `fx3`
let fx3_contents = read_to_string(fx3_file_path).unwrap();
assert_eq!(fx3_contents, "gold");
}
#[test]
#[cfg(unix)]
#[cfg(not(target_os = "openbsd"))]