aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/Config.in11
-rw-r--r--coreutils/dd.c62
2 files changed, 66 insertions, 7 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index 2d745e260..fa35241f4 100644
--- a/coreutils/Config.in
+++ b/coreutils/Config.in
@@ -127,7 +127,16 @@ config FEATURE_DD_SIGNAL_HANDLING
$ dd if=/dev/zero of=/dev/null&
$ pid=$! kill -USR1 $pid; sleep 1; kill $pid
- 10899206+0 records in 10899206+0 records out
+ 10899206+0 records in
+ 10899206+0 records out
+
+config FEATURE_DD_THIRD_STATUS_LINE
+ bool "Enable the third status line upon signal"
+ default n
+ 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"
diff --git a/coreutils/dd.c b/coreutils/dd.c
index c5c9476af..768a12995 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -34,6 +34,10 @@ static const struct suffix_mult dd_suffixes[] = {
struct globals {
off_t out_full, out_part, in_full, in_part;
+#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
+ unsigned long long total_bytes;
+ unsigned long long begin_time_us;
+#endif
};
#define G (*(struct globals*)&bb_common_bufsiz1)
#define INIT_G() do { \
@@ -44,11 +48,50 @@ struct globals {
static void dd_output_status(int UNUSED_PARAM cur_signal)
{
+#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
+ unsigned long long total;
+ unsigned long long diff_scaled;
+ unsigned long long diff_us = monotonic_us(); /* before fprintf */
+#endif
+
/* Deliberately using %u, not %d */
fprintf(stderr, "%"OFF_FMT"u+%"OFF_FMT"u records in\n"
"%"OFF_FMT"u+%"OFF_FMT"u records out\n",
G.in_full, G.in_part,
G.out_full, G.out_part);
+
+#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
+ fprintf(stderr, "%llu bytes (%sB) copied, ",
+ G.total_bytes,
+ /* show fractional digit, use suffixes */
+ make_human_readable_str(G.total_bytes, 1, 0)
+ );
+ /* Corner cases:
+ * ./busybox dd </dev/null >/dev/null
+ * ./busybox dd bs=1M count=2000 </dev/zero >/dev/null
+ * (echo DONE) | ./busybox dd >/dev/null
+ * (sleep 1; echo DONE) | ./busybox dd >/dev/null
+ */
+ diff_us -= G.begin_time_us;
+ /* We need to calculate "(total * 1M) / usec" without overflow.
+ * this would work too, but is bigger than integer code below.
+ * total = G.total_bytes * (double)(1024 * 1024) / (diff_us ? diff_us : 1);
+ */
+ diff_scaled = diff_us;
+ total = G.total_bytes;
+ while (total > MAXINT(unsigned long long) / (1024 * 1024)) {
+ total >>= 1;
+ diff_scaled >>= 1;
+ }
+ total *= (1024 * 1024);
+ if (diff_scaled > 1)
+ total /= diff_scaled;
+ fprintf(stderr, "%f seconds, %sB/s\n",
+ diff_us / 1000000.0,
+ /* show fractional digit, use suffixes */
+ make_human_readable_str(total, 1, 0)
+ );
+#endif
}
static ssize_t full_write_or_warn(const void *buf, size_t len,
@@ -70,13 +113,16 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs,
G.out_full++;
else if (n) /* > 0 */
G.out_part++;
+#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
+ G.total_bytes += n;
+#endif
return 0;
}
#if ENABLE_LFS
-#define XATOU_SFX xatoull_sfx
+# define XATOU_SFX xatoull_sfx
#else
-#define XATOU_SFX xatoul_sfx
+# define XATOU_SFX xatoul_sfx
#endif
int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -157,10 +203,6 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
INIT_G();
//fflush(NULL); - is this needed because of NOEXEC?
-#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
- signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status);
-#endif
-
for (n = 1; argv[n]; n++) {
int what;
char *val;
@@ -246,6 +288,14 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
flags |= FLAG_TWOBUFS;
obuf = xmalloc(obs);
}
+
+#if ENABLE_FEATURE_DD_SIGNAL_HANDLING
+ signal_SA_RESTART_empty_mask(SIGUSR1, dd_output_status);
+#endif
+#if ENABLE_FEATURE_DD_THIRD_STATUS_LINE
+ G.begin_time_us = monotonic_us();
+#endif
+
if (infile != NULL)
xmove_fd(xopen(infile, O_RDONLY), ifd);
else {