mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 630d876e2d | |||
| 1938be86ff | |||
| 0980d5f0ad | |||
| d8c1b3b61b | |||
| 969523ae8a | |||
| 5d960ec744 | |||
| 3b36b8ca57 | |||
| 05f14764e6 | |||
| 3a180b24e3 | |||
| 02ab58e001 | |||
| fd158b41e1 | |||
| 89e0ede12f | |||
| 4d7b2410ef | |||
| c1f6a2f755 | |||
| 9c455c3b0f | |||
| d4ea9dfd21 | |||
| 08071e6e7e | |||
| ec87174f30 | |||
| 835e5b51c9 | |||
| 07c5ef255e | |||
| 476b55c17d | |||
| 4a53cfa312 | |||
| 50ea515476 | |||
| cbd9f72bc8 | |||
| 29eaa35f4c | |||
| 97c89c39d3 | |||
| 5769791185 | |||
| 894c66d793 | |||
| 75290154b0 | |||
| b08eea76b1 | |||
| 61d83af9ea | |||
| 2d497038eb | |||
| f8a5d5561a | |||
| 2e7e68ef23 | |||
| b812f3ccde | |||
| 6da8181bbe | |||
| a51dd641c1 | |||
| 0d20164d40 | |||
| 3320532668 | |||
| bcc6492115 | |||
| c60bc8ee5b | |||
| 4eefab8ccf | |||
| 9cda7e20fb | |||
| 79d0197dcf | |||
| ba01b1e4ce | |||
| 58908f69ba | |||
| 114088b845 | |||
| 6e77b592cb | |||
| 73bc71e922 | |||
| 090529ffef | |||
| 3c291f1af9 | |||
| fc31fe4aa4 | |||
| 563f9598be | |||
| 03bc2dade9 | |||
| 09d683b706 | |||
| 523a9590b8 | |||
| 3c3188eb05 | |||
| 354062118f | |||
| 85d7390fa8 | |||
| 8509f97054 | |||
| 8d5d8b4c90 | |||
| 536ad9594e | |||
| a57bbbadf4 | |||
| 3def466ee0 | |||
| 59868c66a0 | |||
| e13eb05073 |
@@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
linux-amd64:
|
||||
name: Linux-amd64
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
@@ -80,12 +80,12 @@ jobs:
|
||||
run: cat /proc/cpuinfo
|
||||
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev directx-headers-dev
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -151,8 +151,13 @@ jobs:
|
||||
- name: install required packages
|
||||
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev libchafa-dev libddcutil-dev rpm
|
||||
|
||||
- name: install linuxbrew packages
|
||||
run: |
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
|
||||
|
||||
- name: configure project
|
||||
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --target package --verbose -j4
|
||||
@@ -654,6 +659,68 @@ jobs:
|
||||
name: fastfetch-windows-amd64
|
||||
path: ./fastfetch-windows-amd64.*
|
||||
|
||||
windows-aarch64:
|
||||
name: Windows-aarch64
|
||||
runs-on: windows-11-arm
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: setup-msys2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: CLANGARM64
|
||||
update: true
|
||||
install: git mingw-w64-clang-aarch64-7zip mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-vulkan-loader mingw-w64-clang-aarch64-vulkan-headers mingw-w64-clang-aarch64-opencl-icd mingw-w64-clang-aarch64-opencl-headers mingw-w64-clang-aarch64-cppwinrt mingw-w64-clang-aarch64-imagemagick
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
- name: configure project
|
||||
run: env PKG_CONFIG_PATH=/clangarm64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
|
||||
|
||||
- name: build project
|
||||
run: cmake --build . --verbose -j4
|
||||
|
||||
- name: copy necessary dlls
|
||||
run: cp /clangarm64/bin/{OpenCL,vulkan-1}.dll .
|
||||
|
||||
- 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: ldd fastfetch
|
||||
|
||||
- name: run tests
|
||||
run: ctest --output-on-failure
|
||||
|
||||
- name: create zip archive
|
||||
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-aarch64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: create 7z archive
|
||||
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-aarch64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
|
||||
|
||||
- name: upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: fastfetch-windows-aarch64
|
||||
path: ./fastfetch-windows-aarch64.*
|
||||
|
||||
release:
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
|
||||
name: Release
|
||||
@@ -673,6 +740,7 @@ jobs:
|
||||
- netbsd-amd64
|
||||
- sunos-amd64
|
||||
- windows-amd64
|
||||
- windows-aarch64
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
|
||||
+60
-1
@@ -1,3 +1,62 @@
|
||||
# 2.42.0
|
||||
|
||||
Changes:
|
||||
* Normalize the module name `Bios` to `BIOS` (#1721)
|
||||
* No configuration file changes are required because fastfetch parses module names case-insensitively.
|
||||
|
||||
Bugfixes:
|
||||
* Disable disk type detection for virtual disks (PhysicalDisk, Linux, #1669)
|
||||
* Fix incorrect CPU temperature reporting (CPU, OpenBSD)
|
||||
* Fix setting `logo.chafa.symbols` in JSON configuration (Logo, #1709)
|
||||
* Fix non-normalized time display (Uptime, #1720)
|
||||
* Miscellaneous minor fixes
|
||||
|
||||
Features:
|
||||
* Add CPU temperature detection support (CPU, SunOS)
|
||||
* Improve CPU frequency detection (CPU, NetBSD)
|
||||
* Add Wi-Fi detection support (Wifi, NetBSD)
|
||||
* Add Webcam detection support (Camera, OpenBSD)
|
||||
* Requires root privileges
|
||||
|
||||
Logos:
|
||||
* Remove GoralixOS logo (#1699)
|
||||
* Add Aurora logo (#1700)
|
||||
* Add Codex Linux logo (#1701)
|
||||
|
||||
# 2.41.0
|
||||
|
||||
Changes:
|
||||
* Due to [the deprecation](https://github.com/actions/runner-images/issues/11101), Linux x86_64 binaries are now built with Ubuntu 22.04 (Glibc 2.35, Debian 12)
|
||||
* You can always build fastfetch yourself on your own. Please don't report bugs related to this change.
|
||||
|
||||
Features:
|
||||
* Support physical core count detection on non-x86 platforms (CPU, Linux / FreeBSD)
|
||||
* Support CPU frequency detection on PPC64 (CPU, FreeBSD)
|
||||
* Support soar packages count detection (Packages, Linux)
|
||||
* Support `~` path expanding on Windows (Logo, Windows)
|
||||
* Support retrieving full user name (Title)
|
||||
* Exposed with `--title-format '{full-user-name}'`
|
||||
* Improve CPU (thermal zone) temperature detection on Windows (CPU, Windows)
|
||||
* Administrator privileges are no longer needed
|
||||
* Support base Wifi info detection on OpenBSD (Wifi, OpenBSD)
|
||||
* To be tested
|
||||
* Support GPU temperature detection for Intel dGPU on Linux (GPU, Linux)
|
||||
* To be tested
|
||||
* Add new ARM CPU part numbers (CPU, Linux)
|
||||
* Add base implementation of Bluetooth device detection (Bluetooth, NetBSD, #1690)
|
||||
* Some small improvements
|
||||
|
||||
Logo:
|
||||
* Add anduinos
|
||||
* Add 2 more Alpine logos
|
||||
|
||||
# 2.40.4
|
||||
|
||||
Bugfixes:
|
||||
* Fix loading presets config on Windows (Windows, #1682)
|
||||
* Regression of v2.40.0
|
||||
* Remove the prefix `v` of Hyprland version on Arch Linux (WM, Linux)
|
||||
|
||||
# 2.40.3
|
||||
|
||||
Bugfixes:
|
||||
@@ -844,7 +903,7 @@ Bugfixes:
|
||||
* Fix some presets
|
||||
* Better detection for XTerm terminal fonts (#1095, TerminalFont, Linux)
|
||||
* Remove debug output (#1097, Windows)
|
||||
* Fix command line option `--gpu-hide-type` doesn't work (#1098, GPU)
|
||||
* Fix flag `--gpu-hide-type` doesn't work (#1098, GPU)
|
||||
* Fix wrong date on Raspbian 10 (#1108, DateTime, Linux)
|
||||
* Use `brightness` instead of `actuall_brightness` when detecting current brightness level (Brightness, Linux)
|
||||
* Ref: https://bugzilla.kernel.org/show_bug.cgi?id=203905
|
||||
|
||||
+31
-7
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.40.3
|
||||
VERSION 2.42.0
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -102,7 +102,7 @@ if(NOT BINARY_LINK_TYPE IN_LIST BINARY_LINK_TYPE_OPTIONS)
|
||||
message(FATAL_ERROR "BINARY_LINK_TYPE must be one of ${BINARY_LINK_TYPE_OPTIONS}")
|
||||
endif()
|
||||
|
||||
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SORCERY WINGET XBPS)
|
||||
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SOAR SORCERY WINGET XBPS)
|
||||
foreach(package_manager ${PACKAGE_MANAGERS})
|
||||
if(package_manager STREQUAL "WINGET")
|
||||
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" ON)
|
||||
@@ -705,7 +705,7 @@ elseif(FreeBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.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
|
||||
@@ -734,7 +734,7 @@ elseif(NetBSD)
|
||||
src/common/sysctl.c
|
||||
src/detection/battery/battery_nbsd.c
|
||||
src/detection/bios/bios_nbsd.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
src/detection/bluetooth/bluetooth_bsd.c
|
||||
src/detection/bluetoothradio/bluetoothradio_nosupport.c
|
||||
src/detection/board/board_nbsd.c
|
||||
src/detection/bootmgr/bootmgr_bsd.c
|
||||
@@ -797,7 +797,7 @@ elseif(NetBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_linux.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wifi/wifi_nbsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
@@ -879,7 +879,7 @@ elseif(OpenBSD)
|
||||
src/detection/uptime/uptime_bsd.c
|
||||
src/detection/users/users_obsd.c
|
||||
src/detection/wallpaper/wallpaper_linux.c
|
||||
src/detection/wifi/wifi_nosupport.c
|
||||
src/detection/wifi/wifi_obsd.c
|
||||
src/detection/wm/wm_nosupport.c
|
||||
src/detection/de/de_linux.c
|
||||
src/detection/wmtheme/wmtheme_linux.c
|
||||
@@ -977,7 +977,6 @@ elseif(WIN32)
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_windows.c
|
||||
src/detection/cpu/cpu_windows.cpp
|
||||
src/detection/cpucache/cpucache_windows.c
|
||||
src/detection/cpuusage/cpuusage_windows.c
|
||||
src/detection/cursor/cursor_windows.c
|
||||
@@ -1589,7 +1588,15 @@ elseif(WIN32)
|
||||
PRIVATE "cfgmgr32"
|
||||
PRIVATE "winbrand"
|
||||
PRIVATE "propsys"
|
||||
PRIVATE "secur32"
|
||||
PRIVATE "pdh"
|
||||
)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
|
||||
# WoA only works on Windows 10 or higher
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "mincore"
|
||||
)
|
||||
endif()
|
||||
elseif(FreeBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "m"
|
||||
@@ -1613,6 +1620,7 @@ elseif(OpenBSD)
|
||||
)
|
||||
elseif(NetBSD)
|
||||
target_link_libraries(libfastfetch
|
||||
PRIVATE "bluetooth"
|
||||
PRIVATE "m"
|
||||
PRIVATE "prop"
|
||||
)
|
||||
@@ -1826,10 +1834,26 @@ if (BUILD_TESTS)
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
add_executable(fastfetch-test-color
|
||||
tests/color.c
|
||||
)
|
||||
target_link_libraries(fastfetch-test-color
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
add_executable(fastfetch-test-duration
|
||||
tests/duration.c
|
||||
)
|
||||
target_link_libraries(fastfetch-test-duration
|
||||
PRIVATE libfastfetch
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
|
||||
add_test(NAME test-list COMMAND fastfetch-test-list)
|
||||
add_test(NAME test-format COMMAND fastfetch-test-format)
|
||||
add_test(NAME test-color COMMAND fastfetch-test-color)
|
||||
add_test(NAME test-duration COMMAND fastfetch-test-duration)
|
||||
endif()
|
||||
|
||||
##################
|
||||
|
||||
@@ -71,6 +71,10 @@ You may also download the program directly from [the GitHub releases page](https
|
||||
|
||||
* `pkg install fastfetch`
|
||||
|
||||
### NetBSD
|
||||
|
||||
* `pkgin in fastfetch`
|
||||
|
||||
### Android (Termux)
|
||||
|
||||
* `pkg install fastfetch`
|
||||
@@ -230,6 +234,56 @@ Set the key to a white space.
|
||||
}
|
||||
```
|
||||
|
||||
### Q: How can I display images on Windows?
|
||||
|
||||
As of April 2025:
|
||||
|
||||
#### mintty and Wezterm
|
||||
|
||||
mintty (used by Bash on Windows and MSYS2) and Wezterm (nightly build only) support the iTerm image protocol on Windows.
|
||||
|
||||
In `config.jsonc`:
|
||||
```json
|
||||
{
|
||||
"logo": {
|
||||
"type": "iterm",
|
||||
"source": "C:/path/to/image.png",
|
||||
"width": <num-in-chars>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Windows Terminal
|
||||
|
||||
Windows Terminal supports the sixel image protocol only.
|
||||
|
||||
* If you installed fastfetch through MSYS2:
|
||||
1. Install imagemagick: `pacman -S mingw-w64-<subsystem>-x86_64-imagemagick`
|
||||
2. In `config.jsonc`:
|
||||
```jsonc
|
||||
{
|
||||
"logo": {
|
||||
"type": "sixel", // DO NOT USE "auto"
|
||||
"source": "C:/path/to/image.png", // Do NOT use `~` as fastfetch is a native Windows program and doesn't apply cygwin path conversion
|
||||
"width": <image-width-in-chars>, // Optional
|
||||
"height": <image-height-in-chars> // Optional
|
||||
}
|
||||
}
|
||||
```
|
||||
* If you installed fastfetch via scoop or downloaded the binary directly from the GitHub Releases page:
|
||||
1. Convert your image manually to sixel format using [any online image conversion service](https://www.google.com/search?q=convert+image+to+sixel)
|
||||
2. In `config.jsonc`:
|
||||
```jsonc
|
||||
{
|
||||
"logo": {
|
||||
"type": "raw", // DO NOT USE "auto"
|
||||
"source": "C:/path/to/image.sixel",
|
||||
"width": <image-width-in-chars>, // Required
|
||||
"height": <image-height-in-chars> // Required
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Q: I want feature A / B / C. Will fastfetch support it?
|
||||
|
||||
Fastfetch is a system information tool. We only accept hardware or system-level software feature requests. For most personal uses, I recommend using the `Command` module to implement custom functionality, which can be used to grab output from a custom shell script:
|
||||
|
||||
Vendored
+18
@@ -1,3 +1,21 @@
|
||||
fastfetch (2.41.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.41.0
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Wed, 16 Apr 2025 13:42:58 +0800
|
||||
|
||||
fastfetch (2.40.4) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.4
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Thu, 10 Apr 2025 15:38:21 +0800
|
||||
|
||||
fastfetch (2.40.3) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.3
|
||||
|
||||
-- Carter Li <zhangsongcui@live.cn> Mon, 07 Apr 2025 09:29:27 +0800
|
||||
|
||||
fastfetch (2.40.0) jammy; urgency=medium
|
||||
|
||||
* Update to 2.40.0
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.40.0_source.buildinfo universe/utils optional
|
||||
fastfetch_2.41.0_source.buildinfo universe/utils optional
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"packagesFormat": {
|
||||
"description": "Output format of the module `Packages`. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {nix-all}: Total number of all nix packages\n 43. {flatpak-all}: Total number of all flatpak app packages\n 44. {brew-all}: Total number of all brew packages\n 45. {guix-all}: Total number of all guix packages\n 46. {hpkg-all}: Total number of all hpkg packages",
|
||||
"description": "Output format of the module `Packages`. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {soar}: Number of soar packages\n 43. {nix-all}: Total number of all nix packages\n 44. {flatpak-all}: Total number of all flatpak app packages\n 45. {brew-all}: Total number of all brew packages\n 46. {guix-all}: Total number of all guix packages\n 47. {hpkg-all}: Total number of all hpkg packages",
|
||||
"type": "string"
|
||||
},
|
||||
"physicaldiskFormat": {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/init.h"
|
||||
#include "common/parsing.h"
|
||||
#include "common/thread.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
void ffInitInstance(void);
|
||||
void ffStart(void);
|
||||
void ffFinish(void);
|
||||
void ffDestroyInstance(void);
|
||||
void ffListFeatures(void);
|
||||
@@ -147,6 +147,14 @@ ssize_t ffReadFileDataRelative(HANDLE dfd, const char* fileName, size_t dataSize
|
||||
|
||||
bool ffPathExpandEnv(const char* in, FFstrbuf* out)
|
||||
{
|
||||
if (in[0] == '~') {
|
||||
if ((in[1] == '/' || in[1] == '\\' || in[1] == '\0') && !ffStrContainsC(in, '%')) {
|
||||
ffStrbufSet(out, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(out, in + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD length = ExpandEnvironmentStringsA(in, NULL, 0);
|
||||
if (length <= 1) return false;
|
||||
|
||||
|
||||
@@ -177,6 +177,7 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
|
||||
if (ffCharIsEnglishAlphabet(value[0]))
|
||||
{
|
||||
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
|
||||
else FF_APPEND_COLOR_CODE_COND(bold_, FF_COLOR_MODE_BOLD)
|
||||
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
|
||||
else FF_APPEND_COLOR_CODE_COND(dim_, FF_COLOR_MODE_DIM)
|
||||
else FF_APPEND_COLOR_CODE_COND(italic_, FF_COLOR_MODE_ITALIC)
|
||||
@@ -212,6 +213,35 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
|
||||
exit(479);
|
||||
}
|
||||
}
|
||||
else if (value[0] == '#')
|
||||
{
|
||||
// RGB color
|
||||
++value;
|
||||
char* pend = NULL;
|
||||
uint32_t rgb = (uint32_t) strtoul(value, &pend, 16);
|
||||
if (pend == value) {
|
||||
fprintf(stderr, "Error: invalid RGB color code found: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
if (pend - value > 6) {
|
||||
fprintf(stderr, "Error: RGB color code too long: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
else if (pend - value == 3) {
|
||||
rgb = ((rgb & 0xF00) >> 8) * 0x110000 +
|
||||
((rgb & 0x0F0) >> 4) * 0x001100 +
|
||||
((rgb & 0x00F) >> 0) * 0x000011;
|
||||
}
|
||||
else if (pend - value != 6) {
|
||||
fprintf(stderr, "Error: invalid RGB color code length: %s\n", value);
|
||||
exit(479);
|
||||
}
|
||||
|
||||
uint32_t r = rgb >> 16, g = (rgb >> 8) & 0xFF, b = rgb & 0xFF;
|
||||
ffStrbufAppendF(buffer, FF_COLOR_FG_RGB "%u;%u;%u", r, g, b);
|
||||
value = pend;
|
||||
continue;
|
||||
}
|
||||
ffStrbufAppendC(buffer, *value);
|
||||
++value;
|
||||
|
||||
|
||||
+15
-8
@@ -190,19 +190,26 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
|
||||
}
|
||||
}
|
||||
|
||||
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result)
|
||||
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result)
|
||||
{
|
||||
if(days == 0 && hours == 0 && minutes == 0)
|
||||
if(totalSeconds < 60)
|
||||
{
|
||||
ffStrbufAppendF(result, "%u seconds", seconds);
|
||||
ffStrbufAppendF(result, "%u second", (unsigned) totalSeconds);
|
||||
if (totalSeconds != 1)
|
||||
ffStrbufAppendC(result, 's');
|
||||
return;
|
||||
}
|
||||
|
||||
if(seconds >= 30)
|
||||
{
|
||||
minutes++;
|
||||
seconds = 0;
|
||||
}
|
||||
uint32_t seconds = totalSeconds % 60;
|
||||
totalSeconds /= 60;
|
||||
if (seconds >= 30)
|
||||
totalSeconds++;
|
||||
|
||||
uint32_t minutes = totalSeconds % 60;
|
||||
totalSeconds /= 60;
|
||||
uint32_t hours = totalSeconds % 24;
|
||||
totalSeconds /= 24;
|
||||
uint32_t days = (uint32_t) totalSeconds;
|
||||
|
||||
if(days > 0)
|
||||
{
|
||||
|
||||
@@ -27,4 +27,4 @@ int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
|
||||
|
||||
void ffParseSize(uint64_t bytes, FFstrbuf* result);
|
||||
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result);
|
||||
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result);
|
||||
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/printing.h"
|
||||
#include "logo/logo.h"
|
||||
#include "util/textModifier.h"
|
||||
|
||||
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType)
|
||||
@@ -99,7 +100,7 @@ void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleAr
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
|
||||
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
if(!instance.config.display.showErrors)
|
||||
return;
|
||||
@@ -109,7 +110,10 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
vprintf(message, arguments);
|
||||
va_end(arguments);
|
||||
|
||||
if(!instance.config.display.pipe)
|
||||
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
|
||||
@@ -117,14 +121,6 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
|
||||
{
|
||||
va_list arguments;
|
||||
va_start(arguments, message);
|
||||
printError(moduleName, moduleIndex, moduleArgs, printType, message, arguments);
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
void ffPrintColor(const FFstrbuf* colorValue)
|
||||
{
|
||||
//If the color is not set, this would reset in \033[m, which resets everything.
|
||||
|
||||
@@ -130,7 +130,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
switch (GetLastError())
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
if (!timeout || WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
|
||||
#if __aarch64__
|
||||
if (!GetOverlappedResultEx(hChildPipeRead, &overlapped, &nRead, timeout < 0 ? INFINITE : (DWORD) timeout, FALSE))
|
||||
#else
|
||||
// To support Windows 7
|
||||
if (timeout >= 0 && WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
|
||||
{
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
@@ -138,13 +142,18 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
|
||||
}
|
||||
|
||||
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
|
||||
#endif
|
||||
{
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
return NULL;
|
||||
|
||||
CancelIo(hChildPipeRead);
|
||||
TerminateProcess(hProcess, 1);
|
||||
return "GetOverlappedResult(hChildPipeRead) failed";
|
||||
return "GetOverlappedResult"
|
||||
#if __aarch64__
|
||||
"Ex"
|
||||
#endif
|
||||
"(hChildPipeRead) failed";
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -6,7 +6,13 @@
|
||||
static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFlist* devices)
|
||||
{
|
||||
FFBluetoothResult* device = ffListAdd(devices);
|
||||
ffStrbufInitS(&device->name, bt_devremote_name_gen(dev->devname, &dev->bdaddr));
|
||||
ffStrbufInitS(&device->name,
|
||||
#if __FreeBSD__
|
||||
bt_devremote_name_gen(dev->devname, &dev->bdaddr)
|
||||
#else
|
||||
dev->devname
|
||||
#endif
|
||||
);
|
||||
ffStrbufInitS(&device->address, bt_ntoa(&dev->bdaddr, NULL));
|
||||
ffStrbufUpperCase(&device->address);
|
||||
ffStrbufInit(&device->type);
|
||||
|
||||
@@ -232,7 +232,7 @@ static uint32_t connectedDevices(void)
|
||||
|
||||
#endif
|
||||
|
||||
const char* ffDetectBluetooth(FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
|
||||
{
|
||||
#ifdef FF_HAVE_DBUS
|
||||
int32_t connectedCount = -1;
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#if FF_HAVE_LINUX_VIDEODEV2
|
||||
#include <linux/videodev2.h>
|
||||
#elif __has_include(<sys/videoio.h>) // OpenBSD
|
||||
#include <sys/videoio.h>
|
||||
#define FF_HAVE_LINUX_VIDEODEV2 1
|
||||
#endif
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
@@ -19,7 +22,13 @@ const char* ffDetectCamera(FFlist* result)
|
||||
path[ARRAY_SIZE(path) - 2] = (char) (i + '0');
|
||||
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
break;
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
break;
|
||||
if (errno == ENXIO)
|
||||
continue;
|
||||
return "Failed to open /dev/videoN";
|
||||
}
|
||||
|
||||
struct v4l2_capability cap = {};
|
||||
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
|
||||
@@ -106,9 +106,14 @@ static const char* armPartId2name(uint32_t partId)
|
||||
case 0xd80: return "Cortex-A520";
|
||||
case 0xd81: return "Cortex-A720";
|
||||
case 0xd82: return "Cortex-X4";
|
||||
case 0xd83: return "Neoverse-V3AE";
|
||||
case 0xd84: return "Neoverse-V3";
|
||||
case 0xd85: return "Cortex-X925";
|
||||
case 0xd87: return "Cortex-A725";
|
||||
case 0xd88: return "Cortex-A520AE";
|
||||
case 0xd89: return "Cortex-A720AE";
|
||||
case 0xd8e: return "Neoverse-N3";
|
||||
case 0xd8f: return "Cortex-A320";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@@ -314,6 +319,7 @@ static const char* fujitsuPartId2name(uint32_t partId)
|
||||
switch (partId)
|
||||
{
|
||||
case 0x001: return "A64FX";
|
||||
case 0x003: return "MONAKA";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+65
-21
@@ -1,5 +1,6 @@
|
||||
#include "cpu.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#if __has_include(<sys/cpuset.h>)
|
||||
@@ -34,35 +35,60 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (ffSysctlGetString("hw.model", &cpu->name) != NULL)
|
||||
return "sysctlbyname(hw.model) failed";
|
||||
|
||||
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||
cpu->coresLogical = cpu->coresPhysical;
|
||||
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
|
||||
cpu->coresPhysical = 0;
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("kern.smp.cpus", cpu->coresLogical);
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0)
|
||||
{
|
||||
// <groups>
|
||||
// <group level="1" cache-level="3">
|
||||
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
|
||||
// <children>
|
||||
// <group level="2" cache-level="2">
|
||||
// <cpu count="2" mask="3,0,0,0">0, 1</cpu>
|
||||
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
|
||||
// </group>
|
||||
// <group level="2" cache-level="2">
|
||||
// <cpu count="2" mask="c,0,0,0">2, 3</cpu>
|
||||
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
|
||||
// </group>
|
||||
// </children>
|
||||
// </group>
|
||||
// <group level="1" cache-level="3">
|
||||
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
|
||||
// <children>
|
||||
// <group level="2" cache-level="2">
|
||||
// <cpu count="2" mask="3,0,0,0">0, 1</cpu>
|
||||
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
|
||||
// </group>
|
||||
// <group level="2" cache-level="2">
|
||||
// <cpu count="2" mask="c,0,0,0">2, 3</cpu>
|
||||
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
|
||||
// </group>
|
||||
// </children>
|
||||
// </group>
|
||||
// </groups>
|
||||
uint32_t i = 0;
|
||||
while (true)
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
bool inLvl2 = false, threadGroup = false;
|
||||
uint32_t cpuCount = 0;
|
||||
while (ffStrbufGetline(&line, &len, &buffer))
|
||||
{
|
||||
i = ffStrbufNextIndexS(&buffer, i, "<flag name=\"THREAD\">THREAD group</flag>"); // Find physical core with hyper-threading enabled
|
||||
if (i >= buffer.length) break;
|
||||
cpu->coresPhysical--;
|
||||
i += (uint32_t) strlen("<flag name=\"THREAD\">THREAD group</flag>");
|
||||
if (!inLvl2)
|
||||
{
|
||||
if (ffStrStartsWith(line, " <group level=\"2\""))
|
||||
{
|
||||
inLvl2 = true;
|
||||
cpuCount = 0;
|
||||
threadGroup = false;
|
||||
}
|
||||
else if (ffStrStartsWith(line, " <group level=\"1\""))
|
||||
cpu->packages++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ffStrEquals(line, " </group>"))
|
||||
{
|
||||
cpu->coresPhysical += threadGroup ? 1 : cpuCount;
|
||||
inLvl2 = false;
|
||||
}
|
||||
else if (cpuCount == 0 && ffStrStartsWith(line, " <cpu count=\""))
|
||||
cpuCount = (uint32_t) strtoul(line + strlen(" <cpu count=\""), NULL, 10);
|
||||
else if (cpuCount > 0 && ffStrStartsWith(line, " <flags>"))
|
||||
{
|
||||
if (ffStrContains(line, "<flag name=\"THREAD\">THREAD group</flag>"))
|
||||
threadGroup = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +105,24 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
uint32_t clockrate = (uint32_t) ffSysctlGetInt("hw.clockrate", 0);
|
||||
if (clockrate > cpu->frequencyBase) cpu->frequencyBase = clockrate;
|
||||
|
||||
for (uint16_t i = 0; i < cpu->coresLogical; ++i)
|
||||
{
|
||||
ffStrbufClear(&buffer);
|
||||
char key[32];
|
||||
snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i);
|
||||
if (ffSysctlGetString(key, &buffer) == NULL)
|
||||
{
|
||||
if (buffer.length == 0) continue;
|
||||
|
||||
// MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000
|
||||
uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10);
|
||||
if (cpu->frequencyMax < fmax) cpu->frequencyMax = fmax;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
if (options->temp)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define FF_CPUINFO_PATH "/proc/cpuinfo"
|
||||
|
||||
@@ -432,11 +433,11 @@ FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo)
|
||||
{
|
||||
p += strlen("\nphysical id\t:");
|
||||
char* pend;
|
||||
unsigned long id = strtoul(p, &pend, 10);
|
||||
unsigned long long id = strtoul(p, &pend, 10);
|
||||
if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist?
|
||||
high |= 1 << (id - 64);
|
||||
high |= 1ULL << (id - 64);
|
||||
else
|
||||
low |= 1 << id;
|
||||
low |= 1ULL << id;
|
||||
p = pend;
|
||||
}
|
||||
|
||||
@@ -458,9 +459,7 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
cpu->packages = getPackageCount(&cpuinfo);
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 0); // physical cores in single package
|
||||
if (cpu->coresPhysical == 0)
|
||||
cpu->coresPhysical = cpu->coresLogical;
|
||||
else if (cpu->packages > 1)
|
||||
if (cpu->coresPhysical > 0 && cpu->packages > 1)
|
||||
cpu->coresPhysical *= cpu->packages;
|
||||
|
||||
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
|
||||
@@ -473,6 +472,82 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
|
||||
|
||||
#else
|
||||
|
||||
static const char* detectPhysicalCores(FFCPUResult* cpu)
|
||||
{
|
||||
int dfd = open("/sys/devices/system/cpu/", O_RDONLY | O_DIRECTORY);
|
||||
if (dfd < 0) return "open(\"/sys/devices/system/cpu/\") failed";
|
||||
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = fdopendir(dfd);
|
||||
if (!dir) return "fdopendir(dfd) failed";
|
||||
|
||||
uint64_t pkgLow = 0, pkgHigh = 0;
|
||||
|
||||
struct dirent* entry;
|
||||
FF_LIST_AUTO_DESTROY cpuList = ffListCreate(sizeof(uint32_t));
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if (entry->d_type != DT_DIR || !ffStrStartsWith(entry->d_name, "cpu") || !ffCharIsDigit(entry->d_name[strlen("cpu")]))
|
||||
continue;
|
||||
|
||||
FF_AUTO_CLOSE_FD int cpuxfd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_DIRECTORY);
|
||||
if (cpuxfd < 0)
|
||||
continue;
|
||||
|
||||
char buf[128];
|
||||
|
||||
// Check if the directory contains a file named "topology/physical_package_id"
|
||||
// that lists the physical package id of the CPU.
|
||||
|
||||
ssize_t len = ffReadFileDataRelative(cpuxfd, "topology/physical_package_id", sizeof(buf) - 1, buf);
|
||||
if (len > 0)
|
||||
{
|
||||
buf[len] = '\0';
|
||||
unsigned long long id = strtoul(buf, NULL, 10);
|
||||
if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist?
|
||||
pkgHigh |= 1ULL << (id - 64);
|
||||
else
|
||||
pkgLow |= 1ULL << id;
|
||||
}
|
||||
|
||||
// Check if the directory contains a file named "topology/core_cpus_list"
|
||||
// that lists the physical cores in the package.
|
||||
|
||||
len = ffReadFileDataRelative(cpuxfd, "topology/core_cpus_list", sizeof(buf) - 1, buf);
|
||||
if (len > 0)
|
||||
{
|
||||
buf[len] = '\0'; // low-high or low
|
||||
|
||||
for (const char* p = buf; *p;)
|
||||
{
|
||||
char* pend;
|
||||
uint32_t coreId = (uint32_t) strtoul(p, &pend, 10);
|
||||
if (pend == p) break;
|
||||
|
||||
bool found = false;
|
||||
FF_LIST_FOR_EACH(uint32_t, id, cpuList)
|
||||
{
|
||||
if (*id == coreId)
|
||||
{
|
||||
// This core is already counted
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
*(uint32_t*) ffListAdd(&cpuList) = coreId;
|
||||
|
||||
p = strchr(pend, ',');
|
||||
if (!p) break;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpu->coresPhysical = (uint16_t) cpuList.length;
|
||||
cpu->packages = (uint16_t) (__builtin_popcountll(pkgLow) + __builtin_popcountll(pkgHigh));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa)
|
||||
{
|
||||
// Always use the last part of the ISA string. Ref: #590 #1204
|
||||
@@ -601,7 +676,7 @@ FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const c
|
||||
|
||||
FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
cpu->coresPhysical = cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresLogical = (uint16_t) get_nprocs_conf();
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
|
||||
#if __ANDROID__
|
||||
@@ -663,6 +738,9 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cpu->coresPhysical == 0)
|
||||
detectPhysicalCores(cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -67,6 +67,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
|
||||
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
|
||||
if (freq == 0) freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
|
||||
if (freq == 0) freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
|
||||
if (freq > cpu->frequencyBase) cpu->frequencyBase = freq;
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
@@ -1,10 +1,53 @@
|
||||
#include "cpu.h"
|
||||
#include "common/sysctl.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/sensors.h>
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
static const char* detectCPUTemp(FFCPUResult* cpu)
|
||||
{
|
||||
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
|
||||
|
||||
for (mib[2] = 0; mib[2] < 1024; mib[2]++)
|
||||
{
|
||||
struct sensordev sensordev;
|
||||
size_t sdlen = sizeof(struct sensordev);
|
||||
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
break;
|
||||
if (errno == ENXIO)
|
||||
continue;
|
||||
return "sysctl(sensordev) failed";
|
||||
}
|
||||
|
||||
if (!ffStrStartsWith(sensordev.xname, "cpu"))
|
||||
continue;
|
||||
|
||||
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
|
||||
{
|
||||
struct sensor sensor;
|
||||
size_t slen = sizeof(struct sensor);
|
||||
if (sysctl(mib, 5, &sensor, &slen, NULL, 0) < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return "sysctl(sensor) failed";
|
||||
continue;
|
||||
}
|
||||
if (sensor.flags & SENSOR_FINVALID)
|
||||
continue;
|
||||
|
||||
cpu->temperature = (double)(sensor.value - 273150000) / 1E6;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return "No sensor for CPU temp found";
|
||||
}
|
||||
|
||||
const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name))
|
||||
return "sysctl(hw.model) failed";
|
||||
@@ -19,13 +62,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
|
||||
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
if (options->temp)
|
||||
{
|
||||
struct sensor sensors;
|
||||
size_t size = sizeof(sensors);
|
||||
if (sysctl((int[]) {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0}, 5, &sensors, &size, NULL, 0) == 0)
|
||||
cpu->temperature = (double) (sensors.value - 273150000) / 1E6;
|
||||
}
|
||||
if (options->temp) detectCPUTemp(cpu);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,59 @@
|
||||
#include "cpu.h"
|
||||
#include "common/processing.h"
|
||||
#include <kstat.h>
|
||||
|
||||
static const char* detectCPUTempByKstat(kstat_ctl_t* kc, FFCPUResult* cpu)
|
||||
{
|
||||
const char* possibleModules[] = {"temperature", "cpu_temp", "acpi_thermal", NULL};
|
||||
|
||||
for (int i = 0; possibleModules[i] != NULL; i++) {
|
||||
kstat_t* ks = kstat_lookup(kc, possibleModules[i], -1, NULL);
|
||||
if (ks && kstat_read(kc, ks, NULL) >= 0) {
|
||||
kstat_named_t* kn = kstat_data_lookup(ks, "temperature");
|
||||
if (kn) {
|
||||
switch (kn->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
cpu->temperature = (float)kn->value.i32;
|
||||
return NULL;
|
||||
case KSTAT_DATA_UINT32:
|
||||
cpu->temperature = (float)kn->value.ui32;
|
||||
return NULL;
|
||||
case KSTAT_DATA_FLOAT:
|
||||
cpu->temperature = kn->value.f;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "Failed to find CPU temperature using kstat";
|
||||
}
|
||||
|
||||
static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]){
|
||||
"ipmitool",
|
||||
"-c",
|
||||
"sdr",
|
||||
"list",
|
||||
NULL
|
||||
});
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
char* line = NULL;
|
||||
size_t len = 0;
|
||||
while (ffStrbufGetline(&line, &len, &buffer))
|
||||
{
|
||||
if (sscanf(line, "CPU%*d Temp,%lf,degrees C,ok", &cpu->temperature) == 1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "ipmitool sdr list failed to find CPU temperature";
|
||||
}
|
||||
|
||||
static inline void kstatFreeWrap(kstat_ctl_t** pkc)
|
||||
{
|
||||
assert(pkc);
|
||||
@@ -8,7 +61,7 @@ static inline void kstatFreeWrap(kstat_ctl_t** pkc)
|
||||
kstat_close(*pkc);
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
__attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open();
|
||||
if (!kc)
|
||||
@@ -43,5 +96,11 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
|
||||
if (kn) cpu->coresLogical = cpu->coresPhysical = cpu->coresOnline = (uint16_t) kn->value.ui32;
|
||||
}
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
if (detectCPUTempByKstat(kc, cpu) != NULL)
|
||||
detectCPUTempByIpmiTool(cpu);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,46 @@
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
#include <pdh.h>
|
||||
|
||||
static void ffPdhOpenCloseQuery(HQUERY* query)
|
||||
{
|
||||
assert(query);
|
||||
if (*query)
|
||||
{
|
||||
PdhCloseQuery(*query);
|
||||
*query = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* detectThermalTemp(double* result)
|
||||
{
|
||||
// typeperf.exe -sc 1 "\Thermal Zone Information(*)\Temperature"
|
||||
|
||||
__attribute__((__cleanup__(ffPdhOpenCloseQuery))) HQUERY query = NULL;
|
||||
|
||||
if (PdhOpenQuery(NULL, 0, &query) != ERROR_SUCCESS)
|
||||
return "Failed to open PDH query";
|
||||
|
||||
HCOUNTER counter = NULL;
|
||||
if (PdhAddEnglishCounter(query,
|
||||
L"\\Thermal Zone Information(*)\\Temperature",
|
||||
0,
|
||||
&counter) != ERROR_SUCCESS)
|
||||
return "Failed to add TZI temperature counter";
|
||||
|
||||
if (PdhCollectQueryData(query) != ERROR_SUCCESS)
|
||||
return "Failed to collect query data";
|
||||
|
||||
PDH_FMT_COUNTERVALUE value;
|
||||
if (PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, NULL, &value) != ERROR_SUCCESS)
|
||||
return "Failed to format counter value";
|
||||
|
||||
*result = value.doubleValue - 273;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 7.5
|
||||
typedef struct FFSmbiosProcessorInfo
|
||||
{
|
||||
@@ -165,8 +205,6 @@ static const char* detectCoreTypes(FFCPUResult* cpu)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* detectThermalTemp(double* current, double* critical);
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
detectNCores(cpu);
|
||||
@@ -182,7 +220,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
|
||||
if(options->temp)
|
||||
detectThermalTemp(&cpu->temperature, NULL);
|
||||
detectThermalTemp(&cpu->temperature);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#include "util/windows/wmi.hpp"
|
||||
|
||||
extern "C"
|
||||
const char* detectThermalTemp(double* current, double* critical)
|
||||
{
|
||||
// Requires Administrator privileges
|
||||
// https://wutils.com/wmi/root/wmi/msacpi_thermalzonetemperature/#properties
|
||||
FFWmiQuery query(L"SELECT CurrentTemperature, CriticalTripPoint FROM MSAcpi_ThermalZoneTemperature WHERE Active = TRUE", nullptr, FFWmiNamespace::WMI);
|
||||
if(!query)
|
||||
return "Query WMI service failed";
|
||||
|
||||
if(FFWmiRecord record = query.next())
|
||||
{
|
||||
if (current)
|
||||
{
|
||||
if(auto vtCurrent = record.get(L"CurrentTemperature"))
|
||||
*current = vtCurrent.get<int32_t>() / 10 - 273.15; // In tenth of degrees Kelvin
|
||||
else
|
||||
*current = 0.0/0.0;
|
||||
}
|
||||
|
||||
if (critical)
|
||||
{
|
||||
if(auto vtCritical = record.get(L"CriticalTripPoint"))
|
||||
*critical = vtCritical.get<int32_t>() / 10 - 273.15; // In tenth of degrees Kelvin
|
||||
else
|
||||
*critical = 0.0/0.0;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return "No WMI result returned";
|
||||
}
|
||||
@@ -228,7 +228,7 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
|
||||
}
|
||||
}
|
||||
|
||||
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey)
|
||||
static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey)
|
||||
{
|
||||
// Works for Intel GPUs
|
||||
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
|
||||
@@ -238,12 +238,46 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf*
|
||||
|
||||
if (!drmKey) return;
|
||||
|
||||
if (ffStrbufEqualS(&gpu->driver, "xe"))
|
||||
const uint32_t pciDirLen = pciDir->length;
|
||||
|
||||
bool isXE = ffStrbufEqualS(&gpu->driver, "xe");
|
||||
if (isXE)
|
||||
ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq");
|
||||
else
|
||||
ffStrbufAppendF(pciDir, "/drm/%s/gt_max_freq_mhz", drmKey);
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
|
||||
if (options->temp)
|
||||
{
|
||||
ffStrbufAppendS(pciDir, "/hwmon/");
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
|
||||
if (dirp)
|
||||
{
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (entry->d_name[0] == '.') continue;
|
||||
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen + strlen("/hwmon/"));
|
||||
ffStrbufAppendS(pciDir, entry->d_name);
|
||||
// https://github.com/Syllo/nvtop/blob/73291884d926445e499d6b9b71cb7a9bdbc7c393/src/extract_gpuinfo_intel.c#L279-L281
|
||||
ffStrbufAppendS(pciDir, isXE ? "/temp2_input" : "/temp1_input");
|
||||
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
{
|
||||
uint64_t value = ffStrbufToUInt(buffer, 0);
|
||||
if (value > 0)
|
||||
{
|
||||
gpu->temperature = (double) value / 1000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(pciDir, pciDirLen);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
|
||||
@@ -500,7 +534,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
{
|
||||
pciDetectIntelSpecific(gpu, deviceDir, buffer, drmKey);
|
||||
pciDetectIntelSpecific(options, gpu, deviceDir, buffer, drmKey);
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
if (options->driverSpecific && drmKey)
|
||||
drmDetectIntelSpecific(gpu, drmKey, buffer);
|
||||
|
||||
@@ -4,60 +4,46 @@
|
||||
#include "common/netif/netif.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <net/if.h>
|
||||
|
||||
static void getData(FFstrbuf* buffer, const char* ifName, bool isDefaultRoute, FFstrbuf* path, FFlist* result)
|
||||
static void getData(FFstrbuf* buffer, const char* ifName, bool isDefaultRoute, int basefd, FFlist* result)
|
||||
{
|
||||
ffStrbufSetF(path, "/sys/class/net/%s/operstate", ifName);
|
||||
if(!ffReadFileBuffer(path->chars, buffer) || !ffStrbufEqualS(buffer, "up\n"))
|
||||
FF_AUTO_CLOSE_FD int dfd = openat(basefd, ifName, O_RDONLY | O_DIRECTORY);
|
||||
if (dfd < 0)
|
||||
return;
|
||||
|
||||
char operstate;
|
||||
if(!ffReadFileDataRelative(dfd, "operstate", 1, &operstate) || operstate != 'u' /* up or unknown */)
|
||||
return;
|
||||
|
||||
FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&counters->name, ifName);
|
||||
counters->defaultRoute = isDefaultRoute;
|
||||
|
||||
ffStrbufSetF(path, "/sys/class/net/%s/statistics/", ifName);
|
||||
uint32_t statLen = path->length;
|
||||
|
||||
ffStrbufAppendS(path, "rx_bytes");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/rx_bytes", buffer))
|
||||
counters->rxBytes = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_bytes");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/tx_bytes", buffer))
|
||||
counters->txBytes = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "rx_packets");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/rx_packets", buffer))
|
||||
counters->rxPackets = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_packets");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/tx_packets", buffer))
|
||||
counters->txPackets = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "rx_errors");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/rx_errors", buffer))
|
||||
counters->rxErrors = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_errors");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/tx_errors", buffer))
|
||||
counters->txErrors = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "rx_dropped");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/rx_dropped", buffer))
|
||||
counters->rxDrops = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
|
||||
ffStrbufAppendS(path, "tx_dropped");
|
||||
if (ffReadFileBuffer(path->chars, buffer))
|
||||
if (ffReadFileBufferRelative(dfd, "statistics/tx_dropped", buffer))
|
||||
counters->txDrops = ffStrbufToUInt(buffer, 0);
|
||||
ffStrbufSubstrBefore(path, statLen);
|
||||
}
|
||||
|
||||
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
@@ -65,7 +51,6 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net");
|
||||
if (!dirp) return "opendir(\"/sys/class/net\") == NULL";
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName();
|
||||
@@ -75,7 +60,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
if (options->namePrefix.length && strncmp(defaultRouteIfName, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
return NULL;
|
||||
|
||||
getData(&buffer, defaultRouteIfName, true, &path, result);
|
||||
getData(&buffer, defaultRouteIfName, true, dirfd(dirp), result);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -89,7 +74,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
|
||||
if (options->namePrefix.length && strncmp(ifName, options->namePrefix.chars, options->namePrefix.length) != 0)
|
||||
continue;
|
||||
|
||||
getData(&buffer, ifName, ffStrEquals(ifName, defaultRouteIfName), &path, result);
|
||||
getData(&buffer, ifName, ffStrEquals(ifName, defaultRouteIfName), dirfd(dirp), result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ typedef struct FFPackagesResult
|
||||
uint32_t rpm;
|
||||
uint32_t scoop;
|
||||
uint32_t snap;
|
||||
uint32_t soar;
|
||||
uint32_t sorcery;
|
||||
uint32_t winget;
|
||||
uint32_t xbps;
|
||||
|
||||
@@ -682,4 +682,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT))
|
||||
result->amUser = getAMUser();
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_SOAR_BIT))
|
||||
result->soar += getSQLite3Int(&baseDir, ".local/share/soar/db/soar.db", "SELECT COUNT(DISTINCT pkg_id || pkg_name) FROM packages WHERE is_installed = true", "soar");
|
||||
}
|
||||
|
||||
@@ -78,10 +78,18 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
|
||||
ffStrbufInitMove(&device->name, &name);
|
||||
ffStrbufInitF(&device->devPath, "/dev/%s", devName);
|
||||
|
||||
bool isVirtual = false;
|
||||
{
|
||||
ffStrbufInit(&device->interconnect);
|
||||
if (ffStrStartsWith(devName, "nvme"))
|
||||
ffStrbufSetStatic(&device->interconnect, "NVMe");
|
||||
else if (ffStrStartsWith(devName, "mmcblk"))
|
||||
ffStrbufSetStatic(&device->interconnect, "MMC");
|
||||
else if (ffStrStartsWith(devName, "md"))
|
||||
{
|
||||
ffStrbufSetStatic(&device->interconnect, "RAID");
|
||||
isVirtual = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
char pathSysDeviceLink[64];
|
||||
@@ -97,6 +105,11 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
|
||||
ffStrbufSetStatic(&device->interconnect, "SCSI");
|
||||
else if (strstr(pathSysDeviceReal, "/nvme") != NULL)
|
||||
ffStrbufSetStatic(&device->interconnect, "NVMe");
|
||||
else if (strstr(pathSysDeviceReal, "/virtio") != NULL)
|
||||
{
|
||||
ffStrbufSetStatic(&device->interconnect, "Virtual");
|
||||
isVirtual = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect))
|
||||
@@ -106,6 +119,7 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
|
||||
}
|
||||
}
|
||||
|
||||
if (!isVirtual)
|
||||
{
|
||||
char isRotationalChar = '1';
|
||||
if (ffReadFileDataRelative(dfd, "queue/rotational", 1, &isRotationalChar) > 0)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include "uptime.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#include <sysinfoapi.h>
|
||||
#include <realtimeapiset.h>
|
||||
|
||||
const char* ffDetectUptime(FFUptimeResult* result)
|
||||
{
|
||||
result->uptime = GetTickCount64();
|
||||
// According to MSDN, this function only fails if it's called with NULL
|
||||
QueryUnbiasedInterruptTime(&result->uptime);
|
||||
result->uptime /= 10000; // Convert from 100-nanosecond intervals to milliseconds
|
||||
result->bootTime = ffTimeGetNow() - result->uptime;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,11 @@
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
@@ -21,6 +17,7 @@ const char* ffDetectWifi(FFlist* result)
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0) {
|
||||
if_freenameindex(infs);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
@@ -86,22 +83,23 @@ const char* ffDetectWifi(FFlist* result)
|
||||
item->conn.channel = curchan.ic_ieee;
|
||||
item->conn.frequency = curchan.ic_freq;
|
||||
|
||||
if (IEEE80211_IS_CHAN_FHSS(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
|
||||
if (IEEE80211_IS_CHAN_A(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
if (IEEE80211_IS_CHAN_B(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
|
||||
if (IEEE80211_IS_CHAN_ANYG(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
if (IEEE80211_IS_CHAN_HT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
if (IEEE80211_IS_CHAN_VHT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
#ifdef IEEE80211_IS_CHAN_HE // for future use
|
||||
if (IEEE80211_IS_CHAN_HE(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
|
||||
else
|
||||
#endif
|
||||
if (IEEE80211_IS_CHAN_VHT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
else if (IEEE80211_IS_CHAN_HT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
else if (IEEE80211_IS_CHAN_ANYG(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
else if (IEEE80211_IS_CHAN_B(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
|
||||
else if (IEEE80211_IS_CHAN_A(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
else if (IEEE80211_IS_CHAN_FHSS(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
|
||||
}
|
||||
|
||||
union {
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
#include "wifi.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define COMPAT_FREEBSD_NET80211 1
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net80211/ieee80211.h>
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
|
||||
// ieee80211 header of NetBSD is full of mess. Add compatibility macros from FreeBSD
|
||||
#undef IEEE80211_IS_CHAN_ANYG
|
||||
#define IEEE80211_IS_CHAN_ANYG(x) (IEEE80211_IS_CHAN_PUREG(x) || IEEE80211_IS_CHAN_G(x))
|
||||
#undef IEEE80211_IS_CHAN_HT
|
||||
#define IEEE80211_IS_CHAN_HT(x) (((x)->ic_flags & IEEE80211_CHAN_HT) != 0)
|
||||
#undef IEEE80211_IS_CHAN_VHT
|
||||
#define IEEE80211_IS_CHAN_VHT(x) (((x)->ic_flags & IEEE80211_CHAN_VHT) != 0)
|
||||
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
struct if_nameindex* infs = if_nameindex();
|
||||
if(!infs) {
|
||||
return "if_nameindex() failed";
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0) {
|
||||
if_freenameindex(infs);
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
|
||||
{
|
||||
if (!ffStrStartsWith(i->if_name, "iwm")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&item->inf.description, i->if_name);
|
||||
ffStrbufInit(&item->inf.status);
|
||||
ffStrbufInit(&item->conn.status);
|
||||
ffStrbufInit(&item->conn.ssid);
|
||||
ffStrbufInit(&item->conn.bssid);
|
||||
ffStrbufInit(&item->conn.protocol);
|
||||
ffStrbufInit(&item->conn.security);
|
||||
item->conn.signalQuality = 0.0/0.0;
|
||||
item->conn.rxRate = 0.0/0.0;
|
||||
item->conn.txRate = 0.0/0.0;
|
||||
item->conn.channel = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
char ssid[IEEE80211_NWID_LEN + 1] = {};
|
||||
struct ieee80211req ireq = {};
|
||||
strlcpy(ireq.i_name, i->if_name, sizeof(ireq.i_name));
|
||||
ireq.i_type = IEEE80211_IOC_SSID;
|
||||
ireq.i_data = ssid;
|
||||
ireq.i_len = sizeof(ssid) - 1;
|
||||
|
||||
if (ioctl(sock, SIOCG80211, &ireq) < 0 || ireq.i_len == 0) {
|
||||
struct ifreq ifr;
|
||||
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
ffStrbufSetStatic(&item->inf.status, "Unknown");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
|
||||
}
|
||||
ffStrbufAppendS(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSetStatic(&item->inf.status, "Up");
|
||||
ffStrbufSetStatic(&item->conn.status, "Associated");
|
||||
ffStrbufAppendNS(&item->conn.ssid, ireq.i_len, ssid);
|
||||
|
||||
uint8_t bssid[IEEE80211_ADDR_LEN] = {};
|
||||
ireq.i_type = IEEE80211_IOC_BSSID;
|
||||
ireq.i_data = bssid;
|
||||
ireq.i_len = sizeof(bssid);
|
||||
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
|
||||
}
|
||||
|
||||
struct ieee80211_channel curchan = {};
|
||||
ireq.i_type = IEEE80211_IOC_CHANNEL;
|
||||
ireq.i_data = &curchan;
|
||||
ireq.i_len = sizeof(curchan);
|
||||
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
// item->conn.channel = curchan.ic_ieee; // No ic_ieee in NetBSD
|
||||
item->conn.channel = ffWifiFreqToChannel(curchan.ic_freq);
|
||||
item->conn.frequency = curchan.ic_freq;
|
||||
|
||||
#ifdef IEEE80211_IS_CHAN_HE // for future use
|
||||
if (IEEE80211_IS_CHAN_HE(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
|
||||
else
|
||||
#endif
|
||||
if (IEEE80211_IS_CHAN_VHT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
else if (IEEE80211_IS_CHAN_HT(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
else if (IEEE80211_IS_CHAN_ANYG(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
else if (IEEE80211_IS_CHAN_B(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
|
||||
else if (IEEE80211_IS_CHAN_A(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
else if (IEEE80211_IS_CHAN_FHSS(&curchan))
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
|
||||
}
|
||||
|
||||
union {
|
||||
struct ieee80211req_sta_req req;
|
||||
uint8_t buf[1024];
|
||||
} stareq = {};
|
||||
memcpy(stareq.req.is_u.macaddr, bssid, sizeof(bssid));
|
||||
ireq.i_type = IEEE80211_IOC_STA_INFO;
|
||||
ireq.i_data = &stareq;
|
||||
ireq.i_len = sizeof(stareq);
|
||||
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
struct ieee80211req_sta_info* sta = stareq.req.info;
|
||||
if (sta->isi_len != 0) {
|
||||
int8_t rssi = (int8_t) sta->isi_rssi; // Strangely, `sta->isi_rssi` is unsigned
|
||||
item->conn.signalQuality = (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2);
|
||||
|
||||
if (sta->isi_txrate) {
|
||||
item->conn.txRate = (double)sta->isi_txrate / 2.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ireq.i_type = IEEE80211_IOC_AUTHMODE;
|
||||
ireq.i_data = NULL;
|
||||
ireq.i_len = 0;
|
||||
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
|
||||
switch (ireq.i_val) {
|
||||
case IEEE80211_AUTH_NONE:
|
||||
ffStrbufSetStatic(&item->conn.security, "Insecure");
|
||||
break;
|
||||
case IEEE80211_AUTH_OPEN:
|
||||
ffStrbufSetStatic(&item->conn.security, "Open");
|
||||
break;
|
||||
case IEEE80211_AUTH_SHARED:
|
||||
ffStrbufSetStatic(&item->conn.security, "Shared");
|
||||
break;
|
||||
case IEEE80211_AUTH_8021X:
|
||||
ffStrbufSetStatic(&item->conn.security, "8021X");
|
||||
break;
|
||||
case IEEE80211_AUTH_AUTO:
|
||||
ffStrbufSetStatic(&item->conn.security, "Auto");
|
||||
break;
|
||||
case IEEE80211_AUTH_WPA:
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA");
|
||||
break;
|
||||
default:
|
||||
ffStrbufSetF(&item->conn.security, "Unknown (%d)", ireq.i_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if_freenameindex(infs);
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "wifi.h"
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net80211/ieee80211.h>
|
||||
#include <net80211/ieee80211_ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char* ffDetectWifi(FFlist* result)
|
||||
{
|
||||
struct if_nameindex* infs = if_nameindex();
|
||||
if(!infs) {
|
||||
return "if_nameindex() failed";
|
||||
}
|
||||
|
||||
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0) {
|
||||
return "socket() failed";
|
||||
}
|
||||
|
||||
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
|
||||
{
|
||||
if (!ffStrStartsWith(i->if_name, "iwm")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
|
||||
ffStrbufInitS(&item->inf.description, i->if_name);
|
||||
ffStrbufInit(&item->inf.status);
|
||||
ffStrbufInit(&item->conn.status);
|
||||
ffStrbufInit(&item->conn.ssid);
|
||||
ffStrbufInit(&item->conn.bssid);
|
||||
ffStrbufInit(&item->conn.protocol);
|
||||
ffStrbufInit(&item->conn.security);
|
||||
item->conn.signalQuality = 0.0/0.0;
|
||||
item->conn.rxRate = 0.0/0.0;
|
||||
item->conn.txRate = 0.0/0.0;
|
||||
item->conn.channel = 0;
|
||||
item->conn.frequency = 0;
|
||||
|
||||
struct ieee80211_nodereq nr = {};
|
||||
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
|
||||
|
||||
struct ifreq ifr = {};
|
||||
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
|
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
ffStrbufSetStatic(&item->inf.status, "Unknown");
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
|
||||
}
|
||||
|
||||
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nr.nr_nwid_len > 0) {
|
||||
ffStrbufSetStatic(&item->conn.status, "Associated");
|
||||
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*)nr.nr_nwid);
|
||||
} else {
|
||||
ffStrbufSetStatic(&item->conn.status, "Not associated");
|
||||
continue;
|
||||
}
|
||||
|
||||
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2],
|
||||
nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]);
|
||||
|
||||
item->conn.channel = nr.nr_channel;
|
||||
|
||||
if (nr.nr_max_rssi) {
|
||||
item->conn.signalQuality = ((float)nr.nr_rssi / nr.nr_max_rssi) * 100.0;
|
||||
}
|
||||
|
||||
if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
|
||||
} else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
|
||||
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) {
|
||||
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
|
||||
}
|
||||
|
||||
struct ieee80211_wpaparams wpa = {};
|
||||
strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) {
|
||||
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2)
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA2");
|
||||
else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1)
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA");
|
||||
} else {
|
||||
struct ieee80211_nwkey nwkey = {};
|
||||
strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name));
|
||||
|
||||
if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) {
|
||||
if (nwkey.i_wepon)
|
||||
ffStrbufSetStatic(&item->conn.security, "WEP");
|
||||
else
|
||||
ffStrbufSetStatic(&item->conn.security, "Open");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if_freenameindex(infs);
|
||||
return NULL;
|
||||
}
|
||||
@@ -38,6 +38,7 @@ static const char* getHyprland(FFstrbuf* result)
|
||||
{
|
||||
ffStrbufSubstrAfterFirstC(result, '"');
|
||||
ffStrbufSubstrBeforeFirstC(result, '"');
|
||||
ffStrbufTrimLeft(result, 'v');
|
||||
FF_DEBUG("Extracted version from version.h: %s", result->chars);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+14
-3
@@ -1,9 +1,11 @@
|
||||
#include "fastfetch.h"
|
||||
#include "common/commandoption.h"
|
||||
#include "common/init.h"
|
||||
#include "common/io/io.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "common/printing.h"
|
||||
#include "detection/version/version.h"
|
||||
#include "logo/logo.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "fastfetch_datatext.h"
|
||||
@@ -483,13 +485,22 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
|
||||
|
||||
if (instance.state.platform.exePath.length)
|
||||
{
|
||||
ffStrbufSet(&absolutePath, &instance.state.platform.exePath);
|
||||
ffStrbufSubstrBeforeLastC(&absolutePath, '/');
|
||||
ffStrbufAppendS(&absolutePath, "/");
|
||||
uint32_t lastSlash = ffStrbufLastIndexC(&instance.state.platform.exePath, '/') + 1;
|
||||
assert(lastSlash < instance.state.platform.exePath.length);
|
||||
|
||||
// Try {exePath}/
|
||||
ffStrbufSetNS(&absolutePath, lastSlash, instance.state.platform.exePath.chars);
|
||||
ffStrbufAppendS(&absolutePath, value);
|
||||
if (needExtension)
|
||||
ffStrbufAppendS(&absolutePath, ".jsonc");
|
||||
if (parseJsoncFile(absolutePath.chars, strictJson)) return;
|
||||
|
||||
// Try {exePath}/presets/
|
||||
ffStrbufSubstrBefore(&absolutePath, lastSlash);
|
||||
ffStrbufAppendS(&absolutePath, "presets/");
|
||||
ffStrbufAppendS(&absolutePath, value);
|
||||
if (needExtension)
|
||||
ffStrbufAppendS(&absolutePath, ".jsonc");
|
||||
if (parseJsoncFile(absolutePath.chars, strictJson)) return;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,27 +63,3 @@ typedef struct FFinstance
|
||||
} FFinstance;
|
||||
extern FFinstance instance; // Defined in `common/init.c`
|
||||
extern FFModuleBaseInfo** ffModuleInfos[];
|
||||
|
||||
//////////////////////
|
||||
// Init functions //
|
||||
//////////////////////
|
||||
|
||||
//common/init.c
|
||||
void ffInitInstance();
|
||||
void ffStart();
|
||||
void ffFinish();
|
||||
void ffDestroyInstance();
|
||||
|
||||
void ffListFeatures();
|
||||
|
||||
////////////////////
|
||||
// Logo functions //
|
||||
////////////////////
|
||||
|
||||
void ffLogoPrint();
|
||||
void ffLogoPrintRemaining();
|
||||
void ffLogoPrintLine();
|
||||
|
||||
void ffLogoBuiltinPrint();
|
||||
void ffLogoBuiltinList();
|
||||
void ffLogoBuiltinListAutocompletion();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include "common/init.h"
|
||||
#include "modules/modules.h"
|
||||
|
||||
int main(void)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
.:::::::::::::::::::::.
|
||||
.:::::::::::::::::::::::.
|
||||
.:::::::::::::::::::::::::.
|
||||
.:::::::::::::::::::::::::::.
|
||||
.:::::::::$2,db,$1::::::::::::::::.
|
||||
.::::::::$2,d%%%%b,$1::$2,db,$1:::::::::.
|
||||
.:::::::$2,%%%%P'%%%b,d%%%b,$1::::::::.
|
||||
.::::::$2,%%%%P,$1:::$2`%%%b'^q%%b,$1:::::::.
|
||||
'::::$2,%%%%P,d|$1:::::$2`%%%b:'^%%b,$1:::::'
|
||||
'::$2`%%%'$1:$2'q$|$1:::::::$2'q%%b'`q%%b'$1::'
|
||||
':::::::::::::::::::::::::::::::'
|
||||
':::::::::::::::::::::::::::::'
|
||||
':::::::::::::::::::::::::::'
|
||||
':::::::::::::::::::::::::'
|
||||
':::::::::::::::::::::::'
|
||||
':::::::::::::::::::::'
|
||||
@@ -0,0 +1,6 @@
|
||||
,db,
|
||||
,d%%%%b, ,db,
|
||||
,%%%%P'%%%b,d%%%b,
|
||||
,%%%%P, `%%%b'^q%%b,
|
||||
,%%%%P,d| `%%%b '^%%b,
|
||||
`%%%' 'q$| 'q%%b'`q%%b
|
||||
@@ -0,0 +1,19 @@
|
||||
$1+++++++++++
|
||||
+++++++++++++++++++++
|
||||
+++++++++++++++++++++++++++++++
|
||||
=+++++++++++++++++++++++++++++++++++++++=
|
||||
+++++++++++++++++++++++++++++++++++++++++++++
|
||||
=++++++++++++++++++++++++++++++++++++++++++++
|
||||
==+++++++++++++++++++++++++++++++++==
|
||||
+++++++++++++++++++++++++++
|
||||
$2**** $1++=+++++++++++=++ $2****
|
||||
********** $1+++++++ $2**********
|
||||
************** **************
|
||||
**************** ****************
|
||||
***********************
|
||||
****** ************* ******
|
||||
*********** *** ***********
|
||||
*************** ***************
|
||||
*************** ***************
|
||||
*********************
|
||||
***********
|
||||
@@ -0,0 +1,28 @@
|
||||
+++++++++
|
||||
+++++$4+$1++++++$4+$1++
|
||||
++++++$4+$1+++ +++++++++++
|
||||
+++++++++++ $2+$1 +++++$4+$1+++++
|
||||
++++++$4+$1++++ $4+++$1 +++++++++++
|
||||
++++++++++$4 + +++++ ++ $2+++++$4+$2++++
|
||||
+++$4+$1++++$4 + + + +++++++ + + $2+++++$4+$2++
|
||||
++++++$4 $2+$4 +++ +++++++++ +++ $2++++++++
|
||||
+++$4+$1++$4 + +++++ +++++ +
|
||||
++++++$4 $2+$4 +++++ +++++ +++++
|
||||
++$4+$2+++$4 + +++++ ++++++ ++++++++++
|
||||
++++++$4 +++++ +++++ + +++++++++++++++++++
|
||||
++++++$4 + +++++ + +++++++++++++++
|
||||
+++$4++$2+$4 ++++++ +++++++++++++
|
||||
++++++$4 + ++++++ +++++++++++++ $2+++ $4++
|
||||
++++++$4 ++++++++++++++++ $2++$4+$2+ $4++ $1+
|
||||
++++++$4 ++++++++++++++ $3+ $2++++
|
||||
++++++$4 +++++++++++ + $4+ $3++++++
|
||||
++$4+$3+++$4 ++++++++++ +++ $3+++++++++++++
|
||||
+++++ $4+++++++++ + $3+++++++++++++
|
||||
+++ $4++++++++ $2++$4 + $3++++++++++++++ ++++
|
||||
++ $4++++++++ $3+ ++++++++++++++ +++++++
|
||||
$4++++++ $2+ $3+++++++++++++ +++++++$2++
|
||||
$4++++ $3+++++++++++++ ++++++$2+++
|
||||
+++++++++++ ++++++$2+++
|
||||
+++++ ++++++$2+++
|
||||
++++++$2++
|
||||
+++++
|
||||
@@ -0,0 +1,12 @@
|
||||
^"^"^". `"^"""`
|
||||
";;;;;:. `;;;;;;.
|
||||
^;":;:;: .;,,;:;:
|
||||
.'`",, '":::. ^;'';;;;, .:: ,;;;:
|
||||
';;;;:":::::' ^;` `;;;;" ::. ,;;;:
|
||||
";:;:. ^;` ^;;;;^ ,;. ,;;;:
|
||||
";;;: ^;` ";;;;^ ";' ,;;;:
|
||||
";;;: ^;` ,;;;;`^;` ,;;;:
|
||||
";;;: ^;` ,;;;;;^ ,;;;:
|
||||
";:;: ^;` .:;:;" ,;:;:
|
||||
,;;;;. ";" .:;, :;;;;.
|
||||
."""""` ^"^ '" ."""""`
|
||||
@@ -1,11 +0,0 @@
|
||||
.7J~
|
||||
~G@^ .^.
|
||||
:5&&&&##B?. !B&G7
|
||||
7B##&&B##BBP~ ^P&@&##P~
|
||||
$2^YGP5PBPPP5YY55?: .7GGGB#BPPP7.
|
||||
.?PPPPPPPPPP55YYY5Y!.^YPPPPPP5YYY5J~
|
||||
!PPPPPPPPPPPPPP5YYYY5JY5PPPPPPP55YY55?:
|
||||
^YPPPPPPPPPPPPPPPPYYYYYYYYY5PPPPPPP5YYY5Y!.
|
||||
.7PPPPPPPPPPPPPPPPPP5YYYYYYYYY55PPPPP5YYYYY5J~
|
||||
!5GPPPPPPPPPPPPPPPPPPPP55555555YY5PPPPPP5555555?:
|
||||
7777777777777777777777777!!!!!!!!!77777777!!!!!7!:
|
||||
+14
-6
@@ -1,6 +1,14 @@
|
||||
${c2}TTTTTTTTTT
|
||||
tt ${c1}222${c2}
|
||||
tt ${c1}2 2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}22222${c2}
|
||||
$3//$2
|
||||
$3//$2
|
||||
$1TTTTTTTTTTTTTTT$2 $3//$2 $1..::$2 $4:-:.$2
|
||||
$4ttt$2 $3//$2 $1.::.$2 $4.:-:$2
|
||||
$4ttt$2 $3//$2 $1.:.$2 $4--$2
|
||||
$4ttt$2 $3//$2 $4:-:$2
|
||||
$4ttt$2 $3//$2 $4.:-:$2
|
||||
$4ttt$2 $3//$2 $4:-:.$2
|
||||
$4ttt$2 $3//$2 $4.--.$2
|
||||
$4ttt$2 $3//$2 $4.:-:$2
|
||||
$4ttt$2 $3//$2 $4...$2
|
||||
$4ttt$2 $3//$2
|
||||
$3//$2 $3.:::::::::::.$2
|
||||
$3//$2
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
${c2}TTTTTTTTTT
|
||||
tt ${c1}222${c2}
|
||||
tt ${c1}2 2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}2${c2}
|
||||
tt ${c1}22222${c2}
|
||||
+67
-11
@@ -89,6 +89,18 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_MAGENTA,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Alpine2
|
||||
{
|
||||
.names = {"Alpine2"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ALPINE2,
|
||||
.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// AlpineSmall
|
||||
{
|
||||
.names = {"Alpine_small"},
|
||||
@@ -113,6 +125,17 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_MAGENTA,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Alpine3Small
|
||||
{
|
||||
.names = {"alpine3_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT | FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ALPINE3_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Alter
|
||||
{
|
||||
.names = {"Alter"},
|
||||
@@ -197,6 +220,17 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_GREEN,
|
||||
.colorTitle = FF_COLOR_FG_GREEN,
|
||||
},
|
||||
//AnduinOS
|
||||
{
|
||||
.names = {"anduinos"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_ANDUINOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_CYAN,
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Antergos
|
||||
{
|
||||
.names = {"Antergos"},
|
||||
@@ -629,6 +663,17 @@ static const FFlogo A[] = {
|
||||
.colorKeys = FF_COLOR_FG_YELLOW,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Aurora
|
||||
{
|
||||
.names = {"Aurora"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_AURORA,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// Azos
|
||||
{
|
||||
.names = {"Azos"},
|
||||
@@ -1090,6 +1135,14 @@ static const FFlogo C[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// Codex Linux (reMarkable OS)
|
||||
{
|
||||
.names = {"Codex Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_CODEX,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE
|
||||
},
|
||||
},
|
||||
// Condres
|
||||
{
|
||||
.names = {"Condres"},
|
||||
@@ -1984,15 +2037,6 @@ static const FFlogo G[] = {
|
||||
.colorKeys = FF_COLOR_FG_MAGENTA,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// GoralixOS
|
||||
{
|
||||
.names = {"GoralixOS"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_GORALIXOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
},
|
||||
},
|
||||
// GrapheneOS
|
||||
{
|
||||
.names = {"GrapheneOS"},
|
||||
@@ -2365,7 +2409,7 @@ static const FFlogo K[] = {
|
||||
},
|
||||
// KDE Neon
|
||||
{
|
||||
.names = {"KDE Neon"}, // Distro ID is `neon`; Distro name is `KDE Neon`
|
||||
.names = {"KDE Neon"}, // Distro ID is "neon"; Distro name is "KDE Neon"
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_KDENEON,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
@@ -4556,8 +4600,20 @@ static const FFlogo S[] = {
|
||||
static const FFlogo T[] = {
|
||||
// T2
|
||||
{
|
||||
.names = {"T2"},
|
||||
.names = {"T2", "T2 SDE", "T2/Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_T2,
|
||||
.colors = {
|
||||
FF_COLOR_FG_RED,
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_BLUE,
|
||||
},
|
||||
},
|
||||
// T2Small
|
||||
{
|
||||
.names = {"T2_small", "T2 SDE_small", "T2/Linux_small"},
|
||||
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_T2_SMALL,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_BLUE,
|
||||
|
||||
@@ -21,7 +21,13 @@ typedef struct FFlogo
|
||||
} FFlogo;
|
||||
|
||||
//logo.c
|
||||
void ffLogoPrint(void);
|
||||
void ffLogoPrintChars(const char* data, bool doColorReplacement);
|
||||
void ffLogoPrintLine(void);
|
||||
void ffLogoPrintRemaining(void);
|
||||
void ffLogoBuiltinPrint(void);
|
||||
void ffLogoBuiltinList(void);
|
||||
void ffLogoBuiltinListAutocompletion(void);
|
||||
|
||||
//builtin.c
|
||||
extern const FFlogo* ffLogoBuiltins[];
|
||||
|
||||
@@ -27,17 +27,6 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
uint32_t timeRemaining = result->timeRemaining < 0 ? 0 : (uint32_t) result->timeRemaining;
|
||||
|
||||
uint32_t seconds = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t minutes = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t hours = timeRemaining % 24;
|
||||
timeRemaining /= 24;
|
||||
uint32_t days = timeRemaining;
|
||||
|
||||
FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type;
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
@@ -70,7 +59,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
if(str.length > 0)
|
||||
ffStrbufAppendS(&str, " (");
|
||||
|
||||
ffParseDuration(days, hours, minutes, seconds, &str);
|
||||
ffParseDuration((uint32_t) result->timeRemaining, &str);
|
||||
ffStrbufAppendS(&str, " remaining)");
|
||||
}
|
||||
}
|
||||
@@ -95,6 +84,15 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t timeRemaining = result->timeRemaining < 0 ? 0 : (uint32_t) result->timeRemaining;
|
||||
uint32_t seconds = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t minutes = timeRemaining % 60;
|
||||
timeRemaining /= 60;
|
||||
uint32_t hours = timeRemaining % 24;
|
||||
timeRemaining /= 24;
|
||||
uint32_t days = timeRemaining;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY capacityNum = ffStrbufCreate();
|
||||
if(percentType & FF_PERCENTAGE_TYPE_NUM_BIT)
|
||||
ffPercentAppendNum(&capacityNum, result->capacity, options->percent, false, &options->moduleArgs);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_BIOS_MODULE_NAME "Bios"
|
||||
#define FF_BIOS_MODULE_NAME "BIOS"
|
||||
|
||||
void ffPrintBios(FFBiosOptions* options);
|
||||
void ffInitBiosOptions(FFBiosOptions* options);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "common/printing.h"
|
||||
#include "logo/logo.h"
|
||||
#include "modules/break/break.h"
|
||||
|
||||
void ffPrintBreak(FF_MAYBE_UNUSED FFBreakOptions* options)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "common/printing.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "logo/logo.h"
|
||||
#include "modules/colors/colors.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
static inline uint8_t min(uint8_t a, uint8_t b)
|
||||
|
||||
@@ -220,7 +220,7 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
yyjson_mut_obj_add_uint(doc, frequency, "max", cpu.frequencyMax);
|
||||
|
||||
yyjson_mut_val* coreTypes = yyjson_mut_obj_add_arr(doc, obj, "coreTypes");
|
||||
for (uint32_t i = 0; i < sizeof (cpu.coreTypes) / sizeof (cpu.coreTypes[0]) && cpu.coreTypes[i].count > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(cpu.coreTypes) && cpu.coreTypes[i].count > 0; i++)
|
||||
{
|
||||
yyjson_mut_val* core = yyjson_mut_arr_add_obj(doc, coreTypes);
|
||||
yyjson_mut_obj_add_uint(doc, core, "count", cpu.coreTypes[i].count);
|
||||
|
||||
@@ -12,7 +12,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption
|
||||
FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate();
|
||||
|
||||
char levelStr[4] = "L";
|
||||
for (uint32_t i = 0; i < sizeof (result->caches) / sizeof (result->caches[0]) && result->caches[i].length > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(result->caches) && result->caches[i].length > 0; i++)
|
||||
{
|
||||
ffStrbufClear(&key);
|
||||
levelStr[1] = (char) ('1' + i);
|
||||
@@ -72,7 +72,7 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
uint64_t sum = 0;
|
||||
for (uint32_t i = 0; i < sizeof (result->caches) / sizeof (result->caches[0]) && result->caches[i].length > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(result->caches) && result->caches[i].length > 0; i++)
|
||||
{
|
||||
if (buffer.length)
|
||||
ffStrbufAppendS(&buffer, ", ");
|
||||
@@ -199,7 +199,7 @@ void ffGenerateCPUCacheJsonResult(FF_MAYBE_UNUSED FFCPUCacheOptions* options, yy
|
||||
|
||||
yyjson_mut_val* caches = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
|
||||
for (uint32_t i = 0; i < sizeof (result.caches) / sizeof (result.caches[0]) && result.caches[i].length > 0; i++)
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(result.caches) && result.caches[i].length > 0; i++)
|
||||
{
|
||||
yyjson_mut_val* level = yyjson_mut_obj_add_arr(doc, caches, &"l1\0l2\0l3\0l4\0"[i * 3]);
|
||||
FF_LIST_FOR_EACH(FFCPUCache, src, result.caches[i])
|
||||
|
||||
@@ -7,40 +7,41 @@
|
||||
typedef enum __attribute__((__packed__)) FFPackagesFlags
|
||||
{
|
||||
FF_PACKAGES_FLAG_NONE = 0,
|
||||
FF_PACKAGES_FLAG_APK_BIT = 1 << 0,
|
||||
FF_PACKAGES_FLAG_BREW_BIT = 1 << 1,
|
||||
FF_PACKAGES_FLAG_CHOCO_BIT = 1 << 2,
|
||||
FF_PACKAGES_FLAG_DPKG_BIT = 1 << 3,
|
||||
FF_PACKAGES_FLAG_EMERGE_BIT = 1 << 4,
|
||||
FF_PACKAGES_FLAG_EOPKG_BIT = 1 << 5,
|
||||
FF_PACKAGES_FLAG_FLATPAK_BIT = 1 << 6,
|
||||
FF_PACKAGES_FLAG_NIX_BIT = 1 << 7,
|
||||
FF_PACKAGES_FLAG_OPKG_BIT = 1 << 8,
|
||||
FF_PACKAGES_FLAG_PACMAN_BIT = 1 << 9,
|
||||
FF_PACKAGES_FLAG_PALUDIS_BIT = 1 << 10,
|
||||
FF_PACKAGES_FLAG_PKG_BIT = 1 << 11,
|
||||
FF_PACKAGES_FLAG_PKGTOOL_BIT = 1 << 12,
|
||||
FF_PACKAGES_FLAG_MACPORTS_BIT = 1 << 13,
|
||||
FF_PACKAGES_FLAG_RPM_BIT = 1 << 14,
|
||||
FF_PACKAGES_FLAG_SCOOP_BIT = 1 << 15,
|
||||
FF_PACKAGES_FLAG_SNAP_BIT = 1 << 16,
|
||||
FF_PACKAGES_FLAG_WINGET_BIT = 1 << 17,
|
||||
FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18,
|
||||
FF_PACKAGES_FLAG_AM_BIT = 1 << 19,
|
||||
FF_PACKAGES_FLAG_SORCERY_BIT = 1 << 20,
|
||||
FF_PACKAGES_FLAG_LPKG_BIT = 1 << 21,
|
||||
FF_PACKAGES_FLAG_LPKGBUILD_BIT = 1 << 22,
|
||||
FF_PACKAGES_FLAG_GUIX_BIT = 1 << 23,
|
||||
FF_PACKAGES_FLAG_LINGLONG_BIT = 1 << 24,
|
||||
FF_PACKAGES_FLAG_PACSTALL_BIT = 1 << 25,
|
||||
FF_PACKAGES_FLAG_MPORT_BIT = 1 << 26,
|
||||
FF_PACKAGES_FLAG_QI_BIT = 1 << 27,
|
||||
FF_PACKAGES_FLAG_PKGSRC_BIT = 1 << 28,
|
||||
FF_PACKAGES_FLAG_HPKG_BIT = 1 << 29,
|
||||
FF_PACKAGES_FLAG_PISI_BIT = 1 << 30,
|
||||
FF_PACKAGES_FLAG_FORCE_UNSIGNED = UINT32_MAX,
|
||||
FF_PACKAGES_FLAG_APK_BIT = 1ULL << 0,
|
||||
FF_PACKAGES_FLAG_BREW_BIT = 1ULL << 1,
|
||||
FF_PACKAGES_FLAG_CHOCO_BIT = 1ULL << 2,
|
||||
FF_PACKAGES_FLAG_DPKG_BIT = 1ULL << 3,
|
||||
FF_PACKAGES_FLAG_EMERGE_BIT = 1ULL << 4,
|
||||
FF_PACKAGES_FLAG_EOPKG_BIT = 1ULL << 5,
|
||||
FF_PACKAGES_FLAG_FLATPAK_BIT = 1ULL << 6,
|
||||
FF_PACKAGES_FLAG_NIX_BIT = 1ULL << 7,
|
||||
FF_PACKAGES_FLAG_OPKG_BIT = 1ULL << 8,
|
||||
FF_PACKAGES_FLAG_PACMAN_BIT = 1ULL << 9,
|
||||
FF_PACKAGES_FLAG_PALUDIS_BIT = 1ULL << 10,
|
||||
FF_PACKAGES_FLAG_PKG_BIT = 1ULL << 11,
|
||||
FF_PACKAGES_FLAG_PKGTOOL_BIT = 1ULL << 12,
|
||||
FF_PACKAGES_FLAG_MACPORTS_BIT = 1ULL << 13,
|
||||
FF_PACKAGES_FLAG_RPM_BIT = 1ULL << 14,
|
||||
FF_PACKAGES_FLAG_SCOOP_BIT = 1ULL << 15,
|
||||
FF_PACKAGES_FLAG_SNAP_BIT = 1ULL << 16,
|
||||
FF_PACKAGES_FLAG_WINGET_BIT = 1ULL << 17,
|
||||
FF_PACKAGES_FLAG_XBPS_BIT = 1ULL << 18,
|
||||
FF_PACKAGES_FLAG_AM_BIT = 1ULL << 19,
|
||||
FF_PACKAGES_FLAG_SORCERY_BIT = 1ULL << 20,
|
||||
FF_PACKAGES_FLAG_LPKG_BIT = 1ULL << 21,
|
||||
FF_PACKAGES_FLAG_LPKGBUILD_BIT = 1ULL << 22,
|
||||
FF_PACKAGES_FLAG_GUIX_BIT = 1ULL << 23,
|
||||
FF_PACKAGES_FLAG_LINGLONG_BIT = 1ULL << 24,
|
||||
FF_PACKAGES_FLAG_PACSTALL_BIT = 1ULL << 25,
|
||||
FF_PACKAGES_FLAG_MPORT_BIT = 1ULL << 26,
|
||||
FF_PACKAGES_FLAG_QI_BIT = 1ULL << 27,
|
||||
FF_PACKAGES_FLAG_PKGSRC_BIT = 1ULL << 28,
|
||||
FF_PACKAGES_FLAG_HPKG_BIT = 1ULL << 29,
|
||||
FF_PACKAGES_FLAG_PISI_BIT = 1ULL << 30,
|
||||
FF_PACKAGES_FLAG_SOAR_BIT = 1ULL << 31,
|
||||
FF_PACKAGES_FLAG_FORCE_UNSIGNED = UINT64_MAX,
|
||||
} FFPackagesFlags;
|
||||
static_assert(sizeof(FFPackagesFlags) == sizeof(uint32_t), "");
|
||||
static_assert(sizeof(FFPackagesFlags) == sizeof(uint64_t), "");
|
||||
|
||||
typedef struct FFPackagesOptions
|
||||
{
|
||||
|
||||
@@ -78,6 +78,7 @@ void ffPrintPackages(FFPackagesOptions* options)
|
||||
FF_PRINT_PACKAGE(mport)
|
||||
FF_PRINT_PACKAGE(qi)
|
||||
FF_PRINT_PACKAGE(pisi)
|
||||
FF_PRINT_PACKAGE(soar)
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
@@ -130,6 +131,7 @@ void ffPrintPackages(FFPackagesOptions* options)
|
||||
FF_FORMAT_ARG(counts.hpkgSystem, "hpkg-system"),
|
||||
FF_FORMAT_ARG(counts.hpkgUser, "hpkg-user"),
|
||||
FF_FORMAT_ARG(counts.pisi, "pisi"),
|
||||
FF_FORMAT_ARG(counts.soar, "soar"),
|
||||
FF_FORMAT_ARG(nixAll, "nix-all"),
|
||||
FF_FORMAT_ARG(flatpakAll, "flatpak-all"),
|
||||
FF_FORMAT_ARG(brewAll, "brew-all"),
|
||||
@@ -222,6 +224,7 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
|
||||
case 'S': if (false);
|
||||
FF_TEST_PACKAGE_NAME(SCOOP)
|
||||
FF_TEST_PACKAGE_NAME(SNAP)
|
||||
FF_TEST_PACKAGE_NAME(SOAR)
|
||||
FF_TEST_PACKAGE_NAME(SORCERY)
|
||||
break;
|
||||
case 'W': if (false);
|
||||
@@ -341,6 +344,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
|
||||
case 'S': if (false);
|
||||
FF_TEST_PACKAGE_NAME(SCOOP)
|
||||
FF_TEST_PACKAGE_NAME(SNAP)
|
||||
FF_TEST_PACKAGE_NAME(SOAR)
|
||||
FF_TEST_PACKAGE_NAME(SORCERY)
|
||||
break;
|
||||
case 'W': if (false);
|
||||
@@ -400,6 +404,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
|
||||
FF_TEST_PACKAGE_NAME(RPM)
|
||||
FF_TEST_PACKAGE_NAME(SCOOP)
|
||||
FF_TEST_PACKAGE_NAME(SNAP)
|
||||
FF_TEST_PACKAGE_NAME(SOAR)
|
||||
FF_TEST_PACKAGE_NAME(SORCERY)
|
||||
FF_TEST_PACKAGE_NAME(WINGET)
|
||||
FF_TEST_PACKAGE_NAME(XBPS)
|
||||
@@ -459,6 +464,7 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
|
||||
FF_APPEND_PACKAGE_COUNT(rpm)
|
||||
FF_APPEND_PACKAGE_COUNT(scoop)
|
||||
FF_APPEND_PACKAGE_COUNT(snap)
|
||||
FF_APPEND_PACKAGE_COUNT(soar)
|
||||
FF_APPEND_PACKAGE_COUNT(sorcery)
|
||||
FF_APPEND_PACKAGE_COUNT(winget)
|
||||
FF_APPEND_PACKAGE_COUNT(xbps)
|
||||
@@ -515,6 +521,7 @@ static FFModuleBaseInfo ffModuleInfo = {
|
||||
{"Number of hpkg-system packages", "hpkg-system"},
|
||||
{"Number of hpkg-user packages", "hpkg-user"},
|
||||
{"Number of pisi packages", "pisi"},
|
||||
{"Number of soar packages", "soar"},
|
||||
{"Total number of all nix packages", "nix-all"},
|
||||
{"Total number of all flatpak app packages", "flatpak-all"},
|
||||
{"Total number of all brew packages", "brew-all"},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "common/printing.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "logo/logo.h"
|
||||
#include "modules/separator/separator.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/mallocHelper.h"
|
||||
|
||||
@@ -63,6 +63,7 @@ void ffPrintTitle(FFTitleOptions* options)
|
||||
FF_FORMAT_ARG(userNameColored, "user-name-colored"),
|
||||
FF_FORMAT_ARG(atColored, "at-symbol-colored"),
|
||||
FF_FORMAT_ARG(hostNameColored, "host-name-colored"),
|
||||
FF_FORMAT_ARG(instance.state.platform.fullUserName, "full-user-name"),
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -170,6 +171,7 @@ void ffGenerateTitleJsonResult(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_m
|
||||
{
|
||||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "userName", &instance.state.platform.userName);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "fullUserName", &instance.state.platform.fullUserName);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &instance.state.platform.hostName);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "homeDir", &instance.state.platform.homeDir);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &instance.state.platform.exePath);
|
||||
@@ -193,6 +195,7 @@ static FFModuleBaseInfo ffModuleInfo = {
|
||||
{"User name (colored)", "user-name-colored"},
|
||||
{"@ symbol (colored)", "at-symbol-colored"},
|
||||
{"Host name (colored)", "host-name-colored"},
|
||||
{"Full user name", "full-user-name"},
|
||||
}))
|
||||
};
|
||||
|
||||
|
||||
+12
-12
@@ -7,7 +7,7 @@
|
||||
|
||||
void ffPrintUptime(FFUptimeOptions* options)
|
||||
{
|
||||
FFUptimeResult result;
|
||||
FFUptimeResult result = {};
|
||||
|
||||
const char* error = ffDetectUptime(&result);
|
||||
|
||||
@@ -19,26 +19,26 @@ void ffPrintUptime(FFUptimeOptions* options)
|
||||
|
||||
uint64_t uptime = result.uptime;
|
||||
|
||||
uint32_t milliseconds = (uint32_t) (uptime % 1000);
|
||||
uptime /= 1000;
|
||||
uint32_t seconds = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t minutes = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t hours = (uint32_t) (uptime % 24);
|
||||
uptime /= 24;
|
||||
uint32_t days = (uint32_t) uptime;
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
ffParseDuration(days, hours, minutes, seconds, &buffer);
|
||||
ffParseDuration((uptime + 500) / 1000, &buffer);
|
||||
|
||||
ffStrbufPutTo(&buffer, stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t milliseconds = (uint32_t) (uptime % 1000);
|
||||
uptime /= 1000;
|
||||
uint32_t seconds = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t minutes = (uint32_t) (uptime % 60);
|
||||
uptime /= 60;
|
||||
uint32_t hours = (uint32_t) (uptime % 24);
|
||||
uptime /= 24;
|
||||
uint32_t days = (uint32_t) uptime;
|
||||
|
||||
FF_PRINT_FORMAT_CHECKED(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){
|
||||
FF_FORMAT_ARG(days, "days"),
|
||||
FF_FORMAT_ARG(hours, "hours"),
|
||||
|
||||
+1
-1
@@ -401,7 +401,7 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo
|
||||
|
||||
yyjson_val* symbols = yyjson_obj_get(val, "symbols");
|
||||
if (symbols)
|
||||
ffStrbufAppendS(&options->chafaSymbols, yyjson_get_str(symbols));
|
||||
ffStrbufSetS(&options->chafaSymbols, yyjson_get_str(symbols));
|
||||
|
||||
yyjson_val* canvasMode = yyjson_obj_get(val, "canvasMode");
|
||||
if (canvasMode)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "common/io/io.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#if !_WIN32
|
||||
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
|
||||
{
|
||||
char* path = getenv("PATH");
|
||||
@@ -47,6 +48,22 @@ const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
|
||||
ffStrbufClear(result);
|
||||
return "Executable not found";
|
||||
}
|
||||
#else
|
||||
#include <windows.h>
|
||||
|
||||
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
|
||||
{
|
||||
char buffer[MAX_PATH + 1];
|
||||
DWORD length = SearchPathA(NULL, name, ".exe", sizeof(buffer), buffer, NULL);
|
||||
if (length == 0)
|
||||
{
|
||||
ffStrbufClear(result);
|
||||
return "Executable not found";
|
||||
}
|
||||
ffStrbufSetS(result, buffer);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ffIsAbsolutePath(const char* path)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ void ffPlatformInit(FFPlatform* platform)
|
||||
ffStrbufInit(&platform->exePath);
|
||||
|
||||
ffStrbufInit(&platform->userName);
|
||||
ffStrbufInit(&platform->fullUserName);
|
||||
ffStrbufInit(&platform->hostName);
|
||||
ffStrbufInit(&platform->userShell);
|
||||
|
||||
@@ -48,6 +49,7 @@ void ffPlatformDestroy(FFPlatform* platform)
|
||||
ffStrbufDestroy(&platform->userName);
|
||||
ffStrbufDestroy(&platform->hostName);
|
||||
ffStrbufDestroy(&platform->userShell);
|
||||
ffStrbufDestroy(&platform->fullUserName);
|
||||
|
||||
FFPlatformSysinfo* info = &platform->sysinfo;
|
||||
ffStrbufDestroy(&info->architecture);
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef struct FFPlatform
|
||||
FFstrbuf exePath; // The real path of current exe
|
||||
|
||||
FFstrbuf userName;
|
||||
FFstrbuf fullUserName;
|
||||
FFstrbuf hostName;
|
||||
FFstrbuf userShell;
|
||||
|
||||
|
||||
@@ -172,14 +172,6 @@ static void getDataDirs(FFPlatform* platform)
|
||||
#endif
|
||||
ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/");
|
||||
ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/");
|
||||
|
||||
if (platform->exePath.length > 0)
|
||||
{
|
||||
// Add ${currentExePath}
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateCopy(&platform->exePath);
|
||||
ffStrbufSubstrBeforeLastC(&path, '/');
|
||||
ffPlatformPathAddAbsolute(&platform->dataDirs, path.chars);
|
||||
}
|
||||
}
|
||||
|
||||
static void getUserName(FFPlatform* platform, const struct passwd* pwd)
|
||||
@@ -189,6 +181,8 @@ static void getUserName(FFPlatform* platform, const struct passwd* pwd)
|
||||
user = pwd->pw_name;
|
||||
|
||||
ffStrbufAppendS(&platform->userName, user);
|
||||
|
||||
if (pwd) ffStrbufAppendS(&platform->fullUserName, pwd->pw_gecos);
|
||||
}
|
||||
|
||||
static void getHostName(FFPlatform* platform, const struct utsname* uts)
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#define SECURITY_WIN32 1 // For secext.h
|
||||
#include <secext.h>
|
||||
|
||||
static void getExePath(FFPlatform* platform)
|
||||
{
|
||||
wchar_t exePathW[MAX_PATH];
|
||||
@@ -129,14 +132,6 @@ static void getDataDirs(FFPlatform* platform)
|
||||
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_RoamingAppData);
|
||||
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_LocalAppData);
|
||||
ffPlatformPathAddHome(&platform->dataDirs, platform, "");
|
||||
|
||||
if (platform->exePath.length > 0)
|
||||
{
|
||||
// Add ${currentExePath}
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateCopy(&platform->exePath);
|
||||
ffStrbufSubstrBeforeLastC(&path, '/');
|
||||
ffPlatformPathAddAbsolute(&platform->dataDirs, path.chars);
|
||||
}
|
||||
}
|
||||
|
||||
static void getUserName(FFPlatform* platform)
|
||||
@@ -146,11 +141,16 @@ static void getUserName(FFPlatform* platform)
|
||||
ffStrbufSetS(&platform->userName, userName);
|
||||
else
|
||||
{
|
||||
wchar_t buffer[128];
|
||||
wchar_t buffer[256];
|
||||
DWORD len = ARRAY_SIZE(buffer);
|
||||
if(GetUserNameW(buffer, &len))
|
||||
ffStrbufSetWS(&platform->userName, buffer);
|
||||
}
|
||||
|
||||
wchar_t buffer[256];
|
||||
DWORD len = ARRAY_SIZE(buffer);
|
||||
if (GetUserNameExW(NameDisplay, buffer, &len))
|
||||
ffStrbufSetWS(&platform->fullUserName, buffer);
|
||||
}
|
||||
|
||||
static void getHostName(FFPlatform* platform)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "common/format.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void verify(const char* color, const char* expected, int lineNo)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
|
||||
ffOptionParseColorNoClear(color, &result);
|
||||
if (!ffStrbufEqualS(&result, expected))
|
||||
{
|
||||
fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %s: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, color, expected, result.chars);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define VERIFY(color, expected) verify((color), (expected), __LINE__)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
instance.config.display.pipe = true;
|
||||
// Initialize dummy config colors for property tests
|
||||
ffStrbufInitS(&instance.config.display.colorKeys, "94"); // light_blue
|
||||
ffStrbufInitS(&instance.config.display.colorTitle, "95"); // light_magenta
|
||||
|
||||
{
|
||||
VERIFY("", "");
|
||||
VERIFY("1", "1");
|
||||
|
||||
VERIFY("red", "31");
|
||||
VERIFY("light_green", "92");
|
||||
VERIFY("default", "39");
|
||||
VERIFY("blue", "34");
|
||||
VERIFY("light_cyan", "96");
|
||||
|
||||
VERIFY("bold_red", "1;31");
|
||||
VERIFY("dim_light_yellow", "2;93");
|
||||
VERIFY("italic_underline_green", "3;4;32");
|
||||
VERIFY("reset_blue", "0;34"); // Reset followed by color
|
||||
|
||||
VERIFY("#ff0000", "38;2;255;0;0"); // RRGGBB
|
||||
VERIFY("#0f0", "38;2;0;255;0"); // RGB
|
||||
VERIFY("#123456", "38;2;18;52;86");
|
||||
VERIFY("#abc", "38;2;170;187;204");
|
||||
|
||||
VERIFY("bold_#ff00ff", "1;38;2;255;0;255");
|
||||
VERIFY("underline_#123", "4;38;2;17;34;51");
|
||||
|
||||
VERIFY("\e[32m", "32"); // Direct ANSI code
|
||||
VERIFY("\e[1;94m", "1;94"); // Direct ANSI code with mode
|
||||
|
||||
// Property colors (ensure dummy config colors are set)
|
||||
VERIFY("keys", "94");
|
||||
VERIFY("title", "95");
|
||||
VERIFY("bold_keys", "1;94");
|
||||
}
|
||||
|
||||
// Clean up dummy config colors
|
||||
ffStrbufDestroy(&instance.config.display.colorKeys);
|
||||
ffStrbufDestroy(&instance.config.display.colorTitle);
|
||||
|
||||
//Success
|
||||
puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#include "common/parsing.h"
|
||||
#include "util/textModifier.h"
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static void verify(uint64_t totalSeconds, const char* expected, int lineNo)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate();
|
||||
ffParseDuration(totalSeconds, &result);
|
||||
if (!ffStrbufEqualS(&result, expected))
|
||||
{
|
||||
fprintf(stderr, FASTFETCH_TEXT_MODIFIER_ERROR "[%d] %llu: expected \"%s\", got \"%s\"\n" FASTFETCH_TEXT_MODIFIER_RESET, lineNo, (unsigned long long) totalSeconds, expected, result.chars);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#define VERIFY(color, expected) verify((color), (expected), __LINE__)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Test seconds less than 60
|
||||
VERIFY(0, "0 seconds");
|
||||
VERIFY(1, "1 second");
|
||||
VERIFY(2, "2 seconds");
|
||||
VERIFY(59, "59 seconds");
|
||||
|
||||
// Test minute rounding (when seconds >= 30)
|
||||
VERIFY(60, "1 min");
|
||||
VERIFY(60 + 29, "1 min");
|
||||
VERIFY(60 + 30, "2 mins");
|
||||
|
||||
// Test only minutes
|
||||
VERIFY(60 * 2 - 1, "2 mins");
|
||||
VERIFY(60 * 2, "2 mins");
|
||||
VERIFY(60 * 59 + 29, "59 mins");
|
||||
|
||||
// Test only hours (no minutes)
|
||||
VERIFY(60 * 59 + 30, "1 hour");
|
||||
VERIFY(60 * 60, "1 hour");
|
||||
VERIFY(2 * 60 * 60, "2 hours");
|
||||
VERIFY(23 * 60 * 60, "23 hours");
|
||||
|
||||
// Test combination of hours and minutes
|
||||
VERIFY(60 * 60 + 60, "1 hour, 1 min");
|
||||
VERIFY(60 * 60 + 60 * 2, "1 hour, 2 mins");
|
||||
VERIFY(60 * 60 * 2 + 60 + 29, "2 hours, 1 min");
|
||||
VERIFY(60 * 60 * 2 + 60 + 30, "2 hours, 2 mins");
|
||||
|
||||
// Test days
|
||||
VERIFY(60 * 60 * 24, "1 day");
|
||||
VERIFY(60 * 60 * 24 - 1, "1 day");
|
||||
VERIFY(60 * 60 * 24 * 2, "2 days");
|
||||
|
||||
// Test combination of days and hours
|
||||
VERIFY(60 * 60 * 24 + 60 * 60, "1 day, 1 hour");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 60, "2 days, 1 hour");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 60 * 2, "2 days, 2 hours");
|
||||
|
||||
// Test combination of days, hours, and minutes
|
||||
VERIFY(60 * 60 * 24 + 60 * 60 + 60, "1 day, 1 hour, 1 min");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 60 + 60 * 2, "2 days, 1 hour, 2 mins");
|
||||
VERIFY(60 * 60 * 24 * 2 + 60 * 2, "2 days, 2 mins");
|
||||
|
||||
// Test very large number of days
|
||||
VERIFY(60 * 60 * 24 * 100, "100 days(!)");
|
||||
VERIFY(60 * 60 * 24 * 200, "200 days(!)");
|
||||
|
||||
//Success
|
||||
puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET);
|
||||
}
|
||||
Reference in New Issue
Block a user