Commit: 244b48cc3ef715e190ecdaac511f302404eb8365
Parent: 14800b7b382676f2e8e8760ff99145124337f8b3
Author: Randy Palamar
Date: Tue, 24 Dec 2024 10:59:51 -0700
battery_info: remove 4K stack buffer
We have an Arena for this purpose and we can determine the needed
size at compile time so we don't need to do this.
Diffstat:
4 files changed, 59 insertions(+), 15 deletions(-)
diff --git a/blocks/linux/battery_info.c b/blocks/linux/battery_info.c
@@ -1,13 +1,13 @@
/* See LICENSE for license details. */
struct bat_arg {
- char *bat; /* BAT name (ex. BAT0) */
+ s8 bat; /* BAT name (ex. s8("BAT0")) */
char *pre; /* prefix for percentages less than thres */
char *suf; /* suffix for percentages less than thres */
i32 thres; /* % threshold to consider low (-1 to disable) */
f32 interval; /* [s] */
};
-struct linux_battery_data { i64 energy_full; f32 timer; };
+struct linux_battery_data { Stream path_base; i64 energy_full; f32 timer; };
static BLOCK_UPDATE_FN(battery_info_update)
{
@@ -19,29 +19,34 @@ static BLOCK_UPDATE_FN(battery_info_update)
char *pre = ba->pre ? ba->pre : "";
char *suf = ba->suf ? ba->suf : "";
- char path[4096], state[12];
+ char state[12];
i32 h, m;
i64 power_now, energy_now;
f64 timeleft;
- snprintf(path, sizeof(path), "/sys/class/power_supply/%s/energy_now", ba->bat);
- if (pscanf(path, "%ld", &energy_now) != 1)
+ size sidx = lbd->path_base.write_index;
+
+ stream_push_s8(&lbd->path_base, s8("/energy_now"));
+ if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &energy_now) != 1)
energy_now = 0;
+ lbd->path_base.write_index = sidx;
f32 percent = (100 * energy_now / (f64)lbd->energy_full) + 0.5;
b32 warn = percent < ba->thres;
- snprintf(path, sizeof(path), "/sys/class/power_supply/%s/status", ba->bat);
- if (pscanf(path, "%12s", &state) != 1)
+ stream_push_s8(&lbd->path_base, s8("/status"));
+ if (pscanf(stream_ensure_c_str(&lbd->path_base), "%12s", &state) != 1)
snprintf(state, sizeof(state), "Unknown");
+ lbd->path_base.write_index = sidx;
/* NOTE(rnp): proper devices use negative power to indicate discharging but that
* is not always the case. The status string can mostly be trusted */
if (!strcmp(state, "Discharging")) {
- snprintf(path, sizeof(path), "/sys/class/power_supply/%s/power_now", ba->bat);
- if (pscanf(path, "%ld", &power_now) != 1)
+ stream_push_s8(&lbd->path_base, s8("/power_now"));
+ if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &power_now) != 1)
power_now = 1;
+ lbd->path_base.write_index = sidx;
timeleft = energy_now / (f64)ABS(power_now);
h = timeleft;
@@ -60,16 +65,33 @@ static BLOCK_UPDATE_FN(battery_info_update)
return 1;
}
+#define LINUX_BAT_INFO_STRS \
+ X("/energy_full") \
+ X("/energy_now") \
+ X("/power_now") \
+ X("/status")
+
static BLOCK_INIT_FN(battery_info_init)
{
struct bat_arg *ba = b->arg;
struct linux_battery_data *lbd;
b->user_data = lbd = push_struct(a, struct linux_battery_data);
- char path[4096];
- snprintf(path, sizeof(path), "/sys/class/power_supply/%s/energy_full", ba->bat);
- if (pscanf(path, "%ld", &lbd->energy_full) != 1)
+ size max_length = 0;
+ #define X(cstr) if (sizeof(cstr) > max_length) max_length = sizeof(cstr);
+ LINUX_BAT_INFO_STRS
+ #undef X
+
+ size needed_length = max_length + sizeof("/sys/class/power_supply/") - 1 + ba->bat.len;
+ lbd->path_base = stream_alloc(a, needed_length);
+
+ stream_push_s8(&lbd->path_base, s8("/sys/class/power_supply/"));
+ stream_push_s8(&lbd->path_base, ba->bat);
+ size sidx = lbd->path_base.write_index;
+ stream_push_s8(&lbd->path_base, s8("/energy_full"));
+ if (pscanf(stream_ensure_c_str(&lbd->path_base), "%ld", &lbd->energy_full) != 1)
die("battery_info_init: failed to read battery capacity\n");
+ lbd->path_base.write_index = sidx;
battery_info_update(b, 1);
}
diff --git a/build.sh b/build.sh
@@ -3,12 +3,13 @@
cflags="-march=native -O3 -std=c11 -Wall -pedantic"
cflags="$cflags -D_XOPEN_SOURCE=500"
cflags="$cflags -I /usr/X11R6/include"
+#cflags="${cflags} -O0 -ggdb -D_DEBUG"
ldflags="-lX11"
#ldflags="$ldflags -lmpdclient" # needed for blocks/mpd.c
#ldflags="$ldflags -lasound" # needed for blocks/linux/volume.c
-echo "cflags: $cflags"
-echo "ldflags: $ldflags"
+#echo "cflags: $cflags"
+#echo "ldflags: $ldflags"
cc $cflags status.c $ldflags -o status
diff --git a/config.def.h b/config.def.h
@@ -14,7 +14,7 @@
// static struct vol_arg va = { "default", "Speaker" };
/* check blocks/xxx/battery_info.c for info */
-static struct bat_arg ba = {.bat = "BAT0", .interval = 30};
+static struct bat_arg ba = {.bat = s8("BAT0"), .interval = 30};
/* check blocks/date.c for info */
static struct date_arg da = {.fmt = "%R", .interval = 30};
diff --git a/status.c b/status.c
@@ -62,6 +62,9 @@ typedef size_t usize;
typedef struct { u8 *beg, *end; } Arena;
+#define s8(s) (s8){.len = sizeof(s) - 1, .data = (u8 *)s}
+typedef struct { size len; u8 *data; } s8;
+
typedef struct {
u8 *buffer;
i32 capacity;
@@ -180,6 +183,24 @@ stream_alloc(Arena *a, size capacity)
return result;
}
+static char *
+stream_ensure_c_str(Stream *s)
+{
+ ASSERT(s->write_index < s->capacity);
+ s->buffer[s->write_index] = 0;
+ return (char *)s->buffer;
+}
+
+static void
+stream_push_s8(Stream *s, s8 str)
+{
+ s->errors |= s->capacity <= (s->write_index + str.len);
+ if (!s->errors) {
+ memcpy(s->buffer + s->write_index, str.data, str.len);
+ s->write_index += str.len;
+ }
+}
+
static void
add_file_watch(Arena *a, char *path, i32 block_index, block_update_fn *update_fn)
{