Compare commits

..

878 Commits

Author SHA1 Message Date
Carter Li acf610416c Merge pull request #2331 from fastfetch-cli/dev
Release: v2.63.1
2026-05-13 19:54:48 +08:00
Carter Li 90d3b3d49f Release: v2.63.1 2026-05-13 19:41:21 +08:00
Carter Li bbc5b4de98 Wifi (Linux): disables usage of Netlink on big-endian platforms
Until some can confirm it works
2026-05-13 19:29:33 +08:00
Carter Li 7f9b6187a6 CommandOption: fixes segfault with unknown module 2026-05-13 19:28:36 +08:00
Carter Li 8067e43631 Media (Linux): be compatible with signed media length
Fixes Chrome support
2026-05-13 19:07:14 +08:00
Carter Li 61dba1ea05 Packaging: update debian stuff [ci skip] 2026-05-13 16:04:51 +08:00
Carter Li a94df76bfa Merge pull request #2330 from fastfetch-cli/dev
Release v2.63.0
2026-05-13 16:04:31 +08:00
Carter Li b2b748b07c DisplayServer (Linux): fixes a memory leak 2026-05-13 15:44:00 +08:00
Carter Li 77ce6b0e4c Settings (Linux): shuts libeet down if applicate 2026-05-13 15:33:55 +08:00
Carter Li d28d307b63 Release: v2.63.0 2026-05-13 14:56:22 +08:00
Carter Li 3492f9bfa1 Common (Linux): tidy 2026-05-13 14:38:16 +08:00
李通洲 79c67ec0d7 CI (Linux): installs libefl 2026-05-13 14:37:39 +08:00
Carter Li 6527f03a9b Logo (Builtin): add Ximper Linux
Fixes #2283
2026-05-13 13:53:00 +08:00
Carter Li a8b629f58c DE (Linux): fixes an inverted test 2026-05-13 13:23:23 +08:00
Carter Li 5df00a3394 Global: adds missing #endifs back 2026-05-13 13:14:21 +08:00
Carter Li 8a7c83cac6 Doc: update changelog 2026-05-13 11:08:02 +08:00
Carter Li 27bffb3464 Windows: removes unused config wmiTimeout 2026-05-13 11:07:48 +08:00
李通洲 875afb7cde Media (Windows): adds global.playerName selection support 2026-05-13 10:19:45 +08:00
李通洲 3e99a7035b Media (Windows): adds length & position detection support 2026-05-13 10:19:31 +08:00
Carter Li 63873763de Doc: update JsonSchema [ci skip] 2026-05-13 10:17:06 +08:00
Carter Li 27c83e88f2 Media: prints hours if the song is longer than 1 hour 2026-05-13 10:12:07 +08:00
Carter Li f48904805f Media: fixes percentage format 2026-05-13 10:12:07 +08:00
Carter Li 531cd0909a Media (Linux): don't use playerctld as a media player 2026-05-13 10:12:07 +08:00
李通洲 eafcdfec9e WM (Linux): fixes building 2026-05-12 23:10:09 +08:00
李通洲 d6bd855733 DateTime: adds AM/PM format support to date and time output
Fixes #2325
2026-05-12 22:54:49 +08:00
李通洲 af7e2d47d1 OS (Windows): adds support for Embedded variant in OS detection 2026-05-12 22:54:31 +08:00
Carter Li f71c0b0866 Media: adds progress number & bar format support 2026-05-12 19:14:56 +08:00
Carter Li 1400291ae9 Media (macOS): adds length & position detection support 2026-05-12 15:07:22 +08:00
Carter Li 7799dbe481 WM: adds full support of Enlightenment
Fixes #2165
2026-05-12 10:56:14 +08:00
Carter Li 8426833c36 DE (Linux): adds Enlightenment version detection support 2026-05-12 08:36:50 +08:00
Carter Li 235a2018fc Chore: update .clang-format [ci skip] 2026-05-12 08:36:50 +08:00
李通洲 470e3b4e57 IO (Linux): fixes a possible fd leak 2026-05-12 00:08:27 +08:00
Carter Li 1942dce980 Media (Linux): detects song length & play position 2026-05-11 23:25:52 +08:00
Carter Li efca4f3597 DBus: expands Get(U)Int to (u)int64 2026-05-11 23:24:45 +08:00
Carter Li 43ddbdca85 Logo (Builtin): tidy
Fk `clang-format`
2026-05-11 11:06:01 +08:00
Carter Li 5d29e26509 Logo (Builtin): cleans up Kylin 2026-05-11 11:03:15 +08:00
Carter Li 8daec2568c Common (Windows): adds a missing #include 2026-05-11 10:13:48 +08:00
Carter Li 320e1bf4e0 Doc: update changelog [ci skip] 2026-05-11 09:42:48 +08:00
Carter Li 38e98d3d51 Logo (Builtin): cleans up xj380 2026-05-11 09:37:57 +08:00
HNO₃ 50964fcddf Logo (Builtin): adds openRuyi (#2318)
* Logo: Add openRuyi

* Update ASCII art in openruyi.txt

* Fix casing of 'openRuyi' in builtin.c

---------

Co-authored-by: Z572 <z572@z572.online>
Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-05-11 09:37:02 +08:00
国企鱼 6c7a8a8c41 Logo (Builtin): adds XJ380 OS Logo (#2309) 2026-05-11 09:36:32 +08:00
Carter Li 92082eed54 Doc: update PR template [ci skip] 2026-05-11 08:56:31 +08:00
Carter Li 26b3a84b8a Terminal: fixes TDE konsole version detection
Fixes #2319
2026-05-11 08:51:46 +08:00
Carter Li 0747fc0887 CI (OmniOS): fixes build 2026-05-10 17:35:33 +08:00
Carter Li 60fbe1fd0b Common (Windows): uses WinRT APIs only when FF_HAVE_WINRT is defined 2026-05-10 16:46:20 +08:00
Carter Li f8667d9faa Doc: updates changelog 2026-05-10 16:20:48 +08:00
Carter Li 1c89bbc34e Chore: clang-format 2026-05-10 16:00:22 +08:00
Carter Li b37f020270 DisplayServer (Linux): binds minimal version to avoid breakage 2026-05-10 15:43:13 +08:00
Carter Li fbc9569e13 DisplayServer (Linux): updates kde-output-device-v2 again 2026-05-10 15:37:03 +08:00
François Revol a923f61115 Wallpaper (Haiku): adds support (#2314)
* Wallpaper (Haiku): Add support

* Refactor wallpaper detection logic and memory handling

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-05-09 20:35:25 -05:00
李通洲 bc0a515998 Common (Windows): works around a compiler optimise bug 2026-05-09 15:43:15 +08:00
李通洲 87d89130ad Common (Windows): fixes Windows 11 detection code 2026-05-09 15:43:15 +08:00
李通洲 f46aa316cb Wifi (Linux): improves protocol reporting 2026-05-09 14:34:23 +08:00
Carter Li fdb5f30cb8 CMake (Linux): removes linux/wireless detection
Always required now
2026-05-09 11:04:39 +08:00
Carter Li 91f1c4db10 Wifi: fixes 60 GHz band detection 2026-05-09 11:01:50 +08:00
Carter Li 44e2948b1d Wifi: adds 6 GHz channels detection 2026-05-09 11:01:05 +08:00
Carter Li b86acf6c36 Wifi (Linux): fixes bugs when multiple BSS exists; adds ioctl fallback 2026-05-09 11:00:40 +08:00
Carter Li 9a15666248 Wifi (Linux): switches to netlink impl 2026-05-08 22:43:16 +08:00
李通洲 f5dfec6dcb Battery (Windows): tidy
Co-authored-by: Copilot <copilot@github.com>
2026-05-08 14:31:42 +08:00
Carter Li 8c55c06fa7 OS (Linux): detects bedrock only on Linux 2026-05-06 18:15:57 +08:00
李通洲 8159f473cc Common (Windows): allows COM be used in C sources 2026-05-06 15:01:40 +08:00
李通洲 dca3b154ef Global (Windows): fixes possible use-before-init errors 2026-05-06 15:00:52 +08:00
李通洲 79b61f1391 Common (Windows): inits WinRT/COM globally 2026-05-06 14:38:10 +08:00
李通洲 ba54763dde Camera (Windows): adds support for Display P3 color space 2026-05-06 11:06:07 +08:00
Oliver Lin 451bc394ee OS (Linux): enhances Deepin version detection using /etc/os-version (#2300)
* feat(os): enhance Deepin detection with os-version data

Add a Deepin-specific enhancement in Linux OS detection that reads
`/etc/os-version` for `MinorVersion` and `EditionName`.

When available, it now:
- sets `versionID` to `MinorVersion`
- updates `prettyName` to include version and optional edition

This improves Deepin version accuracy and provides a clearer OS name
than relying solely on generic `os-release` fields.feat(os): enhance Deepin detection with os-version data

Add a Deepin-specific enhancement in Linux OS detection that reads
`/etc/os-version` for `MinorVersion` and `EditionName`.

When available, it now:
- sets `versionID` to `MinorVersion`
- updates `prettyName` to include version and optional edition

This improves Deepin version accuracy and provides a clearer OS name
than relying solely on generic `os-release` fields.

* fix(os): use distro name when formatting Deepin prettyName

Update Deepin enhancement formatting to build `prettyName` from
`result->name` instead of hardcoding "Deepin". This keeps output
consistent with the detected distro name while still appending version
and edition details.fix(os): use distro name when formatting Deepin prettyName

Update Deepin enhancement formatting to build `prettyName` from
`result->name` instead of hardcoding "Deepin". This keeps output
consistent with the detected distro name while still appending version
and edition details.

* fix(os/linux): guard Deepin minor version override

Only apply Deepin’s `minor` value to `versionID` when an edition is
present and `prettyName` does not already include parenthesized details.
This avoids incorrectly overriding parsed version info in enhanced names.fix(os/linux): guard Deepin minor version override

Only apply Deepin’s `minor` value to `versionID` when an edition is
present and `prettyName` does not already include parenthesized details.
This avoids incorrectly overriding parsed version info in enhanced names.

Co-authored-by: Copilot <copilot@github.com>

* Refactor Deepin enhancement detection logic

* Refactor detectDeepinEnhancement function

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-05-05 20:43:17 -05:00
李通洲 93f9ed1bf5 Wmtheme (Linux): adds NebiDE support
Ref: #2295
2026-05-04 19:44:42 +08:00
Sarp Mateson d9e4389ed4 Logo (Builtin): add NebiOS (#2295)
* added logo with nebisoft's color palette, updated builtin.c

* forgot to update the nebios logo with    color placeholders
2026-05-04 19:42:51 +08:00
李通洲 b465052ad2 Logo (Builtin): removes Ubuntu KDE 2026-05-02 22:19:26 +08:00
李通洲 2e6b9cd503 OS (Linux): adds comments 2026-05-02 22:18:08 +08:00
李通洲 0557f16c16 OS (Linux): adds Ubuntu Unity detection 2026-05-02 22:06:18 +08:00
李通洲 08e252a44c OS (Linux): adds Ubuntu Kylin detection 2026-05-02 21:59:22 +08:00
Oliver Lin 90e2d8f8d9 OS (Linux): detects Ubuntu Studio before Kubuntu on KDE systems (#2298)
* fix(os): detect Ubuntu Studio before KDE-based flavor checks

Add an explicit Ubuntu Studio detection in `getUbuntuFlavour()` by
checking for `/usr/share/doc/ubuntustudio-desktop` and setting
`name`, `id`, and `idLike` accordingly.

This prevents Ubuntu Studio systems from being misidentified as
Kubuntu when KDE/Plasma-related XDG config paths are present.fix(os): detect Ubuntu Studio before KDE-based flavor checks

Add an explicit Ubuntu Studio detection in `getUbuntuFlavour()` by
checking for `/usr/share/doc/ubuntustudio-desktop` and setting
`name`, `id`, and `idLike` accordingly.

This prevents Ubuntu Studio systems from being misidentified as
Kubuntu when KDE/Plasma-related XDG config paths are present.

* refactor(os): detect Ubuntu Studio via package presence
2026-05-02 21:54:33 +08:00
Angelo Verlain 0dd8d80e02 Logo (Builtin): correctly detects GNOME OS (#2296)
* Correctly detect GNOME OS

* Update builtin.c

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-05-02 01:06:47 +08:00
Christopher L Fox Junior 3cddf31987 Add ASCII logo for KibaOS (#2294)
* Add ASCII logo for KibaOS

* Add KibaOS logo to builtin.c

* Update builtin.c

* Update builtin.c

* Add KibaOS logo to builtin logo configurations

Added KibaOS logo configuration to the logo data structure.

* Fix KibaOS Syntax
2026-05-01 17:13:32 +08:00
李通洲 fe1c5c8f6f Media (Windows): improves readability
Co-authored-by: Copilot <copilot@github.com>
2026-05-01 11:58:19 +08:00
李通洲 994bd53d30 Media (Windows): major code refactor
moves detection code into fastfetch binary

Co-authored-by: Copilot <copilot@github.com>
2026-04-30 20:26:57 +08:00
李通洲 383a4190ca Comon (macOS): tidy
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 13:26:46 +08:00
李通洲 42f2e5a745 Netif (macOS): improves reliability 2026-04-30 11:01:07 +08:00
Carter Li 14b8bb2bb5 Temps: validates temp color thresholds as integers in JSON parsing
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 09:33:48 +08:00
Carter Li b68ad3626c Sysctl: returns error on failed string fetch and removes malloc null check
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 09:31:28 +08:00
Carter Li cd25803e32 Option: adds a missing validation 2026-04-30 09:27:05 +08:00
Carter Li 3d6bffe7fe Settings: fixes DBusMessage reply leaks in XFConf functions
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 09:04:02 +08:00
Carter Li e694c8ac84 Properties: fixes a typo
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 08:50:23 +08:00
李通洲 dfff57dd85 Percent: improve reliability
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 08:40:30 +08:00
李通洲 c5141855a2 Path: removes dead code 2026-04-30 08:40:30 +08:00
李通洲 6cb186f229 Parsing: improves reliablity
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 08:40:30 +08:00
李通洲 e91f62aa70 Option: improve reliablity 2026-04-30 08:40:30 +08:00
李通洲 ab5cf94099 Networking: improves reliablity
Co-authored-by: Copilot <copilot@github.com>
2026-04-30 08:40:30 +08:00
李通洲 d9eccd70ed Battery (Windows): removes option useSetupApi 2026-04-29 18:54:18 +08:00
李通洲 025febc78d Battery (Windows): switches to query WMI with NtApi as a fast path
Co-authored-by: Copilot <copilot@github.com>
2026-04-29 18:50:04 +08:00
李通洲 69cc19d6f5 Brightness (Windows): cleanups debug log 2026-04-29 18:42:12 +08:00
李通洲 2e4dd1d262 Chore: silenses compiler warnings 2026-04-29 17:36:37 +08:00
李通洲 24ec0e6035 Common (Windows): removes old COM based WMI query implementation 2026-04-29 00:11:29 +08:00
李通洲 6e50aaf3ff Brightness (Windows): uses COM-less method to query WMI
Co-authored-by: Copilot <copilot@github.com>
2026-04-29 00:11:29 +08:00
李通洲 e7cd5f618d Bluetooth (Windows): uses CM API to detect BTH battery detection
Co-authored-by: Copilot <copilot@github.com>
2026-04-28 19:52:38 +08:00
李通洲 55e4896524 Chore: runs clang-format 2026-04-28 19:45:19 +08:00
李通洲 594c73461e Netif: fixes compiler warnings 2026-04-28 15:19:44 +08:00
Or-simen 94ceeb4482 Chore: fixes typo from FF_UNITIALIZED to FF_UNINITIALIZED (#2290)
Co-authored-by: or sim <you@example.com>
2026-04-27 21:23:42 -05:00
李通洲 4ee7dd72d0 IO: improves code quality & reliablity 2026-04-28 09:03:24 +08:00
李通洲 414f7ce067 Netif: improves code quality
Co-authored-by: Copilot <copilot@github.com>
2026-04-28 08:51:03 +08:00
李通洲 e1dffe794b Library: improves code quality
Co-authored-by: Copilot <copilot@github.com>
2026-04-28 08:51:03 +08:00
李通洲 181b775f73 Init: don't print unecessary ANSI escape codes
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 23:15:30 +08:00
李通洲 c4c934d23e Format: fixes UINT64 handling
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 23:00:52 +08:00
李通洲 31c73543e8 Font: improves pt handling
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 22:57:29 +08:00
李通洲 d79e1d7fbc FFstrbuf: improves robustness of ffStrbufMatchSeparatedNS
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 22:49:31 +08:00
李通洲 3883047dce Platform: initializes pageSize
Noop, because the whole platform is statically initialized

Co-authored-by: Copilot <copilot@github.com>
2026-04-27 22:35:11 +08:00
李通洲 4eebc1b6ee Platform (Windows): adds comments
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 22:30:48 +08:00
李通洲 08b79ff4ae Platform (OpenBSD): silences a compiler warning
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 22:27:10 +08:00
李通洲 ffc38eb0f1 FFlist: add __restrict 2026-04-27 22:21:45 +08:00
李通洲 37ee193c40 DBus: improves message handling 2026-04-27 22:11:34 +08:00
李通洲 c10027f1d7 JsonConfig: fixes CPUUsage preparation never executed
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 21:56:52 +08:00
李通洲 039fa1ba77 CommandOption: generates JSON result entry even for unknown modules
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 20:28:11 +08:00
李通洲 0db820a6c1 Binary: skips short string entirely to improve performance
Co-authored-by: Copilot <copilot@github.com>
2026-04-27 19:51:14 +08:00
tnut 8b611899d1 Packages (Linux): adds cards counting (NuTyX) (#2287)
* Packages:add cards counting (NuTyX)

* package.c
no need to add counts.catds

* Sort packages print alphabetically

* ditto

* ditto

* packages.c
update FF_ARG and ffpackagesModule.info

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-04-27 19:31:08 +08:00
李通洲 ba7e1eb18b Netif (Windows): correctly selects lowest-metric default route on IPv4
... and improve performance slightly
2026-04-26 16:57:38 +08:00
李通洲 6979b1efc5 Dep (3rdparty): upgrades display-library 2026-04-26 16:00:01 +08:00
Carter Li 4a61cdb1c9 Merge pull request #2280 from fastfetch-cli/dev
Release v2.62.1
2026-04-23 20:12:45 +08:00
李通洲 75c28ec671 Release: v2.62.1 2026-04-23 19:09:24 +08:00
李通洲 639252ece0 Logo (Builtin): adds uzbek
Fixes #2159
2026-04-23 15:19:33 +08:00
lost a31d8ce87b Logo (Builtin): adds support for Redrose (#2236)
* Added support for Redrose.

* Remove 'redrose' OS identification logic

* Remove dollar signs from ASCII art in redrose.txt

* Update logo name from 'redrose' to 'Redrose'

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-04-23 02:19:19 -05:00
Uzair Mughal 41143c23f4 Logo (Builtin): adds LimeOS logo (#2137)
* Logo (Builtin): adds LimeOS logo

Adds support for LimeOS, a Debian-based distribution.

- Adds ASCII logo (white color scheme)
- Adds OS detection for `ID=limeos`

Homepage: https://limeos.org

* Logo (Builtin): adds LimeOS logo

Adds support for LimeOS, a Debian-based distribution.

Homepage: https://limeos.org

* Logo (Builtin): adds LimeOS logo

* Update builtin.c
2026-04-23 01:53:11 -05:00
Endscape 3c2e21b7b1 Logo (Builtin): adds EN-OS
[LOGO] Add EN-OS
2026-04-23 01:51:50 -05:00
Carter Li 3eaebd3359 Host (Linux): fixes host is missing in some machine
Fixes #2279
2026-04-23 09:35:03 +08:00
Carter Li 768bc154d4 Packaging: updates debian stuff [ci skip] 2026-04-22 10:02:21 +08:00
Carter Li 00cc19e28b Merge pull request #2277 from fastfetch-cli/dev
Release v2.62.0
2026-04-22 09:35:08 +08:00
李通洲 bf0564f9e5 Terminal (Windows): removes using of Win32 registry APIs 2026-04-21 23:41:34 +08:00
Carter Li dbb060eb62 Global: addresses AI's comments 2026-04-21 19:43:11 +08:00
Carter Li 1314c18a52 Release: v2.62.0 2026-04-21 17:15:23 +08:00
李通洲 05f5e25c66 Packages: rearranges the packages output in alphabet order
... and improves string format logic
2026-04-21 14:41:27 +08:00
李通洲 4b4c37ed88 Packages (Linux): adds AppImage packages support
Fixes #2179
2026-04-21 14:16:55 +08:00
李通洲 8970774e5f Doc: update changelog [ci skip] 2026-04-21 10:53:19 +08:00
Carter Li 69c86c95b7 GPU: hard codes QEMU virtual GPU 2026-04-20 22:30:51 +08:00
李通洲 910ba413da Modules: adds missing options when generating full config file 2026-04-20 16:14:58 +08:00
李通洲 dbed1b32b4 Style: runs clang-format 2026-04-20 15:22:10 +08:00
李通洲 278a3834ce Logo (Image): uses iterm image protocol on iTerm terminal
Fixes #2246
2026-04-18 23:30:20 +08:00
李通洲 5ce3220f50 Logo (Builtin): updates AerynOS
Fixes #2272
2026-04-18 23:16:37 +08:00
李通洲 c1c6ccce9a Shell (Linux): fixes ash version detection
Fixes #2271
2026-04-17 18:50:35 +08:00
李通洲 e2526521a2 Smbios: fixes typo 2026-04-16 23:18:56 +08:00
李通洲 1956c66a5e PhysicalMemory (Android): fixes compiling 2026-04-16 22:42:59 +08:00
李通洲 c601b68bc6 Doc: improves overall English grammer 2026-04-16 18:27:11 +08:00
李通洲 528f9f152c Config: adds display.common.(ndigits|spaceBeforeUnit) 2026-04-16 15:45:12 +08:00
李通洲 64d2c4410e Binary (macOS): improve performance with mmap(2) 2026-04-16 15:15:50 +08:00
李通洲 6e4de3e9f1 Platform (Windows): uses LsaGetUserName to acquire user name 2026-04-16 15:03:08 +08:00
Carter Li ce51dbf7ea Smbios (Linux): fixes compiling errors 2026-04-16 15:03:08 +08:00
李通洲 abc6c0593c Chore: IndentPPDirectives: BeforeHash [ci skip] 2026-04-15 16:17:08 +08:00
李通洲 b63bd5b8c9 Smbios: refactors code 2026-04-15 16:13:56 +08:00
李通洲 4236d830cc Options: uses enums instead of hard code number [ci skip] 2026-04-15 10:09:44 +08:00
李通洲 c851c39837 Options: fixes copy&paste errors 2026-04-15 09:56:23 +08:00
Carter Li 1cd196b726 Smbios: uses the standard type off_t 2026-04-15 09:02:35 +08:00
李通洲 f8a8864be5 Smbios (OpenBSD): reads table address from dmesg 2026-04-15 09:02:35 +08:00
Carter Li 683e90cec6 Smbios (FreeBSD): unifies pread/mmap handling
Don't try `pread(/dev/mem)` on FreeBSD, which causes kernel panic
2026-04-15 09:02:35 +08:00
李通洲 08de5eabed Sound: merges isMain and isActive to type 2026-04-15 09:02:35 +08:00
李通洲 c7ecc33b64 Global: removes FFlist::elementSize
Improves performance of module Sound and PhysicalMemory
2026-04-14 15:47:26 +08:00
Carter Li ee7f574349 Smbios (OpenBSD): reads table address from dmesg 2026-04-14 15:47:26 +08:00
Carter Li 10f58e405e Smbios (FreeBSD): adds fallback method for non-UEFI systems 2026-04-14 00:20:01 +08:00
Carter Li d81a7b6278 Smbios: improves logging 2026-04-13 18:20:19 +08:00
李通洲 48daf4ac1e Camera (macOS): fixes a compiler warning 2026-04-13 16:16:57 +08:00
李通洲 6d01c0b438 PhysicalDisk (NetBSD/OpenBSD): adds debug logs 2026-04-13 14:25:42 +08:00
李通洲 3cc0e40e5a Smbios: updates EMTF standard version 2026-04-13 09:38:47 +08:00
李通洲 679def253d Global: formats code [ci skip] 2026-04-12 19:19:55 +08:00
李通洲 4dc5033c80 PowerAdapter (Linux): checks if the device is present 2026-04-10 08:48:55 +08:00
Carter Li b3603391eb Battery: refactors status field from string to bit-fields 2026-04-09 20:02:04 +08:00
Carter Li f6a363f7ad Global: unifies GCC attributes usage 2026-04-09 20:02:04 +08:00
Carter Li 3e69361196 Battery (OpenBSD): adds Unknown state 2026-04-09 15:49:41 +08:00
Carter Li 04bd5045b9 PowerAdapter (Linux): tidy 2026-04-09 15:20:36 +08:00
李通洲 886bde47d6 Battery (Linux): checks if battery's present before parsing 2026-04-09 14:01:24 +08:00
李通洲 254fb82520 Battery (Linux): fixes AC status can be incorrectly detected as Connected
... in machine that has multiple batteries

Fixes #2263
2026-04-09 13:54:50 +08:00
李通洲 af884bb638 FFstrbuf: silence a compiler warning 2026-04-09 13:54:50 +08:00
李通洲 e8e43c10fc PhysicalDisk: renames hideUnknown for hideUnused 2026-04-09 13:54:50 +08:00
李通洲 9090dbd276 PhysicalDisk (macOS): detects 0-size disks 2026-04-09 13:54:50 +08:00
李通洲 f683586623 Swap (Windows): fixes out-of-bound memory access when swaps are disabled 2026-04-09 13:54:50 +08:00
Carter Li d71d6a679d Swap (macOS): fixes a compiler warning 2026-04-09 13:54:50 +08:00
李通洲 17eb22dfdb PhysicalDisk: adds option hideVirtual (defaults to false) and hideUnknown (defaults to true) 2026-04-09 13:54:50 +08:00
Carter Li c09a788ce3 PhysicalDisk (OpenBSD): honors namePrefix 2026-04-09 09:35:48 +08:00
Carter Li ab32056c3f PhysicalDisk (NetBSD): honors namePrefix 2026-04-09 09:35:48 +08:00
李通洲 e15049856f GPU (Windows): improves support of non-PCI devices 2026-04-09 09:35:48 +08:00
李通洲 16423487fb GPU (Windows): updates comments 2026-04-09 09:35:48 +08:00
李通洲 6b95eb2c74 GPU: fixes the vendor name of Parallels 2026-04-09 09:35:48 +08:00
Faisal Ahmed Moshiur 2b82e9ab02 Fix potential use-after-free and overlapping memory copy in ffStrbufSetNS 2026-04-09 09:33:58 +08:00
李通洲 5fe2cc6350 PhysicalDisk (Windows): adds simple debug log 2026-04-06 10:36:46 +08:00
李通洲 50739ee890 Cursor (Windows): fixes Win8.1 support 2026-04-06 10:00:40 +08:00
李通洲 97ce079488 GPU (Windows): adds fallback method for GPU vendor detection 2026-04-06 09:33:23 +08:00
Carter Li 7045dea284 Global (Windows): fixes building on i686 2026-04-05 14:40:38 +08:00
李通洲 7887067301 PhysicalDisk (Windows): switches to CMAPI; adds floppy support 2026-04-05 20:37:23 +08:00
李通洲 39cfc7aac8 Debug (Windows): ensures UTF-8 output 2026-04-05 20:21:50 +08:00
李通洲 44af8b85ad Battery (Windows): tidy 2026-04-05 20:21:50 +08:00
李通洲 85594d2056 GPU (Windows): restores Win8.1 support 2026-04-05 14:26:22 +08:00
Данил Голдышев 14cd933969 fix(help): align format placeholders dynamically 2026-04-05 10:32:23 +08:00
Данил Голдышев 6550b77c2f fix(zpool): correct documented format placeholders 2026-04-05 10:32:23 +08:00
李通洲 7147f23504 GPU (Windows): ignores invalid D3DKMT responses 2026-04-05 01:31:14 +08:00
李通洲 94164b873c GPU (WSL): unifies code with the windows version 2026-04-05 00:37:58 +08:00
李通洲 9cfe7a74bc GPU (Windows): rewrites with D3DKMT APIs
... which aligns to WSL impl
2026-04-05 00:37:58 +08:00
Eli Sher 604aacbae2 Wifi (macOS): corrects typo in WPA Personal Mixed security string (#2260) 2026-04-04 23:39:53 +08:00
Carter Li 04c486d3db PhysicalDisk (SunOS): detects unknown type 2026-04-04 00:29:08 +08:00
Carter Li 152f3cdee1 Disk (SunOS): trims disk name 2026-04-04 00:18:42 +08:00
李通洲 b7890e1e2a PhysicalDisk (SunOS): better device type detection 2026-04-04 00:08:25 +08:00
李通洲 8913620aa5 PhysicalDisk (NetBSD): fixes building on older systems 2026-04-03 22:32:35 +08:00
李通洲 2a103f620d PhysicalDisk (NetBSD): adds support
Requires root permission
2026-04-03 21:01:49 +08:00
李通洲 8d0ceff7fa PhysicalDisk (OpenBSD): fixes issues found later 2026-04-03 21:01:15 +08:00
李通洲 ce9f4daec4 PhysicalDisk: adds unknown in JSON result 2026-04-03 15:45:10 +08:00
李通洲 e639700387 PhysicalDisk (OpenBSD): fix potencial out-of-bound read 2026-04-03 15:44:47 +08:00
李通洲 3da344db1f DiskIO (NetBSD): ignores partitions 2026-04-03 10:53:51 +08:00
Carter Li 31a35cf845 Bios (NetBSD): adds fall back method 2026-04-03 10:25:04 +08:00
李通洲 77c916f747 CI: splits different jobs into different yml files 2026-04-03 08:55:38 +08:00
李通洲 c9dbf990d8 PhysicalDisk (OpenBSD): adds support 2026-04-02 20:10:14 +08:00
李通洲 ed4d903e69 Sysctl (OpenBSD): improves error messages 2026-04-02 20:06:23 +08:00
李通洲 299451ca62 GPU (Linux): ensures we don't pass invalid length to calloc
Fixes #2259
2026-04-01 23:31:36 +08:00
李通洲 6319b68c2c PhysicalDisk (FreeBSD): adds type virtual and type unknown detection 2026-04-01 15:08:44 +08:00
李通洲 c37ac4da2b PhysicalDisk (Windows): adds type virtual and type unknown detection 2026-04-01 15:08:26 +08:00
李通洲 643db92cd1 PhysicalDisk (Linux): adds type unknown detection 2026-04-01 15:08:02 +08:00
李通洲 99795154b5 PhysicalDisk (macOS): adds type unknown detection 2026-04-01 15:06:15 +08:00
Carter Li 6cf403da7d Global: renames smbiosHelper to smbios 2026-03-31 20:01:25 +08:00
Carter Li 4f3e82330b Smbios: improves log 2026-03-31 19:58:47 +08:00
李通洲 0c401a0112 PhysicalDisk: detects virtual disks 2026-03-31 19:48:54 +08:00
李通洲 d4b1ae9751 PhysicalDisk / DiskIO (macOS): improves performance by query less IO entries 2026-03-31 14:20:21 +08:00
李通洲 831659966f Style: adds Cpp11BracedListStyle: Block 2026-03-31 14:20:21 +08:00
李通洲 5f261702a9 Style: adds BreakBeforeCloseBracketBracedList: true 2026-03-31 14:20:21 +08:00
李通洲 c2da9b0cb1 Chore: tidy 2026-03-31 14:20:21 +08:00
李通洲 239233f4e0 Swap (macOS): don't check if swap is enabled on macOS 26 or later 2026-03-31 14:20:21 +08:00
Eitan b00593ae05 JsonSchema: adds "command-raw" to schema (#2255)
* Add "command-raw" to json_schema.json

* I spelled it wrong
2026-03-31 13:11:14 +08:00
Roshan Warrier b4e6688dfe Localip: uses assigned netlink port id on Linux (#2253)
Fixes #2252
2026-03-30 18:39:43 +08:00
Carter Li b022babd7e Packaging: update debian stuff [ci skip] 2026-03-30 10:33:58 +08:00
Carter Li 52c7f9f973 Swap (macOS): display Unused instead of Disabled for 0/0
Fixes #2248
2026-03-29 11:19:07 +08:00
李通洲 e0eba8ce21 Chore: run clang-format
```bash
find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) ! -path "src/3rdparty/*" -print0 | xargs -0 clang-format -i
```
2026-03-29 10:03:32 +08:00
李通洲 cdd4cee968 Chore: add clang-format configuration 2026-03-29 10:03:22 +08:00
李通洲 1b23edc5c1 Flashfetch: reduces duplicated code 2026-03-29 09:30:00 +08:00
Carter Li e5d6006006 Merge pull request #2244 from fastfetch-cli/dev
Release: v2.61.0
2026-03-28 14:10:34 +08:00
李通洲 18f3809681 Display: rounds scaled size when calcuating
Follows 179539ccba
2026-03-28 13:01:16 +08:00
李通洲 1cd87dc994 GPU (Windows): silences a compiler warning [ci skip] 2026-03-28 12:52:33 +08:00
李通洲 1e58e04024 Doc: updates changelog [ci skip] 2026-03-28 12:49:23 +08:00
李通洲 408d939664 GPU (Windows/WSL): adds basic GPU type detection code 2026-03-28 12:11:29 +08:00
李通洲 9b1061719c Chore (OpenBSD): silences compiler warnings 2026-03-28 12:04:10 +08:00
李通洲 179539ccba Display: rounds scaled size when calcuating
Follows f50059dc7b
2026-03-28 08:50:15 +08:00
李通洲 6d73ecb944 CI: updates deps 2026-03-27 20:53:57 +08:00
李通洲 b981e4fd8b GPU (Windows): adds GPU type detection fallback with DXCore
Requires installation of `directx-headers`

Was using it in WSL -_-!!
2026-03-27 20:53:57 +08:00
李通洲 8e660136e0 GPU (WSL): increases maximum number of GPU adapters 2026-03-27 20:41:51 +08:00
李通洲 90ca39b464 Debug (Windows): adds ffDebugHResult 2026-03-27 20:14:47 +08:00
李通洲 63f7e15554 Sound (Windows): tidy 2026-03-27 20:14:21 +08:00
李通洲 ab37216f7d GPU (Windows): logs driver-specific detection error message 2026-03-27 15:37:33 +08:00
李通洲 57440a7a45 Global (Windows): makes NtWaitForSingleObject not alertable 2026-03-27 14:37:41 +08:00
李通洲 f50059dc7b Display: rounds scaled size when calculating 2026-03-27 14:35:29 +08:00
李通洲 92fb5cb0c1 GPU (WSL): supports VMEM total size query on Windows 10
Also adds debug logs
2026-03-27 13:33:38 +08:00
李通洲 5f84630276 CI (macOS): disables vulkan because it crashes on Intel build 2026-03-27 09:50:32 +08:00
李通洲 22696fe3de Common (Windows): fixes buf len handling 2026-03-26 23:41:17 +08:00
李通洲 cd00820546 FFstrbuf: adds a comment 2026-03-26 23:39:47 +08:00
李通洲 918153f974 Host (macOS): fixes typo 2026-03-26 23:39:31 +08:00
李通洲 58e67dcc7a Common (Windows): fixes potential out-of-bound mem access 2026-03-26 23:31:59 +08:00
李通洲 940d15c2e6 Doc: updates changelog [ci skip] 2026-03-26 23:17:03 +08:00
李通洲 9ffa46652d Common (Windows): remove default language attempt when querying file version 2026-03-26 23:08:28 +08:00
李通洲 d45dc53da0 GPU (OpenBSD): silences compiler warnings 2026-03-26 22:53:43 +08:00
李通洲 00d1812e8d Debug (Windows): let OS choose language to print 2026-03-26 22:53:28 +08:00
李通洲 50dc260fd6 Common (Windows): fixes str length variable handling 2026-03-26 20:27:57 +08:00
李通洲 bf99aeda92 Global: replaces %m for %s + strerror(errno)
Not portable

This reverts aabab6dff5
2026-03-26 19:54:10 +08:00
李通洲 397822d0db Global (Windows): resets console codepage on program exit
Fixes #2245
2026-03-26 18:22:00 +08:00
李通洲 12746a9681 Global: fixes issues raised by AI 2026-03-26 16:40:15 +08:00
李通洲 355e21c099 Release: v2.61.0 2026-03-26 15:23:51 +08:00
李通洲 9036b891a8 Host (macOS): adds new M5 models 2026-03-26 15:18:14 +08:00
李通洲 b7e4e91664 JsonSchema: regenerates moduleFormat 2026-03-26 15:01:31 +08:00
李通洲 aabab6dff5 Global (Linux): replaces strerror(errno) with %m 2026-03-26 14:55:46 +08:00
李通洲 62c2eb4d96 Networking (Linux): shutdown before recv 2026-03-26 14:47:33 +08:00
李通洲 c69a6b7640 Processing (Linux): reports command not found earlier 2026-03-26 14:23:12 +08:00
李通洲 0521513609 Sound (Windows): a small refactor 2026-03-25 16:17:20 +08:00
李通洲 a1c5fe2bf2 Processing (Windows): improves reliablity when terminating child process 2026-03-25 15:40:33 +08:00
李通洲 2d4a77b6f0 Networking (Windows): waits for completion of CancelIO 2026-03-25 15:03:23 +08:00
李通洲 9027f72353 Wifi (Linux): decodes SSID string printed by iw 2026-03-25 14:14:26 +08:00
李通洲 fe0f292cec FFstrbuf: adds new ffStrbufDecodeHexEscapeSequences 2026-03-25 14:13:03 +08:00
Carter Li 06ecd5a1ff Smbios (Linux): improve performance of small file reading 2026-03-25 11:05:36 +08:00
Carter Li 8fdaa987e3 IO: inlines more helper functions 2026-03-25 10:41:10 +08:00
李通洲 15804091b0 PhysicalDisk (Windows): detects tape devices 2026-03-24 18:42:56 +08:00
李通洲 d8b44a5eae Monitor: updates the description 2026-03-24 17:40:46 +08:00
李通洲 6357dcc6b4 README: adds comments 2026-03-24 17:40:22 +08:00
李通洲 947cddd926 Binary (Windows): fixes unmatched fn calls 2026-03-24 17:20:47 +08:00
李通洲 246ff0bc88 Common (Windows): adds a unique type for querying registry binary data 2026-03-24 17:20:47 +08:00
李通洲 339de56407 PhysicalMemory (macOS): don't set runningSpeed 2026-03-24 15:17:40 +08:00
Carter Li 795bbde459 Smbios: improves robostness; adds maiformed SMBIOS data verification and more debug log 2026-03-24 15:12:21 +08:00
李通洲 f32bf9e94f Bios (macOS): tidy 2026-03-24 15:12:21 +08:00
李通洲 8facb7c6e9 Uptime (Windows): improves comments 2026-03-23 16:01:29 +08:00
李通洲 92c65aad10 Font (Windows): reads Control Panel registry directly
Improves performance
2026-03-23 10:50:03 +08:00
李通洲 76d6e86fe5 Time (Windows): prefers RTL APIs 2026-03-23 10:03:12 +08:00
李通洲 e3d7eab4df Binary (Windows): prefers NT APIs 2026-03-23 09:54:04 +08:00
李通洲 ff8d4b46ef Icons (Windows): handles the case when users never changes the default settings 2026-03-22 20:21:11 +08:00
李通洲 4fb7860a8e Common (Windows): uses RtlOpenCurrentUser directly 2026-03-22 19:52:41 +08:00
李通洲 f188e9518d Colors: add brightness option for color display configuration
Fixes #2238
2026-03-22 13:43:16 +08:00
李通洲 a39419b12a Chore: tidy 2026-03-22 13:26:05 +08:00
李通洲 941502d718 Platform (Windows): fixes kernel version detection on Win 8 2026-03-21 23:19:45 +08:00
李通洲 de146c6370 Windows: removes 7/8 from manifest.xml 2026-03-21 23:19:23 +08:00
李通洲 09efb0d897 Host: fixes building on niche platforms 2026-03-21 22:39:42 +08:00
李通洲 8defffabff DisplayServer (Linux): fixes build failure on older Wayland versions
Fixes #2237
2026-03-21 18:56:23 +08:00
Carter Li 1b543b1eb8 PhysicalMemory: ignores custom SMBIOS entry
Fixes less memory devices are reported on certain devices
Found this issue on my old Intel MacBook Pro
2026-03-21 18:44:20 +08:00
Carter Li ab17fb08ef Global (macOS): queries SMBIOS data directly on Intel Mac 2026-03-21 18:38:01 +08:00
Carter Li a4bc3c812d SMBIOS: improves garbage data cleanup code 2026-03-21 18:27:48 +08:00
李通洲 c8fcabf4cc GPU (WSL): don't try to fetch info on unsupported systems 2026-03-21 11:04:07 +08:00
李通洲 a961a964ff GPU: adds more useful info 2026-03-21 11:03:32 +08:00
李通洲 412de625b2 GPU (Windows): detects used memory size by D3DKMT 2026-03-20 21:59:11 +08:00
李通洲 b739736527 GPU (WSL2): moves to D3DKMT/WDDM
Removes C++ dependency on Linux
2026-03-20 19:14:55 +08:00
李通洲 2b19f8078e GPU (Windows): prepares Linux support of d3dkmthk.h 2026-03-20 19:14:49 +08:00
李通洲 56eabbe2cb Brightness (Windows): queries monitor description if display name is not available 2026-03-19 18:07:24 +08:00
李通洲 b0215aae37 Common (Windows): fixes random failures of WMI initialization 2026-03-19 15:46:19 +08:00
李通洲 86cfa4eded Library (Windows): prefers Ldr APIs 2026-03-19 15:24:55 +08:00
李通洲 bab1e4ff82 Global (Windows): adds full TEB/PEB definitions 2026-03-19 15:16:50 +08:00
李通洲 6ec59f8654 Brightness (Windows): fixes detection of external monitors 2026-03-19 00:56:02 +08:00
李通洲 d3459af71f LocalIP: removes usage of htonl 2026-03-18 18:52:24 +08:00
李通洲 00b5f17f0d Global (Windows): prefers Rtl APIs 2026-03-18 18:36:41 +08:00
李通洲 b8ad833b4b Networking (Windows): prefers WSA functions 2026-03-18 18:35:59 +08:00
李通洲 fb412576e1 Host (macOS): updates M5 models 2026-03-18 13:11:07 +08:00
李通洲 d551651d63 WM (macOS): adds glazewm; removes unmaintained plugins 2026-03-18 10:56:09 +08:00
李通洲 4e234c52a3 Platform (Windows): adds implementation of POSIX readlink(2) and realpath(3) 2026-03-17 17:59:24 +08:00
李通洲 edc718d1d1 Locale: reports API failure messages 2026-03-17 17:33:02 +08:00
李通洲 42e01e7b8f Global (Windows): uses GetCurrentConsoleFontEx instead of GetCurrentConsoleFont 2026-03-16 15:16:54 +08:00
李通洲 8edfda979e Processing (Windows): prefers *W version APIs 2026-03-16 15:09:43 +08:00
李通洲 cc3595c3a4 Processing (Windows): prefers NT APIs 2026-03-16 14:41:52 +08:00
李通洲 8c72792e31 Common (Windows): adds a universal function ffFileTimeToUnixMs and use it 2026-03-16 13:49:49 +08:00
李通洲 f7ebeb58e2 Packages (Windows): prefers NT APIs 2026-03-16 10:50:30 +08:00
Carter Li ea4a4f0691 CPUCache (Linux): makes shared cache dedupe key boundary-safe
Fixes #2228
2026-03-16 09:52:43 +08:00
李通洲 81984e6e97 Global (Windows): prefers NtWaitForSingleObject 2026-03-14 23:36:59 +08:00
李通洲 f46e97fc62 Common (Windows): fixes querying HKEY_LOCAL_MACHINE on Windows 8.1
... and adds debug log
2026-03-14 22:57:29 +08:00
李通洲 7821552761 Common (Windows): adds ffDebugNtStatus for debugging 2026-03-14 22:55:16 +08:00
李通洲 cd8a0fc5f1 Global: enables debug mode when $FF_DEBUG is set
in case of `debugMode` is accessed before `--debug` is parsed
2026-03-14 22:27:36 +08:00
Carter Li 30f32f1fb5 CI (DFBSD): workarounds building errors 2026-03-14 21:52:55 +08:00
Carter Li 9af918b1ef DisplayServer (Linux): swaps width/height in vertical mode and native X11 2026-03-13 23:47:39 +08:00
李通洲 37b8bb4fc0 DisplayServer: reports DPI instead of scaled resolution
Fixes #2224
2026-03-13 20:44:21 +08:00
李通洲 66edea702e Common (Windows): reverts 42509f115c
Fixes warp terminal version detection
2026-03-13 13:58:50 +08:00
李通洲 930fb06ca7 TerminalFont (Windows): adds style detection support for warp terminal 2026-03-13 13:27:58 +08:00
李通洲 ca9c67353f Global (Windows): prefers NtClose over CloseHandle 2026-03-13 13:27:58 +08:00
李通洲 ea6ad4ac86 Global (Windows): prefers NTAPI for querying registry values 2026-03-13 13:27:58 +08:00
李通洲 6ed8aac6bb FFlist: adds ffListReserve 2026-03-13 09:52:18 +08:00
李通洲 cfabee4ba7 Common: adds ffEdidIsValid 2026-03-13 09:39:28 +08:00
李通洲 3a35f9735b Global: renames FFformatArgType to FFArgType for future reuse 2026-03-12 15:07:19 +08:00
Carter Li 05fa8b0994 CI (Linux): fixes a CI error
```
kde-output-device-v2-client-protocol.h:257:9: error: implicit declaration of function 'wl_proxy_marshal_flags'; did you mean 'wl_proxy_marshal_array'? [-Werror=implicit-function-declaration]
    257 |         wl_proxy_marshal_flags((struct wl_proxy *) kde_output_device_registry_v2,
        |         ^~~~~~~~~~~~~~~~~~~~~~
        |         wl_proxy_marshal_array
```
2026-03-12 10:06:00 +08:00
Carter Li 07f6f93415 Host (Linux): reports marketing product name on Asahi Linux 2026-03-12 10:01:40 +08:00
李通洲 d2de3a01bb IO (Windows): prefers native functions 2026-03-11 23:28:41 +08:00
李通洲 c9b7c65ba5 Brightness (Linux): prefers FF_LIBRARY_LOAD_SYMBOL_LAZY 2026-03-11 22:40:14 +08:00
李通洲 6ad8e68d26 Global: simplifies code with __auto_type 2026-03-11 22:40:14 +08:00
李通洲 b128260eb2 IO (Windows): improves sub directory creation logic 2026-03-11 22:40:13 +08:00
李通洲 ecfaf4d54d IO (Windows): fixes wrong va_list handling 2026-03-11 22:40:13 +08:00
李通洲 72bdee7fbf Global (Windows): prefers RtlUnicodeToUTF8N instead of WideCharToMultiByte 2026-03-11 22:40:13 +08:00
李通洲 bdb9593c0d Platform (Windows): prefers data in PEB 2026-03-11 22:40:13 +08:00
Carter Li 1e234754c2 PhysicalMemory (Linux): adds option showEmptySlots to show empty memory slots
Fixes #2222
2026-03-11 22:33:32 +08:00
Carter Li 4a4afdadb8 Keyboard (Linux): optimises detection code & reduces syscalls
Ref: #2220
2026-03-11 10:42:27 +08:00
Benny Powers 7cadece9a0 Keyboard (Linux): adds Bluetooth support (#2220)
* Keyboard (Linux) Bluetooth support

* fix: code review

* fix: code review

* fix: code review
2026-03-11 09:30:59 +08:00
李通洲 724ab6ba69 Platform (Windows): prefers info inside TEB/PEB 2026-03-09 20:25:10 +08:00
李通洲 6370485dcb Processing (Windows): prefers NT APIs 2026-03-09 20:24:19 +08:00
李通洲 60d343ca14 Platform (Windows): simplifies SID retrival 2026-03-09 20:19:47 +08:00
李通洲 bdc844f857 Bootmgr (Windows): prefers NT APIs 2026-03-09 15:20:01 +08:00
李通洲 d49c018f86 Common (Windows): updates nt.h 2026-03-09 15:19:36 +08:00
李通洲 be2201b5fc Platform (Windows): don't use instance.config here
... as it's not initialized yet
2026-03-07 23:50:31 +08:00
李通洲 9ba1cd1291 DisplayServer (Linux): updates kde-output-device-v2 again 2026-03-07 23:50:31 +08:00
butteronarchbtw 22fa9b51e8 WM (Linux): fixes version reporting for niri WM (#2218)
Signed-off-by: butteronarchbtw <152636161+butteronarchbtw@users.noreply.github.com>
2026-03-07 23:29:08 +08:00
李通洲 f781f8d9ea Global (Windows): drops WIN7_COMPAT support 2026-03-07 11:49:56 +08:00
Carter Li 06ecc9c480 Merge pull request #2217 from fastfetch-cli/dev
Release: v2.60.0
2026-03-06 21:08:19 -06:00
李通洲 50288d91e4 Doc: updates changelog [ci skip] 2026-03-07 10:43:16 +08:00
李通洲 499b4ff445 Kmod (Windows): don't specify maybe_unused on used params 2026-03-07 10:43:01 +08:00
李通洲 dd0021cd5e GPU (Windows): adds kernel version check before D3DKMT syscall 2026-03-07 10:34:21 +08:00
李通洲 f5b70dd8b7 Doc: updates changelog 2026-03-07 09:31:26 +08:00
李通洲 8f8ca11203 Kernel (Windows): simplifies kernel version detection 2026-03-07 09:26:13 +08:00
李通洲 121d399641 CPUUsage (Windows): simplifies Win10 detection 2026-03-07 09:24:38 +08:00
李通洲 26ae4eb21b Chore (Windows): removes unnecessary headers 2026-03-07 01:18:07 +08:00
李通洲 52a81dbdc4 Disk (Windows): reads SystemWindowsDirectory directly from SharedUserData 2026-03-07 00:35:07 +08:00
李通洲 f924a8bf06 Uptime: reads (System|Interrupt)Time directly from SharedUserData 2026-03-07 00:09:08 +08:00
李通洲 c7363f904a Common (Windows): adds definition of KUSER_SHARED_DATA 2026-03-06 23:59:19 +08:00
李通洲 53ffe8459f Global: applies Copilot's suggestions 2026-03-06 18:33:29 +08:00
李通洲 1b702e123e Release: v2.60.0 2026-03-06 15:27:55 +08:00
李通洲 14dccce393 CI (Linux): builds fastfetch with chafa support 2026-03-06 15:27:55 +08:00
李通洲 d040cc810f SMBIOS (Windows): fixes issues raised by Copilot 2026-03-06 14:46:51 +08:00
李通洲 224bea2559 WM (Windows): fixes issues raised by Copilot 2026-03-06 14:36:40 +08:00
李通洲 777d3e599d WM (macOS): fixes issues raised by Copilot 2026-03-06 14:09:13 +08:00
李通洲 7c47bc2656 WM: honors general.detectVersion 2026-03-06 11:10:35 +08:00
李通洲 e4d31381d8 WM (macOS): fetches WM plugin version 2026-03-06 11:08:41 +08:00
Dariqq abf8d75454 Chore (Windows): adds missing header (#2215) 2026-03-05 18:39:03 -06:00
李通洲 2ce152beaf SmbiosHelper (Windows): prefers NtQuerySystemInformation 2026-03-05 10:18:18 +08:00
李通洲 766ed07999 Refactor: prefers ffStr* 2026-03-05 10:16:24 +08:00
李通洲 ddc2131343 Chore (Windows): adds comments 2026-03-05 10:16:11 +08:00
Carter Li b64d8a013d DisplayServer (Linux): check if RANDR is running in Emulation mode 2026-03-05 10:12:38 +08:00
Carter Li e6db59fdde WM (Linux): fix niri version detection logic 2026-03-05 08:45:56 +08:00
李通洲 7ea0bbfb21 CPU / CPUCache (Windows): prefers NtQuerySystemInformation(Ex) 2026-03-03 16:01:36 +08:00
李通洲 ab041e0ad2 JsonSchema: update [ci skip] 2026-03-03 14:34:45 +08:00
李通洲 207f742624 TerminalFont (Windows): hardens the Windows Terminal font detection logic 2026-03-03 14:21:19 +08:00
李通洲 68f0b11b6f WM (Windows): loads wintrust lazily 2026-03-03 11:00:41 +08:00
李通洲 b86c0880b9 Bluetooth (Windows): adds a string variant helper; removes propsys dependency 2026-03-03 11:00:37 +08:00
李通洲 75f4a3d92d Platform (Windows): don't error out on i686 2026-03-03 08:47:34 +08:00
李通洲 70fa1341a8 Bootmgr (Windows): prefers NT API 2026-03-03 08:47:21 +08:00
李通洲 0a55314d37 WM (Windows): uses WinVerifyTrustEx consistantly 2026-03-03 00:27:28 +08:00
李通洲 2198e6123e DisplayServer (Windows): uses the standard GetDpiForMonitor to query scale factors 2026-03-03 00:23:36 +08:00
李通洲 dd37ee0e50 Doc: updates README [ci skip] 2026-03-01 19:27:33 +08:00
李通洲 7006ae0420 CMake (Windows): disable ENABLE_WIN7_COMPAT by default 2026-03-01 19:12:35 +08:00
李通洲 86458ab32a Kmod (SunOS): adds support 2026-03-01 14:44:29 +08:00
李通洲 67ca907e38 Kmod (Windows): adds support 2026-03-01 14:06:54 +08:00
李通洲 e15d06bbad Chore (Windows): move NT stuff to common 2026-03-01 13:58:38 +08:00
zamhedonia eb53797174 Logo (Builtin): adds support for Emmabuntüs (#2207)
* Logo (Builtin): adds Emmabuntüs Logo

* Add Detection for Emmabuntüs

* Update ASCII art in emmabuntus.txt

* Remove duplicate name for Emmabuntus logo

* Update emmabuntus.txt

* Update colors for Emmabuntus logo

---------

Co-authored-by: zamhedonia <zamhedonia@gmx.de>
Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-03-01 00:13:16 +08:00
李通洲 c8c32a78b0 Presets: adds examples/32 2026-02-28 18:51:36 +08:00
李通洲 1c032624ac Title: adds {cwd-tilde} support 2026-02-28 18:44:13 +08:00
Carter Li 5087ea77b4 Presets: replaces outer single-line border with double-lines in examples/25 2026-02-28 17:48:36 +08:00
李通洲 b6b42e69c3 DisplayServer (Windows): reduce system dependencies 2026-02-28 10:37:03 +08:00
李通洲 000a688bb6 TerminalShell (Windows): improves logic of GUI program check 2026-02-28 10:06:13 +08:00
李通洲 3e25b213b1 WM (Windows): supports komorebi detection 2026-02-28 10:03:27 +08:00
李通洲 a69cf456ea Binary (Windows): removes imagehlp dep 2026-02-27 22:59:46 +08:00
李通洲 072b76cb12 WM: defaults detectPlugin to true 2026-02-27 18:26:53 +08:00
Carter Li ca8f54d331 CI: forwards envs & upgrades deps 2026-02-27 15:44:09 +08:00
李通洲 6423feaa94 Revert "OS (Windows): restores compatibility with WINE"
Seems WINE now has winbrand.dll

This reverts commit 554184ec72.
2026-02-27 15:41:55 +08:00
李通洲 92ada88ea7 WM (Windows): detect FancyWM & GlazeWM and their versions 2026-02-27 15:35:32 +08:00
李通洲 1789ef85d7 Processing (Windows): tidy 2026-02-27 15:04:43 +08:00
李通洲 42509f115c Common (Windows): always uses en_US when fetching exe version 2026-02-27 15:04:28 +08:00
李通洲 340a58bda1 Shell (Windows): ignore lldb-dap 2026-02-27 15:03:15 +08:00
李通洲 08dfd1321c Platform (macOS): use _NSGetExecutablePath to query current exe path
Unlike proc_pidpath which uses syscall
2026-02-26 15:12:53 +08:00
Carter Li 45d324a8c6 OpenGL: releases EGL context to avoid memleaks 2026-02-26 10:11:23 +08:00
Carter Li afa986efd4 Global (Linux): unrefs dbus replies to avoid memleaks 2026-02-26 10:11:12 +08:00
Carter Li bc6e8c7813 Global (Linux): unrefs dbus connection to avoid memleaks 2026-02-26 09:47:18 +08:00
Carter Li 627fee23d1 Chore: adds assertions 2026-02-26 09:00:24 +08:00
Carter Li 27b474f205 CPU: ensures tempSensor accepts string only
Fixes #2202
2026-02-26 08:55:53 +08:00
李通洲 418c7eecc7 Logo (Builtin): updates secureblue 2026-02-25 13:51:46 +08:00
李通洲 350250d640 Doc: updates json schema [ci skip] 2026-02-25 13:24:33 +08:00
Alxhr0 3cc21905af Editor: adds Zed version detection support (#2200) 2026-02-25 10:56:28 +08:00
underscorejoser c698eb8eb5 Logo (Builtin): fixes Fedora secureblue (#2201)
* fix: colored inside shackle

* Update ASCII art in secureblue.txt

* Fix formatting in secureblue.txt

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-02-25 10:55:47 +08:00
Carter Li 463c24beb8 WM (Linux): for LXQt, only query wm settings when wm was not detected
Fixes #2199
2026-02-25 10:37:18 +08:00
李通洲 a5d1b96ecc Logo (Builtin): update ArcoLinux entries to reflect discontinuation and simplify name list 2026-02-24 13:16:58 +08:00
李通洲 63106ebdc1 Logo (Builtin): simplify name entries for Artix and its variants 2026-02-24 12:59:52 +08:00
李通洲 fd36783adb Logo (Builtin): removes redundant name entry for Exherbo 2026-02-24 12:49:02 +08:00
李通洲 3b5186da53 Logo (Builtin): rename ExodiaPredator to ExodiaOS and simplify name entries 2026-02-24 12:48:31 +08:00
李通洲 0140a46090 Logo (Builtin): corrects name casing for Deepin and removes redundant entry 2026-02-24 12:18:04 +08:00
李通洲 9c38e1255f Logo (Builtin): remove redundant names for Debian and DebianSmall 2026-02-24 12:17:56 +08:00
李通洲 663f9d69ff Logo (Builtin): corrects spelling of LinuxLight to LinuxLite 2026-02-24 12:05:52 +08:00
李通洲 d12e5ab801 Logo (Builtin): tidy 2026-02-24 11:56:25 +08:00
李通洲 1d770d85f6 Logo (Builtin): simplifies MassOS name entry 2026-02-24 11:56:06 +08:00
李通洲 5b00afe45d Logo (Builtin): simplifies MiracleLinux name entry 2026-02-24 11:55:41 +08:00
李通洲 5b276567ac Logo (Builtin): simplifies MX and MXSmall name entries 2026-02-24 11:55:22 +08:00
李通洲 56566916e3 Logo (Builtin): simplifies Nobara name entries 2026-02-24 11:54:48 +08:00
李通洲 2c0b4ca3a2 Logo (Builtin): simplifies Raspbian name entries 2026-02-24 11:45:29 +08:00
李通洲 54ffdd32dc Logo (Builtin): simplifies RedOS name entries 2026-02-24 11:45:14 +08:00
李通洲 64f24bdee9 Logo (Builtin): renames Refracted Devuan to Refracta
Ref: https://github.com/dylanaraps/neofetch/issues/2338
2026-02-24 11:41:21 +08:00
李通洲 4706f97bf0 Logo (Builtin): simplifies Rocky Linux 2026-02-24 11:38:01 +08:00
李通洲 0bdb198d52 Logo (Builtin): updates RengeOS entry to remove redundant name 2026-02-24 11:02:11 +08:00
s0s fc7710821e Common: fixes segmentation fault triggered by dereferencing value at negative index (#2198) 2026-02-24 11:00:25 +08:00
thealio e22a9990ec Logo (Builtin): Aritx logos improvements (#2157)
* Create artix4.txt

* Rename artix4.txt to artix2.txt

* Rename artix_small.txt to artix1_small.txt

* Rename artix2_small.txt to artix_small.txt

* Rename artix1_small.txt to artix2_small.txt
2026-02-24 10:59:47 +08:00
Crystal_ForceIX fc7f3a1650 Logo (Builtin): adds RengeOS Logo (#2170) 2026-02-24 10:52:39 +08:00
Carter Li 915af9546d Keyboard (Linux): supports more keyboard events 2026-02-22 22:48:17 +08:00
Carter Li 54a68640ef Packages (Linux): supports moss
Fixes #2191
2026-02-22 22:33:27 +08:00
李通洲 ec1af7c92b Platform (OpenBSD): improves executable path retrieval method
Fixes #2195
2026-02-22 18:14:36 +08:00
Carter Li a1e20270ad Platform: add current working directory (cwd) to FFPlatform structure and initialization 2026-02-21 00:29:02 +08:00
Chiron 4996986ce6 Logo (Builtin): updates Linux Mint ASCII Logo (#2186) 2026-02-19 02:56:56 +08:00
李通洲 e6de2d4fd9 Doc: update issue template [ci skip] 2026-02-19 00:50:43 +08:00
李通洲 5347e74a1b Logo (Builtin): adds linuxmint2
Ref: #2186
2026-02-18 23:58:39 +08:00
李通洲 0ea5639a22 Platform (Windows): prefers Nt* APIs 2026-02-18 20:13:33 +08:00
Carter Li aa3a916d5a Merge pull request #2183 from fastfetch-cli/dev
Release: v2.59.0
2026-02-14 00:15:11 +08:00
Carter Li 6e64b758bf Chore: silences a compiler warning 2026-02-13 23:37:40 +08:00
李通洲 49ef7fc51f Packages (Windows): code cleanups 2026-02-13 20:50:45 +08:00
李通洲 0e9a5acdbd Platform (Windows): adds init / destroy of field sid 2026-02-13 20:42:35 +08:00
李通洲 4f6e80e940 Release: v2.59.0 2026-02-13 19:39:33 +08:00
李通洲 df87cdfa6e Windows: defines NtCurrentProcess and uses it 2026-02-13 19:38:22 +08:00
李通洲 dee4b36a46 Bluetooth (Windows): use modern dlls 2026-02-13 19:25:06 +08:00
李通洲 d04a26337a Swap (Windows): removes unused code 2026-02-13 19:25:06 +08:00
Dark Knightz 2afe8d11d1 Common: fixes discarded-qualifiers warnings (#2181) 2026-02-13 18:05:07 +08:00
李通洲 f31d3b8b21 Doc: update changelog 2026-02-13 10:04:54 +08:00
李通洲 8a20af9917 Doc: update JSON schema 2026-02-13 10:02:28 +08:00
李通洲 fc5c2f6213 Title: adds {user-id} in custom format 2026-02-13 09:38:22 +08:00
Carter Li 6c314e148a Logo (Builtin): updates nixos_small too
Ref #2180
2026-02-13 09:09:05 +08:00
Konnor Klercke a86d0017a9 Logo (Builtin): adds 6-color support to nixos logo (#2180)
Co-authored-by: Konnor Klercke <kklercke@brite.com>
2026-02-13 08:58:48 +08:00
李通洲 4038ed2656 GPU: adds debug logs
Thanks Github Copilot
2026-02-12 18:56:42 +08:00
李通洲 0f4bb47c2f Global: fixes compiler warnings 2026-02-12 16:25:33 +08:00
李通洲 19f7c67ede Platform: adds pid field and use it 2026-02-12 14:29:49 +08:00
李通洲 ff7e81ed81 Memory (Windows): adds comments [ci skip] 2026-02-11 21:47:20 +08:00
李通洲 681a102a2b Processing (Windows): adds TODO [ci skip] 2026-02-11 21:47:09 +08:00
李通洲 ba27f4f2ef CI: adds Solaris 2026-02-11 15:50:58 +08:00
李通洲 cbe33a4860 CI (DragonFly): disables packaging .pkg file to fix a weird CI error 2026-02-11 15:50:58 +08:00
李通洲 5847e3f269 FFPlatform (Windows): fixes memory corruption 2026-02-11 10:03:29 +08:00
李通洲 b248dfa01c Platform: prefers system API to retreive user name 2026-02-10 23:42:57 +08:00
李通洲 357aa77e21 Media (Solaris): fixes another compiling error
Fixes #2173
2026-02-10 22:42:36 +08:00
李通洲 a44bde6f94 Platform: adds UID / SID detection 2026-02-10 20:33:28 +08:00
李通洲 5825bce57d Disk (Windows): replaces most Kernel32 calls to ntdll calls
* Improves accurancy of detection of drive create time
* Improves performance slightly
* Removes remove drive check, `hideFolders` should be used instead
2026-02-10 18:50:35 +08:00
李通洲 996cdd3155 Refactor: moves memrchr to global impl for potential future use 2026-02-10 18:16:58 +08:00
李通洲 61cdfcabf8 Windows: uses SHGetKnownFolderPath instead of the unreliable getenv 2026-02-10 17:32:34 +08:00
李通洲 359a77097c Terminal (Windows): uses NtQueryInformationProcess to retrieve information of conhost.exe 2026-02-10 17:32:34 +08:00
李通洲 1323d007d3 Global: uses alignas where applicable 2026-02-10 17:32:34 +08:00
李通洲 d2215f26ac Processing (Windows): uses NtQueryInformationProcess instead of its wrapper 2026-02-10 17:32:34 +08:00
李通洲 958e7dbd8f Bluetooth (Windows): simplifies code 2026-02-10 17:32:34 +08:00
Verdgil 5b10cde59f Global: Add support for Oracle Solaris (#2176)
* Fix Oracle Solaris zpool build

* Add memrchr fallback

* Change to include fron extern

* add new line

* remove ; in zpool.c

* Change wrapper to macro

Also change README.md

* Tweaks

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-02-10 17:32:20 +08:00
李通洲 e8f2b9a1c7 Common: uses _Countof in ARRAY_SIZE definition when available 2026-02-02 11:08:26 +08:00
Carter Li 0686d1db4a GPU (Hurd): uses native API; removes libpciaccess dep 2026-01-30 20:34:47 +08:00
李通洲 7c284f9ee8 CMake (macOS): disable ENABLE_APPLE_MEMSIZE_USABLE by default 2026-01-29 13:11:48 +08:00
李通洲 dc04273bd7 Memory (macOS): updates algorithm in order not to use hw.memsize_usable which is available on newer macOS version
Adds a new CMake option to use usable memory size at the same time

Fixes #2171
2026-01-29 09:34:50 +08:00
李通洲 d698be6239 CPU (ARM): removes duplicated cases 2026-01-27 14:48:05 +08:00
李通洲 e44df27c96 Memory (macOS): adds debug info
Usage: `fastfetch -s memory:swap -l none --dynamic-interval 1000 --debug --no-buffer`
See https://github.com/fastfetch-cli/fastfetch/issues/2171#issuecomment-3803309478
2026-01-27 14:24:38 +08:00
李通洲 b365d4cca1 CPU (ARM): adds more ARM parts 2026-01-26 10:17:28 +08:00
李通洲 19d3c948ad DE (Android): clarifies that Google Pixel and other OSes also report ro.build.display.id 2026-01-26 10:17:28 +08:00
李通洲 4a581039d5 CI: fixes building 2026-01-24 09:17:13 +08:00
李通洲 79849fb2b5 CI: updates dependencies 2026-01-23 10:26:04 +08:00
李通洲 c116a5abdf Chore: uses elvis operators where applicatable 2026-01-22 15:36:42 +08:00
Carter Li 8f082730a8 Packaging: update debian stuff [ci skip] 2026-01-22 15:35:44 +08:00
Carter Li b81c4a04db Merge pull request #2164 from fastfetch-cli/dev
Release: v2.58.0
2026-01-21 15:03:51 +08:00
李通洲 e26a05e3ac DE (Linux): ensures process returns successfully before using its output 2026-01-21 14:28:40 +08:00
李通洲 f08a1fb0b4 Release: v2.58.0 2026-01-21 14:12:53 +08:00
李通洲 2a82009ffe WM (macOS): checks the version of WindowServer instead of WindowManager 2026-01-21 09:39:31 +08:00
李通洲 e851f3a7ed Packages (Linux): optimises pacman detection code 2026-01-20 10:06:02 +08:00
Sean Will 3a865df09e Packages (Linux): Auto detect the DBPath directory for pacman on archlinux (#2154)
Fixes #2068
2026-01-19 19:44:30 -06:00
berezka bae80e2932 Add new KISS Linux logo based off favicon 2026-01-20 09:42:28 +08:00
berezka 4445e1e78d Fix Bedrock Linux version detection & futureproof for 0.8 2026-01-20 09:42:28 +08:00
Carter Li f0e3d3d8e1 Host (Linux): uses /sys/firmware/devicetree/base/smbios if available 2026-01-20 09:20:48 +08:00
Carter Li a313fd1572 Linux: uses the standard /sys/firmware/devicetree/base instead of the outdated /proc/device-tree 2026-01-20 09:11:47 +08:00
Carter Li 927d44d919 Chassis (Linux): uses /proc/device-tree/smbios if available 2026-01-20 08:59:22 +08:00
Carter Li 3b9a91e8af DE (Linux): silences compiler warnings [ci skip] 2026-01-20 08:34:46 +08:00
李通洲 70b4582bb6 DE (Linux): removes option slowVersionDetection
It's always true now

Fixes #2149
2026-01-19 10:55:30 +08:00
李通洲 461552b8d0 DynamicInterval: reruns prepare code before next interval
Fixes #2152
2026-01-16 20:02:03 +08:00
Carter Li 0f3db37199 Chassis (Linux): supports arm devices 2026-01-16 16:47:51 +08:00
Carter Li 67f16b269a DisplayServer (Linux): regenerates wlr-output-management-unstable-v1*
NOOP
2026-01-16 10:40:53 +08:00
李通洲 25671fa4b4 DisplayServer (Linux): fixes crashes on KDE beta
Fixes #2150
2026-01-16 10:13:50 +08:00
Kirill Rekhov 4eaa04d4a4 Presets: update examples to replace deprecated --load-config with --config 2026-01-16 00:43:03 +08:00
李通洲 7592885b9f GPU (Windows): ensures devId is uppercase for consistent parsing 2026-01-15 15:46:21 +08:00
李通洲 508a3fde36 Windows: fixes building 2026-01-15 15:43:05 +08:00
李通洲 f0273224e0 JsonSchema: update [ci skip] 2026-01-15 15:24:54 +08:00
李通洲 31e833c02e Colors: updates module description
Fixes #2147
2026-01-15 15:20:38 +08:00
李通洲 a20d915412 JsonConfig: supports --structure-disabled 2026-01-15 15:11:08 +08:00
李通洲 d3453de73c Global: puts more fastfetch-only properties into FFdata 2026-01-15 15:06:23 +08:00
李通洲 79a11c4728 CommandOption: adds a new option --structure-disabled (WIP)
To disable modules temporarily
2026-01-15 10:35:21 +08:00
李通洲 24591417ce FFstrbuf: clarify usage requirements for ffStrbufGetdelim and friends 2026-01-15 10:30:40 +08:00
李通洲 de6d066fc9 LICENSE: update copyright year to 2026 [ci skip] 2026-01-14 16:33:51 +08:00
Carter Li 6362c896f8 Packaging: updates debian stuff [ci skip] 2026-01-14 14:10:46 +08:00
Carter Li 0418e9ca5e Merge pull request #2145 from fastfetch-cli/dev
Release: v2.57.1
2026-01-13 23:58:22 -06:00
李通洲 ba0eeab18c DisplayServer (Linux): cleanup code 2026-01-14 13:47:40 +08:00
李通洲 5ef630cbc8 Release: v2.57.1 2026-01-14 13:20:55 +08:00
李通洲 1699d14984 Common: ensures thread safety of ffTimeInitQpcMultiplier 2026-01-14 10:03:51 +08:00
Carter Li 501746a270 Logo: removes unneeded #includes
Fixes #2143
2026-01-14 08:50:56 +08:00
李通洲 e6bd1c340f Common: add on_scope_exit utility for scope-based resource management 2026-01-13 18:33:02 +08:00
李通洲 49fc95689d Platform (Windows): improves hostname retrieval by adding fallback to NetBIOS name 2026-01-13 10:44:52 +08:00
李通洲 3d84ad19be macOS: uses MACH_PORT_NULL to maintain compatibility with older SDKs
Fixes #2140
2026-01-13 10:12:31 +08:00
Rain Xelelo 57aa0cf499 Logo (Builtin): updates PrismLinux and adds a small variant (#2141)
* Add files via upload

* Update builtin.c

* Update builtin.c

* Update builtin.c

* PrismLinux logo update + small variant

* Update ASCII art in prismlinux.txt

* Revise ASCII art in prismlinux_small.txt

Updated ASCII art in prismlinux_small.txt

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-01-13 10:04:38 +08:00
Carter Li 6496dcd7d0 DisplayServer (Linux): refactors property handling in xcb and xlib 2026-01-13 09:24:27 +08:00
李通洲 1c066bc69a Common: updates ffTimeSleep to return true on success 2026-01-12 15:16:03 +08:00
李通洲 2f1e37bb7c Common (Windows): improves performance of ffTimeGetTick 2026-01-12 15:16:02 +08:00
李通洲 fd3c87abe7 Github: adds pull_request_template.md [ci skip] 2026-01-12 11:04:04 +08:00
李通洲 af075b8ef8 Github: update logo_request.yml [ci skip] 2026-01-12 11:04:04 +08:00
Carter Li 71d461266e Packaging: updates debian stuff [ci skip] 2026-01-12 10:19:39 +08:00
Carter Li 163781557f Merge pull request #2134 from fastfetch-cli/dev
Release: v2.57.0
2026-01-11 20:02:57 -06:00
Carter Li 16e6decebf Logo: general fixes
1. updates JSON schema
2. removes unused fields
3. runs tests in CI
2026-01-12 09:34:25 +08:00
Carter Li e10c9cc164 Doc: updates changelog 2026-01-12 09:06:43 +08:00
Carter Li 7ef994d0cf Logo (Builtin): update macOS variants 2026-01-12 09:00:57 +08:00
ctb unit 248 019c9f0f77 Logo (Builtin): macOS large Apple logo: add missing warm band using ANSI LIGHT_RED (#2138)
Co-authored-by: ctb248 <ctb248@pm.me>
2026-01-10 09:44:27 +08:00
李通洲 5fec607ebe Doc: updates changelog 2026-01-09 20:14:00 +08:00
李通洲 b065b3da51 Global: optimises usage of FFstrbuf and FFlist 2026-01-09 20:14:00 +08:00
李通洲 1337525eb5 Shell: fixes xonsh version detection 2026-01-09 20:14:00 +08:00
李通洲 30ea52938e Processing (SunOS): tidy 2026-01-09 20:14:00 +08:00
李通洲 d43ed33661 Shell (macOS): fixes exePath not reports absolute paths 2026-01-09 20:14:00 +08:00
李通洲 03aab33507 Shell (Linux): supports version detection for deleted binaries
Fixes #2136
2026-01-09 20:14:00 +08:00
李通洲 420d1cf804 FFstrbuf: updates ffStrbufSet* that they won't reserve extra space 2026-01-09 20:13:59 +08:00
Ezozbek 5d901da81b Logo (Builtin): adds Xinux logo (#2135)
* Logo (Builtin): adds Xinux logo

* Fix formatting in xinux.txt ASCII art

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2026-01-08 18:57:28 -06:00
李通洲 5c783e64c0 Logo: adds new module for querying raw builtin logo data
Fixes #2124
2026-01-08 16:39:52 +08:00
李通洲 2efa5a1869 Logo: code refactor for future use 2026-01-08 15:56:44 +08:00
李通洲 5bfabe7a52 Presets: adds a new example 2026-01-08 14:13:19 +08:00
李通洲 c9c9a58f59 Colors: supports @<color-index> 2026-01-08 14:10:47 +08:00
李通洲 546908fc29 Release: v2.57.0 2026-01-08 10:02:31 +08:00
李通洲 0a17da2da0 CI (Windows): build win7-compat artifacts 2026-01-08 09:40:11 +08:00
李通洲 bc6fd025cb Common: silences compiler warnings 2026-01-07 20:11:41 +08:00
李通洲 9e49451340 Display (Windows): supports dpi scale factor detection on Win 7 2026-01-07 20:04:54 +08:00
李通洲 4d185e64ac SunOS: silences compiler warnings 2026-01-07 18:38:44 +08:00
李通洲 1fa9a61b3f CMake (Windows): fixes option ENABLE_WIN7_COMPAT 2026-01-07 18:32:58 +08:00
李通洲 234552fbf2 CI (OpenBSD): uses clang-21 2026-01-07 16:22:28 +08:00
李通洲 8423efb686 CMake (Windows): introduces a flag to remove Win7 compat mode 2026-01-07 11:05:12 +08:00
李通洲 cd8c15d01e OS (Windows): acquires OS name from registry 2026-01-07 10:36:28 +08:00
李通洲 3163cfb1b6 Common (Windows): improves performance a littile 2026-01-07 10:35:48 +08:00
李通洲 7ae007a1d0 CI (OpenBSD): upgrades OS version 2026-01-07 08:58:20 +08:00
李通洲 0b52d75415 GPU (Windows): assumes Win10+ on WoA 2026-01-07 08:58:03 +08:00
李通洲 3a7f4f5848 Uptime (Windows): silences a compiler warning 2026-01-07 08:56:00 +08:00
李通洲 072f67988f Networking: prefers WSA* functions
No functional change.
2026-01-06 22:57:27 +08:00
李通洲 c640ddbff7 Uptime (Windows): uses QueryInterruptTime on WoA unconditionally 2026-01-06 22:41:00 +08:00
李通洲 981ae6bdd1 GPU: improves error handling and add case-insensitive PCI ID parsing 2026-01-06 20:21:03 +08:00
李通洲 977e3f317e Uptime (Windows): improves accurancy on Windows 10 and later 2026-01-06 19:59:02 +08:00
Carter Li e2ee24598c Zpool: add "Is read-only" option to module info 2026-01-06 18:49:52 +08:00
李通洲 1be90084ab Networking: fixes some issues and memory leaks 2026-01-06 16:44:36 +08:00
李通洲 6ded0f9bb0 CMake: fixes building 2026-01-06 10:25:41 +08:00
Carter Li d60b25e424 Refactor: renames src/util to src/common 2026-01-06 09:48:38 +08:00
Carter Li 874f3918b7 Util: moves util/*.c to util/impl/ 2026-01-06 09:42:54 +08:00
Carter Li 61690a1804 Util: moves util/io/io.h to util/io.h 2026-01-06 09:13:40 +08:00
李通洲 1e43e35857 Chore: merges common/* into util/* 2026-01-05 17:54:41 +08:00
李通洲 8c86003220 Common: introduces FF_LIBRARY_LOAD_MESSAGE to simplify library-loading 2026-01-05 17:54:41 +08:00
Carter Li 18c3cd2e66 CPU (Linux): fixes speed detection on s390x
Fixes #2129
2026-01-05 10:50:55 +08:00
Carter Li b21f35e914 CMake (Hurd): defines O_PATH=0 2026-01-05 10:45:19 +08:00
李通洲 32e3ed1fda SMC: optimises code 2026-01-04 16:45:02 +08:00
李通洲 6f87026b0c Host (macOS): uses IORegistryEntryFromPath if applicatable 2026-01-04 15:38:25 +08:00
李通洲 e23edae917 Board (macOS): removes an unused #include 2026-01-04 15:37:11 +08:00
Carter Li bdc867031a TerminalFont (Linux): check xterm.vt100.faceName for xterm font detection 2026-01-04 10:41:24 +08:00
李通洲 e96b0f7a73 Netif (Linux): skips local/loopback routes
Fixes #2127
2026-01-01 23:35:14 +08:00
Carter Li 37fe446a58 TerminalFont (Linux): supports cosmic-term 2026-01-01 22:52:03 +08:00
Carter Li f03a0bc202 Terminal (Linux): supports cosmic-term version detection 2026-01-01 22:32:32 +08:00
Carter Li bcbc5a4bff DE (Linux): fix COSMIC version detection 2026-01-01 22:29:11 +08:00
qaqland 0b1e2faba1 Logo (Builtin): fix colors of UOS 2025-12-31 08:03:19 +08:00
qaqland 4708a5e59c Logo (Builtin): fix colors of deepin 2025-12-31 08:03:19 +08:00
Carter Li 7925469e2f DE (Linux): detect COSMIC version 2025-12-28 23:16:58 +08:00
Carter Li 53116d65f1 WM (Linux): supports niri version detection
Fixes #2121
2025-12-28 23:16:45 +08:00
李通洲 01917b781b Bootmgr (macOS): supports secure boot detection on Intel 2025-12-27 18:12:23 +08:00
李通洲 d01fc56ea2 Bootmgr (macOS): supports secure boot detection 2025-12-27 16:11:16 +08:00
李通洲 9c870a57f0 PhysicalMemory (macOS): improves performance on Apple Silicon 2025-12-27 15:58:56 +08:00
3ventic 7e557a06b3 JsonSchema: correct references for keyboard, mouse items (#2119) [ci skip] 2025-12-27 10:15:04 +08:00
Joe_ fa63038862 Logo (Builtin): renames HydraPWK to NetHydra 2025-12-26 20:38:12 +08:00
Carter Li 8439204cef DisplayServer (Linux): upgrades kde-output-device-v2 wayland protocol files (again) 2025-12-23 16:17:01 +08:00
李通洲 710df0b87b TerminalFont (Linux): improves rxvt detection
Ref #2105
2025-12-23 16:03:04 +08:00
李通洲 302f0fc85f TerminalFont (Linux): supports urxvt
Fixes #2105
2025-12-23 11:05:54 +08:00
Carter Li 241aa3a02c GPU (Linux): silences a strict-aliasing warning
Fixes #2106
2025-12-22 10:28:56 +08:00
李通洲 a17f3dc3f8 Util: fixes building on DragonFly BSD 2025-12-22 08:44:00 +08:00
李通洲 34c0bf58cb Logo (Builtin): adds Tumbleweed braille logo 2025-12-21 18:07:07 +08:00
Carter Li b64b93fc4a Util (mallocHelper): implements ffMallocUsableSize and uses it 2025-12-20 09:26:37 +08:00
Carter Li a9f43ff466 Packaging: update debian stuff 2025-12-18 15:00:51 +08:00
Carter Li 924d78d3c4 Release: v2.56.1 (#2097)
* Logo (Builtin): drop opak

Ref: #1070

* Swap (Windows): adds `K32GetPerformanceInfo` fallback

* Platform (Windows): fixes if checks

* Platform (Windows): adds a null check

* Packages (Windows): improves performance for directory enumeration

* Util (Windows): fixes / adds a new Unicode conversion function

* Packaging: update debian stuff [ci skip]

* IO (Windows): enhances `openat`

* CPU: adds option `tempSensor`

* CPU (macOS): supports `tempSensor`

* CPU (Windows): supports `tempSensor`

* CPU (Linux): supports `tempSensor`

* CPU (FreeBSD): supports `tempSensor`

* CPU (NetBSD): supports `tempSensor`

* CPU (OpenBSD): supports `tempSensor`

* CPU (Linux): prevents variables from integer overflow

* GPU (Linux): add comments

* CPU (SunOS): supports `tempSensor`

* Doc: clarifies that we supports illumos only

* JsonSchema: documents `cpu.tempSensor`

Fixes #2073

* CPUCache (macOS): fixes cache line size detection

* CPU(Linux): Fix build on GNU.

* Chore: refines usage of `PATH_MAX`

* DisplayServer (Linux): upgrades kde-output-device-v2 wayland protocol files (again)

Fixes #2093

* Logo (Builtin): adds gxde logo (#2094)

* add gxde-logo

* add gxdeos

* add gxdeos

* add gxdeos

* Release: v2.56.1

* Memory (macOS): uses `hw.memsize_usable`

* Chore (Windows): Standardize windows header casing. (#2096) [ci skip]

Followup to 0b6ca158ea.

Co-authored-by: Dariqq <dariqq@noreply.codeberg.org>

* IO (Windows): removes unneeded null terminator appending

* CPU (SunOS): adds `const` for consistancy

* Host (macOS): prefers `hw.product` than `hw.model`

... because `HW_MODEL` is deprecated

* Doc: update changelog

* Memory (macOS): Refines Memory usage detection on macOS to match Activity Monitor more closely

* Packages (Windows): fixes possible UB

Reported by Github Copilot

* JsonSchema: refines comments [ci skip]

---------

Co-authored-by: Yelninei <yelninei@tutamail.com>
Co-authored-by: gitee-zeqi <a202128502@163.com>
Co-authored-by: Dariqq <77271900+Dariqq@users.noreply.github.com>
Co-authored-by: Dariqq <dariqq@noreply.codeberg.org>
2025-12-18 14:46:24 +08:00
李通洲 fa92bb84ae JsonSchema: refines comments [ci skip] 2025-12-18 14:35:21 +08:00
李通洲 288d25e17c Packages (Windows): fixes possible UB
Reported by Github Copilot
2025-12-18 14:21:55 +08:00
李通洲 610fc2ea36 Memory (macOS): Refines Memory usage detection on macOS to match Activity Monitor more closely 2025-12-18 13:36:38 +08:00
李通洲 716c0e2b5c Doc: update changelog 2025-12-18 10:00:05 +08:00
李通洲 945aed7160 Host (macOS): prefers hw.product than hw.model
... because `HW_MODEL` is deprecated
2025-12-18 10:00:05 +08:00
李通洲 1d4d68f6e0 CPU (SunOS): adds const for consistancy 2025-12-17 14:30:07 +08:00
李通洲 3e1167260d IO (Windows): removes unneeded null terminator appending 2025-12-17 14:30:07 +08:00
Dariqq 0130f610e9 Chore (Windows): Standardize windows header casing. (#2096) [ci skip]
Followup to 0b6ca158ea.

Co-authored-by: Dariqq <dariqq@noreply.codeberg.org>
2025-12-16 18:53:26 -06:00
李通洲 94941daf4f Memory (macOS): uses hw.memsize_usable 2025-12-16 10:41:27 +08:00
李通洲 2bbd723321 Release: v2.56.1 2025-12-16 10:16:36 +08:00
gitee-zeqi 608382109c Logo (Builtin): adds gxde logo (#2094)
* add gxde-logo

* add gxdeos

* add gxdeos

* add gxdeos
2025-12-15 13:30:47 +08:00
李通洲 bdc5174f68 DisplayServer (Linux): upgrades kde-output-device-v2 wayland protocol files (again)
Fixes #2093
2025-12-15 13:25:26 +08:00
李通洲 bc869f1be9 Chore: refines usage of PATH_MAX 2025-12-12 09:03:18 +08:00
Yelninei dc69e44829 CPU(Linux): Fix build on GNU. 2025-12-11 21:32:45 +08:00
李通洲 d236850119 CPUCache (macOS): fixes cache line size detection 2025-12-11 14:38:06 +08:00
李通洲 60ec8c9097 JsonSchema: documents cpu.tempSensor
Fixes #2073
2025-12-11 14:37:28 +08:00
李通洲 42e7a7d2f7 Doc: clarifies that we supports illumos only 2025-12-11 14:28:12 +08:00
李通洲 e766809e3a CPU (SunOS): supports tempSensor 2025-12-11 14:24:07 +08:00
Carter Li cb1f0300b9 GPU (Linux): add comments 2025-12-11 09:52:50 +08:00
Carter Li f2a29309f3 CPU (Linux): prevents variables from integer overflow 2025-12-11 09:52:50 +08:00
李通洲 6e7b4bab75 CPU (OpenBSD): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 b4f39e251c CPU (NetBSD): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 af6196fe6e CPU (FreeBSD): supports tempSensor 2025-12-11 09:52:50 +08:00
Carter Li bca56b2049 CPU (Linux): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 f4401f172e CPU (Windows): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 c11b88fee5 CPU (macOS): supports tempSensor 2025-12-11 09:52:50 +08:00
李通洲 88b1b558d7 CPU: adds option tempSensor 2025-12-11 09:52:50 +08:00
李通洲 ba6cdc77c9 IO (Windows): enhances openat 2025-12-11 09:52:50 +08:00
Carter Li b952772902 Packaging: update debian stuff [ci skip] 2025-12-11 09:52:50 +08:00
李通洲 7a322154fa Util (Windows): fixes / adds a new Unicode conversion function 2025-12-08 20:11:14 +08:00
李通洲 0b6ca158ea Packages (Windows): improves performance for directory enumeration 2025-12-08 16:42:14 +08:00
李通洲 100cd9a72b Platform (Windows): adds a null check 2025-12-08 09:49:54 +08:00
李通洲 98fb810f1f Platform (Windows): fixes if checks 2025-12-08 09:49:54 +08:00
李通洲 c613e558fd Swap (Windows): adds K32GetPerformanceInfo fallback 2025-12-08 09:49:41 +08:00
Carter Li c324f83826 Logo (Builtin): drop opak
Ref: #1070
2025-12-08 09:03:28 +08:00
Carter Li e50421a6ce Merge pull request #2083 from fastfetch-cli/dev
Release: v2.56.0
2025-12-05 22:42:51 +08:00
李通洲 417b944e1c Doc: updates changelog 2025-12-05 21:12:11 +08:00
李通洲 cb8b4b335d FFstrbuf: removes an unnecessary return 2025-12-05 21:10:19 +08:00
李通洲 c0160537b0 Zpool: fixes inconsistant CMake variables 2025-12-05 21:09:00 +08:00
李通洲 4cb7a6424a Logo (Builtin): tidy 2025-12-05 21:08:28 +08:00
李通洲 7d6c79d73e Doc: documents -c - 2025-12-05 10:41:18 +08:00
李通洲 8652737f64 Fastfetch: enhances config file loading with support for config directory
Fixes #2080
2025-12-05 10:32:42 +08:00
李通洲 d6ac89ea8d Release: v2.56.0 2025-12-04 16:15:20 +08:00
李通洲 2b620cf487 CI (SunOS): fixes a CI error 2025-12-04 16:15:20 +08:00
李通洲 f644df481c CPU: exposes numa node count in custom format 2025-12-04 15:21:27 +08:00
李通洲 e99ecacb52 Chore: adds ffIsValidNativeFD and uses it 2025-12-03 09:26:32 +08:00
李通洲 3e22dd4b0e Chore: uses _WIN32 always 2025-12-03 09:26:32 +08:00
Noa Himesaka 19f30ec687 Logo (Builtin): updates Codex Linux new logo (#2071)
* fix: Codex Linux new logo

reMarkable changed their logo so reflecting that change here too

* Modify ASCII art in codex.txt

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-12-03 09:09:07 +08:00
Alxhr0 76bee78200 Chore: fixes comment for AerynOS in builtin.c (#2078) 2025-12-03 09:00:09 +08:00
李通洲 ce7455d8f0 Zpool: allows disabling module 2025-12-01 17:20:50 +08:00
李通洲 5e27ee0f57 Shell: fixes ksh version detection on Linux 2025-12-01 10:04:40 +08:00
全てずんだもんの所爲です 84a5c6ebe8 Packages (Linux): add kiss packages count (#2072) 2025-11-30 19:10:07 -06:00
李通洲 ad7e23f64c TerminalFont: supports the newest Alacritty config format
Fixes #2070
2025-11-28 16:35:14 +08:00
李通洲 2738f20eea GPU (Linux): detect driver specific info for zhaoxin 2025-11-28 03:06:23 +00:00
李通洲 09362b236c Util (Windows): fixes compiling 2025-11-25 19:10:43 +08:00
Carter Li 3cfef81877 Users (Linux): always report the newest session info 2025-11-25 19:04:36 +08:00
Carter Li 3a04ae2542 Users (Linux): adds systemd fallback for user detection on Linux
Fixes #2064
2025-11-25 16:40:52 +08:00
Carter Li dbaf8a319d FFstrbuf: adds ffStrbufGetdelim(Restore) 2025-11-25 15:08:42 +08:00
Carter Li 2fe2a21bfe Terminal: reports sshd if $SSH_TTY is not available 2025-11-25 14:33:35 +08:00
Carter Li 37639c3582 Utils: inlines ffIsAbsolutePath 2025-11-25 14:33:35 +08:00
李通洲 9a74e6d7bc Users (Linux): adds missing endutxent 2025-11-25 14:32:36 +08:00
Carter Li 5d13389827 TerminalShell: uses absolute path when detecting version if available
Closes #2067
2025-11-25 09:10:30 +08:00
李通洲 1c2c6644d5 DE: adds Android OEM UI detection
Ref #1900
2025-11-24 15:17:52 +08:00
李通洲 ffcddf30e3 Logo: improve builtin logo printing for piping and buffering
Fixes #2065
2025-11-24 14:18:45 +08:00
李通洲 22c92c7b05 Doc: recommand Ubuntu PPA [ci skip] 2025-11-21 15:56:43 +08:00
李通洲 b569048010 CMake (SunOS): remove static link of libzfs 2025-11-21 15:56:43 +08:00
李通洲 f703d9ac89 Zpool: simplifies implementation by dropping platform-specific code 2025-11-20 18:18:25 +08:00
Steve Gilissen ed6abfd626 Logo (Builtin): adds OS/2 Warp logo (#2062)
* Add OS2 Warp logo

* Update ASCII art in os2warp.txt

* Refactor OS/2 Warp logo names for consistency

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-11-19 20:16:19 -06:00
李通洲 50388efc78 Zpool: uses runtime lookup for zpool properties to ensure portability
Fixes #2051
2025-11-19 20:26:18 +08:00
李通洲 7e8fb0fa14 Zpool: simplifies impl; exposes allocated/guid/readOnly 2025-11-19 19:27:19 +08:00
Steve Gilissen 9d70469665 Logo (Builtin): adds Amiga logo (#2061)
* Add Amiga logo

* Update ASCII art in amiga.txt

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-11-17 19:52:07 -06:00
李通洲 a94f0efb5b CPU: adds NUMA node detection 2025-11-18 09:30:47 +08:00
Carter Li da3a9be7c6 Packaging: update debian stuff [ci skip] 2025-11-18 09:11:54 +08:00
李通洲 cd8ab8e55a Command: Adds splitLines option 2025-11-17 11:01:32 +08:00
李通洲 1b5b32afad GPU (macOS): fixes a comment [ci skip] 2025-11-17 08:59:39 +08:00
Carter Li 917f784438 Merge pull request #2060 from fastfetch-cli/dev
Release: v2.55.1
2025-11-16 09:56:42 +08:00
李通洲 c2d5d5cca1 Release: v2.55.1 2025-11-16 09:29:24 +08:00
Carter Li b435738c34 CMake (macOS): corrects rpath addition for dlopen builds 2025-11-16 09:15:11 +08:00
apocelipes 934905e63a GPU: silence unused parameter warnings 2025-11-16 08:28:28 +08:00
apocelipes d15bb8a232 Display: fix an uninitialized FFDisplayOptions field 2025-11-15 22:34:33 +08:00
李通洲 c22bca1f87 Processing (Linux): blocks SIGCHLD and simplify poll error handling
Partially reverts e9ab67b380

Fixes #2056 & unfixes #1418
2025-11-15 19:34:13 +08:00
Carter Li e04cc9c9d5 Packaging: update debian changelog [ci skip] 2025-11-12 09:24:50 +08:00
Carter Li 7a2bf4e0ac Merge pull request #2049 from fastfetch-cli/dev
Releases: v2.55.0
2025-11-11 18:51:24 +08:00
李通洲 662f5127fa Shell: makes fish shell version detection more robust (v2) 2025-11-11 15:38:53 +08:00
李通洲 fb9117553b Shell: makes fish shell version detection more robust 2025-11-11 15:19:40 +08:00
李通洲 9f24e4363f Media (Linux): handles invalid percent-encoding in cover metadata 2025-11-11 15:16:12 +08:00
李通洲 084f9294f2 Media: updates naming convention from mediacover to media-cover for media cover logo sources 2025-11-11 14:42:55 +08:00
李通洲 a9f1f9a647 Doc: update changelog 2025-11-11 14:31:23 +08:00
李通洲 0aed89036b Chore: silenses some compiler warnings 2025-11-11 14:24:32 +08:00
李通洲 df15bbc5f2 Media: moves media cover cleanup logic to media detection 2025-11-11 14:00:43 +08:00
李通洲 e6b0bd3817 Media: fixes album cover serialization in JSON result 2025-11-11 13:58:45 +08:00
李通洲 11cd7153a2 Logo (Builtin): tidy [ci skip] 2025-11-11 13:53:34 +08:00
李通洲 f8bc1cb605 Releases: v2.55.0 2025-11-11 11:01:54 +08:00
李通洲 8b8eb6f290 TerminalShell (Linux): ignores run-parts
Ref: #2048
2025-11-11 10:10:47 +08:00
李通洲 056fe21ee2 Examples/25: removes parallel: true since we had it enabled by default [ci skip] 2025-11-11 10:07:58 +08:00
Carter Li cb0a88df22 [Command] enables parallel command execution by default 2025-11-11 09:28:44 +08:00
Carter Li 298c0431c3 Examples: improves clang version extraction method in 25.jsonc [ci skip] 2025-11-11 09:00:01 +08:00
Carter Li 448de9afa5 Command: makes compiler happy 2025-11-10 22:48:22 +08:00
Carter Li 9401a4b9ad Processing: adds a missing header 2025-11-10 18:09:19 +08:00
李通洲 ea92ad3785 Command: adds parallel and useStdErr options
Fixes #2045
2025-11-10 16:34:23 +08:00
李通洲 7aaad5e03e Processing: refactors process execution to separate spawning and reading 2025-11-10 16:34:23 +08:00
李通洲 645bf5c839 Disk: moves disk hiding by folder and FS type to detection code
Don't probe if hided

Fixes #2043
2025-11-06 13:39:30 +08:00
李通洲 7638e0e4a1 CMake: improves wordexp/glob detection and messaging 2025-11-05 10:21:05 +08:00
李通洲 302b8a7b1b CommandLine: adds dynamic output refresh support with interval option 2025-11-05 10:21:05 +08:00
李通洲 dbb9d8a660 Display: adds missing #include 2025-11-05 09:59:27 +08:00
李通洲 c51a164042 PublicIP / Weather: cleans up states after detection 2025-11-05 09:56:23 +08:00
李通洲 6b8a62da6e Linux (Host): improves Mac family detection by using prefix match 2025-11-04 09:12:35 +08:00
李通洲 578ca23e75 GPU (Hurd): adds support (requires libpciaccess) 2025-11-01 09:57:52 +00:00
李通洲 2e73a90835 GPU (OpenBSD): adds native GPU detection support 2025-11-01 17:23:59 +08:00
李通洲 cc6273fecc GPU (NetBSD): don't use system function name 2025-11-01 17:19:25 +08:00
李通洲 e63b777916 GPU: handles missing GPU type as null in JSON output 2025-11-01 16:44:36 +08:00
李通洲 907567f511 GPU (NetBSD): improves performance; drops libpciaccess dependency 2025-11-01 16:42:19 +08:00
李通洲 e0fd7308be Logo (Builtin): add Vincent OS
Fixes #2030
2025-10-31 11:04:18 +08:00
李通洲 b761034aae OS (Linux): prints debian version on Raspbery Pi OS
Fixes #2032
2025-10-31 11:04:18 +08:00
李通洲 04d6b1453d GPU (NetBSD): adds native GPU detection support 2025-10-31 11:04:18 +08:00
Carter Li 11d1754686 GPU: skips auxiliary display controllers
Fixes #2034
2025-10-30 14:46:30 +08:00
Carter Li 25e84decff GPU: unifies non-pci GPU device ID formatting across platforms 2025-10-30 11:01:06 +08:00
Carter Li 7d665b203f GPU: unifies GPU PCI device ID calculation logic across different platforms 2025-10-30 10:26:35 +08:00
李通洲 ac62442798 CMake: refines yyjson config and Apple rpath handling
Fixes #1998
2025-10-28 09:30:46 +08:00
李通洲 758f96de60 Icons (Windows): hides module when no icons are found
Fixes #2023
2025-10-24 14:46:09 +08:00
李通洲 db623b9c86 CI (Linux): adds Debian i386 packaging and verify deb package in CI
Fixes #2019
2025-10-22 17:45:50 +08:00
李通洲 c353bf3c96 Logo: adds automatic cleanup of temporary media cover files 2025-10-22 13:51:36 +08:00
李通洲 338b552499 Logo: adds support for using media cover as logo source 2025-10-21 15:05:25 +08:00
李通洲 5d73cc1232 Media: save media cover to temp file 2025-10-21 14:36:35 +08:00
李通洲 faddef7a3b Media (Windows): adds media cover extraction 2025-10-21 14:01:26 +08:00
Carter Li 2d9bbc8049 Media (Linux): adds media cover extraction 2025-10-21 09:44:36 +08:00
李通洲 64afaa07e7 Media (macOS): adds media cover extraction 2025-10-21 09:44:36 +08:00
李通洲 5cf3ab23b0 Utils (macOS): adds ffCfDictGetDataAsString 2025-10-21 08:49:34 +08:00
李通洲 3fe926d3a0 Doc: adds code-signing credit and privacy statement in README [ci skip]
As required by signpath
2025-10-20 23:43:32 +08:00
李通洲 f71bb682de Logo (Builtin): adds MacaroniOS
Fixes #2018
2025-10-20 15:12:11 +08:00
Carter Li 904f860f3c Packaging: builds for all Ubuntu versions [ci skip] 2025-10-20 14:58:23 +08:00
Carter Li 8f15c9604c Merge remote-tracking branch 'origin/master' into dev 2025-10-20 14:57:59 +08:00
李通洲 ff28f5807b Shell: supports brush version detection 2025-10-19 10:25:28 +08:00
李通洲 6a317366d7 Shell: fix fish version detection when LC_ALL is set
Fixes #2014
2025-10-19 10:25:28 +08:00
李通洲 dc3e4a2d18 JsonSchema: fixes copy-paste errors [ci skip]
Fixes #2013
2025-10-18 18:38:39 +08:00
Carter Li 46c4a71ba3 Merge pull request #2012 from fastfetch-cli/dev
Release: v2.54.0
2025-10-18 10:15:23 +08:00
Carter Li f0759acd11 Brightness (macOS): tidy 2025-10-18 09:35:34 +08:00
李通洲 96c7c2966d Brightness (macOS): prioritizes DDC/CI reply over simple I²C transaction 2025-10-18 01:11:03 +08:00
李通洲 554e7bce4a Logo (Builtin): adds Zraxyl
Fixes #1860
2025-10-18 00:56:14 +08:00
李通洲 70377a8afd Release: v2.54.0 2025-10-18 00:47:35 +08:00
李通洲 51bc6d421a CI (Windows): switches CI to use the release signing policy on the master branch 2025-10-18 00:47:35 +08:00
李通洲 be0756f8ba CMake: adds a new build option to gate wordexp usage and detection 2025-10-16 15:29:24 +08:00
李通洲 71a2cb4e1b Doc: adds security warning for Command module in README 2025-10-16 14:34:51 +08:00
李通洲 2eba761bed IO (OpenBSD): fixes incorrect glob usage 2025-10-16 14:33:53 +08:00
李通洲 4b5e1a816b Display (Windows): rename VRR to DRR 2025-10-16 13:24:44 +08:00
Dariqq a92e4b2d67 Chore (Windows): standardize more windows header casing.
Followup to 25353261d0
2025-10-14 15:49:06 +08:00
李通洲 a32404ba98 Doc: updates changelog 2025-10-14 14:51:44 +08:00
李通洲 0a792e4935 CPU (Android): adds detection support for Samsung Exynos SoCs 2025-10-14 14:49:29 +08:00
李通洲 05108977e8 CPU (Android): improves Android SoC vendor and model detection 2025-10-14 14:49:29 +08:00
李通洲 25353261d0 Chore (Windows): standardizes Windows header include casing. NOOP.
Fixes #2006
2025-10-14 09:10:24 +08:00
李通洲 4b517263d0 Chore (macOS): refactors code for better resource management 2025-10-13 14:27:23 +08:00
李通洲 98a65966e7 Doc: update changelog [ci skip] 2025-10-13 10:19:22 +08:00
李通洲 32dcf9487f Option: adds configurable spacing between icon and string keys
Fixes #2004
2025-10-13 09:54:34 +08:00
Carter Li e3a698f7b1 Brightness (macOS): fixes detection for external monitor on Intel platform 2025-10-11 21:26:37 +08:00
李通洲 1631f74700 Disk (Linux): revisits 78c6d71049 2025-10-11 18:20:56 +08:00
李通洲 78c6d71049 Disk (Linux): adds glob pattern matching for hidden disk folders
Fixes #1999
2025-10-11 16:19:11 +08:00
李通洲 0b9ecdeade Doc: adds Chinese README [ci skip] 2025-10-11 09:31:59 +08:00
李通洲 185a9211f1 Doc: update changelog 2025-10-10 15:09:25 +08:00
李通洲 24459b2fbf Brightness (macOS): enhance DDC/CI detection by enumerating all I2C buses 2025-10-10 14:24:11 +08:00
Carter Li 88c8dcb3e8 CPU (Linux): improves detection for T-Head CPU vendor
Ref: #1997
2025-10-10 10:55:12 +08:00
Carter Li f3a8fedf0a CPU (Linux): improves SoC name detection from device tree
Fixes #1997
2025-10-10 10:50:20 +08:00
李通洲 6b8b7c1a62 CI (Windows): signs PE files 2025-10-08 00:39:22 +08:00
李通洲 af26828f91 CPU (Linux): adds support for HP PA‑RISC & SuperH CPU architecture detection 2025-10-05 09:22:06 +08:00
李通洲 f4c43abbf7 Display (Windows): adds VRR status detection support 2025-10-05 09:17:30 +08:00
李通洲 e84739bff0 Logo (Builtin): update T2 2025-10-05 09:15:59 +08:00
李通洲 66aad0e4f1 Revert "Display (Windows): fixes incorrect refresh rate when VRR is enabled"
Doesn't work

This reverts commit 31ae7a642a.
2025-10-05 00:16:49 +08:00
Carter Li 77c43c0214 Display (Linux): prefer resolutions reported by randr mode info 2025-10-04 22:19:25 +08:00
李通洲 31ae7a642a Display (Windows): fixes incorrect refresh rate when VRR is enabled
Fixes #1994
2025-10-03 23:42:57 +08:00
Carter Li 1bbb21486c Disk (Linux): f* Android
Fixes #1993
2025-10-03 16:53:09 +08:00
李通洲 316d8ddf9b CI (Linux): disables post operations for polyfilled binaries
Fixes #1990
2025-10-03 12:16:15 +08:00
Carter Li 5d8c21a5ca Memory (Linux): fallbacks to calcuate ourselves when MemAvailable seems unreasonable
Fixes #1988
2025-10-02 07:39:20 +08:00
李通洲 240ba5c00c Platform (Windows): adds missing else for Wine version detection 2025-10-01 16:45:13 +08:00
Carter Li 554184ec72 OS (Windows): restores compatibility with WINE
Revert "OS (Windows): hard linking winbrand"

This reverts commit 4146bb6731.
2025-10-01 16:12:45 +08:00
李通洲 7a055a2254 CI: upgrades compiler versions 2025-10-01 10:07:28 +08:00
Carter Li 0a807ac1a3 TerminalFont (Linux): fixes default font size for ghostty
Fixes #1986
2025-10-01 08:09:04 +08:00
Carter Li 4d831c8c73 OS (Linux): don't change prettyName on Ubuntu development branch
Ref: #1483
2025-09-30 15:24:52 +08:00
李通洲 e6e78a7aae OS (macOS): improves OS detection accuracy and sets pretty name 2025-09-30 13:35:48 +08:00
李通洲 09bef5f41d OS (macOS): removes fallback parsing of legacy macOS license file
Doesn't work on Tahoe anymore
2025-09-30 13:22:00 +08:00
李通洲 e394efdd85 OS (macOS): trims whitespace from full user name 2025-09-30 13:19:58 +08:00
李通洲 c10b652a2e Swap (Windows): prevents integer overflow in swap size
Regression from 7ec0c664c5
2025-09-30 10:05:08 +08:00
李通洲 1594a69d6c Kernel (Windows): move kernel.displayVersion to OS.codeName 2025-09-30 10:01:01 +08:00
李通洲 9b1e318bd1 OS (Linux): sets code name for Ubuntu 2025-09-30 09:09:36 +08:00
李通洲 e292bf1dee OS (Linux): sets point release for Debian
Fixes #1985
2025-09-30 09:06:12 +08:00
李通洲 55a0c6e97d Logo (Builtin): adds EmperorOS
Fixes #1963
2025-09-29 10:07:26 +08:00
Rain Xelelo 8b8e4a40a4 Logo (Builtin): adds PrismLinux
Fixes #1983
2025-09-28 21:01:03 -05:00
李通洲 8be070998f Theme (Windows): moves Windows theme detection logic from DE to dedicated module
Like the last commit
2025-09-29 09:40:10 +08:00
李通洲 093f56a03d Theme (macOS): moves macOS theme detection logic from DE to dedicated module
The old behavior was inherited from neofetch. However `Aqua` and `Liquid Glass` are actually design language, not a DE. There is no DE on macOS.
2025-09-29 09:25:24 +08:00
李通洲 bd9744c27c CommandLine: adds --json flag as a shortcut for enabling JSON output 2025-09-28 15:07:45 +08:00
李通洲 adc25f4420 CI: adds Debian libc6 dependency to package config
Fixes #1981
2025-09-28 14:43:38 +08:00
李通洲 229fe7c7bf CMake: update contact info 2025-09-28 14:43:38 +08:00
李通洲 5d571752ae Chore: updates FUNDING info 2025-09-28 14:43:38 +08:00
李通洲 512ddfae6b Doc: adds padding check to logo request template 2025-09-28 09:40:48 +08:00
李通洲 7b689f94df Logo (Builtin): adds secureblue
Fixes #1979
2025-09-28 09:40:21 +08:00
李通洲 9eed149b09 CMake (Linux): adds i686 CI build and unify processor naming
Fixes #1978
2025-09-25 16:30:59 +08:00
李通洲 0f5d321df8 Chore: updates comments to use English descriptions 2025-09-24 10:11:02 +08:00
李通洲 4e84094fd8 CI (OpenBSD): updates CI workflow to upgrade packages before install 2025-09-23 16:41:18 +08:00
李通洲 7b9fce0189 CI (Linux): adds GCC 13 toolchain to CI build environment 2025-09-23 16:00:45 +08:00
李通洲 9ab5c33008 CI: fix release action 2025-09-23 10:19:55 +08:00
Carter Li 613b1d63f1 Packaging: updates debian stuff [ci skip] 2025-09-23 10:03:30 +08:00
Carter Li 8c86cafec7 Merge pull request #1976 from fastfetch-cli/dev
Release: v2.53.0
2025-09-23 09:55:28 +08:00
李通洲 4098cf51b3 Release: v2.53.0 2025-09-23 09:27:52 +08:00
李通洲 bfc23232f8 CPU (Android): adds support for new Qualcomm and MediaTek SoC codes 2025-09-23 09:13:10 +08:00
李通洲 483fba44dc Doc: update changelog [ci skip] 2025-09-22 16:40:10 +08:00
李通洲 851751f99d CPU (Linux): adds support for new ARM C1 series CPU part IDs
Follows changes of util-linux
2025-09-22 16:24:36 +08:00
李通洲 3e86130ddd Zpool: increase libzfs so version to 6
Fixes #1973
2025-09-22 14:32:19 +08:00
李通洲 350ffced13 CI: upgrades runner of intel macOS 2025-09-22 14:13:41 +08:00
李通洲 cdcdb78b97 CPU (Windows): refines ARMv8.4-A detection to require LSE2 2025-09-22 14:08:29 +08:00
Osama Albahrani 2ae9d01200 OS (Linux): Better Ubuntu flavor detection
- Fixes https://github.com/fastfetch-cli/fastfetch/issues/1974
2025-09-22 10:04:45 +08:00
李通洲 e95393750b Wifi (macOS): add (B)SSID detection back for Tohoe 26.0
Fixes #1874
2025-09-22 09:37:07 +08:00
李通洲 de9229697a TerminalFont: improve ghostty with command ghostty +show-config
Ref: #1972
2025-09-20 23:34:07 +08:00
NEOAPPS 9d23d28594 Logo (Builtin): update ObsidianOS logo (#1970)
* feat(logos): add new ObsidianOS logo

* feat(logos): update colors

* chore: remove internal paddings since they're not allowed
2025-09-20 23:02:25 +08:00
李通洲 57a4b9b6ed Disk: refactors mountpoint matching to use shared string utilities 2025-09-19 14:54:13 +08:00
李通洲 ef3989d18d CommandOption: refactors code with ffStrbufSeparatedContainIgnCaseS 2025-09-19 14:51:31 +08:00
李通洲 3079b44f63 FFstrbuf: adds more functions to match separated strings
1. ffStrbufMatchSeparatedIgnCaseNS
2. ffStrbufSeparatedContainNS
3. ffStrbufSeparatedContainNS
2025-09-19 14:34:27 +08:00
李通洲 403900639c Gamepad / Keyboard / Mouse: improves device error handling and memory cleanup 2025-09-19 13:36:02 +08:00
李通洲 0bb5b4cc9c Gamepad / Keyboard / Mouse: adds support to ignore input devices by name prefix
Fixes #1950
2025-09-19 11:00:18 +08:00
李通洲 1180eb55a4 Logo (Builtin): adds TempleOS
Fixes #1969
2025-09-19 09:46:23 +08:00
李通洲 f0e9caaf04 Disk: allows array input for disk folder and filesystem options 2025-09-18 14:51:00 +08:00
李通洲 2c22c3b0c0 CI (Windows): add chafa dependency 2025-09-18 13:44:51 +08:00
李通洲 e9065e15e8 TerminalFont: Improves Ghostty font config parsing with fallback font detection
Fixes #1967
2025-09-18 10:30:28 +08:00
李通洲 9e7816069b Revert "Logo (Builtin): add Starry Linux"
Ref: #1963

This reverts commit 4df4a1de78.
2025-09-17 16:09:05 +08:00
李通洲 82cdc4cd91 Disk (Linux): avoids invalid disk creation times before Linux epoch
Prevent fastfetch from printing invalid create date on Android
2025-09-17 15:37:51 +08:00
Carter Li 822ddc6dc6 Disk (Linux): replace statx(2) call to syscall(2) 2025-09-17 15:09:39 +08:00
李通洲 8bd171a9ff CI: adds glibc polyfill step for compatibility 2025-09-17 14:28:40 +08:00
李通洲 509d6bf30c CI: merge more jobs 2025-09-17 14:00:23 +08:00
李通洲 ab8a13b2d3 CI: update cmake version 2025-09-17 10:39:59 +08:00
Carter Li 3bcdcc5dbf CI: merge amd64 and aarch64 code with matrix 2025-09-16 16:28:45 +08:00
李通洲 38f4215a94 CPU (Windows): trims vendor string read from registry 2025-09-16 10:55:17 +08:00
李通洲 e3eec3f62a CPU (Windows): handles zero temperature data and refactors value use
Fixes #1960
2025-09-14 19:39:17 +08:00
李通洲 e025f28cdc Wifi (macOS): removes wdutil-based Wi-Fi detection code
Let's stop this hide and seek game.
2025-09-12 14:28:01 +08:00
李通洲 3ece4e3b4d Presets: add a new example [ci skip] 2025-09-12 14:11:41 +08:00
Carter Li 6d72a32d1d 3rdparty: upgrade widecharwidth 2025-09-11 14:54:25 +08:00
Carter Li 45be29bad3 CPU (Linux): replaces HWCAP defines with explicit bitmasks for ARM 2025-09-11 14:02:41 +08:00
李通洲 6f5e618341 CPU (Linux): add new ARM part numbers 2025-09-10 14:32:07 +08:00
李通洲 1abfa70237 LocalIP: adds IPv6 type selection for local IP display
`{ "type": "localip", "showIpv6": "ula" /* Show ULA only */ }`

Fixes #1459
2025-09-10 13:42:48 +08:00
李通洲 baaeef5ab5 Separator: uses widecharwidth for Unicode wcwidth and fixes issue that wchar_t on Windows is 2-byte length 2025-09-10 10:34:07 +08:00
李通洲 8eafec479e Separator: rename property length with times 2025-09-09 09:52:10 +08:00
李通洲 5f9e7c799a OpenGL (Windows): simplifies code by removing custom window proc
Adds more cleanups
2025-09-08 00:06:49 +08:00
Carter Li aeb1722eb9 Packaging: update debian stuff [ci skip] 2025-09-05 15:12:49 +08:00
Carter Li de18a07938 Release: v2.52.0 2025-09-05 13:04:53 +08:00
李通洲 88147f80ac Doc: update changelog 2025-09-05 12:38:14 +08:00
李通洲 505ff6ff65 Global: renames fractionTrailingZeros enum to always/never for consistance 2025-09-05 12:27:03 +08:00
李通洲 390549394d Fastfetch: removes redundant assignment in display config parsing
found by copilot
2025-09-05 11:08:37 +08:00
Carter Li f7e7d54c16 Release: v2.52.0 2025-09-05 10:46:30 +08:00
Carter Li 5e068d22c8 Btrfs (Linux): refactors Btrfs allocation to use profile string
Fixes #1941
2025-09-05 10:46:23 +08:00
李通洲 b77646f23e Btrfs (Linux): adds tracking of Btrfs data copy counts
Fixes(?) #1941
2025-09-05 00:18:00 +08:00
李通洲 aa40366a49 Terminal: ignores WSL2 unknown process for terminal detection 2025-09-04 22:31:59 +08:00
Carter Li a64a82f215 WMTheme (Linux): supports labwc on XFCE4 2025-09-04 18:50:23 +08:00
Qing Yun 0a4d6220e9 CPU (Linux): add cpu name detection for ia64 2025-09-04 18:34:14 +08:00
李通洲 6b037c595f Doc: update README 2025-09-04 16:36:55 +08:00
李通洲 f628f5c382 Settings: renames GNOME settings accessor for clarity 2025-09-04 16:17:01 +08:00
李通洲 cf713e32e1 Wallpaper (Linux): improves XFCE wallpaper detection via property enumeration 2025-09-04 13:54:49 +08:00
Carter Li 7d08f81075 Settings: removes direct XFConf support in favor of DBus backend 2025-09-04 09:43:57 +08:00
Carter Li 8822653335 DBus: adds function ffDBusGetInt 2025-09-04 09:35:52 +08:00
李通洲 75ff054255 Dbus: adds 2nd argument to ffDBusGetMethodReply 2025-09-04 08:45:09 +08:00
李通洲 c51cc8ce6b CI: bump dependencies 2025-09-03 16:01:09 +08:00
李通洲 44e23412b5 Doc: update changelog 2025-09-03 16:01:09 +08:00
李通洲 59742bca00 Fastfetch: improves frequency display config validation and schema 2025-09-03 16:01:09 +08:00
李通洲 303edb97ce Fastfetch: add option --faction-trailing-zeros 2025-09-03 14:20:23 +08:00
李通洲 37ab380a6f Logo (Chafa): fixes setting logo.width with chafa
Regression in v2.51.0

Fixes #1947
2025-09-03 10:49:58 +08:00
Carter Li a06e245c34 JsonSchema: update 2025-09-03 09:58:50 +08:00
Carter Li 5de432b083 Fastfetch: defaults display.fraction.ndigits to 2 2025-09-03 09:58:40 +08:00
Carter Li 817285ac01 Fastfetch: informs users that module-specific CLI options are no longer supported
... and provides guidance on transitioning to JSON config
2025-09-03 09:36:16 +08:00
李通洲 8687505505 LocalIP (Linux): skips interfaces without IPs unless MAC display is enabled 2025-09-02 15:00:35 +08:00
李通洲 34c34d25c4 JsonConfig: fixes fractionNdigits will be incorrectly set to 0 when specifying null 2025-09-02 14:44:15 +08:00
李通洲 21b15ee944 Display: rearranges default format; removes scaled resolution 2025-09-02 14:15:37 +08:00
李通洲 8e0a65126e LocalIP: honors fractionTrailingZeros 2025-09-02 14:13:37 +08:00
李通洲 54d8b0a95d Global: adds configurable trailing zeros for double formatting 2025-09-02 14:12:58 +08:00
李通洲 48fc72e95c DisplayServer: improves display size rounding and argument clarity 2025-09-02 09:36:19 +08:00
Carter Li e3d6a85888 Display (Linux): detect scale factor for X11 2025-09-01 21:20:34 +08:00
李通洲 7d92da8829 Global (Android): enable X11 related stuff 2025-09-01 16:28:13 +08:00
李通洲 2f3a361b1f CMake: enable zlib on all platforms 2025-09-01 09:59:06 +08:00
李通洲 ac71f21e6c DisplayServer (Android): update WM name accurately
See #1933
2025-08-30 14:14:48 +08:00
李通洲 8d5316f6aa CMake (Android): link to libm
Fix #1939
2025-08-30 13:31:37 +08:00
Carter Li 1242fda66f Merge pull request #1938 from fastfetch-cli/dev
Release: v2.51.1
2025-08-29 14:05:34 +08:00
李通洲 5a2b618d27 Release: v2.51.1 2025-08-29 13:55:52 +08:00
李通洲 d836d7569f CPU (macOS): removes reliance on unavailable ARM capability headers on macOS
Fixes https://github.com/Homebrew/homebrew-core/pull/235425
2025-08-29 13:45:16 +08:00
Carter Li 8a412e6823 Packaging: update debian stuff [ci skip] 2025-08-29 08:56:30 +08:00
883 changed files with 52252 additions and 40067 deletions
+89
View File
@@ -0,0 +1,89 @@
# find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" -o -name "*.m" -o -name "*.mm" \) -print0 | xargs -0 clang-format -i
BasedOnStyle: LLVM
UseTab: Never
IndentWidth: 4
TabWidth: 4
ContinuationIndentWidth: 4
ColumnLimit: 0
ReflowComments: true
BreakBeforeBraces: Attach
BreakBeforeCloseBracketBracedList: true
BraceWrapping:
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeElse: false
BeforeCatch: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
IndentExternBlock: NoIndent
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLoopsOnASingleLine: true
AllowShortBlocksOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
InsertBraces: true
PointerAlignment: Left
DerivePointerAlignment: false
SpaceBeforeParens: ControlStatements
SpacesInParentheses: false
SpaceAfterCStyleCast: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 1
SpacesInContainerLiterals: true
SortIncludes: Never
IndentPPDirectives: BeforeHash
PPIndentWidth: 4
IndentCaseLabels: true
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignOperands: DontAlign
BinPackParameters: false
BinPackArguments: false
AlignAfterOpenBracket: DontAlign
BracedInitializerIndentWidth: 4
Cpp11BracedListStyle: Block
ForEachMacros:
- FF_LIST_FOR_EACH
- yyjson_obj_foreach
- yyjson_arr_foreach
- yyjson_mut_obj_foreach
- yyjson_mut_arr_foreach
AttributeMacros:
- FF_A_FALLTHROUGH
- FF_A_DEPRECATED
- FF_A_CLEANUP
- FF_A_NODISCARD
- FF_A_PRINTF
- FF_A_SCANF
- FF_A_NONNULL
- FF_A_RETURNS_NONNULL
- FF_A_UNUSED
- FF_A_PACKED
- FF_A_WEAK_IMPORT
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: false
---
Language: ObjC
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
ObjCBreakBeforeNestedBlockParam: true
+3
View File
@@ -0,0 +1,3 @@
src/3rdparty/**
build/**
src/logo/builtin.c
+3
View File
@@ -0,0 +1,3 @@
github: LinusDierheimer
ko_fi: carterli
custom: https://paypal.me/zhangsongcui
@@ -16,6 +16,15 @@ body:
options:
- label: I have checked the FAQ but the issue is not covered
required: true
- type: checkboxes
attributes:
label: Not a known issue
description: Please check if the issue is already known and being worked on.
options:
- label: I have checked the existing issues but the issue is not covered
required: true
- label: My issue is not about crashing on Fedora and KDE 6.6
required: true
- type: markdown
attributes:
value: "### General description of the bug"
+18 -9
View File
@@ -6,33 +6,42 @@ body:
- type: markdown
attributes:
value: |
Tip: A logo can be displayed by fastfetch without getting into fastfetch's official repo.
For highly customized logo for personal use, it's recommended to keep it locally.
Tip: You can display a logo in fastfetch without adding it to fastfetch's official repo.
For highly customized, personal logos, we recommend keeping them locally.
Please refer to https://github.com/fastfetch-cli/fastfetch/wiki/Migrate-Neofetch-Logo-To-Fastfetch
- type: textarea
attributes:
label: OS
description: Paste content of `/etc/os-release` and `/etc/lsb-release` here. If none of these files exist, describe a way to identify the distro
description: Paste the contents of `/etc/os-release` and `/etc/lsb-release` here. If neither file exists, describe how to identify the distro.
placeholder: cat /etc/os-release
validations:
required: true
- type: input
attributes:
label: Distro Website
description: To help prevent spam and verify the request, a distro website is required, and a downloadable ISO must be available on that site.
placeholder: https://example.com
validations:
required: true
- type: textarea
attributes:
label: ASCII Art
description: An ASCII logo should not take up too much space (smaller than 50x20 characters). Please also include the color codes if not available in `os-release`
description: The ASCII logo should not take up too much space (smaller than 50x20 characters, W x H). Please also include the color codes if they are not available in `os-release`.
placeholder: Paste ASCII art here
validations:
required: true
- type: input
attributes:
label: Original Image
description: If the ASCII art is based on an image, please provide a link to the original image
placeholder: Image URL or distro website URL
label: Original Image URL
description: If the ASCII art is based on an image, please provide a link to the original image file.
placeholder: Image URL from the distro website mentioned above
- type: checkboxes
attributes:
label: Checklist
options:
- label: The ASCII art is smaller than 50x20 characters (width x height)
- label: The ASCII art is smaller than 50x20 characters (W x H).
required: true
- label: The ASCII art contains color codes, or the color codes are available in `os-release`
- label: The ASCII art includes color codes, or the color codes are available in `os-release`.
required: true
- label: The ASCII art has no internal padding (spaces at the start and/or end of lines).
required: true
+30
View File
@@ -0,0 +1,30 @@
## Summary
<!-- Briefly describe what this PR does. -->
## Related issue (required for new logos for new distros)
<!--
If this PR adds a new logo, it MUST be linked to an existing "Logo Request" issue and has the requests fulfilled.
Use one of the following formats so GitHub links it properly:
- Closes #1234
- Fixes #1234
- Resolves #1234
PRs that add logos without an associated Logo Request issue will not be accepted.
-->
Closes #
## Changes
-
## Screenshots
<!-- Required if this PR introduces visual changes. -->
## Checklist
- [ ] I have tested my changes locally.
@@ -0,0 +1,40 @@
name: Reusable DragonFly amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: vmactions/dragonflybsd-vm@v1
with:
usesh: yes
envs: 'CMAKE_BUILD_TYPE'
prepare: |
uname -a
pkg update
pkg install -y llvm cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa libelf
run: |
env CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-dragonfly-amd64
path: ./fastfetch-*.*
+42
View File
@@ -0,0 +1,42 @@
name: Reusable FreeBSD amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: cross-platform-actions/action@master
with:
operating_system: freebsd
architecture: x86-64
cpu_count: 4
shell: bash
version: '15.0'
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
sudo pkg update
sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm glib dconf dbus sqlite3-tcl egl opencl ocl-icd v4l_compat chafa
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-freebsd-amd64
path: ./fastfetch-*.*
+40
View File
@@ -0,0 +1,40 @@
name: Reusable Haiku amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: cross-platform-actions/action@master
with:
operating_system: haiku
version: 'r1beta5'
architecture: x86-64
cpu_count: 4
shell: bash
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10 || pkgman install -y git dbus_devel mesa_devel libelf_devel imagemagick_devel opencl_headers ocl_icd_devel vulkan_devel zlib_devel chafa_devel cmake gcc make pkgconfig python3.10
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-haiku-amd64
path: ./fastfetch-*.*
+40
View File
@@ -0,0 +1,40 @@
name: Reusable Linux armv6l
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-24.04
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: uraimo/run-on-arch-action@v3
id: runcmd
with:
arch: armv6
distro: bookworm
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y wget
apt-get install -y cmake make gcc libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libefl-all-dev rpm
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-linux-armv6l
path: ./fastfetch-*.*
+44
View File
@@ -0,0 +1,44 @@
name: Reusable Linux armv7l
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-24.04
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: uraimo/run-on-arch-action@v3
id: runcmd
with:
arch: armv7
distro: ubuntu22.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y software-properties-common ca-certificates gpg curl
add-apt-repository -y ppa:ubuntu-toolchain-r/test
curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ jammy main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
echo -e 'Acquire::https::Verify-Peer "false";\nAcquire::https::Verify-Host "false";' >> /etc/apt/apt.conf.d/99ignore-certificates
apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libefl-all-dev rpm
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-linux-armv7l
path: ./fastfetch-*.*
+103
View File
@@ -0,0 +1,103 @@
name: Reusable Linux Hosts
on:
workflow_call:
inputs:
arch:
required: true
type: string
runs-on:
required: true
type: string
outputs:
ffversion:
description: fastfetch version from linux host build
value: ${{ jobs.build.outputs.ffversion }}
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ${{ inputs.runs-on }}
outputs:
ffversion: ${{ steps.ffversion.outputs.ffversion }}
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: uname -a
run: uname -a
- name: cat /etc/os-release
run: cat /etc/os-release
- name: cat /proc/cpuinfo
run: cat /proc/cpuinfo
- name: add gcc-13 repo
run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev rpm ninja-build
- 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: Initialize CodeQL
if: inputs.arch == 'amd64'
uses: github/codeql-action/init@v4
with:
languages: c
- name: configure project
run: CC=gcc-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -GNinja -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
- name: perform CodeQL analysis
if: inputs.arch == 'amd64'
uses: github/codeql-action/analyze@v4
- 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: get fastfetch version
id: ffversion
run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT
- name: polyfill glibc
run: |
wget https://github.com/CarterLi/polyfill-glibc/releases/download/v0.0.1/polyfill-glibc-${{ inputs.arch }} -O polyfill-glibc
chmod +x polyfill-glibc
strip fastfetch && ./polyfill-glibc fastfetch --target-glibc=2.17
strip flashfetch && ./polyfill-glibc flashfetch --target-glibc=2.17
echo 'set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-polyfilled")' >> CPackConfig.cmake
echo 'set(CPACK_PACKAGE_RELOCATABLE OFF)' >> CPackConfig.cmake
echo 'set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.17)")' >> CPackConfig.cmake
echo 'set(CPACK_RPM_SPEC_MORE_DEFINE "%global __os_install_post %{nil}")' >> CPackConfig.cmake
cpack -V
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-linux-${{ inputs.arch }}
path: ./fastfetch-*.*
+70
View File
@@ -0,0 +1,70 @@
name: Reusable Linux i686
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: uname -a
run: uname -a
- name: cat /etc/os-release
run: cat /etc/os-release
- name: cat /proc/cpuinfo
run: cat /proc/cpuinfo
- name: add gcc-13 repo
run: sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y gcc-13 gcc-13-multilib libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev libefl-all-dev libunwind-dev rpm ninja-build
- 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: cmake version
run: cmake --version
- name: configure project
run: CC=gcc-13 PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DCMAKE_C_FLAGS="-m32 -march=i686 -mtune=i686" -DCMAKE_SYSTEM_PROCESSOR_OVERRIDE=i686 -DCPACK_DEBIAN_PACKAGE_ARCHITECTURE=i386 -GNinja -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
- name: check deb package
run: dpkg -I fastfetch-*.deb
- 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: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-linux-i686
path: ./fastfetch-*.*
+45
View File
@@ -0,0 +1,45 @@
name: Reusable Linux VMs
on:
workflow_call:
inputs:
arch:
required: true
type: string
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: uraimo/run-on-arch-action@v3
id: runcmd
with:
arch: ${{ inputs.arch }}
distro: ubuntu22.04
githubToken: ${{ github.token }}
run: |
uname -a
apt-get update && apt-get install -y software-properties-common
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt-get update && apt-get install -y cmake make gcc-13 libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev libefl-all-dev rpm
CC=gcc-13 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-linux-${{ inputs.arch }}
path: ./fastfetch-*.*
+58
View File
@@ -0,0 +1,58 @@
name: Reusable macOS Hosts
on:
workflow_call:
inputs:
arch:
required: true
type: string
runs-on:
required: true
type: string
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ${{ inputs.runs-on }}
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: uname -a
run: uname -a
- name: install required packages
run: |
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --target package --verbose -j4
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan --stat false
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: otool -L fastfetch
- name: run tests
run: ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-macos-${{ inputs.arch }}
path: ./fastfetch-*.*
+45
View File
@@ -0,0 +1,45 @@
name: Reusable Musl amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: setup alpine linux
uses: jirutka/setup-alpine@master
- name: install dependencies
run: |
cat /etc/alpine-release
uname -a
apk add cmake samurai vulkan-loader-dev libxcb-dev libxrandr-dev rpm-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++
shell: alpine.sh --root {0}
- name: build
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -GNinja .
cmake --build . --target package --verbose -j4
shell: alpine.sh {0}
- name: run
run: |
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
shell: alpine.sh {0}
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-musl-amd64
path: ./fastfetch-*.*
+41
View File
@@ -0,0 +1,41 @@
name: Reusable NetBSD amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: cross-platform-actions/action@master
with:
operating_system: netbsd
architecture: x86-64
cpu_count: 4
shell: bash
version: '10.1'
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
sudo pkgin -y install clang cmake git pkgconf wayland vulkan-headers dconf dbus sqlite3 ImageMagick
CC=clang cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-netbsd-amd64
path: ./fastfetch-*.*
@@ -0,0 +1,42 @@
name: Reusable No Features Test
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: uname -a
run: uname -a
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_EET=OFF -DENABLE_THREADS=OFF
- name: build project
run: cmake --build . --target package --verbose -j4
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: ldd fastfetch
- name: run tests
run: ctest --output-on-failure
+42
View File
@@ -0,0 +1,42 @@
name: Reusable OmniOS amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: vmactions/omnios-vm@v1
with:
usesh: true
envs: 'CMAKE_BUILD_TYPE'
prepare: |
uname -a
pkg update --accept || true
pkg install gcc14 cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja
run: |
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja .
cmake --build . --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-omnios-amd64")' >> CPackConfig.cmake
cpack -V
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-omnios-amd64
path: ./fastfetch-*.*
+42
View File
@@ -0,0 +1,42 @@
name: Reusable OpenBSD amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: cross-platform-actions/action@master
with:
operating_system: openbsd
architecture: x86-64
cpu_count: 4
shell: bash
version: '7.8'
environment_variables: 'CMAKE_BUILD_TYPE'
run: |
uname -a
sudo pkg_add -u
sudo pkg_add -r llvm-21.1.2p0 cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 imagemagick chafa
CC=clang-21 cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On .
cmake --build . --target package --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-openbsd-amd64
path: ./fastfetch-*.*
+58
View File
@@ -0,0 +1,58 @@
name: Reusable Release
on:
workflow_call:
inputs:
ffversion:
required: true
type: string
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: get latest release version
id: get_version_release
uses: pozetroninc/github-action-get-latest-release@master
with:
repository: ${{ github.repository }}
- name: download artifacts
if: inputs.ffversion != steps.get_version_release.outputs.release
uses: actions/download-artifact@v8
- name: create release
if: inputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ inputs.ffversion }}
commit: ${{ github.sha }}
artifactErrorsFailBuild: true
artifacts: fastfetch-*/fastfetch-*
body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ inputs.ffversion }}/CHANGELOG.md) for details."
- name: download source tarballs
if: inputs.ffversion != steps.get_version_release.outputs.release
run: |
for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ inputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done
ls fastfetch-*/*
- name: generate release notes
if: inputs.ffversion != steps.get_version_release.outputs.release
run: |
echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ inputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md
echo -e "\n---\n\n<details><summary>SHA256SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
sha256sum fastfetch-*/* >> fastfetch-release-notes.md
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
echo -e "\n<details><summary>SHA512SUMs</summary><br>\n\n\`\`\`" >> fastfetch-release-notes.md
sha512sum fastfetch-*/* >> fastfetch-release-notes.md
echo -e "\`\`\`\n</details>" >> fastfetch-release-notes.md
- name: update release body
if: inputs.ffversion != steps.get_version_release.outputs.release
uses: ncipollo/release-action@v1
with:
tag: ${{ inputs.ffversion }}
commit: ${{ github.sha }}
bodyFile: fastfetch-release-notes.md
allowUpdates: true
+43
View File
@@ -0,0 +1,43 @@
name: Reusable Solaris amd64
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: run VM
uses: vmactions/solaris-vm@v1
with:
usesh: true
envs: 'CMAKE_BUILD_TYPE'
release: "11.4-gcc-14"
prepare: |
uname -a
pkg install cmake git pkg-config glib2 dbus sqlite-3 imagemagick ninja dconf mesa
run: |
export PKG_CONFIG_PATH=/usr/lib/64/pkgconfig
cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -GNinja .
cmake --build . --verbose -j4
./fastfetch --list-features
time ./fastfetch -c presets/ci.jsonc --stat false
time ./fastfetch -c presets/ci.jsonc --format json
time ./flashfetch
ldd fastfetch
ctest --output-on-failure
echo 'set(CPACK_PACKAGE_FILE_NAME "fastfetch-solaris-amd64")' >> CPackConfig.cmake
cpack -V
- name: upload artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-solaris-amd64
path: ./fastfetch-*.*
+24
View File
@@ -0,0 +1,24 @@
name: Reusable Spellcheck
on:
workflow_call:
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
spellcheck:
runs-on: ubuntu-latest
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: Install codespell
shell: bash
run: |
sudo apt-get update || true
sudo apt-get install -y codespell
- name: Run Spellchecker
run: codespell
+106
View File
@@ -0,0 +1,106 @@
name: Reusable Windows Hosts
on:
workflow_call:
inputs:
arch:
required: true
type: string
runs-on:
required: true
type: string
msystem:
required: true
type: string
msystem-lower:
required: true
type: string
msys-arch:
required: true
type: string
env:
CMAKE_BUILD_TYPE: ${{ vars.CMAKE_BUILD_TYPE || 'RelWithDebInfo' }}
jobs:
build:
runs-on: ${{ inputs.runs-on }}
defaults:
run:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v6
- name: setup-msys2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ inputs.msystem }}
update: true
install: git mingw-w64-clang-${{ inputs.msys-arch }}-7zip mingw-w64-clang-${{ inputs.msys-arch }}-cmake mingw-w64-clang-${{ inputs.msys-arch }}-clang mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-loader mingw-w64-clang-${{ inputs.msys-arch }}-vulkan-headers mingw-w64-clang-${{ inputs.msys-arch }}-opencl-icd mingw-w64-clang-${{ inputs.msys-arch }}-opencl-headers mingw-w64-clang-${{ inputs.msys-arch }}-cppwinrt mingw-w64-clang-${{ inputs.msys-arch }}-imagemagick mingw-w64-clang-${{ inputs.msys-arch }}-chafa mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers
- name: print msys version
run: uname -a
- name: configure project
run: env PKG_CONFIG_PATH=/${{ inputs.msystem-lower }}/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 /${{ inputs.msystem-lower }}/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
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
id: upload-unsigned-artifact
name: upload artifacts for signing
uses: actions/upload-artifact@v7
with:
name: fastfetch-windows-${{ inputs.arch }}
path: |
*.dll
fastfetch.exe
flashfetch.exe
- if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch'
name: submit signing request
uses: signpath/github-action-submit-signing-request@v1
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
organization-id: '${{ vars.SIGNPATH_ORG_ID }}'
project-slug: 'fastfetch'
signing-policy-slug: ${{ github.ref == 'refs/heads/master' && 'release-signing' || 'test-signing' }}
github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}'
wait-for-completion: true
output-artifact-directory: '.'
- name: create zip archive
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-${{ inputs.arch }}.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-${{ inputs.arch }}.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: upload true artifacts
uses: actions/upload-artifact@v7
with:
name: fastfetch-windows-${{ inputs.arch }}
path: ./fastfetch-windows-${{ inputs.arch }}.*
overwrite: true
+106 -819
View File
File diff suppressed because it is too large Load Diff
+470
View File
@@ -1,3 +1,473 @@
# 2.63.1
Bugfixes:
* Fixes media length detection for Chrome on Linux (Media, Linux)
* Fixes segmentation fault when specifying unsupported modules on command line
* Disables usage of Netlink for Wi-Fi detection on s390x architectures (Wifi, Linux)
# 2.63.0
Changes:
* Introduces a new **build-only** dependency, `libefl`, for querying the Enlightenment window manager configuration:
* `libefl-all-dev` on Debian/Ubuntu
* `libefl-devel` on Fedora
* `efl` on Arch Linux
* The Windows-specific options `battery.useSetupApi` and `global.wmiTimeout` have been removed. (Windows)
Features:
* Adds wallpaper detection support on Haiku (#2314, Wallpaper, Haiku)
* Adds Wi-Fi 6 GHz channel detection and improves protocol reporting (Wifi, Linux)
* Improves Deepin version detection using `/etc/os-version` (#2300, OS, Linux)
* Adds Ubuntu Kylin and Ubuntu Unity flavor detection (OS, Linux)
* Adds NebiDE support (WMTheme, Linux)
* Adds package counting for `cards` on NuTyX (#2287, Packages, Linux)
* Adds `{am-pm}` to custom format for 12-hour time with am/pm (DateTime)
* Adds support for the Enlightenment desktop environment (#2165, WM, Linux)
* Adds support for playback progress detection (Media)
* The module now prints the current playback position and total media duration when supported by the player. If you prefer the previous behavior, you can set `media.percent.type: ["hide-others"]` to hide the new fields.
* Adds support for `global.playerName` for Windows (Media, Windows)
* This allows detecting a specified media player while ignoring others.
* Multi-battery detection is enabled on Windows by default (Battery, Windows)
Bugfixes:
* Improves DisplayServer compatibility on Linux by handling newer `kde-output-device-v2` protocol updates (DisplayServer, Linux)
* This fixes a long-standing issue where display detection fails with an `interface 'kde_output_device_mode_v2' has no event X` error.
* Improves Wi-Fi reliability on Linux by switching to a netlink implementation (Wifi, Linux)
* Improves network interface reliability and default route selection on macOS and Windows (Netif, macOS / Windows)
* Validates temperature color thresholds as integers when parsing JSON configs (Temps)
* Fixes TDE Konsole version detection (#2319, Terminal, Linux)
* Various internal cleanups and optimizations
Logos:
* Adds KibaOS, NebiOS, XJ380, openRuyi, Ximper
* Fixes GNOME OS built-in logo detection (#2296)
# 2.62.1
Bugfixes:
* Fixes the Host module not working on some devices (#2279, Host, Linux)
* Regression from v2.61.0
Logos:
* Adds EN-OS, LimeOS, Redrose and Uzbek
# 2.62.0
Changes:
* Sort package managers alphabetically in output and format arguments (Packages)
* The positional order of format arguments has changed — this is a breaking change for users relying on numeric placeholders. Named arguments are always preferred; e.g., use `{pacman}` (refer to `fastfetch -h packages-format`) instead of `{1}` to keep your config future-proof.
Features:
* Reports `Unused` instead of `Disabled` for zero-size swap on macOS (#2248, Swap, macOS)
* Improves the robustness of default route detection on Linux (#2252, LocalIP, Linux)
* PhysicalDisk module improvements
* Detects virtual disks and adds support for hiding them via `hideVirtual` option (defaults to `false`)
* Detects unused/disconnected disks and adds support for hiding them via `hideUnused` option (defaults to `true`)
* Adds support for OpenBSD and NetBSD (root privileges are required to access disk information)
* Improves interconnect type detection on SunOS
* Adds floppy drive support on Windows
* Rewrites Windows GPU detection with D3DKMT APIs, unifying it with WSL GPU detection (GPU, Windows)
* Verifies that the battery and power adapter are present before detection (Battery / PowerAdapter, Linux)
* Improves PhysicalMemory reliability on OpenBSD and FreeBSD, including support for x86 UEFI systems on OpenBSD and non-UEFI systems on FreeBSD (PhysicalMemory, OpenBSD / FreeBSD)
* Adds `display.common.(ndigits|spaceBeforeUnit)` options to configure common formatting for duration, percent, size, frequency and temperature values (#2234)
* Slightly improves performance by skipping probes for ignored device types (Sound)
* Adds support for AppImage package detection (#2179, Packages, Linux)
Bugfixes:
* Fixes a potential crash on certain Intel GPU models when using `--gpu-driver-specific` (#2259, GPU, Linux)
* Doesn't report partitions as physical disks (DiskIO, NetBSD)
* Fixes a typo (#2260, Wifi, macOS)
* Corrects documentation for zpool format placeholders (#2261, Zpool)
* Restores Windows 8.1 support (Cursor, Windows)
* Fixes an out-of-bounds memory access when swaps are disabled (Swap, Windows)
* Fixes battery status being incorrectly reported as `Charging` on systems with multiple batteries (#2263, Battery, Linux)
* Fixes ash shell version detection (#2271, Shell, Linux)
* Uses the `iterm` image protocol automatically on iTerm terminals for auto logo type (Logo)
* Adds missing options when generating full config file
Logos:
* Updates AerynOS (#2272)
# 2.61.0
Changes:
* Support for Windows 7 and 8 has been removed.
* Windows 8.1 is now the oldest version supported by fastfetch.
* The GPU module on WSL no longer relies on `DXCore`.
* The `directx-headers` dependency is no longer required.
* Fastfetch on Linux is now pure C; a C++ compiler is no longer required.
* GPU type detection is now slightly less accurate, but detection speed should be slightly faster.
* The GPU module on Windows now uses `DXCore` for more accurate GPU type detection (requires Windows 10 or later).
* This feature is built only when `DXCore` headers are available, which requires installing `mingw-w64-<msystem>-x86_64-directx-headers` on MSYS2.
Features:
* Adds a `brightness` option for color display configuration (#2238, Colors)
* Adds support for detecting Bluetooth keyboards on Linux (#2220, Keyboard)
* Adds support for detecting GlazeWM (WM, macOS)
* Adds a `showEmptySlots` option to display empty memory slots on Linux (#2222, PhysicalMemory)
* Adds marketing product name detection on Asahi Linux (Host, Linux)
* Adds support for new M5 Mac models (Host, macOS)
* Improves SMBIOS robustness by validating malformed data and improving error handling
* Improves reliability when terminating child processes (Processing, Windows)
* Improves Intel Mac support by querying SMBIOS data directly (Global, macOS)
* Includes numerous internal cleanups and optimizations
Bugfixes:
* Fixes missing memory devices on some machines (PhysicalMemory)
* Fixes CPUCache deduplication for shared caches (#2228, CPUCache, Linux)
* Fixes WM version reporting for niri (#2218, WM, Linux)
* Fixes SSID decoding issues from `iw` output (Wifi, Linux)
* Fixes the CMD code page being changed after running fastfetch on Windows (#2245, Windows)
# 2.60.0
Changes:
* The CMake option `ENABLE_WIN7_COMPAT:BOOLEAN` now defaults to `OFF` and will be removed in v2.61.0, effectively dropping support for Windows 7 in the next release.
* This follows the Windows 7 deprecation notice introduced in v2.57.0.
* `wm.detectPlugin` now defaults to `true` (WM)
Features:
* Adds `{cwd}` for custom title formatting, which displays the current working directory (Title)
* Adds support for detecting the Zed version (#2200, Editor)
* Adds support for detecting `moss` packages (Packages, Linux)
* Adds support for detecting komorebi, FancyWM, and GlazeWM (WM, Windows)
* Adds support for WM plugin version detection on macOS (WM, macOS)
* Adds support for retrieving the executable path on OpenBSD (#2195, OpenBSD)
Bugfixes:
* Fixes a potential segmentation fault caused by dereferencing a negative index (#2198)
* Fixes `tempSensor` parsing so that it accepts only string values (#2202, CPU)
* Fixes an issue that unexpectedly caused fewer devices to be reported (Keyboard, Linux)
* Improves WM detection on LXQt by querying WM settings only when no WM has already been detected (#2199, WM, Linux)
* Fixes memory leaks in DBus connection handling and in the OpenGL EGL context lifecycle
* Fixes niri version detection on Fedora (WM, Linux)
* Includes various internal cleanups and optimizations
Logos:
* Adds `RengeOS` (#2170)
* Adds `Emmabuntüs` (#2207)
* Updates Artix Linux (#2157)
* Updates Linux Mint (#2186)
* Renames `Refracted Devuan` to `Refracta`
* Renames `ExodiaPredator` to `ExodiaOS`
# 2.59.0
Changes:
* Fastfetch no longer relies on the unreliable environment variables `$USER` or `%USERPROFILE%` to determine the current username (Title)
* People who set `$USER` to customize the Fastfetch title should use `{ "type": "title", "format": "your-custom-user-name" }` to achieve the same result.
* Fastfetch no longer tries to probe inaccessible remote disk drives on Windows (Disk, Windows)
* People who have remote drives may use `{ "type": "disk", "hideFolders": "X:\\" }` to ignore problematic ones.
* This change removes some ugly hacks from the codebase and matches the behavior on `*nix`.
Features:
* Adds Oracle Solaris support (#2176, SunOS)
* Adds UID / SID detection (Title)
* In custom format: `{user-id}`
* Switches to native GPU detection on GNU/Hurd and removes the `libpciaccess` dependency (GPU, Hurd)
* Improves memory size detection on macOS (Memory, macOS)
* Avoids relying on `hw.memsize_usable` by default, which may not be available on older macOS versions
* Improves Windows disk detection accuracy and performance (Disk, Windows)
* Adds more ARM CPU parts and removes duplicated cases (CPU, ARM)
Logos:
* Adds 6-color support to the NixOS logo (including the small variant) (#2180)
# 2.58.0
An early release to fix compatibility issues with KDE Plasma 6.6.
Breaking changes:
* The `de.slowVersionDetection` option has been removed. Slow version detection is now always enabled, as required on non-FHS-compliant distros (e.g., NixOS). (#2149, DE, Linux)
Features:
* Adds the `--structure-disabled <modules...>` command-line flag to temporarily disable module structure printing.
* For example: `fastfetch --structure-disabled colors` removes the color blocks from the default output.
* Supports chassis type detection on Linux ARM devices when reported via the device tree (Chassis, Linux)
* Supports Bedrock Linux version detection (#2155, OS, Linux)
* Honors the `DBPath` and `RootDir` settings in `pacman.conf` when detecting Pacman packages (#2154, Packages, Linux)
Bugfixes:
* Fixes a crash issue on KDE Plasma 6.6 (Display, Linux)
* Fixes the Command module not working with `--dynamic-interval` (#2152, Command)
* Fixes Quartz Compositor version detection. It now correctly reports the version of `WindowServer` (`SkyLight`) instead of `WindowManager`. (WM, macOS)
Logos:
* Adds Kiss2
# 2.57.1
Features:
* Tiny performance improvements (Windows)
* Improves the reliability of hostname retrieval (Title, Windows)
Bugfixes:
* Fixes potential compilation issues on Linux (#2142, Linux)
* Fixes compilation errors on macOS when building with older SDKs (#2140, macOS)
* Fixes compilation issues when building with `-DENABLE_SYSTEM_YYJSON=ON` (#2143)
Logos:
* Updates PrismLinux and adds a small variant
# 2.57.0
Deprecation notice:
* Support for Windows 7 (and 8.x) is deprecated and will be removed in a future release. Extended support for Windows 7 (and 8.1) ended on January 10, 2023. These versions do not officially support ANSI escape codes (running fastfetch on them requires a third-party terminal such as ConEmu). In addition, Windows 7 lacks some APIs used by fastfetch. Fastfetch currently loads these APIs dynamically at runtime to maintain compatibility, but this adds complexity to the codebase and increases the maintenance burden.
* A CMake flag `ENABLE_WIN7_COMPAT:BOOLEAN` has been introduced (defaults to `ON` for now). If set to `OFF`, Windows 7 compatibility code is excluded, and the resulting binaries will support only Windows 10 (version 1607 and later) and Windows 11.
* The main prebuilt Windows binaries on the Release page (`fastfetch-windows-amd64.*`) are built with `ENABLE_WIN7_COMPAT=OFF`. These are the binaries used by `scoop` and `winget`. Users who need Windows 7 (or 8.x) support can download the `-win7` variant instead.
* ~~The `ENABLE_WIN7_COMPAT` CMake option and the `-win7` variant binaries are planned to be removed in 2.60.0~~.
Features:
* Supports COSMIC DE version detection (DE, Linux)
* Supports niri version detection (#2121, WM, Linux)
* Supports cosmic-term version and terminal font detection (Terminal / TerminalFont, Linux)
* Supports urxvt font detection (TerminalFont, Linux) (#2105)
* Improves xterm font detection by checking `xterm.vt100.faceName` (TerminalFont, Linux)
* Supports Secure Boot detection (Bootmgr, macOS)
* Supports DPI scale factor detection on Windows 7 (Display, Windows)
* Supports xterm 256-color codes in color configuration
* In `display.color`: "`@<color-index>`" (e.g., "`@34`" for color index `34`)
* In `*.format` strings: "`#@<color-index>`" (e.g., "`#@34`" for color index `34`)
* Improves uptime accuracy on Windows 10+ (Uptime, Windows)
* Adds a new module `Logo` to query built-in logo raw data in JSON output (Logo)
* Usage: `fastfetch -s logo -l <logo-name> -j # Supported in JSON format only`
* Supports shell version detection even if the binary has been deleted (#2136, Shell, Linux)
* Overall code refinements and optimizations
Bugfixes:
* Skips local / loopback routes when detecting network interfaces (LocalIP, Linux) (#2127)
* Fixes CPU speed detection on s390x (CPU, Linux) (#2129)
* Fixes GPU detection error handling and supports case-insensitive PCI ID parsing (GPU, Windows)
* Fixes some networking issues and memory leaks (Networking)
* Fixes `exePath` reporting relative paths on macOS (Shell, macOS)
Logos:
* Adds openSUSE Tumbleweed braille logo
* Adds Xinux
* Renames HydraPWK to NetHydra
* Fixes colors of deepin and UOS
* Fixes colors of macOS and variants
# 2.56.1
Features:
* Improves compatibility with KDE Plasma 6.5 (#2093, Display)
* Adds a `tempSensor` option to specify the sensor name used for CPU temperature detection (CPU)
* Example: `{ "type": "cpu", "tempSensor": "hwmon0" /* Use /sys/class/hwmon/hwmon0 for temperature detection */ }`
* Refines Memory usage detection on macOS to match Activity Monitor more closely (Memory, macOS)
* Minor optimizations
Bugfixes:
* Fixes cache line size detection (CPU, macOS)
Logos:
* Removes Opak
* Updates GXDE
# 2.56.0
Features:
* Enhances config file loading. `--config` and `-c` with relative path now also searches paths defined in `fastfetch --list-config-paths` (typically `~/.config/fastfetch/`)
* This allows users to use `fastfetch -c my-config` without needing to specify the full path.
* Adds NUMA node count detection (CPU)
* Exposed via `{numa-nodes}` in custom format
* Supported on Linux, FreeBSD and Windows
* Supports the newest Alacritty config format (#2070, TerminalFont)
* Detects driver specific info for Zhaoxin GPUs (GPU, Linux)
* Detects Android OEM UI for certain OSes (DE, Android)
* Improves users detection on Linux (#2064, Users, Linux)
* Adds systemd fallback when utmp is unavailable
* Fixes resource leaks
* Always reports the newest session info
* Adds kiss package manager support (#2072, Packages, Linux)
* Reports `sshd` if `$SSH_TTY` is not available (Terminal)
* Zpool module rewrite (#2051, Zpool)
* Adds new Zpool properties: allocated, guid, readOnly
* Zpool module now uses runtime lookup for properties to ensure portability
* Adds NetBSD (requires `sudo`) and macOS support
* Adds `splitLines` option for Command module, which splits the output into sub modules, each containing one line of the output (Command)
```
* Command output:
Line 1
Line 2
Line 3
* Old behavior:
Command: Line 1
Line 2
Line 3
* With `"splitLines": true`:
Command 1: Line 1
Command 2: Line 2
Command 3: Line 3
```
Bugfixes:
* Fixes {m,o}ksh version detection on Linux (Shell)
* Fixes Alacritty config parsing for TOML format (#2070, TerminalFont)
* Improves builtin logo printing for piping and buffering (#2065, Logo)
* Uses absolute path when detecting shell and terminal version if available (#2067, TerminalShell)
Logos:
* Updates Codex Linux logo (#2071)
* Adds OS/2 Warp logo (#2062)
* Adds Amiga logo (#2061)
# 2.55.1
Bugfixes:
* Fix parallel command execution breaks randomly (#2056 / #2058, Command)
* Regression from v2.55.0
* Fix `dylib` searching path on macOS (macOS)
* Regression from v2.55.0
* Fix an uninitialized field (#2057, Display)
# 2.55.0
Changes:
* Commands are now executed in parallel by default to improve performance (#2045, Command)
* This behavior can be disabled in the config file with `"parallel": false` if it causes problems with certain scripts
* Folder/filesystem hiding is moved to the detection stage; hidden entries are no longer probed, improving performance (#2043, Disk)
Features:
* Adds `command.parallel` and `command.useStdErr` config options (Command)
* `parallel`: set to `false` to disable parallel execution (see Changes above)
* `useStdErr`: set to `true` to use stderr output instead of stdout
* Adds the command-line flag `--dynamic-interval <interval-in-ms>` to enable dynamic output auto-refresh (#2041)
* Due to internal limitations, some modules do not support dynamic updates (notably Display and Media)
* Adds support for using the current playing media's cover art as a logo source (Media / Logo)
* Usage: `"logo": { "type": "<image-protocol>", "source": "media-cover" }` in JSON config; or `--<image-protocol> media-cover` in command line
* Supports local sources only
* Adds native GPU detection support on OpenBSD and NetBSD (instead of depending on `libpciaccess`) (GPU)
* No functional changes
* Root privileges are required to access PCI config space on OpenBSD (as always)
* Adds GPU detection support on GNU/Hurd (GPU)
* Requires building with `libpciaccess`
* Shows Debian point release on Raspberry Pi OS (#2032, OS, Linux)
* Adds `Brush` shell version detection (Shell)
* Improves Mac family detection via prefix matching (Host)
Bugfixes:
* Ignores `run-parts` during terminal/shell detection (#2048, Terminal / Shell, Linux)
* Fixes fish version detection when `LC_ALL` is set (#2014, Shell, Linux)
* Hides the module when no desktop icons are found (#2023, Icons, Windows)
* Skips auxiliary display controllers to prevent the module from reporting duplicate entries (#2034, GPU, Linux)
* Refines Apple rpath handling; fixes building for the Homebrew version on macOS (#1998, CMake)
Logos:
* Adds Vincent OS and MacaroniOS
# 2.54.0
Windows binaries in Release page are now signed by SignPath.
Changes:
* Moves macOS and Windows design language detection from the DE module to the Theme module
Features:
* Adds `--json` and `-j` command line flags as a shortcut for `--format json`
* Various improvements to the OS module (OS)
* Displays point releases for Debian
* Displays code names for Ubuntu
* Displays build ID for macOS
* Displays code names for Windows (previously shown in the Kernel module)
* Adds basic support for Wine (Windows)
* Adds basic support for hppa and sh architectures (CPU, Linux)
* Improves T-Head SoC name detection from the device tree (#1997, CPU, Linux)
* Supports glob patterns in `Disk.hideFolders` (Disk)
* For example, `/boot/*` will match both `/boot/efi` and `/boot/firmware`
* Adds brightness-level detection for external monitor support on Intel macOS (Brightness, macOS)
* Adds configurable spacing between icon and text in keys
* `display.key.type: "both-N"` where N is `0-4`
* Useful for non-monospaced Nerd Fonts
* Adds detection support for modern Samsung Exynos SoCs (CPU, Android)
* Adds a new CMake option `-DENABLE_WORDEXP=<ON|OFF>` to enable or disable using `wordexp(3)` for acquiring logo file paths (`logo.source`)
* Enabled by default for compatibility
* Disabling this option reverts to using `glob(3)`, which is less functional but more secure
Bugfixes:
* Avoids integer overflow when calculating swap size (#1988, Swap, Windows)
* Trims whitespace from full user name (Title, macOS)
* Fixes default font size for Ghostty (#1986, TerminalFont, Linux)
* Works around an issue that could report impossibly high memory usage in rare cases (#1988, Memory, Linux)
* Fixes incorrect glibc dependency in polyfilled DEB packages (#1983, Linux)
* Fixes corrupted binaries in polyfilled RPM packages (#1990, Linux)
* Fixes crashes on ancient Android kernels (#1993, Disk, Android)
* Fixes incorrect usage of `glob(3)` (OpenBSD)
* Prefers resolutions reported by RandR mode info, fixing incorrect resolutions on XFCE when DPI scaling is enabled (Display, Linux)
* Various code cleanups and minor fixes
Logos:
* Adds secureblue, PrismLinux, EmperorOS and Zraxyl
* Updates T2
# 2.53.0
Changes:
* JSON property `length` in `Separator` module has been renamed to `times` for clarity (Separator)
Features:
* Adds IPv6 type selection (#1459, LocalIP)
* For example: `{ "type": "localip", "showIpv6": "ula" /* Show ULA only */ }`
* Adds more ARM CPU part IDs (CPU, Linux)
* Improves Ghostty font config parsing with fallback font detection (#1967, TerminalFont)
* Replaces statx(2) call with syscall(2) for better compatibility (Disk, Linux)
* Allows array input for disk folder and filesystem options (Disk)
* For example: `{ "type": "disk", "folders": ["/", "/home"] }`
* Adds support for ignoring input devices by name prefix (#1950, Keyboard / Mouse / Gamepad)
* For example: `{ "type": "keyboard", "ignores": ["Apple ", "Corsair "] }`
* Adds support for (B)SSID detection on macOS Tahoe (Wifi, macOS)
* Please don't expect it to work on later macOS versions
* Improves Ubuntu flavor detection (#1975, OS, Linux)
* Refines ARMv8.4-A detection to require LSE2 (CPU, Windows)
* Detects the latest Dimensity & Snapdragon SoC names (CPU, Android)
Bugfixes:
* Handles zero temperature data (#1960, CPU, Windows)
* Fixes `dlopen libzfs.so failed` error on Proxmox 9 (#1973, Zpool, Linux)
Logos:
* Removes Starry Linux
* Adds TempleOS
* Updates ObsidianOS
# 2.52.0
Changes:
* New optional build dependencies on Android
* main: chafa dbus glib imagemagick libelf libxcb libxrandr pulseaudio zlib
* x11: dconf (Optional)
* Dependency on `libxfconf` is removed. XFCE related detection now uses `libdbus` instead (Linux)
* The default format of `Display` module is updated to `{width}x{height} @ {scale-factor}x in {inch}", {refresh-rate} Hz`
* Replaced scaled resolution with scale factor for shorter texts and avoiding potential confusion.
Bugfixes:
* Fixes linking on 32-bit Android (#1939)
* Skips network interfaces without IPs unless MAC address is requested (#1949, LocalIP)
* Fixes unexpected padding when setting `logo.width` with chafa logos (#1947, Logo)
* Regression from v2.51.0
* Improves Wallpaper detection on XFCE4 (Wallpaper, Linux)
* Ignores process `Relay(xxx)` when detecting terminal on WSL2 (Terminal, Linux)
Features:
* Enables X11-related info (i.e., WM/DE) detection on Android (Global, Android)
* This requires many dependencies. See above.
* Adds scale factors detection for X11 (Display, Linux)
* X11 doesn't natively report scale factor as Wayland does. Instead, Fastfetch tries to detect `Xft.dpi` (DPI used by X FreeType for scaling fonts), which is usually set by the WM when DPI scaling is enabled.
* It's not always accurate. For example, XFCE4 has a separate config for text scaling, which is unaffected by the global DPI scaling setting.
* Adds `display.fraction.trailingZeros: [always|never]` option for fraction formatting
* The default value of `display.fraction.ndigits` is changed from `-1` (unlimited) to `2` for usability.
* Used for displaying scale factor in Display module mentioned above, alongside other places for printing raw fraction numbers.
* Informs users that module-specific CLI options are no longer supported and provide guidance for transitioning to JSON config
* Adds CPU name detection support for IA64 (CPU, Linux)
* Support Btrfs allocation profile detection (#1941, Btrfs, Linux)
# 2.51.1
Bugfixes:
* Fix building on macOS 14 or older; no functional changes (CPU, macOS)
# 2.51.0
Changes:
+345 -284
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,7 +1,7 @@
MIT License
Copyright (c) 2021-2023 Linus Dierheimer
Copyright (c) 2022-2025 Carter Li
Copyright (c) 2022-2026 Carter Li
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+75
View File
@@ -0,0 +1,75 @@
# Fastfetch
Fastfetch 是一款类似 neofetch 的系统信息展示工具,主要用 C 编写,强调性能和可定制性。支持 Linux、macOS、Windows 7+、Android、FreeBSD、OpenBSD、NetBSD、DragonFly、Haiku、SunOS。
示例配置见 presets/examples,更多截图与平台说明见 Wiki。
## 安装
Linux(部分):
- Debian 13+ / Ubuntu: apt install fastfetch
- Arch: pacman -S fastfetch
- Fedora: dnf install fastfetch
- openSUSE: zypper install fastfetch
- Linuxbrewbrew install fastfetch
- 各发行版打包状态:https://repology.org/project/fastfetch/versions
macOS
- Homebrewbrew install fastfetch
- MacPortssudo port install fastfetch
Windows
- scoop install fastfetch
- choco install fastfetch
- winget install fastfetch
- MSYS2pacman -S mingw-w64-<subsystem>-<arch>-fastfetch
BSD
- FreeBSDpkg install fastfetch
- NetBSDpkgin in fastfetch
- OpenBSDpkg_add fastfetch
AndroidTermux):
- pkg install fastfetch
Nightly 构建:
- https://nightly.link/fastfetch-cli/fastfetch/workflows/ci/dev?preview
## 源码构建
基本上是 `cmake . && make`。详见 Wikihttps://github.com/fastfetch-cli/fastfetch/wiki/Building
## 使用
- 默认运行:`fastfetch`
- 查看所有可用模块示例:`fastfetch -c all.jsonc`
- 以 JSON 输出指定模块:`fastfetch -s <module1>[:<module2>] --format json`
- 完整命令行帮助:`fastfetch --help`
- 生成最小配置:`fastfetch --gen-config [</path/to/config.jsonc>]`
- 生成完整配置:`fastfetch --gen-config-full`
- 请使用支持 JSON schema 的编辑器(如 VSCode)编辑配置文件!
- 如果你连接 Github 有网络困难(智能提示不生效),可将配置文件中的 `$schema` 的值替换为 `https://gitee.com/carterl/fastfetch/raw/dev/doc/json_schema.json`
## 定制
- 配置使用 JSONC,语法与选项见 Wikihttps://github.com/fastfetch-cli/fastfetch/wiki/Configuration
- 预设示例位于 presets,可用 `-c <filename>` 加载
- Logo 选项与图像显示见文档:https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options
- 模块格式化(示例,仅显示 GPU 名称):
```jsonc
{
"modules": [
{ "type": "gpu", "format": "{name}" }
]
}
```
详见:https://github.com/fastfetch-cli/fastfetch/wiki/Format-String-Guide
## 反馈与支持
- 使用问题:Discussions https://github.com/fastfetch-cli/fastfetch/discussions
- 疑似缺陷:Issues https://github.com/fastfetch-cli/fastfetch/issues(请填写模版)
## 赞助
<img src="https://github.com/user-attachments/assets/a36a6501-e8b0-4a10-9061-b9206d12ffba" width="220">
+15 -2
View File
@@ -11,8 +11,11 @@
[![latest packaged version(s)](https://repology.org/badge/latest-versions/fastfetch.svg)](https://repology.org/project/fastfetch/versions)
[![Packaging status](https://repology.org/badge/tiny-repos/fastfetch.svg)](https://repology.org/project/fastfetch/versions)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/fastfetch-cli/fastfetch)
[![中文README](https://img.shields.io/badge/%E4%B8%AD%E6%96%87-README-red)](README-cn.md)
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 7+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku, and SunOS.
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying it in a visually appealing way. It is written mainly in C, with a focus on performance and customizability. Currently, it supports Linux, macOS, Windows 8.1+, Android, FreeBSD, OpenBSD, NetBSD, DragonFly, Haiku and SunOS (illumos, Solaris).
> Note: Fastfetch is only actively tested on x86-64 and aarch64 platforms. It may work on other platforms but is not guaranteed to do so.
<img src="screenshots/example1.png" width="49%" align="left" />
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
@@ -36,7 +39,8 @@ Some distributions package outdated versions of fastfetch. Older versions receiv
<img src="https://repology.org/badge/vertical-allrepos/fastfetch.svg?columns=2" alt="Packaging status" align="right">
</a>
* Debian: `apt install fastfetch` (for Debian 13 or newer)
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (Ubuntu 22.04 or newer; latest version)
* Debian / Ubuntu: `apt install fastfetch` (Debian 13 or newer; Ubuntu 25.04 or newer)
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
* Arch Linux: `pacman -S fastfetch`
* Fedora: `dnf install fastfetch`
@@ -103,6 +107,10 @@ Fastfetch uses JSONC (JSON with comments) for configuration. [See the Wiki for d
Logos can also be heavily customized; see the [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for more information.
### WARNING
Fastfetch supports a `Command` module that can run arbitrary shell commands. If you copy-paste a config file from an untrusted source, it may contain malicious commands that can harm your system or compromise your privacy. Please always review the config file before using it.
## FAQ
### Q: Neofetch is good enough. Why do I need fastfetch?
@@ -317,6 +325,11 @@ If you find Fastfetch useful, please consider donating.
* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui)
* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer)
## Code signing
* Free code signing provided by [SignPath.io](https://about.signpath.io/), certificate by [SignPath Foundation](https://signpath.org/)
* This program will not transfer any information to other networked systems unless specifically requested by the user or the person installing or operating it
## Star History
Give us a star to show your support!
+97 -1
View File
@@ -1,3 +1,100 @@
fastfetch (2.63.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.63.0
-- Carter Li <zhangsongcui@live.cn> Wed, 13 May 2026 16:02:28 +0800
fastfetch (2.62.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.62.1
-- Carter Li <zhangsongcui@live.cn> Fri, 24 Apr 2026 15:45:15 +0800
fastfetch (2.62.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.62.0
-- Carter Li <zhangsongcui@live.cn> Wed, 22 Apr 2026 09:49:55 +0800
fastfetch (2.61.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.61.0
-- Carter Li <zhangsongcui@live.cn> Mon, 30 Mar 2026 09:51:18 +0800
fastfetch (2.58.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.58.0
-- Carter Li <zhangsongcui@live.cn> Thu, 22 Jan 2026 15:30:58 +0800
fastfetch (2.57.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.57.1
-- Carter Li <zhangsongcui@live.cn> Wed, 14 Jan 2026 14:00:17 +0800
fastfetch (2.57.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.57.0
-- Carter Li <zhangsongcui@live.cn> Mon, 12 Jan 2026 10:11:21 +0800
fastfetch (2.56.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.56.1
-- Carter Li <zhangsongcui@live.cn> Thu, 18 Dec 2025 14:57:36 +0800
fastfetch (2.56.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.56.0
-- Carter Li <zhangsongcui@live.cn> Mon, 08 Dec 2025 09:21:58 +0800
fastfetch (2.55.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.55.1
-- Carter Li <zhangsongcui@live.cn> Mon, 17 Nov 2025 10:15:44 +0800
fastfetch (2.55.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.55.0
-- Carter Li <zhangsongcui@live.cn> Wed, 12 Nov 2025 09:15:24 +0800
fastfetch (2.54.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Fix building on plucky
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 14:27:02 +0800
fastfetch (2.54.0~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium
* Update to 2.54.0
* Test independent changelog entries for different Ubuntu releases
-- Carter Li <zhangsongcui@live.cn> Mon, 20 Oct 2025 10:47:02 +0800
fastfetch (2.53.0) jammy; urgency=medium
* Update to 2.53.0
-- Carter Li <zhangsongcui@live.cn> Tue, 23 Sep 2025 09:58:48 +0800
fastfetch (2.52.0) jammy; urgency=medium
* Update to 2.52.0
-- Carter Li <zhangsongcui@live.cn> Fri, 05 Sep 2025 14:59:44 +0800
fastfetch (2.51.0) jammy; urgency=medium
* Update to 2.51.0
-- Carter Li <zhangsongcui@live.cn> Fri, 29 Aug 2025 08:55:03 +0800
fastfetch (2.50.2) jammy; urgency=medium
* Update to 2.50.2
@@ -417,4 +514,3 @@ fastfetch (2.7.1) jammy; urgency=medium
* Initial release.
-- Carter Li <zhangsongcui@live.cn> Tue, 06 Feb 2024 15:01:11 +0800
+1 -1
View File
@@ -2,7 +2,7 @@ Source: fastfetch
Section: universe/utils
Priority: optional
Maintainer: Carter Li <zhangsongcui@live.cn>
Build-Depends: 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, libddcutil-dev, libchafa-dev, directx-headers-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build
Build-Depends: libelf-dev, libvulkan-dev, libwayland-dev, libxrandr-dev, libxcb-randr0-dev, libdconf-dev, libdbus-1-dev, libmagickcore-dev, libsqlite3-dev, librpm-dev, libegl-dev, libglx-dev, ocl-icd-opencl-dev, libpulse-dev, libdrm-dev, libddcutil-dev, libchafa-dev, libefl-all-dev, pkgconf, cmake (>= 3.12), debhelper (>= 11.2), dh-cmake, dh-cmake-compat (= 1), dh-sequence-cmake, dh-sequence-ctest, ninja-build, python3-setuptools
Standards-Version: 4.0.0
Homepage: https://github.com/fastfetch-cli/fastfetch
-1
View File
@@ -1 +0,0 @@
fastfetch_2.50.2_source.buildinfo universe/utils optional
+74 -2
View File
@@ -1,4 +1,76 @@
#!/usr/bin/env bash
# WARNING: DO NOT RUN THIS SCRIPT UNLESS YOU KNOW WHAT YOU ARE DOING.
debuild -S -i -I
dput ppa:zhangsongcui3371/fastfetch ~/fastfetch_*.changes
set -euo pipefail
command -v debuild >/dev/null 2>&1 || { echo "debuild not found. Install devscripts." >&2; exit 1; }
command -v dput >/dev/null 2>&1 || { echo "dput not found." >&2; exit 1; }
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd)"
OUT_DIR="$(dirname "$ROOT_DIR")"
PPA="ppa:zhangsongcui3371/fastfetch"
CODENAMES=( jammy noble plucky questing resolute )
DRY_RUN=0
if [[ -d "$OUT_DIR/build" ]]; then
echo "Output directory exists: $OUT_DIR/build" >&2
echo "Please move or delete it before proceeding." >&2
exit 1
fi
TEMPLATE="$ROOT_DIR/debian/changelog.tpl"
CHANGELOG_DEBIAN="$ROOT_DIR/debian/changelog"
if [[ ! -f "$TEMPLATE" ]]; then
echo "Template not found: $TEMPLATE" >&2
exit 1
fi
if ! grep -q '#UBUNTU_CODENAME#' "$TEMPLATE"; then
echo "Template missing placeholder: #UBUNTU_CODENAME#" >&2
exit 1
fi
echo "IMPORTANT: Before proceeding, please ensure that 'debian/changelog.tpl' is up-to-date"
echo " with the correct version number, release notes, and maintainer information."
echo
echo " The template must contain a placeholder like '#UBUNTU_CODENAME#' for the codename."
echo
read -p "Have you reviewed and updated 'debian/changelog.tpl'? (y/N): " -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
cleanup() {
rm -f "$CHANGELOG_DEBIAN"
rm -f "$ROOT_DIR/debian/files"
}
trap cleanup EXIT
shopt -s nullglob
for codename in "${CODENAMES[@]}"; do
echo "==> Publishing distro: $codename"
sed "s/#UBUNTU_CODENAME#/${codename}/g" "$TEMPLATE" > "$CHANGELOG_DEBIAN"
( cd "$ROOT_DIR" && debuild -S -i -I )
changes=( "$OUT_DIR"/fastfetch_*~${codename}_source.changes )
if [[ ${#changes[@]} -ne 1 ]]; then
echo "Unable to uniquely identify .changes for '$codename' in: $OUT_DIR" >&2
printf 'Found:\n'; printf ' %s\n' "${changes[@]}" >&2 || true
exit 1
fi
if [[ $DRY_RUN -eq 1 ]]; then
echo "[DRY-RUN] dput \"$PPA\" \"${changes[0]}\""
else
dput "$PPA" "${changes[0]}"
fi
rm -f "$OUT_DIR"/fastfetch_*~${codename}_source.{changes,dsc,tar.*}
echo "<== Done: $codename"
done
+532 -305
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -109,6 +109,7 @@
},
"tpm",
"version",
"logo",
"break",
"colors"
]
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+52 -51
View File
@@ -9,25 +9,26 @@
// Constants are reusable strings referenced by {$1}, {$2}, etc.
// These contain ANSI escape codes for cursor positioning
"constants": [
"──────────────────────────────────────────────", // {$1} - horizontal line for borders
"──────────────────────────────────────────────", // {$1} - horizontal line for inner borders
"\u001b[47D", // {$2} - move cursor left 47 columns
"\u001b[47C", // {$3} - move cursor right 47 columns
"\u001b[46C" // {$4} - move cursor right 46 columns
"\u001b[46C", // {$4} - move cursor right 46 columns
"══════════════════════════════════════════════" // {$5} - horizontal line for outer borders
],
"brightColor": false
},
"modules": [
{
"type": "version",
"key": "┌───────────────┬─{$1}┐\u001b[41D",
"key": "╔═══════════════╦═{$5}╗\u001b[41D",
"format": "\u001b[1m{#keys} {1} - {2} "
},
{
"type": "os",
// Key format breakdown for OS module:
// " {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}{$2}"
// " {icon} \u001b[s{sysname}\u001b[u\u001b[10C│{$3}{$2}"
//
// - Left border of key block
// - Left border of key block
// {icon} - OS icon (defined internally by fastfetch)
// \u001b[s - ANSI escape: save cursor position (ESC[s)
// {sysname} - Format variable: system name (e.g., "Linux", "Darwin")
@@ -36,28 +37,28 @@
// \u001b[10C - ANSI escape: move cursor right 10 columns (ESC[10C)
// │ - Right border of key block (always 10 columns from left border)
// {$3} - Reference to constants[2]: move cursor right 47 columns
// - Right border of value block
// - Right border of value block
// {$2} - Reference to constants[1]: move cursor left 47 columns
//
// This creates a fixed-width layout where the key block is exactly 10 columns wide,
// regardless of the actual content length. The cursor manipulation ensures proper
// alignment for the table-like structure.
"key": " {icon} \u001b[s{sysname}\u001b[u\u001b[10C{$3}{$2}"
"key": " {icon} \u001b[s{sysname}\u001b[u\u001b[10C{$3}{$2}"
},
{
"type": "datetime",
"key": " {icon} Fetched {$3}{$2}",
"key": " {icon} Fetched {$3}{$2}",
"format": "{year}-{month-pretty}-{day-pretty} {hour-pretty}:{minute-pretty}:{second-pretty} {timezone-name}"
},
{
"type": "locale",
"key": " {icon} Locale {$3}{$2}"
"key": " {icon} Locale {$3}{$2}"
},
// Hardware section with cyan color theme
{
"type": "custom",
"key": "{#cyan}┌──────────────┬{$1}┐{#keys}\u001b[37D",
"key": "{#cyan}┌──────────────┬{$1}┐{#keys}\u001b[37D",
"format": "{#bright_cyan} Hardware "
},
{
@@ -66,113 +67,113 @@
// │{#cyan}│ - Left border with cyan color
// {icon} - Chassis icon
// Chassis - Fixed label text
// │{$4}│{#keys}{$2} - Positioning and borders for value area
"key": "{#cyan}│ {icon} Chassis │{$4}│{#keys}{$2}"
// │{$4}│{#keys}{$2} - Positioning and borders for value area
"key": "{#cyan}│ {icon} Chassis │{$4}│{#keys}{$2}"
},
{
"type": "memory",
"key": "{#cyan}│ {icon} RAM │{$4}│{#keys}{$2}"
"key": "{#cyan}│ {icon} RAM │{$4}│{#keys}{$2}"
},
{
"type": "swap",
"key": "{#cyan}│ {icon} SWAP │{$4}│{#keys}{$2}"
"key": "{#cyan}│ {icon} SWAP │{$4}│{#keys}{$2}"
},
{
"type": "cpu",
"key": "{#cyan}│ {icon} CPU │{$4}│{#keys}{$2}",
"key": "{#cyan}│ {icon} CPU │{$4}│{#keys}{$2}",
"showPeCoreCount": true
},
{
"type": "gpu",
"key": "{#cyan}│ {icon} GPU │{$4}│{#keys}{$2}"
"key": "{#cyan}│ {icon} GPU │{$4}│{#keys}{$2}"
},
{
"type": "disk",
"key": "{#cyan}│ {icon} Disk │{$4}│{#keys}{$2}",
"key": "{#cyan}│ {icon} Disk │{$4}│{#keys}{$2}",
"format": "{size-used} \/ {size-total} ({size-percentage}) - {filesystem}",
},
{
"type": "battery",
"key": "{#cyan}│ {icon} Battery │{$4}│{#keys}{$2}"
"key": "{#cyan}│ {icon} Battery │{$4}│{#keys}{$2}"
},
{
"type": "custom",
"key": "{#cyan}└──────────────┴{$1}┘{#keys}",
"key": "{#cyan}└──────────────┴{$1}┘{#keys}",
"format": ""
},
// Desktop section with green color theme
{
"type": "custom",
"key": "{#green}┌──────────────┬{$1}┐{#keys}\u001b[37D",
"key": "{#green}┌──────────────┬{$1}┐{#keys}\u001b[37D",
"format": "{#bright_green} Desktop "
},
{
"type": "de",
"key": "{#green}│ {icon} Desktop │{$4}│{#keys}{$2}"
"key": "{#green}│ {icon} Desktop │{$4}│{#keys}{$2}"
},
{
"type": "wm",
"key": "{#green}│ {icon} Session │{$4}│{#keys}{$2}"
"key": "{#green}│ {icon} Session │{$4}│{#keys}{$2}"
},
{
"type": "display",
"key": "{#green}│ {icon} Display │{$4}│{#keys}{$2}",
"key": "{#green}│ {icon} Display │{$4}│{#keys}{$2}",
"compactType": "original-with-refresh-rate"
},
{
"type": "gpu",
"key": "{#green}│ {icon} G-Driver │{$4}│{#keys}{$2}",
"key": "{#green}│ {icon} G-Driver │{$4}│{#keys}{$2}",
"format": "{driver}"
},
{
"type": "custom",
"key": "{#green}└──────────────┴{$1}┘{#keys}",
"key": "{#green}└──────────────┴{$1}┘{#keys}",
"format": ""
},
// Terminal section with yellow color theme
{
"type": "custom",
"key": "{#yellow}┌──────────────┬{$1}┐{#keys}\u001b[37D",
"key": "{#yellow}┌──────────────┬{$1}┐{#keys}\u001b[37D",
"format": "{#bright_yellow} Terminal "
},
{
"type": "shell",
"key": "{#yellow}│ {icon} Shell │{$4}│{#keys}{$2}"
"key": "{#yellow}│ {icon} Shell │{$4}│{#keys}{$2}"
},
{
"type": "terminal",
"key": "{#yellow}│ {icon} Terminal │{$4}│{#keys}{$2}"
"key": "{#yellow}│ {icon} Terminal │{$4}│{#keys}{$2}"
},
{
"type": "terminalfont",
"key": "{#yellow}│ {icon} Term Font │{$4}│{#keys}{$2}"
"key": "{#yellow}│ {icon} Term Font │{$4}│{#keys}{$2}"
},
{
"type": "terminaltheme",
"key": "{#yellow}│ {icon} Colors │{$4}│{#keys}{$2}"
"key": "{#yellow}│ {icon} Colors │{$4}│{#keys}{$2}"
},
{
"type": "packages",
"key": "{#yellow}│ {icon} Packages │{$4}│{#keys}{$2}"
"key": "{#yellow}│ {icon} Packages │{$4}│{#keys}{$2}"
},
{
"type": "custom",
"key": "{#yellow}└──────────────┴{$1}┘{#keys}",
"key": "{#yellow}└──────────────┴{$1}┘{#keys}",
"format": ""
},
// Development section with red color theme
{
"type": "custom",
"key": "{#red}┌──────────────┬{$1}┐{#keys}\u001b[39D",
"key": "{#red}┌──────────────┬{$1}┐{#keys}\u001b[39D",
"format": "{#bright_red} Development "
},
{
"type": "command",
"keyIcon": "", // Custom icon override
"key": "{#red}│ {icon} Rust │{$4}│{#keys}{$2}",
"key": "{#red}│ {icon} Rust │{$4}│{#keys}{$2}",
"text": "rustc --version",
"format": "rustc {~6,13}" // Print 6th to 13th characters (version number)
},
@@ -182,8 +183,8 @@
"!system": "Windows" // Posix version
},
"keyIcon": "",
"key": "{#red}│ {icon} Clang │{$4}│{#keys}{$2}",
"text": "clang --version | head -1 | awk '{print $NF}'",
"key": "{#red}│ {icon} Clang │{$4}│{#keys}{$2}",
"text": "clang --version | sed -n 's/.*version \\([0-9][0-9.]*\\).*/\\1/p'",
"format": "clang {}"
},
{
@@ -192,67 +193,67 @@
"system": "Windows" // Windows version
},
"keyIcon": "",
"key": "{#red}│ {icon} Clang │{$4}│{#keys}{$2}",
"key": "{#red}│ {icon} Clang │{$4}│{#keys}{$2}",
"text": "clang --version | findstr version", // Finds the line with "version"
"format": "clang {~-6}" // Prints the last 6 characters (version number)
},
{
"type": "command",
"keyIcon": "",
"key": "{#red}│ {icon} NodeJS │{$4}│{#keys}{$2}",
"key": "{#red}│ {icon} NodeJS │{$4}│{#keys}{$2}",
"text": "node --version",
"format": "node {~1}" // {~1} removes first character (v)
},
{
"type": "command",
"keyIcon": "",
"key": "{#red}│ {icon} Go │{$4}│{#keys}{$2}",
"key": "{#red}│ {icon} Go │{$4}│{#keys}{$2}",
"text": "go version | cut -d' ' -f3",
"format": "go {~2}" // {~2} removes first 2 characters (go)
},
{
"type": "command",
"keyIcon": "",
"key": "{#red}│ {icon} Zig │{$4}│{#keys}{$2}",
"key": "{#red}│ {icon} Zig │{$4}│{#keys}{$2}",
"text": "zig version",
"format": "zig {}"
},
{
"type": "editor",
"key": "{#red}│ {icon} Editor │{$4}│{#keys}{$2}"
"key": "{#red}│ {icon} Editor │{$4}│{#keys}{$2}"
},
{
"type": "command",
"keyIcon": "󰊢",
"key": "{#red}│ {icon} Git │{$4}│{#keys}{$2}",
"key": "{#red}│ {icon} Git │{$4}│{#keys}{$2}",
"text": "git version",
"format": "git {~12}"
},
{
"type": "font",
"key": "{#red}│ {icon} Interface │{$4}│{#keys}{$2}"
"key": "{#red}│ {icon} Interface │{$4}│{#keys}{$2}"
},
{
"type": "custom",
"key": "{#red}└──────────────┴{$1}┘{#keys}",
"key": "{#red}└──────────────┴{$1}┘{#keys}",
"format": ""
},
// Uptime section with magenta color theme
{
"type": "custom",
"key": "{#magenta}┌──────────────┬{$1}┐{#keys}\u001b[36D",
"key": "{#magenta}┌──────────────┬{$1}┐{#keys}\u001b[36D",
"format": "{#bright_magenta} Uptime "
},
{
"type": "uptime",
"key": "{#magenta}│ {icon} Uptime │{$4}│{#keys}{$2}"
"key": "{#magenta}│ {icon} Uptime │{$4}│{#keys}{$2}"
},
{
"type": "users",
"myselfOnly": true, // Only show current user
"keyIcon": "",
"key": "{#magenta}│ {icon} Login │{$4}│{#keys}{$2}"
"key": "{#magenta}│ {icon} Login │{$4}│{#keys}{$2}"
},
{
"condition": { // Conditional module: only show on non-macOS
@@ -260,7 +261,7 @@
},
"type": "disk",
"keyIcon": "",
"key": "{#magenta}│ {icon} OS Age │{$4}│{#keys}{$2}",
"key": "{#magenta}│ {icon} OS Age │{$4}│{#keys}{$2}",
"folders": "/", // Check root filesystem
"format": "{create-time:10} [{days} days]" // Show creation time and age in days
},
@@ -270,18 +271,18 @@
},
"type": "disk",
"keyIcon": "",
"key": "{#magenta}│ {icon} OS Age │{$4}│{#keys}{$2}",
"key": "{#magenta}│ {icon} OS Age │{$4}│{#keys}{$2}",
"folders": "/System/Volumes/VM", // Work around for APFS on macOS
"format": "{create-time:10} [{days} days]"
},
{
"type": "custom",
"key": "{#magenta}└──────────────┴{$1}┘{#keys}",
"key": "{#magenta}└──────────────┴{$1}┘{#keys}",
"format": ""
},
{
"type": "custom",
"key": "└─────────────────{$1}┘", // Bottom border of the entire layout
"key": "╚═════════════════{$5}╝", // Bottom border of the entire layout
"format": ""
},
+1 -1
View File
@@ -1,6 +1,6 @@
// #1887
{
"$schema": "file:///Users/carter/fastfetch/doc/json_schema.json",
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": null,
"display": {
"constants": [
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/3.jsonc
// Load with --config examples/3.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+87
View File
@@ -0,0 +1,87 @@
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": null,
"display": {
"key": {
"type": "both",
"paddingLeft": 6,
"width": 17
}
},
"modules": [
{
"type": "custom",
"format": "|---------------------: {#1}Hardware{#} : ---------------------|"
},
"break",
{
"keyColor": "green",
"type": "host"
},
{
"keyColor": "green",
"type": "cpu"
},
{
"keyColor": "yellow",
"type": "memory"
},
{
"keyColor": "yellow",
"type": "swap"
},
{
"type": "custom",
"keyIcon": "",
"key": "Disks"
},
{
"type": "disk",
"key": " ",
"format": " [{mountpoint}] - {size-used} / {size-total} ({size-percentage})"
},
"break",
{
"type": "title",
"format": "|-------------------------------------------------------|\u001b[40D: {#1}{user-name} @ {host-name}{#} :"
},
"break",
{
"type": "os",
"keyColor": "cyan"
},
{
"type": "kernel",
"keyColor": "cyan"
},
{
"type": "packages",
"keyColor": "red",
"key": "Pkgs"
},
{
"type": "shell",
"keyColor": "red"
},
{
"type": "terminal",
"key": "Term",
"keyColor": "red"
},
{
"type": "locale",
"keyColor": "magenta"
},
"break",
{
"type": "custom",
"format": "|---------------------: {#1}Software{#} : ---------------------|"
},
"break",
{
"type": "colors",
"symbol": "circle",
"paddingLeft": 8
}
]
}
File diff suppressed because one or more lines are too long
+57
View File
@@ -0,0 +1,57 @@
// Inspired by microfetch
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
"logo": {
"type": "small"
},
"general": {
"detectVersion": false
},
"display": {
"separator": "  ",
"brightColor": false,
"key": {
"type": "both-2"
}
},
"modules": [
{
"type": "title",
"format": "{user-name-colored}{#light_red}@{host-name-colored} {#}{cwd}"
},
{
"type": "os",
"key": "System "
},
{
"type": "kernel",
"key": "Kernel "
},
{
"type": "shell",
"key": "Shell "
},
{
"type": "uptime",
"key": "Uptime "
},
{
"type": "wm",
"key": "Desktop "
},
{
"type": "memory",
"key": "Memory "
},
{
"type": "disk",
"key": "Storage (/) ",
"folders": "/"
},
{
"type": "colors",
"key": "Colors ",
"symbol": "circle"
}
]
}
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/4.jsonc
// Load with --config examples/4.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/5.jsonc
// Load with --config examples/5.jsonc
{
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+1 -1
View File
@@ -1,4 +1,4 @@
// Load with --load-config examples/2.jsonc
// Load with --config examples/2.jsonc
// Note that you must replace the image path to an existing image to display it.
{
+3
View File
@@ -6,6 +6,9 @@ def main(amdgpu_ids_path: str):
with open(amdgpu_ids_path, 'r') as f:
full_text = f.read()
if full_text == '':
sys.exit(f'Error: {amdgpu_ids_path} file is empty')
products = []
for line in full_text.split('\n'):
if not line or line[0] == '#' or not ',\t' in line:
+3
View File
@@ -18,6 +18,9 @@ def main(keep_vendor_list: set, pci_ids_path: str):
with open(pci_ids_path, 'r') as f:
full_text = f.read()
if full_text == '':
sys.exit(f'Error: {pci_ids_path} file is empty')
dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes
for line in dev_list_text.split('\n'):
if not line or line[0] == '#':
+141 -88
View File
@@ -21,7 +21,7 @@
// SOFTWARE.
/// \file adl_defines.h
/// \brief Contains all definitions exposed by ADL for \ALL platforms.\n <b>Included in ADL SDK</b>
/// \brief Contains all definitions exposed by ADL for \WIN platforms.\n <b>Included in ADL SDK</b>
///
/// This file contains all definitions used by ADL.
/// The ADL definitions include the following:
@@ -61,6 +61,8 @@
#define ADL_ADAPTER_INDEX_ALL -1
/// Defines APIs with iOption none
#define ADL_MAIN_API_OPTION_NONE 0
/// Defines the maximum of RPC endpoint
#define ADL_MAX_RPC_ENDPOINT 32
/// @}
/// \name Definitions for iOption parameter used by
@@ -141,6 +143,12 @@
#define ADL_ERR_FEATURESYNC_NOT_STARTED -24
/// Adapter is in an invalid power state
#define ADL_ERR_INVALID_POWER_STATE -25
/// The RPC server is in busy state
#define ADL_ERR_SERVER_BUSY -26
/// The GPU is occupied by application which cannot be powered off
#define ADL_ERR_GPU_IN_USE -27
/// The general RPC connection error
#define ADL_ERR_RPC -28
/// @}
/// </A>
@@ -380,6 +388,7 @@
#define ADL_BUSTYPE_PCIE_GEN2 3 /* PCI Express 2nd generation bus */
#define ADL_BUSTYPE_PCIE_GEN3 4 /* PCI Express 3rd generation bus */
#define ADL_BUSTYPE_PCIE_GEN4 5 /* PCI Express 4th generation bus */
#define ADL_BUSTYPE_PCIE_GEN5 6 /* PCI Express 5th generation bus */
/// @}
/// \defgroup define_ws_caps Workstation Capabilities
@@ -872,7 +881,7 @@
typedef enum ADLThreadingModel
{
ADL_THREADING_UNLOCKED = 0, /*!< Default behavior. ADL will not enforce serialization of ADL API executions by multiple threads. Multiple threads will be allowed to enter to ADL at the same time. Note that ADL library is not guaranteed to be thread-safe. Client that calls ADL_Main_Control_Create have to provide its own mechanism for ADL calls serialization. */
ADL_THREADING_LOCKED /*!< ADL will enforce serialization of ADL API when called by multiple threads. Only single thread will be allowed to enter ADL API at the time. This option makes ADL calls thread-safe. You shouldn't use this option if ADL calls will be executed on Linux on x-server rendering thread. It can cause the application to hung. */
ADL_THREADING_LOCKED /*!< ADL will enforce serialization of ADL API when called by multiple threads. Only single thread will be allowed to enter ADL API at the time. This option makes ADL calls thread-safe. */
}ADLThreadingModel;
/// @}
@@ -1844,12 +1853,12 @@ enum ADLOD8FeatureControl
ADL_OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature
ADL_OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp
ADL_OD8_MEMORY_TIMING_TUNE = 1 << 8,
ADL_OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 ,
ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage
ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine
ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory
ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve
ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller
ADL_OD8_FAN_ZERO_RPM_CONTROL = 1 << 9,
ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage
ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine
ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory
ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve
ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller
ADL_OD8_GFXCLK_QUADRATIC_CURVE = 1 << 15,
ADL_OD8_OPTIMIZED_GPU_POWER_MODE = 1 << 16,
ADL_OD8_ODVOLTAGE_LIMIT = 1 << 17,
@@ -1860,43 +1869,45 @@ enum ADLOD8FeatureControl
ADL_OD8_TDC_LIMIT = 1 << 22, //TDC slider
ADL_OD8_FULL_CONTROL_MODE = 1 << 23, //Full control
ADL_OD8_POWER_SAVING_FEATURE_CONTROL = 1 << 24, //Power saving feature control
ADL_OD8_POWER_GAUGE = 1 << 25 //Power Gauge
ADL_OD8_ACTIMING_PARAMETERS_TUNE = 1 << 25, // AC Timing Parameters Tuning
ADL_OD8_OVERDRIVE_INTERFACE = 1 << 26, // Version info feature ID for RSX, do not expose in ADL.
ADL_OD8_AUTO_UV_ENGINE_V2 = 1 << 27, // Auto UV 2.0 with actual stress testing.
ADL_OD8_POWER_GAUGE = 1 << 28 //Power Gauge
};
typedef enum ADLOD8SettingId
{
OD8_GFXCLK_FMAX = 0,
OD8_GFXCLK_FMIN,
OD8_GFXCLK_FREQ1,
OD8_GFXCLK_VOLTAGE1,
OD8_GFXCLK_FREQ2,
OD8_GFXCLK_VOLTAGE2,
OD8_GFXCLK_FREQ3,
OD8_GFXCLK_VOLTAGE3,
OD8_UCLK_FMAX,
OD8_POWER_PERCENTAGE,
OD8_FAN_MIN_SPEED,
OD8_FAN_ACOUSTIC_LIMIT,
OD8_FAN_TARGET_TEMP,
OD8_OPERATING_TEMP_MAX,
OD8_AC_TIMING,
OD8_FAN_ZERORPM_CONTROL,
OD8_AUTO_UV_ENGINE_CONTROL,
OD8_AUTO_OC_ENGINE_CONTROL,
OD8_AUTO_OC_MEMORY_CONTROL,
OD8_FAN_CURVE_TEMPERATURE_1,
OD8_FAN_CURVE_SPEED_1,
OD8_FAN_CURVE_TEMPERATURE_2,
OD8_FAN_CURVE_SPEED_2,
OD8_FAN_CURVE_TEMPERATURE_3,
OD8_FAN_CURVE_SPEED_3,
OD8_FAN_CURVE_TEMPERATURE_4,
OD8_FAN_CURVE_SPEED_4,
OD8_FAN_CURVE_TEMPERATURE_5,
OD8_FAN_CURVE_SPEED_5,
OD8_WS_FAN_AUTO_FAN_ACOUSTIC_LIMIT,
OD8_GFXCLK_CURVE_COEFFICIENT_A, // As part of the agreement with UI team, the min/max voltage limits for the
OD8_GFXCLK_FMAX = 0,
OD8_GFXCLK_FMIN,
OD8_GFXCLK_FREQ1,
OD8_GFXCLK_VOLTAGE1,
OD8_GFXCLK_FREQ2,
OD8_GFXCLK_VOLTAGE2,
OD8_GFXCLK_FREQ3,
OD8_GFXCLK_VOLTAGE3,
OD8_UCLK_FMAX,
OD8_POWER_PERCENTAGE,
OD8_FAN_MIN_SPEED, //10
OD8_FAN_ACOUSTIC_LIMIT,
OD8_FAN_TARGET_TEMP,
OD8_OPERATING_TEMP_MAX,
OD8_AC_TIMING,
OD8_FAN_ZERORPM_CONTROL,
OD8_AUTO_UV_ENGINE_CONTROL,
OD8_AUTO_OC_ENGINE_CONTROL,
OD8_AUTO_OC_MEMORY_CONTROL,
OD8_FAN_CURVE_TEMPERATURE_1,
OD8_FAN_CURVE_SPEED_1, //20
OD8_FAN_CURVE_TEMPERATURE_2,
OD8_FAN_CURVE_SPEED_2,
OD8_FAN_CURVE_TEMPERATURE_3,
OD8_FAN_CURVE_SPEED_3,
OD8_FAN_CURVE_TEMPERATURE_4,
OD8_FAN_CURVE_SPEED_4,
OD8_FAN_CURVE_TEMPERATURE_5,
OD8_FAN_CURVE_SPEED_5,
OD8_WS_FAN_AUTO_FAN_ACOUSTIC_LIMIT,
OD8_GFXCLK_CURVE_COEFFICIENT_A, // 30 As part of the agreement with UI team, the min/max voltage limits for the
OD8_GFXCLK_CURVE_COEFFICIENT_B, // quadratic curve graph will be stored in the min and max limits of
OD8_GFXCLK_CURVE_COEFFICIENT_C, // coefficient a, b and c. A, b and c themselves do not have limits.
OD8_GFXCLK_CURVE_VFT_FMIN,
@@ -1906,7 +1917,7 @@ typedef enum ADLOD8SettingId
OD8_OD_VOLTAGE,// RSX - voltage offset feature
OD8_ADV_OC_LIMITS_SETTING,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_1,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_2,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_2, //40
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_3,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_4,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_5,
@@ -1915,8 +1926,33 @@ typedef enum ADLOD8SettingId
OD8_GFX_VOLTAGE_LIMIT_SETTING,
OD8_TDC_PERCENTAGE,
OD8_FULL_CONTROL_MODE_SETTING,
OD8_FULL_CONTROL_MODE_GFXCLK,
OD8_FULL_CONTROL_MODE_UCLK, // 50,
OD8_IDLE_POWER_SAVING_FEATURE_CONTROL,
OD8_RUNTIME_POWER_SAVING_FEATURE_CONTROL,
OD8_FULL_CONTROL_MODE_FEATURE_CONTROL,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_1,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_2,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_3,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_4,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_5,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_FREQ_ANCHOR_6,
OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_VOLTAGE_LIMIT, //60
OD8_ACTIMING_PARAMETER_TRRDS,
OD8_ACTIMING_PARAMETER_TCL,
OD8_ACTIMING_PARAMETER_TCWL,
OD8_ACTIMING_PARAMETER_TRCDRD,
OD8_ACTIMING_PARAMETER_TRCDWR,
OD8_ACTIMING_PARAMETER_TRAS,
OD8_ACTIMING_PARAMETER_TRPAB,
OD8_ACTIMING_PARAMETER_TRFC,
OD8_ACTIMING_PARAMETER_TRFCPB,
OD8_ACTIMING_PARAMETER_TRREFD, //70
OD8_ACTIMING_PARAMETER_TREF,
OD8_ACTIMING_PARAMETER_TWR,
OD8_ACTIMING_PARAMETER_TWTRS,
OD8_OVERDRIVE_INTERFACE_ID, //74
OD8_AUTO_UV_ENGINE_V2_ID, //75
OD8_POWER_GAUGE,
OD8_COUNT
} ADLOD8SettingId;
@@ -1980,28 +2016,28 @@ typedef enum ADLSensorType
PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit
PMLOG_TEMPERATURE_HOTSPOT_GCD = 50,
PMLOG_TEMPERATURE_HOTSPOT_MCD = 51,
PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52,
PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53,
PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54,
PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55,
PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56,
PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57,
PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58,
PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59,
PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60,
PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61,
PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62,
PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63,
PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64,
PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65,
PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66,
PMLOG_THROTTLER_PPT0_PERCENTAGE = 67,
PMLOG_THROTTLER_PPT1_PERCENTAGE = 68,
PMLOG_THROTTLER_PPT2_PERCENTAGE = 69,
PMLOG_THROTTLER_PPT3_PERCENTAGE = 70,
PMLOG_THROTTLER_FIT_PERCENTAGE = 71,
PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72,
PMLOG_BOARD_POWER = 73,
PMLOG_THROTTLE_PERCENTAGE_TEMP_GFX = 52,
PMLOG_THROTTLE_PERCENTAGE_TEMP_MEM = 53,
PMLOG_THROTTLE_PERCENTAGE_TEMP_VR = 54,
PMLOG_THROTTLE_PERCENTAGE_POWER = 55,
PMLOG_THROTTLE_PERCENTAGE_TDC = 56,
PMLOG_THROTTLE_PERCENTAGE_VMAX = 57,
PMLOG_BUS_CURR_MAX_SPEED = 58,
PMLOG_RESERVED_1 = 59, //Currently Unused
PMLOG_RESERVED_2 = 60, //Currently Unused
PMLOG_RESERVED_3 = 61, //Currently Unused
PMLOG_RESERVED_4 = 62, //Currently Unused
PMLOG_RESERVED_5 = 63, //Currently Unused
PMLOG_RESERVED_6 = 64, //Currently Unused
PMLOG_RESERVED_7 = 65, //Currently Unused
PMLOG_RESERVED_8 = 66, //Currently Unused
PMLOG_RESERVED_9 = 67, //Currently Unused
PMLOG_RESERVED_10 = 68, //Currently Unused
PMLOG_RESERVED_11 = 69, //Currently Unused
PMLOG_RESERVED_12 = 70, //Currently Unused
PMLOG_RESERVED_13 = 71, //Currently Unused
PMLOG_RESERVED_14 = 72,
PMLOG_BOARD_POWER = 73,
PMLOG_MAX_SENSORS_REAL
} ADLSensorType;
@@ -2068,28 +2104,29 @@ typedef enum ADL_PMLOG_SENSORS
ADL_PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit
ADL_PMLOG_TEMPERATURE_HOTSPOT_GCD = 50,
ADL_PMLOG_TEMPERATURE_HOTSPOT_MCD = 51,
ADL_PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52,
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53,
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54,
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55,
ADL_PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56,
ADL_PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57,
ADL_PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58,
ADL_PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59,
ADL_PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60,
ADL_PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61,
ADL_PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62,
ADL_PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63,
ADL_PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64,
ADL_PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65,
ADL_PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66,
ADL_PMLOG_THROTTLER_PPT0_PERCENTAGE = 67,
ADL_PMLOG_THROTTLER_PPT1_PERCENTAGE = 68,
ADL_PMLOG_THROTTLER_PPT2_PERCENTAGE = 69,
ADL_PMLOG_THROTTLER_PPT3_PERCENTAGE = 70,
ADL_PMLOG_THROTTLER_FIT_PERCENTAGE = 71,
ADL_PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72,
ADL_PMLOG_BOARD_POWER = 73,
ADL_PMLOG_THROTTLE_PERCENTAGE_TEMP_GFX = 52,
ADL_PMLOG_THROTTLE_PERCENTAGE_TEMP_MEM = 53,
ADL_PMLOG_THROTTLE_PERCENTAGE_TEMP_VR = 54,
ADL_PMLOG_THROTTLE_PERCENTAGE_POWER = 55,
ADL_PMLOG_THROTTLE_PERCENTAGE_TDC = 56,
ADL_PMLOG_THROTTLE_PERCENTAGE_VMAX = 57,
ADL_PMLOG_BUS_CURR_MAX_SPEED = 58,
ADL_PMLOG_RESERVED_1 = 59, //Currently Unused
ADL_PMLOG_RESERVED_2 = 60, //Currently Unused
ADL_PMLOG_RESERVED_3 = 61, //Currently Unused
ADL_PMLOG_RESERVED_4 = 62, //Currently Unused
ADL_PMLOG_RESERVED_5 = 63, //Currently Unused
ADL_PMLOG_RESERVED_6 = 64, //Currently Unused
ADL_PMLOG_RESERVED_7 = 65, //Currently Unused
ADL_PMLOG_RESERVED_8 = 66, //Currently Unused
ADL_PMLOG_RESERVED_9 = 67, //Currently Unused
ADL_PMLOG_RESERVED_10 = 68, //Currently Unused
ADL_PMLOG_RESERVED_11 = 69, //Currently Unused
ADL_PMLOG_RESERVED_12 = 70, //Currently Unused
ADL_PMLOG_CLK_NPUCLK = 71, //NPU frequency
ADL_PMLOG_NPU_BUSY_AVG = 72, //NPU busy
ADL_PMLOG_BOARD_POWER = 73,
ADL_PMLOG_TEMPERATURE_INTAKE = 74,
ADL_PMLOG_MAX_SENSORS_REAL
} ADL_PMLOG_SENSORS;
@@ -2393,6 +2430,9 @@ typedef enum ADL_PMLOG_SENSORS
/// Indicates there is crossGPU clone
#define ADL_CROSSGPUDISPLAYCLONE 0x2
/// @}
/// @}
/// \defgroup define_D3DKMT_HANDLE
@@ -2493,7 +2533,11 @@ typedef enum ADL_UIFEATURES_GROUP
ADL_UIFEATURES_GROUP_PROVSR = 12,
ADL_UIFEATURES_GROUP_SMA = 13,
ADL_UIFEATURES_GROUP_CAMERA = 14,
ADL_UIFEATURES_GROUP_FRTCPRO = 15
ADL_UIFEATURES_GROUP_FRTCPRO = 15,
ADL_UIFEATURES_GROUP_DELAGNEXT = 16,
ADL_UIFEATURES_GROUP_RTBOOST = 17,
ADL_UIFEATURES_GROUP_UAI = 18
} ADL_UIFEATURES_GROUP;
@@ -2587,9 +2631,18 @@ typedef enum ADL_USER_SETTINGS
ADL_USER_SETTINGS_USU_PROFILE = 1 << 4, //notify USU settings change
ADL_USER_SETTINGS_CVDC_PROFILE = 1 << 5, //notify Color Vision Deficiency Corretion settings change
ADL_USER_SETTINGS_SCE_PROFILE = 1 << 6,
ADL_USER_SETTINGS_PROVSR = 1 << 7
ADL_USER_SETTINGS_PROVSR = 1 << 7,
ADL_USER_SETTINGS_RTBOOST_PROFILE=1 << 8,
ADL_USER_SETTINGS_USU2_PROFILE = 1 << 9, //notify USU2 settings change
} ADL_USER_SETTINGS;
//FRAME_TIMESTAMPS_SHARED_MEMORY type
typedef enum FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE
{
FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE_UNKNOWN = 0,
FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE_LEGACY,
FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE_INDEXED
}FRAME_TIMESTAMPS_SHARED_MEMORY_TYPE;
#define ADL_REG_DEVICE_FUNCTION_1 0x00000001
#endif /* ADL_DEFINES_H_ */
+2 -6
View File
@@ -33,14 +33,10 @@
#include "adl_structures.h"
#if defined (LINUX)
#define __stdcall
#endif /* (LINUX) */
/// Memory Allocation Call back
typedef void* ( __stdcall *ADL_MAIN_MALLOC_CALLBACK )( int );
#define ADL_SDK_MAJOR_VERSION 17
#define ADL_SDK_MINOR_VERSION 1
#define ADL_SDK_MAJOR_VERSION 18
#define ADL_SDK_MINOR_VERSION 0
#endif /* ADL_SDK_H_ */
+29 -36
View File
@@ -21,7 +21,7 @@
// SOFTWARE.
/// \file adl_structures.h
///\brief This file contains the structure declarations that are used by the public ADL interfaces for \ALL platforms.\n <b>Included in ADL SDK</b>
///\brief This file contains the structure declarations that are used by the public ADL interfaces for \WIN platforms.\n <b>Included in ADL SDK</b>
///
/// All data structures used in AMD Display Library (ADL) public interfaces should be defined in this header file.
///
@@ -41,7 +41,7 @@
////////////////////////////////////////////////////////////////////////////////////////////
typedef struct AdapterInfo
{
/// \ALL_STRUCT_MEM
/// \WIN_STRUCT_MEM
/// Size of the structure.
int iSize;
@@ -59,7 +59,7 @@ typedef struct AdapterInfo
int iVendorID;
/// Adapter name.
char strAdapterName[ADL_MAX_PATH];
/// Display name. For example, "\\\\Display0" for Windows or ":0:0" for Linux.
/// Display name. For example, "\\\\Display0" for Windows.
char strDisplayName[ADL_MAX_PATH];
/// Present or not; 1 if present and 0 if not present.It the logical adapter is present, the display name such as \\\\.\\Display1 can be found from OS
int iPresent;
@@ -80,38 +80,8 @@ typedef struct AdapterInfo
#endif /* (_WIN32) || (_WIN64) */
#if defined (LINUX)
/// \LNX_STRUCT_MEM
/// Internal X screen number from GPUMapInfo (DEPRICATED use XScreenInfo)
int iXScreenNum;
/// Internal driver index from GPUMapInfo
int iDrvIndex;
/// \deprecated Internal x config file screen identifier name. Use XScreenInfo instead.
char strXScreenConfigName[ADL_MAX_PATH];
#endif /* (LINUX) */
} AdapterInfo, *LPAdapterInfo;
/////////////////////////////////////////////////////////////////////////////////////////////
///\brief Structure containing information about the Linux X screen information.
///
/// This structure is used to store the current screen number and xorg.conf ID name assoicated with an adapter index.
/// This structure is updated during ADL_Main_Control_Refresh or ADL_ScreenInfo_Update.
/// Note: This structure should be used in place of iXScreenNum and strXScreenConfigName in AdapterInfo as they will be
/// deprecated.
/// \nosubgrouping
////////////////////////////////////////////////////////////////////////////////////////////
#if defined (LINUX)
typedef struct XScreenInfo
{
/// Internal X screen number from GPUMapInfo.
int iXScreenNum;
/// Internal x config file screen identifier name.
char strXScreenConfigName[ADL_MAX_PATH];
} XScreenInfo, *LPXScreenInfo;
#endif /* (LINUX) */
/////////////////////////////////////////////////////////////////////////////////////////////
///\brief Structure containing information about an controller mode
///
@@ -453,8 +423,12 @@ typedef struct ADLDDCInfo2
int ulMaxBacklightMinLuminanceData;
int ulMinBacklightMinLuminanceData;
// Display screen width/height
int ulScreenWidth;
int ulScreenHeight;
// Reserved for future use
int iReserved[4];
int iReserved[2];
} ADLDDCInfo2, *LPADLDDCInfo2;
/////////////////////////////////////////////////////////////////////////////////////////////
@@ -3614,6 +3588,23 @@ typedef struct ADL_BOOST_SETTINGS
int GlobalMinRes_Step; //Gloabl Min Resolution step value
}ADL_BOOST_SETTINGS;
/////////////////////////////////////////////////////////////////////////////////////////////
///\brief Structure containing information about BOOST Settings
///
/// Elements of BOOST settings.
/// \nosubgrouping
////////////////////////////////////////////////////////////////////////////////////////////
typedef struct ADL_BOOST_SETTINGSX2
{
int Hotkey; // Hotkey value
int GlobalEnable; //Global enable value
int GlobalMinRes; //Gloabl Min Resolution value
int GlobalMinRes_MinLimit; //Gloabl Min Resolution slider min limit value
int GlobalMinRes_MaxLimit; //Gloabl Min Resolution slider max limit value
int GlobalMinRes_Step; //Gloabl Min Resolution step value
int VsrSupported; //Allows for interop with Upscaling/RSR
}ADL_BOOST_SETTINGSX2;
/////////////////////////////////////////////////////////////////////////////////////////////
///\brief Structure containing information about ProVSR Settings change reason
@@ -3817,7 +3808,7 @@ typedef struct ADL_RADEON_LED_PATTERN_CONFIG
////////////////////////////////////////////////////////////////////////////////////////////
typedef struct AdapterInfoX2
{
/// \ALL_STRUCT_MEM
/// \WIN_STRUCT_MEM
/// Size of the structure.
int iSize;
@@ -4164,6 +4155,7 @@ typedef struct ADLHDCPSettings
///
/// This structure is used to store the Mantle Driver information
/// \nosubgrouping
/// \deprecated This structure has been deprecated.
////////////////////////////////////////////////////////////////////////////////////////////
typedef struct ADLMantleAppInfo
@@ -4286,4 +4278,5 @@ typedef struct ADLSmartShiftSettings
int iCurrentValue;
int iFlags; //refer to define_smartshift_bits
}ADLSmartShiftSettings, *LPADLSmartShiftSettings;
#endif /* ADL_STRUCTURES_H_ */
#endif /* ADL_STRUCTURES_H_ */
+1 -1
View File
@@ -1,6 +1,6 @@
{
"home": "https://github.com/GPUOpen-LibrariesAndSDKs/display-library",
"license": "MIT (embeded in source)",
"version": "ADL SDK 17.1",
"version": "ADL SDK 18.1",
"author": "Advanced Micro Devices, Inc"
}
-7
View File
@@ -1,7 +0,0 @@
{
"home": "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c",
"license": "MIT compatible (embed in source)",
"version": "2007-05-26 (Unicode 5.0)",
"author": "Markus Kuhn",
"modified": "CarterLi"
}
-314
View File
@@ -1,314 +0,0 @@
/*
* This is an implementation of wcwidth() and wcswidth() (defined in
* IEEE Std 1002.1-2001) for Unicode.
*
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
*
* In fixed-width output devices, Latin characters all occupy a single
* "cell" position of equal width, whereas ideographic CJK characters
* occupy two such cells. Interoperability between terminal-line
* applications and (teletype-style) character terminals using the
* UTF-8 encoding requires agreement on which character should advance
* the cursor by how many cell positions. No established formal
* standards exist at present on which Unicode character shall occupy
* how many cell positions on character terminals. These routines are
* a first attempt of defining such behavior based on simple rules
* applied to data provided by the Unicode Consortium.
*
* For some graphical characters, the Unicode standard explicitly
* defines a character-cell width via the definition of the East Asian
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
* In all these cases, there is no ambiguity about which width a
* terminal shall use. For characters in the East Asian Ambiguous (A)
* class, the width choice depends purely on a preference of backward
* compatibility with either historic CJK or Western practice.
* Choosing single-width for these characters is easy to justify as
* the appropriate long-term solution, as the CJK practice of
* displaying these characters as double-width comes from historic
* implementation simplicity (8-bit encoded characters were displayed
* single-width and 16-bit ones double-width, even for Greek,
* Cyrillic, etc.) and not any typographic considerations.
*
* Much less clear is the choice of width for the Not East Asian
* (Neutral) class. Existing practice does not dictate a width for any
* of these characters. It would nevertheless make sense
* typographically to allocate two character cells to characters such
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
* represented adequately with a single-width glyph. The following
* routines at present merely assign a single-cell width to all
* neutral characters, in the interest of simplicity. This is not
* entirely satisfactory and should be reconsidered before
* establishing a formal standard in this area. At the moment, the
* decision which Not East Asian (Neutral) characters should be
* represented by double-width glyphs cannot yet be answered by
* applying a simple rule from the Unicode database content. Setting
* up a proper standard for the behavior of UTF-8 character terminals
* will require a careful analysis not only of each Unicode character,
* but also of each presentation form, something the author of these
* routines has avoided to do so far.
*
* http://www.unicode.org/unicode/reports/tr11/
*
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without fee is hereby granted. The author
* disclaims all warranties with regard to this software.
*
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
#include <wchar.h>
struct interval {
int first;
int last;
};
/* auxiliary function for binary search in interval table */
static int bisearch(wchar_t ucs, const struct interval *table, int max) {
int min = 0;
int mid;
if (ucs < table[0].first || ucs > table[max].last)
return 0;
while (max >= min) {
mid = (min + max) / 2;
if (ucs > table[mid].last)
min = mid + 1;
else if (ucs < table[mid].first)
max = mid - 1;
else
return 1;
}
return 0;
}
/* The following two functions define the column width of an ISO 10646
* character as follows:
*
* - The null character (U+0000) has a column width of 0.
*
* - Other C0/C1 control characters and DEL will lead to a return
* value of -1.
*
* - Non-spacing and enclosing combining characters (general
* category code Mn or Me in the Unicode database) have a
* column width of 0.
*
* - SOFT HYPHEN (U+00AD) has a column width of 1.
*
* - Other format characters (general category code Cf in the Unicode
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
*
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
* have a column width of 0.
*
* - Spacing characters in the East Asian Wide (W) or East Asian
* Full-width (F) category as defined in Unicode Technical
* Report #11 have a column width of 2.
*
* - All remaining characters (including all printable
* ISO 8859-1 and WGL4 characters, Unicode control characters,
* etc.) have a column width of 1.
*
* This implementation assumes that wchar_t characters are encoded
* in ISO 10646.
*/
int mk_wcwidth(wchar_t ucs)
{
/* sorted list of non-overlapping intervals of non-spacing characters */
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
static const struct interval combining[] = {
{ 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
{ 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
{ 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
{ 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
{ 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
{ 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
{ 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
{ 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
{ 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
{ 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
{ 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
{ 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
{ 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
{ 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
{ 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
{ 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
{ 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
{ 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
{ 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
{ 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
{ 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
{ 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
{ 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
{ 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
{ 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
{ 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
{ 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
{ 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
{ 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
{ 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
{ 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
{ 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
{ 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
{ 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
{ 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
{ 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
{ 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
{ 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
{ 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
{ 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
{ 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
{ 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
{ 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
{ 0xE0100, 0xE01EF }
};
/* test for 8-bit control characters */
if (ucs == 0)
return 0;
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
return -1;
/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining,
sizeof(combining) / sizeof(struct interval) - 1))
return 0;
/* if we arrive here, ucs is not a combining or C0/C1 control character */
return 1 +
(ucs >= 0x1100 &&
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
ucs == 0x2329 || ucs == 0x232a ||
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
ucs != 0x303f) || /* CJK ... Yi */
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
#ifndef _WIN32 // sizeof(wchar_t) == 2
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
(ucs >= 0x30000 && ucs <= 0x3fffd) ||
#endif
0
));
}
int mk_wcswidth(const wchar_t *pwcs, size_t n)
{
int w, width = 0;
for (;*pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
/*
* The following functions are the same as mk_wcwidth() and
* mk_wcswidth(), except that spacing characters in the East Asian
* Ambiguous (A) category as defined in Unicode Technical Report #11
* have a column width of 2. This variant might be useful for users of
* CJK legacy encodings who want to migrate to UCS without changing
* the traditional terminal character-width behaviour. It is not
* otherwise recommended for general use.
*/
int mk_wcwidth_cjk(wchar_t ucs)
{
/* sorted list of non-overlapping intervals of East Asian Ambiguous
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
static const struct interval ambiguous[] = {
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
{ 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
{ 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
{ 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
{ 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
{ 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
{ 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
{ 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
{ 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
{ 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
{ 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
{ 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
{ 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
{ 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
{ 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
{ 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
{ 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
{ 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
{ 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
{ 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
{ 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
{ 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
{ 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
{ 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
{ 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
{ 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
{ 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
{ 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
{ 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
{ 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
{ 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
{ 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
{ 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
{ 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
{ 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
{ 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
{ 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
{ 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
{ 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
{ 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
{ 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
{ 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
{ 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
{ 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
{ 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
{ 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
{ 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
{ 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
{ 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
{ 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
{ 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
};
/* binary search in table of non-spacing characters */
if (bisearch(ucs, ambiguous,
sizeof(ambiguous) / sizeof(struct interval) - 1))
return 2;
return mk_wcwidth(ucs);
}
int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
{
int w, width = 0;
for (;*pwcs && n-- > 0; pwcs++)
if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
return -1;
else
width += w;
return width;
}
+6
View File
@@ -0,0 +1,6 @@
{
"home": "https://github.com/ridiculousfish/widecharwidth",
"license": "Public domain",
"version": "Unicode 17",
"author": "ridiculousfish"
}
File diff suppressed because it is too large Load Diff
@@ -1,26 +1,30 @@
#pragma once
#include "util/FFstrbuf.h"
#include "util/FFlist.h"
#include "common/FFstrbuf.h"
#include "common/FFlist.h"
typedef struct FFPlatformSysinfo
{
typedef struct FFPlatformSysinfo {
FFstrbuf name;
FFstrbuf release;
FFstrbuf version;
FFstrbuf architecture;
FFstrbuf displayVersion;
uint32_t pageSize;
} FFPlatformSysinfo;
typedef struct FFPlatform
{
typedef struct FFPlatform {
FFstrbuf homeDir; // Trailing slash included
FFstrbuf cacheDir; // Trailing slash included
FFlist configDirs; // List of FFstrbuf, trailing slash included
FFlist dataDirs; // List of FFstrbuf, trailing slash included
FFstrbuf exePath; // The real path of current exe
FFstrbuf exePath; // The real path of current exe (empty if unavailable)
FFstrbuf cwd; // Trailing slash included
uint32_t pid;
#ifndef _WIN32
uint32_t uid;
#else
FFstrbuf sid;
#endif
FFstrbuf userName;
FFstrbuf fullUserName;
FFstrbuf hostName;
+141
View File
@@ -0,0 +1,141 @@
#pragma once
#include "common/attributes.h"
#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
#define FF_LIST_DEFAULT_ALLOC 16
typedef struct FFlist {
uint8_t* data;
uint32_t length;
uint32_t capacity;
} FFlist;
void* ffListAdd(FFlist* list, uint32_t elementSize);
// Removes the first element, and copy its value to `*result`
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result);
// Removes the last element, and copy its value to `*result`
bool ffListPop(FFlist* list, uint32_t elementSize, void* __restrict result);
static inline void ffListInit(FFlist* list) {
list->capacity = 0;
list->length = 0;
list->data = NULL;
}
static inline void ffListInitA(FFlist* list, uint32_t elementSize, uint32_t capacity) {
ffListInit(list);
list->capacity = capacity;
list->data = __builtin_expect(capacity == 0, 0) ? NULL : (uint8_t*) malloc((size_t) capacity * elementSize);
}
FF_A_NODISCARD static inline FFlist ffListCreate() {
FFlist result;
ffListInit(&result);
return result;
}
FF_A_NODISCARD static inline FFlist ffListCreateA(uint32_t elementSize, uint32_t capacity) {
FFlist result;
ffListInitA(&result, elementSize, capacity);
return result;
}
FF_A_NODISCARD static inline void* ffListGet(const FFlist* list, uint32_t elementSize, uint32_t index) {
assert(list->capacity > index);
return list->data + (index * elementSize);
}
FF_A_NODISCARD static inline uint32_t ffListFirstIndexComp(const FFlist* list, uint32_t elementSize, void* compElement, bool (*compFunc)(const void*, const void*)) {
for (uint32_t i = 0; i < list->length; i++) {
if (compFunc(ffListGet(list, elementSize, i), compElement)) {
return i;
}
}
return list->length;
}
FF_A_NODISCARD static inline bool ffListContains(const FFlist* list, uint32_t elementSize, void* compElement, bool (*compFunc)(const void*, const void*)) {
return ffListFirstIndexComp(list, elementSize, compElement, compFunc) != list->length;
}
static inline void ffListSort(FFlist* list, uint32_t elementSize, int (*compar)(const void*, const void*)) {
qsort(list->data, list->length, elementSize, compar);
}
// Move the contents of `src` into `list`, and left `src` empty
static inline void ffListInitMove(FFlist* list, FFlist* src) {
if (src) {
list->capacity = src->capacity;
list->length = src->length;
list->data = src->data;
ffListInit(src);
} else {
ffListInit(list);
}
}
static inline void ffListDestroy(FFlist* list) {
if (!list->data) {
return;
}
// Avoid free-after-use. These 3 assignments are cheap so don't remove them
list->capacity = list->length = 0;
free(list->data);
list->data = NULL;
}
static inline void ffListClear(FFlist* list) {
list->length = 0;
}
static inline void ffListReserve(FFlist* list, uint32_t elementSize, uint32_t newCapacity) {
if (__builtin_expect(newCapacity <= list->capacity, false)) {
return;
}
list->data = (uint8_t*) realloc(list->data, (size_t) newCapacity * elementSize);
list->capacity = newCapacity;
}
#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \
for (itemType* itemVarName = (itemType*) (listVar).data; \
itemVarName - (itemType*) (listVar).data < (intptr_t) (listVar).length; \
++itemVarName)
#define FF_LIST_AUTO_DESTROY FFlist FF_A_CLEANUP(ffListDestroy)
#define FF_LIST_GET(itemType, listVar, index) \
({ \
assert((listVar).capacity > (index)); \
(itemType*) (listVar).data + (index); \
})
#define FF_LIST_ADD(itemType, listVar) (itemType*) ffListAdd(&(listVar), (uint32_t) sizeof(itemType))
#define FF_LIST_FIRST(itemType, listVar) FF_LIST_GET(itemType, listVar, 0)
#define FF_LIST_LAST(itemType, listVar) \
({ \
assert((listVar).length > 0); \
FF_LIST_GET(itemType, listVar, ((listVar).length - 1)); \
})
#define FF_LIST_CONTAINS(listVar, pCompElement, compFunc) \
({ \
typedef __typeof__(*(pCompElement)) compElementType; \
typedef bool compFuncType(const compElementType*, const compElementType*); \
static_assert(__builtin_types_compatible_p(__typeof__(compFunc), compFuncType), "Incompatible callback function"); \
ffListContains(&(listVar), (uint32_t) sizeof(*(pCompElement)), (pCompElement), (bool (*)(const void*, const void*)) compFunc); \
})
#define FF_LIST_SHIFT(listVar, pResult) \
ffListShift(&(listVar), (uint32_t) sizeof(*(pResult)), (pResult))
#define FF_LIST_POP(listVar, pResult) \
ffListPop(&(listVar), (uint32_t) sizeof(*(pResult)), (pResult))
+567
View File
@@ -0,0 +1,567 @@
#pragma once
#include "common/attributes.h"
#include <stdint.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#ifdef FF_USE_SYSTEM_YYJSON
#include <yyjson.h>
#else
#include "3rdparty/yyjson/yyjson.h"
#endif
#ifdef _WIN32
// #include <shlwapi.h>
__stdcall char* StrStrIA(const char* lpFirst, const char* lpSrch);
#define strcasestr StrStrIA
#endif
#define FASTFETCH_STRBUF_DEFAULT_ALLOC 32
// static string (allocated == 0), chars points to a string literal
// dynamic string (allocated > 0), chars points to a heap allocated buffer
typedef struct FFstrbuf {
uint32_t allocated;
uint32_t length;
char* chars;
} FFstrbuf;
static inline void ffStrbufInit(FFstrbuf* strbuf);
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments);
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr);
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free);
void ffStrbufClear(FFstrbuf* strbuf);
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value);
void ffStrbufAppendC(FFstrbuf* strbuf, char c);
void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c);
void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value);
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int));
FF_A_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments);
const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until);
void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value);
void ffStrbufPrependC(FFstrbuf* strbuf, char c);
void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c);
// Clear the content of strbuf and set new value
// NOTE: Unlike ffStrbufAppend*, ffStrbufSet* functions may NOT reserve extra space
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value);
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value);
FF_A_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c);
void ffStrbufTrimRight(FFstrbuf* strbuf, char c);
void ffStrbufTrimLeftSpace(FFstrbuf* strbuf);
void ffStrbufTrimRightSpace(FFstrbuf* strbuf);
bool ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex);
void ffStrbufRemoveS(FFstrbuf* strbuf, const char* str);
void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, const char* strings[]);
FF_A_NODISCARD uint32_t ffStrbufNextIndexC(const FFstrbuf* strbuf, uint32_t start, char c);
FF_A_NODISCARD uint32_t ffStrbufNextIndexS(const FFstrbuf* strbuf, uint32_t start, const char* str);
FF_A_NODISCARD uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c);
void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace);
// Returns true if the strbuf is modified
bool ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index);
bool ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index); // Not including the index
bool ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c);
bool ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str);
bool ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c);
bool ffStrbufSubstr(FFstrbuf* strbuf, uint32_t start, uint32_t end);
FF_A_NODISCARD uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c);
bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end);
bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c);
void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file);
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file);
FF_A_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue);
FF_A_NODISCARD int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue);
FF_A_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue);
void ffStrbufUpperCase(FFstrbuf* strbuf);
void ffStrbufLowerCase(FFstrbuf* strbuf);
// Function alters the buffer to extract lines or delimited segments (replaces the delimiter with '\0')
// so that buffer MUST be heap allocated (NOT a static string)
// `lineptr` must be `NULL` and `n` MUST be `0` for the first call
// Caller MUST NOT free `*lineptr`
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer);
/**
* @brief Read a line from a FFstrbuf.
*
* @details Behaves like getline(3) but reads from a FFstrbuf.
*
* @param[in,out] lineptr The pointer to a pointer that will be set to the start of the line
(points to buffer's internal memory address to avoid memory allocation and copy).
MUST NOT be freed by the caller, unlike `getline(3)`.
* MUST be NULL for the first call.
* @param[in,out] n The pointer to the size of the buffer of lineptr.
MUST be 0 for the first call.
* @param[in] buffer The buffer to read from.
MUST be heap allocated (NOT a static string).
*
* @return true if a line has been read, false if the end of the buffer has been reached.
*/
static inline bool ffStrbufGetline(char** lineptr, size_t* n, FFstrbuf* buffer) {
return ffStrbufGetdelim(lineptr, n, '\n', buffer);
}
/**
* @brief Restore the end of a line that was modified by ffStrbufGetline.
* @warning This function should be called before breaking an ffStrbufGetline loop if `buffer` will be used later.
*/
static inline void ffStrbufGetlineRestore(char** lineptr, size_t* n, FFstrbuf* buffer) {
ffStrbufGetdelimRestore(lineptr, n, '\n', buffer);
}
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf);
bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
bool ffStrbufMatchSeparatedIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
bool ffStrbufSeparatedContainNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
bool ffStrbufSeparatedContainIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator);
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint);
void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value);
void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value);
// Appends a double value to the string buffer with the specified precision (0~15).
// if `precision < 0`, let yyjson decide the precision
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision, bool trailingZeros);
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate) {
FFstrbuf strbuf;
ffStrbufInitA(&strbuf, allocate);
return strbuf;
}
static inline void ffStrbufInitCopy(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict src) {
if (src->allocated == 0) { // static string
*strbuf = *src;
} else {
ffStrbufInitA(strbuf, src->allocated);
ffStrbufAppend(strbuf, src);
}
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateCopy(const FFstrbuf* src) {
FFstrbuf strbuf;
ffStrbufInitCopy(&strbuf, src);
return strbuf;
}
// Move the content of `src` into `strbuf`, and left `src` empty
static inline void ffStrbufInitMove(FFstrbuf* strbuf, FFstrbuf* src) {
if (src) {
*strbuf = *src;
ffStrbufInit(src);
} else {
ffStrbufInit(strbuf);
}
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateMove(FFstrbuf* src) {
FFstrbuf strbuf;
ffStrbufInitMove(&strbuf, src);
return strbuf;
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateVF(const char* format, va_list arguments) {
FFstrbuf strbuf;
ffStrbufInitVF(&strbuf, format, arguments);
return strbuf;
}
FF_A_PRINTF(2, 3) static inline void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...) {
va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(strbuf, format, arguments);
va_end(arguments);
}
FF_A_PRINTF(1, 2) FF_A_NODISCARD static inline FFstrbuf
ffStrbufCreateF(const char* format, ...) {
FFstrbuf strbuf;
va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(&strbuf, format, arguments);
va_end(arguments);
return strbuf;
}
static inline void ffStrbufInitMoveS(FFstrbuf* strbuf, char* heapStr) {
ffStrbufInitMoveNS(strbuf, (uint32_t) strlen(heapStr), heapStr);
}
// Despite the name, this function resets strbuf to the initial/unallocated state
static inline void ffStrbufDestroy(FFstrbuf* strbuf) {
if (strbuf->allocated > 0) {
free(strbuf->chars);
}
ffStrbufInit(strbuf);
}
FF_A_NODISCARD static inline uint32_t ffStrbufGetFree(const FFstrbuf* strbuf) {
assert(strbuf != NULL);
if (strbuf->allocated == 0) {
return 0;
}
return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte
}
static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf) {
strbuf->length = (uint32_t) strlen(strbuf->chars);
}
static inline void ffStrbufSetS(FFstrbuf* strbuf, const char* value) {
assert(strbuf != NULL);
if (value == NULL) {
ffStrbufClear(strbuf);
} else {
ffStrbufSetNS(strbuf, (uint32_t) strlen(value), value);
}
}
static inline bool ffStrbufSetJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) {
assert(strbuf != NULL);
if (yyjson_is_str(jsonVal)) {
ffStrbufSetNS(strbuf, (uint32_t) unsafe_yyjson_get_len(jsonVal), unsafe_yyjson_get_str(jsonVal));
return true;
}
ffStrbufClear(strbuf);
return false;
}
static inline void ffStrbufAppendS(FFstrbuf* strbuf, const char* value) {
if (value == NULL) {
return;
}
ffStrbufAppendNS(strbuf, (uint32_t) strlen(value), value);
}
static inline bool ffStrbufAppendJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) {
if (yyjson_is_str(jsonVal)) {
ffStrbufAppendNS(strbuf, (uint32_t) unsafe_yyjson_get_len(jsonVal), unsafe_yyjson_get_str(jsonVal));
return true;
}
return false;
}
static inline void ffStrbufInit(FFstrbuf* strbuf) {
extern char* CHAR_NULL_PTR;
strbuf->allocated = strbuf->length = 0;
strbuf->chars = CHAR_NULL_PTR;
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreate(void) {
FFstrbuf strbuf;
ffStrbufInit(&strbuf);
return strbuf;
}
static inline void ffStrbufInitStatic(FFstrbuf* strbuf, const char* str) {
ffStrbufInit(strbuf);
if (!str) {
return;
}
strbuf->allocated = 0;
strbuf->length = (uint32_t) strlen(str);
strbuf->chars = (char*) str;
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateStatic(const char* str) {
FFstrbuf strbuf;
ffStrbufInitStatic(&strbuf, str);
return strbuf;
}
static inline void ffStrbufSetStatic(FFstrbuf* strbuf, const char* value) {
if (strbuf->allocated > 0) {
free(strbuf->chars);
}
if (value != NULL) {
ffStrbufInitStatic(strbuf, value);
} else {
ffStrbufInit(strbuf);
}
}
static inline void ffStrbufInitNS(FFstrbuf* strbuf, uint32_t length, const char* str) {
ffStrbufInit(strbuf);
ffStrbufAppendNS(strbuf, length, str);
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateNS(uint32_t length, const char* str) {
FFstrbuf strbuf;
ffStrbufInitNS(&strbuf, length, str);
return strbuf;
}
static inline bool ffStrbufInitJsonVal(FFstrbuf* strbuf, yyjson_val* jsonVal) {
ffStrbufInit(strbuf);
return ffStrbufAppendJsonVal(strbuf, jsonVal);
}
static inline void ffStrbufInitS(FFstrbuf* strbuf, const char* str) {
ffStrbufInit(strbuf);
ffStrbufAppendS(strbuf, str);
}
FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateS(const char* str) {
FFstrbuf strbuf;
ffStrbufInitS(&strbuf, str);
return strbuf;
}
static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
assert(value != strbuf);
if (value == NULL) {
return;
}
ffStrbufAppendNS(strbuf, value->length, value->chars);
}
static inline void ffStrbufPrepend(FFstrbuf* strbuf, FFstrbuf* value) {
if (value == NULL) {
return;
}
ffStrbufPrependNS(strbuf, value->length, value->chars);
}
static inline void ffStrbufPrependS(FFstrbuf* strbuf, const char* value) {
if (value == NULL) {
return;
}
ffStrbufPrependNS(strbuf, (uint32_t) strlen(value), value);
}
static inline FF_A_NODISCARD int ffStrbufComp(const FFstrbuf* strbuf, const FFstrbuf* comp) {
uint32_t length = strbuf->length > comp->length ? comp->length : strbuf->length;
return memcmp(strbuf->chars, comp->chars, length + 1);
}
static inline FF_A_NODISCARD bool ffStrbufEqual(const FFstrbuf* strbuf, const FFstrbuf* comp) {
return ffStrbufComp(strbuf, comp) == 0;
}
static inline FF_A_NODISCARD int ffStrbufCompS(const FFstrbuf* strbuf, const char* comp) {
return strcmp(strbuf->chars, comp);
}
static inline FF_A_NODISCARD bool ffStrbufEqualS(const FFstrbuf* strbuf, const char* comp) {
return ffStrbufCompS(strbuf, comp) == 0;
}
static inline FF_A_NODISCARD int ffStrbufIgnCaseCompS(const FFstrbuf* strbuf, const char* comp) {
return strcasecmp(strbuf->chars, comp);
}
static inline FF_A_NODISCARD bool ffStrbufIgnCaseEqualS(const FFstrbuf* strbuf, const char* comp) {
return ffStrbufIgnCaseCompS(strbuf, comp) == 0;
}
static inline FF_A_NODISCARD int ffStrbufIgnCaseComp(const FFstrbuf* strbuf, const FFstrbuf* comp) {
return ffStrbufIgnCaseCompS(strbuf, comp->chars);
}
static inline FF_A_NODISCARD bool ffStrbufIgnCaseEqual(const FFstrbuf* strbuf, const FFstrbuf* comp) {
return ffStrbufIgnCaseComp(strbuf, comp) == 0;
}
static inline FF_A_NODISCARD bool ffStrbufContainC(const FFstrbuf* strbuf, char c) {
return memchr(strbuf->chars, c, strbuf->length) != NULL;
}
static inline FF_A_NODISCARD bool ffStrbufContainS(const FFstrbuf* strbuf, const char* str) {
return strstr(strbuf->chars, str) != NULL;
}
static inline FF_A_NODISCARD bool ffStrbufContain(const FFstrbuf* strbuf, const FFstrbuf* str) {
return ffStrbufContainS(strbuf, str->chars);
}
static inline FF_A_NODISCARD bool ffStrbufContainIgnCaseS(const FFstrbuf* strbuf, const char* str) {
return strcasestr(strbuf->chars, str) != NULL;
}
static inline FF_A_NODISCARD bool ffStrbufContainIgnCase(const FFstrbuf* strbuf, const FFstrbuf* str) {
return ffStrbufContainIgnCaseS(strbuf, str->chars);
}
static inline FF_A_NODISCARD uint32_t ffStrbufFirstIndexC(const FFstrbuf* strbuf, char c) {
return ffStrbufNextIndexC(strbuf, 0, c);
}
static inline FF_A_NODISCARD uint32_t ffStrbufFirstIndex(const FFstrbuf* strbuf, const FFstrbuf* searched) {
return ffStrbufNextIndexS(strbuf, 0, searched->chars);
}
static inline FF_A_NODISCARD uint32_t ffStrbufFirstIndexS(const FFstrbuf* strbuf, const char* str) {
return ffStrbufNextIndexS(strbuf, 0, str);
}
static inline FF_A_NODISCARD uint32_t ffStrbufLastIndexC(const FFstrbuf* strbuf, char c) {
if (strbuf->length == 0) {
return 0;
}
return ffStrbufPreviousIndexC(strbuf, strbuf->length - 1, c);
}
static inline bool ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c) {
return ffStrbufSubstrBefore(strbuf, ffStrbufFirstIndexC(strbuf, c));
}
static inline bool ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c) {
return ffStrbufSubstrBefore(strbuf, ffStrbufLastIndexC(strbuf, c));
}
static inline FF_A_NODISCARD bool ffStrbufStartsWithC(const FFstrbuf* strbuf, char c) {
return strbuf->chars[0] == c;
}
static inline FF_A_NODISCARD bool ffStrbufStartsWithSN(const FFstrbuf* strbuf, const char* start, uint32_t length) {
if (length > strbuf->length) {
return false;
}
return memcmp(strbuf->chars, start, length) == 0;
}
static inline FF_A_NODISCARD bool ffStrbufStartsWithS(const FFstrbuf* strbuf, const char* start) {
return ffStrbufStartsWithSN(strbuf, start, (uint32_t) strlen(start));
}
static inline FF_A_NODISCARD bool ffStrbufStartsWith(const FFstrbuf* strbuf, const FFstrbuf* start) {
return ffStrbufStartsWithSN(strbuf, start->chars, start->length);
}
static inline FF_A_NODISCARD bool ffStrbufStartsWithIgnCaseNS(const FFstrbuf* strbuf, uint32_t length, const char* start) {
if (length > strbuf->length) {
return false;
}
return strncasecmp(strbuf->chars, start, length) == 0;
}
static inline FF_A_NODISCARD bool ffStrbufStartsWithIgnCaseS(const FFstrbuf* strbuf, const char* start) {
return ffStrbufStartsWithIgnCaseNS(strbuf, (uint32_t) strlen(start), start);
}
static inline FF_A_NODISCARD bool ffStrbufStartsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* start) {
return ffStrbufStartsWithIgnCaseNS(strbuf, start->length, start->chars);
}
static inline FF_A_NODISCARD bool ffStrbufEndsWithC(const FFstrbuf* strbuf, char c) {
return strbuf->length == 0 ? false : strbuf->chars[strbuf->length - 1] == c;
}
static inline FF_A_NODISCARD bool ffStrbufEndsWithNS(const FFstrbuf* strbuf, uint32_t endLength, const char* end) {
if (endLength > strbuf->length) {
return false;
}
return memcmp(strbuf->chars + strbuf->length - endLength, end, endLength) == 0;
}
static inline FF_A_NODISCARD bool ffStrbufEndsWithS(const FFstrbuf* strbuf, const char* end) {
return ffStrbufEndsWithNS(strbuf, (uint32_t) strlen(end), end);
}
static inline FF_A_NODISCARD bool ffStrbufEndsWithFn(const FFstrbuf* strbuf, int (*const fn)(int)) {
return strbuf->length == 0 ? false : fn(strbuf->chars[strbuf->length - 1]);
}
static inline FF_A_NODISCARD bool ffStrbufEndsWith(const FFstrbuf* strbuf, const FFstrbuf* end) {
return ffStrbufEndsWithNS(strbuf, end->length, end->chars);
}
static inline FF_A_NODISCARD bool ffStrbufEndsWithIgnCaseNS(const FFstrbuf* strbuf, uint32_t endLength, const char* end) {
if (endLength > strbuf->length) {
return false;
}
return strcasecmp(strbuf->chars + strbuf->length - endLength, end) == 0;
}
static inline FF_A_NODISCARD bool ffStrbufEndsWithIgnCaseS(const FFstrbuf* strbuf, const char* end) {
return ffStrbufEndsWithIgnCaseNS(strbuf, (uint32_t) strlen(end), end);
}
static inline FF_A_NODISCARD bool ffStrbufEndsWithIgnCase(const FFstrbuf* strbuf, const FFstrbuf* end) {
return ffStrbufEndsWithIgnCaseNS(strbuf, end->length, end->chars);
}
static inline void ffStrbufTrim(FFstrbuf* strbuf, char c) {
ffStrbufTrimRight(strbuf, c);
ffStrbufTrimLeft(strbuf, c);
}
static inline void ffStrbufTrimSpace(FFstrbuf* strbuf) {
ffStrbufTrimRightSpace(strbuf);
ffStrbufTrimLeftSpace(strbuf);
}
static inline bool ffStrbufMatchSeparatedS(const FFstrbuf* strbuf, const char* comp, char separator) {
return ffStrbufMatchSeparatedNS(strbuf, (uint32_t) strlen(comp), comp, separator);
}
static inline bool ffStrbufMatchSeparated(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
return ffStrbufMatchSeparatedNS(strbuf, comp->length, comp->chars, separator);
}
static inline bool ffStrbufMatchSeparatedIgnCaseS(const FFstrbuf* strbuf, const char* comp, char separator) {
return ffStrbufMatchSeparatedIgnCaseNS(strbuf, (uint32_t) strlen(comp), comp, separator);
}
static inline bool ffStrbufMatchSeparatedIgnCase(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
return ffStrbufMatchSeparatedIgnCaseNS(strbuf, comp->length, comp->chars, separator);
}
static inline bool ffStrbufSeparatedContainS(const FFstrbuf* strbuf, const char* comp, char separator) {
return ffStrbufSeparatedContainNS(strbuf, (uint32_t) strlen(comp), comp, separator);
}
static inline bool ffStrbufSeparatedContain(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
return ffStrbufSeparatedContainNS(strbuf, comp->length, comp->chars, separator);
}
static inline bool ffStrbufSeparatedContainIgnCaseS(const FFstrbuf* strbuf, const char* comp, char separator) {
return ffStrbufSeparatedContainIgnCaseNS(strbuf, (uint32_t) strlen(comp), comp, separator);
}
static inline bool ffStrbufSeparatedContainIgnCase(const FFstrbuf* strbuf, const FFstrbuf* comp, char separator) {
return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator);
}
// Returns true if the strbuf is modified
bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf);
#define FF_STRBUF_AUTO_DESTROY FFstrbuf FF_A_CLEANUP(ffStrbufDestroy)
+225
View File
@@ -0,0 +1,225 @@
#include "cf_helpers.h"
const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result) {
if (CFGetTypeID(cf) == CFNumberGetTypeID()) {
if (!CFNumberGetValue((CFNumberRef) cf, kCFNumberSInt64Type, result)) {
return "Number type is not SInt64";
}
return NULL;
} else if (CFGetTypeID(cf) == CFDataGetTypeID()) {
if (CFDataGetLength((CFDataRef) cf) != sizeof(int64_t)) {
return "Data length is not sizeof(int64_t)";
}
CFDataGetBytes((CFDataRef) cf, CFRangeMake(0, sizeof(int64_t)), (uint8_t*) result);
return NULL;
}
return "TypeID is neither 'CFNumber' nor 'CFData'";
}
const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result) {
if (CFGetTypeID(cf) == CFNumberGetTypeID()) {
if (!CFNumberGetValue((CFNumberRef) cf, kCFNumberSInt32Type, result)) {
return "Number type is not SInt32";
}
return NULL;
} else if (CFGetTypeID(cf) == CFDataGetTypeID()) {
if (CFDataGetLength((CFDataRef) cf) != sizeof(*result)) {
return "Data length is not sizeof(int32_t)";
}
CFDataGetBytes((CFDataRef) cf, CFRangeMake(0, sizeof(*result)), (uint8_t*) result);
return NULL;
}
return "TypeID is neither 'CFNumber' nor 'CFData'";
}
const char* ffCfNumGetDouble(CFTypeRef cf, double* result) {
if (CFGetTypeID(cf) == CFNumberGetTypeID()) {
if (!CFNumberGetValue((CFNumberRef) cf, kCFNumberDoubleType, result) &&
!CFNumberGetValue((CFNumberRef) cf, kCFNumberFloatType, result)) {
return "Number type is not Double or Float";
}
return NULL;
}
return "TypeID is neither 'CFNumber'";
}
const char* ffCfDateGetEpoch(CFTypeRef cf, uint64_t* result) {
if (CFGetTypeID(cf) != CFDateGetTypeID()) {
return "TypeID is not 'CFDate'";
}
CFAbsoluteTime absTime = CFDateGetAbsoluteTime((CFDateRef) cf);
// Convert from seconds to milliseconds and add the difference between 1970 and 2001 in milliseconds
*result = (uint64_t) ((absTime + 978307200 /*kCFAbsoluteTimeIntervalSince1970*/) * 1000);
return NULL;
}
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result) {
ffStrbufClear(result);
if (!cf) {
return NULL;
}
if (CFGetTypeID(cf) == CFStringGetTypeID()) {
CFStringRef cfStr = (CFStringRef) cf;
const char* cstr = CFStringGetCStringPtr(cfStr, kCFStringEncodingUTF8);
if (cstr) {
ffStrbufSetS(result, cstr);
} else {
uint32_t length = (uint32_t) CFStringGetLength(cfStr);
if (length == 0) {
return NULL;
}
ffStrbufEnsureFixedLengthFree(result, (uint32_t) CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8));
if (!CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8)) {
return "CFStringGetCString() failed";
}
// CFStringGetCString ensures the buffer is NUL terminated
// https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring
result->length = (uint32_t) strnlen(result->chars, (uint32_t) result->allocated);
}
} else if (CFGetTypeID(cf) == CFDataGetTypeID()) {
CFDataRef cfData = (CFDataRef) cf;
uint32_t length = (uint32_t) CFDataGetLength(cfData);
if (length == 0) {
return NULL;
}
ffStrbufEnsureFixedLengthFree(result, length + 1);
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*) result->chars);
result->length = (uint32_t) strnlen(result->chars, length);
result->chars[result->length] = '\0';
} else {
return "TypeID is neither 'CFString' nor 'CFData'";
}
return NULL;
}
const char* ffCfDataGetDataAsString(CFTypeRef cf, FFstrbuf* result) {
ffStrbufClear(result);
if (!cf) {
return NULL;
}
if (CFGetTypeID(cf) == CFDataGetTypeID()) {
CFDataRef cfData = (CFDataRef) cf;
uint32_t length = (uint32_t) CFDataGetLength(cfData);
if (length == 0) {
return NULL;
}
ffStrbufEnsureFixedLengthFree(result, length + 1);
CFDataGetBytes(cfData, CFRangeMake(0, length), (uint8_t*) result->chars);
result->length = length;
result->chars[result->length] = '\0';
} else {
return "TypeID is not 'CFData'";
}
return NULL;
}
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result) {
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
return ffCfStrGetString(cf, result);
}
const char* ffCfDictGetDataAsString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result) {
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
return ffCfDataGetDataAsString(cf, result);
}
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result) {
CFBooleanRef cf = (CFBooleanRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
if (CFGetTypeID(cf) != CFBooleanGetTypeID()) {
return "TypeID is not 'CFBoolean'";
}
*result = CFBooleanGetValue(cf);
return NULL;
}
const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) {
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
return ffCfNumGetInt(cf, result);
}
const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result) {
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
return ffCfNumGetInt64(cf, result);
}
const char* ffCfDictGetDouble(CFDictionaryRef dict, CFStringRef key, double* result) {
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
return ffCfNumGetDouble(cf, result);
}
const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length) {
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
if (CFGetTypeID(cf) != CFDataGetTypeID()) {
return "TypeID is not 'CFData'";
}
CFIndex trueLength = CFDataGetLength((CFDataRef) cf);
if (trueLength < offset + size) {
return "Data length is less than offset + size";
}
if (length) {
*length = (uint32_t) trueLength;
}
CFDataGetBytes((CFDataRef) cf, CFRangeMake(offset, size), result);
return NULL;
}
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result) {
CFDictionaryRef cf = (CFDictionaryRef) CFDictionaryGetValue(dict, key);
if (cf == NULL || CFGetTypeID(cf) != CFDictionaryGetTypeID()) {
return "TypeID is not 'CFDictionary'";
}
*result = cf;
return NULL;
}
const char* ffCfDictGetDateAsEpoch(CFDictionaryRef dict, CFStringRef key, uint64_t* result) {
CFTypeRef cf = (CFTypeRef) CFDictionaryGetValue(dict, key);
if (cf == NULL) {
return "CFDictionaryGetValue() failed";
}
return ffCfDateGetEpoch(cf, result);
}
@@ -4,34 +4,40 @@
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
//Return error info if failed, NULL otherwise
// Return error info if failed, NULL otherwise
const char* ffCfStrGetString(CFTypeRef cf, FFstrbuf* result);
const char* ffCfNumGetInt(CFTypeRef cf, int32_t* result);
const char* ffCfNumGetInt64(CFTypeRef cf, int64_t* result);
const char* ffCfNumGetDouble(CFTypeRef cf, double* result);
const char* ffCfDateGetEpoch(CFTypeRef cf, uint64_t* result);
const char* ffCfDataGetDataAsString(CFTypeRef cf, FFstrbuf* result);
const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);
const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result);
const char* ffCfDictGetInt64(CFDictionaryRef dict, CFStringRef key, int64_t* result);
const char* ffCfDictGetDouble(CFDictionaryRef dict, CFStringRef key, double* result);
const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length);
const char* ffCfDictGetDataAsString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result);
const char* ffCfDictGetDateAsEpoch(CFDictionaryRef dict, CFStringRef key, uint64_t* result);
static inline CFNumberRef ffCfCreateInt(int value)
{
static inline CFNumberRef ffCfCreateInt(int value) {
return CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value);
}
static inline void cfReleaseWrapper(void* type)
{
if (*(CFTypeRef*) type)
static inline void cfReleaseWrapper(void* type) {
assert(type);
if (*(CFTypeRef*) type) {
CFRelease(*(CFTypeRef*) type);
}
}
#define FF_CFTYPE_AUTO_RELEASE __attribute__((__cleanup__(cfReleaseWrapper)))
#define FF_CFTYPE_AUTO_RELEASE FF_A_CLEANUP(cfReleaseWrapper)
static inline void wrapIoObjectRelease(io_object_t* service)
{
static inline void wrapIoObjectRelease(io_object_t* service) {
assert(service);
if (*service)
if (*service) {
IOObjectRelease(*service);
}
}
#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease)))
#define FF_IOOBJECT_AUTO_RELEASE FF_A_CLEANUP(wrapIoObjectRelease)
@@ -1,8 +1,6 @@
#include "osascript.h"
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <CoreData/CoreData.h>
bool ffOsascript(const char* input, FFstrbuf* result)
{
+465
View File
@@ -0,0 +1,465 @@
#include "smc_temps.h"
#include "common/apple/cf_helpers.h"
#include "common/stringUtils.h"
#include <stdint.h>
#include <IOKit/IOKitLib.h>
static const char kSmcCmdReadBytes = 5;
static const char kSmcCmdReadKeyInfo = 9;
static const uint32_t kKernelIndexSmc = 2;
typedef struct
{
char major;
char minor;
char build;
char reserved[1];
uint16_t release;
} SmcKeyData_vers_t;
typedef struct
{
uint16_t version;
uint16_t length;
uint32_t cpuPLimit;
uint32_t gpuPLimit;
uint32_t memPLimit;
} SmcKeyData_pLimitData_t;
typedef struct
{
uint32_t dataSize;
uint32_t dataType;
char dataAttributes;
} SmcKeyData_keyInfo_t;
typedef unsigned char SmcBytes_t[32];
typedef struct
{
uint32_t key;
SmcKeyData_vers_t vers;
SmcKeyData_pLimitData_t pLimitData;
SmcKeyData_keyInfo_t keyInfo;
char result;
char status;
char data8;
uint32_t data32;
SmcBytes_t bytes;
} SmcKeyData_t;
typedef char UInt32Char_t[5];
typedef struct
{
UInt32Char_t key;
uint32_t dataSize;
UInt32Char_t dataType;
SmcBytes_t bytes;
} SmcVal_t;
static uint32_t smcStrtoul(const char* str, int size, int base) {
uint32_t total = 0;
for (int i = 0; i < size; i++) {
if (base == 16) {
total += (uint32_t) (str[i] << (size - 1 - i) * 8);
} else {
total += (uint32_t) ((unsigned char) (str[i]) << (size - 1 - i) * 8);
}
}
return total;
}
static void smcUltostr(char* str, uint32_t val) {
str[0] = (char) (val >> 24);
str[1] = (char) (val >> 16);
str[2] = (char) (val >> 8);
str[3] = (char) val;
str[4] = '\0';
}
static const char* smcCall(io_connect_t conn, uint32_t selector, SmcKeyData_t* inputStructure, SmcKeyData_t* outputStructure) {
size_t size = sizeof(SmcKeyData_t);
if (IOConnectCallStructMethod(conn, selector, inputStructure, size, outputStructure, &size) != kIOReturnSuccess) {
return "IOConnectCallStructMethod(conn) failed";
}
return NULL;
}
// Provides key info, using a cache to dramatically improve the energy impact of smcFanControl
static const char* smcGetKeyInfo(io_connect_t conn, const uint32_t key, SmcKeyData_keyInfo_t* key_info) {
SmcKeyData_t inputStructure = { 0 };
SmcKeyData_t outputStructure = { 0 };
inputStructure.key = key;
inputStructure.data8 = kSmcCmdReadKeyInfo;
const char* error = smcCall(conn, kKernelIndexSmc, &inputStructure, &outputStructure);
if (error) {
return error;
}
*key_info = outputStructure.keyInfo;
return NULL;
}
static const char* smcReadSmcVal(io_connect_t conn, const UInt32Char_t key, SmcVal_t* val) {
SmcKeyData_t inputStructure = { 0 };
SmcKeyData_t outputStructure = { 0 };
inputStructure.key = smcStrtoul(key, 4, 16);
strcpy(val->key, key);
const char* error = smcGetKeyInfo(conn, inputStructure.key, &outputStructure.keyInfo);
if (error) {
return error;
}
val->dataSize = outputStructure.keyInfo.dataSize;
smcUltostr(val->dataType, outputStructure.keyInfo.dataType);
inputStructure.keyInfo.dataSize = val->dataSize;
inputStructure.data8 = kSmcCmdReadBytes;
error = smcCall(conn, kKernelIndexSmc, &inputStructure, &outputStructure);
if (error) {
return error;
}
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
return NULL;
}
static const char* smcOpen(io_connect_t* conn) {
FF_IOOBJECT_AUTO_RELEASE io_object_t device = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceMatching("AppleSMC"));
if (!device) {
return "No SMC device found";
}
if (IOServiceOpen(device, mach_task_self(), 0, conn) != kIOReturnSuccess) {
return "IOServiceOpen() failed";
}
return NULL;
}
static const char* smcReadValue(io_connect_t conn, const UInt32Char_t key, double* value) {
SmcVal_t val = { 0 };
const char* error = smcReadSmcVal(conn, key, &val);
if (error != NULL) {
return error;
}
if (val.dataSize == 0) {
return "Empty SMC result";
}
switch (val.dataType[0]) {
case 'u': // unsigned integer types
if (val.dataType[1] == 'i') {
switch (val.dataSize) {
case 1:
*value = *(uint8_t*) (val.bytes);
break;
case 2:
*value = ntohs(*(uint16_t*) (val.bytes));
break;
case 4:
*value = ntohl(*(uint32_t*) (val.bytes));
break;
case 8:
*value = (double) ntohll(*(uint64_t*) (val.bytes));
break;
default:
return "Unsupported SMC unsigned integer data size";
}
} else {
return "Unsupported SMC unsigned data type";
}
break;
case 'f': // floating point types
if (ffStrEquals(val.dataType, "flt ") && val.dataSize == 4) {
*value = *(float*) (val.bytes);
} else if (val.dataType[1] == 'p' && val.dataSize == 2) // fixed point types
{
if (ffStrEquals(val.dataType, "fp1f")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 32768.0;
} else if (ffStrEquals(val.dataType, "fp4c")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 4096.0;
} else if (ffStrEquals(val.dataType, "fp5b")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 2048.0;
} else if (ffStrEquals(val.dataType, "fp6a")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 1024.0;
} else if (ffStrEquals(val.dataType, "fp79")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 512.0;
} else if (ffStrEquals(val.dataType, "fp88")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 256.0;
} else if (ffStrEquals(val.dataType, "fpa6")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 64.0;
} else if (ffStrEquals(val.dataType, "fpc4")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 16.0;
} else if (ffStrEquals(val.dataType, "fpe2")) {
*value = ntohs(*(uint16_t*) (val.bytes)) / 4.0;
} else {
return "Unsupported SMC floating point data type";
}
} else {
return "Unsupported SMC floating point data type";
}
break;
case 's': // signed integer types
if (val.dataType[1] == 'i') {
switch (val.dataSize) {
case 1:
*value = *(int8_t*) (val.bytes);
break;
case 2:
*value = ntohs(*(int16_t*) (val.bytes));
break;
case 4:
*value = ntohl(*(int32_t*) (val.bytes));
break;
case 8:
*value = (double) ntohll(*(int64_t*) (val.bytes));
break;
default:
return "Unsupported SMC signed integer data size";
}
} else if (val.dataType[1] == 'p' && val.dataSize == 2) // signed fixed point types
{
if (ffStrEquals(val.dataType, "sp1e")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 16384.0;
} else if (ffStrEquals(val.dataType, "sp3c")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 4096.0;
} else if (ffStrEquals(val.dataType, "sp4b")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 2048.0;
} else if (ffStrEquals(val.dataType, "sp5a")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 1024.0;
} else if (ffStrEquals(val.dataType, "sp69")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 512.0;
} else if (ffStrEquals(val.dataType, "sp78")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 256.0;
} else if (ffStrEquals(val.dataType, "sp87")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 128.0;
} else if (ffStrEquals(val.dataType, "sp96")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 64.0;
} else if (ffStrEquals(val.dataType, "spb4")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 16.0;
} else if (ffStrEquals(val.dataType, "spf0")) {
*value = (int16_t) ntohs(*(int16_t*) (val.bytes)) / 1.0;
} else {
return "Unsupported SMC signed integer data type";
}
} else {
return "Unsupported SMC signed data type";
}
break;
case '{': // special types like pwm
if (ffStrEquals(val.dataType, "{pwm") && val.dataSize == 2) {
*value = (double) ntohs(*(uint16_t*) (val.bytes)) * 100 / 65536.0;
} else {
return "Unsupported SMC special data type";
}
break;
default:
return "Unsupported SMC data type";
}
return NULL;
}
static bool detectTemp(io_connect_t conn, const char* sensor, double* sum) {
double temp = 0;
const char* error = smcReadValue(conn, sensor, &temp);
if (error) {
return false;
}
// https://github.com/exelban/stats/blob/14e29c4d60229c363cca9c9d25c30c87b7870830/Modules/Sensors/readers.swift#L124
if (temp < 10 || temp > 120) {
return false;
}
*sum += temp;
return true;
}
static io_connect_t conn;
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result) {
if (!conn) {
if (smcOpen(&conn) != NULL) {
conn = (io_connect_t) -1;
}
}
if (conn == (io_connect_t) -1) {
return "Could not open SMC connection";
}
if (!detectTemp(conn, sensor, result)) {
return "Could not read SMC temperature";
}
return NULL;
}
const char* ffDetectSmcTemps(enum FFTempType type, double* result) {
if (!conn) {
if (smcOpen(&conn) != NULL) {
conn = (io_connect_t) -1;
}
}
if (conn == (io_connect_t) -1) {
return "Could not open SMC connection";
}
uint32_t count = 0;
*result = 0;
// https://github.com/exelban/stats/blob/master/Modules/Sensors/values.swift
switch (type) {
case FF_TEMP_CPU_X64:
count += detectTemp(conn, "TC0D", result); // CPU diode
count += detectTemp(conn, "TC0E", result); // CPU diode virtual
count += detectTemp(conn, "TC0F", result); // CPU diode filtered
count += detectTemp(conn, "TC0P", result); // CPU proximity
break;
case FF_TEMP_CPU_M1X:
count += detectTemp(conn, "Tp09", result); // CPU efficient core 1
count += detectTemp(conn, "Tp0T", result); // CPU efficient core 2
count += detectTemp(conn, "Tp01", result); // CPU performance core 1
count += detectTemp(conn, "Tp05", result); // CPU performance core 2
count += detectTemp(conn, "Tp0D", result); // CPU performance core 3
count += detectTemp(conn, "Tp0H", result); // CPU performance core 4
count += detectTemp(conn, "Tp0L", result); // CPU performance core 5
count += detectTemp(conn, "Tp0P", result); // CPU performance core 6
count += detectTemp(conn, "Tp0X", result); // CPU performance core 7
count += detectTemp(conn, "Tp0b", result); // CPU performance core 8
break;
case FF_TEMP_CPU_M2X:
count += detectTemp(conn, "Tp1h", result); // CPU efficiency core 1
count += detectTemp(conn, "Tp1t", result); // CPU efficiency core 2
count += detectTemp(conn, "Tp1p", result); // CPU efficiency core 3
count += detectTemp(conn, "Tp1l", result); // CPU efficiency core 4
count += detectTemp(conn, "Tp01", result); // CPU performance core 1
count += detectTemp(conn, "Tp05", result); // CPU performance core 2
count += detectTemp(conn, "Tp09", result); // CPU performance core 3
count += detectTemp(conn, "Tp0D", result); // CPU performance core 4
count += detectTemp(conn, "Tp0X", result); // CPU performance core 5
count += detectTemp(conn, "Tp0b", result); // CPU performance core 6
count += detectTemp(conn, "Tp0f", result); // CPU performance core 7
count += detectTemp(conn, "Tp0j", result); // CPU performance core 8
break;
case FF_TEMP_CPU_M3X:
count += detectTemp(conn, "Te05", result); // CPU efficiency core 1
count += detectTemp(conn, "Te0L", result); // CPU efficiency core 2
count += detectTemp(conn, "Te0P", result); // CPU efficiency core 3
count += detectTemp(conn, "Te0S", result); // CPU efficiency core 4
count += detectTemp(conn, "Tf04", result); // CPU performance core 1
count += detectTemp(conn, "Tf09", result); // CPU performance core 2
count += detectTemp(conn, "Tf0A", result); // CPU performance core 3
count += detectTemp(conn, "Tf0B", result); // CPU performance core 4
count += detectTemp(conn, "Tf0D", result); // CPU performance core 5
count += detectTemp(conn, "Tf0E", result); // CPU performance core 6
count += detectTemp(conn, "Tf44", result); // CPU performance core 7
count += detectTemp(conn, "Tf49", result); // CPU performance core 8
count += detectTemp(conn, "Tf4A", result); // CPU performance core 9
count += detectTemp(conn, "Tf4B", result); // CPU performance core 10
count += detectTemp(conn, "Tf4D", result); // CPU performance core 11
count += detectTemp(conn, "Tf4E", result); // CPU performance core 12
break;
case FF_TEMP_CPU_M4X:
count += detectTemp(conn, "Te05", result); // CPU efficiency core 1
count += detectTemp(conn, "Te0S", result); // CPU efficiency core 2
count += detectTemp(conn, "Te09", result); // CPU efficiency core 3
count += detectTemp(conn, "Te0H", result); // CPU efficiency core 4
count += detectTemp(conn, "Tp01", result); // CPU performance core 1
count += detectTemp(conn, "Tp05", result); // CPU performance core 2
count += detectTemp(conn, "Tp09", result); // CPU performance core 3
count += detectTemp(conn, "Tp0D", result); // CPU performance core 4
count += detectTemp(conn, "Tp0V", result); // CPU performance core 5
count += detectTemp(conn, "Tp0Y", result); // CPU performance core 6
count += detectTemp(conn, "Tp0b", result); // CPU performance core 7
count += detectTemp(conn, "Tp0e", result); // CPU performance core 8
break;
case FF_TEMP_GPU_INTEL:
count += detectTemp(conn, "TCGC", result); // GPU Intel Graphics
goto gpu_unknown;
case FF_TEMP_GPU_AMD:
count += detectTemp(conn, "TGDD", result); // GPU AMD Radeon
goto gpu_unknown;
case FF_TEMP_GPU_UNKNOWN: // Nvidia?
gpu_unknown:
count += detectTemp(conn, "TG0D", result); // GPU diode
count += detectTemp(conn, "TG0P", result); // GPU proximity
break;
case FF_TEMP_GPU_M1X:
count += detectTemp(conn, "Tg05", result); // GPU 1
count += detectTemp(conn, "Tg0D", result); // GPU 2
count += detectTemp(conn, "Tg0L", result); // GPU 3
count += detectTemp(conn, "Tg0T", result); // GPU 4
break;
case FF_TEMP_GPU_M2X:
count += detectTemp(conn, "Tg0f", result); // GPU 1
count += detectTemp(conn, "Tg0j", result); // GPU 2
break;
case FF_TEMP_GPU_M3X:
count += detectTemp(conn, "Tf14", result); // GPU 1
count += detectTemp(conn, "Tf18", result); // GPU 2
count += detectTemp(conn, "Tf19", result); // GPU 3
count += detectTemp(conn, "Tf1A", result); // GPU 4
count += detectTemp(conn, "Tf24", result); // GPU 5
count += detectTemp(conn, "Tf28", result); // GPU 6
count += detectTemp(conn, "Tf29", result); // GPU 7
count += detectTemp(conn, "Tf2A", result); // GPU 8
break;
case FF_TEMP_GPU_M4X:
count += detectTemp(conn, "Tg0G", result); // GPU 1 (Basic)
count += detectTemp(conn, "Tg0H", result); // GPU 2 (Basic)
count += detectTemp(conn, "Tg1U", result); // GPU 1 (Pro / Max)
count += detectTemp(conn, "Tg1k", result); // GPU 2 (Pro / Max)
count += detectTemp(conn, "Tg0K", result); // GPU 3
count += detectTemp(conn, "Tg0L", result); // GPU 4
count += detectTemp(conn, "Tg0d", result); // GPU 5
count += detectTemp(conn, "Tg0e", result); // GPU 6
count += detectTemp(conn, "Tg0j", result); // GPU 7
count += detectTemp(conn, "Tg0k", result); // GPU 8
break;
case FF_TEMP_BATTERY:
count += detectTemp(conn, "TB1T", result); // Battery
count += detectTemp(conn, "TB2T", result); // Battery
break;
case FF_TEMP_MEMORY:
count += detectTemp(conn, "Tm02", result); // Memory 1
count += detectTemp(conn, "Tm06", result); // Memory 2
count += detectTemp(conn, "Tm08", result); // Memory 3
count += detectTemp(conn, "Tm09", result); // Memory 4
break;
}
if (count == 0) {
return "No temperatures detected";
}
*result /= count;
return NULL;
}
@@ -2,15 +2,13 @@
#include "fastfetch.h"
typedef struct FFTempValue
{
typedef struct FFTempValue {
FFstrbuf name;
FFstrbuf deviceClass;
double value;
} FFTempValue;
enum FFTempType
{
enum FFTempType {
FF_TEMP_CPU_X64,
FF_TEMP_CPU_M1X,
FF_TEMP_CPU_M2X,
@@ -30,4 +28,5 @@ enum FFTempType
FF_TEMP_MEMORY,
};
const char* ffDetectSmcSpecificTemp(const char* sensor, double* result);
const char* ffDetectSmcTemps(enum FFTempType type, double* result);
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "common/FFstrbuf.h"
// For ffRegReadValue(s)
// If length is 0, data will be allocated with malloc() and must be freed by the caller
// Otherwise, data must point to a buffer of at least length bytes, and the actual length of the data will be written to length.
typedef struct FFArgBuffer {
void* data;
uint32_t length;
} FFArgBuffer;
typedef enum FF_A_PACKED FFArgType {
FF_ARG_TYPE_NULL = 0,
FF_ARG_TYPE_UINT,
FF_ARG_TYPE_UINT64,
FF_ARG_TYPE_UINT16,
FF_ARG_TYPE_UINT8,
FF_ARG_TYPE_INT,
FF_ARG_TYPE_STRING,
FF_ARG_TYPE_STRBUF,
FF_ARG_TYPE_FLOAT,
FF_ARG_TYPE_DOUBLE,
FF_ARG_TYPE_LIST,
FF_ARG_TYPE_BOOL,
FF_ARG_TYPE_BUFFER,
} FFArgType;
#define FF_ARG(variable, var_name) { _Generic((variable), \
uint32_t: FF_ARG_TYPE_UINT, \
uint64_t: FF_ARG_TYPE_UINT64, \
uint16_t: FF_ARG_TYPE_UINT16, \
uint8_t: FF_ARG_TYPE_UINT8, \
int32_t: FF_ARG_TYPE_INT, \
char*: FF_ARG_TYPE_STRING, \
const char*: FF_ARG_TYPE_STRING, \
FFstrbuf: FF_ARG_TYPE_STRBUF, \
float: FF_ARG_TYPE_FLOAT, \
double: FF_ARG_TYPE_DOUBLE, \
FFlist: FF_ARG_TYPE_LIST, \
bool: FF_ARG_TYPE_BOOL, \
FFArgBuffer: FF_ARG_TYPE_BUFFER), \
_Generic((variable), char*: (variable), const char*: (variable), default: &(variable)), \
(var_name) }
@@ -3,7 +3,9 @@
#include <assert.h>
#ifdef __has_builtin
#if __has_builtin(__is_array)
#if !__cplusplus && FF_SUPPORTS_COUNT_OF
#define ARRAY_SIZE(x) _Countof(x)
#elif __has_builtin(__is_array)
#define ARRAY_SIZE(x) ({ static_assert(__is_array(__typeof__(x)), "Must be an array"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
#elif __has_builtin(__builtin_types_compatible_p)
#define ARRAY_SIZE(x) ({ static_assert(!__builtin_types_compatible_p(__typeof__(x), __typeof__(&*(x))), "Must not be a pointer"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifndef __has_attribute
#error Unsupported compiler
#define __attribute__(x)
#endif
#define FF_A_FALLTHROUGH __attribute__((__fallthrough__))
#define FF_A_DEPRECATED __attribute__((__deprecated__))
#define FF_A_CLEANUP(func) __attribute__((__cleanup__(func)))
#define FF_A_NODISCARD __attribute__((__warn_unused_result__))
#define FF_A_PRINTF(formatStrIndex, argsStartIndex) __attribute__((__format__(printf, formatStrIndex, argsStartIndex)))
#define FF_A_SCANF(formatStrIndex, argsStartIndex) __attribute__((__format__(scanf, formatStrIndex, argsStartIndex)))
#define FF_A_NONNULL(argIndex, ...) __attribute__((__nonnull__(argIndex, ##__VA_ARGS__)))
#define FF_A_RETURNS_NONNULL __attribute__((__returns_nonnull__))
#define FF_A_UNUSED __attribute__((__unused__))
#define FF_A_PACKED __attribute__((__packed__))
#define FF_A_WEAK_IMPORT __attribute__((__weak_import__))
+4 -6
View File
@@ -2,9 +2,8 @@
#include "fastfetch.h"
void ffBase64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output);
static inline FFstrbuf ffBase64EncodeStrbuf(const FFstrbuf* in)
{
void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* output);
static inline FFstrbuf ffBase64EncodeStrbuf(const FFstrbuf* in) {
FFstrbuf out = ffStrbufCreateA(10 + in->length * 4 / 3);
ffBase64EncodeRaw(in->length, in->chars, &out.length, out.chars);
assert(out.length < out.allocated);
@@ -12,9 +11,8 @@ static inline FFstrbuf ffBase64EncodeStrbuf(const FFstrbuf* in)
return out;
}
bool ffBase64DecodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output);
static inline FFstrbuf ffBase64DecodeStrbuf(const FFstrbuf* in)
{
bool ffBase64DecodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* output);
static inline FFstrbuf ffBase64DecodeStrbuf(const FFstrbuf* in) {
FFstrbuf out = ffStrbufCreateA(10 + in->length * 3 / 4);
ffBase64DecodeRaw(in->length, in->chars, &out.length, out.chars);
assert(out.length < out.allocated);
-180
View File
@@ -1,180 +0,0 @@
#include "commandoption.h"
#include "common/color.h"
#include "common/printing.h"
#include "common/time.h"
#include "common/jsonconfig.h"
#include "fastfetch_datatext.h"
#include "modules/modules.h"
#include "util/stringUtils.h"
#include <ctype.h>
#include <inttypes.h>
void ffPrepareCommandOption(FFdata* data)
{
//If we don't have a custom structure, use the default one
if(data->structure.length == 0)
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME))
ffPrepareCPUUsage();
if(ffStrbufContainIgnCaseS(&data->structure, FF_DISKIO_MODULE_NAME))
{
__attribute__((__cleanup__(ffDestroyDiskIOOptions))) FFDiskIOOptions options;
ffInitDiskIOOptions(&options);
ffPrepareDiskIO(&options);
}
if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME))
{
__attribute__((__cleanup__(ffDestroyNetIOOptions))) FFNetIOOptions options;
ffInitNetIOOptions(&options);
ffPrepareNetIO(&options);
}
if(instance.config.general.multithreading)
{
if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME))
{
__attribute__((__cleanup__(ffDestroyPublicIpOptions))) FFPublicIPOptions options;
ffInitPublicIpOptions(&options);
ffPreparePublicIp(&options);
}
if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME))
{
__attribute__((__cleanup__(ffDestroyWeatherOptions))) FFWeatherOptions options;
ffInitWeatherOptions(&options);
ffPrepareWeather(&options);
}
}
}
static void genJsonConfig(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
{
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
if (!modules)
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
ffStrbufLowerCase(&type);
if (instance.state.fullConfig)
{
yyjson_mut_val* module = yyjson_mut_obj(doc);
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
if (baseInfo->generateJsonConfig)
baseInfo->generateJsonConfig(options, doc, module);
if (yyjson_mut_obj_size(module) > 1)
yyjson_mut_arr_add_val(modules, module);
else
yyjson_mut_arr_add_strbuf(doc, modules, &type);
}
else
{
yyjson_mut_arr_add_strbuf(doc, modules, &type);
}
}
static void genJsonResult(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* doc)
{
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJsonResult)
baseInfo->generateJsonResult(options, doc, module);
else
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
}
static void parseStructureCommand(
const char* line,
void (*fn)(FFModuleBaseInfo* baseInfo, void* options, yyjson_mut_doc* jsonDoc),
yyjson_mut_doc* jsonDoc
)
{
if(ffCharIsEnglishAlphabet(line[0]))
{
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules)
{
FFModuleBaseInfo* baseInfo = *modules;
if (ffStrEqualsIgnCase(line, baseInfo->name))
{
uint8_t optionBuf[FF_OPTION_MAX_SIZE];
baseInfo->initOptions(optionBuf);
if (__builtin_expect(jsonDoc != NULL, false))
fn(baseInfo, optionBuf, jsonDoc);
else
baseInfo->printModule(optionBuf);
baseInfo->destroyOptions(optionBuf);
return;
}
}
}
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
}
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc)
{
//Parse the structure and call the modules
int32_t thres = instance.config.display.stat;
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
data->structure.chars[colonIndex] = '\0';
double ms = 0;
if(thres >= 0)
ms = ffTimeGetTick();
parseStructureCommand(data->structure.chars + startIndex, genJsonResult, jsonDoc);
if(thres >= 0)
{
ms = ffTimeGetTick() - ms;
if (jsonDoc)
{
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(jsonDoc->root);
yyjson_mut_obj_add_real(jsonDoc, moduleJson, "stat", ms);
}
else
{
char str[64];
int len = snprintf(str, sizeof str, "%.3fms", ms);
if (thres > 0)
snprintf(str, sizeof str, "\e[%sm%.3fms\e[m", (ms <= thres ? FF_COLOR_FG_GREEN : ms <= 2 * thres ? FF_COLOR_FG_YELLOW : FF_COLOR_FG_RED), ms);
printf("\e7\e[1A\e[9999999C\e[%dD%s\e8", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
}
}
#if defined(_WIN32)
if (!jsonDoc && !instance.config.display.noBuffer) fflush(stdout);
#endif
startIndex = colonIndex + 1;
}
}
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc)
{
//If we don't have a custom structure, use the default one
if(data->structure.length == 0)
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
//Parse the structure and call the modules
uint32_t startIndex = 0;
while (startIndex < data->structure.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':');
data->structure.chars[colonIndex] = '\0';
parseStructureCommand(data->structure.chars + startIndex, genJsonConfig, jsonDoc);
startIndex = colonIndex + 1;
}
}
+4 -10
View File
@@ -1,14 +1,8 @@
#pragma once
#include "fastfetch.h"
// Things only needed by fastfetch
typedef struct FFdata
{
FFstrbuf structure;
bool configLoaded;
} FFdata;
#include "common/ffdata.h"
void ffPrepareCommandOption(FFdata* data);
void ffPrintCommandOption(FFdata* data, yyjson_mut_doc* jsonDoc);
void ffMigrateCommandOptionToJsonc(FFdata* data, yyjson_mut_doc* jsonDoc);
void ffPrintCommandOption(FFdata* data);
void ffMigrateCommandOptionToJsonc(FFdata* data);
bool ffParseModuleOptions(const char* key, const char* value);
+16 -14
View File
@@ -1,13 +1,12 @@
#pragma once
#ifdef FF_HAVE_DBUS
#include <dbus/dbus.h>
#include <dbus/dbus.h>
#include "util/FFstrbuf.h"
#include "common/library.h"
#include "common/FFstrbuf.h"
#include "common/library.h"
typedef struct FFDBusLibrary
{
typedef struct FFDBusLibrary {
FF_LIBRARY_SYMBOL(dbus_bus_get)
FF_LIBRARY_SYMBOL(dbus_message_new_method_call)
FF_LIBRARY_SYMBOL(dbus_message_append_args)
@@ -19,26 +18,29 @@ typedef struct FFDBusLibrary
FF_LIBRARY_SYMBOL(dbus_message_iter_next)
FF_LIBRARY_SYMBOL(dbus_message_unref)
FF_LIBRARY_SYMBOL(dbus_connection_send_with_reply_and_block)
FF_LIBRARY_SYMBOL(dbus_connection_unref)
} FFDBusLibrary;
typedef struct FFDBusData
{
typedef struct FFDBusData {
const FFDBusLibrary* lib;
DBusConnection* connection;
} FFDBusData;
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); //Returns an error message or NULL on success
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data); // Returns an error message or NULL on success
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result);
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result);
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result);
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg);
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint64_t* result);
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg1, const char* arg2);
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property);
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result);
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result);
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int64_t* result);
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint64_t* result);
void ffDBusDestroyData(FFDBusData* data);
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface)
{
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface);
static inline DBusMessage* ffDBusGetAllProperties(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface) {
return ffDBusGetMethodReply(dbus, busName, objectPath, "org.freedesktop.DBus.Properties", "GetAll", interface, NULL);
}
#define FF_DBUS_AUTO_DESTROY_DATA FF_A_CLEANUP(ffDBusDestroyData)
#endif // FF_HAVE_DBUS
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include "fastfetch.h"
#include "common/time.h"
static inline const char* ffFindFileName(const char* file) {
const char* lastSlash = __builtin_strrchr(file, '/');
#ifdef _WIN32
if (lastSlash == NULL) {
lastSlash = __builtin_strrchr(file, '\\');
}
#endif
if (lastSlash != NULL) {
return lastSlash + 1;
}
return file;
}
#ifndef NDEBUG
#define FF_DEBUG_PRINT(file_, line_, format_, ...) \
do { \
if (instance.config.display.debugMode) \
fprintf(stderr, "[%s%4d, %s] " format_ "\n", ffFindFileName(file_), line_, ffTimeToTimeStr(ffTimeGetNow()), ##__VA_ARGS__); \
} while (0)
#else
#define FF_DEBUG_PRINT(file_, line_, format_, ...) \
do { \
} while (0)
#endif
#define FF_DEBUG(format, ...) FF_DEBUG_PRINT(__FILE__, __LINE__, format, ##__VA_ARGS__)
#if _WIN32
const char* ffDebugWin32Error(DWORD errorCode);
const char* ffDebugNtStatus(NTSTATUS status);
const char* ffDebugHResult(HRESULT hr);
#endif
+2
View File
@@ -1,3 +1,5 @@
#pragma once
#include "fastfetch.h"
void ffDurationAppendNum(uint64_t totalSeconds, FFstrbuf* result);
@@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include "util/FFstrbuf.h"
#include "common/FFstrbuf.h"
void ffEdidGetVendorAndModel(const uint8_t edid[128], FFstrbuf* result);
bool ffEdidGetName(const uint8_t edid[128], FFstrbuf* name);
@@ -10,3 +10,4 @@ void ffEdidGetPhysicalResolution(const uint8_t edid[128], uint32_t* width, uint3
void ffEdidGetPhysicalSize(const uint8_t edid[128], uint32_t* width, uint32_t* height); // in mm
void ffEdidGetSerialAndManufactureDate(const uint8_t edid[128], uint32_t* serial, uint16_t* year, uint16_t* week);
bool ffEdidGetHdrCompatible(const uint8_t* edid, uint32_t length);
bool ffEdidIsValid(const uint8_t edid[128], uint32_t length);
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include "common/FFstrbuf.h"
typedef enum FF_A_PACKED FFDataResultDocType {
FF_RESULT_DOC_TYPE_DEFAULT = 0,
FF_RESULT_DOC_TYPE_JSON,
FF_RESULT_DOC_TYPE_CONFIG,
FF_RESULT_DOC_TYPE_CONFIG_FULL,
} FFDataResultDocType;
// FFdata aggregates configuration, generation parameters, and output state used by fastfetch.
// It holds the parsed configuration document, a mutable JSON document for results, and related metadata.
typedef struct FFdata {
yyjson_doc* configDoc; // Parsed JSON configuration document
yyjson_mut_doc* resultDoc; // Mutable JSON document for storing results
FFstrbuf structure; // Custom output structure from command line
FFstrbuf structureDisabled; // Disabled modules in the output structure from command line
FFstrbuf genConfigPath; // Path to generate configuration file
FFDataResultDocType docType; // Type of result document
bool configLoaded;
} FFdata;
-221
View File
@@ -1,221 +0,0 @@
#include "fastfetch.h"
#include "common/font.h"
#include <string.h>
#include <ctype.h>
void ffFontInit(FFfont* font)
{
// Ensure no memory allocates
ffStrbufInit(&font->pretty);
ffStrbufInit(&font->name);
ffStrbufInit(&font->size);
ffListInit(&font->styles, sizeof(FFstrbuf));
}
static void strbufAppendNSExcludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude)
{
if(value == NULL || length == 0)
return;
ffStrbufEnsureFree(strbuf, length);
for(uint32_t i = 0; i < length; i++)
{
if(value[i] != exclude)
strbuf->chars[strbuf->length++] = value[i];
}
strbuf->chars[strbuf->length] = '\0';
}
static void fontInitPretty(FFfont* font)
{
ffStrbufAppend(&font->pretty, &font->name);
if(font->size.length == 0 && font->styles.length == 0)
return;
else if(font->pretty.length == 0)
ffStrbufAppendS(&font->pretty, "default");
ffStrbufAppendS(&font->pretty, " (");
if(font->size.length > 0)
{
ffStrbufAppend(&font->pretty, &font->size);
ffStrbufAppendS(&font->pretty, "pt");
if(font->styles.length > 0)
ffStrbufAppendS(&font->pretty, ", ");
}
for(uint32_t i = 0; i < font->styles.length; i++)
{
ffStrbufAppend(&font->pretty, FF_LIST_GET(FFstrbuf, font->styles, i));
if(i < font->styles.length - 1)
ffStrbufAppendS(&font->pretty, ", ");
}
ffStrbufAppendC(&font->pretty, ')');
}
void ffFontInitQt(FFfont* font, const char* data)
{
ffFontInit(font);
//See https://doc.qt.io/qt-5/qfont.html#toString
//Family
data = ffStrbufAppendSUntilC(&font->name, data, ',');
ffStrbufTrim(&font->name, ' ');
if (!data) goto exit;
data++;
//Size
data = ffStrbufAppendSUntilC(&font->size, data, ',');
ffStrbufTrim(&font->size, ' ');
if (!data) goto exit;
data++;
//Style
data = strrchr(data, ',');
if (!data) goto exit;
data++;
if (isalpha(*data))
{
do
{
FFstrbuf* style = (FFstrbuf*) ffListAdd(&font->styles);
ffStrbufInit(style);
data = ffStrbufAppendSUntilC(style, data, ' ');
if (data) data++;
} while (data);
}
exit:
fontInitPretty(font);
}
static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* alternativeBuffer)
{
while(**data == ' ' || **data == '\t' || **data == ',')
++(*data);
const char* wordStart = *data;
while(**data != ' ' && **data != '\t' && **data != ',' && **data != '\0' && **data != '`' && **data != '\\')
++(*data);
uint32_t wordLength = (uint32_t) (*data - wordStart);
if(wordLength == 0)
return;
if(**data == '\0' || **data == '`' || **data == '\\')
{
ffStrbufAppendNS(&font->size, wordLength, wordStart);
if(ffStrbufEndsWithS(&font->size, "px"))
ffStrbufSubstrBefore(&font->size, font->size.length - 2);
double dummy;
if(sscanf(font->size.chars, "%lf", &dummy) == 1)
return;
ffStrbufClear(&font->size);
}
if(
strncasecmp(wordStart, "Ultra", 5) == 0 ||
strncasecmp(wordStart, "Extra", 5) == 0 ||
strncasecmp(wordStart, "Semi", 4) == 0 ||
strncasecmp(wordStart, "Demi", 4) == 0 ||
strncasecmp(wordStart, "Normal", wordLength) == 0 ||
strncasecmp(wordStart, "Roman", wordLength) == 0 ||
strncasecmp(wordStart, "Oblique", wordLength) == 0 ||
strncasecmp(wordStart, "Italic", wordLength) == 0 ||
strncasecmp(wordStart, "Thin", wordLength) == 0 ||
strncasecmp(wordStart, "Light", wordLength) == 0 ||
strncasecmp(wordStart, "Bold", wordLength) == 0 ||
strncasecmp(wordStart, "Black", wordLength) == 0 ||
strncasecmp(wordStart, "Condensed", wordLength) == 0 ||
strncasecmp(wordStart, "Expanded", wordLength) == 0
) {
if(alternativeBuffer == NULL)
{
alternativeBuffer = (FFstrbuf*) ffListAdd(&font->styles);
ffStrbufInit(alternativeBuffer);
}
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
if(
strncasecmp(wordStart, "Ultra ", 6) == 0 ||
strncasecmp(wordStart, "Extra ", 6) == 0 ||
strncasecmp(wordStart, "Semi ", 5) == 0 ||
strncasecmp(wordStart, "Demi ", 5) == 0
) {
fontPangoParseWord(data, font, alternativeBuffer);
}
return;
}
if(alternativeBuffer != NULL)
{
strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-');
return;
}
if(font->name.length > 0)
ffStrbufAppendC(&font->name, ' ');
ffStrbufAppendNS(&font->name, wordLength, wordStart);
}
void ffFontInitPango(FFfont* font, const char* data)
{
ffFontInit(font);
while(*data != '\0' && *data != '`' && *data != '\\')
fontPangoParseWord(&data, font, NULL);
fontInitPretty(font);
}
void ffFontInitValues(FFfont* font, const char* name, const char* size)
{
ffFontInit(font);
ffStrbufAppendS(&font->name, name);
ffStrbufTrim(&font->name, '"');
ffStrbufAppendS(&font->size, size);
fontInitPretty(font);
}
void ffFontInitWithSpace(FFfont* font, const char* rawName)
{
const char* pspace = strrchr(rawName, ' ');
if(pspace == NULL)
{
ffFontInitCopy(font, rawName);
return;
}
ffFontInit(font);
ffStrbufAppendNS(&font->name, (uint32_t)(pspace - rawName), rawName);
ffStrbufAppendS(&font->size, pspace + 1);
fontInitPretty(font);
}
void ffFontDestroy(FFfont* font)
{
ffStrbufDestroy(&font->pretty);
ffStrbufDestroy(&font->name);
ffStrbufDestroy(&font->size);
FF_LIST_FOR_EACH(FFstrbuf, str, font->styles)
ffStrbufDestroy(str);
ffListDestroy(&font->styles);
}
+7 -6
View File
@@ -1,10 +1,9 @@
#pragma once
#include "util/FFstrbuf.h"
#include "util/FFlist.h"
#include "common/FFstrbuf.h"
#include "common/FFlist.h"
typedef struct FFfont
{
typedef struct FFfont {
FFstrbuf pretty;
FFstrbuf name;
FFstrbuf size;
@@ -15,10 +14,12 @@ void ffFontInit(FFfont* font);
void ffFontInitQt(FFfont* font, const char* data);
void ffFontInitPango(FFfont* font, const char* data);
void ffFontInitValues(FFfont* font, const char* name, const char* size);
void ffFontInitXlfd(FFfont* font, const char* xlfd);
void ffFontInitXft(FFfont* font, const char* xft);
void ffFontInitMoveValues(FFfont* font, FFstrbuf* name, FFstrbuf* size, FFstrbuf* style);
void ffFontInitWithSpace(FFfont* font, const char* rawName);
void ffFontDestroy(FFfont* font);
static inline void ffFontInitCopy(FFfont* font, const char* name)
{
static inline void ffFontInitCopy(FFfont* font, const char* name) {
ffFontInitValues(font, name, NULL);
}
+3 -35
View File
@@ -1,41 +1,9 @@
#pragma once
#include "util/FFstrbuf.h"
#include "common/argType.h"
typedef enum __attribute__((__packed__)) FFformatArgType
{
FF_FORMAT_ARG_TYPE_NULL = 0,
FF_FORMAT_ARG_TYPE_UINT,
FF_FORMAT_ARG_TYPE_UINT64,
FF_FORMAT_ARG_TYPE_UINT16,
FF_FORMAT_ARG_TYPE_UINT8,
FF_FORMAT_ARG_TYPE_INT,
FF_FORMAT_ARG_TYPE_STRING,
FF_FORMAT_ARG_TYPE_STRBUF,
FF_FORMAT_ARG_TYPE_FLOAT,
FF_FORMAT_ARG_TYPE_DOUBLE,
FF_FORMAT_ARG_TYPE_LIST,
FF_FORMAT_ARG_TYPE_BOOL
} FFformatArgType;
#define FF_FORMAT_ARG(variable, var_name) { _Generic((variable), \
uint32_t: FF_FORMAT_ARG_TYPE_UINT, \
uint64_t: FF_FORMAT_ARG_TYPE_UINT64, \
uint16_t: FF_FORMAT_ARG_TYPE_UINT16, \
uint8_t: FF_FORMAT_ARG_TYPE_UINT8, \
int32_t: FF_FORMAT_ARG_TYPE_INT, \
char*: FF_FORMAT_ARG_TYPE_STRING, \
const char*: FF_FORMAT_ARG_TYPE_STRING, \
FFstrbuf: FF_FORMAT_ARG_TYPE_STRBUF, \
float: FF_FORMAT_ARG_TYPE_FLOAT, \
double: FF_FORMAT_ARG_TYPE_DOUBLE, \
FFlist: FF_FORMAT_ARG_TYPE_LIST, \
bool: FF_FORMAT_ARG_TYPE_BOOL \
), _Generic((variable), char*: (variable), const char*: (variable), default: &(variable) ), (var_name) }
typedef struct FFformatarg
{
FFformatArgType type;
typedef struct FFformatarg {
FFArgType type;
const void* value;
const char* name; // argument name, must start with an alphabet
} FFformatarg;
-25
View File
@@ -1,25 +0,0 @@
#include "frequency.h"
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result)
{
if (mhz == 0)
return false;
const FFOptionsDisplay* options = &instance.config.display;
bool spaceBeforeUnit = options->freqSpaceBeforeUnit != FF_SPACE_BEFORE_UNIT_NEVER;
int8_t ndigits = options->freqNdigits;
if (ndigits >= 0)
{
ffStrbufAppendDouble(result, mhz / 1000., ndigits);
if (spaceBeforeUnit) ffStrbufAppendC(result, ' ');
ffStrbufAppendS(result, "GHz");
}
else
{
ffStrbufAppendUInt(result, mhz);
if (spaceBeforeUnit) ffStrbufAppendC(result, ' ');
ffStrbufAppendS(result, "MHz");
}
return true;
}
+2
View File
@@ -1,3 +1,5 @@
#pragma once
#include "fastfetch.h"
bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result);
@@ -5,20 +5,22 @@ extern "C" {
#include <File.h>
#include <AppFileInfo.h>
bool ffGetFileVersion(const char* filePath, FFstrbuf* version)
{
bool ffGetFileVersion(const char* filePath, FFstrbuf* version) {
BFile f(filePath, B_READ_ONLY);
if (f.InitCheck() != B_OK)
if (f.InitCheck() != B_OK) {
return false;
}
BAppFileInfo fileInfo(&f);
if (f.InitCheck() != B_OK)
if (f.InitCheck() != B_OK) {
return false;
}
version_info info;
if (fileInfo.GetVersionInfo(&info, B_SYSTEM_VERSION_KIND) != B_OK)
if (fileInfo.GetVersionInfo(&info, B_SYSTEM_VERSION_KIND) != B_OK) {
return false;
}
ffStrbufSetF(version, "%d.%d.%d", (int)info.major, (int)info.middle, (int)info.minor);
ffStrbufSetF(version, "%d.%d.%d", (int) info.major, (int) info.middle, (int) info.minor);
return true;
}
@@ -1,3 +1,3 @@
#include "util/FFstrbuf.h"
#include "common/FFstrbuf.h"
bool ffGetFileVersion(const char* filePath, FFstrbuf* version);
@@ -1,81 +1,94 @@
#include "FFPlatform_private.h"
#include "util/stringUtils.h"
#include "common/io/io.h"
#include "common/stringUtils.h"
#include "common/io.h"
#include "detection/version/version.h"
void ffPlatformInit(FFPlatform* platform)
{
void ffPlatformInit(FFPlatform* platform) {
ffStrbufInit(&platform->homeDir);
ffStrbufInit(&platform->cacheDir);
ffListInit(&platform->configDirs, sizeof(FFstrbuf));
ffListInit(&platform->dataDirs, sizeof(FFstrbuf));
ffListInit(&platform->configDirs);
ffListInit(&platform->dataDirs);
ffStrbufInit(&platform->exePath);
ffStrbufInit(&platform->cwd);
ffStrbufInit(&platform->userName);
ffStrbufInit(&platform->fullUserName);
ffStrbufInit(&platform->hostName);
ffStrbufInit(&platform->userShell);
#ifdef _WIN32
ffStrbufInit(&platform->sid);
#endif
FFPlatformSysinfo* info = &platform->sysinfo;
ffStrbufInit(&info->name);
ffStrbufInit(&info->release);
ffStrbufInit(&info->version);
ffStrbufInit(&info->architecture);
info->pageSize = 0;
ffPlatformInitImpl(platform);
if(info->name.length == 0)
if (info->name.length == 0) {
ffStrbufSetStatic(&info->name, ffVersionResult.sysName);
}
if(info->architecture.length == 0)
if (info->architecture.length == 0) {
ffStrbufSetStatic(&info->architecture, ffVersionResult.architecture);
}
}
void ffPlatformDestroy(FFPlatform* platform)
{
void ffPlatformDestroy(FFPlatform* platform) {
ffStrbufDestroy(&platform->homeDir);
ffStrbufDestroy(&platform->cacheDir);
FF_LIST_FOR_EACH(FFstrbuf, dir, platform->configDirs)
FF_LIST_FOR_EACH (FFstrbuf, dir, platform->configDirs) {
ffStrbufDestroy(dir);
}
ffListDestroy(&platform->configDirs);
FF_LIST_FOR_EACH(FFstrbuf, dir, platform->dataDirs)
FF_LIST_FOR_EACH (FFstrbuf, dir, platform->dataDirs) {
ffStrbufDestroy(dir);
}
ffListDestroy(&platform->dataDirs);
ffStrbufDestroy(&platform->exePath);
ffStrbufDestroy(&platform->cwd);
ffStrbufDestroy(&platform->userName);
ffStrbufDestroy(&platform->hostName);
ffStrbufDestroy(&platform->userShell);
ffStrbufDestroy(&platform->fullUserName);
#ifdef _WIN32
ffStrbufDestroy(&platform->sid);
#endif
FFPlatformSysinfo* info = &platform->sysinfo;
ffStrbufDestroy(&info->architecture);
ffStrbufDestroy(&info->name);
ffStrbufDestroy(&info->release);
ffStrbufDestroy(&info->version);
ffStrbufDestroy(&info->displayVersion);
}
void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path)
{
if (!ffPathExists(path, FF_PATHTYPE_DIRECTORY))
void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path) {
if (!ffPathExists(path, FF_PATHTYPE_DIRECTORY)) {
return;
}
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateS(path);
ffStrbufEnsureEndsWithC(&buffer, '/');
if (!ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
if (!FF_LIST_CONTAINS(*dirs, &buffer, ffStrbufEqual)) {
ffStrbufInitMove(FF_LIST_ADD(FFstrbuf, *dirs), &buffer);
}
}
void ffPlatformPathAddHome(FFlist* dirs, const FFPlatform* platform, const char* suffix)
{
void ffPlatformPathAddHome(FFlist* dirs, const FFPlatform* platform, const char* suffix) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateA(64);
ffStrbufAppend(&buffer, &platform->homeDir);
ffStrbufAppendS(&buffer, suffix);
ffStrbufEnsureEndsWithC(&buffer, '/');
if (ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY) && !ffListContains(dirs, &buffer, (void*) ffStrbufEqual))
ffStrbufInitMove((FFstrbuf*) ffListAdd(dirs), &buffer);
if (ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY) && !FF_LIST_CONTAINS(*dirs, &buffer, ffStrbufEqual)) {
ffStrbufInitMove(FF_LIST_ADD(FFstrbuf, *dirs), &buffer);
}
}
@@ -1,6 +1,6 @@
#pragma once
#include "FFPlatform.h"
#include "common/FFPlatform.h"
void ffPlatformInitImpl(FFPlatform* platform);
+321
View File
@@ -0,0 +1,321 @@
#include "FFPlatform_private.h"
#include "common/FFstrbuf.h"
#include "common/arrayUtils.h"
#include "common/stringUtils.h"
#include "common/io.h"
#include "fastfetch_config.h"
#include <unistd.h>
#include <pwd.h>
#include <limits.h>
#include <sys/utsname.h>
#include <paths.h>
#ifdef __APPLE__
#include <mach-o/dyld.h>
#include <sys/sysctl.h>
#elif defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/sysctl.h>
#elif defined(__OpenBSD__)
#include <sys/sysctl.h>
#include <sys/stat.h>
#include <kvm.h>
#include "common/path.h"
#elif defined(__HAIKU__)
#include <image.h>
#include <OS.h>
#endif
static void getExePath(FFPlatform* platform) {
char exePath[PATH_MAX];
#if defined(__linux__) || defined(__GNU__)
ssize_t exePathLen = readlink("/proc/self/exe", exePath, sizeof(exePath) - 1);
if (exePathLen >= 0) {
exePath[exePathLen] = '\0';
}
#elif defined(__APPLE__)
uint32_t exePathLen = sizeof(exePath);
if (_NSGetExecutablePath(exePath, &exePathLen) == 0) {
exePathLen = (uint32_t) strlen(exePath);
} else {
exePathLen = 0;
}
#elif defined(__FreeBSD__) || defined(__NetBSD__)
size_t exePathLen = sizeof(exePath);
if (sysctl(
(int[]) { CTL_KERN,
#ifdef __FreeBSD__
KERN_PROC,
KERN_PROC_PATHNAME,
(pid_t) platform->pid
#else
KERN_PROC_ARGS,
(pid_t) platform->pid,
KERN_PROC_PATHNAME
#endif
},
4,
exePath,
&exePathLen,
NULL,
0) < 0)
exePathLen = 0;
else {
exePathLen--; // remove terminating NUL
}
#elif defined(__OpenBSD__)
// OpenBSD doesn't have a reliable way to get the executable path.
// Current implementation uses argv[0], which can be easily spoofed.
// See #2195
size_t exePathLen = 0;
kvm_t* kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
if (kd) {
int kpCount;
struct kinfo_proc* kp = kvm_getprocs(kd, KERN_PROC_PID, (pid_t) platform->pid, sizeof(*kp), &kpCount);
if (kp && kpCount == 1) {
char** argv = kvm_getargv(kd, kp, 0);
if (argv && argv[0]) {
char* arg0 = argv[0];
if (arg0[0]) {
if (strchr(arg0, '/') != NULL) // likely a path (absolute or relative)
{
exePathLen = strlen(arg0);
if (exePathLen < ARRAY_SIZE(exePath)) {
memcpy(exePath, arg0, exePathLen);
exePath[exePathLen] = '\0';
} else {
exePathLen = 0;
}
} else {
FF_STRBUF_AUTO_DESTROY tmpPath = ffStrbufCreate();
if (ffFindExecutableInPath(arg0, &tmpPath) == NULL && tmpPath.length < ARRAY_SIZE(exePath)) {
memcpy(exePath, tmpPath.chars, tmpPath.length + 1);
exePathLen = tmpPath.length;
}
}
if (exePathLen > 0) {
struct stat st;
if (stat(exePath, &st) == 0 && S_ISREG(st.st_mode)) {
int cntp;
struct kinfo_file* kf = kvm_getfiles(kd, KERN_FILE_BYPID, (pid_t) platform->pid, sizeof(*kf), &cntp);
if (kf) {
int i;
for (i = 0; i < cntp; i++) {
if (kf[i].fd_fd == KERN_FILE_TEXT) {
// KERN_FILE_TEXT is the executable file, not a shared library, and should be unique in the list.
if (st.st_dev != (dev_t) kf[i].va_fsid || st.st_ino != (ino_t) kf[i].va_fileid) {
i = -1;
}
break;
}
}
if (i < 0) {
exePathLen = 0;
}
} else {
// If we can't get the list of open files, we can't verify that the file is actually the executable
// Assume it is
}
} else {
exePathLen = 0;
}
}
}
}
}
kvm_close(kd);
}
#elif defined(__sun)
ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1);
if (exePathLen >= 0) {
exePath[exePathLen] = '\0';
}
#elif defined(__HAIKU__)
size_t exePathLen = 0;
image_info info;
int32 cookie = 0;
while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
if (info.type == B_APP_IMAGE) {
exePathLen = strlcpy(exePath, info.name, sizeof(exePath));
break;
}
}
#endif
if (exePathLen > 0) {
ffStrbufEnsureFree(&platform->exePath, PATH_MAX);
if (realpath(exePath, platform->exePath.chars)) {
ffStrbufRecalculateLength(&platform->exePath);
} else {
ffStrbufSetNS(&platform->exePath, (uint32_t) exePathLen, exePath);
}
}
}
static void platformPathAddEnv(FFlist* dirs, const char* env) {
const char* envValue = getenv(env);
if (!ffStrSet(envValue)) {
return;
}
FF_STRBUF_AUTO_DESTROY value = ffStrbufCreateA(64);
ffStrbufAppendS(&value, envValue);
uint32_t startIndex = 0;
while (startIndex < value.length) {
uint32_t colonIndex = ffStrbufNextIndexC(&value, startIndex, ':');
value.chars[colonIndex] = '\0';
if (!ffStrSet(value.chars + startIndex)) {
startIndex = colonIndex + 1;
continue;
}
ffPlatformPathAddAbsolute(dirs, value.chars + startIndex);
startIndex = colonIndex + 1;
}
}
static void getHomeDir(FFPlatform* platform, const struct passwd* pwd) {
const char* home = pwd ? pwd->pw_dir : getenv("HOME");
ffStrbufAppendS(&platform->homeDir, home);
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
}
static void getCacheDir(FFPlatform* platform) {
const char* cache = getenv("XDG_CACHE_HOME");
if (ffStrSet(cache)) {
ffStrbufAppendS(&platform->cacheDir, cache);
ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
} else {
ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
ffStrbufAppendS(&platform->cacheDir, ".cache/");
}
}
static void getConfigDirs(FFPlatform* platform) {
// Always make sure `${XDG_CONFIG_HOME:-$HOME/.config}` is the first entry
platformPathAddEnv(&platform->configDirs, "XDG_CONFIG_HOME");
ffPlatformPathAddHome(&platform->configDirs, platform, ".config/");
#if defined(__APPLE__)
ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Preferences/");
ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Application Support/");
#endif
#if defined(__HAIKU__)
ffPlatformPathAddHome(&platform->configDirs, platform, "config/settings/");
#endif
ffPlatformPathAddHome(&platform->configDirs, platform, "");
platformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS");
#if !defined(__APPLE__)
ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC "/xdg/");
#endif
ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_ETC "/");
ffPlatformPathAddAbsolute(&platform->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF "/");
}
static void getDataDirs(FFPlatform* platform) {
platformPathAddEnv(&platform->dataDirs, "XDG_DATA_HOME");
ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/");
// Add ${currentExePath}/../share
if (platform->exePath.length > 0) {
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateCopy(&platform->exePath);
ffStrbufSubstrBeforeLastC(&path, '/');
ffStrbufSubstrBeforeLastC(&path, '/');
ffStrbufAppendS(&path, "/share");
ffPlatformPathAddAbsolute(&platform->dataDirs, path.chars);
}
#ifdef __APPLE__
ffPlatformPathAddHome(&platform->dataDirs, platform, "Library/Application Support/");
#endif
ffPlatformPathAddHome(&platform->dataDirs, platform, "");
platformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS");
#ifdef _PATH_LOCALBASE
ffPlatformPathAddAbsolute(&platform->dataDirs, _PATH_LOCALBASE "/share/");
#endif
ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/");
ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/");
}
static void getUserName(FFPlatform* platform, const struct passwd* pwd) {
if (pwd) {
ffStrbufSetS(&platform->userName, pwd->pw_name);
ffStrbufSetS(&platform->fullUserName, pwd->pw_gecos);
ffStrbufTrimSpace(&platform->fullUserName);
} else {
ffStrbufSetS(&platform->userName, getenv("USER"));
}
}
static void getHostName(FFPlatform* platform, const struct utsname* uts) {
ffStrbufAppendS(&platform->hostName, uts->nodename);
}
static void getUserShell(FFPlatform* platform, const struct passwd* pwd) {
const char* shell = getenv("SHELL");
if (!ffStrSet(shell) && pwd) {
shell = pwd->pw_shell;
}
ffStrbufAppendS(&platform->userShell, shell);
}
static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts) {
ffStrbufAppendS(&info->name, uts->sysname);
ffStrbufAppendS(&info->release, uts->release);
ffStrbufAppendS(&info->version, uts->version);
#ifdef __HAIKU__
/* historical reason */
if (ffStrEquals(uts->machine, "BePC")) {
ffStrbufSetStatic(&info->architecture, "i386");
} else
#endif
ffStrbufAppendS(&info->architecture, uts->machine);
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
size_t length = sizeof(info->pageSize);
sysctl((int[]) { CTL_HW, HW_PAGESIZE }, 2, &info->pageSize, &length, NULL, 0);
#else
info->pageSize = (uint32_t) sysconf(_SC_PAGESIZE);
#endif
}
static void getCwd(FFPlatform* platform) {
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
ffStrbufSetS(&platform->cwd, cwd);
ffStrbufEnsureEndsWithC(&platform->cwd, '/');
}
}
void ffPlatformInitImpl(FFPlatform* platform) {
platform->pid = (uint32_t) getpid();
platform->uid = getuid();
struct passwd* pwd = getpwuid(platform->uid);
struct utsname uts;
if (uname(&uts) < 0) {
memset(&uts, 0, sizeof(uts));
}
getExePath(platform);
getCwd(platform);
getHomeDir(platform, pwd);
getCacheDir(platform);
getConfigDirs(platform);
getDataDirs(platform);
getUserName(platform, pwd);
getHostName(platform, &uts);
getUserShell(platform, pwd);
getSysinfo(&platform->sysinfo, &uts);
}
+313
View File
@@ -0,0 +1,313 @@
#include "FFPlatform_private.h"
#include "common/io.h"
#include "common/library.h"
#include "common/stringUtils.h"
#include "common/windows/unicode.h"
#include "common/windows/registry.h"
#include "common/windows/nt.h"
#include <stdalign.h>
#include <windows.h>
#include <shlobj.h>
#include <sddl.h>
#define SECURITY_WIN32 1 // For secext.h
#include <secext.h>
static void getExePath(FFPlatform* platform) {
wchar_t exePathW[MAX_PATH];
FF_AUTO_CLOSE_FD HANDLE hPath = CreateFileW(
ffGetPeb()->ProcessParameters->ImagePathName.Buffer,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hPath != INVALID_HANDLE_VALUE) {
DWORD len = GetFinalPathNameByHandleW(hPath, exePathW, MAX_PATH, FILE_NAME_NORMALIZED);
if (len > 0 && len < MAX_PATH) {
ffStrbufSetNWS(&platform->exePath, len, exePathW);
if (ffStrbufStartsWithS(&platform->exePath, "\\\\?\\")) {
ffStrbufSubstrAfter(&platform->exePath, 3);
}
}
}
if (platform->exePath.length == 0) {
PCUNICODE_STRING imagePathName = &ffGetPeb()->ProcessParameters->ImagePathName;
ffStrbufSetNWS(&platform->exePath, imagePathName->Length / sizeof(wchar_t), imagePathName->Buffer);
}
ffStrbufReplaceAllC(&platform->exePath, '\\', '/');
}
static void getHomeDir(FFPlatform* platform) {
PWSTR pPath = NULL;
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, KF_FLAG_DEFAULT, NULL, &pPath))) {
ffStrbufSetWS(&platform->homeDir, pPath);
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
} else {
ffStrbufSetS(&platform->homeDir, getenv("USERPROFILE"));
ffStrbufReplaceAllC(&platform->homeDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->homeDir, '/');
}
CoTaskMemFree(pPath);
}
static void getCacheDir(FFPlatform* platform) {
PWSTR pPath = NULL;
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_LocalAppData, KF_FLAG_DEFAULT, NULL, &pPath))) {
ffStrbufSetWS(&platform->cacheDir, pPath);
ffStrbufReplaceAllC(&platform->cacheDir, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->cacheDir, '/');
} else {
ffStrbufAppend(&platform->cacheDir, &platform->homeDir);
ffStrbufAppendS(&platform->cacheDir, "AppData/Local/");
}
CoTaskMemFree(pPath);
}
static void platformPathAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId) {
PWSTR pPath = NULL;
if (SUCCEEDED(SHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT, NULL, &pPath))) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateWS(pPath);
CoTaskMemFree(pPath);
ffStrbufReplaceAllC(&buffer, '\\', '/');
ffStrbufEnsureEndsWithC(&buffer, '/');
if (!FF_LIST_CONTAINS(*dirs, &buffer, ffStrbufEqual)) {
ffStrbufInitMove(FF_LIST_ADD(FFstrbuf, *dirs), &buffer);
}
}
}
static void platformPathAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix) {
const char* value = getenv(env);
if (!ffStrSet(value)) {
return;
}
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateA(64);
ffStrbufAppendS(&buffer, value);
ffStrbufReplaceAllC(&buffer, '\\', '/');
ffStrbufEnsureEndsWithC(&buffer, '/');
if (suffix) {
ffStrbufAppendS(&buffer, suffix);
ffStrbufEnsureEndsWithC(&buffer, '/');
}
if (ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY) && !FF_LIST_CONTAINS(*dirs, &buffer, ffStrbufEqual)) {
ffStrbufInitMove(FF_LIST_ADD(FFstrbuf, *dirs), &buffer);
}
}
static void getConfigDirs(FFPlatform* platform) {
if (getenv("MSYSTEM")) {
// We are in MSYS2 / Git Bash
platformPathAddEnvSuffix(&platform->configDirs, "HOME", ".config/");
platformPathAddEnvSuffix(&platform->configDirs, "HOME", NULL);
platformPathAddEnvSuffix(&platform->configDirs, "MINGW_PREFIX", "etc");
}
ffPlatformPathAddHome(&platform->configDirs, platform, ".config/");
platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_ProgramData);
platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_RoamingAppData);
platformPathAddKnownFolder(&platform->configDirs, &FOLDERID_LocalAppData);
ffPlatformPathAddHome(&platform->configDirs, platform, "");
}
static void getDataDirs(FFPlatform* platform) {
if (getenv("MSYSTEM") && getenv("HOME")) {
// We are in MSYS2 / Git Bash
platformPathAddEnvSuffix(&platform->dataDirs, "HOME", ".local/share/");
platformPathAddEnvSuffix(&platform->dataDirs, "HOME", NULL);
platformPathAddEnvSuffix(&platform->dataDirs, "MINGW_PREFIX", "share");
}
ffPlatformPathAddHome(&platform->dataDirs, platform, ".local/share/");
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_ProgramData);
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_RoamingAppData);
platformPathAddKnownFolder(&platform->dataDirs, &FOLDERID_LocalAppData);
ffPlatformPathAddHome(&platform->dataDirs, platform, "");
}
static void getUserName(FFPlatform* platform) {
wchar_t buffer[256];
DWORD size = ARRAY_SIZE(buffer);
if (GetUserNameExW(NameDisplay, buffer, &size)) {
ffStrbufSetWS(&platform->fullUserName, buffer);
}
NTSYSAPI NTSTATUS NTAPI LsaGetUserName(
_Outptr_ PLSA_UNICODE_STRING * UserName,
_Outptr_opt_ PLSA_UNICODE_STRING * DomainName);
PLSA_UNICODE_STRING userName = NULL;
if (NT_SUCCESS(LsaGetUserName(&userName, NULL))) {
ffStrbufSetNWS(&platform->userName, userName->Length / sizeof(wchar_t), userName->Buffer);
RtlFreeUnicodeString(userName); // Required. userName.Buffer is allocated separately
LsaFreeMemory(userName);
} else {
ffStrbufSetS(&platform->userName, getenv("USERNAME"));
}
alignas(TOKEN_USER) char buf[SECURITY_MAX_SID_SIZE + sizeof(TOKEN_USER)];
if (NT_SUCCESS(NtQueryInformationToken(NtCurrentProcessToken(), TokenUser, buf, sizeof(buf), &size))) {
TOKEN_USER* tokenUser = (TOKEN_USER*) buf;
UNICODE_STRING sidString = { .Buffer = buffer, .Length = 0, .MaximumLength = sizeof(buffer) };
if (NT_SUCCESS(RtlConvertSidToUnicodeString(&sidString, tokenUser->User.Sid, FALSE))) {
ffStrbufSetNWS(&platform->sid, sidString.Length / sizeof(wchar_t), sidString.Buffer);
}
}
}
static void getHostName(FFPlatform* platform) {
wchar_t buffer[256];
DWORD len = ARRAY_SIZE(buffer);
if (GetComputerNameExW(ComputerNameDnsHostname, buffer, &len) && len > 0) {
ffStrbufSetNWS(&platform->hostName, len, buffer);
} else {
len = ARRAY_SIZE(buffer);
if (GetComputerNameExW(ComputerNameNetBIOS, buffer, &len) && len > 0) {
ffStrbufSetNWS(&platform->hostName, len, buffer);
}
}
}
static void getUserShell(FFPlatform* platform) {
// Works in MSYS2
const char* userShell = getenv("SHELL");
if (userShell) {
ffStrbufAppendS(&platform->userShell, userShell);
ffStrbufReplaceAllC(&platform->userShell, '\\', '/');
}
}
static const char* detectWine(void) {
const char* __cdecl wine_get_version(void);
void* hntdll = ffLibraryGetModule(L"ntdll.dll");
if (!hntdll) {
return NULL;
}
FF_LIBRARY_LOAD_SYMBOL_LAZY(hntdll, wine_get_version);
if (!ffwine_get_version) {
return NULL;
}
return ffwine_get_version();
}
static void getSystemReleaseAndVersion(FFPlatformSysinfo* info) {
FF_AUTO_CLOSE_FD HANDLE hKey = NULL;
if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL)) {
return;
}
uint32_t ubr = 0;
ffRegReadValues(hKey, 2, (FFRegValueArg[]) {
FF_ARG(ubr, L"UBR"),
FF_ARG(info->version, L"BuildLabEx"),
},
NULL);
PPEB_FULL peb = ffGetPeb();
ffStrbufSetF(&info->release,
"%u.%u.%u.%u",
(unsigned) peb->OSMajorVersion,
(unsigned) peb->OSMinorVersion,
(unsigned) peb->OSBuildNumber,
(unsigned) ubr);
const char* wineVersion = detectWine();
if (wineVersion) {
ffStrbufSetF(&info->name, "Wine_%s", wineVersion);
} else {
ffStrbufSetStatic(&info->name, "WIN32_NT");
}
}
static void getSystemPageSize(FFPlatformSysinfo* info) {
SYSTEM_BASIC_INFORMATION sbi;
if (NT_SUCCESS(NtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL))) {
info->pageSize = sbi.PhysicalPageSize;
} else {
info->pageSize = 4096;
}
}
static void getSystemArchitecture(FFPlatformSysinfo* info) {
SYSTEM_PROCESSOR_INFORMATION spi;
if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorInformation, &spi, sizeof(spi), NULL))) {
switch (spi.ProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
ffStrbufSetStatic(&info->architecture, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA64:
ffStrbufSetStatic(&info->architecture, "ia64");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
switch (spi.ProcessorLevel) {
case 4:
ffStrbufSetStatic(&info->architecture, "i486");
break;
case 5:
ffStrbufSetStatic(&info->architecture, "i586");
break;
case 6:
ffStrbufSetStatic(&info->architecture, "i686");
break;
default:
ffStrbufSetStatic(&info->architecture, "i386");
break;
}
break;
case PROCESSOR_ARCHITECTURE_ARM64:
ffStrbufSetStatic(&info->architecture, "aarch64");
break;
case PROCESSOR_ARCHITECTURE_ARM:
ffStrbufSetStatic(&info->architecture, "arm");
break;
case PROCESSOR_ARCHITECTURE_PPC:
ffStrbufSetStatic(&info->architecture, "ppc");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
ffStrbufSetStatic(&info->architecture, "mips");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
ffStrbufSetStatic(&info->architecture, "alpha");
break;
case PROCESSOR_ARCHITECTURE_ALPHA64:
ffStrbufSetStatic(&info->architecture, "alpha64");
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
ffStrbufSetStatic(&info->architecture, "unknown");
break;
}
}
}
static void getCwd(FFPlatform* platform) {
PCURDIR cwd = &ffGetPeb()->ProcessParameters->CurrentDirectory;
ffStrbufSetNWS(&platform->cwd, cwd->DosPath.Length / sizeof(WCHAR), cwd->DosPath.Buffer);
ffStrbufReplaceAllC(&platform->cwd, '\\', '/');
ffStrbufEnsureEndsWithC(&platform->cwd, '/');
}
void ffPlatformInitImpl(FFPlatform* platform) {
platform->pid = (uint32_t) (uintptr_t) ffGetTeb()->ClientId.UniqueProcess;
getExePath(platform);
getCwd(platform);
getHomeDir(platform);
getCacheDir(platform);
getConfigDirs(platform);
getDataDirs(platform);
getUserName(platform);
getHostName(platform);
getUserShell(platform);
getSystemReleaseAndVersion(&platform->sysinfo);
getSystemArchitecture(&platform->sysinfo);
getSystemPageSize(&platform->sysinfo);
}
+34
View File
@@ -0,0 +1,34 @@
#include "common/FFlist.h"
#include <stdlib.h>
#include <string.h>
void* ffListAdd(FFlist* list, uint32_t elementSize) {
if (list->length == list->capacity) {
ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2);
}
++list->length;
return ffListGet(list, elementSize, list->length - 1);
}
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result) {
if (list->length == 0) {
return false;
}
memcpy(result, list->data, elementSize);
memmove(list->data, list->data + elementSize, (size_t) elementSize * (list->length - 1));
--list->length;
return true;
}
bool ffListPop(FFlist* list, uint32_t elementSize, void* __restrict result) {
if (list->length == 0) {
return false;
}
memcpy(result, ffListGet(list, elementSize, list->length - 1), elementSize);
--list->length;
return true;
}
+929
View File
@@ -0,0 +1,929 @@
#include "common/FFstrbuf.h"
#include "common/mallocHelper.h"
#include "common/stringUtils.h"
#include <ctype.h>
#include <inttypes.h>
#include <math.h>
char* CHAR_NULL_PTR = "";
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate) {
strbuf->allocated = allocate;
if (strbuf->allocated > 0) {
strbuf->chars = (char*) malloc(sizeof(char) * strbuf->allocated);
}
// This will set the length to zero and the null byte.
ffStrbufClear(strbuf);
}
void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments) {
assert(format != NULL);
char* buffer = NULL;
int len = vasprintf(&buffer, format, arguments);
assert(len >= 0);
ffStrbufInitMoveNS(strbuf, (uint32_t) len, buffer);
}
// Takes ownership of `heapStr`. The caller must not free `heapStr` after calling this
// function; the memory will be managed and freed via the associated FFstrbuf.
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr) {
assert(heapStr != NULL);
strbuf->length = length;
size_t allocSize = ffMallocUsableSize(heapStr);
if (allocSize == 0) {
allocSize = length + 1;
} else if (allocSize > UINT32_MAX) {
allocSize = UINT32_MAX;
}
strbuf->allocated = (uint32_t) allocSize;
strbuf->chars = heapStr;
}
void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) {
if (ffStrbufGetFree(strbuf) >= free && !(strbuf->allocated == 0 && strbuf->length > 0)) {
return;
}
uint32_t allocate = strbuf->allocated;
if (allocate < FASTFETCH_STRBUF_DEFAULT_ALLOC) {
allocate = FASTFETCH_STRBUF_DEFAULT_ALLOC;
}
while ((strbuf->length + free + 1) > allocate) { // + 1 for the null byte
allocate *= 2;
}
if (strbuf->allocated == 0) {
char* newbuf = malloc(sizeof(*strbuf->chars) * allocate);
if (strbuf->length == 0) {
*newbuf = '\0';
} else {
memcpy(newbuf, strbuf->chars, strbuf->length + 1);
}
strbuf->chars = newbuf;
} else {
strbuf->chars = realloc(strbuf->chars, sizeof(*strbuf->chars) * allocate);
}
strbuf->allocated = allocate;
}
// Ensure that at least `free` bytes are available in the buffer besides the current length
// for an empty buffer, free + 1 length memory will be allocated(+1 for the NUL)
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) {
uint32_t oldFree = ffStrbufGetFree(strbuf);
if (oldFree >= free && !(strbuf->allocated == 0 && strbuf->length > 0)) {
return;
}
uint32_t newCap = strbuf->allocated + (free - oldFree);
if (strbuf->allocated == 0) {
newCap += strbuf->length + 1;
char* newbuf = malloc(sizeof(*strbuf->chars) * newCap);
if (strbuf->length == 0) {
*newbuf = '\0';
} else {
memcpy(newbuf, strbuf->chars, strbuf->length + 1);
}
strbuf->chars = newbuf;
} else {
strbuf->chars = realloc(strbuf->chars, sizeof(*strbuf->chars) * newCap);
}
strbuf->allocated = newCap;
}
void ffStrbufClear(FFstrbuf* strbuf) {
assert(strbuf != NULL);
if (strbuf->allocated == 0) {
strbuf->chars = CHAR_NULL_PTR;
} else {
strbuf->chars[0] = '\0';
}
strbuf->length = 0;
}
void ffStrbufAppendC(FFstrbuf* strbuf, char c) {
ffStrbufEnsureFree(strbuf, 1);
strbuf->chars[strbuf->length++] = c;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) {
if (num == 0) {
return;
}
ffStrbufEnsureFree(strbuf, num);
memset(&strbuf->chars[strbuf->length], c, num);
strbuf->length += num;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
if (value == NULL || length == 0) {
return;
}
ffStrbufEnsureFree(strbuf, length);
memcpy(&strbuf->chars[strbuf->length], value, length);
strbuf->length += length;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int)) {
if (value == NULL) {
return;
}
// Ensure capacity > 0 or the modification below will fail
uint32_t length = (uint32_t) strlen(value);
if (length == 0) {
return;
}
ffStrbufEnsureFree(strbuf, length);
for (uint32_t i = 0; value[i] != '\0'; i++) {
strbuf->chars[strbuf->length++] = (char) transformFunc(value[i]);
}
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments) {
assert(format != NULL);
va_list copy;
va_copy(copy, arguments);
uint32_t free = ffStrbufGetFree(strbuf);
int written = vsnprintf(strbuf->chars + strbuf->length, strbuf->allocated > 0 ? free + 1 : 0, format, arguments);
if (written > 0 && (uint32_t) written > free) {
ffStrbufEnsureFree(strbuf, (uint32_t) written);
written = vsnprintf(strbuf->chars + strbuf->length, (uint32_t) written + 1, format, copy);
}
va_end(copy);
if (written > 0) {
strbuf->length += (uint32_t) written;
}
}
const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until) {
if (value == NULL) {
return NULL;
}
const char* end = strchr(value, until);
if (end == NULL) {
ffStrbufAppendS(strbuf, value);
} else {
ffStrbufAppendNS(strbuf, (uint32_t) (end - value), value);
}
return end;
}
void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...) {
assert(format != NULL);
va_list arguments;
va_start(arguments, format);
if (strbuf->allocated == 0) {
ffStrbufInitVF(strbuf, format, arguments);
va_end(arguments);
return;
}
ffStrbufClear(strbuf);
ffStrbufAppendVF(strbuf, format, arguments);
va_end(arguments);
}
void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...) {
assert(format != NULL);
va_list arguments;
va_start(arguments, format);
ffStrbufAppendVF(strbuf, format, arguments);
va_end(arguments);
}
void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
if (value == NULL || length == 0) {
return;
}
ffStrbufEnsureFree(strbuf, length);
memmove(strbuf->chars + length, strbuf->chars, strbuf->length + 1); // + 1 for the null byte
memcpy(strbuf->chars, value, length);
strbuf->length += length;
}
void ffStrbufPrependC(FFstrbuf* strbuf, char c) {
ffStrbufEnsureFree(strbuf, 1);
memmove(strbuf->chars + 1, strbuf->chars, strbuf->length + 1); // + 1 for the null byte
strbuf->chars[0] = c;
strbuf->length += 1;
}
void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
assert(strbuf != NULL);
if (length == 0) {
ffStrbufClear(strbuf);
return;
}
assert(value != NULL);
if (strbuf->allocated <= length) {
char* newBuf = malloc(sizeof(char) * (length + 1));
memcpy(newBuf, value, length);
if (strbuf->allocated > 0) {
free(strbuf->chars);
}
strbuf->chars = newBuf;
strbuf->allocated = length + 1;
} else {
memmove(strbuf->chars, value, length);
}
strbuf->length = length;
strbuf->chars[length] = '\0';
}
void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value) {
assert(value && value != strbuf);
if (value->length == 0) {
ffStrbufClear(strbuf);
return;
}
if (value->allocated == 0) // static string
{
if (strbuf->allocated != 0) {
free(strbuf->chars);
strbuf->allocated = 0;
}
strbuf->chars = value->chars;
strbuf->length = value->length;
return;
}
ffStrbufSetNS(strbuf, value->length, value->chars);
}
void ffStrbufTrimLeft(FFstrbuf* strbuf, char c) {
if (strbuf->length == 0) {
return;
}
uint32_t index = 0;
while (index < strbuf->length && strbuf->chars[index] == c) {
++index;
}
if (index == 0) {
return;
}
if (strbuf->allocated == 0) {
// static string
strbuf->length -= index;
strbuf->chars += index;
return;
}
memmove(strbuf->chars, strbuf->chars + index, strbuf->length - index);
strbuf->length -= index;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufTrimRight(FFstrbuf* strbuf, char c) {
if (strbuf->length == 0) {
return;
}
if (!ffStrbufEndsWithC(strbuf, c)) {
return;
}
do {
--strbuf->length;
} while (ffStrbufEndsWithC(strbuf, c));
if (strbuf->allocated == 0) {
// static string
ffStrbufInitNS(strbuf, strbuf->length, strbuf->chars);
return;
}
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufTrimLeftSpace(FFstrbuf* strbuf) {
if (strbuf->length == 0) {
return;
}
uint32_t index = 0;
while (index < strbuf->length && isspace(strbuf->chars[index])) {
++index;
}
if (index == 0) {
return;
}
if (strbuf->allocated == 0) {
// static string
strbuf->length -= index;
strbuf->chars += index;
return;
}
memmove(strbuf->chars, strbuf->chars + index, strbuf->length - index);
strbuf->length -= index;
strbuf->chars[strbuf->length] = '\0';
}
void ffStrbufTrimRightSpace(FFstrbuf* strbuf) {
if (strbuf->length == 0) {
return;
}
if (!ffStrbufEndsWithFn(strbuf, isspace)) {
return;
}
do {
--strbuf->length;
} while (ffStrbufEndsWithFn(strbuf, isspace));
if (strbuf->allocated == 0) {
// static string
ffStrbufInitNS(strbuf, strbuf->length, strbuf->chars);
return;
}
strbuf->chars[strbuf->length] = '\0';
}
bool ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex) {
if (startIndex > strbuf->length || startIndex >= endIndex) {
return false;
}
if (endIndex > strbuf->length) {
ffStrbufSubstrBefore(strbuf, startIndex);
return true;
}
ffStrbufEnsureFree(strbuf, 0);
memmove(strbuf->chars + startIndex, strbuf->chars + endIndex, strbuf->length - endIndex);
strbuf->length -= (endIndex - startIndex);
strbuf->chars[strbuf->length] = '\0';
return true;
}
void ffStrbufRemoveS(FFstrbuf* strbuf, const char* str) {
uint32_t stringLength = (uint32_t) strlen(str);
for (uint32_t i = ffStrbufNextIndexS(strbuf, 0, str); i < strbuf->length; i = ffStrbufNextIndexS(strbuf, i, str)) {
ffStrbufRemoveSubstr(strbuf, i, i + stringLength);
}
}
void ffStrbufRemoveStrings(FFstrbuf* strbuf, uint32_t numStrings, const char* strings[]) {
for (uint32_t i = 0; i < numStrings; i++) {
ffStrbufRemoveS(strbuf, strings[i]);
}
}
uint32_t ffStrbufNextIndexC(const FFstrbuf* strbuf, uint32_t start, char c) {
assert(start <= strbuf->length);
const char* ptr = (const char*) memchr(strbuf->chars + start, c, strbuf->length - start);
return ptr ? (uint32_t) (ptr - strbuf->chars) : strbuf->length;
}
uint32_t ffStrbufNextIndexS(const FFstrbuf* strbuf, uint32_t start, const char* str) {
assert(start <= strbuf->length);
const char* ptr = strstr(strbuf->chars + start, str);
return ptr ? (uint32_t) (ptr - strbuf->chars) : strbuf->length;
}
uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c) {
assert(start <= strbuf->length);
// We need to loop one higher than the actual index, because uint32_t is guaranteed to be >= 0, so this statement would always be true
for (uint32_t i = start + 1; i > 0; i--) {
if (strbuf->chars[i - 1] == c) {
return i - 1;
}
}
return strbuf->length;
}
void ffStrbufReplaceAllC(FFstrbuf* strbuf, char find, char replace) {
if (strbuf->length == 0) {
return;
}
ffStrbufEnsureFree(strbuf, 0);
for (
char* current_pos = memchr(strbuf->chars, find, strbuf->length);
current_pos;
current_pos = memchr(
current_pos + 1,
find,
strbuf->length - (uint32_t) (current_pos + 1 - strbuf->chars))) {
*current_pos = replace;
}
}
bool ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index) {
if (strbuf->length <= index) {
return false;
}
if (strbuf->allocated == 0) {
// static string
if (index < strbuf->length) {
ffStrbufInitNS(strbuf, index, strbuf->chars);
}
return true;
}
strbuf->length = index;
strbuf->chars[strbuf->length] = '\0';
return true;
}
bool ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index) {
if (index >= strbuf->length) {
ffStrbufClear(strbuf);
return true;
}
if (strbuf->allocated == 0) {
// static string
strbuf->length -= index + 1;
strbuf->chars += index + 1;
return true;
}
memmove(strbuf->chars, strbuf->chars + index + 1, strbuf->length - index - 1);
strbuf->length -= (index + 1);
strbuf->chars[strbuf->length] = '\0';
return true;
}
bool ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c) {
uint32_t index = ffStrbufFirstIndexC(strbuf, c);
if (index >= strbuf->length) {
return false;
}
ffStrbufSubstrAfter(strbuf, index);
return true;
}
bool ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str) {
if (*str == '\0') {
return false;
}
uint32_t index = ffStrbufFirstIndexS(strbuf, str) + (uint32_t) strlen(str) - 1; // -1, because firstIndexS is already pointing to str[0], we want to add only the remaining length
if (index >= strbuf->length) {
return false;
}
ffStrbufSubstrAfter(strbuf, index);
return true;
}
bool ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c) {
uint32_t index = ffStrbufLastIndexC(strbuf, c);
if (index >= strbuf->length) {
return false;
}
ffStrbufSubstrAfter(strbuf, index);
return true;
}
bool ffStrbufSubstr(FFstrbuf* strbuf, uint32_t start, uint32_t end) {
if (__builtin_expect(start >= end, false)) {
ffStrbufClear(strbuf);
return false;
}
if (__builtin_expect(start == 0, false)) {
return ffStrbufSubstrBefore(strbuf, end);
}
if (__builtin_expect(end >= strbuf->length, false)) {
return ffStrbufSubstrAfter(strbuf, start - 1);
}
uint32_t len = end - start;
ffStrbufEnsureFixedLengthFree(strbuf, len); // In case of static string
memmove(strbuf->chars, strbuf->chars + start, len);
strbuf->length = len;
strbuf->chars[len] = '\0';
return true;
}
uint32_t ffStrbufCountC(const FFstrbuf* strbuf, char c) {
uint32_t result = 0;
for (uint32_t i = 0; i < strbuf->length; i++) {
if (strbuf->chars[i] == c) {
result++;
}
}
return result;
}
bool ffStrbufRemoveIgnCaseEndS(FFstrbuf* strbuf, const char* end) {
uint32_t endLength = (uint32_t) strlen(end);
if (ffStrbufEndsWithIgnCaseNS(strbuf, endLength, end)) {
ffStrbufSubstrBefore(strbuf, strbuf->length - endLength);
return true;
}
return false;
}
bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c) {
if (ffStrbufEndsWithC(strbuf, c)) {
return false;
}
ffStrbufAppendC(strbuf, c);
return true;
}
void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) {
fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file);
}
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
ffStrbufWriteTo(strbuf, file);
fputc('\n', file);
}
double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) {
char* str_end;
double result = strtod(strbuf->chars, &str_end);
return str_end == strbuf->chars ? defaultValue : result;
}
uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) {
char* str_end;
unsigned long long result = strtoull(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (uint64_t) result;
}
int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) {
char* str_end;
long long result = strtoll(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (int64_t) result;
}
void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value) {
ffStrbufEnsureFree(strbuf, 21); // Required by yyjson_write_number
char* start = strbuf->chars + strbuf->length;
yyjson_val val = {};
unsafe_yyjson_set_sint(&val, value);
char* end = yyjson_write_number(&val, start);
assert(end != NULL);
strbuf->length += (uint32_t) (end - start);
}
void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value) {
ffStrbufEnsureFree(strbuf, 21); // Required by yyjson_write_number
char* start = strbuf->chars + strbuf->length;
yyjson_val val = {};
unsafe_yyjson_set_uint(&val, value);
char* end = yyjson_write_number(&val, start);
assert(end != NULL);
strbuf->length += (uint32_t) (end - start);
}
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision, bool trailingZeros) {
assert(precision <= 15); // yyjson_write_number supports up to 15 digits after the decimal point
ffStrbufEnsureFree(strbuf, 40); // Required by yyjson_write_number
char* start = strbuf->chars + strbuf->length;
if (precision == 0) {
value = round(value);
}
yyjson_val val = {};
unsafe_yyjson_set_double(&val, value);
if (precision > 0) {
unsafe_yyjson_set_fp_to_fixed(&val, precision);
}
// Write at most <precision> digits after the decimal point; doesn't append trailing zeros
char* end = yyjson_write_number(&val, start);
assert(end > start);
strbuf->length += (uint32_t) (end - start);
if (__builtin_expect(value > 1e21 || value < -1e21, false)) {
// If the value is too large, yyjson_write_number will write it in scientific notation
return;
}
if (trailingZeros) {
if (precision > 1) {
for (char* p = end - 1; *p != '.' && p > start; --p) {
--precision;
}
if (precision > 0) {
ffStrbufAppendNC(strbuf, (uint32_t) precision, '0');
}
} else if (precision == 0 || (precision < 0 && end[-1] == '0')) {
goto removeDecimalPoint;
}
} else {
if (end[-1] == '0') {
removeDecimalPoint:
// yyjson always appends ".0" to make it a float point number. We need to remove it
strbuf->length -= 2;
strbuf->chars[strbuf->length] = '\0';
}
}
}
void ffStrbufUpperCase(FFstrbuf* strbuf) {
for (uint32_t i = 0; i < strbuf->length; ++i) {
strbuf->chars[i] = (char) toupper(strbuf->chars[i]);
}
}
void ffStrbufLowerCase(FFstrbuf* strbuf) {
for (uint32_t i = 0; i < strbuf->length; ++i) {
strbuf->chars[i] = (char) tolower(strbuf->chars[i]);
}
}
void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c) {
if (num == 0) {
return;
}
if (index >= strbuf->length) {
index = strbuf->length;
}
ffStrbufEnsureFree(strbuf, num);
memmove(strbuf->chars + index + num, strbuf->chars + index, strbuf->length - index + 1);
memset(&strbuf->chars[index], c, num);
strbuf->length += num;
}
bool ffStrbufGetdelim(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer) {
assert(lineptr && n && buffer);
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
assert(!*lineptr || (*lineptr >= buffer->chars && *lineptr <= buffer->chars + buffer->length));
const char* pBufferEnd = buffer->chars + buffer->length;
if (!*lineptr) {
*lineptr = buffer->chars;
} else {
*lineptr += *n;
if (*lineptr >= pBufferEnd) { // non-empty last line
return false;
}
**lineptr = delimiter;
++*lineptr;
}
if (*lineptr >= pBufferEnd) { // empty last line
return false;
}
size_t remaining = (size_t) (pBufferEnd - *lineptr);
char* ending = memchr(*lineptr, delimiter, remaining);
if (ending) {
*n = (size_t) (ending - *lineptr);
*ending = '\0';
} else {
*n = remaining;
}
return true;
}
void ffStrbufGetdelimRestore(char** lineptr, size_t* n, char delimiter, FFstrbuf* buffer) {
assert(buffer && lineptr && n);
assert(buffer->allocated > 0 || (buffer->allocated == 0 && buffer->length == 0));
assert(!*lineptr || (*lineptr >= buffer->chars && *lineptr <= buffer->chars + buffer->length));
if (!*lineptr) {
return;
}
*lineptr += *n;
if (*lineptr < buffer->chars + buffer->length) {
**lineptr = delimiter;
}
}
bool ffStrbufRemoveDupWhitespaces(FFstrbuf* strbuf) {
if (strbuf->allocated == 0) {
return false; // Doesn't work with static strings
}
bool changed = false;
for (uint32_t i = 0; i < strbuf->length; i++) {
if (strbuf->chars[i] != ' ') {
continue;
}
i++;
uint32_t j = i;
for (; j < strbuf->length && strbuf->chars[j] == ' '; j++);
if (j == i) {
continue;
}
memmove(&strbuf->chars[i], &strbuf->chars[j], strbuf->length - j + 1);
strbuf->length -= j - i;
changed = true;
}
return changed;
}
/// @brief Check if a separated string (comp) contains a substring (strbuf).
/// @param strbuf The substring to check.
/// @param compLength The length of the separated string to check.
/// @param comp The separated string to check.
/// @param separator The separator character.
bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator) {
if (strbuf->length == 0) {
return true;
}
if (compLength == 0) {
return false;
}
for (const char* p = comp; p < comp + compLength;) {
const char* colon = memchr(p, separator, (size_t) (comp + compLength - p));
if (colon == NULL) {
uint32_t remainingLen = (uint32_t) (comp + compLength - p);
return strbuf->length == remainingLen && memcmp(strbuf->chars, p, remainingLen) == 0;
}
uint32_t substrLength = (uint32_t) (colon - p);
if (strbuf->length == substrLength && memcmp(strbuf->chars, p, substrLength) == 0) {
return true;
}
p = colon + 1;
}
return false;
}
/// @brief Case insensitive version of ffStrbufMatchSeparatedNS.
bool ffStrbufMatchSeparatedIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator) {
if (strbuf->length == 0) {
return true;
}
if (compLength == 0) {
return false;
}
for (const char* p = comp; p < comp + compLength;) {
const char* colon = memchr(p, separator, (size_t) (comp + compLength - p));
if (colon == NULL) {
uint32_t remainingLen = (uint32_t) (comp + compLength - p);
return strbuf->length == remainingLen && strncasecmp(strbuf->chars, p, remainingLen) == 0;
}
uint32_t substrLength = (uint32_t) (colon - p);
if (strbuf->length == substrLength && strncasecmp(strbuf->chars, p, substrLength) == 0) {
return true;
}
p = colon + 1;
}
return false;
}
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint) {
if (codepoint <= 0x7F) {
ffStrbufAppendC(strbuf, (char) codepoint);
return 1;
} else if (codepoint <= 0x7FF) {
ffStrbufAppendNS(strbuf, 2, (char[]) { (char) (0xC0 | (codepoint >> 6)), (char) (0x80 | (codepoint & 0x3F)) });
return 2;
} else if (codepoint <= 0xFFFF) {
ffStrbufAppendNS(strbuf, 3, (char[]) { (char) (0xE0 | (codepoint >> 12)), (char) (0x80 | ((codepoint >> 6) & 0x3F)), (char) (0x80 | (codepoint & 0x3F)) });
return 3;
} else if (codepoint <= 0x10FFFF) {
ffStrbufAppendNS(strbuf, 4, (char[]) { (char) (0xF0 | (codepoint >> 18)), (char) (0x80 | ((codepoint >> 12) & 0x3F)), (char) (0x80 | ((codepoint >> 6) & 0x3F)), (char) (0x80 | (codepoint & 0x3F)) });
return 4;
}
ffStrbufAppendS(strbuf, ""); // U+FFFD REPLACEMENT CHARACTER
return 1;
}
/// @brief Check if a separated string (strbuf) contains a substring (comp).
/// @param strbuf The separated to check.
/// @param compLength The length of the separated string to check.
/// @param comp The substring to check.
/// @param separator The separator character.
bool ffStrbufSeparatedContainNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator) {
uint32_t startIndex = 0;
while (startIndex < strbuf->length) {
uint32_t colonIndex = ffStrbufNextIndexC(strbuf, startIndex, separator);
uint32_t folderLength = colonIndex - startIndex;
if (folderLength == compLength && memcmp(strbuf->chars + startIndex, comp, compLength) == 0) {
return true;
}
startIndex = colonIndex + 1;
}
return false;
}
bool ffStrbufSeparatedContainIgnCaseNS(const FFstrbuf* strbuf, uint32_t compLength, const char* comp, char separator) {
uint32_t startIndex = 0;
while (startIndex < strbuf->length) {
uint32_t colonIndex = ffStrbufNextIndexC(strbuf, startIndex, separator);
uint32_t folderLength = colonIndex - startIndex;
if (folderLength == compLength && strncasecmp(strbuf->chars + startIndex, comp, compLength) == 0) {
return true;
}
startIndex = colonIndex + 1;
}
return false;
}
bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf) {
assert(strbuf);
if (strbuf->length < 4) {
return false;
}
// Static string must be converted first.
assert(strbuf->allocated > 0);
bool changed = false;
uint32_t read = 0;
uint32_t write = 0;
while (read < strbuf->length) {
if (
read + 3 < strbuf->length &&
strbuf->chars[read] == '\\' &&
strbuf->chars[read + 1] == 'x') {
int8_t hi = ffHexCharToInt(strbuf->chars[read + 2]);
int8_t lo = ffHexCharToInt(strbuf->chars[read + 3]);
if (hi >= 0 && lo >= 0) {
strbuf->chars[write++] = (char) ((hi << 4) | lo);
read += 4;
changed = true;
continue;
}
}
strbuf->chars[write++] = strbuf->chars[read++];
}
strbuf->length = write;
strbuf->chars[write] = '\0';
return changed;
}
+46 -48
View File
@@ -1,14 +1,12 @@
#include "base64.h"
#include "common/base64.h"
// https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145
void ffBase64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output)
{
void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* output) {
static const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *out = output;
const char *ends = str + (size - size % 3);
while (str != ends)
{
uint32_t n = __builtin_bswap32(*(uint32_t *)str);
char* out = output;
const char* ends = str + (size - size % 3);
while (str != ends) {
uint32_t n = __builtin_bswap32(*(uint32_t*) str);
*out++ = chars[(n >> 26) & 63];
*out++ = chars[(n >> 20) & 63];
*out++ = chars[(n >> 14) & 63];
@@ -16,94 +14,94 @@ void ffBase64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char
str += 3;
}
if (size % 3 == 1)
{
uint64_t n = (uint64_t)*str << 16;
if (size % 3 == 1) {
uint64_t n = (uint64_t) *str << 16;
*out++ = chars[(n >> 18) & 63];
*out++ = chars[(n >> 12) & 63];
*out++ = '=';
*out++ = '=';
}
else if (size % 3 == 2)
{
uint64_t n = (uint64_t)*str++ << 16;
n |= (uint64_t)*str << 8;
} else if (size % 3 == 2) {
uint64_t n = (uint64_t) *str++ << 16;
n |= (uint64_t) *str << 8;
*out++ = chars[(n >> 18) & 63];
*out++ = chars[(n >> 12) & 63];
*out++ = chars[(n >> 6) & 63];
*out++ = '=';
}
*out = '\0';
*out_size = (uint32_t)(out - output);
*out_size = (uint32_t) (out - output);
}
static uint8_t decode_table[256];
void init_decode_table()
{
void init_decode_table() {
uint8_t ch = 0;
do
{
do {
int32_t code = -1;
if (ch >= 'A' && ch <= 'Z')
if (ch >= 'A' && ch <= 'Z') {
code = ch - 0x41;
if (ch >= 'a' && ch <= 'z')
}
if (ch >= 'a' && ch <= 'z') {
code = ch - 0x47;
if (ch >= '0' && ch <= '9')
}
if (ch >= '0' && ch <= '9') {
code = ch + 0x04;
if (ch == '+' || ch == '-')
}
if (ch == '+' || ch == '-') {
code = 0x3E;
if (ch == '/' || ch == '_')
}
if (ch == '/' || ch == '_') {
code = 0x3F;
}
decode_table[ch] = (uint8_t) code;
} while (ch++ < 0xFF);
}
#define next_char(x) uint8_t x = decode_table[(uint8_t) *str++];
bool ffBase64DecodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output)
{
if (*(uint64_t*) decode_table == 0)
bool ffBase64DecodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* output) {
if (*(uint64_t*) decode_table == 0) {
init_decode_table();
}
char *out = output;
while (size > 0 && (str[size - 1] == '\n' || str[size - 1] == '\r' || str[size - 1] == '='))
char* out = output;
while (size > 0 && (str[size - 1] == '\n' || str[size - 1] == '\r' || str[size - 1] == '=')) {
size--;
}
const char *ends = str + size - 4;
while (true)
{
if (str > ends)
const char* ends = str + size - 4;
while (true) {
if (str > ends) {
break;
while (*str == '\n' || *str == '\r')
}
while (*str == '\n' || *str == '\r') {
str++;
}
if (str > ends)
if (str > ends) {
break;
}
next_char(a);
next_char(b);
next_char(c);
next_char(d);
*out++ = (char)(a << 2 | b >> 4);
*out++ = (char)(b << 4 | c >> 2);
*out++ = (char)(c << 6 | d >> 0);
*out++ = (char) (a << 2 | b >> 4);
*out++ = (char) (b << 4 | c >> 2);
*out++ = (char) (c << 6 | d >> 0);
}
uint8_t mod = (uint8_t) (ends - str + 4) % 4;
if (mod == 2)
{
if (mod == 2) {
next_char(a);
next_char(b);
*out++ = (char)(a << 2 | b >> 4);
}
else if (mod == 3)
{
*out++ = (char) (a << 2 | b >> 4);
} else if (mod == 3) {
next_char(a);
next_char(b);
next_char(c);
*out++ = (char)(a << 2 | b >> 4);
*out++ = (char)(b << 4 | c >> 2);
*out++ = (char) (a << 2 | b >> 4);
*out++ = (char) (b << 4 | c >> 2);
}
*out = '\0';
+303
View File
@@ -0,0 +1,303 @@
#include "common/binary.h"
#include "common/io.h"
#include "common/stringUtils.h"
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <mach-o/loader.h>
#include <mach-o/swap.h>
#include <mach-o/fat.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // swap_fat_arch
// Ref: https://github.com/AlexDenisov/segment_dumper/blob/master/main.c
typedef struct {
const uint8_t* data;
size_t length;
} FFMemoryMapping;
static inline void wrapMunmap(FFMemoryMapping* mapping) {
assert(mapping);
if (mapping->data == NULL || mapping->data == MAP_FAILED) {
return;
}
munmap((void*) mapping->data, mapping->length);
}
/**
* Helper function to access data from a memory-mapped file at a specific offset
*/
static inline const void* readData(const FFMemoryMapping* mapping, size_t size, off_t offset) {
if (offset < 0) {
return NULL;
}
size_t start = (size_t) offset;
if (start > mapping->length || size > mapping->length - start) {
return NULL;
}
return mapping->data + start;
}
/**
* Handles a Mach-O section by extracting strings from the __cstring section
*
* @param mapping Memory mapping of the Mach-O object file
* @param name Section name to check
* @param offset Offset of the section in the file
* @param size Size of the section
* @param cb Callback function to process strings
* @param userdata User data for the callback
* @param minLength Minimum string length to extract
*
* @return true to continue processing, false to stop
*/
static bool handleMachSection(const FFMemoryMapping* mapping, const char* name, off_t offset, size_t size, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength) {
if (!ffStrEquals(name, "__cstring")) {
return true;
}
const char* data = readData(mapping, size, offset);
if (!data) {
return true;
}
for (size_t off = 0; off < size; ++off) {
const char* p = data + off;
if (*p == '\0') {
continue;
}
uint32_t len = (uint32_t) strnlen(p, size - off);
if (len < minLength) {
off += len; // Skip short strings
continue;
}
if (*p >= ' ' && *p <= '~') { // Ignore control characters
if (!cb(p, len, userdata)) {
return false;
}
}
off += len;
}
return true;
}
/**
* Processes a Mach-O header (32-bit or 64-bit)
*
* This function parses the load commands in a Mach-O header, looking for
* LC_SEGMENT or LC_SEGMENT_64 commands that contain the __TEXT segment.
* It then processes the sections within that segment to extract strings.
*
* @param mapping Memory mapping of the Mach-O object file
* @param offset Offset of the Mach header in the file
* @param is_64 Whether this is a 64-bit Mach-O header
* @param cb Callback function to process strings
* @param userdata User data for the callback
* @param minLength Minimum string length to extract
*
* @return NULL on success, error message on failure
*/
static const char* dumpMachHeader(const FFMemoryMapping* mapping, off_t offset, bool is_64, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength) {
uint32_t ncmds;
off_t loadCommandsOffset = offset;
if (is_64) {
const struct mach_header_64* header = readData(mapping, sizeof(struct mach_header_64), offset);
if (!header) {
return "read mach header failed";
}
ncmds = header->ncmds;
loadCommandsOffset += sizeof(*header);
} else {
const struct mach_header* header = readData(mapping, sizeof(struct mach_header), offset);
if (!header) {
return "read mach header failed";
}
ncmds = header->ncmds;
loadCommandsOffset += sizeof(*header);
}
off_t commandOffset = loadCommandsOffset;
const struct load_command* cmd = NULL;
for (uint32_t i = 0U; i < ncmds; i++, commandOffset += cmd->cmdsize) {
cmd = readData(mapping, sizeof(*cmd), commandOffset);
if (!cmd) {
break;
}
if (cmd->cmdsize < sizeof(*cmd)) {
break;
}
if (cmd->cmd == LC_SEGMENT_64) {
const struct segment_command_64* segment = readData(mapping, sizeof(struct segment_command_64), commandOffset);
if (!segment) {
continue;
}
if (!ffStrEquals(segment->segname, "__TEXT")) {
continue;
}
for (uint32_t j = 0U; j < segment->nsects; j++) {
off_t sectionOffset = commandOffset + (off_t) sizeof(*segment) + (off_t) (j * sizeof(struct section_64));
const struct section_64* section = readData(mapping, sizeof(struct section_64), sectionOffset);
if (!section) {
continue;
}
if (!handleMachSection(mapping, section->sectname, (off_t) section->offset, (size_t) section->size, cb, userdata, minLength)) {
return NULL;
}
}
} else if (cmd->cmd == LC_SEGMENT) {
const struct segment_command* segment = readData(mapping, sizeof(struct segment_command), commandOffset);
if (!segment) {
continue;
}
if (!ffStrEquals(segment->segname, "__TEXT")) {
continue;
}
for (uint32_t j = 0; j < segment->nsects; j++) {
off_t sectionOffset = commandOffset + (off_t) sizeof(*segment) + (off_t) (j * sizeof(struct section));
const struct section* section = readData(mapping, sizeof(struct section), sectionOffset);
if (!section) {
continue;
}
if (!handleMachSection(mapping, section->sectname, (off_t) section->offset, (size_t) section->size, cb, userdata, minLength)) {
return NULL;
}
}
}
}
return NULL;
}
/**
* Processes a Fat binary header (Universal binary)
*
* This function handles the fat header of a universal binary, which can contain
* multiple Mach-O binaries for different architectures. It extracts and processes
* each embedded Mach-O file.
*
* @param mapping Memory mapping of the universal binary
* @param cb Callback function to process strings
* @param userdata User data for the callback
* @param minLength Minimum string length to extract
*
* @return NULL on success, error message on failure
*/
static const char* dumpFatHeader(const FFMemoryMapping* mapping, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength) {
const struct fat_header* headerRaw = readData(mapping, sizeof(struct fat_header), 0);
if (!headerRaw) {
return "read fat header failed";
}
struct fat_header header = *headerRaw;
bool needSwap = header.magic == FAT_CIGAM || header.magic == FAT_CIGAM_64;
if (needSwap) {
swap_fat_header(&header, NX_UnknownByteOrder);
}
for (uint32_t i = 0U; i < header.nfat_arch; i++) {
off_t machHeaderOffset = 0;
if (header.magic == FAT_MAGIC) {
off_t archOffset = (off_t) sizeof(struct fat_header) + (off_t) (i * sizeof(struct fat_arch));
const struct fat_arch* archRaw = readData(mapping, sizeof(struct fat_arch), archOffset);
if (!archRaw) {
continue;
}
struct fat_arch arch = *archRaw;
if (needSwap) {
swap_fat_arch(&arch, 1, NX_UnknownByteOrder);
}
machHeaderOffset = (off_t) arch.offset;
} else {
off_t archOffset = (off_t) sizeof(struct fat_header) + (off_t) (i * sizeof(struct fat_arch_64));
const struct fat_arch_64* archRaw = readData(mapping, sizeof(struct fat_arch_64), archOffset);
if (!archRaw) {
continue;
}
struct fat_arch_64 arch = *archRaw;
if (needSwap) {
swap_fat_arch_64(&arch, 1, NX_UnknownByteOrder);
}
machHeaderOffset = (off_t) arch.offset;
}
const uint32_t* magic = readData(mapping, sizeof(uint32_t), machHeaderOffset);
if (!magic) {
continue;
}
if (*magic == MH_MAGIC_64 || *magic == MH_MAGIC) {
return dumpMachHeader(mapping, machHeaderOffset, *magic == MH_MAGIC_64, cb, userdata, minLength);
}
}
return "Unsupported fat header";
}
/**
* Extracts string literals from a Mach-O (Apple) binary file
*
* This function supports both single-architecture Mach-O files and
* universal binaries (fat binaries) containing multiple architectures.
* It locates the __cstring section in the __TEXT segment which contains
* the string literals used in the program.
*/
const char* ffBinaryExtractStrings(const char* machoFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength) {
FF_AUTO_CLOSE_FD int fd = open(machoFile, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return "File could not be opened";
}
struct stat st;
if (fstat(fd, &st) != 0 || st.st_size <= 0) {
return "Failed to stat file";
}
FF_A_CLEANUP(wrapMunmap) FFMemoryMapping mapping = {
.data = mmap(NULL, (size_t) st.st_size, PROT_READ, MAP_PRIVATE, fd, 0),
.length = (size_t) st.st_size,
};
if (mapping.data == MAP_FAILED) {
return "mmap failed";
}
// Read the magic number to determine the type of binary
const uint32_t* magic = readData(&mapping, sizeof(uint32_t), 0);
if (!magic) {
return "read magic number failed";
}
// Check for supported formats
// MH_CIGAM and MH_CIGAM_64 seem to be no longer used, as `swap_mach_header` is marked as deprecated.
// However FAT_CIGAM and FAT_CIGAM_64 are still used (/usr/bin/vim).
if (*magic != MH_MAGIC && *magic != MH_MAGIC_64 && *magic != FAT_CIGAM && *magic != FAT_CIGAM_64 && *magic != FAT_MAGIC && *magic != FAT_MAGIC_64) {
return "Unsupported format or big endian mach-o file";
}
// Process either a fat binary or a regular Mach-O binary
if (*magic == FAT_MAGIC || *magic == FAT_MAGIC_64 || *magic == FAT_CIGAM || *magic == FAT_CIGAM_64) {
return dumpFatHeader(&mapping, cb, userdata, minLength);
} else {
return dumpMachHeader(&mapping, 0, *magic == MH_MAGIC_64, cb, userdata, minLength);
}
}
@@ -1,13 +1,13 @@
#include "binary.h"
#include "common/binary.h"
#if defined(FF_HAVE_ELF) || defined(__sun) || (defined(__FreeBSD__) && !defined(__DragonFly__)) || defined(__OpenBSD__) || defined(__NetBSD__)
#include "common/io/io.h"
#include "common/library.h"
#include "util/stringUtils.h"
#include "common/io.h"
#include "common/library.h"
#include "common/stringUtils.h"
#include <libelf.h> // #1254
#include <fcntl.h>
#include <libelf.h> // #1254
#include <fcntl.h>
/**
* Structure to hold dynamically loaded libelf function pointers
@@ -36,15 +36,15 @@ struct FFElfData {
*
* The function supports both 32-bit and 64-bit ELF formats.
*/
const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength)
{
const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength) {
// Initialize libelf if not already done
if (!elfData.inited)
{
if (!elfData.inited) {
elfData.inited = true;
FF_LIBRARY_LOAD(libelf, "dlopen libelf" FF_LIBRARY_EXTENSION " failed", "libelf" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_MESSAGE(libelf, "libelf" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_version)
if (elfData.ffelf_version(EV_CURRENT) == EV_NONE) return "elf_version() failed";
if (elfData.ffelf_version(EV_CURRENT) == EV_NONE) {
return "elf_version() failed";
}
// Load all required libelf functions
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_begin)
@@ -59,56 +59,70 @@ const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* s
libelf = NULL;
}
if (elfData.ffelf_end == NULL)
if (elfData.ffelf_end == NULL) {
return "load libelf failed";
}
// Open the ELF file
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY | O_CLOEXEC);
if (fd < 0) return "open() failed";
if (fd < 0) {
return "open() failed";
}
Elf* elf = elfData.ffelf_begin(fd, ELF_C_READ, NULL);
if (elf == NULL) return "elf_begin() failed";
if (elf == NULL) {
return "elf_begin() failed";
}
// Get the section header string table index
size_t shstrndx = 0;
if (elfData.ffelf_getshdrstrndx(elf, &shstrndx) < 0)
{
if (elfData.ffelf_getshdrstrndx(elf, &shstrndx) < 0) {
elfData.ffelf_end(elf);
return "elf_getshdrstrndx() failed";
}
// Iterate through all sections, looking for .rodata which contains string literals
Elf_Scn* scn = NULL;
while ((scn = elfData.ffelf_nextscn(elf, scn)) != NULL)
{
while ((scn = elfData.ffelf_nextscn(elf, scn)) != NULL) {
// Try 64-bit section header first, then 32-bit if that fails
Elf64_Shdr* shdr64 = elfData.ffelf64_getshdr(scn);
Elf32_Shdr* shdr32 = NULL;
if (shdr64 == NULL)
{
if (shdr64 == NULL) {
shdr32 = elfData.ffelf32_getshdr(scn);
if (shdr32 == NULL) continue;
if (shdr32 == NULL) {
continue;
}
}
// Get the section name and check if it's .rodata
const char* name = elfData.ffelf_strptr(elf, shstrndx, shdr64 ? shdr64->sh_name : shdr32->sh_name);
if (name == NULL || !ffStrEquals(name, ".rodata")) continue;
if (name == NULL || !ffStrEquals(name, ".rodata")) {
continue;
}
// Get the section data
Elf_Data* data = elfData.ffelf_getdata(scn, NULL);
if (data == NULL) continue;
if (data == NULL) {
continue;
}
// Scan the section for string literals
for (size_t off = 0; off < data->d_size; ++off)
{
for (size_t off = 0; off < data->d_size; ++off) {
const char* p = (const char*) data->d_buf + off;
if (*p == '\0') continue;
uint32_t len = (uint32_t) strlen(p);
if (len < minLength) continue;
if (*p == '\0') {
continue;
}
uint32_t len = (uint32_t) strnlen(p, data->d_size - off);
if (len < minLength) {
off += len;
continue;
}
// Only process printable ASCII characters
if (*p >= ' ' && *p <= '~') // Ignore control characters
{
if (!cb(p, len, userdata)) break;
if (!cb(p, len, userdata)) {
break;
}
}
off += len;
}
@@ -125,8 +139,7 @@ const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* s
/**
* Fallback implementation when libelf is not available
*/
const char* ffBinaryExtractStrings(const char* file, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength)
{
const char* ffBinaryExtractStrings(const char* file, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength) {
FF_UNUSED(file, cb, userdata, minLength);
return "Fastfetch was built without libelf support";
}
+71
View File
@@ -0,0 +1,71 @@
#include "common/binary.h"
#include "common/io.h"
#include "common/stringUtils.h"
#include "common/windows/nt.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
/**
* Extracts string literals from a PE (Windows) executable
*
* This function maps the PE file into memory, locates the .rdata section
* (which typically contains string literals), and scans it for valid strings.
* Each string found is passed to the callback function for processing.
*/
const char* ffBinaryExtractStrings(const char* peFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata, uint32_t minLength) {
FF_AUTO_CLOSE_FD HANDLE hFile = CreateFileA(peFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return "CreateFileA() failed";
}
FF_AUTO_CLOSE_FD HANDLE hSection = NULL;
if (!NT_SUCCESS(NtCreateSection(&hSection, SECTION_MAP_READ, NULL, NULL, PAGE_READONLY, SEC_COMMIT, hFile))) {
return "NtCreateSection() failed";
}
PVOID base = NULL;
SIZE_T viewSize = 0;
if (!NT_SUCCESS(NtMapViewOfSection(hSection, NtCurrentProcess(), &base, 0, 0, NULL, &viewSize, ViewUnmap, 0, PAGE_READONLY))) {
return "NtMapViewOfSection() failed";
}
PIMAGE_NT_HEADERS ntHeaders = RtlImageNtHeader(base);
if (!ntHeaders) {
NtUnmapViewOfSection(NtCurrentProcess(), base);
return "RtlImageNtHeader() failed";
}
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i, ++section) {
// Look for initialized data sections with the name ".rdata" which typically contains string literals
if ((section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) && ffStrEquals((const char*) section->Name, ".rdata")) {
uint8_t* data = (uint8_t*) base + section->PointerToRawData;
// Scan the section for string literals
for (size_t off = 0; off < section->SizeOfRawData; ++off) {
const char* p = (const char*) data + off;
if (*p == '\0') {
continue;
}
uint32_t len = (uint32_t) strnlen(p, section->SizeOfRawData - off);
if (len < minLength) {
off += len;
continue;
}
// Only process printable ASCII characters
if (*p >= ' ' && *p <= '~') // Ignore control characters
{
if (!cb(p, len, userdata)) {
break;
}
}
off += len;
}
}
}
NtUnmapViewOfSection(NtCurrentProcess(), base);
return NULL;
}
+251
View File
@@ -0,0 +1,251 @@
#include "common/commandoption.h"
#include "common/color.h"
#include "common/printing.h"
#include "common/time.h"
#include "common/jsonconfig.h"
#include "common/stringUtils.h"
#include "fastfetch_datatext.h"
#include "modules/modules.h"
#include <ctype.h>
#include <inttypes.h>
bool ffParseModuleOptions(const char* key, const char* value) {
if (!ffStrStartsWith(key, "--") || !ffCharIsEnglishAlphabet(key[2])) {
return false;
}
if (value && !*value) {
value = NULL;
}
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(key[2]) - 'A']; *modules; ++modules) {
FFModuleBaseInfo* baseInfo = *modules;
const char* subKey = ffOptionTestPrefix(key, baseInfo->name);
if (subKey != NULL) {
if (subKey[0] == '\0' || subKey[0] == '-') // Key is exactly the module name or has a leading '-'
{
fprintf(stderr, "Error: unknown module key %s\n", key);
exit(477);
}
FF_STRBUF_AUTO_DESTROY moduleName = ffStrbufCreateS(baseInfo->name);
ffStrbufLowerCase(&moduleName);
FF_STRBUF_AUTO_DESTROY jsonKey = ffStrbufCreate();
bool flag = false;
for (const char* p = subKey; *p; ++p) {
if (*p == '-') {
if (flag) {
fprintf(stderr, "Error: invalid double `-` in module key %s\n", key);
exit(477);
}
flag = true;
} else {
if (!isalpha((unsigned char) *p) && !isdigit((unsigned char) *p)) {
fprintf(stderr, "Error: invalid character `%c` in module key %s\n", *p, key);
exit(477);
}
if (flag) {
flag = false;
ffStrbufAppendC(&jsonKey, (char) toupper((unsigned char) *p));
} else {
ffStrbufAppendC(&jsonKey, *p);
}
}
}
fprintf(stderr, "Error: Unsupported module option: %s\n", key);
fputs(" Support of module options has been removed. Please add the flag to the JSON config instead.\n", stderr);
fprintf(stderr, " Example (demonstration only): `{ \"modules\": [ { \"type\": \"%s\", \"%s\": %s%s%s } ] }`\n", moduleName.chars, jsonKey.chars, value ? "\"" : "", value ?: "true", value ? "\"" : "");
fputs(" See <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration> for more information.\n", stderr);
exit(477);
}
}
return false;
}
void ffPrepareCommandOption(FFdata* data) {
char* moduleType = NULL;
size_t moduleLen = 0;
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure)) {
#define FF_IF_MODULE_MATCH(moduleNameConstant) if (moduleLen == strlen(moduleNameConstant) && ffStrEqualsIgnCase(moduleType, moduleNameConstant) && !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':'))
switch (moduleType[0]) {
case 'C':
case 'c':
FF_IF_MODULE_MATCH(FF_CPUUSAGE_MODULE_NAME)
ffPrepareCPUUsage();
break;
case 'D':
case 'd':
FF_IF_MODULE_MATCH(FF_DISKIO_MODULE_NAME) {
FF_A_CLEANUP(ffDestroyDiskIOOptions) FFDiskIOOptions options;
ffInitDiskIOOptions(&options);
ffPrepareDiskIO(&options);
}
break;
case 'N':
case 'n':
FF_IF_MODULE_MATCH(FF_NETIO_MODULE_NAME) {
FF_A_CLEANUP(ffDestroyNetIOOptions) FFNetIOOptions options;
ffInitNetIOOptions(&options);
ffPrepareNetIO(&options);
}
break;
case 'P':
case 'p':
FF_IF_MODULE_MATCH(FF_PUBLICIP_MODULE_NAME) {
FF_A_CLEANUP(ffDestroyPublicIpOptions) FFPublicIPOptions options;
ffInitPublicIpOptions(&options);
ffPreparePublicIp(&options);
}
break;
case 'W':
case 'w':
FF_IF_MODULE_MATCH(FF_WEATHER_MODULE_NAME) {
FF_A_CLEANUP(ffDestroyWeatherOptions) FFWeatherOptions options;
ffInitWeatherOptions(&options);
ffPrepareWeather(&options);
}
break;
}
#undef FF_IF_MODULE_MATCH
}
}
static void genJsonConfig(FFdata* data, FFModuleBaseInfo* baseInfo, void* options) {
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* modules = yyjson_mut_obj_get(doc->root, "modules");
if (!modules) {
modules = yyjson_mut_obj_add_arr(doc, doc->root, "modules");
}
FF_STRBUF_AUTO_DESTROY type = ffStrbufCreateS(baseInfo->name);
ffStrbufLowerCase(&type);
if (data->docType == FF_RESULT_DOC_TYPE_CONFIG_FULL) {
yyjson_mut_val* module = yyjson_mut_obj(doc);
yyjson_mut_obj_add_strbuf(doc, module, "type", &type);
if (baseInfo->generateJsonConfig) {
baseInfo->generateJsonConfig(options, doc, module);
}
if (yyjson_mut_obj_size(module) > 1) {
yyjson_mut_arr_add_val(modules, module);
} else {
yyjson_mut_arr_add_strbuf(doc, modules, &type);
}
} else {
yyjson_mut_arr_add_strbuf(doc, modules, &type);
}
}
static void genJsonResult(FFdata* data, FFModuleBaseInfo* baseInfo, void* options) {
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name);
if (baseInfo->generateJsonResult) {
baseInfo->generateJsonResult(options, doc, module);
} else {
yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format");
}
}
static bool parseStructureCommand(
FFdata* data,
const char* line,
void (*fn)(FFdata*, FFModuleBaseInfo* baseInfo, void* options)) {
if (ffCharIsEnglishAlphabet(line[0])) {
for (FFModuleBaseInfo** modules = ffModuleInfos[toupper(line[0]) - 'A']; *modules; ++modules) {
FFModuleBaseInfo* baseInfo = *modules;
if (ffStrEqualsIgnCase(line, baseInfo->name)) {
uint8_t optionBuf[FF_OPTION_MAX_SIZE];
baseInfo->initOptions(optionBuf);
if (data->resultDoc != NULL) {
fn(data, baseInfo, optionBuf);
} else {
baseInfo->printModule(optionBuf);
}
baseInfo->destroyOptions(optionBuf);
return true;
}
}
}
if (data->resultDoc) {
yyjson_mut_doc* doc = data->resultDoc;
yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root);
yyjson_mut_obj_add_str(doc, module, "type", line);
yyjson_mut_obj_add_str(doc, module, "error", "Unknown module type");
} else {
ffPrintError(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "<no implementation provided>");
}
return false;
}
void ffPrintCommandOption(FFdata* data) {
// Parse the structure and call the modules
int32_t thres = instance.config.display.stat;
char* moduleType = NULL;
size_t moduleLen = 0;
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure)) {
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleType, ':')) {
continue;
}
double ms = 0;
if (thres >= 0) {
ms = ffTimeGetTick();
}
parseStructureCommand(data, moduleType, genJsonResult);
if (thres >= 0) {
ms = ffTimeGetTick() - ms;
if (data->resultDoc) {
yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(data->resultDoc->root);
yyjson_mut_obj_add_real(data->resultDoc, moduleJson, "stat", ms);
} else {
char str[64];
int len = snprintf(str, sizeof str, "%.3fms", ms);
if (thres > 0) {
snprintf(str, sizeof str, "\e[%sm%.3fms\e[m", (ms <= thres ? FF_COLOR_FG_GREEN : ms <= 2 * thres ? FF_COLOR_FG_YELLOW
: FF_COLOR_FG_RED),
ms);
}
printf("\e7\e[1A\e[9999999C\e[%dD%s\e8", len, str); // Save; Up 1; Right 9999999; Left <len>; Print <str>; Load
}
}
#if defined(_WIN32)
if (!data->resultDoc && !instance.config.display.noBuffer) {
fflush(stdout);
}
#endif
}
}
void ffMigrateCommandOptionToJsonc(FFdata* data) {
// If we don't have a custom structure, use the default one
if (data->structure.length == 0) {
ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string
}
char* moduleType = NULL;
size_t moduleLen = 0;
while (ffStrbufGetdelim(&moduleType, &moduleLen, ':', &data->structure)) {
if (ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleType, ':')) {
continue;
}
parseStructureCommand(data, moduleType, genJsonConfig);
}
}
+163 -68
View File
@@ -1,12 +1,11 @@
#include "dbus.h"
#include "common/dbus.h"
#ifdef FF_HAVE_DBUS
#include "common/thread.h"
#include "util/stringUtils.h"
#include "common/thread.h"
#include "common/stringUtils.h"
static bool loadLibSymbols(FFDBusLibrary* lib)
{
static bool loadLibSymbols(FFDBusLibrary* lib) {
FF_LIBRARY_LOAD(dbus, false, "libdbus-1" FF_LIBRARY_EXTENSION, 4);
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_bus_get, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_new_method_call, false)
@@ -19,18 +18,17 @@ static bool loadLibSymbols(FFDBusLibrary* lib)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_iter_next, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_message_unref, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_send_with_reply_and_block, false)
FF_LIBRARY_LOAD_SYMBOL_PTR(dbus, lib, dbus_connection_unref, false)
dbus = NULL; // don't auto dlclose
return true;
}
static const FFDBusLibrary* loadLib(void)
{
static const FFDBusLibrary* loadLib(void) {
static FFDBusLibrary lib;
static bool loaded = false;
static bool loadSuccess = false;
if(!loaded)
{
if (!loaded) {
loaded = true;
loadSuccess = loadLibSymbols(&lib);
}
@@ -38,138 +36,235 @@ static const FFDBusLibrary* loadLib(void)
return loadSuccess ? &lib : NULL;
}
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data)
{
const char* ffDBusLoadData(DBusBusType busType, FFDBusData* data) {
data->lib = loadLib();
if(data->lib == NULL)
if (data->lib == NULL) {
return "Failed to load DBus library";
}
data->connection = data->lib->ffdbus_bus_get(busType, NULL);
if(data->connection == NULL)
if (data->connection == NULL) {
return "Failed to connect to DBus";
}
return NULL;
}
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result)
{
void ffDBusDestroyData(FFDBusData* data) {
if (data->connection != NULL) {
data->lib->ffdbus_connection_unref(data->connection);
data->connection = NULL;
}
}
bool ffDBusGetString(FFDBusData* dbus, DBusMessageIter* iter, FFstrbuf* result) {
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_STRING || argType == DBUS_TYPE_OBJECT_PATH)
{
if (argType == DBUS_TYPE_STRING || argType == DBUS_TYPE_OBJECT_PATH) {
const char* value = NULL;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
if(!ffStrSet(value))
if (!ffStrSet(value)) {
return false;
}
ffStrbufAppendS(result, value);
return true;
}
if (argType == DBUS_TYPE_BYTE)
{
if (argType == DBUS_TYPE_BYTE) {
uint8_t value;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
ffStrbufAppendC(result, (char) value);
return false; // Don't append a comma
return true;
}
if(argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY)
if (argType != DBUS_TYPE_VARIANT && argType != DBUS_TYPE_ARRAY) {
return false;
}
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
if(argType == DBUS_TYPE_VARIANT)
if (argType == DBUS_TYPE_VARIANT) {
return ffDBusGetString(dbus, &subIter, result);
}
//At this point we have an array
// At this point we have an array
int subArgType = dbus->lib->ffdbus_message_iter_get_arg_type(&subIter);
if (subArgType == DBUS_TYPE_INVALID) {
return false;
}
if (subArgType == DBUS_TYPE_BYTE) {
while (true) {
uint8_t value;
dbus->lib->ffdbus_message_iter_get_basic(&subIter, &value);
ffStrbufAppendC(result, (char) value);
if (!dbus->lib->ffdbus_message_iter_next(&subIter)) {
break;
}
}
return true;
}
bool foundAValue = false;
while(true)
{
if(ffDBusGetString(dbus, &subIter, result))
{
while (true) {
if (ffDBusGetString(dbus, &subIter, result)) {
foundAValue = true;
ffStrbufAppendS(result, ", ");
}
if(!dbus->lib->ffdbus_message_iter_next(&subIter))
if (!dbus->lib->ffdbus_message_iter_next(&subIter)) {
break;
else
} else {
continue;
}
}
if(foundAValue)
if (foundAValue) {
ffStrbufSubstrBefore(result, result->length - 2);
}
return foundAValue;
}
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result)
{
bool ffDBusGetBool(FFDBusData* dbus, DBusMessageIter* iter, bool* result) {
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_BOOLEAN)
{
if (argType == DBUS_TYPE_BOOLEAN) {
dbus_bool_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value != 0;
return true;
}
if(argType != DBUS_TYPE_VARIANT)
if (argType != DBUS_TYPE_VARIANT) {
return false;
}
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetBool(dbus, &subIter, result);
}
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint32_t* result)
{
bool ffDBusGetUint(FFDBusData* dbus, DBusMessageIter* iter, uint64_t* result) {
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if(argType == DBUS_TYPE_BYTE)
{
if (argType == DBUS_TYPE_BYTE) {
uint8_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if(argType == DBUS_TYPE_UINT16)
{
if (argType == DBUS_TYPE_UINT16) {
uint16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if(argType == DBUS_TYPE_UINT32)
{
if (argType == DBUS_TYPE_UINT32) {
uint32_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if (argType == DBUS_TYPE_UINT64) {
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
return true;
}
if(argType != DBUS_TYPE_VARIANT)
if (argType != DBUS_TYPE_VARIANT) {
return false;
}
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetUint(dbus, &subIter, result);
}
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg)
{
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
if(message == NULL)
return NULL;
bool ffDBusGetInt(FFDBusData* dbus, DBusMessageIter* iter, int64_t* result) {
int argType = dbus->lib->ffdbus_message_iter_get_arg_type(iter);
if (arg)
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID);
if (argType == DBUS_TYPE_INT16) {
int16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if (argType == DBUS_TYPE_INT32) {
int32_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if (argType == DBUS_TYPE_INT64) {
dbus->lib->ffdbus_message_iter_get_basic(iter, result);
return true;
}
if (argType == DBUS_TYPE_BYTE) {
uint8_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = value;
return true;
}
if (argType == DBUS_TYPE_UINT16) {
uint16_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = (int32_t) value;
return true;
}
if (argType == DBUS_TYPE_UINT32) {
uint32_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
*result = (int32_t) value;
return true;
}
if (argType == DBUS_TYPE_UINT64) {
uint64_t value = 0;
dbus->lib->ffdbus_message_iter_get_basic(iter, &value);
if (value > INT64_MAX) {
return false;
}
*result = (int64_t) value;
return true;
}
if (argType != DBUS_TYPE_VARIANT) {
return false;
}
DBusMessageIter subIter;
dbus->lib->ffdbus_message_iter_recurse(iter, &subIter);
return ffDBusGetInt(dbus, &subIter, result);
}
DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* method, const char* arg1, const char* arg2) {
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, interface, method);
if (message == NULL) {
return NULL;
}
if (arg1) {
if (arg2) {
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg1, DBUS_TYPE_STRING, &arg2, DBUS_TYPE_INVALID);
} else {
dbus->lib->ffdbus_message_append_args(message, DBUS_TYPE_STRING, &arg1, DBUS_TYPE_INVALID);
}
}
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, NULL);
@@ -178,15 +273,17 @@ DBusMessage* ffDBusGetMethodReply(FFDBusData* dbus, const char* busName, const c
return reply;
}
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property)
{
DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property) {
DBusMessage* message = dbus->lib->ffdbus_message_new_method_call(busName, objectPath, "org.freedesktop.DBus.Properties", "Get");
if(message == NULL)
if (message == NULL) {
return NULL;
}
dbus->lib->ffdbus_message_append_args(message,
DBUS_TYPE_STRING, &interface,
DBUS_TYPE_STRING, &property,
DBUS_TYPE_STRING,
&interface,
DBUS_TYPE_STRING,
&property,
DBUS_TYPE_INVALID);
DBusMessage* reply = dbus->lib->ffdbus_connection_send_with_reply_and_block(dbus->connection, message, instance.config.general.processingTimeout, NULL);
@@ -196,15 +293,14 @@ DBusMessage* ffDBusGetProperty(FFDBusData* dbus, const char* busName, const char
return reply;
}
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result)
{
bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, FFstrbuf* result) {
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
if(reply == NULL)
if (reply == NULL) {
return false;
}
DBusMessageIter rootIterator;
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
{
if (!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator)) {
dbus->lib->ffdbus_message_unref(reply);
return false;
}
@@ -216,15 +312,14 @@ bool ffDBusGetPropertyString(FFDBusData* dbus, const char* busName, const char*
return ret;
}
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint32_t* result)
{
bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* objectPath, const char* interface, const char* property, uint64_t* result) {
DBusMessage* reply = ffDBusGetProperty(dbus, busName, objectPath, interface, property);
if(reply == NULL)
if (reply == NULL) {
return false;
}
DBusMessageIter rootIterator;
if(!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator))
{
if (!dbus->lib->ffdbus_message_iter_init(reply, &rootIterator)) {
dbus->lib->ffdbus_message_unref(reply);
return false;
}
@@ -236,4 +331,4 @@ bool ffDBusGetPropertyUint(FFDBusData* dbus, const char* busName, const char* ob
return ret;
}
#endif //FF_HAVE_DBUS
#endif // FF_HAVE_DBUS
+55
View File
@@ -0,0 +1,55 @@
#include "common/debug.h"
#include "common/windows/nt.h"
#include <windows.h>
const char* ffDebugWin32Error(DWORD errorCode) {
static char buffer[512];
wchar_t bufferW[256];
ULONG len = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
(DWORD) errorCode,
0,
bufferW,
ARRAY_SIZE(bufferW),
NULL);
if (len == 0) {
snprintf(buffer, sizeof(buffer), "Unknown error code (%lu)", errorCode);
} else {
// Remove trailing newline
while (len > 0 && (bufferW[len - 1] == '\r' || bufferW[len - 1] == '\n')) {
--len;
}
if (NT_SUCCESS(RtlUnicodeToUTF8N(buffer, sizeof(buffer), &len, bufferW, len * sizeof(wchar_t)))) {
snprintf(buffer + len, sizeof(buffer) - len, " (%lu)", errorCode);
} else {
snprintf(buffer, sizeof(buffer), "Unknown error (%lu)", errorCode);
}
}
return buffer;
}
const char* ffDebugNtStatus(NTSTATUS status) {
return ffDebugWin32Error(RtlNtStatusToDosError(status));
}
static inline DWORD HRESULTToWin32Error(HRESULT hr) {
if (SUCCEEDED(hr)) {
return ERROR_SUCCESS;
}
if (HRESULT_FACILITY(hr) == FACILITY_WIN32) {
return HRESULT_CODE(hr);
}
return ERROR_INTERNAL_ERROR;
}
const char* ffDebugHResult(HRESULT hr) {
return ffDebugWin32Error(HRESULTToWin32Error(hr));
}

Some files were not shown because too many files have changed in this diff Show More