diff --git a/lib/compat.c b/lib/compat.c index 513d79b23..71738afe2 100644 --- a/lib/compat.c +++ b/lib/compat.c @@ -173,34 +173,34 @@ char *do_big_num(int64 num, int human_flag, const char *fract) static unsigned int n; char *s; int len, negated; + uint64_t abs_num; if (human_flag && !number_separator) (void)get_number_separator(); n = (n + 1) % (sizeof bufs / sizeof bufs[0]); + abs_num = num < 0 ? 0 - (uint64_t)num : (uint64_t)num; if (human_flag > 1) { - int mult = human_flag == 2 ? 1000 : 1024; - if (num >= mult || num <= -mult) { - double dnum = (double)num / mult; - char units; - if (num < 0) - dnum = -dnum; - if (dnum < mult) - units = 'K'; - else if ((dnum /= mult) < mult) - units = 'M'; - else if ((dnum /= mult) < mult) - units = 'G'; - else if ((dnum /= mult) < mult) - units = 'T'; - else { - dnum /= mult; - units = 'P'; + unsigned int mult = human_flag == 2 ? 1000 : 1024; + + if (abs_num >= mult) { + const char* units = " KMGTPE"; + uint64_t powi = 1; + + for (;;) { + if (abs_num / mult < powi) + break; + + if (units[1] == '\0') + break; + + powi *= mult; + ++units; } - if (num < 0) - dnum = -dnum; - snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); + + snprintf(bufs[n], sizeof bufs[0], "%.2f%c", + (double) num / powi, *units); return bufs[n]; } } diff --git a/rsync.1.md b/rsync.1.md index fdf0b2e95..30bf59d51 100644 --- a/rsync.1.md +++ b/rsync.1.md @@ -3352,9 +3352,9 @@ expand it. digits) by specifying the `--no-human-readable` (`--no-h`) option. The unit letters that are appended in levels 2 and 3 are: `K` (kilo), `M` - (mega), `G` (giga), `T` (tera), or `P` (peta). For example, a 1234567-byte - file would output as 1.23M in level-2 (assuming that a period is your local - decimal point). + (mega), `G` (giga), `T` (tera), `P` (peta) or `E` (exa). For example, a + 1234567-byte file would output as 1.23M in level-2 (assuming that a + period is your local decimal point). Backward compatibility note: versions of rsync prior to 3.1.0 do not support human-readable level 1, and they default to level 0. Thus,