master ohmu/fastfetch-openbsd / src / detection / memory / memory_linux.c
ohmu  ·  2026-10-15
  1#include "memory.h"
  2#include "common/debug.h"
  3#include "common/io.h"
  4
  5const char* ffDetectMemory(FFMemoryResult* ram) {
  6    char buf[PROC_FILE_BUFFSIZ];
  7    ssize_t nRead = ffReadFileData("/proc/meminfo", ARRAY_SIZE(buf) - 1, buf);
  8    if (nRead < 0) {
  9        FF_DEBUG("ffReadFileData(\"/proc/meminfo\", ARRAY_SIZE(buf)-1, buf) failed: %s", strerror(errno));
 10        return "ffReadFileData(\"/proc/meminfo\", ARRAY_SIZE(buf)-1, buf)";
 11    }
 12    buf[nRead] = '\0';
 13
 14    uint64_t memTotal = 0,
 15             memAvailable = 0,
 16             shmem = 0,
 17             memFree = 0,
 18             buffers = 0,
 19             cached = 0,
 20             sReclaimable = 0;
 21
 22    char* token = nullptr;
 23    if ((token = memmem(buf, (size_t) nRead, "MemTotal:", strlen("MemTotal:"))) != nullptr) {
 24        memTotal = (uint64_t) strtoull(token + strlen("MemTotal:"), nullptr, 10);
 25    } else {
 26        FF_DEBUG("MemTotal not found in /proc/meminfo");
 27        return "MemTotal not found in /proc/meminfo";
 28    }
 29
 30    if ((token = memmem(buf, (size_t) nRead, "MemAvailable:", strlen("MemAvailable:"))) != nullptr) {
 31        memAvailable = (uint64_t) strtoull(token + strlen("MemAvailable:"), nullptr, 10);
 32    }
 33
 34    if (memAvailable == 0 || memAvailable >= memTotal) { // MemAvailable can be unreasonable. #1988
 35        if ((token = memmem(buf, (size_t) nRead, "MemFree:", strlen("MemFree:"))) != nullptr) {
 36            memFree = (uint64_t) strtoull(token + strlen("MemFree:"), nullptr, 10);
 37        }
 38
 39        if ((token = memmem(buf, (size_t) nRead, "Buffers:", strlen("Buffers:"))) != nullptr) {
 40            buffers = (uint64_t) strtoull(token + strlen("Buffers:"), nullptr, 10);
 41        }
 42
 43        if ((token = memmem(buf, (size_t) nRead, "Cached:", strlen("Cached:"))) != nullptr) {
 44            cached = (uint64_t) strtoull(token + strlen("Cached:"), nullptr, 10);
 45        }
 46
 47        if ((token = memmem(buf, (size_t) nRead, "Shmem:", strlen("Shmem:"))) != nullptr) {
 48            shmem = (uint64_t) strtoull(token + strlen("Shmem:"), nullptr, 10);
 49        }
 50
 51        if ((token = memmem(buf, (size_t) nRead, "SReclaimable:", strlen("SReclaimable:"))) != nullptr) {
 52            sReclaimable = (uint64_t) strtoull(token + strlen("SReclaimable:"), nullptr, 10);
 53        }
 54
 55        memAvailable = memFree + buffers + cached + sReclaimable - shmem;
 56    }
 57
 58    ram->bytesTotal = memTotal * 1024lu;
 59    ram->bytesUsed = (memTotal - memAvailable) * 1024lu;
 60
 61    uint64_t arcSize = 0;
 62    nRead = ffReadFileData("/proc/spl/kstat/zfs/arcstats", ARRAY_SIZE(buf) - 1, buf);
 63    if (nRead > 0) {
 64        buf[nRead] = '\0';
 65        // 24 1 0x01 148 40256 2053603602 851614020716
 66        // name                            type data
 67        // hits                            4    752
 68
 69        // Skip first line
 70        const char* p = memchr(buf, '\n', (size_t) nRead);
 71        if (__builtin_expect(p != nullptr, true)) {
 72            ++p;
 73            nRead -= (p - buf);
 74            assert(nRead > 0);
 75
 76            // Find line offset of data
 77            const char* pData = memmem(p, (size_t) nRead, "data\n", strlen("data\n"));
 78            if (__builtin_expect(pData != nullptr, true)) {
 79                uint32_t dataOffset = (uint32_t) (pData - p);
 80                p += dataOffset + strlen("data\n");
 81                nRead -= (ssize_t) (dataOffset + strlen("data\n"));
 82                assert(nRead > 0);
 83
 84                if ((token = memmem(p, (size_t) nRead, "\nsize ", strlen("\nsize "))) != nullptr) {
 85                    arcSize = (uint64_t) strtoull(token + 1 + dataOffset, nullptr, 10);
 86                    if (arcSize > 0) {
 87                        uint64_t arcMin = 0;
 88                        if ((token = memmem(p, (size_t) nRead, "\nc_min ", strlen("\nc_min "))) != nullptr) {
 89                            arcMin = (uint64_t) strtoull(token + 1 + dataOffset, nullptr, 10);
 90                            if (arcSize > arcMin) {
 91                                arcSize -= arcMin;
 92                                if (ram->bytesUsed > arcSize) {
 93                                    ram->bytesUsed -= arcSize;
 94                                }
 95                            }
 96                        }
 97                    }
 98                }
 99            }
100        }
101    }
102
103    return nullptr;
104}