summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2004-11-15 06:49:59 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2004-11-15 06:49:59 +0000
commit7d8f8967f3b1216508bc40237a93bd88894143f2 (patch)
tree807ec1d4be1cdacab0b64537e801c12cf75aad11
parentc7169d726fc3c68ce7c1425192d9643af4108098 (diff)
downloadcoreutils-7d8f8967f3b1216508bc40237a93bd88894143f2.tar.xz
Include "human.h".
(w_bytes, start_time): New vars. (usage): Document new I/O statistics output (print_stats): Output new I/O statistics. (cleanup): Do statistics after closing stdin and stdout, so that the times are more accurate. (write_output, dd_copy): Count output bytes. (main): Get initial value of clock.
-rw-r--r--src/dd.c66
1 files changed, 59 insertions, 7 deletions
diff --git a/src/dd.c b/src/dd.c
index 879a88e33..19014a752 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -30,6 +30,7 @@
#include "error.h"
#include "full-write.h"
#include "getpagesize.h"
+#include "human.h"
#include "inttostr.h"
#include "long-options.h"
#include "quote.h"
@@ -140,6 +141,12 @@ static uintmax_t r_partial = 0;
/* Number of full blocks read. */
static uintmax_t r_full = 0;
+/* Number of bytes written. */
+static uintmax_t w_bytes = 0;
+
+/* Time that dd started. */
+static struct timespec start_time;
+
/* True if input is seekable. */
static bool input_seekable;
@@ -402,14 +409,14 @@ Each FLAG symbol may be:\n\
fputs (_(" nofollow do not follow symlinks\n"), stdout);
fputs (_("\
\n\
-Note that sending a SIGUSR1 signal to a running `dd' process makes it\n\
-print to standard error the number of records read and written so far,\n\
-then to resume copying.\n\
+Sending a SIGUSR1 signal to a running `dd' process makes it\n\
+print I/O statistics to standard error, then to resume copying.\n\
\n\
$ dd if=/dev/zero of=/dev/null& pid=$!\n\
$ kill -USR1 $pid; sleep 1; kill $pid\n\
- 10899206+0 records in\n\
- 10899206+0 records out\n\
+ 10807656+0 records in\n\
+ 10807656+0 records out\n\
+ 5.5GB copied in 20.8225s (266MB/s)\n\
\n\
Options are:\n\
\n\
@@ -442,7 +449,16 @@ multiple_bits_set (int i)
static void
print_stats (void)
{
- char buf[2][INT_BUFSIZE_BOUND (uintmax_t)];
+ char buf[2][MAX (INT_BUFSIZE_BOUND (uintmax_t), LONGEST_HUMAN_READABLE + 1)];
+ struct timespec now;
+ int human_opts =
+ human_autoscale | human_round_to_nearest | human_SI | human_B;
+ uintmax_t start_sec = start_time.tv_sec;
+ enum { BILLION = 1000000000 };
+ double delta_s;
+ char const *bytes_per_second;
+
+ gettime (&now);
fprintf (stderr, _("%s+%s records in\n"),
umaxtostr (r_full, buf[0]), umaxtostr (r_partial, buf[1]));
fprintf (stderr, _("%s+%s records out\n"),
@@ -455,18 +471,49 @@ print_stats (void)
? _("truncated record")
: _("truncated records")));
}
+
+ /* Use integer arithmetic to compute the transfer rate if possible,
+ since that makes it easy to use SI abbreviations; otherwise, fall
+ back on floating-point without abbreviations. */
+
+ if ((start_time.tv_sec < now.tv_sec
+ || (start_time.tv_sec == now.tv_sec
+ && start_time.tv_nsec < now.tv_nsec))
+ && now.tv_sec - start_sec < UINTMAX_MAX / BILLION)
+ {
+ uintmax_t delta_ns = (BILLION * (now.tv_sec - start_sec)
+ + now.tv_nsec - start_time.tv_nsec);
+ delta_s = delta_ns / 1e9;
+ bytes_per_second = human_readable (w_bytes, buf[1], human_opts,
+ BILLION, delta_ns);
+ }
+ else
+ {
+ delta_s = now.tv_sec;
+ delta_s -= start_time.tv_sec;
+ delta_s += 1e-9 * (now.tv_nsec - start_time.tv_nsec);
+ if (0 < delta_s)
+ sprintf (buf[1], "%gB", w_bytes / delta_s);
+ else
+ sprintf (buf[1], "%s B", _("Infinity"));
+ bytes_per_second = buf[1];
+ }
+
+ fprintf (stderr, _("%s copied in %gs (%s/s)\n"),
+ human_readable (w_bytes, buf[0], human_opts, 1, 1),
+ delta_s, bytes_per_second);
}
static void
cleanup (void)
{
- print_stats ();
if (close (STDIN_FILENO) < 0)
error (EXIT_FAILURE, errno,
_("closing input file %s"), quote (input_file));
if (close (STDOUT_FILENO) < 0)
error (EXIT_FAILURE, errno,
_("closing output file %s"), quote (output_file));
+ print_stats ();
}
static inline void
@@ -548,6 +595,7 @@ static void
write_output (void)
{
size_t nwritten = full_write (STDOUT_FILENO, obuf, output_blocksize);
+ w_bytes += nwritten;
if (nwritten != output_blocksize)
{
error (0, errno, _("writing to %s"), quote (output_file));
@@ -1238,6 +1286,7 @@ dd_copy (void)
if (ibuf == obuf) /* If not C_TWOBUFS. */
{
size_t nwritten = full_write (STDOUT_FILENO, obuf, n_bytes_read);
+ w_bytes += nwritten;
if (nwritten != n_bytes_read)
{
error (0, errno, _("writing %s"), quote (output_file));
@@ -1297,6 +1346,7 @@ dd_copy (void)
if (oc != 0)
{
size_t nwritten = full_write (STDOUT_FILENO, obuf, oc);
+ w_bytes += nwritten;
if (nwritten != 0)
w_partial++;
if (nwritten != oc)
@@ -1450,6 +1500,8 @@ main (int argc, char **argv)
install_handler (SIGPIPE, interrupt_handler);
install_handler (SIGINFO, siginfo_handler);
+ gettime (&start_time);
+
exit_status = dd_copy ();
quit (exit_status);