summaryrefslogtreecommitdiffstats
path: root/lib/strutils.c
diff options
context:
space:
mode:
authorDavidlohr Bueso2010-12-09 21:54:17 +0100
committerKarel Zak2010-12-09 21:54:17 +0100
commitc4ecaf21d59671ac7ec0bd26bd2c346c98c7771c (patch)
treecd89a4e8048653d693b7d9f4a1507479d1ad7314 /lib/strutils.c
parentmount: be more explicit about --move in mount.8 (diff)
downloadkernel-qcow2-util-linux-c4ecaf21d59671ac7ec0bd26bd2c346c98c7771c.tar.gz
kernel-qcow2-util-linux-c4ecaf21d59671ac7ec0bd26bd2c346c98c7771c.tar.xz
kernel-qcow2-util-linux-c4ecaf21d59671ac7ec0bd26bd2c346c98c7771c.zip
partx: complete rewrite
Co-Author: Karel Zak <kzak@redhat.com> Signed-off-by: Davidlohr Bueso <dave@gnu.org> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/strutils.c')
-rw-r--r--lib/strutils.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/strutils.c b/lib/strutils.c
index dcae9f2d3..e8e868653 100644
--- a/lib/strutils.c
+++ b/lib/strutils.c
@@ -3,12 +3,15 @@
* Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org>
*/
+#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <ctype.h>
#include <errno.h>
#include <err.h>
#include <sys/stat.h>
+#include <locale.h>
+#include <string.h>
static int do_scale_by_power (uintmax_t *x, int base, int power)
{
@@ -224,3 +227,49 @@ void strmode(mode_t mode, char *str)
: (mode & S_IXOTH ? 'x' : '-'));
str[10] = '\0';
}
+
+/*
+ * returns exponent (2^x=n) in range KiB..PiB
+ */
+static int get_exp(uint64_t n)
+{
+ int shft;
+
+ for (shft = 10; shft <= 60; shft += 10) {
+ if (n < (1ULL << shft))
+ break;
+ }
+ return shft - 10;
+}
+
+char *size_to_human_string(uint64_t bytes)
+{
+ char buf[32];
+ int dec, frac, exp;
+ const char *letters = "BKMGTP";
+ char c;
+
+ exp = get_exp(bytes);
+ c = *(letters + (exp ? exp / 10 : 0));
+ dec = exp ? bytes / (1ULL << exp) : bytes;
+ frac = exp ? bytes % (1ULL << exp) : 0;
+
+ if (frac) {
+ /* round */
+ frac = (frac / (1ULL << (exp - 10)) + 50) / 100;
+ if (frac == 10)
+ dec++, frac = 0;
+ }
+
+ if (frac) {
+ struct lconv const *l = localeconv();
+ char *dp = l ? l->decimal_point : NULL;
+
+ if (!dp || !*dp)
+ dp = ".";
+ snprintf(buf, sizeof(buf), "%d%s%d%c", dec, dp, frac, c);
+ } else
+ snprintf(buf, sizeof(buf), "%d%c", dec, c);
+
+ return strdup(buf);
+}