diff options
-rw-r--r-- | coreutils/dd.c | 29 |
1 files 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 @@ | |||
30 | //usage: "\n conv=noerror Continue after read errors" | 30 | //usage: "\n conv=noerror Continue after read errors" |
31 | //usage: "\n conv=sync Pad blocks with zeros" | 31 | //usage: "\n conv=sync Pad blocks with zeros" |
32 | //usage: "\n conv=fsync Physically write data out before finishing" | 32 | //usage: "\n conv=fsync Physically write data out before finishing" |
33 | //usage: "\n conv=swab Swap every pair of bytes" | ||
33 | //usage: ) | 34 | //usage: ) |
34 | //usage: "\n" | 35 | //usage: "\n" |
35 | //usage: "\nNumbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024)," | 36 | //usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G" |
36 | //usage: "\nMD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)" | ||
37 | //usage: | 37 | //usage: |
38 | //usage:#define dd_example_usage | 38 | //usage:#define dd_example_usage |
39 | //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" | 39 | //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) | |||
155 | FLAG_SYNC = 1 << 1, | 155 | FLAG_SYNC = 1 << 1, |
156 | FLAG_NOERROR = 1 << 2, | 156 | FLAG_NOERROR = 1 << 2, |
157 | FLAG_FSYNC = 1 << 3, | 157 | FLAG_FSYNC = 1 << 3, |
158 | FLAG_SWAB = 1 << 4, | ||
158 | /* end of conv flags */ | 159 | /* end of conv flags */ |
159 | FLAG_TWOBUFS = 1 << 4, | 160 | FLAG_TWOBUFS = 1 << 5, |
160 | FLAG_COUNT = 1 << 5, | 161 | FLAG_COUNT = 1 << 6, |
161 | }; | 162 | }; |
162 | static const char keywords[] ALIGN1 = | 163 | static const char keywords[] ALIGN1 = |
163 | "bs\0""count\0""seek\0""skip\0""if\0""of\0" | 164 | "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) | |||
167 | ; | 168 | ; |
168 | #if ENABLE_FEATURE_DD_IBS_OBS | 169 | #if ENABLE_FEATURE_DD_IBS_OBS |
169 | static const char conv_words[] ALIGN1 = | 170 | static const char conv_words[] ALIGN1 = |
170 | "notrunc\0""sync\0""noerror\0""fsync\0"; | 171 | "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; |
171 | #endif | 172 | #endif |
172 | enum { | 173 | enum { |
173 | OP_bs = 0, | 174 | OP_bs = 0, |
@@ -185,11 +186,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
185 | OP_conv_sync, | 186 | OP_conv_sync, |
186 | OP_conv_noerror, | 187 | OP_conv_noerror, |
187 | OP_conv_fsync, | 188 | OP_conv_fsync, |
189 | OP_conv_swab, | ||
188 | /* Unimplemented conv=XXX: */ | 190 | /* Unimplemented conv=XXX: */ |
189 | //nocreat do not create the output file | 191 | //nocreat do not create the output file |
190 | //excl fail if the output file already exists | 192 | //excl fail if the output file already exists |
191 | //fdatasync physically write output file data before finishing | 193 | //fdatasync physically write output file data before finishing |
192 | //swab swap every pair of input bytes | ||
193 | //lcase change upper case to lower case | 194 | //lcase change upper case to lower case |
194 | //ucase change lower case to upper case | 195 | //ucase change lower case to upper case |
195 | //block pad newline-terminated records with spaces to cbs-size | 196 | //block pad newline-terminated records with spaces to cbs-size |
@@ -197,6 +198,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
197 | //ascii from EBCDIC to ASCII | 198 | //ascii from EBCDIC to ASCII |
198 | //ebcdic from ASCII to EBCDIC | 199 | //ebcdic from ASCII to EBCDIC |
199 | //ibm from ASCII to alternate EBCDIC | 200 | //ibm from ASCII to alternate EBCDIC |
201 | /* Partially implemented: */ | ||
202 | //swab swap every pair of input bytes: will abort on non-even reads | ||
200 | #endif | 203 | #endif |
201 | }; | 204 | }; |
202 | int exitcode = EXIT_FAILURE; | 205 | int exitcode = EXIT_FAILURE; |
@@ -377,6 +380,20 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |||
377 | * conv=noerror just ignores input bad blocks */ | 380 | * conv=noerror just ignores input bad blocks */ |
378 | n = 0; | 381 | n = 0; |
379 | } | 382 | } |
383 | if (flags & FLAG_SWAB) { | ||
384 | /* If n is odd, last byte is not swapped: | ||
385 | * echo -n "qwe" | dd conv=swab bs=1 | ||
386 | * prints "wqe". | ||
387 | * The code does not handle correctly odd-sized reads | ||
388 | * in the *middle* of the input. FIXME. | ||
389 | */ | ||
390 | uint16_t *p16 = (void*) ibuf; | ||
391 | uint16_t *end = (void*) (ibuf + (n & ~(ssize_t)1)); | ||
392 | while (p16 < end) { | ||
393 | *p16 = bswap_16(*p16); | ||
394 | p16++; | ||
395 | } | ||
396 | } | ||
380 | if ((size_t)n == ibs) | 397 | if ((size_t)n == ibs) |
381 | G.in_full++; | 398 | G.in_full++; |
382 | else { | 399 | else { |