]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
dd: summarize in --human-readable format too
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 31 Dec 2015 19:43:09 +0000 (11:43 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 31 Dec 2015 19:49:55 +0000 (11:49 -0800)
Problem reported by Linda Walsh in: http://bugs.gnu.org/17505
* NEWS: Document this.
* doc/coreutils.texi (dd invocation): Use a simpler script.
Adjust output example to match new behavior.
* src/dd.c (human_size): Remove.
All uses changed to use human_readable and ...
(human_opts): ... this new constant.
(abbreviation_lacks_prefix): New function.
(print_xfer_stats): Use it.  Output both --si and --human-readable
summaries, but only if they have prefixes.
* tests/dd/reblock.sh, tests/dd/stats.sh: Test new behavior.

NEWS
doc/coreutils.texi
src/dd.c
tests/dd/reblock.sh
tests/dd/stats.sh

diff --git a/NEWS b/NEWS
index 5080f0f4edba9fced32071045757ddf86782756a..ae8d9e0bef08ea6a228733f4938a3ec7bb6bd973 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -29,6 +29,10 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** New features
 
+  dd now summarizes sizes in --human-readable format too, not just --si.
+  E.g., "3441325000 bytes (3.4 GB, 3.2 GiB) copied".  It omits the summaries
+  if they would not provide useful information, e.g., "3 bytes copied".
+
   md5sum now supports the --ignore-missing option to allow
   verifying a subset of files given a larger list of checksums.
   This also affects sha1sum, sha224sum, sha256sum, sha384sum and sha512sum.
index 64419c769208adbaea9114c27c96238cc6238268..8eb2a3e1e8a60f720b23d4ae08bc9d54951deb98 100644 (file)
@@ -8835,23 +8835,23 @@ trap '' USR1
 # which can be triggered by reception of signals.
 dd iflag=fullblock if=/dev/zero of=/dev/null count=5000000 bs=1000 & pid=$!
 
-# Output stats every half second
-until ! kill -s USR1 $pid 2>/dev/null; do sleep .5; done
+# Output stats every second.
+while kill -s USR1 $pid 2>/dev/null; do sleep 1; done
 @end example
 
-The above script will output in the following format
+The above script will output in the following format:
 
 @example
-859+0 records in
-859+0 records out
-4295000000 bytes (4.3 GB) copied, 0.539934 s, 8.0 GB/s
-1000+0 records in
-1000+0 records out
-5000000000 bytes (5.0 GB) copied, 0.630785 s, 7.9 GB/s
+3441325+0 records in
+3441325+0 records out
+3441325000 bytes (3.4 GB, 3.2 GiB) copied, 1.00036 s, 3.4 GB/s
+5000000+0 records in
+5000000+0 records out
+5000000000 bytes (5.0 GB, 4.7 GiB) copied, 1.44433 s, 3.5 GB/s
 @end example
 
-Note also the @samp{status=progress} option which periodically updates
-the last line of the transfer statistics above.
+The @samp{status=progress} option periodically updates the last line
+of the transfer statistics above.
 
 @vindex POSIXLY_CORRECT
 On systems lacking the @samp{INFO} signal @command{dd} responds to the
index a5557a85b470be852230398c6376c277132af375..4a247759745ea0a4dd93d3ec7bfdbced60f27c58 100644 (file)
--- a/src/dd.c
+++ b/src/dd.c
@@ -673,15 +673,10 @@ Options are:\n\
   exit (status);
 }
 
-static char *
-human_size (size_t n)
-{
-  static char hbuf[LONGEST_HUMAN_READABLE + 1];
-  int human_opts =
-    (human_autoscale | human_round_to_nearest | human_base_1024
-     | human_space_before_unit | human_SI | human_B);
-  return human_readable (n, hbuf, human_opts, 1, 1);
-}
+/* Common options to use when displaying sizes and rates.  */
+
+enum { human_opts = (human_autoscale | human_round_to_nearest
+                     | human_space_before_unit | human_SI | human_B) };
 
 /* Ensure input buffer IBUF is allocated.  */
 
@@ -693,9 +688,15 @@ alloc_ibuf (void)
 
   char *real_buf = malloc (input_blocksize + INPUT_BLOCK_SLOP);
   if (!real_buf)
-    error (EXIT_FAILURE, 0,
-           _("memory exhausted by input buffer of size %"PRIuMAX" bytes (%s)"),
-           (uintmax_t) input_blocksize, human_size (input_blocksize));
+    {
+      uintmax_t ibs = input_blocksize;
+      char hbuf[LONGEST_HUMAN_READABLE + 1];
+      error (EXIT_FAILURE, 0,
+             _("memory exhausted by input buffer of size %"PRIuMAX" bytes (%s)"),
+             ibs,
+             human_readable (input_blocksize, hbuf,
+                             human_opts | human_base_1024, 1, 1));
+    }
 
   real_buf += SWAB_ALIGN_OFFSET;       /* allow space for swab */
 
@@ -715,10 +716,16 @@ alloc_obuf (void)
       /* Page-align the output buffer, too.  */
       char *real_obuf = malloc (output_blocksize + OUTPUT_BLOCK_SLOP);
       if (!real_obuf)
-        error (EXIT_FAILURE, 0,
-               _("memory exhausted by output buffer of size %"PRIuMAX
-                 " bytes (%s)"),
-               (uintmax_t) output_blocksize, human_size (output_blocksize));
+        {
+          uintmax_t obs = output_blocksize;
+          char hbuf[LONGEST_HUMAN_READABLE + 1];
+          error (EXIT_FAILURE, 0,
+                 _("memory exhausted by output buffer of size %"PRIuMAX
+                   " bytes (%s)"),
+                 obs,
+                 human_readable (output_blocksize, hbuf,
+                                 human_opts | human_base_1024, 1, 1));
+        }
       obuf = ptr_align (real_obuf, page_size);
     }
   else
@@ -746,17 +753,23 @@ multiple_bits_set (int i)
   return MULTIPLE_BITS_SET (i);
 }
 
+static bool
+abbreviation_lacks_prefix (char const *message)
+{
+  return message[strlen (message) - 2] == ' ';
+}
+
 /* Print transfer statistics.  */
 
 static void
-print_xfer_stats (xtime_t progress_time) {
-  char hbuf[LONGEST_HUMAN_READABLE + 1];
-  int human_opts =
-    (human_autoscale | human_round_to_nearest
-     | human_space_before_unit | human_SI | human_B);
+print_xfer_stats (xtime_t progress_time)
+{
+  char hbuf[2][LONGEST_HUMAN_READABLE + 1];
   double delta_s;
   char const *bytes_per_second;
-
+  char const *si = human_readable (w_bytes, hbuf[0], human_opts, 1, 1);
+  char const *iec = human_readable (w_bytes, hbuf[1],
+                                    human_opts | human_base_1024, 1, 1);
   if (progress_time)
     fputc ('\r', stderr);
 
@@ -764,11 +777,14 @@ print_xfer_stats (xtime_t progress_time) {
      since that makes it easy to use SI abbreviations.  */
 
   fprintf (stderr,
-           ngettext ("%"PRIuMAX" byte (%s) copied",
-                     "%"PRIuMAX" bytes (%s) copied",
+           ngettext ("%"PRIuMAX" byte copied",
+                     (abbreviation_lacks_prefix (si)
+                      ? "%"PRIuMAX" bytes copied"
+                      : abbreviation_lacks_prefix (iec)
+                      ? "%"PRIuMAX" bytes (%s) copied"
+                      : "%"PRIuMAX" bytes (%s, %s) copied"),
                      select_plural (w_bytes)),
-           w_bytes,
-           human_readable (w_bytes, hbuf, human_opts, 1, 1));
+           w_bytes, si, iec);
 
   xtime_t now = progress_time ? progress_time : gethrxtime ();
 
@@ -778,7 +794,7 @@ print_xfer_stats (xtime_t progress_time) {
       uintmax_t delta_xtime = now;
       delta_xtime -= start_time;
       delta_s = delta_xtime / XTIME_PRECISIONe0;
-      bytes_per_second = human_readable (w_bytes, hbuf, human_opts,
+      bytes_per_second = human_readable (w_bytes, hbuf[0], human_opts,
                                          XTIME_PRECISION, delta_xtime);
     }
   else
index cd9d94205d5d3ba6eb699f6e4f9ec2b6c4ca7d1c..d950b39f4eded784c344f8cdf67e2e99c90a517f 100755 (executable)
@@ -23,14 +23,14 @@ print_ver_ dd
 cat <<\EOF > exp-reblock || framework_failure_
 0+2 records in
 1+1 records out
-4 bytes (4 B) copied
+4 bytes copied
 EOF
 
 # 2 short reads -> 2 partial writes
 cat <<\EOF > exp-no-reblock || framework_failure_
 0+2 records in
 0+2 records out
-4 bytes (4 B) copied
+4 bytes copied
 EOF
 
 
index da2c2d25ff6f426f9acdb4406c8deb35b7bfa7d8..f2cbef94b5f5a11726483f74f698860ef6d6f01f 100755 (executable)
@@ -60,14 +60,14 @@ for open in '' '1'; do
   wait
 
   # Ensure all data processed and at least last status written
-  grep '250000000 bytes .* copied' err || { cat err; fail=1; }
+  grep '250000000 bytes (250 MB, 238 MiB) copied' err || { cat err; fail=1; }
 done
 
 progress_output()
 {
   { sleep "$1"; echo 1; } | dd bs=1 status=progress of=/dev/null 2>err
-  # Progress output should be for "byte ... copied", while final is "bytes ..."
-  grep 'byte .* copied' err
+  # Progress output should be for "byte copied", while final is "bytes ..."
+  grep 'byte copied' err
 }
 retry_delay_ progress_output 1 4 || { cat err; fail=1; }