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:
commit
2d77ea6b68
1 changed files with 58 additions and 45 deletions
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue