aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comet.conf2
-rw-r--r--src/blocks/fs.c45
-rw-r--r--src/format.c4
-rw-r--r--src/format.h4
-rw-r--r--src/util.c108
-rw-r--r--src/util.h15
6 files changed, 107 insertions, 71 deletions
diff --git a/comet.conf b/comet.conf
index d1fc212..31bde13 100644
--- a/comet.conf
+++ b/comet.conf
@@ -52,7 +52,7 @@
[block.disk]
type = fs
- text = SSD %{used} / %{total} -- %{free-percentage}
+ text = SSD %{used-si} / %{total} -- %{free-percentage}
color = #18baf2
text-color = #fff
path = /
diff --git a/src/blocks/fs.c b/src/blocks/fs.c
index 7163cc5..a0e1133 100644
--- a/src/blocks/fs.c
+++ b/src/blocks/fs.c
@@ -25,10 +25,26 @@ typedef enum {
FS_USED_PERC,
} block_fs_mark_t;
+#define FS_SHIFT 12
+
+static const format_pair_t block_fs_units[] = {
+ { "-si", UNIT_SI << FS_SHIFT },
+ { "-b", UNIT_B << FS_SHIFT },
+ { "-kib", UNIT_KB << FS_SHIFT },
+ { "-mib", UNIT_MB << FS_SHIFT },
+ { "-gib", UNIT_GB << FS_SHIFT },
+ { "-tib", UNIT_TB << FS_SHIFT },
+ { "-kb", (UNIT_KB | UNIT_SI) << FS_SHIFT },
+ { "-mb", (UNIT_MB | UNIT_SI) << FS_SHIFT },
+ { "-gb", (UNIT_GB | UNIT_SI) << FS_SHIFT },
+ { "-tb", (UNIT_TB | UNIT_SI) << FS_SHIFT },
+ { NULL },
+};
+
static const format_option_t block_fs_options[] = {
- { { "total", FS_TOTAL } },
- { { "free", FS_FREE } },
- { { "used", FS_USED } },
+ { { "total", FS_TOTAL }, .suffixes = block_fs_units },
+ { { "free", FS_FREE }, .suffixes = block_fs_units },
+ { { "used", FS_USED }, .suffixes = block_fs_units },
{ { "free-percentage", FS_FREE_PERC } },
{ { "used-percentage", FS_USED_PERC } },
{ { NULL } },
@@ -45,13 +61,19 @@ static void block_fs_update(block_t *block)
struct statvfs sbuf;
if (statvfs(fs->path, &sbuf) < 0) {
- log_value_debug("Failed to read filesystem",
+ log_value_debug("Failed to read filesystem info",
"s:label", block->label,
"s:path", fs->path,
"i:errno", errno);
return;
}
+ uint64_t total = sbuf.f_bsize * sbuf.f_blocks;
+ uint64_t available = sbuf.f_bsize * sbuf.f_bavail;
+ uint64_t used = sbuf.f_bsize * (sbuf.f_blocks - sbuf.f_bavail);
+ uint64_t free_perc = (100 * sbuf.f_bavail) / sbuf.f_blocks;
+ uint64_t used_perc = (100 * (sbuf.f_blocks - sbuf.f_bavail)) / sbuf.f_blocks;
+
char buffer[256] = { 0 };
size_t start = 0, size = sizeof(buffer);
@@ -59,28 +81,31 @@ static void block_fs_update(block_t *block)
size_t rest = start >= size ? 0 : size - start;
if (rest == 0) break;
- switch (fs->format.parts[i].mark) {
+ unit_t mask = UNIT_MASK << FS_SHIFT;
+ unit_t unit = (fs->format.parts[i].mark & mask) >> FS_SHIFT;
+
+ switch (fs->format.parts[i].mark & ~mask) {
case FS_STRING:
start += snprintf(buffer + start, rest, "%s", fs->format.parts[i].string);
break;
case FS_TOTAL:
- start += snprintf(buffer + start, rest, "%ld", sbuf.f_bsize * (uint64_t)sbuf.f_blocks);
+ start += snprintf_units(buffer + start, rest, total, unit);
break;
case FS_FREE:
- start += snprintf(buffer + start, rest, "%ld", sbuf.f_bsize * (uint64_t)sbuf.f_bavail);
+ start += snprintf_units(buffer + start, rest, available, unit);
break;
case FS_USED:
- start += snprintf(buffer + start, rest, "%ld", sbuf.f_bsize * (sbuf.f_blocks - sbuf.f_bavail));
+ start += snprintf_units(buffer + start, rest, used, unit);
break;
case FS_FREE_PERC:
- start += snprintf(buffer + start, rest, "%ld", (100 * sbuf.f_bavail) / sbuf.f_blocks);
+ start += snprintf(buffer + start, rest, "%ld", free_perc);
break;
case FS_USED_PERC:
- start += snprintf(buffer + start, rest, "%ld", (100 * (sbuf.f_blocks - sbuf.f_bavail)) / sbuf.f_blocks);
+ start += snprintf(buffer + start, rest, "%ld", used_perc);
break;
default:
diff --git a/src/format.c b/src/format.c
index 0f25084..73d645e 100644
--- a/src/format.c
+++ b/src/format.c
@@ -94,7 +94,7 @@ static bool format_option_match(format_pair_t *part, const format_option_t *opti
format_mark_t mark = 0;
size_t off = 0, tmp = 0;
- for (format_pair_t *ps = option->prefixes; ps != NULL && ps->string != NULL; ps++) {
+ for (const format_pair_t *ps = option->prefixes; ps != NULL && ps->string != NULL; ps++) {
tmp = format_option_cmp(part->string, ps->string);
if (tmp != 0) {
off += tmp;
@@ -108,7 +108,7 @@ static bool format_option_match(format_pair_t *part, const format_option_t *opti
off += tmp;
mark |= option->option.mark;
- for (format_pair_t *ss = option->suffixes; ss != NULL && ss->string != NULL; ss++) {
+ for (const format_pair_t *ss = option->suffixes; ss != NULL && ss->string != NULL; ss++) {
tmp = format_option_cmp(part->string + off, ss->string);
if (tmp != 0) {
off += tmp;
diff --git a/src/format.h b/src/format.h
index e5173de..d7f8976 100644
--- a/src/format.h
+++ b/src/format.h
@@ -18,8 +18,8 @@ typedef struct {
typedef struct {
format_pair_t option;
- format_pair_t *prefixes;
- format_pair_t *suffixes;
+ const format_pair_t *prefixes;
+ const format_pair_t *suffixes;
} format_option_t;
bool format_init(format_t *format, const char *string, char delim);
diff --git a/src/util.c b/src/util.c
index d5ca902..714ce9d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <math.h>
#include "util.h"
#include "any_log.h"
@@ -152,60 +153,6 @@ size_t strprefix(const char *string, const char *prefix)
return i;
}
-// FIXME: Slow and inefficient
-char *strformat(const char *string, char delim, const char **keys, const char **values)
-{
- size_t length = strlen(string);
- size_t size = length;
- size_t n = 0;
- char *buffer = malloc(size);
-
- for (size_t i = 0; i < length; i++) {
- if (string[i] == delim && i + 2 < length && string[i + 1] == '{') {
- bool found = false;
- size_t j = i + 2;
- for ( ; j < length; j++) {
- if (string[j] == '}') {
- found = true;
- break;
- }
- }
-
- if (found) {
- for (int k = 0; keys[k] != NULL; k++) {
- if (!strncmp(string + i + 2, keys[k], j - i - 2)) {
-
- size_t vl = strlen(values[k]);
- while (n + vl >= size) {
- size *= 1.5;
- buffer = realloc(buffer, size);
- if (buffer == NULL)
- return NULL;
- }
-
- memcpy(buffer + n, values[k], vl);
- n += vl;
- i = j;
- goto next;
- }
- }
- }
- }
-
- if (n + 1 >= size) {
- size *= 1.5;
- buffer = realloc(buffer, size);
- if (buffer == NULL)
- return NULL;
- }
- buffer[n++] = string[i];
-next:
- }
-
- buffer[n] = '\0';
- return buffer;
-}
-
void strfree(char **list)
{
if (list == NULL)
@@ -225,3 +172,56 @@ bool iszero(const void *ptr, size_t size)
}
return true;
}
+
+int snprintf_units(char *buffer, size_t max, uint64_t bytes, unit_t unit)
+{
+ int base = unit & UNIT_SI ? 1000 : 1024;
+ double value = bytes;
+ const char *label = "";
+
+ switch (unit & ~UNIT_SI) {
+ case UNIT_B:
+ break;
+
+ case UNIT_TB:
+ value /= base;
+ // fallthrough
+
+ case UNIT_GB:
+ value /= base;
+ // fallthrough
+
+ case UNIT_MB:
+ value /= base;
+ // fallthrough
+
+ case UNIT_KB:
+ value /= base;
+ break;
+
+ default: {
+ int i = -1;
+ do {
+ value /= base;
+ i++;
+ } while (round(value * 10) / 10 >= base && i < 4);
+
+ const char *units[2][5] = {
+ { " B", " kB", " MB", " GB", " TB" },
+ { " B", " KiB", " MiB", " GiB", " TiB" },
+ };
+ label = units[!(unit & UNIT_SI)][i];
+ break;
+ }
+ }
+
+ int prec = 1;
+ if (floor(value) >= 100.0) {
+ value = ceil(value);
+ prec = 0;
+ }
+
+ int ret = snprintf(buffer, max, "%.*lf%s", prec, value, label);
+ assert(ret > 0);
+ return ret;
+}
diff --git a/src/util.h b/src/util.h
index 5f58a79..8d60eb2 100644
--- a/src/util.h
+++ b/src/util.h
@@ -5,6 +5,7 @@
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdint.h>
#define unreachable() log_panic("The impossible happened");
@@ -67,10 +68,20 @@ bool strfind(const char *string, const char *cases[]);
size_t strprefix(const char *string, const char *prefix);
-char *strformat(const char *string, char delim, const char *keys[], const char *values[]);
-
void strfree(char **list);
bool iszero(const void *ptr, size_t size);
+typedef enum {
+ UNIT_B = 1 << 0,
+ UNIT_KB = 1 << 1,
+ UNIT_MB = 1 << 2,
+ UNIT_GB = 1 << 3,
+ UNIT_TB = 1 << 4,
+ UNIT_SI = 1 << 5,
+ UNIT_MASK = UNIT_B | UNIT_KB | UNIT_MB | UNIT_GB | UNIT_TB | UNIT_SI,
+} unit_t;
+
+int snprintf_units(char *buffer, size_t max, uint64_t bytes, unit_t unit);
+
#endif