1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 19:47:45 +00:00

dd: allow B as a suffix for count, seek, and skip

Allow uppercase "B" on its own as a unit specifier for the `count`,
`seek`, and `skip` arguments to `dd`.

For example,

    $ printf "abcdef" | dd count=3B status=none
    abc
This commit is contained in:
Jeffrey Finkelstein 2022-11-18 20:27:42 -05:00
parent 847378f8d2
commit 701550d76b
3 changed files with 38 additions and 2 deletions

View file

@ -14,7 +14,7 @@ use crate::conversion_tables::ConversionTable;
use std::error::Error;
use uucore::display::Quotable;
use uucore::error::UError;
use uucore::parse_size::ParseSizeError;
use uucore::parse_size::{ParseSizeError, Parser as SizeParser};
use uucore::show_warning;
/// Parser Errors describe errors with parser input
@ -499,8 +499,11 @@ fn parse_bytes_only(s: &str) -> Result<u64, ParseError> {
/// assert_eq!(parse_bytes_no_x("2k", "2k").unwrap(), 2 * 1024);
/// ```
fn parse_bytes_no_x(full: &str, s: &str) -> Result<u64, ParseError> {
let parser = SizeParser {
capital_b_bytes: true,
};
let (num, multiplier) = match (s.find('c'), s.rfind('w'), s.rfind('b')) {
(None, None, None) => match uucore::parse_size::parse_size(s) {
(None, None, None) => match parser.parse(s) {
Ok(n) => (n, 1),
Err(ParseSizeError::InvalidSuffix(_)) | Err(ParseSizeError::ParseFailure(_)) => {
return Err(ParseError::InvalidNumber(full.to_string()))

View file

@ -15,6 +15,8 @@ use crate::display::Quotable;
/// The [`Parser::parse`] function performs the parse.
#[derive(Default)]
pub struct Parser {
/// Whether to treat the suffix "B" as meaning "bytes".
pub capital_b_bytes: bool,
}
impl Parser {
@ -67,6 +69,7 @@ impl Parser {
let unit = &size[numeric_string.len()..];
let (base, exponent): (u128, u32) = match unit {
"" => (1, 0),
"B" if self.capital_b_bytes => (1, 0),
"b" => (512, 1),
"KiB" | "kiB" | "K" | "k" => (1024, 1),
"MiB" | "miB" | "M" | "m" => (1024, 2),

View file

@ -1295,3 +1295,33 @@ fn test_big_multiplication() {
.fails()
.stderr_contains("invalid number");
}
/// Test for count, seek, and skip given in units of bytes.
#[test]
fn test_bytes_suffix() {
new_ucmd!()
.args(&["count=3B", "status=none"])
.pipe_in("abcdef")
.succeeds()
.stdout_only("abc");
new_ucmd!()
.args(&["skip=3B", "status=none"])
.pipe_in("abcdef")
.succeeds()
.stdout_only("def");
new_ucmd!()
.args(&["iseek=3B", "status=none"])
.pipe_in("abcdef")
.succeeds()
.stdout_only("def");
new_ucmd!()
.args(&["seek=3B", "status=none"])
.pipe_in("abcdef")
.succeeds()
.stdout_only("\0\0\0abcdef");
new_ucmd!()
.args(&["oseek=3B", "status=none"])
.pipe_in("abcdef")
.succeeds()
.stdout_only("\0\0\0abcdef");
}