From b686ea42f0a3430ca2bf09294a2fceb82324d00c Mon Sep 17 00:00:00 2001 From: oech3 <79379754+oech3@users.noreply.github.com> Date: Sat, 27 Jun 2026 23:21:55 +0900 Subject: [PATCH] cat: change is_unsafe_override to is_safe_override --- src/uu/cat/src/cat.rs | 6 ++--- src/uu/cat/src/platform/mod.rs | 8 +++---- src/uu/cat/src/platform/unix.rs | 38 +++++++++++++++--------------- src/uu/cat/src/platform/windows.rs | 6 ++--- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/uu/cat/src/cat.rs b/src/uu/cat/src/cat.rs index 0075272733e..cfd236d5b8e 100644 --- a/src/uu/cat/src/cat.rs +++ b/src/uu/cat/src/cat.rs @@ -7,7 +7,7 @@ mod platform; -use crate::platform::is_unsafe_overwrite; +use crate::platform::is_safe_overwrite; use clap::{Arg, ArgAction, Command}; use memchr::memchr2; use std::ffi::OsString; @@ -370,7 +370,7 @@ fn cat_path(path: &OsString, options: &OutputOptions, state: &mut OutputState) - InputType::StdIn => { let stdin = io::stdin(); let is_interactive = stdin.is_terminal(); - if is_unsafe_overwrite(&stdin, &io::stdout()) { + if !is_safe_overwrite(&stdin, &io::stdout()) { return Err(CatError::OutputIsInput); } let mut handle = InputHandle { @@ -384,7 +384,7 @@ fn cat_path(path: &OsString, options: &OutputOptions, state: &mut OutputState) - InputType::Socket => Err(CatError::NoSuchDeviceOrAddress), _ => { let file = File::open(path)?; - if is_unsafe_overwrite(&file, &io::stdout()) { + if !is_safe_overwrite(&file, &io::stdout()) { return Err(CatError::OutputIsInput); } let mut handle = InputHandle { diff --git a/src/uu/cat/src/platform/mod.rs b/src/uu/cat/src/platform/mod.rs index 80ef6e233ac..cde1ee96cbb 100644 --- a/src/uu/cat/src/platform/mod.rs +++ b/src/uu/cat/src/platform/mod.rs @@ -4,15 +4,15 @@ // file that was distributed with this source code. #[cfg(unix)] -pub use self::unix::is_unsafe_overwrite; +pub use self::unix::is_safe_overwrite; #[cfg(windows)] -pub use self::windows::is_unsafe_overwrite; +pub use self::windows::is_safe_overwrite; // WASI: no fstat-based device/inode checks available; assume safe. #[cfg(target_os = "wasi")] -pub fn is_unsafe_overwrite(_input: &I, _output: &O) -> bool { - false +pub fn is_safe_overwrite(_input: &I, _output: &O) -> bool { + true } #[cfg(unix)] diff --git a/src/uu/cat/src/platform/unix.rs b/src/uu/cat/src/platform/unix.rs index aaabfd3d6c7..dbd4b76762e 100644 --- a/src/uu/cat/src/platform/unix.rs +++ b/src/uu/cat/src/platform/unix.rs @@ -14,36 +14,36 @@ use uucore::fs::FileInformation; /// In this scenario, bytes read from stdin are written to a later part of the file /// via stdout, which can then be read again by stdin and written again by stdout, /// causing an infinite loop and potential file corruption. -pub fn is_unsafe_overwrite(input: &I, output: &O) -> bool { +pub fn is_safe_overwrite(input: &I, output: &O) -> bool { // `FileInformation::from_file` returns an error if the file descriptor is closed, invalid, // or refers to a non-regular file (e.g., socket, pipe, or special device). let Ok(input_info) = FileInformation::from_file(input) else { - return false; + return true; }; let Ok(output_info) = FileInformation::from_file(output) else { - return false; + return true; }; if input_info != output_info { - return false; + return true; } let file_size = output_info.file_size(); if file_size == 0 { - return false; + return true; } // `seek` returns an error if the file descriptor is closed or it refers to // a non-seekable resource (e.g., pipe, socket, or some devices). let input_pos = rustix::fs::seek(input, SeekFrom::Current(0)).map(|v| v as i64); let output_pos = rustix::fs::seek(output, SeekFrom::Current(0)).map(|v| v as i64); if is_appending(output) { - return !input_pos.is_ok_and(|pos| pos >= 0 && (pos as u64) >= file_size); + return input_pos.is_ok_and(|pos| pos >= 0 && (pos as u64) >= file_size); } let Ok(input_pos) = input_pos else { - return false; + return true; }; let Ok(output_pos) = output_pos else { - return false; + return true; }; - input_pos < output_pos + input_pos >= output_pos } /// Whether the file is opened with the `O_APPEND` flag @@ -54,7 +54,7 @@ fn is_appending(file: &F) -> bool { #[cfg(test)] mod tests { - use crate::platform::unix::{is_appending, is_unsafe_overwrite}; + use crate::platform::unix::{is_appending, is_safe_overwrite}; use std::fs::OpenOptions; use std::io::{Seek, SeekFrom, Write}; use tempfile::NamedTempFile; @@ -75,7 +75,7 @@ mod tests { } #[test] - fn test_is_unsafe_overwrite() { + fn test_is_safe_overwrite() { // Create two temp files one of which is empty let empty = NamedTempFile::new().unwrap(); let mut nonempty = NamedTempFile::new().unwrap(); @@ -83,30 +83,30 @@ mod tests { nonempty.seek(SeekFrom::Start(0)).unwrap(); // Using a different file as input and output does not result in an overwrite - assert!(!is_unsafe_overwrite(&empty, &nonempty)); + assert!(is_safe_overwrite(&empty, &nonempty)); // Overwriting an empty file is always safe - assert!(!is_unsafe_overwrite(&empty, &empty)); + assert!(is_safe_overwrite(&empty, &empty)); // Overwriting a nonempty file with itself is safe - assert!(!is_unsafe_overwrite(&nonempty, &nonempty)); + assert!(is_safe_overwrite(&nonempty, &nonempty)); // Overwriting an empty file opened in append mode is safe let empty_append = OpenOptions::new().append(true).open(&empty).unwrap(); - assert!(!is_unsafe_overwrite(&empty, &empty_append)); + assert!(is_safe_overwrite(&empty, &empty_append)); // Overwriting a nonempty file opened in append mode is unsafe let nonempty_append = OpenOptions::new().append(true).open(&nonempty).unwrap(); - assert!(is_unsafe_overwrite(&nonempty, &nonempty_append)); + assert!(!is_safe_overwrite(&nonempty, &nonempty_append)); // Overwriting a file opened in write mode is safe let mut nonempty_write = OpenOptions::new().write(true).open(&nonempty).unwrap(); - assert!(!is_unsafe_overwrite(&nonempty, &nonempty_write)); + assert!(is_safe_overwrite(&nonempty, &nonempty_write)); // Overwriting a file when the input and output file descriptors are pointing to // different offsets is safe if the input offset is further than the output offset nonempty_write.seek(SeekFrom::Start(1)).unwrap(); - assert!(!is_unsafe_overwrite(&nonempty_write, &nonempty)); - assert!(is_unsafe_overwrite(&nonempty, &nonempty_write)); + assert!(is_safe_overwrite(&nonempty_write, &nonempty)); + assert!(!is_safe_overwrite(&nonempty, &nonempty_write)); } } diff --git a/src/uu/cat/src/platform/windows.rs b/src/uu/cat/src/platform/windows.rs index ae7ff7a78d5..a91f66097f2 100644 --- a/src/uu/cat/src/platform/windows.rs +++ b/src/uu/cat/src/platform/windows.rs @@ -14,10 +14,10 @@ use windows_sys::Win32::Storage::FileSystem::{ /// An unsafe overwrite occurs when the same file is used as both stdin and stdout /// and the stdout file is not empty. -pub fn is_unsafe_overwrite(input: &I, output: &O) -> bool { - is_same_file_by_path(input, output) && +pub fn is_safe_overwrite(input: &I, output: &O) -> bool { + !is_same_file_by_path(input, output) || // Check if the output file is empty - FileInformation::from_file(output).is_ok_and(|info| info.file_size() > 0) + !FileInformation::from_file(output).is_ok_and(|info| info.file_size() > 0) } /// Get the file path for a file handle