From fe5b537f567774f1cb43d2ca51bb141090233faf Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Fri, 28 Jan 2022 22:24:07 -0500 Subject: [PATCH 1/2] truncate: error when trying to truncate a fifo Terminate the `truncate` program with an error message when trying to truncate a named pipe (also known as a fifo). --- src/uu/truncate/src/truncate.rs | 43 ++++++++++++++++++++++++++++++++- tests/by-util/test_truncate.rs | 35 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/uu/truncate/src/truncate.rs b/src/uu/truncate/src/truncate.rs index 685363f8f..5072502db 100644 --- a/src/uu/truncate/src/truncate.rs +++ b/src/uu/truncate/src/truncate.rs @@ -10,6 +10,8 @@ use clap::{crate_version, App, AppSettings, Arg}; use std::convert::TryFrom; use std::fs::{metadata, OpenOptions}; use std::io::ErrorKind; +#[cfg(unix)] +use std::os::unix::fs::FileTypeExt; use std::path::Path; use uucore::display::Quotable; use uucore::error::{FromIo, UResult, USimpleError, UUsageError}; @@ -207,6 +209,8 @@ fn file_truncate(filename: &str, create: bool, size: usize) -> std::io::Result<( /// /// If the any file could not be opened, or there was a problem setting /// the size of at least one file. +/// +/// If at least one file is a named pipe (also known as a fifo). fn truncate_reference_and_size( rfilename: &str, size_string: &str, @@ -239,6 +243,17 @@ fn truncate_reference_and_size( let fsize = metadata.len() as usize; let tsize = mode.to_size(fsize); for filename in filenames { + #[cfg(unix)] + if std::fs::metadata(filename)?.file_type().is_fifo() { + return Err(USimpleError::new( + 1, + format!( + "cannot open {} for writing: No such device or address", + filename.quote() + ), + )); + } + file_truncate(filename, create, tsize) .map_err_context(|| format!("cannot open {} for writing", filename.quote()))?; } @@ -256,6 +271,8 @@ fn truncate_reference_and_size( /// /// If the any file could not be opened, or there was a problem setting /// the size of at least one file. +/// +/// If at least one file is a named pipe (also known as a fifo). fn truncate_reference_file_only( rfilename: &str, filenames: &[String], @@ -273,6 +290,16 @@ fn truncate_reference_file_only( })?; let tsize = metadata.len() as usize; for filename in filenames { + #[cfg(unix)] + if std::fs::metadata(filename)?.file_type().is_fifo() { + return Err(USimpleError::new( + 1, + format!( + "cannot open {} for writing: No such device or address", + filename.quote() + ), + )); + } file_truncate(filename, create, tsize) .map_err_context(|| format!("cannot open {} for writing", filename.quote()))?; } @@ -294,6 +321,8 @@ fn truncate_reference_file_only( /// /// If the any file could not be opened, or there was a problem setting /// the size of at least one file. +/// +/// If at least one file is a named pipe (also known as a fifo). fn truncate_size_only(size_string: &str, filenames: &[String], create: bool) -> UResult<()> { let mode = parse_mode_and_size(size_string) .map_err(|e| USimpleError::new(1, format!("Invalid number: {}", e)))?; @@ -302,7 +331,19 @@ fn truncate_size_only(size_string: &str, filenames: &[String], create: bool) -> } for filename in filenames { let fsize = match metadata(filename) { - Ok(m) => m.len(), + Ok(m) => { + #[cfg(unix)] + if m.file_type().is_fifo() { + return Err(USimpleError::new( + 1, + format!( + "cannot open {} for writing: No such device or address", + filename.quote() + ), + )); + } + m.len() + } Err(_) => 0, }; let tsize = mode.to_size(fsize as usize); diff --git a/tests/by-util/test_truncate.rs b/tests/by-util/test_truncate.rs index 0ef65ec16..716c77ab0 100644 --- a/tests/by-util/test_truncate.rs +++ b/tests/by-util/test_truncate.rs @@ -398,3 +398,38 @@ fn test_underflow_relative_size() { assert!(at.file_exists(FILE1)); assert!(at.read_bytes(FILE1).is_empty()); } + +#[cfg(not(windows))] +#[test] +fn test_fifo_error_size_only() { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkfifo("fifo"); + ucmd.args(&["-s", "0", "fifo"]) + .fails() + .no_stdout() + .stderr_contains("cannot open 'fifo' for writing: No such device or address"); +} + +#[cfg(not(windows))] +#[test] +fn test_fifo_error_reference_file_only() { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkfifo("fifo"); + at.make_file("reference_file"); + ucmd.args(&["-r", "reference_file", "fifo"]) + .fails() + .no_stdout() + .stderr_contains("cannot open 'fifo' for writing: No such device or address"); +} + +#[cfg(not(windows))] +#[test] +fn test_fifo_error_reference_and_size() { + let (at, mut ucmd) = at_and_ucmd!(); + at.mkfifo("fifo"); + at.make_file("reference_file"); + ucmd.args(&["-r", "reference_file", "-s", "+0", "fifo"]) + .fails() + .no_stdout() + .stderr_contains("cannot open 'fifo' for writing: No such device or address"); +} From 371278e043389d80afa48ac5dd7c6bc0d6cb8aeb Mon Sep 17 00:00:00 2001 From: Jeffrey Finkelstein Date: Sat, 29 Jan 2022 12:20:11 -0500 Subject: [PATCH 2/2] truncate: fix typo in docs: "the any" -> "any" --- src/uu/truncate/src/truncate.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uu/truncate/src/truncate.rs b/src/uu/truncate/src/truncate.rs index 5072502db..fdcef0706 100644 --- a/src/uu/truncate/src/truncate.rs +++ b/src/uu/truncate/src/truncate.rs @@ -207,7 +207,7 @@ fn file_truncate(filename: &str, create: bool, size: usize) -> std::io::Result<( /// /// # Errors /// -/// If the any file could not be opened, or there was a problem setting +/// If any file could not be opened, or there was a problem setting /// the size of at least one file. /// /// If at least one file is a named pipe (also known as a fifo). @@ -269,7 +269,7 @@ fn truncate_reference_and_size( /// /// # Errors /// -/// If the any file could not be opened, or there was a problem setting +/// If any file could not be opened, or there was a problem setting /// the size of at least one file. /// /// If at least one file is a named pipe (also known as a fifo). @@ -319,7 +319,7 @@ fn truncate_reference_file_only( /// /// # Errors /// -/// If the any file could not be opened, or there was a problem setting +/// If any file could not be opened, or there was a problem setting /// the size of at least one file. /// /// If at least one file is a named pipe (also known as a fifo).