Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 4 additions & 29 deletions src/uucore/src/lib/features/checksum/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ use std::fs::File;
use std::io::{self, BufReader, Read, Write};
use std::path::Path;

use crate::checksum::{AlgoKind, ChecksumError, SizedAlgoKind, digest_reader, escape_filename};
use crate::checksum::{
AlgoKind, ChecksumError, ReadingMode, SizedAlgoKind, digest_reader, escape_filename,
};
use crate::error::{FromIo, UResult, USimpleError};
use crate::line_ending::LineEnding;
use crate::sum::DigestOutput;
Expand All @@ -36,33 +38,6 @@ pub struct ChecksumComputeOptions {
pub line_ending: LineEnding,
}

/// Reading mode used to compute digest.
///
/// On most linux systems, this is irrelevant, as there is no distinction
/// between text and binary files. Refer to GNU's cksum documentation for more
/// information.
///
/// As discussed in #9168, we decide to ignore the reading mode to compute the
/// digest, both on Windows and UNIX. The reason for that is that this is a
/// legacy feature that is poorly documented and used. This enum is kept
/// nonetheless to still take into account the flags passed to cksum when
/// generating untagged lines.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReadingMode {
Binary,
Text,
}

impl ReadingMode {
#[inline]
fn as_char(self) -> char {
match self {
Self::Binary => '*',
Self::Text => ' ',
}
}
}

/// Whether to write the digest as hexadecimal or encoded in base64.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DigestFormat {
Expand Down Expand Up @@ -315,7 +290,7 @@ where

// Always compute the "binary" version of the digest, i.e. on Windows,
// never handle CRLFs specifically.
let (digest_output, sz) = digest_reader(&mut digest, &mut file, /* binary: */ true)
let (digest_output, sz) = digest_reader(&mut digest, &mut file, ReadingMode::Binary)
.map_err_context(|| translate!("checksum-error-failed-to-read-input"))?;

// Encodes the sum if df is Base64, leaves as-is otherwise.
Expand Down
31 changes: 29 additions & 2 deletions src/uucore/src/lib/features/checksum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,10 +417,37 @@ impl UError for ChecksumError {
}
}

/// Reading mode used to compute digest.
///
/// On most linux systems, this is irrelevant, as there is no distinction
/// between text and binary files. Refer to GNU's cksum documentation for more
/// information.
///
/// As discussed in #9168, we decide to ignore the reading mode to compute the
/// digest, both on Windows and UNIX. The reason for that is that this is a
/// legacy feature that is poorly documented and used. This enum is kept
/// nonetheless to still take into account the flags passed to cksum when
/// generating untagged lines.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReadingMode {
Binary,
Text,
}

impl ReadingMode {
#[inline]
fn as_char(self) -> char {
match self {
Self::Binary => '*',
Self::Text => ' ',
}
}
}

pub fn digest_reader<T: Read>(
digest: &mut Box<dyn Digest>,
reader: &mut T,
binary: bool,
mode: ReadingMode,
) -> io::Result<(DigestOutput, usize)> {
digest.reset();

Expand All @@ -436,7 +463,7 @@ pub fn digest_reader<T: Read>(
// `DigestWriter` and only written if the following character is
// "\n". But when "\r" is the last character read, we need to force
// it to be written.)
let mut digest_writer = DigestWriter::new(digest, binary);
let mut digest_writer = DigestWriter::new(digest, mode == ReadingMode::Binary);
let output_size = io::copy(reader, &mut digest_writer)? as usize;
digest_writer.finalize();

Expand Down
44 changes: 23 additions & 21 deletions src/uucore/src/lib/features/checksum/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use std::io::{self, BufReader, Read, Write, stderr, stdin};

use os_display::Quotable;

use crate::checksum::{AlgoKind, ChecksumError, SizedAlgoKind, digest_reader, unescape_filename};
use crate::checksum::{
AlgoKind, ChecksumError, ReadingMode, SizedAlgoKind, digest_reader, unescape_filename,
};
use crate::error::{FromIo, UError, UIoError, UResult, USimpleError};
use crate::quoting_style::{QuotingStyle, locale_aware_escape_name};
use crate::sum::DigestOutput;
Expand Down Expand Up @@ -679,28 +681,28 @@ fn compute_and_check_digest_from_file(
// Read the file and calculate the checksum
let mut digest = algo.create_digest();

// TODO: improve function signature to use ReadingMode instead of binary bool
// Set binary to false because --binary is not supported with --check

let (calculated_checksum, _) = match digest_reader(&mut digest, &mut file_reader, false) {
Ok(result) => result,
Err(err) => {
show!(err.map_err_context(|| {
locale_aware_escape_name(&real_filename_to_check, QuotingStyle::SHELL_ESCAPE)
.to_string_lossy()
.to_string()
}));

write_file_report(
io::stdout(),
filename,
FileChecksumResult::CantOpen,
prefix,
opts.verbose,
);
return Err(LineCheckError::CantOpenFile);
}
};
let (calculated_checksum, _) =
match digest_reader(&mut digest, &mut file_reader, ReadingMode::Text) {
Ok(result) => result,
Err(err) => {
show!(err.map_err_context(|| {
locale_aware_escape_name(&real_filename_to_check, QuotingStyle::SHELL_ESCAPE)
.to_string_lossy()
.to_string()
}));

write_file_report(
io::stdout(),
filename,
FileChecksumResult::CantOpen,
prefix,
opts.verbose,
);
return Err(LineCheckError::CantOpenFile);
}
};

// Do the checksum validation
let checksum_correct = match calculated_checksum {
Expand Down
Loading