From 5c8c7efe687ab0ff83bbb504b030d9febcd7fce6 Mon Sep 17 00:00:00 2001 From: Tyler Date: Tue, 6 Apr 2021 20:44:37 -0700 Subject: [PATCH] Starts arg parsing. Cleans & refactors. - Moves all arg parsing & tests to parseargs.rs - Moves conversion tables to conversion_tables.rs - Adds ebcdic_lcase and _ucase tables - Refactors options: This **Breaks Write for Output** --- src/uu/dd/src/conversion_tables.rs | 139 +++++++++ src/uu/dd/src/dd.rs | 257 ++++++--------- src/uu/dd/src/{ddargs.rs => parseargs.rs} | 198 +++++++++++- src/uu/dd/src/test_dd_internal.rs | 292 ++++++++++-------- ...nudd-conv-ebcdic-ltou-seq-byte-values.spec | Bin 0 -> 256 bytes ...nudd-conv-ebcdic-utol-seq-byte-values.spec | Bin 0 -> 256 bytes 6 files changed, 578 insertions(+), 308 deletions(-) create mode 100644 src/uu/dd/src/conversion_tables.rs rename src/uu/dd/src/{ddargs.rs => parseargs.rs} (56%) create mode 100644 src/uu/dd/test-resources/gnudd-conv-ebcdic-ltou-seq-byte-values.spec create mode 100644 src/uu/dd/test-resources/gnudd-conv-ebcdic-utol-seq-byte-values.spec diff --git a/src/uu/dd/src/conversion_tables.rs b/src/uu/dd/src/conversion_tables.rs new file mode 100644 index 000000000..62c75febc --- /dev/null +++ b/src/uu/dd/src/conversion_tables.rs @@ -0,0 +1,139 @@ + +// 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. +pub type ConversionTable = [u8; 256]; + +pub const ASCII_TO_EBCDIC: ConversionTable = [ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, + 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, + 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b, + 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +pub const ASCII_TO_IBM: ConversionTable = [ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, + 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, + 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d, + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b, + 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +pub const EBCDIC_TO_ASCII: ConversionTable = [ + 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f, 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, + 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, + 0x20, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xd5, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, + 0x26, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x7e, + 0x2d, 0x2f, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xcb, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, + 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, + 0xc3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, + 0xca, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x5e, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xe5, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xd2, 0xd3, 0xd4, 0x5b, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x5d, 0xe6, 0xe7, + 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, + 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, + 0x5c, 0x9f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +pub const ASCII_LCASE_TO_UCASE: ConversionTable = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + +]; + +pub const ASCII_UCASE_TO_LCASE: ConversionTable = [ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +pub const EBCDIC_LCASE_TO_UCASE: ConversionTable = [ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, + 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, + 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, + 0x79, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, + 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b, + 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; + +pub const EBCDIC_UCASE_TO_LCASE: ConversionTable = [ + 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, + 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, + 0x7c, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, + 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b, + 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, + 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e, + 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +]; diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index 9fb896e2e..cd04ee85d 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -13,7 +13,11 @@ extern crate uucore; #[cfg(test)] mod test_dd_internal; -mod ddargs; +mod parseargs; +mod conversion_tables; + +use conversion_tables::*; +use parseargs::*; use std::error::Error; use std::fs::File; @@ -24,117 +28,14 @@ use std::sync::mpsc; use std::thread; use getopts; -const NAME: &str = "dd"; -const SUMMARY: &str = "convert and copy a file"; -const LONG_HELP: &str = "TODO: This is where the long help string for dd goes!"; +const SYNTAX: &str = "dd [OPERAND]...\ndd OPTION"; +const SUMMARY: &str = "convert, and optionally copy, a file"; +const LONG_HELP: &str = ""; const RTN_SUCCESS: i32 = 0; const RTN_FAILURE: i32 = 1; -// ----- Conversion ----- -// -// 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. -type ConversionTable = [u8; 256]; - -const ASCII_TO_EBCDIC: ConversionTable = [ - 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, - 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, - 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, - 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x9a, 0x6d, - 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0x5f, 0x07, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b, - 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1, - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, - 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x6a, 0x9b, 0x9c, 0x9d, 0x9e, - 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0x4a, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xa1, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb, - 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - -const ASCII_TO_IBM: ConversionTable = [ - 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, - 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, - 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, - 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xad, 0xe0, 0xbd, 0x5f, 0x6d, - 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x15, 0x06, 0x17, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x09, 0x0a, 0x1b, - 0x30, 0x31, 0x1a, 0x33, 0x34, 0x35, 0x36, 0x08, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x14, 0x3e, 0xe1, - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, - 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, - 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xda, 0xdb, - 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - -const EBCDIC_TO_ASCII: ConversionTable = [ - 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f, 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, - 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, - 0x20, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xd5, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, - 0x26, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x7e, - 0x2d, 0x2f, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xcb, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, - 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, - 0xc3, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, - 0xca, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x5e, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, - 0xd1, 0xe5, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0xd2, 0xd3, 0xd4, 0x5b, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x5d, 0xe6, 0xe7, - 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, - 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, - 0x5c, 0x9f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - -const LCASE_TO_UCASE: ConversionTable = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, - -]; - -const UCASE_TO_LCASE: ConversionTable = [ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, -]; - -// ----- Types ----- +// ----- Datatypes ----- enum SrcStat { Read(usize), @@ -161,7 +62,6 @@ struct Input { src: R, ibs: usize, - output_progress: bool, } impl Read for Input @@ -176,14 +76,12 @@ impl Input { fn new(matches: &getopts::Matches) -> Result> { - let ibs: usize = ddargs::parse_ibs(matches)?; - let output_progress = ddargs::parse_progress_level(matches)?; + let ibs: usize = parseargs::parse_ibs(matches)?; Ok( Input { src: io::stdin(), ibs, - output_progress, } ) @@ -194,15 +92,13 @@ impl Input { fn new(matches: &getopts::Matches) -> Result> { - let ibs: usize = ddargs::parse_ibs(matches)?; - let output_progress = ddargs::parse_progress_level(matches)?; + let ibs: usize = parseargs::parse_ibs(matches)?; if let Some(fname) = matches.opt_str("if") { Ok(Input { src: File::open(fname)?, ibs, - output_progress, }) } else @@ -243,20 +139,17 @@ struct Output { dst: W, obs: usize, - conv_table: Option, } impl Output { fn new(matches: &getopts::Matches) -> Result> { - let obs: usize = ddargs::parse_obs(matches)?; - let conv_table = ddargs::parse_conv_table(matches)?; + let obs: usize = parseargs::parse_obs(matches)?; Ok( Output { dst: io::stdout(), obs, - conv_table, } ) } @@ -265,15 +158,13 @@ impl Output { impl Output { fn new(matches: &getopts::Matches) -> Result> { - let obs: usize = ddargs::parse_obs(matches)?; - let conv_table = ddargs::parse_conv_table(matches)?; + let obs: usize = parseargs::parse_obs(matches)?; if let Some(fname) = matches.opt_str("if") { Ok(Output { dst: File::open(fname)?, obs, - conv_table, }) } else @@ -310,6 +201,33 @@ impl Write for Output } } +struct Options +{ + conv: Option, + status_level: StatusLevel, + // ... +} + +struct ConversionOptions +{ + table: Option, + block: bool, + unblock: bool, + lcase: bool, + ucase: bool, + sparse: bool, + swab: bool, + sync: bool, +} + +#[derive(PartialEq)] +enum StatusLevel +{ + Progress, + Noxfer, + None, +} + fn gen_prog_updater(rx: mpsc::Receiver) -> impl Fn() -> () { move || { @@ -333,10 +251,12 @@ fn gen_prog_updater(rx: mpsc::Receiver) -> impl Fn() -> () } } -fn dd(mut i: Input, mut o: Output) -> Result<(usize, usize), Box> +fn dd(mut i: Input, mut o: Output, opts: Options) -> Result<(usize, usize), Box> { - let prog_tx = if i.output_progress { + let prog_tx = if opts.status_level == StatusLevel::Progress + { let (prog_tx, prog_rx) = mpsc::channel(); + thread::spawn(gen_prog_updater(prog_rx)); Some(prog_tx) @@ -364,7 +284,9 @@ fn dd(mut i: Input, mut o: Output) -> Result<(usize, us }; let w_len = o.write(&buf[..r_len])?; - o.flush()?; + + // TODO: Some flag (sync?) controls this behaviour + // o.flush()?; bytes_out += w_len; @@ -377,6 +299,44 @@ fn dd(mut i: Input, mut o: Output) -> Result<(usize, us Ok((bytes_in, bytes_out)) } +#[macro_export] +macro_rules! build_app ( + () => + { + app!(SYNTAX, SUMMARY, LONG_HELP) + .optopt( + "", + "if", + "The input file", + "FILE" + ) + .optopt( + "", + "ibs", + "read up to BYTES bytes at a time (default: 512)", + "BYTES" + ) + .optopt( + "", + "of", + "The output file", + "FILE" + ) + .optopt( + "", + "obs", + "write BYTES bytes at a time (default: 512)", + "BYTES" + ) + .optopt( + "", + "conv", + "One or more conversion options as a comma-serparated list", + "OPT[,OPT]..." + ) + } +); + fn append_dashes_if_not_present(mut acc: Vec, s: &String) -> Vec { if Some("--") == s.get(0..=1) { @@ -393,43 +353,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 .iter() .fold(Vec::new(), append_dashes_if_not_present); - let syntax = format!( - "{0} [OPERAND]...\n{0} OPTION", - NAME - ); + let matches = build_app!().parse(dashed_args); - let matches = app!(&syntax, SUMMARY, LONG_HELP) - .optopt( - "", - "if", - "The input file", - "FILE" - ) - .optopt( - "", - "ibs", - "read up to BYTES bytes at a time (default: 512)", - "BYTES" - ) - .optopt( - "", - "of", - "The output file", - "FILE" - ) - .optopt( - "", - "obs", - "write BYTES bytes at a time (default: 512)", - "BYTES" - ) - .optopt( - "", - "conv", - "One or more conversion options as a comma-serparated list", - "OPT[,OPT]..." - ) - .parse(dashed_args); + let opts = parse_options(&matches) + .expect("TODO: Return correct error code"); let result = match (matches.opt_present("if"), matches.opt_present("of")) { @@ -440,7 +367,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 let o = Output::::new(&matches) .expect("TODO: Return correct error code"); - dd(i, o) + dd(i, o, opts) }, (true, false) => { @@ -449,7 +376,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 let o = Output::::new(&matches) .expect("TODO: Return correct error code"); - dd(i, o) + dd(i, o, opts) }, (false, true) => { @@ -458,7 +385,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 let o = Output::::new(&matches) .expect("TODO: Return correct error code"); - dd(i, o) + dd(i, o, opts) }, (false, false) => { @@ -467,7 +394,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 let o = Output::::new(&matches) .expect("TODO: Return correct error code"); - dd(i, o) + dd(i, o, opts) }, }; diff --git a/src/uu/dd/src/ddargs.rs b/src/uu/dd/src/parseargs.rs similarity index 56% rename from src/uu/dd/src/ddargs.rs rename to src/uu/dd/src/parseargs.rs index 86805d213..69b4cea9d 100644 --- a/src/uu/dd/src/ddargs.rs +++ b/src/uu/dd/src/parseargs.rs @@ -1,8 +1,11 @@ use super::*; +use crate::conversion_tables::*; + #[derive(Debug)] enum ParseError { + ConvFlagNoMatch(String), MultiplierString(String), MultiplierStringWouldOverflow(String), } @@ -16,6 +19,52 @@ impl std::fmt::Display for ParseError impl Error for ParseError {} +enum ConvFlag +{ + Table(ConversionTable), + Block, + Unblock, + UCase, + LCase, + Sparse, + Swab, + Sync, +} + +impl std::str::FromStr for ConvFlag +{ + type Err = ParseError; + + fn from_str(s: &str) -> Result + { + match s + { + "ascii" => + Ok(Self::Table(EBCDIC_TO_ASCII)), + "ebcdic" => + Ok(Self::Table(ASCII_TO_EBCDIC)), + "ibm" => + Ok(Self::Table(ASCII_TO_IBM)), + "block" => + Ok(Self::Block), + "unblock" => + Ok(Self::Unblock), + "lcase" => + Ok(Self::LCase), + "ucase" => + Ok(Self::UCase), + "sparse" => + Ok(Self::Sparse), + "swab" => + Ok(Self::Swab), + "sync" => + Ok(Self::Sync), + _ => + Err(ParseError::ConvFlagNoMatch(String::from(s))) + } + } +} + fn parse_multiplier<'a>(s: &'a str) -> Result> { let s = s.trim(); @@ -114,17 +163,13 @@ pub fn parse_progress_level(matches: &getopts::Matches) -> Result Result> { - if let Some(str_with_prefixes) = matches.opt_str("bs") + if let Some(mixed_str) = matches.opt_str("bs") { - // TODO: Parse a string containing the number with potential k, kB, kiB, ... multiplier - // possibly implemented elsewhere, but probably not in exactly the dd style - panic!() + parse_bytes_with_opt_multiplier(mixed_str) } - else if let Some(str_with_prefixes) = matches.opt_str("obs") + else if let Some(mixed_str) = matches.opt_str("obs") { - // TODO: Parse a string containing the number with potential k, kB, kiB, ... multiplier - // possibly implemented elsewhere, but probably not in exactly the dd style - panic!() + parse_bytes_with_opt_multiplier(mixed_str) } else { @@ -132,19 +177,105 @@ pub fn parse_obs(matches: &getopts::Matches) -> Result> } } -pub fn parse_conv_table(matches: &getopts::Matches) -> Result, Box> +/// Parse the options and flags that control the way +/// the file(s) is(are) copied and converted +pub fn parse_options(matches: &getopts::Matches) -> Result> { - // TODO: Complete this stub fn - Ok(None) + panic!() +} + +/// Parse Conversion Options that control how the file is converted +pub fn parse_conv_options(matches: &getopts::Matches) -> Result> +{ + let flags = parse_conv_opts(matches)?; + + let mut table = None; + let mut block = false; + let mut unblock = false; + let mut ucase = false; + let mut lcase = false; + let mut sparse = false; + let mut swab = false; + let mut sync = false; + + for flag in flags + { + match flag + { + ConvFlag::Table(ct) => + { + table = Some(ct); + }, + ConvFlag::Block => + { + block = true; + }, + ConvFlag::Unblock => + { + unblock = true; + }, + ConvFlag::UCase => + { + ucase = true; + }, + ConvFlag::LCase => + { + lcase = true; + }, + ConvFlag::Sparse => + { + sparse = true; + }, + ConvFlag::Swab => + { + swab = true; + }, + ConvFlag::Sync => + { + sync = true; + }, + } + } + + Ok(ConversionOptions + { + table, + block, + unblock, + ucase, + lcase, + sparse, + swab, + sync, + }) +} + +fn parse_conv_opts(matches: &getopts::Matches) -> Result, Box> +{ + let mut flags = Vec::new(); + + if let Some(comma_str) = matches.opt_str("conv") + { + for s in comma_str.split(",") + { + let flag = s.parse()?; + flags.push(flag); + } + + } + + Ok(flags) } #[cfg(test)] mod test { + use super::*; macro_rules! test_byte_parser ( ( $test_name:ident, $bs_str:expr, $bs:expr ) => { + #[allow(non_snake_case)] #[test] fn $test_name() { @@ -167,9 +298,30 @@ mod test { } #[test] - fn test_conv_options_parser() + fn test_conv_parser_ibm_conv_table() { - panic!() + let args = vec![ + String::from("ketchup"), + String::from("mustard"), + String::from("--conv=ibm"), + String::from("relish"), + ]; + + let matches = build_app!().parse(args); + + assert!(matches.opt_present("conv")); + + if let Some(table) = parse_conv_opts(&matches).unwrap() + { + for (s, t) in ASCII_TO_IBM.iter().zip(table.iter()) + { + assert_eq!(s, t) + } + } + else + { + panic!() + } } test_byte_parser!( @@ -293,11 +445,31 @@ mod test { #[test] #[should_panic] + #[allow(non_snake_case)] fn test_KB_multiplier_error() { + // KB is not valid (kB, K, and KiB are) let bs_str = String::from("2000 KB"); parse_bytes_with_opt_multiplier(bs_str).unwrap(); } + #[test] + #[should_panic] + fn test_overflow_panic() + { + let bs_str = format!("{} KiB", usize::MAX); + + parse_bytes_with_opt_multiplier(bs_str).unwrap(); + } + + #[test] + #[should_panic] + fn test_neg_panic() + { + let bs_str = format!("{} KiB", -1); + + parse_bytes_with_opt_multiplier(bs_str).unwrap(); + } + } diff --git a/src/uu/dd/src/test_dd_internal.rs b/src/uu/dd/src/test_dd_internal.rs index c171e5b36..bea25b54d 100644 --- a/src/uu/dd/src/test_dd_internal.rs +++ b/src/uu/dd/src/test_dd_internal.rs @@ -3,13 +3,88 @@ use super::*; use std::io::prelude::*; use std::io::BufReader; use std::fs; -use md5::{ Md5, Digest, }; -use hex_literal::hex; +// use md5::{ Md5, Digest, }; +// use hex_literal::hex; + // use tempfile::tempfile; // TODO: (Maybe) Use tempfiles in the tests. -macro_rules! make_hash_test ( - ( $test_id:ident, $test_name:expr, $src:expr, $exp:expr ) => +//macro_rules! make_hash_test ( +// ( $test_id:ident, $test_name:expr, $src:expr, $exp:expr ) => +// { +// #[test] +// fn $test_id() +// { +// let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name); +// +// let i = Input { +// src: $src, +// ibs: 256, +// output_progress: false, +// }; +// +// let o = Output { +// dst: File::create(&tmp_fname).unwrap(), +// obs: 1024, +// conv_table: None, +// }; +// +// dd(i,o).unwrap(); +// +// let res = { +// let res = File::open(&tmp_fname).unwrap(); +// let res = BufReader::new(res); +// +// let mut h = Md5::new(); +// for b in res.bytes() +// { +// h.update([b.unwrap()]); +// } +// +// h.finalize() +// }; +// +// assert_eq!(hex!($exp), res[..]); +// +// fs::remove_file(&tmp_fname).unwrap(); +// } +// }; +// ( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $exp:expr ) => +// { +// #[test] +// fn $test_id() +// { +// let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name); +// +// let o = Output { +// dst: File::create(&tmp_fname).unwrap(), +// obs: $o.obs, +// }; +// +// dd($i,o).unwrap(); +// +// let res = { +// let res = File::open(&tmp_fname).unwrap(); +// let res = BufReader::new(res); +// +// let mut h = Md5::new(); +// for b in res.bytes() +// { +// h.update([b.unwrap()]); +// } +// +// h.finalize() +// }; +// +// assert_eq!(hex!($exp), res[..]); +// +// fs::remove_file(&tmp_fname).unwrap(); +// } +// }; +//); + +macro_rules! make_spec_test ( + ( $test_id:ident, $test_name:expr, $src:expr, $spec:expr ) => { #[test] fn $test_id() @@ -18,37 +93,45 @@ macro_rules! make_hash_test ( let i = Input { src: $src, - ibs: 256, - output_progress: false, + ibs: 512, }; let o = Output { dst: File::create(&tmp_fname).unwrap(), - obs: 1024, - conv_table: None, + obs: 512, }; - dd(i,o).unwrap(); - - let res = { - let res = File::open(&tmp_fname).unwrap(); - let res = BufReader::new(res); - - let mut h = Md5::new(); - for b in res.bytes() - { - h.update([b.unwrap()]); - } - - h.finalize() + let opts = Options { + conv: Some(ConversionOptions { + table: None, + block: false, + unblock: false, + lcase: false, + ucase: false, + sparse: false, + swab: false, + sync: false, + }), + status_level: None, }; - assert_eq!(hex!($exp), res[..]); + dd($i,o,opts).unwrap(); + + let res = File::open(&tmp_fname).unwrap(); + let res = BufReader::new(res); + + let spec = BufReader::new($spec); + + for (b_res, b_spec) in res.bytes().zip(spec.bytes()) + { + assert_eq!(b_res.unwrap(), + b_spec.unwrap()); + } fs::remove_file(&tmp_fname).unwrap(); } }; - ( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $exp:expr ) => + ( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $conv:expr, $spec:expr ) => { #[test] fn $test_id() @@ -58,46 +141,23 @@ macro_rules! make_hash_test ( let o = Output { dst: File::create(&tmp_fname).unwrap(), obs: $o.obs, - conv_table: $o.conv_table, }; - dd($i,o).unwrap(); - - let res = { - let res = File::open(&tmp_fname).unwrap(); - let res = BufReader::new(res); - - let mut h = Md5::new(); - for b in res.bytes() - { - h.update([b.unwrap()]); - } - - h.finalize() + let opts = Options { + conv: Some(ConversionOptions { + table: $conv, + block: false, + unblock: false, + lcase: false, + ucase: false, + sparse: false, + swab: false, + sync: false, + }), + status_level: None, }; - assert_eq!(hex!($exp), res[..]); - - fs::remove_file(&tmp_fname).unwrap(); - } - }; -); - -macro_rules! make_spec_test ( - ( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $spec:expr ) => - { - #[test] - fn $test_id() - { - let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name); - - let o = Output { - dst: File::create(&tmp_fname).unwrap(), - obs: $o.obs, - conv_table: $o.conv_table, - }; - - dd($i,o).unwrap(); + dd($i,o,opts).unwrap(); let res = File::open(&tmp_fname).unwrap(); let res = BufReader::new(res); @@ -115,39 +175,32 @@ macro_rules! make_spec_test ( }; ); -make_hash_test!( - empty_file_test, - "stdio-empty-file", - io::empty(), - "d41d8cd98f00b204e9800998ecf8427e" -); - -make_hash_test!( +make_spec_test!( zeros_4k_test, "zeros-4k", File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap(), - "620f0b67a91f7f74151bc5be745b7110" + File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap() ); -make_hash_test!( +make_spec_test!( ones_4k_test, "ones-4k", File::open("./test-resources/ones-6ae59e64850377ee5470c854761551ea.test").unwrap(), - "6ae59e64850377ee5470c854761551ea" + File::open("./test-resources/ones-6ae59e64850377ee5470c854761551ea.test").unwrap() ); -make_hash_test!( +make_spec_test!( deadbeef_32k_test, "deadbeef-32k", File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(), - "18d99661a1de1fc9af21b0ec2cd67ba3" + File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap() ); -make_hash_test!( +make_spec_test!( random_73k_test, "random-73k", File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(), - "5828891cb1230748e146f34223bbd3b5" + File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap() ); make_spec_test!( @@ -156,13 +209,12 @@ make_spec_test!( Input { src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(), ibs: 512, - output_progress: false, }, Output { dst: Vec::new(), // unused! obs: 512, - conv_table: Some(ASCII_TO_EBCDIC), }, + Some(ASCII_TO_EBCDIC), File::open("./test-resources/gnudd-conv-atoe-seq-byte-values.spec").unwrap() ); @@ -172,13 +224,12 @@ make_spec_test!( Input { src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(), ibs: 512, - output_progress: false, }, Output { dst: Vec::new(), // unused! obs: 512, - conv_table: Some(EBCDIC_TO_ASCII), }, + Some(EBCDIC_TO_ASCII), File::open("./test-resources/gnudd-conv-etoa-seq-byte-values.spec").unwrap() ); @@ -188,13 +239,12 @@ make_spec_test!( Input { src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(), ibs: 512, - output_progress: false, }, Output { dst: Vec::new(), // unused! obs: 512, - conv_table: Some(ASCII_TO_IBM), }, + Some(ASCII_TO_IBM), File::open("./test-resources/gnudd-conv-atoibm-seq-byte-values.spec").unwrap() ); @@ -204,13 +254,12 @@ make_spec_test!( Input { src: File::open("./test-resources/lcase-ascii.test").unwrap(), ibs: 512, - output_progress: false, }, Output { dst: Vec::new(), // unused! obs: 512, - conv_table: Some(LCASE_TO_UCASE), }, + Some(LCASE_TO_UCASE), File::open("./test-resources/ucase-ascii.test").unwrap() ); @@ -220,13 +269,12 @@ make_spec_test!( Input { src: File::open("./test-resources/ucase-ascii.test").unwrap(), ibs: 512, - output_progress: false, }, Output { dst: Vec::new(), // unused! obs: 512, - conv_table: Some(UCASE_TO_LCASE), }, + Some(UCASE_TO_LCASE), File::open("./test-resources/lcase-ascii.test").unwrap() ); @@ -240,16 +288,28 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test() let i = Input { src: File::open("./test-resources/all-valid-ascii-chars-37eff01866ba3f538421b30b7cbefcac.test").unwrap(), ibs: 256, - output_progress: false, }; let o = Output { dst: File::create(&tmp_fname_ae).unwrap(), obs: 1024, - conv_table: Some(ASCII_TO_EBCDIC), }; - dd(i,o).unwrap(); + let opts = Options { + conv: Some(ConversionOptions { + table: Some(ASCII_TO_EBCDIC), + block: false, + unblock: false, + lcase: false, + ucase: false, + sparse: false, + swab: false, + sync: false, + }), + status_level: None, + }; + + dd(i,o,opts).unwrap(); // EBCDIC->ASCII let test_name = "all-valid-ebcdic-to-ascii"; @@ -258,16 +318,28 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test() let i = Input { src: File::open(&tmp_fname_ae).unwrap(), ibs: 256, - output_progress: false, }; let o = Output { dst: File::create(&tmp_fname_ea).unwrap(), obs: 1024, - conv_table: Some(EBCDIC_TO_ASCII), }; - dd(i,o).unwrap(); + let opts = Options { + conv: Some(ConversionOptions { + table: Some(ASCII_TO_EBCDIC), + block: false, + unblock: false, + lcase: false, + ucase: false, + sparse: false, + swab: false, + sync: false, + }), + status_level: None, + }; + + dd(i,o,opts).unwrap(); let res = { let res = File::open(&tmp_fname_ea).unwrap(); @@ -287,43 +359,3 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test() fs::remove_file(&tmp_fname_ae).unwrap(); fs::remove_file(&tmp_fname_ea).unwrap(); } - -// #[test] -// fn copy_zerofile_from_args() -// { -// let spec = File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap(); -// let tmp_fname = format!("./test-resources/{}", "zeros-from-args.test"); -// -// let args = vec![ -// String::from("if=./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test"), -// String::from(&tmp_fname), -// ]; -// let args = Args { args }; -// -// uumain(args); -// -// let res = File::open(&tmp_fname).unwrap(); -// let res = BufReader::new(res); -// -// let spec = BufReader::new(spec); -// -// for (b_res, b_spec) in res.bytes().zip(spec.bytes()) -// { -// assert_eq!(b_res.unwrap(), -// b_spec.unwrap()); -// } -// -// fs::remove_file(&tmp_fname).unwrap(); -// } - -//use rand::prelude::*; -//#[test] -//fn make_test_data() -//{ -// let mut f = File::create("./test-resources/random-walk-through-the-ascii-ranged-forest.test").unwrap(); -// // let mut rng = rand::thread_rng(); - -// for _ in 0..65536 { -// f.write(&[c]).unwrap(); -// } -//} diff --git a/src/uu/dd/test-resources/gnudd-conv-ebcdic-ltou-seq-byte-values.spec b/src/uu/dd/test-resources/gnudd-conv-ebcdic-ltou-seq-byte-values.spec new file mode 100644 index 0000000000000000000000000000000000000000..ed0686639a7ec0d1d4df7e51ef806dd6f76a0e2a GIT binary patch literal 256 zcmZQ%U}n-a*Vkhe<5uP6;pY<+5EinvQ8SX1P`8(rk(Y~dsIJe6t__Iw^@~Z!PW1lx z;q#}jU%r3)`6I5X&L=a}c5AB>BU7X!qJ=_C5 zgM>!owmXl9N(X($g|C3JZ#hN=wSi8Y;TGdVBi&vL?)#J#X%U`KwoXty#Zr&h5-No literal 0 HcmV?d00001 diff --git a/src/uu/dd/test-resources/gnudd-conv-ebcdic-utol-seq-byte-values.spec b/src/uu/dd/test-resources/gnudd-conv-ebcdic-utol-seq-byte-values.spec new file mode 100644 index 0000000000000000000000000000000000000000..13c82e5e3c8500dbc52f6820c5fe57b5ab5e9762 GIT binary patch literal 256 zcmZQ%U}n-a*Vkhe<5uP6;pY<+5EinvQ8SX1P`8(rk(Y~dsIJe6t__Iw^@~Z!PW1lx z;q#}jU%r3)`6I5X&L=;wv8K7HwWYnSvt!c4DU+v7oiTmU%q5GLEnTsE?aI9ma%VMG z;*vkG@`68myrP1#lBkL}o2G`g7N?Fhm!W~Nl&J}anWcrbl?cm2J10jMXE#?5_dw6! zpwN);u*ityq|}u3w9Jgcg5sjmlJc^Kiteu7p8me933F!8o4a8C>Q!EA*00;RVe_V~ sTeff8xnuXPg?skzJALZxne*pv-@1F}{=L_)-oAPN?)R_1fBydi0I5)U0RR91 literal 0 HcmV?d00001