diff options
Diffstat (limited to 'coreutils/dd.c')
| -rw-r--r-- | coreutils/dd.c | 78 |
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 | ||
| 302 | static void *alloc_buf(size_t size) | 320 | static 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? | ||
| 332 | static 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 | |||
| 310 | int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 341 | int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 311 | int dd_main(int argc UNUSED_PARAM, char **argv) | 342 | int 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 | } |
