From bbd80e4061499f62faf3b0c27b866b6590860a10 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Tue, 14 May 2024 19:17:19 +0200 Subject: [PATCH] cksum: various improvements/fixes --- src/uu/cksum/src/cksum.rs | 58 ++++++++++++++++++++---------------- tests/by-util/test_cksum.rs | 59 ++++++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 36 deletions(-) diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index 00576d94e..b23550616 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -15,6 +15,7 @@ use std::io::{self, stdin, stdout, BufReader, Read, Write}; use std::iter; use std::path::Path; use uucore::checksum::cksum_output; +use uucore::display::Quotable; use uucore::error::set_exit_code; use uucore::{ encoding, @@ -419,8 +420,9 @@ where { // Regexp to handle the two input formats: // 1. [-] () = + // algo must be uppercase or b (for blake2b) // 2. [* ] - let regex_pattern = r"^(?P\w+)(-(?P\d+))?\s?\((?P.*)\) = (?P[a-fA-F0-9]+)$|^(?P[a-fA-F0-9]+)\s[* ](?P.*)"; + let regex_pattern = r"^(?P[A-Z0-9b]+)(-(?P\d+))?\s?\((?P.*)\) = (?P[a-fA-F0-9]+)$|^(?P[a-fA-F0-9]+)\s[* ](?P.*)"; let re = Regex::new(regex_pattern).unwrap(); // if cksum has several input files, it will print the result for each file @@ -474,7 +476,7 @@ where .as_str(); // If the algo_name is provided, we use it, otherwise we try to detect it - let algo_details = if algo_based_format { + let (algo_name, length) = if algo_based_format { // When the algo-based format is matched, extract details from regex captures let algorithm = caps.name("algo").map_or("", |m| m.as_str()).to_lowercase(); let bits = caps @@ -488,18 +490,18 @@ where // Default case if no algorithm is specified and non-algo based format is matched (String::new(), None) }; - if algo_based_format - && algo_name_input.map_or(false, |input| algo_details.0 != input) - { + + if algo_based_format && algo_name_input.map_or(false, |input| algo_name != input) { bad_format += 1; continue; } - if algo_details.0.is_empty() { + + if algo_name.is_empty() { // we haven't been able to detect the algo name. No point to continue properly_formatted = false; continue; } - let (_, mut algo, bits) = detect_algo(&algo_details.0, algo_details.1); + let (_, mut algo, bits) = detect_algo(&algo_name, length); // manage the input file let file_to_check: Box = if filename_to_check == "-" { @@ -538,9 +540,15 @@ where // not a single line correctly formatted found // return an error if !properly_formatted { + let filename = filename_input.to_string_lossy(); uucore::show_error!( "{}: no properly formatted checksum lines found", - filename_input.to_string_lossy() + if input_is_stdin { + "standard input" + } else { + &filename + } + .maybe_quote() ); set_exit_code(1); } @@ -586,6 +594,23 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { .into()); } + let input_length = matches.get_one::(options::LENGTH); + + let length = match input_length { + Some(length) => { + 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()); + } + } + None => None, + }; + if check { let text_flag: bool = matches.get_flag(options::TEXT); let binary_flag: bool = matches.get_flag(options::BINARY); @@ -612,23 +637,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { }; } - let input_length = matches.get_one::(options::LENGTH); - - let length = match input_length { - Some(length) => { - if algo_name != ALGORITHM_OPTIONS_BLAKE2B { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "--length is only supported with --algorithm=blake2b", - ) - .into()); - } else { - calculate_blake2b_length(*length)? - } - } - None => None, - }; - let (tag, asterisk) = handle_tag_text_binary_flags(&matches)?; let (name, algo, bits) = detect_algo(algo_name, length); diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index 0a15f4ef3..de53a19a9 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -316,6 +316,16 @@ fn test_length_with_wrong_algorithm() { .no_stdout() .stderr_contains("cksum: --length is only supported with --algorithm=blake2b") .code_is(1); + + new_ucmd!() + .arg("--length=16") + .arg("--algorithm=md5") + .arg("-c") + .arg("foo.sums") + .fails() + .no_stdout() + .stderr_contains("cksum: --length is only supported with --algorithm=blake2b") + .code_is(1); } #[test] @@ -725,22 +735,36 @@ fn test_check_algo_err() { .code_is(1); } +#[test] +fn test_check_pipe() { + let scene = TestScenario::new(util_name!()); + + let at = &scene.fixtures; + + at.touch("f"); + + scene + .ucmd() + .arg("--check") + .arg("-") + .pipe_in("f") + .fails() + .no_stdout() + .stderr_contains("cksum: 'standard input': no properly formatted checksum lines found") + .code_is(1); +} + #[test] fn test_cksum_check() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; - let commands = [ - vec!["-a", "sha384"], - vec!["-a", "blake2b"], - vec!["-a", "blake2b", "-l", "384"], - vec!["-a", "sm3"], - ]; + at.touch("f"); - at.touch("CHECKSUM"); - for command in &commands { - let result = scene.ucmd().args(command).arg("f").succeeds(); - at.append("CHECKSUM", result.stdout_str()); - } + at.write("CHECKSUM", "\ + SHA384 (f) = 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b\n\ + BLAKE2b (f) = 786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce\n\ + BLAKE2b-384 (f) = b32811423377f52d7862286ee1a72ee540524380fda1724a6f25d7978c6fd3244a6caf0498812673c5e05ef583825100\n\ + SM3 (f) = 1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b\n"); scene .ucmd() .arg("--check") @@ -775,6 +799,19 @@ fn test_cksum_check() { .stderr_contains("line is improperly formatted"); } +#[test] +fn test_cksum_check_case() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + + at.touch("f"); + at.write( + "CHECKSUM", + "Sha1 (f) = da39a3ee5e6b4b0d3255bfef95601890afd80709\n", + ); + scene.ucmd().arg("--check").arg("CHECKSUM").fails(); +} + #[test] fn test_cksum_check_invalid() { let scene = TestScenario::new(util_name!());