mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a9f43ff466 | |||
| 924d78d3c4 | |||
| fa92bb84ae | |||
| 288d25e17c | |||
| 610fc2ea36 | |||
| 716c0e2b5c | |||
| 945aed7160 | |||
| 1d4d68f6e0 | |||
| 3e1167260d | |||
| 0130f610e9 | |||
| 94941daf4f | |||
| 2bbd723321 | |||
| 608382109c | |||
| bdc5174f68 | |||
| bc869f1be9 | |||
| dc69e44829 | |||
| d236850119 | |||
| 60ec8c9097 | |||
| 42e7a7d2f7 | |||
| e766809e3a | |||
| cb1f0300b9 | |||
| f2a29309f3 | |||
| 6e7b4bab75 | |||
| b4f39e251c | |||
| af6196fe6e | |||
| bca56b2049 | |||
| f4401f172e | |||
| c11b88fee5 | |||
| 88b1b558d7 | |||
| ba6cdc77c9 | |||
| b952772902 | |||
| 7a322154fa | |||
| 0b6ca158ea | |||
| 100cd9a72b | |||
| 98fb810f1f | |||
| c613e558fd | |||
| c324f83826 | |||
| e50421a6ce | |||
| 417b944e1c | |||
| cb8b4b335d | |||
| c0160537b0 | |||
| 4cb7a6424a | |||
| 7d6c79d73e | |||
| 8652737f64 | |||
| d6ac89ea8d | |||
| 2b620cf487 | |||
| f644df481c | |||
| e99ecacb52 | |||
| 3e22dd4b0e | |||
| 19f30ec687 | |||
| 76bee78200 | |||
| ce7455d8f0 | |||
| 5e27ee0f57 | |||
| 84a5c6ebe8 | |||
| ad7e23f64c | |||
| 2738f20eea | |||
| 09362b236c | |||
| 3cfef81877 | |||
| 3a04ae2542 | |||
| dbaf8a319d | |||
| 2fe2a21bfe | |||
| 37639c3582 | |||
| 9a74e6d7bc | |||
| 5d13389827 | |||
| 1c2c6644d5 | |||
| ffcddf30e3 | |||
| 22c92c7b05 | |||
| b569048010 | |||
| f703d9ac89 | |||
| ed6abfd626 | |||
| 50388efc78 | |||
| 7e8fb0fa14 | |||
| 9d70469665 | |||
| a94f0efb5b | |||
| da3a9be7c6 | |||
| cd8ab8e55a | |||
| 1b5b32afad | |||
| 917f784438 | |||
| c2d5d5cca1 | |||
| b435738c34 | |||
| 934905e63a | |||
| d15bb8a232 | |||
| c22bca1f87 | |||
| e04cc9c9d5 |
@@ -446,7 +446,6 @@ jobs:
|
||||
usesh: true
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg install pkg:/package/pkg
|
||||
pkg update --accept
|
||||
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick
|
||||
|
||||
|
||||
@@ -1,3 +1,78 @@
|
||||
# 2.56.1
|
||||
|
||||
Features:
|
||||
* Improves compatibility with KDE Plasma 6.5 (#2093, Display)
|
||||
* Adds a `tempSensor` option to specify the sensor name used for CPU temperature detection (CPU)
|
||||
* Example: `{ "type": "cpu", "tempSensor": "hwmon0" /* Use /sys/class/hwmon/hwmon0 for temperature detection */ }`
|
||||
* Refines Memory usage detection on macOS to match Activity Monitor more closely (Memory, macOS)
|
||||
* Minor optimizations
|
||||
|
||||
Bugfixes:
|
||||
* Fixes cache line size detection (CPU, macOS)
|
||||
|
||||
Logos:
|
||||
* Removes Opak
|
||||
* Updates GXDE
|
||||
|
||||
# 2.56.0
|
||||
|
||||
Features:
|
||||
* Enhances config file loading. `--config` and `-c` with relative path now also searches paths defined in `fastfetch --list-config-paths` (typically `~/.config/fastfetch/`)
|
||||
* This allows users to use `fastfetch -c my-config` without needing to specify the full path.
|
||||
* Adds NUMA node count detection (CPU)
|
||||
* Exposed via `{numa-nodes}` in custom format
|
||||
* Supported on Linux, FreeBSD and Windows
|
||||
* Supports the newest Alacritty config format (#2070, TerminalFont)
|
||||
* Detects driver specific info for Zhaoxin GPUs (GPU, Linux)
|
||||
* Detects Android OEM UI for certain OSes (DE, Android)
|
||||
* Improves users detection on Linux (#2064, Users, Linux)
|
||||
* Adds systemd fallback when utmp is unavailable
|
||||
* Fixes resource leaks
|
||||
* Always reports the newest session info
|
||||
* Adds kiss package manager support (#2072, Packages, Linux)
|
||||
* Reports `sshd` if `$SSH_TTY` is not available (Terminal)
|
||||
* Zpool module rewrite (#2051, Zpool)
|
||||
* Adds new Zpool properties: allocated, guid, readOnly
|
||||
* Zpool module now uses runtime lookup for properties to ensure portability
|
||||
* Adds NetBSD (requires `sudo`) and macOS support
|
||||
* Adds `splitLines` option for Command module, which splits the output into sub modules, each containing one line of the output (Command)
|
||||
```
|
||||
* Command output:
|
||||
Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* Old behavior:
|
||||
Command: Line 1
|
||||
Line 2
|
||||
Line 3
|
||||
|
||||
* With `"splitLines": true`:
|
||||
Command 1: Line 1
|
||||
Command 2: Line 2
|
||||
Command 3: Line 3
|
||||
```
|
||||
|
||||
Bugfixes:
|
||||
* Fixes {m,o}ksh version detection on Linux (Shell)
|
||||
* Fixes Alacritty config parsing for TOML format (#2070, TerminalFont)
|
||||
* Improves builtin logo printing for piping and buffering (#2065, Logo)
|
||||
* Uses absolute path when detecting shell and terminal version if available (#2067, TerminalShell)
|
||||
|
||||
Logos:
|
||||
* Updates Codex Linux logo (#2071)
|
||||
* Adds OS/2 Warp logo (#2062)
|
||||
* Adds Amiga logo (#2061)
|
||||
|
||||
# 2.55.1
|
||||
|
||||
Bugfixes:
|
||||
* Fix parallel command execution breaks randomly (#2056 / #2058, Command)
|
||||
* Regression from v2.55.0
|
||||
* Fix `dylib` searching path on macOS (macOS)
|
||||
* Regression from v2.55.0
|
||||
* Fix an uninitialized field (#2057, Display)
|
||||
|
||||
# 2.55.0
|
||||
|
||||
Changes:
|
||||
|
||||
+13
-33
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.55.0
|
||||
VERSION 2.56.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -92,7 +92,6 @@ cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku OR GNU" OFF)
|
||||
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
|
||||
cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "GNU" OFF)
|
||||
|
||||
option(ENABLE_ZLIB "Enable zlib" ON)
|
||||
@@ -107,6 +106,7 @@ option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON)
|
||||
option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF)
|
||||
option(ENABLE_EMBEDDED_AMDGPUIDS "Embed amdgpu.ids into fastfetch, requires `python`" OFF)
|
||||
option(ENABLE_WORDEXP "Enable using of wordexp(3) if available, instead of glob(3)" ON)
|
||||
option(ENABLE_LIBZFS "Enable libzfs" ON)
|
||||
|
||||
set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
|
||||
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
|
||||
@@ -410,6 +410,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/detection/version/version.c
|
||||
src/detection/vulkan/vulkan.c
|
||||
src/detection/weather/weather.c
|
||||
src/detection/zpool/zpool.c
|
||||
src/logo/builtin.c
|
||||
src/logo/image/im6.c
|
||||
src/logo/image/im7.c
|
||||
@@ -582,7 +583,6 @@ if(LINUX)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -656,7 +656,6 @@ elseif(ANDROID)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_android.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -739,7 +738,6 @@ elseif(FreeBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -833,7 +831,6 @@ elseif(NetBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -916,7 +913,6 @@ elseif(OpenBSD)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/smbiosHelper.c
|
||||
@@ -986,7 +982,6 @@ elseif(APPLE)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_apple.m
|
||||
src/detection/camera/camera_apple.m
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/apple/cf_helpers.c
|
||||
src/util/apple/osascript.m
|
||||
src/util/apple/smc_temps.c
|
||||
@@ -1056,7 +1051,6 @@ elseif(WIN32)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_windows.c
|
||||
src/detection/camera/camera_windows.cpp
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/windows/getline.c
|
||||
src/util/windows/com.cpp
|
||||
src/util/windows/registry.c
|
||||
@@ -1145,7 +1139,6 @@ elseif(SunOS)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_linux.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -1214,7 +1207,6 @@ elseif(Haiku)
|
||||
src/detection/de/de_nosupport.c
|
||||
src/detection/wmtheme/wmtheme_nosupport.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
src/util/haiku/version.cpp
|
||||
@@ -1294,7 +1286,6 @@ elseif(GNU)
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_nosupport.c
|
||||
src/detection/zpool/zpool_nosupport.c
|
||||
src/util/platform/FFPlatform_unix.c
|
||||
src/util/binary_linux.c
|
||||
)
|
||||
@@ -1348,7 +1339,7 @@ endif()
|
||||
|
||||
# Used for dlopen finding dylibs installed by homebrew
|
||||
# `/opt/homebrew/lib` is not on in dlopen search path by default
|
||||
if(APPLE AND NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
if(APPLE AND BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,/opt/homebrew/lib -Wl,-rpath,/usr/local/lib")
|
||||
endif()
|
||||
|
||||
@@ -1611,24 +1602,6 @@ ff_lib_enable(PCIACCESS
|
||||
"pciaccess"
|
||||
"pciaccess"
|
||||
)
|
||||
# The system <libzfs.h> is only usable on SunOS. We provide our local copy of it so it's always available.
|
||||
if(ENABLE_LIBZFS)
|
||||
if(BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
else()
|
||||
set(CMAKE_REQUIRED_LIBRARIES_BACKUP ${CMAKE_REQUIRED_LIBRARIES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} zfs)
|
||||
check_function_exists("libzfs_init" LIBZFS_FOUND)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_BACKUP})
|
||||
if(NOT LIBZFS_FOUND)
|
||||
message(STATUS "Library: missing: LIBZFS")
|
||||
else()
|
||||
message(STATUS "Library: found LIBZFS")
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
target_link_libraries(libfastfetch PRIVATE zfs)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_THREADS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
|
||||
@@ -1643,6 +1616,15 @@ endif()
|
||||
if(ENABLE_EMBEDDED_AMDGPUIDS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_AMDGPUIDS=1)
|
||||
endif()
|
||||
if(ENABLE_LIBZFS)
|
||||
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_LIBZFS=1)
|
||||
|
||||
if(NOT BINARY_LINK_TYPE STREQUAL "dlopen")
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "zfs"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
target_link_libraries(libfastfetch
|
||||
@@ -1733,8 +1715,6 @@ elseif(SunOS)
|
||||
PRIVATE "socket"
|
||||
PRIVATE "kstat"
|
||||
PRIVATE "proc"
|
||||
PRIVATE "zfs"
|
||||
PRIVATE "nvpair"
|
||||
PRIVATE "devinfo"
|
||||
)
|
||||
elseif(GNU)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
[](https://deepwiki.com/fastfetch-cli/fastfetch)
|
||||
[](README-cn.md)
|
||||
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and SunOS.
|
||||
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and illumos (SunOS).
|
||||
|
||||
<img src="screenshots/example1.png" width="49%" align="left" />
|
||||
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
|
||||
@@ -37,7 +37,8 @@ Some distributions package outdated versions of fastfetch. Older versions receiv
|
||||
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
|
||||
</a>
|
||||
|
||||
* Debian: `apt install fastfetch` (for Debian 13 or newer)
|
||||
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (Ubuntu 22.04 or newer; latest version)
|
||||
* Debian / Ubuntu: `apt install fastfetch` (Debian 13 or newer; Ubuntu 25.04 or newer)
|
||||
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
|
||||
* Arch Linux: `pacman -S fastfetch`
|
||||
* Fedora: `dnf install fastfetch`
|
||||
|
||||
Vendored
+24
@@ -1,3 +1,27 @@
|
||||
fastfetch (2.56.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 18 Dec 2025 14:57:36 +0800
|
||||
|
||||
fastfetch (2.56.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.56.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Dec 2025 09:21:58 +0800
|
||||
|
||||
fastfetch (2.55.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.1
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 17 Nov 2025 10:15:44 +0800
|
||||
|
||||
fastfetch (2.55.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Update to 2.55.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 12 Nov 2025 09:15:24 +0800
|
||||
|
||||
fastfetch (2.54.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
|
||||
|
||||
* Fix building on plucky
|
||||
|
||||
@@ -1880,6 +1880,10 @@
|
||||
"temp": {
|
||||
"$ref": "#/$defs/temperature"
|
||||
},
|
||||
"tempSensor": {
|
||||
"description": "Set the temperature sensor to use for CPU temperature detection\n* Linux: `hwmon` or `thermal` path name (eg. `hwmon0`, `thermal_zone0)`\n* macOS: SMC sensor key (eg. `Tp01`)\n* Windows: thermal zone key (eg. `\\_TZ.CPUZ`)\n* FreeBSD: sysctl key (eg. `dev.cpu.0.temperature`)\n* NetBSD: sysmon sensor key (eg. `coretemp0`)",
|
||||
"type": "string"
|
||||
},
|
||||
"showPeCoreCount": {
|
||||
"description": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported",
|
||||
"type": "boolean",
|
||||
@@ -2111,6 +2115,11 @@
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"splitLines": {
|
||||
"description": "Set if the command output should be split into multiple lines",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "common/font.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -192,6 +194,21 @@ void ffFontInitValues(FFfont* font, const char* name, const char* size)
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style)
|
||||
{
|
||||
ffFontInit(font);
|
||||
|
||||
if (name) ffStrbufInitMove(&font->name, name);
|
||||
if (size) ffStrbufInitMove(&font->size, size);
|
||||
if (style)
|
||||
{
|
||||
FFstrbuf* styleBuf = FF_LIST_ADD(FFstrbuf, font->styles);
|
||||
ffStrbufInitMove(styleBuf, style);
|
||||
}
|
||||
|
||||
fontInitPretty(font);
|
||||
}
|
||||
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName)
|
||||
{
|
||||
const char* pspace = strrchr(rawName, ' ');
|
||||
|
||||
@@ -15,6 +15,7 @@ void ffFontInit(FFfont* font);
|
||||
void ffFontInitQt(FFfont* font, const char* data);
|
||||
void ffFontInitPango(FFfont* font, const char* data);
|
||||
void ffFontInitValues(FFfont* font, const char* name, const char* size);
|
||||
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style);
|
||||
void ffFontInitWithSpace(FFfont* font, const char* rawName);
|
||||
void ffFontDestroy(FFfont* font);
|
||||
|
||||
|
||||
+5
-6
@@ -49,7 +49,7 @@ static void defaultConfig(void)
|
||||
|
||||
void ffInitInstance(void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setlocale-wsetlocale?source=recommendat>
|
||||
setlocale(LC_ALL, ".UTF8");
|
||||
#else
|
||||
@@ -92,10 +92,6 @@ static void exitSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
resetConsole();
|
||||
exit(0);
|
||||
}
|
||||
static void chldSignalHandler(FF_MAYBE_UNUSED int signal)
|
||||
{
|
||||
// empty; used to interrupt the poll and read syscalls
|
||||
}
|
||||
#endif
|
||||
|
||||
void ffStart(void)
|
||||
@@ -121,7 +117,10 @@ void ffStart(void)
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
sigaction(SIGQUIT, &action, NULL);
|
||||
sigaction(SIGCHLD, &(struct sigaction) { .sa_handler = chldSignalHandler }, NULL);
|
||||
sigset_t newmask;
|
||||
sigemptyset(&newmask);
|
||||
sigaddset(&newmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &newmask, NULL);
|
||||
#endif
|
||||
|
||||
//reset everything to default before we start printing
|
||||
|
||||
+22
-6
@@ -83,6 +83,13 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer);
|
||||
FF_C_NONNULL(2, 3)
|
||||
bool ffAppendFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer);
|
||||
|
||||
FF_C_NONNULL(2)
|
||||
static inline bool ffReadFDBuffer(FFNativeFD fd, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufClear(buffer);
|
||||
return ffAppendFDBuffer(fd, buffer);
|
||||
}
|
||||
|
||||
FF_C_NONNULL(1, 2)
|
||||
static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
@@ -171,19 +178,27 @@ static inline void ffUnsuppressIO(bool* suppressed)
|
||||
|
||||
void ffListFilesRecursively(const char* path, bool pretty);
|
||||
|
||||
static inline bool ffIsValidNativeFD(FFNativeFD fd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return fd >= 0;
|
||||
#else
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
return fd != INVALID_HANDLE_VALUE && fd != NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
FF_C_NONNULL(1)
|
||||
static inline bool wrapClose(FFNativeFD* pfd)
|
||||
{
|
||||
assert(pfd);
|
||||
|
||||
#ifndef WIN32
|
||||
if (*pfd < 0)
|
||||
return false;
|
||||
if (!ffIsValidNativeFD(*pfd))
|
||||
return false;
|
||||
|
||||
#ifndef _WIN32
|
||||
close(*pfd);
|
||||
#else
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
|
||||
if (*pfd == NULL || *pfd == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
CloseHandle(*pfd);
|
||||
#endif
|
||||
|
||||
@@ -246,4 +261,5 @@ bool ffRemoveFile(const char* fileName);
|
||||
#ifdef _WIN32
|
||||
// Only O_RDONLY is supported
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory);
|
||||
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory);
|
||||
#endif
|
||||
|
||||
+35
-18
@@ -3,8 +3,8 @@
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "util/windows/nt.h"
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
static void createSubfolders(const char* fileName)
|
||||
{
|
||||
@@ -102,31 +102,48 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer)
|
||||
return ffAppendFDBuffer(handle, buffer);
|
||||
}
|
||||
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
|
||||
HANDLE openatW(HANDLE dfd, const wchar_t* fileName, uint16_t fileNameLen, bool directory)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
UNICODE_STRING fileNameW;
|
||||
ret = RtlAnsiStringToUnicodeString(&fileNameW, &(ANSI_STRING) {
|
||||
.Length = (USHORT) strlen(fileName),
|
||||
.Buffer = (PCHAR) fileName
|
||||
}, TRUE);
|
||||
if (!NT_SUCCESS(ret)) return INVALID_HANDLE_VALUE;
|
||||
assert(fileNameLen <= 0x7FFF);
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hFile;
|
||||
HANDLE hFile;
|
||||
IO_STATUS_BLOCK iosb = {};
|
||||
ret = NtOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
|
||||
.Length = sizeof(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = dfd,
|
||||
.ObjectName = &fileNameW,
|
||||
}, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE));
|
||||
RtlFreeUnicodeString(&fileNameW);
|
||||
|
||||
if(!NT_SUCCESS(ret) || iosb.Information != FILE_OPENED)
|
||||
if(!NT_SUCCESS(NtOpenFile(&hFile,
|
||||
(directory ? FILE_LIST_DIRECTORY | FILE_TRAVERSE : FILE_READ_DATA | FILE_READ_EA) | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) {
|
||||
.Length = sizeof(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = dfd,
|
||||
.ObjectName = &(UNICODE_STRING) {
|
||||
.Buffer = (PWSTR) fileName,
|
||||
.Length = fileNameLen * (USHORT) sizeof(wchar_t),
|
||||
.MaximumLength = (fileNameLen + 1) * (USHORT) sizeof(wchar_t),
|
||||
},
|
||||
.Attributes = OBJ_CASE_INSENSITIVE,
|
||||
},
|
||||
&iosb,
|
||||
FILE_SHARE_READ | (directory ? FILE_SHARE_WRITE | FILE_SHARE_DELETE : 0),
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE)
|
||||
)))
|
||||
return INVALID_HANDLE_VALUE;
|
||||
|
||||
return hFile;
|
||||
}
|
||||
|
||||
HANDLE openat(HANDLE dfd, const char* fileName, bool directory)
|
||||
{
|
||||
wchar_t fileNameW[MAX_PATH];
|
||||
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName, -1, fileNameW, ARRAY_SIZE(fileNameW));
|
||||
if (len == 0) return INVALID_HANDLE_VALUE;
|
||||
// Implies `fileNameW[len] = L'\0';` and `len` includes the null terminator
|
||||
|
||||
for (int i = 0; i < len - 1; ++i)
|
||||
{
|
||||
if (fileNameW[i] == L'/')
|
||||
fileNameW[i] = L'\\';
|
||||
}
|
||||
|
||||
return openatW(dfd, fileNameW, (uint16_t)(len - 1), directory);
|
||||
}
|
||||
|
||||
bool ffAppendFileBufferRelative(HANDLE dfd, const char* fileName, FFstrbuf* buffer)
|
||||
{
|
||||
HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false);
|
||||
|
||||
@@ -184,30 +184,13 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) timeout (try increasing --processing-timeout)";
|
||||
}
|
||||
else if (pollret < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
{
|
||||
// The child process has been terminated. See `chldSignalHandler` in `common/init.c`
|
||||
if (waitpid(childPid, NULL, WNOHANG) == childPid)
|
||||
{
|
||||
// Read remaining data from the pipe
|
||||
fcntl(childPipeFd, F_SETFL, O_CLOEXEC | O_NONBLOCK);
|
||||
childPid = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error: not EINTR";
|
||||
}
|
||||
}
|
||||
else if (pollfd.revents & POLLERR)
|
||||
else if (pollret < 0 || (pollfd.revents & POLLERR))
|
||||
{
|
||||
kill(childPid, SIGTERM);
|
||||
waitpid(childPid, NULL, 0);
|
||||
return "poll(&pollfd, 1, timeout) error: POLLERR";
|
||||
return pollret < 0
|
||||
? "poll(&pollfd, 1, timeout) error: pollret < 0"
|
||||
: "poll(&pollfd, 1, timeout) error: pollfd.revents & POLLERR";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,12 +212,7 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
|
||||
return NULL;
|
||||
}
|
||||
else if (nRead < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
return NULL;
|
||||
else
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return "read(childPipeFd, str, FF_PIPE_BUFSIZ) failed";
|
||||
@@ -295,6 +273,10 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons
|
||||
ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length);
|
||||
ffStrbufAppendNS(exePath, (uint32_t)length, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSetS(exePath, filePath);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@
|
||||
"short": "c",
|
||||
"long": "config",
|
||||
"desc": "Specify the config file or preset to load",
|
||||
"remark": "The file will be searched according to the order shown by \"fastfetch --list-config-paths\". Use \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for more info",
|
||||
"remark": "The file will be searched according to the order shown by \"fastfetch --list-config-paths\". Use \"-\" to read config from stdin or \"none\" to disable further config loading. See also https://github.com/fastfetch-cli/fastfetch/wiki/Configuration for more info",
|
||||
"arg": {
|
||||
"type": "config"
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ static const char* detectWithBacklight(FFlist* result)
|
||||
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
|
||||
ffStrbufSubstrBeforeLastC(&backlightDir, '/');
|
||||
ffStrbufAppendS(&backlightDir, "/device");
|
||||
ffStrbufInitA(&brightness->name, PATH_MAX + 1);
|
||||
ffStrbufInitA(&brightness->name, PATH_MAX);
|
||||
if(realpath(backlightDir.chars, brightness->name.chars))
|
||||
{
|
||||
ffStrbufRecalculateLength(&brightness->name);
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef struct FFCPUResult
|
||||
uint16_t coresPhysical;
|
||||
uint16_t coresLogical;
|
||||
uint16_t coresOnline;
|
||||
uint16_t numaNodes;
|
||||
|
||||
uint32_t frequencyBase; // GHz
|
||||
uint32_t frequencyMax; // GHz
|
||||
|
||||
@@ -3,26 +3,34 @@
|
||||
#include "util/apple/smc_temps.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static double detectCpuTemp(const FFstrbuf* cpuName)
|
||||
static double detectCpuTemp(const FFCPUOptions* options, const FFstrbuf* cpuName)
|
||||
{
|
||||
double result = 0;
|
||||
|
||||
const char* error = NULL;
|
||||
if (ffStrbufStartsWithS(cpuName, "Apple M"))
|
||||
{
|
||||
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
|
||||
{
|
||||
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
|
||||
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
|
||||
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
|
||||
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
|
||||
default: error = "Unsupported Apple Silicon CPU";
|
||||
}
|
||||
}
|
||||
else // PPC?
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
|
||||
|
||||
if(error)
|
||||
if (options->tempSensor.length)
|
||||
{
|
||||
error = ffDetectSmcSpecificTemp(options->tempSensor.chars, &result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ffStrbufStartsWithS(cpuName, "Apple M"))
|
||||
{
|
||||
switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10))
|
||||
{
|
||||
case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break;
|
||||
case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break;
|
||||
case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break;
|
||||
case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break;
|
||||
default: error = "Unsupported Apple Silicon CPU";
|
||||
}
|
||||
}
|
||||
else // PPC?
|
||||
error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result);
|
||||
}
|
||||
|
||||
if (error)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return result;
|
||||
@@ -130,7 +138,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectFrequency(cpu);
|
||||
if (options->showPeCoreCount) detectCoreCount(cpu);
|
||||
|
||||
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
|
||||
cpu->temperature = options->temp ? detectCpuTemp(options, &cpu->name) : FF_CPU_TEMP_UNSET;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+22
-20
@@ -8,22 +8,26 @@
|
||||
#define FF_HAVE_CPUSET 1
|
||||
#endif
|
||||
|
||||
static const char* detectCpuTemp(double* current)
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
|
||||
{
|
||||
int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed";
|
||||
|
||||
// In tenth of degrees Kelvin
|
||||
*current = (double) temp / 10 - 273.15;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectThermalTemp(double* current)
|
||||
{
|
||||
int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed";
|
||||
int temp;
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
temp = ffSysctlGetInt(options->tempSensor.chars, -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(options->tempSensor) failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
{
|
||||
// Thermal zone temperature
|
||||
temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999);
|
||||
if (temp == -999999)
|
||||
return "ffSysctlGetInt(\"dev.cpu.0.temperature\" or \"hw.acpi.thermal.tz0.temperature\") failed";
|
||||
}
|
||||
}
|
||||
|
||||
// In tenth of degrees Kelvin
|
||||
*current = (double) temp / 10 - 273.15;
|
||||
@@ -94,11 +98,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (detectCpuTemp(&cpu->temperature) != NULL)
|
||||
detectThermalTemp(&cpu->temperature);
|
||||
}
|
||||
if (options->temp) detectCpuTemp(options, &cpu->temperature);
|
||||
|
||||
cpu->numaNodes = (uint16_t) ffSysctlGetInt("vm.ndomains", 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "common/properties.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/path.h"
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <stdlib.h>
|
||||
@@ -13,6 +14,22 @@
|
||||
|
||||
#define FF_CPUINFO_PATH "/proc/cpuinfo"
|
||||
|
||||
#ifndef O_PATH
|
||||
#define O_PATH 0
|
||||
#endif
|
||||
|
||||
static double readTempFile(int dfd, const char* filename, FFstrbuf* buffer)
|
||||
{
|
||||
if (filename ? !ffReadFileBufferRelative(dfd, filename, buffer) : !ffReadFDBuffer(dfd, buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET); // millidegree Celsius
|
||||
if (value == FF_CPU_TEMP_UNSET)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return value / 1000.;
|
||||
}
|
||||
|
||||
static double parseTZDir(int dfd, FFstrbuf* buffer)
|
||||
{
|
||||
if (!ffReadFileBufferRelative(dfd, "type", buffer))
|
||||
@@ -26,18 +43,12 @@ static double parseTZDir(int dfd, FFstrbuf* buffer)
|
||||
true
|
||||
) return FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (!ffReadFileBufferRelative(dfd, "temp", buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius
|
||||
if (value == FF_CPU_TEMP_UNSET)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return value / 1000.;
|
||||
return readTempFile(dfd, "temp", buffer);
|
||||
}
|
||||
|
||||
static double parseHwmonDir(int dfd, FFstrbuf* buffer)
|
||||
{
|
||||
//https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||
if (!ffReadFileBufferRelative(dfd, "name", buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
@@ -53,25 +64,64 @@ static double parseHwmonDir(int dfd, FFstrbuf* buffer)
|
||||
true
|
||||
) return FF_CPU_TEMP_UNSET;
|
||||
|
||||
//https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||
if (!ffReadFileBufferRelative(dfd, "temp1_input", buffer))
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
double value = ffStrbufToDouble(buffer, FF_CPU_TEMP_UNSET);// millidegree Celsius
|
||||
if (value == FF_CPU_TEMP_UNSET)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return value / 1000.;
|
||||
return readTempFile(dfd, "temp1_input", buffer);
|
||||
}
|
||||
|
||||
static double detectCPUTemp(void)
|
||||
static double detectCPUTemp(const FFCPUOptions* options)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int subfd = -1;
|
||||
const char* fileName = NULL;
|
||||
if (ffStrbufStartsWithS(&options->tempSensor, "hwmon") && ffCharIsDigit(options->tempSensor.chars[strlen("hwmon")]))
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/hwmon/", O_PATH | O_CLOEXEC);
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp1_input";
|
||||
else
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&options->tempSensor, "thermal_zone") && ffCharIsDigit(options->tempSensor.chars[strlen("thermal_zone")]))
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/thermal/", O_PATH | O_CLOEXEC);
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp";
|
||||
else
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&options->tempSensor, "cputemp.") && ffCharIsDigit(options->tempSensor.chars[strlen("cputemp.")]))
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open("/sys/class/platform/", O_PATH | O_CLOEXEC);
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp1_input";
|
||||
else
|
||||
subfd = openat(dfd, options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
else if (ffIsAbsolutePath(options->tempSensor.chars))
|
||||
{
|
||||
subfd = open(options->tempSensor.chars, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (subfd >= 0)
|
||||
fileName = "temp1_input";
|
||||
else
|
||||
subfd = open(options->tempSensor.chars, O_RDONLY | O_CLOEXEC);
|
||||
}
|
||||
if (subfd < 0)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
|
||||
return readTempFile(subfd, fileName, &buffer);
|
||||
}
|
||||
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/hwmon/");
|
||||
if(dirp)
|
||||
{
|
||||
int dfd = dirfd(dirp);
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
@@ -138,6 +188,21 @@ static double detectCPUTemp(void)
|
||||
return FF_CPU_TEMP_UNSET;
|
||||
}
|
||||
|
||||
static void detectNumaNodes(FFCPUResult* cpu)
|
||||
{
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/sys/devices/system/node/");
|
||||
if (!dir) return;
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
if (ffStrStartsWith(entry->d_name, "node") && ffCharIsDigit(entry->d_name[strlen("node")]))
|
||||
cpu->numaNodes++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "common/settings.h"
|
||||
|
||||
@@ -568,6 +633,8 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
|
||||
if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0)
|
||||
cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0);
|
||||
|
||||
detectNumaNodes(cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -799,9 +866,9 @@ FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const c
|
||||
char* pend;
|
||||
unsigned long id = strtoul(p, &pend, 10);
|
||||
if (__builtin_expect(id > 64, false))
|
||||
high |= 1 << (id - 64);
|
||||
high |= 1UL << (id - 64);
|
||||
else
|
||||
low |= 1 << id;
|
||||
low |= 1UL << id;
|
||||
p = pend;
|
||||
}
|
||||
|
||||
@@ -877,6 +944,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
|
||||
detectPhysicalCores(cpu);
|
||||
|
||||
ffCPUDetectByCpuid(cpu);
|
||||
detectNumaNodes(cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -884,7 +952,7 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET;
|
||||
cpu->temperature = options->temp ? detectCPUTemp(options) : FF_CPU_TEMP_UNSET;
|
||||
|
||||
#if __x86_64__ || __i386__
|
||||
return detectCPUX86(options, cpu);
|
||||
|
||||
@@ -16,7 +16,7 @@ static void freePropDict(prop_dictionary_t* pdict)
|
||||
prop_object_release(*pdict);
|
||||
}
|
||||
|
||||
static const char* detectCpuTemp(double* current)
|
||||
static const char* detectCpuTemp(const FFCPUOptions* options, double* current)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY | O_CLOEXEC) failed";
|
||||
@@ -25,11 +25,21 @@ static const char* detectCpuTemp(double* current)
|
||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
|
||||
return "prop_dictionary_recv_ioctl(ENVSYS_GETDICTIONARY) failed";
|
||||
|
||||
prop_array_t array = prop_dictionary_get(root, "coretemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "viac7temp0");
|
||||
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
|
||||
if (!array) return "No temp data found in root dictionary";
|
||||
prop_array_t array;
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
array = prop_dictionary_get(root, options->tempSensor.chars);
|
||||
if (!array) return "No temp data found in specified sensor";
|
||||
}
|
||||
else
|
||||
{
|
||||
array = prop_dictionary_get(root, "coretemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "amdzentemp0");
|
||||
if (!array) array = prop_dictionary_get(root, "viac7temp0");
|
||||
if (!array) array = prop_dictionary_get(root, "acpitz0"); // Thermal Zones
|
||||
if (!array) return "No temp data found in root dictionary";
|
||||
}
|
||||
|
||||
if (prop_array_count(array) != 2)
|
||||
return "Unexpected `xtemp0` data";
|
||||
@@ -73,7 +83,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp) detectCpuTemp(&cpu->temperature);
|
||||
if (options->temp) detectCpuTemp(options, &cpu->temperature);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/sensors.h>
|
||||
|
||||
static const char* detectCPUTemp(FFCPUResult* cpu)
|
||||
static const char* detectCPUTemp(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
|
||||
|
||||
@@ -23,8 +23,16 @@ static const char* detectCPUTemp(FFCPUResult* cpu)
|
||||
return "sysctl(sensordev) failed";
|
||||
}
|
||||
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu"))
|
||||
continue;
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
if (!ffStrbufEqualS(&options->tempSensor, sensordev.xname))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu"))
|
||||
continue;
|
||||
}
|
||||
|
||||
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
|
||||
{
|
||||
@@ -62,7 +70,7 @@ const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
if (options->temp) detectCPUTemp(cpu);
|
||||
if (options->temp) detectCPUTemp(options, cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
#include "util/stringUtils.h"
|
||||
#include <kstat.h>
|
||||
|
||||
static const char* detectCPUTempByKstat(kstat_ctl_t* kc, FFCPUResult* cpu)
|
||||
static const char* detectCPUTempByKstat(const FFCPUOptions* options, kstat_ctl_t* kc, FFCPUResult* cpu)
|
||||
{
|
||||
const char* possibleModules[] = {"temperature", "cpu_temp", "acpi_thermal", NULL};
|
||||
|
||||
if (options->tempSensor.length > 0) {
|
||||
possibleModules[0] = options->tempSensor.chars;
|
||||
possibleModules[1] = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; possibleModules[i] != NULL; i++) {
|
||||
kstat_t* ks = kstat_lookup(kc, possibleModules[i], -1, NULL);
|
||||
if (ks && kstat_read(kc, ks, NULL) >= 0) {
|
||||
@@ -141,7 +146,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (detectCPUTempByKstat(kc, cpu) != NULL)
|
||||
if (detectCPUTempByKstat(options, kc, cpu) != NULL)
|
||||
detectCPUTempByIpmiTool(cpu);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
|
||||
}
|
||||
}
|
||||
|
||||
const char* detectThermalTemp(double* result)
|
||||
const char* detectThermalTemp(const FFCPUOptions* options, double* result)
|
||||
{
|
||||
struct FFPerfQuerySpec
|
||||
{
|
||||
@@ -35,6 +35,14 @@ const char* detectThermalTemp(double* result)
|
||||
.Name = L"\\_TZ.CPUZ", // The standard(?) instance name for CPU temperature in the thermal provider
|
||||
};
|
||||
|
||||
if (options->tempSensor.length > 0)
|
||||
{
|
||||
int written = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, options->tempSensor.chars, (int) options->tempSensor.length, querySpec.Name, (int)(ARRAY_SIZE(querySpec.Name) - 1));
|
||||
if (written == 0)
|
||||
return "Invalid temp sensor string";
|
||||
querySpec.Name[written] = L'\0';
|
||||
}
|
||||
|
||||
DWORD dataSize = 0;
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
|
||||
return "PerfEnumerateCounterSetInstances() failed";
|
||||
@@ -62,6 +70,9 @@ const char* detectThermalTemp(double* result)
|
||||
|
||||
if (dataSize == 0)
|
||||
{
|
||||
if (options->tempSensor.length > 0)
|
||||
return "Unable to find CPU sensor";
|
||||
|
||||
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pHead + sizeof(*pHead));
|
||||
wcscpy(querySpec.Name, instanceName); // Use the first instance name if the specific one is not found
|
||||
}
|
||||
@@ -230,6 +241,8 @@ static const char* detectNCores(FFCPUResult* cpu)
|
||||
++cpu->coresPhysical;
|
||||
else if (ptr->Relationship == RelationProcessorPackage)
|
||||
++cpu->packages;
|
||||
else if (ptr->Relationship == RelationNumaNode)
|
||||
++cpu->numaNodes;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -299,7 +312,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
|
||||
if(options->temp)
|
||||
detectThermalTemp(&cpu->temperature);
|
||||
detectThermalTemp(options, &cpu->temperature);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result)
|
||||
if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed";
|
||||
|
||||
// macOS provides the global system cache line size
|
||||
uint32_t lineSize = (uint32_t) ffSysctlGetInt("hw.cachelinesize", 0);
|
||||
uint32_t lineSize = (uint32_t) ffSysctlGetInt64("hw.cachelinesize", 0);
|
||||
|
||||
char sysctlKey[128] = "hw.perflevelN.";
|
||||
char* pNum = sysctlKey + strlen("hw.perflevel");
|
||||
|
||||
@@ -140,6 +140,61 @@ static bool detectWithGetprop(FFDisplayServerResult* ds)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool detectDE(FFDisplayServerResult* ds)
|
||||
{
|
||||
if (ffSettingsGetAndroidProperty("ro.vivo.os.build.display.id", &ds->dePrettyName)) // OriginOS 6
|
||||
{
|
||||
ffStrbufAppendC(&ds->dePrettyName, ' ');
|
||||
ffSettingsGetAndroidProperty("ro.vivo.product.version", &ds->dePrettyName); // PD2505D_xxx
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.build.version.magic", &ds->dePrettyName) ||
|
||||
ffSettingsGetAndroidProperty("ro.build.version.emui", &ds->dePrettyName))
|
||||
{
|
||||
ffStrbufReplaceAllC(&ds->dePrettyName, '_', ' ');
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.mi.os.version.name", &ds->dePrettyName))
|
||||
{
|
||||
// MiUI like
|
||||
ffStrbufClear(&ds->dePrettyName);
|
||||
ffSettingsGetAndroidProperty("ro.build.version.incremental", &ds->dePrettyName); // Detail version number
|
||||
if (ffStrbufStartsWithS(&ds->dePrettyName, "OS"))
|
||||
{
|
||||
ds->dePrettyName.chars[0] = 'S';
|
||||
ds->dePrettyName.chars[1] = ' ';
|
||||
ffStrbufPrependS(&ds->dePrettyName, "HyperO");
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&ds->dePrettyName, "V"))
|
||||
{
|
||||
ds->dePrettyName.chars[0] = ' ';
|
||||
ffStrbufPrependS(&ds->dePrettyName, "MiUI");
|
||||
}
|
||||
else
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "MiUI");
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.build.version.oplusrom", &ds->dePrettyName))
|
||||
{
|
||||
if (ffStrbufStartsWithS(&ds->dePrettyName, "V"))
|
||||
ffStrbufSubstrAfter(&ds->dePrettyName, 0);
|
||||
ffStrbufPrependS(&ds->dePrettyName, "ColorOS");
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.oxygen.version", &ds->dePrettyName))
|
||||
{
|
||||
ffStrbufPrependS(&ds->dePrettyName, "OxygenOS");
|
||||
return true;
|
||||
}
|
||||
if (ffSettingsGetAndroidProperty("ro.build.display.id", &ds->dePrettyName) && ffStrbufStartsWithS(&ds->dePrettyName, "RedMagicOS"))
|
||||
{
|
||||
ffStrbufInsertNC(&ds->dePrettyName, strlen("RedMagicOS"), 1, ' ');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
{
|
||||
const char* error = ffdsConnectXcbRandr(ds);
|
||||
@@ -158,4 +213,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
|
||||
if (!detectWithGetprop(ds))
|
||||
detectWithDumpsys(ds);
|
||||
|
||||
detectDE(ds);
|
||||
}
|
||||
|
||||
@@ -239,6 +239,11 @@ enum kde_output_device_v2_capability {
|
||||
* @since 17
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_SHARPNESS = 0x1000,
|
||||
/**
|
||||
* if this outputdevice supports custom modes
|
||||
* @since 18
|
||||
*/
|
||||
KDE_OUTPUT_DEVICE_V2_CAPABILITY_CUSTOM_MODES = 0x2000,
|
||||
};
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
@@ -280,6 +285,10 @@ enum kde_output_device_v2_capability {
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_SHARPNESS_SINCE_VERSION 17
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_CAPABILITY_CUSTOM_MODES_SINCE_VERSION 18
|
||||
#endif /* KDE_OUTPUT_DEVICE_V2_CAPABILITY_ENUM */
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_V2_VRR_POLICY_ENUM
|
||||
@@ -794,6 +803,23 @@ struct kde_output_device_v2_listener {
|
||||
void (*sharpness)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t sharpness);
|
||||
/**
|
||||
* output priority
|
||||
*
|
||||
* Describes the position of the output in the output order list,
|
||||
* with lower values being earlier in the list. There's no specific
|
||||
* value the list has to start at, this value is only used in
|
||||
* sorting outputs.
|
||||
*
|
||||
* Note that the output order protocol is not sufficient for this,
|
||||
* as an output may not be in the output order if it's disabled or
|
||||
* mirroring another screen.
|
||||
* @param priority priority
|
||||
* @since 18
|
||||
*/
|
||||
void (*priority)(void *data,
|
||||
struct kde_output_device_v2 *kde_output_device_v2,
|
||||
uint32_t priority);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -943,6 +969,10 @@ kde_output_device_v2_add_listener(struct kde_output_device_v2 *kde_output_device
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_SHARPNESS_SINCE_VERSION 17
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_V2_PRIORITY_SINCE_VERSION 18
|
||||
|
||||
|
||||
/** @ingroup iface_kde_output_device_v2 */
|
||||
@@ -972,6 +1002,18 @@ kde_output_device_v2_destroy(struct kde_output_device_v2 *kde_output_device_v2)
|
||||
wl_proxy_destroy((struct wl_proxy *) kde_output_device_v2);
|
||||
}
|
||||
|
||||
#ifndef KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
* mode flags
|
||||
*/
|
||||
enum kde_output_device_mode_v2_flags {
|
||||
KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_CUSTOM = 0x1,
|
||||
KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_REDUCED_BLANKING = 0x2,
|
||||
};
|
||||
#endif /* KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_ENUM */
|
||||
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
* @struct kde_output_device_mode_v2_listener
|
||||
@@ -1017,6 +1059,15 @@ struct kde_output_device_mode_v2_listener {
|
||||
*/
|
||||
void (*removed)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2);
|
||||
/**
|
||||
* mode flags
|
||||
*
|
||||
* This event describes the mode's flags.
|
||||
* @since 19
|
||||
*/
|
||||
void (*flags)(void *data,
|
||||
struct kde_output_device_mode_v2 *kde_output_device_mode_v2,
|
||||
uint32_t flags);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1046,6 +1097,10 @@ kde_output_device_mode_v2_add_listener(struct kde_output_device_mode_v2 *kde_out
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_REMOVED_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_kde_output_device_mode_v2
|
||||
*/
|
||||
#define KDE_OUTPUT_DEVICE_MODE_V2_FLAGS_SINCE_VERSION 19
|
||||
|
||||
|
||||
/** @ingroup iface_kde_output_device_mode_v2 */
|
||||
|
||||
@@ -67,12 +67,13 @@ static const struct wl_message kde_output_device_v2_events[] = {
|
||||
{ "automatic_max_bits_per_color_limit", "15u", kde_output_device_v2_types + 0 },
|
||||
{ "edr_policy", "16u", kde_output_device_v2_types + 0 },
|
||||
{ "sharpness", "17u", kde_output_device_v2_types + 0 },
|
||||
{ "priority", "18u", kde_output_device_v2_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface kde_output_device_v2_interface = {
|
||||
"kde_output_device_v2", 17,
|
||||
"kde_output_device_v2", 19,
|
||||
0, NULL,
|
||||
34, kde_output_device_v2_events,
|
||||
35, kde_output_device_v2_events,
|
||||
};
|
||||
|
||||
static const struct wl_message kde_output_device_mode_v2_events[] = {
|
||||
@@ -80,12 +81,13 @@ static const struct wl_message kde_output_device_mode_v2_events[] = {
|
||||
{ "refresh", "i", kde_output_device_v2_types + 0 },
|
||||
{ "preferred", "", kde_output_device_v2_types + 0 },
|
||||
{ "removed", "", kde_output_device_v2_types + 0 },
|
||||
{ "flags", "19u", kde_output_device_v2_types + 0 },
|
||||
};
|
||||
|
||||
WL_EXPORT const struct wl_interface kde_output_device_mode_v2_interface = {
|
||||
"kde_output_device_mode_v2", 1,
|
||||
"kde_output_device_mode_v2", 19,
|
||||
0, NULL,
|
||||
4, kde_output_device_mode_v2_events,
|
||||
5, kde_output_device_mode_v2_events,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -178,6 +178,7 @@ static struct kde_output_device_v2_listener outputListener = {
|
||||
.automatic_max_bits_per_color_limit = (void*) stubListener,
|
||||
.edr_policy = (void*) stubListener,
|
||||
.sharpness = (void*) stubListener,
|
||||
.priority = (void*) stubListener,
|
||||
};
|
||||
|
||||
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
|
||||
|
||||
@@ -15,11 +15,18 @@ extern const char* FF_GPU_VENDOR_NAME_AMD;
|
||||
extern const char* FF_GPU_VENDOR_NAME_INTEL;
|
||||
extern const char* FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
extern const char* FF_GPU_VENDOR_NAME_MTHREADS;
|
||||
extern const char* FF_GPU_VENDOR_NAME_QUALCOMM;
|
||||
extern const char* FF_GPU_VENDOR_NAME_MTK;
|
||||
extern const char* FF_GPU_VENDOR_NAME_VMWARE;
|
||||
extern const char* FF_GPU_VENDOR_NAME_PARALLEL;
|
||||
extern const char* FF_GPU_VENDOR_NAME_MICROSOFT;
|
||||
extern const char* FF_GPU_VENDOR_NAME_REDHAT;
|
||||
extern const char* FF_GPU_VENDOR_NAME_ORACLE;
|
||||
extern const char* FF_GPU_VENDOR_NAME_BROADCOM;
|
||||
extern const char* FF_GPU_VENDOR_NAME_LOONGSON;
|
||||
extern const char* FF_GPU_VENDOR_NAME_JINGJIA_MICRO;
|
||||
extern const char* FF_GPU_VENDOR_NAME_HUAWEI;
|
||||
extern const char* FF_GPU_VENDOR_NAME_ZHAOXIN;
|
||||
|
||||
typedef struct FFGPUMemory
|
||||
{
|
||||
|
||||
@@ -57,7 +57,7 @@ static const char* detectFrequency(FFGPUResult* gpu)
|
||||
if (!freqProperty || CFGetTypeID(freqProperty) != CFDataGetTypeID())
|
||||
return "\"voltage-states9-sram\" in \"pmgr\" is not found";
|
||||
|
||||
// voltage-states5-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
|
||||
// voltage-states9-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
|
||||
CFIndex propLength = CFDataGetLength(freqProperty);
|
||||
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0)
|
||||
return "Invalid \"voltage-states9-sram\" length";
|
||||
|
||||
@@ -153,7 +153,7 @@ const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, con
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(gpu, renderPath);
|
||||
FF_UNUSED(options, gpu, renderPath);
|
||||
return "Fastfetch is compiled without libdrm support";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
#include "detection/gpu/gpu_driver_specific.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "modules/gpu/option.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef FF_HAVE_DRM_AMDGPU
|
||||
#include <amdgpu.h>
|
||||
@@ -120,7 +123,7 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
FF_UNUSED(gpu, drmKey, buffer);
|
||||
FF_UNUSED(options, gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with drm support";
|
||||
#endif
|
||||
}
|
||||
@@ -263,7 +266,7 @@ static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey,
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* pciDetectNouveauSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
static const char* pciDetectTempGeneral(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
if (options->temp)
|
||||
{
|
||||
@@ -306,6 +309,48 @@ static const char* drmDetectNouveauSpecific(FFGPUResult* gpu, const char* drmKey
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char* pciDetectZxSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
|
||||
const uint32_t pciDirLen = pciDir->length;
|
||||
ffStrbufAppendS(pciDir, "/zx_info/eclk");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, FF_GPU_FREQUENCY_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
if (options->driverSpecific)
|
||||
{
|
||||
ffStrbufAppendS(pciDir, "/zx_info/engine_3d_usage");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->coreUsage = ffStrbufToDouble(buffer, FF_GPU_CORE_USAGE_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
ffStrbufAppendS(pciDir, "/zx_info/fb_size");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->shared.total = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET)
|
||||
{
|
||||
gpu->shared.total *= 1024 * 1024;
|
||||
|
||||
ffStrbufAppendS(pciDir, "/zx_info/free_fb_mem");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->shared.used = ffStrbufToUInt(buffer, FF_GPU_VMEM_SIZE_UNSET);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET)
|
||||
{
|
||||
gpu->shared.used *= 1024 * 1024;
|
||||
gpu->shared.used = gpu->shared.total - gpu->shared.used;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
|
||||
{
|
||||
const uint32_t drmDirPathLength = deviceDir->length;
|
||||
@@ -417,10 +462,15 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && ffStrbufEqualS(&gpu->driver, "nouveau"))
|
||||
{
|
||||
pciDetectNouveauSpecific(options, gpu, deviceDir, buffer);
|
||||
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
|
||||
if (options->driverSpecific && drmKey)
|
||||
drmDetectNouveauSpecific(gpu, drmKey, buffer);
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_ZHAOXIN && ffStrbufStartsWithS(&gpu->driver, "zx"))
|
||||
{
|
||||
pciDetectTempGeneral(options, gpu, deviceDir, buffer);
|
||||
pciDetectZxSpecific(options, gpu, deviceDir, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
@@ -555,7 +605,7 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
|
||||
if (ffStrbufStartsWithS(&buffer, "pci:"))
|
||||
detectPci(options, gpus, &buffer, &drmDir, entry->d_name);
|
||||
else if (ffStrbufStartsWithS(&buffer, "of:"))
|
||||
else if (ffStrbufStartsWithS(&buffer, "of:")) // Open Firmware
|
||||
detectOf(gpus, &buffer, &drmDir, entry->d_name);
|
||||
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
|
||||
@@ -45,7 +45,8 @@ const char* getOthersByIokit(FFHostResult* host)
|
||||
|
||||
const char* ffDetectHost(FFHostResult* host)
|
||||
{
|
||||
const char* error = ffSysctlGetString("hw.model", &host->family);
|
||||
const char* error = ffSysctlGetString("hw.product", &host->family);
|
||||
if (error) error = ffSysctlGetString("hw.model", &host->family);
|
||||
if (error) return error;
|
||||
|
||||
ffStrbufSetStatic(&host->name, ffHostGetMacProductNameWithHwModel(&host->family));
|
||||
|
||||
@@ -8,24 +8,25 @@
|
||||
const char* ffDetectMemory(FFMemoryResult* ram)
|
||||
{
|
||||
size_t length = sizeof(ram->bytesTotal);
|
||||
if (sysctl((int[]){ CTL_HW, HW_MEMSIZE }, 2, &ram->bytesTotal, &length, NULL, 0))
|
||||
if (sysctl((int[]){ CTL_HW, HW_MEMSIZE }, 2, &ram->bytesTotal, &length, NULL, 0) != 0)
|
||||
return "Failed to read hw.memsize";
|
||||
uint64_t usableMemory = 0;
|
||||
length = sizeof(usableMemory);
|
||||
if (sysctlbyname("hw.memsize_usable", &usableMemory, &length, NULL, 0) != 0)
|
||||
usableMemory = ram->bytesTotal;
|
||||
|
||||
mach_msg_type_number_t count = HOST_VM_INFO64_COUNT;
|
||||
vm_statistics64_data_t vmstat;
|
||||
if(host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) (&vmstat), &count) != KERN_SUCCESS)
|
||||
return "Failed to read host_statistics64";
|
||||
|
||||
// https://github.com/exelban/stats/blob/master/Modules/RAM/readers.swift#L56
|
||||
ram->bytesUsed = ((uint64_t)
|
||||
+ vmstat.active_count
|
||||
+ vmstat.inactive_count
|
||||
+ vmstat.speculative_count
|
||||
+ vmstat.wire_count
|
||||
+ vmstat.compressor_page_count
|
||||
- vmstat.purgeable_count
|
||||
- vmstat.external_page_count
|
||||
) * instance.state.platform.sysinfo.pageSize;
|
||||
uint64_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
uint64_t appMemory = vmstat.internal_page_count * pageSize;
|
||||
uint64_t wiredMemory = vmstat.wire_count * pageSize;
|
||||
uint64_t compressed = vmstat.compressor_page_count * pageSize;
|
||||
uint64_t reserved = ram->bytesTotal - usableMemory;
|
||||
|
||||
ram->bytesUsed = appMemory + wiredMemory + compressed + reserved;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef struct FFPackagesResult
|
||||
uint32_t guixUser;
|
||||
uint32_t hpkgSystem;
|
||||
uint32_t hpkgUser;
|
||||
uint32_t kiss;
|
||||
uint32_t linglong;
|
||||
uint32_t lpkg;
|
||||
uint32_t lpkgbuild;
|
||||
|
||||
@@ -420,6 +420,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_EMERGE_BIT)) packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_EOPKG_BIT)) packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", true);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpakPackages(baseDir, "/var/lib");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_KISS_BIT)) packageCounts->kiss += getNumElements(baseDir, "/var/db/kiss/installed", true);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT))
|
||||
{
|
||||
packageCounts->nixDefault += ffPackagesGetNix(baseDir, "/nix/var/nix/profiles/default");
|
||||
|
||||
@@ -2,35 +2,67 @@
|
||||
#include "common/processing.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/path.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <handleapi.h>
|
||||
#include <fileapi.h>
|
||||
#include <windows.h>
|
||||
#include "util/windows/nt.h"
|
||||
#include <ntstatus.h>
|
||||
|
||||
static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type, const char* ignore)
|
||||
static uint32_t getNumElements(const char* searchPath, DWORD type, const wchar_t* ignore)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
bool flag = ignore == NULL;
|
||||
WIN32_FIND_DATAA wfd;
|
||||
HANDLE hFind = FindFirstFileA(searchPath, &wfd);
|
||||
FF_AUTO_CLOSE_FD HANDLE dfd = CreateFileA(searchPath, FILE_LIST_DIRECTORY | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (dfd == INVALID_HANDLE_VALUE) return 0;
|
||||
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do // Managed to locate and create an handle to that folder.
|
||||
bool flag = ignore == NULL;
|
||||
uint32_t counter = 0;
|
||||
uint8_t buffer[64 * 1024] __attribute__((aligned(8))); // Required for WoA
|
||||
BOOLEAN firstScan = TRUE;
|
||||
|
||||
size_t ignoreLen = ignore ? wcslen(ignore) : 0;
|
||||
|
||||
while (true) {
|
||||
IO_STATUS_BLOCK ioStatus = {};
|
||||
NTSTATUS status = NtQueryDirectoryFile(
|
||||
dfd,
|
||||
NULL, NULL, NULL,
|
||||
&ioStatus,
|
||||
buffer, ARRAY_SIZE(buffer),
|
||||
FileDirectoryInformation,
|
||||
FALSE,
|
||||
NULL,
|
||||
firstScan
|
||||
);
|
||||
firstScan = FALSE;
|
||||
|
||||
if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) break;
|
||||
|
||||
for (FILE_DIRECTORY_INFORMATION* entry = (FILE_DIRECTORY_INFORMATION*) buffer;
|
||||
;
|
||||
entry = (FILE_DIRECTORY_INFORMATION*) ((uint8_t*) entry + entry->NextEntryOffset))
|
||||
{
|
||||
if(!(wfd.dwFileAttributes & type)) continue;
|
||||
if(!flag && ffStrEqualsIgnCase(ignore, wfd.cFileName))
|
||||
if (!(entry->FileAttributes & type)) continue;
|
||||
|
||||
if (!flag &&
|
||||
ignoreLen == entry->FileNameLength / sizeof(*entry->FileName) &&
|
||||
_wcsnicmp(entry->FileName, ignore, ignoreLen) == 0)
|
||||
{
|
||||
flag = true;
|
||||
continue;
|
||||
}
|
||||
counter++;
|
||||
} while (FindNextFileA(hFind, &wfd));
|
||||
FindClose(hFind);
|
||||
|
||||
if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2)
|
||||
counter -= 2; // accounting for . and ..
|
||||
counter++;
|
||||
|
||||
if (entry->NextEntryOffset == 0) break;
|
||||
}
|
||||
|
||||
if (status == STATUS_SUCCESS) break; // No next page
|
||||
}
|
||||
|
||||
if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2)
|
||||
counter -= 2; // accounting for . and ..
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
@@ -65,8 +97,8 @@ static void detectScoop(FFPackagesResult* result)
|
||||
ffStrbufSet(&scoopPath, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(&scoopPath, "/scoop");
|
||||
}
|
||||
ffStrbufAppendS(&scoopPath, "/apps/*");
|
||||
result->scoopUser = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
|
||||
ffStrbufAppendS(&scoopPath, "/apps/");
|
||||
result->scoopUser = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, L"scoop");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -78,8 +110,8 @@ static void detectScoop(FFPackagesResult* result)
|
||||
ffStrbufSetS(&scoopPath, getenv("ProgramData"));
|
||||
ffStrbufAppendS(&scoopPath, "/scoop");
|
||||
}
|
||||
ffStrbufAppendS(&scoopPath, "/apps/*");
|
||||
result->scoopGlobal = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
|
||||
ffStrbufAppendS(&scoopPath, "/apps/");
|
||||
result->scoopGlobal = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, L"scoop");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +123,8 @@ static void detectChoco(FF_MAYBE_UNUSED FFPackagesResult* result)
|
||||
|
||||
char chocoPath[MAX_PATH + 3];
|
||||
char* pend = ffStrCopy(chocoPath, chocoInstall, ARRAY_SIZE(chocoPath));
|
||||
ffStrCopy(pend, "/lib/*", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath));
|
||||
result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco");
|
||||
ffStrCopy(pend, "/lib/", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath));
|
||||
result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, L"choco");
|
||||
}
|
||||
|
||||
static void detectPacman(FFPackagesResult* result)
|
||||
@@ -104,7 +136,7 @@ static void detectPacman(FFPackagesResult* result)
|
||||
// MSYS2
|
||||
char pacmanPath[MAX_PATH + 3];
|
||||
char* pend = ffStrCopy(pacmanPath, msystemPrefix, ARRAY_SIZE(pacmanPath));
|
||||
ffStrCopy(pend, "/../var/lib/pacman/local/*", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath));
|
||||
ffStrCopy(pend, "/../var/lib/pacman/local/", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath));
|
||||
result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#include <winternl.h>
|
||||
#include <ntstatus.h>
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
const char* detectByNqsi(FFlist* result)
|
||||
{
|
||||
uint8_t buffer[4096];
|
||||
ULONG size = sizeof(buffer);
|
||||
@@ -26,6 +27,27 @@ const char* ffDetectSwap(FFlist* result)
|
||||
if (current->NextEntryOffset == 0)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* detectByKgpi(FFlist* result)
|
||||
{
|
||||
PERFORMANCE_INFORMATION pi = {};
|
||||
if (!K32GetPerformanceInfo(&pi, sizeof(pi)))
|
||||
return "K32GetPerformanceInfo(&pi, sizeof(pi)) failed";
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitS(&swap->name, "Page File");
|
||||
swap->bytesTotal = (uint64_t) (pi.CommitLimit > pi.PhysicalTotal ? pi.CommitLimit - pi.PhysicalTotal : 0) * pi.PageSize;
|
||||
swap->bytesUsed = (uint64_t) (pi.CommitTotal > pi.PhysicalTotal ? pi.CommitTotal - pi.PhysicalTotal : 0) * pi.PageSize;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
const char* err = detectByNqsi(result);
|
||||
if (err == NULL)
|
||||
return NULL;
|
||||
|
||||
return detectByKgpi(result);
|
||||
}
|
||||
|
||||
@@ -8,13 +8,18 @@
|
||||
|
||||
static void detectAlacritty(FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
|
||||
// Maybe using a toml parser to read the config file is better?
|
||||
// https://github.com/cktan/tomlc17
|
||||
|
||||
// Doc: https://alacritty.org/config-alacritty.html#s26
|
||||
FF_STRBUF_AUTO_DESTROY fontNormal = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontFamily = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontStyle = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
|
||||
|
||||
do {
|
||||
// Latest alacritty uses toml instead of yaml
|
||||
FFpropquery fontQueryToml[] = {
|
||||
{"family =", &fontName},
|
||||
{"normal =", &fontNormal},
|
||||
{"size =", &fontSize},
|
||||
};
|
||||
|
||||
@@ -25,29 +30,39 @@ static void detectAlacritty(FFTerminalFontResult* terminalFont)
|
||||
break;
|
||||
if(ffParsePropFileConfigValues(".alacritty.toml", 2, fontQueryToml))
|
||||
break;
|
||||
|
||||
FFpropquery fontQueryYaml[] = {
|
||||
{"family:", &fontName},
|
||||
{"size:", &fontSize},
|
||||
};
|
||||
|
||||
if(ffParsePropFileConfigValues("alacritty/alacritty.yml", 2, fontQueryYaml))
|
||||
break;
|
||||
if(ffParsePropFileConfigValues("alacritty.yml", 2, fontQueryYaml))
|
||||
break;
|
||||
if(ffParsePropFileConfigValues(".alacritty.yml", 2, fontQueryYaml))
|
||||
break;
|
||||
} while (false);
|
||||
|
||||
//by default alacritty uses its own font called alacritty
|
||||
if(fontName.length == 0)
|
||||
ffStrbufAppendS(&fontName, "alacritty");
|
||||
if(fontNormal.length > 0)
|
||||
{
|
||||
// { family = "Fira Code", style = "Medium" }
|
||||
ffStrbufTrimSpace(&fontNormal);
|
||||
ffStrbufTrimRight(&fontNormal, '}');
|
||||
ffStrbufTrimLeft(&fontNormal, '{');
|
||||
ffStrbufTrimSpace(&fontNormal);
|
||||
|
||||
// family = "Fira Code", style = "Medium"
|
||||
ffStrbufReplaceAllC(&fontNormal, ',', '\n'); // Assume no commas in font names
|
||||
ffParsePropLines(fontNormal.chars, "family =", &fontFamily);
|
||||
ffParsePropLines(fontNormal.chars, "style =", &fontStyle);
|
||||
}
|
||||
|
||||
if (fontFamily.length == 0)
|
||||
{
|
||||
#if __APPLE__
|
||||
ffStrbufSetStatic(&fontFamily, "Menlo");
|
||||
#elif _WIN32
|
||||
ffStrbufSetStatic(&fontFamily, "Consolas");
|
||||
#else
|
||||
ffStrbufSetStatic(&fontFamily, "monospace");
|
||||
#endif
|
||||
}
|
||||
if (fontStyle.length == 0)
|
||||
ffStrbufSetStatic(&fontStyle, "Regular");
|
||||
|
||||
// the default font size is 11
|
||||
if(fontSize.length == 0)
|
||||
ffStrbufAppendS(&fontSize, "11");
|
||||
ffStrbufSetStatic(&fontSize, "11.25");
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
ffFontInitMoveValues(&terminalFont->font, &fontFamily, &fontSize, &fontStyle);
|
||||
}
|
||||
|
||||
static void detectGhostty(const FFstrbuf* exe, FFTerminalFontResult* terminalFont)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "common/io/io.h"
|
||||
#include "common/processing.h"
|
||||
#include "common/properties.h"
|
||||
#include "util/path.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/binary.h"
|
||||
|
||||
@@ -64,12 +65,9 @@ static bool extractBashVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, v
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getShellVersionBash(FFstrbuf* exe, FFstrbuf* exePath, FFstrbuf* version)
|
||||
static bool getShellVersionBash(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
const char* path = exePath->chars;
|
||||
if (*path == '\0')
|
||||
path = exe->chars;
|
||||
ffBinaryExtractStrings(path, extractBashVersion, version, (uint32_t) strlen("@(#)Bash version 0.0.0(0) release GNU"));
|
||||
ffBinaryExtractStrings(exe->chars, extractBashVersion, version, (uint32_t) strlen("@(#)Bash version 0.0.0(0) release GNU"));
|
||||
if (version->length > 0) return true;
|
||||
|
||||
if(!getExeVersionRaw(exe, version))
|
||||
@@ -122,35 +120,39 @@ static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
|
||||
static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
#if __OpenBSD__ || __NetBSD__
|
||||
if(ffProcessAppendStdErr(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL && ffStrbufSubstrAfterFirstS(version, " (AT&T Research) "))
|
||||
{
|
||||
// version sh (AT&T Research) 93u+ 2012-08-01
|
||||
ffStrbufSubstrBeforeFirstC(version, ' ');
|
||||
return true;
|
||||
}
|
||||
|
||||
ffStrbufClear(version);
|
||||
if(ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"-c",
|
||||
"echo $KSH_VERSION",
|
||||
NULL
|
||||
}) != NULL)
|
||||
return false;
|
||||
}) == NULL && ffStrbufSubstrAfterFirstS(version, " KSH "))
|
||||
{
|
||||
// OKSH: @(#)PD KSH v5.2.14 99/07/13.2
|
||||
// MKSH: @(#)MIRBSD KSH R59 2025/04/26 +Debian
|
||||
// $OKSH_VERSION doesn't exist on OpenBSD
|
||||
ffStrbufSubstrBeforeFirstC(version, ' ');
|
||||
ffStrbufTrimLeft(version, 'v');
|
||||
return true;
|
||||
}
|
||||
|
||||
// @(#)PD KSH v5.2.14 99/07/13.2
|
||||
ffStrbufSubstrAfterFirstC(version, 'v');
|
||||
ffStrbufSubstrBeforeFirstC(version, ' ');
|
||||
#else
|
||||
if(ffProcessAppendStdErr(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"--version",
|
||||
NULL
|
||||
}) != NULL)
|
||||
return false;
|
||||
|
||||
// version sh (AT&T Research) 93u+ 2012-08-01
|
||||
ffStrbufSubstrAfterLastC(version, ')');
|
||||
ffStrbufTrim(version, ' ');
|
||||
#endif
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getShellVersionOksh(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
// Homebrew version
|
||||
if(ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exe->chars,
|
||||
"-c",
|
||||
@@ -230,13 +232,9 @@ static bool extractZshVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, vo
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getShellVersionZsh(FFstrbuf* exe, FFstrbuf* exePath, FFstrbuf* version)
|
||||
static bool getShellVersionZsh(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
const char* path = exePath->chars;
|
||||
if (*path == '\0')
|
||||
path = exe->chars;
|
||||
|
||||
ffBinaryExtractStrings(path, extractZshVersion, version, (uint32_t) strlen("zsh-0.0-0"));
|
||||
ffBinaryExtractStrings(exe->chars, extractZshVersion, version, (uint32_t) strlen("zsh-0.0-0"));
|
||||
if (version->length) return true;
|
||||
|
||||
return getExeVersionGeneral(exe, version); //zsh 5.9 (arm-apple-darwin21.3.0)
|
||||
@@ -263,7 +261,7 @@ static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath, FFstrbuf* version)
|
||||
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
|
||||
{
|
||||
if (!instance.config.general.detectVersion) return false;
|
||||
|
||||
@@ -271,9 +269,9 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath,
|
||||
return false;
|
||||
|
||||
if(ffStrEqualsIgnCase(exeName, "bash"))
|
||||
return getShellVersionBash(exe, exePath, version);
|
||||
return getShellVersionBash(exe, version);
|
||||
if(ffStrEqualsIgnCase(exeName, "zsh"))
|
||||
return getShellVersionZsh(exe, exePath, version);
|
||||
return getShellVersionZsh(exe, version);
|
||||
if(ffStrEqualsIgnCase(exeName, "fish"))
|
||||
return getShellVersionFish(exe, version);
|
||||
if(ffStrEqualsIgnCase(exeName, "pwsh"))
|
||||
@@ -282,7 +280,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath,
|
||||
return getExeVersionGeneral(exe, version); //tcsh 6.24.07 (Astron) 2022-12-21 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec
|
||||
if(ffStrEqualsIgnCase(exeName, "nu"))
|
||||
return getShellVersionNushell(exe, version);
|
||||
if(ffStrEqualsIgnCase(exeName, "ksh"))
|
||||
if(ffStrEqualsIgnCase(exeName, "ksh") || ffStrEqualsIgnCase(exeName, "mksh"))
|
||||
return getShellVersionKsh(exe, version);
|
||||
if(ffStrEqualsIgnCase(exeName, "oksh"))
|
||||
return getShellVersionOksh(exe, version);
|
||||
@@ -325,7 +323,7 @@ static bool extractGeneralVersion(const char *str, FF_MAYBE_UNUSED uint32_t len,
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if (exe->chars[0] == '/')
|
||||
if (ffIsAbsolutePath(exe->chars))
|
||||
{
|
||||
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
|
||||
if (version->length) return true;
|
||||
@@ -345,7 +343,7 @@ FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* exe, FFstrbuf* ver
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionXfce4Terminal(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if (exe->chars[0] == '/')
|
||||
if (ffIsAbsolutePath(exe->chars))
|
||||
{
|
||||
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
|
||||
if (version->length) return true;
|
||||
@@ -582,6 +580,44 @@ static bool getTerminalVersionZed(FFstrbuf* exe, FFstrbuf* version)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool extractSshdVersion(const char *str, FF_MAYBE_UNUSED uint32_t len, void *userdata)
|
||||
{
|
||||
if (!ffStrStartsWith(str, "OpenSSH_") || !ffCharIsDigit(str[strlen("OpenSSH_")])) return true;
|
||||
str += strlen("OpenSSH_");
|
||||
int count = 0;
|
||||
sscanf(str, "%*d.%*dp%*d%n", &count);
|
||||
if (count == 0) return true;
|
||||
ffStrbufSetS((FFstrbuf*) userdata, str);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool getTerminalVersionSshd(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY exePath = ffStrbufCreate();
|
||||
if (ffIsAbsolutePath(exe->chars))
|
||||
ffStrbufSet(&exePath, exe);
|
||||
else if (ffFindExecutableInPath("sshd", &exePath) != NULL)
|
||||
return false;
|
||||
|
||||
ffBinaryExtractStrings(exePath.chars, extractSshdVersion, version, (uint32_t) strlen("OpenSSH0.0"));
|
||||
if (version->length) return true;
|
||||
|
||||
if(ffProcessAppendStdOut(version, (char* const[]) {
|
||||
exePath.chars,
|
||||
"-V",
|
||||
NULL
|
||||
}) != NULL)
|
||||
return false;
|
||||
|
||||
if (ffStrbufStartsWithS(version, "unknown ")) // `unknown option -- V` (ancient OpenSSH version)
|
||||
ffStrbufSubstrAfterFirstC(version, '\n');
|
||||
|
||||
// OpenSSH_10.0p2 Ubuntu-5ubuntu5, OpenSSL 3.5.3 16 Sep 2025
|
||||
ffStrbufSubstrAfterFirstC(version, '_');
|
||||
ffStrbufSubstrBeforeFirstC(version, ',');
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
@@ -681,7 +717,7 @@ FF_MAYBE_UNUSED static bool getTerminalVersionPtyxis(FF_MAYBE_UNUSED FFstrbuf* e
|
||||
|
||||
FF_MAYBE_UNUSED static bool getTerminalVersionTilix(FFstrbuf* exe, FFstrbuf* version)
|
||||
{
|
||||
if (exe->chars[0] == '/')
|
||||
if (ffIsAbsolutePath(exe->chars))
|
||||
{
|
||||
ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0"));
|
||||
if (version->length) return true;
|
||||
@@ -925,6 +961,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
|
||||
if(ffStrbufStartsWithIgnCaseS(processName, "tmux"))
|
||||
return getTerminalVersionTmux(exe, version);
|
||||
|
||||
if(ffStrbufIgnCaseEqualS(processName, "sshd") || ffStrbufStartsWithIgnCaseS(processName, "sshd-"))
|
||||
return getTerminalVersionSshd(exe, version);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
return getFileVersion(exe, NULL, version);
|
||||
|
||||
@@ -292,14 +292,14 @@ static void getUserShellFromEnv(FFShellResult* result)
|
||||
}
|
||||
}
|
||||
|
||||
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* exePath, FFstrbuf* version);
|
||||
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
|
||||
|
||||
bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version);
|
||||
|
||||
static void setShellInfoDetails(FFShellResult* result)
|
||||
{
|
||||
ffStrbufClear(&result->version);
|
||||
fftsGetShellVersion(&result->exe, result->exeName, &result->exePath, &result->version);
|
||||
fftsGetShellVersion(result->exePath.length > 0 ? &result->exePath : &result->exe, result->exeName, &result->version);
|
||||
|
||||
if(ffStrbufEqualS(&result->processName, "pwsh"))
|
||||
ffStrbufInitStatic(&result->prettyName, "PowerShell");
|
||||
@@ -331,7 +331,12 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
|
||||
else if(ffStrbufStartsWithS(&result->processName, "screen-"))
|
||||
ffStrbufInitStatic(&result->prettyName, "screen");
|
||||
else if(ffStrbufEqualS(&result->processName, "sshd") || ffStrbufStartsWithS(&result->processName, "sshd-"))
|
||||
ffStrbufInitCopy(&result->prettyName, &result->tty);
|
||||
{
|
||||
if (result->tty.length)
|
||||
ffStrbufInitCopy(&result->prettyName, &result->tty);
|
||||
else
|
||||
ffStrbufSetStatic(&result->prettyName, "sshd");
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
@@ -383,7 +388,7 @@ static void setTerminalInfoDetails(FFTerminalResult* result)
|
||||
else
|
||||
ffStrbufInitCopy(&result->prettyName, &result->processName);
|
||||
|
||||
fftsGetTerminalVersion(&result->processName, &result->exe, &result->version);
|
||||
fftsGetTerminalVersion(&result->processName, result->exePath.length > 0 ? &result->exePath : &result->exe, &result->version);
|
||||
}
|
||||
|
||||
#if defined(MAXPATH)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <wchar.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, const FFstrbuf* exePath, FFstrbuf* version);
|
||||
bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version);
|
||||
|
||||
static uint32_t getShellInfo(FFShellResult* result, uint32_t pid)
|
||||
{
|
||||
@@ -332,7 +332,7 @@ const FFShellResult* ffDetectShell(void)
|
||||
strcpy(tmp, result.exeName);
|
||||
char* ext = strrchr(tmp, '.');
|
||||
if (ext) *ext = '\0';
|
||||
fftsGetShellVersion(&result.exe, tmp, &result.exePath, &result.version);
|
||||
fftsGetShellVersion(result.exePath.length > 0 ? &result.exePath : &result.exe, tmp, &result.version);
|
||||
}
|
||||
|
||||
return &result;
|
||||
@@ -368,7 +368,7 @@ const FFTerminalResult* ffDetectTerminal(void)
|
||||
if(result.processName.length > 0)
|
||||
{
|
||||
setTerminalInfoDetails(&result);
|
||||
fftsGetTerminalVersion(&result.processName, &result.exe, &result.version);
|
||||
fftsGetTerminalVersion(&result.processName, result.exePath.length > 0 ? &result.exePath : &result.exe, &result.version);
|
||||
}
|
||||
|
||||
return &result;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#include "common/io/io.h"
|
||||
#include "common/properties.h"
|
||||
#include "fastfetch.h"
|
||||
#include "users.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#if FF_HAVE_UTMPX
|
||||
#include <utmpx.h>
|
||||
#else
|
||||
@@ -15,7 +19,140 @@
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
const char* ffDetectUsers(FFUsersOptions* options, FFlist* users)
|
||||
#if __linux__
|
||||
bool detectUserBySystemd(const FFstrbuf* pathUsers, FFlist* users)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY state = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY userName = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY loginTime = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY sessions = ffStrbufCreate();
|
||||
|
||||
// WARNING: This is private data. Do not parse
|
||||
if (!ffParsePropFileValues(pathUsers->chars, 4, (FFpropquery[]) {
|
||||
{"NAME=", &userName},
|
||||
{"STATE=", &state},
|
||||
{"REALTIME=", &loginTime},
|
||||
{"ONLINE_SESSIONS=", &sessions},
|
||||
}) || !ffStrbufEqualS(&state, "active"))
|
||||
return false;
|
||||
|
||||
FFUserResult* user = FF_LIST_ADD(FFUserResult, *users);
|
||||
ffStrbufInitMove(&user->name, &userName);
|
||||
ffStrbufInit(&user->hostName);
|
||||
ffStrbufInit(&user->sessionName);
|
||||
ffStrbufInit(&user->clientIp);
|
||||
ffStrbufSubstrBefore(&loginTime, loginTime.length - 3); // converts us to ms
|
||||
user->loginTime = ffStrbufToUInt(&loginTime, 0);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY pathSessions = ffStrbufCreateS("/run/systemd/sessions/");
|
||||
const uint32_t pathSessionsBaseLen = pathSessions.length;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY tty = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY remoteHost = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY service = ffStrbufCreate();
|
||||
|
||||
char* token = NULL;
|
||||
size_t n = 0;
|
||||
while (ffStrbufGetdelim(&token, &n, ' ', &sessions))
|
||||
{
|
||||
ffStrbufSubstrBefore(&pathSessions, pathSessionsBaseLen);
|
||||
ffStrbufAppendS(&pathSessions, token);
|
||||
|
||||
ffStrbufClear(&remoteHost);
|
||||
ffStrbufClear(&service);
|
||||
ffStrbufClear(&tty);
|
||||
ffStrbufClear(&loginTime);
|
||||
|
||||
// WARNING: This is private data. Do not parse
|
||||
if (ffParsePropFileValues(pathSessions.chars, 4, (FFpropquery[]) {
|
||||
{"REMOTE_HOST=", &remoteHost},
|
||||
{"TTY=", &tty},
|
||||
{"SERVICE=", &service},
|
||||
{"REALTIME=", &loginTime},
|
||||
}) && !ffStrbufEqualS(&service, "systemd-user"))
|
||||
{
|
||||
if (remoteHost.length)
|
||||
{
|
||||
ffStrbufTrimRight(&remoteHost, ']');
|
||||
ffStrbufTrimLeft(&remoteHost, '[');
|
||||
ffStrbufInitMove(&user->hostName, &remoteHost);
|
||||
}
|
||||
else
|
||||
ffStrbufSetStatic(&user->hostName, "localhost");
|
||||
ffStrbufInitMove(&user->sessionName, tty.length ? &tty : &service);
|
||||
if (loginTime.length)
|
||||
{
|
||||
ffStrbufSubstrBefore(&loginTime, loginTime.length - 3); // converts us to ms
|
||||
user->loginTime = ffStrbufToUInt(&loginTime, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* detectBySystemd(FFUsersOptions* options, FFlist* users)
|
||||
{
|
||||
// For some reason, debian/ubuntu no longer updates `/var/run/utmp` (#2064)
|
||||
// Query systemd instead
|
||||
FF_STRBUF_AUTO_DESTROY pathUsers = ffStrbufCreateS("/run/systemd/users/");
|
||||
|
||||
if (options->myselfOnly)
|
||||
{
|
||||
ffStrbufAppendUInt(&pathUsers, getuid());
|
||||
detectUserBySystemd(&pathUsers, users);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t pathUsersBaseLen = pathUsers.length;
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pathUsers.chars);
|
||||
if (!dirp) return "opendir(\"/run/systemd/users/\") failed";
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)))
|
||||
{
|
||||
if (entry->d_type != DT_REG) continue;
|
||||
|
||||
ffStrbufAppendS(&pathUsers, entry->d_name);
|
||||
detectUserBySystemd(&pathUsers, users);
|
||||
ffStrbufSubstrBefore(&pathUsers, pathUsersBaseLen);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __linux__ || __GNU__
|
||||
static void fillUtmpIpAddr(FFUserResult* user, struct utmpx* n)
|
||||
{
|
||||
bool isIpv6 = false;
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
if (n->ut_addr_v6[i] != 0) {
|
||||
isIpv6 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isIpv6) {
|
||||
char ipv6_str[INET6_ADDRSTRLEN];
|
||||
if (inet_ntop(AF_INET6, n->ut_addr_v6, ipv6_str, INET6_ADDRSTRLEN) != NULL) {
|
||||
ffStrbufSetS(&user->clientIp, ipv6_str);
|
||||
}
|
||||
} else if (n->ut_addr_v6[0] != 0) {
|
||||
char ipv4_str[INET_ADDRSTRLEN];
|
||||
if (inet_ntop(AF_INET, n->ut_addr_v6, ipv4_str, INET_ADDRSTRLEN) != NULL) {
|
||||
ffStrbufSetS(&user->clientIp, ipv4_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void fillUtmpIpAddr(FF_MAYBE_UNUSED FFUserResult* user, FF_MAYBE_UNUSED struct utmpx* n)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* detectByUtmp(FFUsersOptions* options, FFlist* users)
|
||||
{
|
||||
struct utmpx* n = NULL;
|
||||
setutxent();
|
||||
@@ -32,37 +169,41 @@ next:
|
||||
FF_LIST_FOR_EACH(FFUserResult, user, *users)
|
||||
{
|
||||
if(ffStrbufEqualS(&user->name, n->ut_user))
|
||||
{
|
||||
uint64_t newLoginTime = (uint64_t) n->ut_tv.tv_sec * 1000 + (uint64_t) n->ut_tv.tv_usec / 1000;
|
||||
if (newLoginTime > user->loginTime)
|
||||
{
|
||||
ffStrbufSetS(&user->hostName, n->ut_host);
|
||||
ffStrbufSetS(&user->sessionName, n->ut_line);
|
||||
fillUtmpIpAddr(user, n);
|
||||
user->loginTime = newLoginTime;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
FFUserResult* user = (FFUserResult*) ffListAdd(users);
|
||||
FFUserResult* user = FF_LIST_ADD(FFUserResult, *users);
|
||||
ffStrbufInitS(&user->name, n->ut_user);
|
||||
ffStrbufInitS(&user->hostName, n->ut_host);
|
||||
ffStrbufInitS(&user->sessionName, n->ut_line);
|
||||
ffStrbufInit(&user->clientIp);
|
||||
#if __linux__ || __GNU__
|
||||
bool isIpv6 = false;
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
if (n->ut_addr_v6[i] != 0) {
|
||||
isIpv6 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isIpv6) {
|
||||
char ipv6_str[INET6_ADDRSTRLEN];
|
||||
if (inet_ntop(AF_INET6, n->ut_addr_v6, ipv6_str, INET6_ADDRSTRLEN) != NULL) {
|
||||
ffStrbufSetS(&user->clientIp, ipv6_str);
|
||||
}
|
||||
} else if (n->ut_addr_v6[0] != 0) {
|
||||
char ipv4_str[INET_ADDRSTRLEN];
|
||||
if (inet_ntop(AF_INET, n->ut_addr_v6, ipv4_str, INET_ADDRSTRLEN) != NULL) {
|
||||
ffStrbufSetS(&user->clientIp, ipv4_str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fillUtmpIpAddr(user, n);
|
||||
user->loginTime = (uint64_t) n->ut_tv.tv_sec * 1000 + (uint64_t) n->ut_tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
endutxent();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectUsers(FFUsersOptions* options, FFlist* users)
|
||||
{
|
||||
const char* err = detectByUtmp(options, users);
|
||||
if (err) return err;
|
||||
|
||||
#if __linux__
|
||||
if (users->length == 0) detectBySystemd(options, users);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -25,65 +25,24 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
ZPOOL_PROP_INVAL = -1,
|
||||
ZPOOL_PROP_NAME,
|
||||
ZPOOL_PROP_SIZE,
|
||||
ZPOOL_PROP_CAPACITY,
|
||||
ZPOOL_PROP_ALTROOT,
|
||||
ZPOOL_PROP_HEALTH,
|
||||
ZPOOL_PROP_GUID,
|
||||
ZPOOL_PROP_VERSION,
|
||||
ZPOOL_PROP_BOOTFS,
|
||||
ZPOOL_PROP_DELEGATION,
|
||||
ZPOOL_PROP_AUTOREPLACE,
|
||||
ZPOOL_PROP_CACHEFILE,
|
||||
ZPOOL_PROP_FAILUREMODE,
|
||||
ZPOOL_PROP_LISTSNAPS,
|
||||
ZPOOL_PROP_AUTOEXPAND,
|
||||
ZPOOL_PROP_DEDUPDITTO,
|
||||
ZPOOL_PROP_DEDUPRATIO,
|
||||
ZPOOL_PROP_FREE,
|
||||
ZPOOL_PROP_ALLOCATED,
|
||||
ZPOOL_PROP_READONLY,
|
||||
ZPOOL_PROP_ASHIFT,
|
||||
ZPOOL_PROP_COMMENT,
|
||||
ZPOOL_PROP_EXPANDSZ,
|
||||
ZPOOL_PROP_FREEING,
|
||||
ZPOOL_PROP_FRAGMENTATION,
|
||||
ZPOOL_PROP_LEAKED,
|
||||
ZPOOL_PROP_MAXBLOCKSIZE,
|
||||
ZPOOL_PROP_TNAME,
|
||||
ZPOOL_PROP_MAXDNODESIZE,
|
||||
ZPOOL_PROP_MULTIHOST,
|
||||
ZPOOL_PROP_CHECKPOINT,
|
||||
ZPOOL_PROP_LOAD_GUID,
|
||||
ZPOOL_PROP_AUTOTRIM,
|
||||
ZPOOL_PROP_COMPATIBILITY,
|
||||
ZPOOL_PROP_BCLONEUSED,
|
||||
ZPOOL_PROP_BCLONESAVED,
|
||||
ZPOOL_PROP_BCLONERATIO,
|
||||
ZPOOL_NUM_PROPS
|
||||
} zpool_prop_t;
|
||||
|
||||
typedef enum {
|
||||
ZPROP_SRC_NONE = 0x1,
|
||||
ZPROP_SRC_DEFAULT = 0x2,
|
||||
ZPROP_SRC_TEMPORARY = 0x4,
|
||||
ZPROP_SRC_LOCAL = 0x8,
|
||||
ZPROP_SRC_INHERITED = 0x10,
|
||||
ZPROP_SRC_RECEIVED = 0x20
|
||||
} zprop_source_t;
|
||||
|
||||
typedef bool boolean_t;
|
||||
// zpool_prop_t and zprop_source_t were previously enums in upstream OpenZFS.
|
||||
// However, the enum values for these types vary greatly between different platforms,
|
||||
// making it unsafe to use the enum values directly. To ensure portability,
|
||||
// we define them as simple int typedefs and use zpool_name_to_prop to look up
|
||||
// the correct value for a property at runtime.
|
||||
typedef int zpool_prop_t;
|
||||
typedef int zprop_source_t;
|
||||
typedef int boolean_t;
|
||||
|
||||
typedef struct libzfs_handle libzfs_handle_t;
|
||||
typedef struct zpool_handle zpool_handle_t;
|
||||
typedef int (*zpool_iter_f)(zpool_handle_t *, void *);
|
||||
extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *);
|
||||
|
||||
extern libzfs_handle_t *libzfs_init(void);
|
||||
extern void libzfs_fini(libzfs_handle_t *);
|
||||
extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t, zprop_source_t *);
|
||||
extern const char *zpool_get_name(zpool_handle_t *);
|
||||
extern const char *zpool_get_state_str(zpool_handle_t *);
|
||||
extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *);
|
||||
extern zpool_prop_t zpool_name_to_prop(const char *);
|
||||
// https://github.com/openzfs/zfs/blob/06c73cffabc30b61a695988ec8e290f43cb3768d/lib/libzfs/libzfs_pool.c#L300
|
||||
extern uint64_t zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *srctype);
|
||||
extern int zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, zprop_source_t *srctype, boolean_t literal);
|
||||
extern void zpool_close(zpool_handle_t *);
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
#include "zpool.h"
|
||||
|
||||
#if FF_HAVE_LIBZFS
|
||||
|
||||
#include "util/kmod.h"
|
||||
|
||||
#ifdef __sun
|
||||
#include <libzfs.h>
|
||||
#else
|
||||
#include "libzfs_simplified.h"
|
||||
#endif
|
||||
|
||||
#include "common/library.h"
|
||||
|
||||
typedef struct FFZfsData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(libzfs_fini)
|
||||
FF_LIBRARY_SYMBOL(zpool_get_prop_int)
|
||||
FF_LIBRARY_SYMBOL(zpool_get_prop)
|
||||
FF_LIBRARY_SYMBOL(zpool_close)
|
||||
|
||||
// The fields in this struct store property IDs returned by `zpool_name_to_prop`,
|
||||
// not the property values themselves.
|
||||
struct {
|
||||
int name;
|
||||
int health;
|
||||
int guid;
|
||||
int size;
|
||||
int free;
|
||||
int allocated;
|
||||
int fragmentation;
|
||||
int readonly;
|
||||
} props;
|
||||
|
||||
libzfs_handle_t* handle;
|
||||
FFlist* result;
|
||||
} FFZfsData;
|
||||
|
||||
static inline void cleanLibzfs(FFZfsData* data)
|
||||
{
|
||||
if (data->fflibzfs_fini && data->handle)
|
||||
{
|
||||
data->fflibzfs_fini(data->handle);
|
||||
data->handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int enumZpoolCallback(zpool_handle_t* zpool, void* param)
|
||||
{
|
||||
FFZfsData* data = (FFZfsData*) param;
|
||||
zprop_source_t source;
|
||||
FFZpoolResult* item = ffListAdd(data->result);
|
||||
char buf[1024];
|
||||
if (data->ffzpool_get_prop(zpool, data->props.name, buf, ARRAY_SIZE(buf), &source, false) == 0)
|
||||
ffStrbufInitS(&item->name, buf);
|
||||
else
|
||||
ffStrbufInitStatic(&item->name, "unknown");
|
||||
if (data->ffzpool_get_prop(zpool, data->props.health, buf, ARRAY_SIZE(buf), &source, false) == 0)
|
||||
ffStrbufInitS(&item->state, buf);
|
||||
else
|
||||
ffStrbufInitStatic(&item->state, "unknown");
|
||||
item->guid = data->ffzpool_get_prop_int(zpool, data->props.guid, &source);
|
||||
item->total = data->ffzpool_get_prop_int(zpool, data->props.size, &source);
|
||||
item->used = item->total - data->ffzpool_get_prop_int(zpool, data->props.free, &source);
|
||||
item->allocated = data->ffzpool_get_prop_int(zpool, data->props.allocated, &source);
|
||||
uint64_t fragmentation = data->ffzpool_get_prop_int(zpool, data->props.fragmentation, &source);
|
||||
item->fragmentation = fragmentation == UINT64_MAX ? -DBL_MAX : (double) fragmentation;
|
||||
item->readOnly = (bool) data->ffzpool_get_prop_int(zpool, data->props.readonly, &source);
|
||||
data->ffzpool_close(zpool);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libzfs, "dlopen libzfs" FF_LIBRARY_EXTENSION " failed", "libzfs" FF_LIBRARY_EXTENSION, 6);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, libzfs_init);
|
||||
|
||||
libzfs_handle_t* handle = fflibzfs_init();
|
||||
if (!handle)
|
||||
{
|
||||
if (!ffKmodLoaded("zfs")) return "`zfs` kernel module is not loaded";
|
||||
return "libzfs_init() failed";
|
||||
}
|
||||
|
||||
__attribute__((__cleanup__(cleanLibzfs))) FFZfsData data = {
|
||||
.handle = handle,
|
||||
.result = result,
|
||||
};
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, zpool_name_to_prop);
|
||||
|
||||
#define FF_QUERY_ZPOOL_PROP_FROM_NAME(prop_name) do { \
|
||||
data.props.prop_name = ffzpool_name_to_prop(#prop_name); \
|
||||
if (data.props.prop_name < 0) \
|
||||
return "Failed to query prop: " #prop_name; \
|
||||
} while (false)
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(name);
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(health);
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(guid);
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(size);
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(free);
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(allocated);
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(fragmentation);
|
||||
FF_QUERY_ZPOOL_PROP_FROM_NAME(readonly);
|
||||
#undef FF_QUERY_ZPOOL_PROP_FROM_NAME
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, zpool_iter);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, libzfs_fini);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_prop_int);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_prop);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_close);
|
||||
|
||||
if (ffzpool_iter(handle, enumZpoolCallback, &data) < 0)
|
||||
return "zpool_iter() failed";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffDetectZpool(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
return "fastfetch was compiled without libzfs support";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -7,10 +7,12 @@ typedef struct FFZpoolResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf state;
|
||||
uint64_t guid;
|
||||
uint64_t used;
|
||||
uint64_t total;
|
||||
uint64_t version;
|
||||
uint64_t allocated;
|
||||
double fragmentation;
|
||||
bool readOnly;
|
||||
} FFZpoolResult;
|
||||
|
||||
const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */);
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
#include "zpool.h"
|
||||
|
||||
#ifdef FF_HAVE_LIBZFS
|
||||
#include "util/kmod.h"
|
||||
|
||||
#ifdef __sun
|
||||
#define FF_DISABLE_DLOPEN
|
||||
#include <libzfs.h>
|
||||
|
||||
const char* zpool_get_state_str(zpool_handle_t* zpool)
|
||||
{
|
||||
if (zpool_get_state(zpool) == POOL_STATE_UNAVAIL)
|
||||
return "FAULTED";
|
||||
else
|
||||
{
|
||||
const char *str;
|
||||
zpool_errata_t errata;
|
||||
zpool_status_t status = zpool_get_status(zpool, (char**) &str, &errata);
|
||||
if (status == ZPOOL_STATUS_IO_FAILURE_WAIT ||
|
||||
status == ZPOOL_STATUS_IO_FAILURE_CONTINUE ||
|
||||
status == ZPOOL_STATUS_IO_FAILURE_MMP)
|
||||
return "SUSPENDED";
|
||||
else
|
||||
{
|
||||
nvlist_t *nvroot = fnvlist_lookup_nvlist(zpool_get_config(zpool, NULL), ZPOOL_CONFIG_VDEV_TREE);
|
||||
uint_t vsc;
|
||||
vdev_stat_t *vs;
|
||||
#ifdef __x86_64__
|
||||
if (nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, (uint64_t**) &vs, &vsc) != 0)
|
||||
#else
|
||||
if (nvlist_lookup_uint32_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, (uint32_t**) &vs, &vsc) != 0)
|
||||
#endif
|
||||
return "UNKNOWN";
|
||||
else
|
||||
return zpool_state_to_name(vs->vs_state, vs->vs_aux);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#include "libzfs_simplified.h"
|
||||
#endif
|
||||
|
||||
#include "common/library.h"
|
||||
|
||||
typedef struct FFZfsData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(libzfs_fini)
|
||||
FF_LIBRARY_SYMBOL(zpool_iter)
|
||||
FF_LIBRARY_SYMBOL(zpool_get_prop_int)
|
||||
FF_LIBRARY_SYMBOL(zpool_get_name)
|
||||
FF_LIBRARY_SYMBOL(zpool_get_state_str)
|
||||
|
||||
libzfs_handle_t* handle;
|
||||
FFlist* result;
|
||||
} FFZfsData;
|
||||
|
||||
static inline void cleanLibzfs(FFZfsData* data)
|
||||
{
|
||||
if (data->fflibzfs_fini && data->handle)
|
||||
{
|
||||
data->fflibzfs_fini(data->handle);
|
||||
data->handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int enumZpoolCallback(zpool_handle_t* zpool, void* param)
|
||||
{
|
||||
FFZfsData* data = (FFZfsData*) param;
|
||||
zprop_source_t source;
|
||||
FFZpoolResult* item = ffListAdd(data->result);
|
||||
ffStrbufInitS(&item->name, data->ffzpool_get_name(zpool));
|
||||
ffStrbufInitS(&item->state, data->ffzpool_get_state_str(zpool));
|
||||
item->version = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_VERSION, &source);
|
||||
item->total = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_SIZE, &source);
|
||||
item->used = item->total - data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FREE, &source);
|
||||
uint64_t fragmentation = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FRAGMENTATION, &source);
|
||||
item->fragmentation = fragmentation == UINT64_MAX ? -DBL_MAX : (double) fragmentation;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libzfs, "dlopen libzfs" FF_LIBRARY_EXTENSION " failed", "libzfs" FF_LIBRARY_EXTENSION, 6);
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, libzfs_init);
|
||||
|
||||
libzfs_handle_t* handle = fflibzfs_init();
|
||||
if (!handle)
|
||||
{
|
||||
if (!ffKmodLoaded("zfs")) return "`zfs` kernel module is not loaded";
|
||||
return "libzfs_init() failed";
|
||||
}
|
||||
|
||||
__attribute__((__cleanup__(cleanLibzfs))) FFZfsData data = {
|
||||
.handle = handle,
|
||||
.result = result,
|
||||
};
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, zpool_iter);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, libzfs_fini);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_prop_int);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_name);
|
||||
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_state_str);
|
||||
|
||||
if (ffzpool_iter(handle, enumZpoolCallback, &data) < 0)
|
||||
return "zpool_iter() failed";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const char* ffDetectZpool(FF_MAYBE_UNUSED FFlist* result)
|
||||
{
|
||||
return "Fastfetch was compiled without libzfs support";
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "zpool.h"
|
||||
|
||||
const char* ffDetectZpool(FF_MAYBE_UNUSED FFlist* result /* list of FFZpoolResult */)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
+16
-3
@@ -14,7 +14,7 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#include "util/windows/getline.h"
|
||||
#endif
|
||||
|
||||
@@ -502,7 +502,20 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
|
||||
//Try to load as a relative path
|
||||
//Try to load as a relative path with the config directory
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, path, instance.state.platform.configDirs)
|
||||
{
|
||||
ffStrbufSet(&absolutePath, path);
|
||||
ffStrbufAppendS(&absolutePath, "fastfetch/");
|
||||
ffStrbufAppendS(&absolutePath, value);
|
||||
if (needExtension)
|
||||
ffStrbufAppendS(&absolutePath, ".jsonc");
|
||||
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
}
|
||||
|
||||
//Try to load as a preset
|
||||
|
||||
FF_LIST_FOR_EACH(FFstrbuf, path, instance.state.platform.dataDirs)
|
||||
{
|
||||
@@ -515,7 +528,7 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
if (parseJsoncFile(absolutePath.chars, flag)) return;
|
||||
}
|
||||
|
||||
//Try to load as a relative path with the directory of fastfetch binary
|
||||
//Try to load as a relative path with the directory of fastfetch binary, for Windows support
|
||||
|
||||
if (instance.state.platform.exePath.length)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
----.---
|
||||
:-==.-==-
|
||||
$2 -=== ===:
|
||||
===-:===.
|
||||
$3 -+++:=++=
|
||||
=+++ +++.
|
||||
$6 .+++-=++=
|
||||
$4.::. ::: $6 :**+ +**-
|
||||
$4 :--:.---. $6 .+**=-***.
|
||||
$5 :--- ---::$6***:***+
|
||||
$5 .---::-$6=##*.*##-
|
||||
$7 ----+$6##=:##*.
|
||||
$7 :-$6###-*##+
|
||||
+12
-12
@@ -1,12 +1,12 @@
|
||||
^"^"^". `"^"""`
|
||||
";;;;;:. `;;;;;;.
|
||||
^;":;:;: .;,,;:;:
|
||||
.'`",, '":::. ^;'';;;;, .:: ,;;;:
|
||||
';;;;:":::::' ^;` `;;;;" ::. ,;;;:
|
||||
";:;:. ^;` ^;;;;^ ,;. ,;;;:
|
||||
";;;: ^;` ";;;;^ ";' ,;;;:
|
||||
";;;: ^;` ,;;;;`^;` ,;;;:
|
||||
";;;: ^;` ,;;;;;^ ,;;;:
|
||||
";:;: ^;` .:;:;" ,;:;:
|
||||
,;;;;. ";" .:;, :;;;;.
|
||||
."""""` ^"^ '" ."""""`
|
||||
#: :+#@@@@%#
|
||||
@@#: .*@@@@@@@@@
|
||||
@@@@#- .@@@@@@@@@@@
|
||||
@@@@@@%- %@@@@@@@@@@@
|
||||
@@@@@@@@%= :@@@@%%%%@@@@
|
||||
@@@@@@@@@@%==*-: .:=#
|
||||
:*@@@@@@@@@@=
|
||||
:*@@@@@@@@=
|
||||
.*@@@@@@=
|
||||
.+@@@@=
|
||||
.+%@=
|
||||
+=
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
################
|
||||
########################
|
||||
##########-- --##########
|
||||
#######* ****** *#######
|
||||
###### --*######--- ######
|
||||
##### --- *#### #####
|
||||
##### *-- #*#*#* * #### #####
|
||||
#####* ##- ##*-#* ### ### *#####
|
||||
##### ###* -##*#* *# *# *### #####
|
||||
##### ###* -*##*-*## *#* ### #####
|
||||
##### #### - --#### - ##* ### #####
|
||||
##### *####* * - ###- ##* #####
|
||||
#####* #######- *###- ### *#####
|
||||
#####* ***#####****--- ### *#####
|
||||
###### ----------- - ### ######
|
||||
###### ----- ### ######
|
||||
####### #######
|
||||
##########*----*##########
|
||||
######################
|
||||
##############
|
||||
@@ -1,13 +0,0 @@
|
||||
.':ldkOOOOkxo:,.
|
||||
.:d0KKXXXXXXXXXXKkl,
|
||||
.;xOOO0000KKKKXXXXXXX0l.
|
||||
.cxxxkkkkOOO0000KKKKXXXXx'
|
||||
;ool;,,,,;coxkOOOO0000KKKd.
|
||||
.clc'.........:oxkkkkOOOO0O,
|
||||
.ccc:ccclc:,....,:oddxxdxkO;
|
||||
cllllccccccc;'........'lxx.
|
||||
'ooooolllllccc:;,''',,coo,
|
||||
,ddddooooollllllccccccl'
|
||||
cxxxdddddooooollllc;
|
||||
,dxxxxxddddddol.
|
||||
.';::,.
|
||||
@@ -0,0 +1,17 @@
|
||||
.-==: . .
|
||||
-+:::+= * *- = -. -%*
|
||||
** *# :%- . :.*=: -%%
|
||||
%@: -@% =%@%%*: - :. -%=
|
||||
-@@: :@@- -+#%%+ .: :*.
|
||||
-@@: :@@-- -% = .*
|
||||
.%@- -%% ++ # . -: .
|
||||
#* ** =.:*: +- = #%%%%#+-*:
|
||||
-=====- .:- ..
|
||||
|
||||
$2 =*+ -+*:
|
||||
.*+ :*+= -+*++**-
|
||||
+*-++++ -++-:. .:-=++.=*+. =*-
|
||||
-***:-+:*++=*++*: +*+=:-**+=**++-
|
||||
:- :***==*+.=++ +*+=++*=.=*+.
|
||||
.=-=*+***+*= +*+ :**+=++
|
||||
. -*+ +*+ .=:
|
||||
+25
-8
@@ -39,7 +39,7 @@ static const FFlogo A[] = {
|
||||
FF_COLOR_FG_256 "36",
|
||||
},
|
||||
},
|
||||
// Aeon
|
||||
// AerynOS
|
||||
{
|
||||
.names = {"AerynOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_AERYNOS,
|
||||
@@ -181,6 +181,20 @@ static const FFlogo A[] = {
|
||||
FF_COLOR_FG_256 "178",
|
||||
}
|
||||
},
|
||||
// Amiga
|
||||
{
|
||||
.names = {"Amiga"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_AMIGA,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_LIGHT_RED,
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_CYAN,
|
||||
FF_COLOR_FG_LIGHT_YELLOW,
|
||||
FF_COLOR_FG_GREEN,
|
||||
}
|
||||
},
|
||||
// AmogOS
|
||||
{
|
||||
.names = {"AmogOS"},
|
||||
@@ -2143,7 +2157,7 @@ static const FFlogo G[] = {
|
||||
// GXDE
|
||||
{
|
||||
.names = {"GXDE"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_DEEPIN,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_GXDE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
},
|
||||
@@ -3441,12 +3455,6 @@ static const FFlogo O[] = {
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
}
|
||||
},
|
||||
// Opak
|
||||
{
|
||||
.names = {"Opak"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OPAK,
|
||||
.colors = {}, // #1070
|
||||
},
|
||||
// OpenKylin
|
||||
{
|
||||
.names = {"openkylin", "open-kylin"},
|
||||
@@ -3686,6 +3694,15 @@ static const FFlogo O[] = {
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
},
|
||||
// OS/2 Warp
|
||||
{
|
||||
.names = {"OS2Warp"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_OS2WARP,
|
||||
.colors = {
|
||||
FF_COLOR_FG_LIGHT_WHITE,
|
||||
FF_COLOR_FG_LIGHT_BLUE,
|
||||
}
|
||||
},
|
||||
// OS_Elbrus
|
||||
{
|
||||
.names = {"OS Elbrus"},
|
||||
|
||||
@@ -891,13 +891,13 @@ static bool printCachedPixel(FFLogoRequestData* requestData)
|
||||
if(requestData->type == FF_LOGO_TYPE_IMAGE_KITTY)
|
||||
{
|
||||
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_COMPRESSED);
|
||||
if(fd == FF_INVALID_FD)
|
||||
if(!ffIsValidNativeFD(fd))
|
||||
fd = getCacheFD(requestData, FF_CACHE_FILE_KITTY_UNCOMPRESSED);
|
||||
}
|
||||
else if(requestData->type == FF_LOGO_TYPE_IMAGE_SIXEL)
|
||||
fd = getCacheFD(requestData, FF_CACHE_FILE_SIXEL);
|
||||
|
||||
if(fd == FF_INVALID_FD)
|
||||
if(!ffIsValidNativeFD(fd))
|
||||
return false;
|
||||
|
||||
ffPrintCharTimes('\n', options->paddingTop);
|
||||
|
||||
+8
-7
@@ -733,22 +733,23 @@ void ffLogoPrintRemaining(void)
|
||||
void ffLogoBuiltinPrint(void)
|
||||
{
|
||||
FFOptionsLogo* options = &instance.config.logo;
|
||||
options->position = FF_LOGO_POSITION_TOP;
|
||||
options->paddingRight = 2; // empty line after logo printing
|
||||
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
|
||||
|
||||
for(uint8_t ch = 0; ch < 26; ++ch)
|
||||
{
|
||||
for(const FFlogo* logo = ffLogoBuiltins[ch]; *logo->names; ++logo)
|
||||
{
|
||||
printf("\033[%sm%s:\033[0m\n", logo->colors[0], logo->names[0]);
|
||||
if (instance.config.display.pipe)
|
||||
ffStrbufSetF(&buf, "%s:\n", logo->names[0]);
|
||||
else
|
||||
ffStrbufSetF(&buf, "\e[%sm%s:\e[0m\n", logo->colors[0], logo->names[0]);
|
||||
ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf);
|
||||
logoPrintStruct(logo);
|
||||
ffLogoPrintRemaining();
|
||||
|
||||
//reset everything
|
||||
instance.state.logoHeight = 0;
|
||||
instance.state.keysHeight = 0;
|
||||
for(uint8_t i = 0; i < FASTFETCH_LOGO_MAX_COLORS; i++)
|
||||
ffStrbufClear(&options->colors[i]);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,39 @@ bool ffPrintCommand(FFCommandOptions* options)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options->moduleArgs.outputFormat.length == 0)
|
||||
if (options->splitLines)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufPutTo(&result, stdout);
|
||||
uint8_t index = 0;
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, &result))
|
||||
{
|
||||
if (options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
puts(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
|
||||
FF_FORMAT_ARG(line, "result")
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
|
||||
FF_FORMAT_ARG(result, "result")
|
||||
}));
|
||||
if (options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufPutTo(&result, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
|
||||
FF_FORMAT_ARG(result, "result")
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -74,6 +97,12 @@ void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "splitLines"))
|
||||
{
|
||||
options->splitLines = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key));
|
||||
}
|
||||
}
|
||||
@@ -87,6 +116,7 @@ void ffGenerateCommandJsonConfig(FFCommandOptions* options, yyjson_mut_doc* doc,
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "text", &options->text);
|
||||
yyjson_mut_obj_add_bool(doc, module, "useStdErr", options->useStdErr);
|
||||
yyjson_mut_obj_add_bool(doc, module, "parallel", options->parallel);
|
||||
yyjson_mut_obj_add_bool(doc, module, "splitLines", options->splitLines);
|
||||
}
|
||||
|
||||
bool ffGenerateCommandJsonResult(FF_MAYBE_UNUSED FFCommandOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
@@ -106,7 +136,16 @@ bool ffGenerateCommandJsonResult(FF_MAYBE_UNUSED FFCommandOptions* options, yyjs
|
||||
return false;
|
||||
}
|
||||
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "result", &result);
|
||||
if (options->splitLines)
|
||||
{
|
||||
yyjson_mut_val* jsonArray = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, &result))
|
||||
yyjson_mut_arr_add_strncpy(doc, jsonArray, line, len);
|
||||
}
|
||||
else
|
||||
yyjson_mut_obj_add_strbuf(doc, module, "result", &result);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -132,6 +171,7 @@ void ffInitCommandOptions(FFCommandOptions* options)
|
||||
ffStrbufInit(&options->text);
|
||||
options->useStdErr = false;
|
||||
options->parallel = true;
|
||||
options->splitLines = false;
|
||||
}
|
||||
|
||||
void ffDestroyCommandOptions(FFCommandOptions* options)
|
||||
|
||||
@@ -11,6 +11,7 @@ typedef struct FFCommandOptions
|
||||
FFstrbuf text;
|
||||
bool useStdErr;
|
||||
bool parallel;
|
||||
bool splitLines;
|
||||
} FFCommandOptions;
|
||||
|
||||
static_assert(sizeof(FFCommandOptions) <= FF_OPTION_MAX_SIZE, "FFCommandOptions size exceeds maximum allowed size");
|
||||
|
||||
+16
-2
@@ -5,7 +5,6 @@
|
||||
#include "common/frequency.h"
|
||||
#include "detection/cpu/cpu.h"
|
||||
#include "modules/cpu/cpu.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static int sortCores(const FFCPUCore* a, const FFCPUCore* b)
|
||||
{
|
||||
@@ -111,6 +110,7 @@ bool ffPrintCPU(FFCPUOptions* options)
|
||||
FF_FORMAT_ARG(coreTypes, "core-types"),
|
||||
FF_FORMAT_ARG(cpu.packages, "packages"),
|
||||
FF_FORMAT_ARG(cpu.march, "march"),
|
||||
FF_FORMAT_ARG(cpu.numaNodes, "numa-nodes"),
|
||||
}));
|
||||
}
|
||||
success = true;
|
||||
@@ -134,6 +134,12 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module)
|
||||
if (ffTempsParseJsonObject(key, val, &options->temp, &options->tempConfig))
|
||||
continue;
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "tempSensor"))
|
||||
{
|
||||
ffStrbufSetS(&options->tempSensor, unsafe_yyjson_get_str(val));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unsafe_yyjson_equals_str(key, "freqNdigits"))
|
||||
{
|
||||
ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits");
|
||||
@@ -217,6 +223,11 @@ bool ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
else
|
||||
yyjson_mut_obj_add_null(doc, obj, "march");
|
||||
|
||||
if (cpu.numaNodes > 0)
|
||||
yyjson_mut_obj_add_uint(doc, obj, "numaNodes", cpu.numaNodes);
|
||||
else
|
||||
yyjson_mut_obj_add_null(doc, obj, "numaNodes");
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
@@ -229,6 +240,7 @@ bool ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
void ffInitCPUOptions(FFCPUOptions* options)
|
||||
{
|
||||
ffOptionInitModuleArg(&options->moduleArgs, "");
|
||||
ffStrbufInit(&options->tempSensor);
|
||||
options->temp = false;
|
||||
options->tempConfig = (FFColorRangeConfig) { 60, 80 };
|
||||
options->showPeCoreCount = false;
|
||||
@@ -237,6 +249,7 @@ void ffInitCPUOptions(FFCPUOptions* options)
|
||||
void ffDestroyCPUOptions(FFCPUOptions* options)
|
||||
{
|
||||
ffOptionDestroyModuleArg(&options->moduleArgs);
|
||||
ffStrbufDestroy(&options->tempSensor);
|
||||
}
|
||||
|
||||
FFModuleBaseInfo ffCPUModuleInfo = {
|
||||
@@ -259,6 +272,7 @@ FFModuleBaseInfo ffCPUModuleInfo = {
|
||||
{"Temperature (formatted)", "temperature"},
|
||||
{"Logical core count grouped by frequency", "core-types"},
|
||||
{"Processor package count", "packages"},
|
||||
{"X86-64 CPU microarchitecture", "march"},
|
||||
{"CPU microarchitecture", "march"},
|
||||
{"NUMA node count", "numa-nodes"},
|
||||
}))
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ typedef struct FFCPUOptions
|
||||
{
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFstrbuf tempSensor;
|
||||
bool temp;
|
||||
FFColorRangeConfig tempConfig;
|
||||
bool showPeCoreCount;
|
||||
|
||||
@@ -28,7 +28,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options)
|
||||
{
|
||||
sumValue += *percent;
|
||||
|
||||
#if WIN32
|
||||
#if _WIN32
|
||||
// Windows may return values greater than 100%, cap them to 100%
|
||||
if (*percent > 100) *percent = 100;
|
||||
#endif
|
||||
@@ -48,7 +48,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options)
|
||||
++index;
|
||||
}
|
||||
double avgValue = sumValue / (double) valueCount;
|
||||
#if WIN32
|
||||
#if _WIN32
|
||||
// See above comment
|
||||
if (avgValue > 100) avgValue = 100;
|
||||
#endif
|
||||
|
||||
@@ -436,6 +436,7 @@ void ffInitDisplayOptions(FFDisplayOptions* options)
|
||||
ffOptionInitModuleArg(&options->moduleArgs, "");
|
||||
options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE;
|
||||
options->preciseRefreshRate = false;
|
||||
options->order = FF_DISPLAY_ORDER_NONE;
|
||||
}
|
||||
|
||||
void ffDestroyDisplayOptions(FFDisplayOptions* options)
|
||||
|
||||
@@ -36,6 +36,7 @@ typedef enum __attribute__((__packed__)) FFPackagesFlags
|
||||
FF_PACKAGES_FLAG_HPKG_BIT = 1ULL << 28,
|
||||
FF_PACKAGES_FLAG_PISI_BIT = 1ULL << 29,
|
||||
FF_PACKAGES_FLAG_SOAR_BIT = 1ULL << 30,
|
||||
FF_PACKAGES_FLAG_KISS_BIT = 1ULL << 31,
|
||||
FF_PACKAGES_FLAG_FORCE_UNSIGNED = UINT64_MAX,
|
||||
} FFPackagesFlags;
|
||||
static_assert(sizeof(FFPackagesFlags) == sizeof(uint64_t), "");
|
||||
|
||||
@@ -76,6 +76,7 @@ bool ffPrintPackages(FFPackagesOptions* options)
|
||||
FF_PRINT_PACKAGE(apk)
|
||||
FF_PRINT_PACKAGE(pkg)
|
||||
FF_PRINT_PACKAGE(pkgsrc)
|
||||
FF_PRINT_PACKAGE(kiss)
|
||||
if (options->combined)
|
||||
{
|
||||
FF_PRINT_PACKAGE_ALL(hpkg)
|
||||
@@ -194,6 +195,7 @@ bool ffPrintPackages(FFPackagesOptions* options)
|
||||
FF_FORMAT_ARG(counts.hpkgUser, "hpkg-user"),
|
||||
FF_FORMAT_ARG(counts.pisi, "pisi"),
|
||||
FF_FORMAT_ARG(counts.soar, "soar"),
|
||||
FF_FORMAT_ARG(counts.kiss, "kiss"),
|
||||
FF_FORMAT_ARG(nixAll, "nix-all"),
|
||||
FF_FORMAT_ARG(flatpakAll, "flatpak-all"),
|
||||
FF_FORMAT_ARG(brewAll, "brew-all"),
|
||||
@@ -268,6 +270,9 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
|
||||
case 'H': if (false);
|
||||
FF_TEST_PACKAGE_NAME(HPKG)
|
||||
break;
|
||||
case 'K': if (false);
|
||||
FF_TEST_PACKAGE_NAME(KISS)
|
||||
break;
|
||||
case 'L': if (false);
|
||||
FF_TEST_PACKAGE_NAME(LPKG)
|
||||
FF_TEST_PACKAGE_NAME(LPKGBUILD)
|
||||
@@ -346,6 +351,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
|
||||
FF_TEST_PACKAGE_NAME(FLATPAK)
|
||||
FF_TEST_PACKAGE_NAME(GUIX)
|
||||
FF_TEST_PACKAGE_NAME(HPKG)
|
||||
FF_TEST_PACKAGE_NAME(KISS)
|
||||
FF_TEST_PACKAGE_NAME(LINGLONG)
|
||||
FF_TEST_PACKAGE_NAME(LPKG)
|
||||
FF_TEST_PACKAGE_NAME(LPKGBUILD)
|
||||
@@ -425,6 +431,7 @@ bool ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
|
||||
FF_APPEND_PACKAGE_COUNT(scoopGlobal)
|
||||
FF_APPEND_PACKAGE_COUNT(snap)
|
||||
FF_APPEND_PACKAGE_COUNT(soar)
|
||||
FF_APPEND_PACKAGE_COUNT(kiss)
|
||||
FF_APPEND_PACKAGE_COUNT(sorcery)
|
||||
FF_APPEND_PACKAGE_COUNT(winget)
|
||||
FF_APPEND_PACKAGE_COUNT(xbps)
|
||||
@@ -498,6 +505,7 @@ FFModuleBaseInfo ffPackagesModuleInfo = {
|
||||
{"Number of hpkg-user packages", "hpkg-user"},
|
||||
{"Number of pisi packages", "pisi"},
|
||||
{"Number of soar packages", "soar"},
|
||||
{"Number of kiss packages", "kiss"},
|
||||
{"Total number of all nix packages", "nix-all"},
|
||||
{"Total number of all flatpak app packages", "flatpak-all"},
|
||||
{"Total number of all brew packages", "brew-all"},
|
||||
|
||||
+39
-11
@@ -4,6 +4,7 @@
|
||||
#include "common/size.h"
|
||||
#include "detection/zpool/zpool.h"
|
||||
#include "modules/zpool/zpool.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t index)
|
||||
@@ -22,6 +23,7 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&buffer, &options->moduleArgs.key, ((FFformatarg[]) {
|
||||
FF_FORMAT_ARG(index, "index"),
|
||||
FF_FORMAT_ARG(result->name, "name"),
|
||||
FF_FORMAT_ARG(result->guid, "guid"),
|
||||
FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"),
|
||||
}));
|
||||
}
|
||||
@@ -29,10 +31,14 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i
|
||||
FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate();
|
||||
ffSizeAppendNum(result->used, &usedPretty);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY allocatedPretty = ffStrbufCreate();
|
||||
ffSizeAppendNum(result->allocated, &allocatedPretty);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate();
|
||||
ffSizeAppendNum(result->total, &totalPretty);
|
||||
|
||||
double bytesPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0;
|
||||
double usedPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0;
|
||||
double allocatedPercentage = result->total > 0 ? (double) result->allocated / (double) result->total * 100.0 : 0;
|
||||
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
@@ -41,20 +47,31 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i
|
||||
|
||||
ffStrbufClear(&buffer);
|
||||
ffStrbufSetF(&buffer, "%s / %s (", usedPretty.chars, totalPretty.chars);
|
||||
ffPercentAppendNum(&buffer, bytesPercentage, options->percent, false, &options->moduleArgs);
|
||||
ffPercentAppendNum(&buffer, usedPercentage, options->percent, false, &options->moduleArgs);
|
||||
ffStrbufAppendS(&buffer, ", ");
|
||||
ffPercentAppendNum(&buffer, allocatedPercentage, options->percent, false, &options->moduleArgs);
|
||||
ffStrbufAppendS(&buffer, " allocated, ");
|
||||
ffPercentAppendNum(&buffer, result->fragmentation, options->percent, false, &options->moduleArgs);
|
||||
ffStrbufAppendF(&buffer, " frag) - %s", result->state.chars);
|
||||
if (result->readOnly)
|
||||
ffStrbufAppendS(&buffer, " [Read-only]");
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY bytesPercentageNum = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY usedPercentageNum = ffStrbufCreate();
|
||||
if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
|
||||
ffPercentAppendNum(&bytesPercentageNum, bytesPercentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY bytesPercentageBar = ffStrbufCreate();
|
||||
ffPercentAppendNum(&usedPercentageNum, usedPercentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY usedPercentageBar = ffStrbufCreate();
|
||||
if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
|
||||
ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs);
|
||||
ffPercentAppendBar(&usedPercentageBar, usedPercentage, options->percent, &options->moduleArgs);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY allocatedPercentageNum = ffStrbufCreate();
|
||||
if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
|
||||
ffPercentAppendNum(&allocatedPercentageNum, allocatedPercentage, options->percent, false, &options->moduleArgs);
|
||||
FF_STRBUF_AUTO_DESTROY allocatedPercentageBar = ffStrbufCreate();
|
||||
if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
|
||||
ffPercentAppendBar(&allocatedPercentageBar, allocatedPercentage, options->percent, &options->moduleArgs);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY fragPercentageNum = ffStrbufCreate();
|
||||
if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
|
||||
@@ -65,13 +82,18 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) {
|
||||
FF_FORMAT_ARG(result->name, "name"),
|
||||
FF_FORMAT_ARG(result->guid, "guid"),
|
||||
FF_FORMAT_ARG(result->state, "state"),
|
||||
FF_FORMAT_ARG(usedPretty, "size-used"),
|
||||
FF_FORMAT_ARG(allocatedPretty, "size-allocated"),
|
||||
FF_FORMAT_ARG(totalPretty, "size-total"),
|
||||
FF_FORMAT_ARG(bytesPercentageNum, "size-percentage"),
|
||||
FF_FORMAT_ARG(usedPercentageNum, "used-percentage"),
|
||||
FF_FORMAT_ARG(allocatedPercentageNum, "allocated-percentage"),
|
||||
FF_FORMAT_ARG(fragPercentageNum, "frag-percentage"),
|
||||
FF_FORMAT_ARG(bytesPercentageBar, "size-percentage-bar"),
|
||||
FF_FORMAT_ARG(usedPercentageBar, "used-percentage-bar"),
|
||||
FF_FORMAT_ARG(allocatedPercentageBar, "allocated-percentage-bar"),
|
||||
FF_FORMAT_ARG(fragPercentageBar, "frag-percentage-bar"),
|
||||
FF_FORMAT_ARG(result->readOnly, "is-readonly"),
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -149,13 +171,15 @@ bool ffGenerateZpoolJsonResult(FF_MAYBE_UNUSED FFZpoolOptions* options, yyjson_m
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &zpool->name);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "state", &zpool->state);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "guid", zpool->guid);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "used", zpool->used);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "allocated", zpool->allocated);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "total", zpool->total);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "version", zpool->version);
|
||||
if (zpool->fragmentation != -DBL_MAX)
|
||||
yyjson_mut_obj_add_real(doc, obj, "fragmentation", zpool->fragmentation);
|
||||
else
|
||||
yyjson_mut_obj_add_null(doc, obj, "fragmentation");
|
||||
yyjson_mut_obj_add_bool(doc, obj, "readOnly", zpool->readOnly);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFZpoolResult, zpool, results)
|
||||
@@ -188,12 +212,16 @@ FFModuleBaseInfo ffZpoolModuleInfo = {
|
||||
.generateJsonConfig = (void*) ffGenerateZpoolJsonConfig,
|
||||
.formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) {
|
||||
{"Zpool name", "name"},
|
||||
{"Zpool guid", "guid"},
|
||||
{"Zpool state", "state"},
|
||||
{"Size used", "used"},
|
||||
{"Size allocated", "allocated"},
|
||||
{"Size total", "total"},
|
||||
{"Size percentage num", "used-percentage"},
|
||||
{"Size used percentage num", "used-percentage"},
|
||||
{"Size allocated percentage num", "allocated-percentage"},
|
||||
{"Fragmentation percentage num", "fragmentation-percentage"},
|
||||
{"Size percentage bar", "used-percentage-bar"},
|
||||
{"Size used percentage bar", "used-percentage-bar"},
|
||||
{"Size allocated percentage bar", "allocated-percentage-bar"},
|
||||
{"Fragmentation percentage bar", "fragmentation-percentage-bar"},
|
||||
}))
|
||||
};
|
||||
|
||||
+5
-19
@@ -648,19 +648,7 @@ void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c)
|
||||
strbuf->length += num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a line from a FFstrbuf.
|
||||
*
|
||||
* @details Behaves like getline(3) but reads from a FFstrbuf.
|
||||
*
|
||||
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line.
|
||||
* Can be NULL for the first call.
|
||||
* @param[in,out] n The pointer to the size of the buffer of lineptr.
|
||||
* @param[in] buffer The buffer to read from. The buffer must not be a string literal.
|
||||
*
|
||||
* @return true if a line has been read, false if the end of the buffer has been reached.
|
||||
*/
|
||||
bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer)
|
||||
{
|
||||
assert(lineptr && n && buffer);
|
||||
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
|
||||
@@ -674,14 +662,14 @@ bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
*lineptr += *n;
|
||||
if (*lineptr >= pBufferEnd) // non-empty last line
|
||||
return false;
|
||||
**lineptr = '\n';
|
||||
**lineptr = delimiter;
|
||||
++*lineptr;
|
||||
}
|
||||
if (*lineptr >= pBufferEnd) // empty last line
|
||||
return false;
|
||||
|
||||
size_t remaining = (size_t) (pBufferEnd - *lineptr);
|
||||
char* ending = memchr(*lineptr, '\n', remaining);
|
||||
char* ending = memchr(*lineptr, delimiter, remaining);
|
||||
if (ending)
|
||||
{
|
||||
*n = (size_t) (ending - *lineptr);
|
||||
@@ -692,9 +680,7 @@ bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Restore the end of a line that was modified by ffStrbufGetline.
|
||||
/// @warning This function should be called before breaking an ffStrbufGetline loop.
|
||||
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer)
|
||||
{
|
||||
assert(buffer && lineptr && n);
|
||||
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
|
||||
@@ -705,7 +691,7 @@ void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
|
||||
*lineptr += *n;
|
||||
if (*lineptr < buffer->chars + buffer->length)
|
||||
**lineptr = '\n';
|
||||
**lineptr = delimiter;
|
||||
}
|
||||
|
||||
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf)
|
||||
|
||||
+27
-2
@@ -96,8 +96,33 @@ FF_C_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultV
|
||||
void ffStrbufUpperCase(FFstrbuf* strbuf);
|
||||
void ffStrbufLowerCase(FFstrbuf* strbuf);
|
||||
|
||||
bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer);
|
||||
void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer);
|
||||
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
|
||||
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
|
||||
|
||||
/**
|
||||
* @brief Read a line from a FFstrbuf.
|
||||
*
|
||||
* @details Behaves like getline(3) but reads from a FFstrbuf.
|
||||
*
|
||||
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line.
|
||||
* Can be NULL for the first call.
|
||||
* @param[in,out] n The pointer to the size of the buffer of lineptr.
|
||||
* @param[in] buffer The buffer to read from. The buffer must not be a string literal.
|
||||
*
|
||||
* @return true if a line has been read, false if the end of the buffer has been reached.
|
||||
*/
|
||||
static inline bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
{
|
||||
return ffStrbufGetdelim(lineptr, n, '\n', buffer);
|
||||
}
|
||||
/**
|
||||
* @brief Restore the end of a line that was modified by ffStrbufGetline.
|
||||
* @warning This function should be called before breaking an ffStrbufGetline loop.
|
||||
*/
|
||||
static inline void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer)
|
||||
{
|
||||
ffStrbufGetdelimRestore(lineptr, n, '\n', buffer);
|
||||
}
|
||||
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
|
||||
bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
bool ffStrbufMatchSeparatedIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
|
||||
|
||||
@@ -277,15 +277,32 @@ static bool detectTemp(io_connect_t conn, const char* sensor, double* sum)
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result)
|
||||
static io_connect_t conn;
|
||||
|
||||
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result)
|
||||
{
|
||||
static io_connect_t conn;
|
||||
if (!conn)
|
||||
{
|
||||
if (smcOpen(&conn) != NULL)
|
||||
conn = (io_connect_t) -1;
|
||||
}
|
||||
else if (conn == (io_connect_t) -1)
|
||||
if (conn == (io_connect_t) -1)
|
||||
return "Could not open SMC connection";
|
||||
|
||||
if (!detectTemp(conn, sensor, result))
|
||||
return "Could not read SMC temperature";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result)
|
||||
{
|
||||
if (!conn)
|
||||
{
|
||||
if (smcOpen(&conn) != NULL)
|
||||
conn = (io_connect_t) -1;
|
||||
}
|
||||
if (conn == (io_connect_t) -1)
|
||||
return "Could not open SMC connection";
|
||||
|
||||
uint32_t count = 0;
|
||||
|
||||
@@ -30,4 +30,5 @@ enum FFTempType
|
||||
FF_TEMP_MEMORY,
|
||||
};
|
||||
|
||||
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result);
|
||||
const char* ffDetectSmcTemps(enum FFTempType type, double* result);
|
||||
|
||||
@@ -64,13 +64,3 @@ const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ffIsAbsolutePath(const char* path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (ffCharIsEnglishAlphabet(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) // drive letter path
|
||||
|| (path[0] == '\\' && path[1] == '\\'); // UNC path
|
||||
#else
|
||||
return path[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
+11
-2
@@ -1,6 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
#include "util/FFstrbuf.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result);
|
||||
bool ffIsAbsolutePath(const char* path);
|
||||
static inline bool ffIsAbsolutePath(const char* path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (ffCharIsEnglishAlphabet(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) // drive letter path
|
||||
|| (path[0] == '\\' && path[1] == '\\'); // UNC path
|
||||
#else
|
||||
return path[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
static void getExePath(FFPlatform* platform)
|
||||
{
|
||||
char exePath[PATH_MAX + 1];
|
||||
char exePath[PATH_MAX];
|
||||
#if defined(__linux__) || defined (__GNU__)
|
||||
ssize_t exePathLen = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
|
||||
if (exePathLen >= 0)
|
||||
@@ -58,7 +58,7 @@ static void getExePath(FFPlatform* platform)
|
||||
|
||||
while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
|
||||
if (info.type == B_APP_IMAGE) {
|
||||
exePathLen = strlcpy(exePath, info.name, PATH_MAX);
|
||||
exePathLen = strlcpy(exePath, info.name, sizeof(exePath));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ static void getExePath(FFPlatform* platform)
|
||||
{
|
||||
wchar_t exePathW[MAX_PATH];
|
||||
DWORD exePathWLen = GetModuleFileNameW(NULL, exePathW, MAX_PATH);
|
||||
if (exePathWLen == 0 && exePathWLen >= MAX_PATH) return;
|
||||
if (exePathWLen == 0 || exePathWLen >= MAX_PATH) return;
|
||||
|
||||
FF_AUTO_CLOSE_FD HANDLE hPath = CreateFileW(exePathW, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (hPath != INVALID_HANDLE_VALUE)
|
||||
@@ -164,8 +164,12 @@ static void getHostName(FFPlatform* platform)
|
||||
static void getUserShell(FFPlatform* platform)
|
||||
{
|
||||
// Works in MSYS2
|
||||
ffStrbufAppendS(&platform->userShell, getenv("SHELL"));
|
||||
ffStrbufReplaceAllC(&platform->userShell, '\\', '/');
|
||||
const char* userShell = getenv("SHELL");
|
||||
if (userShell)
|
||||
{
|
||||
ffStrbufAppendS(&platform->userShell, userShell);
|
||||
ffStrbufReplaceAllC(&platform->userShell, '\\', '/');
|
||||
}
|
||||
}
|
||||
|
||||
static const char* detectWine(void)
|
||||
|
||||
@@ -232,3 +232,19 @@ typedef struct _D3DKMT_NODEMETADATA
|
||||
static_assert(sizeof(D3DKMT_NODEMETADATA) == 0x4E, "D3DKMT_NODEMETADATA structure size mismatch");
|
||||
|
||||
#endif
|
||||
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtQueryDirectoryFile(
|
||||
IN HANDLE FileHandle,
|
||||
IN HANDLE Event OPTIONAL,
|
||||
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
||||
IN PVOID ApcContext OPTIONAL,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
OUT PVOID FileInformation,
|
||||
IN ULONG Length,
|
||||
IN FILE_INFORMATION_CLASS FileInformationClass,
|
||||
IN BOOLEAN ReturnSingleEntry,
|
||||
IN PUNICODE_STRING FileName OPTIONAL,
|
||||
IN BOOLEAN RestartScan);
|
||||
|
||||
@@ -11,7 +11,7 @@ void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source)
|
||||
}
|
||||
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, source, (int)length, NULL, 0, NULL, NULL);
|
||||
if (size_needed < 0)
|
||||
if (size_needed <= 0)
|
||||
{
|
||||
ffStrbufSetF(result, "WCTMB failed: %u", (unsigned) GetLastError());
|
||||
return;
|
||||
@@ -21,3 +21,18 @@ void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source)
|
||||
result->length = (uint32_t)size_needed;
|
||||
result->chars[size_needed] = '\0';
|
||||
}
|
||||
|
||||
void ffStrbufAppendNWS(FFstrbuf* result, uint32_t length, const wchar_t* source)
|
||||
{
|
||||
if(!length)
|
||||
return;
|
||||
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, source, (int)length, NULL, 0, NULL, NULL);
|
||||
if (size_needed <= 0)
|
||||
return;
|
||||
|
||||
ffStrbufEnsureFree(result, (uint32_t)size_needed);
|
||||
WideCharToMultiByte(CP_UTF8, 0, source, (int)length, result->chars + result->length, size_needed, NULL, NULL);
|
||||
result->length += (uint32_t)size_needed;
|
||||
result->chars[result->length] = '\0';
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <wchar.h>
|
||||
|
||||
void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source);
|
||||
void ffStrbufAppendNWS(FFstrbuf* result, uint32_t length, const wchar_t* source);
|
||||
|
||||
static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source)
|
||||
{
|
||||
@@ -11,6 +12,12 @@ static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source)
|
||||
return ffStrbufSetNWS(result, (uint32_t)wcslen(source), source);
|
||||
}
|
||||
|
||||
static inline void ffStrbufAppendWS(FFstrbuf* result, const wchar_t* source)
|
||||
{
|
||||
if (!source) return;
|
||||
return ffStrbufAppendNWS(result, (uint32_t)wcslen(source), source);
|
||||
}
|
||||
|
||||
static inline void ffStrbufInitNWS(FFstrbuf* result, uint32_t length, const wchar_t* source)
|
||||
{
|
||||
ffStrbufInit(result);
|
||||
|
||||
Reference in New Issue
Block a user