mirror of
https://github.com/uutils/coreutils
synced 2024-11-15 17:28:03 +00:00
cksum: implement and test --base64 output method
This commit is contained in:
parent
7b219aee63
commit
133cdde885
15 changed files with 100 additions and 15 deletions
|
@ -15,6 +15,7 @@ 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::{
|
||||||
|
encoding,
|
||||||
error::{FromIo, UError, UResult, USimpleError},
|
error::{FromIo, UError, UResult, USimpleError},
|
||||||
format_usage, help_about, help_section, help_usage, show,
|
format_usage, help_about, help_section, help_usage, show,
|
||||||
sum::{
|
sum::{
|
||||||
|
@ -44,6 +45,13 @@ enum CkSumError {
|
||||||
RawMultipleFiles,
|
RawMultipleFiles,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum OutputFormat {
|
||||||
|
Hexadecimal,
|
||||||
|
Raw,
|
||||||
|
Base64,
|
||||||
|
}
|
||||||
|
|
||||||
impl UError for CkSumError {
|
impl UError for CkSumError {
|
||||||
fn code(&self) -> i32 {
|
fn code(&self) -> i32 {
|
||||||
match self {
|
match self {
|
||||||
|
@ -138,7 +146,7 @@ struct Options {
|
||||||
output_bits: usize,
|
output_bits: usize,
|
||||||
untagged: bool,
|
untagged: bool,
|
||||||
length: Option<usize>,
|
length: Option<usize>,
|
||||||
raw: bool,
|
output_format: OutputFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate checksum
|
/// Calculate checksum
|
||||||
|
@ -153,7 +161,7 @@ where
|
||||||
I: Iterator<Item = &'a OsStr>,
|
I: Iterator<Item = &'a OsStr>,
|
||||||
{
|
{
|
||||||
let files: Vec<_> = files.collect();
|
let files: Vec<_> = files.collect();
|
||||||
if options.raw && files.len() > 1 {
|
if options.output_format == OutputFormat::Raw && files.len() > 1 {
|
||||||
return Err(Box::new(CkSumError::RawMultipleFiles));
|
return Err(Box::new(CkSumError::RawMultipleFiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +185,7 @@ where
|
||||||
};
|
};
|
||||||
Box::new(file_buf) as Box<dyn Read>
|
Box::new(file_buf) as Box<dyn Read>
|
||||||
});
|
});
|
||||||
let (sum, sz) = digest_read(&mut options.digest, &mut file, options.output_bits)
|
let (sum_hex, 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 filename.is_dir() {
|
if filename.is_dir() {
|
||||||
show!(USimpleError::new(
|
show!(USimpleError::new(
|
||||||
|
@ -186,17 +194,25 @@ where
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if options.raw {
|
let sum = match options.output_format {
|
||||||
let bytes = match options.algo_name {
|
OutputFormat::Raw => {
|
||||||
ALGORITHM_OPTIONS_CRC => sum.parse::<u32>().unwrap().to_be_bytes().to_vec(),
|
let bytes = match options.algo_name {
|
||||||
ALGORITHM_OPTIONS_SYSV | ALGORITHM_OPTIONS_BSD => {
|
ALGORITHM_OPTIONS_CRC => sum_hex.parse::<u32>().unwrap().to_be_bytes().to_vec(),
|
||||||
sum.parse::<u16>().unwrap().to_be_bytes().to_vec()
|
ALGORITHM_OPTIONS_SYSV | ALGORITHM_OPTIONS_BSD => {
|
||||||
}
|
sum_hex.parse::<u16>().unwrap().to_be_bytes().to_vec()
|
||||||
_ => decode(sum).unwrap(),
|
}
|
||||||
};
|
_ => decode(sum_hex).unwrap(),
|
||||||
stdout().write_all(&bytes)?;
|
};
|
||||||
return Ok(());
|
// Cannot handle multiple files anyway, output immediately.
|
||||||
}
|
stdout().write_all(&bytes)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
OutputFormat::Hexadecimal => sum_hex,
|
||||||
|
OutputFormat::Base64 => match options.algo_name {
|
||||||
|
ALGORITHM_OPTIONS_CRC | ALGORITHM_OPTIONS_SYSV | ALGORITHM_OPTIONS_BSD => sum_hex,
|
||||||
|
_ => encoding::encode(encoding::Format::Base64, &decode(sum_hex).unwrap()).unwrap(),
|
||||||
|
},
|
||||||
|
};
|
||||||
// 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) {
|
||||||
|
@ -289,6 +305,7 @@ mod options {
|
||||||
pub const TAG: &str = "tag";
|
pub const TAG: &str = "tag";
|
||||||
pub const LENGTH: &str = "length";
|
pub const LENGTH: &str = "length";
|
||||||
pub const RAW: &str = "raw";
|
pub const RAW: &str = "raw";
|
||||||
|
pub const BASE64: &str = "base64";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[uucore::main]
|
#[uucore::main]
|
||||||
|
@ -343,13 +360,21 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
|
||||||
let (name, algo, bits) = detect_algo(algo_name, length);
|
let (name, algo, bits) = detect_algo(algo_name, length);
|
||||||
|
|
||||||
|
let output_format = if matches.get_flag(options::RAW) {
|
||||||
|
OutputFormat::Raw
|
||||||
|
} else if matches.get_flag(options::BASE64) {
|
||||||
|
OutputFormat::Base64
|
||||||
|
} else {
|
||||||
|
OutputFormat::Hexadecimal
|
||||||
|
};
|
||||||
|
|
||||||
let opts = Options {
|
let opts = Options {
|
||||||
algo_name: name,
|
algo_name: name,
|
||||||
digest: algo,
|
digest: algo,
|
||||||
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),
|
output_format,
|
||||||
};
|
};
|
||||||
|
|
||||||
match matches.get_many::<String>(options::FILE) {
|
match matches.get_many::<String>(options::FILE) {
|
||||||
|
@ -420,5 +445,14 @@ pub fn uu_app() -> Command {
|
||||||
.help("emit a raw binary digest, not hexadecimal")
|
.help("emit a raw binary digest, not hexadecimal")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::BASE64)
|
||||||
|
.long(options::BASE64)
|
||||||
|
.help("emit a base64 digest, not hexadecimal")
|
||||||
|
.action(ArgAction::SetTrue)
|
||||||
|
// Even though this could easily just override an earlier '--raw',
|
||||||
|
// GNU cksum does not permit these flags to be combined:
|
||||||
|
.conflicts_with(options::RAW),
|
||||||
|
)
|
||||||
.after_help(AFTER_HELP)
|
.after_help(AFTER_HELP)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub enum DecodeError {
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum EncodeError {
|
pub enum EncodeError {
|
||||||
Z85InputLenNotMultipleOf4,
|
Z85InputLenNotMultipleOf4,
|
||||||
InvalidInput,
|
InvalidInput,
|
||||||
|
|
|
@ -363,6 +363,43 @@ fn test_raw_multiple_files() {
|
||||||
.code_is(1);
|
.code_is(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_base64_raw_conflicts() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--base64")
|
||||||
|
.arg("--raw")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.fails()
|
||||||
|
.no_stdout()
|
||||||
|
.stderr_contains("--base64")
|
||||||
|
.stderr_contains("cannot be used with")
|
||||||
|
.stderr_contains("--raw");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_base64_single_file() {
|
||||||
|
for algo in ALGOS {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--base64")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.arg(format!("--algorithm={algo}"))
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr()
|
||||||
|
.stdout_is_fixture_bytes(format!("base64/{algo}_single_file.expected"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_base64_multiple_files() {
|
||||||
|
new_ucmd!()
|
||||||
|
.arg("--base64")
|
||||||
|
.arg("--algorithm=md5")
|
||||||
|
.arg("lorem_ipsum.txt")
|
||||||
|
.arg("alice_in_wonderland.txt")
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr()
|
||||||
|
.stdout_is_fixture_bytes(format!("base64/md5_multiple_files.expected"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fail_on_folder() {
|
fn test_fail_on_folder() {
|
||||||
let (at, mut ucmd) = at_and_ucmd!();
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
|
1
tests/fixtures/cksum/base64/blake2b_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/blake2b_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
BLAKE2b (lorem_ipsum.txt) = DpegkYnlYMN4nAv/HwIBZoYe+FfR+/5FdN4YQuPAbKu5V15K9jCaFmFYwrQI08A4wbSdgos1FYFCzcA5bRGVww==
|
1
tests/fixtures/cksum/base64/bsd_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/bsd_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
08109 1 lorem_ipsum.txt
|
1
tests/fixtures/cksum/base64/crc_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/crc_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
378294376 772 lorem_ipsum.txt
|
2
tests/fixtures/cksum/base64/md5_multiple_files.expected
vendored
Normal file
2
tests/fixtures/cksum/base64/md5_multiple_files.expected
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
MD5 (lorem_ipsum.txt) = zXJGkPfcYXdd+sQApx8sqg==
|
||||||
|
MD5 (alice_in_wonderland.txt) = 9vpwM+FhZqlYmqHAOI/9WA==
|
1
tests/fixtures/cksum/base64/md5_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/md5_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
MD5 (lorem_ipsum.txt) = zXJGkPfcYXdd+sQApx8sqg==
|
1
tests/fixtures/cksum/base64/sha1_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/sha1_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SHA1 (lorem_ipsum.txt) = qx3QuuHYiDo9GKZt5q+9KCUs++8=
|
1
tests/fixtures/cksum/base64/sha224_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/sha224_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SHA224 (lorem_ipsum.txt) = PeZvvK0QbhtAqzkb5WxR0gB+sfnGVdD04pv8AQ==
|
1
tests/fixtures/cksum/base64/sha256_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/sha256_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SHA256 (lorem_ipsum.txt) = 98QgUBxQ4AswklAQDWfqXpEJgVNrRYL+nENb2Ss/HwI=
|
1
tests/fixtures/cksum/base64/sha384_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/sha384_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SHA384 (lorem_ipsum.txt) = S+S5Cg0NMpZpkpIQGfJKvIJNz7ixxAgQLx9niPuAupqaTFp7V1ozU6kKjucZSB3L
|
1
tests/fixtures/cksum/base64/sha512_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/sha512_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SHA512 (lorem_ipsum.txt) = llRkqyVWqtWOvHPYmtIh5Vl5dSnsr8D0ZsEXlc/21uLGD5agfFQs/R9Cbl5P4KSKoVZnukQJayE9CBPNA436BQ==
|
1
tests/fixtures/cksum/base64/sm3_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/sm3_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SM3 (lorem_ipsum.txt) = bSlrgF0GC/7SKAjfMI27m0MXeU3U7WdAoQdwp4Jpm8I=
|
1
tests/fixtures/cksum/base64/sysv_single_file.expected
vendored
Normal file
1
tests/fixtures/cksum/base64/sysv_single_file.expected
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
6985 2 lorem_ipsum.txt
|
Loading…
Reference in a new issue