Skip to content

Commit

Permalink
dd: block/unblock on ebcdic/ascii conversions
Browse files Browse the repository at this point in the history
Update `dd` so that the conversion `conv=ascii` implies `conv=unblock`
and, symmetrically, the conversion `conv=ebcdic` implies `conv=block`.
  • Loading branch information
jfinkels committed Jan 23, 2022
1 parent 8a787fe commit 2b2b5b3
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/uu/dd/src/parseargs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,13 +444,40 @@ pub fn parse_conv_flag_input(matches: &Matches) -> Result<IConvFlags, ParseError
return Err(ParseError::MultipleFmtTable);
} else {
fmt = Some(flag);
// From the GNU documentation:
//
// > ‘ascii’
// >
// > Convert EBCDIC to ASCII, using the conversion
// > table specified by POSIX. This provides a 1:1
// > translation for all 256 bytes. This implies
// > ‘conv=unblock’; input is converted to ASCII
// > before trailing spaces are deleted.
//
// -- https://www.gnu.org/software/coreutils/manual/html_node/dd-invocation.html
if cbs.is_some() {
iconvflags.unblock = cbs;
}
}
}
ConvFlag::FmtAtoE => {
if fmt.is_some() {
return Err(ParseError::MultipleFmtTable);
} else {
fmt = Some(flag);
// From the GNU documentation:
//
// > ‘ebcdic’
// >
// > Convert ASCII to EBCDIC. This is the inverse
// > of the ‘ascii’ conversion. This implies
// > ‘conv=block’; trailing spaces are added before
// > being converted to EBCDIC.
//
// -- https://www.gnu.org/software/coreutils/manual/html_node/dd-invocation.html
if cbs.is_some() {
iconvflags.block = cbs;
}
}
}
ConvFlag::FmtAtoI => {
Expand Down
33 changes: 33 additions & 0 deletions tests/by-util/test_dd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,5 +559,38 @@ fn test_unicode_filenames() {
);
}

#[test]
fn test_conv_ascii_implies_unblock() {
// 0x40 = 0o100 = 64, which gets converted to ' '
// 0xc1 = 0o301 = 193, which gets converted to 'A'
//
// `conv=ascii` implies `conv=unblock`, which means trailing paces
// are stripped and a newline is appended at the end of each
// block.
//
// `cbs=4` means use a conversion block size of 4 bytes per block.
new_ucmd!()
.args(&["conv=ascii", "cbs=4"])
.pipe_in(b"\x40\xc1\x40\xc1\x40\xc1\x40\x40".to_vec())
.succeeds()
.stdout_is(" A A\n A\n");
}

#[test]
fn test_conv_ebcdic_implies_block() {
// 0x40 = 0o100 = 64, which is the result of converting from ' '
// 0xc1 = 0o301 = 193, which is the result of converting from 'A'
//
// `conv=ebcdic` implies `conv=block`, which means trailing spaces
// are added to pad each block.
//
// `cbs=4` means use a conversion block size of 4 bytes per block.
new_ucmd!()
.args(&["conv=ebcdic", "cbs=4"])
.pipe_in(" A A\n A\n")
.succeeds()
.stdout_is_bytes(b"\x40\xc1\x40\xc1\x40\xc1\x40\x40");
}

// conv=[ascii,ebcdic,ibm], conv=[ucase,lcase], conv=[block,unblock], conv=sync
// TODO: Move conv tests from unit test module

0 comments on commit 2b2b5b3

Please sign in to comment.