dd: add optional support for status=noxfer/none
No binary (build failed)
—
(log yok)
| @@ -87,44 +87,6 @@ config CUT | |
| cut is used to print selected parts of lines from | |
| each file to stdout. | |
| - | config DD |
| - | bool "dd" |
| - | default y |
| - | help |
| - | dd copies a file (from standard input to standard output, |
| - | by default) using specific input and output blocksizes, |
| - | while optionally performing conversions on it. |
| - | |
| - | config FEATURE_DD_SIGNAL_HANDLING |
| - | bool "Enable DD signal handling for status reporting" |
| - | default y |
| - | depends on DD |
| - | help |
| - | Sending a SIGUSR1 signal to a running `dd' process makes it |
| - | print to standard error the number of records read and written |
| - | so far, then to resume copying. |
| - | |
| - | $ dd if=/dev/zero of=/dev/null& |
| - | $ pid=$! kill -USR1 $pid; sleep 1; kill $pid |
| - | 10899206+0 records in |
| - | 10899206+0 records out |
| - | |
| - | config FEATURE_DD_THIRD_STATUS_LINE |
| - | bool "Enable the third status line upon signal" |
| - | default y |
| - | depends on DD && FEATURE_DD_SIGNAL_HANDLING |
| - | help |
| - | Displays a coreutils-like third status line with transferred bytes, |
| - | elapsed time and speed. |
| - | |
| - | config FEATURE_DD_IBS_OBS |
| - | bool "Enable ibs, obs and conv options" |
| - | default y |
| - | depends on DD |
| - | help |
| - | Enables support for writing a certain number of bytes in and out, |
| - | at a time, and performing conversions on the data stream. |
| - | |
| config DF | |
| bool "df" | |
| default y | |
| @@ -8,6 +8,51 @@ | |
| * Licensed under GPLv2 or later, see file LICENSE in this source tree. | |
| */ | |
| + | //config:config DD |
| + | //config: bool "dd" |
| + | //config: default y |
| + | //config: help |
| + | //config: dd copies a file (from standard input to standard output, |
| + | //config: by default) using specific input and output blocksizes, |
| + | //config: while optionally performing conversions on it. |
| + | //config: |
| + | //config:config FEATURE_DD_SIGNAL_HANDLING |
| + | //config: bool "Enable signal handling for status reporting" |
| + | //config: default y |
| + | //config: depends on DD |
| + | //config: help |
| + | //config: Sending a SIGUSR1 signal to a running `dd' process makes it |
| + | //config: print to standard error the number of records read and written |
| + | //config: so far, then to resume copying. |
| + | //config: |
| + | //config: $ dd if=/dev/zero of=/dev/null & |
| + | //config: $ pid=$!; kill -USR1 $pid; sleep 1; kill $pid |
| + | //config: 10899206+0 records in |
| + | //config: 10899206+0 records out |
| + | //config: |
| + | //config:config FEATURE_DD_THIRD_STATUS_LINE |
| + | //config: bool "Enable the third status line upon signal" |
| + | //config: default y |
| + | //config: depends on DD && FEATURE_DD_SIGNAL_HANDLING |
| + | //config: help |
| + | //config: Displays a coreutils-like third status line with transferred bytes, |
| + | //config: elapsed time and speed. |
| + | //config: |
| + | //config:config FEATURE_DD_IBS_OBS |
| + | //config: bool "Enable ibs, obs and conv options" |
| + | //config: default y |
| + | //config: depends on DD |
| + | //config: help |
| + | //config: Enables support for writing a certain number of bytes in and out, |
| + | //config: at a time, and performing conversions on the data stream. |
| + | //config: |
| + | //config:config FEATURE_DD_STATUS |
| + | //config: bool "Enable status display options" |
| + | //config: default y |
| + | //config: depends on DD |
| + | //config: help |
| + | //config: Enables support for status=noxfer/none option. |
| + | |
| //usage:#define dd_trivial_usage | |
| //usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" | |
| //usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") | |
| @@ -32,8 +77,12 @@ | |
| //usage: "\n conv=fsync Physically write data out before finishing" | |
| //usage: "\n conv=swab Swap every pair of bytes" | |
| //usage: ) | |
| + | //usage: IF_FEATURE_DD_STATUS( |
| + | //usage: "\n status=noxfer Suppress rate output" |
| + | //usage: "\n status=none Suppress all output" |
| + | //usage: ) |
| //usage: "\n" | |
| - | //usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G" |
| + | //usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G" |
| //usage: | |
| //usage:#define dd_example_usage | |
| //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" | |
| @@ -54,13 +103,18 @@ static const struct suffix_mult dd_suffixes[] = { | |
| { "c", 1 }, | |
| { "w", 2 }, | |
| { "b", 512 }, | |
| + | { "kB", 1000 }, |
| { "kD", 1000 }, | |
| { "k", 1024 }, | |
| - | { "K", 1024 }, /* compat with coreutils dd */ |
| + | { "K", 1024 }, /* compat with coreutils dd (it also accepts KB and KD, TODO?) */ |
| + | { "MB", 1000000 }, |
| { "MD", 1000000 }, | |
| - | { "M", 1048576 }, |
| + | { "M", 1024*1024 }, |
| + | { "GB", 1000000000 }, |
| { "GD", 1000000000 }, | |
| - | { "G", 1073741824 }, |
| + | { "G", 1024*1024*1024 }, |
| + | /* "D" suffix for decimal is not in coreutils manpage, looks like it's deprecated */ |
| + | /* coreutils also understands TPEZY suffixes for tera- and so on, with B suffix for decimal */ |
| { "", 0 } | |
| }; | |
| @@ -70,6 +124,7 @@ struct globals { | |
| unsigned long long total_bytes; | |
| unsigned long long begin_time_us; | |
| #endif | |
| + | int flags; |
| } FIX_ALIASING; | |
| #define G (*(struct globals*)&bb_common_bufsiz1) | |
| #define INIT_G() do { \ | |
| @@ -77,6 +132,21 @@ struct globals { | |
| memset(&G, 0, sizeof(G)); \ | |
| } while (0) | |
| + | enum { |
| + | /* Must be in the same order as OP_conv_XXX! */ |
| + | /* (see "flags |= (1 << what)" below) */ |
| + | FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, |
| + | FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, |
| + | FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, |
| + | FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, |
| + | FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, |
| + | /* end of conv flags */ |
| + | FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, |
| + | FLAG_COUNT = 1 << 6, |
| + | FLAG_STATUS = 1 << 7, |
| + | FLAG_STATUS_NONE = 1 << 7, |
| + | FLAG_STATUS_NOXFER = 1 << 8, |
| + | }; |
| static void dd_output_status(int UNUSED_PARAM cur_signal) | |
| { | |
| @@ -93,6 +163,13 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) | |
| G.out_full, G.out_part); | |
| #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE | |
| + | # if ENABLE_FEATURE_DD_STATUS |
| + | if (G.flags & FLAG_STATUS_NOXFER) /* status=noxfer active? */ |
| + | return; |
| + | //TODO: should status=none make dd stop reacting to USR1 entirely? |
| + | //So far we react to it (we print the stats), |
| + | //status=none only suppresses final, non-USR1 generated status message. |
| + | # endif |
| fprintf(stderr, "%llu bytes (%sB) copied, ", | |
| G.total_bytes, | |
| /* show fractional digit, use suffixes */ | |
| @@ -148,20 +225,8 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, | |
| int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int dd_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| - | enum { |
| - | /* Must be in the same order as OP_conv_XXX! */ |
| - | /* (see "flags |= (1 << what)" below) */ |
| - | FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, |
| - | FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, |
| - | FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, |
| - | FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, |
| - | FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, |
| - | /* end of conv flags */ |
| - | FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, |
| - | FLAG_COUNT = 1 << 6, |
| - | }; |
| static const char keywords[] ALIGN1 = | |
| - | "bs\0""count\0""seek\0""skip\0""if\0""of\0" |
| + | "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") |
| #if ENABLE_FEATURE_DD_IBS_OBS | |
| "ibs\0""obs\0""conv\0" | |
| #endif | |
| @@ -169,6 +234,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| #if ENABLE_FEATURE_DD_IBS_OBS | |
| static const char conv_words[] ALIGN1 = | |
| "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; | |
| + | #endif |
| + | #if ENABLE_FEATURE_DD_STATUS |
| + | static const char status_words[] ALIGN1 = |
| + | "none\0""noxfer\0"; |
| #endif | |
| enum { | |
| OP_bs = 0, | |
| @@ -177,6 +246,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| OP_skip, | |
| OP_if, | |
| OP_of, | |
| + | IF_FEATURE_DD_STATUS(OP_status,) |
| #if ENABLE_FEATURE_DD_IBS_OBS | |
| OP_ibs, | |
| OP_obs, | |
| @@ -215,14 +285,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| #endif | |
| /* These are all zeroed at once! */ | |
| struct { | |
| - | int flags; |
| size_t oc; | |
| ssize_t prev_read_size; /* for detecting swab failure */ | |
| off_t count; | |
| off_t seek, skip; | |
| const char *infile, *outfile; | |
| } Z; | |
| - | #define flags (Z.flags ) |
| #define oc (Z.oc ) | |
| #define prev_read_size (Z.prev_read_size) | |
| #define count (Z.count ) | |
| @@ -278,7 +346,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| n = index_in_strings(conv_words, val); | |
| if (n < 0) | |
| bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); | |
| - | flags |= (1 << n); |
| + | G.flags |= (1 << n); |
| if (!arg) /* no ',' left, so this was the last specifier */ | |
| break; | |
| /* *arg = ','; - to preserve ps listing? */ | |
| @@ -294,7 +362,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| } | |
| /* These can be large: */ | |
| if (what == OP_count) { | |
| - | flags |= FLAG_COUNT; |
| + | G.flags |= FLAG_COUNT; |
| count = XATOU_SFX(val, dd_suffixes); | |
| /*continue;*/ | |
| } | |
| @@ -314,6 +382,16 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| outfile = val; | |
| /*continue;*/ | |
| } | |
| + | #if ENABLE_FEATURE_DD_STATUS |
| + | if (what == OP_status) { |
| + | int n; |
| + | n = index_in_strings(status_words, val); |
| + | if (n < 0) |
| + | bb_error_msg_and_die(bb_msg_invalid_arg, val, "status"); |
| + | G.flags |= FLAG_STATUS << n; |
| + | /*continue;*/ |
| + | } |
| + | #endif |
| } /* end of "for (argv[i])" */ | |
| //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever | |
| @@ -321,7 +399,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| obuf = ibuf; | |
| #if ENABLE_FEATURE_DD_IBS_OBS | |
| if (ibs != obs) { | |
| - | flags |= FLAG_TWOBUFS; |
| + | G.flags |= FLAG_TWOBUFS; |
| obuf = xmalloc(obs); | |
| } | |
| #endif | |
| @@ -341,12 +419,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| if (outfile) { | |
| int oflag = O_WRONLY | O_CREAT; | |
| - | if (!seek && !(flags & FLAG_NOTRUNC)) |
| + | if (!seek && !(G.flags & FLAG_NOTRUNC)) |
| oflag |= O_TRUNC; | |
| xmove_fd(xopen(outfile, oflag), ofd); | |
| - | if (seek && !(flags & FLAG_NOTRUNC)) { |
| + | if (seek && !(G.flags & FLAG_NOTRUNC)) { |
| if (ftruncate(ofd, seek * obs) < 0) { | |
| struct stat st; | |
| @@ -377,7 +455,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| goto die_outfile; | |
| } | |
| - | while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { |
| + | while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { |
| ssize_t n; | |
| n = safe_read(ifd, ibuf, ibs); | |
| @@ -385,7 +463,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| break; | |
| if (n < 0) { | |
| /* "Bad block" */ | |
| - | if (!(flags & FLAG_NOERROR)) |
| + | if (!(G.flags & FLAG_NOERROR)) |
| goto die_infile; | |
| bb_simple_perror_msg(infile); | |
| /* GNU dd with conv=noerror skips over bad blocks */ | |
| @@ -394,7 +472,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| * conv=noerror just ignores input bad blocks */ | |
| n = 0; | |
| } | |
| - | if (flags & FLAG_SWAB) { |
| + | if (G.flags & FLAG_SWAB) { |
| uint16_t *p16; | |
| ssize_t n2; | |
| @@ -419,12 +497,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| G.in_full++; | |
| else { | |
| G.in_part++; | |
| - | if (flags & FLAG_SYNC) { |
| + | if (G.flags & FLAG_SYNC) { |
| memset(ibuf + n, 0, ibs - n); | |
| n = ibs; | |
| } | |
| } | |
| - | if (flags & FLAG_TWOBUFS) { |
| + | if (G.flags & FLAG_TWOBUFS) { |
| char *tmp = ibuf; | |
| while (n) { | |
| size_t d = obs - oc; | |
| @@ -446,7 +524,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| goto out_status; | |
| } | |
| - | if (flags & FLAG_FSYNC) { |
| + | if (G.flags & FLAG_FSYNC) { |
| if (fsync(ofd) < 0) | |
| goto die_outfile; | |
| } | |
| @@ -468,11 +546,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) | |
| exitcode = EXIT_SUCCESS; | |
| out_status: | |
| - | dd_output_status(0); |
| + | if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) |
| + | dd_output_status(0); |
| if (ENABLE_FEATURE_CLEAN_UP) { | |
| free(obuf); | |
| - | if (flags & FLAG_TWOBUFS) |
| + | if (G.flags & FLAG_TWOBUFS) |
| free(ibuf); | |
| } | |