diff options
author | Dave Reisner | 2011-02-15 10:06:08 +0100 |
---|---|---|
committer | Karel Zak | 2011-02-15 10:13:31 +0100 |
commit | f9e05dafd0fa36b2cb29eb30250dc63039a34bf2 (patch) | |
tree | 8292541ecb2c91f601517f2261960cdd918b164a /lib/strutils.c | |
parent | more: new usage output, and some trivial fixes (diff) | |
download | kernel-qcow2-util-linux-f9e05dafd0fa36b2cb29eb30250dc63039a34bf2.tar.gz kernel-qcow2-util-linux-f9e05dafd0fa36b2cb29eb30250dc63039a34bf2.tar.xz kernel-qcow2-util-linux-f9e05dafd0fa36b2cb29eb30250dc63039a34bf2.zip |
lib: [strutils] avoid integer overflow on large values
This is visible on a 2TB disk via lsblk, where a large partition
incorrectly displays as 1.171798692T instead of 1.8T. This is
corrected by using a uint64_t type instead of a simple int --
consistant with the type used in lsblk.c to represent the raw size in
bytes.
[kzak@redhat.com: - add EiB support
- add size_to_human_string() to regression tests]
Signed-off-by: Dave Reisner <d@falconindy.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/strutils.c')
-rw-r--r-- | lib/strutils.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/lib/strutils.c b/lib/strutils.c index 8089fbe8b..39c9bdf02 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -245,8 +245,9 @@ static int get_exp(uint64_t n) char *size_to_human_string(uint64_t bytes) { char buf[32]; - int dec, frac, exp; - const char *letters = "BKMGTP"; + int dec, exp; + uint64_t frac; + const char *letters = "BKMGTPE"; char c; exp = get_exp(bytes); @@ -254,6 +255,10 @@ char *size_to_human_string(uint64_t bytes) dec = exp ? bytes / (1ULL << exp) : bytes; frac = exp ? bytes % (1ULL << exp) : 0; + /* fprintf(stderr, "exp: %d, c: %c, dec: %d, frac: %jd\n", + * exp, c, dec, frac); + */ + if (frac) { /* round */ frac = (frac / (1ULL << (exp - 10)) + 50) / 100; @@ -267,7 +272,7 @@ char *size_to_human_string(uint64_t bytes) if (!dp || !*dp) dp = "."; - snprintf(buf, sizeof(buf), "%d%s%d%c", dec, dp, frac, c); + snprintf(buf, sizeof(buf), "%d%s%jd%c", dec, dp, frac, c); } else snprintf(buf, sizeof(buf), "%d%c", dec, c); @@ -280,6 +285,7 @@ char *size_to_human_string(uint64_t bytes) int main(int argc, char *argv[]) { uintmax_t size = 0; + char *hum; if (argc < 2) { fprintf(stderr, "usage: %s <number>[suffix]\n", argv[0]); @@ -289,7 +295,11 @@ int main(int argc, char *argv[]) if (strtosize(argv[1], &size)) errx(EXIT_FAILURE, "invalid size '%s' value", argv[1]); - printf("%25s : %20ju\n", argv[1], size); + hum = size_to_human_string(size); + + printf("%25s : %20ju : %8s\n", argv[1], size, hum); + free(hum); + return EXIT_FAILURE; } #endif /* TEST_PROGRAM */ |