[Toybox] [CLEANUP] dd summary() using human_readable().

Rob Landley rob at landley.net
Tue May 6 05:12:30 PDT 2014


In dd summary() is a thing we need to do (whether it's a new
implementation or the old one), so let's look at the old one. The first
question is why is "double seconds" initialized to 5.0, and then
unconditionally overwritten 4 lines later?

It's using a number of global variables outside of the GLOBALS() block,
which I try to avoid. Mostly it's defining several structures grouping
things that don't really need to be grouped (struct iostat).

This uses human_readable(), which is in lib/pending.c (and returning a
pointer to stack space, which is not good), so let's clean that up:

human_readable:

Pass in the buffer to write to, so allocation and lifetime are the
caller's responsibility. (32 bytes is plenty of space. I could actually
trim it with a limit on sprintf, but didn't bother. Biggest 64 bit
unsigned number is 20 bytes + null terminator.)

Hmmm... The name "human readable" doesn't really say what the function
is _doing_. Maybe show_units()? Eh, not realy enough of an improvement.
anything truly descriptive I can think of is too long.

Doing sprintf(buf, "%s", buf) makes me nervous, and you can just skip
past strlen(buf) and not do that.

Comparing against 1024 could produce 4 digit output before the units, is
that really what we want? If we instead compare with 999, 1000 through
1023 show up as 1.0 at the lower level, which would actually be rounding
up since the units would switch over prematurely. Hmmm... Aesthetic
judgement call here.

Maybe the right thing to do is multiply by 1000 and divide by 1024
(first adding 1023 to round up), so we're scaling the part we _show_ to
a decimal range within the given units. Except we don't want to do that
for numbers without a unit, so don't do that if !index...

Except that's not what the gnu/dammit version of dd is doing at all:

  $ dd if=/dev/zero of=/dev/null bs=999136724 count=1
  999136724 bytes (999 MB) copied, 1.81826 s, 550 MB/s
  $ dd if=/dev/zero of=/dev/null bs=1000136724 count=1
  1000136724 bytes (1.0 GB) copied, 1.80374 s, 554 MB/s
  $ dd if=/dev/zero of=/dev/null bs=1 count=1
  1 byte (1 B) copied, 3.2095e-05 s, 31.2 kB/s

They're just cheating and using number of digits. So their "gigabyte" is
a decimal billion bytes. Ok, fine then.

Except... the _other_ user in the tree (well, in my tree) is "du -h",
and _that_ version is doing the crazy "sort of binary, sort of decimal"
can't decide thing. (Possibly this human_readable() was factored out
from there initially? Don't remember...) And that is indeed more or less
what the gnu version is doing. (Hands up everybody surprised that
various gnu utilities are inconsistent?)

Right, unless anybody has a strong objection I think I'm going to redo
human_readable() to do the "actually decimal" thing, _and_ make both dd
and du use it. This means our du -h doesn't match what gnu is producing,
but I'm personally ok with that. (The gnu guys actually implemented
"sort -h" but don't have a standard metric for _producing_ these things.
Sigh.)

I've checked it in. I can revert the du part if anybody cares enough to
speak up for the non-shared code. (What _other_ human_readable use cases
are there? I just spotted the two in the tree at the moment...)

Back to reading the dd posix spec...

Rob

 1399378350.0


More information about the Toybox mailing list