Skip to content

Commit

Permalink
feat(checksum): get rid of ChecksumResult at the line level
Browse files Browse the repository at this point in the history
  • Loading branch information
RenjiSann committed Aug 31, 2024
1 parent f71bd2c commit 1d6dbc4
Showing 1 changed file with 38 additions and 44 deletions.
82 changes: 38 additions & 44 deletions src/uucore/src/lib/features/checksum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ impl UError for ChecksumError {

enum LineCheckError {
UError(Box<dyn UError>),
ImproperlyFormatted,
ImproperlyFormatted(bool),
CantOpenFile,
Skipped,
}

Expand Down Expand Up @@ -243,10 +244,9 @@ fn get_expected_checksum(filename: &str, checksum: &[u8]) -> UResult<String> {
/// Returns a reader that reads from the specified file, or from stdin if `filename_to_check` is "-".
fn get_file_to_check(
filename: &OsStr,
filename_lossy: &str,
ignore_missing: bool,
res: &mut ChecksumResult,
) -> Option<Box<dyn Read>> {
let filename_lossy = String::from_utf8_lossy(os_str_as_bytes(filename).expect("UTF-8 error"));
if filename == "-" {
Some(Box::new(stdin())) // Use stdin if "-" is specified in the checksum file

Check warning on line 251 in src/uucore/src/lib/features/checksum/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/uucore/src/lib/features/checksum/mod.rs#L251

Added line #L251 was not covered by tests
} else {
Expand All @@ -268,7 +268,6 @@ fn get_file_to_check(
show!(err.map_err_context(|| filename_lossy.to_string()));
println!("{}: FAILED open or read", filename_lossy);
}
res.failed_open_file += 1;
// we could not open the file but we want to continue
None
}
Expand Down Expand Up @@ -302,8 +301,6 @@ fn get_input_file(filename: &OsStr) -> UResult<Box<dyn Read>> {
fn identify_algo_name_and_length(
caps: &Captures,
algo_name_input: Option<&str>,
res: &mut ChecksumResult,
properly_formatted: &mut bool,
) -> Option<(String, Option<usize>)> {
// When the algo-based format is matched, extract details from regex captures
let algorithm = caps
Expand All @@ -317,14 +314,11 @@ fn identify_algo_name_and_length(
// (for example SHA1 (f) = d...)
// Also handle the case cksum -s sm3 but the file contains other formats
if algo_name_input.is_some() && algo_name_input != Some(&algorithm) {
res.bad_format += 1;
*properly_formatted = false;
return None;
}

if !SUPPORTED_ALGORITHMS.contains(&algorithm.as_str()) {
// Not supported algo, leave early
*properly_formatted = false;
return None;

Check warning on line 322 in src/uucore/src/lib/features/checksum/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/uucore/src/lib/features/checksum/mod.rs#L322

Added line #L322 was not covered by tests
}

Expand All @@ -336,28 +330,35 @@ fn identify_algo_name_and_length(
if bits_value % 8 == 0 {
Some(Some(bits_value / 8))
} else {
*properly_formatted = false;
None // Return None to signal a divisibility issue

Check warning on line 333 in src/uucore/src/lib/features/checksum/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/uucore/src/lib/features/checksum/mod.rs#L333

Added line #L333 was not covered by tests
}
})?;

Some((algorithm, bits))
}

fn print_line_result(is_checksum_correct: bool, opts: ChecksumOptions, filename: &str) {
if is_checksum_correct {
if !opts.quiet && !opts.status {
println!("{filename}: OK");
}
} else if !opts.status {
println!("{filename}: FAILED");
}
}

#[allow(clippy::too_many_arguments)]
fn process_checksum_line(
filename_input: &OsStr,
line: &OsStr,
i: usize,
chosen_regex: &Regex,
is_algo_based_format: bool,
res: &mut ChecksumResult,
cli_algo_name: Option<&str>,
cli_algo_length: Option<usize>,
properly_formatted: &mut bool,
correct_format: &mut usize,
opts: ChecksumOptions,
) -> Result<(), LineCheckError> {
) -> Result<bool, LineCheckError> {
if line.is_empty() || os_str_as_bytes(line)?.starts_with(b"#") {
// Skip empty and comment lines.
return Err(LineCheckError::Skipped);
Expand Down Expand Up @@ -387,23 +388,19 @@ fn process_checksum_line(

let filename_lossy = String::from_utf8_lossy(filename_to_check);
let expected_checksum = get_expected_checksum(&filename_lossy, checksum)
.map_err(LineCheckError::from)?;
.map_err(|_| LineCheckError::ImproperlyFormatted(true))?;

// If the algo_name is provided, we use it, otherwise we try to detect it
let (algo_name, length) = if is_algo_based_format {
let (algo, mut len) =
identify_algo_name_and_length(&caps, cli_algo_name, res, properly_formatted)
.unwrap_or((String::new(), None));
let (algo, mut len) = identify_algo_name_and_length(&caps, cli_algo_name)
.unwrap_or((String::new(), None));

// Specific case for BLAKE2b length
if algo == ALGORITHM_OPTIONS_BLAKE2B && len.is_none() {
if expected_checksum.len() / 2 == 64 {
len = Some(64);
} else {
// FIXME(dprn): Improve error handling
res.bad_format += 1;
*properly_formatted = false;
return Ok(());
return Err(LineCheckError::ImproperlyFormatted(true));

Check warning on line 403 in src/uucore/src/lib/features/checksum/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/uucore/src/lib/features/checksum/mod.rs#L403

Added line #L403 was not covered by tests
}
}
(algo, len)
Expand All @@ -425,10 +422,7 @@ fn process_checksum_line(

if algo_name.is_empty() {
// we haven't been able to detect the algo name. No point to continue
*properly_formatted = false;

// FIXME(dprn): report error in some way ?
return Ok(());
return Err(LineCheckError::ImproperlyFormatted(true));
}
let mut algo = algo::detect_algo(&algo_name, length)?;

Expand All @@ -442,11 +436,11 @@ fn process_checksum_line(

// manage the input file
let file_to_check =
match get_file_to_check(real_filename_to_check, opts.ignore_missing, res) {
match get_file_to_check(real_filename_to_check, &filename_lossy, opts.ignore_missing) {
Some(file) => file,
None => {
// FIXME(dprn): report error in some way ?
return Ok(());
return Err(LineCheckError::CantOpenFile);
}
};
let mut file_reader = BufReader::new(file_to_check);
Expand All @@ -457,18 +451,16 @@ fn process_checksum_line(
digest_reader(&mut digest, &mut file_reader, opts.binary, algo.bits).unwrap();

// Do the checksum validation
if expected_checksum == calculated_checksum {
if !opts.quiet && !opts.status {
println!("{prefix}{filename_lossy}: OK");
}
*correct_format += 1;
} else {
if !opts.status {
println!("{prefix}{filename_lossy}: FAILED");
}
res.failed_cksum += 1;
}
let is_checksum_correct = expected_checksum == calculated_checksum;
print_line_result(
is_checksum_correct,
opts,
&format!("{}{}", prefix, filename_lossy),
);

Ok(is_checksum_correct)
} else {
// The line did not match the regex.
if opts.warn {
let algo = if let Some(algo_name_input) = cli_algo_name {
algo_name_input.to_uppercase()
Expand All @@ -484,9 +476,8 @@ fn process_checksum_line(
);
}

res.bad_format += 1;
Err(LineCheckError::ImproperlyFormatted(false))
}
Ok(())
}

fn process_checksum_file(
Expand Down Expand Up @@ -535,20 +526,23 @@ fn process_checksum_file(
i,
&chosen_regex,
is_algo_based_format,
&mut res,
algo_name_input,
length_input,
&mut properly_formatted,
&mut correct_format,
opts,
) {
Err(UError(e)) => return Err(e.into()),

Check warning on line 534 in src/uucore/src/lib/features/checksum/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/uucore/src/lib/features/checksum/mod.rs#L534

Added line #L534 was not covered by tests
Err(ImproperlyFormatted) => {
Err(ImproperlyFormatted(reset_properly_formatted)) => {
res.bad_format += 1;
if reset_properly_formatted {
properly_formatted = false;
}
continue;
}
Err(CantOpenFile) => res.failed_open_file += 1,
Err(Skipped) => continue,
Ok(_) => (),
Ok(true) => correct_format += 1,
Ok(false) => res.failed_cksum += 1,
}
}

Expand Down

0 comments on commit 1d6dbc4

Please sign in to comment.