summaryrefslogtreecommitdiff
path: root/utils.c
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.cz>2014-08-30 15:27:00 -0300
committerDavid Sterba <dsterba@suse.cz>2014-10-10 18:58:28 +0200
commit0b90a24e11484548801a30a6ad4bbafc0b3d682f (patch)
tree37583cda03a1fba56928a4d2a109c6709a41297c /utils.c
parentf404c1ab6cc4cbfa67037cc530714f582127f326 (diff)
btrfs-progs: add options to tune units for fi df output
The size unit format is a longstanding annoyance. This patch is based on the work of Nils and Alexandre and enhances the options. It's possible to select raw bytes, SI-based or IEC-based compact units (human frientdly) or a fixed base from kilobytes to terabytes. The default is compact human readable IEC-based, no change to current version. CC: Nils Steinger <nst@voidptr.de> CC: Alexandre Oliva <oliva@gnu.org> Reviewed-by: Hugo Mills <hugo@carfax.org.uk> Signed-off-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/utils.c b/utils.c
index bdb73999..e86292ac 100644
--- a/utils.c
+++ b/utils.c
@@ -1297,35 +1297,38 @@ out:
static const char* unit_suffix_binary[] =
{ "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"};
static const char* unit_suffix_decimal[] =
- { "B", "KB", "MB", "GB", "TB", "PB", "EB"};
+ { "B", "kB", "mB", "gB", "tB", "pB", "eB"};
-int pretty_size_snprintf(u64 size, char *str, size_t str_size, int unit_mode)
+int pretty_size_snprintf(u64 size, char *str, size_t str_size, unsigned unit_mode)
{
int num_divs;
float fraction;
- int base = 0;
+ u64 base = 0;
+ int mult = 0;
const char** suffix = NULL;
u64 last_size;
if (str_size == 0)
return 0;
- if (unit_mode == UNITS_RAW) {
+ if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_RAW) {
snprintf(str, str_size, "%llu", size);
return 0;
}
- if (unit_mode == UNITS_BINARY) {
+ if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_BINARY) {
base = 1024;
+ mult = 1024;
suffix = unit_suffix_binary;
- } else if (unit_mode == UNITS_DECIMAL) {
+ } else if ((unit_mode & ~UNITS_MODE_MASK) == UNITS_DECIMAL) {
base = 1000;
+ mult = 1000;
suffix = unit_suffix_decimal;
}
/* Unknown mode */
if (!base) {
- fprintf(stderr, "INTERNAL ERROR: unknown unit base, mode %d",
+ fprintf(stderr, "INTERNAL ERROR: unknown unit base, mode %d\n",
unit_mode);
assert(0);
return -1;
@@ -1333,11 +1336,22 @@ int pretty_size_snprintf(u64 size, char *str, size_t str_size, int unit_mode)
num_divs = 0;
last_size = size;
-
- while (size >= base) {
- last_size = size;
- size /= base;
- num_divs++;
+ switch (unit_mode & UNITS_MODE_MASK) {
+ case UNITS_TBYTES: base *= mult; num_divs++;
+ case UNITS_GBYTES: base *= mult; num_divs++;
+ case UNITS_MBYTES: base *= mult; num_divs++;
+ case UNITS_KBYTES: num_divs++;
+ break;
+ case UNITS_BYTES:
+ base = 1;
+ num_divs = 0;
+ break;
+ default:
+ while (size >= mult) {
+ last_size = size;
+ size /= mult;
+ num_divs++;
+ }
}
if (num_divs >= ARRAY_SIZE(unit_suffix_binary)) {
@@ -2377,3 +2391,17 @@ int test_isdir(const char *path)
return S_ISDIR(st.st_mode);
}
+
+void units_set_mode(unsigned *units, unsigned mode)
+{
+ unsigned base = *units & UNITS_MODE_MASK;
+
+ *units = base | mode;
+}
+
+void units_set_base(unsigned *units, unsigned base)
+{
+ unsigned mode = *units & ~UNITS_MODE_MASK;
+
+ *units = base | mode;
+}