From b941316ae5313be523b64f0a9151ee4decb2b35b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 19 Aug 2013 09:01:39 +0200 Subject: [PATCH] dd: support conv=swab function old new delta dd_main 1482 1520 +38 static.conv_words 28 33 +5 packed_usage 29377 29375 -2 Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index 9cb96bb06..1732a5c19 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -30,10 +30,10 @@ //usage: "\n conv=noerror Continue after read errors" //usage: "\n conv=sync Pad blocks with zeros" //usage: "\n conv=fsync Physically write data out before finishing" +//usage: "\n conv=swab Swap every pair of bytes" //usage: ) //usage: "\n" -//usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024)," -//usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)" +//usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G" //usage: //usage:#define dd_example_usage //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" @@ -155,9 +155,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) FLAG_SYNC = 1 << 1, FLAG_NOERROR = 1 << 2, FLAG_FSYNC = 1 << 3, + FLAG_SWAB = 1 << 4, /* end of conv flags */ - FLAG_TWOBUFS = 1 << 4, - FLAG_COUNT = 1 << 5, + FLAG_TWOBUFS = 1 << 5, + FLAG_COUNT = 1 << 6, }; static const char keywords[] ALIGN1 = "bs\0""count\0""seek\0""skip\0""if\0""of\0" @@ -167,7 +168,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) ; #if ENABLE_FEATURE_DD_IBS_OBS static const char conv_words[] ALIGN1 = - "notrunc\0""sync\0""noerror\0""fsync\0"; + "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; #endif enum { OP_bs = 0, @@ -185,11 +186,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv) OP_conv_sync, OP_conv_noerror, OP_conv_fsync, + OP_conv_swab, /* Unimplemented conv=XXX: */ //nocreat do not create the output file //excl fail if the output file already exists //fdatasync physically write output file data before finishing - //swab swap every pair of input bytes //lcase change upper case to lower case //ucase change lower case to upper case //block pad newline-terminated records with spaces to cbs-size @@ -197,6 +198,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) //ascii from EBCDIC to ASCII //ebcdic from ASCII to EBCDIC //ibm from ASCII to alternate EBCDIC + /* Partially implemented: */ + //swab swap every pair of input bytes: will abort on non-even reads #endif }; int exitcode = EXIT_FAILURE; @@ -377,6 +380,20 @@ int dd_main(int argc UNUSED_PARAM, char **argv) * conv=noerror just ignores input bad blocks */ n = 0; } + if (flags & FLAG_SWAB) { + /* If n is odd, last byte is not swapped: + * echo -n "qwe" | dd conv=swab bs=1 + * prints "wqe". + * The code does not handle correctly odd-sized reads + * in the *middle* of the input. FIXME. + */ + uint16_t *p16 = (void*) ibuf; + uint16_t *end = (void*) (ibuf + (n & ~(ssize_t)1)); + while (p16 < end) { + *p16 = bswap_16(*p16); + p16++; + } + } if ((size_t)n == ibs) G.in_full++; else {