mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
Addresses code-quality issues from testsdiepraam and miDeb.
- Removes dd from feat_require_unix (keeps it in feat_common_core) - Changes name of make_linux_iflags parameter from oflags to iflags. - Removes roughed out SIGINFO impl. - Renames plen -> target_len. - Removes internal fn def for build_blocks and replaces with a call to chunks from std. - Renames apply_ct to the more descriptive apply_conversion - Replaces manual swap steps in perform_swab with call to swap from std. - Replaces manual solution with chunks where appropriate (in Read, and Write impl). - Renames xfer -> transfer (in local variable names). - Improves documentation for dd_filout/dd_stdout issue. - Removes commented debug_assert statements. - Modifies ProdUpdate to contain ReadStat and WriteStat rather than copying their fields. - Addresses verbose return in `Output<File>::new(...)` - Resoves compiler warning when built as release when signal handler fails to register. - Derives _Default_ trait on ReadStat. - Adds comments for truncated lines in block unblock tests - Removes `as u8` in block unblock tests. - Removes unecessary `#[inline]` - Delegates multiplier string parsing to uucore::parse_size. - Renames 'unfailed' -> 'succeeded' for clairity. - Removes #dead_code warnings. No clippy warnings on my local machine. - Reworks signal handler to better accomodate platform-specific signals. - Removes explicit references to "if" and "of" in dd.rs. - Removes explicit references to "bs", "ibs", "cbs" and "status" in parseargs.rs. - Removes `#[allow(deadcode)]` for OFlags, and IFlags. - Removes spellchecker ignore from all dd files. - Adds tests for 'traditional' and 'modern' CLI.
This commit is contained in:
@@ -153,7 +153,6 @@ feat_require_unix = [
|
||||
"chmod",
|
||||
"chown",
|
||||
"chroot",
|
||||
"dd",
|
||||
"groups",
|
||||
"hostid",
|
||||
"id",
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
/* cspell:disable */
|
||||
|
||||
// Note: Conversion tables are just lookup tables.
|
||||
// eg. The ASCII->EBCDIC table stores the EBCDIC code at the index
|
||||
// obtained by treating the ASCII representation as a number.
|
||||
|
||||
@@ -5,23 +5,18 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
/* cspell:disable */
|
||||
|
||||
use crate::conversion_tables::*;
|
||||
|
||||
use std::error::Error;
|
||||
use std::time;
|
||||
|
||||
pub struct ProgUpdate {
|
||||
pub reads_complete: u64,
|
||||
pub reads_partial: u64,
|
||||
pub writes_complete: u64,
|
||||
pub writes_partial: u64,
|
||||
pub bytes_total: u128,
|
||||
pub records_truncated: u32,
|
||||
pub read_stat: ReadStat,
|
||||
pub write_stat: WriteStat,
|
||||
pub duration: time::Duration,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct ReadStat {
|
||||
pub reads_complete: u64,
|
||||
pub reads_partial: u64,
|
||||
@@ -37,6 +32,7 @@ impl std::ops::AddAssign for ReadStat {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct WriteStat {
|
||||
pub writes_complete: u64,
|
||||
pub writes_partial: u64,
|
||||
@@ -55,6 +51,7 @@ impl std::ops::AddAssign for WriteStat {
|
||||
type Cbs = usize;
|
||||
|
||||
/// Stores all Conv Flags that apply to the input
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct IConvFlags {
|
||||
pub ctable: Option<&'static ConversionTable>,
|
||||
pub block: Option<Cbs>,
|
||||
@@ -65,7 +62,7 @@ pub struct IConvFlags {
|
||||
}
|
||||
|
||||
/// Stores all Conv Flags that apply to the output
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct OConvFlags {
|
||||
pub sparse: bool,
|
||||
pub excl: bool,
|
||||
@@ -76,32 +73,20 @@ pub struct OConvFlags {
|
||||
}
|
||||
|
||||
/// Stores all Flags that apply to the input
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct IFlags {
|
||||
#[allow(dead_code)]
|
||||
pub cio: bool,
|
||||
#[allow(dead_code)]
|
||||
pub direct: bool,
|
||||
#[allow(dead_code)]
|
||||
pub directory: bool,
|
||||
#[allow(dead_code)]
|
||||
pub dsync: bool,
|
||||
#[allow(dead_code)]
|
||||
pub sync: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nocache: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nonblock: bool,
|
||||
#[allow(dead_code)]
|
||||
pub noatime: bool,
|
||||
#[allow(dead_code)]
|
||||
pub noctty: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nofollow: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nolinks: bool,
|
||||
#[allow(dead_code)]
|
||||
pub binary: bool,
|
||||
#[allow(dead_code)]
|
||||
pub text: bool,
|
||||
pub fullblock: bool,
|
||||
pub count_bytes: bool,
|
||||
@@ -109,33 +94,21 @@ pub struct IFlags {
|
||||
}
|
||||
|
||||
/// Stores all Flags that apply to the output
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
pub struct OFlags {
|
||||
pub append: bool,
|
||||
#[allow(dead_code)]
|
||||
pub cio: bool,
|
||||
#[allow(dead_code)]
|
||||
pub direct: bool,
|
||||
#[allow(dead_code)]
|
||||
pub directory: bool,
|
||||
#[allow(dead_code)]
|
||||
pub dsync: bool,
|
||||
#[allow(dead_code)]
|
||||
pub sync: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nocache: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nonblock: bool,
|
||||
#[allow(dead_code)]
|
||||
pub noatime: bool,
|
||||
#[allow(dead_code)]
|
||||
pub noctty: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nofollow: bool,
|
||||
#[allow(dead_code)]
|
||||
pub nolinks: bool,
|
||||
#[allow(dead_code)]
|
||||
pub binary: bool,
|
||||
#[allow(dead_code)]
|
||||
pub text: bool,
|
||||
pub seek_bytes: bool,
|
||||
}
|
||||
@@ -153,6 +126,7 @@ pub enum StatusLevel {
|
||||
/// Defaults to Reads(N)
|
||||
/// if iflag=count_bytes
|
||||
/// then becomes Bytes(N)
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum CountType {
|
||||
Reads(usize),
|
||||
Bytes(usize),
|
||||
|
||||
+123
-228
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,7 @@
|
||||
/* cspell:disable */
|
||||
|
||||
use super::*;
|
||||
|
||||
const NL: u8 = '\n' as u8;
|
||||
const SPACE: u8 = ' ' as u8;
|
||||
|
||||
macro_rules! rs (
|
||||
() =>
|
||||
{
|
||||
ReadStat {
|
||||
reads_complete: 0,
|
||||
reads_partial: 0,
|
||||
records_truncated: 0,
|
||||
}
|
||||
};
|
||||
);
|
||||
const NL: u8 = b'\n';
|
||||
const SPACE: u8 = b' ';
|
||||
|
||||
macro_rules! make_block_test (
|
||||
( $test_id:ident, $test_name:expr, $src:expr, $block:expr, $spec:expr ) =>
|
||||
@@ -25,7 +12,7 @@ macro_rules! make_block_test (
|
||||
src: $src,
|
||||
non_ascii: false,
|
||||
ibs: 512,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: IConvFlags {
|
||||
ctable: None,
|
||||
@@ -57,7 +44,7 @@ macro_rules! make_unblock_test (
|
||||
src: $src,
|
||||
non_ascii: false,
|
||||
ibs: 512,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: IConvFlags {
|
||||
ctable: None,
|
||||
@@ -82,7 +69,7 @@ macro_rules! make_unblock_test (
|
||||
|
||||
#[test]
|
||||
fn block_test_no_nl() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8];
|
||||
let res = block(buf, 4, &mut rs);
|
||||
|
||||
@@ -91,7 +78,7 @@ fn block_test_no_nl() {
|
||||
|
||||
#[test]
|
||||
fn block_test_no_nl_short_record() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8];
|
||||
let res = block(buf, 8, &mut rs);
|
||||
|
||||
@@ -103,17 +90,18 @@ fn block_test_no_nl_short_record() {
|
||||
|
||||
#[test]
|
||||
fn block_test_no_nl_trunc() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8, 4u8];
|
||||
let res = block(buf, 4, &mut rs);
|
||||
|
||||
// Commented section should be truncated and appear for reference only.
|
||||
assert_eq!(res, vec![vec![0u8, 1u8, 2u8, 3u8 /*, 4u8*/],]);
|
||||
assert_eq!(rs.records_truncated, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_test_nl_gt_cbs_trunc() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![
|
||||
0u8, 1u8, 2u8, 3u8, 4u8, NL, 0u8, 1u8, 2u8, 3u8, 4u8, NL, 5u8, 6u8, 7u8, 8u8,
|
||||
];
|
||||
@@ -122,6 +110,7 @@ fn block_test_nl_gt_cbs_trunc() {
|
||||
assert_eq!(
|
||||
res,
|
||||
vec![
|
||||
// Commented lines should be truncated and appear for reference only.
|
||||
vec![0u8, 1u8, 2u8, 3u8],
|
||||
// vec![4u8, SPACE, SPACE, SPACE],
|
||||
vec![0u8, 1u8, 2u8, 3u8],
|
||||
@@ -134,7 +123,7 @@ fn block_test_nl_gt_cbs_trunc() {
|
||||
|
||||
#[test]
|
||||
fn block_test_surrounded_nl() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, 4u8, 5u8, 6u8, 7u8, 8u8];
|
||||
let res = block(buf, 8, &mut rs);
|
||||
|
||||
@@ -149,7 +138,7 @@ fn block_test_surrounded_nl() {
|
||||
|
||||
#[test]
|
||||
fn block_test_multiple_nl_same_cbs_block() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, 4u8, NL, 5u8, 6u8, 7u8, 8u8, 9u8];
|
||||
let res = block(buf, 8, &mut rs);
|
||||
|
||||
@@ -165,7 +154,7 @@ fn block_test_multiple_nl_same_cbs_block() {
|
||||
|
||||
#[test]
|
||||
fn block_test_multiple_nl_diff_cbs_block() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, 4u8, 5u8, 6u8, 7u8, NL, 8u8, 9u8];
|
||||
let res = block(buf, 8, &mut rs);
|
||||
|
||||
@@ -181,7 +170,7 @@ fn block_test_multiple_nl_diff_cbs_block() {
|
||||
|
||||
#[test]
|
||||
fn block_test_end_nl_diff_cbs_block() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8, NL];
|
||||
let res = block(buf, 4, &mut rs);
|
||||
|
||||
@@ -190,7 +179,7 @@ fn block_test_end_nl_diff_cbs_block() {
|
||||
|
||||
#[test]
|
||||
fn block_test_end_nl_same_cbs_block() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, NL];
|
||||
let res = block(buf, 4, &mut rs);
|
||||
|
||||
@@ -199,7 +188,7 @@ fn block_test_end_nl_same_cbs_block() {
|
||||
|
||||
#[test]
|
||||
fn block_test_double_end_nl() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, NL, NL];
|
||||
let res = block(buf, 4, &mut rs);
|
||||
|
||||
@@ -211,7 +200,7 @@ fn block_test_double_end_nl() {
|
||||
|
||||
#[test]
|
||||
fn block_test_start_nl() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![NL, 0u8, 1u8, 2u8, 3u8];
|
||||
let res = block(buf, 4, &mut rs);
|
||||
|
||||
@@ -223,7 +212,7 @@ fn block_test_start_nl() {
|
||||
|
||||
#[test]
|
||||
fn block_test_double_surrounded_nl_no_trunc() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, NL, 4u8, 5u8, 6u8, 7u8];
|
||||
let res = block(buf, 8, &mut rs);
|
||||
|
||||
@@ -239,13 +228,14 @@ fn block_test_double_surrounded_nl_no_trunc() {
|
||||
|
||||
#[test]
|
||||
fn block_test_double_surrounded_nl_double_trunc() {
|
||||
let mut rs = rs!();
|
||||
let mut rs = ReadStat::default();
|
||||
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, NL, 4u8, 5u8, 6u8, 7u8, 8u8];
|
||||
let res = block(buf, 4, &mut rs);
|
||||
|
||||
assert_eq!(
|
||||
res,
|
||||
vec![
|
||||
// Commented section should be truncated and appear for reference only.
|
||||
vec![0u8, 1u8, 2u8, 3u8],
|
||||
vec![SPACE, SPACE, SPACE, SPACE],
|
||||
vec![4u8, 5u8, 6u8, 7u8 /*, 8u8*/],
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* cspell:disable */
|
||||
|
||||
use super::*;
|
||||
|
||||
macro_rules! make_sync_test (
|
||||
@@ -11,7 +9,7 @@ macro_rules! make_sync_test (
|
||||
src: $src,
|
||||
non_ascii: false,
|
||||
ibs: $ibs,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: IConvFlags {
|
||||
ctable: None,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* cspell:disable */
|
||||
|
||||
use super::*;
|
||||
|
||||
macro_rules! make_conv_test (
|
||||
@@ -11,7 +9,7 @@ macro_rules! make_conv_test (
|
||||
src: $src,
|
||||
non_ascii: false,
|
||||
ibs: 512,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: icf!($ctable),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -36,7 +34,7 @@ macro_rules! make_icf_test (
|
||||
src: $src,
|
||||
non_ascii: false,
|
||||
ibs: 512,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: $icf,
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -141,7 +139,7 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test() {
|
||||
.unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 128,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: icf!(Some(&ASCII_TO_EBCDIC)),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -163,7 +161,7 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test() {
|
||||
src: File::open(&tmp_fname_ae).unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 256,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: icf!(Some(&EBCDIC_TO_ASCII)),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* cspell:disable */
|
||||
|
||||
use super::*;
|
||||
|
||||
mod block_unblock_tests;
|
||||
@@ -39,24 +37,6 @@ const DEFAULT_IFLAGS: IFlags = IFlags {
|
||||
skip_bytes: false,
|
||||
};
|
||||
|
||||
// const DEFAULT_OFLAGS: OFlags = OFlags {
|
||||
// append: false,
|
||||
// cio: false,
|
||||
// direct: false,
|
||||
// directory: false,
|
||||
// dsync: false,
|
||||
// sync: false,
|
||||
// nocache: false,
|
||||
// nonblock: false,
|
||||
// noatime: false,
|
||||
// noctty: false,
|
||||
// nofollow: false,
|
||||
// nolinks: false,
|
||||
// binary: false,
|
||||
// text: false,
|
||||
// seek_bytes: false,
|
||||
// };
|
||||
|
||||
struct LazyReader<R: Read> {
|
||||
src: R,
|
||||
}
|
||||
@@ -102,7 +82,7 @@ macro_rules! make_spec_test (
|
||||
src: $src,
|
||||
non_ascii: false,
|
||||
ibs: 512,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* cspell:disable */
|
||||
|
||||
use super::*;
|
||||
|
||||
const DST_PLACEHOLDER: Vec<u8> = Vec::new();
|
||||
@@ -52,7 +50,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 521,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -72,7 +70,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 1031,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -92,7 +90,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 1024,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: Some(CountType::Reads(32)),
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -112,7 +110,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 531,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: Some(CountType::Bytes(32 * 1024)),
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -132,7 +130,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 1024,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: Some(CountType::Reads(16)),
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -152,7 +150,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 531,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: Some(CountType::Bytes(12345)),
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -172,7 +170,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 1024,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: Some(CountType::Reads(32)),
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -192,7 +190,7 @@ make_io_test!(
|
||||
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
|
||||
non_ascii: false,
|
||||
ibs: 521,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: Some(CountType::Bytes(32 * 1024)),
|
||||
cflags: icf!(),
|
||||
iflags: DEFAULT_IFLAGS,
|
||||
@@ -215,7 +213,7 @@ make_io_test!(
|
||||
},
|
||||
non_ascii: false,
|
||||
ibs: 521,
|
||||
xfer_stats: None,
|
||||
print_level: None,
|
||||
count: None,
|
||||
cflags: icf!(),
|
||||
iflags: IFlags {
|
||||
|
||||
+29
-56
@@ -5,8 +5,6 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
/* cspell:disable */
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests;
|
||||
|
||||
@@ -24,9 +22,8 @@ pub enum ParseError {
|
||||
MultipleExclNoCreat,
|
||||
FlagNoMatch(String),
|
||||
ConvFlagNoMatch(String),
|
||||
NoMatchingMultiplier(String),
|
||||
ByteStringContainsNoValue(String),
|
||||
MultiplierStringWouldOverflow(String),
|
||||
MultiplierStringParseFailure(String),
|
||||
MultiplierStringOverflow(String),
|
||||
BlockUnblockWithoutCBS,
|
||||
StatusLevelNotRecognized(String),
|
||||
Unimplemented(String),
|
||||
@@ -56,13 +53,10 @@ impl std::fmt::Display for ParseError {
|
||||
Self::ConvFlagNoMatch(arg) => {
|
||||
write!(f, "Unrecognized conv=CONV -> {}", arg)
|
||||
}
|
||||
Self::NoMatchingMultiplier(arg) => {
|
||||
Self::MultiplierStringParseFailure(arg) => {
|
||||
write!(f, "Unrecognized byte multiplier -> {}", arg)
|
||||
}
|
||||
Self::ByteStringContainsNoValue(arg) => {
|
||||
write!(f, "Unrecognized byte value -> {}", arg)
|
||||
}
|
||||
Self::MultiplierStringWouldOverflow(arg) => {
|
||||
Self::MultiplierStringOverflow(arg) => {
|
||||
write!(
|
||||
f,
|
||||
"Multiplier string would overflow on current system -> {}",
|
||||
@@ -302,61 +296,40 @@ impl std::str::FromStr for StatusLevel {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_multiplier(s: &'_ str) -> Result<usize, ParseError> {
|
||||
let mult: u128 = match s {
|
||||
"c" => 1,
|
||||
"w" => 2,
|
||||
"b" => 512,
|
||||
"kB" => 1000,
|
||||
"K" | "KiB" => 1024,
|
||||
"MB" => 1000 * 1000,
|
||||
"M" | "MiB" => 1024 * 1024,
|
||||
"GB" => 1000 * 1000 * 1000,
|
||||
"G" | "GiB" => 1024 * 1024 * 1024,
|
||||
"TB" => 1000 * 1000 * 1000 * 1000,
|
||||
"T" | "TiB" => 1024 * 1024 * 1024 * 1024,
|
||||
"PB" => 1000 * 1000 * 1000 * 1000 * 1000,
|
||||
"P" | "PiB" => 1024 * 1024 * 1024 * 1024 * 1024,
|
||||
"EB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
|
||||
"E" | "EiB" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
|
||||
"ZB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
|
||||
"Z" | "ZiB" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
|
||||
"YB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
|
||||
"Y" | "YiB" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
|
||||
_ => return Err(ParseError::NoMatchingMultiplier(s.to_string())),
|
||||
};
|
||||
|
||||
mult.try_into()
|
||||
.map_err(|_e| ParseError::MultiplierStringWouldOverflow(s.to_string()))
|
||||
}
|
||||
|
||||
/// Parse bytes using str::parse, then map error if needed.
|
||||
fn parse_bytes_only(s: &str) -> Result<usize, ParseError> {
|
||||
match s.parse() {
|
||||
Ok(bytes) => Ok(bytes),
|
||||
Err(_) => Err(ParseError::ByteStringContainsNoValue(s.to_string())),
|
||||
}
|
||||
s.parse()
|
||||
.map_err(|_| ParseError::MultiplierStringParseFailure(s.to_string()))
|
||||
}
|
||||
|
||||
/// Parse byte and multiplier like 512, 5KiB, or 1G.
|
||||
/// Uses uucore::parse_size, and adds the 'w' and 'c' suffixes which are mentioned
|
||||
/// in dd's info page.
|
||||
fn parse_bytes_with_opt_multiplier(s: &str) -> Result<usize, ParseError> {
|
||||
match s.find(char::is_alphabetic) {
|
||||
Some(idx) => {
|
||||
let base = parse_bytes_only(&s[..idx])?;
|
||||
let mult = parse_multiplier(&s[idx..])?;
|
||||
if let Some(idx) = s.rfind('c') {
|
||||
parse_bytes_only(&s[..idx])
|
||||
} else if let Some(idx) = s.rfind('w') {
|
||||
let partial = parse_bytes_only(&s[..idx])?;
|
||||
|
||||
if let Some(bytes) = base.checked_mul(mult) {
|
||||
Ok(bytes)
|
||||
} else {
|
||||
Err(ParseError::MultiplierStringWouldOverflow(s.to_string()))
|
||||
partial
|
||||
.checked_mul(2)
|
||||
.ok_or_else(|| ParseError::MultiplierStringOverflow(s.to_string()))
|
||||
} else {
|
||||
uucore::parse_size::parse_size(s).map_err(|e| match e {
|
||||
uucore::parse_size::ParseSizeError::ParseFailure(s) => {
|
||||
ParseError::MultiplierStringParseFailure(s)
|
||||
}
|
||||
}
|
||||
_ => parse_bytes_only(s),
|
||||
uucore::parse_size::ParseSizeError::SizeTooBig(s) => {
|
||||
ParseError::MultiplierStringOverflow(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_ibs(matches: &Matches) -> Result<usize, ParseError> {
|
||||
if let Some(mixed_str) = matches.value_of("bs") {
|
||||
if let Some(mixed_str) = matches.value_of(options::BS) {
|
||||
parse_bytes_with_opt_multiplier(mixed_str)
|
||||
} else if let Some(mixed_str) = matches.value_of("ibs") {
|
||||
} else if let Some(mixed_str) = matches.value_of(options::IBS) {
|
||||
parse_bytes_with_opt_multiplier(mixed_str)
|
||||
} else {
|
||||
Ok(512)
|
||||
@@ -364,7 +337,7 @@ pub fn parse_ibs(matches: &Matches) -> Result<usize, ParseError> {
|
||||
}
|
||||
|
||||
fn parse_cbs(matches: &Matches) -> Result<Option<usize>, ParseError> {
|
||||
if let Some(s) = matches.value_of("cbs") {
|
||||
if let Some(s) = matches.value_of(options::CBS) {
|
||||
let bytes = parse_bytes_with_opt_multiplier(s)?;
|
||||
Ok(Some(bytes))
|
||||
} else {
|
||||
@@ -373,7 +346,7 @@ fn parse_cbs(matches: &Matches) -> Result<Option<usize>, ParseError> {
|
||||
}
|
||||
|
||||
pub fn parse_status_level(matches: &Matches) -> Result<Option<StatusLevel>, ParseError> {
|
||||
match matches.value_of("status") {
|
||||
match matches.value_of(options::STATUS) {
|
||||
Some(s) => {
|
||||
let st = s.parse()?;
|
||||
Ok(Some(st))
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* cspell:disable */
|
||||
|
||||
use super::*;
|
||||
|
||||
use crate::StatusLevel;
|
||||
@@ -7,7 +5,7 @@ use crate::StatusLevel;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
#[test]
|
||||
fn unimplemented_flags_should_error_non_unix() {
|
||||
let mut unfailed = Vec::new();
|
||||
let mut succeeded = Vec::new();
|
||||
|
||||
// The following flags are only implemented in linux
|
||||
for flag in vec![
|
||||
@@ -28,26 +26,26 @@ fn unimplemented_flags_should_error_non_unix() {
|
||||
let matches = uu_app().get_matches_from_safe(args).unwrap();
|
||||
|
||||
match parse_iflags(&matches) {
|
||||
Ok(_) => unfailed.push(format!("iflag={}", flag)),
|
||||
Ok(_) => succeeded.push(format!("iflag={}", flag)),
|
||||
Err(_) => { /* expected behaviour :-) */ }
|
||||
}
|
||||
match parse_oflags(&matches) {
|
||||
Ok(_) => unfailed.push(format!("oflag={}", flag)),
|
||||
Ok(_) => succeeded.push(format!("oflag={}", flag)),
|
||||
Err(_) => { /* expected behaviour :-) */ }
|
||||
}
|
||||
}
|
||||
|
||||
if !unfailed.is_empty() {
|
||||
if !succeeded.is_empty() {
|
||||
panic!(
|
||||
"The following flags did not panic as expected: {:?}",
|
||||
unfailed
|
||||
succeeded
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unimplemented_flags_should_error() {
|
||||
let mut unfailed = Vec::new();
|
||||
let mut succeeded = Vec::new();
|
||||
|
||||
// The following flags are not implemented
|
||||
for flag in vec!["cio", "nocache", "nolinks", "text", "binary"] {
|
||||
@@ -59,19 +57,19 @@ fn unimplemented_flags_should_error() {
|
||||
let matches = uu_app().get_matches_from_safe(args).unwrap();
|
||||
|
||||
match parse_iflags(&matches) {
|
||||
Ok(_) => unfailed.push(format!("iflag={}", flag)),
|
||||
Ok(_) => succeeded.push(format!("iflag={}", flag)),
|
||||
Err(_) => { /* expected behaviour :-) */ }
|
||||
}
|
||||
match parse_oflags(&matches) {
|
||||
Ok(_) => unfailed.push(format!("oflag={}", flag)),
|
||||
Ok(_) => succeeded.push(format!("oflag={}", flag)),
|
||||
Err(_) => { /* expected behaviour :-) */ }
|
||||
}
|
||||
}
|
||||
|
||||
if !unfailed.is_empty() {
|
||||
if !succeeded.is_empty() {
|
||||
panic!(
|
||||
"The following flags did not panic as expected: {:?}",
|
||||
unfailed
|
||||
succeeded
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -105,6 +103,176 @@ fn test_status_level_none() {
|
||||
assert_eq!(st, StatusLevel::None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_top_level_args_no_leading_dashes_sep_by_equals() {
|
||||
let args = vec![
|
||||
String::from("dd"),
|
||||
String::from("if=foo.file"),
|
||||
String::from("of=bar.file"),
|
||||
String::from("ibs=10"),
|
||||
String::from("obs=10"),
|
||||
String::from("cbs=1"),
|
||||
String::from("bs=100"),
|
||||
String::from("count=2"),
|
||||
String::from("skip=2"),
|
||||
String::from("seek=2"),
|
||||
String::from("status=progress"),
|
||||
String::from("conv=ascii,ucase"),
|
||||
String::from("iflag=count_bytes,skip_bytes"),
|
||||
String::from("oflag=append,seek_bytes"),
|
||||
];
|
||||
let args = args
|
||||
.into_iter()
|
||||
.fold(Vec::new(), append_dashes_if_not_present);
|
||||
|
||||
let matches = uu_app().get_matches_from_safe(args).unwrap();
|
||||
|
||||
assert_eq!(100, parse_ibs(&matches).unwrap());
|
||||
assert_eq!(100, parse_obs(&matches).unwrap());
|
||||
assert_eq!(1, parse_cbs(&matches).unwrap().unwrap());
|
||||
assert_eq!(
|
||||
CountType::Bytes(2),
|
||||
parse_count(
|
||||
&IFlags {
|
||||
count_bytes: true,
|
||||
..IFlags::default()
|
||||
},
|
||||
&matches
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
200,
|
||||
parse_skip_amt(&100, &IFlags::default(), &matches)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
200,
|
||||
parse_seek_amt(&100, &OFlags::default(), &matches)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
StatusLevel::Progress,
|
||||
parse_status_level(&matches).unwrap().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
IConvFlags {
|
||||
ctable: Some(&EBCDIC_TO_ASCII_LCASE_TO_UCASE),
|
||||
..IConvFlags::default()
|
||||
},
|
||||
parse_conv_flag_input(&matches).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
OConvFlags::default(),
|
||||
parse_conv_flag_output(&matches).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
IFlags {
|
||||
count_bytes: true,
|
||||
skip_bytes: true,
|
||||
..IFlags::default()
|
||||
},
|
||||
parse_iflags(&matches).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
OFlags {
|
||||
append: true,
|
||||
seek_bytes: true,
|
||||
..OFlags::default()
|
||||
},
|
||||
parse_oflags(&matches).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
// TODO: This should work, but Clap doesn't seem to understand it. Leaving it for now since the traditional dd if=foo.file works just fine.
|
||||
fn test_all_top_level_args_leading_dashes_sep_by_spaces() {
|
||||
let args = vec![
|
||||
String::from("dd"),
|
||||
String::from("--if foo.file"),
|
||||
String::from("--of bar.file"),
|
||||
String::from("--ibs 10"),
|
||||
String::from("--obs 10"),
|
||||
String::from("--cbs 1"),
|
||||
String::from("--bs 100"),
|
||||
String::from("--count 2"),
|
||||
String::from("--skip 2"),
|
||||
String::from("--seek 2"),
|
||||
String::from("--status progress"),
|
||||
String::from("--conv ascii,ucase"),
|
||||
String::from("--iflag count_bytes,skip_bytes"),
|
||||
String::from("--oflag append,seek_bytes"),
|
||||
];
|
||||
let args = args
|
||||
.into_iter()
|
||||
.fold(Vec::new(), append_dashes_if_not_present);
|
||||
|
||||
let matches = uu_app().get_matches_from_safe(args).unwrap();
|
||||
|
||||
assert_eq!(100, parse_ibs(&matches).unwrap());
|
||||
assert_eq!(100, parse_obs(&matches).unwrap());
|
||||
assert_eq!(1, parse_cbs(&matches).unwrap().unwrap());
|
||||
assert_eq!(
|
||||
CountType::Bytes(2),
|
||||
parse_count(
|
||||
&IFlags {
|
||||
count_bytes: true,
|
||||
..IFlags::default()
|
||||
},
|
||||
&matches
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
200,
|
||||
parse_skip_amt(&100, &IFlags::default(), &matches)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
200,
|
||||
parse_seek_amt(&100, &OFlags::default(), &matches)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
StatusLevel::Progress,
|
||||
parse_status_level(&matches).unwrap().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
IConvFlags {
|
||||
ctable: Some(&EBCDIC_TO_ASCII_LCASE_TO_UCASE),
|
||||
..IConvFlags::default()
|
||||
},
|
||||
parse_conv_flag_input(&matches).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
OConvFlags::default(),
|
||||
parse_conv_flag_output(&matches).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
IFlags {
|
||||
count_bytes: true,
|
||||
skip_bytes: true,
|
||||
..IFlags::default()
|
||||
},
|
||||
parse_iflags(&matches).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
OFlags {
|
||||
append: true,
|
||||
seek_bytes: true,
|
||||
..OFlags::default()
|
||||
},
|
||||
parse_oflags(&matches).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_status_level_progress() {
|
||||
let args = vec![
|
||||
@@ -374,16 +542,6 @@ test_byte_parser!(
|
||||
6 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024
|
||||
);
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
#[allow(non_snake_case)]
|
||||
fn test_KB_multiplier_error() {
|
||||
// KB is not valid (kB, K, and KiB are)
|
||||
let bs_str = "2000KB";
|
||||
|
||||
parse_bytes_with_opt_multiplier(bs_str).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_overflow_panic() {
|
||||
@@ -395,7 +553,7 @@ fn test_overflow_panic() {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_neg_panic() {
|
||||
let bs_str = format!("{}KiB", -1);
|
||||
let bs_str = format!("{}", -1);
|
||||
|
||||
parse_bytes_with_opt_multiplier(&bs_str).unwrap();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* cspell:disable */
|
||||
|
||||
use crate::common::util::*;
|
||||
|
||||
use std::fs::{File, OpenOptions};
|
||||
|
||||
Reference in New Issue
Block a user