1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Address review comments

This commit is contained in:
Sylvestre Ledru 2024-06-18 18:49:17 +02:00
parent ab2cc2f17a
commit 2e704b8572

View file

@ -68,12 +68,11 @@ pub struct HashAlgorithm {
pub bits: usize, pub bits: usize,
} }
#[derive(Default)]
struct ChecksumResult { struct ChecksumResult {
pub bad_format: i32, pub bad_format: i32,
pub failed_cksum: i32, pub failed_cksum: i32,
pub failed_open_file: i32, pub failed_open_file: i32,
pub correct_format: i32,
pub properly_formatted: bool,
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -322,7 +321,7 @@ fn determine_regex(
.into()) .into())
} }
// Function to convert bytes to a hexadecimal string // Converts bytes to a hexadecimal string
fn bytes_to_hex(bytes: &[u8]) -> String { fn bytes_to_hex(bytes: &[u8]) -> String {
bytes bytes
.iter() .iter()
@ -331,8 +330,6 @@ fn bytes_to_hex(bytes: &[u8]) -> String {
.join("") .join("")
} }
// Function to get the expected checksum
fn get_expected_checksum( fn get_expected_checksum(
filename: &str, filename: &str,
caps: &regex::Captures, caps: &regex::Captures,
@ -358,22 +355,21 @@ fn get_expected_checksum(
} }
} }
/// Returns a reader that reads from the specified file, or from stdin if `input_is_stdin` is true. /// Returns a reader that reads from the specified file, or from stdin if `filename_to_check` is "-".
fn get_file_to_check( fn get_file_to_check(
filename_to_check: &str, filename: &str,
filename_to_check_unescaped: &str,
ignore_missing: bool, ignore_missing: bool,
res: &mut ChecksumResult, res: &mut ChecksumResult,
) -> Option<Box<dyn Read>> { ) -> Option<Box<dyn Read>> {
if filename_to_check == "-" { if filename == "-" {
Some(Box::new(stdin())) // Use stdin if "-" is specified in the checksum file Some(Box::new(stdin())) // Use stdin if "-" is specified in the checksum file
} else { } else {
match File::open(filename_to_check_unescaped) { match File::open(filename) {
Ok(f) => { Ok(f) => {
if f.metadata().ok()?.is_dir() { if f.metadata().ok()?.is_dir() {
show!(USimpleError::new( show!(USimpleError::new(
1, 1,
format!("{}: Is a directory", filename_to_check_unescaped) format!("{}: Is a directory", filename)
)); ));
None None
} else { } else {
@ -383,8 +379,8 @@ fn get_file_to_check(
Err(err) => { Err(err) => {
if !ignore_missing { if !ignore_missing {
// yes, we have both stderr and stdout here // yes, we have both stderr and stdout here
show!(err.map_err_context(|| filename_to_check.to_string())); show!(err.map_err_context(|| filename.to_string()));
println!("{}: FAILED open or read", filename_to_check); println!("{}: FAILED open or read", filename);
} }
res.failed_open_file += 1; res.failed_open_file += 1;
// we could not open the file but we want to continue // we could not open the file but we want to continue
@ -395,33 +391,34 @@ fn get_file_to_check(
} }
/// Returns a reader to the list of checksums /// Returns a reader to the list of checksums
fn get_input_file(filename_input: &OsStr, input_is_stdin: bool) -> UResult<Box<dyn Read>> { fn get_input_file(filename: &OsStr) -> UResult<Box<dyn Read>> {
if input_is_stdin { match File::open(filename) {
Ok(Box::new(stdin())) // Use stdin if "-" is specified Ok(f) => {
if f.metadata()?.is_dir() {
Err(io::Error::new(
io::ErrorKind::Other,
format!("{}: Is a directory", filename.to_string_lossy()),
)
.into())
} else { } else {
match File::open(filename_input) { Ok(Box::new(f))
Ok(f) => Ok(Box::new(f)), }
}
Err(_) => Err(io::Error::new( Err(_) => Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
format!( format!("{}: No such file or directory", filename.to_string_lossy()),
"{}: No such file or directory",
filename_input.to_string_lossy()
),
) )
.into()), .into()),
} }
}
} }
/// Extracts the algorithm name and length from the regex captures if the algo-based format is matched. /// Extracts the algorithm name and length from the regex captures if the algo-based format is matched.
fn get_algo_name_and_length( fn identify_algo_name_and_length(
caps: &regex::Captures, caps: &regex::Captures,
is_algo_based_format: bool,
algo_name_input: Option<&str>, algo_name_input: Option<&str>,
length_input: Option<usize>,
res: &mut ChecksumResult, res: &mut ChecksumResult,
properly_formatted: &mut bool,
) -> (String, Option<usize>) { ) -> (String, Option<usize>) {
if is_algo_based_format {
// When the algo-based format is matched, extract details from regex captures // 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 algorithm = caps.name("algo").map_or("", |m| m.as_str()).to_lowercase();
@ -430,13 +427,13 @@ fn get_algo_name_and_length(
// Also handle the case cksum -s sm3 but the file contains other formats // Also handle the case cksum -s sm3 but the file contains other formats
if algo_name_input.is_some() && algo_name_input != Some(&algorithm) { if algo_name_input.is_some() && algo_name_input != Some(&algorithm) {
res.bad_format += 1; res.bad_format += 1;
res.properly_formatted = false; *properly_formatted = false;
return (String::new(), None); return (String::new(), None);
} }
if !SUPPORTED_ALGORITHMS.contains(&algorithm.as_str()) { if !SUPPORTED_ALGORITHMS.contains(&algorithm.as_str()) {
// Not supported algo, leave early // Not supported algo, leave early
res.properly_formatted = false; *properly_formatted = false;
return (String::new(), None); return (String::new(), None);
} }
@ -445,7 +442,7 @@ fn get_algo_name_and_length(
if bits_value % 8 == 0 { if bits_value % 8 == 0 {
Some(Some(bits_value / 8)) Some(Some(bits_value / 8))
} else { } else {
res.properly_formatted = false; *properly_formatted = false;
None // Return None to signal a divisibility issue None // Return None to signal a divisibility issue
} }
}); });
@ -457,13 +454,6 @@ fn get_algo_name_and_length(
} }
(algorithm, bits.unwrap()) (algorithm, bits.unwrap())
} else if let Some(a) = algo_name_input {
// When a specific algorithm name is input, use it and use the provided bits
(a.to_lowercase(), length_input)
} else {
// Default case if no algorithm is specified and non-algo based format is matched
(String::new(), None)
}
} }
/*** /***
@ -486,16 +476,17 @@ where
{ {
// if cksum has several input files, it will print the result for each file // if cksum has several input files, it will print the result for each file
for filename_input in files { for filename_input in files {
let mut res = ChecksumResult { let mut correct_format = 0;
bad_format: 0, let mut properly_formatted = false;
failed_cksum: 0, let mut res = ChecksumResult::default();
failed_open_file: 0,
correct_format: 0,
properly_formatted: false,
};
let input_is_stdin = filename_input == OsStr::new("-"); let input_is_stdin = filename_input == OsStr::new("-");
let file: Box<dyn Read> = get_input_file(filename_input, input_is_stdin)?; let file: Box<dyn Read> = if input_is_stdin {
// Use stdin if "-" is specified
Box::new(stdin())
} else {
get_input_file(filename_input)?
};
let reader = BufReader::new(file); let reader = BufReader::new(file);
let lines: Vec<String> = reader.lines().collect::<Result<_, _>>()?; let lines: Vec<String> = reader.lines().collect::<Result<_, _>>()?;
@ -504,7 +495,7 @@ where
for (i, line) in lines.iter().enumerate() { for (i, line) in lines.iter().enumerate() {
if let Some(caps) = chosen_regex.captures(line) { if let Some(caps) = chosen_regex.captures(line) {
res.properly_formatted = true; properly_formatted = true;
let mut filename_to_check = caps.name("filename").unwrap().as_str(); let mut filename_to_check = caps.name("filename").unwrap().as_str();
if filename_to_check.starts_with('*') if filename_to_check.starts_with('*')
@ -520,17 +511,24 @@ where
// If the algo_name is provided, we use it, otherwise we try to detect it // If the algo_name is provided, we use it, otherwise we try to detect it
let (algo_name, length) = get_algo_name_and_length( let (algo_name, length) = if is_algo_based_format {
identify_algo_name_and_length(
&caps, &caps,
is_algo_based_format,
algo_name_input, algo_name_input,
length_input,
&mut res, &mut res,
); &mut properly_formatted,
)
} else if let Some(a) = algo_name_input {
// When a specific algorithm name is input, use it and use the provided bits
(a.to_lowercase(), length_input)
} else {
// Default case if no algorithm is specified and non-algo based format is matched
(String::new(), None)
};
if algo_name.is_empty() { if algo_name.is_empty() {
// we haven't been able to detect the algo name. No point to continue // we haven't been able to detect the algo name. No point to continue
res.properly_formatted = false; properly_formatted = false;
continue; continue;
} }
let mut algo = detect_algo(&algo_name, length)?; let mut algo = detect_algo(&algo_name, length)?;
@ -538,17 +536,12 @@ where
let (filename_to_check_unescaped, prefix) = unescape_filename(filename_to_check); let (filename_to_check_unescaped, prefix) = unescape_filename(filename_to_check);
// manage the input file // manage the input file
let file_to_check =
let file_to_check = match get_file_to_check( match get_file_to_check(&filename_to_check_unescaped, ignore_missing, &mut res)
filename_to_check, {
&filename_to_check_unescaped,
ignore_missing,
&mut res,
) {
Some(file) => file, Some(file) => file,
None => continue, None => continue,
}; };
let mut file_reader = BufReader::new(file_to_check); let mut file_reader = BufReader::new(file_to_check);
// Read the file and calculate the checksum // Read the file and calculate the checksum
let create_fn = &mut algo.create_fn; let create_fn = &mut algo.create_fn;
@ -561,7 +554,7 @@ where
if !quiet && !status { if !quiet && !status {
println!("{prefix}{filename_to_check}: OK"); println!("{prefix}{filename_to_check}: OK");
} }
res.correct_format += 1; correct_format += 1;
} else { } else {
if !status { if !status {
println!("{prefix}{filename_to_check}: FAILED"); println!("{prefix}{filename_to_check}: FAILED");
@ -594,7 +587,7 @@ where
// not a single line correctly formatted found // not a single line correctly formatted found
// return an error // return an error
if !res.properly_formatted { if !properly_formatted {
if !status { if !status {
return Err(ChecksumError::NoProperlyFormattedChecksumLinesFound { return Err(ChecksumError::NoProperlyFormattedChecksumLinesFound {
filename: get_filename_for_output(filename_input, input_is_stdin), filename: get_filename_for_output(filename_input, input_is_stdin),
@ -606,7 +599,7 @@ where
return Ok(()); return Ok(());
} }
if ignore_missing && res.correct_format == 0 { if ignore_missing && correct_format == 0 {
// we have only bad format // we have only bad format
// and we had ignore-missing // and we had ignore-missing
eprintln!( eprintln!(