Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 70 additions & 5 deletions src/uu/cksum/src/cksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) fname, algo
use clap::{crate_version, Arg, ArgAction, Command};
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
use hex::encode;
use std::ffi::OsStr;
use std::fs::File;
Expand Down Expand Up @@ -36,7 +36,10 @@ const ALGORITHM_OPTIONS_SHA512: &str = "sha512";
const ALGORITHM_OPTIONS_BLAKE2B: &str = "blake2b";
const ALGORITHM_OPTIONS_SM3: &str = "sm3";

fn detect_algo(program: &str) -> (&'static str, Box<dyn Digest + 'static>, usize) {
fn detect_algo(
program: &str,
length: Option<usize>,
) -> (&'static str, Box<dyn Digest + 'static>, usize) {
match program {
ALGORITHM_OPTIONS_SYSV => (
ALGORITHM_OPTIONS_SYSV,
Expand Down Expand Up @@ -85,7 +88,11 @@ fn detect_algo(program: &str) -> (&'static str, Box<dyn Digest + 'static>, usize
),
ALGORITHM_OPTIONS_BLAKE2B => (
ALGORITHM_OPTIONS_BLAKE2B,
Box::new(Blake2b::new()) as Box<dyn Digest>,
Box::new(if let Some(length) = length {
Blake2b::with_output_bytes(length)
} else {
Blake2b::new()
}) as Box<dyn Digest>,
512,
),
ALGORITHM_OPTIONS_SM3 => (
Expand All @@ -102,6 +109,7 @@ struct Options {
digest: Box<dyn Digest + 'static>,
output_bits: usize,
untagged: bool,
length: Option<usize>,
}

/// Calculate checksum
Expand Down Expand Up @@ -161,7 +169,12 @@ where
(ALGORITHM_OPTIONS_CRC, true) => println!("{sum} {sz}"),
(ALGORITHM_OPTIONS_CRC, false) => println!("{sum} {sz} {}", filename.display()),
(ALGORITHM_OPTIONS_BLAKE2B, _) if !options.untagged => {
println!("BLAKE2b ({}) = {sum}", filename.display());
if let Some(length) = options.length {
// Multiply by 8 here, as we want to print the length in bits.
println!("BLAKE2b-{} ({}) = {sum}", length * 8, filename.display());
} else {
println!("BLAKE2b ({}) = {sum}", filename.display());
}
}
_ => {
if options.untagged {
Expand Down Expand Up @@ -217,6 +230,7 @@ mod options {
pub const ALGORITHM: &str = "algorithm";
pub const FILE: &str = "file";
pub const UNTAGGED: &str = "untagged";
pub const LENGTH: &str = "length";
}

#[uucore::main]
Expand All @@ -228,11 +242,54 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
None => ALGORITHM_OPTIONS_CRC,
};

let (name, algo, bits) = detect_algo(algo_name);
let input_length = matches.get_one::<usize>(options::LENGTH);
let length = if let Some(length) = input_length {
match length.to_owned() {
0 => None,
n if n % 8 != 0 => {
// GNU's implementation seem to use these quotation marks
// in their error messages, so we do the same.
uucore::show_error!("invalid length: \u{2018}{length}\u{2019}");
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"length is not a multiple of 8",
)
.into());
}
n if n > 512 => {
uucore::show_error!("invalid length: \u{2018}{length}\u{2019}");

return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"maximum digest length for \u{2018}BLAKE2b\u{2019} is 512 bits",
)
.into());
}
n => {
if algo_name != ALGORITHM_OPTIONS_BLAKE2B {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"--length is only supported with --algorithm=blake2b",
)
.into());
}

// Divide by 8, as our blake2b implementation expects bytes
// instead of bits.
Some(n / 8)
}
}
} else {
None
};

let (name, algo, bits) = detect_algo(algo_name, length);

let opts = Options {
algo_name: name,
digest: algo,
output_bits: bits,
length,
untagged: matches.get_flag(options::UNTAGGED),
};

Expand Down Expand Up @@ -282,5 +339,13 @@ pub fn uu_app() -> Command {
.help("create a reversed style checksum, without digest type")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::LENGTH)
.long(options::LENGTH)
.value_parser(value_parser!(usize))
.short('l')
.help("digest length in bits; must not exceed the max for the blake2 algorithm and must be a multiple of 8")
.action(ArgAction::Set),
)
.after_help(AFTER_HELP)
}
58 changes: 58 additions & 0 deletions tests/by-util/test_cksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,61 @@ fn test_untagged_algorithm_stdin() {
.stdout_is_fixture(format!("untagged/{algo}_stdin.expected"));
}
}

#[test]
fn test_length_with_wrong_algorithm() {
new_ucmd!()
.arg("--length=16")
.arg("--algorithm=md5")
.arg("lorem_ipsum.txt")
.fails()
.no_stdout()
.stderr_contains("cksum: --length is only supported with --algorithm=blake2b")
.code_is(1);
}

#[test]
fn test_length_not_supported() {
new_ucmd!()
.arg("--length=15")
.arg("lorem_ipsum.txt")
.fails()
.no_stdout()
.stderr_is_fixture("unsupported_length.expected")
.code_is(1);
}

#[test]
fn test_length() {
new_ucmd!()
.arg("--length=16")
.arg("--algorithm=blake2b")
.arg("lorem_ipsum.txt")
.arg("alice_in_wonderland.txt")
.succeeds()
.stdout_is_fixture("supported_length.expected");
}

#[test]
fn test_length_greater_than_512() {
new_ucmd!()
.arg("--length=1024")
.arg("--algorithm=blake2b")
.arg("lorem_ipsum.txt")
.arg("alice_in_wonderland.txt")
.fails()
.no_stdout()
.stderr_is_fixture("length_larger_than_512.expected");
}

#[test]
fn test_length_is_zero() {
new_ucmd!()
.arg("--length=0")
.arg("--algorithm=blake2b")
.arg("lorem_ipsum.txt")
.arg("alice_in_wonderland.txt")
.succeeds()
.no_stderr()
.stdout_is_fixture("length_is_zero.expected");
}
2 changes: 2 additions & 0 deletions tests/fixtures/cksum/length_is_zero.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BLAKE2b (lorem_ipsum.txt) = 0e97a09189e560c3789c0bff1f020166861ef857d1fbfe4574de1842e3c06cabb9575e4af6309a166158c2b408d3c038c1b49d828b35158142cdc0396d1195c3
BLAKE2b (alice_in_wonderland.txt) = 91b8b0f0868e905ad18b8ac35e4a1dacd289857b19258ab5d1e071761af758b0134ec152d4f011fe1825ca889c80c2e072ca70eb50548c25fc49a98937515af4
2 changes: 2 additions & 0 deletions tests/fixtures/cksum/length_larger_than_512.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cksum: invalid length: ‘1024’
cksum: maximum digest length for ‘BLAKE2b’ is 512 bits
2 changes: 2 additions & 0 deletions tests/fixtures/cksum/supported_length.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BLAKE2b-16 (lorem_ipsum.txt) = 7e2f
BLAKE2b-16 (alice_in_wonderland.txt) = a546
2 changes: 2 additions & 0 deletions tests/fixtures/cksum/unsupported_length.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cksum: invalid length: ‘15’
cksum: length is not a multiple of 8