mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
hashsum: Get rid of non-GNU --bits argument
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::iter;
|
||||
use std::num::ParseIntError;
|
||||
use std::path::Path;
|
||||
|
||||
use clap::builder::ValueParser;
|
||||
@@ -19,7 +18,10 @@ use uucore::checksum::compute::{
|
||||
use uucore::checksum::validate::{
|
||||
ChecksumValidateOptions, ChecksumVerbose, perform_checksum_validation,
|
||||
};
|
||||
use uucore::checksum::{AlgoKind, ChecksumError, SizedAlgoKind, calculate_blake2b_length_str};
|
||||
use uucore::checksum::{
|
||||
AlgoKind, ChecksumError, SizedAlgoKind, calculate_blake2b_length_str,
|
||||
sanitize_sha2_sha3_length_str,
|
||||
};
|
||||
use uucore::error::UResult;
|
||||
use uucore::line_ending::LineEnding;
|
||||
use uucore::{format_usage, translate};
|
||||
@@ -74,9 +76,11 @@ fn create_algorithm_from_flags(matches: &ArgMatches) -> UResult<(AlgoKind, Optio
|
||||
set_or_err((AlgoKind::Blake3, None))?;
|
||||
}
|
||||
if matches.get_flag("sha3") {
|
||||
match matches.get_one::<usize>("bits") {
|
||||
Some(bits @ (224 | 256 | 384 | 512)) => set_or_err((AlgoKind::Sha3, Some(*bits)))?,
|
||||
Some(bits) => return Err(ChecksumError::InvalidLengthForSha(bits.to_string()).into()),
|
||||
match matches.get_one::<String>(options::LENGTH) {
|
||||
Some(len) => set_or_err((
|
||||
AlgoKind::Sha3,
|
||||
Some(sanitize_sha2_sha3_length_str(AlgoKind::Sha3, len)?),
|
||||
))?,
|
||||
None => return Err(ChecksumError::LengthRequired("SHA3".into()).into()),
|
||||
}
|
||||
}
|
||||
@@ -93,16 +97,10 @@ fn create_algorithm_from_flags(matches: &ArgMatches) -> UResult<(AlgoKind, Optio
|
||||
set_or_err((AlgoKind::Sha3, Some(512)))?;
|
||||
}
|
||||
if matches.get_flag("shake128") {
|
||||
match matches.get_one::<usize>("bits") {
|
||||
Some(bits) => set_or_err((AlgoKind::Shake128, Some(*bits)))?,
|
||||
None => return Err(ChecksumError::LengthRequired("SHAKE128".into()).into()),
|
||||
}
|
||||
set_or_err((AlgoKind::Shake128, Some(128)))?;
|
||||
}
|
||||
if matches.get_flag("shake256") {
|
||||
match matches.get_one::<usize>("bits") {
|
||||
Some(bits) => set_or_err((AlgoKind::Shake256, Some(*bits)))?,
|
||||
None => return Err(ChecksumError::LengthRequired("SHAKE256".into()).into()),
|
||||
}
|
||||
set_or_err((AlgoKind::Shake256, Some(256)))?;
|
||||
}
|
||||
|
||||
if alg.is_none() {
|
||||
@@ -112,11 +110,6 @@ fn create_algorithm_from_flags(matches: &ArgMatches) -> UResult<(AlgoKind, Optio
|
||||
Ok(alg.unwrap())
|
||||
}
|
||||
|
||||
// TODO: return custom error type
|
||||
fn parse_bit_num(arg: &str) -> Result<usize, ParseIntError> {
|
||||
arg.parse()
|
||||
}
|
||||
|
||||
#[uucore::main]
|
||||
pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
|
||||
// if there is no program name for some reason, default to "hashsum"
|
||||
@@ -139,17 +132,16 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
|
||||
// least somewhat better from a user's perspective.
|
||||
let matches = uucore::clap_localization::handle_clap_result(command, args)?;
|
||||
|
||||
let input_length: Option<&String> = if binary_name == "b2sum" {
|
||||
matches.get_one::<String>(options::LENGTH)
|
||||
let length: Option<usize> = if binary_name == "b2sum" {
|
||||
if let Some(len) = matches.get_one::<String>(options::LENGTH) {
|
||||
calculate_blake2b_length_str(len)?
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let length = match input_length {
|
||||
Some(length) => calculate_blake2b_length_str(length)?,
|
||||
None => None,
|
||||
};
|
||||
|
||||
let (algo_kind, length) = if is_hashsum_bin {
|
||||
create_algorithm_from_flags(&matches)?
|
||||
} else {
|
||||
@@ -371,24 +363,8 @@ fn uu_app_opt_length(command: Command) -> Command {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn uu_app_bits() -> Command {
|
||||
uu_app_opt_bits(uu_app_common())
|
||||
}
|
||||
|
||||
fn uu_app_opt_bits(command: Command) -> Command {
|
||||
// Needed for variable-length output sums (e.g. SHAKE)
|
||||
command.arg(
|
||||
Arg::new("bits")
|
||||
.long("bits")
|
||||
.help(translate!("hashsum-help-bits"))
|
||||
.value_name("BITS")
|
||||
// XXX: should we actually use validators? they're not particularly efficient
|
||||
.value_parser(parse_bit_num),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn uu_app_custom() -> Command {
|
||||
let mut command = uu_app_opt_bits(uu_app_common());
|
||||
let mut command = uu_app_opt_length(uu_app_common());
|
||||
let algorithms = &[
|
||||
("md5", translate!("hashsum-help-md5")),
|
||||
("sha1", translate!("hashsum-help-sha1")),
|
||||
|
||||
+195
-82
@@ -16,87 +16,207 @@ macro_rules! get_hash(
|
||||
);
|
||||
|
||||
macro_rules! test_digest {
|
||||
($($id:ident $t:ident $size:expr)*) => ($(
|
||||
($id:ident, $t:ident) => {
|
||||
mod $id {
|
||||
use uutests::util::*;
|
||||
use uutests::util_name;
|
||||
static DIGEST_ARG: &'static str = concat!("--", stringify!($t));
|
||||
static EXPECTED_FILE: &'static str = concat!(stringify!($id), ".expected");
|
||||
static CHECK_FILE: &'static str = concat!(stringify!($id), ".checkfile");
|
||||
static INPUT_FILE: &'static str = "input.txt";
|
||||
|
||||
mod $id {
|
||||
use uutests::util::*;
|
||||
use uutests::util_name;
|
||||
static DIGEST_ARG: &'static str = concat!("--", stringify!($t));
|
||||
static BITS_ARG: &'static str = concat!("--bits=", stringify!($size));
|
||||
static EXPECTED_FILE: &'static str = concat!(stringify!($id), ".expected");
|
||||
static CHECK_FILE: &'static str = concat!(stringify!($id), ".checkfile");
|
||||
static INPUT_FILE: &'static str = "input.txt";
|
||||
#[test]
|
||||
fn test_single_file() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(
|
||||
ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg(DIGEST_ARG)
|
||||
.arg(INPUT_FILE)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_str()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_single_file() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(ts.ucmd().arg(DIGEST_ARG).arg(BITS_ARG).arg(INPUT_FILE).succeeds().no_stderr().stdout_str()));
|
||||
#[test]
|
||||
fn test_stdin() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(
|
||||
ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg(DIGEST_ARG)
|
||||
.pipe_in_fixture(INPUT_FILE)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_str()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
println!("File content='{}'", ts.fixtures.read(INPUT_FILE));
|
||||
println!("Check file='{}'", ts.fixtures.read(CHECK_FILE));
|
||||
|
||||
ts.ucmd()
|
||||
.args(&[DIGEST_ARG, "--check", CHECK_FILE])
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_is("input.txt: OK\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(
|
||||
ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg(DIGEST_ARG)
|
||||
.arg("--zero")
|
||||
.arg(INPUT_FILE)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_str()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_file() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
let at = &ts.fixtures;
|
||||
|
||||
at.write("a", "file1\n");
|
||||
at.write("c", "file3\n");
|
||||
|
||||
ts.ucmd()
|
||||
.args(&[DIGEST_ARG, "a", "b", "c"])
|
||||
.fails()
|
||||
.stdout_contains("a\n")
|
||||
.stdout_contains("c\n")
|
||||
.stderr_contains("b: No such file or directory");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdin() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(ts.ucmd().arg(DIGEST_ARG).arg(BITS_ARG).pipe_in_fixture(INPUT_FILE).succeeds().no_stderr().stdout_str()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
println!("File content='{}'", ts.fixtures.read(INPUT_FILE));
|
||||
println!("Check file='{}'", ts.fixtures.read(CHECK_FILE));
|
||||
|
||||
ts.ucmd()
|
||||
.args(&[DIGEST_ARG, BITS_ARG, "--check", CHECK_FILE])
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_is("input.txt: OK\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(ts.ucmd().arg(DIGEST_ARG).arg(BITS_ARG).arg("--zero").arg(INPUT_FILE).succeeds().no_stderr().stdout_str()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_file() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
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");
|
||||
}
|
||||
}
|
||||
)*)
|
||||
};
|
||||
}
|
||||
|
||||
test_digest! {
|
||||
md5 md5 128
|
||||
sha1 sha1 160
|
||||
sha224 sha224 224
|
||||
sha256 sha256 256
|
||||
sha384 sha384 384
|
||||
sha512 sha512 512
|
||||
sha3_224 sha3 224
|
||||
sha3_256 sha3 256
|
||||
sha3_384 sha3 384
|
||||
sha3_512 sha3 512
|
||||
shake128_256 shake128 256
|
||||
shake256_512 shake256 512
|
||||
b2sum b2sum 512
|
||||
b3sum b3sum 256
|
||||
macro_rules! test_digest_with_len {
|
||||
($id:ident, $t:ident, $size:expr) => {
|
||||
mod $id {
|
||||
use uutests::util::*;
|
||||
use uutests::util_name;
|
||||
static DIGEST_ARG: &'static str = concat!("--", stringify!($t));
|
||||
static LENGTH_ARG: &'static str = concat!("--length=", stringify!($size));
|
||||
static EXPECTED_FILE: &'static str = concat!(stringify!($id), ".expected");
|
||||
static CHECK_FILE: &'static str = concat!(stringify!($id), ".checkfile");
|
||||
static INPUT_FILE: &'static str = "input.txt";
|
||||
|
||||
#[test]
|
||||
fn test_single_file() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(
|
||||
ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg(DIGEST_ARG)
|
||||
.arg(LENGTH_ARG)
|
||||
.arg(INPUT_FILE)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_str()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stdin() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(
|
||||
ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg(DIGEST_ARG)
|
||||
.arg(LENGTH_ARG)
|
||||
.pipe_in_fixture(INPUT_FILE)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_str()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
println!("File content='{}'", ts.fixtures.read(INPUT_FILE));
|
||||
println!("Check file='{}'", ts.fixtures.read(CHECK_FILE));
|
||||
|
||||
ts.ucmd()
|
||||
.args(&[DIGEST_ARG, LENGTH_ARG, "--check", CHECK_FILE])
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_is("input.txt: OK\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
assert_eq!(
|
||||
ts.fixtures.read(EXPECTED_FILE),
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg(DIGEST_ARG)
|
||||
.arg(LENGTH_ARG)
|
||||
.arg("--zero")
|
||||
.arg(INPUT_FILE)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_str()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_missing_file() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
let at = &ts.fixtures;
|
||||
|
||||
at.write("a", "file1\n");
|
||||
at.write("c", "file3\n");
|
||||
|
||||
ts.ucmd()
|
||||
.args(&[DIGEST_ARG, LENGTH_ARG, "a", "b", "c"])
|
||||
.fails()
|
||||
.stdout_contains("a\n")
|
||||
.stdout_contains("c\n")
|
||||
.stderr_contains("b: No such file or directory");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test_digest! {md5, md5}
|
||||
test_digest! {sha1, sha1}
|
||||
test_digest! {b3sum, b3sum}
|
||||
test_digest! {shake128, shake128}
|
||||
test_digest! {shake256, shake256}
|
||||
|
||||
test_digest_with_len! {sha224, sha224, 224}
|
||||
test_digest_with_len! {sha256, sha256, 256}
|
||||
test_digest_with_len! {sha384, sha384, 384}
|
||||
test_digest_with_len! {sha512, sha512, 512}
|
||||
test_digest_with_len! {sha3_224, sha3, 224}
|
||||
test_digest_with_len! {sha3_256, sha3, 256}
|
||||
test_digest_with_len! {sha3_384, sha3, 384}
|
||||
test_digest_with_len! {sha3_512, sha3, 512}
|
||||
test_digest_with_len! {b2sum, b2sum, 512}
|
||||
|
||||
#[test]
|
||||
fn test_check_sha1() {
|
||||
// To make sure that #3815 doesn't happen again
|
||||
@@ -1037,7 +1157,6 @@ fn test_sha256_binary() {
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg("--sha256")
|
||||
.arg("--bits=256")
|
||||
.arg("binary.png")
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
@@ -1054,7 +1173,6 @@ fn test_sha256_stdin_binary() {
|
||||
get_hash!(
|
||||
ts.ucmd()
|
||||
.arg("--sha256")
|
||||
.arg("--bits=256")
|
||||
.pipe_in_fixture("binary.png")
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
@@ -1068,12 +1186,7 @@ fn test_sha256_stdin_binary() {
|
||||
#[cfg_attr(windows, ignore = "Discussion is in #9168")]
|
||||
fn test_check_sha256_binary() {
|
||||
new_ucmd!()
|
||||
.args(&[
|
||||
"--sha256",
|
||||
"--bits=256",
|
||||
"--check",
|
||||
"binary.sha256.checkfile",
|
||||
])
|
||||
.args(&["--sha256", "--check", "binary.sha256.checkfile"])
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_is("binary.png: OK\n");
|
||||
|
||||
Reference in New Issue
Block a user