--- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -10,7 +10,7 @@ //usage:#define dd_trivial_usage //usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" -//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") +//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync|swab]") //usage:#define dd_full_usage "\n\n" //usage: "Copy a file with converting and formatting\n" //usage: "\n if=FILE Read from FILE instead of stdin" @@ -30,6 +30,7 @@ //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)," @@ -155,9 +156,10 @@ int dd_main(int argc UNUSED_PARAM, char 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 +169,7 @@ int dd_main(int argc UNUSED_PARAM, char ; #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 +187,11 @@ int dd_main(int argc UNUSED_PARAM, char 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 @@ -207,12 +209,14 @@ int dd_main(int argc UNUSED_PARAM, char struct { int flags; size_t oc; + ssize_t prev_read_size; /* for detecting swab failure */ off_t count; off_t seek, skip; const char *infile, *outfile; } Z; #define flags (Z.flags ) #define oc (Z.oc ) +#define prev_read_size (Z.prev_read_size) #define count (Z.count ) #define seek (Z.seek ) #define skip (Z.skip ) @@ -375,6 +379,27 @@ int dd_main(int argc UNUSED_PARAM, char * conv=noerror just ignores input bad blocks */ n = 0; } + if (flags & FLAG_SWAB) { + uint16_t *p16; + ssize_t n2; + + /* Our code allows only last read to be odd-sized */ + if (prev_read_size & 1) + bb_error_msg_and_die("can't swab %lu byte buffer", + (unsigned long)prev_read_size); + prev_read_size = n; + + /* If n is odd, last byte is not swapped: + * echo -n "qwe" | dd conv=swab + * prints "wqe". + */ + p16 = (void*) ibuf; + n2 = (n >> 1); + while (--n2 >= 0) { + *p16 = bswap_16(*p16); + p16++; + } + } if ((size_t)n == ibs) G.in_full++; else {