1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-06 07:57:48 +00:00

Merge pull request #2800 from jfinkels/hashsum-uresult

hashsum: return UResult from uumain() function
This commit is contained in:
Terts Diepraam 2021-12-29 15:04:03 +01:00 committed by GitHub
commit 2d77ea6b68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -28,6 +28,7 @@ use sha1::Sha1;
use sha2::{Sha224, Sha256, Sha384, Sha512}; use sha2::{Sha224, Sha256, Sha384, Sha512};
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256}; use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::error::Error;
use std::ffi::{OsStr, OsString}; use std::ffi::{OsStr, OsString};
use std::fs::File; use std::fs::File;
use std::io::{self, stdin, BufRead, BufReader, Read}; use std::io::{self, stdin, BufRead, BufReader, Read};
@ -35,6 +36,7 @@ use std::iter;
use std::num::ParseIntError; use std::num::ParseIntError;
use std::path::Path; use std::path::Path;
use uucore::display::Quotable; use uucore::display::Quotable;
use uucore::error::{FromIo, UError, UResult};
const NAME: &str = "hashsum"; const NAME: &str = "hashsum";
@ -274,7 +276,8 @@ fn is_valid_bit_num(arg: String) -> Result<(), String> {
.map_err(|e| format!("{}", e)) .map_err(|e| format!("{}", e))
} }
pub fn uumain(mut args: impl uucore::Args) -> i32 { #[uucore_procs::gen_uumain]
pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
// if there is no program name for some reason, default to "hashsum" // if there is no program name for some reason, default to "hashsum"
let program = args.next().unwrap_or_else(|| OsString::from(NAME)); let program = args.next().unwrap_or_else(|| OsString::from(NAME));
let binary_name = Path::new(&program) let binary_name = Path::new(&program)
@ -324,14 +327,9 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 {
warn, warn,
}; };
let res = match matches.values_of_os("FILE") { match matches.values_of_os("FILE") {
Some(files) => hashsum(opts, files), Some(files) => hashsum(opts, files),
None => hashsum(opts, iter::once(OsStr::new("-"))), None => hashsum(opts, iter::once(OsStr::new("-"))),
};
match res {
Ok(()) => 0,
Err(e) => e,
} }
} }
@ -453,8 +451,26 @@ fn uu_app(binary_name: &str) -> App<'static, 'static> {
} }
} }
#[derive(Debug)]
enum HashsumError {
InvalidRegex,
InvalidFormat,
}
impl Error for HashsumError {}
impl UError for HashsumError {}
impl std::fmt::Display for HashsumError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
HashsumError::InvalidRegex => write!(f, "invalid regular expression"),
HashsumError::InvalidFormat => Ok(()),
}
}
}
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
fn hashsum<'a, I>(mut options: Options, files: I) -> Result<(), i32> fn hashsum<'a, I>(mut options: Options, files: I) -> UResult<()>
where where
I: Iterator<Item = &'a OsStr>, I: Iterator<Item = &'a OsStr>,
{ {
@ -470,7 +486,8 @@ where
stdin_buf = stdin(); stdin_buf = stdin();
Box::new(stdin_buf) as Box<dyn Read> Box::new(stdin_buf) as Box<dyn Read>
} else { } else {
file_buf = crash_if_err!(1, File::open(filename)); file_buf =
File::open(filename).map_err_context(|| "failed to open file".to_string())?;
Box::new(file_buf) as Box<dyn Read> Box::new(file_buf) as Box<dyn Read>
}); });
if options.check { if options.check {
@ -487,25 +504,24 @@ where
} else { } else {
"+".to_string() "+".to_string()
}; };
let gnu_re = crash_if_err!( let gnu_re = Regex::new(&format!(
1, r"^(?P<digest>[a-fA-F0-9]{}) (?P<binary>[ \*])(?P<fileName>.*)",
Regex::new(&format!( modifier,
r"^(?P<digest>[a-fA-F0-9]{}) (?P<binary>[ \*])(?P<fileName>.*)", ))
modifier, .map_err(|_| HashsumError::InvalidRegex)?;
)) let bsd_re = Regex::new(&format!(
); r"^{algorithm} \((?P<fileName>.*)\) = (?P<digest>[a-fA-F0-9]{digest_size})",
let bsd_re = crash_if_err!( algorithm = options.algoname,
1, digest_size = modifier,
Regex::new(&format!( ))
r"^{algorithm} \((?P<fileName>.*)\) = (?P<digest>[a-fA-F0-9]{digest_size})", .map_err(|_| HashsumError::InvalidRegex)?;
algorithm = options.algoname,
digest_size = modifier,
))
);
let buffer = file; let buffer = file;
for (i, line) in buffer.lines().enumerate() { for (i, maybe_line) in buffer.lines().enumerate() {
let line = crash_if_err!(1, line); let line = match maybe_line {
Ok(l) => l,
Err(e) => return Err(e.map_err_context(|| "failed to read file".to_string())),
};
let (ck_filename, sum, binary_check) = match gnu_re.captures(&line) { let (ck_filename, sum, binary_check) = match gnu_re.captures(&line) {
Some(caps) => ( Some(caps) => (
caps.name("fileName").unwrap().as_str(), caps.name("fileName").unwrap().as_str(),
@ -521,7 +537,7 @@ where
None => { None => {
bad_format += 1; bad_format += 1;
if options.strict { if options.strict {
return Err(1); return Err(HashsumError::InvalidFormat.into());
} }
if options.warn { if options.warn {
show_warning!( show_warning!(
@ -535,17 +551,16 @@ where
} }
}, },
}; };
let f = crash_if_err!(1, File::open(ck_filename)); let f = File::open(ck_filename)
.map_err_context(|| "failed to open file".to_string())?;
let mut ckf = BufReader::new(Box::new(f) as Box<dyn Read>); let mut ckf = BufReader::new(Box::new(f) as Box<dyn Read>);
let real_sum = crash_if_err!( let real_sum = digest_reader(
1, &mut options.digest,
digest_reader( &mut ckf,
&mut options.digest, binary_check,
&mut ckf, options.output_bits,
binary_check,
options.output_bits
)
) )
.map_err_context(|| "failed to read input".to_string())?
.to_ascii_lowercase(); .to_ascii_lowercase();
// FIXME: Filenames with newlines should be treated specially. // FIXME: Filenames with newlines should be treated specially.
// GNU appears to replace newlines by \n and backslashes by // GNU appears to replace newlines by \n and backslashes by
@ -568,15 +583,13 @@ where
} }
} }
} else { } else {
let sum = crash_if_err!( let sum = digest_reader(
1, &mut options.digest,
digest_reader( &mut file,
&mut options.digest, options.binary,
&mut file, options.output_bits,
options.binary, )
options.output_bits .map_err_context(|| "failed to read input".to_string())?;
)
);
if options.tag { if options.tag {
println!("{} ({}) = {}", options.algoname, filename.display(), sum); println!("{} ({}) = {}", options.algoname, filename.display(), sum);
} else { } else {