diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index de47ea977..ca87da2a8 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -11,8 +11,7 @@ use std::fs::File; use std::io::{self, stdin, BufReader, Read}; use std::path::Path; use uucore::display::Quotable; -use uucore::error::UResult; -use uucore::error::USimpleError; +use uucore::error::{FromIo, UResult}; use uucore::show; use uucore::InvalidEncodingHandling; @@ -81,27 +80,18 @@ fn cksum(fname: &str) -> io::Result<(u32, usize)> { let mut crc = 0u32; let mut size = 0usize; - let file; let mut rd: Box = match fname { "-" => Box::new(stdin()), _ => { - let path = &Path::new(fname); - if path.is_dir() { - return Err(std::io::Error::new( - io::ErrorKind::InvalidInput, - "Is a directory", - )); - }; - // Silent the warning as we want to the error message - #[allow(clippy::question_mark)] - if path.metadata().is_err() { - return Err(std::io::Error::new( - io::ErrorKind::NotFound, - "No such file or directory", - )); - }; - file = File::open(&path)?; - Box::new(BufReader::new(file)) + let p = Path::new(fname); + + // Directories should not give an error, but should be interpreted + // as empty files to match GNU semantics. + if p.is_dir() { + Box::new(BufReader::new(io::empty())) as Box + } else { + Box::new(BufReader::new(File::open(p)?)) as Box + } } }; @@ -136,23 +126,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { }; if files.is_empty() { - match cksum("-") { - Ok((crc, size)) => println!("{} {}", crc, size), - Err(err) => { - return Err(USimpleError::new(2, format!("{}", err))); - } - } + let (crc, size) = cksum("-")?; + println!("{} {}", crc, size); return Ok(()); } for fname in &files { - match cksum(fname.as_ref()) { + match cksum(fname.as_ref()).map_err_context(|| format!("{}", fname.maybe_quote())) { Ok((crc, size)) => println!("{} {} {}", crc, size, fname), - Err(err) => show!(USimpleError::new( - 2, - format!("{}: {}", fname.maybe_quote(), err) - )), - } + Err(err) => show!(err), + }; } Ok(()) } diff --git a/src/uucore/src/lib/mods/error.rs b/src/uucore/src/lib/mods/error.rs index c04a0f2f1..37231576f 100644 --- a/src/uucore/src/lib/mods/error.rs +++ b/src/uucore/src/lib/mods/error.rs @@ -371,7 +371,7 @@ impl UError for UUsageError { /// ``` #[derive(Debug)] pub struct UIoError { - context: String, + context: Option, inner: std::io::Error, } @@ -379,7 +379,7 @@ impl UIoError { #[allow(clippy::new_ret_no_self)] pub fn new>(kind: std::io::ErrorKind, context: S) -> Box { Box::new(Self { - context: context.into(), + context: Some(context.into()), inner: kind.into(), }) } @@ -435,7 +435,11 @@ impl Display for UIoError { capitalize(&mut message); &message }; - write!(f, "{}: {}", self.context, message) + if let Some(ctx) = &self.context { + write!(f, "{}: {}", ctx, message) + } else { + write!(f, "{}", message) + } } } @@ -464,7 +468,7 @@ pub trait FromIo { impl FromIo> for std::io::Error { fn map_err_context(self, context: impl FnOnce() -> String) -> Box { Box::new(UIoError { - context: (context)(), + context: Some((context)()), inner: self, }) } @@ -479,12 +483,28 @@ impl FromIo> for std::io::Result { impl FromIo> for std::io::ErrorKind { fn map_err_context(self, context: impl FnOnce() -> String) -> Box { Box::new(UIoError { - context: (context)(), + context: Some((context)()), inner: std::io::Error::new(self, ""), }) } } +impl From for UIoError { + fn from(f: std::io::Error) -> UIoError { + UIoError { + context: None, + inner: f, + } + } +} + +impl From for Box { + fn from(f: std::io::Error) -> Box { + let u_error: UIoError = f.into(); + Box::new(u_error) as Box + } +} + /// Shorthand to construct [`UIoError`]-instances. /// /// This macro serves as a convenience call to quickly construct instances of diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index bf31ceb18..66bdba9e3 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -74,9 +74,8 @@ fn test_invalid_file() { at.mkdir(folder_name); ts.ucmd() .arg(folder_name) - .fails() - .no_stdout() - .stderr_contains("cksum: asdf: Is a directory"); + .succeeds() + .stdout_only("4294967295 0 asdf\n"); } // Make sure crc is correct for files larger than 32 bytes