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

hashsum: don't exit early on io errors

This commit is contained in:
Jeremy Smart 2025-05-11 19:10:08 -04:00
parent bcc02e9cea
commit 67acfbcbf3
No known key found for this signature in database
GPG key ID: 5AD8086D5DF29A8F
3 changed files with 39 additions and 8 deletions

View file

@ -33,10 +33,11 @@ const NAME: &str = "hashsum";
const ABOUT: &str = help_about!("hashsum.md"); const ABOUT: &str = help_about!("hashsum.md");
const USAGE: &str = help_usage!("hashsum.md"); const USAGE: &str = help_usage!("hashsum.md");
struct Options { struct Options<'a> {
algoname: &'static str, algoname: &'static str,
digest: Box<dyn Digest + 'static>, digest: Box<dyn Digest + 'static>,
binary: bool, binary: bool,
binary_name: &'a str,
//check: bool, //check: bool,
tag: bool, tag: bool,
nonames: bool, nonames: bool,
@ -274,6 +275,7 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
digest: (algo.create_fn)(), digest: (algo.create_fn)(),
output_bits: algo.bits, output_bits: algo.bits,
binary, binary,
binary_name: &binary_name,
tag: matches.get_flag("tag"), tag: matches.get_flag("tag"),
nonames, nonames,
//status, //status,
@ -520,17 +522,25 @@ where
I: Iterator<Item = &'a OsStr>, I: Iterator<Item = &'a OsStr>,
{ {
let binary_marker = if options.binary { "*" } else { " " }; let binary_marker = if options.binary { "*" } else { " " };
let mut err = None;
for filename in files { for filename in files {
let filename = Path::new(filename); let filename = Path::new(filename);
let stdin_buf;
let file_buf;
let mut file = BufReader::new(if filename == OsStr::new("-") { let mut file = BufReader::new(if filename == OsStr::new("-") {
stdin_buf = stdin(); Box::new(stdin()) as Box<dyn Read>
Box::new(stdin_buf) as Box<dyn Read>
} else { } else {
file_buf = let file_buf = match File::open(filename) {
File::open(filename).map_err_context(|| "failed to open file".to_string())?; Ok(f) => f,
Err(e) => {
eprintln!(
"{}: {}: {e}",
options.binary_name,
filename.to_string_lossy()
);
err = Some(ChecksumError::Io(e));
continue;
}
};
Box::new(file_buf) as Box<dyn Read> Box::new(file_buf) as Box<dyn Read>
}); });
@ -568,5 +578,8 @@ where
println!("{prefix}{sum} {binary_marker}{escaped_filename}"); println!("{prefix}{sum} {binary_marker}{escaped_filename}");
} }
} }
Ok(()) match err {
None => Ok(()),
Some(e) => Err(Box::new(e)),
}
} }

View file

@ -233,6 +233,8 @@ pub enum ChecksumError {
CombineMultipleAlgorithms, CombineMultipleAlgorithms,
#[error("Needs an algorithm to hash with.\nUse --help for more information.")] #[error("Needs an algorithm to hash with.\nUse --help for more information.")]
NeedAlgorithmToHash, NeedAlgorithmToHash,
#[error("")]
Io(#[from] io::Error),
} }
impl UError for ChecksumError { impl UError for ChecksumError {

View file

@ -98,6 +98,22 @@ macro_rules! test_digest {
.no_stderr() .no_stderr()
.stdout_is(std::str::from_utf8(&expected).unwrap()); .stdout_is(std::str::from_utf8(&expected).unwrap());
} }
#[test]
fn test_missing_file() {
let ts = TestScenario::new("hashsum");
let at = &ts.fixtures;
at.write("a", "file1\n");
at.write("c", "file3\n");
ts.ucmd()
.args(&[DIGEST_ARG, BITS_ARG, "a", "b", "c"])
.fails()
.stdout_contains("a\n")
.stdout_contains("c\n")
.stderr_contains("b: No such file or directory");
}
} }
)*) )*)
} }