aboutsummaryrefslogtreecommitdiff
path: root/coreutils/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/dd.c')
-rw-r--r--coreutils/dd.c116
1 files changed, 83 insertions, 33 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 042355e24..c150ef5bc 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -59,7 +59,7 @@
59//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=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: IF_FEATURE_DD_IBS_OBS( 60//usage: IF_FEATURE_DD_IBS_OBS(
61//usage: " [conv=notrunc|noerror|sync|fsync]\n" 61//usage: " [conv=notrunc|noerror|sync|fsync]\n"
62//usage: " [iflag=skip_bytes|fullblock] [oflag=seek_bytes|append]" 62//usage: " [iflag=skip_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]"
63//usage: ) 63//usage: )
64//usage:#define dd_full_usage "\n\n" 64//usage:#define dd_full_usage "\n\n"
65//usage: "Copy a file with converting and formatting\n" 65//usage: "Copy a file with converting and formatting\n"
@@ -82,9 +82,11 @@
82//usage: "\n conv=fsync Physically write data out before finishing" 82//usage: "\n conv=fsync Physically write data out before finishing"
83//usage: "\n conv=swab Swap every pair of bytes" 83//usage: "\n conv=swab Swap every pair of bytes"
84//usage: "\n iflag=skip_bytes skip=N is in bytes" 84//usage: "\n iflag=skip_bytes skip=N is in bytes"
85//usage: "\n iflag=fullblock Read full blocks"
86//usage: "\n oflag=seek_bytes seek=N is in bytes" 85//usage: "\n oflag=seek_bytes seek=N is in bytes"
87//usage: "\n oflag=append Open output file in append mode" 86//usage: "\n iflag=direct O_DIRECT input"
87//usage: "\n oflag=direct O_DIRECT output"
88//usage: "\n iflag=fullblock Read full blocks"
89//usage: "\n oflag=append Open output in append mode"
88//usage: ) 90//usage: )
89//usage: IF_FEATURE_DD_STATUS( 91//usage: IF_FEATURE_DD_STATUS(
90//usage: "\n status=noxfer Suppress rate output" 92//usage: "\n status=noxfer Suppress rate output"
@@ -140,16 +142,18 @@ enum {
140 FLAG_IFLAG_SHIFT = 5, 142 FLAG_IFLAG_SHIFT = 5,
141 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 143 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
142 FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, 144 FLAG_FULLBLOCK = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
145 FLAG_IDIRECT = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
143 /* end of input flags */ 146 /* end of input flags */
144 /* start of output flags */ 147 /* start of output flags */
145 FLAG_OFLAG_SHIFT = 7, 148 FLAG_OFLAG_SHIFT = 8,
146 FLAG_SEEK_BYTES = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, 149 FLAG_SEEK_BYTES = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS,
147 FLAG_APPEND = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, 150 FLAG_APPEND = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS,
151 FLAG_ODIRECT = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS,
148 /* end of output flags */ 152 /* end of output flags */
149 FLAG_TWOBUFS = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, 153 FLAG_TWOBUFS = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS,
150 FLAG_COUNT = 1 << 10, 154 FLAG_COUNT = 1 << 12,
151 FLAG_STATUS_NONE = 1 << 11, 155 FLAG_STATUS_NONE = 1 << 13,
152 FLAG_STATUS_NOXFER = 1 << 12, 156 FLAG_STATUS_NOXFER = 1 << 14,
153}; 157};
154 158
155static void dd_output_status(int UNUSED_PARAM cur_signal) 159static void dd_output_status(int UNUSED_PARAM cur_signal)
@@ -195,12 +199,50 @@ static void dd_output_status(int UNUSED_PARAM cur_signal)
195#endif 199#endif
196} 200}
197 201
202#if ENABLE_FEATURE_DD_IBS_OBS
203static int clear_O_DIRECT(int fd)
204{
205 if (errno == EINVAL) {
206 int fl = fcntl(fd, F_GETFL);
207 if (fl & O_DIRECT) {
208 fcntl(fd, F_SETFL, fl & ~O_DIRECT);
209 return 1;
210 }
211 }
212 return 0;
213}
214#endif
215
216static ssize_t dd_read(void *ibuf, size_t ibs)
217{
218 ssize_t n;
219
220#if ENABLE_FEATURE_DD_IBS_OBS
221 read_again:
222 if (G.flags & FLAG_FULLBLOCK)
223 n = full_read(ifd, ibuf, ibs);
224 else
225#endif
226 n = safe_read(ifd, ibuf, ibs);
227#if ENABLE_FEATURE_DD_IBS_OBS
228 if (n < 0 && (G.flags & FLAG_IDIRECT) && clear_O_DIRECT(ifd))
229 goto read_again;
230#endif
231 return n;
232}
233
198static bool write_and_stats(const void *buf, size_t len, size_t obs, 234static bool write_and_stats(const void *buf, size_t len, size_t obs,
199 const char *filename) 235 const char *filename)
200{ 236{
201 ssize_t n; 237 ssize_t n;
202 238
239 IF_FEATURE_DD_IBS_OBS(write_again:)
203 n = full_write(ofd, buf, len); 240 n = full_write(ofd, buf, len);
241#if ENABLE_FEATURE_DD_IBS_OBS
242 if (n < 0 && (G.flags & FLAG_ODIRECT) && clear_O_DIRECT(ofd))
243 goto write_again;
244#endif
245
204#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE 246#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
205 if (n > 0) 247 if (n > 0)
206 G.total_bytes += n; 248 G.total_bytes += n;
@@ -257,6 +299,16 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in)
257} 299}
258#endif 300#endif
259 301
302static void *alloc_buf(size_t size)
303{
304#if !ENABLE_PLATFORM_MINGW32
305 /* Important for "{i,o}flag=direct" - buffers must be page aligned */
306 if (size >= bb_getpagesize())
307 return xmmap_anon(size);
308#endif
309 return xmalloc(size);
310}
311
260int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 312int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
261int dd_main(int argc UNUSED_PARAM, char **argv) 313int dd_main(int argc UNUSED_PARAM, char **argv)
262{ 314{
@@ -270,9 +322,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
270 static const char conv_words[] ALIGN1 = 322 static const char conv_words[] ALIGN1 =
271 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 323 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
272 static const char iflag_words[] ALIGN1 = 324 static const char iflag_words[] ALIGN1 =
273 "skip_bytes\0""fullblock\0"; 325 "skip_bytes\0""fullblock\0""direct\0";
274 static const char oflag_words[] ALIGN1 = 326 static const char oflag_words[] ALIGN1 =
275 "seek_bytes\0append\0"; 327 "seek_bytes\0append\0""direct\0";
276#endif 328#endif
277#if ENABLE_FEATURE_DD_STATUS 329#if ENABLE_FEATURE_DD_STATUS
278 static const char status_words[] ALIGN1 = 330 static const char status_words[] ALIGN1 =
@@ -313,7 +365,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
313 //swab swap every pair of input bytes: will abort on non-even reads 365 //swab swap every pair of input bytes: will abort on non-even reads
314 OP_iflag_skip_bytes, 366 OP_iflag_skip_bytes,
315 OP_iflag_fullblock, 367 OP_iflag_fullblock,
368 OP_iflag_direct,
316 OP_oflag_seek_bytes, 369 OP_oflag_seek_bytes,
370 OP_oflag_direct,
317#endif 371#endif
318 }; 372 };
319 smallint exitcode = EXIT_FAILURE; 373 smallint exitcode = EXIT_FAILURE;
@@ -429,13 +483,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
429#endif 483#endif
430 } /* end of "for (argv[i])" */ 484 } /* end of "for (argv[i])" */
431 485
432//XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever 486 ibuf = alloc_buf(ibs);
433 ibuf = xmalloc(ibs);
434 obuf = ibuf; 487 obuf = ibuf;
435#if ENABLE_FEATURE_DD_IBS_OBS 488#if ENABLE_FEATURE_DD_IBS_OBS
436 if (ibs != obs) { 489 if (ibs != obs) {
437 G.flags |= FLAG_TWOBUFS; 490 G.flags |= FLAG_TWOBUFS;
438 obuf = xmalloc(obs); 491 obuf = alloc_buf(obs);
439 } 492 }
440#endif 493#endif
441 494
@@ -447,10 +500,15 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
447#endif 500#endif
448 501
449 if (infile) { 502 if (infile) {
503 int iflag = O_RDONLY;
504#if ENABLE_FEATURE_DD_IBS_OBS
505 if (G.flags & FLAG_IDIRECT)
506 iflag |= O_DIRECT;
507#endif
450#if !ENABLE_PLATFORM_MINGW32 508#if !ENABLE_PLATFORM_MINGW32
451 xmove_fd(xopen(infile, O_RDONLY), ifd); 509 xmove_fd(xopen(infile, iflag), ifd);
452#else 510#else
453 xmove_fd(mingw_xopen(infile, O_RDONLY), ifd); 511 xmove_fd(mingw_xopen(infile, iflag), ifd);
454 update_dev_fd(get_dev_type(infile), ifd); 512 update_dev_fd(get_dev_type(infile), ifd);
455#endif 513#endif
456 } else { 514 } else {
@@ -463,7 +521,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
463 oflag |= O_TRUNC; 521 oflag |= O_TRUNC;
464 if (G.flags & FLAG_APPEND) 522 if (G.flags & FLAG_APPEND)
465 oflag |= O_APPEND; 523 oflag |= O_APPEND;
466 524#if ENABLE_FEATURE_DD_IBS_OBS
525 if (G.flags & FLAG_ODIRECT)
526 oflag |= O_DIRECT;
527#endif
467 xmove_fd(xopen(outfile, oflag), ofd); 528 xmove_fd(xopen(outfile, oflag), ofd);
468 529
469#if ENABLE_PLATFORM_MINGW32 530#if ENABLE_PLATFORM_MINGW32
@@ -508,13 +569,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
508 size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs; 569 size_t blocksz = (G.flags & FLAG_SKIP_BYTES) ? 1 : ibs;
509 if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) { 570 if (lseek(ifd, skip * blocksz, SEEK_CUR) < 0) {
510 do { 571 do {
511 ssize_t n; 572 ssize_t n = dd_read(ibuf, blocksz);
512#if ENABLE_FEATURE_DD_IBS_OBS
513 if (G.flags & FLAG_FULLBLOCK)
514 n = full_read(ifd, ibuf, blocksz);
515 else
516#endif
517 n = safe_read(ifd, ibuf, blocksz);
518 if (n < 0) 573 if (n < 0)
519 goto die_infile; 574 goto die_infile;
520 if (n == 0) 575 if (n == 0)
@@ -529,14 +584,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
529 } 584 }
530 585
531 while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { 586 while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) {
532 ssize_t n; 587 ssize_t n = dd_read(ibuf, ibs);
533
534#if ENABLE_FEATURE_DD_IBS_OBS
535 if (G.flags & FLAG_FULLBLOCK)
536 n = full_read(ifd, ibuf, ibs);
537 else
538#endif
539 n = safe_read(ifd, ibuf, ibs);
540 if (n == 0) 588 if (n == 0)
541 break; 589 break;
542 if (n < 0) { 590 if (n < 0) {
@@ -631,11 +679,13 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
631 if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) 679 if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE))
632 dd_output_status(0); 680 dd_output_status(0);
633 681
682#if 0 /* can't just free(), they can be mmap()ed */
634 if (ENABLE_FEATURE_CLEAN_UP) { 683 if (ENABLE_FEATURE_CLEAN_UP) {
635 free(obuf); 684 free(obuf);
636 if (G.flags & FLAG_TWOBUFS) 685 if (G.flags & FLAG_TWOBUFS)
637 free(ibuf); 686 free(ibuf);
638 } 687 }
688#endif
639 689
640 return exitcode; 690 return exitcode;
641} 691}