summaryrefslogtreecommitdiffstats
path: root/lib/strutils.c
diff options
context:
space:
mode:
authorDave Reisner2011-02-15 10:06:08 +0100
committerKarel Zak2011-02-15 10:13:31 +0100
commitf9e05dafd0fa36b2cb29eb30250dc63039a34bf2 (patch)
tree8292541ecb2c91f601517f2261960cdd918b164a /lib/strutils.c
parentmore: new usage output, and some trivial fixes (diff)
downloadkernel-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.c18
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 */