diff options
| author | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
|---|---|---|
| committer | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
| commit | 76424950e373d3b04ac3dd13019151bfba3e8423 (patch) | |
| tree | 4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/swap | |
Add the files
Diffstat (limited to 'src/detection/swap')
| -rw-r--r-- | src/detection/swap/swap.h | 12 | ||||
| -rw-r--r-- | src/detection/swap/swap_apple.c | 28 | ||||
| -rw-r--r-- | src/detection/swap/swap_bsd.c | 78 | ||||
| -rw-r--r-- | src/detection/swap/swap_haiku.c | 27 | ||||
| -rw-r--r-- | src/detection/swap/swap_linux.c | 82 | ||||
| -rw-r--r-- | src/detection/swap/swap_nosupport.c | 5 | ||||
| -rw-r--r-- | src/detection/swap/swap_obsd.c | 35 | ||||
| -rw-r--r-- | src/detection/swap/swap_sunos.c | 32 | ||||
| -rw-r--r-- | src/detection/swap/swap_windows.c | 35 |
9 files changed, 334 insertions, 0 deletions
diff --git a/src/detection/swap/swap.h b/src/detection/swap/swap.h new file mode 100644 index 0000000..eb32f75 --- /dev/null +++ b/src/detection/swap/swap.h @@ -0,0 +1,12 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/swap/option.h" + +typedef struct FFSwapResult { + FFstrbuf name; + uint64_t bytesUsed; + uint64_t bytesTotal; +} FFSwapResult; + +const char* ffDetectSwap(FFlist* result /* List of FFSwapResult */); diff --git a/src/detection/swap/swap_apple.c b/src/detection/swap/swap_apple.c new file mode 100644 index 0000000..40dda49 --- /dev/null +++ b/src/detection/swap/swap_apple.c @@ -0,0 +1,28 @@ +#include "swap.h" + +#include "common/sysctl.h" +#include <mach/mach.h> + +const char* ffDetectSwap(FFlist* result) { + struct xsw_usage xsw; + size_t size = sizeof(xsw); + if (sysctl((int[]) { CTL_VM, VM_SWAPUSAGE }, 2, &xsw, &size, NULL, 0) != 0) { + return "Failed to read vm.swapusage"; + } + + if (xsw.xsu_total == 0) { + if (__builtin_available(macOS 26.0, *)) { + // "vm.compressor_mode" no longer exists in macOS 26.0 + } else { + if (ffSysctlGetInt("vm.compressor_mode", 4) <= 2) { + return NULL; // Swap is disabled + } + } + } + + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + ffStrbufInitStatic(&swap->name, xsw.xsu_encrypted ? "Encrypted" : "Normal"); + swap->bytesTotal = xsw.xsu_total; + swap->bytesUsed = xsw.xsu_used; + return NULL; +} diff --git a/src/detection/swap/swap_bsd.c b/src/detection/swap/swap_bsd.c new file mode 100644 index 0000000..a54cd52 --- /dev/null +++ b/src/detection/swap/swap_bsd.c @@ -0,0 +1,78 @@ +#include "swap.h" +#include "common/sysctl.h" + +#include <vm/vm_param.h> +#include <sys/stat.h> +#include <sys/param.h> + +static void addSwapEntry(FFlist* result, struct xswdev* xsw, uint32_t pageSize) { + if (xsw->xsw_nblks == 0) { // DFBSD reports some /dev/wdog devices with nblks == 0 + return; + } + + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + if (xsw->xsw_dev == NODEV) { + ffStrbufInitStatic(&swap->name, "[NFS]"); + } else { + ffStrbufInitF(&swap->name, "/dev/%s", devname(xsw->xsw_dev, S_IFCHR)); + } + swap->bytesUsed = (uint64_t) xsw->xsw_used * pageSize; + swap->bytesTotal = (uint64_t) xsw->xsw_nblks * pageSize; +} + +#if __DragonFly__ + +const char* ffDetectSwap(FFlist* result) { + struct xswdev xsws[32]; + size_t size = sizeof(xsws); + if (sysctlbyname("vm.swap_info_array", xsws, &size, NULL, 0) < 0) { + return "sysctlbyname(\"vm.swap_info_array\") failed"; + } + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + size_t count = size / sizeof(struct xswdev); + if (count == 0) { + return NULL; + } + + if (xsws->xsw_version != XSWDEV_VERSION) { + return "xswdev version mismatch"; + } + + for (uint32_t i = 0; i < count; ++i) { + addSwapEntry(result, &xsws[i], pageSize); + } + + return NULL; +} + +#elif __FreeBSD__ + +const char* ffDetectSwap(FFlist* result) { + int mib[16]; + size_t mibsize = ARRAY_SIZE(mib); + if (sysctlnametomib("vm.swap_info", mib, &mibsize) < 0) { + return "sysctlnametomib(\"vm.swap_info\") failed"; + } + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (int n = 0;; ++n) { + mib[mibsize] = n; + struct xswdev xsw; + size_t size = sizeof(xsw); + if (sysctl(mib, (uint32_t) (mibsize + 1), &xsw, &size, NULL, 0) < 0) { + break; + } + if (xsw.xsw_version != XSWDEV_VERSION) { + return "xswdev version mismatch"; + } + + addSwapEntry(result, &xsw, pageSize); + } + + return NULL; +} + +#endif diff --git a/src/detection/swap/swap_haiku.c b/src/detection/swap/swap_haiku.c new file mode 100644 index 0000000..8a3b08c --- /dev/null +++ b/src/detection/swap/swap_haiku.c @@ -0,0 +1,27 @@ +#include "swap.h" + +#include <OS.h> +#include <driver_settings.h> + +const char* ffDetectSwap(FFlist* result) { + system_info info; + if (get_system_info(&info) != B_OK) { + return "Error getting system info"; + } + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + ffStrbufInitStatic(&swap->name, "System"); + void* kvms = load_driver_settings("virtual_memory"); // /boot/home/config/settings/kernel/drivers/virtual_memory + if (kvms) { + const char* swapAuto = get_driver_parameter(kvms, "swap_auto", NULL, NULL); + if (swapAuto) { + ffStrbufSetStatic(&swap->name, swapAuto[0] == 'y' ? "Auto" : "Manual"); + } + unload_driver_settings(kvms); + } + swap->bytesTotal = pageSize * (uint64_t) info.max_swap_pages; + swap->bytesUsed = pageSize * (uint64_t) (info.max_swap_pages - info.free_swap_pages); + + return NULL; +} diff --git a/src/detection/swap/swap_linux.c b/src/detection/swap/swap_linux.c new file mode 100644 index 0000000..b31f268 --- /dev/null +++ b/src/detection/swap/swap_linux.c @@ -0,0 +1,82 @@ +#include "swap.h" + +#include "common/io.h" +#include "common/mallocHelper.h" + +#include <inttypes.h> + +static const char* detectByProcMeminfo(FFlist* result) { + // For Android + // Ref: #620 + char buf[PROC_FILE_BUFFSIZ]; + ssize_t nRead = ffReadFileData("/proc/meminfo", ARRAY_SIZE(buf) - 1, buf); + if (nRead < 0) { + return "ffReadFileData(\"/proc/meminfo\", ARRAY_SIZE(buf)-1, buf)"; + } + buf[nRead] = '\0'; + + uint64_t swapTotal = 0, swapFree = 0; + + char* token = NULL; + if ((token = strstr(buf, "SwapTotal:")) != NULL) { + swapTotal = strtoul(token + strlen("SwapTotal:"), NULL, 10); + } + + if ((token = strstr(buf, "SwapFree:")) != NULL) { + swapFree = strtoul(token + strlen("SwapFree:"), NULL, 10); + } + + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + ffStrbufInitStatic(&swap->name, "Total"); + swap->bytesTotal = swapTotal * 1024lu; + swap->bytesUsed = (swapTotal - swapFree) * 1024lu; + + return NULL; +} + +static const char* detectByProcSwaps(FFlist* result) { + // Ref: #620 + char buf[PROC_FILE_BUFFSIZ]; + ssize_t nRead = ffReadFileData("/proc/swaps", ARRAY_SIZE(buf) - 1, buf); + if (nRead <= 0) { + return "ffReadFileData(\"/proc/swaps\", ARRAY_SIZE(buf)-1, buf) failed"; + } + buf[nRead] = '\0'; + + // Skip header + char* line = memchr(buf, '\n', (size_t) nRead); + + while (line && *++line) { + uint64_t total, used; + char name[256]; + if (sscanf(line, "%255s %*[^\t]%" SCNu64 "%" SCNu64, name, &total, &used) != 3) { + return "Invalid /proc/swaps format found"; + } + + uint32_t nameLen = (uint32_t) strnlen(name, sizeof(name)); + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + ffStrbufInitA(&swap->name, nameLen); + for (size_t i = 0; i < nameLen; ++i) { + if (name[i] == '\\') { + char octal[4] = { name[i + 1], name[i + 2], name[i + 3], '\0' }; + ffStrbufAppendC(&swap->name, (char) strtol(octal, NULL, 8)); + i += 3; + } else { + ffStrbufAppendC(&swap->name, name[i]); + } + } + swap->bytesTotal = total * 1024u; + swap->bytesUsed = used * 1024u; + + line = memchr(line, '\n', (size_t) (nRead - (line - buf))); + } + + return NULL; +} + +const char* ffDetectSwap(FFlist* result) { + if (detectByProcSwaps(result) == NULL) { + return NULL; + } + return detectByProcMeminfo(result); +} diff --git a/src/detection/swap/swap_nosupport.c b/src/detection/swap/swap_nosupport.c new file mode 100644 index 0000000..ebc29b4 --- /dev/null +++ b/src/detection/swap/swap_nosupport.c @@ -0,0 +1,5 @@ +#include "swap.h" + +const char* ffDetectSwap(FFSwapResult* swap) { + return "Not supported on this platform"; +} diff --git a/src/detection/swap/swap_obsd.c b/src/detection/swap/swap_obsd.c new file mode 100644 index 0000000..1296aeb --- /dev/null +++ b/src/detection/swap/swap_obsd.c @@ -0,0 +1,35 @@ +#include "swap.h" +#include "common/FFlist.h" +#include "common/mallocHelper.h" + +#include <sys/types.h> +#include <sys/swap.h> +#include <sys/param.h> +#include <unistd.h> + +const char* ffDetectSwap(FFlist* result) { + int nswap = swapctl(SWAP_NSWAP, 0, 0); + if (nswap < 0) { + return "swapctl(SWAP_NSWAP) failed"; + } + if (nswap == 0) { + return NULL; + } + + FF_AUTO_FREE struct swapent* swdev = malloc((uint32_t) nswap * sizeof(*swdev)); + + if (swapctl(SWAP_STATS, swdev, nswap) < 0) { + return "swapctl(SWAP_STATS) failed"; + } + + for (int i = 0; i < nswap; i++) { + if (swdev[i].se_flags & SWF_ENABLE) { + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + ffStrbufInitS(&swap->name, swdev[i].se_path); + swap->bytesUsed = (uint64_t) swdev[i].se_inuse * DEV_BSIZE; + swap->bytesTotal = (uint64_t) swdev[i].se_nblks * DEV_BSIZE; + } + } + + return NULL; +} diff --git a/src/detection/swap/swap_sunos.c b/src/detection/swap/swap_sunos.c new file mode 100644 index 0000000..fa3260d --- /dev/null +++ b/src/detection/swap/swap_sunos.c @@ -0,0 +1,32 @@ +#include "swap.h" +#include <sys/stat.h> +#include <sys/swap.h> +#include <limits.h> +#include <stdalign.h> + +enum { FFMaxNSwap = 8 }; + +const char* ffDetectSwap(FFlist* result) { + char strings[FFMaxNSwap][PATH_MAX]; + alignas(swaptbl_t) uint8_t buffer[sizeof(swaptbl_t) + sizeof(swapent_t) * (FFMaxNSwap - 1)] = {}; + swaptbl_t* table = (swaptbl_t*) buffer; + table->swt_n = FFMaxNSwap; + for (int i = 0; i < FFMaxNSwap; ++i) { + table->swt_ent[i].ste_path = strings[i]; + } + + int size = swapctl(SC_LIST, table); + if (size < 0) { + return "swapctl() failed"; + } + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + for (int i = 0; i < size; ++i) { + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + ffStrbufInitS(&swap->name, table->swt_ent[i].ste_path); + swap->bytesTotal = (uint64_t) table->swt_ent[i].ste_pages * pageSize; + swap->bytesUsed = swap->bytesTotal - (uint64_t) table->swt_ent[i].ste_free * pageSize; + } + + return NULL; +} diff --git a/src/detection/swap/swap_windows.c b/src/detection/swap/swap_windows.c new file mode 100644 index 0000000..e96298b --- /dev/null +++ b/src/detection/swap/swap_windows.c @@ -0,0 +1,35 @@ +#include "swap.h" +#include "common/windows/unicode.h" + +#include <winternl.h> +#include <ntstatus.h> +#include <windows.h> +#include <stdalign.h> + +const char* ffDetectSwap(FFlist* result) { + alignas(SYSTEM_PAGEFILE_INFORMATION) uint8_t buffer[4096]; + ULONG size = sizeof(buffer); + SYSTEM_PAGEFILE_INFORMATION* pstart = (SYSTEM_PAGEFILE_INFORMATION*) buffer; + if (!NT_SUCCESS(NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size))) { + return "NtQuerySystemInformation(SystemPagefileInformation, size) failed"; + } + + if (size == 0) { + return NULL; + } + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + for (SYSTEM_PAGEFILE_INFORMATION* current = pstart;; current = (SYSTEM_PAGEFILE_INFORMATION*) ((uint8_t*) current + current->NextEntryOffset)) { + FFSwapResult* swap = FF_LIST_ADD(FFSwapResult, *result); + ffStrbufInitNWS(&swap->name, current->FileName.Length / sizeof(wchar_t), current->FileName.Buffer); + if (ffStrbufStartsWithS(&swap->name, "\\??\\")) { + ffStrbufSubstrAfter(&swap->name, strlen("\\??\\") - 1); + } + swap->bytesUsed = (uint64_t) current->TotalUsed * pageSize; + swap->bytesTotal = (uint64_t) current->CurrentSize * pageSize; + if (current->NextEntryOffset == 0) { + break; + } + } + return NULL; +} |