#include <ctype.h>
#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int pakfire_cpuinfo(struct pakfire_cpuinfo* cpuinfo) {
return pakfire_parse_file("/proc/cpuinfo", pakfire_parse_cpuinfo, cpuinfo);
}
+
+// Meminfo
+
+static int pakfire_parse_meminfo_value(uint64_t* mem, const char* s) {
+ char* remainder = NULL;
+ uint64_t m = 0;
+
+ // Parse the numeric value
+ m = strtoul(s, &remainder, 10);
+ if (m == ULONG_MAX)
+ return -errno;
+
+ // Convert into bytes
+ if (strcmp(remainder, " kB") == 0) {
+ // Check if the multiplication won't overflow
+ if (m > UINT64_MAX / 1024)
+ return -EOVERFLOW;
+
+ m *= 1024;
+
+ // Fail on anything else
+ } else if (*remainder)
+ return -EINVAL;
+
+ // Store the value
+ *mem = m;
+
+ return 0;
+}
+
+static int pakfire_parse_meminfo(char* line, size_t length, void* data) {
+ struct pakfire_meminfo* meminfo = data;
+ int r;
+
+ // Key & Value
+ const char* k = NULL;
+ const char* v = NULL;
+
+ // Split the line
+ r = pakfire_split_line(line, length, &k, &v);
+ if (r)
+ return r;
+
+ // If we didn't get a result we skip this line
+ if (!k || !v)
+ return 0;
+
+ // Total
+ if (strcmp(k, "MemTotal") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->total, v);
+
+ // Free
+ else if (strcmp(k, "MemFree") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->free, v);
+
+ // Available
+ else if (strcmp(k, "MemAvailable") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->available, v);
+
+ // Buffers
+ else if (strcmp(k, "Buffers") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->buffers, v);
+
+ // Cached
+ else if (strcmp(k, "Cached") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->cached, v);
+
+ // Active
+ else if (strcmp(k, "Active") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->active, v);
+
+ // Inactive
+ else if (strcmp(k, "Inactive") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->inactive, v);
+
+ // Swap Total
+ else if (strcmp(k, "SwapTotal") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->swap_total, v);
+
+ // Swap Free
+ else if (strcmp(k, "SwapFree") == 0)
+ return pakfire_parse_meminfo_value(&meminfo->swap_free, v);
+
+ return 0;
+}
+
+int pakfire_meminfo(struct pakfire_meminfo* meminfo) {
+ int r;
+
+ // Parse /proc/meminfo
+ r = pakfire_parse_file("/proc/meminfo", pakfire_parse_meminfo, meminfo);
+ if (r)
+ return r;
+
+ // Set used memory
+ meminfo->used = meminfo->total - meminfo->free;
+
+ // Set used swap
+ meminfo->swap_used = meminfo->swap_total - meminfo->swap_free;
+
+ return 0;
+}
return EXIT_FAILURE;
}
+// This test parses /proc/meminfo
+static int test_meminfo(const struct test* t) {
+ struct pakfire_meminfo meminfo = {};
+
+ ASSERT_SUCCESS(pakfire_meminfo(&meminfo));
+
+ // We can only check is something has been read
+ ASSERT(meminfo.total > 0);
+ ASSERT(meminfo.used > 0);
+ ASSERT(meminfo.free > 0);
+ ASSERT(meminfo.available > 0);
+ ASSERT(meminfo.buffers > 0);
+ ASSERT(meminfo.cached > 0);
+ ASSERT(meminfo.active > 0);
+ ASSERT(meminfo.inactive > 0);
+ ASSERT(meminfo.swap_total >= 0);
+ ASSERT(meminfo.swap_used >= 0);
+ ASSERT(meminfo.swap_free >= 0);
+
+ return EXIT_SUCCESS;
+
+FAIL:
+ return EXIT_FAILURE;
+}
+
int main(int argc, const char* argv[]) {
testsuite_add_test(test_cpuinfo);
+ testsuite_add_test(test_meminfo);
return testsuite_run(argc, argv);
}