#include #include #include #include #include #include #include "../block.h" #include "../any_log.h" typedef struct { block_text_t block; char *format; char *path; } block_fs_t; static const struct timespec block_fs_interval = { .tv_sec = 20, .tv_nsec = 0, }; static void block_fs_update(block_t *block) { block_fs_t *fs = (block_fs_t *)block; struct statvfs sbuf; assert(statvfs(fs->path, &sbuf) == 0); static const char *fs_formats[] = { "total", "free", "used", "free-percentage", "used-percentage", NULL, }; char buffer[5][32] = { 0 }; snprintf(buffer[0], 32, "%lu", sbuf.f_bsize * (uint64_t)sbuf.f_blocks); snprintf(buffer[1], 32, "%lu", sbuf.f_bsize * (uint64_t)sbuf.f_bavail); snprintf(buffer[2], 32, "%lu", sbuf.f_bsize * (sbuf.f_blocks - sbuf.f_bavail)); snprintf(buffer[3], 32, "%lu", (100 * sbuf.f_bavail) / sbuf.f_blocks); snprintf(buffer[4], 32, "%lu", (100 * (sbuf.f_blocks - sbuf.f_bavail)) / sbuf.f_blocks); const char *fs_values[] = { buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], NULL, }; free(fs->block.text); fs->block.text = strformat(fs->format, '%', fs_formats, fs_values); assert(fs->block.text != NULL); } static block_t *block_fs_alloc(const block_scheme_t *scheme) { block_t *block = calloc(1, sizeof(block_fs_t)); block->type = BLOCK_TEXT; block->update_interval = block_fs_interval; block->update_fn = block_fs_update; return block; } static void block_fs_clean(block_t *block) { block_fs_t *fs = (block_fs_t *)block; free(fs->format); free(fs->path); free(fs->block.text); } static bool block_fs_validate(block_t *block, const block_scheme_t *scheme) { block_fs_t *fs = (block_fs_t *)block; if (fs->block.text == NULL) { log_error("Block '%s' requires key '%s'", block->label, "text"); return false; } if (strstr(fs->block.text, "%{") == NULL) { log_warn("Block '%s' does not use any fs variable", block->label); block->update_fn = NULL; log_debug("Disabled updates for block '%s'", block->label); return true; } struct stat sbuf; if (fs->path == NULL || stat(fs->path, &sbuf) < 0) { log_error("Block '%s' was given an invalid path '%s'", block->label, fs->path); return false; } fs->format = fs->block.text; fs->block.text = NULL; return true; } static const config_entry_t block_fs_entries[] = { { "path", CONFIG_STRING, NULL, offsetof(block_fs_t, path) }, { 0 }, }; const block_scheme_t block_fs_scheme = { .name = "fs", .entries = block_fs_entries, .alloc_fn = block_fs_alloc, .clean_fn = block_fs_clean, .validate_fn = block_fs_validate, .resolve_fn = NULL, };