summaryrefslogtreecommitdiffstats
path: root/src/detection/swap
diff options
context:
space:
mode:
Diffstat (limited to 'src/detection/swap')
-rw-r--r--src/detection/swap/swap.h12
-rw-r--r--src/detection/swap/swap_apple.c28
-rw-r--r--src/detection/swap/swap_bsd.c78
-rw-r--r--src/detection/swap/swap_haiku.c27
-rw-r--r--src/detection/swap/swap_linux.c82
-rw-r--r--src/detection/swap/swap_nosupport.c5
-rw-r--r--src/detection/swap/swap_obsd.c35
-rw-r--r--src/detection/swap/swap_sunos.c32
-rw-r--r--src/detection/swap/swap_windows.c35
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;
+}