|
|
@@ -1,52 +1,71 @@
|
|
|
/* 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;
|
|
|
-
|
|
|
- if (!(fp = fopen(path, "r"))) {
|
|
|
- warn("fopen '%s':", path);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (!(bytes_read = fread(buf, sizeof(char), bufsiz, fp))) {
|
|
|
- warn("fread '%s':", path);
|
|
|
- fclose(fp);
|
|
|
- return 0;
|
|
|
+ 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;
|
|
|
+
|
|
|
+ /* get number of fields we want to extract */
|
|
|
+ for (i = 0, left = 0; i < LEN(ent); i++) {
|
|
|
+ if (ent[i].var) {
|
|
|
+ left++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(fp = fopen("/proc/meminfo", "r"))) {
|
|
|
+ warn("fopen '/proc/meminfo':");
|
|
|
+ return 1;
|
|
|
}
|
|
|
- fclose(fp);
|
|
|
|
|
|
- buf[bytes_read] = '\0';
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- return bytes_read;
|
|
|
+ fclose(fp);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
const char *
|
|
|
swap_free(void)
|
|
|
{
|
|
|
- long total, free;
|
|
|
- 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);
|
|
|
+ long free;
|
|
|
|
|
|
- if (!(match = strstr(buf, "SwapFree"))) {
|
|
|
+ if (get_swap_info(NULL, &free, NULL)) {
|
|
|
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,16 +86,10 @@
|
|
|
swap_total(void)
|
|
|
{
|
|
|
long total;
|
|
|
- char *match;
|
|
|
-
|
|
|
- if (!pread("/proc/meminfo", buf, sizeof(buf) - 1)) {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
|
|
|
- if (!(match = strstr(buf, "SwapTotal"))) {
|
|
|
+ if (get_swap_info(&total, NULL, NULL)) {
|
|
|
return NULL;
|
|
|
}
|
|
|
- sscanf(match, "SwapTotal: %ld kB\n", &total);
|
|
|
|
|
|
return fmt_human(total * 1024, 1024);
|
|
|
}
|
|
|
@@ -105,26 +98,10 @@
|
|
|
swap_used(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"))) {
|
|
|
+ if (get_swap_info(&total, &free, &cached)) {
|
|
|
return NULL;
|
|
|
}
|
|
|
- sscanf(match, "SwapFree: %ld kB\n", &free);
|
|
|
|
|
|
return fmt_human((total - free - cached) * 1024, 1024);
|
|
|
}
|