From 231987b10956ed775749d7609c0e607858e162df Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 12:48:19 +0530 Subject: [PATCH 1/9] cksum: create initial implementation of the --length option --- src/uu/cksum/src/cksum.rs | 56 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index 245760409..8e6f4f3af 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -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; @@ -36,7 +36,12 @@ 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, usize) { +// enum CksumError + +fn detect_algo( + program: &str, + length: Option, +) -> (&'static str, Box, usize) { match program { ALGORITHM_OPTIONS_SYSV => ( ALGORITHM_OPTIONS_SYSV, @@ -85,7 +90,11 @@ fn detect_algo(program: &str) -> (&'static str, Box, usize ), ALGORITHM_OPTIONS_BLAKE2B => ( ALGORITHM_OPTIONS_BLAKE2B, - Box::new(Blake2b::new()) as Box, + Box::new(if let Some(length) = length { + Blake2b::with_output_bytes(length) + } else { + Blake2b::new() + }) as Box, 512, ), ALGORITHM_OPTIONS_SM3 => ( @@ -115,6 +124,10 @@ fn cksum<'a, I>(mut options: Options, files: I) -> UResult<()> where I: Iterator, { + // if options.length != None && options.algo_name != ALGORITHM_OPTIONS_BLAKE2B { + // return UError; + // } + for filename in files { let filename = Path::new(filename); let stdin_buf; @@ -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] @@ -228,7 +242,33 @@ 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::(options::LENGTH); + let length = if let Some(length) = input_length { + if algo_name != ALGORITHM_OPTIONS_BLAKE2B { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "--length is only supported with --algorithm=blake2b", + ) + .into()); + } + + if length % 8 != 0 { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + // TODO: Fix formatting for this error message + // GNU has the executable path/name on both lines + format!("invalid length {length}\nlength is not a multiple of 8"), + ) + .into()); + } + + Some(length / 8) + } else { + None + }; + + let (name, algo, bits) = detect_algo(algo_name, length); + let opts = Options { algo_name: name, digest: algo, @@ -282,5 +322,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) } From 037073d852c1af1100d1931418fd921fcf2073b5 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 15:59:29 +0530 Subject: [PATCH 2/9] cksum: make the output formatting match GNU --- src/uu/cksum/src/cksum.rs | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index 8e6f4f3af..ed9f3573f 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -111,6 +111,7 @@ struct Options { digest: Box, output_bits: usize, untagged: bool, + length: Option, } /// Calculate checksum @@ -174,7 +175,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 { @@ -244,24 +250,28 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let input_length = matches.get_one::(options::LENGTH); let length = if let Some(length) = input_length { - if algo_name != ALGORITHM_OPTIONS_BLAKE2B { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "--length is only supported with --algorithm=blake2b", - ) - .into()); - } - + if length % 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, - // TODO: Fix formatting for this error message - // GNU has the executable path/name on both lines - format!("invalid length {length}\nlength is not a multiple of 8"), + "length is not a multiple of 8", ) .into()); - } + } + 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(length / 8) } else { None @@ -273,6 +283,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { algo_name: name, digest: algo, output_bits: bits, + length, untagged: matches.get_flag(options::UNTAGGED), }; From 09ef150085f34b5e260b6a75d15e8da4a9721681 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 16:01:22 +0530 Subject: [PATCH 3/9] tests/cksum: add tests for the length argument --- tests/by-util/test_cksum.rs | 34 +++++++++++++++++++ .../fixtures/cksum/supported_length.expected | 2 ++ .../cksum/unsupported_length.expected | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 tests/fixtures/cksum/supported_length.expected create mode 100644 tests/fixtures/cksum/unsupported_length.expected diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index a9d9b272b..dbf7264e8 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -228,3 +228,37 @@ 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"); +} diff --git a/tests/fixtures/cksum/supported_length.expected b/tests/fixtures/cksum/supported_length.expected new file mode 100644 index 000000000..a2edb23e9 --- /dev/null +++ b/tests/fixtures/cksum/supported_length.expected @@ -0,0 +1,2 @@ +BLAKE2b-16 (lorem_ipsum.txt) = 7e2f +BLAKE2b-16 (alice_in_wonderland.txt) = a546 diff --git a/tests/fixtures/cksum/unsupported_length.expected b/tests/fixtures/cksum/unsupported_length.expected new file mode 100644 index 000000000..c2a05fec7 --- /dev/null +++ b/tests/fixtures/cksum/unsupported_length.expected @@ -0,0 +1,2 @@ +cksum: invalid length: ‘15’ +cksum: length is not a multiple of 8 From 7caa0bcdea3dcee68d954c19f4a4961a61843571 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 16:02:10 +0530 Subject: [PATCH 4/9] cksum: fix formatting in cksum.rs --- src/uu/cksum/src/cksum.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index ed9f3573f..2a4b539f9 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -250,7 +250,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let input_length = matches.get_one::(options::LENGTH); let length = if let Some(length) = input_length { - if length % 8 != 0 { // GNU's implementation seem to use these quotation marks // in their error messages, so we do the same. @@ -260,15 +259,15 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { "length is not a multiple of 8", ) .into()); - } + } - if algo_name != ALGORITHM_OPTIONS_BLAKE2B { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "--length is only supported with --algorithm=blake2b", - ) - .into()); - } + 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. From aec0cfa6e3e0939c578835c5a526f81d4cea9cf6 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 16:05:20 +0530 Subject: [PATCH 5/9] cksum: remove commented code --- src/uu/cksum/src/cksum.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index 2a4b539f9..029aff998 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -36,8 +36,6 @@ const ALGORITHM_OPTIONS_SHA512: &str = "sha512"; const ALGORITHM_OPTIONS_BLAKE2B: &str = "blake2b"; const ALGORITHM_OPTIONS_SM3: &str = "sm3"; -// enum CksumError - fn detect_algo( program: &str, length: Option, @@ -125,10 +123,6 @@ fn cksum<'a, I>(mut options: Options, files: I) -> UResult<()> where I: Iterator, { - // if options.length != None && options.algo_name != ALGORITHM_OPTIONS_BLAKE2B { - // return UError; - // } - for filename in files { let filename = Path::new(filename); let stdin_buf; From e1863ac64e0bb501be8dc7ef3cd0f6c565e33d35 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 20:14:30 +0530 Subject: [PATCH 6/9] tests/cksum: test when the --length argument is 0 or >512 --- tests/by-util/test_cksum.rs | 24 +++++++++++++++++++ tests/fixtures/cksum/length_is_zero.expected | 2 ++ .../cksum/length_larger_than_512.expected | 2 ++ 3 files changed, 28 insertions(+) create mode 100644 tests/fixtures/cksum/length_is_zero.expected create mode 100644 tests/fixtures/cksum/length_larger_than_512.expected diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index dbf7264e8..0e1aec38d 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -262,3 +262,27 @@ fn test_length() { .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"); +} \ No newline at end of file diff --git a/tests/fixtures/cksum/length_is_zero.expected b/tests/fixtures/cksum/length_is_zero.expected new file mode 100644 index 000000000..97d06eb6f --- /dev/null +++ b/tests/fixtures/cksum/length_is_zero.expected @@ -0,0 +1,2 @@ +BLAKE2b (lorem_ipsum.txt) = 0e97a09189e560c3789c0bff1f020166861ef857d1fbfe4574de1842e3c06cabb9575e4af6309a166158c2b408d3c038c1b49d828b35158142cdc0396d1195c3 +BLAKE2b (alice_in_wonderland.txt) = 91b8b0f0868e905ad18b8ac35e4a1dacd289857b19258ab5d1e071761af758b0134ec152d4f011fe1825ca889c80c2e072ca70eb50548c25fc49a98937515af4 diff --git a/tests/fixtures/cksum/length_larger_than_512.expected b/tests/fixtures/cksum/length_larger_than_512.expected new file mode 100644 index 000000000..312b6230e --- /dev/null +++ b/tests/fixtures/cksum/length_larger_than_512.expected @@ -0,0 +1,2 @@ +cksum: invalid length: ‘1024’ +cksum: maximum digest length for ‘BLAKE2b’ is 512 bits From e7cb4e9ff0e685a14f10323fc5f0a0fff8f1b889 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 20:28:03 +0530 Subject: [PATCH 7/9] cksum: properly handle cases where --lenghth is 0 or >512 --- src/uu/cksum/src/cksum.rs | 53 ++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index 029aff998..5e21b3876 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -244,28 +244,41 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let input_length = matches.get_one::(options::LENGTH); let length = if let Some(length) = input_length { - if length % 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()); - } + match length.to_owned() { + n if n == 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}"); - if algo_name != ALGORITHM_OPTIONS_BLAKE2B { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "--length is only supported with --algorithm=blake2b", - ) - .into()); - } + 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(length / 8) + // Divide by 8, as our blake2b implementation expects bytes + // instead of bits. + Some(n / 8) + } + } } else { None }; From 1fc6a760f3e31f80c8eef080a21ae4f073a8e242 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 20:31:52 +0530 Subject: [PATCH 8/9] tests/cksum: fix formatting --- tests/by-util/test_cksum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index 0e1aec38d..00c768164 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -285,4 +285,4 @@ fn test_length_is_zero() { .succeeds() .no_stderr() .stdout_is_fixture("length_is_zero.expected"); -} \ No newline at end of file +} From d99002157208a3514ab0df3fb4411ceeec32d5e4 Mon Sep 17 00:00:00 2001 From: Vardhan Patil Date: Sat, 30 Dec 2023 20:39:09 +0530 Subject: [PATCH 9/9] cksum: remove redundant guard --- src/uu/cksum/src/cksum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index 5e21b3876..e8d7da60e 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -245,7 +245,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let input_length = matches.get_one::(options::LENGTH); let length = if let Some(length) = input_length { match length.to_owned() { - n if n == 0 => None, + 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.