Refactor swap.c to use getline() instead of buf-filling

This drops a lot of code and even though we are using a common function,
the specification of only the needed things keeps it very efficient and
even more efficient in memory and time than the previous solution.
This commit is contained in:
Laslo Hunhold 2018-05-28 21:16:02 +02:00 committed by Aaron Marcher
parent 5d6415608b
commit a18439af11
1 changed files with 49 additions and 72 deletions

View File

@ -1,53 +1,72 @@
/* See LICENSE file for copyright and license details. */
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../util.h"
#if defined(__linux__)
static size_t
pread(const char *path, char *buf, size_t bufsiz)
static int
get_swap_info(long *s_total, long *s_free, long *s_cached)
{
FILE *fp;
size_t bytes_read;
struct {
const char *name;
const size_t len;
long *var;
} ent[] = {
{ "SwapTotal", sizeof("SwapTotal") - 1, s_total },
{ "SwapFree", sizeof("SwapFree") - 1, s_free },
{ "SwapCached", sizeof("SwapCached") - 1, s_cached },
};
size_t line_len = 0, i, left;
char *line = NULL;
if (!(fp = fopen(path, "r"))) {
warn("fopen '%s':", path);
return 0;
/* get number of fields we want to extract */
for (i = 0, left = 0; i < LEN(ent); i++) {
if (ent[i].var) {
left++;
}
}
if (!(bytes_read = fread(buf, sizeof(char), bufsiz, fp))) {
warn("fread '%s':", path);
fclose(fp);
return 0;
if (!(fp = fopen("/proc/meminfo", "r"))) {
warn("fopen '/proc/meminfo':");
return 1;
}
/* read file line by line and extract field information */
while (left > 0 && getline(&line, &line_len, fp) >= 0) {
for (i = 0; i < LEN(ent); i++) {
if (ent[i].var &&
!strncmp(line, ent[i].name, ent[i].len)) {
sscanf(line + ent[i].len + 1, "%ld kB\n",
ent[i].var);
left--;
break;
}
}
}
free(line);
if (ferror(fp)) {
warn("getline '/proc/meminfo':");
return 1;
}
fclose(fp);
buf[bytes_read] = '\0';
return bytes_read;
return 0;
}
const char *
swap_free(void)
{
long total, free;
char *match;
long free;
if (!pread("/proc/meminfo", buf, sizeof(buf) - 1)) {
if (get_swap_info(NULL, &free, NULL)) {
return NULL;
}
if (!(match = strstr(buf, "SwapTotal"))) {
return NULL;
}
sscanf(match, "SwapTotal: %ld kB\n", &total);
if (!(match = strstr(buf, "SwapFree"))) {
return NULL;
}
sscanf(match, "SwapFree: %ld kB\n", &free);
return fmt_human(free * 1024, 1024);
}
@ -55,28 +74,8 @@
swap_perc(void)
{
long total, free, cached;
char *match;
if (!pread("/proc/meminfo", buf, sizeof(buf) - 1)) {
return NULL;
}
if (!(match = strstr(buf, "SwapTotal"))) {
return NULL;
}
sscanf(match, "SwapTotal: %ld kB\n", &total);
if (!(match = strstr(buf, "SwapCached"))) {
return NULL;
}
sscanf(match, "SwapCached: %ld kB\n", &cached);
if (!(match = strstr(buf, "SwapFree"))) {
return NULL;
}
sscanf(match, "SwapFree: %ld kB\n", &free);
if (total == 0) {
if (get_swap_info(&total, &free, &cached) || total == 0) {
return NULL;
}
@ -87,17 +86,11 @@
swap_total(void)
{
long total;
char *match;
if (!pread("/proc/meminfo", buf, sizeof(buf) - 1)) {
if (get_swap_info(&total, NULL, NULL)) {
return NULL;
}
if (!(match = strstr(buf, "SwapTotal"))) {
return NULL;
}
sscanf(match, "SwapTotal: %ld kB\n", &total);
return fmt_human(total * 1024, 1024);
}
@ -105,27 +98,11 @@
swap_used(void)
{
long total, free, cached;
char *match;
if (!pread("/proc/meminfo", buf, sizeof(buf) - 1)) {
if (get_swap_info(&total, &free, &cached)) {
return NULL;
}
if (!(match = strstr(buf, "SwapTotal"))) {
return NULL;
}
sscanf(match, "SwapTotal: %ld kB\n", &total);
if (!(match = strstr(buf, "SwapCached"))) {
return NULL;
}
sscanf(match, "SwapCached: %ld kB\n", &cached);
if (!(match = strstr(buf, "SwapFree"))) {
return NULL;
}
sscanf(match, "SwapFree: %ld kB\n", &free);
return fmt_human((total - free - cached) * 1024, 1024);
}
#elif defined(__OpenBSD__)