From 266c70eb6eb5762e0f639555a4b3118f4dd098b4 Mon Sep 17 00:00:00 2001 From: Yang Hau Date: Sun, 12 Feb 2023 21:13:04 +0800 Subject: [PATCH] cksum: Add untagged option Closes #3811 --- src/uu/cksum/src/cksum.rs | 54 +++++++++++++++---- src/uucore/src/lib/features/sum.rs | 25 ++++++++- tests/by-util/test_cksum.rs | 9 ++++ .../cksum/single_file_untagged.expected | 1 + 4 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 tests/fixtures/cksum/single_file_untagged.expected diff --git a/src/uu/cksum/src/cksum.rs b/src/uu/cksum/src/cksum.rs index e66d5f0293e..88cd31d2de7 100644 --- a/src/uu/cksum/src/cksum.rs +++ b/src/uu/cksum/src/cksum.rs @@ -102,6 +102,7 @@ struct Options { algo_name: &'static str, digest: Box, output_bits: usize, + reverse: bool, } /// Calculate checksum @@ -130,36 +131,49 @@ where File::open(filename).map_err_context(|| filename.to_str().unwrap().to_string())?; Box::new(file_buf) as Box }); - let (sum, sz) = digest_read(&mut options.digest, &mut file, options.output_bits) + let (mut sum, sz) = digest_read(&mut options.digest, &mut file, options.output_bits) .map_err_context(|| "failed to read input".to_string())?; + if options.reverse { + sum = reverse_cksum(&sum); + } // The BSD checksum output is 5 digit integer let bsd_width = 5; match (options.algo_name, not_file) { (ALGORITHM_OPTIONS_SYSV, true) => println!( "{} {}", - sum.parse::().unwrap(), + u16::from_ne_bytes(sum.try_into().unwrap()), div_ceil(sz, options.output_bits) ), (ALGORITHM_OPTIONS_SYSV, false) => println!( "{} {} {}", - sum.parse::().unwrap(), + u16::from_ne_bytes(sum.try_into().unwrap()), div_ceil(sz, options.output_bits), filename.display() ), (ALGORITHM_OPTIONS_BSD, true) => println!( "{:0bsd_width$} {:bsd_width$}", - sum.parse::().unwrap(), + u16::from_ne_bytes(sum.try_into().unwrap()), div_ceil(sz, options.output_bits) ), (ALGORITHM_OPTIONS_BSD, false) => println!( "{:0bsd_width$} {:bsd_width$} {}", - sum.parse::().unwrap(), + u16::from_ne_bytes(sum.try_into().unwrap()), div_ceil(sz, options.output_bits), filename.display() ), - (_, true) => println!("{sum} {sz}"), - (_, false) => println!("{sum} {sz} {}", filename.display()), + (ALGORITHM_OPTIONS_CRC, true) => { + println!("{} {sz}", u32::from_ne_bytes(sum.try_into().unwrap())); + } + (ALGORITHM_OPTIONS_CRC, false) => { + println!( + "{} {sz} {}", + u32::from_ne_bytes(sum.try_into().unwrap()), + filename.display() + ); + } + (_, true) => println!("{} {sz}", encode(sum)), + (_, false) => println!("{} {sz} {}", encode(sum), filename.display()), } } @@ -170,7 +184,7 @@ fn digest_read( digest: &mut Box, reader: &mut BufReader, output_bits: usize, -) -> io::Result<(String, usize)> { +) -> io::Result<(Vec, usize)> { digest.reset(); // Read bytes from `reader` and write those bytes to `digest`. @@ -188,21 +202,30 @@ fn digest_read( let mut digest_writer = DigestWriter::new(digest, true); let output_size = std::io::copy(reader, &mut digest_writer)? as usize; digest_writer.finalize(); - if digest.output_bits() > 0 { - Ok((digest.result_str(), output_size)) + Ok((digest.result_bytes(), output_size)) } else { // Assume it's SHAKE. result_str() doesn't work with shake (as of 8/30/2016) let mut bytes = Vec::new(); bytes.resize((output_bits + 7) / 8, 0); digest.hash_finalize(&mut bytes); - Ok((encode(bytes), output_size)) + Ok((bytes, output_size)) + } +} + +fn reverse_cksum(checksum: &[u8]) -> Vec { + let sz = checksum.len(); + let mut ret: Vec = std::iter::repeat(0).take(sz).collect::>(); + for i in 0..sz { + ret[i] = checksum[sz - i - 1].reverse_bits(); } + ret } mod options { pub static FILE: &str = "file"; pub static ALGORITHM: &str = "algorithm"; + pub static UNTAGGED: &str = "untagged"; } const ALGORITHM_HELP_DESC: &str = @@ -231,11 +254,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { None => ALGORITHM_OPTIONS_CRC, }; + let untagged: bool = matches.get_flag(options::UNTAGGED); + let (name, algo, bits) = detect_algo(algo_name); let opts = Options { algo_name: name, digest: algo, output_bits: bits, + reverse: untagged, }; match matches.get_many::(options::FILE) { @@ -278,5 +304,11 @@ pub fn uu_app() -> Command { ALGORITHM_OPTIONS_SM3, ]), ) + .arg( + Arg::new(options::UNTAGGED) + .long(options::UNTAGGED) + .help("create a reversed style checksum, without digest type") + .action(clap::ArgAction::SetTrue), + ) .after_help(ALGORITHM_HELP_DESC) } diff --git a/src/uucore/src/lib/features/sum.rs b/src/uucore/src/lib/features/sum.rs index 3394146308c..c0c8053ab58 100644 --- a/src/uucore/src/lib/features/sum.rs +++ b/src/uucore/src/lib/features/sum.rs @@ -36,6 +36,11 @@ pub trait Digest { self.hash_finalize(&mut buf); encode(buf) } + fn result_bytes(&mut self) -> Vec { + let mut buf: Vec = vec![0; self.output_bytes()]; + self.hash_finalize(&mut buf); + buf + } } pub struct Blake2b(blake2b_simd::State); @@ -185,12 +190,18 @@ impl Digest for CRC { format!("{}", self.state) } + fn result_bytes(&mut self) -> Vec { + let mut out: Vec = vec![0; 4]; + self.hash_finalize(&mut out); + out.to_vec() + } + fn reset(&mut self) { *self = Self::new(); } fn output_bits(&self) -> usize { - 256 + 32 } } @@ -226,6 +237,12 @@ impl Digest for BSD { format!("{}", self.state) } + fn result_bytes(&mut self) -> Vec { + let mut out: Vec = vec![0; 2]; + self.hash_finalize(&mut out); + out.to_vec() + } + fn reset(&mut self) { *self = Self::new(); } @@ -261,6 +278,12 @@ impl Digest for SYSV { format!("{}", self.state) } + fn result_bytes(&mut self) -> Vec { + let mut out: Vec = vec![0; 2]; + self.hash_finalize(&mut out); + out.to_vec() + } + fn reset(&mut self) { *self = Self::new(); } diff --git a/tests/by-util/test_cksum.rs b/tests/by-util/test_cksum.rs index 361a9c47201..0019d24e43a 100644 --- a/tests/by-util/test_cksum.rs +++ b/tests/by-util/test_cksum.rs @@ -15,6 +15,15 @@ fn test_single_file() { .stdout_is_fixture("single_file.expected"); } +#[test] +fn test_single_file_untagged() { + new_ucmd!() + .arg("--untagged") + .arg("lorem_ipsum.txt") + .succeeds() + .stdout_is_fixture("single_file_untagged.expected"); +} + #[test] fn test_multiple_files() { new_ucmd!() diff --git a/tests/fixtures/cksum/single_file_untagged.expected b/tests/fixtures/cksum/single_file_untagged.expected new file mode 100644 index 00000000000..e965284ac71 --- /dev/null +++ b/tests/fixtures/cksum/single_file_untagged.expected @@ -0,0 +1 @@ +369766760 772 lorem_ipsum.txt