mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
commit
19a9380089
13 changed files with 90 additions and 2 deletions
|
@ -5,14 +5,17 @@
|
||||||
|
|
||||||
// spell-checker:ignore (ToDO) fname, algo
|
// spell-checker:ignore (ToDO) fname, algo
|
||||||
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
|
use clap::{crate_version, value_parser, Arg, ArgAction, Command};
|
||||||
|
use hex::decode;
|
||||||
use hex::encode;
|
use hex::encode;
|
||||||
|
use std::error::Error;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
use std::fmt::Display;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, stdin, BufReader, Read};
|
use std::io::{self, stdin, stdout, BufReader, Read, Write};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use uucore::{
|
use uucore::{
|
||||||
error::{FromIo, UResult},
|
error::{FromIo, UError, UResult},
|
||||||
format_usage, help_about, help_section, help_usage,
|
format_usage, help_about, help_section, help_usage,
|
||||||
sum::{
|
sum::{
|
||||||
div_ceil, Blake2b, Digest, DigestWriter, Md5, Sha1, Sha224, Sha256, Sha384, Sha512, Sm3,
|
div_ceil, Blake2b, Digest, DigestWriter, Md5, Sha1, Sha224, Sha256, Sha384, Sha512, Sm3,
|
||||||
|
@ -36,6 +39,31 @@ const ALGORITHM_OPTIONS_SHA512: &str = "sha512";
|
||||||
const ALGORITHM_OPTIONS_BLAKE2B: &str = "blake2b";
|
const ALGORITHM_OPTIONS_BLAKE2B: &str = "blake2b";
|
||||||
const ALGORITHM_OPTIONS_SM3: &str = "sm3";
|
const ALGORITHM_OPTIONS_SM3: &str = "sm3";
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum CkSumError {
|
||||||
|
RawMultipleFiles,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UError for CkSumError {
|
||||||
|
fn code(&self) -> i32 {
|
||||||
|
match self {
|
||||||
|
Self::RawMultipleFiles => 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for CkSumError {}
|
||||||
|
|
||||||
|
impl Display for CkSumError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::RawMultipleFiles => {
|
||||||
|
write!(f, "the --raw option is not supported with multiple files")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn detect_algo(
|
fn detect_algo(
|
||||||
program: &str,
|
program: &str,
|
||||||
length: Option<usize>,
|
length: Option<usize>,
|
||||||
|
@ -110,6 +138,7 @@ struct Options {
|
||||||
output_bits: usize,
|
output_bits: usize,
|
||||||
untagged: bool,
|
untagged: bool,
|
||||||
length: Option<usize>,
|
length: Option<usize>,
|
||||||
|
raw: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate checksum
|
/// Calculate checksum
|
||||||
|
@ -123,6 +152,11 @@ fn cksum<'a, I>(mut options: Options, files: I) -> UResult<()>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a OsStr>,
|
I: Iterator<Item = &'a OsStr>,
|
||||||
{
|
{
|
||||||
|
let files: Vec<_> = files.collect();
|
||||||
|
if options.raw && files.len() > 1 {
|
||||||
|
return Err(Box::new(CkSumError::RawMultipleFiles));
|
||||||
|
}
|
||||||
|
|
||||||
for filename in files {
|
for filename in files {
|
||||||
let filename = Path::new(filename);
|
let filename = Path::new(filename);
|
||||||
let stdin_buf;
|
let stdin_buf;
|
||||||
|
@ -141,6 +175,17 @@ where
|
||||||
let (sum, sz) = digest_read(&mut options.digest, &mut file, options.output_bits)
|
let (sum, sz) = digest_read(&mut options.digest, &mut file, options.output_bits)
|
||||||
.map_err_context(|| "failed to read input".to_string())?;
|
.map_err_context(|| "failed to read input".to_string())?;
|
||||||
|
|
||||||
|
if options.raw {
|
||||||
|
let bytes = match options.algo_name {
|
||||||
|
ALGORITHM_OPTIONS_CRC => sum.parse::<u32>().unwrap().to_be_bytes().to_vec(),
|
||||||
|
ALGORITHM_OPTIONS_SYSV | ALGORITHM_OPTIONS_BSD => {
|
||||||
|
sum.parse::<u16>().unwrap().to_be_bytes().to_vec()
|
||||||
|
}
|
||||||
|
_ => decode(sum).unwrap(),
|
||||||
|
};
|
||||||
|
stdout().write_all(&bytes)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
// The BSD checksum output is 5 digit integer
|
// The BSD checksum output is 5 digit integer
|
||||||
let bsd_width = 5;
|
let bsd_width = 5;
|
||||||
match (options.algo_name, not_file) {
|
match (options.algo_name, not_file) {
|
||||||
|
@ -238,6 +283,7 @@ mod options {
|
||||||
pub const FILE: &str = "file";
|
pub const FILE: &str = "file";
|
||||||
pub const UNTAGGED: &str = "untagged";
|
pub const UNTAGGED: &str = "untagged";
|
||||||
pub const LENGTH: &str = "length";
|
pub const LENGTH: &str = "length";
|
||||||
|
pub const RAW: &str = "raw";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
|
@ -298,6 +344,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
output_bits: bits,
|
output_bits: bits,
|
||||||
length,
|
length,
|
||||||
untagged: matches.get_flag(options::UNTAGGED),
|
untagged: matches.get_flag(options::UNTAGGED),
|
||||||
|
raw: matches.get_flag(options::RAW),
|
||||||
};
|
};
|
||||||
|
|
||||||
match matches.get_many::<String>(options::FILE) {
|
match matches.get_many::<String>(options::FILE) {
|
||||||
|
@ -354,5 +401,11 @@ pub fn uu_app() -> Command {
|
||||||
.help("digest length in bits; must not exceed the max for the blake2 algorithm and must be a multiple of 8")
|
.help("digest length in bits; must not exceed the max for the blake2 algorithm and must be a multiple of 8")
|
||||||
.action(ArgAction::Set),
|
.action(ArgAction::Set),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::RAW)
|
||||||
|
.long(options::RAW)
|
||||||
|
.help("emit a raw binary digest, not hexadecimal")
|
||||||
|
.action(ArgAction::SetTrue),
|
||||||
|
)
|
||||||
.after_help(AFTER_HELP)
|
.after_help(AFTER_HELP)
|
||||||
}
|
}
|
||||||
|
|
|
@ -287,6 +287,30 @@ fn test_length_is_zero() {
|
||||||
.stdout_is_fixture("length_is_zero.expected");
|
.stdout_is_fixture("length_is_zero.expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_raw_single_file() {
|
||||||
|
for algo in ALGOS {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--raw")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.arg(format!("--algorithm={algo}"))
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr()
|
||||||
|
.stdout_is_fixture_bytes(format!("raw/{algo}_single_file.expected"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_raw_multiple_files() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--raw")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.arg("alice_in_wonderland.txt")
|
||||||
|
.fails()
|
||||||
|
.no_stdout()
|
||||||
|
.stderr_contains("cksum: the --raw option is not supported with multiple files")
|
||||||
|
.code_is(1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_blake2b_fail_on_directory() {
|
fn test_blake2b_fail_on_directory() {
|
||||||
let (at, mut ucmd) = at_and_ucmd!();
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
|
1
tests/fixtures/cksum/raw/blake2b_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/blake2b_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
— ‘‰å`Ãxœÿf†øWÑûþEtÞBãÀl«¹W^Jö0šaX´ÓÀ8Á´<C381>‚‹5<15>BÍÀ9m•Ã
|
1
tests/fixtures/cksum/raw/bsd_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/bsd_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<1F>
|
1
tests/fixtures/cksum/raw/crc_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/crc_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
訓h
|
BIN
tests/fixtures/cksum/raw/md5_single_file.expected
vendored
Normal file
BIN
tests/fixtures/cksum/raw/md5_single_file.expected
vendored
Normal file
Binary file not shown.
1
tests/fixtures/cksum/raw/sha1_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/sha1_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>к<>؈:=<18>m毽(%,<2C><>
|
BIN
tests/fixtures/cksum/raw/sha224_single_file.expected
vendored
Normal file
BIN
tests/fixtures/cksum/raw/sha224_single_file.expected
vendored
Normal file
Binary file not shown.
1
tests/fixtures/cksum/raw/sha256_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/sha256_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
÷Ä PPà0’P
gê^‘ <09>SkE‚þœC[Ù+?
|
3
tests/fixtures/cksum/raw/sha384_single_file.expected
vendored
Normal file
3
tests/fixtures/cksum/raw/sha384_single_file.expected
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
K荵
|
||||||
|
2吠鋳<19>シ<EFBFBD>マクアト/g胤コ囹LZ{WZ3Sゥ
|
||||||
|
守Hヒ
|
1
tests/fixtures/cksum/raw/sha512_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/sha512_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
–Td«%VªÕ޼sØšÒ!åYyu)ì¯ÀôfÁ•ÏöÖâÆ– |T,ýBn^Oऊ¡VgºD k!=Í<03>ú
|
1
tests/fixtures/cksum/raw/sm3_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/sm3_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
m)k€]þÒ(ß0<C39F>»›CyMÔíg@¡p§‚i›Â
|
1
tests/fixtures/cksum/raw/sysv_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/raw/sysv_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
I
|
Loading…
Add table
Add a link
Reference in a new issue