Subject: Re: bug#17505: Interface inconsistency, use of intelligent defaults.

From: Pádraig Brady <[email-masked]>
Date: Fri, 16 May 2014 10:37:55 +0100

On 05/16/2014 02:24 AM, Linda Walsh wrote:
> On programs that allow input and output by specifying computer-base2 powers
> of K/M/G  OR decimal based powers of 10,
> 
> If the input units are specified in in powers of 2 then the output should be
> given in the same units.
> 
> Example:
> 
> dd if=/dev/zero of=/dev/null bs=256M count=2
> ... So 512MB, total -... but what do I see:
> 536870912 bytes (537 MB) copied, 0.225718 s, 2.4 GB/s
> 
> Clearly 256*2 != 537.
> 
> At the very least this violates the design principle of 'least surprise'
> and/or 'least astonishment'.

I agree that the units representation is unfortunate,
but an accident of history.
POSIX species 'k' and 'b' to mean 1024 and 512 respectively.
Standards wise 'k' should really mean 1000 and 'K' 1024.
Then extending from that we now have (which we can't change for compat reasons):

  k=K=kiB=KiB=1024
  kb=KB=1000
  M=MiB=1024^2
  MB=1000^2
  ...

However when _outputting) the stats line we could use the
least ambiguous and most standard unit, which would be the IEC unit.
The attached patch changes the output to:

  $ dd if=/dev/zero of=/dev/null bs=256M count=2
  2+0 records in
  2+0 records out
  536870912 bytes (512 MiB) copied, 0.152887 s, 3.3 GiB/s

thanks,
Pádraig.
>From 4daba619de539b3d7cf43196c19e7754df9df98f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email-masked]>
Date: Fri, 16 May 2014 10:32:43 +0100
Subject: [PATCH] dd: output status transfer counts in IEC units

IEC units are the most often used with dd,
and also the least ambiguous representation.

* src/dd.c (human_size): Add from/to block size params so we
can reuse this function for all output size conversions.
(print_stats): Use human_size() in all cases, which will change
the output units from SI to IEC.
Fixes http://bugs.gnu.org/17505
---
 src/dd.c |   18 ++++++------------
 1 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/src/dd.c b/src/dd.c
index 1e387f3..aafbc80 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -653,13 +653,13 @@ Options are:\n\
 }
 
 static char *
-human_size (size_t n)
+human_size (size_t n, uintmax_t from_block_size, uintmax_t to_block_size)
 {
   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);
+  return human_readable (n, hbuf, human_opts, from_block_size, to_block_size);
 }
 
 /* Ensure input buffer IBUF is allocated.  */
@@ -674,7 +674,7 @@ alloc_ibuf (void)
   if (!real_buf)
     error (EXIT_FAILURE, 0,
            _("memory exhausted by input buffer of size %zu bytes (%s)"),
-           input_blocksize, human_size (input_blocksize));
+           input_blocksize, human_size (input_blocksize, 1, 1));
 
   real_buf += SWAB_ALIGN_OFFSET;	/* allow space for swab */
 
@@ -696,7 +696,7 @@ alloc_obuf (void)
       if (!real_obuf)
         error (EXIT_FAILURE, 0,
                _("memory exhausted by output buffer of size %zu bytes (%s)"),
-               output_blocksize, human_size (output_blocksize));
+               output_blocksize, human_size (output_blocksize, 1, 1));
       obuf = ptr_align (real_obuf, page_size);
     }
   else
@@ -734,10 +734,6 @@ multiple_bits_set (int i)
 static void
 print_stats (void)
 {
-  char hbuf[LONGEST_HUMAN_READABLE + 1];
-  int human_opts =
-    (human_autoscale | human_round_to_nearest
-     | human_space_before_unit | human_SI | human_B);
   double delta_s;
   char const *bytes_per_second;
 
@@ -766,8 +762,7 @@ print_stats (void)
            ngettext ("%"PRIuMAX" byte (%s) copied",
                      "%"PRIuMAX" bytes (%s) copied",
                      select_plural (w_bytes)),
-           w_bytes,
-           human_readable (w_bytes, hbuf, human_opts, 1, 1));
+           w_bytes, human_size (w_bytes, 1, 1));
 
   xtime_t now = gethrxtime ();
   if (start_time < now)
@@ -776,8 +771,7 @@ print_stats (void)
       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,
-                                         XTIME_PRECISION, delta_xtime);
+      bytes_per_second = human_size (w_bytes, XTIME_PRECISION, delta_xtime);
     }
   else
     {
-- 
1.7.7.6