aboutsummaryrefslogtreecommitdiff
path: root/coreutils/dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/dd.c')
-rw-r--r--coreutils/dd.c78
1 files changed, 70 insertions, 8 deletions
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 7a64c3513..f439326fd 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -59,8 +59,13 @@
59//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]" 59//usage: "[if=FILE] [of=FILE] [" IF_FEATURE_DD_IBS_OBS("ibs=N obs=N/") "bs=N] [count=N] [skip=N] [seek=N]"
60//usage: IF_FEATURE_DD_IBS_OBS("\n" 60//usage: IF_FEATURE_DD_IBS_OBS("\n"
61//usage: " [conv=notrunc|noerror|sync|fsync]\n" 61//usage: " [conv=notrunc|noerror|sync|fsync]\n"
62//usage: IF_NOT_PLATFORM_MINGW32(
62//usage: " [iflag=skip_bytes|count_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]" 63//usage: " [iflag=skip_bytes|count_bytes|fullblock|direct] [oflag=seek_bytes|append|direct]"
63//usage: ) 64//usage: )
65//usage: IF_PLATFORM_MINGW32(
66//usage: " [iflag=skip_bytes|count_bytes|fullblock] [oflag=seek_bytes|append]"
67//usage: )
68//usage: )
64//usage:#define dd_full_usage "\n\n" 69//usage:#define dd_full_usage "\n\n"
65//usage: "Copy a file with converting and formatting\n" 70//usage: "Copy a file with converting and formatting\n"
66//usage: "\n if=FILE Read from FILE instead of stdin" 71//usage: "\n if=FILE Read from FILE instead of stdin"
@@ -84,8 +89,10 @@
84//usage: "\n iflag=skip_bytes skip=N is in bytes" 89//usage: "\n iflag=skip_bytes skip=N is in bytes"
85//usage: "\n iflag=count_bytes count=N is in bytes" 90//usage: "\n iflag=count_bytes count=N is in bytes"
86//usage: "\n oflag=seek_bytes seek=N is in bytes" 91//usage: "\n oflag=seek_bytes seek=N is in bytes"
92//usage: IF_NOT_PLATFORM_MINGW32(
87//usage: "\n iflag=direct O_DIRECT input" 93//usage: "\n iflag=direct O_DIRECT input"
88//usage: "\n oflag=direct O_DIRECT output" 94//usage: "\n oflag=direct O_DIRECT output"
95//usage: )
89//usage: "\n iflag=fullblock Read full blocks" 96//usage: "\n iflag=fullblock Read full blocks"
90//usage: "\n oflag=append Open output in append mode" 97//usage: "\n oflag=append Open output in append mode"
91//usage: ) 98//usage: )
@@ -94,6 +101,9 @@
94//usage: "\n status=none Suppress all output" 101//usage: "\n status=none Suppress all output"
95//usage: ) 102//usage: )
96//usage: "\n" 103//usage: "\n"
104//usage: IF_PLATFORM_MINGW32(
105//usage: "\nif=/dev/zero and if=/dev/urandom are supported"
106//usage: )
97//usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G" 107//usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G"
98//usage: 108//usage:
99//usage:#define dd_example_usage 109//usage:#define dd_example_usage
@@ -104,6 +114,10 @@
104#include "libbb.h" 114#include "libbb.h"
105#include "common_bufsiz.h" 115#include "common_bufsiz.h"
106 116
117#if ENABLE_PLATFORM_MINGW32
118# undef O_DIRECT
119#endif
120
107/* This is a NOEXEC applet. Be very careful! */ 121/* This is a NOEXEC applet. Be very careful! */
108 122
109 123
@@ -141,13 +155,13 @@ enum {
141 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, 155 FLAG_SKIP_BYTES = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS,
142 FLAG_COUNT_BYTES = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS, 156 FLAG_COUNT_BYTES = (1 << 6) * ENABLE_FEATURE_DD_IBS_OBS,
143 FLAG_FULLBLOCK = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS, 157 FLAG_FULLBLOCK = (1 << 7) * ENABLE_FEATURE_DD_IBS_OBS,
144 FLAG_IDIRECT = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS, 158 FLAG_IDIRECT = (1 << 8) * ENABLE_FEATURE_DD_IBS_OBS * ENABLE_PLATFORM_POSIX,
145 /* end of input flags */ 159 /* end of input flags */
146 /* start of output flags */ 160 /* start of output flags */
147 FLAG_OFLAG_SHIFT = 9, 161 FLAG_OFLAG_SHIFT = 9,
148 FLAG_SEEK_BYTES = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS, 162 FLAG_SEEK_BYTES = (1 << 9) * ENABLE_FEATURE_DD_IBS_OBS,
149 FLAG_APPEND = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS, 163 FLAG_APPEND = (1 << 10) * ENABLE_FEATURE_DD_IBS_OBS,
150 FLAG_ODIRECT = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS, 164 FLAG_ODIRECT = (1 << 11) * ENABLE_FEATURE_DD_IBS_OBS * ENABLE_PLATFORM_POSIX,
151 /* end of output flags */ 165 /* end of output flags */
152 FLAG_TWOBUFS = (1 << 12) * ENABLE_FEATURE_DD_IBS_OBS, 166 FLAG_TWOBUFS = (1 << 12) * ENABLE_FEATURE_DD_IBS_OBS,
153 FLAG_COUNT = 1 << 13, 167 FLAG_COUNT = 1 << 13,
@@ -220,7 +234,9 @@ static ssize_t dd_read(void *ibuf, size_t ibs)
220 ssize_t n; 234 ssize_t n;
221 235
222#if ENABLE_FEATURE_DD_IBS_OBS 236#if ENABLE_FEATURE_DD_IBS_OBS
237# if !ENABLE_PLATFORM_MINGW32
223 read_again: 238 read_again:
239# endif
224 if (G.flags & FLAG_FULLBLOCK) 240 if (G.flags & FLAG_FULLBLOCK)
225 n = full_read(ifd, ibuf, ibs); 241 n = full_read(ifd, ibuf, ibs);
226 else 242 else
@@ -240,7 +256,9 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
240{ 256{
241 ssize_t n; 257 ssize_t n;
242 258
259#if !ENABLE_PLATFORM_MINGW32
243 IF_FEATURE_DD_IBS_OBS(write_again:) 260 IF_FEATURE_DD_IBS_OBS(write_again:)
261#endif
244 n = full_write(ofd, buf, len); 262 n = full_write(ofd, buf, len);
245#if ENABLE_FEATURE_DD_IBS_OBS 263#if ENABLE_FEATURE_DD_IBS_OBS
246# ifdef O_DIRECT 264# ifdef O_DIRECT
@@ -301,12 +319,25 @@ static int parse_comma_flags(char *val, const char *words, const char *error_in)
301 319
302static void *alloc_buf(size_t size) 320static void *alloc_buf(size_t size)
303{ 321{
322#if !ENABLE_PLATFORM_MINGW32
304 /* Important for "{i,o}flag=direct" - buffers must be page aligned */ 323 /* Important for "{i,o}flag=direct" - buffers must be page aligned */
305 if (size >= bb_getpagesize()) 324 if (size >= bb_getpagesize())
306 return xmmap_anon(size); 325 return xmmap_anon(size);
326#endif
307 return xmalloc(size); 327 return xmalloc(size);
308} 328}
309 329
330#if ENABLE_PLATFORM_MINGW32
331// Does 'path' refer to a physical drive in the win32 device namespace?
332static int is_drive_path(const char *path)
333{
334 char *s = auto_string(strdup(path));
335
336 bs_to_slash(s);
337 return strncasecmp(s, "//./PhysicalDrive", 17) == 0;
338}
339#endif
340
310int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 341int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
311int dd_main(int argc UNUSED_PARAM, char **argv) 342int dd_main(int argc UNUSED_PARAM, char **argv)
312{ 343{
@@ -320,9 +351,9 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
320 static const char conv_words[] ALIGN1 = 351 static const char conv_words[] ALIGN1 =
321 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; 352 "notrunc\0""sync\0""noerror\0""fsync\0""swab\0";
322 static const char iflag_words[] ALIGN1 = 353 static const char iflag_words[] ALIGN1 =
323 "skip_bytes\0""count_bytes\0""fullblock\0""direct\0"; 354 "skip_bytes\0""count_bytes\0""fullblock\0"IF_PLATFORM_POSIX("direct\0");
324 static const char oflag_words[] ALIGN1 = 355 static const char oflag_words[] ALIGN1 =
325 "seek_bytes\0append\0""direct\0"; 356 "seek_bytes\0append\0"IF_PLATFORM_POSIX("direct\0");
326#endif 357#endif
327#if ENABLE_FEATURE_DD_STATUS 358#if ENABLE_FEATURE_DD_STATUS
328 static const char status_words[] ALIGN1 = 359 static const char status_words[] ALIGN1 =
@@ -423,11 +454,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
423#if ENABLE_FEATURE_DD_IBS_OBS 454#if ENABLE_FEATURE_DD_IBS_OBS
424 if (what == OP_ibs) { 455 if (what == OP_ibs) {
425 /* Must fit into positive ssize_t */ 456 /* Must fit into positive ssize_t */
426 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 457 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
427 /*continue;*/ 458 /*continue;*/
428 } 459 }
429 if (what == OP_obs) { 460 if (what == OP_obs) {
430 obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 461 obs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
431 /*continue;*/ 462 /*continue;*/
432 } 463 }
433 if (what == OP_conv) { 464 if (what == OP_conv) {
@@ -444,7 +475,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
444 } 475 }
445#endif 476#endif
446 if (what == OP_bs) { 477 if (what == OP_bs) {
447 ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); 478 ibs = xatoul_range_sfx(val, 1, ULONG_MAX/2, cwbkMG_suffixes);
448 obs = ibs; 479 obs = ibs;
449 /*continue;*/ 480 /*continue;*/
450 } 481 }
@@ -509,7 +540,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
509# endif 540# endif
510 } 541 }
511#endif 542#endif
512 xmove_fd(xopen(infile, iflag), ifd); 543 xmove_fd(MINGW_SPECIAL(xopen)(infile, iflag), ifd);
544#if ENABLE_PLATFORM_MINGW32
545 update_special_fd(get_dev_type(infile), ifd);
546#endif
513 } else { 547 } else {
514 infile = bb_msg_standard_input; 548 infile = bb_msg_standard_input;
515 } 549 }
@@ -529,8 +563,35 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
529# endif 563# endif
530 } 564 }
531#endif 565#endif
566#if ENABLE_PLATFORM_MINGW32
567 if (is_drive_path(outfile)) {
568 // Turn off options not supported by Windows device files.
569 oflag &= ~(O_CREAT | O_TRUNC);
570 }
571#endif
532 xmove_fd(xopen(outfile, oflag), ofd); 572 xmove_fd(xopen(outfile, oflag), ofd);
533 573
574#if ENABLE_PLATFORM_MINGW32
575 {
576 off_t len = (off_t)seek * ((G.flags & FLAG_SEEK_BYTES) ? 1 : obs);
577 struct stat st;
578 int ret = fstat(ofd, &st);
579
580 if (ret == 0 && !(G.flags & FLAG_APPEND) && len > st.st_size)
581 make_sparse(ofd, st.st_size, len);
582
583 if (seek && !(G.flags & FLAG_NOTRUNC)) {
584 if (ftruncate(ofd, len) < 0) {
585 if (ret < 0
586 || S_ISREG(st.st_mode)
587 || S_ISDIR(st.st_mode)
588 ) {
589 goto die_outfile;
590 }
591 }
592 }
593 }
594#else
534 if (seek && !(G.flags & FLAG_NOTRUNC)) { 595 if (seek && !(G.flags & FLAG_NOTRUNC)) {
535 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs; 596 size_t blocksz = (G.flags & FLAG_SEEK_BYTES) ? 1 : obs;
536 if (ftruncate(ofd, seek * blocksz) < 0) { 597 if (ftruncate(ofd, seek * blocksz) < 0) {
@@ -544,6 +605,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
544 } 605 }
545 } 606 }
546 } 607 }
608#endif
547 } else { 609 } else {
548 outfile = bb_msg_standard_output; 610 outfile = bb_msg_standard_output;
549 } 611 }