aboutsummaryrefslogtreecommitdiff
path: root/coreutils/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/dd.c')
-rw-r--r--coreutils/dd.c65
1 files changed, 43 insertions, 22 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c
index d29357dae..d73f6224b 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -37,7 +37,7 @@
37//config: elapsed time and speed. 37//config: elapsed time and speed.
38//config: 38//config:
39//config:config FEATURE_DD_IBS_OBS 39//config:config FEATURE_DD_IBS_OBS
40//config: bool "Enable ibs, obs, iflag and conv options" 40//config: bool "Enable ibs, obs, iflag, oflag and conv options"
41//config: default y 41//config: default y
42//config: depends on DD 42//config: depends on DD
43//config: help 43//config: help
@@ -56,8 +56,11 @@
56//kbuild:lib-$(CONFIG_DD) += dd.o 56//kbuild:lib-$(CONFIG_DD) += dd.o
57 57
58//usage:#define dd_trivial_usage 58//usage:#define dd_trivial_usage
59//usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" 59//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]\n"
60//usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync] [iflag=skip_bytes|fullblock]") 60//usage: IF_FEATURE_DD_IBS_OBS(
61//usage: " [conv=notrunc|noerror|sync|fsync]\n"
62//usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes]"
63//usage: )
61//usage:#define dd_full_usage "\n\n" 64//usage:#define dd_full_usage "\n\n"
62//usage: "Copy a file with converting and formatting\n" 65//usage: "Copy a file with converting and formatting\n"
63//usage: "\n if=FILE Read from FILE instead of stdin" 66//usage: "\n if=FILE Read from FILE instead of stdin"
@@ -80,6 +83,7 @@
80//usage: "\n conv=swab Swap every pair of bytes" 83//usage: "\n conv=swab Swap every pair of bytes"
81//usage: "\n iflag=skip_bytes skip=N is in bytes" 84//usage: "\n iflag=skip_bytes skip=N is in bytes"
82//usage: "\n iflag=fullblock Read full blocks" 85//usage: "\n iflag=fullblock Read full blocks"
86//usage: "\n oflag=seek_bytes seek=N is in bytes"
83//usage: ) 87//usage: )
84//usage: IF_FEATURE_DD_STATUS( 88//usage: IF_FEATURE_DD_STATUS(
85//usage: "\n status=noxfer Suppress rate output" 89//usage: "\n status=noxfer Suppress rate output"
@@ -136,10 +140,14 @@ enum {
136 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 140 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
137 FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, 141 FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
138 /* end of input flags */ 142 /* end of input flags */
139 FLAG_TWOBUFS = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, 143 /* start of output flags */
140 FLAG_COUNT = 1 << 8, 144 FLAG_OFLAG_SHIFT = 7,
141 FLAG_STATUS_NONE = 1 << 9, 145 FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
142 FLAG_STATUS_NOXFER = 1 << 10, 146 /* end of output flags */
147 FLAG_TWOBUFS = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
148 FLAG_COUNT = 1 << 9,
149 FLAG_STATUS_NONE = 1 << 10,
150 FLAG_STATUS_NOXFER = 1 << 11,
143}; 151};
144 152
145static void dd_output_status(int UNUSED_PARAM cur_signal) 153static void dd_output_status(int UNUSED_PARAM cur_signal)
@@ -253,7 +261,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
253 static const char keywords[] ALIGN1 = 261 static const char keywords[] ALIGN1 =
254 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") 262 "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0")
255#if ENABLE_FEATURE_DD_IBS_OBS 263#if ENABLE_FEATURE_DD_IBS_OBS
256 "ibs\0""obs\0""conv\0""iflag\0" 264 "ibs\0""obs\0""conv\0""iflag\0""oflag\0"
257#endif 265#endif
258 ; 266 ;
259#if ENABLE_FEATURE_DD_IBS_OBS 267#if ENABLE_FEATURE_DD_IBS_OBS
@@ -261,6 +269,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
261 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 269 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
262 static const char iflag_words[] ALIGN1 = 270 static const char iflag_words[] ALIGN1 =
263 "skip_bytes\0""fullblock\0"; 271 "skip_bytes\0""fullblock\0";
272 static const char oflag_words[] ALIGN1 =
273 "seek_bytes\0";
264#endif 274#endif
265#if ENABLE_FEATURE_DD_STATUS 275#if ENABLE_FEATURE_DD_STATUS
266 static const char status_words[] ALIGN1 = 276 static const char status_words[] ALIGN1 =
@@ -279,6 +289,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
279 OP_obs, 289 OP_obs,
280 OP_conv, 290 OP_conv,
281 OP_iflag, 291 OP_iflag,
292 OP_oflag,
282 /* Must be in the same order as FLAG_XXX! */ 293 /* Must be in the same order as FLAG_XXX! */
283 OP_conv_notrunc = 0, 294 OP_conv_notrunc = 0,
284 OP_conv_sync, 295 OP_conv_sync,
@@ -300,6 +311,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
300 //swab swap every pair of input bytes: will abort on non-even reads 311 //swab swap every pair of input bytes: will abort on non-even reads
301 OP_iflag_skip_bytes, 312 OP_iflag_skip_bytes,
302 OP_iflag_fullblock, 313 OP_iflag_fullblock,
314 OP_oflag_seek_bytes,
303#endif 315#endif
304 }; 316 };
305 smallint exitcode = EXIT_FAILURE; 317 smallint exitcode = EXIT_FAILURE;
@@ -315,13 +327,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
315#endif 327#endif
316 /* These are all zeroed at once! */ 328 /* These are all zeroed at once! */
317 struct { 329 struct {
318 size_t oc; 330 IF_FEATURE_DD_IBS_OBS(size_t ocount;)
319 ssize_t prev_read_size; /* for detecting swab failure */ 331 ssize_t prev_read_size; /* for detecting swab failure */
320 off_t count; 332 off_t count;
321 off_t seek, skip; 333 off_t seek, skip;
322 const char *infile, *outfile; 334 const char *infile, *outfile;
323 } Z; 335 } Z;
324#define oc (Z.oc ) 336#define ocount (Z.ocount )
325#define prev_read_size (Z.prev_read_size) 337#define prev_read_size (Z.prev_read_size)
326#define count (Z.count ) 338#define count (Z.count )
327#define seek (Z.seek ) 339#define seek (Z.seek )
@@ -371,6 +383,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
371 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT; 383 G.flags |= parse_comma_flags(val, iflag_words, "iflag") << FLAG_IFLAG_SHIFT;
372 /*continue;*/ 384 /*continue;*/
373 } 385 }
386 if (what == OP_oflag) {
387 G.flags |= parse_comma_flags(val, oflag_words, "oflag") << FLAG_OFLAG_SHIFT;
388 /*continue;*/
389 }
374#endif 390#endif
375 if (what == OP_bs) { 391 if (what == OP_bs) {
376 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes); 392 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
@@ -447,7 +463,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
447 xmove_fd(xopen(outfile, oflag), ofd); 463 xmove_fd(xopen(outfile, oflag), ofd);
448 464
449 if (seek && !(G.flags & FLAG_NOTRUNC)) { 465 if (seek && !(G.flags & FLAG_NOTRUNC)) {
450 if (ftruncate(ofd, seek * obs) < 0) { 466 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
467 if (ftruncate(ofd, seek * blocksz) < 0) {
451 struct stat st; 468 struct stat st;
452 469
453 if (fstat(ofd, &st) < 0 470 if (fstat(ofd, &st) < 0
@@ -480,7 +497,8 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
480 } 497 }
481 } 498 }
482 if (seek) { 499 if (seek) {
483 if (lseek(ofd, seek * obs, SEEK_CUR) < 0) 500 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
501 if (lseek(ofd, seek * blocksz, SEEK_CUR) < 0)
484 goto die_outfile; 502 goto die_outfile;
485 } 503 }
486 504
@@ -536,24 +554,26 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
536 n = ibs; 554 n = ibs;
537 } 555 }
538 } 556 }
557#if ENABLE_FEATURE_DD_IBS_OBS
539 if (G.flags & FLAG_TWOBUFS) { 558 if (G.flags & FLAG_TWOBUFS) {
540 char *tmp = ibuf; 559 char *tmp = ibuf;
541 while (n) { 560 while (n) {
542 size_t d = obs - oc; 561 size_t d = obs - ocount;
543
544 if (d > (size_t)n) 562 if (d > (size_t)n)
545 d = n; 563 d = n;
546 memcpy(obuf + oc, tmp, d); 564 memcpy(obuf + ocount, tmp, d);
547 n -= d; 565 n -= d;
548 tmp += d; 566 tmp += d;
549 oc += d; 567 ocount += d;
550 if (oc == obs) { 568 if (ocount == obs) {
551 if (write_and_stats(obuf, obs, obs, outfile)) 569 if (write_and_stats(obuf, obs, obs, outfile))
552 goto out_status; 570 goto out_status;
553 oc = 0; 571 ocount = 0;
554 } 572 }
555 } 573 }
556 } else { 574 } else
575#endif
576 {
557 if (write_and_stats(ibuf, n, obs, outfile)) 577 if (write_and_stats(ibuf, n, obs, outfile))
558 goto out_status; 578 goto out_status;
559 } 579 }
@@ -564,11 +584,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
564 goto die_outfile; 584 goto die_outfile;
565 } 585 }
566 586
567 if (ENABLE_FEATURE_DD_IBS_OBS && oc) { 587#if ENABLE_FEATURE_DD_IBS_OBS
568 if (write_and_stats(obuf, oc, obs, outfile)) 588 if (ocount != 0) {
589 if (write_and_stats(obuf, ocount, obs, outfile))
569 goto out_status; 590 goto out_status;
570 } 591 }
571 592#endif
572 if (close(ifd) < 0) { 593 if (close(ifd) < 0) {
573 die_infile: 594 die_infile:
574 bb_simple_perror_msg_and_die(infile); 595 bb_simple_perror_msg_and_die(infile);