mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
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.
This commit is contained in:
4
NEWS
4
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.
|
||||
|
||||
@@ -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
|
||||
|
||||
70
src/dd.c
70
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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user