@@ -464,6 +464,9 @@ impl LineInfo {
464464
465465 let mut r = * regex;
466466 if !algo_based {
467+ // The cached regex ensures that when processing non-algo based regexes,
468+ // its cannot be changed (can't have single and double space regexes
469+ // used in the same file).
467470 if cached_regex. is_some ( ) {
468471 r = cached_regex. unwrap ( ) ;
469472 } else {
@@ -636,13 +639,101 @@ fn identify_algo_name_and_length(
636639 Some ( ( algorithm, bits) )
637640}
638641
642+ /// Given a filename and an algorithm, compute the digest and compare it with
643+ /// the expected one.
644+ fn compute_and_check_digest_from_file (
645+ filename : & [ u8 ] ,
646+ expected_checksum : & str ,
647+ mut algo : HashAlgorithm ,
648+ opts : ChecksumOptions ,
649+ ) -> Result < ( ) , LineCheckError > {
650+ let ( filename_to_check_unescaped, prefix) = unescape_filename ( filename) ;
651+ let real_filename_to_check = os_str_from_bytes ( & filename_to_check_unescaped) ?;
652+
653+ // Open the input file
654+ let file_to_check = get_file_to_check ( & real_filename_to_check, opts) ?;
655+ let mut file_reader = BufReader :: new ( file_to_check) ;
656+
657+ // Read the file and calculate the checksum
658+ let create_fn = & mut algo. create_fn ;
659+ let mut digest = create_fn ( ) ;
660+ let ( calculated_checksum, _) =
661+ digest_reader ( & mut digest, & mut file_reader, opts. binary , algo. bits ) . unwrap ( ) ;
662+
663+ // Do the checksum validation
664+ let checksum_correct = expected_checksum == calculated_checksum;
665+ print_file_report (
666+ std:: io:: stdout ( ) ,
667+ filename,
668+ FileChecksumResult :: from_bool ( checksum_correct) ,
669+ prefix,
670+ opts,
671+ ) ;
672+
673+ if checksum_correct {
674+ Ok ( ( ) )
675+ } else {
676+ Err ( LineCheckError :: DigestMismatch )
677+ }
678+ }
679+
680+ /// Check a digest checksum with non-algo based pre-treatment.
681+ fn process_algo_based_line (
682+ line_info : & LineInfo ,
683+ cli_algo_name : Option < & str > ,
684+ opts : ChecksumOptions ,
685+ ) -> Result < ( ) , LineCheckError > {
686+ let filename_to_check = line_info. filename . as_slice ( ) ;
687+ let expected_checksum =
688+ get_expected_digest_as_hex_string ( line_info) . ok_or ( LineCheckError :: ImproperlyFormatted ) ?;
689+
690+ let ( algo_name, algo_bitlen) = identify_algo_name_and_length ( line_info, cli_algo_name)
691+ . ok_or ( LineCheckError :: ImproperlyFormatted ) ?;
692+
693+ let algo = detect_algo ( & algo_name, algo_bitlen) ?;
694+
695+ compute_and_check_digest_from_file ( filename_to_check, & expected_checksum, algo, opts)
696+ }
697+
698+ /// Check a digest checksum with non-algo based pre-treatment.
699+ fn process_non_algo_based_line (
700+ i : usize ,
701+ line_info : & LineInfo ,
702+ cli_algo_name : & str ,
703+ cli_algo_length : Option < usize > ,
704+ opts : ChecksumOptions ,
705+ ) -> Result < ( ) , LineCheckError > {
706+ let mut filename_to_check = line_info. filename . as_slice ( ) ;
707+ if filename_to_check. starts_with ( b"*" ) && i == 0 && line_info. regex_str ( ) == SINGLE_SPACE_REGEX
708+ {
709+ // Remove the leading asterisk if present - only for the first line
710+ filename_to_check = & filename_to_check[ 1 ..] ;
711+ }
712+ let expected_checksum =
713+ get_expected_digest_as_hex_string ( line_info) . ok_or ( LineCheckError :: ImproperlyFormatted ) ?;
714+
715+ // When a specific algorithm name is input, use it and use the provided bits
716+ // except when dealing with blake2b, where we will detect the length
717+ let ( algo_name, algo_bitlen) = if cli_algo_name == ALGORITHM_OPTIONS_BLAKE2B {
718+ // division by 2 converts the length of the Blake2b checksum from hexadecimal
719+ // characters to bytes, as each byte is represented by two hexadecimal characters.
720+ let length = Some ( expected_checksum. len ( ) / 2 ) ;
721+ ( ALGORITHM_OPTIONS_BLAKE2B . to_string ( ) , length)
722+ } else {
723+ ( cli_algo_name. to_lowercase ( ) , cli_algo_length)
724+ } ;
725+
726+ let algo = detect_algo ( & algo_name, algo_bitlen) ?;
727+
728+ compute_and_check_digest_from_file ( filename_to_check, & expected_checksum, algo, opts)
729+ }
730+
639731/// Parses a checksum line, detect the algorithm to use, read the file and produce
640732/// its digest, and compare it to the expected value.
641733///
642734/// Returns `Ok(bool)` if the comparison happened, bool indicates if the digest
643735/// matched the expected.
644736/// If the comparison didn't happen, return a `LineChecksumError`.
645- #[ allow( clippy:: too_many_arguments) ]
646737fn process_checksum_line (
647738 filename_input : & OsStr ,
648739 line : & OsStr ,
@@ -654,82 +745,23 @@ fn process_checksum_line(
654745) -> Result < ( ) , LineCheckError > {
655746 let line_bytes = os_str_as_bytes ( line) ?;
656747
657- // early return on empty or commented lines.
748+ // Early return on empty or commented lines.
658749 if line. is_empty ( ) || line_bytes. starts_with ( b"#" ) {
659750 return Err ( LineCheckError :: Skipped ) ;
660751 }
661752
753+ // Use `LineInfo` to extract the data of a line.
754+ // Then, depending on its format, apply a different pre-treatment.
662755 if let Some ( line_info) = LineInfo :: parse ( line, cached_regex) {
663- // The cached regex ensures that when processing non-algo based regexes,
664- // its cannot be changed (can't have single and double space regexes
665- // used in the same file).
666- if cached_regex. is_none ( ) && !line_info. is_algo_based ( ) {
667- let _ = cached_regex. insert ( line_info. regex ) ;
668- }
669-
670- let mut filename_to_check = line_info. filename . as_slice ( ) ;
671-
672- if filename_to_check. starts_with ( b"*" )
673- && i == 0
674- && line_info. regex_str ( ) == SINGLE_SPACE_REGEX
675- {
676- // Remove the leading asterisk if present - only for the first line
677- filename_to_check = & filename_to_check[ 1 ..] ;
678- }
679-
680- let expected_checksum = get_expected_digest_as_hex_string ( & line_info)
681- . ok_or ( LineCheckError :: ImproperlyFormatted ) ?;
682-
683- // If the algo_name is provided, we use it, otherwise we try to detect it
684- let ( algo_name, length) = if line_info. is_algo_based ( ) {
685- identify_algo_name_and_length ( & line_info, cli_algo_name)
686- . ok_or ( LineCheckError :: ImproperlyFormatted ) ?
687- } else if let Some ( a) = cli_algo_name {
688- // When a specific algorithm name is input, use it and use the provided bits
689- // except when dealing with blake2b, where we will detect the length
690- if cli_algo_name == Some ( ALGORITHM_OPTIONS_BLAKE2B ) {
691- // division by 2 converts the length of the Blake2b checksum from hexadecimal
692- // characters to bytes, as each byte is represented by two hexadecimal characters.
693- let length = Some ( expected_checksum. len ( ) / 2 ) ;
694- ( ALGORITHM_OPTIONS_BLAKE2B . to_string ( ) , length)
695- } else {
696- ( a. to_lowercase ( ) , cli_algo_length)
697- }
756+ if line_info. is_algo_based ( ) {
757+ process_algo_based_line ( & line_info, cli_algo_name, opts)
758+ } else if let Some ( cli_algo) = cli_algo_name {
759+ // If we match a non-algo based regex, we expect a cli argument
760+ // to give us the algorithm to use
761+ process_non_algo_based_line ( i, & line_info, cli_algo, cli_algo_length, opts)
698762 } else {
699- // Default case if no algorithm is specified and non-algo based format is matched
763+ // We have no clue of what algorithm to use
700764 return Err ( LineCheckError :: ImproperlyFormatted ) ;
701- } ;
702-
703- let mut algo = detect_algo ( & algo_name, length) ?;
704-
705- let ( filename_to_check_unescaped, prefix) = unescape_filename ( filename_to_check) ;
706-
707- let real_filename_to_check = os_str_from_bytes ( & filename_to_check_unescaped) ?;
708-
709- // manage the input file
710- let file_to_check = get_file_to_check ( & real_filename_to_check, opts) ?;
711- let mut file_reader = BufReader :: new ( file_to_check) ;
712-
713- // Read the file and calculate the checksum
714- let create_fn = & mut algo. create_fn ;
715- let mut digest = create_fn ( ) ;
716- let ( calculated_checksum, _) =
717- digest_reader ( & mut digest, & mut file_reader, opts. binary , algo. bits ) . unwrap ( ) ;
718-
719- // Do the checksum validation
720- let checksum_correct = expected_checksum == calculated_checksum;
721- print_file_report (
722- std:: io:: stdout ( ) ,
723- filename_to_check,
724- FileChecksumResult :: from_bool ( checksum_correct) ,
725- prefix,
726- opts,
727- ) ;
728-
729- if checksum_correct {
730- Ok ( ( ) )
731- } else {
732- Err ( LineCheckError :: DigestMismatch )
733765 }
734766 } else {
735767 if opts. warn {
0 commit comments