Merge pull request #4729 from spineki/b2sum-missing-l-option

B2sum: add -l/--length option
This commit is contained in:
Daniel Hofstetter 2023-04-13 09:57:55 +02:00 committed by GitHub
commit dd3c0f7fe9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 6 deletions

View file

@ -65,7 +65,28 @@ fn detect_algo(
"sha256sum" => ("SHA256", Box::new(Sha256::new()) as Box<dyn Digest>, 256),
"sha384sum" => ("SHA384", Box::new(Sha384::new()) as Box<dyn Digest>, 384),
"sha512sum" => ("SHA512", Box::new(Sha512::new()) as Box<dyn Digest>, 512),
"b2sum" => ("BLAKE2", Box::new(Blake2b::new()) as Box<dyn Digest>, 512),
"b2sum" => match matches.get_one::<usize>("length") {
// by default, blake2 uses 64 bytes (512 bits)
// --length=0 falls back to default behavior
Some(0) | None => ("BLAKE2", Box::new(Blake2b::new()) as Box<dyn Digest>, 512),
Some(length_in_bits) => {
if *length_in_bits > 512 {
crash!(1, "Invalid length (maximum digest length is 512 bits)")
}
// blake2 output size must be a multiple of 8 bits
if length_in_bits % 8 == 0 {
let length_in_bytes = length_in_bits / 8;
(
"BLAKE2",
Box::new(Blake2b::with_output_bytes(length_in_bytes)),
*length_in_bits,
)
} else {
crash!(1, "Invalid length (expected a multiple of 8)")
}
}
},
"b3sum" => ("BLAKE3", Box::new(Blake3::new()) as Box<dyn Digest>, 256),
"sha3sum" => match matches.get_one::<usize>("bits") {
Some(224) => (
@ -379,6 +400,21 @@ pub fn uu_app_common() -> Command {
)
}
pub fn uu_app_length() -> Command {
uu_app_opt_length(uu_app_common())
}
fn uu_app_opt_length(command: Command) -> Command {
command.arg(
Arg::new("length")
.short('l')
.long("length")
.help("digest length in bits; must not exceed the max for the blake2 algorithm (512) and must be a multiple of 8")
.value_name("BITS")
.value_parser(parse_bit_num),
)
}
pub fn uu_app_b3sum() -> Command {
uu_app_b3sum_opts(uu_app_common())
}
@ -454,7 +490,7 @@ fn uu_app(binary_name: &str) -> Command {
uu_app_common()
}
// b2sum supports the md5sum options plus -l/--length.
"b2sum" => uu_app_common(), // TODO: Implement -l/--length
"b2sum" => uu_app_length(),
// These have never been part of GNU Coreutils, but can function with the same
// options as md5sum.
"sha3-224sum" | "sha3-256sum" | "sha3-384sum" | "sha3-512sum" => uu_app_common(),

View file

@ -38,10 +38,25 @@ pub trait Digest {
}
}
pub struct Blake2b(blake2b_simd::State);
/// first element of the tuple is the blake2b state
/// second is the number of output bits
pub struct Blake2b(blake2b_simd::State, usize);
impl Blake2b {
/// Return a new Blake2b instance with a custom output bytes length
pub fn with_output_bytes(output_bytes: usize) -> Self {
let mut params = blake2b_simd::Params::new();
params.hash_length(output_bytes);
let state = params.to_state();
Self(state, output_bytes * 8)
}
}
impl Digest for Blake2b {
fn new() -> Self {
Self(blake2b_simd::State::new())
// by default, Blake2b output is 512 bits long (= 64B)
Self::with_output_bytes(64)
}
fn hash_update(&mut self, input: &[u8]) {
@ -54,11 +69,11 @@ impl Digest for Blake2b {
}
fn reset(&mut self) {
*self = Self::new();
*self = Self::with_output_bytes(self.output_bytes());
}
fn output_bits(&self) -> usize {
512
self.1
}
}

View file

@ -125,6 +125,70 @@ fn test_check_sha1() {
.stderr_is("");
}
#[test]
fn test_check_b2sum_length_option_0() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.write("testf", "foobar\n");
at.write("testf.b2sum", "9e2bf63e933e610efee4a8d6cd4a9387e80860edee97e27db3b37a828d226ab1eb92a9cdd8ca9ca67a753edaf8bd89a0558496f67a30af6f766943839acf0110 testf\n");
scene
.ccmd("b2sum")
.arg("--length=0")
.arg("-c")
.arg(at.subdir.join("testf.b2sum"))
.succeeds()
.stdout_only("testf: OK\n");
}
#[test]
fn test_check_b2sum_length_option_8() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.write("testf", "foobar\n");
at.write("testf.b2sum", "6a testf\n");
scene
.ccmd("b2sum")
.arg("--length=8")
.arg("-c")
.arg(at.subdir.join("testf.b2sum"))
.succeeds()
.stdout_only("testf: OK\n");
}
#[test]
fn test_invalid_b2sum_length_option_not_multiple_of_8() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.write("testf", "foobar\n");
scene
.ccmd("b2sum")
.arg("--length=9")
.arg(at.subdir.join("testf"))
.fails()
.code_is(1);
}
#[test]
fn test_invalid_b2sum_length_option_too_large() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.write("testf", "foobar\n");
scene
.ccmd("b2sum")
.arg("--length=513")
.arg(at.subdir.join("testf"))
.fails()
.code_is(1);
}
#[test]
fn test_check_file_not_found_warning() {
let scene = TestScenario::new(util_name!());