mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:32:10 +02:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 469e21cce9 | |||
| 925e09c88a | |||
| 488454c1aa | |||
| c67c52d606 | |||
| e4e11ee509 | |||
| a3e2592555 | |||
| e0e966dadf | |||
| b079a8643b | |||
| 3291a9945f | |||
| 68fd21d0e4 | |||
| 0e1ef96992 | |||
| c377872438 | |||
| 4f42d38e4d | |||
| 7b2243496b | |||
| 960a817d03 | |||
| 6917f9479e | |||
| 8559cc45eb | |||
| 40e33c676d | |||
| d20371040e | |||
| 71faf1c7e3 | |||
| d182f3f743 | |||
| 39e009b945 | |||
| a1873f3e9e | |||
| 636bcaaaf9 | |||
| 3fcbd80ef0 | |||
| 38887e7fbd | |||
| da958e11f9 | |||
| c2ed71c4eb | |||
| 2e1ddcf9f8 | |||
| f1cc2d124c | |||
| 1e32a95f83 | |||
| 9e959bc57f | |||
| e68406ee22 | |||
| ba69e316b2 | |||
| f3e8e8af52 | |||
| c9adab3892 | |||
| c8d1d29017 | |||
| 541acca7c0 | |||
| ddf5099461 | |||
| 781a692b06 | |||
| 9c37f1b370 | |||
| a66c26f4df | |||
| 3bd750bedf | |||
| 4a1ada604c | |||
| e5f57a34a2 | |||
| 20a3737dce | |||
| e0452d9db5 | |||
| d8e74ba84c | |||
| 04b13096ac | |||
| 64d4035cae | |||
| 5e0ba57f53 | |||
| d89263c218 | |||
| 6a42588786 | |||
| 5883bf359c | |||
| 6a6b4070ca | |||
| 2c80cd6d29 | |||
| fa4b00b027 | |||
| 5fdc924b5d | |||
| 3d4a117093 | |||
| 7ec0c664c5 | |||
| 9d2df589b5 | |||
| 7107d08e92 | |||
| 4c34f99c12 | |||
| d7a8c92b46 | |||
| bbb29ff766 | |||
| 35235b9557 | |||
| 6b94605804 | |||
| 4b2fa07fdc | |||
| e203f4eeaf | |||
| 8db70b40e2 | |||
| 1f967849e5 | |||
| d60b2ddfd4 | |||
| fb68d8a841 | |||
| 047411ba87 | |||
| 08ed14b42a | |||
| d94a41cc1b | |||
| 81b7fb06c1 | |||
| c8debccd16 | |||
| 2853bd15c0 | |||
| 2f4146fde8 | |||
| eeceade14e | |||
| 1875c78e96 | |||
| f389864e17 | |||
| b9317734b9 | |||
| 4df4a1de78 | |||
| 0cd8c6ead6 | |||
| f8479dae94 | |||
| a7d623fa75 | |||
| 7a8ffb27bd | |||
| 73c0347469 | |||
| fde5f3bd0f | |||
| 9e1b1302fb |
+130
-8
@@ -383,7 +383,7 @@ jobs:
|
||||
run: |
|
||||
cat /etc/alpine-release
|
||||
uname -a
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
|
||||
shell: alpine.sh --root {0}
|
||||
|
||||
- name: build
|
||||
@@ -408,9 +408,9 @@ jobs:
|
||||
name: fastfetch-musl-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-universal:
|
||||
name: macOS-universal
|
||||
runs-on: macos-latest
|
||||
macos-amd64:
|
||||
name: macOS-amd64
|
||||
runs-on: macos-13
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -426,7 +426,7 @@ jobs:
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' .
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -452,7 +452,54 @@ jobs:
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-universal
|
||||
name: fastfetch-macos-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
macos-aarch64:
|
||||
name: macOS-aarch64
|
||||
runs-on: macos-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: uname -a
|
||||
run: uname -a
|
||||
|
||||
- name: install required packages
|
||||
run: |
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
|
||||
- name: list features
|
||||
run: ./fastfetch --list-features
|
||||
|
||||
- name: run fastfetch
|
||||
run: time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
|
||||
- name: run fastfetch --format json
|
||||
run: time ./fastfetch -c presets/ci.jsonc --format json
|
||||
|
||||
- name: run flashfetch
|
||||
run: time ./flashfetch
|
||||
|
||||
- name: print dependencies
|
||||
run: otool -L fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-macos-aarch64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
sunos-amd64:
|
||||
@@ -542,7 +589,7 @@ jobs:
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: '7.6'
|
||||
version: '7.7'
|
||||
run: |
|
||||
uname -a
|
||||
sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa
|
||||
@@ -597,6 +644,80 @@ jobs:
|
||||
name: fastfetch-netbsd-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
dragonfly-amd64:
|
||||
name: DragonFly-amd64
|
||||
runs-on: ubuntu-latest
|
||||
if: false
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: vmactions/dragonflybsd-vm@v1
|
||||
with:
|
||||
usesh: yes
|
||||
prepare: |
|
||||
uname -a
|
||||
pkg update
|
||||
pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl xfce4-conf egl opencl ocl-icd v4l_compat chafa libelf
|
||||
|
||||
run: |
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-dragonfly-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
haiku-amd64:
|
||||
name: Haiku-amd64
|
||||
runs-on: ubuntu-latest
|
||||
if: false
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run VM
|
||||
uses: cross-platform-actions/action@master
|
||||
with:
|
||||
operating_system: haiku
|
||||
architecture: x86-64
|
||||
cpu_count: 4
|
||||
shell: bash
|
||||
version: 'r1beta5'
|
||||
run: |
|
||||
uname -a
|
||||
ls -l
|
||||
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10
|
||||
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
|
||||
cmake --build . --target package --verbose -j4
|
||||
./fastfetch --list-features
|
||||
time ./fastfetch -c presets/ci.jsonc --stat false
|
||||
time ./fastfetch -c presets/ci.jsonc --format json
|
||||
time ./flashfetch
|
||||
ldd fastfetch
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-haiku-amd64
|
||||
path: ./fastfetch-*.*
|
||||
|
||||
windows-amd64:
|
||||
name: Windows-amd64
|
||||
runs-on: windows-latest
|
||||
@@ -734,7 +855,8 @@ jobs:
|
||||
- linux-ppc64le
|
||||
- linux-s390x
|
||||
- musl-amd64
|
||||
- macos-universal
|
||||
- macos-amd64
|
||||
- macos-aarch64
|
||||
- freebsd-amd64
|
||||
- openbsd-amd64
|
||||
- netbsd-amd64
|
||||
|
||||
@@ -1,3 +1,67 @@
|
||||
# 2.46.0
|
||||
|
||||
Features:
|
||||
* Support Rio terminal font detection (#1789, TerminalFont, Linux)
|
||||
* Support GPU detection by DRM on FreeBSD (GPU, FreeBSD)
|
||||
* Enable by `--gpu-detection-method auto`
|
||||
* Require proper DRM drivers installed and loaded
|
||||
* Support PowerPC CPU detection on NetBSD (#1802, CPU, NetBSD)
|
||||
* Support Aerospace WM detection (#1796, WM, macOS)
|
||||
* Improve Raspberry Pi OS for RPI5 detection (#1773, OS, Linux)
|
||||
* Support Linux Binary Compatibility detection on FreeBSD (#1786, Host, Linux)
|
||||
* Use `board-id` as board name if available (Board, macOS)
|
||||
* Intel only
|
||||
* Support shared VRAM usage detection for AMD GPUs (GPU, Linux)
|
||||
* Use `perflib.h` instead of `pdh.h` for CPU temperature querying to get rid of pdh.dll (#1787, CPU, Windows)
|
||||
* Support GPU info detection for old ATI radeon driver (#1810, GPU, Linux)
|
||||
* Add macOS 26 Tahoe support (macOS)
|
||||
* Report macOS 26 code name (OS)
|
||||
* Report Liquid Glass DE on macOS 26+ (DE)
|
||||
* Detect Metal 4 support (GPU)
|
||||
|
||||
Bugfixes:
|
||||
* Fix packages counting by ignoring hidden folders (Packages, OpenBSD)
|
||||
* Fix Hyprland version detection (WM, FreeBSD)
|
||||
* Don't show `Please insert a disk into drive D:` error dialogs (#1805, Disk, Windows)
|
||||
* Hide `/boot/firmware` by default (Disk, Linux)
|
||||
|
||||
Logos:
|
||||
* Rename Hydra Framework to HydraPwk (#1812)
|
||||
* Add AnushOS (#1806)
|
||||
* Add HarmonyOS (#1804)
|
||||
* Add GhostFreak (#1801)
|
||||
* Add TrueNAS Scale (#1795)
|
||||
* Add Fedora2_small (#1785)
|
||||
* Add xenia_old; update colors of xenia (#1797)
|
||||
* Improve colors of bedrock_small (#1790)
|
||||
* Add Kalpa Desktop (#1807)
|
||||
|
||||
# 2.45.0
|
||||
|
||||
Features:
|
||||
* Support OnePlus marketing name detection (#1768, Host, Android)
|
||||
* Recognize additional GPU vendors (GPU, Linux)
|
||||
* Support CTWM, FVWM and I3 window manager version detection (WM)
|
||||
* Support KDE version detection on *BSD (DE, FreeBSD)
|
||||
* Support `"logo": { "type": "command-raw" }` to run a command and display its output as logo (#1780, Logo)
|
||||
* Useful for displaying custom logos generated by other programs such as `pokeget`: `{ "type": "command-raw", "source": "pokeget random --hide-name" }`
|
||||
* Supported in JSONC config file only. `pokeget random --hide-name | fastfetch --file-raw -` should be used in shell.
|
||||
* Acquire SMBIOS information on DragonFly BSD from `/dev/mem`; legacy BIOS only (PhysicalMemory, DragonFly)
|
||||
* Support swap usage detection on DragonFly BSD (Swap, DragonFly)
|
||||
* Support `--swap-separate` to display detailed swap devices on separate lines (Swap)
|
||||
|
||||
Bugfixes
|
||||
* Fix MacBook Air model name (#1779, Host, macOS)
|
||||
* Don't ignore sshfs mountpoints (#1776, Disk, Linux / FreeBSD)
|
||||
* Fix dnf package count detection (#1777, Packages, Linux)
|
||||
|
||||
Logos:
|
||||
* Add Starry Linux (#1771)
|
||||
* Add rhel_small (#1774)
|
||||
* Update color palette of voidlinux (#1775)
|
||||
* Add void2
|
||||
* Update Xenia Linux (#1783)
|
||||
|
||||
# 2.44.0
|
||||
|
||||
Features:
|
||||
|
||||
+26
-20
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.44.0
|
||||
VERSION 2.46.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -61,7 +61,7 @@ cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeB
|
||||
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF)
|
||||
cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX OR FreeBSD" OFF)
|
||||
cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF)
|
||||
cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR Haiku" OFF)
|
||||
@@ -529,6 +529,7 @@ if(LINUX)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_linux.c
|
||||
src/detection/gpu/gpu_drm.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_linux.c
|
||||
@@ -676,6 +677,7 @@ elseif(FreeBSD)
|
||||
src/detection/displayserver/linux/xlib.c
|
||||
src/detection/font/font_linux.c
|
||||
src/detection/gpu/gpu_bsd.c
|
||||
src/detection/gpu/gpu_drm.c
|
||||
src/detection/gpu/gpu_pci.c
|
||||
src/detection/gtk_qt/gtk.c
|
||||
src/detection/host/host_bsd.c
|
||||
@@ -787,7 +789,7 @@ elseif(NetBSD)
|
||||
src/detection/netio/netio_bsd.c
|
||||
src/detection/opengl/opengl_linux.c
|
||||
src/detection/os/os_nbsd.c
|
||||
src/detection/packages/packages_obsd.c
|
||||
src/detection/packages/packages_nbsd.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_nbsd.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
@@ -802,7 +804,7 @@ elseif(NetBSD)
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nbsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/wm/wm_linux.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
@@ -884,7 +886,7 @@ elseif(OpenBSD)
|
||||
src/detection/users/users_obsd.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_obsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/wm/wm_linux.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
src/detection/camera/camera_linux.c
|
||||
@@ -1593,7 +1595,6 @@ elseif(WIN32)
|
||||
PRIVATE "winbrand"
|
||||
PRIVATE "propsys"
|
||||
PRIVATE "secur32"
|
||||
PRIVATE "pdh"
|
||||
)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
|
||||
# WoA only works on Windows 10 or higher
|
||||
@@ -1925,17 +1926,17 @@ install(
|
||||
##################
|
||||
|
||||
set(CPACK_GENERATOR "TGZ;ZIP")
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "amd64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "aarch64")
|
||||
endif()
|
||||
if(APPLE)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-universal" CPACK_PACKAGE_FILE_NAME)
|
||||
else() # We don't use this in Windows
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
|
||||
set(CMAKE_SYSTEM_PROCESSOR "amd64")
|
||||
endif()
|
||||
if(IS_MUSL)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
else()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
endif()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-macos-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME) # use macos instead of darwin
|
||||
elseif(IS_MUSL)
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-musl-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
else()
|
||||
string(TOLOWER "${CMAKE_PROJECT_NAME}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" CPACK_PACKAGE_FILE_NAME)
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
@@ -1961,12 +1962,17 @@ if(LINUX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_program(HAVE_RPMBUILD "rpmbuild")
|
||||
if(HAVE_RPMBUILD)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
|
||||
if(NOT IS_MUSL)
|
||||
find_program(HAVE_RPMBUILD "rpmbuild")
|
||||
if(HAVE_RPMBUILD)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
|
||||
endif()
|
||||
endif()
|
||||
elseif(FreeBSD)
|
||||
set(CPACK_FREEBSD_PACKAGE_LICENSE "MIT")
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};FREEBSD")
|
||||
endif()
|
||||
|
||||
set(CPACK_SET_DESTDIR ON)
|
||||
|
||||
Vendored
+12
@@ -1,3 +1,15 @@
|
||||
fastfetch (2.45.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.45.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 05 Jun 2025 10:56:38 +0800
|
||||
|
||||
fastfetch (2.44.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.44.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 26 May 2025 14:59:01 +0800
|
||||
|
||||
fastfetch (2.43.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.43.0
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.43.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.45.0_source.buildinfo universe/utils optional
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"biosFormat": {
|
||||
"description": "Output format of the module `Bios`. See Wiki for formatting syntax\n 1. {date}: Bios date\n 2. {release}: Bios release\n 3. {vendor}: Bios vendor\n 4. {version}: Bios version\n 5. {type}: Firmware type",
|
||||
"description": "Output format of the module `BIOS`. See Wiki for formatting syntax\n 1. {date}: Bios date\n 2. {release}: Bios release\n 3. {vendor}: Bios vendor\n 4. {version}: Bios version\n 5. {type}: Firmware type",
|
||||
"type": "string"
|
||||
},
|
||||
"bluetoothFormat": {
|
||||
@@ -339,7 +339,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"titleFormat": {
|
||||
"description": "Output format of the module `Title`. See Wiki for formatting syntax\n 1. {user-name}: User name\n 2. {host-name}: Host name\n 3. {home-dir}: Home directory\n 4. {exe-path}: Executable path of current process\n 5. {user-shell}: User's default shell\n 6. {user-name-colored}: User name (colored)\n 7. {at-symbol-colored}: @ symbol (colored)\n 8. {host-name-colored}: Host name (colored)",
|
||||
"description": "Output format of the module `Title`. See Wiki for formatting syntax\n 1. {user-name}: User name\n 2. {host-name}: Host name\n 3. {home-dir}: Home directory\n 4. {exe-path}: Executable path of current process\n 5. {user-shell}: User's default shell\n 6. {user-name-colored}: User name (colored)\n 7. {at-symbol-colored}: @ symbol (colored)\n 8. {host-name-colored}: Host name (colored)\n 9. {full-user-name}: Full user name",
|
||||
"type": "string"
|
||||
},
|
||||
"themeFormat": {
|
||||
@@ -429,6 +429,7 @@
|
||||
"file-raw",
|
||||
"data",
|
||||
"data-raw",
|
||||
"command-raw",
|
||||
"sixel",
|
||||
"kitty",
|
||||
"kitty-direct",
|
||||
@@ -3001,6 +3002,11 @@
|
||||
"const": "swap",
|
||||
"description": "Print swap (paging file) space usage"
|
||||
},
|
||||
"separate": {
|
||||
"type": "boolean",
|
||||
"description": "Set if detailed swap devices should be reported on separate lines instead of a summary",
|
||||
"default": false
|
||||
},
|
||||
"percent": {
|
||||
"$ref": "#/$defs/percent"
|
||||
},
|
||||
|
||||
+4
-1
@@ -52,7 +52,10 @@
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
"swap",
|
||||
{
|
||||
"type": "swap",
|
||||
"separate": true
|
||||
},
|
||||
"disk",
|
||||
"btrfs",
|
||||
"zpool",
|
||||
|
||||
+4
-1
@@ -54,7 +54,10 @@
|
||||
},
|
||||
"memory",
|
||||
"physicalmemory",
|
||||
"swap",
|
||||
{
|
||||
"type": "swap",
|
||||
"separate": true
|
||||
},
|
||||
"disk",
|
||||
"btrfs",
|
||||
"zpool",
|
||||
|
||||
@@ -105,6 +105,7 @@ void ffStart(void)
|
||||
ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc;
|
||||
|
||||
#ifdef _WIN32
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
if (instance.config.display.noBuffer)
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
else
|
||||
|
||||
@@ -290,7 +290,7 @@ bool ffSuppressIO(bool suppress)
|
||||
|
||||
void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indentation, const char* folderName, bool pretty)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int dfd = open(folder->chars, O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int dfd = open(folder->chars, O_RDONLY | O_CLOEXEC);
|
||||
if (dfd < 0)
|
||||
return;
|
||||
|
||||
|
||||
+2
-2
@@ -1144,11 +1144,11 @@
|
||||
"arg": {
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"auto": "Query platform-specific graphics APIs. Requires proper GPU drivers to be installed. Not supported on BSDs",
|
||||
"auto": "Query platform-specific graphics APIs. Requires proper GPU drivers to be installed. Supported on Linux, FreeBSD, Windows and macOS",
|
||||
"pci": "Search PCI devices, which does not require GPU drivers to be installed. Not supported on Windows and macOS",
|
||||
"vulkan": "Use Vulkan API. Slow and requires proper Vulkan drivers to be installed. Used for Android",
|
||||
"opencl": "Use OpenCL API. Slow and requires proper OpenCL drivers to be installed",
|
||||
"opengl": "Use OpenGL API. Slow and only detects one GPU"
|
||||
"opengl": "Use OpenGL API. Slow and only detects one GPU. Used for OpenBSD"
|
||||
},
|
||||
"default": "auto"
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
|
||||
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
|
||||
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";
|
||||
|
||||
prop_dictionary_t root = NULL;
|
||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int devfd = open("/dev/apm", O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (devfd < 0) return "open(dev/apm, O_RDONLY) failed";
|
||||
if (devfd < 0) return "open(dev/apm, O_RDONLY | O_CLOEXEC) failed";
|
||||
|
||||
struct apm_power_info info = {};
|
||||
|
||||
|
||||
@@ -9,9 +9,19 @@ const char* ffDetectBoard(FFBoardResult* result)
|
||||
if (!service)
|
||||
return "No IOPlatformExpertDevice found";
|
||||
|
||||
io_name_t name;
|
||||
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
|
||||
ffStrbufSetS(&result->name, name);
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef boardId = IORegistryEntryCreateCFProperty(service, CFSTR("board-id"), kCFAllocatorDefault, kNilOptions);
|
||||
if (boardId)
|
||||
ffCfStrGetString(boardId, &result->name);
|
||||
else
|
||||
{
|
||||
io_name_t name;
|
||||
if (IORegistryEntryGetName(service, name) == kIOReturnSuccess)
|
||||
ffStrbufSetS(&result->name, name);
|
||||
}
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef version = IORegistryEntryCreateCFProperty(service, CFSTR("version"), kCFAllocatorDefault, kNilOptions);
|
||||
if (version)
|
||||
ffCfStrGetString(version, &result->version);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFTypeRef manufacturer = IORegistryEntryCreateCFProperty(service, CFSTR("manufacturer"), kCFAllocatorDefault, kNilOptions);
|
||||
if (manufacturer)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR);
|
||||
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR | O_CLOEXEC);
|
||||
if (efifd < 0) return "open(/dev/efi) failed";
|
||||
|
||||
uint8_t buffer[2048];
|
||||
|
||||
@@ -12,7 +12,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl
|
||||
for (char i = '0'; i <= '9'; ++i) {
|
||||
path[strlen("/dev/ttyC")] = i;
|
||||
|
||||
FF_AUTO_CLOSE_FD int devfd = open(path, O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int devfd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
|
||||
if (devfd < 0) {
|
||||
if (errno == EACCES && i == '0')
|
||||
|
||||
@@ -20,7 +20,7 @@ const char* ffDetectCamera(FFlist* result)
|
||||
for (uint32_t i = 0; i <= 9; ++i)
|
||||
{
|
||||
path[ARRAY_SIZE(path) - 2] = (char) (i + '0');
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
|
||||
@@ -474,7 +474,7 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
|
||||
|
||||
static const char* detectPhysicalCores(FFCPUResult* cpu)
|
||||
{
|
||||
int dfd = open("/sys/devices/system/cpu/", O_RDONLY | O_DIRECTORY);
|
||||
int dfd = open("/sys/devices/system/cpu/", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
if (dfd < 0) return "open(\"/sys/devices/system/cpu/\") failed";
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = fdopendir(dfd);
|
||||
|
||||
@@ -18,8 +18,8 @@ static void freePropDict(prop_dictionary_t* pdict)
|
||||
|
||||
static const char* detectCpuTemp(double* current)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open(_PATH_SYSMON, O_RDONLY);
|
||||
if (fd < 0) return "open(_PATH_SYSMON, O_RDONLY) failed";
|
||||
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";
|
||||
|
||||
__attribute__((__cleanup__(freePropDict))) prop_dictionary_t root = NULL;
|
||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &root) < 0)
|
||||
@@ -51,7 +51,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.cpu_brand", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("machdep.dmi.processor-version", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("hw.cpu0.name", &cpu->name) != NULL)
|
||||
ffSysctlGetString("hw.cpu0.name", &cpu->name) != NULL &&
|
||||
ffSysctlGetString("hw.model", &cpu->name) != NULL)
|
||||
{
|
||||
ffStrbufSetS(&cpu->name, "Unknown CPU");
|
||||
}
|
||||
|
||||
@@ -4,42 +4,116 @@
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
#include <pdh.h>
|
||||
#include <windows.h>
|
||||
#include "perflib_.h"
|
||||
#include <wchar.h>
|
||||
|
||||
static void ffPdhOpenCloseQuery(HQUERY* query)
|
||||
static inline void ffPerfCloseQueryHandle(HANDLE* phQuery)
|
||||
{
|
||||
assert(query);
|
||||
if (*query)
|
||||
if (*phQuery != NULL)
|
||||
{
|
||||
PdhCloseQuery(*query);
|
||||
*query = NULL;
|
||||
PerfCloseQueryHandle(*phQuery);
|
||||
*phQuery = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* detectThermalTemp(double* result)
|
||||
const char* detectThermalTemp(double* result)
|
||||
{
|
||||
// typeperf.exe -sc 1 "\Thermal Zone Information(*)\Temperature"
|
||||
struct FFPerfQuerySpec
|
||||
{
|
||||
PERF_COUNTER_IDENTIFIER Identifier;
|
||||
WCHAR Name[16];
|
||||
} querySpec = {
|
||||
.Identifier = {
|
||||
// Thermal Zone Information
|
||||
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{383487a6-3676-4870-a4e7-d45b30c35629}\{52bc5412-dac2-449c-8bc2-96443888fe6b}
|
||||
.CounterSetGuid = { 0x52bc5412, 0xdac2, 0x449c, {0x8b, 0xc2, 0x96, 0x44, 0x38, 0x88, 0xfe, 0x6b} },
|
||||
.Size = sizeof(querySpec),
|
||||
.CounterId = PERF_WILDCARD_COUNTER,
|
||||
.InstanceId = PERF_WILDCARD_COUNTER,
|
||||
},
|
||||
.Name = L"\\_TZ.CPUZ", // The standard(?) instance name for CPU temperature in the thermal provider
|
||||
};
|
||||
|
||||
__attribute__((__cleanup__(ffPdhOpenCloseQuery))) HQUERY query = NULL;
|
||||
DWORD dataSize = 0;
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
|
||||
return "PerfEnumerateCounterSetInstances() failed";
|
||||
|
||||
if (PdhOpenQueryW(NULL, 0, &query) != ERROR_SUCCESS)
|
||||
return "Failed to open PDH query";
|
||||
if (dataSize <= sizeof(PERF_INSTANCE_HEADER))
|
||||
return "No `Thermal Zone Information` instances found";
|
||||
|
||||
HCOUNTER counter = NULL;
|
||||
if (PdhAddEnglishCounterW(query,
|
||||
L"\\Thermal Zone Information(*)\\Temperature",
|
||||
0,
|
||||
&counter) != ERROR_SUCCESS)
|
||||
return "Failed to add TZI temperature counter";
|
||||
{
|
||||
FF_AUTO_FREE PERF_INSTANCE_HEADER* const pHead = malloc(dataSize);
|
||||
if (PerfEnumerateCounterSetInstances(NULL, &querySpec.Identifier.CounterSetGuid, pHead, dataSize, &dataSize) != ERROR_SUCCESS)
|
||||
return "PerfEnumerateCounterSetInstances() failed to get instance headers";
|
||||
|
||||
if (PdhCollectQueryData(query) != ERROR_SUCCESS)
|
||||
return "Failed to collect query data";
|
||||
PERF_INSTANCE_HEADER* pInstanceHeader = pHead;
|
||||
while (1)
|
||||
{
|
||||
const wchar_t* instanceName = (const wchar_t*)((BYTE*)pInstanceHeader + sizeof(*pInstanceHeader));
|
||||
if (wcscmp(instanceName, querySpec.Name) == 0)
|
||||
break;
|
||||
|
||||
PDH_FMT_COUNTERVALUE value;
|
||||
if (PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, NULL, &value) != ERROR_SUCCESS)
|
||||
return "Failed to format counter value";
|
||||
dataSize -= pInstanceHeader->Size;
|
||||
if (dataSize == 0)
|
||||
break;
|
||||
pInstanceHeader = (PERF_INSTANCE_HEADER*)((BYTE*)pInstanceHeader + pInstanceHeader->Size);
|
||||
}
|
||||
|
||||
*result = value.doubleValue - 273;
|
||||
if (dataSize == 0)
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((__cleanup__(ffPerfCloseQueryHandle)))
|
||||
HANDLE hQuery = NULL;
|
||||
|
||||
if (PerfOpenQueryHandle(NULL, &hQuery) != ERROR_SUCCESS)
|
||||
return "PerfOpenQueryHandle() failed";
|
||||
|
||||
if (PerfAddCounters(hQuery, &querySpec.Identifier, sizeof(querySpec)) != ERROR_SUCCESS)
|
||||
return "PerfAddCounters() failed";
|
||||
|
||||
if (querySpec.Identifier.Status != ERROR_SUCCESS)
|
||||
return "PerfAddCounters() reports invalid identifier";
|
||||
|
||||
if (PerfQueryCounterData(hQuery, NULL, 0, &dataSize) != ERROR_NOT_ENOUGH_MEMORY)
|
||||
return "PerfQueryCounterData(NULL) failed";
|
||||
|
||||
if (dataSize <= sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER)) // PERF_ERROR_RETURN, should not happen
|
||||
return "instance doesn't exist";
|
||||
|
||||
FF_AUTO_FREE PERF_DATA_HEADER* const pDataHeader = malloc(dataSize);
|
||||
|
||||
if (PerfQueryCounterData(hQuery, pDataHeader, dataSize, &dataSize) != ERROR_SUCCESS)
|
||||
return "PerfQueryCounterData(pDataHeader) failed";
|
||||
|
||||
PERF_COUNTER_HEADER* pCounterHeader = (PERF_COUNTER_HEADER*)(pDataHeader + 1);
|
||||
if (pCounterHeader->dwType != PERF_MULTIPLE_COUNTERS)
|
||||
return "Invalid counter type";
|
||||
|
||||
PERF_MULTI_COUNTERS* pMultiCounters = (PERF_MULTI_COUNTERS*)(pCounterHeader + 1);
|
||||
PERF_COUNTER_DATA* pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pMultiCounters + pMultiCounters->dwSize);
|
||||
|
||||
for (ULONG iCounter = 0; iCounter != pMultiCounters->dwCounters; iCounter++)
|
||||
{
|
||||
if (pCounterData->dwDataSize == sizeof(int32_t))
|
||||
{
|
||||
DWORD* pCounterIds = (DWORD*)(pMultiCounters + 1);
|
||||
switch (pCounterIds[iCounter]) {
|
||||
case 0: // Temperature
|
||||
*result = *(int32_t*)(pCounterData + 1) - 273;
|
||||
break;
|
||||
case 3: // High Precision Temperature
|
||||
*result = *(int32_t*)(pCounterData + 1) / 10.0 - 273;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pCounterData = (PERF_COUNTER_DATA*)((BYTE*)pCounterData + pCounterData->dwSize);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -151,7 +225,7 @@ static const char* detectNCores(FFCPUResult* cpu)
|
||||
else if (ptr->Relationship == RelationProcessorCore)
|
||||
++cpu->coresPhysical;
|
||||
else if (ptr->Relationship == RelationProcessorPackage)
|
||||
cpu->packages++;
|
||||
++cpu->packages;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <perflib.h>
|
||||
|
||||
// Missing from <perflib.h> of MinGW-w64 SDK
|
||||
|
||||
#define PERF_WILDCARD_COUNTER 0xFFFFFFFF
|
||||
#define PERF_WILDCARD_INSTANCE L"*"
|
||||
#define PERF_AGGREGATE_INSTANCE L"_Total"
|
||||
#define PERF_MAX_INSTANCE_NAME 1024
|
||||
|
||||
typedef struct _PERF_INSTANCE_HEADER {
|
||||
ULONG Size; // = sizeof(PERF_INSTANCE_HEADER) + sizeof(InstanceName) + sizeof(Padding)
|
||||
ULONG InstanceId; // Instance ID.
|
||||
// Followed by:
|
||||
// WCHAR InstanceName[]; // Nul-terminated.
|
||||
// WCHAR Padding[]; // Pad to a multiple of 8 bytes
|
||||
} PERF_INSTANCE_HEADER, *PPERF_INSTANCE_HEADER;
|
||||
|
||||
typedef struct _PERF_COUNTER_IDENTIFIER {
|
||||
GUID CounterSetGuid; // The GUID of the counterset.
|
||||
ULONG Status; // Win32 error code indicating success/failure of the add/delete operation.
|
||||
ULONG Size; // sizeof(PERF_COUNTER_IDENTIFIER) + sizeof(InstanceName) + sizeof(Padding)
|
||||
ULONG CounterId; // CounterId, or PERF_WILDCARD_COUNTER for all counters.
|
||||
ULONG InstanceId; // InstanceId, or 0xFFFFFFFF to not filter on instance ID.
|
||||
ULONG Index; // Set by PerfQueryCounterInfo to the position in which the corresponding counter data is returned.
|
||||
ULONG Reserved; // Reserved.
|
||||
// Followed by:
|
||||
// WCHAR InstanceName[];
|
||||
// WCHAR Padding[];
|
||||
} PERF_COUNTER_IDENTIFIER, * PPERF_COUNTER_IDENTIFIER;
|
||||
|
||||
typedef struct _PERF_DATA_HEADER {
|
||||
ULONG dwTotalSize; // = sizeof(PERF_DATA_HEADER) + sizeof(PERF_COUNTER_HEADER blocks...)
|
||||
ULONG dwNumCounters; // The number of PERF_COUNTER_HEADER blocks.
|
||||
LONGLONG PerfTimeStamp; // Timestamp from a high-resolution clock.
|
||||
LONGLONG PerfTime100NSec; // The number of 100 nanosecond intervals since January 1, 1601, in Coordinated Universal Time (UTC).
|
||||
LONGLONG PerfFreq; // The frequency of a high-resolution clock.
|
||||
SYSTEMTIME SystemTime; // The time at which data is collected on the provider side.
|
||||
// Followed by:
|
||||
// PERF_COUNTER_HEADER blocks...;
|
||||
} PERF_DATA_HEADER, * PPERF_DATA_HEADER;
|
||||
|
||||
typedef enum _PerfCounterDataType {
|
||||
PERF_ERROR_RETURN = 0, /* An error occurred when the performance counter value was queried. */
|
||||
PERF_SINGLE_COUNTER = 1, /* Query returned a single counter from a single-instance. */
|
||||
PERF_MULTIPLE_COUNTERS = 2, /* Query returned multiple counters from a single instance. */
|
||||
PERF_MULTIPLE_INSTANCES = 4, /* Query returned a single counter from each of multiple instances. */
|
||||
PERF_COUNTERSET = 6 /* Query returned multiple counters from each of multiple instances. */
|
||||
} PerfCounterDataType;
|
||||
|
||||
typedef struct _PERF_COUNTER_HEADER {
|
||||
ULONG dwStatus; // Win32 error code indicating success/failure of the query operation.
|
||||
PerfCounterDataType dwType; // Result type - error, single/single, multi/single, single/multi, multi/multi.
|
||||
ULONG dwSize; // = sizeof(PERF_COUNTER_HEADER) + sizeof(Additional data)
|
||||
ULONG Reserved; // Reserved.
|
||||
// Followed by additional data:
|
||||
// If dwType == PERF_ERROR_RETURN: nothing.
|
||||
// If dwType == PERF_SINGLE_COUNTER: PERF_COUNTER_DATA block.
|
||||
// If dwType == PERF_MULTIPLE_COUNTERS: PERF_MULTI_COUNTERS block + PERF_COUNTER_DATA blocks.
|
||||
// If dwType == PERF_MULTIPLE_INSTANCES: PERF_MULTI_INSTANCES block.
|
||||
// If dwType == PERF_COUNTERSET: PERF_MULTI_COUNTERS block + PERF_MULTI_INSTANCES block.
|
||||
} PERF_COUNTER_HEADER, * PPERF_COUNTER_HEADER;
|
||||
|
||||
typedef struct _PERF_MULTI_COUNTERS {
|
||||
ULONG dwSize; // sizeof(PERF_MULTI_COUNTERS) + sizeof(CounterIds)
|
||||
ULONG dwCounters; // Number of counter ids.
|
||||
// Followed by:
|
||||
// DWORD CounterIds[dwCounters];
|
||||
} PERF_MULTI_COUNTERS, * PPERF_MULTI_COUNTERS;
|
||||
|
||||
typedef struct _PERF_COUNTER_DATA {
|
||||
ULONG dwDataSize; // Size of the counter data, in bytes.
|
||||
ULONG dwSize; // = sizeof(PERF_COUNTER_DATA) + sizeof(Data) + sizeof(Padding)
|
||||
// Followed by:
|
||||
// BYTE Data[dwDataSize];
|
||||
// BYTE Padding[];
|
||||
} PERF_COUNTER_DATA, * PPERF_COUNTER_DATA;
|
||||
|
||||
_Success_(return == ERROR_SUCCESS)
|
||||
ULONG
|
||||
WINAPI
|
||||
PerfEnumerateCounterSetInstances(
|
||||
_In_opt_z_ LPCWSTR szMachine,
|
||||
_In_ LPCGUID pCounterSetId,
|
||||
_Out_opt_bytecap_post_bytecount_(cbInstances, *pcbInstancesActual) PPERF_INSTANCE_HEADER pInstances,
|
||||
DWORD cbInstances,
|
||||
_Out_ LPDWORD pcbInstancesActual
|
||||
);
|
||||
|
||||
_Success_(return == ERROR_SUCCESS)
|
||||
ULONG
|
||||
WINAPI
|
||||
PerfOpenQueryHandle(
|
||||
_In_opt_z_ LPCWSTR szMachine,
|
||||
_Out_ HANDLE * phQuery
|
||||
);
|
||||
|
||||
_Success_(return == ERROR_SUCCESS)
|
||||
ULONG
|
||||
WINAPI
|
||||
PerfCloseQueryHandle(
|
||||
_In_ HANDLE hQuery
|
||||
);
|
||||
|
||||
_Success_(return == ERROR_SUCCESS)
|
||||
ULONG
|
||||
WINAPI
|
||||
PerfAddCounters(
|
||||
_In_ HANDLE hQuery,
|
||||
_Inout_bytecount_(cbCounters) PPERF_COUNTER_IDENTIFIER pCounters,
|
||||
DWORD cbCounters
|
||||
);
|
||||
|
||||
_Success_(return == ERROR_SUCCESS)
|
||||
ULONG
|
||||
WINAPI
|
||||
PerfDeleteCounters(
|
||||
_In_ HANDLE hQuery,
|
||||
_Inout_bytecount_(cbCounters) PPERF_COUNTER_IDENTIFIER pCounters,
|
||||
DWORD cbCounters
|
||||
);
|
||||
|
||||
_Success_(return == ERROR_SUCCESS)
|
||||
ULONG
|
||||
WINAPI
|
||||
PerfQueryCounterData(
|
||||
_In_ HANDLE hQuery,
|
||||
_Out_opt_bytecap_post_bytecount_(cbCounterBlock, *pcbCounterBlockActual) PPERF_DATA_HEADER pCounterBlock,
|
||||
DWORD cbCounterBlock,
|
||||
_Out_ LPDWORD pcbCounterBlockActual
|
||||
);
|
||||
@@ -10,18 +10,29 @@
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <paths.h>
|
||||
#ifndef _PATH_LOCALBASE
|
||||
#define _PATH_LOCALBASE "/usr/local"
|
||||
#endif
|
||||
#elif __OpenBSD__
|
||||
#define _PATH_LOCALBASE "/usr/local"
|
||||
#elif __NetBSD__
|
||||
#define _PATH_LOCALBASE "/usr/pkg"
|
||||
#endif
|
||||
|
||||
static void getKDE(FFstrbuf* result, FFDEOptions* options)
|
||||
{
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
#ifdef _PATH_LOCALBASE
|
||||
ffParsePropFile(_PATH_LOCALBASE "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
{
|
||||
ffParsePropFileValues(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", 1, (FFpropquery[]) {
|
||||
{"X-KDE-PluginInfo-Version =", result}
|
||||
});
|
||||
}
|
||||
ffParsePropFile(_PATH_LOCALBASE "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
#else
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
ffParsePropFile(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
#endif
|
||||
|
||||
if(result->length == 0)
|
||||
ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result);
|
||||
if(result->length == 0)
|
||||
|
||||
@@ -52,7 +52,7 @@ static const char* detectFsLabel(struct statfs* fs, FFDisk* disk)
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
static const char* detectFsLabel(struct statfs* fs, FFDisk* disk)
|
||||
static const char* detectFsLabel(FF_MAYBE_UNUSED struct statfs* fs, FF_MAYBE_UNUSED FFDisk* disk)
|
||||
{
|
||||
return "Fastfetch was compiled without libgeom support";
|
||||
}
|
||||
@@ -148,7 +148,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
if(!ffDiskMatchMountpoint(&options->folders, fs->f_mntonname))
|
||||
continue;
|
||||
}
|
||||
else if(!ffStrEquals(fs->f_mntonname, "/") && !ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs"))
|
||||
else if(!ffStrEquals(fs->f_mntonname, "/") && !ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs") && !ffStrEquals(fs->f_fstypename, "fusefs.sshfs"))
|
||||
continue;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
@@ -159,13 +159,13 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
FFDisk* disk = ffListAdd(disks);
|
||||
|
||||
disk->bytesTotal = (uint64_t)fs->f_blocks * fs->f_bsize;
|
||||
disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize;
|
||||
disk->bytesAvailable = (uint64_t)fs->f_bavail * fs->f_bsize;
|
||||
disk->bytesTotal = (uint64_t)fs->f_blocks * (uint64_t)fs->f_bsize;
|
||||
disk->bytesFree = (uint64_t)fs->f_bfree * (uint64_t)fs->f_bsize;
|
||||
disk->bytesAvailable = (uint64_t)fs->f_bavail * (uint64_t)fs->f_bsize;
|
||||
disk->bytesUsed = 0; // To be filled in ./disk.c
|
||||
|
||||
disk->filesTotal = (uint32_t) fs->f_files;
|
||||
disk->filesUsed = (uint32_t) (fs->f_files - fs->f_ffree);
|
||||
disk->filesUsed = (uint32_t) fs->f_files - (uint32_t) fs->f_ffree;
|
||||
|
||||
ffStrbufInitS(&disk->mountFrom, fs->f_mntfromname);
|
||||
ffStrbufInitS(&disk->mountpoint, fs->f_mntonname);
|
||||
|
||||
@@ -37,6 +37,10 @@ static bool isPhysicalDevice(const struct mntent* device)
|
||||
if(ffStrEquals(device->mnt_type, "zfs"))
|
||||
return true;
|
||||
|
||||
//sshfs
|
||||
if(ffStrEquals(device->mnt_type, "fuse.sshfs"))
|
||||
return true;
|
||||
|
||||
//Pseudo filesystems don't have a device in /dev
|
||||
if(!ffStrStartsWith(device->mnt_fsname, "/dev/"))
|
||||
return false;
|
||||
|
||||
@@ -99,9 +99,6 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
|
||||
wchar_t diskName[MAX_PATH + 1], diskFileSystem[MAX_PATH + 1];
|
||||
|
||||
//https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa#remarks
|
||||
UINT errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
|
||||
DWORD diskFlags;
|
||||
BOOL result = GetVolumeInformationW(mountpoint,
|
||||
diskName, ARRAY_SIZE(diskName), //Volume name
|
||||
@@ -110,7 +107,6 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
&diskFlags, //File system flags
|
||||
diskFileSystem, ARRAY_SIZE(diskFileSystem)
|
||||
);
|
||||
SetErrorMode(errorMode);
|
||||
|
||||
if(result)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "util/apple/cf_helpers.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/edidHelper.h"
|
||||
#include "detection/os/os.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -194,7 +195,22 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
|
||||
ffStrbufSetStatic(&ds->wmPrettyName, "Quartz Compositor");
|
||||
}
|
||||
}
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Aqua");
|
||||
|
||||
const FFOSResult* os = ffDetectOS();
|
||||
|
||||
char* str_end;
|
||||
const char* version = os->version.chars;
|
||||
unsigned long osNum = strtoul(version, &str_end, 10);
|
||||
if (str_end != version)
|
||||
{
|
||||
if (osNum > 15) { // Tahoe
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Liquid Glass");
|
||||
} else if (osNum < 10) {
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Platinum");
|
||||
} else {
|
||||
ffStrbufSetStatic(&ds->dePrettyName, "Aqua");
|
||||
}
|
||||
}
|
||||
|
||||
detectDisplays(ds);
|
||||
}
|
||||
|
||||
+12
-2
@@ -15,6 +15,11 @@ const char* FF_GPU_VENDOR_NAME_PARALLEL = "Parallel";
|
||||
const char* FF_GPU_VENDOR_NAME_MICROSOFT = "Microsoft";
|
||||
const char* FF_GPU_VENDOR_NAME_REDHAT = "RedHat";
|
||||
const char* FF_GPU_VENDOR_NAME_ORACLE = "Oracle";
|
||||
const char* FF_GPU_VENDOR_NAME_BROADCOM = "Broadcom";
|
||||
const char* FF_GPU_VENDOR_NAME_LOONGSON = "Loongson";
|
||||
const char* FF_GPU_VENDOR_NAME_JINGJIA_MICRO = "Jingjia Micro";
|
||||
const char* FF_GPU_VENDOR_NAME_HUAWEI = "Huawei";
|
||||
const char* FF_GPU_VENDOR_NAME_ZHAOXIN = "Zhaoxin";
|
||||
|
||||
const char* ffGPUGetVendorString(unsigned vendorId)
|
||||
{
|
||||
@@ -22,17 +27,22 @@ const char* ffGPUGetVendorString(unsigned vendorId)
|
||||
switch (vendorId)
|
||||
{
|
||||
case 0x106b: return FF_GPU_VENDOR_NAME_APPLE;
|
||||
case 0x1002: case 0x1022: return FF_GPU_VENDOR_NAME_AMD;
|
||||
case 0x1002: case 0x1022: case 0x1dd8: return FF_GPU_VENDOR_NAME_AMD;
|
||||
case 0x8086: case 0x8087: case 0x03e7: return FF_GPU_VENDOR_NAME_INTEL;
|
||||
case 0x0955: case 0x10de: case 0x12d2: return FF_GPU_VENDOR_NAME_NVIDIA;
|
||||
case 0x1ed5: return FF_GPU_VENDOR_NAME_MTHREADS;
|
||||
case 0x5143: return FF_GPU_VENDOR_NAME_QUALCOMM;
|
||||
case 0x17cb: case 0x5143: return FF_GPU_VENDOR_NAME_QUALCOMM;
|
||||
case 0x14c3: return FF_GPU_VENDOR_NAME_MTK;
|
||||
case 0x15ad: return FF_GPU_VENDOR_NAME_VMWARE;
|
||||
case 0x1af4: return FF_GPU_VENDOR_NAME_REDHAT;
|
||||
case 0x1ab8: return FF_GPU_VENDOR_NAME_PARALLEL;
|
||||
case 0x1414: return FF_GPU_VENDOR_NAME_MICROSOFT;
|
||||
case 0x108e: return FF_GPU_VENDOR_NAME_ORACLE;
|
||||
case 0x182f: case 0x14e4: return FF_GPU_VENDOR_NAME_BROADCOM;
|
||||
case 0x0014: return FF_GPU_VENDOR_NAME_LOONGSON;
|
||||
case 0x0731: return FF_GPU_VENDOR_NAME_JINGJIA_MICRO;
|
||||
case 0x19e5: return FF_GPU_VENDOR_NAME_HUAWEI;
|
||||
case 0x1d17: return FF_GPU_VENDOR_NAME_ZHAOXIN;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+19
-1
@@ -49,7 +49,25 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
|
||||
|
||||
const char* ffGPUGetVendorString(unsigned vendorId);
|
||||
|
||||
typedef struct FFGpuDriverPciBusId
|
||||
{
|
||||
uint32_t domain;
|
||||
uint32_t bus;
|
||||
uint32_t device;
|
||||
uint32_t func;
|
||||
} FFGpuDriverPciBusId;
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__HAIKU__)
|
||||
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
|
||||
void ffGPUQueryAmdGpuName(uint16_t deviceId, uint8_t revisionId, FFGPUResult* gpu);
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
|
||||
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath);
|
||||
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd);
|
||||
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd);
|
||||
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd);
|
||||
#endif // FF_HAVE_DRM
|
||||
|
||||
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId);
|
||||
#endif // defined(XXX)
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#import <Metal/MTLDevice.h>
|
||||
#import <IOKit/kext/KextManager.h>
|
||||
|
||||
#ifndef MAC_OS_VERSION_26_0
|
||||
#define MTLGPUFamilyMetal4 ((MTLGPUFamily) 5002)
|
||||
#endif
|
||||
#ifndef MAC_OS_VERSION_13_0
|
||||
#define MTLGPUFamilyMetal3 ((MTLGPUFamily) 5001)
|
||||
#endif
|
||||
@@ -57,7 +60,9 @@ const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1");
|
||||
#else // MAC_OS_X_VERSION_10_15
|
||||
if ([device supportsFamily:MTLGPUFamilyMetal3])
|
||||
if ([device supportsFamily:MTLGPUFamilyMetal4])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal 4");
|
||||
else if ([device supportsFamily:MTLGPUFamilyMetal3])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal 3");
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon3])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3");
|
||||
|
||||
+156
-44
@@ -1,6 +1,7 @@
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <fcntl.h>
|
||||
@@ -10,11 +11,145 @@
|
||||
#include <bus/pci/pcireg.h> // DragonFly
|
||||
#endif
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
static void fillGPUTypeGeneric(FFGPUResult* gpu)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY, 0);
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
||||
{
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
{
|
||||
// 0000:00:02.0 is reserved for Intel integrated graphics
|
||||
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
#include "common/library.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <xf86drm.h>
|
||||
|
||||
static const char* detectByDrm(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm" FF_LIBRARY_EXTENSION " failed", "libdrm" FF_LIBRARY_EXTENSION, 2)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices)
|
||||
|
||||
drmDevicePtr devices[64];
|
||||
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
|
||||
if (nDevices < 0)
|
||||
return "drmGetDevices() failed";
|
||||
|
||||
for (int iDev = 0; iDev < nDevices; ++iDev)
|
||||
{
|
||||
drmDevice* dev = devices[iDev];
|
||||
|
||||
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY)))
|
||||
continue;
|
||||
|
||||
const char* path = dev->nodes[DRM_NODE_PRIMARY];
|
||||
|
||||
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInit(&gpu->name);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInitS(&gpu->platformApi, path);
|
||||
ffStrbufInit(&gpu->memoryType);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET;
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
||||
gpu->deviceId = 0;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
switch (dev->bustype)
|
||||
{
|
||||
case DRM_BUS_PCI:
|
||||
ffStrbufInitStatic(&gpu->vendor, ffGPUGetVendorString(dev->deviceinfo.pci->vendor_id));
|
||||
gpu->deviceId = (dev->businfo.pci->domain * 100000ull) + (dev->businfo.pci->bus * 1000ull) + (dev->businfo.pci->dev * 10ull) + dev->businfo.pci->func;
|
||||
break;
|
||||
case DRM_BUS_HOST1X:
|
||||
ffStrbufSetS(&gpu->name, dev->deviceinfo.host1x->compatible[0]);
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
break;
|
||||
case DRM_BUS_PLATFORM:
|
||||
ffStrbufSetS(&gpu->name, dev->deviceinfo.platform->compatible[0]);
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
break;
|
||||
case DRM_BUS_USB:
|
||||
ffStrbufSetF(&gpu->name, "USB Device (%u-%u)", dev->deviceinfo.usb->vendor, dev->deviceinfo.usb->product);
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
break;
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) continue;
|
||||
|
||||
char driverName[64];
|
||||
driverName[0] = '\0';
|
||||
struct drm_version ver = {
|
||||
.name = driverName,
|
||||
.name_len = ARRAY_SIZE(driverName),
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_VERSION, &ver) == 0)
|
||||
ffStrbufSetF(&gpu->driver, "%*s %d.%d.%d", (int) ver.name_len, ver.name, ver.version_major, ver.version_minor, ver.version_patchlevel);
|
||||
|
||||
if (ffStrStartsWith(driverName, "i915"))
|
||||
ffDrmDetectI915(gpu, fd);
|
||||
else if (ffStrStartsWith(driverName, "amdgpu"))
|
||||
ffDrmDetectAmdgpu(options, gpu, dev->nodes[DRM_NODE_RENDER]);
|
||||
else if (ffStrStartsWith(driverName, "radeon"))
|
||||
ffDrmDetectRadeon(options, gpu, dev->nodes[DRM_NODE_RENDER]);
|
||||
else if (ffStrStartsWith(driverName, "xe"))
|
||||
ffDrmDetectXe(gpu, fd);
|
||||
else if (ffStrStartsWith(driverName, "asahi"))
|
||||
ffDrmDetectAsahi(gpu, fd);
|
||||
else if (dev->bustype == DRM_BUS_PCI)
|
||||
{
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
.domain = (uint32_t) dev->businfo.pci->domain,
|
||||
.bus = dev->businfo.pci->bus,
|
||||
.device = dev->businfo.pci->dev,
|
||||
.func = dev->businfo.pci->func,
|
||||
});
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
ffGPUQueryAmdGpuName(dev->deviceinfo.pci->device_id, dev->deviceinfo.pci->revision_id, gpu);
|
||||
if (gpu->name.length == 0)
|
||||
ffGPUFillVendorAndName(0, dev->deviceinfo.pci->vendor_id, dev->deviceinfo.pci->device_id, gpu);
|
||||
}
|
||||
|
||||
fillGPUTypeGeneric(gpu);
|
||||
}
|
||||
|
||||
ffdrmFreeDevices(devices, nDevices);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* detectByPci(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/pci", O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return "open(\"/dev/pci\", O_RDONLY, 0) failed";
|
||||
return "open(\"/dev/pci\", O_RDONLY | O_CLOEXEC, 0) failed";
|
||||
|
||||
struct pci_conf confs[128];
|
||||
struct pci_match_conf match = {
|
||||
@@ -54,27 +189,12 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
gpu->deviceId = (pc->pc_sel.pc_domain * 100000ull) + (pc->pc_sel.pc_bus * 1000ull) + (pc->pc_sel.pc_dev * 10ull) + pc->pc_sel.pc_func;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
||||
{
|
||||
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = (uint32_t) pc->pc_sel.pc_domain,
|
||||
.bus = pc->pc_sel.pc_bus,
|
||||
.device = pc->pc_sel.pc_dev,
|
||||
.func = pc->pc_sel.pc_func,
|
||||
},
|
||||
}, (FFGpuDriverResult) {
|
||||
.index = &gpu->index,
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.type = &gpu->type,
|
||||
.frequency = &gpu->frequency,
|
||||
.coreUsage = &gpu->coreUsage,
|
||||
.name = &gpu->name,
|
||||
}, "libnvidia-ml.so");
|
||||
}
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
.domain = (uint32_t) pc->pc_sel.pc_domain,
|
||||
.bus = pc->pc_sel.pc_bus,
|
||||
.device = pc->pc_sel.pc_dev,
|
||||
.func = pc->pc_sel.pc_func,
|
||||
});
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
{
|
||||
@@ -84,27 +204,19 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
|
||||
}
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_UNKNOWN)
|
||||
{
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "GeForce") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Quadro") ||
|
||||
ffStrbufStartsWithIgnCaseS(&gpu->name, "Tesla"))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_MTHREADS)
|
||||
{
|
||||
if (ffStrbufStartsWithIgnCaseS(&gpu->name, "MTT "))
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
{
|
||||
// 0000:00:02.0 is reserved for Intel integrated graphics
|
||||
gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
}
|
||||
}
|
||||
fillGPUTypeGeneric(gpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
|
||||
{
|
||||
detectByDrm(options, gpus);
|
||||
if (gpus->length > 0) return NULL;
|
||||
}
|
||||
|
||||
return detectByPci(options, gpus);
|
||||
}
|
||||
|
||||
@@ -10,14 +10,6 @@ typedef enum __attribute__((__packed__)) FFGpuDriverConditionType
|
||||
FF_GPU_DRIVER_CONDITION_TYPE_FORCE_UNSIGNED = UINT8_MAX,
|
||||
} FFGpuDriverConditionType;
|
||||
|
||||
typedef struct FFGpuDriverPciBusId
|
||||
{
|
||||
uint32_t domain;
|
||||
uint32_t bus;
|
||||
uint32_t device;
|
||||
uint32_t func;
|
||||
} FFGpuDriverPciBusId;
|
||||
|
||||
typedef struct FFGpuDriverPciDeviceId
|
||||
{
|
||||
uint32_t deviceId;
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
#include "gpu.h"
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
#include <drm.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "common/library.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include "intel_drm.h"
|
||||
#include "asahi_drm.h"
|
||||
#include <radeon_drm.h>
|
||||
|
||||
const char* ffDrmDetectRadeon(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) return "Failed to open DRM render device";
|
||||
|
||||
uint32_t value;
|
||||
|
||||
// https://github.com/torvalds/linux/blob/fb4d33ab452ea254e2c319bac5703d1b56d895bf/drivers/gpu/drm/radeon/radeon_kms.c#L231
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
|
||||
.request = RADEON_INFO_ACTIVE_CU_COUNT,
|
||||
.value = (uintptr_t) &value,
|
||||
}) >= 0)
|
||||
gpu->coreCount = (int32_t) value;
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
|
||||
.request = RADEON_INFO_CURRENT_GPU_TEMP, // millidegrees C
|
||||
.value = (uintptr_t) &value,
|
||||
}) >= 0 && value != 0) // 0 means unavailable
|
||||
gpu->temperature = (double) value / 1000.0;
|
||||
}
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
|
||||
.request = RADEON_INFO_MAX_SCLK, // MHz
|
||||
.value = (uintptr_t) &value,
|
||||
}) >= 0)
|
||||
gpu->frequency = (uint32_t) (value / 1000u);
|
||||
|
||||
if (options->driverSpecific)
|
||||
{
|
||||
struct drm_radeon_gem_info gemInfo;
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_GEM_INFO, &gemInfo) >= 0)
|
||||
{
|
||||
// vram_usage can be bigger than vram_usage, so we use vram_size here
|
||||
gpu->dedicated.total = gemInfo.vram_size;
|
||||
gpu->shared.total = gemInfo.gart_size;
|
||||
|
||||
uint64_t memSize;
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
|
||||
.request = RADEON_INFO_VRAM_USAGE, // uint64_t
|
||||
.value = (uintptr_t) &memSize,
|
||||
}) >= 0)
|
||||
gpu->dedicated.used = memSize;
|
||||
|
||||
if (ioctl(fd, DRM_IOCTL_RADEON_INFO, &(struct drm_radeon_info) {
|
||||
.request = RADEON_INFO_GTT_USAGE, // uint64_t
|
||||
.value = (uintptr_t) &memSize,
|
||||
}) >= 0)
|
||||
gpu->shared.used = memSize;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef FF_HAVE_DRM_AMDGPU
|
||||
#include <amdgpu.h>
|
||||
#include <amdgpu_drm.h>
|
||||
|
||||
const char* ffDrmDetectAmdgpu(const FFGPUOptions* options, FFGPUResult* gpu, const char* renderPath)
|
||||
{
|
||||
#if FF_HAVE_DRM_AMDGPU
|
||||
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open(renderPath, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) return "Failed to open DRM render device";
|
||||
|
||||
amdgpu_device_handle handle;
|
||||
uint32_t majorVersion, minorVersion;
|
||||
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0)
|
||||
return "Failed to initialize AMDGPU device";
|
||||
|
||||
uint32_t value;
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0)
|
||||
gpu->temperature = value / 1000.;
|
||||
}
|
||||
|
||||
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
|
||||
|
||||
struct amdgpu_gpu_info gpuInfo;
|
||||
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0)
|
||||
{
|
||||
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
|
||||
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
#define FF_VRAM_CASE(name, value) case value /* AMDGPU_VRAM_TYPE_ ## name */: ffStrbufSetStatic(&gpu->memoryType, #name); break
|
||||
switch (gpuInfo.vram_type)
|
||||
{
|
||||
FF_VRAM_CASE(UNKNOWN, 0);
|
||||
FF_VRAM_CASE(GDDR1, 1);
|
||||
FF_VRAM_CASE(DDR2, 2);
|
||||
FF_VRAM_CASE(GDDR3, 3);
|
||||
FF_VRAM_CASE(GDDR4, 4);
|
||||
FF_VRAM_CASE(GDDR5, 5);
|
||||
FF_VRAM_CASE(HBM, 6);
|
||||
FF_VRAM_CASE(DDR3, 7);
|
||||
FF_VRAM_CASE(DDR4, 8);
|
||||
FF_VRAM_CASE(GDDR6, 9);
|
||||
FF_VRAM_CASE(DDR5, 10);
|
||||
FF_VRAM_CASE(LPDDR4, 11);
|
||||
FF_VRAM_CASE(LPDDR5, 12);
|
||||
default:
|
||||
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
|
||||
break;
|
||||
}
|
||||
|
||||
struct amdgpu_heap_info heapInfo;
|
||||
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
|
||||
{
|
||||
gpu->dedicated.total = heapInfo.heap_size;
|
||||
gpu->dedicated.used = heapInfo.heap_usage;
|
||||
}
|
||||
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_GTT, 0, &heapInfo) >= 0)
|
||||
{
|
||||
gpu->shared.total = heapInfo.heap_size;
|
||||
gpu->shared.used = heapInfo.heap_usage;
|
||||
}
|
||||
}
|
||||
|
||||
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0)
|
||||
gpu->coreUsage = value;
|
||||
|
||||
ffamdgpu_device_deinitialize(handle);
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(gpu, renderPath);
|
||||
return "Fastfetch is compiled without libdrm support";
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* ffDrmDetectI915(FFGPUResult* gpu, int fd)
|
||||
{
|
||||
{
|
||||
int value;
|
||||
drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value };
|
||||
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0)
|
||||
gpu->coreCount = value;
|
||||
}
|
||||
{
|
||||
struct drm_i915_query_item queryItem = {
|
||||
.query_id = DRM_I915_QUERY_MEMORY_REGIONS,
|
||||
};
|
||||
struct drm_i915_query query = {
|
||||
.items_ptr = (uintptr_t) &queryItem,
|
||||
.num_items = 1,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 )
|
||||
{
|
||||
FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length);
|
||||
queryItem.data_ptr = (uintptr_t) buffer;
|
||||
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
|
||||
struct drm_i915_query_memory_regions* regionInfo = (void*) buffer;
|
||||
for (uint32_t i = 0; i < regionInfo->num_regions; i++)
|
||||
{
|
||||
struct drm_i915_memory_region_info* region = regionInfo->regions + i;
|
||||
switch (region->region.memory_class)
|
||||
{
|
||||
case I915_MEMORY_CLASS_SYSTEM:
|
||||
gpu->shared.total += region->probed_size;
|
||||
gpu->shared.used += region->probed_size - region->unallocated_size;
|
||||
break;
|
||||
case I915_MEMORY_CLASS_DEVICE:
|
||||
gpu->dedicated.total += region->probed_size;
|
||||
gpu->dedicated.used += region->probed_size - region->unallocated_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
|
||||
{
|
||||
int count = 0;
|
||||
while (length >= 8)
|
||||
{
|
||||
count += __builtin_popcountll(*(uint64_t*) bytes);
|
||||
bytes += 8;
|
||||
length -= 8;
|
||||
}
|
||||
if (length >= 4)
|
||||
{
|
||||
count += __builtin_popcountl(*(uint32_t*) bytes);
|
||||
bytes += 4;
|
||||
length -= 4;
|
||||
}
|
||||
if (length >= 2)
|
||||
{
|
||||
count += __builtin_popcountl(*(uint16_t*) bytes);
|
||||
bytes += 2;
|
||||
length -= 2;
|
||||
}
|
||||
if (length)
|
||||
{
|
||||
count += __builtin_popcountl(*(uint8_t*) bytes);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
const char* ffDrmDetectXe(FFGPUResult* gpu, int fd)
|
||||
{
|
||||
bool flag = false;
|
||||
{
|
||||
struct drm_xe_device_query query = {
|
||||
.query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
|
||||
query.data = (uintptr_t) buffer;
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
int dssCount = 0, euPerDssCount = 0;
|
||||
for (struct drm_xe_query_topology_mask* topo = (void*) buffer;
|
||||
(uint8_t*) topo < buffer + query.size;
|
||||
topo = (void*) (topo->mask + topo->num_bytes)
|
||||
) {
|
||||
switch (topo->type)
|
||||
{
|
||||
case DRM_XE_TOPO_DSS_COMPUTE:
|
||||
case DRM_XE_TOPO_DSS_GEOMETRY:
|
||||
dssCount += popcountBytes(topo->mask, topo->num_bytes);
|
||||
break;
|
||||
case DRM_XE_TOPO_EU_PER_DSS:
|
||||
euPerDssCount += popcountBytes(topo->mask, topo->num_bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
gpu->coreCount = dssCount * euPerDssCount;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct drm_xe_device_query query = {
|
||||
.query = DRM_XE_DEVICE_QUERY_MEM_REGIONS,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
|
||||
query.data = (uintptr_t) buffer;
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
|
||||
struct drm_xe_query_mem_regions* regionInfo = (void*) buffer;
|
||||
for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++)
|
||||
{
|
||||
struct drm_xe_mem_region* region = regionInfo->mem_regions + i;
|
||||
switch (region->mem_class)
|
||||
{
|
||||
case DRM_XE_MEM_REGION_CLASS_SYSMEM:
|
||||
gpu->shared.total += region->total_size;
|
||||
gpu->shared.used += region->used;
|
||||
break;
|
||||
case DRM_XE_MEM_REGION_CLASS_VRAM:
|
||||
gpu->dedicated.total += region->total_size;
|
||||
gpu->dedicated.used += region->used;
|
||||
break;
|
||||
}
|
||||
}
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flag ? NULL : "Failed to query Xe GPU information";
|
||||
}
|
||||
|
||||
const char* ffDrmDetectAsahi(FFGPUResult* gpu, int fd)
|
||||
{
|
||||
struct drm_asahi_params_global paramsGlobal = {};
|
||||
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) {
|
||||
.param_group = DRM_ASAHI_GET_PARAMS,
|
||||
.pointer = (uint64_t) ¶msGlobal,
|
||||
.size = sizeof(paramsGlobal),
|
||||
}) >= 0)
|
||||
{
|
||||
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
|
||||
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
|
||||
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
|
||||
gpu->deviceId = paramsGlobal.chip_id;
|
||||
|
||||
if (!gpu->name.length)
|
||||
{
|
||||
const char* variant = " Unknown";
|
||||
switch (paramsGlobal.gpu_variant) {
|
||||
case 'G':
|
||||
variant = "";
|
||||
break;
|
||||
case 'S':
|
||||
variant = " Pro";
|
||||
break;
|
||||
case 'C':
|
||||
variant = " Max";
|
||||
break;
|
||||
case 'D':
|
||||
variant = " Ultra";
|
||||
break;
|
||||
}
|
||||
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
|
||||
paramsGlobal.gpu_generation - 12, variant,
|
||||
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
|
||||
paramsGlobal.gpu_revision + 0xA0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "Failed to query Asahi GPU information";
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_DRM
|
||||
|
||||
#include "gpu_driver_specific.h"
|
||||
|
||||
const char* ffGPUDetectDriverSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFGpuDriverPciBusId pciBusId)
|
||||
{
|
||||
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
|
||||
const char* soName;
|
||||
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific))
|
||||
{
|
||||
return detectFn(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = pciBusId,
|
||||
}, (FFGpuDriverResult) {
|
||||
.index = &gpu->index,
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
|
||||
.type = &gpu->type,
|
||||
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
|
||||
.name = &gpu->name,
|
||||
}, soName);
|
||||
}
|
||||
|
||||
return "No driver-specific detection function found for the GPU vendor";
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int pokefd = open(POKE_DEVICE_FULLNAME, O_RDWR);
|
||||
FF_AUTO_CLOSE_FD int pokefd = open(POKE_DEVICE_FULLNAME, O_RDWR | O_CLOEXEC);
|
||||
if (pokefd < 0) return "open(POKE_DEVICE_FULLNAME) failed";
|
||||
|
||||
pci_info dev;
|
||||
|
||||
+55
-309
@@ -105,93 +105,23 @@ FF_MAYBE_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey,
|
||||
|
||||
static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
|
||||
{
|
||||
#if FF_HAVE_DRM_AMDGPU
|
||||
|
||||
FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize)
|
||||
|
||||
#if FF_HAVE_DRM
|
||||
const char* error = drmFindRenderFromCard(drmKey, buffer);
|
||||
if (error) return error;
|
||||
if (ffStrbufEqualS(&gpu->driver, "radeon"))
|
||||
return ffDrmDetectRadeon(options, gpu, buffer->chars);
|
||||
else
|
||||
{
|
||||
const char* error = drmFindRenderFromCard(drmKey, buffer);
|
||||
if (error) return error;
|
||||
#if FF_HAVE_DRM_AMDGPU
|
||||
return ffDrmDetectAmdgpu(options, gpu, buffer->chars);
|
||||
#else
|
||||
FF_UNUSED(options, gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with libdrm_amdgpu support";
|
||||
#endif
|
||||
}
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
||||
if (fd < 0) return "Failed to open DRM device";
|
||||
|
||||
amdgpu_device_handle handle;
|
||||
uint32_t majorVersion, minorVersion;
|
||||
if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0)
|
||||
return "Failed to initialize AMDGPU device";
|
||||
|
||||
ffStrbufAppendF(&gpu->driver, " %u.%u", (unsigned) majorVersion, (unsigned) minorVersion);
|
||||
|
||||
uint32_t value;
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0)
|
||||
gpu->temperature = value / 1000.;
|
||||
}
|
||||
|
||||
ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle));
|
||||
|
||||
struct amdgpu_gpu_info gpuInfo;
|
||||
if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0)
|
||||
{
|
||||
gpu->coreCount = (int32_t) gpuInfo.cu_active_number;
|
||||
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
|
||||
gpu->index = FF_GPU_INDEX_UNSET;
|
||||
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
#define FF_VRAM_CASE(name, value) case value /* AMDGPU_VRAM_TYPE_ ## name */: ffStrbufSetStatic(&gpu->memoryType, #name); break
|
||||
switch (gpuInfo.vram_type)
|
||||
{
|
||||
FF_VRAM_CASE(UNKNOWN, 0);
|
||||
FF_VRAM_CASE(GDDR1, 1);
|
||||
FF_VRAM_CASE(DDR2, 2);
|
||||
FF_VRAM_CASE(GDDR3, 3);
|
||||
FF_VRAM_CASE(GDDR4, 4);
|
||||
FF_VRAM_CASE(GDDR5, 5);
|
||||
FF_VRAM_CASE(HBM, 6);
|
||||
FF_VRAM_CASE(DDR3, 7);
|
||||
FF_VRAM_CASE(DDR4, 8);
|
||||
FF_VRAM_CASE(GDDR6, 9);
|
||||
FF_VRAM_CASE(DDR5, 10);
|
||||
FF_VRAM_CASE(LPDDR4, 11);
|
||||
FF_VRAM_CASE(LPDDR5, 12);
|
||||
default:
|
||||
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
|
||||
break;
|
||||
}
|
||||
|
||||
struct amdgpu_heap_info heapInfo;
|
||||
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
|
||||
{
|
||||
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
||||
{
|
||||
gpu->dedicated.total = heapInfo.heap_size;
|
||||
gpu->dedicated.used = heapInfo.heap_usage;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu->shared.total = heapInfo.heap_size;
|
||||
gpu->shared.used = heapInfo.heap_usage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0)
|
||||
gpu->coreUsage = value;
|
||||
|
||||
ffamdgpu_device_deinitialize(handle);
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
FF_UNUSED(options, gpu, drmKey, buffer);
|
||||
return "Fastfetch is compiled without libdrm support";
|
||||
FF_UNUSED(gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with drm support";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -215,47 +145,50 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
|
||||
ffStrbufAppendC(pciDir, '/');
|
||||
|
||||
const uint32_t hwmonLen = pciDir->length;
|
||||
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
|
||||
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY))
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
else
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
|
||||
uint64_t value = 0;
|
||||
if (options->temp)
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, hwmonLen);
|
||||
ffStrbufAppendS(pciDir, "temp1_input"); // The on die GPU temperature in millidegrees Celsius
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
gpu->temperature = (double) value / 1000;
|
||||
}
|
||||
|
||||
if (options->driverSpecific)
|
||||
if (ffStrbufEqualS(&gpu->driver, "amdgpu")) // Ancient radeon drivers don't have these files
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
{
|
||||
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
||||
gpu->dedicated.total = value;
|
||||
else
|
||||
gpu->shared.total = value;
|
||||
ffStrbufSubstrBefore(pciDir, hwmonLen);
|
||||
ffStrbufAppendS(pciDir, "in1_input"); // Northbridge voltage in millivolts (APUs only)
|
||||
if (ffPathExists(pciDir->chars, FF_PATHTYPE_ANY))
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
else
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
|
||||
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
|
||||
if (options->driverSpecific)
|
||||
{
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
{
|
||||
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
||||
gpu->dedicated.used = value;
|
||||
gpu->dedicated.total = value;
|
||||
else
|
||||
gpu->shared.used = value;
|
||||
}
|
||||
}
|
||||
gpu->shared.total = value;
|
||||
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
ffStrbufAppendS(pciDir, "/gpu_busy_percent");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
gpu->coreUsage = (double) value;
|
||||
ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total"));
|
||||
ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
{
|
||||
if (gpu->type == FF_GPU_TYPE_DISCRETE)
|
||||
gpu->dedicated.used = value;
|
||||
else
|
||||
gpu->shared.used = value;
|
||||
}
|
||||
}
|
||||
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
ffStrbufAppendS(pciDir, "/gpu_busy_percent");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
|
||||
gpu->coreUsage = (double) value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,153 +244,19 @@ static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu
|
||||
}
|
||||
}
|
||||
|
||||
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
|
||||
{
|
||||
int count = 0;
|
||||
while (length >= 8)
|
||||
{
|
||||
count += __builtin_popcountll(*(uint64_t*) bytes);
|
||||
bytes += 8;
|
||||
length -= 8;
|
||||
}
|
||||
if (length >= 4)
|
||||
{
|
||||
count += __builtin_popcountl(*(uint32_t*) bytes);
|
||||
bytes += 4;
|
||||
length -= 4;
|
||||
}
|
||||
if (length >= 2)
|
||||
{
|
||||
count += __builtin_popcountl(*(uint16_t*) bytes);
|
||||
bytes += 2;
|
||||
length -= 2;
|
||||
}
|
||||
if (length)
|
||||
{
|
||||
count += __builtin_popcountl(*(uint8_t*) bytes);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer)
|
||||
{
|
||||
#if FF_HAVE_DRM
|
||||
ffStrbufSetS(buffer, "/dev/dri/");
|
||||
ffStrbufAppendS(buffer, drmKey);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) return "Failed to open drm device";
|
||||
|
||||
if (ffStrbufEqualS(&gpu->driver, "xe"))
|
||||
{
|
||||
{
|
||||
struct drm_xe_device_query query = {
|
||||
.extensions = 0,
|
||||
.query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY,
|
||||
.size = 0,
|
||||
.data = 0,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
|
||||
query.data = (uintptr_t) buffer;
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
int dssCount = 0, euPerDssCount = 0;
|
||||
for (struct drm_xe_query_topology_mask* topo = (void*) buffer;
|
||||
(uint8_t*) topo < buffer + query.size;
|
||||
topo = (void*) (topo->mask + topo->num_bytes)
|
||||
) {
|
||||
switch (topo->type)
|
||||
{
|
||||
case DRM_XE_TOPO_DSS_COMPUTE:
|
||||
case DRM_XE_TOPO_DSS_GEOMETRY:
|
||||
dssCount += popcountBytes(topo->mask, topo->num_bytes);
|
||||
break;
|
||||
case DRM_XE_TOPO_EU_PER_DSS:
|
||||
euPerDssCount += popcountBytes(topo->mask, topo->num_bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
gpu->coreCount = dssCount * euPerDssCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
struct drm_xe_device_query query = {
|
||||
.query = DRM_XE_DEVICE_QUERY_MEM_REGIONS,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
FF_AUTO_FREE uint8_t* buffer = malloc(query.size);
|
||||
query.data = (uintptr_t) buffer;
|
||||
if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
|
||||
struct drm_xe_query_mem_regions* regionInfo = (void*) buffer;
|
||||
for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++)
|
||||
{
|
||||
struct drm_xe_mem_region* region = regionInfo->mem_regions + i;
|
||||
switch (region->mem_class)
|
||||
{
|
||||
case DRM_XE_MEM_REGION_CLASS_SYSMEM:
|
||||
gpu->shared.total += region->total_size;
|
||||
gpu->shared.used += region->used;
|
||||
break;
|
||||
case DRM_XE_MEM_REGION_CLASS_VRAM:
|
||||
gpu->dedicated.total += region->total_size;
|
||||
gpu->dedicated.used += region->used;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ffDrmDetectXe(gpu, fd);
|
||||
else if (ffStrbufEqualS(&gpu->driver, "i915"))
|
||||
{
|
||||
{
|
||||
int value;
|
||||
drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value };
|
||||
if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0)
|
||||
gpu->coreCount = value;
|
||||
}
|
||||
{
|
||||
struct drm_i915_query_item queryItem = {
|
||||
.query_id = DRM_I915_QUERY_MEMORY_REGIONS,
|
||||
};
|
||||
struct drm_i915_query query = {
|
||||
.items_ptr = (uintptr_t) &queryItem,
|
||||
.num_items = 1,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 )
|
||||
{
|
||||
FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length);
|
||||
queryItem.data_ptr = (uintptr_t) buffer;
|
||||
if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0)
|
||||
{
|
||||
gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0;
|
||||
struct drm_i915_query_memory_regions* regionInfo = (void*) buffer;
|
||||
for (uint32_t i = 0; i < regionInfo->num_regions; i++)
|
||||
{
|
||||
struct drm_i915_memory_region_info* region = regionInfo->regions + i;
|
||||
switch (region->region.memory_class)
|
||||
{
|
||||
case I915_MEMORY_CLASS_SYSTEM:
|
||||
gpu->shared.total += region->probed_size;
|
||||
gpu->shared.used += region->probed_size - region->unallocated_size;
|
||||
break;
|
||||
case I915_MEMORY_CLASS_DEVICE:
|
||||
gpu->dedicated.total += region->probed_size;
|
||||
gpu->dedicated.used += region->probed_size - region->unallocated_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return ffDrmDetectI915(gpu, fd);
|
||||
return "Unknown Intel GPU driver";
|
||||
#else
|
||||
FF_UNUSED(gpu, drmKey, buffer);
|
||||
return "Fastfetch is not compiled with drm support";
|
||||
@@ -572,29 +371,12 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
}
|
||||
else
|
||||
{
|
||||
__typeof__(&ffDetectNvidiaGpuInfo) detectFn;
|
||||
const char* soName;
|
||||
if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &soName) && (options->temp || options->driverSpecific))
|
||||
{
|
||||
detectFn(&(FFGpuDriverCondition) {
|
||||
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
||||
.pciBusId = {
|
||||
.domain = pciDomain,
|
||||
.bus = pciBus,
|
||||
.device = pciDevice,
|
||||
.func = pciFunc,
|
||||
},
|
||||
}, (FFGpuDriverResult) {
|
||||
.index = &gpu->index,
|
||||
.temp = options->temp ? &gpu->temperature : NULL,
|
||||
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
||||
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
||||
.coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL,
|
||||
.type = &gpu->type,
|
||||
.frequency = options->driverSpecific ? &gpu->frequency : NULL,
|
||||
.name = &gpu->name,
|
||||
}, soName);
|
||||
}
|
||||
ffGPUDetectDriverSpecific(options, gpu, (FFGpuDriverPciBusId) {
|
||||
.domain = pciDomain,
|
||||
.bus = pciBus,
|
||||
.device = pciDevice,
|
||||
.func = pciFunc,
|
||||
});
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
@@ -630,45 +412,9 @@ FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, cons
|
||||
#if FF_HAVE_DRM_ASAHI
|
||||
ffStrbufSetS(buffer, "/dev/dri/");
|
||||
ffStrbufAppendS(buffer, drmKey);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY | O_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
{
|
||||
struct drm_asahi_params_global paramsGlobal = {};
|
||||
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) {
|
||||
.param_group = DRM_ASAHI_GET_PARAMS,
|
||||
.pointer = (uint64_t) ¶msGlobal,
|
||||
.size = sizeof(paramsGlobal),
|
||||
}) >= 0)
|
||||
{
|
||||
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
|
||||
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
|
||||
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
|
||||
gpu->deviceId = paramsGlobal.chip_id;
|
||||
|
||||
if (!gpu->name.length)
|
||||
{
|
||||
const char* variant = " Unknown";
|
||||
switch (paramsGlobal.gpu_variant) {
|
||||
case 'G':
|
||||
variant = "";
|
||||
break;
|
||||
case 'S':
|
||||
variant = " Pro";
|
||||
break;
|
||||
case 'C':
|
||||
variant = " Max";
|
||||
break;
|
||||
case 'D':
|
||||
variant = " Ultra";
|
||||
break;
|
||||
}
|
||||
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
|
||||
paramsGlobal.gpu_generation - 12, variant,
|
||||
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
|
||||
paramsGlobal.gpu_revision + 0xA0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ffDrmDetectAsahi(gpu, fd);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -12,6 +12,7 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
|| ffSettingsGetAndroidProperty("ro.vivo.market.name", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.oppo_model", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.oppo.market.name", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.vendor.oplus.market.enname", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.config.devicename", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.config.marketing_name", &host->name)
|
||||
|| ffSettingsGetAndroidProperty("ro.product.vendor.model", &host->name)
|
||||
|
||||
@@ -36,6 +36,10 @@ const char* getOthersByIokit(FFHostResult* host)
|
||||
if (manufacturer)
|
||||
ffCfStrGetString(manufacturer, &host->vendor);
|
||||
|
||||
FF_CFTYPE_AUTO_RELEASE CFStringRef version = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("version"), kCFAllocatorDefault, kNilOptions);
|
||||
if (version)
|
||||
ffCfStrGetString(version, &host->version);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,10 +77,11 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
//On WSL, the real host can't be detected. Instead use WSL as host.
|
||||
if(wslDistroName != NULL || getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
|
||||
{
|
||||
ffStrbufAppendS(&host->name, "Windows Subsystem for Linux");
|
||||
ffStrbufSetStatic(&host->name, "Windows Subsystem for Linux");
|
||||
if (wslDistroName)
|
||||
ffStrbufAppendF(&host->name, " - %s", wslDistroName);
|
||||
ffStrbufAppendS(&host->family, "WSL");
|
||||
ffStrbufSetStatic(&host->family, "WSL");
|
||||
ffStrbufSetStatic(&host->vendor, "Microsoft Corporation");
|
||||
|
||||
if (instance.config.general.detectVersion)
|
||||
{
|
||||
@@ -92,6 +93,17 @@ const char* ffDetectHost(FFHostResult* host)
|
||||
}); // supported in 2.2.3 and later
|
||||
}
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&instance.state.platform.sysinfo.version, "FreeBSD "))
|
||||
{
|
||||
ffStrbufSetStatic(&host->name, "Linux Binary Compatibility on FreeBSD");
|
||||
ffStrbufSetStatic(&host->family, "FreeBSD");
|
||||
ffStrbufSetStatic(&host->vendor, "FreeBSD Foundation");
|
||||
if (instance.config.general.detectVersion)
|
||||
{
|
||||
ffStrbufSetS(&host->version, instance.state.platform.sysinfo.version.chars + strlen("FreeBSD "));
|
||||
ffStrbufSubstrBeforeFirstC(&host->version, ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -121,7 +121,7 @@ const char* ffHostGetMacProductNameWithHwModel(const FFstrbuf* hwModel)
|
||||
ffStrEquals(version, "16,5")) return "MacBook Pro (16-inch, 2024, Three Thunderbolt 5 ports)";
|
||||
if(ffStrEquals(version, "15,14")) return "Mac Studio (M3 Ultra, 2025)";
|
||||
if(ffStrEquals(version, "15,13")) return "MacBook Air (15-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,2")) return "MacBook Air (13-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,12")) return "MacBook Air (13-inch, M3, 2024)";
|
||||
if(ffStrEquals(version, "15,3")) return "MacBook Pro (14-inch, Nov 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,4")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports)";
|
||||
if(ffStrEquals(version, "15,5")) return "iMac (24-inch, 2023, Two Thunderbolt / USB 4 ports, Two USB 3 ports)";
|
||||
|
||||
@@ -8,8 +8,9 @@ const char* ffDetectMemory(FFMemoryResult* ram)
|
||||
if (get_system_info(&info) != B_OK)
|
||||
return "Error getting system info";
|
||||
|
||||
ram->bytesTotal = B_PAGE_SIZE * info.max_pages;
|
||||
ram->bytesUsed = B_PAGE_SIZE * info.used_pages;
|
||||
uint32_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
ram->bytesTotal = pageSize * info.max_pages;
|
||||
ram->bytesUsed = pageSize * info.used_pages;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ static bool detectOSCodeName(FFOSResult* os)
|
||||
|
||||
switch (num)
|
||||
{
|
||||
case 26:
|
||||
case 16: ffStrbufSetStatic(&os->codename, "Tahoe"); return true;
|
||||
case 15: ffStrbufSetStatic(&os->codename, "Sequoia"); return true;
|
||||
case 14: ffStrbufSetStatic(&os->codename, "Sonoma"); return true;
|
||||
case 13: ffStrbufSetStatic(&os->codename, "Ventura"); return true;
|
||||
|
||||
@@ -231,6 +231,24 @@ FF_MAYBE_UNUSED static bool detectDebianDerived(FFOSResult* result)
|
||||
ffStrbufSetF(&result->prettyName, "Proxmox VE %s", result->versionID.chars);
|
||||
return true;
|
||||
}
|
||||
else if (ffStrbufContainS(&instance.state.platform.sysinfo.release, "+rpt-rpi-"))
|
||||
{
|
||||
// Raspberry Pi OS
|
||||
ffStrbufSetS(&result->id, "raspbian");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetS(&result->name, "Raspberry Pi OS");
|
||||
ffStrbufSetS(&result->prettyName, "Raspberry Pi OS");
|
||||
return true;
|
||||
}
|
||||
else if (ffStrbufEndsWithS(&instance.state.platform.sysinfo.release, "+truenas"))
|
||||
{
|
||||
// TrueNAS Scale
|
||||
ffStrbufSetS(&result->id, "truenas-scale");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
ffStrbufSetS(&result->name, "TrueNAS Scale");
|
||||
ffStrbufSetS(&result->prettyName, "TrueNAS Scale");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hack for MX Linux. See #847
|
||||
@@ -286,8 +304,19 @@ static void detectOS(FFOSResult* os)
|
||||
parseOsRelease(FASTFETCH_TARGET_DIR_ETC "/os-release", os);
|
||||
if (os->id.length == 0 || os->version.length == 0 || os->prettyName.length == 0 || os->codename.length == 0)
|
||||
parseLsbRelease(FASTFETCH_TARGET_DIR_ETC "/lsb-release", os);
|
||||
if (os->id.length == 0 || os->name.length > 0 || os->prettyName.length > 0)
|
||||
if (os->id.length == 0 || os->name.length == 0 || os->prettyName.length == 0)
|
||||
parseOsRelease(FASTFETCH_TARGET_DIR_USR "/lib/os-release", os);
|
||||
if (os->id.length == 0 && os->name.length == 0 && os->prettyName.length == 0)
|
||||
{
|
||||
// HarmonyOS has no os-release file
|
||||
if (ffStrbufEqualS(&instance.state.platform.sysinfo.name, "HarmonyOS"))
|
||||
{
|
||||
ffStrbufSetS(&os->id, "harmonyos");
|
||||
ffStrbufSetS(&os->idLike, "harmonyos");
|
||||
ffStrbufSetS(&os->name, "HarmonyOS");
|
||||
ffStrbufSetS(&os->prettyName, "HarmonyOS");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ffDetectOSImpl(FFOSResult* os)
|
||||
|
||||
@@ -100,22 +100,23 @@ uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir)
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
#if !defined(__sun) && !defined(__HAIKU__)
|
||||
if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK)
|
||||
ok = entry->d_type == (isdir ? DT_DIR : DT_REG);
|
||||
else
|
||||
#endif
|
||||
if (entry->d_name[0] != '.')
|
||||
{
|
||||
struct stat stbuf;
|
||||
if (fstatat(dirfd(dirp), entry->d_name, &stbuf, 0) == 0)
|
||||
ok = isdir ? S_ISDIR(stbuf.st_mode) : S_ISREG(stbuf.st_mode);
|
||||
#if !defined(__sun) && !defined(__HAIKU__)
|
||||
if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK)
|
||||
ok = entry->d_type == (isdir ? DT_DIR : DT_REG);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
struct stat stbuf;
|
||||
if (fstatat(dirfd(dirp), entry->d_name, &stbuf, 0) == 0)
|
||||
ok = isdir ? S_ISDIR(stbuf.st_mode) : S_ISREG(stbuf.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
if(ok) ++num_elements;
|
||||
}
|
||||
|
||||
if(isdir && num_elements >= 2)
|
||||
num_elements -= 2; // accounting for . and ..
|
||||
|
||||
return num_elements;
|
||||
}
|
||||
|
||||
@@ -554,7 +554,11 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", true);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_LPKGBUILD_BIT)) packageCounts->lpkgbuild += getNumElements(baseDir, "/opt/Loc-OS-LPKG/lpkgbuild/remove", false);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKGTOOL_BIT)) packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", false);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT)) packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Packages", "rpm");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT))
|
||||
{
|
||||
// `Sigmd5` is the only table that doesn't contain the virtual `gpg-pubkey` package
|
||||
packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Sigmd5", "rpm");
|
||||
}
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_SNAP_BIT)) packageCounts->snap += getSnap(baseDir);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_XBPS_BIT)) packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_BREW_BIT))
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "packages.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKGSRC_BIT))
|
||||
result->pkgsrc = ffPackagesGetNumElements(FASTFETCH_TARGET_DIR_ROOT "/usr/pkg/pkgdb", true);
|
||||
}
|
||||
@@ -4,11 +4,6 @@
|
||||
|
||||
void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
{
|
||||
#if __OpenBSD__
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT))
|
||||
result->pkg = ffPackagesGetNumElements(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg", true);
|
||||
#elif __NetBSD__
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKGSRC_BIT))
|
||||
result->pkgsrc = ffPackagesGetNumElements(FASTFETCH_TARGET_DIR_ROOT "/usr/pkg/pkgdb", true);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
static const char* detectDisk(FFstrbuf* path, const char* diskType, FFlist* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int rawfd = open(path->chars, O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int rawfd = open(path->chars, O_RDONLY | O_CLOEXEC);
|
||||
if (rawfd < 0) return "detectDisk: open(rawfd) failed";
|
||||
|
||||
device_geometry geometry;
|
||||
|
||||
@@ -32,7 +32,7 @@ const char* ffDetectSound(FFlist* devices)
|
||||
for (int idev = 0; idev <= info.nummixers; ++idev)
|
||||
{
|
||||
path[strlen("/dev/mixer")] = (char) ('0' + idev);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) break;
|
||||
|
||||
if (idev == 0)
|
||||
|
||||
@@ -25,7 +25,7 @@ const char* ffDetectSound(FFlist* devices)
|
||||
for (int idev = 0; idev < 9; ++idev)
|
||||
{
|
||||
path[strlen("/dev/audio")] = (char) ('0' + idev);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR);
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR | O_CLOEXEC);
|
||||
if (fd < 0) break;
|
||||
|
||||
audio_device_t ad;
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
typedef struct FFSwapResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
uint64_t bytesUsed;
|
||||
uint64_t bytesTotal;
|
||||
} FFSwapResult;
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap);
|
||||
const char* ffDetectSwap(FFlist* result /* List of FFSwapResult */);
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
#include <mach/mach.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
struct xsw_usage xsw;
|
||||
size_t size = sizeof(xsw);
|
||||
if(sysctl((int[]){ CTL_VM, VM_SWAPUSAGE }, 2, &xsw, &size, NULL, 0) != 0)
|
||||
return "Failed to read vm.swapusage";
|
||||
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitStatic(&swap->name, xsw.xsu_encrypted ? "Encrypted" : "Normal");
|
||||
swap->bytesTotal = xsw.xsu_total;
|
||||
swap->bytesUsed = xsw.xsu_used;
|
||||
return NULL;
|
||||
|
||||
@@ -2,15 +2,57 @@
|
||||
#include "common/sysctl.h"
|
||||
|
||||
#include <vm/vm_param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
static void addSwapEntry(FFlist* result, struct xswdev* xsw, uint32_t pageSize)
|
||||
{
|
||||
if (xsw->xsw_nblks == 0) // DFBSD reports some /dev/wdog devices with nblks == 0
|
||||
return;
|
||||
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
if (xsw->xsw_dev == NODEV)
|
||||
ffStrbufInitStatic(&swap->name, "[NFS]");
|
||||
else
|
||||
ffStrbufInitF(&swap->name, "/dev/%s", devname(xsw->xsw_dev, S_IFCHR));
|
||||
swap->bytesUsed = (uint64_t) xsw->xsw_used * pageSize;
|
||||
swap->bytesTotal = (uint64_t) xsw->xsw_nblks * pageSize;
|
||||
}
|
||||
|
||||
#if __DragonFly__
|
||||
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
struct xswdev xsws[32];
|
||||
size_t size = sizeof(xsws);
|
||||
if (sysctlbyname("vm.swap_info_array", xsws, &size, NULL, 0) < 0)
|
||||
return "sysctlbyname(\"vm.swap_info_array\") failed";
|
||||
|
||||
uint32_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
|
||||
size_t count = size / sizeof(struct xswdev);
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
|
||||
if (xsws->xsw_version != XSWDEV_VERSION)
|
||||
return "xswdev version mismatch";
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
addSwapEntry(result, &xsws[i], pageSize);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#elif __FreeBSD__
|
||||
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
int mib[16];
|
||||
size_t mibsize = ARRAY_SIZE(mib);
|
||||
if (sysctlnametomib("vm.swap_info", mib, &mibsize) < 0)
|
||||
return "sysctlnametomib(\"vm.swap_info\") failed";
|
||||
|
||||
swap->bytesUsed = swap->bytesTotal = 0;
|
||||
uint32_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
|
||||
for (int n = 0; ; ++n)
|
||||
{
|
||||
@@ -21,12 +63,11 @@ const char* ffDetectSwap(FFSwapResult* swap)
|
||||
break;
|
||||
if (xsw.xsw_version != XSWDEV_VERSION)
|
||||
return "xswdev version mismatch";
|
||||
swap->bytesUsed += (uint64_t) xsw.xsw_used;
|
||||
swap->bytesTotal += (uint64_t) xsw.xsw_nblks;
|
||||
}
|
||||
|
||||
swap->bytesUsed *= instance.state.platform.sysinfo.pageSize;
|
||||
swap->bytesTotal *= instance.state.platform.sysinfo.pageSize;
|
||||
addSwapEntry(result, &xsw, pageSize);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
#include "swap.h"
|
||||
|
||||
#include <OS.h>
|
||||
#include <driver_settings.h>
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
system_info info;
|
||||
if (get_system_info(&info) != B_OK)
|
||||
return "Error getting system info";
|
||||
|
||||
swap->bytesTotal = B_PAGE_SIZE * (uint64_t) info.max_swap_pages;
|
||||
swap->bytesUsed = B_PAGE_SIZE * (uint64_t) (info.max_swap_pages - info.free_swap_pages);
|
||||
uint32_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitStatic(&swap->name, "System");
|
||||
void* kvms = load_driver_settings("virtual_memory"); // /boot/home/config/settings/kernel/drivers/virtual_memory
|
||||
if (kvms)
|
||||
{
|
||||
const char* swapAuto = get_driver_parameter(kvms, "swap_auto", NULL, NULL);
|
||||
if (swapAuto)
|
||||
ffStrbufSetStatic(&swap->name, swapAuto[0] == 'y' ? "Auto" : "Manual");
|
||||
unload_driver_settings(kvms);
|
||||
}
|
||||
swap->bytesTotal = pageSize * (uint64_t) info.max_swap_pages;
|
||||
swap->bytesUsed = pageSize * (uint64_t) (info.max_swap_pages - info.free_swap_pages);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
static const char* detectByProcMeminfo(FFlist* result)
|
||||
{
|
||||
// For Android
|
||||
// Ref: #620
|
||||
char buf[PROC_FILE_BUFFSIZ];
|
||||
ssize_t nRead = ffReadFileData("/proc/meminfo", ARRAY_SIZE(buf) - 1, buf);
|
||||
@@ -23,8 +24,59 @@ const char* ffDetectSwap(FFSwapResult* swap)
|
||||
if ((token = strstr(buf, "SwapFree:")) != NULL)
|
||||
swapFree = strtoul(token + strlen("SwapFree:"), NULL, 10);
|
||||
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitStatic(&swap->name, "Total");
|
||||
swap->bytesTotal = swapTotal * 1024lu;
|
||||
swap->bytesUsed = (swapTotal - swapFree) * 1024lu;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectByProcSwaps(FFlist* result)
|
||||
{
|
||||
// Ref: #620
|
||||
char buf[PROC_FILE_BUFFSIZ];
|
||||
ssize_t nRead = ffReadFileData("/proc/swaps", ARRAY_SIZE(buf) - 1, buf);
|
||||
if(nRead <= 0)
|
||||
return "ffReadFileData(\"/proc/swaps\", ARRAY_SIZE(buf)-1, buf) failed";
|
||||
buf[nRead] = '\0';
|
||||
|
||||
// Skip header
|
||||
char* line = memchr(buf, '\n', (size_t) nRead);
|
||||
|
||||
while(line && *++line)
|
||||
{
|
||||
uint64_t total, used;
|
||||
char name[256];
|
||||
if(sscanf(line, "%255s %*[^\t]%" SCNu64 "%" SCNu64, name, &total, &used) != 3)
|
||||
return "Invalid /proc/swaps format found";
|
||||
|
||||
uint32_t nameLen = (uint32_t) strnlen(name, sizeof(name));
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitA(&swap->name, nameLen);
|
||||
for (size_t i = 0; i < nameLen; ++i)
|
||||
{
|
||||
if(name[i] == '\\')
|
||||
{
|
||||
char octal[4] = { name[i + 1], name[i + 2], name[i + 3], '\0' };
|
||||
ffStrbufAppendC(&swap->name, (char) strtol(octal, NULL, 8));
|
||||
i += 3;
|
||||
}
|
||||
else
|
||||
ffStrbufAppendC(&swap->name, name[i]);
|
||||
}
|
||||
swap->bytesTotal = total * 1024u;
|
||||
swap->bytesUsed = used * 1024u;
|
||||
|
||||
line = memchr(line, '\n', (size_t) (nRead - (line - buf)));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
if (detectByProcSwaps(result) == NULL)
|
||||
return NULL;
|
||||
return detectByProcMeminfo(result);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "swap.h"
|
||||
#include "util/FFlist.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
@@ -6,7 +7,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
int nswap = swapctl(SWAP_NSWAP, 0, 0);
|
||||
if (nswap < 0) return "swapctl(SWAP_NSWAP) failed";
|
||||
@@ -17,17 +18,16 @@ const char* ffDetectSwap(FFSwapResult* swap)
|
||||
if (swapctl(SWAP_STATS, swdev, nswap) < 0)
|
||||
return "swapctl(SWAP_STATS) failed";
|
||||
|
||||
uint64_t swapTotal = 0, swapUsed = 0;
|
||||
for (int i = 0; i < nswap; i++)
|
||||
{
|
||||
if (swdev[i].se_flags & SWF_ENABLE)
|
||||
{
|
||||
swapUsed += (uint64_t) swdev[i].se_inuse;
|
||||
swapTotal += (uint64_t) swdev[i].se_nblks;
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitS(&swap->name, swdev[i].se_path);
|
||||
swap->bytesUsed = (uint64_t) swdev[i].se_inuse * DEV_BSIZE;
|
||||
swap->bytesTotal = (uint64_t) swdev[i].se_nblks * DEV_BSIZE;
|
||||
}
|
||||
}
|
||||
swap->bytesUsed = swapUsed * DEV_BSIZE;
|
||||
swap->bytesTotal = swapTotal * DEV_BSIZE;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
enum { FFMaxNSwap = 8 };
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
char strings[FFMaxNSwap][PATH_MAX];
|
||||
uint8_t buffer[sizeof(swaptbl_t) + sizeof(swapent_t) * (FFMaxNSwap - 1)] = {};
|
||||
@@ -18,16 +18,14 @@ const char* ffDetectSwap(FFSwapResult* swap)
|
||||
if (size < 0)
|
||||
return "swapctl() failed";
|
||||
|
||||
swap->bytesTotal = swap->bytesUsed = 0;
|
||||
|
||||
uint32_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
swap->bytesTotal += (uint64_t) table->swt_ent[i].ste_pages;
|
||||
swap->bytesUsed += (uint64_t) table->swt_ent[i].ste_free;
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitS(&swap->name, table->swt_ent[i].ste_path);
|
||||
swap->bytesTotal = (uint64_t) table->swt_ent[i].ste_pages * pageSize;
|
||||
swap->bytesUsed = swap->bytesTotal - (uint64_t) table->swt_ent[i].ste_free * pageSize;
|
||||
}
|
||||
swap->bytesUsed = swap->bytesTotal - swap->bytesUsed;
|
||||
swap->bytesTotal *= instance.state.platform.sysinfo.pageSize;
|
||||
swap->bytesUsed *= instance.state.platform.sysinfo.pageSize;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "swap.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/windows/unicode.h"
|
||||
|
||||
#include <winternl.h>
|
||||
#include <ntstatus.h>
|
||||
#include <windows.h>
|
||||
|
||||
const char* ffDetectSwap(FFSwapResult* swap)
|
||||
const char* ffDetectSwap(FFlist* result)
|
||||
{
|
||||
uint8_t buffer[4096];
|
||||
ULONG size = sizeof(buffer);
|
||||
@@ -13,16 +14,18 @@ const char* ffDetectSwap(FFSwapResult* swap)
|
||||
if(!NT_SUCCESS(NtQuerySystemInformation(SystemPagefileInformation, pstart, size, &size)))
|
||||
return "NtQuerySystemInformation(SystemPagefileInformation, size) failed";
|
||||
|
||||
uint32_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
for (SYSTEM_PAGEFILE_INFORMATION* current = pstart; ; current = (SYSTEM_PAGEFILE_INFORMATION*)((uint8_t*) current + current->NextEntryOffset))
|
||||
{
|
||||
swap->bytesUsed += current->TotalUsed;
|
||||
swap->bytesTotal += current->CurrentSize;
|
||||
FFSwapResult* swap = ffListAdd(result);
|
||||
ffStrbufInitNWS(&swap->name, current->FileName.Length / sizeof(wchar_t), current->FileName.Buffer);
|
||||
if (ffStrbufStartsWithS(&swap->name, "\\??\\"))
|
||||
ffStrbufSubstrAfter(&swap->name, strlen("\\??\\") - 1);
|
||||
swap->bytesUsed = current->TotalUsed * pageSize;
|
||||
swap->bytesTotal = current->CurrentSize * pageSize;
|
||||
if (current->NextEntryOffset == 0)
|
||||
break;
|
||||
}
|
||||
uint32_t pageSize = instance.state.platform.sysinfo.pageSize;
|
||||
swap->bytesUsed *= pageSize;
|
||||
swap->bytesTotal *= pageSize;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -243,6 +243,29 @@ static bool detectContour(const FFstrbuf* exe, FFTerminalFontResult* result)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool detectRio(FFTerminalFontResult* terminalFont)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate();
|
||||
FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate();
|
||||
|
||||
FFpropquery fontQueryToml[] = {
|
||||
{"family =", &fontName},
|
||||
{"size =", &fontSize},
|
||||
};
|
||||
|
||||
ffParsePropFileConfigValues("rio/config.toml", 2, fontQueryToml);
|
||||
|
||||
if(fontName.length == 0)
|
||||
ffStrbufAppendS(&fontName, "Cascadia Code");
|
||||
|
||||
if(fontSize.length == 0)
|
||||
ffStrbufAppendS(&fontSize, "18");
|
||||
|
||||
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont);
|
||||
|
||||
static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
|
||||
@@ -257,6 +280,8 @@ static bool detectTerminalFontCommon(const FFTerminalResult* terminal, FFTermina
|
||||
detectContour(&terminal->exe, terminalFont);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "ghostty"))
|
||||
detectGhostty(terminalFont);
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->processName, "rio"))
|
||||
detectRio(terminalFont);
|
||||
|
||||
#ifndef _WIN32
|
||||
else if(ffStrbufStartsWithIgnCaseS(&terminal->exe, "/dev/pts/"))
|
||||
|
||||
@@ -30,6 +30,7 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName)
|
||||
!ffStrEqualsIgnCase(comm, "kwm") &&
|
||||
!ffStrEqualsIgnCase(comm, "chunkwm") &&
|
||||
!ffStrEqualsIgnCase(comm, "yabai") &&
|
||||
!ffStrEqualsIgnCase(comm, "aerospace") &&
|
||||
!ffStrEqualsIgnCase(comm, "rectangle")
|
||||
) continue;
|
||||
|
||||
|
||||
@@ -128,6 +128,39 @@ static const char* getSway(FFstrbuf* result)
|
||||
return "Failed to run command `sway --version`";
|
||||
}
|
||||
|
||||
static bool extractI3Version(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
|
||||
{
|
||||
int count = 0;
|
||||
sscanf(line, "%*d.%*d%n", &count);
|
||||
if (count == 0) return true;
|
||||
|
||||
ffStrbufSetNS((FFstrbuf*) userdata, len, line);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* getI3(FFstrbuf* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
|
||||
const char* error = ffFindExecutableInPath("i3", &path);
|
||||
if (error) return "Failed to find i3 executable path";
|
||||
|
||||
ffBinaryExtractStrings(path.chars, extractI3Version, result, (uint32_t) strlen("0.0"));
|
||||
if (result->length > 0) return NULL;
|
||||
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
path.chars,
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL)
|
||||
{ // i3 version 1.10 C 2009...
|
||||
ffStrbufSubstrAfterFirstS(result, "version ");
|
||||
ffStrbufSubstrBeforeFirstC(result, ' ');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "Failed to run command `i3 --version`";
|
||||
}
|
||||
|
||||
static const char* getWslg(FFstrbuf* result)
|
||||
{
|
||||
if (!ffAppendFileBuffer("/mnt/wslg/versions.txt", result))
|
||||
@@ -143,19 +176,84 @@ static const char* getWslg(FFstrbuf* result)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool extractCtFvWmVersion(const char* line, FF_MAYBE_UNUSED uint32_t len, void *userdata)
|
||||
{
|
||||
int count = 0;
|
||||
sscanf(line, "%*d.%*d.%*d%n", &count);
|
||||
if (count == 0) return true;
|
||||
|
||||
ffStrbufSetNS((FFstrbuf*) userdata, len, line);
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* getCtwm(FFstrbuf* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
|
||||
const char* error = ffFindExecutableInPath("ctwm", &path);
|
||||
if (error) return "Failed to find ctwm executable path";
|
||||
|
||||
ffBinaryExtractStrings(path.chars, extractCtFvWmVersion, result, (uint32_t) strlen("0.0.0"));
|
||||
if (result->length > 0) return NULL;
|
||||
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
path.chars,
|
||||
"--version",
|
||||
NULL
|
||||
}) == NULL)
|
||||
{ // ctwm version 4.0.1\n...
|
||||
ffStrbufSubstrBeforeFirstC(result, '\n');
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "Failed to run command `ctwm --version`";
|
||||
}
|
||||
|
||||
static const char* getFvwm(FFstrbuf* result)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
|
||||
const char* error = ffFindExecutableInPath("fvwm", &path);
|
||||
if (error) return "Failed to find fvwm executable path";
|
||||
|
||||
ffBinaryExtractStrings(path.chars, extractCtFvWmVersion, result, (uint32_t) strlen("0.0.0"));
|
||||
if (result->length > 0) return NULL;
|
||||
|
||||
if (ffProcessAppendStdOut(result, (char* const[]){
|
||||
path.chars,
|
||||
"-version",
|
||||
NULL
|
||||
}) == NULL)
|
||||
{ // [FVWM][main]: fvwm Version 2.2.5\n...
|
||||
ffStrbufSubstrBeforeFirstC(result, '\n');
|
||||
ffStrbufSubstrAfterLastC(result, ' ');
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "Failed to run command `fvwm -version`";
|
||||
}
|
||||
|
||||
const char* ffDetectWMVersion(const FFstrbuf* wmName, FFstrbuf* result, FF_MAYBE_UNUSED FFWMOptions* options)
|
||||
{
|
||||
if (!wmName)
|
||||
return "No WM detected";
|
||||
|
||||
if (ffStrbufEqualS(wmName, "Hyprland"))
|
||||
if (ffStrbufIgnCaseEqualS(wmName, "Hyprland"))
|
||||
return getHyprland(result);
|
||||
|
||||
if (ffStrbufEqualS(wmName, "sway"))
|
||||
return getSway(result);
|
||||
|
||||
if (ffStrbufEqualS(wmName, "i3"))
|
||||
return getI3(result);
|
||||
|
||||
if (ffStrbufEqualS(wmName, "WSLg"))
|
||||
return getWslg(result);
|
||||
|
||||
if (ffStrbufEqualS(wmName, "ctwm"))
|
||||
return getCtwm(result);
|
||||
|
||||
if (ffStrbufEqualS(wmName, "fvwm"))
|
||||
return getFvwm(result);
|
||||
|
||||
return "Unsupported WM";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
$4#######################
|
||||
$4# $2##### $4#
|
||||
$4# $2####### $4#
|
||||
$4# $2##$5O$2#$5O$2## $4#
|
||||
$4# $2#$3#####$2# $4#
|
||||
$4# $2##$1##$3###$1##$2## $4#
|
||||
$4# $2#$1##########$2## $4#
|
||||
$4# $2#$1############$2## $4#
|
||||
$4# $2#$1######$5A_O$1####$2### $4#
|
||||
$4# $3##$2#$1############$2##$3## $4#
|
||||
$4#$3######$2#$1#######$2#$3######$4#
|
||||
$4#$3#######$2#$1#####$2#$3#######$4#
|
||||
$4# $3#####$2#######$3##### $4#
|
||||
$4#######################
|
||||
$4#$5╔═╗╔╗╔╦ ╦╔═╗╦ ╦╔═╗╔═╗$4#
|
||||
$4#$5╠═╣║║║║ ║╚═╗╠═╣║ ║╚═╗$4#
|
||||
$4#$5╩ ╩╝╚╝╚═╝╚═╝╩ ╩╚═╝╚═╝$4#
|
||||
$4#######################
|
||||
$4# $3WWW.ANUSHOS.ORG $4#
|
||||
$4#######################
|
||||
@@ -1,6 +1,6 @@
|
||||
_________
|
||||
| __ |
|
||||
| \ \___ |
|
||||
| \ _ \ |
|
||||
| \___/ |
|
||||
_________
|
||||
| $2__ $1 |
|
||||
| $2\ \___ $1 |
|
||||
| $2 \ _ \$1 |
|
||||
| $2 \___/$1 |
|
||||
|_________|
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
__
|
||||
/ \
|
||||
__ |_
|
||||
/ |
|
||||
\__/
|
||||
@@ -0,0 +1,19 @@
|
||||
xSSSSSSSSSSSx:
|
||||
XSSSSSSSSSSSSSSSSSSSSX
|
||||
xSSSSSSSSSSSSSSSSSSSSSSSxSSX
|
||||
xSSSSSSSSSSSSSSSSSSSSSSSSSSSSXSS
|
||||
SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSXXXS;
|
||||
+SSSSSSx++SSSSSSSSSSSSSSSSSSSSSSSSSXSX
|
||||
SSSSS:::::::SSSSSSSSSSSSSXSSSSSSSSSS+S+
|
||||
XSSSX::::::::XxSSSSSSSSXSx;::xSSSSSSSSSS
|
||||
;SSSS:::::::::XSSSSSSSSS+:::::::xSSSSSSSS;
|
||||
+SSSSx::::::::SSSSSSSSS;:::::::::XSSSSSSSX
|
||||
SSSSXSx:::::SSSSxXSSSS::::::::::XSSSSSSSX
|
||||
xSSSSSSSSSSSS:::::SSSX::::::::::XSSSSSSS;
|
||||
+SSSSSSSSSSSSSSX:SSSSS;:::::::SxSSSSSSS
|
||||
+SSSSSSSSSSSSSSSSSSSSSSSSSXSSxSSSSSS
|
||||
xxSSSSSSSSSSSSSSSSSSSSSSSSSSSSSx
|
||||
SSSSSSSSSSSSSSSSSSSSSSSSSSSX
|
||||
xXSSSSSSSSSSSSX
|
||||
SSS +SSSxSSSSS
|
||||
;x xSSx
|
||||
@@ -0,0 +1,19 @@
|
||||
....-----....
|
||||
.-+##############+-..
|
||||
.+######################+..
|
||||
.########+- -++#######-.
|
||||
.+######- -######+.
|
||||
.######. .######..
|
||||
.+####+ +#####..
|
||||
.-####+. +####+.
|
||||
.+####+ -####+..
|
||||
..+####+ -####+...
|
||||
$2......--$1+####+$2--.......................--$1+####+$2-.........
|
||||
..$1--++++-$2...... ...$1-++++--$2..
|
||||
..$1--+++--$2... ...$1-+++++-$2..
|
||||
.$1--+++--$2.... ....$1--+++-$2...
|
||||
..$1-++++++--$2..... ......$1---+---$2...
|
||||
...$1-+++++++++-----$2..$1----++++++--$2..
|
||||
...$1---++++++----++++++++---$2...
|
||||
.....$1-----+++-----$2...
|
||||
...$1---$2...
|
||||
@@ -0,0 +1,22 @@
|
||||
+++
|
||||
++++++++ +
|
||||
++++++++++++ +++
|
||||
++++++++++* +++++++++ ++++
|
||||
+++++++ ++++++++++++++++++
|
||||
++++ ++++ +++++
|
||||
++++ +++ ++++
|
||||
+++++ +++ ++++++ +++
|
||||
+++++++++++++ +++++++++ +++
|
||||
+++++++++++++ +++ +++ +++
|
||||
+++++++++++++ ++++ +++ +++
|
||||
++++++++ +++ +++++++ +++
|
||||
+++++++ +++
|
||||
++++++++ ++++ ++
|
||||
+++++++++++ +++++ +++++
|
||||
++++++++ ++++++++++++ +++++++++
|
||||
++++++++++++++ ++++++++++++++++
|
||||
++++++++++++++++++++++++ +++++++++
|
||||
++++++ +++++++++ ++++
|
||||
+ +++++++
|
||||
+++++++
|
||||
+++++
|
||||
@@ -0,0 +1,9 @@
|
||||
.M.:MMM
|
||||
MMMMMMMMMM.
|
||||
,MMMMMMMMMMM
|
||||
.MM MMMMMMMMMMM
|
||||
MMMM MMMMMMMMM
|
||||
MMMMMM MM
|
||||
MMMMMMMMM ,MMMM
|
||||
MMMMMMMMMMMMMMMM:
|
||||
`MMMMMMMMMMMM
|
||||
@@ -0,0 +1,14 @@
|
||||
*/
|
||||
*,*,*(
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,*,*,*,*,*,*,*,*,*,*,*,*
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
*,*,*,*,*,*,*,*,*,*,*,*,*,*,*
|
||||
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,*
|
||||
,*,*,*,*,*,*,*,*,*,*,*,*,*,*
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
(*,*,*,*,*,*,*,*,*,*,*,*,*,
|
||||
,,,,,,,,,,,,,,,,
|
||||
&*,*,*#@@*,*,*,
|
||||
@@ -0,0 +1,18 @@
|
||||
++ $2++
|
||||
$1++++++ $2++++++
|
||||
$1+++++++++ $2+++++++++
|
||||
$1+++++++ $2+++++++
|
||||
$1+++ $2+++ $1+ $3--------$1 $2+ $1+++ $2+++
|
||||
$1++++++ $2++++++ $3------$1 ++++++ $2++++++
|
||||
$1++++++++ $2++++++++++ $1++++++++++ $2++++++++
|
||||
$1+++++++ $3--$1 $2+++++++ $1+++++++ $3--$1 $2+++++++
|
||||
$2+++ $1+ $3--------$1 $2+ $1+++ $2+++ $1+ $3--------$1 $2+ $1+++
|
||||
$2++++++ $3--------$1 ++++++ $2++++++ $3--------$1 ++++++
|
||||
$2++++++++++ $1+++++++++ $2+++++++++ $1++++++++++
|
||||
$2+++++++++ $1+++++++ $3--$1 $2+++++++ $1+++++++++
|
||||
$2+++++ +++ $3--------$1 +++ +++++
|
||||
$2++ +++++++ $3------$1 +++++++ ++
|
||||
$2++++++++++ $1++++++++++
|
||||
$2++++++++ $1++++++++
|
||||
$2+++++ $1+++++
|
||||
$2++ $1++
|
||||
@@ -0,0 +1,25 @@
|
||||
..........
|
||||
.::::::::::::::::::..
|
||||
..:::::::::::::::::::::::::.
|
||||
'::::::::::::::::::::::::::::.
|
||||
':::::'' '':::::::::::::.
|
||||
$3 .. $1' '':::::::::.
|
||||
$3 .||. $1':::::::::
|
||||
$3 .|||||. $1'::::::::
|
||||
$3 .|||||||: $1::::::::
|
||||
$3 |||||||: $1.::::::::. ::::::::
|
||||
$2 ######$3||||||' $2##^ v##########v$1::. $2##### #############v
|
||||
$2 ######$3||||| $2##^ v####$1::::::$2####v$1::$2##### #####$1:::::$2#####
|
||||
$2 ######$3||$2##^ #####$1::::::$2#####$1::$2##### #####$1:::::$2######
|
||||
$2 ######^$3|| $2#####$1:::::$2####^$1::$2##### #####$1:::::$2#####^
|
||||
$2 ##^$3||||| $2^###########^$1:::$2##### ##############^
|
||||
$3 |||||||: $1'::::::::' .::::::::
|
||||
$3 '|||||||: $1.::::::::'
|
||||
$3 '|||||||:. $1'::::::
|
||||
$3 '||||||||:. $1':::
|
||||
$3 ':|||||||||. . $1'
|
||||
$3 '|||||||||||:... ...:||||.
|
||||
':||||||||||||||||||||||||||.
|
||||
':|||||||||||||||||||||||''
|
||||
'':||||||||||||||:''
|
||||
''''''
|
||||
+15
-21
@@ -1,21 +1,15 @@
|
||||
$2 ,c. .c;
|
||||
$2 .$1KMMMk$2.... ....$1kMMMK$2.
|
||||
$2 .$1WMMMMMX$2..... .....$1KMMMMMW.
|
||||
$1 XMMMMMMM0$2..... ....$1OMMMMMMMN
|
||||
$1 dMMMMMMMMM;$2.... ..... ....,$1MMMMMMMMMd
|
||||
$1 WMMMMMMMMMl;$3okKKKKKKKKKOo$1;cMMMMMMMMMM
|
||||
$1 'MMMMMMMNX$2K0$3KKKKKKKKKKKKKKK$20K$1XNMMMMMMM;
|
||||
$1 oMMMMMMM$2Oxo$3KKKKKKKKKKKKKKKKK$2oxO$1MMMMMMMd
|
||||
$1 dMMMMMMM$2dxxx$3KKKKKKKKKKKKKKK$2xxxd$1NMMMMMMk
|
||||
$1 :MMMMX0$2xxxxxx$30KKKKKKKK0KK0$2xxxxxx0$1XMMMMc
|
||||
$1 MMMO$2xxxxxxxxdx$3kdd$20x0$3ddk$2xdxxxxxxxx$1OMMM
|
||||
$1 ;$2xxkxddxxxxdodxxxxdxdxxxxdodxxxxddxkxx$1;
|
||||
$1dxd$2KMMMWXo$1'.....'$2cdxxxdc$1'.....'$2lXWMMMX$1dxd
|
||||
$1cxd$2XMMMN$1,..........$2dxd$1'.........'$2XMMMN$1dxl
|
||||
$1 .xx$2WMMl$1...''....'.;k:.'....''...$2lMMW$1xx.
|
||||
$1..:kXMMx..'....''..kMk..''....'..xMMXkc..
|
||||
$1 dMMMMMMd.....'...xMMMx...''....dMMMMMMx
|
||||
$1 kMMMMWOoc:coOkolllokOoc:coOWMMMMO
|
||||
$1 .MMMMMMMMl$2...$1lNMMMMMMM.
|
||||
$1 KMMMMMMX$2l$1KMMMMMMX
|
||||
$1 .MMMMMMMMM.
|
||||
**
|
||||
* ** */
|
||||
$2@$1///// / *** *** **** ***/
|
||||
//////////////**** ** * ** *** **/
|
||||
,, ,,//////////* ****** ** ** ** /
|
||||
, , ,,, /////******* ********* /
|
||||
, ,,,,, ** ** ***********
|
||||
., ,,,**** ******* *** ///
|
||||
,, *********** ** ////
|
||||
,,,,, ******* //// //
|
||||
,,,,,,. ///// //
|
||||
,,, , ///////
|
||||
,,,, /////
|
||||
,, / /
|
||||
/
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
$2 ,c. .c;
|
||||
$2 .$1KMMMk$2.... ....$1kMMMK$2.
|
||||
$2 .$1WMMMMMX$2..... .....$1KMMMMMW.
|
||||
$1 XMMMMMMM0$2..... ....$1OMMMMMMMN
|
||||
$1 dMMMMMMMMM;$2.... ..... ....,$1MMMMMMMMMd
|
||||
$1 WMMMMMMMMMl;$3okKKKKKKKKKOo$1;cMMMMMMMMMM
|
||||
$1 'MMMMMMMNX$2K0$3KKKKKKKKKKKKKKK$20K$1XNMMMMMMM;
|
||||
$1 oMMMMMMM$2Oxo$3KKKKKKKKKKKKKKKKK$2oxO$1MMMMMMMd
|
||||
$1 dMMMMMMM$2dxxx$3KKKKKKKKKKKKKKK$2xxxd$1NMMMMMMk
|
||||
$1 :MMMMX0$2xxxxxx$30KKKKKKKK0KK0$2xxxxxx0$1XMMMMc
|
||||
$1 MMMO$2xxxxxxxxdx$3kdd$20x0$3ddk$2xdxxxxxxxx$1OMMM
|
||||
$1 ;$2xxkxddxxxxdodxxxxdxdxxxxdodxxxxddxkxx$1;
|
||||
$1dxd$2KMMMWXo$1'.....'$2cdxxxdc$1'.....'$2lXWMMMX$1dxd
|
||||
$1cxd$2XMMMN$1,..........$2dxd$1'.........'$2XMMMN$1dxl
|
||||
$1 .xx$2WMMl$1...''....'.;k:.'....''...$2lMMW$1xx.
|
||||
$1..:kXMMx..'....''..kMk..''....'..xMMXkc..
|
||||
$1 dMMMMMMd.....'...xMMMx...''....dMMMMMMx
|
||||
$1 kMMMMWOoc:coOkolllokOoc:coOWMMMMO
|
||||
$1 .MMMMMMMMl$2...$1lNMMMMMMM.
|
||||
$1 KMMMMMMX$2l$1KMMMMMMX
|
||||
$1 .MMMMMMMMM.
|
||||
+155
-44
@@ -252,6 +252,20 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// AnushOS
|
||||
{
|
||||
.names = {"AnushOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ANUSHOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_BLACK,
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_CYAN,
|
||||
FF_COLOR_FG_RED,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_WHITE,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// AoscOsRetro
|
||||
{
|
||||
.names = {"Aosc OS/Retro", "aoscosretro"},
|
||||
@@ -706,10 +720,10 @@ static const FFlogo B[] = {
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_BEDROCK,
|
||||
.colors = {
|
||||
FF_COLOR_FG_LIGHT_BLACK, //grey
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_LIGHT_BLACK, //grey
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
// BedrockSmall
|
||||
{
|
||||
@@ -717,10 +731,11 @@ static const FFlogo B[] = {
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_BEDROCK_SMALL,
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_LIGHT_BLACK, //grey
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_WHITE,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
.colorKeys = FF_COLOR_FG_LIGHT_BLACK, //grey
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
// BigLinux
|
||||
{
|
||||
@@ -1731,6 +1746,16 @@ static const FFlogo F[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
{
|
||||
.names = {"Fedora2_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT | FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_FEDORA2_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// FedoraOld
|
||||
{
|
||||
.names = {"Fedora_old"},
|
||||
@@ -1989,6 +2014,16 @@ static const FFlogo G[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
},
|
||||
// GhostFreak
|
||||
{
|
||||
.names = {"GhostFreak"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_GHOSTFREAK,
|
||||
.colors = {
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_DEFAULT,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Glaucus
|
||||
{
|
||||
.names = {"Glaucus"},
|
||||
@@ -2175,6 +2210,17 @@ static const FFlogo H[] = {
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
},
|
||||
// HarmonyOS
|
||||
{
|
||||
.names = {"HarmonyOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_HARMONYOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Hash
|
||||
{
|
||||
.names = {"Hash"},
|
||||
@@ -2267,13 +2313,13 @@ static const FFlogo H[] = {
|
||||
.colorKeys = FF_COLOR_FG_LIGHT_BLACK,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Hydra Framework
|
||||
// HydraPWK
|
||||
{
|
||||
.names = {"Hydra"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_HYDRA,
|
||||
.names = {"HydraPWK"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_HYDRAPWK,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
},
|
||||
// LAST
|
||||
@@ -2378,18 +2424,18 @@ static const FFlogo K[] = {
|
||||
},
|
||||
// Kali
|
||||
{
|
||||
.names = {"Kali", "Kalilinux"},
|
||||
.names = {"Kali"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_KALI,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
// KaliSmall
|
||||
{
|
||||
.names = {"Kali_small", "Kalilinux_small"},
|
||||
.names = {"Kali_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_KALI_SMALL,
|
||||
.colors = {
|
||||
@@ -2397,7 +2443,17 @@ static const FFlogo K[] = {
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
// Kalpa Desktop
|
||||
{
|
||||
.names = {"kalpa-desktop"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_KALPA_DESKTOP,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_GREEN,
|
||||
.colorTitle = FF_COLOR_FG_DEFAULT,
|
||||
},
|
||||
// KaOS
|
||||
{
|
||||
@@ -4060,7 +4116,7 @@ static const FFlogo R[] = {
|
||||
},
|
||||
// RedHatEnterpriseLinux
|
||||
{
|
||||
.names = {"rhel", "redhat", "redhat-linux"},
|
||||
.names = {"rhel", "redhat"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_RHEL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
@@ -4068,9 +4124,20 @@ static const FFlogo R[] = {
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
},
|
||||
// RedHatEnterpriseLinux
|
||||
{
|
||||
.names = {"rhel_small", "redhat_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_RHEL_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
},
|
||||
// RedHatEnterpriseLinux_old
|
||||
{
|
||||
.names = {"rhel_old", "redhat_old", "redhat-linux_old"},
|
||||
.names = {"rhel_old", "redhat_old"},
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_RHEL_OLD,
|
||||
.colors = {
|
||||
@@ -4082,11 +4149,10 @@ static const FFlogo R[] = {
|
||||
{
|
||||
.names = {"RedOS", "RED OS", "red-os", "redos"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_REDOS,
|
||||
.colors =
|
||||
{
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
},
|
||||
@@ -4095,11 +4161,10 @@ static const FFlogo R[] = {
|
||||
.names = {"RedOS_small", "RED OS_small", "red-os_small", "redos_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_REDOS_SMALL,
|
||||
.colors =
|
||||
{
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
.colorKeys = FF_COLOR_FG_RED,
|
||||
},
|
||||
@@ -4527,6 +4592,16 @@ static const FFlogo S[] = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// Starry
|
||||
{
|
||||
.names = {"Starry"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_STARRY,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_GREEN,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// StockLinux
|
||||
{
|
||||
.names = {"Stock Linux"},
|
||||
@@ -4709,6 +4784,18 @@ static const FFlogo T[] = {
|
||||
FF_COLOR_FG_CYAN,
|
||||
},
|
||||
},
|
||||
// TrueNAS Scale
|
||||
{
|
||||
.names = {"TrueNAS-Scale"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_TRUENAS_SCALE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_256 "39",
|
||||
FF_COLOR_FG_256 "32",
|
||||
FF_COLOR_FG_256 "248",
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_256 "248",
|
||||
.colorTitle = FF_COLOR_FG_256 "32",
|
||||
},
|
||||
// TuxedoOS
|
||||
{
|
||||
.names = {"Tuxedo OS", "tuxedo"},
|
||||
@@ -5089,9 +5176,9 @@ static const FFlogo V[] = {
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_VOID,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
FF_COLOR_FG_BLACK,
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_WHITE,
|
||||
.colorKeys = FF_COLOR_FG_DEFAULT,
|
||||
.colorTitle = FF_COLOR_FG_GREEN,
|
||||
},
|
||||
// VoidSmall
|
||||
@@ -5102,7 +5189,19 @@ static const FFlogo V[] = {
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_WHITE,
|
||||
.colorKeys = FF_COLOR_FG_DEFAULT,
|
||||
.colorTitle = FF_COLOR_FG_GREEN,
|
||||
},
|
||||
// Void2
|
||||
{
|
||||
.names = {"void2"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_VOID2,
|
||||
.colors = {
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_DEFAULT,
|
||||
FF_COLOR_FG_GREEN,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_DEFAULT,
|
||||
.colorTitle = FF_COLOR_FG_GREEN,
|
||||
},
|
||||
// Void2Small
|
||||
@@ -5225,16 +5324,6 @@ static const FFlogo W[] = {
|
||||
};
|
||||
|
||||
static const FFlogo X[] = {
|
||||
// Xenia
|
||||
{
|
||||
.names = {"Xenia"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_XENIA,
|
||||
.colors = {
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_GREEN,
|
||||
FF_COLOR_FG_RED,
|
||||
}
|
||||
},
|
||||
// XCP-ng
|
||||
{
|
||||
.names = {"XCP-ng", "xenenterprise"},
|
||||
@@ -5248,14 +5337,27 @@ static const FFlogo X[] = {
|
||||
FF_COLOR_FG_YELLOW,
|
||||
}
|
||||
},
|
||||
// Xferience
|
||||
// Xenia
|
||||
{
|
||||
.names = {"Xferience"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_XFERIENCE,
|
||||
.names = {"Xenia"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_XENIA,
|
||||
.colors = {
|
||||
FF_COLOR_FG_CYAN,
|
||||
FF_COLOR_FG_CYAN,
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_DEFAULT,
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
},
|
||||
// Xenia_old
|
||||
{
|
||||
.names = {"Xenia_old"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_XENIA_OLD,
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.colors = {
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_GREEN,
|
||||
FF_COLOR_FG_RED,
|
||||
}
|
||||
},
|
||||
//XeroArch
|
||||
{
|
||||
@@ -5270,6 +5372,15 @@ static const FFlogo X[] = {
|
||||
FF_COLOR_FG_256 "15",
|
||||
}
|
||||
},
|
||||
// Xferience
|
||||
{
|
||||
.names = {"Xferience"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_XFERIENCE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_CYAN,
|
||||
FF_COLOR_FG_CYAN,
|
||||
},
|
||||
},
|
||||
// LAST
|
||||
{},
|
||||
};
|
||||
|
||||
+34
-8
@@ -1,6 +1,7 @@
|
||||
#include "logo/logo.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/printing.h"
|
||||
#include "common/processing.h"
|
||||
#include "detection/os/os.h"
|
||||
#include "detection/terminalshell/terminalshell.h"
|
||||
#include "util/textModifier.h"
|
||||
@@ -455,14 +456,13 @@ static inline void logoPrintDetected(FFLogoSize size)
|
||||
logoPrintStruct(logoGetBuiltinDetected(size));
|
||||
}
|
||||
|
||||
static bool logoPrintData(bool doColorReplacement)
|
||||
static bool logoPrintData(bool doColorReplacement, FFstrbuf* source)
|
||||
{
|
||||
FFOptionsLogo* options = &instance.config.logo;
|
||||
if(options->source.length == 0)
|
||||
if(source->length == 0)
|
||||
return false;
|
||||
|
||||
logoApplyColors(logoGetBuiltinDetected(FF_LOGO_SIZE_NORMAL), doColorReplacement);
|
||||
ffLogoPrintChars(options->source.chars, doColorReplacement);
|
||||
ffLogoPrintChars(source->chars, doColorReplacement);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -510,7 +510,7 @@ static bool logoPrintFileIfExists(bool doColorReplacement, bool raw)
|
||||
)
|
||||
{
|
||||
if (instance.config.display.showErrors)
|
||||
fprintf(stderr, "Logo: Failed to load file content from logo source: %s \n", options->source.chars);
|
||||
fprintf(stderr, "Logo: Failed to load file content from logo source: %s\n", options->source.chars);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -548,10 +548,36 @@ static bool logoTryKnownType(void)
|
||||
return logoPrintBuiltinIfExists(&options->source, FF_LOGO_SIZE_SMALL);
|
||||
|
||||
if(options->type == FF_LOGO_TYPE_DATA)
|
||||
return logoPrintData(true);
|
||||
return logoPrintData(true, &options->source);
|
||||
|
||||
if(options->type == FF_LOGO_TYPE_DATA_RAW)
|
||||
return logoPrintData(false);
|
||||
return logoPrintData(false, &options->source);
|
||||
|
||||
if(options->type == FF_LOGO_TYPE_COMMAND_RAW)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY source = ffStrbufCreate();
|
||||
|
||||
FFCommandOptions* commandOptions = &instance.config.modules.command;
|
||||
const char* error = ffProcessAppendStdOut(&source, commandOptions->param.length ? (char* const[]){
|
||||
commandOptions->shell.chars,
|
||||
commandOptions->param.chars,
|
||||
options->source.chars,
|
||||
NULL
|
||||
} : (char* const[]){
|
||||
commandOptions->shell.chars,
|
||||
options->source.chars,
|
||||
NULL
|
||||
});
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (instance.config.display.showErrors)
|
||||
fprintf(stderr, "Logo: failed to execute command `%s`: %s\n", options->source.chars, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return logoPrintData(false, &source);
|
||||
}
|
||||
|
||||
updateLogoPath(); //We sure have a file, resolve relative paths
|
||||
|
||||
@@ -603,7 +629,7 @@ void ffLogoPrint(void)
|
||||
{
|
||||
// Image logo should have been handled
|
||||
if(options->type == FF_LOGO_TYPE_BUILTIN || options->type == FF_LOGO_TYPE_SMALL)
|
||||
fprintf(stderr, "Logo: Failed to load %s logo: %s \n", options->type == FF_LOGO_TYPE_BUILTIN ? "builtin" : "builtin small", options->source.chars);
|
||||
fprintf(stderr, "Logo: Failed to load %s logo: %s\n", options->type == FF_LOGO_TYPE_BUILTIN ? "builtin" : "builtin small", options->source.chars);
|
||||
}
|
||||
|
||||
logoPrintDetected(FF_LOGO_SIZE_UNKNOWN);
|
||||
|
||||
@@ -535,7 +535,7 @@ void ffInitDiskOptions(FFDiskOptions* options)
|
||||
#if _WIN32 || __APPLE__ || __ANDROID__
|
||||
ffStrbufInit(&options->hideFolders);
|
||||
#else
|
||||
ffStrbufInitStatic(&options->hideFolders, "/efi:/boot:/boot/efi");
|
||||
ffStrbufInitStatic(&options->hideFolders, "/efi:/boot:/boot/efi:/boot/firmware");
|
||||
#endif
|
||||
ffStrbufInit(&options->hideFS);
|
||||
options->showTypes = FF_DISK_VOLUME_TYPE_REGULAR_BIT | FF_DISK_VOLUME_TYPE_EXTERNAL_BIT | FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
|
||||
@@ -11,4 +11,5 @@ typedef struct FFSwapOptions
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFPercentageModuleConfig percent;
|
||||
bool separate;
|
||||
} FFSwapOptions;
|
||||
|
||||
+93
-18
@@ -6,34 +6,44 @@
|
||||
#include "modules/swap/swap.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
void ffPrintSwap(FFSwapOptions* options)
|
||||
void printSwap(FFSwapOptions* options, uint8_t index, FFSwapResult* storage)
|
||||
{
|
||||
FFSwapResult storage = {};
|
||||
const char* error = ffDetectSwap(&storage);
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
|
||||
if(error)
|
||||
if (options->moduleArgs.key.length == 0)
|
||||
{
|
||||
ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return;
|
||||
if (storage->name.length > 0)
|
||||
ffStrbufSetF(&key, "%s (%s)", FF_SWAP_MODULE_NAME, storage->name.chars);
|
||||
else
|
||||
ffStrbufSetS(&key, FF_SWAP_MODULE_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufClear(&key);
|
||||
FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) {
|
||||
FF_FORMAT_ARG(index, "index"),
|
||||
FF_FORMAT_ARG(storage->name, "name"),
|
||||
FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"),
|
||||
}));
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate();
|
||||
ffParseSize(storage.bytesUsed, &usedPretty);
|
||||
ffParseSize(storage->bytesUsed, &usedPretty);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate();
|
||||
ffParseSize(storage.bytesTotal, &totalPretty);
|
||||
ffParseSize(storage->bytesTotal, &totalPretty);
|
||||
|
||||
double percentage = storage.bytesTotal == 0
|
||||
double percentage = storage->bytesTotal == 0
|
||||
? 0
|
||||
: (double) storage.bytesUsed / (double) storage.bytesTotal * 100.0;
|
||||
: (double) storage->bytesUsed / (double) storage->bytesTotal * 100.0;
|
||||
|
||||
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY);
|
||||
FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate();
|
||||
|
||||
if (storage.bytesTotal == 0)
|
||||
if (storage->bytesTotal == 0)
|
||||
{
|
||||
if(percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
|
||||
{
|
||||
@@ -71,15 +81,56 @@ void ffPrintSwap(FFSwapOptions* options)
|
||||
FF_STRBUF_AUTO_DESTROY percentageBar = ffStrbufCreate();
|
||||
if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT)
|
||||
ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
|
||||
FF_PRINT_FORMAT_CHECKED(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]){
|
||||
FF_FORMAT_ARG(usedPretty, "used"),
|
||||
FF_FORMAT_ARG(totalPretty, "total"),
|
||||
FF_FORMAT_ARG(percentageNum, "percentage"),
|
||||
FF_FORMAT_ARG(percentageBar, "percentage-bar"),
|
||||
FF_FORMAT_ARG(storage->name, "name"),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void ffPrintSwap(FFSwapOptions* options)
|
||||
{
|
||||
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFSwapResult));
|
||||
const char* error = ffDetectSwap(&result);
|
||||
|
||||
if(error)
|
||||
{
|
||||
ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (options->separate)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
FF_LIST_FOR_EACH(FFSwapResult, storage, result)
|
||||
{
|
||||
++index;
|
||||
printSwap(options, index, storage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FFSwapResult total = {
|
||||
.name = ffStrbufCreate(),
|
||||
};
|
||||
FF_LIST_FOR_EACH(FFSwapResult, storage, result)
|
||||
{
|
||||
total.bytesUsed += storage->bytesUsed;
|
||||
total.bytesTotal += storage->bytesTotal;
|
||||
}
|
||||
printSwap(options, 0, &total);
|
||||
ffStrbufDestroy(&total.name);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFSwapResult, storage, result)
|
||||
{
|
||||
ffStrbufDestroy(&storage->name);
|
||||
}
|
||||
}
|
||||
|
||||
bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const char* value)
|
||||
{
|
||||
const char* subKey = ffOptionTestPrefix(key, FF_SWAP_MODULE_NAME);
|
||||
@@ -90,6 +141,12 @@ bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const ch
|
||||
if (ffPercentParseCommandOptions(key, subKey, value, &options->percent))
|
||||
return true;
|
||||
|
||||
if (ffStrEqualsIgnCase(subKey, "separate"))
|
||||
{
|
||||
options->separate = ffOptionParseBoolean(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -109,6 +166,12 @@ void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module)
|
||||
if (ffPercentParseJsonObject(key, val, &options->percent))
|
||||
continue;
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "separate"))
|
||||
{
|
||||
options->separate = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key);
|
||||
}
|
||||
}
|
||||
@@ -125,8 +188,8 @@ void ffGenerateSwapJsonConfig(FFSwapOptions* options, yyjson_mut_doc* doc, yyjso
|
||||
|
||||
void ffGenerateSwapJsonResult(FF_MAYBE_UNUSED FFSwapOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
FFSwapResult storage = {};
|
||||
const char* error = ffDetectSwap(&storage);
|
||||
FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFSwapResult));
|
||||
const char* error = ffDetectSwap(&result);
|
||||
|
||||
if(error)
|
||||
{
|
||||
@@ -134,9 +197,19 @@ void ffGenerateSwapJsonResult(FF_MAYBE_UNUSED FFSwapOptions* options, yyjson_mut
|
||||
return;
|
||||
}
|
||||
|
||||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
yyjson_mut_obj_add_uint(doc, obj, "total", storage.bytesTotal);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed);
|
||||
yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result");
|
||||
FF_LIST_FOR_EACH(FFSwapResult, storage, result)
|
||||
{
|
||||
yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &storage->name);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "used", storage->bytesUsed);
|
||||
yyjson_mut_obj_add_uint(doc, obj, "total", storage->bytesTotal);
|
||||
}
|
||||
|
||||
FF_LIST_FOR_EACH(FFSwapResult, storage, result)
|
||||
{
|
||||
ffStrbufDestroy(&storage->name);
|
||||
}
|
||||
}
|
||||
|
||||
static FFModuleBaseInfo ffModuleInfo = {
|
||||
@@ -152,6 +225,7 @@ static FFModuleBaseInfo ffModuleInfo = {
|
||||
{"Total size", "total"},
|
||||
{"Percentage used (num)", "percentage"},
|
||||
{"Percentage used (bar)", "percentage-bar"},
|
||||
{"Name", "name"},
|
||||
}))
|
||||
};
|
||||
|
||||
@@ -160,6 +234,7 @@ void ffInitSwapOptions(FFSwapOptions* options)
|
||||
options->moduleInfo = ffModuleInfo;
|
||||
ffOptionInitModuleArg(&options->moduleArgs, "");
|
||||
options->percent = (FFPercentageModuleConfig) { 50, 80, 0 };
|
||||
options->separate = false;
|
||||
}
|
||||
|
||||
void ffDestroySwapOptions(FFSwapOptions* options)
|
||||
|
||||
@@ -60,6 +60,7 @@ logoType:
|
||||
{ "file-raw", FF_LOGO_TYPE_FILE_RAW },
|
||||
{ "data", FF_LOGO_TYPE_DATA },
|
||||
{ "data-raw", FF_LOGO_TYPE_DATA_RAW },
|
||||
{ "command-raw", FF_LOGO_TYPE_COMMAND_RAW },
|
||||
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
|
||||
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
|
||||
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
|
||||
@@ -286,6 +287,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
|
||||
{ "file-raw", FF_LOGO_TYPE_FILE_RAW },
|
||||
{ "data", FF_LOGO_TYPE_DATA },
|
||||
{ "data-raw", FF_LOGO_TYPE_DATA_RAW },
|
||||
{ "command-raw", FF_LOGO_TYPE_COMMAND_RAW },
|
||||
{ "sixel", FF_LOGO_TYPE_IMAGE_SIXEL },
|
||||
{ "kitty", FF_LOGO_TYPE_IMAGE_KITTY },
|
||||
{ "kitty-direct", FF_LOGO_TYPE_IMAGE_KITTY_DIRECT },
|
||||
@@ -492,6 +494,9 @@ void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc
|
||||
case FF_LOGO_TYPE_DATA_RAW:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "data-raw");
|
||||
break;
|
||||
case FF_LOGO_TYPE_COMMAND_RAW:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "command-raw");
|
||||
break;
|
||||
case FF_LOGO_TYPE_IMAGE_SIXEL:
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", "sixel");
|
||||
break;
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef enum __attribute__((__packed__)) FFLogoType
|
||||
FF_LOGO_TYPE_FILE_RAW, //text file, printed as is
|
||||
FF_LOGO_TYPE_DATA, //text data, printed with color code replacement
|
||||
FF_LOGO_TYPE_DATA_RAW, //text data, printed as is
|
||||
FF_LOGO_TYPE_COMMAND_RAW, //command to generate text data, printed as is
|
||||
FF_LOGO_TYPE_IMAGE_SIXEL, //image file, printed as sixel codes
|
||||
FF_LOGO_TYPE_IMAGE_KITTY, //image file, printed as kitty graphics protocol
|
||||
FF_LOGO_TYPE_IMAGE_KITTY_DIRECT, //image file, tell the terminal emulator to read image data from the specified file (Supported by kitty and wezterm)
|
||||
|
||||
@@ -63,7 +63,7 @@ const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* s
|
||||
return "load libelf failed";
|
||||
|
||||
// Open the ELF file
|
||||
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY, 0);
|
||||
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) return "open() failed";
|
||||
|
||||
Elf* elf = elfData.ffelf_begin(fd, ELF_C_READ, NULL);
|
||||
|
||||
@@ -51,7 +51,6 @@ bool ffKmodLoaded(const char* modName)
|
||||
{
|
||||
struct iovec iov = {};
|
||||
|
||||
// 初始尝试分配的内存大小
|
||||
for (size_t len = 8192;; len = iov.iov_len)
|
||||
{
|
||||
iov.iov_len = len;
|
||||
|
||||
@@ -143,7 +143,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
{
|
||||
FF_DEBUG("Initializing SMBIOS buffer");
|
||||
ffStrbufInit(&buffer);
|
||||
#if !__HAIKU__ && !__OpenBSD__
|
||||
#if !__HAIKU__ && !__OpenBSD__ && !__DragonFly__
|
||||
#ifdef __linux__
|
||||
FF_DEBUG("Using Linux implementation - trying /sys/firmware/dmi/tables/DMI");
|
||||
if (!ffAppendFileBuffer("/sys/firmware/dmi/tables/DMI", &buffer))
|
||||
@@ -183,7 +183,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
}
|
||||
FF_DEBUG("Parsed SMBIOS entry address: 0x%lx", (unsigned long)entryAddress);
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/mem", O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/mem", O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
FF_DEBUG("Failed to open /dev/mem: %s", strerror(errno));
|
||||
return NULL;
|
||||
@@ -219,7 +219,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
#endif
|
||||
);
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/smbios", O_RDONLY);
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/smbios", O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
FF_DEBUG("Failed to open /dev/smbios: %s", strerror(errno));
|
||||
return NULL;
|
||||
@@ -328,7 +328,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
#else
|
||||
"/dev/mem" // kern.securelevel must be -1
|
||||
#endif
|
||||
, O_RDONLY);
|
||||
, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
FF_DEBUG("Failed to open memory device: %s", strerror(errno));
|
||||
return NULL;
|
||||
|
||||
Reference in New Issue
Block a user