mirror of
https://github.com/uutils/coreutils
synced 2024-07-22 10:24:54 +00:00
cksum/hashsum: factor the error structure and use it more
This commit is contained in:
parent
dbe7a20e08
commit
0882eea07c
|
@ -5,21 +5,19 @@
|
|||
|
||||
// spell-checker:ignore (ToDO) fname, algo
|
||||
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
|
||||
use std::error::Error;
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt::Display;
|
||||
use std::fs::File;
|
||||
use std::io::{self, stdin, stdout, BufReader, Read, Write};
|
||||
use std::iter;
|
||||
use std::path::Path;
|
||||
use uucore::checksum::{
|
||||
calculate_blake2b_length, detect_algo, digest_reader, perform_checksum_validation,
|
||||
ALGORITHM_OPTIONS_BLAKE2B, ALGORITHM_OPTIONS_BSD, ALGORITHM_OPTIONS_CRC,
|
||||
ChecksumError, ALGORITHM_OPTIONS_BLAKE2B, ALGORITHM_OPTIONS_BSD, ALGORITHM_OPTIONS_CRC,
|
||||
ALGORITHM_OPTIONS_SYSV, SUPPORTED_ALGO,
|
||||
};
|
||||
use uucore::{
|
||||
encoding,
|
||||
error::{FromIo, UError, UResult, USimpleError},
|
||||
error::{FromIo, UResult, USimpleError},
|
||||
format_usage, help_about, help_section, help_usage, show,
|
||||
sum::{div_ceil, Digest},
|
||||
};
|
||||
|
@ -28,11 +26,6 @@ const USAGE: &str = help_usage!("cksum.md");
|
|||
const ABOUT: &str = help_about!("cksum.md");
|
||||
const AFTER_HELP: &str = help_section!("after help", "cksum.md");
|
||||
|
||||
#[derive(Debug)]
|
||||
enum CkSumError {
|
||||
RawMultipleFiles,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum OutputFormat {
|
||||
Hexadecimal,
|
||||
|
@ -40,26 +33,6 @@ enum OutputFormat {
|
|||
Base64,
|
||||
}
|
||||
|
||||
impl UError for CkSumError {
|
||||
fn code(&self) -> i32 {
|
||||
match self {
|
||||
Self::RawMultipleFiles => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CkSumError {}
|
||||
|
||||
impl Display for CkSumError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::RawMultipleFiles => {
|
||||
write!(f, "the --raw option is not supported with multiple files")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Options {
|
||||
algo_name: &'static str,
|
||||
digest: Box<dyn Digest + 'static>,
|
||||
|
@ -83,7 +56,7 @@ where
|
|||
{
|
||||
let files: Vec<_> = files.collect();
|
||||
if options.output_format == OutputFormat::Raw && files.len() > 1 {
|
||||
return Err(Box::new(CkSumError::RawMultipleFiles));
|
||||
return Err(Box::new(ChecksumError::RawMultipleFiles));
|
||||
}
|
||||
|
||||
for filename in files {
|
||||
|
@ -287,11 +260,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
};
|
||||
|
||||
if ["bsd", "crc", "sysv"].contains(&algo_name) && check {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"--check is not supported with --algorithm={bsd,sysv,crc}",
|
||||
)
|
||||
.into());
|
||||
return Err(ChecksumError::AlgorithmNotSupportedWithCheck.into());
|
||||
}
|
||||
|
||||
let input_length = matches.get_one::<usize>(options::LENGTH);
|
||||
|
@ -301,11 +270,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
if algo_name == ALGORITHM_OPTIONS_BLAKE2B {
|
||||
calculate_blake2b_length(*length)?
|
||||
} else {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"--length is only supported with --algorithm=blake2b",
|
||||
)
|
||||
.into());
|
||||
return Err(ChecksumError::LengthOnlyForBlake2b.into());
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
|
@ -320,11 +285,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
let ignore_missing = matches.get_flag(options::IGNORE_MISSING);
|
||||
|
||||
if (binary_flag || text_flag) && check {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"the --binary and --text options are meaningless when verifying checksums",
|
||||
)
|
||||
.into());
|
||||
return Err(ChecksumError::BinaryTextConflict.into());
|
||||
}
|
||||
// Determine the appropriate algorithm option to pass
|
||||
let algo_option = if algo_name.is_empty() {
|
||||
|
|
|
@ -10,10 +10,9 @@ use clap::crate_version;
|
|||
use clap::value_parser;
|
||||
use clap::ArgAction;
|
||||
use clap::{Arg, ArgMatches, Command};
|
||||
use std::error::Error;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fs::File;
|
||||
use std::io::{self, stdin, BufReader, Read};
|
||||
use std::io::{stdin, BufReader, Read};
|
||||
use std::iter;
|
||||
use std::num::ParseIntError;
|
||||
use std::path::Path;
|
||||
|
@ -23,10 +22,10 @@ use uucore::checksum::detect_algo;
|
|||
use uucore::checksum::digest_reader;
|
||||
use uucore::checksum::escape_filename;
|
||||
use uucore::checksum::perform_checksum_validation;
|
||||
use uucore::checksum::ChecksumError;
|
||||
use uucore::checksum::HashAlgorithm;
|
||||
use uucore::checksum::ALGORITHM_OPTIONS_BLAKE2B;
|
||||
use uucore::error::USimpleError;
|
||||
use uucore::error::{FromIo, UError, UResult};
|
||||
use uucore::error::{FromIo, UResult};
|
||||
use uucore::sum::{Digest, Sha3_224, Sha3_256, Sha3_384, Sha3_512, Shake128, Shake256};
|
||||
use uucore::{format_usage, help_about, help_usage};
|
||||
|
||||
|
@ -67,10 +66,7 @@ fn create_algorithm_from_flags(matches: &ArgMatches) -> UResult<HashAlgorithm> {
|
|||
|
||||
let mut set_or_err = |new_alg: HashAlgorithm| -> UResult<()> {
|
||||
if alg.is_some() {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
"You cannot combine multiple hash algorithms!",
|
||||
));
|
||||
return Err(ChecksumError::CombineMultipleAlgorithms.into());
|
||||
}
|
||||
alg = Some(new_alg);
|
||||
Ok(())
|
||||
|
@ -139,7 +135,7 @@ fn create_algorithm_from_flags(matches: &ArgMatches) -> UResult<HashAlgorithm> {
|
|||
create_fn: Box::new(|| Box::new(Shake128::new())),
|
||||
bits: *bits,
|
||||
})?,
|
||||
None => return Err(USimpleError::new(1, "--bits required for SHAKE128")),
|
||||
None => return Err(ChecksumError::BitsRequiredForShake128.into()),
|
||||
};
|
||||
}
|
||||
if matches.get_flag("shake256") {
|
||||
|
@ -149,15 +145,12 @@ fn create_algorithm_from_flags(matches: &ArgMatches) -> UResult<HashAlgorithm> {
|
|||
create_fn: Box::new(|| Box::new(Shake256::new())),
|
||||
bits: *bits,
|
||||
})?,
|
||||
None => return Err(USimpleError::new(1, "--bits required for SHAKE256")),
|
||||
None => return Err(ChecksumError::BitsRequiredForShake256.into()),
|
||||
};
|
||||
}
|
||||
|
||||
if alg.is_none() {
|
||||
return Err(USimpleError::new(
|
||||
1,
|
||||
"Needs an algorithm to hash with.\nUse --help for more information.",
|
||||
));
|
||||
return Err(ChecksumError::NeedAlgoToHash.into());
|
||||
}
|
||||
|
||||
Ok(alg.unwrap())
|
||||
|
@ -201,11 +194,7 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
|
|||
if binary_name == ALGORITHM_OPTIONS_BLAKE2B || binary_name == "b2sum" {
|
||||
calculate_blake2b_length(*length)?
|
||||
} else {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"--length is only supported with --algorithm=blake2b",
|
||||
)
|
||||
.into());
|
||||
return Err(ChecksumError::LengthOnlyForBlake2b.into());
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
|
@ -239,7 +228,7 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
|
|||
|
||||
if ignore_missing && !check {
|
||||
// --ignore-missing needs -c
|
||||
return Err(HashsumError::IgnoreNotCheck.into());
|
||||
return Err(ChecksumError::IgnoreNotCheck.into());
|
||||
}
|
||||
|
||||
let opts = Options {
|
||||
|
@ -264,11 +253,7 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
|
|||
let strict = matches.get_flag("strict");
|
||||
|
||||
if (binary_flag || text_flag) && check {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"the --binary and --text options are meaningless when verifying checksums",
|
||||
)
|
||||
.into());
|
||||
return Err(ChecksumError::BinaryTextConflict.into());
|
||||
}
|
||||
// Determine the appropriate algorithm option to pass
|
||||
let algo_option = if algo.name.is_empty() {
|
||||
|
@ -524,27 +509,6 @@ fn uu_app(binary_name: &str) -> (Command, bool) {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum HashsumError {
|
||||
//InvalidRegex,
|
||||
IgnoreNotCheck,
|
||||
}
|
||||
|
||||
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 {
|
||||
//Self::InvalidRegex => write!(f, "invalid regular expression"),
|
||||
Self::IgnoreNotCheck => write!(
|
||||
f,
|
||||
"the --ignore-missing option is meaningful only when verifying checksums"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
fn hashsum<'a, I>(mut options: Options, files: I) -> UResult<()>
|
||||
where
|
||||
|
|
|
@ -6,14 +6,16 @@
|
|||
use os_display::Quotable;
|
||||
use regex::Regex;
|
||||
use std::{
|
||||
error::Error,
|
||||
ffi::OsStr,
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{self, BufReader, Read},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
error::{set_exit_code, FromIo, UResult, USimpleError},
|
||||
error::{set_exit_code, FromIo, UError, UResult, USimpleError},
|
||||
show, show_error, show_warning_caps,
|
||||
sum::{
|
||||
Blake2b, Blake3, Digest, DigestWriter, Md5, Sha1, Sha224, Sha256, Sha384, Sha3_224,
|
||||
|
@ -65,6 +67,74 @@ pub struct HashAlgorithm {
|
|||
pub bits: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ChecksumError {
|
||||
RawMultipleFiles,
|
||||
IgnoreNotCheck,
|
||||
InvalidOutputSizeForSha3,
|
||||
BitsRequiredForSha3,
|
||||
BitsRequiredForShake128,
|
||||
BitsRequiredForShake256,
|
||||
UnknownAlgorithm,
|
||||
InvalidLength,
|
||||
LengthOnlyForBlake2b,
|
||||
BinaryTextConflict,
|
||||
AlgorithmNotSupportedWithCheck,
|
||||
CombineMultipleAlgorithms,
|
||||
NeedAlgoToHash,
|
||||
}
|
||||
|
||||
impl Error for ChecksumError {}
|
||||
|
||||
impl UError for ChecksumError {
|
||||
fn code(&self) -> i32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ChecksumError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::RawMultipleFiles => {
|
||||
write!(f, "the --raw option is not supported with multiple files")
|
||||
}
|
||||
Self::IgnoreNotCheck => write!(
|
||||
f,
|
||||
"the --ignore-missing option is meaningful only when verifying checksums"
|
||||
),
|
||||
Self::InvalidOutputSizeForSha3 => write!(
|
||||
f,
|
||||
"Invalid output size for SHA3 (expected 224, 256, 384, or 512)"
|
||||
),
|
||||
Self::BitsRequiredForSha3 => write!(f, "--bits required for SHA3"),
|
||||
Self::BitsRequiredForShake128 => write!(f, "--bits required for SHAKE128"),
|
||||
Self::BitsRequiredForShake256 => write!(f, "--bits required for SHAKE256"),
|
||||
Self::UnknownAlgorithm => {
|
||||
write!(f, "unknown algorithm: clap should have prevented this case")
|
||||
}
|
||||
Self::InvalidLength => write!(f, "length is not a multiple of 8"),
|
||||
Self::LengthOnlyForBlake2b => {
|
||||
write!(f, "--length is only supported with --algorithm=blake2b")
|
||||
}
|
||||
Self::BinaryTextConflict => write!(
|
||||
f,
|
||||
"the --binary and --text options are meaningless when verifying checksums"
|
||||
),
|
||||
Self::AlgorithmNotSupportedWithCheck => write!(
|
||||
f,
|
||||
"--check is not supported with --algorithm={{bsd,sysv,crc}}"
|
||||
),
|
||||
Self::CombineMultipleAlgorithms => {
|
||||
write!(f, "You cannot combine multiple hash algorithms!")
|
||||
}
|
||||
Self::NeedAlgoToHash => write!(
|
||||
f,
|
||||
"Needs an algorithm to hash with.\nUse --help for more information."
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a SHA3 hasher instance based on the specified bits argument.
|
||||
///
|
||||
/// # Returns
|
||||
|
@ -95,11 +165,8 @@ pub fn create_sha3(bits: Option<usize>) -> UResult<HashAlgorithm> {
|
|||
bits: 512,
|
||||
}),
|
||||
|
||||
Some(_) => Err(USimpleError::new(
|
||||
1,
|
||||
"Invalid output size for SHA3 (expected 224, 256, 384, or 512)",
|
||||
)),
|
||||
None => Err(USimpleError::new(1, "--bits required for SHA3")),
|
||||
Some(_) => Err(ChecksumError::InvalidOutputSizeForSha3.into()),
|
||||
None => Err(ChecksumError::BitsRequiredForSha3.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,10 +295,7 @@ pub fn detect_algo(algo: &str, length: Option<usize>) -> UResult<HashAlgorithm>
|
|||
//ALGORITHM_OPTIONS_SHA3 | "sha3" => (
|
||||
alg if alg.starts_with("sha3") => create_sha3(length),
|
||||
|
||||
_ => Err(USimpleError::new(
|
||||
1,
|
||||
"unknown algorithm: clap should have prevented this case",
|
||||
)),
|
||||
_ => Err(ChecksumError::UnknownAlgorithm.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -561,8 +561,7 @@ fn test_blake2b_512() {
|
|||
.arg("--check")
|
||||
.arg("checksum")
|
||||
.succeeds()
|
||||
.stdout_contains("")
|
||||
.stderr_contains("");
|
||||
.no_output();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -370,7 +370,7 @@ fn test_check_md5sum_not_enough_space() {
|
|||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
for f in &["a", " b"] {
|
||||
for f in ["a", "b"] {
|
||||
at.write(f, &format!("{f}\n"));
|
||||
}
|
||||
at.write(
|
||||
|
@ -384,8 +384,7 @@ fn test_check_md5sum_not_enough_space() {
|
|||
.arg("-c")
|
||||
.arg("check.md5sum")
|
||||
.fails()
|
||||
.stdout_is("")
|
||||
.stderr_is("md5sum: check.md5sum: no properly formatted checksum lines found\nmd5sum: WARNING: 2 lines are improperly formatted\n");
|
||||
.stderr_only("md5sum: check.md5sum: no properly formatted checksum lines found\nmd5sum: WARNING: 2 lines are improperly formatted\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue