diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2015-12-31 11:43:09 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2015-12-31 11:49:55 -0800 |
commit | 8f9bf300174afa9b29027542ec59892f610c08e4 (patch) | |
tree | 349c787e6aec9ae9dc1447936897da5e44320683 | |
parent | 26323928d9b045c29c02028bf30823ead0b0be75 (diff) | |
download | coreutils-8f9bf300174afa9b29027542ec59892f610c08e4.tar.xz |
dd: summarize in --human-readable format too
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.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/coreutils.texi | 22 | ||||
-rw-r--r-- | src/dd.c | 70 | ||||
-rwxr-xr-x | tests/dd/reblock.sh | 4 | ||||
-rwxr-xr-x | tests/dd/stats.sh | 6 |
5 files changed, 63 insertions, 43 deletions
@@ -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. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 64419c769..8eb2a3e1e 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -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 @@ -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 diff --git a/tests/dd/reblock.sh b/tests/dd/reblock.sh index cd9d94205..d950b39f4 100755 --- a/tests/dd/reblock.sh +++ b/tests/dd/reblock.sh @@ -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 diff --git a/tests/dd/stats.sh b/tests/dd/stats.sh index da2c2d25f..f2cbef94b 100755 --- a/tests/dd/stats.sh +++ b/tests/dd/stats.sh @@ -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; } |