From bfe30eec7941d0ce78a35825b87738a750185dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 17:05:06 +0800 Subject: [PATCH 001/109] Doc: updates changelog [ci skip] --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 598addb3a2..7eab173fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ # 2.67.1 Bugfixes: -* Fixed a `Symbol not found` error when running on macOS 10.15. (Codec, macOS) -* Fixed Alacritty font size never being parsed from the TOML config. (TerminalFont) +* Fixed a `Symbol not found` error when running on macOS 10.15. (#2499, Codec, macOS) +* Fixed Alacritty font size never being parsed from the TOML config. (#2501, TerminalFont) * Fixed bright colors incorrectly being active when the terminal uses a light theme. (#2509, Display) * Fixed Ghostty terminal font detection (TerminalFont) * Now tries to load the config with the `.ghostty` extension. (#2500) From 51f36fa4b46bf594fb8f448f6ed0ffeea078f4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 17:54:36 +0800 Subject: [PATCH 002/109] FFstrbuf: adds comments [ci skip] --- src/common/impl/FFstrbuf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/impl/FFstrbuf.c b/src/common/impl/FFstrbuf.c index 2ed3e9de84..27cb4d66a6 100644 --- a/src/common/impl/FFstrbuf.c +++ b/src/common/impl/FFstrbuf.c @@ -83,6 +83,7 @@ void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free) { // Round up to the next power of 2. // If the value is already a power of 2, it will be rounded up to the next power of 2. + // allocate = __builtin_stdc_bit_ceil(allocate + 1); // Currently generates worse asm code allocate = 1U << (32 - __builtin_clz(allocate)); } From 858d3749f49febf4c3602ff0181411a3d2bdfdc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 18:27:53 +0800 Subject: [PATCH 003/109] FFstrbuf: adds `FF_STRBUF_STATIC` --- src/common/FFstrbuf.h | 2 ++ tests/strbuf.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/common/FFstrbuf.h b/src/common/FFstrbuf.h index e3722ad82d..d84ed35066 100644 --- a/src/common/FFstrbuf.h +++ b/src/common/FFstrbuf.h @@ -8,6 +8,7 @@ #include #include #include "common/memrchr.h" +#include "common/arrutil.h" #ifdef FF_USE_SYSTEM_YYJSON #include @@ -628,3 +629,4 @@ static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) { bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf); #define FF_STRBUF_AUTO_DESTROY [[gnu::cleanup(ffStrbufDestroy)]] FFstrbuf +#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) ARRAY_SIZE(str) - 1, .chars = str } diff --git a/tests/strbuf.c b/tests/strbuf.c index a8e698cafc..d1ca642658 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -23,6 +23,8 @@ int shouldNotBeCalled(int c) { exit(1); } +const FFstrbuf testCreateStatic = FF_STRBUF_STATIC("TEST"); + int main(void) { FFstrbuf strbuf; From 3908c39ce21bb9dbe28d643ed15d31e8f5e01bd7 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 14 Aug 2026 20:38:58 +0800 Subject: [PATCH 004/109] Modules: adds l10n strings --- src/common/option.h | 17 +++++++++++++++++ src/modules/battery/battery.c | 14 ++++++++++++++ src/modules/bios/bios.c | 14 ++++++++++++++ src/modules/bluetooth/bluetooth.c | 14 ++++++++++++++ src/modules/bluetoothradio/bluetoothradio.c | 14 ++++++++++++++ src/modules/board/board.c | 14 ++++++++++++++ src/modules/bootmgr/bootmgr.c | 14 ++++++++++++++ src/modules/break/break.c | 14 ++++++++++++++ src/modules/brightness/brightness.c | 14 ++++++++++++++ src/modules/btrfs/btrfs.c | 14 ++++++++++++++ src/modules/camera/camera.c | 14 ++++++++++++++ src/modules/chassis/chassis.c | 14 ++++++++++++++ src/modules/codec/codec.c | 14 ++++++++++++++ src/modules/colors/colors.c | 14 ++++++++++++++ src/modules/command/command.c | 14 ++++++++++++++ src/modules/cpu/cpu.c | 14 ++++++++++++++ src/modules/cpucache/cpucache.c | 14 ++++++++++++++ src/modules/cpuusage/cpuusage.c | 14 ++++++++++++++ src/modules/cursor/cursor.c | 14 ++++++++++++++ src/modules/custom/custom.c | 14 ++++++++++++++ src/modules/datetime/datetime.c | 14 ++++++++++++++ src/modules/de/de.c | 14 ++++++++++++++ src/modules/disk/disk.c | 14 ++++++++++++++ src/modules/diskio/diskio.c | 14 ++++++++++++++ src/modules/display/display.c | 14 ++++++++++++++ src/modules/dns/dns.c | 14 ++++++++++++++ src/modules/editor/editor.c | 14 ++++++++++++++ src/modules/font/font.c | 14 ++++++++++++++ src/modules/gamepad/gamepad.c | 14 ++++++++++++++ src/modules/gpu/gpu.c | 14 ++++++++++++++ src/modules/host/host.c | 14 ++++++++++++++ src/modules/icons/icons.c | 14 ++++++++++++++ src/modules/initsystem/initsystem.c | 14 ++++++++++++++ src/modules/kernel/kernel.c | 14 ++++++++++++++ src/modules/keyboard/keyboard.c | 14 ++++++++++++++ src/modules/lm/lm.c | 14 ++++++++++++++ src/modules/loadavg/loadavg.c | 14 ++++++++++++++ src/modules/locale/locale.c | 14 ++++++++++++++ src/modules/localip/localip.c | 14 ++++++++++++++ src/modules/logo/logo.c | 14 ++++++++++++++ src/modules/media/media.c | 14 ++++++++++++++ src/modules/memory/memory.c | 14 ++++++++++++++ src/modules/monitor/monitor.c | 14 ++++++++++++++ src/modules/mouse/mouse.c | 14 ++++++++++++++ src/modules/netio/netio.c | 14 ++++++++++++++ src/modules/opencl/opencl.c | 14 ++++++++++++++ src/modules/opengl/opengl.c | 14 ++++++++++++++ src/modules/os/os.c | 14 ++++++++++++++ src/modules/packages/packages.c | 14 ++++++++++++++ src/modules/physicaldisk/physicaldisk.c | 14 ++++++++++++++ src/modules/physicalmemory/physicalmemory.c | 14 ++++++++++++++ src/modules/player/player.c | 14 ++++++++++++++ src/modules/poweradapter/poweradapter.c | 14 ++++++++++++++ src/modules/processes/processes.c | 14 ++++++++++++++ src/modules/publicip/publicip.c | 14 ++++++++++++++ src/modules/separator/separator.c | 14 ++++++++++++++ src/modules/shell/shell.c | 14 ++++++++++++++ src/modules/sound/sound.c | 14 ++++++++++++++ src/modules/swap/swap.c | 14 ++++++++++++++ src/modules/terminal/terminal.c | 14 ++++++++++++++ src/modules/terminalfont/terminalfont.c | 14 ++++++++++++++ src/modules/terminalsize/terminalsize.c | 14 ++++++++++++++ src/modules/terminaltheme/terminaltheme.c | 14 ++++++++++++++ src/modules/theme/theme.c | 14 ++++++++++++++ src/modules/title/title.c | 14 ++++++++++++++ src/modules/tpm/tpm.c | 14 ++++++++++++++ src/modules/uptime/uptime.c | 14 ++++++++++++++ src/modules/users/users.c | 14 ++++++++++++++ src/modules/version/version.c | 14 ++++++++++++++ src/modules/vulkan/vulkan.c | 14 ++++++++++++++ src/modules/wallpaper/wallpaper.c | 14 ++++++++++++++ src/modules/weather/weather.c | 14 ++++++++++++++ src/modules/wifi/wifi.c | 14 ++++++++++++++ src/modules/wm/wm.c | 14 ++++++++++++++ src/modules/wmtheme/wmtheme.c | 14 ++++++++++++++ src/modules/zpool/zpool.c | 14 ++++++++++++++ 76 files changed, 1067 insertions(+) diff --git a/src/common/option.h b/src/common/option.h index e2697042c6..bda0316907 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -18,10 +18,27 @@ typedef struct FFModuleFormatArgList { #define FF_FORMAT_ARG_LIST(list) { .args = list, .count = sizeof(list) / sizeof(FFModuleFormatArg) } +typedef struct FFModuleDisplayName { + const char* en; // English + + const char* de; // German + const char* es; // Spanish + const char* fr; // French + const char* it; // Italian + const char* ja; // Japanese + const char* ko; // Korean + const char* pl; // Polish + const char* pt_BR; // Brazilian Portuguese + const char* ru; // Russian + const char* zh_CN; // Simplified Chinese + const char* zh_TW; // Traditional Chinese +} FFModuleDisplayName; + // Must be the first field of FFModuleOptions typedef struct FFModuleBaseInfo { const char* name; const char* description; + FFModuleDisplayName displayName; // A dirty polymorphic implementation in C. // This is UB, because `void*` is not compatible with `FF*Options*`. // However we can't do it better unless we move to C++, so that `option` becomes a `this` pointer diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 7b8405e71e..da2279624b 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -299,6 +299,20 @@ void ffDestroyBatteryOptions(FFBatteryOptions* options) { FFModuleBaseInfo ffBatteryModuleInfo = { .name = FF_BATTERY_MODULE_NAME, .description = "Print battery information", + .displayName = { + .en = "Battery", + .de = "Akku", + .es = "Batería", + .fr = "Batterie", + .it = "Batteria", + .ja = "バッテリー", + .ko = "배터리", + .pl = "Bateria", + .pt_BR = "Bateria", + .ru = "Батарея", + .zh_CN = "电池", + .zh_TW = "電池", + }, .initOptions = (void*) ffInitBatteryOptions, .destroyOptions = (void*) ffDestroyBatteryOptions, .parseJsonObject = (void*) ffParseBatteryJsonObject, diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index c000080f49..b494dae21d 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -132,6 +132,20 @@ void ffDestroyBiosOptions(FFBiosOptions* options) { FFModuleBaseInfo ffBiosModuleInfo = { .name = FF_BIOS_MODULE_NAME, .description = "Print first-stage bootloader information (name, version, release date, etc.)", + .displayName = { + .en = "BIOS", + .de = "BIOS", + .es = "BIOS", + .fr = "BIOS", + .it = "BIOS", + .ja = "BIOS", + .ko = "BIOS", + .pl = "BIOS", + .pt_BR = "BIOS", + .ru = "BIOS", + .zh_CN = "BIOS", + .zh_TW = "BIOS", + }, .initOptions = (void*) ffInitBiosOptions, .destroyOptions = (void*) ffDestroyBiosOptions, .parseJsonObject = (void*) ffParseBiosJsonObject, diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 42a251886a..50d4de366e 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -153,6 +153,20 @@ void ffDestroyBluetoothOptions(FFBluetoothOptions* options) { FFModuleBaseInfo ffBluetoothModuleInfo = { .name = FF_BLUETOOTH_MODULE_NAME, .description = "List connected Bluetooth devices", + .displayName = { + .en = "Bluetooth", + .de = "Bluetooth", + .es = "Bluetooth", + .fr = "Bluetooth", + .it = "Bluetooth", + .ja = "ブルートゥース", + .ko = "블루투스", + .pl = "Bluetooth", + .pt_BR = "Bluetooth", + .ru = "Блютус", + .zh_CN = "蓝牙", + .zh_TW = "藍牙", + }, .initOptions = (void*) ffInitBluetoothOptions, .destroyOptions = (void*) ffDestroyBluetoothOptions, .parseJsonObject = (void*) ffParseBluetoothJsonObject, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index fc113fc832..911519997d 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -192,6 +192,20 @@ void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) { FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .name = FF_BLUETOOTHRADIO_MODULE_NAME, .description = "List Bluetooth radios (supported versions, vendors, etc.)", + .displayName = { + .en = "Bluetooth Radio", + .de = "Bluetooth-Adapter", + .es = "Adaptador Bluetooth", + .fr = "Adaptateur Bluetooth", + .it = "Adattatore Bluetooth", + .ja = "ブルートゥースアダプター", + .ko = "블루투스 어댑터", + .pl = "Adapter Bluetooth", + .pt_BR = "Adaptador Bluetooth", + .ru = "Блютус-адаптер", + .zh_CN = "蓝牙适配器", + .zh_TW = "藍牙配接器", + }, .initOptions = (void*) ffInitBluetoothRadioOptions, .destroyOptions = (void*) ffDestroyBluetoothRadioOptions, .parseJsonObject = (void*) ffParseBluetoothRadioJsonObject, diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 1a85ea3930..070070a01c 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -110,6 +110,20 @@ void ffDestroyBoardOptions(FFBoardOptions* options) { FFModuleBaseInfo ffBoardModuleInfo = { .name = FF_BOARD_MODULE_NAME, .description = "Print motherboard name and other information", + .displayName = { + .en = "Board", + .de = "Mainboard", + .es = "Placa base", + .fr = "Carte mère", + .it = "Scheda madre", + .ja = "マザーボード", + .ko = "메인보드", + .pl = "Płyta główna", + .pt_BR = "Placa-mãe", + .ru = "Материнская плата", + .zh_CN = "主板", + .zh_TW = "主機板", + }, .initOptions = (void*) ffInitBoardOptions, .destroyOptions = (void*) ffDestroyBoardOptions, .parseJsonObject = (void*) ffParseBoardJsonObject, diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 494885fd6c..037de24bd2 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -105,6 +105,20 @@ void ffDestroyBootmgrOptions(FFBootmgrOptions* options) { FFModuleBaseInfo ffBootmgrModuleInfo = { .name = FF_BOOTMGR_MODULE_NAME, .description = "Print second-stage bootloader information (name, firmware, etc.)", + .displayName = { + .en = "Boot Manager", + .de = "Boot-Manager", + .es = "Administrador de arranque", + .fr = "Gestionnaire de démarrage", + .it = "Gestore di avvio", + .ja = "ブートマネージャー", + .ko = "부트 매니저", + .pl = "Menedżer rozruchu", + .pt_BR = "Gerenciador de inicialização", + .ru = "Менеджер загрузки", + .zh_CN = "启动管理器", + .zh_TW = "啟動管理器", + }, .initOptions = (void*) ffInitBootmgrOptions, .destroyOptions = (void*) ffDestroyBootmgrOptions, .parseJsonObject = (void*) ffParseBootmgrJsonObject, diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 011458a283..c627f339b8 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -29,6 +29,20 @@ void ffDestroyBreakOptions([[maybe_unused]] FFBreakOptions* options) { FFModuleBaseInfo ffBreakModuleInfo = { .name = FF_BREAK_MODULE_NAME, .description = "Print an empty line", + .displayName = { + .en = "Break", + .de = "Umbruch", + .es = "Salto de línea", + .fr = "Saut de ligne", + .it = "Interruzione", + .ja = "改行", + .ko = "줄 바꿈", + .pl = "Przerwa", + .pt_BR = "Quebra", + .ru = "Разрыв", + .zh_CN = "换行", + .zh_TW = "換行", + }, .initOptions = (void*) ffInitBreakOptions, .destroyOptions = (void*) ffDestroyBreakOptions, .parseJsonObject = (void*) ffParseBreakJsonObject, diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 479a2ccb9b..835711c2c1 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -192,6 +192,20 @@ void ffDestroyBrightnessOptions(FFBrightnessOptions* options) { FFModuleBaseInfo ffBrightnessModuleInfo = { .name = FF_BRIGHTNESS_MODULE_NAME, .description = "Print the current brightness level of your monitors", + .displayName = { + .en = "Brightness", + .de = "Helligkeit", + .es = "Brillo", + .fr = "Luminosité", + .it = "Luminosità", + .ja = "明るさ", + .ko = "밝기", + .pl = "Jasność", + .pt_BR = "Brilho", + .ru = "Яркость", + .zh_CN = "亮度", + .zh_TW = "亮度", + }, .initOptions = (void*) ffInitBrightnessOptions, .destroyOptions = (void*) ffDestroyBrightnessOptions, .parseJsonObject = (void*) ffParseBrightnessJsonObject, diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 21068e85db..12ed8977b8 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -200,6 +200,20 @@ void ffDestroyBtrfsOptions(FFBtrfsOptions* options) { FFModuleBaseInfo ffBtrfsModuleInfo = { .name = FF_BTRFS_MODULE_NAME, .description = "Print Linux BTRFS volumes", + .displayName = { + .en = "BTRFS", + .de = "BTRFS", + .es = "BTRFS", + .fr = "BTRFS", + .it = "BTRFS", + .ja = "BTRFS", + .ko = "BTRFS", + .pl = "BTRFS", + .pt_BR = "BTRFS", + .ru = "BTRFS", + .zh_CN = "BTRFS", + .zh_TW = "BTRFS", + }, .initOptions = (void*) ffInitBtrfsOptions, .destroyOptions = (void*) ffDestroyBtrfsOptions, .parseJsonObject = (void*) ffParseBtrfsJsonObject, diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 02c454bbbf..4a35509c04 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -117,6 +117,20 @@ void ffDestroyCameraOptions(FFCameraOptions* options) { FFModuleBaseInfo ffCameraModuleInfo = { .name = FF_CAMERA_MODULE_NAME, .description = "Print available cameras", + .displayName = { + .en = "Camera", + .de = "Kamera", + .es = "Cámara", + .fr = "Caméra", + .it = "Fotocamera", + .ja = "カメラ", + .ko = "카메라", + .pl = "Kamera", + .pt_BR = "Câmera", + .ru = "Камера", + .zh_CN = "摄像头", + .zh_TW = "攝像頭", + }, .initOptions = (void*) ffInitCameraOptions, .destroyOptions = (void*) ffDestroyCameraOptions, .parseJsonObject = (void*) ffParseCameraJsonObject, diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 9b5b21e7a6..2a88c5c89b 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -112,6 +112,20 @@ void ffDestroyChassisOptions(FFChassisOptions* options) { FFModuleBaseInfo ffChassisModuleInfo = { .name = FF_CHASSIS_MODULE_NAME, .description = "Print chassis type information (desktop, laptop, etc.)", + .displayName = { + .en = "Chassis", + .de = "Gehäuse", + .es = "Chasis", + .fr = "Châssis", + .it = "Telaio", + .ja = "シャーシ", + .ko = "섀시", + .pl = "Obudowa", + .pt_BR = "Chassi", + .ru = "Шасси", + .zh_CN = "机箱", + .zh_TW = "機箱", + }, .initOptions = (void*) ffInitChassisOptions, .destroyOptions = (void*) ffDestroyChassisOptions, .parseJsonObject = (void*) ffParseChassisJsonObject, diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index a9a465bf84..f55ed20e5f 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -253,6 +253,20 @@ void ffDestroyCodecOptions(FFCodecOptions* options) { FFModuleBaseInfo ffCodecModuleInfo = { .name = FF_CODEC_MODULE_NAME, .description = "Print hardware video acceleration codec types (decode / encode)", + .displayName = { + .en = "Codec", + .de = "Codec", + .es = "Códec", + .fr = "Codec", + .it = "Codec", + .ja = "コーデック", + .ko = "코덱", + .pl = "Kodek", + .pt_BR = "Codec", + .ru = "Кодек", + .zh_CN = "编解码器", + .zh_TW = "編解碼器", + }, .initOptions = (void*) ffInitCodecOptions, .destroyOptions = (void*) ffDestroyCodecOptions, .parseJsonObject = (void*) ffParseCodecJsonObject, diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 8d225d4bf1..ba6890c672 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -297,6 +297,20 @@ void ffDestroyColorsOptions(FFColorsOptions* options) { FFModuleBaseInfo ffColorsModuleInfo = { .name = FF_COLORS_MODULE_NAME, .description = "Display the terminal's 16-color palette", + .displayName = { + .en = "Colors", + .de = "Farben", + .es = "Colores", + .fr = "Couleurs", + .it = "Colori", + .ja = "色", + .ko = "색상", + .pl = "Kolory", + .pt_BR = "Cores", + .ru = "Цвета", + .zh_CN = "颜色", + .zh_TW = "顏色", + }, .initOptions = (void*) ffInitColorsOptions, .destroyOptions = (void*) ffDestroyColorsOptions, .parseJsonObject = (void*) ffParseColorsJsonObject, diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 4de947a792..b86da3a17e 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -155,6 +155,20 @@ void ffDestroyCommandOptions(FFCommandOptions* options) { FFModuleBaseInfo ffCommandModuleInfo = { .name = FF_COMMAND_MODULE_NAME, .description = "Run custom shell scripts", + .displayName = { + .en = "Command", + .de = "Befehl", + .es = "Comando", + .fr = "Commande", + .it = "Comando", + .ja = "コマンド", + .ko = "명령어", + .pl = "Polecenie", + .pt_BR = "Comando", + .ru = "Команда", + .zh_CN = "命令", + .zh_TW = "命令", + }, .initOptions = (void*) ffInitCommandOptions, .destroyOptions = (void*) ffDestroyCommandOptions, .parseJsonObject = (void*) ffParseCommandJsonObject, diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 2716b2e037..5cccddba26 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -253,6 +253,20 @@ void ffDestroyCPUOptions(FFCPUOptions* options) { FFModuleBaseInfo ffCPUModuleInfo = { .name = FF_CPU_MODULE_NAME, .description = "Print CPU name, frequency, etc.", + .displayName = { + .en = "CPU", + .de = "CPU", + .es = "CPU", + .fr = "CPU", + .it = "CPU", + .ja = "CPU", + .ko = "CPU", + .pl = "CPU", + .pt_BR = "CPU", + .ru = "CPU", + .zh_CN = "CPU", + .zh_TW = "CPU", + }, .initOptions = (void*) ffInitCPUOptions, .destroyOptions = (void*) ffDestroyCPUOptions, .parseJsonObject = (void*) ffParseCPUJsonObject, diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 7dd39d1cb6..4fe29a7356 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -225,6 +225,20 @@ void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options) { FFModuleBaseInfo ffCPUCacheModuleInfo = { .name = FF_CPUCACHE_MODULE_NAME, .description = "Print CPU cache sizes", + .displayName = { + .en = "CPU Cache", + .de = "CPU-Cache", + .es = "Caché de CPU", + .fr = "Cache CPU", + .it = "Cache CPU", + .ja = "CPUキャッシュ", + .ko = "CPU 캐시", + .pl = "Pamięć podręczna CPU", + .pt_BR = "Cache da CPU", + .ru = "Кэш процессора", + .zh_CN = "CPU缓存", + .zh_TW = "CPU快取記憶體", + }, .initOptions = (void*) ffInitCPUCacheOptions, .destroyOptions = (void*) ffDestroyCPUCacheOptions, .parseJsonObject = (void*) ffParseCPUCacheJsonObject, diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index ea592a2739..d9d342bb93 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -183,6 +183,20 @@ void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) { FFModuleBaseInfo ffCPUUsageModuleInfo = { .name = FF_CPUUSAGE_MODULE_NAME, .description = "Print CPU usage. Collecting data takes some time", + .displayName = { + .en = "CPU Usage", + .de = "CPU-Auslastung", + .es = "Uso del CPU", + .fr = "Utilisation du CPU", + .it = "Utilizzo della CPU", + .ja = "CPU使用率", + .ko = "CPU 사용량", + .pl = "Użycie CPU", + .pt_BR = "Uso da CPU", + .ru = "Использование ЦП", + .zh_CN = "CPU使用率", + .zh_TW = "CPU使用率", + }, .initOptions = (void*) ffInitCPUUsageOptions, .destroyOptions = (void*) ffDestroyCPUUsageOptions, .parseJsonObject = (void*) ffParseCPUUsageJsonObject, diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 1be3ac6e35..74c8c65e59 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -102,6 +102,20 @@ void ffDestroyCursorOptions(FFCursorOptions* options) { FFModuleBaseInfo ffCursorModuleInfo = { .name = FF_CURSOR_MODULE_NAME, .description = "Print cursor style name", + .displayName = { + .en = "Cursor", + .de = "Mauszeiger", + .es = "Cursor", + .fr = "Curseur", + .it = "Cursore", + .ja = "カーソル", + .ko = "커서", + .pl = "Kursor", + .pt_BR = "Cursor", + .ru = "Курсор", + .zh_CN = "光标", + .zh_TW = "游標", + }, .initOptions = (void*) ffInitCursorOptions, .destroyOptions = (void*) ffDestroyCursorOptions, .parseJsonObject = (void*) ffParseCursorJsonObject, diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 054f3704ca..0806be5b52 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -37,6 +37,20 @@ void ffDestroyCustomOptions(FFCustomOptions* options) { FFModuleBaseInfo ffCustomModuleInfo = { .name = FF_CUSTOM_MODULE_NAME, .description = "Print a custom string, with or without key", + .displayName = { + .en = "Custom", + .de = "Benutzerdefiniert", + .es = "Personalizado", + .fr = "Personnalisé", + .it = "Personalizzato", + .ja = "カスタム", + .ko = "사용자 정의", + .pl = "Niestandardowy", + .pt_BR = "Personalizado", + .ru = "Пользовательский", + .zh_CN = "自定义", + .zh_TW = "自訂", + }, .initOptions = (void*) ffInitCustomOptions, .destroyOptions = (void*) ffDestroyCustomOptions, .parseJsonObject = (void*) ffParseCustomJsonObject, diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 14e3b8251f..b8bbb6d43a 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -154,6 +154,20 @@ void ffDestroyDateTimeOptions(FFDateTimeOptions* options) { FFModuleBaseInfo ffDateTimeModuleInfo = { .name = FF_DATETIME_MODULE_NAME, .description = "Print the current date and time", + .displayName = { + .en = "Date & Time", + .de = "Datum & Uhrzeit", + .es = "Fecha y hora", + .fr = "Date et heure", + .it = "Data e ora", + .ja = "日付と時刻", + .ko = "날짜/시간", + .pl = "Data i godzina", + .pt_BR = "Data e hora", + .ru = "Дата и время", + .zh_CN = "日期时间", + .zh_TW = "日期時間", + }, .initOptions = (void*) ffInitDateTimeOptions, .destroyOptions = (void*) ffDestroyDateTimeOptions, .parseJsonObject = (void*) ffParseDateTimeJsonObject, diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 8e301fa32e..3111343d7d 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -84,6 +84,20 @@ void ffDestroyDEOptions(FFDEOptions* options) { FFModuleBaseInfo ffDEModuleInfo = { .name = FF_DE_MODULE_NAME, .description = "Print desktop environment name", + .displayName = { + .en = "Desktop Environment", + .de = "Desktop-Umgebung", + .es = "Entorno de Escritorio", + .fr = "Environnement de Bureau", + .it = "Ambiente Desktop", + .ja = "デスクトップ環境", + .ko = "데스크탑 환경", + .pl = "Środowisko graficzne", + .pt_BR = "Ambiente de desktop", + .ru = "Рабочая среда", + .zh_CN = "桌面环境", + .zh_TW = "桌面環境", + }, .initOptions = (void*) ffInitDEOptions, .destroyOptions = (void*) ffDestroyDEOptions, .parseJsonObject = (void*) ffParseDEJsonObject, diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 74b6488558..891d2af613 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -453,6 +453,20 @@ void ffDestroyDiskOptions(FFDiskOptions* options) { FFModuleBaseInfo ffDiskModuleInfo = { .name = FF_DISK_MODULE_NAME, .description = "Print partitions, space usage, file system, etc", + .displayName = { + .en = "Disk", + .de = "Festplatte", + .es = "Disco", + .fr = "Disque", + .it = "Disco", + .ja = "ディスク", + .ko = "디스크", + .pl = "Dysk", + .pt_BR = "Disco", + .ru = "Диск", + .zh_CN = "磁盘", + .zh_TW = "磁碟", + }, .initOptions = (void*) ffInitDiskOptions, .destroyOptions = (void*) ffDestroyDiskOptions, .parseJsonObject = (void*) ffParseDiskJsonObject, diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 372910d10a..5f31a1eb1e 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -174,6 +174,20 @@ void ffDestroyDiskIOOptions(FFDiskIOOptions* options) { FFModuleBaseInfo ffDiskIOModuleInfo = { .name = FF_DISKIO_MODULE_NAME, .description = "Print physical disk I/O throughput", + .displayName = { + .en = "Disk I/O", + .de = "Festplatten I/O", + .es = "E/S de disco", + .fr = "Entrée/Sortie disque", + .it = "I/O del disco", + .ja = "ディスク I/O", + .ko = "디스크 I/O", + .pl = "Dysk I/O", + .pt_BR = "Disco I/O", + .ru = "Диск I/O", + .zh_CN = "磁盘 I/O", + .zh_TW = "磁碟 I/O", + }, .initOptions = (void*) ffInitDiskIOOptions, .destroyOptions = (void*) ffDestroyDiskIOOptions, .parseJsonObject = (void*) ffParseDiskIOJsonObject, diff --git a/src/modules/display/display.c b/src/modules/display/display.c index eceb9a2d13..e6870538a6 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -413,6 +413,20 @@ void ffDestroyDisplayOptions(FFDisplayOptions* options) { FFModuleBaseInfo ffDisplayModuleInfo = { .name = FF_DISPLAY_MODULE_NAME, .description = "Print resolutions, refresh rates, etc", + .displayName = { + .en = "Display", + .de = "Anzeige", + .es = "Pantalla", + .fr = "Écran", + .it = "Display", + .ja = "ディスプレイ", + .ko = "디스플레이", + .pl = "Wyświetlacz", + .pt_BR = "Tela", + .ru = "Дисплей", + .zh_CN = "显示器", + .zh_TW = "顯示器", + }, .initOptions = (void*) ffInitDisplayOptions, .destroyOptions = (void*) ffDestroyDisplayOptions, .parseJsonObject = (void*) ffParseDisplayJsonObject, diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 396c3bd431..7524434c6b 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -136,6 +136,20 @@ void ffDestroyDNSOptions(FFDNSOptions* options) { FFModuleBaseInfo ffDNSModuleInfo = { .name = FF_DNS_MODULE_NAME, .description = "Print configured DNS servers", + .displayName = { + .en = "DNS", + .de = "DNS", + .es = "DNS", + .fr = "DNS", + .it = "DNS", + .ja = "DNS", + .ko = "DNS", + .pl = "DNS", + .pt_BR = "DNS", + .ru = "DNS", + .zh_CN = "DNS", + .zh_TW = "DNS", + }, .initOptions = (void*) ffInitDNSOptions, .destroyOptions = (void*) ffDestroyDNSOptions, .parseJsonObject = (void*) ffParseDNSJsonObject, diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 342b31812c..b1a7438fce 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -105,6 +105,20 @@ void ffDestroyEditorOptions(FFEditorOptions* options) { FFModuleBaseInfo ffEditorModuleInfo = { .name = FF_EDITOR_MODULE_NAME, .description = "Print information about the default editor ($VISUAL or $EDITOR)", + .displayName = { + .en = "Editor", + .de = "Editor", + .es = "Editor", + .fr = "Éditeur", + .it = "Editor", + .ja = "エディター", + .ko = "편집기", + .pl = "Edytor", + .pt_BR = "Editor", + .ru = "Редактор", + .zh_CN = "编辑器", + .zh_TW = "編輯器", + }, .initOptions = (void*) ffInitEditorOptions, .destroyOptions = (void*) ffDestroyEditorOptions, .parseJsonObject = (void*) ffParseEditorJsonObject, diff --git a/src/modules/font/font.c b/src/modules/font/font.c index be940b32d1..9763f257dd 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -97,6 +97,20 @@ void ffDestroyFontOptions(FFFontOptions* options) { FFModuleBaseInfo ffFontModuleInfo = { .name = FF_FONT_MODULE_NAME, .description = "Print system font names", + .displayName = { + .en = "Font", + .de = "Schriftart", + .es = "Fuente", + .fr = "Police", + .it = "Carattere", + .ja = "フォント", + .ko = "글꼴", + .pl = "Czcionka", + .pt_BR = "Fonte", + .ru = "Шрифт", + .zh_CN = "字体", + .zh_TW = "字型", + }, .initOptions = (void*) ffInitFontOptions, .destroyOptions = (void*) ffDestroyFontOptions, .parseJsonObject = (void*) ffParseFontJsonObject, diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index f3c3bdfe40..8eb2cf7201 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -191,6 +191,20 @@ void ffDestroyGamepadOptions(FFGamepadOptions* options) { FFModuleBaseInfo ffGamepadModuleInfo = { .name = FF_GAMEPAD_MODULE_NAME, .description = "List connected gamepads", + .displayName = { + .en = "Gamepad", + .de = "Gamepad", + .es = "Gamepad", + .fr = "Manette", + .it = "Gamepad", + .ja = "ゲームパッド", + .ko = "게임패드", + .pl = "Gamepad", + .pt_BR = "Gamepad", + .ru = "Геймпад", + .zh_CN = "游戏手柄", + .zh_TW = "遊戲手把", + }, .initOptions = (void*) ffInitGamepadOptions, .destroyOptions = (void*) ffDestroyGamepadOptions, .parseJsonObject = (void*) ffParseGamepadJsonObject, diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 19ba8c868b..b11615464b 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -481,6 +481,20 @@ void ffDestroyGPUOptions(FFGPUOptions* options) { FFModuleBaseInfo ffGPUModuleInfo = { .name = FF_GPU_MODULE_NAME, .description = "Print GPU names, memory sizes, types, etc", + .displayName = { + .en = "GPU", + .de = "GPU", + .es = "GPU", + .fr = "GPU", + .it = "GPU", + .ja = "GPU", + .ko = "GPU", + .pl = "GPU", + .pt_BR = "GPU", + .ru = "GPU", + .zh_CN = "显卡", + .zh_TW = "顯卡", + }, .initOptions = (void*) ffInitGPUOptions, .destroyOptions = (void*) ffDestroyGPUOptions, .parseJsonObject = (void*) ffParseGPUJsonObject, diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 041ab712e6..5a2e2a856a 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -138,6 +138,20 @@ void ffDestroyHostOptions(FFHostOptions* options) { FFModuleBaseInfo ffHostModuleInfo = { .name = FF_HOST_MODULE_NAME, .description = "Print your computer's product name", + .displayName = { + .en = "Host", + .de = "Rechner", + .es = "Host", + .fr = "Hôte", + .it = "Host", + .ja = "ホスト", + .ko = "호스트", + .pl = "Host", + .pt_BR = "Host", + .ru = "Хост", + .zh_CN = "主机", + .zh_TW = "主機", + }, .initOptions = (void*) ffInitHostOptions, .destroyOptions = (void*) ffDestroyHostOptions, .parseJsonObject = (void*) ffParseHostJsonObject, diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 15dea09287..971a9655da 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -96,6 +96,20 @@ void ffDestroyIconsOptions(FFIconsOptions* options) { FFModuleBaseInfo ffIconsModuleInfo = { .name = FF_ICONS_MODULE_NAME, .description = "Print icon style name", + .displayName = { + .en = "Icons", + .de = "Symbole", + .es = "Iconos", + .fr = "Icônes", + .it = "Icone", + .ja = "アイコン", + .ko = "아이콘", + .pl = "Ikony", + .pt_BR = "Ícones", + .ru = "Иконки", + .zh_CN = "图标", + .zh_TW = "圖示", + }, .initOptions = (void*) ffInitIconsOptions, .destroyOptions = (void*) ffDestroyIconsOptions, .parseJsonObject = (void*) ffParseIconsJsonObject, diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index 7a02e0309b..a6421f9f79 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -105,6 +105,20 @@ void ffDestroyInitSystemOptions(FFInitSystemOptions* options) { FFModuleBaseInfo ffInitSystemModuleInfo = { .name = FF_INITSYSTEM_MODULE_NAME, .description = "Print init system (pid 1) name and version", + .displayName = { + .en = "Init System", + .de = "Init-System", + .es = "Sistema de inicio", + .fr = "Système d'init", + .it = "Sistema di init", + .ja = "initシステム", + .ko = "초기화 시스템", + .pl = "System init", + .pt_BR = "Sistema de inicialização", + .ru = "Init-система", + .zh_CN = "Init 系统", + .zh_TW = "Init 系統", + }, .initOptions = (void*) ffInitInitSystemOptions, .destroyOptions = (void*) ffDestroyInitSystemOptions, .parseJsonObject = (void*) ffParseInitSystemJsonObject, diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 9ae5878df4..5cd76a0bb0 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -64,6 +64,20 @@ void ffDestroyKernelOptions(FFKernelOptions* options) { FFModuleBaseInfo ffKernelModuleInfo = { .name = FF_KERNEL_MODULE_NAME, .description = "Print system kernel version", + .displayName = { + .en = "Kernel", + .de = "Kernel", + .es = "Kernel", + .fr = "Kernel", + .it = "Kernel", + .ja = "カーネル", + .ko = "커널", + .pl = "Jądro", + .pt_BR = "Kernel", + .ru = "Ядро", + .zh_CN = "内核", + .zh_TW = "核心", + }, .initOptions = (void*) ffInitKernelOptions, .destroyOptions = (void*) ffDestroyKernelOptions, .parseJsonObject = (void*) ffParseKernelJsonObject, diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 76e6c36f95..00bfb16647 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -151,6 +151,20 @@ void ffDestroyKeyboardOptions(FFKeyboardOptions* options) { FFModuleBaseInfo ffKeyboardModuleInfo = { .name = FF_KEYBOARD_MODULE_NAME, .description = "List connected keyboards", + .displayName = { + .en = "Keyboard", + .de = "Tastatur", + .es = "Teclado", + .fr = "Clavier", + .it = "Tastiera", + .ja = "キーボード", + .ko = "키보드", + .pl = "Klawiatura", + .pt_BR = "Teclado", + .ru = "Клавиатура", + .zh_CN = "键盘", + .zh_TW = "鍵盤", + }, .initOptions = (void*) ffInitKeyboardOptions, .destroyOptions = (void*) ffDestroyKeyboardOptions, .parseJsonObject = (void*) ffParseKeyboardJsonObject, diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index ed945bad46..8bfe44442d 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -108,6 +108,20 @@ void ffDestroyLMOptions(FFLMOptions* options) { FFModuleBaseInfo ffLMModuleInfo = { .name = FF_LM_MODULE_NAME, .description = "Print login manager (desktop manager) name and version", + .displayName = { + .en = "Login Manager", + .de = "Anmeldemanager", + .es = "Administrador de inicio de sesión", + .fr = "Gestionnaire de connexion", + .it = "Gestore di accesso", + .ja = "ログインマネージャー", + .ko = "로그인 관리자", + .pl = "Menedżer logowania", + .pt_BR = "Gerenciador de login", + .ru = "Менеджер входа", + .zh_CN = "登录管理器", + .zh_TW = "登入管理器", + }, .initOptions = (void*) ffInitLMOptions, .destroyOptions = (void*) ffDestroyLMOptions, .parseJsonObject = (void*) ffParseLMJsonObject, diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index a6fb6f800a..8f6a8ed85c 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -150,6 +150,20 @@ void ffDestroyLoadavgOptions(FFLoadavgOptions* options) { FFModuleBaseInfo ffLoadavgModuleInfo = { .name = FF_LOADAVG_MODULE_NAME, .description = "Print system load averages", + .displayName = { + .en = "Load Average", + .de = "Systemlast", + .es = "Promedio de carga", + .fr = "Charge moyenne", + .it = "Carico medio", + .ja = "ロードアベレージ", + .ko = "시스템 부하 평균", + .pl = "Średnie obciążenie", + .pt_BR = "Média de carga", + .ru = "Средняя нагрузка", + .zh_CN = "系统负载", + .zh_TW = "系統負載", + }, .initOptions = (void*) ffInitLoadavgOptions, .destroyOptions = (void*) ffDestroyLoadavgOptions, .parseJsonObject = (void*) ffParseLoadavgJsonObject, diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index cb9c8e7ec5..4bc3e9658c 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -69,6 +69,20 @@ void ffDestroyLocaleOptions(FFLocaleOptions* options) { FFModuleBaseInfo ffLocaleModuleInfo = { .name = FF_LOCALE_MODULE_NAME, .description = "Print system locale name", + .displayName = { + .en = "Locale", + .de = "Sprachraum", + .es = "Configuración regional", + .fr = "Paramètres régionaux", + .it = "Impostazioni locali", + .ja = "ロケール", + .ko = "로케일", + .pl = "Ustawienia regionalne", + .pt_BR = "Configuração regional", + .ru = "Локаль", + .zh_CN = "语言环境", + .zh_TW = "語言環境", + }, .initOptions = (void*) ffInitLocaleOptions, .destroyOptions = (void*) ffDestroyLocaleOptions, .parseJsonObject = (void*) ffParseLocaleJsonObject, diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index eeb304e283..bc438be7e5 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -424,6 +424,20 @@ void ffDestroyLocalIpOptions(FFLocalIpOptions* options) { FFModuleBaseInfo ffLocalIPModuleInfo = { .name = FF_LOCALIP_MODULE_NAME, .description = "List local IP addresses (IPv4 or IPv6), MAC addresses, etc", + .displayName = { + .en = "Local IP", + .de = "Lokale IP", + .es = "IP local", + .fr = "IP locale", + .it = "IP locale", + .ja = "ローカル IP", + .ko = "로컬 IP", + .pl = "Lokalny adres IP", + .pt_BR = "IP local", + .ru = "Локальный IP", + .zh_CN = "本地 IP", + .zh_TW = "區域 IP", + }, .initOptions = (void*) ffInitLocalIpOptions, .destroyOptions = (void*) ffDestroyLocalIpOptions, .parseJsonObject = (void*) ffParseLocalIpJsonObject, diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index a2fd7d2d1a..432a1fa829 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -79,6 +79,20 @@ void ffDestroyLogoOptions([[maybe_unused]] FFLogoOptions* options) { FFModuleBaseInfo ffLogoModuleInfo = { .name = FF_LOGO_MODULE_NAME, .description = "Query built-in logo for JSON output", + .displayName = { + .en = "Logo", + .de = "Logo", + .es = "Logo", + .fr = "Logo", + .it = "Logo", + .ja = "ロゴ", + .ko = "로고", + .pl = "Logo", + .pt_BR = "Logo", + .ru = "Логотип", + .zh_CN = "徽标", + .zh_TW = "標誌", + }, .initOptions = (void*) ffInitLogoOptions, .destroyOptions = (void*) ffDestroyLogoOptions, .parseJsonObject = (void*) ffParseLogoJsonObject, diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 5f926d1156..80bc087be5 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -255,6 +255,20 @@ void ffDestroyMediaOptions(FFMediaOptions* options) { FFModuleBaseInfo ffMediaModuleInfo = { .name = FF_MEDIA_MODULE_NAME, .description = "Print the name of the currently playing song", + .displayName = { + .en = "Media", + .de = "Medien", + .es = "Medios", + .fr = "Médias", + .it = "Media", + .ja = "メディア", + .ko = "미디어", + .pl = "Media", + .pt_BR = "Mídia", + .ru = "Медиа", + .zh_CN = "媒体", + .zh_TW = "媒體", + }, .initOptions = (void*) ffInitMediaOptions, .destroyOptions = (void*) ffDestroyMediaOptions, .parseJsonObject = (void*) ffParseMediaJsonObject, diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 73a8fc173b..7a7f58e09b 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -120,6 +120,20 @@ void ffDestroyMemoryOptions(FFMemoryOptions* options) { FFModuleBaseInfo ffMemoryModuleInfo = { .name = FF_MEMORY_MODULE_NAME, .description = "Print system memory usage information", + .displayName = { + .en = "Memory", + .de = "Speicher", + .es = "Memoria", + .fr = "Mémoire", + .it = "Memoria", + .ja = "メモリ", + .ko = "메모리", + .pl = "Pamięć", + .pt_BR = "Memória", + .ru = "Память", + .zh_CN = "内存", + .zh_TW = "記憶體", + }, .initOptions = (void*) ffInitMemoryOptions, .destroyOptions = (void*) ffDestroyMemoryOptions, .parseJsonObject = (void*) ffParseMemoryJsonObject, diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 6c8bed1708..27911bccfb 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -106,6 +106,20 @@ void ffDestroyMonitorOptions(FFMonitorOptions* options) { FFModuleBaseInfo ffMonitorModuleInfo = { .name = FF_MONITOR_MODULE_NAME, .description = "Same as Display module, but with a different default output format", + .displayName = { + .en = "Monitor", + .de = "Monitor", + .es = "Monitor", + .fr = "Moniteur", + .it = "Monitor", + .ja = "モニター", + .ko = "모니터", + .pl = "Monitor", + .pt_BR = "Monitor", + .ru = "Монитор", + .zh_CN = "显示器", + .zh_TW = "顯示器", + }, .initOptions = (void*) ffInitMonitorOptions, .destroyOptions = (void*) ffDestroyMonitorOptions, .parseJsonObject = (void*) ffParseMonitorJsonObject, diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index 82dd6b053e..c14b6e9980 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -154,6 +154,20 @@ void ffDestroyMouseOptions(FFMouseOptions* options) { FFModuleBaseInfo ffMouseModuleInfo = { .name = FF_MOUSE_MODULE_NAME, .description = "List connected mice", + .displayName = { + .en = "Mouse", + .de = "Maus", + .es = "Ratón", + .fr = "Souris", + .it = "Mouse", + .ja = "マウス", + .ko = "마우스", + .pl = "Mysz", + .pt_BR = "Mouse", + .ru = "Мышь", + .zh_CN = "鼠标", + .zh_TW = "滑鼠", + }, .initOptions = (void*) ffInitMouseOptions, .destroyOptions = (void*) ffDestroyMouseOptions, .parseJsonObject = (void*) ffParseMouseJsonObject, diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 8607a21af6..cad480b184 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -201,6 +201,20 @@ void ffDestroyNetIOOptions(FFNetIOOptions* options) { FFModuleBaseInfo ffNetIOModuleInfo = { .name = FF_NETIO_MODULE_NAME, .description = "Print network I/O throughput", + .displayName = { + .en = "Network I/O", + .de = "Netzwerk I/O", + .es = "E/S de red", + .fr = "E/S réseau", + .it = "I/O di rete", + .ja = "ネットワークI/O", + .ko = "네트워크 I/O", + .pl = "I/O sieciowe", + .pt_BR = "E/S de rede", + .ru = "Сетевой I/O", + .zh_CN = "网络 I/O", + .zh_TW = "網路 I/O", + }, .initOptions = (void*) ffInitNetIOOptions, .destroyOptions = (void*) ffDestroyNetIOOptions, .parseJsonObject = (void*) ffParseNetIOJsonObject, diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 0a80d9d16b..353615b648 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -122,6 +122,20 @@ void ffDestroyOpenCLOptions(FFOpenCLOptions* options) { FFModuleBaseInfo ffOpenCLModuleInfo = { .name = FF_OPENCL_MODULE_NAME, .description = "Print the highest OpenCL version supported by the GPU", + .displayName = { + .en = "OpenCL", + .de = "OpenCL", + .es = "OpenCL", + .fr = "OpenCL", + .it = "OpenCL", + .ja = "OpenCL", + .ko = "OpenCL", + .pl = "OpenCL", + .pt_BR = "OpenCL", + .ru = "OpenCL", + .zh_CN = "OpenCL", + .zh_TW = "OpenCL", + }, .initOptions = (void*) ffInitOpenCLOptions, .destroyOptions = (void*) ffDestroyOpenCLOptions, .parseJsonObject = (void*) ffParseOpenCLJsonObject, diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 29adcf0f0d..c10ec7e200 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -129,6 +129,20 @@ void ffDestroyOpenGLOptions(FFOpenGLOptions* options) { FFModuleBaseInfo ffOpenGLModuleInfo = { .name = FF_OPENGL_MODULE_NAME, .description = "Print the highest OpenGL version supported by the GPU", + .displayName = { + .en = "OpenGL", + .de = "OpenGL", + .es = "OpenGL", + .fr = "OpenGL", + .it = "OpenGL", + .ja = "OpenGL", + .ko = "OpenGL", + .pl = "OpenGL", + .pt_BR = "OpenGL", + .ru = "OpenGL", + .zh_CN = "OpenGL", + .zh_TW = "OpenGL", + }, .initOptions = (void*) ffInitOpenGLOptions, .destroyOptions = (void*) ffDestroyOpenGLOptions, .parseJsonObject = (void*) ffParseOpenGLJsonObject, diff --git a/src/modules/os/os.c b/src/modules/os/os.c index d0dc5600b7..65168a6097 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -174,6 +174,20 @@ void ffDestroyOSOptions(FFOSOptions* options) { FFModuleBaseInfo ffOSModuleInfo = { .name = FF_OS_MODULE_NAME, .description = "Print the OS or Linux distribution name and version", + .displayName = { + .en = "OS", + .de = "Betriebssystem", + .es = "Sistema operativo", + .fr = "Système d'exploitation", + .it = "Sistema operativo", + .ja = "オペレーティングシステム", + .ko = "운영 체제", + .pl = "System operacyjny", + .pt_BR = "Sistema operacional", + .ru = "Операционная система", + .zh_CN = "操作系统", + .zh_TW = "操作系統", + }, .initOptions = (void*) ffInitOSOptions, .destroyOptions = (void*) ffDestroyOSOptions, .parseJsonObject = (void*) ffParseOSJsonObject, diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 1553893f1a..258e0f369e 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -512,6 +512,20 @@ void ffDestroyPackagesOptions(FFPackagesOptions* options) { FFModuleBaseInfo ffPackagesModuleInfo = { .name = FF_PACKAGES_MODULE_NAME, .description = "List installed package managers and count of installed packages", + .displayName = { + .en = "Packages", + .de = "Pakete", + .es = "Paquetes", + .fr = "Paquets", + .it = "Pacchetti", + .ja = "パッケージ", + .ko = "패키지", + .pl = "Pakiety", + .pt_BR = "Pacotes", + .ru = "Пакеты", + .zh_CN = "软件包", + .zh_TW = "軟體包", + }, .initOptions = (void*) ffInitPackagesOptions, .destroyOptions = (void*) ffDestroyPackagesOptions, .parseJsonObject = (void*) ffParsePackagesJsonObject, diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 8935438840..d897e131ea 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -267,6 +267,20 @@ void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) { FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .name = FF_PHYSICALDISK_MODULE_NAME, .description = "Print physical disk information", + .displayName = { + .en = "Physical Disk", + .de = "Physische Festplatte", + .es = "Disco físico", + .fr = "Disque physique", + .it = "Disco fisico", + .ja = "物理ディスク", + .ko = "물리 디스크", + .pl = "Dysk fizyczny", + .pt_BR = "Disco físico", + .ru = "Физический диск", + .zh_CN = "物理磁盘", + .zh_TW = "物理磁碟", + }, .initOptions = (void*) ffInitPhysicalDiskOptions, .destroyOptions = (void*) ffDestroyPhysicalDiskOptions, .parseJsonObject = (void*) ffParsePhysicalDiskJsonObject, diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index f044e59071..64e53957df 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -161,6 +161,20 @@ void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) { FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .name = FF_PHYSICALMEMORY_MODULE_NAME, .description = "Print system physical memory devices", + .displayName = { + .en = "Physical Memory", + .de = "Physischer Speicher", + .es = "Memoria física", + .fr = "Mémoire physique", + .it = "Memoria fisica", + .ja = "物理メモリ", + .ko = "물리 메모리", + .pl = "Pamięć fizyczna", + .pt_BR = "Memória física", + .ru = "Физическая память", + .zh_CN = "物理内存", + .zh_TW = "實體記憶體", + }, .initOptions = (void*) ffInitPhysicalMemoryOptions, .destroyOptions = (void*) ffDestroyPhysicalMemoryOptions, .parseJsonObject = (void*) ffParsePhysicalMemoryJsonObject, diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 0d1fd03b8f..a01471446e 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -111,6 +111,20 @@ void ffDestroyPlayerOptions(FFPlayerOptions* options) { FFModuleBaseInfo ffPlayerModuleInfo = { .name = FF_PLAYER_MODULE_NAME, .description = "Print the music player name that is currently active", + .displayName = { + .en = "Media Player", + .de = "Medienplayer", + .es = "Reproductor multimedia", + .fr = "Lecteur multimédia", + .it = "Lettore multimediale", + .ja = "メディアプレイヤー", + .ko = "미디어 플레이어", + .pl = "Odtwarzacz multimediów", + .pt_BR = "Reprodutor de mídia", + .ru = "Медиаплеер", + .zh_CN = "媒体播放器", + .zh_TW = "媒體播放器", + }, .initOptions = (void*) ffInitPlayerOptions, .destroyOptions = (void*) ffDestroyPlayerOptions, .parseJsonObject = (void*) ffParsePlayerJsonObject, diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index be20d2a6d7..74f0bfe898 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -112,6 +112,20 @@ void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options) { FFModuleBaseInfo ffPowerAdapterModuleInfo = { .name = FF_POWERADAPTER_MODULE_NAME, .description = "Print power adapter name and charging watts", + .displayName = { + .en = "Power Adapter", + .de = "Netzteil", + .es = "Adaptador de corriente", + .fr = "Adaptateur secteur", + .it = "Alimentatore", + .ja = "電源アダプター", + .ko = "전원 어댑터", + .pl = "Zasilacz", + .pt_BR = "Fonte de alimentação", + .ru = "Блок питания", + .zh_CN = "电源适配器", + .zh_TW = "電源轉接器", + }, .initOptions = (void*) ffInitPowerAdapterOptions, .destroyOptions = (void*) ffDestroyPowerAdapterOptions, .parseJsonObject = (void*) ffParsePowerAdapterJsonObject, diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index daf7a23ed8..1d02bac2ee 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -65,6 +65,20 @@ void ffDestroyProcessesOptions(FFProcessesOptions* options) { FFModuleBaseInfo ffProcessesModuleInfo = { .name = FF_PROCESSES_MODULE_NAME, .description = "Print number of running processes", + .displayName = { + .en = "Processes", + .de = "Prozesse", + .es = "Procesos", + .fr = "Processus", + .it = "Processi", + .ja = "プロセス", + .ko = "프로세스", + .pl = "Procesy", + .pt_BR = "Processos", + .ru = "Процессы", + .zh_CN = "进程数", + .zh_TW = "進程數", + }, .initOptions = (void*) ffInitProcessesOptions, .destroyOptions = (void*) ffDestroyProcessesOptions, .parseJsonObject = (void*) ffParseProcessesJsonObject, diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 5d52e74a70..fe5002a43f 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -112,6 +112,20 @@ void ffDestroyPublicIpOptions(FFPublicIPOptions* options) { FFModuleBaseInfo ffPublicIPModuleInfo = { .name = FF_PUBLICIP_MODULE_NAME, .description = "Print your public IP address and related information", + .displayName = { + .en = "Public IP", + .de = "Öffentliche IP", + .es = "IP pública", + .fr = "IP publique", + .it = "IP pubblica", + .ja = "パブリックIP", + .ko = "공용 IP", + .pl = "Publiczne IP", + .pt_BR = "IP público", + .ru = "Публичный IP", + .zh_CN = "公网 IP", + .zh_TW = "公網 IP", + }, .initOptions = (void*) ffInitPublicIpOptions, .destroyOptions = (void*) ffDestroyPublicIpOptions, .parseJsonObject = (void*) ffParsePublicIpJsonObject, diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index bd84d7a40d..eaf9128195 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -123,6 +123,20 @@ void ffDestroySeparatorOptions(FFSeparatorOptions* options) { FFModuleBaseInfo ffSeparatorModuleInfo = { .name = FF_SEPARATOR_MODULE_NAME, .description = "Print a separator line", + .displayName = { + .en = "Separator", + .de = "Trennlinie", + .es = "Separador", + .fr = "Séparateur", + .it = "Separatore", + .ja = "セパレーター", + .ko = "구분선", + .pl = "Separator", + .pt_BR = "Separador", + .ru = "Разделитель", + .zh_CN = "分隔线", + .zh_TW = "分隔線", + }, .initOptions = (void*) ffInitSeparatorOptions, .destroyOptions = (void*) ffDestroySeparatorOptions, .parseJsonObject = (void*) ffParseSeparatorJsonObject, diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 84db1baca0..a1df091c36 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -91,6 +91,20 @@ void ffDestroyShellOptions(FFShellOptions* options) { FFModuleBaseInfo ffShellModuleInfo = { .name = FF_SHELL_MODULE_NAME, .description = "Print the current shell name and version", + .displayName = { + .en = "Shell", + .de = "Shell", + .es = "Shell", + .fr = "Shell", + .it = "Shell", + .ja = "シェル", + .ko = "셸", + .pl = "Powłoka", + .pt_BR = "Shell", + .ru = "Оболочка", + .zh_CN = "Shell", + .zh_TW = "Shell", + }, .initOptions = (void*) ffInitShellOptions, .destroyOptions = (void*) ffDestroyShellOptions, .parseJsonObject = (void*) ffParseShellJsonObject, diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 6bc73cbe7b..eaa0d44b7c 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -201,6 +201,20 @@ void ffDestroySoundOptions(FFSoundOptions* options) { FFModuleBaseInfo ffSoundModuleInfo = { .name = FF_SOUND_MODULE_NAME, .description = "Print sound devices, volume levels, etc", + .displayName = { + .en = "Sound", + .de = "Sound", + .es = "Sonido", + .fr = "Son", + .it = "Audio", + .ja = "サウンド", + .ko = "사운드", + .pl = "Dźwięk", + .pt_BR = "Som", + .ru = "Звук", + .zh_CN = "声音", + .zh_TW = "聲音", + }, .initOptions = (void*) ffInitSoundOptions, .destroyOptions = (void*) ffDestroySoundOptions, .parseJsonObject = (void*) ffParseSoundJsonObject, diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index cf9d107c60..5b7c1117e0 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -184,6 +184,20 @@ void ffDestroySwapOptions(FFSwapOptions* options) { FFModuleBaseInfo ffSwapModuleInfo = { .name = FF_SWAP_MODULE_NAME, .description = "Print swap (paging file) space usage", + .displayName = { + .en = "Swap", + .de = "Swap", + .es = "Swap", + .fr = "Swap", + .it = "Swap", + .ja = "スワップ", + .ko = "스왑", + .pl = "Swap", + .pt_BR = "Swap", + .ru = "Своп", + .zh_CN = "交换空间", + .zh_TW = "交換空間", + }, .initOptions = (void*) ffInitSwapOptions, .destroyOptions = (void*) ffDestroySwapOptions, .parseJsonObject = (void*) ffParseSwapJsonObject, diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 5b2e9305fe..7aa4e1a185 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -85,6 +85,20 @@ void ffDestroyTerminalOptions(FFTerminalOptions* options) { FFModuleBaseInfo ffTerminalModuleInfo = { .name = FF_TERMINAL_MODULE_NAME, .description = "Print the current terminal name and version", + .displayName = { + .en = "Terminal", + .de = "Terminal", + .es = "Terminal", + .fr = "Terminal", + .it = "Terminale", + .ja = "ターミナル", + .ko = "터미널", + .pl = "Terminal", + .pt_BR = "Terminal", + .ru = "Терминал", + .zh_CN = "终端", + .zh_TW = "終端機", + }, .initOptions = (void*) ffInitTerminalOptions, .destroyOptions = (void*) ffDestroyTerminalOptions, .parseJsonObject = (void*) ffParseTerminalJsonObject, diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 87a0837185..6c840889df 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -107,6 +107,20 @@ void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options) { FFModuleBaseInfo ffTerminalFontModuleInfo = { .name = FF_TERMINALFONT_MODULE_NAME, .description = "Print the font name and size used by the current terminal", + .displayName = { + .en = "Terminal Font", + .de = "Terminalschriftart", + .es = "Fuente del terminal", + .fr = "Police du terminal", + .it = "Carattere del terminale", + .ja = "ターミナルフォント", + .ko = "터미널 글꼴", + .pl = "Czcionka terminala", + .pt_BR = "Fonte do terminal", + .ru = "Шрифт терминала", + .zh_CN = "终端字体", + .zh_TW = "終端機字型", + }, .initOptions = (void*) ffInitTerminalFontOptions, .destroyOptions = (void*) ffDestroyTerminalFontOptions, .parseJsonObject = (void*) ffParseTerminalFontJsonObject, diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 088b97fcef..11e34551b7 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -78,6 +78,20 @@ void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options) { FFModuleBaseInfo ffTerminalSizeModuleInfo = { .name = FF_TERMINALSIZE_MODULE_NAME, .description = "Print the current terminal size", + .displayName = { + .en = "Terminal Size", + .de = "Terminalgröße", + .es = "Tamaño del terminal", + .fr = "Taille du terminal", + .it = "Dimensioni terminale", + .ja = "ターミナルサイズ", + .ko = "터미널 크기", + .pl = "Rozmiar terminala", + .pt_BR = "Tamanho do terminal", + .ru = "Размер терминала", + .zh_CN = "终端大小", + .zh_TW = "終端機大小", + }, .initOptions = (void*) ffInitTerminalSizeOptions, .destroyOptions = (void*) ffDestroyTerminalSizeOptions, .parseJsonObject = (void*) ffParseTerminalSizeJsonObject, diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 3d5239b2f6..053db3453e 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -95,6 +95,20 @@ void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options) { FFModuleBaseInfo ffTerminalThemeModuleInfo = { .name = FF_TERMINALTHEME_MODULE_NAME, .description = "Print the current terminal theme (foreground and background colors)", + .displayName = { + .en = "Terminal Theme", + .de = "Terminalthema", + .es = "Tema del terminal", + .fr = "Thème du terminal", + .it = "Tema del terminale", + .ja = "ターミナルテーマ", + .ko = "터미널 테마", + .pl = "Motyw terminala", + .pt_BR = "Tema do terminal", + .ru = "Тема терминала", + .zh_CN = "终端主题", + .zh_TW = "終端機主題", + }, .initOptions = (void*) ffInitTerminalThemeOptions, .destroyOptions = (void*) ffDestroyTerminalThemeOptions, .parseJsonObject = (void*) ffParseTerminalThemeJsonObject, diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index f51a4aac64..1769d5fc3e 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -89,6 +89,20 @@ void ffDestroyThemeOptions(FFThemeOptions* options) { FFModuleBaseInfo ffThemeModuleInfo = { .name = FF_THEME_MODULE_NAME, .description = "Print the current desktop environment theme", + .displayName = { + .en = "Theme", + .de = "Thema", + .es = "Tema", + .fr = "Thème", + .it = "Tema", + .ja = "テーマ", + .ko = "테마", + .pl = "Motyw", + .pt_BR = "Tema", + .ru = "Тема", + .zh_CN = "主题", + .zh_TW = "主題", + }, .initOptions = (void*) ffInitThemeOptions, .destroyOptions = (void*) ffDestroyThemeOptions, .parseJsonObject = (void*) ffParseThemeJsonObject, diff --git a/src/modules/title/title.c b/src/modules/title/title.c index ce877caed7..3d8fe1a795 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -178,6 +178,20 @@ void ffDestroyTitleOptions(FFTitleOptions* options) { FFModuleBaseInfo ffTitleModuleInfo = { .name = FF_TITLE_MODULE_NAME, .description = "Print the title, including your username and hostname", + .displayName = { + .en = "Title", + .de = "Titel", + .es = "Título", + .fr = "Titre", + .it = "Titolo", + .ja = "タイトル", + .ko = "제목", + .pl = "Tytuł", + .pt_BR = "Título", + .ru = "Заголовок", + .zh_CN = "标题", + .zh_TW = "標題", + }, .initOptions = (void*) ffInitTitleOptions, .destroyOptions = (void*) ffDestroyTitleOptions, .parseJsonObject = (void*) ffParseTitleJsonObject, diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 6596d6261c..3471d5a12a 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -85,6 +85,20 @@ void ffDestroyTPMOptions(FFTPMOptions* options) { FFModuleBaseInfo ffTPMModuleInfo = { .name = FF_TPM_MODULE_NAME, .description = "Print information about the Trusted Platform Module (TPM) security device", + .displayName = { + .en = "TPM", + .de = "TPM", + .es = "TPM", + .fr = "TPM", + .it = "TPM", + .ja = "TPM", + .ko = "TPM", + .pl = "TPM", + .pt_BR = "TPM", + .ru = "TPM", + .zh_CN = "TPM", + .zh_TW = "TPM", + }, .initOptions = (void*) ffInitTPMOptions, .destroyOptions = (void*) ffDestroyTPMOptions, .parseJsonObject = (void*) ffParseTPMJsonObject, diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 41ac4526a1..b4299d7a5b 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -85,6 +85,20 @@ void ffDestroyUptimeOptions(FFUptimeOptions* options) { FFModuleBaseInfo ffUptimeModuleInfo = { .name = FF_UPTIME_MODULE_NAME, .description = "Print how long the system has been running", + .displayName = { + .en = "Uptime", + .de = "Betriebszeit", + .es = "Tiempo de actividad", + .fr = "Temps de fonctionnement", + .it = "Tempo di attività", + .ja = "稼働時間", + .ko = "업타임", + .pl = "Czas pracy", + .pt_BR = "Tempo de atividade", + .ru = "Время работы", + .zh_CN = "运行时间", + .zh_TW = "運行時間", + }, .initOptions = (void*) ffInitUptimeOptions, .destroyOptions = (void*) ffDestroyUptimeOptions, .parseJsonObject = (void*) ffParseUptimeJsonObject, diff --git a/src/modules/users/users.c b/src/modules/users/users.c index fbf1ffaa8e..f67073e188 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -182,6 +182,20 @@ void ffDestroyUsersOptions(FFUsersOptions* options) { FFModuleBaseInfo ffUsersModuleInfo = { .name = FF_USERS_MODULE_NAME, .description = "Print users who are currently logged in", + .displayName = { + .en = "Users", + .de = "Benutzer", + .es = "Usuarios", + .fr = "Utilisateurs", + .it = "Utenti", + .ja = "ユーザー", + .ko = "사용자", + .pl = "Użytkownicy", + .pt_BR = "Usuários", + .ru = "Пользователи", + .zh_CN = "用户", + .zh_TW = "使用者", + }, .initOptions = (void*) ffInitUsersOptions, .destroyOptions = (void*) ffDestroyUsersOptions, .parseJsonObject = (void*) ffParseUsersJsonObject, diff --git a/src/modules/version/version.c b/src/modules/version/version.c index fa3b59fe7f..2bd906a21f 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -96,6 +96,20 @@ void ffDestroyVersionOptions(FFVersionOptions* options) { FFModuleBaseInfo ffVersionModuleInfo = { .name = FF_VERSION_MODULE_NAME, .description = "Print the Fastfetch version and build information", + .displayName = { + .en = "Version", + .de = "Version", + .es = "Versión", + .fr = "Version", + .it = "Versione", + .ja = "バージョン", + .ko = "버전", + .pl = "Wersja", + .pt_BR = "Versão", + .ru = "Версия", + .zh_CN = "版本", + .zh_TW = "版本", + }, .initOptions = (void*) ffInitVersionOptions, .destroyOptions = (void*) ffDestroyVersionOptions, .parseJsonObject = (void*) ffParseVersionJsonObject, diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 03123b7ae6..9dedfd9cc7 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -134,6 +134,20 @@ void ffDestroyVulkanOptions(FFVulkanOptions* options) { FFModuleBaseInfo ffVulkanModuleInfo = { .name = FF_VULKAN_MODULE_NAME, .description = "Print the highest Vulkan version supported by the GPU", + .displayName = { + .en = "Vulkan", + .de = "Vulkan", + .es = "Vulkan", + .fr = "Vulkan", + .it = "Vulkan", + .ja = "Vulkan", + .ko = "Vulkan", + .pl = "Vulkan", + .pt_BR = "Vulkan", + .ru = "Vulkan", + .zh_CN = "Vulkan", + .zh_TW = "Vulkan", + }, .initOptions = (void*) ffInitVulkanOptions, .destroyOptions = (void*) ffDestroyVulkanOptions, .parseJsonObject = (void*) ffParseVulkanJsonObject, diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index b5fab48f50..fc1393fb9f 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -77,6 +77,20 @@ void ffDestroyWallpaperOptions(FFWallpaperOptions* options) { FFModuleBaseInfo ffWallpaperModuleInfo = { .name = FF_WALLPAPER_MODULE_NAME, .description = "Print the file path of the current wallpaper", + .displayName = { + .en = "Wallpaper", + .de = "Hintergrundbild", + .es = "Fondo de pantalla", + .fr = "Fond d'écran", + .it = "Sfondo", + .ja = "壁紙", + .ko = "배경화면", + .pl = "Tapeta", + .pt_BR = "Papel de parede", + .ru = "Обои", + .zh_CN = "壁纸", + .zh_TW = "桌布", + }, .initOptions = (void*) ffInitWallpaperOptions, .destroyOptions = (void*) ffDestroyWallpaperOptions, .parseJsonObject = (void*) ffParseWallpaperJsonObject, diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 152cb057bd..8307ce4223 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -94,6 +94,20 @@ void ffDestroyWeatherOptions(FFWeatherOptions* options) { FFModuleBaseInfo ffWeatherModuleInfo = { .name = FF_WEATHER_MODULE_NAME, .description = "Print weather information", + .displayName = { + .en = "Weather", + .de = "Wetter", + .es = "Clima", + .fr = "Météo", + .it = "Meteo", + .ja = "天気", + .ko = "날씨", + .pl = "Pogoda", + .pt_BR = "Clima", + .ru = "Погода", + .zh_CN = "天气", + .zh_TW = "天氣", + }, .initOptions = (void*) ffInitWeatherOptions, .destroyOptions = (void*) ffDestroyWeatherOptions, .parseJsonObject = (void*) ffParseWeatherJsonObject, diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 0e9df22c98..58e5da965d 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -215,6 +215,20 @@ void ffDestroyWifiOptions(FFWifiOptions* options) { FFModuleBaseInfo ffWifiModuleInfo = { .name = FF_WIFI_MODULE_NAME, .description = "Print connected Wi-Fi info (SSID, connection and security protocol)", + .displayName = { + .en = "Wi-Fi", + .de = "WLAN", + .es = "Wi-Fi", + .fr = "Wi-Fi", + .it = "Wi-Fi", + .ja = "Wi-Fi", + .ko = "와이파이", + .pl = "Wi-Fi", + .pt_BR = "Wi-Fi", + .ru = "Wi-Fi", + .zh_CN = "无线网络", + .zh_TW = "無線網路", + }, .initOptions = (void*) ffInitWifiOptions, .destroyOptions = (void*) ffDestroyWifiOptions, .parseJsonObject = (void*) ffParseWifiJsonObject, diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 5e23826e1c..3545bfc9e6 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -122,6 +122,20 @@ void ffDestroyWMOptions(FFWMOptions* options) { FFModuleBaseInfo ffWMModuleInfo = { .name = FF_WM_MODULE_NAME, .description = "Print the window manager name and version", + .displayName = { + .en = "WM", + .de = "Fenstermanager", + .es = "Gestor de ventanas", + .fr = "Gestionnaire de fenêtres", + .it = "Gestore finestre", + .ja = "ウィンドウマネージャー", + .ko = "윈도우 관리자", + .pl = "Menedżer okien", + .pt_BR = "Gerenciador de janelas", + .ru = "Менеджер окон", + .zh_CN = "窗口管理器", + .zh_TW = "視窗管理員", + }, .initOptions = (void*) ffInitWMOptions, .destroyOptions = (void*) ffDestroyWMOptions, .parseJsonObject = (void*) ffParseWMJsonObject, diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index f1ab4105f7..7061f66aea 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -63,6 +63,20 @@ void ffDestroyWMThemeOptions(FFWMThemeOptions* options) { FFModuleBaseInfo ffWMThemeModuleInfo = { .name = FF_WMTHEME_MODULE_NAME, .description = "Print the current window manager theme", + .displayName = { + .en = "WM Theme", + .de = "Fenstermanager-Thema", + .es = "Tema del gestor de ventanas", + .fr = "Thème du gestionnaire de fenêtres", + .it = "Tema del gestore finestre", + .ja = "ウィンドウマネージャのテーマ", + .ko = "윈도우 관리자 테마", + .pl = "Motyw menedżera okien", + .pt_BR = "Tema do gerenciador de janelas", + .ru = "Тема менеджера окон", + .zh_CN = "窗口管理器主题", + .zh_TW = "視窗管理員主題", + }, .initOptions = (void*) ffInitWMThemeOptions, .destroyOptions = (void*) ffDestroyWMThemeOptions, .parseJsonObject = (void*) ffParseWMThemeJsonObject, diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 7e5f03a52d..b155ff3b12 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -194,6 +194,20 @@ void ffDestroyZpoolOptions(FFZpoolOptions* options) { FFModuleBaseInfo ffZpoolModuleInfo = { .name = FF_ZPOOL_MODULE_NAME, .description = "Print ZFS storage pools", + .displayName = { + .en = "Zpool", + .de = "Zpool", + .es = "Zpool", + .fr = "Zpool", + .it = "Zpool", + .ja = "Zpool", + .ko = "Zpool", + .pl = "Zpool", + .pt_BR = "Zpool", + .ru = "Zpool", + .zh_CN = "Zpool", + .zh_TW = "Zpool", + }, .initOptions = (void*) ffInitZpoolOptions, .destroyOptions = (void*) ffDestroyZpoolOptions, .parseJsonObject = (void*) ffParseZpoolJsonObject, From f95167e907bf89eb74fc4a1ff5fcea81a2b42e7d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 14 Aug 2026 23:33:54 +0800 Subject: [PATCH 005/109] Global: adds option `key-language` Fixes #2503 --- doc/help.json | 24 +++++ doc/json_schema.json | 70 ++++++++++++ src/common/impl/commandoption.c | 12 +-- src/common/impl/jsonconfig.c | 12 +-- src/common/option.h | 2 + src/modules/battery/battery.c | 12 +-- src/modules/battery/battery.h | 2 - src/modules/bios/bios.c | 10 +- src/modules/bios/bios.h | 2 - src/modules/bluetooth/bluetooth.c | 12 +-- src/modules/bluetooth/bluetooth.h | 2 - src/modules/bluetoothradio/bluetoothradio.c | 14 ++- src/modules/bluetoothradio/bluetoothradio.h | 2 - src/modules/board/board.c | 12 +-- src/modules/board/board.h | 2 - src/modules/bootmgr/bootmgr.c | 10 +- src/modules/bootmgr/bootmgr.h | 2 - src/modules/break/break.c | 4 +- src/modules/break/break.h | 2 - src/modules/brightness/brightness.c | 12 +-- src/modules/brightness/brightness.h | 2 - src/modules/btrfs/btrfs.c | 12 +-- src/modules/btrfs/btrfs.h | 2 - src/modules/camera/camera.c | 12 +-- src/modules/camera/camera.h | 2 - src/modules/chassis/chassis.c | 12 +-- src/modules/chassis/chassis.h | 2 - src/modules/codec/codec.c | 14 +-- src/modules/codec/codec.h | 2 - src/modules/colors/colors.c | 22 ++-- src/modules/colors/colors.h | 2 - src/modules/command/command.c | 16 +-- src/modules/command/command.h | 2 - src/modules/cpu/cpu.c | 14 +-- src/modules/cpu/cpu.h | 2 - src/modules/cpucache/cpucache.c | 14 ++- src/modules/cpucache/cpucache.h | 2 - src/modules/cpuusage/cpuusage.c | 12 +-- src/modules/cpuusage/cpuusage.h | 2 - src/modules/cursor/cursor.c | 10 +- src/modules/cursor/cursor.h | 2 - src/modules/custom/custom.c | 6 +- src/modules/custom/custom.h | 2 - src/modules/datetime/datetime.c | 12 +-- src/modules/datetime/datetime.h | 2 - src/modules/de/de.c | 12 +-- src/modules/de/de.h | 2 - src/modules/disk/disk.c | 10 +- src/modules/disk/disk.h | 2 - src/modules/diskio/diskio.c | 10 +- src/modules/diskio/diskio.h | 2 - src/modules/display/display.c | 18 ++-- src/modules/display/display.h | 2 - src/modules/dns/dns.c | 14 +-- src/modules/dns/dns.h | 2 - src/modules/editor/editor.c | 10 +- src/modules/editor/editor.h | 2 - src/modules/font/font.c | 10 +- src/modules/font/font.h | 2 - src/modules/gamepad/gamepad.c | 14 +-- src/modules/gamepad/gamepad.h | 2 - src/modules/gpu/gpu.c | 16 +-- src/modules/gpu/gpu.h | 2 - src/modules/host/host.c | 12 +-- src/modules/host/host.h | 2 - src/modules/icons/icons.c | 10 +- src/modules/icons/icons.h | 2 - src/modules/initsystem/initsystem.c | 12 +-- src/modules/initsystem/initsystem.h | 2 - src/modules/kernel/kernel.c | 8 +- src/modules/kernel/kernel.h | 2 - src/modules/keyboard/keyboard.c | 14 +-- src/modules/keyboard/keyboard.h | 2 - src/modules/lm/lm.c | 12 +-- src/modules/lm/lm.h | 2 - src/modules/loadavg/loadavg.c | 12 +-- src/modules/loadavg/loadavg.h | 2 - src/modules/locale/locale.c | 10 +- src/modules/locale/locale.h | 2 - src/modules/localip/localip.c | 15 ++- src/modules/localip/localip.h | 2 - src/modules/logo/logo.c | 6 +- src/modules/logo/logo.h | 2 - src/modules/media/media.c | 10 +- src/modules/media/media.h | 2 - src/modules/memory/memory.c | 10 +- src/modules/memory/memory.h | 2 - src/modules/monitor/monitor.c | 8 +- src/modules/monitor/monitor.h | 2 - src/modules/mouse/mouse.c | 14 +-- src/modules/mouse/mouse.h | 2 - src/modules/netio/netio.c | 10 +- src/modules/netio/netio.h | 2 - src/modules/opencl/opencl.c | 10 +- src/modules/opencl/opencl.h | 2 - src/modules/opengl/opengl.c | 12 +-- src/modules/opengl/opengl.h | 2 - src/modules/os/os.c | 8 +- src/modules/os/os.h | 2 - src/modules/packages/packages.c | 16 +-- src/modules/packages/packages.h | 2 - src/modules/physicaldisk/physicaldisk.c | 14 ++- src/modules/physicaldisk/physicaldisk.h | 2 - src/modules/physicalmemory/physicalmemory.c | 14 ++- src/modules/physicalmemory/physicalmemory.h | 2 - src/modules/player/player.c | 14 ++- src/modules/player/player.h | 2 - src/modules/poweradapter/poweradapter.c | 14 ++- src/modules/poweradapter/poweradapter.h | 2 - src/modules/processes/processes.c | 10 +- src/modules/processes/processes.h | 2 - src/modules/publicip/publicip.c | 12 +-- src/modules/publicip/publicip.h | 2 - src/modules/separator/separator.c | 6 +- src/modules/separator/separator.h | 2 - src/modules/shell/shell.c | 10 +- src/modules/shell/shell.h | 2 - src/modules/sound/sound.c | 14 +-- src/modules/sound/sound.h | 2 - src/modules/swap/swap.c | 10 +- src/modules/swap/swap.h | 2 - src/modules/terminal/terminal.c | 10 +- src/modules/terminal/terminal.h | 2 - src/modules/terminalfont/terminalfont.c | 12 +-- src/modules/terminalfont/terminalfont.h | 2 - src/modules/terminalsize/terminalsize.c | 12 +-- src/modules/terminalsize/terminalsize.h | 2 - src/modules/terminaltheme/terminaltheme.c | 12 +-- src/modules/terminaltheme/terminaltheme.h | 2 - src/modules/theme/theme.c | 10 +- src/modules/theme/theme.h | 2 - src/modules/title/title.c | 8 +- src/modules/title/title.h | 2 - src/modules/tpm/tpm.c | 10 +- src/modules/tpm/tpm.h | 2 - src/modules/uptime/uptime.c | 10 +- src/modules/uptime/uptime.h | 2 - src/modules/users/users.c | 14 +-- src/modules/users/users.h | 2 - src/modules/version/version.c | 8 +- src/modules/version/version.h | 2 - src/modules/vulkan/vulkan.c | 10 +- src/modules/vulkan/vulkan.h | 2 - src/modules/wallpaper/wallpaper.c | 10 +- src/modules/wallpaper/wallpaper.h | 2 - src/modules/weather/weather.c | 10 +- src/modules/weather/weather.h | 2 - src/modules/wifi/wifi.c | 12 +-- src/modules/wifi/wifi.h | 2 - src/modules/wm/wm.c | 10 +- src/modules/wm/wm.h | 2 - src/modules/wmtheme/wmtheme.c | 12 +-- src/modules/wmtheme/wmtheme.h | 2 - src/modules/zpool/zpool.c | 12 +-- src/modules/zpool/zpool.h | 2 - src/options/display.c | 113 ++++++++++++++++++++ src/options/display.h | 1 + 157 files changed, 638 insertions(+), 611 deletions(-) diff --git a/doc/help.json b/doc/help.json index e24d294fc7..d1a1482029 100644 --- a/doc/help.json +++ b/doc/help.json @@ -585,6 +585,30 @@ "default": "string" } }, + { + "long": "key-language", + "desc": "Specify the language used for module keys", + "remark": "Leave empty for auto-detection based on the system locale", + "arg": { + "type": "enum", + "default": "en", + "optional": true, + "enum": { + "en": "English", + "de": "German", + "es": "Spanish", + "fr": "French", + "it": "Italian", + "ja": "Japanese", + "ko": "Korean", + "pl": "Polish", + "pt_BR": "Brazilian Portuguese", + "ru": "Russian", + "zh_CN": "Simplified Chinese", + "zh_TW": "Traditional Chinese" + } + } + }, { "long": "bright-color", "desc": "Specify whether keys, title, and ASCII logo should be printed in bright color", diff --git a/doc/json_schema.json b/doc/json_schema.json index 797e03b4d9..01ef306de9 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1057,6 +1057,76 @@ "description": "Left padding for keys", "minimum": 0, "default": 0 + }, + "language": { + "description": "Language used for module keys. `null` for auto detection based on system locale", + "oneOf": [ + { + "type": "null", + "description": "Auto detection based on system locale" + }, + { + "type": "string", + "const": "en", + "description": "English" + }, + { + "type": "string", + "const": "de", + "description": "German" + }, + { + "type": "string", + "const": "es", + "description": "Spanish" + }, + { + "type": "string", + "const": "fr", + "description": "French" + }, + { + "type": "string", + "const": "it", + "description": "Italian" + }, + { + "type": "string", + "const": "ja", + "description": "Japanese" + }, + { + "type": "string", + "const": "ko", + "description": "Korean" + }, + { + "type": "string", + "const": "pl", + "description": "Polish" + }, + { + "type": "string", + "const": "pt_BR", + "description": "Brazilian Portuguese" + }, + { + "type": "string", + "const": "ru", + "description": "Russian" + }, + { + "type": "string", + "const": "zh_CN", + "description": "Simplified Chinese" + }, + { + "type": "string", + "const": "zh_TW", + "description": "Traditional Chinese" + } + ], + "default": "en" } } }, diff --git a/src/common/impl/commandoption.c b/src/common/impl/commandoption.c index c4225a711b..a8764d610c 100644 --- a/src/common/impl/commandoption.c +++ b/src/common/impl/commandoption.c @@ -67,13 +67,13 @@ void ffPrepareCommandOption(FFdata* data) { char* moduleType = nullptr; 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, ':')) +#define FF_IF_MODULE_MATCH(moduleNameConstant) if (ffStrEqualsIgnCase(moduleType, moduleNameConstant) && !ffStrbufSeparatedContainIgnCaseS(&data->structureDisabled, moduleNameConstant, ':')) switch (moduleType[0]) { #if !FF_MODULE_DISABLE_CPUUSAGE case 'C': case 'c': - FF_IF_MODULE_MATCH(FF_CPUUSAGE_MODULE_NAME) + FF_IF_MODULE_MATCH(ffCPUUsageModuleInfo.name) ffPrepareCPUUsage(); break; #endif @@ -81,7 +81,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_DISKIO case 'D': case 'd': - FF_IF_MODULE_MATCH(FF_DISKIO_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffDiskIOModuleInfo.name) { [[gnu::cleanup(ffDestroyDiskIOOptions)]] FFDiskIOOptions options; ffInitDiskIOOptions(&options); ffPrepareDiskIO(&options); @@ -92,7 +92,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_NETIO case 'N': case 'n': - FF_IF_MODULE_MATCH(FF_NETIO_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffNetIOModuleInfo.name) { [[gnu::cleanup(ffDestroyNetIOOptions)]] FFNetIOOptions options; ffInitNetIOOptions(&options); ffPrepareNetIO(&options); @@ -103,7 +103,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_PUBLICIP case 'P': case 'p': - FF_IF_MODULE_MATCH(FF_PUBLICIP_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffPublicIPModuleInfo.name) { [[gnu::cleanup(ffDestroyPublicIpOptions)]] FFPublicIPOptions options; ffInitPublicIpOptions(&options); ffPreparePublicIp(&options); @@ -114,7 +114,7 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_WEATHER case 'W': case 'w': - FF_IF_MODULE_MATCH(FF_WEATHER_MODULE_NAME) { + FF_IF_MODULE_MATCH(ffWeatherModuleInfo.name) { [[gnu::cleanup(ffDestroyWeatherOptions)]] FFWeatherOptions options; ffInitWeatherOptions(&options); ffPrepareWeather(&options); diff --git a/src/common/impl/jsonconfig.c b/src/common/impl/jsonconfig.c index 5179d5b5d3..7c9d44a88d 100644 --- a/src/common/impl/jsonconfig.c +++ b/src/common/impl/jsonconfig.c @@ -136,9 +136,9 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_CPUUSAGE case 'c': case 'C': { - if (ffStrEqualsIgnCase(type, FF_CPUUSAGE_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffCPUUsageModuleInfo.name)) { ffPrepareCPUUsage(); - } else if (ffStrEqualsIgnCase(type, FF_COMMAND_MODULE_NAME)) { + } else if (ffStrEqualsIgnCase(type, ffCommandModuleInfo.name)) { [[gnu::cleanup(ffDestroyCommandOptions)]] FFCommandOptions options; ffInitCommandOptions(&options); if (module) { @@ -153,7 +153,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_DISKIO case 'd': case 'D': { - if (ffStrEqualsIgnCase(type, FF_DISKIO_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffDiskIOModuleInfo.name)) { [[gnu::cleanup(ffDestroyDiskIOOptions)]] FFDiskIOOptions options; ffInitDiskIOOptions(&options); if (module) { @@ -168,7 +168,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_NETIO case 'n': case 'N': { - if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffNetIOModuleInfo.name)) { [[gnu::cleanup(ffDestroyNetIOOptions)]] FFNetIOOptions options; ffInitNetIOOptions(&options); if (module) { @@ -183,7 +183,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_PUBLICIP case 'p': case 'P': { - if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffPublicIPModuleInfo.name)) { [[gnu::cleanup(ffDestroyPublicIpOptions)]] FFPublicIPOptions options; ffInitPublicIpOptions(&options); if (module) { @@ -198,7 +198,7 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { #if !FF_MODULE_DISABLE_WEATHER case 'w': case 'W': { - if (ffStrEqualsIgnCase(type, FF_WEATHER_MODULE_NAME)) { + if (ffStrEqualsIgnCase(type, ffWeatherModuleInfo.name)) { [[gnu::cleanup(ffDestroyWeatherOptions)]] FFWeatherOptions options; ffInitWeatherOptions(&options); if (module) { diff --git a/src/common/option.h b/src/common/option.h index bda0316907..2647cd7ed3 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -111,3 +111,5 @@ static inline void ffOptionDestroyModuleArg(FFModuleArgs* args) { } enum { FF_OPTION_MAX_SIZE = 1 << 8 }; // Maximum size of a single option value, used for static allocation + +#define FF_MODULE_GET_DISPLAY_NAME(moduleName) (*(const char**) ((uint8_t*) &ff ## moduleName ## ModuleInfo.displayName + instance.config.display.keyLanguage)) diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index da2279624b..99a44b676f 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -11,9 +11,9 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (result->modelName.length > 0) { - ffStrbufSetF(&key, "%s (%s)", FF_BATTERY_MODULE_NAME, result->modelName.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Battery), result->modelName.chars); } else { - ffStrbufSetS(&key, FF_BATTERY_MODULE_NAME); + ffStrbufSetS(&key, FF_MODULE_GET_DISPLAY_NAME(Battery)); } } else { ffStrbufClear(&key); @@ -170,11 +170,11 @@ bool ffPrintBattery(FFBatteryOptions* options) { const char* error = ffDetectBattery(options, &results); if (error) { - ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No batteries found"); return false; } @@ -209,7 +209,7 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Battery), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -297,7 +297,7 @@ void ffDestroyBatteryOptions(FFBatteryOptions* options) { } FFModuleBaseInfo ffBatteryModuleInfo = { - .name = FF_BATTERY_MODULE_NAME, + .name = "Battery", .description = "Print battery information", .displayName = { .en = "Battery", diff --git a/src/modules/battery/battery.h b/src/modules/battery/battery.h index 16ad027d80..7157b51a72 100644 --- a/src/modules/battery/battery.h +++ b/src/modules/battery/battery.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BATTERY_MODULE_NAME "Battery" - bool ffPrintBattery(FFBatteryOptions* options); void ffInitBatteryOptions(FFBatteryOptions* options); void ffDestroyBatteryOptions(FFBatteryOptions* options); diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index b494dae21d..94e6022289 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -18,12 +18,12 @@ bool ffPrintBios(FFBiosOptions* options) { FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (error) { - ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (bios.version.length == 0) { - ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "bios_version is not set."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "bios_version is not set."); goto exit; } @@ -34,7 +34,7 @@ bool ffPrintBios(FFBiosOptions* options) { ffStrbufSetStatic(&bios.type, "Legacy"); } - ffStrbufSetF(&key, FF_BIOS_MODULE_NAME " (%s)", bios.type.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Bios), bios.type.chars); } else { ffStrbufClear(&key); FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -80,7 +80,7 @@ void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bios), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -130,7 +130,7 @@ void ffDestroyBiosOptions(FFBiosOptions* options) { } FFModuleBaseInfo ffBiosModuleInfo = { - .name = FF_BIOS_MODULE_NAME, + .name = "BIOS", .description = "Print first-stage bootloader information (name, version, release date, etc.)", .displayName = { .en = "BIOS", diff --git a/src/modules/bios/bios.h b/src/modules/bios/bios.h index d3b077e4d1..d34978d8da 100644 --- a/src/modules/bios/bios.h +++ b/src/modules/bios/bios.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BIOS_MODULE_NAME "BIOS" - bool ffPrintBios(FFBiosOptions* options); void ffInitBiosOptions(FFBiosOptions* options); void ffDestroyBiosOptions(FFBiosOptions* options); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 50d4de366e..232728dc52 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -8,7 +8,7 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* device, uint8_t index) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); bool showBatteryLevel = device->battery > 0 && device->battery <= 100; @@ -44,7 +44,7 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* de ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_BLUETOOTH_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->address, "address"), FF_ARG(device->type, "type"), @@ -60,12 +60,12 @@ bool ffPrintBluetooth(FFBluetoothOptions* options) { const char* error = ffDetectBluetooth(options, &devices); if (error) { - ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (devices.length == 0) { - ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No bluetooth devices found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No bluetooth devices found"); return false; } @@ -100,7 +100,7 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bluetooth), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -151,7 +151,7 @@ void ffDestroyBluetoothOptions(FFBluetoothOptions* options) { } FFModuleBaseInfo ffBluetoothModuleInfo = { - .name = FF_BLUETOOTH_MODULE_NAME, + .name = "Bluetooth", .description = "List connected Bluetooth devices", .displayName = { .en = "Bluetooth", diff --git a/src/modules/bluetooth/bluetooth.h b/src/modules/bluetooth/bluetooth.h index d9aa059e37..fc6fdd8ce4 100644 --- a/src/modules/bluetooth/bluetooth.h +++ b/src/modules/bluetooth/bluetooth.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BLUETOOTH_MODULE_NAME "Bluetooth" - bool ffPrintBluetooth(FFBluetoothOptions* options); void ffInitBluetoothOptions(FFBluetoothOptions* options); void ffDestroyBluetoothOptions(FFBluetoothOptions* options); diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 911519997d..1419eaec5e 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -5,8 +5,6 @@ #include "detection/bluetoothradio/bluetoothradio.h" #include "modules/bluetoothradio/bluetoothradio.h" -#define FF_BLUETOOTHRADIO_DISPLAY_NAME "Bluetooth Radio" - static void destroyBluetoothRadios(FFlist* radios) { FF_LIST_FOR_EACH (FFBluetoothRadioResult, radio, *radios) { ffStrbufDestroy(&radio->name); @@ -18,7 +16,7 @@ static void destroyBluetoothRadios(FFlist* radios) { static void printDevice(FFBluetoothRadioOptions* options, const FFBluetoothRadioResult* radio, uint8_t index) { FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { - ffStrbufAppendF(&key, "%s (%s)", FF_BLUETOOTHRADIO_DISPLAY_NAME, radio->name.chars); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), radio->name.chars); } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { FF_ARG(index, "index"), @@ -101,7 +99,7 @@ bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) { const char* error = ffDetectBluetoothRadio(&radios); if (error) { - ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -117,9 +115,9 @@ bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options) { if (index == 0) { if (radios.length > 0) { - ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Bluetooth radios found but none enabled"); } else { - ffPrintError(FF_BLUETOOTHRADIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); } destroyBluetoothRadios(&radios); return false; @@ -137,7 +135,7 @@ void ffParseBluetoothRadioJsonObject(FFBluetoothRadioOptions* options, yyjson_va continue; } - ffPrintError(FF_BLUETOOTHRADIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(BluetoothRadio), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -190,7 +188,7 @@ void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options) { } FFModuleBaseInfo ffBluetoothRadioModuleInfo = { - .name = FF_BLUETOOTHRADIO_MODULE_NAME, + .name = "BluetoothRadio", .description = "List Bluetooth radios (supported versions, vendors, etc.)", .displayName = { .en = "Bluetooth Radio", diff --git a/src/modules/bluetoothradio/bluetoothradio.h b/src/modules/bluetoothradio/bluetoothradio.h index 4707f1ba5e..391ea64a07 100644 --- a/src/modules/bluetoothradio/bluetoothradio.h +++ b/src/modules/bluetoothradio/bluetoothradio.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BLUETOOTHRADIO_MODULE_NAME "BluetoothRadio" - bool ffPrintBluetoothRadio(FFBluetoothRadioOptions* options); void ffInitBluetoothRadioOptions(FFBluetoothRadioOptions* options); void ffDestroyBluetoothRadioOptions(FFBluetoothRadioOptions* options); diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 070070a01c..324bfe95b3 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -14,24 +14,24 @@ bool ffPrintBoard(FFBoardOptions* options) { const char* error = ffDetectBoard(&result); if (error) { - ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (result.name.length == 0) { - ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "board_name is not set."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "board_name is not set."); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.name, stdout); if (result.version.length) { printf(" (%s)", result.version.chars); } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.name, "name"), FF_ARG(result.vendor, "vendor"), FF_ARG(result.version, "version"), @@ -56,7 +56,7 @@ void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Board), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -108,7 +108,7 @@ void ffDestroyBoardOptions(FFBoardOptions* options) { } FFModuleBaseInfo ffBoardModuleInfo = { - .name = FF_BOARD_MODULE_NAME, + .name = "Board", .description = "Print motherboard name and other information", .displayName = { .en = "Board", diff --git a/src/modules/board/board.h b/src/modules/board/board.h index eae3d73c11..af819fbbaa 100644 --- a/src/modules/board/board.h +++ b/src/modules/board/board.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BOARD_MODULE_NAME "Board" - bool ffPrintBoard(FFBoardOptions* options); void ffInitBoardOptions(FFBoardOptions* options); void ffDestroyBoardOptions(FFBoardOptions* options); diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 037de24bd2..d45030225a 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -14,7 +14,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) { const char* error = ffDetectBootmgr(&bootmgr); if (error) { - ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } else { FF_STRBUF_AUTO_DESTROY firmwareName = ffStrbufCreateCopy(&bootmgr.firmware); @@ -25,7 +25,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) { #endif if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&bootmgr.name, stdout); if (firmwareName.length > 0) { printf(" - %s\n", firmwareName.chars); @@ -33,7 +33,7 @@ bool ffPrintBootmgr(FFBootmgrOptions* options) { putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(bootmgr.name, "name"), FF_ARG(bootmgr.firmware, "firmware-path"), FF_ARG(firmwareName, "firmware-name"), @@ -59,7 +59,7 @@ void ffParseBootmgrJsonObject(FFBootmgrOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Bootmgr), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -103,7 +103,7 @@ void ffDestroyBootmgrOptions(FFBootmgrOptions* options) { } FFModuleBaseInfo ffBootmgrModuleInfo = { - .name = FF_BOOTMGR_MODULE_NAME, + .name = "Bootmgr", .description = "Print second-stage bootloader information (name, firmware, etc.)", .displayName = { .en = "Boot Manager", diff --git a/src/modules/bootmgr/bootmgr.h b/src/modules/bootmgr/bootmgr.h index 4f6a2bac25..947163bd5a 100644 --- a/src/modules/bootmgr/bootmgr.h +++ b/src/modules/bootmgr/bootmgr.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BOOTMGR_MODULE_NAME "Bootmgr" - bool ffPrintBootmgr(FFBootmgrOptions* options); void ffInitBootmgrOptions(FFBootmgrOptions* options); void ffDestroyBootmgrOptions(FFBootmgrOptions* options); diff --git a/src/modules/break/break.c b/src/modules/break/break.c index c627f339b8..b66963ecda 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -16,7 +16,7 @@ void ffParseBreakJsonObject([[maybe_unused]] FFBreakOptions* options, [[maybe_un continue; } - ffPrintError(FF_BREAK_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Break), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -27,7 +27,7 @@ void ffDestroyBreakOptions([[maybe_unused]] FFBreakOptions* options) { } FFModuleBaseInfo ffBreakModuleInfo = { - .name = FF_BREAK_MODULE_NAME, + .name = "Break", .description = "Print an empty line", .displayName = { .en = "Break", diff --git a/src/modules/break/break.h b/src/modules/break/break.h index f611b73790..9b11ebad89 100644 --- a/src/modules/break/break.h +++ b/src/modules/break/break.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BREAK_MODULE_NAME "Break" - bool ffPrintBreak(FFBreakOptions* options); void ffInitBreakOptions(FFBreakOptions* options); void ffDestroyBreakOptions(FFBreakOptions* options); diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 835711c2c1..28fa28be0c 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -11,12 +11,12 @@ bool ffPrintBrightness(FFBrightnessOptions* options) { const char* error = ffDetectBrightness(options, &result); if (error) { - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result is detected."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result is detected."); return false; } @@ -34,7 +34,7 @@ bool ffPrintBrightness(FFBrightnessOptions* options) { ffPercentAppendNum(&str, percent, options->percent, false, &options->moduleArgs); } - ffPrintLogoAndKey(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&str, stdout); return true; } @@ -44,7 +44,7 @@ bool ffPrintBrightness(FFBrightnessOptions* options) { uint32_t index = 0; FF_LIST_FOR_EACH (FFBrightnessResult, item, result) { if (options->moduleArgs.key.length == 0) { - ffStrbufAppendF(&key, "%s (%s)", FF_BRIGHTNESS_MODULE_NAME, item->name.chars); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Brightness), item->name.chars); } else { uint32_t moduleIndex = result.length == 1 ? 0 : index + 1; FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -130,7 +130,7 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul continue; } - ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Brightness), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -190,7 +190,7 @@ void ffDestroyBrightnessOptions(FFBrightnessOptions* options) { } FFModuleBaseInfo ffBrightnessModuleInfo = { - .name = FF_BRIGHTNESS_MODULE_NAME, + .name = "Brightness", .description = "Print the current brightness level of your monitors", .displayName = { .en = "Brightness", diff --git a/src/modules/brightness/brightness.h b/src/modules/brightness/brightness.h index 085366141f..0e03c1ce34 100644 --- a/src/modules/brightness/brightness.h +++ b/src/modules/brightness/brightness.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BRIGHTNESS_MODULE_NAME "Brightness" - bool ffPrintBrightness(FFBrightnessOptions* options); void ffInitBrightnessOptions(FFBrightnessOptions* options); void ffDestroyBrightnessOptions(FFBrightnessOptions* options); diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 12ed8977b8..442a4406d3 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -10,9 +10,9 @@ static void printBtrfs(FFBtrfsOptions* options, FFBtrfsResult* result, uint8_t i FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (result->name.length > 0) { - ffStrbufSetF(&buffer, "%s (%s)", FF_BTRFS_MODULE_NAME, result->name.chars); + ffStrbufSetF(&buffer, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Btrfs), result->name.chars); } else { - ffStrbufSetS(&buffer, FF_BTRFS_MODULE_NAME); + ffStrbufSetS(&buffer, FF_MODULE_GET_DISPLAY_NAME(Btrfs)); } } else { ffStrbufClear(&buffer); @@ -100,11 +100,11 @@ bool ffPrintBtrfs(FFBtrfsOptions* options) { const char* error = ffDetectBtrfs(&results); if (error) { - ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No btrfs drive found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No btrfs drive found"); return false; } @@ -136,7 +136,7 @@ void ffParseBtrfsJsonObject(FFBtrfsOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_BTRFS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Btrfs), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -198,7 +198,7 @@ void ffDestroyBtrfsOptions(FFBtrfsOptions* options) { } FFModuleBaseInfo ffBtrfsModuleInfo = { - .name = FF_BTRFS_MODULE_NAME, + .name = "Btrfs", .description = "Print Linux BTRFS volumes", .displayName = { .en = "BTRFS", diff --git a/src/modules/btrfs/btrfs.h b/src/modules/btrfs/btrfs.h index fc0c6abf4b..813ff8a2b5 100644 --- a/src/modules/btrfs/btrfs.h +++ b/src/modules/btrfs/btrfs.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_BTRFS_MODULE_NAME "Btrfs" - bool ffPrintBtrfs(FFBtrfsOptions* options); void ffInitBtrfsOptions(FFBtrfsOptions* options); void ffDestroyBtrfsOptions(FFBtrfsOptions* options); diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 4a35509c04..f748310652 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -5,7 +5,7 @@ static void printDevice(FFCameraOptions* options, const FFCameraResult* device, uint8_t index) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&device->name, stdout); if (device->colorspace.length > 0) { @@ -19,7 +19,7 @@ static void printDevice(FFCameraOptions* options, const FFCameraResult* device, putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_CAMERA_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Camera), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->vendor, "vendor"), FF_ARG(device->colorspace, "colorspace"), @@ -35,12 +35,12 @@ bool ffPrintCamera(FFCameraOptions* options) { const char* error = ffDetectCamera(&result); if (error) { - ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No camera found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No camera found"); return false; } @@ -67,7 +67,7 @@ void ffParseCameraJsonObject(FFCameraOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CAMERA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Camera), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -115,7 +115,7 @@ void ffDestroyCameraOptions(FFCameraOptions* options) { } FFModuleBaseInfo ffCameraModuleInfo = { - .name = FF_CAMERA_MODULE_NAME, + .name = "Camera", .description = "Print available cameras", .displayName = { .en = "Camera", diff --git a/src/modules/camera/camera.h b/src/modules/camera/camera.h index e8b3560400..f87a8595ec 100644 --- a/src/modules/camera/camera.h +++ b/src/modules/camera/camera.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CAMERA_MODULE_NAME "Camera" - bool ffPrintCamera(FFCameraOptions* options); void ffInitCameraOptions(FFCameraOptions* options); void ffDestroyCameraOptions(FFCameraOptions* options); diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 2a88c5c89b..ae25f19b6e 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -16,24 +16,24 @@ bool ffPrintChassis(FFChassisOptions* options) { const char* error = ffDetectChassis(&result); if (error) { - ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (result.type.length == 0) { - ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "chassis_type is not set by O.E.M."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "chassis_type is not set by O.E.M."); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.type, stdout); if (result.version.length) { printf(" (%s)", result.version.chars); } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.type, "type"), FF_ARG(result.vendor, "vendor"), FF_ARG(result.version, "version"), @@ -58,7 +58,7 @@ void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Chassis), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -110,7 +110,7 @@ void ffDestroyChassisOptions(FFChassisOptions* options) { } FFModuleBaseInfo ffChassisModuleInfo = { - .name = FF_CHASSIS_MODULE_NAME, + .name = "Chassis", .description = "Print chassis type information (desktop, laptop, etc.)", .displayName = { .en = "Chassis", diff --git a/src/modules/chassis/chassis.h b/src/modules/chassis/chassis.h index d3ba4892cb..a57f7b876c 100644 --- a/src/modules/chassis/chassis.h +++ b/src/modules/chassis/chassis.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CHASSIS_MODULE_NAME "Chassis" - bool ffPrintChassis(FFChassisOptions* options); void ffInitChassisOptions(FFChassisOptions* options); void ffDestroyChassisOptions(FFChassisOptions* options); diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index f55ed20e5f..f71dfe2834 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -51,9 +51,9 @@ static void printCodecLine(const FFCodecOptions* options, uint8_t index, FFstrbu FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (gpu->length > 0) { - ffStrbufSetF(&key, "%s (%s - %s)", FF_CODEC_MODULE_NAME, direction, gpu->chars); + ffStrbufSetF(&key, "%s (%s - %s)", FF_MODULE_GET_DISPLAY_NAME(Codec), direction, gpu->chars); } else { - ffStrbufSetF(&key, "%s (%s)", FF_CODEC_MODULE_NAME, direction); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Codec), direction); } } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]){ @@ -100,12 +100,12 @@ bool ffPrintCodec(FFCodecOptions* options) { const char* error = ffDetectCodec(options, &result); if (error) { - ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware video acceleration found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No hardware video acceleration found"); return false; } @@ -174,14 +174,14 @@ void ffParseCodecJsonObject(FFCodecOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_CODEC_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->showType = (FFCodecShowType) value; } continue; } - ffPrintError(FF_CODEC_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Codec), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -251,7 +251,7 @@ void ffDestroyCodecOptions(FFCodecOptions* options) { } FFModuleBaseInfo ffCodecModuleInfo = { - .name = FF_CODEC_MODULE_NAME, + .name = "Codec", .description = "Print hardware video acceleration codec types (decode / encode)", .displayName = { .en = "Codec", diff --git a/src/modules/codec/codec.h b/src/modules/codec/codec.h index efd3d7c018..20b9fbd35c 100644 --- a/src/modules/codec/codec.h +++ b/src/modules/codec/codec.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CODEC_MODULE_NAME "Codec" - bool ffPrintCodec(FFCodecOptions* options); void ffInitCodecOptions(FFCodecOptions* options); void ffDestroyCodecOptions(FFCodecOptions* options); diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index ba6890c672..ac1ef742fb 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -37,7 +37,7 @@ bool ffPrintColors(FFColorsOptions* options) { } } if (result.length > 0) { - ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); flag = true; if (options->paddingLeft > 0) { @@ -122,7 +122,7 @@ bool ffPrintColors(FFColorsOptions* options) { if (flag) { ffLogoPrintLine(); } else { - ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); flag = true; } @@ -136,7 +136,7 @@ bool ffPrintColors(FFColorsOptions* options) { } if (!flag) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Nothing to print"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Nothing to print"); return false; } @@ -164,7 +164,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->symbol = (FFColorsSymbol) value; } @@ -178,7 +178,7 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "block")) { if (!yyjson_is_obj(val)) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: must be an object", unsafe_yyjson_get_str(key)); } else { yyjson_val* width = yyjson_obj_get(val, "width"); if (width) { @@ -188,14 +188,14 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { yyjson_val* range = yyjson_obj_get(val, "range"); if (range) { if (!yyjson_is_arr(range) || yyjson_arr_size(range) != 2) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: must be an array of 2 elements", unsafe_yyjson_get_str(key)); } else { uint8_t start = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 0)); uint8_t end = (uint8_t) yyjson_get_uint(yyjson_arr_get(range, 1)); if (start > end) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[0] > range[1]", unsafe_yyjson_get_str(key)); } else if (end > 15) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s.range value: range[1] > 15", unsafe_yyjson_get_str(key)); } else { options->block.range[0] = start; options->block.range[1] = end; @@ -215,14 +215,14 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->brightness = (FFColorsBrightness) value; } continue; } - ffPrintError(FF_COLORS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Colors), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -295,7 +295,7 @@ void ffDestroyColorsOptions(FFColorsOptions* options) { } FFModuleBaseInfo ffColorsModuleInfo = { - .name = FF_COLORS_MODULE_NAME, + .name = "Colors", .description = "Display the terminal's 16-color palette", .displayName = { .en = "Colors", diff --git a/src/modules/colors/colors.h b/src/modules/colors/colors.h index c88ccd7a50..d7558aff77 100644 --- a/src/modules/colors/colors.h +++ b/src/modules/colors/colors.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_COLORS_MODULE_NAME "Colors" - bool ffPrintColors(FFColorsOptions* options); void ffInitColorsOptions(FFColorsOptions* options); void ffDestroyColorsOptions(FFColorsOptions* options); diff --git a/src/modules/command/command.c b/src/modules/command/command.c index b86da3a17e..d606e033fe 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -8,12 +8,12 @@ bool ffPrintCommand(FFCommandOptions* options) { const char* error = ffDetectCommand(options, &result); if (error) { - ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result generated"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No result generated"); return false; } @@ -23,18 +23,18 @@ bool ffPrintCommand(FFCommandOptions* options) { size_t len = 0; while (ffStrbufGetline(&line, &len, &result)) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Command), ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(line); } else { - FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(line, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Command), ++index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(line, "result") })); } } } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&result, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result") })); } } @@ -79,7 +79,7 @@ void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Command), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -153,7 +153,7 @@ void ffDestroyCommandOptions(FFCommandOptions* options) { } FFModuleBaseInfo ffCommandModuleInfo = { - .name = FF_COMMAND_MODULE_NAME, + .name = "Command", .description = "Run custom shell scripts", .displayName = { .en = "Command", diff --git a/src/modules/command/command.h b/src/modules/command/command.h index e0e143e016..bd55f3fbd9 100644 --- a/src/modules/command/command.h +++ b/src/modules/command/command.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_COMMAND_MODULE_NAME "Command" - bool ffPrepareCommand(FFCommandOptions* options); bool ffPrintCommand(FFCommandOptions* options); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 5cccddba26..20236c9dd1 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -23,9 +23,9 @@ bool ffPrintCPU(FFCPUOptions* options) { const char* error = ffDetectCPU(options, &cpu); if (error) { - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); } else if (cpu.vendor.length == 0 && cpu.name.length == 0 && cpu.coresOnline <= 1) { - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No CPU detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No CPU detected"); } else { FF_STRBUF_AUTO_DESTROY coreTypes = ffStrbufCreate(); if (options->showPeCoreCount) { @@ -43,7 +43,7 @@ bool ffPrintCPU(FFCPUOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); @@ -85,7 +85,7 @@ bool ffPrintCPU(FFCPUOptions* options) { FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs); - FF_PRINT_FORMAT_CHECKED(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(cpu.name, "name"), FF_ARG(cpu.vendor, "vendor"), FF_ARG(cpu.coresPhysical, "cores-physical"), @@ -131,7 +131,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) { } if (unsafe_yyjson_equals_str(key, "freqNdigits")) { - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "modules.CPU.freqNdigits has been moved to display.freq.ndigits"); continue; } @@ -140,7 +140,7 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -251,7 +251,7 @@ void ffDestroyCPUOptions(FFCPUOptions* options) { } FFModuleBaseInfo ffCPUModuleInfo = { - .name = FF_CPU_MODULE_NAME, + .name = "CPU", .description = "Print CPU name, frequency, etc.", .displayName = { .en = "CPU", diff --git a/src/modules/cpu/cpu.h b/src/modules/cpu/cpu.h index 33fff6bf5b..ce816a7725 100644 --- a/src/modules/cpu/cpu.h +++ b/src/modules/cpu/cpu.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CPU_MODULE_NAME "CPU" - bool ffPrintCPU(FFCPUOptions* options); void ffInitCPUOptions(FFCPUOptions* options); void ffDestroyCPUOptions(FFCPUOptions* options); diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 4fe29a7356..1c5c3e8580 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -5,8 +5,6 @@ #include "detection/cpucache/cpucache.h" #include "modules/cpucache/cpucache.h" -#define FF_CPUCACHE_DISPLAY_NAME "CPU Cache" - static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOptions* options) { FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); @@ -16,7 +14,7 @@ static void printCPUCacheNormal(const FFCPUCacheResult* result, FFCPUCacheOption ffStrbufClear(&key); levelStr[1] = (char) ('1' + i); if (options->moduleArgs.key.length == 0) { - ffStrbufAppendF(&key, "%s (%s)", FF_CPUCACHE_DISPLAY_NAME, levelStr); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(CPUCache), levelStr); } else { uint32_t index = i + 1; FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -88,12 +86,12 @@ static void printCPUCacheCompact(const FFCPUCacheResult* result, FFCPUCacheOptio } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&buffer, stdout); } else { FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); ffSizeAppendNum(sum, &buffer2); - FF_PRINT_FORMAT_CHECKED(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(buffer, "result"), FF_ARG(buffer2, "sum"), })); @@ -114,7 +112,7 @@ bool ffPrintCPUCache(FFCPUCacheOptions* options) { const char* error = ffDetectCPUCache(&result); if (error) { - ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } @@ -147,7 +145,7 @@ void ffParseCPUCacheJsonObject(FFCPUCacheOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CPUCACHE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUCache), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -223,7 +221,7 @@ void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options) { } FFModuleBaseInfo ffCPUCacheModuleInfo = { - .name = FF_CPUCACHE_MODULE_NAME, + .name = "CPUCache", .description = "Print CPU cache sizes", .displayName = { .en = "CPU Cache", diff --git a/src/modules/cpucache/cpucache.h b/src/modules/cpucache/cpucache.h index 5061b44417..2bc16fe5f3 100644 --- a/src/modules/cpucache/cpucache.h +++ b/src/modules/cpucache/cpucache.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CPUCACHE_MODULE_NAME "CPUCache" - bool ffPrintCPUCache(FFCPUCacheOptions* options); void ffInitCPUCacheOptions(FFCPUCacheOptions* options); void ffDestroyCPUCacheOptions(FFCPUCacheOptions* options); diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index d9d342bb93..5c9a4135ab 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -5,14 +5,12 @@ #include "detection/cpuusage/cpuusage.h" #include "modules/cpuusage/cpuusage.h" -#define FF_CPUUSAGE_DISPLAY_NAME "CPU Usage" - bool ffPrintCPUUsage(FFCPUUsageOptions* options) { FF_LIST_AUTO_DESTROY percentages = ffListCreate(); const char* error = ffGetCpuUsageResult(options, &percentages); if (error) { - ffPrintError(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -54,7 +52,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); if (!options->separate) { @@ -102,7 +100,7 @@ bool ffPrintCPUUsage(FFCPUUsageOptions* options) { ffPercentAppendBar(&maxBar, maxValue, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_CPUUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(avgNum, "avg"), FF_ARG(maxNum, "max"), FF_ARG(maxIndex, "max-index"), @@ -139,7 +137,7 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(CPUUsage), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -181,7 +179,7 @@ void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) { } FFModuleBaseInfo ffCPUUsageModuleInfo = { - .name = FF_CPUUSAGE_MODULE_NAME, + .name = "CPUUsage", .description = "Print CPU usage. Collecting data takes some time", .displayName = { .en = "CPU Usage", diff --git a/src/modules/cpuusage/cpuusage.h b/src/modules/cpuusage/cpuusage.h index efa8b485cc..bd009a833f 100644 --- a/src/modules/cpuusage/cpuusage.h +++ b/src/modules/cpuusage/cpuusage.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CPUUSAGE_MODULE_NAME "CPUUsage" - void ffPrepareCPUUsage(); bool ffPrintCPUUsage(FFCPUUsageOptions* options); diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 74c8c65e59..04808456f0 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -14,7 +14,7 @@ bool ffPrintCursor(FFCursorOptions* options) { ffDetectCursor(&result); if (result.error.length) { - ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result.error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result.error.chars); } else { ffStrbufRemoveIgnCaseEndS(&result.theme, "cursors"); ffStrbufRemoveIgnCaseEndS(&result.theme, "cursor"); @@ -25,7 +25,7 @@ bool ffPrintCursor(FFCursorOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.theme, stdout); if (result.size.length > 0 && !ffStrbufEqualS(&result.size, "0")) { @@ -34,7 +34,7 @@ bool ffPrintCursor(FFCursorOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.theme, "theme"), FF_ARG(result.size, "size"), })); @@ -58,7 +58,7 @@ void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Cursor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -100,7 +100,7 @@ void ffDestroyCursorOptions(FFCursorOptions* options) { } FFModuleBaseInfo ffCursorModuleInfo = { - .name = FF_CURSOR_MODULE_NAME, + .name = "Cursor", .description = "Print cursor style name", .displayName = { .en = "Cursor", diff --git a/src/modules/cursor/cursor.h b/src/modules/cursor/cursor.h index e7695692cd..e94a259b57 100644 --- a/src/modules/cursor/cursor.h +++ b/src/modules/cursor/cursor.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CURSOR_MODULE_NAME "Cursor" - bool ffPrintCursor(FFCursorOptions* options); void ffInitCursorOptions(FFCursorOptions* options); void ffDestroyCursorOptions(FFCursorOptions* options); diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 0806be5b52..e728b634b1 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -5,7 +5,7 @@ #include "modules/custom/custom.h" bool ffPrintCustom(FFCustomOptions* options) { - ffPrintFormat(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, 0, ((FFformatarg[]) {})); + ffPrintFormat(FF_MODULE_GET_DISPLAY_NAME(Custom), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, 0, ((FFformatarg[]) {})); return true; } @@ -21,7 +21,7 @@ void ffParseCustomJsonObject(FFCustomOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Custom), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -35,7 +35,7 @@ void ffDestroyCustomOptions(FFCustomOptions* options) { } FFModuleBaseInfo ffCustomModuleInfo = { - .name = FF_CUSTOM_MODULE_NAME, + .name = "Custom", .description = "Print a custom string, with or without key", .displayName = { .en = "Custom", diff --git a/src/modules/custom/custom.h b/src/modules/custom/custom.h index 628a621a32..f84dd1266d 100644 --- a/src/modules/custom/custom.h +++ b/src/modules/custom/custom.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_CUSTOM_MODULE_NAME "Custom" - bool ffPrintCustom(FFCustomOptions* options); void ffInitCustomOptions(FFCustomOptions* options); void ffDestroyCustomOptions(FFCustomOptions* options); diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index b8bbb6d43a..347b81d534 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -8,8 +8,6 @@ #pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format -#define FF_DATETIME_DISPLAY_NAME "Date & Time" - typedef struct FFDateTimeResult { // Examples for 21.02.2022 - 15:18:37 uint16_t year; // 2022 @@ -67,7 +65,7 @@ static void printDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) { strftime(result.amPm, sizeof(result.amPm), "%p", tm); FF_PRINT_FORMAT_CHECKED( - FF_DATETIME_DISPLAY_NAME, + FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, moduleArgs, FF_PRINT_TYPE_DEFAULT, @@ -112,11 +110,11 @@ bool ffPrintDateTime(FFDateTimeOptions* options) { char buffer[32]; if (strftime(buffer, ARRAY_SIZE(buffer), "%F %T", tm) == 0) // yyyy-MM-dd HH:mm:ss { - ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "strftime() failed"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "strftime() failed"); return false; } - ffPrintLogoAndKey(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(buffer); return true; @@ -130,7 +128,7 @@ void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DateTime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -152,7 +150,7 @@ void ffDestroyDateTimeOptions(FFDateTimeOptions* options) { } FFModuleBaseInfo ffDateTimeModuleInfo = { - .name = FF_DATETIME_MODULE_NAME, + .name = "DateTime", .description = "Print the current date and time", .displayName = { .en = "Date & Time", diff --git a/src/modules/datetime/datetime.h b/src/modules/datetime/datetime.h index 29c6f54e41..44123ed1a6 100644 --- a/src/modules/datetime/datetime.h +++ b/src/modules/datetime/datetime.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DATETIME_MODULE_NAME "DateTime" - bool ffPrintDateTime(FFDateTimeOptions* options); void ffInitDateTimeOptions(FFDateTimeOptions* options); void ffDestroyDateTimeOptions(FFDateTimeOptions* options); diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 3111343d7d..628cf49b45 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -9,7 +9,7 @@ bool ffPrintDE(FFDEOptions* options) { const FFDisplayServerResult* result = ffConnectDisplayServer(); if (result->dePrettyName.length == 0) { - ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No DE found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No DE found"); return false; } @@ -17,7 +17,7 @@ bool ffPrintDE(FFDEOptions* options) { ffDetectDEVersion(&result->dePrettyName, &version, options); if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result->dePrettyName, stdout); @@ -28,7 +28,7 @@ bool ffPrintDE(FFDEOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->deProcessName, "process-name"), FF_ARG(result->dePrettyName, "pretty-name"), FF_ARG(version, "version") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->deProcessName, "process-name"), FF_ARG(result->dePrettyName, "pretty-name"), FF_ARG(version, "version") })); } return true; @@ -43,11 +43,11 @@ void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module) { } if (unsafe_yyjson_equals_str(key, "slowVersionDetection")) { - ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Key `slowVersionDetection` is deprecated, it's always true"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Key `slowVersionDetection` is deprecated, it's always true"); continue; } - ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DE), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -82,7 +82,7 @@ void ffDestroyDEOptions(FFDEOptions* options) { } FFModuleBaseInfo ffDEModuleInfo = { - .name = FF_DE_MODULE_NAME, + .name = "DE", .description = "Print desktop environment name", .displayName = { .en = "Desktop Environment", diff --git a/src/modules/de/de.h b/src/modules/de/de.h index 8aaf642d07..857524bd7c 100644 --- a/src/modules/de/de.h +++ b/src/modules/de/de.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DE_MODULE_NAME "DE" - bool ffPrintDE(FFDEOptions* options); void ffInitDEOptions(FFDEOptions* options); void ffDestroyDEOptions(FFDEOptions* options); diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 891d2af613..11d6962945 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -16,7 +16,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(&key, "%s (%s)", FF_DISK_MODULE_NAME, disk->mountpoint.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Disk), disk->mountpoint.chars); } else { FF_STRBUF_AUTO_DESTROY mountpointLink = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY nameLink = ffStrbufCreate(); @@ -187,12 +187,12 @@ bool ffPrintDisk(FFDiskOptions* options) { const char* error = ffDetectDisks(options, &disks); if (error) { - ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Disk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (disks.length == 0) { - ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No disks found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Disk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No disks found"); return false; } @@ -327,7 +327,7 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Disk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -451,7 +451,7 @@ void ffDestroyDiskOptions(FFDiskOptions* options) { } FFModuleBaseInfo ffDiskModuleInfo = { - .name = FF_DISK_MODULE_NAME, + .name = "Disk", .description = "Print partitions, space usage, file system, etc", .displayName = { .en = "Disk", diff --git a/src/modules/disk/disk.h b/src/modules/disk/disk.h index 5f7820ac7c..4d5bf76ad7 100644 --- a/src/modules/disk/disk.h +++ b/src/modules/disk/disk.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DISK_MODULE_NAME "Disk" - bool ffPrintDisk(FFDiskOptions* options); void ffInitDiskOptions(FFDiskOptions* options); void ffDestroyDiskOptions(FFDiskOptions* options); diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 5f31a1eb1e..9acfbe5112 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -5,15 +5,13 @@ #include "detection/diskio/diskio.h" #include "modules/diskio/diskio.h" -#define FF_DISKIO_DISPLAY_NAME "Disk IO" - static int sortDevices(const FFDiskIOResult* left, const FFDiskIOResult* right) { return ffStrbufComp(&left->name, &right->name); } static void formatKey(const FFDiskIOOptions* options, FFDiskIOResult* dev, uint32_t index, FFstrbuf* key) { if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(key, FF_DISKIO_DISPLAY_NAME " (%s)", dev->name.length ? dev->name.chars : dev->devPath.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(DiskIO), dev->name.length ? dev->name.chars : dev->devPath.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -30,7 +28,7 @@ bool ffPrintDiskIO(FFDiskIOOptions* options) { const char* error = ffDetectDiskIO(&result, options); if (error) { - ffPrintError(FF_DISKIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DiskIO), 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, "%s", error); return false; } @@ -116,7 +114,7 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DiskIO), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -172,7 +170,7 @@ void ffDestroyDiskIOOptions(FFDiskIOOptions* options) { } FFModuleBaseInfo ffDiskIOModuleInfo = { - .name = FF_DISKIO_MODULE_NAME, + .name = "DiskIO", .description = "Print physical disk I/O throughput", .displayName = { .en = "Disk I/O", diff --git a/src/modules/diskio/diskio.h b/src/modules/diskio/diskio.h index 7fba81c9de..4bbfc3492d 100644 --- a/src/modules/diskio/diskio.h +++ b/src/modules/diskio/diskio.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DISKIO_MODULE_NAME "DiskIO" - void ffPrepareDiskIO(FFDiskIOOptions* options); bool ffPrintDiskIO(FFDiskIOOptions* options); diff --git a/src/modules/display/display.c b/src/modules/display/display.c index e6870538a6..2df6c787cc 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -19,7 +19,7 @@ bool ffPrintDisplay(FFDisplayOptions* options) { const FFDisplayServerResult* dsResult = ffConnectDisplayServer(); if (dsResult->displays.length == 0) { - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect display"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect display"); return false; } @@ -28,7 +28,7 @@ bool ffPrintDisplay(FFDisplayOptions* options) { } if (options->compactType != FF_DISPLAY_COMPACT_TYPE_NONE) { - ffPrintLogoAndKey(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_LIST_FOR_EACH (FFDisplayResult, result, dsResult->displays) { @@ -71,11 +71,11 @@ bool ffPrintDisplay(FFDisplayOptions* options) { ffStrbufClear(&key); if (options->moduleArgs.key.length == 0) { if (result->name.length) { - ffStrbufAppendF(&key, "%s (%s)", FF_DISPLAY_MODULE_NAME, result->name.chars); + ffStrbufAppendF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Display), result->name.chars); } else if (moduleIndex > 0) { - ffStrbufAppendF(&key, "%s (%d)", FF_DISPLAY_MODULE_NAME, moduleIndex); + ffStrbufAppendF(&key, "%s (%d)", FF_MODULE_GET_DISPLAY_NAME(Display), moduleIndex); } else { - ffStrbufAppendS(&key, FF_DISPLAY_MODULE_NAME); + ffStrbufAppendS(&key, FF_MODULE_GET_DISPLAY_NAME(Display)); } } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -221,7 +221,7 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->compactType = (FFDisplayCompactType) value; } @@ -246,7 +246,7 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->order = (FFDisplayOrder) value; } @@ -254,7 +254,7 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Display), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -411,7 +411,7 @@ void ffDestroyDisplayOptions(FFDisplayOptions* options) { } FFModuleBaseInfo ffDisplayModuleInfo = { - .name = FF_DISPLAY_MODULE_NAME, + .name = "Display", .description = "Print resolutions, refresh rates, etc", .displayName = { .en = "Display", diff --git a/src/modules/display/display.h b/src/modules/display/display.h index a0a4b30959..c74e734d5a 100644 --- a/src/modules/display/display.h +++ b/src/modules/display/display.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DISPLAY_MODULE_NAME "Display" - bool ffPrintDisplay(FFDisplayOptions* options); void ffInitDisplayOptions(FFDisplayOptions* options); void ffDestroyDisplayOptions(FFDisplayOptions* options); diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 7524434c6b..6e63c44d8e 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -10,12 +10,12 @@ bool ffPrintDNS(FFDNSOptions* options) { const char* error = ffDetectDNS(options, &result); if (error) { - ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "NO DNS servers detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "NO DNS servers detected"); return false; } @@ -40,11 +40,11 @@ bool ffPrintDNS(FFDNSOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&buf, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(buf, "result"), })); } @@ -73,14 +73,14 @@ void ffParseDNSJsonObject(FFDNSOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_DNS_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->showType = (FFDNSShowType) value; } continue; } - ffPrintError(FF_DNS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(DNS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -134,7 +134,7 @@ void ffDestroyDNSOptions(FFDNSOptions* options) { } FFModuleBaseInfo ffDNSModuleInfo = { - .name = FF_DNS_MODULE_NAME, + .name = "DNS", .description = "Print configured DNS servers", .displayName = { .en = "DNS", diff --git a/src/modules/dns/dns.h b/src/modules/dns/dns.h index aec4e85fc6..6fbffe33d8 100644 --- a/src/modules/dns/dns.h +++ b/src/modules/dns/dns.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_DNS_MODULE_NAME "DNS" - bool ffPrintDNS(FFDNSOptions* options); void ffInitDNSOptions(FFDNSOptions* options); void ffDestroyDNSOptions(FFDNSOptions* options); diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index b1a7438fce..de3e5c96c3 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -16,12 +16,12 @@ bool ffPrintEditor(FFEditorOptions* options) { const char* error = ffDetectEditor(&result); if (error) { - ffPrintError(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.exe.length) { ffStrbufWriteTo(&result.exe, stdout); if (result.version.length) { @@ -32,7 +32,7 @@ bool ffPrintEditor(FFEditorOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.type, "type"), FF_ARG(result.name, "name"), FF_ARG(result.exe, "exe-name"), @@ -57,7 +57,7 @@ void ffParseEditorJsonObject(FFEditorOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_EDITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Editor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -103,7 +103,7 @@ void ffDestroyEditorOptions(FFEditorOptions* options) { } FFModuleBaseInfo ffEditorModuleInfo = { - .name = FF_EDITOR_MODULE_NAME, + .name = "Editor", .description = "Print information about the default editor ($VISUAL or $EDITOR)", .displayName = { .en = "Editor", diff --git a/src/modules/editor/editor.h b/src/modules/editor/editor.h index 293d0a6e19..19d48b7563 100644 --- a/src/modules/editor/editor.h +++ b/src/modules/editor/editor.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_EDITOR_MODULE_NAME "Editor" - bool ffPrintEditor(FFEditorOptions* options); void ffInitEditorOptions(FFEditorOptions* options); void ffDestroyEditorOptions(FFEditorOptions* options); diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 9763f257dd..6df480717d 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -15,13 +15,13 @@ bool ffPrintFont(FFFontOptions* options) { const char* error = ffDetectFont(&font); if (error) { - ffPrintError(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&font.display, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(font.fonts[0], "font1"), FF_ARG(font.fonts[1], "font2"), FF_ARG(font.fonts[2], "font3"), @@ -49,7 +49,7 @@ void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Font), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -95,7 +95,7 @@ void ffDestroyFontOptions(FFFontOptions* options) { } FFModuleBaseInfo ffFontModuleInfo = { - .name = FF_FONT_MODULE_NAME, + .name = "Font", .description = "Print system font names", .displayName = { .en = "Font", diff --git a/src/modules/font/font.h b/src/modules/font/font.h index b793b9fdd3..9af717487d 100644 --- a/src/modules/font/font.h +++ b/src/modules/font/font.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_FONT_MODULE_NAME "Font" - bool ffPrintFont(FFFontOptions* options); void ffInitFontOptions(FFFontOptions* options); void ffDestroyFontOptions(FFFontOptions* options); diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 8eb2cf7201..c0e01b6193 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -8,7 +8,7 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device, uint8_t index) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Gamepad), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); bool showBatteryLevel = device->battery > 0 && device->battery <= 100; @@ -39,7 +39,7 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device ffPercentAppendBar(&percentageBar, device->battery, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Gamepad), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->serial, "serial"), FF_ARG(percentageNum, "battery-percentage"), @@ -54,12 +54,12 @@ bool ffPrintGamepad(FFGamepadOptions* options) { const char* error = ffDetectGamepad(&result); if (error) { - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); return false; } @@ -80,7 +80,7 @@ bool ffPrintGamepad(FFGamepadOptions* options) { bool ret = true; if (!filtered.length) { - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); ret = false; } else { uint8_t index = 0; @@ -122,7 +122,7 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Gamepad), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -189,7 +189,7 @@ void ffDestroyGamepadOptions(FFGamepadOptions* options) { } FFModuleBaseInfo ffGamepadModuleInfo = { - .name = FF_GAMEPAD_MODULE_NAME, + .name = "Gamepad", .description = "List connected gamepads", .displayName = { .en = "Gamepad", diff --git a/src/modules/gamepad/gamepad.h b/src/modules/gamepad/gamepad.h index 395c90b2e3..9855a7b72b 100644 --- a/src/modules/gamepad/gamepad.h +++ b/src/modules/gamepad/gamepad.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_GAMEPAD_MODULE_NAME "Gamepad" - bool ffPrintGamepad(FFGamepadOptions* options); void ffInitGamepadOptions(FFGamepadOptions* options); void ffDestroyGamepadOptions(FFGamepadOptions* options); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index b11615464b..d22f3436cf 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -28,7 +28,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(GPU), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); @@ -145,7 +145,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu snprintf(currSpeed, sizeof(currSpeed), "%d x%d", gpu->psCurr.gen, gpu->psCurr.lanes); } - FF_PRINT_FORMAT_CHECKED(FF_GPU_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(GPU), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(gpu->vendor, "vendor"), FF_ARG(gpu->name, "name"), FF_ARG(gpu->driver, "driver"), @@ -176,7 +176,7 @@ bool ffPrintGPU(FFGPUOptions* options) { FF_LIST_AUTO_DESTROY gpus = ffListCreate(); const char* error = ffDetectGPU(options, &gpus); if (error) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -213,7 +213,7 @@ bool ffPrintGPU(FFGPUOptions* options) { } if (selectedGPUs.length == 0) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (gpus.length > 0 ? "GPUs found but all hidden by hideType option" : "No GPUs detected")); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, (gpus.length > 0 ? "GPUs found but all hidden by hideType option" : "No GPUs detected")); return false; } @@ -249,7 +249,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->detectionMethod = (FFGPUDetectionMethod) value; } @@ -269,7 +269,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->hideType = (FFGPUType) value; } @@ -281,7 +281,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(GPU), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -479,7 +479,7 @@ void ffDestroyGPUOptions(FFGPUOptions* options) { } FFModuleBaseInfo ffGPUModuleInfo = { - .name = FF_GPU_MODULE_NAME, + .name = "GPU", .description = "Print GPU names, memory sizes, types, etc", .displayName = { .en = "GPU", diff --git a/src/modules/gpu/gpu.h b/src/modules/gpu/gpu.h index e2a6f14248..c2a3c7a417 100644 --- a/src/modules/gpu/gpu.h +++ b/src/modules/gpu/gpu.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_GPU_MODULE_NAME "GPU" - bool ffPrintGPU(FFGPUOptions* options); void ffInitGPUOptions(FFGPUOptions* options); void ffDestroyGPUOptions(FFGPUOptions* options); diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 5a2e2a856a..1fafa659a8 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -17,17 +17,17 @@ bool ffPrintHost(FFHostOptions* options) { const char* error = ffDetectHost(&host); if (error) { - ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (host.name.length == 0 && host.family.length == 0) { - ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "neither product_family nor product_name is set by O.E.M."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "neither product_family nor product_name is set by O.E.M."); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); @@ -43,7 +43,7 @@ bool ffPrintHost(FFHostOptions* options) { ffStrbufPutTo(&output, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(host.family, "family"), FF_ARG(host.name, "name"), FF_ARG(host.version, "version"), @@ -75,7 +75,7 @@ void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Host), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -136,7 +136,7 @@ void ffDestroyHostOptions(FFHostOptions* options) { } FFModuleBaseInfo ffHostModuleInfo = { - .name = FF_HOST_MODULE_NAME, + .name = "Host", .description = "Print your computer's product name", .displayName = { .en = "Host", diff --git a/src/modules/host/host.h b/src/modules/host/host.h index 1f98fd406a..cf2ed1871d 100644 --- a/src/modules/host/host.h +++ b/src/modules/host/host.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_HOST_MODULE_NAME "Host" - bool ffPrintHost(FFHostOptions* options); void ffInitHostOptions(FFHostOptions* options); void ffDestroyHostOptions(FFHostOptions* options); diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 971a9655da..eaa1341bd1 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -13,12 +13,12 @@ bool ffPrintIcons(FFIconsOptions* options) { const char* error = ffDetectIcons(&result); if (error) { - ffPrintError(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.icons1.length) { ffStrbufWriteTo(&result.icons1, stdout); } @@ -30,7 +30,7 @@ bool ffPrintIcons(FFIconsOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.icons1, "icons1"), FF_ARG(result.icons2, "icons2"), })); @@ -52,7 +52,7 @@ void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Icons), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -94,7 +94,7 @@ void ffDestroyIconsOptions(FFIconsOptions* options) { } FFModuleBaseInfo ffIconsModuleInfo = { - .name = FF_ICONS_MODULE_NAME, + .name = "Icons", .description = "Print icon style name", .displayName = { .en = "Icons", diff --git a/src/modules/icons/icons.h b/src/modules/icons/icons.h index a583a22571..ee1e74f047 100644 --- a/src/modules/icons/icons.h +++ b/src/modules/icons/icons.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_ICONS_MODULE_NAME "Icons" - bool ffPrintIcons(FFIconsOptions* options); void ffInitIconsOptions(FFIconsOptions* options); void ffDestroyIconsOptions(FFIconsOptions* options); diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index a6421f9f79..b5adbc9062 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -4,8 +4,6 @@ #include "detection/initsystem/initsystem.h" #include "modules/initsystem/initsystem.h" -#define FF_INITSYSTEM_DISPLAY_NAME "Init System" - bool ffPrintInitSystem(FFInitSystemOptions* options) { bool success = false; FFInitSystemResult result = { @@ -18,12 +16,12 @@ bool ffPrintInitSystem(FFInitSystemOptions* options) { const char* error = ffDetectInitSystem(&result); if (error) { - ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.name, stdout); if (result.version.length) { printf(" %s\n", result.version.chars); @@ -31,7 +29,7 @@ bool ffPrintInitSystem(FFInitSystemOptions* options) { putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.name, "name"), FF_ARG(result.exe, "exe"), FF_ARG(result.version, "version"), @@ -56,7 +54,7 @@ void ffParseInitSystemJsonObject(FFInitSystemOptions* options, yyjson_val* modul continue; } - ffPrintError(FF_INITSYSTEM_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(InitSystem), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -103,7 +101,7 @@ void ffDestroyInitSystemOptions(FFInitSystemOptions* options) { } FFModuleBaseInfo ffInitSystemModuleInfo = { - .name = FF_INITSYSTEM_MODULE_NAME, + .name = "InitSystem", .description = "Print init system (pid 1) name and version", .displayName = { .en = "Init System", diff --git a/src/modules/initsystem/initsystem.h b/src/modules/initsystem/initsystem.h index 381b955431..f6379f5956 100644 --- a/src/modules/initsystem/initsystem.h +++ b/src/modules/initsystem/initsystem.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_INITSYSTEM_MODULE_NAME "InitSystem" - bool ffPrintInitSystem(FFInitSystemOptions* options); void ffInitInitSystemOptions(FFInitSystemOptions* options); void ffDestroyInitSystemOptions(FFInitSystemOptions* options); diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 5cd76a0bb0..055dd5fe10 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -7,12 +7,12 @@ bool ffPrintKernel(FFKernelOptions* options) { const FFPlatformSysinfo* info = &instance.state.platform.sysinfo; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Kernel), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%s %s\n", info->name.chars, info->release.chars); } else { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); ffSizeAppendNum(info->pageSize, &str); - FF_PRINT_FORMAT_CHECKED(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Kernel), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(info->name, "sysname"), FF_ARG(info->release, "release"), FF_ARG(info->version, "version"), @@ -32,7 +32,7 @@ void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Kernel), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -62,7 +62,7 @@ void ffDestroyKernelOptions(FFKernelOptions* options) { } FFModuleBaseInfo ffKernelModuleInfo = { - .name = FF_KERNEL_MODULE_NAME, + .name = "Kernel", .description = "Print system kernel version", .displayName = { .en = "Kernel", diff --git a/src/modules/kernel/kernel.h b/src/modules/kernel/kernel.h index 010ec54c4d..faf6212689 100644 --- a/src/modules/kernel/kernel.h +++ b/src/modules/kernel/kernel.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_KERNEL_MODULE_NAME "Kernel" - bool ffPrintKernel(FFKernelOptions* options); void ffInitKernelOptions(FFKernelOptions* options); void ffDestroyKernelOptions(FFKernelOptions* options); diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 00bfb16647..755ac67641 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -7,10 +7,10 @@ static void printDevice(FFKeyboardOptions* options, const FFKeyboardDevice* device, uint8_t index) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_KEYBOARD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Keyboard), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&device->name, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_KEYBOARD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Keyboard), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->serial, "serial"), })); @@ -23,12 +23,12 @@ bool ffPrintKeyboard(FFKeyboardOptions* options) { const char* error = ffDetectKeyboard(&result); if (error) { - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); return false; } @@ -49,7 +49,7 @@ bool ffPrintKeyboard(FFKeyboardOptions* options) { bool ret = true; if (!filtered.length) { - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); ret = false; } else { uint8_t index = 0; @@ -84,7 +84,7 @@ void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Keyboard), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -149,7 +149,7 @@ void ffDestroyKeyboardOptions(FFKeyboardOptions* options) { } FFModuleBaseInfo ffKeyboardModuleInfo = { - .name = FF_KEYBOARD_MODULE_NAME, + .name = "Keyboard", .description = "List connected keyboards", .displayName = { .en = "Keyboard", diff --git a/src/modules/keyboard/keyboard.h b/src/modules/keyboard/keyboard.h index bd6e69c56b..d862173a1a 100644 --- a/src/modules/keyboard/keyboard.h +++ b/src/modules/keyboard/keyboard.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_KEYBOARD_MODULE_NAME "Keyboard" - bool ffPrintKeyboard(FFKeyboardOptions* options); void ffInitKeyboardOptions(FFKeyboardOptions* options); void ffDestroyKeyboardOptions(FFKeyboardOptions* options); diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 8bfe44442d..8c919056bd 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -13,17 +13,17 @@ bool ffPrintLM(FFLMOptions* options) { const char* error = ffDetectLM(&result); if (error) { - ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); goto exit; } if (result.service.length == 0) { - ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No LM service found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No LM service found"); goto exit; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result.service, stdout); if (result.version.length) { printf(" %s", result.version.chars); @@ -33,7 +33,7 @@ bool ffPrintLM(FFLMOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.service, "service"), FF_ARG(result.type, "type"), FF_ARG(result.version, "version"), @@ -57,7 +57,7 @@ void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -106,7 +106,7 @@ void ffDestroyLMOptions(FFLMOptions* options) { } FFModuleBaseInfo ffLMModuleInfo = { - .name = FF_LM_MODULE_NAME, + .name = "LM", .description = "Print login manager (desktop manager) name and version", .displayName = { .en = "Login Manager", diff --git a/src/modules/lm/lm.h b/src/modules/lm/lm.h index 1ec33b6494..8329d9b776 100644 --- a/src/modules/lm/lm.h +++ b/src/modules/lm/lm.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LM_MODULE_NAME "LM" - bool ffPrintLM(FFLMOptions* options); void ffInitLMOptions(FFLMOptions* options); void ffDestroyLMOptions(FFLMOptions* options); diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 8f6a8ed85c..4bd0065e1e 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -11,13 +11,13 @@ bool ffPrintLoadavg(FFLoadavgOptions* options) { const char* error = ffDetectLoadavg(result); if (error) { - ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { if (options->compact) { - ffPrintLogoAndKey(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%.*f, %.*f, %.*f\n", options->ndigits, result[0], options->ndigits, result[1], options->ndigits, result[2]); } else { FFCPUResult cpu = { @@ -34,7 +34,7 @@ bool ffPrintLoadavg(FFLoadavgOptions* options) { uint32_t duration = index == 0 ? 1 : index == 1 ? 5 : 15; if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(&buffer, "%s (%d min)", FF_LOADAVG_MODULE_NAME, duration); + ffStrbufSetF(&buffer, "%s (%d min)", FF_MODULE_GET_DISPLAY_NAME(Loadavg), duration); } else { ffStrbufClear(&buffer); FF_PARSE_FORMAT_STRING_CHECKED(&buffer, &options->moduleArgs.key, ((FFformatarg[]) { @@ -72,7 +72,7 @@ bool ffPrintLoadavg(FFLoadavgOptions* options) { } } } else { - FF_PRINT_FORMAT_CHECKED(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result[0], "loadavg1"), FF_ARG(result[1], "loadavg2"), FF_ARG(result[2], "loadavg3"), @@ -104,7 +104,7 @@ void ffParseLoadavgJsonObject(FFLoadavgOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LOADAVG_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Loadavg), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -148,7 +148,7 @@ void ffDestroyLoadavgOptions(FFLoadavgOptions* options) { } FFModuleBaseInfo ffLoadavgModuleInfo = { - .name = FF_LOADAVG_MODULE_NAME, + .name = "Loadavg", .description = "Print system load averages", .displayName = { .en = "Load Average", diff --git a/src/modules/loadavg/loadavg.h b/src/modules/loadavg/loadavg.h index 9af2786f90..8a2c6a8f5f 100644 --- a/src/modules/loadavg/loadavg.h +++ b/src/modules/loadavg/loadavg.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOADAVG_MODULE_NAME "Loadavg" - bool ffPrintLoadavg(FFLoadavgOptions* options); void ffInitLoadavgOptions(FFLoadavgOptions* options); void ffDestroyLoadavgOptions(FFLoadavgOptions* options); diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 4bc3e9658c..8d3f314741 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -8,15 +8,15 @@ bool ffPrintLocale(FFLocaleOptions* options) { const char* error = ffDetectLocale(&locale); if (error) { - ffPrintError(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&locale, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(locale, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(locale, "result") })); } return true; @@ -30,7 +30,7 @@ void ffParseLocaleJsonObject(FFLocaleOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Locale), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -67,7 +67,7 @@ void ffDestroyLocaleOptions(FFLocaleOptions* options) { } FFModuleBaseInfo ffLocaleModuleInfo = { - .name = FF_LOCALE_MODULE_NAME, + .name = "Locale", .description = "Print system locale name", .displayName = { .en = "Locale", diff --git a/src/modules/locale/locale.h b/src/modules/locale/locale.h index fd86e42c36..a5b6a0981e 100644 --- a/src/modules/locale/locale.h +++ b/src/modules/locale/locale.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOCALE_MODULE_NAME "Locale" - bool ffPrintLocale(FFLocaleOptions* options); void ffInitLocaleOptions(FFLocaleOptions* options); void ffDestroyLocaleOptions(FFLocaleOptions* options); diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index bc438be7e5..46319e97c4 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -4,7 +4,6 @@ #include "detection/localip/localip.h" #include "modules/localip/localip.h" -#define FF_LOCALIP_DISPLAY_NAME "Local IP" #pragma GCC diagnostic ignored "-Wsign-conversion" static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) { @@ -17,7 +16,7 @@ static void formatKey(const FFLocalIpOptions* options, FFLocalIpResult* ip, uint ffStrbufSetF(&ip->name, "unknown %u", (unsigned) index); } - ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(LocalIP), ip->name.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -100,12 +99,12 @@ bool ffPrintLocalIp(FFLocalIpOptions* options) { const char* error = ffDetectLocalIps(options, &results); if (error) { - ffPrintError(FF_LOCALIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_LOCALIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect any IPs"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect any IPs"); return false; } @@ -114,7 +113,7 @@ bool ffPrintLocalIp(FFLocalIpOptions* options) { FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (options->showType & FF_LOCALIP_TYPE_COMPACT_BIT) { - ffPrintLogoAndKey(FF_LOCALIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_LIST_FOR_EACH (FFLocalIpResult, ip, results) { if (buffer.length) { @@ -201,7 +200,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->showType |= FF_LOCALIP_TYPE_IPV6_BIT; options->ipv6Type = (FFLocalIpIpv6Type) value; @@ -296,7 +295,7 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(LocalIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -422,7 +421,7 @@ void ffDestroyLocalIpOptions(FFLocalIpOptions* options) { } FFModuleBaseInfo ffLocalIPModuleInfo = { - .name = FF_LOCALIP_MODULE_NAME, + .name = "LocalIp", .description = "List local IP addresses (IPv4 or IPv6), MAC addresses, etc", .displayName = { .en = "Local IP", diff --git a/src/modules/localip/localip.h b/src/modules/localip/localip.h index f9e9c4e437..2580fac2ee 100644 --- a/src/modules/localip/localip.h +++ b/src/modules/localip/localip.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOCALIP_MODULE_NAME "LocalIp" - bool ffPrintLocalIp(FFLocalIpOptions* options); void ffInitLocalIpOptions(FFLocalIpOptions* options); void ffDestroyLocalIpOptions(FFLocalIpOptions* options); diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 432a1fa829..0b68a64f69 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -4,7 +4,7 @@ #include "options/logo.h" bool ffPrintLogo([[maybe_unused]] FFLogoOptions* options) { - ffPrintError(FF_LOGO_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_DEFAULT, "Supported in JSON format only"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Logo), 0, nullptr, FF_PRINT_TYPE_DEFAULT, "Supported in JSON format only"); return false; } @@ -16,7 +16,7 @@ void ffParseLogoJsonObject([[maybe_unused]] FFLogoOptions* options, [[maybe_unus continue; } - ffPrintError(FF_LOGO_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Logo), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -77,7 +77,7 @@ void ffDestroyLogoOptions([[maybe_unused]] FFLogoOptions* options) { } FFModuleBaseInfo ffLogoModuleInfo = { - .name = FF_LOGO_MODULE_NAME, + .name = "Logo", .description = "Query built-in logo for JSON output", .displayName = { .en = "Logo", diff --git a/src/modules/logo/logo.h b/src/modules/logo/logo.h index 7f48e2dd62..af8ca7a0e6 100644 --- a/src/modules/logo/logo.h +++ b/src/modules/logo/logo.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_LOGO_MODULE_NAME "Logo" - bool ffPrintLogo(FFLogoOptions* options); void ffInitLogoOptions(FFLogoOptions* options); void ffDestroyLogoOptions(FFLogoOptions* options); diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 80bc087be5..08f550a5fe 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -56,7 +56,7 @@ bool ffPrintMedia(FFMediaOptions* options) { const FFMediaResult* media = ffDetectMedia(false); if (media->error.length > 0) { - ffPrintError(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); return false; } @@ -110,7 +110,7 @@ bool ffPrintMedia(FFMediaOptions* options) { ffStrbufClear(&artistPretty); } - ffPrintLogoAndKey(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (artistPretty.length > 0) { ffStrbufWriteTo(&artistPretty, stdout); @@ -171,7 +171,7 @@ bool ffPrintMedia(FFMediaOptions* options) { &options->moduleArgs); } } - FF_PRINT_FORMAT_CHECKED(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ FF_ARG(songPretty, "combined"), FF_ARG(media->song, "title"), FF_ARG(media->artist, "artist"), @@ -201,7 +201,7 @@ void ffParseMediaJsonObject(FFMediaOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Media), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -253,7 +253,7 @@ void ffDestroyMediaOptions(FFMediaOptions* options) { } FFModuleBaseInfo ffMediaModuleInfo = { - .name = FF_MEDIA_MODULE_NAME, + .name = "Media", .description = "Print the name of the currently playing song", .displayName = { .en = "Media", diff --git a/src/modules/media/media.h b/src/modules/media/media.h index 8320227d8a..10f995eaac 100644 --- a/src/modules/media/media.h +++ b/src/modules/media/media.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MEDIA_MODULE_NAME "Media" - bool ffPrintMedia(FFMediaOptions* options); void ffInitMediaOptions(FFMediaOptions* options); void ffDestroyMediaOptions(FFMediaOptions* options); diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 7a7f58e09b..065808c299 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -11,7 +11,7 @@ bool ffPrintMemory(FFMemoryOptions* options) { const char* error = ffDetectMemory(&storage); if (error) { - ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -27,7 +27,7 @@ bool ffPrintMemory(FFMemoryOptions* options) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (storage.bytesTotal == 0) { puts("Disabled"); } else { @@ -59,7 +59,7 @@ bool ffPrintMemory(FFMemoryOptions* options) { ffPercentAppendBar(&percentageBar, percentage, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(usedPretty, "used"), FF_ARG(totalPretty, "total"), FF_ARG(percentageNum, "percentage"), @@ -82,7 +82,7 @@ void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Memory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -118,7 +118,7 @@ void ffDestroyMemoryOptions(FFMemoryOptions* options) { } FFModuleBaseInfo ffMemoryModuleInfo = { - .name = FF_MEMORY_MODULE_NAME, + .name = "Memory", .description = "Print system memory usage information", .displayName = { .en = "Memory", diff --git a/src/modules/memory/memory.h b/src/modules/memory/memory.h index 7ed026fc3d..7883da2d84 100644 --- a/src/modules/memory/memory.h +++ b/src/modules/memory/memory.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MEMORY_MODULE_NAME "Memory" - bool ffPrintMemory(FFMemoryOptions* options); void ffInitMemoryOptions(FFMemoryOptions* options); void ffDestroyMemoryOptions(FFMemoryOptions* options); diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 27911bccfb..c5c9877c1f 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -10,7 +10,7 @@ bool ffPrintMonitor(FFMonitorOptions* options) { const FFDisplayServerResult* result = ffConnectDisplayServer(); if (!result->displays.length) { - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No display detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Monitor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No display detected"); return false; } @@ -23,7 +23,7 @@ bool ffPrintMonitor(FFMonitorOptions* options) { ffStrbufClear(&key); if (options->moduleArgs.key.length == 0) { - ffStrbufAppendS(&key, FF_MONITOR_MODULE_NAME); + ffStrbufAppendS(&key, FF_MODULE_GET_DISPLAY_NAME(Monitor)); if (display->name.length > 0) { ffStrbufAppendF(&key, " (%s)", display->name.chars); } @@ -82,7 +82,7 @@ void ffParseMonitorJsonObject(FFMonitorOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Monitor), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -104,7 +104,7 @@ void ffDestroyMonitorOptions(FFMonitorOptions* options) { } FFModuleBaseInfo ffMonitorModuleInfo = { - .name = FF_MONITOR_MODULE_NAME, + .name = "Monitor", .description = "Same as Display module, but with a different default output format", .displayName = { .en = "Monitor", diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h index 82f9491fe6..598d226920 100644 --- a/src/modules/monitor/monitor.h +++ b/src/modules/monitor/monitor.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MONITOR_MODULE_NAME "Monitor" - bool ffPrintMonitor(FFMonitorOptions* options); void ffInitMonitorOptions(FFMonitorOptions* options); void ffDestroyMonitorOptions(FFMonitorOptions* options); diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index c14b6e9980..dd8f8be6e5 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -7,10 +7,10 @@ static void printDevice(FFMouseOptions* options, const FFMouseDevice* device, uint8_t index) { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_MOUSE_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Mouse), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&device->name, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_MOUSE_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Mouse), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->name, "name"), FF_ARG(device->serial, "serial"), })); @@ -23,12 +23,12 @@ bool ffPrintMouse(FFMouseOptions* options) { const char* error = ffDetectMouse(&result); if (error) { - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); return false; } @@ -49,7 +49,7 @@ bool ffPrintMouse(FFMouseOptions* options) { bool ret = true; if (!filtered.length) { - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "All devices are ignored"); ret = false; } else { uint8_t index = 0; @@ -87,7 +87,7 @@ void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Mouse), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -152,7 +152,7 @@ void ffDestroyMouseOptions(FFMouseOptions* options) { } FFModuleBaseInfo ffMouseModuleInfo = { - .name = FF_MOUSE_MODULE_NAME, + .name = "Mouse", .description = "List connected mice", .displayName = { .en = "Mouse", diff --git a/src/modules/mouse/mouse.h b/src/modules/mouse/mouse.h index afbc20ff9e..f042cbfa45 100644 --- a/src/modules/mouse/mouse.h +++ b/src/modules/mouse/mouse.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_MOUSE_MODULE_NAME "Mouse" - bool ffPrintMouse(FFMouseOptions* options); void ffInitMouseOptions(FFMouseOptions* options); void ffDestroyMouseOptions(FFMouseOptions* options); diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index cad480b184..e062a55c8d 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -5,8 +5,6 @@ #include "detection/netio/netio.h" #include "modules/netio/netio.h" -#define FF_NETIO_DISPLAY_NAME "Network IO" - static int sortInfs(const FFNetIOResult* left, const FFNetIOResult* right) { return ffStrbufComp(&left->name, &right->name); } @@ -17,7 +15,7 @@ static void formatKey(const FFNetIOOptions* options, FFNetIOResult* inf, uint32_ ffStrbufSetF(&inf->name, "unknown %u", (unsigned) index); } - ffStrbufSetF(key, FF_NETIO_DISPLAY_NAME " (%s)", inf->name.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(NetIO), inf->name.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -33,7 +31,7 @@ bool ffPrintNetIO(FFNetIOOptions* options) { const char* error = ffDetectNetIO(&result, options); if (error) { - ffPrintError(FF_NETIO_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(NetIO), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -131,7 +129,7 @@ void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_NETIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(NetIO), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -199,7 +197,7 @@ void ffDestroyNetIOOptions(FFNetIOOptions* options) { } FFModuleBaseInfo ffNetIOModuleInfo = { - .name = FF_NETIO_MODULE_NAME, + .name = "NetIO", .description = "Print network I/O throughput", .displayName = { .en = "Network I/O", diff --git a/src/modules/netio/netio.h b/src/modules/netio/netio.h index 653b7e97ce..2f048e5a36 100644 --- a/src/modules/netio/netio.h +++ b/src/modules/netio/netio.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_NETIO_MODULE_NAME "NetIO" - void ffPrepareNetIO(FFNetIOOptions* options); bool ffPrintNetIO(FFNetIOOptions* options); diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 353615b648..18e9b85d6b 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -9,15 +9,15 @@ bool ffPrintOpenCL(FFOpenCLOptions* options) { FFOpenCLResult* result = ffDetectOpenCL(); if (result->error != nullptr) { - ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result->error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", result->error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&result->version, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->version, "version"), FF_ARG(result->name, "name"), FF_ARG(result->vendor, "vendor"), @@ -35,7 +35,7 @@ void ffParseOpenCLJsonObject(FFOpenCLOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenCL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -120,7 +120,7 @@ void ffDestroyOpenCLOptions(FFOpenCLOptions* options) { } FFModuleBaseInfo ffOpenCLModuleInfo = { - .name = FF_OPENCL_MODULE_NAME, + .name = "OpenCL", .description = "Print the highest OpenCL version supported by the GPU", .displayName = { .en = "OpenCL", diff --git a/src/modules/opencl/opencl.h b/src/modules/opencl/opencl.h index aafab369f1..d7dbe3661e 100644 --- a/src/modules/opencl/opencl.h +++ b/src/modules/opencl/opencl.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_OPENCL_MODULE_NAME "OpenCL" - bool ffPrintOpenCL(FFOpenCLOptions* options); void ffInitOpenCLOptions(FFOpenCLOptions* options); void ffDestroyOpenCLOptions(FFOpenCLOptions* options); diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index c10ec7e200..ad8e431e5b 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -15,13 +15,13 @@ bool ffPrintOpenGL(FFOpenGLOptions* options) { const char* error = ffDetectOpenGL(options, &result); if (error) { - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(result.version.chars); } else { - FF_PRINT_FORMAT_CHECKED(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.version, "version"), FF_ARG(result.renderer, "renderer"), FF_ARG(result.vendor, "vendor"), @@ -58,14 +58,14 @@ void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->library = (FFOpenGLLibrary) value; } continue; } - ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OpenGL), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -127,7 +127,7 @@ void ffDestroyOpenGLOptions(FFOpenGLOptions* options) { } FFModuleBaseInfo ffOpenGLModuleInfo = { - .name = FF_OPENGL_MODULE_NAME, + .name = "OpenGL", .description = "Print the highest OpenGL version supported by the GPU", .displayName = { .en = "OpenGL", diff --git a/src/modules/opengl/opengl.h b/src/modules/opengl/opengl.h index 8caffa5a5b..f7f4c05cc9 100644 --- a/src/modules/opengl/opengl.h +++ b/src/modules/opengl/opengl.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_OPENGL_MODULE_NAME "OpenGL" - bool ffPrintOpenGL(FFOpenGLOptions* options); void ffInitOpenGLOptions(FFOpenGLOptions* options); void ffDestroyOpenGLOptions(FFOpenGLOptions* options); diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 65168a6097..1d6a18cd02 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -50,14 +50,14 @@ bool ffPrintOS(FFOSOptions* options) { const FFOSResult* os = ffDetectOS(); if (os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0) { - ffPrintError(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Could not detect OS"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Could not detect OS"); return false; } FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { - ffStrbufSetStatic(&key, FF_OS_MODULE_NAME); + ffStrbufSetStatic(&key, FF_MODULE_GET_DISPLAY_NAME(OS)); } else { FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, ((FFformatarg[]) { FF_ARG(instance.state.platform.sysinfo.name, "sysname"), @@ -112,7 +112,7 @@ void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_OS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(OS), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -172,7 +172,7 @@ void ffDestroyOSOptions(FFOSOptions* options) { } FFModuleBaseInfo ffOSModuleInfo = { - .name = FF_OS_MODULE_NAME, + .name = "OS", .description = "Print the OS or Linux distribution name and version", .displayName = { .en = "OS", diff --git a/src/modules/os/os.h b/src/modules/os/os.h index a53d28516e..77312c6202 100644 --- a/src/modules/os/os.h +++ b/src/modules/os/os.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_OS_MODULE_NAME "OS" - bool ffPrintOS(FFOSOptions* options); void ffInitOSOptions(FFOSOptions* options); void ffDestroyOSOptions(FFOSOptions* options); diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 258e0f369e..710894c3c8 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -11,12 +11,12 @@ bool ffPrintPackages(FFPackagesOptions* options) { const char* error = ffDetectPackages(&counts, options); if (error) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (counts.all == 0) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No packages from known package managers found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No packages from known package managers found"); return false; } @@ -29,7 +29,7 @@ bool ffPrintPackages(FFPackagesOptions* options) { uint32_t scoopAll = counts.scoopUser + counts.scoopGlobal; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); @@ -141,7 +141,7 @@ bool ffPrintPackages(FFPackagesOptions* options) { output.chars[output.length - 1] = '\n'; ffStrbufWriteTo(&output, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_PACKAGES_MODULE_NAME, + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, @@ -219,7 +219,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) { #if !FF_PACKAGES_REMOVE_DISABLED if (unsafe_yyjson_equals_str(key, "disabled")) { if (!yyjson_is_null(val) && !yyjson_is_arr(val)) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); continue; } @@ -230,7 +230,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) { size_t flagIdx, flagMax; yyjson_arr_foreach (val, flagIdx, flagMax, flagObj) { if (!yyjson_is_str(flagObj)) { - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid JSON value for %s", unsafe_yyjson_get_str(key)); continue; } const char* flag = unsafe_yyjson_get_str(flagObj); @@ -366,7 +366,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Packages), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -510,7 +510,7 @@ void ffDestroyPackagesOptions(FFPackagesOptions* options) { } FFModuleBaseInfo ffPackagesModuleInfo = { - .name = FF_PACKAGES_MODULE_NAME, + .name = "Packages", .description = "List installed package managers and count of installed packages", .displayName = { .en = "Packages", diff --git a/src/modules/packages/packages.h b/src/modules/packages/packages.h index 4e58768702..caf7832d82 100644 --- a/src/modules/packages/packages.h +++ b/src/modules/packages/packages.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PACKAGES_MODULE_NAME "Packages" - bool ffPrintPackages(FFPackagesOptions* options); void ffInitPackagesOptions(FFPackagesOptions* options); void ffDestroyPackagesOptions(FFPackagesOptions* options); diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index d897e131ea..d9e2f36494 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -5,15 +5,13 @@ #include "detection/physicaldisk/physicaldisk.h" #include "modules/physicaldisk/physicaldisk.h" -#define FF_PHYSICALDISK_DISPLAY_NAME "Physical Disk" - static int sortDevices(const FFPhysicalDiskResult* left, const FFPhysicalDiskResult* right) { return ffStrbufComp(&left->name, &right->name); } static void formatKey(const FFPhysicalDiskOptions* options, FFPhysicalDiskResult* dev, uint32_t index, FFstrbuf* key) { if (options->moduleArgs.key.length == 0) { - ffStrbufSetF(key, FF_PHYSICALDISK_DISPLAY_NAME " (%s)", dev->name.length ? dev->name.chars : dev->devPath.chars); + ffStrbufSetF(key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), dev->name.length ? dev->name.chars : dev->devPath.chars); } else { ffStrbufClear(key); FF_PARSE_FORMAT_STRING_CHECKED(key, &options->moduleArgs.key, ((FFformatarg[]) { @@ -30,7 +28,7 @@ bool ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) { const char* error = ffDetectPhysicalDisk(&result, options); if (error) { - ffPrintError(FF_PHYSICALDISK_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -140,7 +138,7 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m if (unsafe_yyjson_equals_str(key, "hideVirtual")) { if (!yyjson_is_bool(val)) { - ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideVirtual must be a boolean"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideVirtual must be a boolean"); } else { if (unsafe_yyjson_is_true(val)) { options->hideType |= FF_PHYSICALDISK_TYPE_VIRTUAL; @@ -153,7 +151,7 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m if (unsafe_yyjson_equals_str(key, "hideUnused")) { if (!yyjson_is_bool(val)) { - ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideUnused must be a boolean"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "hideUnused must be a boolean"); } else { if (unsafe_yyjson_is_true(val)) { options->hideType |= FF_PHYSICALDISK_TYPE_UNUSED; @@ -168,7 +166,7 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m continue; } - ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalDisk), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -265,7 +263,7 @@ void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) { } FFModuleBaseInfo ffPhysicalDiskModuleInfo = { - .name = FF_PHYSICALDISK_MODULE_NAME, + .name = "PhysicalDisk", .description = "Print physical disk information", .displayName = { .en = "Physical Disk", diff --git a/src/modules/physicaldisk/physicaldisk.h b/src/modules/physicaldisk/physicaldisk.h index aaad8883e6..41a8d9987d 100644 --- a/src/modules/physicaldisk/physicaldisk.h +++ b/src/modules/physicaldisk/physicaldisk.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PHYSICALDISK_MODULE_NAME "PhysicalDisk" - bool ffPrintPhysicalDisk(FFPhysicalDiskOptions* options); void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options); void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options); diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 64e53957df..dbb263ad48 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -4,19 +4,17 @@ #include "detection/physicalmemory/physicalmemory.h" #include "modules/physicalmemory/physicalmemory.h" -#define FF_PHYSICALMEMORY_DISPLAY_NAME "Physical Memory" - bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) { FF_LIST_AUTO_DESTROY result = ffListCreate(); const char* error = ffDetectPhysicalMemory(options, &result); if (error) { - ffPrintError(FF_PHYSICALMEMORY_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_PHYSICALMEMORY_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical memory devices detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical memory devices detected"); return false; } @@ -30,7 +28,7 @@ bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PHYSICALMEMORY_DISPLAY_NAME, result.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), result.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (device->installed) { fputs(prettySize.chars, stdout); @@ -59,7 +57,7 @@ bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_PHYSICALMEMORY_DISPLAY_NAME, (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(device->size, "bytes"), FF_ARG(prettySize, "size"), FF_ARG(device->maxSpeed, "max-speed"), @@ -103,7 +101,7 @@ void ffParsePhysicalMemoryJsonObject(FFPhysicalMemoryOptions* options, yyjson_va continue; } - ffPrintError(FF_PHYSICALMEMORY_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PhysicalMemory), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -159,7 +157,7 @@ void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options) { } FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { - .name = FF_PHYSICALMEMORY_MODULE_NAME, + .name = "PhysicalMemory", .description = "Print system physical memory devices", .displayName = { .en = "Physical Memory", diff --git a/src/modules/physicalmemory/physicalmemory.h b/src/modules/physicalmemory/physicalmemory.h index feb3d1d293..ae4ae985ad 100644 --- a/src/modules/physicalmemory/physicalmemory.h +++ b/src/modules/physicalmemory/physicalmemory.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PHYSICALMEMORY_MODULE_NAME "PhysicalMemory" - bool ffPrintPhysicalMemory(FFPhysicalMemoryOptions* options); void ffInitPhysicalMemoryOptions(FFPhysicalMemoryOptions* options); void ffDestroyPhysicalMemoryOptions(FFPhysicalMemoryOptions* options); diff --git a/src/modules/player/player.c b/src/modules/player/player.c index a01471446e..ca19fbefea 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -6,18 +6,16 @@ #include -#define FF_PLAYER_DISPLAY_NAME "Media Player" - bool ffPrintPlayer(FFPlayerOptions* options) { const FFMediaResult* media = ffDetectMedia(false); if (media->error.length > 0) { - ffPrintError(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", media->error.chars); return false; } if (media->player.length == 0) { - ffPrintError(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No media player detected"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No media player detected"); return false; } @@ -65,10 +63,10 @@ bool ffPrintPlayer(FFPlayerOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&playerPretty, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_PLAYER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(playerPretty, "player"), FF_ARG(media->player, "name"), FF_ARG(media->playerId, "id"), @@ -87,7 +85,7 @@ void ffParsePlayerJsonObject(FFPlayerOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_PLAYER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Player), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -109,7 +107,7 @@ void ffDestroyPlayerOptions(FFPlayerOptions* options) { } FFModuleBaseInfo ffPlayerModuleInfo = { - .name = FF_PLAYER_MODULE_NAME, + .name = "Player", .description = "Print the music player name that is currently active", .displayName = { .en = "Media Player", diff --git a/src/modules/player/player.h b/src/modules/player/player.h index 8b18d29828..001d81e373 100644 --- a/src/modules/player/player.h +++ b/src/modules/player/player.h @@ -3,8 +3,6 @@ #include "option.h" -#define FF_PLAYER_MODULE_NAME "Player" - bool ffPrintPlayer(FFPlayerOptions* options); void ffInitPlayerOptions(FFPlayerOptions* options); void ffDestroyPlayerOptions(FFPlayerOptions* options); diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 74f0bfe898..39866ed19c 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -4,20 +4,18 @@ #include "detection/poweradapter/poweradapter.h" #include "modules/poweradapter/poweradapter.h" -#define FF_POWERADAPTER_DISPLAY_NAME "Power Adapter" - bool ffPrintPowerAdapter(FFPowerAdapterOptions* options) { FF_LIST_AUTO_DESTROY results = ffListCreate(); const char* error = ffDetectPowerAdapter(&results); if (error) { - ffPrintError(FF_POWERADAPTER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_POWERADAPTER_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No power adapters found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No power adapters found"); return false; } @@ -25,7 +23,7 @@ bool ffPrintPowerAdapter(FFPowerAdapterOptions* options) { FFPowerAdapterResult* result = FF_LIST_GET(FFPowerAdapterResult, results, i); if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result->name.length > 0) { puts(result->name.chars); @@ -33,7 +31,7 @@ bool ffPrintPowerAdapter(FFPowerAdapterOptions* options) { printf("%dW\n", result->watts); } } else { - FF_PRINT_FORMAT_CHECKED(FF_POWERADAPTER_DISPLAY_NAME, i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), i, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->watts, "watts"), FF_ARG(result->name, "name"), FF_ARG(result->manufacturer, "manufacturer"), @@ -65,7 +63,7 @@ void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* m continue; } - ffPrintError(FF_POWERADAPTER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PowerAdapter), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -110,7 +108,7 @@ void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options) { } FFModuleBaseInfo ffPowerAdapterModuleInfo = { - .name = FF_POWERADAPTER_MODULE_NAME, + .name = "PowerAdapter", .description = "Print power adapter name and charging watts", .displayName = { .en = "Power Adapter", diff --git a/src/modules/poweradapter/poweradapter.h b/src/modules/poweradapter/poweradapter.h index 3e61025506..f4d1170c23 100644 --- a/src/modules/poweradapter/poweradapter.h +++ b/src/modules/poweradapter/poweradapter.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_POWERADAPTER_MODULE_NAME "PowerAdapter" - bool ffPrintPowerAdapter(FFPowerAdapterOptions* options); void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options); void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options); diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 1d02bac2ee..ef6f4bee30 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -9,16 +9,16 @@ bool ffPrintProcesses(FFProcessesOptions* options) { const char* error = ffDetectProcesses(&numProcesses); if (error) { - ffPrintError(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%u\n", numProcesses); } else { - FF_PRINT_FORMAT_CHECKED(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(numProcesses, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(numProcesses, "result") })); } return true; @@ -32,7 +32,7 @@ void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -63,7 +63,7 @@ void ffDestroyProcessesOptions(FFProcessesOptions* options) { } FFModuleBaseInfo ffProcessesModuleInfo = { - .name = FF_PROCESSES_MODULE_NAME, + .name = "Processes", .description = "Print number of running processes", .displayName = { .en = "Processes", diff --git a/src/modules/processes/processes.h b/src/modules/processes/processes.h index 0220c17dd0..6fe14cb87a 100644 --- a/src/modules/processes/processes.h +++ b/src/modules/processes/processes.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PROCESSES_MODULE_NAME "Processes" - bool ffPrintProcesses(FFProcessesOptions* options); void ffInitProcessesOptions(FFProcessesOptions* options); void ffDestroyProcessesOptions(FFProcessesOptions* options); diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index fe5002a43f..6cb741ca14 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -4,8 +4,6 @@ #include "modules/publicip/publicip.h" #include "detection/publicip/publicip.h" -#define FF_PUBLICIP_DISPLAY_NAME "Public IP" - bool ffPrintPublicIp(FFPublicIPOptions* options) { FFPublicIpResult result; ffStrbufInit(&result.ip); @@ -13,19 +11,19 @@ bool ffPrintPublicIp(FFPublicIPOptions* options) { const char* error = ffDetectPublicIp(options, &result); if (error) { - ffPrintError(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.location.length) { printf("%s (%s)\n", result.ip.chars, result.location.chars); } else { ffStrbufPutTo(&result.ip, stdout); } } else { - FF_PRINT_FORMAT_CHECKED(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.ip, "ip"), FF_ARG(result.location, "location"), })); @@ -60,7 +58,7 @@ void ffParsePublicIpJsonObject(FFPublicIPOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_PUBLICIP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(PublicIP), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -110,7 +108,7 @@ void ffDestroyPublicIpOptions(FFPublicIPOptions* options) { } FFModuleBaseInfo ffPublicIPModuleInfo = { - .name = FF_PUBLICIP_MODULE_NAME, + .name = "PublicIp", .description = "Print your public IP address and related information", .displayName = { .en = "Public IP", diff --git a/src/modules/publicip/publicip.h b/src/modules/publicip/publicip.h index 92768cbb6e..65b934bafc 100644 --- a/src/modules/publicip/publicip.h +++ b/src/modules/publicip/publicip.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_PUBLICIP_MODULE_NAME "PublicIp" - void ffPreparePublicIp(FFPublicIPOptions* options); bool ffPrintPublicIp(FFPublicIPOptions* options); diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index eaf9128195..4ef3a3af24 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -95,11 +95,11 @@ void ffParseSeparatorJsonObject(FFSeparatorOptions* options, yyjson_val* module) } if (unsafe_yyjson_equals_str(key, "length")) { - ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "The option length has been renamed to times."); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Separator), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "The option length has been renamed to times."); continue; } - ffPrintError(FF_SEPARATOR_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Separator), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -121,7 +121,7 @@ void ffDestroySeparatorOptions(FFSeparatorOptions* options) { } FFModuleBaseInfo ffSeparatorModuleInfo = { - .name = FF_SEPARATOR_MODULE_NAME, + .name = "Separator", .description = "Print a separator line", .displayName = { .en = "Separator", diff --git a/src/modules/separator/separator.h b/src/modules/separator/separator.h index eebf39af36..2ad9c8fabf 100644 --- a/src/modules/separator/separator.h +++ b/src/modules/separator/separator.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SEPARATOR_MODULE_NAME "Separator" - bool ffPrintSeparator(FFSeparatorOptions* options); void ffInitSeparatorOptions(FFSeparatorOptions* options); void ffDestroySeparatorOptions(FFSeparatorOptions* options); diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index a1df091c36..dd161759ca 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -8,12 +8,12 @@ bool ffPrintShell(FFShellOptions* options) { const FFShellResult* result = ffDetectShell(); if (result->processName.length == 0) { - ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect shell"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect shell"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result->prettyName, stdout); if (result->version.length > 0) { @@ -23,7 +23,7 @@ bool ffPrintShell(FFShellOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->processName, "process-name"), FF_ARG(result->exe, "exe"), FF_ARG(result->exeName, "exe-name"), @@ -46,7 +46,7 @@ void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Shell), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -89,7 +89,7 @@ void ffDestroyShellOptions(FFShellOptions* options) { } FFModuleBaseInfo ffShellModuleInfo = { - .name = FF_SHELL_MODULE_NAME, + .name = "Shell", .description = "Print the current shell name and version", .displayName = { .en = "Shell", diff --git a/src/modules/shell/shell.h b/src/modules/shell/shell.h index 50a094c80a..c8aec55742 100644 --- a/src/modules/shell/shell.h +++ b/src/modules/shell/shell.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SHELL_MODULE_NAME "Shell" - bool ffPrintShell(FFShellOptions* options); void ffInitShellOptions(FFShellOptions* options); void ffDestroyShellOptions(FFShellOptions* options); diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index eaa0d44b7c..c29cb574e9 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -8,7 +8,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, uint8_t index) { FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Sound), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { @@ -54,7 +54,7 @@ static void printDevice(FFSoundOptions* options, const FFSoundDevice* device, ui bool isMain = !!(device->type & FF_SOUND_TYPE_MAIN); bool isActive = !!(device->type & FF_SOUND_TYPE_ACTIVE); - FF_PRINT_FORMAT_CHECKED(FF_SOUND_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Sound), index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(isMain, "is-main"), FF_ARG(isActive, "is-active"), FF_ARG(device->name, "name"), @@ -73,12 +73,12 @@ bool ffPrintSound(FFSoundOptions* options) { const char* error = ffDetectSound(options, &result); if (error) { - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (result.length == 0) { - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No matched sound devices found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No matched sound devices found"); return false; } @@ -113,7 +113,7 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) { {}, }); if (error) { - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { options->soundType = (FFSoundType) value; } @@ -124,7 +124,7 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Sound), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -199,7 +199,7 @@ void ffDestroySoundOptions(FFSoundOptions* options) { } FFModuleBaseInfo ffSoundModuleInfo = { - .name = FF_SOUND_MODULE_NAME, + .name = "Sound", .description = "Print sound devices, volume levels, etc", .displayName = { .en = "Sound", diff --git a/src/modules/sound/sound.h b/src/modules/sound/sound.h index a23f8d5e1b..651d640bfb 100644 --- a/src/modules/sound/sound.h +++ b/src/modules/sound/sound.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SOUND_MODULE_NAME "Sound" - bool ffPrintSound(FFSoundOptions* options); void ffInitSoundOptions(FFSoundOptions* options); void ffDestroySoundOptions(FFSoundOptions* options); diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 5b7c1117e0..a0ef873687 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -11,9 +11,9 @@ void printSwap(FFSwapOptions* options, uint8_t index, uint32_t totalCount, FFSwa if (options->moduleArgs.key.length == 0) { if (storage->name.length > 0) { - ffStrbufSetF(&key, "%s (%s)", FF_SWAP_MODULE_NAME, storage->name.chars); + ffStrbufSetF(&key, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Swap), storage->name.chars); } else { - ffStrbufSetS(&key, FF_SWAP_MODULE_NAME); + ffStrbufSetS(&key, FF_MODULE_GET_DISPLAY_NAME(Swap)); } } else { ffStrbufClear(&key); @@ -90,7 +90,7 @@ bool ffPrintSwap(FFSwapOptions* options) { const char* error = ffDetectSwap(&result); if (error) { - ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Swap), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -136,7 +136,7 @@ void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Swap), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -182,7 +182,7 @@ void ffDestroySwapOptions(FFSwapOptions* options) { } FFModuleBaseInfo ffSwapModuleInfo = { - .name = FF_SWAP_MODULE_NAME, + .name = "Swap", .description = "Print swap (paging file) space usage", .displayName = { .en = "Swap", diff --git a/src/modules/swap/swap.h b/src/modules/swap/swap.h index e6b9a8b8ee..7c0bf13eb8 100644 --- a/src/modules/swap/swap.h +++ b/src/modules/swap/swap.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_SWAP_MODULE_NAME "Swap" - bool ffPrintSwap(FFSwapOptions* options); void ffInitSwapOptions(FFSwapOptions* options); void ffDestroySwapOptions(FFSwapOptions* options); diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 7aa4e1a185..1b06dc4850 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -8,12 +8,12 @@ bool ffPrintTerminal(FFTerminalOptions* options) { const FFTerminalResult* result = ffDetectTerminal(); if (result->processName.length == 0) { - ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect terminal"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Couldn't detect terminal"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result->version.length) { printf("%s %s\n", result->prettyName.chars, result->version.chars); @@ -21,7 +21,7 @@ bool ffPrintTerminal(FFTerminalOptions* options) { ffStrbufPutTo(&result->prettyName, stdout); } } else { - FF_PRINT_FORMAT_CHECKED(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->processName, "process-name"), FF_ARG(result->exe, "exe"), FF_ARG(result->exeName, "exe-name"), @@ -44,7 +44,7 @@ void ffParseTerminalJsonObject(FFTerminalOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Terminal), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -83,7 +83,7 @@ void ffDestroyTerminalOptions(FFTerminalOptions* options) { } FFModuleBaseInfo ffTerminalModuleInfo = { - .name = FF_TERMINAL_MODULE_NAME, + .name = "Terminal", .description = "Print the current terminal name and version", .displayName = { .en = "Terminal", diff --git a/src/modules/terminal/terminal.h b/src/modules/terminal/terminal.h index bb7c9a10d8..c8a2072465 100644 --- a/src/modules/terminal/terminal.h +++ b/src/modules/terminal/terminal.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINAL_MODULE_NAME "Terminal" - bool ffPrintTerminal(FFTerminalOptions* options); void ffInitTerminalOptions(FFTerminalOptions* options); void ffDestroyTerminalOptions(FFTerminalOptions* options); diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 6c840889df..cea077d476 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -4,8 +4,6 @@ #include "detection/terminalfont/terminalfont.h" #include "modules/terminalfont/terminalfont.h" -#define FF_TERMINALFONT_DISPLAY_NAME "Terminal Font" - bool ffPrintTerminalFont(FFTerminalFontOptions* options) { bool success = false; FFTerminalFontResult terminalFont; @@ -14,10 +12,10 @@ bool ffPrintTerminalFont(FFTerminalFontOptions* options) { ffStrbufInit(&terminalFont.error); if (!ffDetectTerminalFont(&terminalFont)) { - ffPrintError(FF_TERMINALFONT_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", terminalFont.error.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", terminalFont.error.chars); } else { if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINALFONT_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&terminalFont.font.pretty, stdout); if (terminalFont.fallback.pretty.length) { fputs(" / ", stdout); @@ -25,7 +23,7 @@ bool ffPrintTerminalFont(FFTerminalFontOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_TERMINALFONT_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(terminalFont.font.pretty, "combined"), FF_ARG(terminalFont.font.name, "name"), FF_ARG(terminalFont.font.size, "size"), @@ -50,7 +48,7 @@ void ffParseTerminalFontJsonObject(FFTerminalFontOptions* options, yyjson_val* m continue; } - ffPrintError(FF_TERMINALFONT_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalFont), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -105,7 +103,7 @@ void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options) { } FFModuleBaseInfo ffTerminalFontModuleInfo = { - .name = FF_TERMINALFONT_MODULE_NAME, + .name = "TerminalFont", .description = "Print the font name and size used by the current terminal", .displayName = { .en = "Terminal Font", diff --git a/src/modules/terminalfont/terminalfont.h b/src/modules/terminalfont/terminalfont.h index 04987a61ea..a32e2e0b43 100644 --- a/src/modules/terminalfont/terminalfont.h +++ b/src/modules/terminalfont/terminalfont.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINALFONT_MODULE_NAME "TerminalFont" - bool ffPrintTerminalFont(FFTerminalFontOptions* options); void ffInitTerminalFontOptions(FFTerminalFontOptions* options); void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options); diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 11e34551b7..6fd7bf5d80 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -4,18 +4,16 @@ #include "detection/terminalsize/terminalsize.h" #include "modules/terminalsize/terminalsize.h" -#define FF_TERMINALSIZE_DISPLAY_NAME "Terminal Size" - bool ffPrintTerminalSize(FFTerminalSizeOptions* options) { FFTerminalSizeResult result = {}; if (!ffDetectTerminalSize(&result)) { - ffPrintError(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal size"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal size"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%u columns x %u rows", result.columns, result.rows); if (result.width != 0 && result.height != 0) { @@ -24,7 +22,7 @@ bool ffPrintTerminalSize(FFTerminalSizeOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.rows, "rows"), FF_ARG(result.columns, "columns"), FF_ARG(result.width, "width"), @@ -42,7 +40,7 @@ void ffParseTerminalSizeJsonObject(FFTerminalSizeOptions* options, yyjson_val* m continue; } - ffPrintError(FF_TERMINALSIZE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalSize), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -76,7 +74,7 @@ void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options) { } FFModuleBaseInfo ffTerminalSizeModuleInfo = { - .name = FF_TERMINALSIZE_MODULE_NAME, + .name = "TerminalSize", .description = "Print the current terminal size", .displayName = { .en = "Terminal Size", diff --git a/src/modules/terminalsize/terminalsize.h b/src/modules/terminalsize/terminalsize.h index 3cd05d5b23..0745b6a007 100644 --- a/src/modules/terminalsize/terminalsize.h +++ b/src/modules/terminalsize/terminalsize.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINALSIZE_MODULE_NAME "TerminalSize" - bool ffPrintTerminalSize(FFTerminalSizeOptions* options); void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options); void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options); diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 053db3453e..c8925e78d2 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -6,18 +6,16 @@ #include -#define FF_TERMINALTHEME_DISPLAY_NAME "Terminal Theme" - bool ffPrintTerminalTheme(FFTerminalThemeOptions* options) { FFTerminalThemeResult result = {}; if (!ffDetectTerminalTheme(&result, false)) { - ffPrintError(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal theme"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Failed to detect terminal theme"); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("#%02" PRIX16 "%02" PRIX16 "%02" PRIX16 " (FG) - #%02" PRIX16 "%02" PRIX16 "%02" PRIX16 " (BG) [%s]\n", result.fg.r, result.fg.g, @@ -32,7 +30,7 @@ bool ffPrintTerminalTheme(FFTerminalThemeOptions* options) { const char* bgType = result.bg.dark ? "Dark" : "Light"; snprintf(fg, ARRAY_SIZE(fg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.fg.r, result.fg.g, result.fg.b); snprintf(bg, ARRAY_SIZE(bg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.bg.r, result.bg.g, result.bg.b); - FF_PRINT_FORMAT_CHECKED(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(fg, "fg-color"), FF_ARG(fgType, "fg-type"), FF_ARG(bg, "bg-color"), @@ -51,7 +49,7 @@ void ffParseTerminalThemeJsonObject(FFTerminalThemeOptions* options, yyjson_val* continue; } - ffPrintError(FF_TERMINALTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TerminalTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -93,7 +91,7 @@ void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options) { } FFModuleBaseInfo ffTerminalThemeModuleInfo = { - .name = FF_TERMINALTHEME_MODULE_NAME, + .name = "TerminalTheme", .description = "Print the current terminal theme (foreground and background colors)", .displayName = { .en = "Terminal Theme", diff --git a/src/modules/terminaltheme/terminaltheme.h b/src/modules/terminaltheme/terminaltheme.h index db120f74ce..e48bca0831 100644 --- a/src/modules/terminaltheme/terminaltheme.h +++ b/src/modules/terminaltheme/terminaltheme.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TERMINALTHEME_MODULE_NAME "TerminalTheme" - bool ffPrintTerminalTheme(FFTerminalThemeOptions* options); void ffInitTerminalThemeOptions(FFTerminalThemeOptions* options); void ffDestroyTerminalThemeOptions(FFTerminalThemeOptions* options); diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 1769d5fc3e..44ab11cc19 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -12,12 +12,12 @@ bool ffPrintTheme(FFThemeOptions* options) { const char* error = ffDetectTheme(&result); if (error) { - ffPrintError(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.theme1.length) { ffStrbufWriteTo(&result.theme1, stdout); } @@ -29,7 +29,7 @@ bool ffPrintTheme(FFThemeOptions* options) { } putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.theme1, "theme1"), FF_ARG(result.theme2, "theme2"), })); @@ -48,7 +48,7 @@ void ffParseThemeJsonObject(FFThemeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Theme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -87,7 +87,7 @@ void ffDestroyThemeOptions(FFThemeOptions* options) { } FFModuleBaseInfo ffThemeModuleInfo = { - .name = FF_THEME_MODULE_NAME, + .name = "Theme", .description = "Print the current desktop environment theme", .displayName = { .en = "Theme", diff --git a/src/modules/theme/theme.h b/src/modules/theme/theme.h index 56ba49c812..83278d764d 100644 --- a/src/modules/theme/theme.h +++ b/src/modules/theme/theme.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_THEME_MODULE_NAME "Theme" - bool ffPrintTheme(FFThemeOptions* options); void ffInitThemeOptions(FFThemeOptions* options); void ffDestroyThemeOptions(FFThemeOptions* options); diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 3d8fe1a795..cce1c6bb1f 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -45,7 +45,7 @@ bool ffPrintTitle(FFTitleOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Title), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&userNameColored, stdout); ffStrbufWriteTo(&atColored, stdout); @@ -68,7 +68,7 @@ bool ffPrintTitle(FFTitleOptions* options) { ffStrbufTrimRight(&cwdTilde, '/'); } - FF_PRINT_FORMAT_CHECKED(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Title), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(instance.state.platform.userName, "user-name"), FF_ARG(hostName, "host-name"), FF_ARG(instance.state.platform.homeDir, "home-dir"), @@ -124,7 +124,7 @@ void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_TITLE_MODULE_NAME, 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Title), 0, nullptr, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -176,7 +176,7 @@ void ffDestroyTitleOptions(FFTitleOptions* options) { } FFModuleBaseInfo ffTitleModuleInfo = { - .name = FF_TITLE_MODULE_NAME, + .name = "Title", .description = "Print the title, including your username and hostname", .displayName = { .en = "Title", diff --git a/src/modules/title/title.h b/src/modules/title/title.h index 83c9496543..ce44461fa1 100644 --- a/src/modules/title/title.h +++ b/src/modules/title/title.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TITLE_MODULE_NAME "Title" - bool ffPrintTitle(FFTitleOptions* options); void ffInitTitleOptions(FFTitleOptions* options); void ffDestroyTitleOptions(FFTitleOptions* options); diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 3471d5a12a..1b85104e7b 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -12,19 +12,19 @@ bool ffPrintTPM(FFTPMOptions* options) { const char* error = ffDetectTPM(&result); if (error) { - ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.description.length > 0) { ffStrbufPutTo(&result.description, stdout); } else { ffStrbufPutTo(&result.version, stdout); } } else { - FF_PRINT_FORMAT_CHECKED(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.version, "version"), FF_ARG(result.description, "description"), })); @@ -44,7 +44,7 @@ void ffParseTPMJsonObject(FFTPMOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(TPM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -83,7 +83,7 @@ void ffDestroyTPMOptions(FFTPMOptions* options) { } FFModuleBaseInfo ffTPMModuleInfo = { - .name = FF_TPM_MODULE_NAME, + .name = "TPM", .description = "Print information about the Trusted Platform Module (TPM) security device", .displayName = { .en = "TPM", diff --git a/src/modules/tpm/tpm.h b/src/modules/tpm/tpm.h index 215f8c98aa..72ce6aac04 100644 --- a/src/modules/tpm/tpm.h +++ b/src/modules/tpm/tpm.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_TPM_MODULE_NAME "TPM" - bool ffPrintTPM(FFTPMOptions* options); void ffInitTPMOptions(FFTPMOptions* options); void ffDestroyTPMOptions(FFTPMOptions* options); diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index b4299d7a5b..0bed6ea134 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -12,7 +12,7 @@ bool ffPrintUptime(FFUptimeOptions* options) { const char* error = ffDetectUptime(&result); if (error) { - ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Uptime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } @@ -21,7 +21,7 @@ bool ffPrintUptime(FFUptimeOptions* options) { ffDurationAppendNum((uptime + 500) / 1000, &buffer); if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Uptime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&buffer, stdout); } else { uint32_t milliseconds = (uint32_t) (uptime % 1000); @@ -36,7 +36,7 @@ bool ffPrintUptime(FFUptimeOptions* options) { FFTimeGetAgeResult age = ffTimeGetAge(result.bootTime, ffTimeGetNow()); - FF_PRINT_FORMAT_CHECKED(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(days, "days"), FF_ARG(hours, "hours"), FF_ARG(minutes, "minutes"), FF_ARG(seconds, "seconds"), FF_ARG(milliseconds, "milliseconds"), { FF_ARG_TYPE_STRING, ffTimeToShortStr(result.bootTime), "boot-time" }, FF_ARG(age.years, "years"), FF_ARG(age.daysOfYear, "days-of-year"), FF_ARG(age.yearsFraction, "years-fraction"), FF_ARG(buffer, "formatted") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Uptime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(days, "days"), FF_ARG(hours, "hours"), FF_ARG(minutes, "minutes"), FF_ARG(seconds, "seconds"), FF_ARG(milliseconds, "milliseconds"), { FF_ARG_TYPE_STRING, ffTimeToShortStr(result.bootTime), "boot-time" }, FF_ARG(age.years, "years"), FF_ARG(age.daysOfYear, "days-of-year"), FF_ARG(age.yearsFraction, "years-fraction"), FF_ARG(buffer, "formatted") })); } return true; @@ -50,7 +50,7 @@ void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Uptime), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -83,7 +83,7 @@ void ffDestroyUptimeOptions(FFUptimeOptions* options) { } FFModuleBaseInfo ffUptimeModuleInfo = { - .name = FF_UPTIME_MODULE_NAME, + .name = "Uptime", .description = "Print how long the system has been running", .displayName = { .en = "Uptime", diff --git a/src/modules/uptime/uptime.h b/src/modules/uptime/uptime.h index dec5f95e5c..c9db7dcd37 100644 --- a/src/modules/uptime/uptime.h +++ b/src/modules/uptime/uptime.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_UPTIME_MODULE_NAME "Uptime" - bool ffPrintUptime(FFUptimeOptions* options); void ffInitUptimeOptions(FFUptimeOptions* options); void ffDestroyUptimeOptions(FFUptimeOptions* options); diff --git a/src/modules/users/users.c b/src/modules/users/users.c index f67073e188..c59373beef 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -13,18 +13,18 @@ bool ffPrintUsers(FFUsersOptions* options) { const char* error = ffDetectUsers(options, &users); if (error) { - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (users.length == 0) { - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Unable to detect any users"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "Unable to detect any users"); return false; } if (options->moduleArgs.outputFormat.length == 0) { if (options->compact) { - ffPrintLogoAndKey(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); for (uint32_t i = 0; i < users.length; ++i) { @@ -39,7 +39,7 @@ bool ffPrintUsers(FFUsersOptions* options) { for (uint32_t i = 0; i < users.length; ++i) { FFUserResult* user = FF_LIST_GET(FFUserResult, users, i); - ffPrintLogoAndKey(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Users), users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateCopy(&user->name); if (user->hostName.length) { @@ -71,7 +71,7 @@ bool ffPrintUsers(FFUsersOptions* options) { FFTimeGetAgeResult age = ffTimeGetAge(user->loginTime, ffTimeGetNow()); - FF_PRINT_FORMAT_CHECKED(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Users), users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(user->name, "name"), FF_ARG(user->hostName, "host-name"), FF_ARG(user->sessionName, "session-name"), @@ -121,7 +121,7 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Users), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -180,7 +180,7 @@ void ffDestroyUsersOptions(FFUsersOptions* options) { } FFModuleBaseInfo ffUsersModuleInfo = { - .name = FF_USERS_MODULE_NAME, + .name = "Users", .description = "Print users who are currently logged in", .displayName = { .en = "Users", diff --git a/src/modules/users/users.h b/src/modules/users/users.h index 44c8b01d7e..2567b395c4 100644 --- a/src/modules/users/users.h +++ b/src/modules/users/users.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_USERS_MODULE_NAME "Users" - bool ffPrintUsers(FFUsersOptions* options); void ffInitUsersOptions(FFUsersOptions* options); void ffDestroyUsersOptions(FFUsersOptions* options); diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 2bd906a21f..56c142d76e 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -9,7 +9,7 @@ bool ffPrintVersion(FFVersionOptions* options) { FFVersionResult* result = &ffVersionResult; if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Version), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); printf("%s %s%s%s (%s)\n", result->projectName, result->version, result->versionTweak, result->debugMode ? "-debug" : "", result->architecture); } else { FFLibcResult libcResult; @@ -23,7 +23,7 @@ bool ffPrintVersion(FFVersionOptions* options) { } const char* buildType = result->debugMode ? "debug" : "release"; - FF_PRINT_FORMAT_CHECKED(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Version), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->projectName, "project-name"), FF_ARG(result->version, "version"), FF_ARG(result->versionTweak, "version-tweak"), @@ -48,7 +48,7 @@ void ffParseVersionJsonObject(FFVersionOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Version), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -94,7 +94,7 @@ void ffDestroyVersionOptions(FFVersionOptions* options) { } FFModuleBaseInfo ffVersionModuleInfo = { - .name = FF_VERSION_MODULE_NAME, + .name = "Version", .description = "Print the Fastfetch version and build information", .displayName = { .en = "Version", diff --git a/src/modules/version/version.h b/src/modules/version/version.h index add5e1198f..5cfaf1f14c 100644 --- a/src/modules/version/version.h +++ b/src/modules/version/version.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_VERSION_MODULE_NAME "Version" - bool ffPrintVersion(FFVersionOptions* options); void ffInitVersionOptions(FFVersionOptions* options); void ffDestroyVersionOptions(FFVersionOptions* options); diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 9dedfd9cc7..a16cac6014 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -9,12 +9,12 @@ bool ffPrintVulkan(FFVulkanOptions* options) { const FFVulkanResult* vulkan = ffDetectVulkan(); if (vulkan->error) { - ffPrintError(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", vulkan->error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", vulkan->error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (vulkan->apiVersion.length == 0 && vulkan->driver.length == 0) { ffStrbufWriteTo(&vulkan->instanceVersion, stdout); @@ -35,7 +35,7 @@ bool ffPrintVulkan(FFVulkanOptions* options) { putchar('\n'); } } else { - FF_PRINT_FORMAT_CHECKED(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(vulkan->driver, "driver"), FF_ARG(vulkan->apiVersion, "api-version"), FF_ARG(vulkan->conformanceVersion, "conformance-version"), @@ -54,7 +54,7 @@ void ffParseVulkanJsonObject(FFVulkanOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Vulkan), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -132,7 +132,7 @@ void ffDestroyVulkanOptions(FFVulkanOptions* options) { } FFModuleBaseInfo ffVulkanModuleInfo = { - .name = FF_VULKAN_MODULE_NAME, + .name = "Vulkan", .description = "Print the highest Vulkan version supported by the GPU", .displayName = { .en = "Vulkan", diff --git a/src/modules/vulkan/vulkan.h b/src/modules/vulkan/vulkan.h index c838028c5d..141ad99334 100644 --- a/src/modules/vulkan/vulkan.h +++ b/src/modules/vulkan/vulkan.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_VULKAN_MODULE_NAME "Vulkan" - bool ffPrintVulkan(FFVulkanOptions* options); void ffInitVulkanOptions(FFVulkanOptions* options); void ffDestroyVulkanOptions(FFVulkanOptions* options); diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index fc1393fb9f..e0f203a581 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -21,15 +21,15 @@ bool ffPrintWallpaper(FFWallpaperOptions* options) { : fullpath.chars + index; if (error) { - ffPrintError(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(filename); } else { - FF_PRINT_FORMAT_CHECKED(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(filename, "file-name"), FF_ARG(fullpath, "full-path"), })); @@ -46,7 +46,7 @@ void ffParseWallpaperJsonObject(FFWallpaperOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wallpaper), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -75,7 +75,7 @@ void ffDestroyWallpaperOptions(FFWallpaperOptions* options) { } FFModuleBaseInfo ffWallpaperModuleInfo = { - .name = FF_WALLPAPER_MODULE_NAME, + .name = "Wallpaper", .description = "Print the file path of the current wallpaper", .displayName = { .en = "Wallpaper", diff --git a/src/modules/wallpaper/wallpaper.h b/src/modules/wallpaper/wallpaper.h index c3e72911be..eed2fa21c8 100644 --- a/src/modules/wallpaper/wallpaper.h +++ b/src/modules/wallpaper/wallpaper.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WALLPAPER_MODULE_NAME "Wallpaper" - bool ffPrintWallpaper(FFWallpaperOptions* options); void ffInitWallpaperOptions(FFWallpaperOptions* options); void ffDestroyWallpaperOptions(FFWallpaperOptions* options); diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 8307ce4223..7a2192a791 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -9,15 +9,15 @@ bool ffPrintWeather(FFWeatherOptions* options) { const char* error = ffDetectWeather(options, &result); if (error) { - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufPutTo(&result, stdout); } else { - FF_PRINT_FORMAT_CHECKED(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result, "result"), })); } @@ -48,7 +48,7 @@ void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Weather), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -92,7 +92,7 @@ void ffDestroyWeatherOptions(FFWeatherOptions* options) { } FFModuleBaseInfo ffWeatherModuleInfo = { - .name = FF_WEATHER_MODULE_NAME, + .name = "Weather", .description = "Print weather information", .displayName = { .en = "Weather", diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h index f28a4c2332..e2b8394eaf 100644 --- a/src/modules/weather/weather.h +++ b/src/modules/weather/weather.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WEATHER_MODULE_NAME "Weather" - void ffPrepareWeather(FFWeatherOptions* options); bool ffPrintWeather(FFWeatherOptions* options); diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 58e5da965d..d5baa00ffe 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -9,11 +9,11 @@ bool ffPrintWifi(FFWifiOptions* options) { const char* error = ffDetectWifi(&result); if (error) { - ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wifi), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (!result.length) { - ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No Wifi interfaces found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wifi), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No Wifi interfaces found"); return false; } @@ -46,7 +46,7 @@ bool ffPrintWifi(FFWifiOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WIFI_MODULE_NAME, moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (item->conn.ssid.length) { @@ -95,7 +95,7 @@ bool ffPrintWifi(FFWifiOptions* options) { ffPercentAppendBar(&percentBar, item->conn.signalQuality, options->percent, &options->moduleArgs); } - FF_PRINT_FORMAT_CHECKED(FF_WIFI_MODULE_NAME, moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(item->inf.description, "inf-desc"), FF_ARG(item->inf.status, "inf-status"), FF_ARG(item->conn.status, "status"), @@ -138,7 +138,7 @@ void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Wifi), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -213,7 +213,7 @@ void ffDestroyWifiOptions(FFWifiOptions* options) { } FFModuleBaseInfo ffWifiModuleInfo = { - .name = FF_WIFI_MODULE_NAME, + .name = "Wifi", .description = "Print connected Wi-Fi info (SSID, connection and security protocol)", .displayName = { .en = "Wi-Fi", diff --git a/src/modules/wifi/wifi.h b/src/modules/wifi/wifi.h index 506e1e22af..dd640815c8 100644 --- a/src/modules/wifi/wifi.h +++ b/src/modules/wifi/wifi.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WIFI_MODULE_NAME "Wifi" - bool ffPrintWifi(FFWifiOptions* options); void ffInitWifiOptions(FFWifiOptions* options); void ffDestroyWifiOptions(FFWifiOptions* options); diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 3545bfc9e6..35e58c4f1f 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -9,7 +9,7 @@ bool ffPrintWM(FFWMOptions* options) { const FFDisplayServerResult* result = ffConnectDisplayServer(); if (result->wmPrettyName.length == 0) { - ffPrintError(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No WM found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No WM found"); return false; } @@ -24,7 +24,7 @@ bool ffPrintWM(FFWMOptions* options) { } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&result->wmPrettyName, stdout); @@ -47,7 +47,7 @@ bool ffPrintWM(FFWMOptions* options) { putchar('\n'); } else { - FF_PRINT_FORMAT_CHECKED(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result->wmProcessName, "process-name"), FF_ARG(result->wmPrettyName, "pretty-name"), FF_ARG(result->wmProtocolName, "protocol-name"), @@ -72,7 +72,7 @@ void ffParseWMJsonObject(FFWMOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -120,7 +120,7 @@ void ffDestroyWMOptions(FFWMOptions* options) { } FFModuleBaseInfo ffWMModuleInfo = { - .name = FF_WM_MODULE_NAME, + .name = "WM", .description = "Print the window manager name and version", .displayName = { .en = "WM", diff --git a/src/modules/wm/wm.h b/src/modules/wm/wm.h index 4819d73946..5e085ef015 100644 --- a/src/modules/wm/wm.h +++ b/src/modules/wm/wm.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WM_MODULE_NAME "WM" - bool ffPrintWM(FFWMOptions* options); void ffInitWMOptions(FFWMOptions* options); void ffDestroyWMOptions(FFWMOptions* options); diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 7061f66aea..8c7e3afe31 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -4,20 +4,18 @@ #include "detection/wmtheme/wmtheme.h" #include "modules/wmtheme/wmtheme.h" -#define FF_WMTHEME_DISPLAY_NAME "WM Theme" - bool ffPrintWMTheme(FFWMThemeOptions* options) { FF_STRBUF_AUTO_DESTROY themeOrError = ffStrbufCreate(); if (!ffDetectWmTheme(&themeOrError)) { - ffPrintError(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", themeOrError.chars); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", themeOrError.chars); return false; } if (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); puts(themeOrError.chars); } else { - FF_PRINT_FORMAT_CHECKED(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(themeOrError, "result"), })); } @@ -33,7 +31,7 @@ void ffParseWMThemeJsonObject(FFWMThemeOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(WMTheme), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -61,7 +59,7 @@ void ffDestroyWMThemeOptions(FFWMThemeOptions* options) { } FFModuleBaseInfo ffWMThemeModuleInfo = { - .name = FF_WMTHEME_MODULE_NAME, + .name = "WMTheme", .description = "Print the current window manager theme", .displayName = { .en = "WM Theme", diff --git a/src/modules/wmtheme/wmtheme.h b/src/modules/wmtheme/wmtheme.h index 5142ca42cc..46c8299c37 100644 --- a/src/modules/wmtheme/wmtheme.h +++ b/src/modules/wmtheme/wmtheme.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_WMTHEME_MODULE_NAME "WMTheme" - bool ffPrintWMTheme(FFWMThemeOptions* options); void ffInitWMThemeOptions(FFWMThemeOptions* options); void ffDestroyWMThemeOptions(FFWMThemeOptions* options); diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index b155ff3b12..0e447d5e45 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -11,9 +11,9 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (options->moduleArgs.key.length == 0) { if (result->name.length > 0) { - ffStrbufSetF(&buffer, "%s (%s)", FF_ZPOOL_MODULE_NAME, result->name.chars); + ffStrbufSetF(&buffer, "%s (%s)", FF_MODULE_GET_DISPLAY_NAME(Zpool), result->name.chars); } else { - ffStrbufSetS(&buffer, FF_ZPOOL_MODULE_NAME); + ffStrbufSetS(&buffer, FF_MODULE_GET_DISPLAY_NAME(Zpool)); } } else { ffStrbufClear(&buffer); @@ -105,11 +105,11 @@ bool ffPrintZpool(FFZpoolOptions* options) { const char* error = ffDetectZpool(&results); if (error) { - ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Zpool), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); return false; } if (results.length == 0) { - ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No zpool found"); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Zpool), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", "No zpool found"); return false; } @@ -138,7 +138,7 @@ void ffParseZpoolJsonObject(FFZpoolOptions* options, yyjson_val* module) { continue; } - ffPrintError(FF_ZPOOL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Zpool), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } @@ -192,7 +192,7 @@ void ffDestroyZpoolOptions(FFZpoolOptions* options) { } FFModuleBaseInfo ffZpoolModuleInfo = { - .name = FF_ZPOOL_MODULE_NAME, + .name = "Zpool", .description = "Print ZFS storage pools", .displayName = { .en = "Zpool", diff --git a/src/modules/zpool/zpool.h b/src/modules/zpool/zpool.h index 35706bb356..3faed199fa 100644 --- a/src/modules/zpool/zpool.h +++ b/src/modules/zpool/zpool.h @@ -2,8 +2,6 @@ #include "option.h" -#define FF_ZPOOL_MODULE_NAME "Zpool" - bool ffPrintZpool(FFZpoolOptions* options); void ffInitZpoolOptions(FFZpoolOptions* options); void ffDestroyZpoolOptions(FFZpoolOptions* options); diff --git a/src/options/display.c b/src/options/display.c index d515e92c1b..434048e92a 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -8,9 +8,68 @@ #if !FF_MODULE_DISABLE_TERMINALTHEME #include "detection/terminaltheme/terminaltheme.h" #endif +#if !FF_MODULE_DISABLE_LOCALE + #include "detection/locale/locale.h" +#endif #include +// @returns offsetof(FFModuleDisplayName, ) +// @see src/common/option.h +static uint32_t optionParseLanguageString(FFstrbuf* language) { + if (language->length == 0) { +#if !FF_MODULE_DISABLE_LOCALE + ffDetectLocale(language); +#else + fputs("Error: --key-language requires a value\n", stderr); + exit(477); +#endif + } + + // The language code is expected to be in the format of "en", "en_US", "de", "de_DE", etc. + // First try to match the full language code, then try to match just the first two characters (the language part). + // If no match is found, report a language not supported error. + // en_US -> offsetof(FFModuleDisplayName, en) + // de_DE -> offsetof(FFModuleDisplayName, de) + // zh_CN -> offsetof(FFModuleDisplayName, zh_CN) + // ar -> Error: Language 'ar' is not supported + + // Try to match the full language code, e.g. "en", "pt_BR", "zh_CN" + static const FFKeyValuePair pairs[] = { + { "en", offsetof(FFModuleDisplayName, en) }, + { "de", offsetof(FFModuleDisplayName, de) }, + { "es", offsetof(FFModuleDisplayName, es) }, + { "fr", offsetof(FFModuleDisplayName, fr) }, + { "it", offsetof(FFModuleDisplayName, it) }, + { "ja", offsetof(FFModuleDisplayName, ja) }, + { "ko", offsetof(FFModuleDisplayName, ko) }, + { "pl", offsetof(FFModuleDisplayName, pl) }, + { "pt_BR", offsetof(FFModuleDisplayName, pt_BR) }, + { "ru", offsetof(FFModuleDisplayName, ru) }, + { "zh_CN", offsetof(FFModuleDisplayName, zh_CN) }, + { "zh_TW", offsetof(FFModuleDisplayName, zh_TW) }, + {}, + }; + + for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { + if (ffStrbufIgnCaseEqualS(language, pair->key)) { + return (uint32_t) pair->value; + } + } + + // Try to match just the first two characters (the language part), e.g. "en" from "en_US", "de" from "de_DE" + if (language->length >= 2) { + for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { + if (ffStrbufStartsWithIgnCaseS(language, pair->key)) { + return (uint32_t) pair->value; + } + } + } + + fprintf(stderr, "Error: Language '%s' is not supported\n", language->chars); + exit(477); +} + const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_val* root, yyjson_val** pkey) { yyjson_val* object = yyjson_obj_get(root, "display"); if (!object) { @@ -483,6 +542,17 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va if (paddingLeft) { options->keyPaddingLeft = (uint16_t) yyjson_get_uint(paddingLeft); } + + yyjson_val* language = yyjson_obj_get(val, "language"); + if (language) { + FF_STRBUF_AUTO_DESTROY languageBuffer = ffStrbufCreate(); + if (yyjson_is_str(language)) { + ffStrbufSetJsonVal(&languageBuffer, language); + } else if (!yyjson_is_null(language)) { + return "display.key.language must be a string or null"; + } + options->keyLanguage = optionParseLanguageString(&languageBuffer); + } } else { return "display.key must be an object"; } @@ -651,6 +721,9 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key options->keyType = (FFModuleKeyType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { { "none", FF_MODULE_KEY_TYPE_NONE }, { "string", FF_MODULE_KEY_TYPE_STRING }, { "icon", FF_MODULE_KEY_TYPE_ICON }, { "both", FF_MODULE_KEY_TYPE_BOTH }, { "both-0", FF_MODULE_KEY_TYPE_BOTH_0 }, { "both-1", FF_MODULE_KEY_TYPE_BOTH_1 }, { "both-2", FF_MODULE_KEY_TYPE_BOTH_2 }, { "both-3", FF_MODULE_KEY_TYPE_BOTH_3 }, { "both-4", FF_MODULE_KEY_TYPE_BOTH_4 }, {} }); } else if (ffStrEqualsIgnCase(subkey, "padding-left")) { options->keyPaddingLeft = (uint16_t) ffOptionParseUInt32(key, value); + } else if (ffStrEqualsIgnCase(subkey, "language")) { + FF_STRBUF_AUTO_DESTROY language = ffStrbufCreateStatic(value); + options->keyLanguage = optionParseLanguageString(&language); } else { return false; } @@ -867,6 +940,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) { options->keyWidth = 0; options->keyPaddingLeft = 0; options->keyType = FF_MODULE_KEY_TYPE_STRING; + options->keyLanguage = offsetof(FFModuleDisplayName, en); options->tempUnit = FF_TEMPERATURE_UNIT_DEFAULT; options->tempNdigits = 1; @@ -1168,6 +1242,45 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) } yyjson_mut_obj_add_uint(doc, key, "paddingLeft", options->keyPaddingLeft); + + switch (options->keyLanguage) { + case offsetof(FFModuleDisplayName, en): + yyjson_mut_obj_add_str(doc, key, "language", "en"); + break; + case offsetof(FFModuleDisplayName, de): + yyjson_mut_obj_add_str(doc, key, "language", "de"); + break; + case offsetof(FFModuleDisplayName, es): + yyjson_mut_obj_add_str(doc, key, "language", "es"); + break; + case offsetof(FFModuleDisplayName, fr): + yyjson_mut_obj_add_str(doc, key, "language", "fr"); + break; + case offsetof(FFModuleDisplayName, it): + yyjson_mut_obj_add_str(doc, key, "language", "it"); + break; + case offsetof(FFModuleDisplayName, ja): + yyjson_mut_obj_add_str(doc, key, "language", "ja"); + break; + case offsetof(FFModuleDisplayName, ko): + yyjson_mut_obj_add_str(doc, key, "language", "ko"); + break; + case offsetof(FFModuleDisplayName, pl): + yyjson_mut_obj_add_str(doc, key, "language", "pl"); + break; + case offsetof(FFModuleDisplayName, pt_BR): + yyjson_mut_obj_add_str(doc, key, "language", "pt_BR"); + break; + case offsetof(FFModuleDisplayName, ru): + yyjson_mut_obj_add_str(doc, key, "language", "ru"); + break; + case offsetof(FFModuleDisplayName, zh_CN): + yyjson_mut_obj_add_str(doc, key, "language", "zh_CN"); + break; + case offsetof(FFModuleDisplayName, zh_TW): + yyjson_mut_obj_add_str(doc, key, "language", "zh_TW"); + break; + } } { diff --git a/src/options/display.h b/src/options/display.h index 8e234b08a0..2706a3e96a 100644 --- a/src/options/display.h +++ b/src/options/display.h @@ -80,6 +80,7 @@ typedef struct FFOptionsDisplay { uint8_t percentWidth; bool noBuffer; FFModuleKeyType keyType; + uint32_t keyLanguage; // Offset of FFModuleDisplayName member uint16_t keyWidth; uint16_t keyPaddingLeft; int8_t freqNdigits; From bdba78c45c3448bb4e3505a8c87a6e112a02ea64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 14 Aug 2026 23:56:29 +0800 Subject: [PATCH 006/109] CI: silences codespell errors --- .codespellrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index 66e8f1098c..1554e62701 100644 --- a/.codespellrc +++ b/.codespellrc @@ -2,4 +2,4 @@ check-filenames = builtin = clear,rare,usage,informal skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h,./src/detection/cpu/cpu_x86.c,./src/detection/gpu/gpu_bsddrm.c,./src/detection/displayserver/linux/wayland/*-protocol.*,./build,./build-*,./build_*,./src/common/impl/genconfig.c -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement From e5c3fa40231b37b7f0ca3d53558d219b53250dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 15 Aug 2026 00:00:27 +0800 Subject: [PATCH 007/109] CI: fixes compiling errors --- src/common/FFstrbuf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/FFstrbuf.h b/src/common/FFstrbuf.h index d84ed35066..0f4f405a6a 100644 --- a/src/common/FFstrbuf.h +++ b/src/common/FFstrbuf.h @@ -629,4 +629,4 @@ static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) { bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf); #define FF_STRBUF_AUTO_DESTROY [[gnu::cleanup(ffStrbufDestroy)]] FFstrbuf -#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) ARRAY_SIZE(str) - 1, .chars = str } +#define FF_STRBUF_STATIC(str) { .allocated = 0, .length = (uint32_t) sizeof(str) - 1, .chars = str } From 4dc27b365fa0550af51cd849c3c89bea8f598283 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 15 Aug 2026 08:51:45 +0800 Subject: [PATCH 008/109] DiskIO / NetIO: fixes I/O rate calculation precision, prevent div-by-zero --- src/detection/diskio/diskio.c | 3 +-- src/detection/netio/netio.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c index 73f0075a75..a2f53439c1 100644 --- a/src/detection/diskio/diskio.c +++ b/src/detection/diskio/diskio.c @@ -72,8 +72,7 @@ const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) { uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); uint64_t temp = *currValue; - *currValue -= *prevValue; - *currValue /= (time2 - time1) / 1000 /* seconds */; + *currValue = (*currValue - *prevValue) * 1000 / (time2 - time1); // Calculate per second // For next function call *prevValue = temp; diff --git a/src/detection/netio/netio.c b/src/detection/netio/netio.c index a6348265bb..3c986a8631 100644 --- a/src/detection/netio/netio.c +++ b/src/detection/netio/netio.c @@ -70,8 +70,7 @@ const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options) { uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); uint64_t temp = *currValue; - *currValue -= *prevValue; - *currValue /= (time2 - time1) / 1000 /* seconds */; + *currValue = (*currValue - *prevValue) * 1000 / (time2 - time1); // Calculate per second *prevValue = temp; } } From 8d82eedaef9dbbd0abe2c58f7ce8b013414a836b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 15 Aug 2026 08:53:00 +0800 Subject: [PATCH 009/109] DiskIO / NetIO: updates default value of waitTime to reduce latency Also corrects docs. --- doc/json_schema.json | 8 ++++---- src/modules/diskio/diskio.c | 2 +- src/modules/netio/netio.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 01ef306de9..5ae9bcc27a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -2655,8 +2655,8 @@ }, "waitTime": { "type": "integer", - "description": "Wait time (in ms). Disk I/O = (totalBytesEnd - totalBytesStart) / waitTime", - "default": 200, + "description": "Wait time (in ms) used to measure the I/O rate (calculated in bytes/sec).\nAvoid setting this too low, as the kernel requires time to accurately update counters.\nIgnored if 'detectTotal' is true.", + "default": 500, "minimum": 1 }, "key": { @@ -3556,8 +3556,8 @@ }, "waitTime": { "type": "integer", - "description": "Wait time (in ms). Net I/O = (totalBytesEnd - totalBytesStart) / waitTime", - "default": 200, + "description": "Wait time (in ms) used to measure the I/O rate (calculated in bytes/sec).\nAvoid setting this too low, as the kernel requires time to accurately update counters.\nIgnored if 'detectTotal' is true.", + "default": 500, "minimum": 1 }, "key": { diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 9acfbe5112..87a18c54d4 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -161,7 +161,7 @@ void ffInitDiskIOOptions(FFDiskIOOptions* options) { ffStrbufInit(&options->namePrefix); options->detectTotal = false; - options->waitTime = 1000; + options->waitTime = 500; } void ffDestroyDiskIOOptions(FFDiskIOOptions* options) { diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index e062a55c8d..6023687909 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -188,7 +188,7 @@ void ffInitNetIOOptions(FFNetIOOptions* options) { #endif ; options->detectTotal = false; - options->waitTime = 1000; + options->waitTime = 500; } void ffDestroyNetIOOptions(FFNetIOOptions* options) { From b677f1e902932b728f547dcfef8eaafdabe99230 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 15 Aug 2026 09:03:12 +0800 Subject: [PATCH 010/109] Theme: improves GTK theme/icons/font detection on standalone WMs (Hyprland, sway, niri, i3) Fixes #2504 --- src/detection/gtk_qt/gtk.c | 99 +++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 43 deletions(-) diff --git a/src/detection/gtk_qt/gtk.c b/src/detection/gtk_qt/gtk.c index 12aaeac143..1740630e16 100644 --- a/src/detection/gtk_qt/gtk.c +++ b/src/detection/gtk_qt/gtk.c @@ -62,50 +62,63 @@ static void detectGTKFromSettings(FFGTKResult* result) { const FFDisplayServerResult* wmde = ffConnectDisplayServer(); - if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4)) { - themeName = ffSettingsGetXFConf("xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetXFConf("xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, nullptr, testXfconfWallpaperPropKey).strValue; - } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON)) { - themeName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetGnome("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; - } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_MATE)) { - themeName = ffSettingsGetGnome("/org/mate/interface/gtk-theme", "org.mate.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetGnome("/org/mate/interface/icon-theme", "org.mate.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetGnome("/org/mate/interface/font-name", "org.mate.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetGnome("/org/mate/desktop/background", "org.mate.background", nullptr, "picture-filename", FF_VARIANT_TYPE_STRING).strValue; - } else if ( - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) || - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_NEBIDE)) { - themeName = ffSettingsGetGnome("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; - iconsName = ffSettingsGetGnome("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; - fontName = ffSettingsGetGnome("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; - cursorTheme = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; - cursorSize = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; - wallpaper = ffSettingsGetGnome("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; - } else if ( - ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_ENLIGHTENMENT)) { - ffEnlightenmentSettings settings = {}; - if (ffSettingsGetEnlightenmentProperty(&settings)) { - themeName = settings.theme; - iconsName = settings.icon_theme; - fontName = settings.font; - cursorTheme = settings.use_e_cursor ? "Enlightenment" : "Application"; - cursorSize = settings.cursor_size; - wallpaper = settings.desktop_default_background; + if (wmde->dePrettyName.length > 0) { + if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_XFCE4)) { + themeName = ffSettingsGetXFConf("xsettings", "/Net/ThemeName", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetXFConf("xsettings", "/Net/IconThemeName", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetXFConf("xsettings", "/Gtk/FontName", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetXFConf("xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetXFConfFirstMatch("xfce4-desktop", "/backdrop/screen0", FF_VARIANT_TYPE_STRING, nullptr, testXfconfWallpaperPropKey).strValue; + } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_CINNAMON)) { + themeName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetGnome("/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetGnome("/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetGnome("/org/cinnamon/desktop/background/picture-uri", "org.cinnamon.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; + } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_MATE)) { + themeName = ffSettingsGetGnome("/org/mate/interface/gtk-theme", "org.mate.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetGnome("/org/mate/interface/icon-theme", "org.mate.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetGnome("/org/mate/interface/font-name", "org.mate.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-theme", "org.mate.peripherals-mouse", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetGnome("/org/mate/peripherals-mouse/cursor-size", "org.mate.peripherals-mouse", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetGnome("/org/mate/desktop/background", "org.mate.background", nullptr, "picture-filename", FF_VARIANT_TYPE_STRING).strValue; + } else if ( + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_UNITY) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_BUDGIE) || + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_NEBIDE)) { + themeName = ffSettingsGetGnome("/org/gnome/desktop/interface/gtk-theme", "org.gnome.desktop.interface", nullptr, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetGnome("/org/gnome/desktop/interface/icon-theme", "org.gnome.desktop.interface", nullptr, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetGnome("/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", nullptr, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", nullptr, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetGnome("/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", nullptr, "cursor-size", FF_VARIANT_TYPE_INT).intValue; + wallpaper = ffSettingsGetGnome("/org/gnome/desktop/background/picture-uri", "org.gnome.desktop.background", nullptr, "picture-uri", FF_VARIANT_TYPE_STRING).strValue; + } else if ( + ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_ENLIGHTENMENT)) { + ffEnlightenmentSettings settings = {}; + if (ffSettingsGetEnlightenmentProperty(&settings)) { + themeName = settings.theme; + iconsName = settings.icon_theme; + fontName = settings.font; + cursorTheme = settings.use_e_cursor ? "Enlightenment" : "Application"; + cursorSize = settings.cursor_size; + wallpaper = settings.desktop_default_background; + } } + } else { + // Standalone WMs (Hyprland, sway, niri, i3, ...) report no DE and have no settings + // daemon, but GTK apps on them still read org.gnome.desktop.interface. + // Read via DConf, not GSettings: GSettings synthesises the schema default for keys + // the user never set, DConf returns nothing. Runs last; applyGTKSettings() only + // fills still-empty fields, so config files always win. + themeName = ffSettingsGetDConf("/org/gnome/desktop/interface/gtk-theme", FF_VARIANT_TYPE_STRING).strValue; + iconsName = ffSettingsGetDConf("/org/gnome/desktop/interface/icon-theme", FF_VARIANT_TYPE_STRING).strValue; + fontName = ffSettingsGetDConf("/org/gnome/desktop/interface/font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGetDConf("/org/gnome/desktop/interface/cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGetDConf("/org/gnome/desktop/interface/cursor-size", FF_VARIANT_TYPE_INT).intValue; } applyGTKSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize, wallpaper); From 233c481f7a8746e210db6c59fc755acfd0b4f7b5 Mon Sep 17 00:00:00 2001 From: Guiorgy Date: Sat, 15 Aug 2026 05:15:03 +0400 Subject: [PATCH 011/109] CMAKE: bumps minimum CMake version to 3.21.0 (#2517) C_STANDARD 23 was added in 3.21 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 687e89b5e6..13a6fa83a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url +cmake_minimum_required(VERSION 3.21.0) # C_STANDARD project(fastfetch VERSION 2.67.1 From 45f9de6cd2b26ed70cb48029dd0dc9ee77bc6eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:27:20 +0800 Subject: [PATCH 012/109] L10n: improves performance --- src/options/display.c | 84 +++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/src/options/display.c b/src/options/display.c index 434048e92a..9ce0a96773 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -19,53 +19,75 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { if (language->length == 0) { #if !FF_MODULE_DISABLE_LOCALE - ffDetectLocale(language); + const char* error = ffDetectLocale(language); + if (__builtin_expect(error != nullptr, false)) { + fprintf(stderr, "ffDetectLocale: %s\n", error); + exit(477); + } #else fputs("Error: --key-language requires a value\n", stderr); exit(477); #endif } + ffStrbufSubstrBeforeFirstC(language, '.'); // Remove the encoding part of the locale + #if __linux__ + ffStrbufSubstrBeforeFirstC(language, '@'); // Remove the modifier part of the locale (Linux only) + #endif + ffStrbufLowerCase(language); + + if (language->length <= 1) { + if (language->chars[0] == 'c') { + return offsetof(FFModuleDisplayName, en); + } else { + goto error; + } + } else if (language->length > 2) { + if (language->chars[2] == '-') { + language->chars[2] = '_'; + } else if (__builtin_expect(language->chars[2] != '_', false)) { + goto error; + } + } + // The language code is expected to be in the format of "en", "en_US", "de", "de_DE", etc. // First try to match the full language code, then try to match just the first two characters (the language part). // If no match is found, report a language not supported error. // en_US -> offsetof(FFModuleDisplayName, en) - // de_DE -> offsetof(FFModuleDisplayName, de) + // en -> offsetof(FFModuleDisplayName, en) // zh_CN -> offsetof(FFModuleDisplayName, zh_CN) - // ar -> Error: Language 'ar' is not supported - - // Try to match the full language code, e.g. "en", "pt_BR", "zh_CN" - static const FFKeyValuePair pairs[] = { - { "en", offsetof(FFModuleDisplayName, en) }, - { "de", offsetof(FFModuleDisplayName, de) }, - { "es", offsetof(FFModuleDisplayName, es) }, - { "fr", offsetof(FFModuleDisplayName, fr) }, - { "it", offsetof(FFModuleDisplayName, it) }, - { "ja", offsetof(FFModuleDisplayName, ja) }, - { "ko", offsetof(FFModuleDisplayName, ko) }, - { "pl", offsetof(FFModuleDisplayName, pl) }, - { "pt_BR", offsetof(FFModuleDisplayName, pt_BR) }, - { "ru", offsetof(FFModuleDisplayName, ru) }, - { "zh_CN", offsetof(FFModuleDisplayName, zh_CN) }, - { "zh_TW", offsetof(FFModuleDisplayName, zh_TW) }, - {}, - }; - - for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { - if (ffStrbufIgnCaseEqualS(language, pair->key)) { - return (uint32_t) pair->value; + // zh -> Error: Language 'zh' is not supported. This is an intentional design decision, as the language code 'zh' could refer to either Simplified or Traditional Chinese. + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmultichar" + switch (language->chars[0] << 8 | language->chars[1]) { + case 'en': return offsetof(FFModuleDisplayName, en); + case 'de': return offsetof(FFModuleDisplayName, de); + case 'es': return offsetof(FFModuleDisplayName, es); + case 'fr': return offsetof(FFModuleDisplayName, fr); + case 'it': return offsetof(FFModuleDisplayName, it); + case 'ja': return offsetof(FFModuleDisplayName, ja); + case 'ko': return offsetof(FFModuleDisplayName, ko); + case 'pl': return offsetof(FFModuleDisplayName, pl); + case 'pt': { + if (ffStrbufEqualS(language, "pt_br")) { + return offsetof(FFModuleDisplayName, pt_BR); + } + goto error; } - } - - // Try to match just the first two characters (the language part), e.g. "en" from "en_US", "de" from "de_DE" - if (language->length >= 2) { - for (const FFKeyValuePair* pair = pairs; pair->key; ++pair) { - if (ffStrbufStartsWithIgnCaseS(language, pair->key)) { - return (uint32_t) pair->value; + case 'ru': return offsetof(FFModuleDisplayName, ru); + case 'zh': { + if (ffStrbufEqualS(language, "zh_cn")) { + return offsetof(FFModuleDisplayName, zh_CN); + } else if (ffStrbufEqualS(language, "zh_tw")) { + return offsetof(FFModuleDisplayName, zh_TW); } + goto error; } } +#pragma GCC diagnostic pop +error: fprintf(stderr, "Error: Language '%s' is not supported\n", language->chars); exit(477); } From 359cb0a79a3531e382fdb0c99357252936f08bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:37:06 +0800 Subject: [PATCH 013/109] L10n (Pt): renames `pt_BR` to `pt` --- doc/help.json | 2 +- doc/json_schema.json | 4 ++-- src/common/option.h | 2 +- src/modules/battery/battery.c | 2 +- src/modules/bios/bios.c | 2 +- src/modules/bluetooth/bluetooth.c | 2 +- src/modules/bluetoothradio/bluetoothradio.c | 2 +- src/modules/board/board.c | 2 +- src/modules/bootmgr/bootmgr.c | 2 +- src/modules/break/break.c | 2 +- src/modules/brightness/brightness.c | 2 +- src/modules/btrfs/btrfs.c | 2 +- src/modules/camera/camera.c | 2 +- src/modules/chassis/chassis.c | 2 +- src/modules/codec/codec.c | 2 +- src/modules/colors/colors.c | 2 +- src/modules/command/command.c | 2 +- src/modules/cpu/cpu.c | 2 +- src/modules/cpucache/cpucache.c | 2 +- src/modules/cpuusage/cpuusage.c | 2 +- src/modules/cursor/cursor.c | 2 +- src/modules/custom/custom.c | 2 +- src/modules/datetime/datetime.c | 2 +- src/modules/de/de.c | 2 +- src/modules/disk/disk.c | 2 +- src/modules/diskio/diskio.c | 2 +- src/modules/display/display.c | 2 +- src/modules/dns/dns.c | 2 +- src/modules/editor/editor.c | 2 +- src/modules/font/font.c | 2 +- src/modules/gamepad/gamepad.c | 2 +- src/modules/gpu/gpu.c | 2 +- src/modules/host/host.c | 2 +- src/modules/icons/icons.c | 2 +- src/modules/initsystem/initsystem.c | 2 +- src/modules/kernel/kernel.c | 2 +- src/modules/keyboard/keyboard.c | 2 +- src/modules/lm/lm.c | 2 +- src/modules/loadavg/loadavg.c | 2 +- src/modules/locale/locale.c | 2 +- src/modules/localip/localip.c | 2 +- src/modules/logo/logo.c | 2 +- src/modules/media/media.c | 2 +- src/modules/memory/memory.c | 2 +- src/modules/monitor/monitor.c | 2 +- src/modules/mouse/mouse.c | 2 +- src/modules/netio/netio.c | 2 +- src/modules/opencl/opencl.c | 2 +- src/modules/opengl/opengl.c | 2 +- src/modules/os/os.c | 2 +- src/modules/packages/packages.c | 2 +- src/modules/physicaldisk/physicaldisk.c | 2 +- src/modules/physicalmemory/physicalmemory.c | 2 +- src/modules/player/player.c | 2 +- src/modules/poweradapter/poweradapter.c | 2 +- src/modules/processes/processes.c | 2 +- src/modules/publicip/publicip.c | 2 +- src/modules/separator/separator.c | 2 +- src/modules/shell/shell.c | 2 +- src/modules/sound/sound.c | 2 +- src/modules/swap/swap.c | 2 +- src/modules/terminal/terminal.c | 2 +- src/modules/terminalfont/terminalfont.c | 2 +- src/modules/terminalsize/terminalsize.c | 2 +- src/modules/terminaltheme/terminaltheme.c | 2 +- src/modules/theme/theme.c | 2 +- src/modules/title/title.c | 2 +- src/modules/tpm/tpm.c | 2 +- src/modules/uptime/uptime.c | 2 +- src/modules/users/users.c | 2 +- src/modules/version/version.c | 2 +- src/modules/vulkan/vulkan.c | 2 +- src/modules/wallpaper/wallpaper.c | 2 +- src/modules/weather/weather.c | 2 +- src/modules/wifi/wifi.c | 2 +- src/modules/wm/wm.c | 2 +- src/modules/wmtheme/wmtheme.c | 2 +- src/modules/zpool/zpool.c | 2 +- src/options/display.c | 8 ++++---- 79 files changed, 83 insertions(+), 83 deletions(-) diff --git a/doc/help.json b/doc/help.json index d1a1482029..4331d2b637 100644 --- a/doc/help.json +++ b/doc/help.json @@ -602,7 +602,7 @@ "ja": "Japanese", "ko": "Korean", "pl": "Polish", - "pt_BR": "Brazilian Portuguese", + "pt": "Portuguese", "ru": "Russian", "zh_CN": "Simplified Chinese", "zh_TW": "Traditional Chinese" diff --git a/doc/json_schema.json b/doc/json_schema.json index 5ae9bcc27a..7075bc47ec 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1107,8 +1107,8 @@ }, { "type": "string", - "const": "pt_BR", - "description": "Brazilian Portuguese" + "const": "pt", + "description": "Portuguese" }, { "type": "string", diff --git a/src/common/option.h b/src/common/option.h index 2647cd7ed3..be7c475f83 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -28,7 +28,7 @@ typedef struct FFModuleDisplayName { const char* ja; // Japanese const char* ko; // Korean const char* pl; // Polish - const char* pt_BR; // Brazilian Portuguese + const char* pt; // (Brazilian) Portuguese const char* ru; // Russian const char* zh_CN; // Simplified Chinese const char* zh_TW; // Traditional Chinese diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 99a44b676f..66334abb7c 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -308,7 +308,7 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .ja = "バッテリー", .ko = "배터리", .pl = "Bateria", - .pt_BR = "Bateria", + .pt = "Bateria", .ru = "Батарея", .zh_CN = "电池", .zh_TW = "電池", diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 94e6022289..34dfcb08a8 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -141,7 +141,7 @@ FFModuleBaseInfo ffBiosModuleInfo = { .ja = "BIOS", .ko = "BIOS", .pl = "BIOS", - .pt_BR = "BIOS", + .pt = "BIOS", .ru = "BIOS", .zh_CN = "BIOS", .zh_TW = "BIOS", diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 232728dc52..22606b77ef 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -162,7 +162,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .ja = "ブルートゥース", .ko = "블루투스", .pl = "Bluetooth", - .pt_BR = "Bluetooth", + .pt = "Bluetooth", .ru = "Блютус", .zh_CN = "蓝牙", .zh_TW = "藍牙", diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 1419eaec5e..330bf89484 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -199,7 +199,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .ja = "ブルートゥースアダプター", .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", - .pt_BR = "Adaptador Bluetooth", + .pt = "Adaptador Bluetooth", .ru = "Блютус-адаптер", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 324bfe95b3..e9f883b1a1 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -119,7 +119,7 @@ FFModuleBaseInfo ffBoardModuleInfo = { .ja = "マザーボード", .ko = "메인보드", .pl = "Płyta główna", - .pt_BR = "Placa-mãe", + .pt = "Placa-mãe", .ru = "Материнская плата", .zh_CN = "主板", .zh_TW = "主機板", diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index d45030225a..f0538f68ae 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -114,7 +114,7 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .ja = "ブートマネージャー", .ko = "부트 매니저", .pl = "Menedżer rozruchu", - .pt_BR = "Gerenciador de inicialização", + .pt = "Gerenciador de inicialização", .ru = "Менеджер загрузки", .zh_CN = "启动管理器", .zh_TW = "啟動管理器", diff --git a/src/modules/break/break.c b/src/modules/break/break.c index b66963ecda..d81400de72 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -38,7 +38,7 @@ FFModuleBaseInfo ffBreakModuleInfo = { .ja = "改行", .ko = "줄 바꿈", .pl = "Przerwa", - .pt_BR = "Quebra", + .pt = "Quebra", .ru = "Разрыв", .zh_CN = "换行", .zh_TW = "換行", diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 28fa28be0c..f70bd13498 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -201,7 +201,7 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .ja = "明るさ", .ko = "밝기", .pl = "Jasność", - .pt_BR = "Brilho", + .pt = "Brilho", .ru = "Яркость", .zh_CN = "亮度", .zh_TW = "亮度", diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 442a4406d3..9df2622659 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -209,7 +209,7 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .ja = "BTRFS", .ko = "BTRFS", .pl = "BTRFS", - .pt_BR = "BTRFS", + .pt = "BTRFS", .ru = "BTRFS", .zh_CN = "BTRFS", .zh_TW = "BTRFS", diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index f748310652..7758229c34 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -126,7 +126,7 @@ FFModuleBaseInfo ffCameraModuleInfo = { .ja = "カメラ", .ko = "카메라", .pl = "Kamera", - .pt_BR = "Câmera", + .pt = "Câmera", .ru = "Камера", .zh_CN = "摄像头", .zh_TW = "攝像頭", diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index ae25f19b6e..576d3b83d6 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -121,7 +121,7 @@ FFModuleBaseInfo ffChassisModuleInfo = { .ja = "シャーシ", .ko = "섀시", .pl = "Obudowa", - .pt_BR = "Chassi", + .pt = "Chassi", .ru = "Шасси", .zh_CN = "机箱", .zh_TW = "機箱", diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index f71dfe2834..202a82236a 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -262,7 +262,7 @@ FFModuleBaseInfo ffCodecModuleInfo = { .ja = "コーデック", .ko = "코덱", .pl = "Kodek", - .pt_BR = "Codec", + .pt = "Codec", .ru = "Кодек", .zh_CN = "编解码器", .zh_TW = "編解碼器", diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index ac1ef742fb..ace03ddd64 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -306,7 +306,7 @@ FFModuleBaseInfo ffColorsModuleInfo = { .ja = "色", .ko = "색상", .pl = "Kolory", - .pt_BR = "Cores", + .pt = "Cores", .ru = "Цвета", .zh_CN = "颜色", .zh_TW = "顏色", diff --git a/src/modules/command/command.c b/src/modules/command/command.c index d606e033fe..13131f6279 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -164,7 +164,7 @@ FFModuleBaseInfo ffCommandModuleInfo = { .ja = "コマンド", .ko = "명령어", .pl = "Polecenie", - .pt_BR = "Comando", + .pt = "Comando", .ru = "Команда", .zh_CN = "命令", .zh_TW = "命令", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 20236c9dd1..b9c4166f50 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -262,7 +262,7 @@ FFModuleBaseInfo ffCPUModuleInfo = { .ja = "CPU", .ko = "CPU", .pl = "CPU", - .pt_BR = "CPU", + .pt = "CPU", .ru = "CPU", .zh_CN = "CPU", .zh_TW = "CPU", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 1c5c3e8580..feeb337d62 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -232,7 +232,7 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .ja = "CPUキャッシュ", .ko = "CPU 캐시", .pl = "Pamięć podręczna CPU", - .pt_BR = "Cache da CPU", + .pt = "Cache da CPU", .ru = "Кэш процессора", .zh_CN = "CPU缓存", .zh_TW = "CPU快取記憶體", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 5c9a4135ab..b33c44f086 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -190,7 +190,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .ja = "CPU使用率", .ko = "CPU 사용량", .pl = "Użycie CPU", - .pt_BR = "Uso da CPU", + .pt = "Uso da CPU", .ru = "Использование ЦП", .zh_CN = "CPU使用率", .zh_TW = "CPU使用率", diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 04808456f0..3cba64db83 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -111,7 +111,7 @@ FFModuleBaseInfo ffCursorModuleInfo = { .ja = "カーソル", .ko = "커서", .pl = "Kursor", - .pt_BR = "Cursor", + .pt = "Cursor", .ru = "Курсор", .zh_CN = "光标", .zh_TW = "游標", diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index e728b634b1..9b3044d51e 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -46,7 +46,7 @@ FFModuleBaseInfo ffCustomModuleInfo = { .ja = "カスタム", .ko = "사용자 정의", .pl = "Niestandardowy", - .pt_BR = "Personalizado", + .pt = "Personalizado", .ru = "Пользовательский", .zh_CN = "自定义", .zh_TW = "自訂", diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 347b81d534..1808317994 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -161,7 +161,7 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .ja = "日付と時刻", .ko = "날짜/시간", .pl = "Data i godzina", - .pt_BR = "Data e hora", + .pt = "Data e hora", .ru = "Дата и время", .zh_CN = "日期时间", .zh_TW = "日期時間", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 628cf49b45..42b1e3c5b9 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -93,7 +93,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .ja = "デスクトップ環境", .ko = "데스크탑 환경", .pl = "Środowisko graficzne", - .pt_BR = "Ambiente de desktop", + .pt = "Ambiente de desktop", .ru = "Рабочая среда", .zh_CN = "桌面环境", .zh_TW = "桌面環境", diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 11d6962945..7e34a6d574 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -462,7 +462,7 @@ FFModuleBaseInfo ffDiskModuleInfo = { .ja = "ディスク", .ko = "디스크", .pl = "Dysk", - .pt_BR = "Disco", + .pt = "Disco", .ru = "Диск", .zh_CN = "磁盘", .zh_TW = "磁碟", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 87a18c54d4..b035133b5a 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -181,7 +181,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .ja = "ディスク I/O", .ko = "디스크 I/O", .pl = "Dysk I/O", - .pt_BR = "Disco I/O", + .pt = "Disco I/O", .ru = "Диск I/O", .zh_CN = "磁盘 I/O", .zh_TW = "磁碟 I/O", diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 2df6c787cc..c4d2e76a8e 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -422,7 +422,7 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .ja = "ディスプレイ", .ko = "디스플레이", .pl = "Wyświetlacz", - .pt_BR = "Tela", + .pt = "Tela", .ru = "Дисплей", .zh_CN = "显示器", .zh_TW = "顯示器", diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 6e63c44d8e..d7d7c0ad33 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -145,7 +145,7 @@ FFModuleBaseInfo ffDNSModuleInfo = { .ja = "DNS", .ko = "DNS", .pl = "DNS", - .pt_BR = "DNS", + .pt = "DNS", .ru = "DNS", .zh_CN = "DNS", .zh_TW = "DNS", diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index de3e5c96c3..4fdddfc97b 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -114,7 +114,7 @@ FFModuleBaseInfo ffEditorModuleInfo = { .ja = "エディター", .ko = "편집기", .pl = "Edytor", - .pt_BR = "Editor", + .pt = "Editor", .ru = "Редактор", .zh_CN = "编辑器", .zh_TW = "編輯器", diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 6df480717d..80bc7bcb7b 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -106,7 +106,7 @@ FFModuleBaseInfo ffFontModuleInfo = { .ja = "フォント", .ko = "글꼴", .pl = "Czcionka", - .pt_BR = "Fonte", + .pt = "Fonte", .ru = "Шрифт", .zh_CN = "字体", .zh_TW = "字型", diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index c0e01b6193..d3e6503ee1 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -200,7 +200,7 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .ja = "ゲームパッド", .ko = "게임패드", .pl = "Gamepad", - .pt_BR = "Gamepad", + .pt = "Gamepad", .ru = "Геймпад", .zh_CN = "游戏手柄", .zh_TW = "遊戲手把", diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index d22f3436cf..996c48338b 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -490,7 +490,7 @@ FFModuleBaseInfo ffGPUModuleInfo = { .ja = "GPU", .ko = "GPU", .pl = "GPU", - .pt_BR = "GPU", + .pt = "GPU", .ru = "GPU", .zh_CN = "显卡", .zh_TW = "顯卡", diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 1fafa659a8..e8b549f30f 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -147,7 +147,7 @@ FFModuleBaseInfo ffHostModuleInfo = { .ja = "ホスト", .ko = "호스트", .pl = "Host", - .pt_BR = "Host", + .pt = "Host", .ru = "Хост", .zh_CN = "主机", .zh_TW = "主機", diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index eaa1341bd1..d1c4e66c85 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -105,7 +105,7 @@ FFModuleBaseInfo ffIconsModuleInfo = { .ja = "アイコン", .ko = "아이콘", .pl = "Ikony", - .pt_BR = "Ícones", + .pt = "Ícones", .ru = "Иконки", .zh_CN = "图标", .zh_TW = "圖示", diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index b5adbc9062..f6315380c5 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -112,7 +112,7 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .ja = "initシステム", .ko = "초기화 시스템", .pl = "System init", - .pt_BR = "Sistema de inicialização", + .pt = "Sistema de inicialização", .ru = "Init-система", .zh_CN = "Init 系统", .zh_TW = "Init 系統", diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 055dd5fe10..3e576816c0 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -73,7 +73,7 @@ FFModuleBaseInfo ffKernelModuleInfo = { .ja = "カーネル", .ko = "커널", .pl = "Jądro", - .pt_BR = "Kernel", + .pt = "Kernel", .ru = "Ядро", .zh_CN = "内核", .zh_TW = "核心", diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 755ac67641..9af46f0d9b 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -160,7 +160,7 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .ja = "キーボード", .ko = "키보드", .pl = "Klawiatura", - .pt_BR = "Teclado", + .pt = "Teclado", .ru = "Клавиатура", .zh_CN = "键盘", .zh_TW = "鍵盤", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 8c919056bd..c8b54c4eb5 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -117,7 +117,7 @@ FFModuleBaseInfo ffLMModuleInfo = { .ja = "ログインマネージャー", .ko = "로그인 관리자", .pl = "Menedżer logowania", - .pt_BR = "Gerenciador de login", + .pt = "Gerenciador de login", .ru = "Менеджер входа", .zh_CN = "登录管理器", .zh_TW = "登入管理器", diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 4bd0065e1e..85d504964c 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -159,7 +159,7 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .ja = "ロードアベレージ", .ko = "시스템 부하 평균", .pl = "Średnie obciążenie", - .pt_BR = "Média de carga", + .pt = "Média de carga", .ru = "Средняя нагрузка", .zh_CN = "系统负载", .zh_TW = "系統負載", diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 8d3f314741..f194edf0c8 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -78,7 +78,7 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .ja = "ロケール", .ko = "로케일", .pl = "Ustawienia regionalne", - .pt_BR = "Configuração regional", + .pt = "Configuração regional", .ru = "Локаль", .zh_CN = "语言环境", .zh_TW = "語言環境", diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 46319e97c4..e7e0986266 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -432,7 +432,7 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .ja = "ローカル IP", .ko = "로컬 IP", .pl = "Lokalny adres IP", - .pt_BR = "IP local", + .pt = "IP local", .ru = "Локальный IP", .zh_CN = "本地 IP", .zh_TW = "區域 IP", diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 0b68a64f69..7e3aed3142 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -88,7 +88,7 @@ FFModuleBaseInfo ffLogoModuleInfo = { .ja = "ロゴ", .ko = "로고", .pl = "Logo", - .pt_BR = "Logo", + .pt = "Logo", .ru = "Логотип", .zh_CN = "徽标", .zh_TW = "標誌", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 08f550a5fe..6211b7c955 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -264,7 +264,7 @@ FFModuleBaseInfo ffMediaModuleInfo = { .ja = "メディア", .ko = "미디어", .pl = "Media", - .pt_BR = "Mídia", + .pt = "Mídia", .ru = "Медиа", .zh_CN = "媒体", .zh_TW = "媒體", diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 065808c299..d5a63f6b09 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -129,7 +129,7 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .ja = "メモリ", .ko = "메모리", .pl = "Pamięć", - .pt_BR = "Memória", + .pt = "Memória", .ru = "Память", .zh_CN = "内存", .zh_TW = "記憶體", diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index c5c9877c1f..aa55c022a7 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -115,7 +115,7 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .ja = "モニター", .ko = "모니터", .pl = "Monitor", - .pt_BR = "Monitor", + .pt = "Monitor", .ru = "Монитор", .zh_CN = "显示器", .zh_TW = "顯示器", diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index dd8f8be6e5..f542c8375a 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -163,7 +163,7 @@ FFModuleBaseInfo ffMouseModuleInfo = { .ja = "マウス", .ko = "마우스", .pl = "Mysz", - .pt_BR = "Mouse", + .pt = "Mouse", .ru = "Мышь", .zh_CN = "鼠标", .zh_TW = "滑鼠", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 6023687909..e750ea92d3 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -208,7 +208,7 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .ja = "ネットワークI/O", .ko = "네트워크 I/O", .pl = "I/O sieciowe", - .pt_BR = "E/S de rede", + .pt = "E/S de rede", .ru = "Сетевой I/O", .zh_CN = "网络 I/O", .zh_TW = "網路 I/O", diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 18e9b85d6b..fbc36c39a9 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -131,7 +131,7 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .ja = "OpenCL", .ko = "OpenCL", .pl = "OpenCL", - .pt_BR = "OpenCL", + .pt = "OpenCL", .ru = "OpenCL", .zh_CN = "OpenCL", .zh_TW = "OpenCL", diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index ad8e431e5b..bac96afc70 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -138,7 +138,7 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .ja = "OpenGL", .ko = "OpenGL", .pl = "OpenGL", - .pt_BR = "OpenGL", + .pt = "OpenGL", .ru = "OpenGL", .zh_CN = "OpenGL", .zh_TW = "OpenGL", diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 1d6a18cd02..71661bf0a5 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -183,7 +183,7 @@ FFModuleBaseInfo ffOSModuleInfo = { .ja = "オペレーティングシステム", .ko = "운영 체제", .pl = "System operacyjny", - .pt_BR = "Sistema operacional", + .pt = "Sistema operacional", .ru = "Операционная система", .zh_CN = "操作系统", .zh_TW = "操作系統", diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 710894c3c8..c21ef4ca6f 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -521,7 +521,7 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .ja = "パッケージ", .ko = "패키지", .pl = "Pakiety", - .pt_BR = "Pacotes", + .pt = "Pacotes", .ru = "Пакеты", .zh_CN = "软件包", .zh_TW = "軟體包", diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index d9e2f36494..b85ec44100 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -274,7 +274,7 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .ja = "物理ディスク", .ko = "물리 디스크", .pl = "Dysk fizyczny", - .pt_BR = "Disco físico", + .pt = "Disco físico", .ru = "Физический диск", .zh_CN = "物理磁盘", .zh_TW = "物理磁碟", diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index dbb263ad48..0ab65cdb57 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -168,7 +168,7 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .ja = "物理メモリ", .ko = "물리 메모리", .pl = "Pamięć fizyczna", - .pt_BR = "Memória física", + .pt = "Memória física", .ru = "Физическая память", .zh_CN = "物理内存", .zh_TW = "實體記憶體", diff --git a/src/modules/player/player.c b/src/modules/player/player.c index ca19fbefea..0693423e01 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -118,7 +118,7 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .ja = "メディアプレイヤー", .ko = "미디어 플레이어", .pl = "Odtwarzacz multimediów", - .pt_BR = "Reprodutor de mídia", + .pt = "Reprodutor de mídia", .ru = "Медиаплеер", .zh_CN = "媒体播放器", .zh_TW = "媒體播放器", diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 39866ed19c..71899d26ee 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -119,7 +119,7 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .ja = "電源アダプター", .ko = "전원 어댑터", .pl = "Zasilacz", - .pt_BR = "Fonte de alimentação", + .pt = "Fonte de alimentação", .ru = "Блок питания", .zh_CN = "电源适配器", .zh_TW = "電源轉接器", diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index ef6f4bee30..bb42ca59e3 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -74,7 +74,7 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .ja = "プロセス", .ko = "프로세스", .pl = "Procesy", - .pt_BR = "Processos", + .pt = "Processos", .ru = "Процессы", .zh_CN = "进程数", .zh_TW = "進程數", diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 6cb741ca14..92c790544b 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -119,7 +119,7 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .ja = "パブリックIP", .ko = "공용 IP", .pl = "Publiczne IP", - .pt_BR = "IP público", + .pt = "IP público", .ru = "Публичный IP", .zh_CN = "公网 IP", .zh_TW = "公網 IP", diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 4ef3a3af24..f70c7a7bd5 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -132,7 +132,7 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .ja = "セパレーター", .ko = "구분선", .pl = "Separator", - .pt_BR = "Separador", + .pt = "Separador", .ru = "Разделитель", .zh_CN = "分隔线", .zh_TW = "分隔線", diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index dd161759ca..55e0da630f 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -100,7 +100,7 @@ FFModuleBaseInfo ffShellModuleInfo = { .ja = "シェル", .ko = "셸", .pl = "Powłoka", - .pt_BR = "Shell", + .pt = "Shell", .ru = "Оболочка", .zh_CN = "Shell", .zh_TW = "Shell", diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index c29cb574e9..7f3a691e53 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -210,7 +210,7 @@ FFModuleBaseInfo ffSoundModuleInfo = { .ja = "サウンド", .ko = "사운드", .pl = "Dźwięk", - .pt_BR = "Som", + .pt = "Som", .ru = "Звук", .zh_CN = "声音", .zh_TW = "聲音", diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index a0ef873687..ea0ac62dee 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -193,7 +193,7 @@ FFModuleBaseInfo ffSwapModuleInfo = { .ja = "スワップ", .ko = "스왑", .pl = "Swap", - .pt_BR = "Swap", + .pt = "Swap", .ru = "Своп", .zh_CN = "交换空间", .zh_TW = "交換空間", diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 1b06dc4850..3752b45e0d 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -94,7 +94,7 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .ja = "ターミナル", .ko = "터미널", .pl = "Terminal", - .pt_BR = "Terminal", + .pt = "Terminal", .ru = "Терминал", .zh_CN = "终端", .zh_TW = "終端機", diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index cea077d476..fdb7990be4 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -114,7 +114,7 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .ja = "ターミナルフォント", .ko = "터미널 글꼴", .pl = "Czcionka terminala", - .pt_BR = "Fonte do terminal", + .pt = "Fonte do terminal", .ru = "Шрифт терминала", .zh_CN = "终端字体", .zh_TW = "終端機字型", diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 6fd7bf5d80..70f6139d14 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -85,7 +85,7 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .ja = "ターミナルサイズ", .ko = "터미널 크기", .pl = "Rozmiar terminala", - .pt_BR = "Tamanho do terminal", + .pt = "Tamanho do terminal", .ru = "Размер терминала", .zh_CN = "终端大小", .zh_TW = "終端機大小", diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index c8925e78d2..4e40876f31 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -102,7 +102,7 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .ja = "ターミナルテーマ", .ko = "터미널 테마", .pl = "Motyw terminala", - .pt_BR = "Tema do terminal", + .pt = "Tema do terminal", .ru = "Тема терминала", .zh_CN = "终端主题", .zh_TW = "終端機主題", diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 44ab11cc19..948e0d4696 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -98,7 +98,7 @@ FFModuleBaseInfo ffThemeModuleInfo = { .ja = "テーマ", .ko = "테마", .pl = "Motyw", - .pt_BR = "Tema", + .pt = "Tema", .ru = "Тема", .zh_CN = "主题", .zh_TW = "主題", diff --git a/src/modules/title/title.c b/src/modules/title/title.c index cce1c6bb1f..939f4daf9d 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -187,7 +187,7 @@ FFModuleBaseInfo ffTitleModuleInfo = { .ja = "タイトル", .ko = "제목", .pl = "Tytuł", - .pt_BR = "Título", + .pt = "Título", .ru = "Заголовок", .zh_CN = "标题", .zh_TW = "標題", diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 1b85104e7b..c216b05b50 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -94,7 +94,7 @@ FFModuleBaseInfo ffTPMModuleInfo = { .ja = "TPM", .ko = "TPM", .pl = "TPM", - .pt_BR = "TPM", + .pt = "TPM", .ru = "TPM", .zh_CN = "TPM", .zh_TW = "TPM", diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 0bed6ea134..9cc364c41f 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -94,7 +94,7 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .ja = "稼働時間", .ko = "업타임", .pl = "Czas pracy", - .pt_BR = "Tempo de atividade", + .pt = "Tempo de atividade", .ru = "Время работы", .zh_CN = "运行时间", .zh_TW = "運行時間", diff --git a/src/modules/users/users.c b/src/modules/users/users.c index c59373beef..d2e1270767 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -191,7 +191,7 @@ FFModuleBaseInfo ffUsersModuleInfo = { .ja = "ユーザー", .ko = "사용자", .pl = "Użytkownicy", - .pt_BR = "Usuários", + .pt = "Usuários", .ru = "Пользователи", .zh_CN = "用户", .zh_TW = "使用者", diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 56c142d76e..d023abe889 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -105,7 +105,7 @@ FFModuleBaseInfo ffVersionModuleInfo = { .ja = "バージョン", .ko = "버전", .pl = "Wersja", - .pt_BR = "Versão", + .pt = "Versão", .ru = "Версия", .zh_CN = "版本", .zh_TW = "版本", diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index a16cac6014..2d6dbfd222 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -143,7 +143,7 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .ja = "Vulkan", .ko = "Vulkan", .pl = "Vulkan", - .pt_BR = "Vulkan", + .pt = "Vulkan", .ru = "Vulkan", .zh_CN = "Vulkan", .zh_TW = "Vulkan", diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index e0f203a581..e57082fc5c 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -86,7 +86,7 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .ja = "壁紙", .ko = "배경화면", .pl = "Tapeta", - .pt_BR = "Papel de parede", + .pt = "Papel de parede", .ru = "Обои", .zh_CN = "壁纸", .zh_TW = "桌布", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 7a2192a791..9f7dae54d9 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -103,7 +103,7 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .ja = "天気", .ko = "날씨", .pl = "Pogoda", - .pt_BR = "Clima", + .pt = "Clima", .ru = "Погода", .zh_CN = "天气", .zh_TW = "天氣", diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index d5baa00ffe..39e99a38ec 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -224,7 +224,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { .ja = "Wi-Fi", .ko = "와이파이", .pl = "Wi-Fi", - .pt_BR = "Wi-Fi", + .pt = "Wi-Fi", .ru = "Wi-Fi", .zh_CN = "无线网络", .zh_TW = "無線網路", diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 35e58c4f1f..4c40bc2061 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -131,7 +131,7 @@ FFModuleBaseInfo ffWMModuleInfo = { .ja = "ウィンドウマネージャー", .ko = "윈도우 관리자", .pl = "Menedżer okien", - .pt_BR = "Gerenciador de janelas", + .pt = "Gerenciador de janelas", .ru = "Менеджер окон", .zh_CN = "窗口管理器", .zh_TW = "視窗管理員", diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 8c7e3afe31..b7ed26b429 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -70,7 +70,7 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .ja = "ウィンドウマネージャのテーマ", .ko = "윈도우 관리자 테마", .pl = "Motyw menedżera okien", - .pt_BR = "Tema do gerenciador de janelas", + .pt = "Tema do gerenciador de janelas", .ru = "Тема менеджера окон", .zh_CN = "窗口管理器主题", .zh_TW = "視窗管理員主題", diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 0e447d5e45..f6ea00c402 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -203,7 +203,7 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .ja = "Zpool", .ko = "Zpool", .pl = "Zpool", - .pt_BR = "Zpool", + .pt = "Zpool", .ru = "Zpool", .zh_CN = "Zpool", .zh_TW = "Zpool", diff --git a/src/options/display.c b/src/options/display.c index 9ce0a96773..78ea684ce3 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -70,8 +70,8 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { case 'ko': return offsetof(FFModuleDisplayName, ko); case 'pl': return offsetof(FFModuleDisplayName, pl); case 'pt': { - if (ffStrbufEqualS(language, "pt_br")) { - return offsetof(FFModuleDisplayName, pt_BR); + if (ffStrbufEqualS(language, "pt")) { + return offsetof(FFModuleDisplayName, pt); } goto error; } @@ -1290,8 +1290,8 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, pl): yyjson_mut_obj_add_str(doc, key, "language", "pl"); break; - case offsetof(FFModuleDisplayName, pt_BR): - yyjson_mut_obj_add_str(doc, key, "language", "pt_BR"); + case offsetof(FFModuleDisplayName, pt): + yyjson_mut_obj_add_str(doc, key, "language", "pt"); break; case offsetof(FFModuleDisplayName, ru): yyjson_mut_obj_add_str(doc, key, "language", "ru"); From b700d9ded52a514e0a65f09129c19f74b979046a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:39:10 +0800 Subject: [PATCH 014/109] =?UTF-8?q?L10n=20(Ru):=20changes=20`=D0=91=D0=BB?= =?UTF-8?q?=D1=8E=D1=82=D1=83=D1=81`=20to=20`=D0=91=D0=BB=D1=8E=D1=82?= =?UTF-8?q?=D1=83=D0=B7`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref: https://github.com/fastfetch-cli/fastfetch/issues/2503#issuecomment-5304614812 --- src/modules/bluetooth/bluetooth.c | 2 +- src/modules/bluetoothradio/bluetoothradio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 22606b77ef..125c68fb28 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -163,7 +163,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .ko = "블루투스", .pl = "Bluetooth", .pt = "Bluetooth", - .ru = "Блютус", + .ru = "Блютуз", .zh_CN = "蓝牙", .zh_TW = "藍牙", }, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 330bf89484..cbb041f583 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -200,7 +200,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", .pt = "Adaptador Bluetooth", - .ru = "Блютус-адаптер", + .ru = "Блютуз-адаптер", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", }, From 2de674ec9a7160c5427e90ad2a80df9c45581997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 10:51:42 +0800 Subject: [PATCH 015/109] L10n (Ar / He): adds support Fixes #2520 --- doc/help.json | 2 ++ doc/json_schema.json | 10 ++++++++++ src/common/option.h | 2 ++ src/modules/battery/battery.c | 2 ++ src/modules/bios/bios.c | 2 ++ src/modules/bluetooth/bluetooth.c | 2 ++ src/modules/bluetoothradio/bluetoothradio.c | 2 ++ src/modules/board/board.c | 2 ++ src/modules/bootmgr/bootmgr.c | 2 ++ src/modules/break/break.c | 2 ++ src/modules/brightness/brightness.c | 2 ++ src/modules/btrfs/btrfs.c | 2 ++ src/modules/camera/camera.c | 2 ++ src/modules/chassis/chassis.c | 2 ++ src/modules/codec/codec.c | 2 ++ src/modules/colors/colors.c | 2 ++ src/modules/command/command.c | 2 ++ src/modules/cpu/cpu.c | 2 ++ src/modules/cpucache/cpucache.c | 2 ++ src/modules/cpuusage/cpuusage.c | 2 ++ src/modules/cursor/cursor.c | 2 ++ src/modules/custom/custom.c | 2 ++ src/modules/datetime/datetime.c | 2 ++ src/modules/de/de.c | 2 ++ src/modules/disk/disk.c | 2 ++ src/modules/diskio/diskio.c | 2 ++ src/modules/display/display.c | 2 ++ src/modules/dns/dns.c | 2 ++ src/modules/editor/editor.c | 2 ++ src/modules/font/font.c | 2 ++ src/modules/gamepad/gamepad.c | 2 ++ src/modules/gpu/gpu.c | 2 ++ src/modules/host/host.c | 2 ++ src/modules/icons/icons.c | 2 ++ src/modules/initsystem/initsystem.c | 2 ++ src/modules/kernel/kernel.c | 2 ++ src/modules/keyboard/keyboard.c | 2 ++ src/modules/lm/lm.c | 2 ++ src/modules/loadavg/loadavg.c | 2 ++ src/modules/locale/locale.c | 2 ++ src/modules/localip/localip.c | 2 ++ src/modules/logo/logo.c | 2 ++ src/modules/media/media.c | 2 ++ src/modules/memory/memory.c | 2 ++ src/modules/monitor/monitor.c | 2 ++ src/modules/mouse/mouse.c | 2 ++ src/modules/netio/netio.c | 2 ++ src/modules/opencl/opencl.c | 2 ++ src/modules/opengl/opengl.c | 2 ++ src/modules/os/os.c | 2 ++ src/modules/packages/packages.c | 2 ++ src/modules/physicaldisk/physicaldisk.c | 2 ++ src/modules/physicalmemory/physicalmemory.c | 2 ++ src/modules/player/player.c | 2 ++ src/modules/poweradapter/poweradapter.c | 2 ++ src/modules/processes/processes.c | 2 ++ src/modules/publicip/publicip.c | 2 ++ src/modules/separator/separator.c | 2 ++ src/modules/shell/shell.c | 2 ++ src/modules/sound/sound.c | 2 ++ src/modules/swap/swap.c | 2 ++ src/modules/terminal/terminal.c | 2 ++ src/modules/terminalfont/terminalfont.c | 2 ++ src/modules/terminalsize/terminalsize.c | 2 ++ src/modules/terminaltheme/terminaltheme.c | 2 ++ src/modules/theme/theme.c | 2 ++ src/modules/title/title.c | 2 ++ src/modules/tpm/tpm.c | 2 ++ src/modules/uptime/uptime.c | 2 ++ src/modules/users/users.c | 2 ++ src/modules/version/version.c | 2 ++ src/modules/vulkan/vulkan.c | 2 ++ src/modules/wallpaper/wallpaper.c | 2 ++ src/modules/weather/weather.c | 2 ++ src/modules/wifi/wifi.c | 2 ++ src/modules/wm/wm.c | 2 ++ src/modules/wmtheme/wmtheme.c | 2 ++ src/modules/zpool/zpool.c | 2 ++ src/options/display.c | 8 ++++++++ 79 files changed, 172 insertions(+) diff --git a/doc/help.json b/doc/help.json index 4331d2b637..b1cfbfa560 100644 --- a/doc/help.json +++ b/doc/help.json @@ -595,9 +595,11 @@ "optional": true, "enum": { "en": "English", + "ar": "Arabic", "de": "German", "es": "Spanish", "fr": "French", + "he": "Hebrew", "it": "Italian", "ja": "Japanese", "ko": "Korean", diff --git a/doc/json_schema.json b/doc/json_schema.json index 7075bc47ec..3dbc06e988 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1070,6 +1070,11 @@ "const": "en", "description": "English" }, + { + "type": "string", + "const": "ar", + "description": "Arabic" + }, { "type": "string", "const": "de", @@ -1085,6 +1090,11 @@ "const": "fr", "description": "French" }, + { + "type": "string", + "const": "he", + "description": "Hebrew" + }, { "type": "string", "const": "it", diff --git a/src/common/option.h b/src/common/option.h index be7c475f83..e8f2dca1d2 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -21,9 +21,11 @@ typedef struct FFModuleFormatArgList { typedef struct FFModuleDisplayName { const char* en; // English + const char* ar; // Arabic const char* de; // German const char* es; // Spanish const char* fr; // French + const char* he; // Hebrew const char* it; // Italian const char* ja; // Japanese const char* ko; // Korean diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 66334abb7c..9fd8c4572e 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -301,9 +301,11 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .description = "Print battery information", .displayName = { .en = "Battery", + .ar = "البطارية", .de = "Akku", .es = "Batería", .fr = "Batterie", + .he = "סוללה", .it = "Batteria", .ja = "バッテリー", .ko = "배터리", diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 34dfcb08a8..6b129213ce 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -134,9 +134,11 @@ FFModuleBaseInfo ffBiosModuleInfo = { .description = "Print first-stage bootloader information (name, version, release date, etc.)", .displayName = { .en = "BIOS", + .ar = "BIOS", .de = "BIOS", .es = "BIOS", .fr = "BIOS", + .he = "BIOS", .it = "BIOS", .ja = "BIOS", .ko = "BIOS", diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 125c68fb28..ab98f1f46d 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -155,9 +155,11 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .description = "List connected Bluetooth devices", .displayName = { .en = "Bluetooth", + .ar = "بلوتوث", .de = "Bluetooth", .es = "Bluetooth", .fr = "Bluetooth", + .he = "בלוטות'", .it = "Bluetooth", .ja = "ブルートゥース", .ko = "블루투스", diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index cbb041f583..f8b22a9f4a 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -192,9 +192,11 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .description = "List Bluetooth radios (supported versions, vendors, etc.)", .displayName = { .en = "Bluetooth Radio", + .ar = "راديو بلوتوث", .de = "Bluetooth-Adapter", .es = "Adaptador Bluetooth", .fr = "Adaptateur Bluetooth", + .he = "רדיו בלוטות'", .it = "Adattatore Bluetooth", .ja = "ブルートゥースアダプター", .ko = "블루투스 어댑터", diff --git a/src/modules/board/board.c b/src/modules/board/board.c index e9f883b1a1..b82d90bc5a 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -112,9 +112,11 @@ FFModuleBaseInfo ffBoardModuleInfo = { .description = "Print motherboard name and other information", .displayName = { .en = "Board", + .ar = "اللوحة الأم", .de = "Mainboard", .es = "Placa base", .fr = "Carte mère", + .he = "לוח אם", .it = "Scheda madre", .ja = "マザーボード", .ko = "메인보드", diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index f0538f68ae..db7a9c473e 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -107,9 +107,11 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .description = "Print second-stage bootloader information (name, firmware, etc.)", .displayName = { .en = "Boot Manager", + .ar = "مدير الإقلاع", .de = "Boot-Manager", .es = "Administrador de arranque", .fr = "Gestionnaire de démarrage", + .he = "מנהל אתחול", .it = "Gestore di avvio", .ja = "ブートマネージャー", .ko = "부트 매니저", diff --git a/src/modules/break/break.c b/src/modules/break/break.c index d81400de72..f0ef529bcb 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -31,9 +31,11 @@ FFModuleBaseInfo ffBreakModuleInfo = { .description = "Print an empty line", .displayName = { .en = "Break", + .ar = "فاصل", .de = "Umbruch", .es = "Salto de línea", .fr = "Saut de ligne", + .he = "מעבר שורה", .it = "Interruzione", .ja = "改行", .ko = "줄 바꿈", diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index f70bd13498..16ff8e8b02 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -194,9 +194,11 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .description = "Print the current brightness level of your monitors", .displayName = { .en = "Brightness", + .ar = "السطوع", .de = "Helligkeit", .es = "Brillo", .fr = "Luminosité", + .he = "בהירות", .it = "Luminosità", .ja = "明るさ", .ko = "밝기", diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index 9df2622659..bbba974e8b 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -202,9 +202,11 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .description = "Print Linux BTRFS volumes", .displayName = { .en = "BTRFS", + .ar = "BTRFS", .de = "BTRFS", .es = "BTRFS", .fr = "BTRFS", + .he = "BTRFS", .it = "BTRFS", .ja = "BTRFS", .ko = "BTRFS", diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 7758229c34..82cf79c033 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -119,9 +119,11 @@ FFModuleBaseInfo ffCameraModuleInfo = { .description = "Print available cameras", .displayName = { .en = "Camera", + .ar = "الكاميرا", .de = "Kamera", .es = "Cámara", .fr = "Caméra", + .he = "מצלמה", .it = "Fotocamera", .ja = "カメラ", .ko = "카메라", diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 576d3b83d6..904f4d1132 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -114,9 +114,11 @@ FFModuleBaseInfo ffChassisModuleInfo = { .description = "Print chassis type information (desktop, laptop, etc.)", .displayName = { .en = "Chassis", + .ar = "الهيكل", .de = "Gehäuse", .es = "Chasis", .fr = "Châssis", + .he = "מארז", .it = "Telaio", .ja = "シャーシ", .ko = "섀시", diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index 202a82236a..6f7a3a1bbb 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -255,9 +255,11 @@ FFModuleBaseInfo ffCodecModuleInfo = { .description = "Print hardware video acceleration codec types (decode / encode)", .displayName = { .en = "Codec", + .ar = "الترميز", .de = "Codec", .es = "Códec", .fr = "Codec", + .he = "קודק", .it = "Codec", .ja = "コーデック", .ko = "코덱", diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index ace03ddd64..38ce77ce66 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -299,9 +299,11 @@ FFModuleBaseInfo ffColorsModuleInfo = { .description = "Display the terminal's 16-color palette", .displayName = { .en = "Colors", + .ar = "الألوان", .de = "Farben", .es = "Colores", .fr = "Couleurs", + .he = "צבעים", .it = "Colori", .ja = "色", .ko = "색상", diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 13131f6279..a8e1b3f648 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -157,9 +157,11 @@ FFModuleBaseInfo ffCommandModuleInfo = { .description = "Run custom shell scripts", .displayName = { .en = "Command", + .ar = "الأمر", .de = "Befehl", .es = "Comando", .fr = "Commande", + .he = "פקודה", .it = "Comando", .ja = "コマンド", .ko = "명령어", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index b9c4166f50..5754fd08d0 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -255,9 +255,11 @@ FFModuleBaseInfo ffCPUModuleInfo = { .description = "Print CPU name, frequency, etc.", .displayName = { .en = "CPU", + .ar = "المعالج", .de = "CPU", .es = "CPU", .fr = "CPU", + .he = "מעבד", .it = "CPU", .ja = "CPU", .ko = "CPU", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index feeb337d62..bf78de62d3 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -225,9 +225,11 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .description = "Print CPU cache sizes", .displayName = { .en = "CPU Cache", + .ar = "ذاكرة المعالج المؤقتة", .de = "CPU-Cache", .es = "Caché de CPU", .fr = "Cache CPU", + .he = "מטמון מעבד", .it = "Cache CPU", .ja = "CPUキャッシュ", .ko = "CPU 캐시", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index b33c44f086..b649edba98 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -183,9 +183,11 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .description = "Print CPU usage. Collecting data takes some time", .displayName = { .en = "CPU Usage", + .ar = "استخدام المعالج", .de = "CPU-Auslastung", .es = "Uso del CPU", .fr = "Utilisation du CPU", + .he = "שימוש במעבד", .it = "Utilizzo della CPU", .ja = "CPU使用率", .ko = "CPU 사용량", diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 3cba64db83..f2c133bb6f 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -104,9 +104,11 @@ FFModuleBaseInfo ffCursorModuleInfo = { .description = "Print cursor style name", .displayName = { .en = "Cursor", + .ar = "المؤشر", .de = "Mauszeiger", .es = "Cursor", .fr = "Curseur", + .he = "סמן", .it = "Cursore", .ja = "カーソル", .ko = "커서", diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 9b3044d51e..c29bea05cd 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -39,9 +39,11 @@ FFModuleBaseInfo ffCustomModuleInfo = { .description = "Print a custom string, with or without key", .displayName = { .en = "Custom", + .ar = "مخصص", .de = "Benutzerdefiniert", .es = "Personalizado", .fr = "Personnalisé", + .he = "מותאם אישית", .it = "Personalizzato", .ja = "カスタム", .ko = "사용자 정의", diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 1808317994..1fb7ab9c55 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -154,9 +154,11 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .description = "Print the current date and time", .displayName = { .en = "Date & Time", + .ar = "التاريخ والوقت", .de = "Datum & Uhrzeit", .es = "Fecha y hora", .fr = "Date et heure", + .he = "תאריך ושעה", .it = "Data e ora", .ja = "日付と時刻", .ko = "날짜/시간", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 42b1e3c5b9..9e4dcc3dfc 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -86,9 +86,11 @@ FFModuleBaseInfo ffDEModuleInfo = { .description = "Print desktop environment name", .displayName = { .en = "Desktop Environment", + .ar = "بيئة سطح المكتب", .de = "Desktop-Umgebung", .es = "Entorno de Escritorio", .fr = "Environnement de Bureau", + .he = "סביבת שולחן עבודה", .it = "Ambiente Desktop", .ja = "デスクトップ環境", .ko = "데스크탑 환경", diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 7e34a6d574..dd823bc2b3 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -455,9 +455,11 @@ FFModuleBaseInfo ffDiskModuleInfo = { .description = "Print partitions, space usage, file system, etc", .displayName = { .en = "Disk", + .ar = "القرص", .de = "Festplatte", .es = "Disco", .fr = "Disque", + .he = "דיסק", .it = "Disco", .ja = "ディスク", .ko = "디스크", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index b035133b5a..51fc95fec6 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -174,9 +174,11 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .description = "Print physical disk I/O throughput", .displayName = { .en = "Disk I/O", + .ar = "إدخال/إخراج القرص", .de = "Festplatten I/O", .es = "E/S de disco", .fr = "Entrée/Sortie disque", + .he = "קלט/פלט דיסק", .it = "I/O del disco", .ja = "ディスク I/O", .ko = "디스크 I/O", diff --git a/src/modules/display/display.c b/src/modules/display/display.c index c4d2e76a8e..b7f0eefe5c 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -415,9 +415,11 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .description = "Print resolutions, refresh rates, etc", .displayName = { .en = "Display", + .ar = "الشاشة", .de = "Anzeige", .es = "Pantalla", .fr = "Écran", + .he = "תצוגה", .it = "Display", .ja = "ディスプレイ", .ko = "디스플레이", diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index d7d7c0ad33..7067de9ca2 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -138,9 +138,11 @@ FFModuleBaseInfo ffDNSModuleInfo = { .description = "Print configured DNS servers", .displayName = { .en = "DNS", + .ar = "DNS", .de = "DNS", .es = "DNS", .fr = "DNS", + .he = "DNS", .it = "DNS", .ja = "DNS", .ko = "DNS", diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 4fdddfc97b..09cc37238a 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -107,9 +107,11 @@ FFModuleBaseInfo ffEditorModuleInfo = { .description = "Print information about the default editor ($VISUAL or $EDITOR)", .displayName = { .en = "Editor", + .ar = "المحرر", .de = "Editor", .es = "Editor", .fr = "Éditeur", + .he = "עורך", .it = "Editor", .ja = "エディター", .ko = "편집기", diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 80bc7bcb7b..22a4645634 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -99,9 +99,11 @@ FFModuleBaseInfo ffFontModuleInfo = { .description = "Print system font names", .displayName = { .en = "Font", + .ar = "الخط", .de = "Schriftart", .es = "Fuente", .fr = "Police", + .he = "גופן", .it = "Carattere", .ja = "フォント", .ko = "글꼴", diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index d3e6503ee1..7273156de8 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -193,9 +193,11 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .description = "List connected gamepads", .displayName = { .en = "Gamepad", + .ar = "يد التحكم", .de = "Gamepad", .es = "Gamepad", .fr = "Manette", + .he = "משטח משחק", .it = "Gamepad", .ja = "ゲームパッド", .ko = "게임패드", diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 996c48338b..d0caa2fcfd 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -483,9 +483,11 @@ FFModuleBaseInfo ffGPUModuleInfo = { .description = "Print GPU names, memory sizes, types, etc", .displayName = { .en = "GPU", + .ar = "معالج الرسوميات", .de = "GPU", .es = "GPU", .fr = "GPU", + .he = "מעבד גרפי", .it = "GPU", .ja = "GPU", .ko = "GPU", diff --git a/src/modules/host/host.c b/src/modules/host/host.c index e8b549f30f..ffe5c52255 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -140,9 +140,11 @@ FFModuleBaseInfo ffHostModuleInfo = { .description = "Print your computer's product name", .displayName = { .en = "Host", + .ar = "المضيف", .de = "Rechner", .es = "Host", .fr = "Hôte", + .he = "מארח", .it = "Host", .ja = "ホスト", .ko = "호스트", diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index d1c4e66c85..5da212d33e 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -98,9 +98,11 @@ FFModuleBaseInfo ffIconsModuleInfo = { .description = "Print icon style name", .displayName = { .en = "Icons", + .ar = "الأيقونات", .de = "Symbole", .es = "Iconos", .fr = "Icônes", + .he = "סמלים", .it = "Icone", .ja = "アイコン", .ko = "아이콘", diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index f6315380c5..395d10261b 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -105,9 +105,11 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .description = "Print init system (pid 1) name and version", .displayName = { .en = "Init System", + .ar = "نظام الإقلاع", .de = "Init-System", .es = "Sistema de inicio", .fr = "Système d'init", + .he = "מערכת אתחול", .it = "Sistema di init", .ja = "initシステム", .ko = "초기화 시스템", diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 3e576816c0..f0deb47278 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -66,9 +66,11 @@ FFModuleBaseInfo ffKernelModuleInfo = { .description = "Print system kernel version", .displayName = { .en = "Kernel", + .ar = "النواة", .de = "Kernel", .es = "Kernel", .fr = "Kernel", + .he = "ליבה", .it = "Kernel", .ja = "カーネル", .ko = "커널", diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 9af46f0d9b..998e04262a 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -153,9 +153,11 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .description = "List connected keyboards", .displayName = { .en = "Keyboard", + .ar = "لوحة المفاتيح", .de = "Tastatur", .es = "Teclado", .fr = "Clavier", + .he = "מקלדת", .it = "Tastiera", .ja = "キーボード", .ko = "키보드", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index c8b54c4eb5..0b7d68649b 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -110,9 +110,11 @@ FFModuleBaseInfo ffLMModuleInfo = { .description = "Print login manager (desktop manager) name and version", .displayName = { .en = "Login Manager", + .ar = "مدير تسجيل الدخول", .de = "Anmeldemanager", .es = "Administrador de inicio de sesión", .fr = "Gestionnaire de connexion", + .he = "מנהל התחברות", .it = "Gestore di accesso", .ja = "ログインマネージャー", .ko = "로그인 관리자", diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 85d504964c..cfa36f857e 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -152,9 +152,11 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .description = "Print system load averages", .displayName = { .en = "Load Average", + .ar = "متوسط الحمل", .de = "Systemlast", .es = "Promedio de carga", .fr = "Charge moyenne", + .he = "עומס ממוצע", .it = "Carico medio", .ja = "ロードアベレージ", .ko = "시스템 부하 평균", diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index f194edf0c8..ca523c90ca 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -71,9 +71,11 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .description = "Print system locale name", .displayName = { .en = "Locale", + .ar = "اللغة", .de = "Sprachraum", .es = "Configuración regional", .fr = "Paramètres régionaux", + .he = "לוקאל", .it = "Impostazioni locali", .ja = "ロケール", .ko = "로케일", diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index e7e0986266..accff5f47a 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -425,9 +425,11 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .description = "List local IP addresses (IPv4 or IPv6), MAC addresses, etc", .displayName = { .en = "Local IP", + .ar = "عنوان IP المحلي", .de = "Lokale IP", .es = "IP local", .fr = "IP locale", + .he = "IP מקומי", .it = "IP locale", .ja = "ローカル IP", .ko = "로컬 IP", diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 7e3aed3142..860960b6ec 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -81,9 +81,11 @@ FFModuleBaseInfo ffLogoModuleInfo = { .description = "Query built-in logo for JSON output", .displayName = { .en = "Logo", + .ar = "الشعار", .de = "Logo", .es = "Logo", .fr = "Logo", + .he = "לוגו", .it = "Logo", .ja = "ロゴ", .ko = "로고", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 6211b7c955..5e7188905e 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -257,9 +257,11 @@ FFModuleBaseInfo ffMediaModuleInfo = { .description = "Print the name of the currently playing song", .displayName = { .en = "Media", + .ar = "الوسائط", .de = "Medien", .es = "Medios", .fr = "Médias", + .he = "מדיה", .it = "Media", .ja = "メディア", .ko = "미디어", diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index d5a63f6b09..d375bd9cc3 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -122,9 +122,11 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .description = "Print system memory usage information", .displayName = { .en = "Memory", + .ar = "الذاكرة", .de = "Speicher", .es = "Memoria", .fr = "Mémoire", + .he = "זיכרון", .it = "Memoria", .ja = "メモリ", .ko = "메모리", diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index aa55c022a7..5019f7e7e0 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -108,9 +108,11 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .description = "Same as Display module, but with a different default output format", .displayName = { .en = "Monitor", + .ar = "الشاشة", .de = "Monitor", .es = "Monitor", .fr = "Moniteur", + .he = "צג", .it = "Monitor", .ja = "モニター", .ko = "모니터", diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index f542c8375a..b6db692436 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -156,9 +156,11 @@ FFModuleBaseInfo ffMouseModuleInfo = { .description = "List connected mice", .displayName = { .en = "Mouse", + .ar = "الفأرة", .de = "Maus", .es = "Ratón", .fr = "Souris", + .he = "עכבר", .it = "Mouse", .ja = "マウス", .ko = "마우스", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index e750ea92d3..328cc36135 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -201,9 +201,11 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .description = "Print network I/O throughput", .displayName = { .en = "Network I/O", + .ar = "إدخال/إخراج الشبكة", .de = "Netzwerk I/O", .es = "E/S de red", .fr = "E/S réseau", + .he = "קלט/פלט רשת", .it = "I/O di rete", .ja = "ネットワークI/O", .ko = "네트워크 I/O", diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index fbc36c39a9..78352f306c 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -124,9 +124,11 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .description = "Print the highest OpenCL version supported by the GPU", .displayName = { .en = "OpenCL", + .ar = "OpenCL", .de = "OpenCL", .es = "OpenCL", .fr = "OpenCL", + .he = "OpenCL", .it = "OpenCL", .ja = "OpenCL", .ko = "OpenCL", diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index bac96afc70..8093e135df 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -131,9 +131,11 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .description = "Print the highest OpenGL version supported by the GPU", .displayName = { .en = "OpenGL", + .ar = "OpenGL", .de = "OpenGL", .es = "OpenGL", .fr = "OpenGL", + .he = "OpenGL", .it = "OpenGL", .ja = "OpenGL", .ko = "OpenGL", diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 71661bf0a5..3e0fecc756 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -176,9 +176,11 @@ FFModuleBaseInfo ffOSModuleInfo = { .description = "Print the OS or Linux distribution name and version", .displayName = { .en = "OS", + .ar = "نظام التشغيل", .de = "Betriebssystem", .es = "Sistema operativo", .fr = "Système d'exploitation", + .he = "מערכת הפעלה", .it = "Sistema operativo", .ja = "オペレーティングシステム", .ko = "운영 체제", diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index c21ef4ca6f..2c6143189c 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -514,9 +514,11 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .description = "List installed package managers and count of installed packages", .displayName = { .en = "Packages", + .ar = "الحزم", .de = "Pakete", .es = "Paquetes", .fr = "Paquets", + .he = "חבילות", .it = "Pacchetti", .ja = "パッケージ", .ko = "패키지", diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index b85ec44100..929ca4b69a 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -267,9 +267,11 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .description = "Print physical disk information", .displayName = { .en = "Physical Disk", + .ar = "القرص الفعلي", .de = "Physische Festplatte", .es = "Disco físico", .fr = "Disque physique", + .he = "דיסק פיזי", .it = "Disco fisico", .ja = "物理ディスク", .ko = "물리 디스크", diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 0ab65cdb57..5c0d6ecec7 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -161,9 +161,11 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .description = "Print system physical memory devices", .displayName = { .en = "Physical Memory", + .ar = "الذاكرة الفعلية", .de = "Physischer Speicher", .es = "Memoria física", .fr = "Mémoire physique", + .he = "זיכרון פיזי", .it = "Memoria fisica", .ja = "物理メモリ", .ko = "물리 메모리", diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 0693423e01..c12da175d9 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -111,9 +111,11 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .description = "Print the music player name that is currently active", .displayName = { .en = "Media Player", + .ar = "مشغل الوسائط", .de = "Medienplayer", .es = "Reproductor multimedia", .fr = "Lecteur multimédia", + .he = "נגן מדיה", .it = "Lettore multimediale", .ja = "メディアプレイヤー", .ko = "미디어 플레이어", diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 71899d26ee..a70d3a36f5 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -112,9 +112,11 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .description = "Print power adapter name and charging watts", .displayName = { .en = "Power Adapter", + .ar = "محول الطاقة", .de = "Netzteil", .es = "Adaptador de corriente", .fr = "Adaptateur secteur", + .he = "מתאם מתח", .it = "Alimentatore", .ja = "電源アダプター", .ko = "전원 어댑터", diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index bb42ca59e3..824fd89d66 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -67,9 +67,11 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .description = "Print number of running processes", .displayName = { .en = "Processes", + .ar = "العمليات", .de = "Prozesse", .es = "Procesos", .fr = "Processus", + .he = "תהליכים", .it = "Processi", .ja = "プロセス", .ko = "프로세스", diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 92c790544b..4fa09c32fc 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -112,9 +112,11 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .description = "Print your public IP address and related information", .displayName = { .en = "Public IP", + .ar = "عنوان IP العام", .de = "Öffentliche IP", .es = "IP pública", .fr = "IP publique", + .he = "IP ציבורי", .it = "IP pubblica", .ja = "パブリックIP", .ko = "공용 IP", diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index f70c7a7bd5..34af6a2867 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -125,9 +125,11 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .description = "Print a separator line", .displayName = { .en = "Separator", + .ar = "الفاصل", .de = "Trennlinie", .es = "Separador", .fr = "Séparateur", + .he = "מפריד", .it = "Separatore", .ja = "セパレーター", .ko = "구분선", diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 55e0da630f..4c9adf343f 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -93,9 +93,11 @@ FFModuleBaseInfo ffShellModuleInfo = { .description = "Print the current shell name and version", .displayName = { .en = "Shell", + .ar = "الصدفة", .de = "Shell", .es = "Shell", .fr = "Shell", + .he = "מעטפת", .it = "Shell", .ja = "シェル", .ko = "셸", diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 7f3a691e53..fa87482f1a 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -203,9 +203,11 @@ FFModuleBaseInfo ffSoundModuleInfo = { .description = "Print sound devices, volume levels, etc", .displayName = { .en = "Sound", + .ar = "الصوت", .de = "Sound", .es = "Sonido", .fr = "Son", + .he = "קול", .it = "Audio", .ja = "サウンド", .ko = "사운드", diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index ea0ac62dee..201282dc06 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -186,9 +186,11 @@ FFModuleBaseInfo ffSwapModuleInfo = { .description = "Print swap (paging file) space usage", .displayName = { .en = "Swap", + .ar = "الذاكرة التبادلية", .de = "Swap", .es = "Swap", .fr = "Swap", + .he = "זיכרון החלפה", .it = "Swap", .ja = "スワップ", .ko = "스왑", diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 3752b45e0d..58e6ae9cfb 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -87,9 +87,11 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .description = "Print the current terminal name and version", .displayName = { .en = "Terminal", + .ar = "الطرفية", .de = "Terminal", .es = "Terminal", .fr = "Terminal", + .he = "טרמינל", .it = "Terminale", .ja = "ターミナル", .ko = "터미널", diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index fdb7990be4..ae792843be 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -107,9 +107,11 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .description = "Print the font name and size used by the current terminal", .displayName = { .en = "Terminal Font", + .ar = "خط الطرفية", .de = "Terminalschriftart", .es = "Fuente del terminal", .fr = "Police du terminal", + .he = "גופן טרמינל", .it = "Carattere del terminale", .ja = "ターミナルフォント", .ko = "터미널 글꼴", diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 70f6139d14..08c2c9de01 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -78,9 +78,11 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .description = "Print the current terminal size", .displayName = { .en = "Terminal Size", + .ar = "حجم الطرفية", .de = "Terminalgröße", .es = "Tamaño del terminal", .fr = "Taille du terminal", + .he = "גודל טרמינל", .it = "Dimensioni terminale", .ja = "ターミナルサイズ", .ko = "터미널 크기", diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 4e40876f31..52e3feebfe 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -95,9 +95,11 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .description = "Print the current terminal theme (foreground and background colors)", .displayName = { .en = "Terminal Theme", + .ar = "سمة الطرفية", .de = "Terminalthema", .es = "Tema del terminal", .fr = "Thème du terminal", + .he = "ערכת נושא של טרמינל", .it = "Tema del terminale", .ja = "ターミナルテーマ", .ko = "터미널 테마", diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 948e0d4696..4ceaf14cbe 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -91,9 +91,11 @@ FFModuleBaseInfo ffThemeModuleInfo = { .description = "Print the current desktop environment theme", .displayName = { .en = "Theme", + .ar = "السمة", .de = "Thema", .es = "Tema", .fr = "Thème", + .he = "ערכת נושא", .it = "Tema", .ja = "テーマ", .ko = "테마", diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 939f4daf9d..788ab2eec6 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -180,9 +180,11 @@ FFModuleBaseInfo ffTitleModuleInfo = { .description = "Print the title, including your username and hostname", .displayName = { .en = "Title", + .ar = "العنوان", .de = "Titel", .es = "Título", .fr = "Titre", + .he = "כותרת", .it = "Titolo", .ja = "タイトル", .ko = "제목", diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index c216b05b50..3ff4a4e8d0 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -87,9 +87,11 @@ FFModuleBaseInfo ffTPMModuleInfo = { .description = "Print information about the Trusted Platform Module (TPM) security device", .displayName = { .en = "TPM", + .ar = "TPM", .de = "TPM", .es = "TPM", .fr = "TPM", + .he = "TPM", .it = "TPM", .ja = "TPM", .ko = "TPM", diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 9cc364c41f..d7ee69e05a 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -87,9 +87,11 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .description = "Print how long the system has been running", .displayName = { .en = "Uptime", + .ar = "مدة التشغيل", .de = "Betriebszeit", .es = "Tiempo de actividad", .fr = "Temps de fonctionnement", + .he = "זמן פעילות", .it = "Tempo di attività", .ja = "稼働時間", .ko = "업타임", diff --git a/src/modules/users/users.c b/src/modules/users/users.c index d2e1270767..e355f40d74 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -184,9 +184,11 @@ FFModuleBaseInfo ffUsersModuleInfo = { .description = "Print users who are currently logged in", .displayName = { .en = "Users", + .ar = "المستخدمون", .de = "Benutzer", .es = "Usuarios", .fr = "Utilisateurs", + .he = "משתמשים", .it = "Utenti", .ja = "ユーザー", .ko = "사용자", diff --git a/src/modules/version/version.c b/src/modules/version/version.c index d023abe889..f90585a73e 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -98,9 +98,11 @@ FFModuleBaseInfo ffVersionModuleInfo = { .description = "Print the Fastfetch version and build information", .displayName = { .en = "Version", + .ar = "الإصدار", .de = "Version", .es = "Versión", .fr = "Version", + .he = "גרסה", .it = "Versione", .ja = "バージョン", .ko = "버전", diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 2d6dbfd222..990b56f1ac 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -136,9 +136,11 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .description = "Print the highest Vulkan version supported by the GPU", .displayName = { .en = "Vulkan", + .ar = "Vulkan", .de = "Vulkan", .es = "Vulkan", .fr = "Vulkan", + .he = "Vulkan", .it = "Vulkan", .ja = "Vulkan", .ko = "Vulkan", diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index e57082fc5c..9ed7d40146 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -79,9 +79,11 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .description = "Print the file path of the current wallpaper", .displayName = { .en = "Wallpaper", + .ar = "الخلفية", .de = "Hintergrundbild", .es = "Fondo de pantalla", .fr = "Fond d'écran", + .he = "טפט", .it = "Sfondo", .ja = "壁紙", .ko = "배경화면", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 9f7dae54d9..5eab9a6c71 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -96,9 +96,11 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .description = "Print weather information", .displayName = { .en = "Weather", + .ar = "الطقس", .de = "Wetter", .es = "Clima", .fr = "Météo", + .he = "מזג אוויר", .it = "Meteo", .ja = "天気", .ko = "날씨", diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 39e99a38ec..8aad2884e4 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -217,9 +217,11 @@ FFModuleBaseInfo ffWifiModuleInfo = { .description = "Print connected Wi-Fi info (SSID, connection and security protocol)", .displayName = { .en = "Wi-Fi", + .ar = "واي فاي", .de = "WLAN", .es = "Wi-Fi", .fr = "Wi-Fi", + .he = "Wi-Fi", .it = "Wi-Fi", .ja = "Wi-Fi", .ko = "와이파이", diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 4c40bc2061..8b7d8ec263 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -124,9 +124,11 @@ FFModuleBaseInfo ffWMModuleInfo = { .description = "Print the window manager name and version", .displayName = { .en = "WM", + .ar = "مدير النوافذ", .de = "Fenstermanager", .es = "Gestor de ventanas", .fr = "Gestionnaire de fenêtres", + .he = "מנהל חלונות", .it = "Gestore finestre", .ja = "ウィンドウマネージャー", .ko = "윈도우 관리자", diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index b7ed26b429..5394b09638 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -63,9 +63,11 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .description = "Print the current window manager theme", .displayName = { .en = "WM Theme", + .ar = "سمة مدير النوافذ", .de = "Fenstermanager-Thema", .es = "Tema del gestor de ventanas", .fr = "Thème du gestionnaire de fenêtres", + .he = "ערכת נושא של מנהל חלונות", .it = "Tema del gestore finestre", .ja = "ウィンドウマネージャのテーマ", .ko = "윈도우 관리자 테마", diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index f6ea00c402..aafb5d4d90 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -196,9 +196,11 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .description = "Print ZFS storage pools", .displayName = { .en = "Zpool", + .ar = "Zpool", .de = "Zpool", .es = "Zpool", .fr = "Zpool", + .he = "Zpool", .it = "Zpool", .ja = "Zpool", .ko = "Zpool", diff --git a/src/options/display.c b/src/options/display.c index 78ea684ce3..20625be92a 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -62,9 +62,11 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { #pragma GCC diagnostic ignored "-Wmultichar" switch (language->chars[0] << 8 | language->chars[1]) { case 'en': return offsetof(FFModuleDisplayName, en); + case 'ar': return offsetof(FFModuleDisplayName, ar); case 'de': return offsetof(FFModuleDisplayName, de); case 'es': return offsetof(FFModuleDisplayName, es); case 'fr': return offsetof(FFModuleDisplayName, fr); + case 'he': return offsetof(FFModuleDisplayName, he); case 'it': return offsetof(FFModuleDisplayName, it); case 'ja': return offsetof(FFModuleDisplayName, ja); case 'ko': return offsetof(FFModuleDisplayName, ko); @@ -1269,6 +1271,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, en): yyjson_mut_obj_add_str(doc, key, "language", "en"); break; + case offsetof(FFModuleDisplayName, ar): + yyjson_mut_obj_add_str(doc, key, "language", "ar"); + break; case offsetof(FFModuleDisplayName, de): yyjson_mut_obj_add_str(doc, key, "language", "de"); break; @@ -1278,6 +1283,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, fr): yyjson_mut_obj_add_str(doc, key, "language", "fr"); break; + case offsetof(FFModuleDisplayName, he): + yyjson_mut_obj_add_str(doc, key, "language", "he"); + break; case offsetof(FFModuleDisplayName, it): yyjson_mut_obj_add_str(doc, key, "language", "it"); break; From bbb906ba10c9b9bcc664c3f0fe016fe6459749c4 Mon Sep 17 00:00:00 2001 From: Hashing <88584784+HashimAbdulaziz@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:15:39 +0300 Subject: [PATCH 016/109] L10n (Pt): matches all Portuguese locales, not only bare `pt` (#2521) 359cb0a79a3531e382fdb0c99357252936f08bf2 renamed the key from `pt_BR` to `pt` but kept the exact-match guard, so only the literal string `pt` matched. Every real Portuguese locale (`pt_BR`, `pt_PT` and their charset and modifier variants) fell through to `goto error` and aborted. Return the offset unconditionally, matching every other two-letter case. --- src/options/display.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/options/display.c b/src/options/display.c index 20625be92a..36d408f78b 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -71,12 +71,7 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { case 'ja': return offsetof(FFModuleDisplayName, ja); case 'ko': return offsetof(FFModuleDisplayName, ko); case 'pl': return offsetof(FFModuleDisplayName, pl); - case 'pt': { - if (ffStrbufEqualS(language, "pt")) { - return offsetof(FFModuleDisplayName, pt); - } - goto error; - } + case 'pt': return offsetof(FFModuleDisplayName, pt); case 'ru': return offsetof(FFModuleDisplayName, ru); case 'zh': { if (ffStrbufEqualS(language, "zh_cn")) { From 7fbd06a135ceb4666c9dd56b83ef8df95efcfc6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 16 Aug 2026 22:16:52 +0800 Subject: [PATCH 017/109] Doc: updates README.md [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f2481cbd2..84ec8e9752 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ See the Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building * View all data that fastfetch detects: `fastfetch -s [:][:] --format json` * Display help messages: `fastfetch --help` * Generate a minimal config file: `fastfetch [-s [:]] --gen-config []` - * Use: `--gen-config-full` to generate a full config file with all optional options + * Use [The online configuration generator](https://fastfetch-cli.github.io/fastfetch-config/) to generate a full config file with all optional options ## Customization From 9ff7969acf6da6db32a6940b36a6bd489691ec8a Mon Sep 17 00:00:00 2001 From: Wehrwolfmann Date: Sun, 16 Aug 2026 17:45:24 +0200 Subject: [PATCH 018/109] Bluetooth / BluetoothRadio: keeps the brand name in Latin script in Russian keys --- src/modules/bluetooth/bluetooth.c | 2 +- src/modules/bluetoothradio/bluetoothradio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index ab98f1f46d..95a0bae93f 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -165,7 +165,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .ko = "블루투스", .pl = "Bluetooth", .pt = "Bluetooth", - .ru = "Блютуз", + .ru = "Bluetooth", .zh_CN = "蓝牙", .zh_TW = "藍牙", }, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index f8b22a9f4a..5a6b47d715 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -202,7 +202,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", .pt = "Adaptador Bluetooth", - .ru = "Блютуз-адаптер", + .ru = "Bluetooth-адаптер", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", }, From bcb48774a0a0cd92a28ec0ec89157288a5bf4fbf Mon Sep 17 00:00:00 2001 From: Wehrwolfmann Date: Sun, 16 Aug 2026 17:51:44 +0200 Subject: [PATCH 019/109] Modules: proofreads Russian l10n strings --- src/modules/chassis/chassis.c | 2 +- src/modules/cpu/cpu.c | 2 +- src/modules/cpuusage/cpuusage.c | 2 +- src/modules/de/de.c | 2 +- src/modules/diskio/diskio.c | 2 +- src/modules/gpu/gpu.c | 2 +- src/modules/host/host.c | 2 +- src/modules/initsystem/initsystem.c | 2 +- src/modules/poweradapter/poweradapter.c | 2 +- src/modules/publicip/publicip.c | 2 +- src/modules/swap/swap.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 904f4d1132..ae99ba9c5d 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -124,7 +124,7 @@ FFModuleBaseInfo ffChassisModuleInfo = { .ko = "섀시", .pl = "Obudowa", .pt = "Chassi", - .ru = "Шасси", + .ru = "Корпус", .zh_CN = "机箱", .zh_TW = "機箱", }, diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 5754fd08d0..ec14dd363f 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -265,7 +265,7 @@ FFModuleBaseInfo ffCPUModuleInfo = { .ko = "CPU", .pl = "CPU", .pt = "CPU", - .ru = "CPU", + .ru = "Процессор", .zh_CN = "CPU", .zh_TW = "CPU", }, diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index b649edba98..e2b09a03aa 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -193,7 +193,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .ko = "CPU 사용량", .pl = "Użycie CPU", .pt = "Uso da CPU", - .ru = "Использование ЦП", + .ru = "Использование процессора", .zh_CN = "CPU使用率", .zh_TW = "CPU使用率", }, diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 9e4dcc3dfc..c8b188d48f 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -96,7 +96,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .ko = "데스크탑 환경", .pl = "Środowisko graficzne", .pt = "Ambiente de desktop", - .ru = "Рабочая среда", + .ru = "Рабочее окружение", .zh_CN = "桌面环境", .zh_TW = "桌面環境", }, diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 51fc95fec6..3ebb8ce305 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -184,7 +184,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .ko = "디스크 I/O", .pl = "Dysk I/O", .pt = "Disco I/O", - .ru = "Диск I/O", + .ru = "Дисковый I/O", .zh_CN = "磁盘 I/O", .zh_TW = "磁碟 I/O", }, diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index d0caa2fcfd..f030795dad 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -493,7 +493,7 @@ FFModuleBaseInfo ffGPUModuleInfo = { .ko = "GPU", .pl = "GPU", .pt = "GPU", - .ru = "GPU", + .ru = "Видеокарта", .zh_CN = "显卡", .zh_TW = "顯卡", }, diff --git a/src/modules/host/host.c b/src/modules/host/host.c index ffe5c52255..0159423bf1 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -150,7 +150,7 @@ FFModuleBaseInfo ffHostModuleInfo = { .ko = "호스트", .pl = "Host", .pt = "Host", - .ru = "Хост", + .ru = "Модель", .zh_CN = "主机", .zh_TW = "主機", }, diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index 395d10261b..edd3d8fdce 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -115,7 +115,7 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .ko = "초기화 시스템", .pl = "System init", .pt = "Sistema de inicialização", - .ru = "Init-система", + .ru = "Система инициализации", .zh_CN = "Init 系统", .zh_TW = "Init 系統", }, diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index a70d3a36f5..d9506c41be 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -122,7 +122,7 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .ko = "전원 어댑터", .pl = "Zasilacz", .pt = "Fonte de alimentação", - .ru = "Блок питания", + .ru = "Адаптер питания", .zh_CN = "电源适配器", .zh_TW = "電源轉接器", }, diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 4fa09c32fc..afad49017d 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -122,7 +122,7 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .ko = "공용 IP", .pl = "Publiczne IP", .pt = "IP público", - .ru = "Публичный IP", + .ru = "Внешний IP", .zh_CN = "公网 IP", .zh_TW = "公網 IP", }, diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 201282dc06..796cf7271b 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -196,7 +196,7 @@ FFModuleBaseInfo ffSwapModuleInfo = { .ko = "스왑", .pl = "Swap", .pt = "Swap", - .ru = "Своп", + .ru = "Подкачка", .zh_CN = "交换空间", .zh_TW = "交換空間", }, From 5e9c31ac311da08043877c5032f3c0405128dcb9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 10:32:40 +0800 Subject: [PATCH 020/109] Completion (Fish): prints enum description [ci skip] --- completions/fastfetch.fish | 80 ++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/completions/fastfetch.fish b/completions/fastfetch.fish index f4804f5f50..45397a6b7e 100755 --- a/completions/fastfetch.fish +++ b/completions/fastfetch.fish @@ -63,46 +63,78 @@ echo ' import json, subprocess, sys +def escape_fish_dq(s: str) -> str: + """Escape special characters for Fish double quotes to prevent unexpected expansions. One slash in output needs four slashes in script""" + return str(s).replace("\\\\", "\\\\\\\\").replace("\\"", "\\\\\\"").replace("$", "\\\\$") + + def main(): data: dict[str, list[dict]] = json.loads(subprocess.check_output(["fastfetch", "--help-raw"])) + enum_functions = [] + complete_commands = [] + for key in data: for flag in data[key]: - if flag["long"] == "logo-color-[1-9]": + long_name = flag.get("long", "") + + # Handle pseudo flag logo-color-[1-9] + if long_name == "logo-color-[1-9]": + safe_desc_global = escape_fish_dq(flag.get("desc", "")) for i in range(1, 10): - print(f"""complete -c fastfetch -d "{flag["desc"]}" -l "logo-color-{i}" -x -a "(__fastfetch_complete_color)" """) + complete_commands.append(f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"logo-color-{i}\" -x -a \"(__fastfetch_complete_color)\"") continue if flag.get("pseudo", False): continue - command_prefix = f"""complete -c fastfetch -d "{flag["desc"]}" -l "{flag["long"]}\"""" + safe_desc_global = escape_fish_dq(flag.get("desc", "")) + command_prefix = f"complete -c fastfetch -d \"{safe_desc_global}\" -l \"{long_name}\"" + if "short" in flag: - command_prefix += f""" -o {flag["short"]}""" + short_name = flag["short"] + command_prefix += f" -o {short_name}" if "arg" in flag: - type: str = flag["arg"]["type"] - if type == "bool": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"") - elif type == "color": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"") - elif type == "command": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"") - elif type == "config": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"") - elif type == "enum": - temp: str = " ".join(flag["arg"]["enum"]) - print(f"{command_prefix} -x -a \"{temp}\"") - elif type == "logo": - print(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"") - elif type == "structure": - print(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"") - elif type == "path": - print(f"{command_prefix} -r -F") + arg_type: str = flag["arg"]["type"] + if arg_type == "bool": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_bool)\"") + elif arg_type == "color": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_color)\"") + elif arg_type == "command": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_command)\"") + elif arg_type == "config": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_config)\"") + elif arg_type == "enum": + # Sanitize flag name to create a valid Fish function name + func_name = long_name.replace("-", "_").replace("[", "_").replace("]", "_") + func_name = f"__fastfetch_complete_enum_{func_name}" + + # Generate the enum function + func_lines = [f"function {func_name}"] + for enum_val, enum_desc in flag["arg"]["enum"].items(): + safe_val = escape_fish_dq(enum_val) + safe_desc = escape_fish_dq(enum_desc) + func_lines.append(f" echo -e \"{safe_val}\\t{safe_desc}\"") + func_lines.append("end\n") + enum_functions.append("\n".join(func_lines)) + + # Append complete command pointing to the new function + complete_commands.append(f"{command_prefix} -x -a \"({func_name})\"") + elif arg_type == "logo": + complete_commands.append(f"{command_prefix} -x -a \"(__fastfetch_complete_logo)\"") + elif arg_type == "structure": + complete_commands.append(f"{command_prefix} -x -a \"(__fish_complete_list : __fastfetch_complete_structure)\"") + elif arg_type == "path": + complete_commands.append(f"{command_prefix} -r -F") else: - print(f"{command_prefix} -x") + complete_commands.append(f"{command_prefix} -x") else: - print(f"{command_prefix} -f") + complete_commands.append(f"{command_prefix} -f") + + # Print generated enum functions first, then complete rules + print("\n".join(enum_functions)) + print("\n".join(complete_commands)) if __name__ == "__main__": From 2ca7e037ef2b6c249faa801fbbe2a3193fdd8880 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 13:36:09 +0800 Subject: [PATCH 021/109] L10n (Zh): translates `shell` --- src/modules/shell/shell.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 4c9adf343f..8abd01d523 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -104,8 +104,8 @@ FFModuleBaseInfo ffShellModuleInfo = { .pl = "Powłoka", .pt = "Shell", .ru = "Оболочка", - .zh_CN = "Shell", - .zh_TW = "Shell", + .zh_CN = "命令行解释器", + .zh_TW = "命令列直譯器", }, .initOptions = (void*) ffInitShellOptions, .destroyOptions = (void*) ffDestroyShellOptions, From 72d240f3259b70abd6dec323a30056934fdeee84 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 13:42:30 +0800 Subject: [PATCH 022/109] L10n (Zh): clarifies `Bluetooth` actually detects `Bluetooth devices` --- src/modules/bluetooth/bluetooth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 95a0bae93f..d4adae8215 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -166,8 +166,8 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .pl = "Bluetooth", .pt = "Bluetooth", .ru = "Bluetooth", - .zh_CN = "蓝牙", - .zh_TW = "藍牙", + .zh_CN = "蓝牙设备", + .zh_TW = "藍牙裝置", }, .initOptions = (void*) ffInitBluetoothOptions, .destroyOptions = (void*) ffDestroyBluetoothOptions, From 679d868b4ad99d1d345b8cdab103e38f7b39d1b9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 13:57:23 +0800 Subject: [PATCH 023/109] L10n (Zh): clarifies `Disk` actually detects `Disk partitions` --- src/modules/disk/disk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index dd823bc2b3..fddd4580f9 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -466,8 +466,8 @@ FFModuleBaseInfo ffDiskModuleInfo = { .pl = "Dysk", .pt = "Disco", .ru = "Диск", - .zh_CN = "磁盘", - .zh_TW = "磁碟", + .zh_CN = "磁盘分区", + .zh_TW = "硬碟分割", }, .initOptions = (void*) ffInitDiskOptions, .destroyOptions = (void*) ffDestroyDiskOptions, From e6d90c2081b907a27a922a4dce2cd1af6ab028c8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 17 Aug 2026 14:20:46 +0800 Subject: [PATCH 024/109] L10n (Zh): uses a different name for `Monitor` --- src/modules/monitor/monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 5019f7e7e0..a9959187bd 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -119,8 +119,8 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .pl = "Monitor", .pt = "Monitor", .ru = "Монитор", - .zh_CN = "显示器", - .zh_TW = "顯示器", + .zh_CN = "监视器", + .zh_TW = "監視器", }, .initOptions = (void*) ffInitMonitorOptions, .destroyOptions = (void*) ffDestroyMonitorOptions, From 6cb15885c7376519faf4daf2e5bc2c401d9b2185 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 09:11:50 +0800 Subject: [PATCH 025/109] L10n: don't use `ffStrbufCreateStatic` for buffers that will be modified later --- src/options/display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options/display.c b/src/options/display.c index 36d408f78b..994296d78a 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -741,7 +741,7 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key } else if (ffStrEqualsIgnCase(subkey, "padding-left")) { options->keyPaddingLeft = (uint16_t) ffOptionParseUInt32(key, value); } else if (ffStrEqualsIgnCase(subkey, "language")) { - FF_STRBUF_AUTO_DESTROY language = ffStrbufCreateStatic(value); + FF_STRBUF_AUTO_DESTROY language = ffStrbufCreateS(value); options->keyLanguage = optionParseLanguageString(&language); } else { return false; From e5b6e3612ac477058503e28bb217a44931a20f9d Mon Sep 17 00:00:00 2001 From: Wehrwolfmann Date: Tue, 18 Aug 2026 02:04:01 +0200 Subject: [PATCH 026/109] L10n: falls back to English when the auto-detected locale is unsupported --key-language with an empty value (and "language": null in the config) asks for the system locale, not for a specific language. When that locale has no translation, fastfetch aborted with exit 477 instead of printing anything, so the same config broke on every locale outside the twelve supported ones, and under LC_ALL=C variants such as POSIX. Auto-detected locales now fall back to English. An explicitly requested language still errors out, so typos and zh are still reported. --- doc/help.json | 2 +- src/options/display.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/help.json b/doc/help.json index b1cfbfa560..b575aa47bc 100644 --- a/doc/help.json +++ b/doc/help.json @@ -588,7 +588,7 @@ { "long": "key-language", "desc": "Specify the language used for module keys", - "remark": "Leave empty for auto-detection based on the system locale", + "remark": "Leave empty for auto-detection based on the system locale. Unsupported locales fall back to English", "arg": { "type": "enum", "default": "en", diff --git a/src/options/display.c b/src/options/display.c index 994296d78a..a352af7192 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -17,7 +17,9 @@ // @returns offsetof(FFModuleDisplayName, ) // @see src/common/option.h static uint32_t optionParseLanguageString(FFstrbuf* language) { - if (language->length == 0) { + const bool detected = language->length == 0; + + if (detected) { #if !FF_MODULE_DISABLE_LOCALE const char* error = ffDetectLocale(language); if (__builtin_expect(error != nullptr, false)) { @@ -52,7 +54,7 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { // The language code is expected to be in the format of "en", "en_US", "de", "de_DE", etc. // First try to match the full language code, then try to match just the first two characters (the language part). - // If no match is found, report a language not supported error. + // If no match is found, report a language not supported error, unless the language was auto-detected. // en_US -> offsetof(FFModuleDisplayName, en) // en -> offsetof(FFModuleDisplayName, en) // zh_CN -> offsetof(FFModuleDisplayName, zh_CN) @@ -85,6 +87,10 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { #pragma GCC diagnostic pop error: + // The user asked for the system locale, not for this specific language. Most locales have no + // translation, so falling back to English is friendlier than aborting fastfetch entirely. + if (detected) return offsetof(FFModuleDisplayName, en); + fprintf(stderr, "Error: Language '%s' is not supported\n", language->chars); exit(477); } From 7c93f9c82af5b909935c5d2dcfa275f49662b2b7 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 15:56:33 +0800 Subject: [PATCH 027/109] GPU (macOS): removes useless `@available` tests --- src/detection/gpu/gpu_apple.m | 112 ++++++++++++++++------------------ 1 file changed, 53 insertions(+), 59 deletions(-) diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index 24ede6de2c..9596dbe76d 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -14,74 +14,68 @@ #define MTLFeatureSet_macOS_GPUFamily2_v1 ((MTLFeatureSet) 10005) #endif -const char* ffGpuDetectDriverVersion(FFlist* gpus) -{ - if (@available(macOS 10.7, *)) - { - NSMutableArray* arr = NSMutableArray.new; - FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) - [arr addObject:@(x->driver.chars)]; +const char* ffGpuDetectDriverVersion(FFlist* gpus) { + NSMutableArray* arr = NSMutableArray.new; + FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) { + [arr addObject:@(x->driver.chars)]; + } - NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef)arr, (__bridge CFArrayRef)@[@"CFBundleVersion"])); - FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) - { - NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"]; - if (version) - { - ffStrbufAppendC(&x->driver, ' '); - ffStrbufAppendS(&x->driver, version.UTF8String); - } + NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef) arr, (__bridge CFArrayRef) @[ @"CFBundleVersion" ])); + FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) { + NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"]; + if (version) { + ffStrbufAppendC(&x->driver, ' '); + ffStrbufAppendS(&x->driver, version.UTF8String); } - return nullptr; } - return "Unsupported macOS version"; + return nullptr; } -const char* ffGpuDetectMetal(FFlist* gpus) -{ - if (@available(macOS 10.13, *)) - { - for (id device in MTLCopyAllDevices()) - { - FFGPUResult* gpu = nullptr; - FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) - { - if (x->deviceId == device.registryID) - { - gpu = x; - break; - } +const char* ffGpuDetectMetal(FFlist* gpus) { + // Metal.framework is statically linked into the application, + // so `MTLCopyAllDevices` is always available, or the application will not start. + for (id device in MTLCopyAllDevices()) { + FFGPUResult* gpu = nullptr; + FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) { + if (x->deviceId == device.registryID) { + gpu = x; + break; } - if (!gpu) continue; + } + if (!gpu) { + continue; + } - #ifndef MAC_OS_X_VERSION_10_15 - if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2"); - else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1"); - #else // MAC_OS_X_VERSION_10_15 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wunguarded-availability-new" - if ([device supportsFamily:MTLGPUFamilyMetal4]) - ffStrbufSetStatic(&gpu->platformApi, "Metal 4"); - else if ([device supportsFamily:MTLGPUFamilyMetal3]) - ffStrbufSetStatic(&gpu->platformApi, "Metal 3"); - #pragma clang diagnostic pop - else if ([device supportsFamily:MTLGPUFamilyCommon3]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3"); - else if ([device supportsFamily:MTLGPUFamilyCommon2]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2"); - else if ([device supportsFamily:MTLGPUFamilyCommon1]) - ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); +#ifndef MAC_OS_X_VERSION_10_15 + if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2"); + } else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1"); + } +#else // MAC_OS_X_VERSION_10_15 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability-new" + if ([device supportsFamily:MTLGPUFamilyMetal4]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal 4"); + } else if ([device supportsFamily:MTLGPUFamilyMetal3]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal 3"); + } + #pragma clang diagnostic pop + else if ([device supportsFamily:MTLGPUFamilyCommon3]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3"); + } else if ([device supportsFamily:MTLGPUFamilyCommon2]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2"); + } else if ([device supportsFamily:MTLGPUFamilyCommon1]) { + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); + } - gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - gpu->index = (uint32_t) device.locationNumber; + gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + gpu->index = (uint32_t) device.locationNumber; - if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0) - gpu->shared.total = device.recommendedMaxWorkingSetSize; - #endif + if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0) { + gpu->shared.total = device.recommendedMaxWorkingSetSize; } - return nullptr; +#endif } - return "Metal API is not supported by this macOS version"; + return nullptr; } From 232cd6659ba39fdff71a1cb74f53e9833eb270b1 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 15:28:25 +0800 Subject: [PATCH 028/109] Wifi (Linux): adds channel width and device driver detection --- src/detection/wifi/wifi.h | 2 + src/detection/wifi/wifi_linux.c | 179 +++++++++++++++++++++++++++++++- src/modules/wifi/wifi.c | 8 ++ 3 files changed, 184 insertions(+), 5 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index e457295c36..7ad22855d4 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -6,6 +6,7 @@ struct FFWifiInterface { FFstrbuf description; FFstrbuf status; + FFstrbuf driver; }; struct FFWifiConnection { @@ -18,6 +19,7 @@ struct FFWifiConnection { double rxRate; double txRate; uint16_t channel; + uint16_t channelWidth; // MHz uint16_t frequency; // MHz }; diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index c609c25c41..1fe21b0c46 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -212,8 +212,9 @@ static bool ffWifiNlInit(FFWifiNlContext* ctx) { return true; } -static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFstrbuf* protocol) { +static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFstrbuf* protocol, uint16_t* channelWidth) { double rate = -DBL_MAX; + uint16_t width = 0; size_t remaining = ffWifiNlAttrPayload(rateAttr); for (const struct nlattr* info = (const struct nlattr*) ffWifiNlAttrData(rateAttr); @@ -223,6 +224,40 @@ static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFst size_t payload = ffWifiNlAttrPayload(info); switch (type) { + case NL80211_RATE_INFO_40_MHZ_WIDTH: + width = 40; + break; + case NL80211_RATE_INFO_80_MHZ_WIDTH: + case NL80211_RATE_INFO_80P80_MHZ_WIDTH: + width = 80; + break; + case NL80211_RATE_INFO_160_MHZ_WIDTH: + width = 160; + break; + case 18 /* NL80211_RATE_INFO_320_MHZ_WIDTH */: + width = 320; + break; + case NL80211_RATE_INFO_10_MHZ_WIDTH: + width = 10; + break; + case NL80211_RATE_INFO_5_MHZ_WIDTH: + width = 5; + break; + case 25 /* NL80211_RATE_INFO_1_MHZ_WIDTH */: + width = 1; + break; + case 26 /* NL80211_RATE_INFO_2_MHZ_WIDTH */: + width = 2; + break; + case 27 /* NL80211_RATE_INFO_4_MHZ_WIDTH */: + width = 4; + break; + case 28 /* NL80211_RATE_INFO_8_MHZ_WIDTH */: + width = 8; + break; + case 29 /* NL80211_RATE_INFO_16_MHZ_WIDTH */: + width = 16; + break; case 30 /* NL80211_RATE_INFO_UHR_MCS */: ffStrbufSetStatic(protocol, "802.11bn (Wi-Fi 8)"); break; @@ -254,9 +289,126 @@ static double ffWifiParseBitrateFromRateInfo(const struct nlattr* rateAttr, FFst } } + if (rate != -DBL_MAX && *channelWidth == 0) { + *channelWidth = width; + } + return rate; } +static uint16_t ffWifiChannelWidthToMhz(uint32_t width) { + switch (width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + return 20; + case NL80211_CHAN_WIDTH_40: + return 40; + case NL80211_CHAN_WIDTH_80: + case NL80211_CHAN_WIDTH_80P80: + return 80; + case NL80211_CHAN_WIDTH_160: + return 160; + case NL80211_CHAN_WIDTH_5: + return 5; + case NL80211_CHAN_WIDTH_10: + return 10; + case NL80211_CHAN_WIDTH_1: + return 1; + case NL80211_CHAN_WIDTH_2: + return 2; + case NL80211_CHAN_WIDTH_4: + return 4; + case NL80211_CHAN_WIDTH_8: + return 8; + case NL80211_CHAN_WIDTH_16: + return 16; + case 13 /* NL80211_CHAN_WIDTH_320 */: + return 320; + default: + return 0; + } +} + +static bool ffWifiFetchInterfaceInfo(FFWifiNlContext* ctx, FFWifiResult* item, uint32_t ifIndex) { + struct { + struct nlmsghdr nlh; + struct genlmsghdr genl; + char attrs[32]; + } req = { + .nlh = { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr)), + .nlmsg_type = ctx->nl80211FamilyId, + .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, + .nlmsg_seq = ++ctx->seq, + .nlmsg_pid = ctx->portId, + }, + .genl = { + .cmd = NL80211_CMD_GET_INTERFACE, + .version = 0, + }, + }; + + if (!ffWifiNlAppendAttr(&req.nlh, sizeof(req), NL80211_ATTR_IFINDEX, &ifIndex, sizeof(ifIndex))) { + FF_DEBUG("Failed to build nl80211 interface request"); + return false; + } + + struct sockaddr_nl addr = { + .nl_family = AF_NETLINK, + }; + + ssize_t sent = sendto(ctx->sockFd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*) &addr, sizeof(addr)); + if (sent != (ssize_t) req.nlh.nlmsg_len) { + FF_DEBUG("Failed to send nl80211 interface request"); + return false; + } + + uint8_t buffer[8192]; + while (true) { + ssize_t received = recvfrom(ctx->sockFd, buffer, sizeof(buffer), 0, nullptr, nullptr); + if (received < 0) { + FF_DEBUG("Failed to receive nl80211 interface reply: %s", strerror(errno)); + return false; + } + + for (const struct nlmsghdr* nlh = (const struct nlmsghdr*) buffer; + NLMSG_OK(nlh, received); + nlh = NLMSG_NEXT(nlh, received)) { + if (nlh->nlmsg_seq != req.nlh.nlmsg_seq) { + continue; + } + + if (nlh->nlmsg_type == NLMSG_ERROR) { + const struct nlmsgerr* err = (const struct nlmsgerr*) NLMSG_DATA(nlh); + if (err->error != 0) { + FF_DEBUG("nl80211 interface request failed: %s", strerror(-err->error)); + } + return false; + } + + if (nlh->nlmsg_type != ctx->nl80211FamilyId) { + continue; + } + + const struct genlmsghdr* genl = (const struct genlmsghdr*) NLMSG_DATA(nlh); + size_t attrRemaining = nlh->nlmsg_len - NLMSG_HDRLEN - GENL_HDRLEN; + for (const struct nlattr* attr = (const struct nlattr*) ((const char*) genl + GENL_HDRLEN); + ffWifiNlAttrOk(attr, attrRemaining); + attr = ffWifiNlAttrNext(attr, &attrRemaining)) { + if ((attr->nla_type & NLA_TYPE_MASK) != NL80211_ATTR_CHANNEL_WIDTH || + ffWifiNlAttrPayload(attr) < sizeof(uint32_t)) { + continue; + } + + item->conn.channelWidth = ffWifiChannelWidthToMhz(*(const uint32_t*) ffWifiNlAttrData(attr)); + return item->conn.channelWidth != 0; + } + + return false; + } + } +} + static void ffWifiApplySecurityFlags(FFWifiResult* item, const FFWifiSecurityFlags* sec) { ffStrbufClear(&item->conn.security); @@ -566,13 +718,13 @@ static void ffWifiParseStationInfo(const struct nlattr* staInfoAttr, FFWifiResul if (type == NL80211_STA_INFO_SIGNAL && payload >= sizeof(uint8_t) && item->conn.signalQuality == -DBL_MAX) { int rssi = (int8_t) *(const uint8_t*) ffWifiNlAttrData(attr); item->conn.signalQuality = rssiToSignalQuality(rssi); - } else if (type == NL80211_STA_INFO_TX_BITRATE && item->conn.txRate == -DBL_MAX) { - double tx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol); + } else if (type == NL80211_STA_INFO_TX_BITRATE && (item->conn.txRate == -DBL_MAX || item->conn.channelWidth == 0)) { + double tx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol, &item->conn.channelWidth); if (tx != -DBL_MAX) { item->conn.txRate = tx; } - } else if (type == NL80211_STA_INFO_RX_BITRATE && item->conn.rxRate == -DBL_MAX) { - double rx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol); + } else if (type == NL80211_STA_INFO_RX_BITRATE && (item->conn.rxRate == -DBL_MAX || item->conn.channelWidth == 0)) { + double rx = ffWifiParseBitrateFromRateInfo(attr, &item->conn.protocol, &item->conn.channelWidth); if (rx != -DBL_MAX) { item->conn.rxRate = rx; } @@ -680,6 +832,7 @@ static const char* detectWithNetlink(FFWifiNlContext* ctx, FFWifiResult* item, u if (ffWifiFetchScanInfo(ctx, item, ifIndex)) { FF_DEBUG("found associated BSS: %s", item->conn.ssid.chars); ffStrbufSetStatic(&item->conn.status, "connected"); + ffWifiFetchInterfaceInfo(ctx, item, ifIndex); ffWifiFetchStationInfo(ctx, item, ifIndex); if (!item->conn.protocol.length && item->conn.txRate != -DBL_MAX) { FF_DEBUG("nl80211 station info did not include MCS family fields"); @@ -914,6 +1067,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -923,8 +1077,23 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; + { + ffStrbufSetF(&buffer, "/sys/class/net/%s/device/driver", i->if_name); + char pathBuf[PATH_MAX]; + ssize_t resultLength = readlink(buffer.chars, pathBuf, ARRAY_SIZE(pathBuf)); + if (resultLength > 0) { + const char* p = memrchr(pathBuf, '/', (size_t) resultLength); + if (p) { + ++p; + ffStrbufSetNS(&item->inf.driver, (uint32_t) (resultLength - (p - pathBuf)), p); + } + } + } + + char operstate; ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name); if (!ffReadFileData(buffer.chars, 1, &operstate)) { diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 8aad2884e4..f96d58e0bc 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -98,6 +98,7 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(item->inf.description, "inf-desc"), FF_ARG(item->inf.status, "inf-status"), + FF_ARG(item->inf.driver, "inf-driver"), FF_ARG(item->conn.status, "status"), FF_ARG(item->conn.ssid, "ssid"), FF_ARG(item->conn.bssid, "bssid"), @@ -108,6 +109,7 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_ARG(item->conn.security, "security"), FF_ARG(percentBar, "signal-quality-bar"), FF_ARG(item->conn.channel, "channel"), + FF_ARG(item->conn.channelWidth, "channel-width"), FF_ARG(bandStr, "band"), })); } @@ -116,6 +118,7 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); + ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -163,6 +166,7 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu yyjson_mut_val* inf = yyjson_mut_obj_add_obj(doc, obj, "inf"); yyjson_mut_obj_add_strbuf(doc, inf, "description", &wifi->inf.description); yyjson_mut_obj_add_strbuf(doc, inf, "status", &wifi->inf.status); + yyjson_mut_obj_add_strbuf(doc, inf, "driver", &wifi->inf.driver); yyjson_mut_val* conn = yyjson_mut_obj_add_obj(doc, obj, "conn"); yyjson_mut_obj_add_strbuf(doc, conn, "status", &wifi->conn.status); @@ -186,12 +190,14 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu yyjson_mut_obj_add_null(doc, conn, "txRate"); } yyjson_mut_obj_add_uint(doc, conn, "channel", wifi->conn.channel); + yyjson_mut_obj_add_uint(doc, conn, "channelWidth", wifi->conn.channelWidth); yyjson_mut_obj_add_uint(doc, conn, "frequency", wifi->conn.frequency); } FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); + ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -240,6 +246,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { { "Interface description", "inf-desc" }, { "Interface status", "inf-status" }, + { "Interface driver", "inf-driver" }, { "Connection status", "status" }, { "Connection SSID", "ssid" }, { "Connection BSSID", "bssid" }, @@ -250,6 +257,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { { "Connection Security algorithm", "security" }, { "Connection signal quality (percentage bar)", "signal-quality-bar" }, { "Connection channel number", "channel" }, + { "Connection channel width in MHz", "channel-width" }, { "Connection channel band in GHz", "band" }, })), .defaultOrder = 51, From 514efab8ebbc28467d2c8b0b9dd4a6e71b11de4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 18 Aug 2026 16:41:11 +0800 Subject: [PATCH 029/109] Wifi (Windows): adds channel width and device driver detection --- src/common/windows/nt.h | 2 +- src/detection/wifi/wifi_windows.c | 149 +++++++++++++++++++++++++----- 2 files changed, 126 insertions(+), 25 deletions(-) diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index 730a75ba81..4a61b8226a 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -169,7 +169,7 @@ NTSTATUS NTAPI NtQuerySystemEnvironmentValueEx( ); NTSTATUS NTAPI RtlGUIDFromString(IN PCUNICODE_STRING GuidString, OUT GUID* Guid); -NTSTATUS NTAPI RtlStringFromGUIDEx(IN GUID* Guid, OUT PCUNICODE_STRING GuidString, _In_ BOOLEAN AllocateGuidString); +NTSTATUS NTAPI RtlStringFromGUIDEx(IN const GUID* Guid, OUT PUNICODE_STRING GuidString, IN BOOLEAN AllocateGuidString); typedef struct _SYSTEM_SECUREBOOT_INFORMATION { BOOLEAN SecureBootEnabled; diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 8e900ad42a..51adcdc338 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -1,45 +1,118 @@ #include "wifi.h" #include "common/library.h" #include "common/windows/unicode.h" +#include "common/windows/registry.h" #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch" - static void convertIfStateToString(WLAN_INTERFACE_STATE state, FFstrbuf* result) { switch (state) { case wlan_interface_state_not_ready: - ffStrbufAppendS(result, "Not ready"); + ffStrbufSetStatic(result, "Not ready"); break; case wlan_interface_state_connected: - ffStrbufAppendS(result, "Connected"); + ffStrbufSetStatic(result, "Connected"); break; case wlan_interface_state_ad_hoc_network_formed: - ffStrbufAppendS(result, "Ad hoc network formed"); + ffStrbufSetStatic(result, "Ad hoc network formed"); break; case wlan_interface_state_disconnecting: - ffStrbufAppendS(result, "Disconnecting"); + ffStrbufSetStatic(result, "Disconnecting"); break; case wlan_interface_state_disconnected: - ffStrbufAppendS(result, "Disconnected"); + ffStrbufSetStatic(result, "Disconnected"); break; case wlan_interface_state_associating: - ffStrbufAppendS(result, "Associating"); + ffStrbufSetStatic(result, "Associating"); break; case wlan_interface_state_discovering: - ffStrbufAppendS(result, "Discovering"); + ffStrbufSetStatic(result, "Discovering"); break; case wlan_interface_state_authenticating: - ffStrbufAppendS(result, "Authenticating"); + ffStrbufSetStatic(result, "Authenticating"); break; default: - ffStrbufAppendS(result, "Unknown"); + ffStrbufSetStatic(result, "Unknown"); break; } } +typedef struct _WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO { + UCHAR ucLinkID; + ULONG ulChannelCenterFrequencyMhz; + ULONG ulBandwidth; + LONG lRssi; + WLAN_RATE_SET wlanRateSet; +} WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO, *PWLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO; + +typedef struct _WLAN_REALTIME_CONNECTION_QUALITY { + DOT11_PHY_TYPE dot11PhyType; + ULONG ulLinkQuality; + ULONG ulRxRate; + ULONG ulTxRate; + BOOL bIsMLOConnection; + ULONG ulNumLinks; + // Array of size ulNumLinks + WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO linksInfo[]; +} WLAN_REALTIME_CONNECTION_QUALITY, *PWLAN_REALTIME_CONNECTION_QUALITY; + +enum { wlan_intf_opcode_realtime_connection_quality = 19 }; + +#define WIFI_DRIVER_REG_PATH L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +static bool detectWifiDriver(const GUID* interfaceGuid, FFstrbuf* driver) { + char interfaceGuidA[64]; + snprintf(interfaceGuidA, sizeof(interfaceGuidA), + "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + (unsigned) interfaceGuid->Data1, + (unsigned) interfaceGuid->Data2, + (unsigned) interfaceGuid->Data3, + (unsigned) interfaceGuid->Data4[0], (unsigned) interfaceGuid->Data4[1], + (unsigned) interfaceGuid->Data4[2], (unsigned) interfaceGuid->Data4[3], + (unsigned) interfaceGuid->Data4[4], (unsigned) interfaceGuid->Data4[5], + (unsigned) interfaceGuid->Data4[6], (unsigned) interfaceGuid->Data4[7]); + + FF_AUTO_CLOSE_FD HANDLE hClassKey = nullptr; + if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, WIFI_DRIVER_REG_PATH, &hClassKey, nullptr)) { + return false; + } + + wchar_t subKeyW[16]; + + for (uint32_t i = 0;; ++i) { + _snwprintf(subKeyW, ARRAY_SIZE(subKeyW), L"%04u", i); + + FF_AUTO_CLOSE_FD HANDLE hDeviceKey = nullptr; + if (!ffRegOpenSubkeyForRead(hClassKey, subKeyW, &hDeviceKey, nullptr)) { + return false; + } + + FF_STRBUF_AUTO_DESTROY netCfgInstanceId = ffStrbufCreate(); + if (!ffRegReadStrbuf(hDeviceKey, L"NetCfgInstanceId", &netCfgInstanceId, nullptr)) { + continue; + } + + if (!ffStrbufEqualS(&netCfgInstanceId, interfaceGuidA)) { + continue; + } + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (ffRegReadStrbuf(hDeviceKey, L"ProviderName", &buffer, nullptr)) { + ffStrbufSet(driver, &buffer); + } + + if (ffRegReadStrbuf(hDeviceKey, L"DriverVersion", &buffer, nullptr)) { + if (driver->length) { + ffStrbufAppendC(driver, ' '); + } + ffStrbufAppend(driver, &buffer); + } + + return true; + } +} + const char* ffDetectWifi(FFlist* result) { FF_LIBRARY_LOAD_MESSAGE(wlanapi, "wlanapi" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle) @@ -54,7 +127,7 @@ const char* ffDetectWifi(FFlist* result) { WLAN_INTERFACE_INFO_LIST* ifList = nullptr; const char* error = nullptr; - if (ffWlanOpenHandle(2, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) { + if (ffWlanOpenHandle(2 /*maxClientVersion*/, nullptr, &curVersion, &hClient) != ERROR_SUCCESS) { error = "WlanOpenHandle() failed"; goto exit; } @@ -70,6 +143,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitWS(&item->inf.description, ifInfo->strInterfaceDescription); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -79,8 +153,10 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; + detectWifiDriver(&ifInfo->InterfaceGuid, &item->inf.driver); convertIfStateToString(ifInfo->isState, &item->inf.status); if (ifInfo->isState != wlan_interface_state_connected) { @@ -200,17 +276,44 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufAppendS(&item->conn.security, "Insecure"); } - WLAN_BSS_LIST* bssList = nullptr; - if (ffWlanGetNetworkBssList(hClient, + WLAN_REALTIME_CONNECTION_QUALITY* connectionQuality = nullptr; + bufSize = 0; + if (ffWlanQueryInterface(hClient, &ifInfo->InterfaceGuid, - &connInfo->wlanAssociationAttributes.dot11Ssid, - connInfo->wlanAssociationAttributes.dot11BssType, - connInfo->wlanSecurityAttributes.bSecurityEnabled, + wlan_intf_opcode_realtime_connection_quality, nullptr, - &bssList) == ERROR_SUCCESS && - bssList->dwNumberOfItems > 0) { - item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000); - ffWlanFreeMemory(bssList); + &bufSize, + (PVOID*) &connectionQuality, + &opCode) == ERROR_SUCCESS) { + const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* bestLink = nullptr; + for (ULONG linkIndex = 0; linkIndex < connectionQuality->ulNumLinks; ++linkIndex) { + const WLAN_REALTIME_CONNECTION_QUALITY_LINK_INFO* link = &connectionQuality->linksInfo[linkIndex]; + if (!bestLink || link->lRssi > bestLink->lRssi) { + bestLink = link; + } + } + if (bestLink) { + item->conn.channelWidth = (uint16_t) bestLink->ulBandwidth; + item->conn.frequency = (uint16_t) bestLink->ulChannelCenterFrequencyMhz; + } + } + if (connectionQuality) { + ffWlanFreeMemory(connectionQuality); + } + + if (item->conn.frequency == 0) { + WLAN_BSS_LIST* bssList = nullptr; + if (ffWlanGetNetworkBssList(hClient, + &ifInfo->InterfaceGuid, + &connInfo->wlanAssociationAttributes.dot11Ssid, + connInfo->wlanAssociationAttributes.dot11BssType, + connInfo->wlanSecurityAttributes.bSecurityEnabled, + nullptr, + &bssList) == ERROR_SUCCESS && + bssList->dwNumberOfItems > 0) { + item->conn.frequency = (uint16_t) (bssList->wlanBssEntries[0].ulChCenterFrequency / 1000); + ffWlanFreeMemory(bssList); + } } ffWlanFreeMemory(connInfo); @@ -238,5 +341,3 @@ const char* ffDetectWifi(FFlist* result) { } return error; } - -#pragma GCC diagnostic pop From f04a53337de0b92276a45c0483386b3e93da2556 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 15:35:41 +0800 Subject: [PATCH 030/109] Wifi (macOS): adds channel width, accurate channel frequency and device driver detection --- src/detection/wifi/wifi_apple.m | 104 +++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index f718179bd4..d84bd2a81a 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -1,29 +1,32 @@ #include "wifi.h" #include "common/processing.h" #include "common/strutil.h" +#include "common/apple/cf_helpers.h" #import +#import +#import -static inline double rssiToSignalQuality(int rssi) -{ - return (double) (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2); +static inline double rssiToSignalQuality(int rssi) { + return (double) (rssi >= -50 ? 100 : rssi <= -100 ? 0 + : (rssi + 100) * 2); } -@interface CWNetworkProfile() -@property(readonly, retain, nullable) NSArray *bssidList; +@interface CWNetworkProfile () +@property (readonly, retain, nullable) NSArray* bssidList; @end -const char* ffDetectWifi(FFlist* result) -{ +const char* ffDetectWifi(FFlist* result) { NSArray* interfaces = CWWiFiClient.sharedWiFiClient.interfaces; - if (!interfaces) + if (!interfaces) { return "CWWiFiClient.sharedWiFiClient.interfaces is nil"; + } - for (CWInterface* inf in interfaces) - { + for (CWInterface* inf in interfaces) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -33,37 +36,69 @@ @interface CWNetworkProfile() item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; - ffStrbufAppendS(&item->inf.description, inf.interfaceName.UTF8String); + ffStrbufSetS(&item->inf.description, inf.interfaceName.UTF8String); ffStrbufSetStatic(&item->inf.status, inf.powerOn ? "Power On" : "Power Off"); - if(!inf.powerOn) + + FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); + FF_IOOBJECT_AUTO_RELEASE io_object_t parentService = IO_OBJECT_NULL; + while (!IOObjectConformsTo(service, "IOUserNetworkWLAN")) { + if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { + IOObjectRelease(service); + service = parentService; + parentService = IO_OBJECT_NULL; + } else { + IOObjectRelease(service); + service = IO_OBJECT_NULL; + break; + } + } + + if (service != IO_OBJECT_NULL) { + if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { // AppleBCMWLANCore + FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions); // Chipsets other than Broadcom? + if (driverName) { + ffCfStrGetString(driverName, &item->inf.driver); + ffStrbufReplaceAllC(&item->inf.driver, '-', ' '); + } else { + driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions); + ffCfStrGetString(driverName, &item->inf.driver); + } + } + } + + if (!inf.powerOn) { continue; + } ffStrbufSetStatic(&item->conn.status, inf.interfaceMode != kCWInterfaceModeNone ? "Active" : "Inactive"); - if(inf.interfaceMode == kCWInterfaceModeNone) + if (inf.interfaceMode == kCWInterfaceModeNone) { continue; + } FF_STRBUF_AUTO_DESTROY ipconfig = ffStrbufCreate(); CWNetworkProfile* networkProfile = inf.configuration.networkProfiles.firstObject; - if (inf.ssid) // https://developer.apple.com/forums/thread/732431 + if (inf.ssid) { // https://developer.apple.com/forums/thread/732431 ffStrbufAppendS(&item->conn.ssid, inf.ssid.UTF8String); - else if (networkProfile.ssid) + } else if (networkProfile.ssid) { ffStrbufSetStatic(&item->conn.ssid, inf.configuration.networkProfiles.firstObject.ssid.UTF8String); - else + } else { ffStrbufSetStatic(&item->conn.ssid, ""); // https://developer.apple.com/forums/thread/732431 + } - if (inf.bssid) + if (inf.bssid) { ffStrbufAppendS(&item->conn.bssid, inf.bssid.UTF8String); - else if (networkProfile.bssidList) + } else if (networkProfile.bssidList) { ffStrbufSetStatic(&item->conn.bssid, [networkProfile.bssidList.firstObject[@"BSSID"] UTF8String]); - else + } else { ffStrbufSetStatic(&item->conn.bssid, ""); + } - switch(inf.activePHYMode) - { + switch (inf.activePHYMode) { case kCWPHYModeNone: ffStrbufSetStatic(&item->conn.protocol, "none"); break; @@ -89,15 +124,15 @@ @interface CWNetworkProfile() ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)"); break; default: - if (inf.activePHYMode < 8) + if (inf.activePHYMode < 8) { ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode); + } break; } item->conn.signalQuality = rssiToSignalQuality((int) inf.rssiValue); item->conn.txRate = inf.transmitRate; - switch(inf.security) - { + switch (inf.security) { case kCWSecurityNone: ffStrbufSetStatic(&item->conn.security, "Insecure"); break; @@ -152,12 +187,21 @@ @interface CWNetworkProfile() } item->conn.channel = (uint16_t) inf.wlanChannel.channelNumber; - switch (inf.wlanChannel.channelBand) - { - case kCWChannelBand2GHz: item->conn.frequency = 2400; break; - case kCWChannelBand5GHz: item->conn.frequency = 5400; break; - case 3 /*kCWChannelBand6GHz*/: item->conn.frequency = 6400; break; - default: item->conn.frequency = 0; break; + switch (inf.wlanChannel.channelWidth) { + case kCWChannelWidth20MHz: item->conn.channelWidth = 20; break; + case kCWChannelWidth40MHz: item->conn.channelWidth = 40; break; + case kCWChannelWidth80MHz: item->conn.channelWidth = 80; break; + case kCWChannelWidth160MHz: item->conn.channelWidth = 160; break; + default: item->conn.channelWidth = 0; break; + } + if (service != IO_OBJECT_NULL) { + FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions); + if (frequency) { + int64_t value; + if (ffCfNumGetInt64(frequency, &value) == nil) { + item->conn.frequency = (uint16_t) value; + } + } } } From 124bbb06f90d33188e3346a3c1d8cd189c899291 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 18 Aug 2026 23:25:07 +0800 Subject: [PATCH 031/109] Wifi (macOS): fixes compatibility for old Intel MBP --- src/detection/wifi/wifi_apple.m | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index d84bd2a81a..24ed6deba9 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -44,7 +44,9 @@ @interface CWNetworkProfile () FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); FF_IOOBJECT_AUTO_RELEASE io_object_t parentService = IO_OBJECT_NULL; - while (!IOObjectConformsTo(service, "IOUserNetworkWLAN")) { + FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency; + // Note: IO80211ChannelFrequency is only available when the interface is connected + while (!(frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions))) { if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { IOObjectRelease(service); service = parentService; @@ -58,12 +60,11 @@ @interface CWNetworkProfile () if (service != IO_OBJECT_NULL) { if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { // AppleBCMWLANCore - FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions); // Chipsets other than Broadcom? - if (driverName) { + FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = nullptr; // Chipsets other than Broadcom? + if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions)) || (driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("IO80211Family.BuildTag"), nullptr, kNilOptions))) { ffCfStrGetString(driverName, &item->inf.driver); ffStrbufReplaceAllC(&item->inf.driver, '-', ' '); - } else { - driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions); + } else if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions))) { ffCfStrGetString(driverName, &item->inf.driver); } } @@ -194,13 +195,10 @@ @interface CWNetworkProfile () case kCWChannelWidth160MHz: item->conn.channelWidth = 160; break; default: item->conn.channelWidth = 0; break; } - if (service != IO_OBJECT_NULL) { - FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions); - if (frequency) { - int64_t value; - if (ffCfNumGetInt64(frequency, &value) == nil) { - item->conn.frequency = (uint16_t) value; - } + if (frequency) { + int64_t value; + if (ffCfNumGetInt64(frequency, &value) == nil) { + item->conn.frequency = (uint16_t) value; } } } From 54fe4ffece284613903a23400fcef57a6840f6d9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 09:32:27 +0800 Subject: [PATCH 032/109] Wifi (FreeBSD): adds channel width detection --- src/detection/wifi/wifi_bsd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index 7ef816ad5d..ce634637ee 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -27,6 +27,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); @@ -37,6 +38,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; char ssid[IEEE80211_NWID_LEN + 1] = {}; @@ -80,6 +82,16 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channel = curchan.ic_ieee; item->conn.frequency = curchan.ic_freq; + // Determine channel width from channel flags + if (curchan.ic_flags & IEEE80211_CHAN_VHT160) + item->conn.channelWidth = 160; + else if (curchan.ic_flags & IEEE80211_CHAN_VHT80) + item->conn.channelWidth = 80; + else if (curchan.ic_flags & IEEE80211_CHAN_HT40) + item->conn.channelWidth = 40; + else + item->conn.channelWidth = 20; + #ifdef IEEE80211_IS_CHAN_HE // for future use if (IEEE80211_IS_CHAN_HE(&curchan)) { ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); From 6d0d093d62d14e208f7df5918c55b29b549ddf95 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 10:15:30 +0800 Subject: [PATCH 033/109] Wifi (NetBSD): adds channel width detection --- src/detection/wifi/wifi_nbsd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/detection/wifi/wifi_nbsd.c b/src/detection/wifi/wifi_nbsd.c index ea8c2ace76..8265873ef4 100644 --- a/src/detection/wifi/wifi_nbsd.c +++ b/src/detection/wifi/wifi_nbsd.c @@ -38,6 +38,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -47,6 +48,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; char ssid[IEEE80211_NWID_LEN + 1] = {}; @@ -91,6 +93,16 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channel = ffWifiFreqToChannel(curchan.ic_freq); item->conn.frequency = curchan.ic_freq; + // Determine channel width from channel flags + if (curchan.ic_flags & IEEE80211_CHAN_VHT160) + item->conn.channelWidth = 160; + else if (curchan.ic_flags & IEEE80211_CHAN_VHT80) + item->conn.channelWidth = 80; + else if (curchan.ic_flags & IEEE80211_CHAN_HT40) + item->conn.channelWidth = 40; + else + item->conn.channelWidth = 20; + #ifdef IEEE80211_IS_CHAN_HE // for future use if (IEEE80211_IS_CHAN_HE(&curchan)) { ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); From 93566cb73c9d8507d7379fde490d609dd323015a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 10:16:30 +0800 Subject: [PATCH 034/109] Wifi (Android / OpenBSD): inits unsupported properties --- src/detection/wifi/wifi_android.c | 2 ++ src/detection/wifi/wifi_obsd.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c index 4fbc4afb20..12f7ac747a 100644 --- a/src/detection/wifi/wifi_android.c +++ b/src/detection/wifi/wifi_android.c @@ -33,6 +33,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -42,6 +43,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; ffStrbufAppendJsonVal(&item->inf.status, yyjson_obj_get(root, "supplicant_state")); diff --git a/src/detection/wifi/wifi_obsd.c b/src/detection/wifi/wifi_obsd.c index bcaec97fd9..18e46566f6 100644 --- a/src/detection/wifi/wifi_obsd.c +++ b/src/detection/wifi/wifi_obsd.c @@ -28,6 +28,7 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -37,6 +38,7 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; + item->conn.channelWidth = 0; item->conn.frequency = 0; struct ieee80211_nodereq nr = {}; From f0765b1a132a4e6a768f1c2abcf3a24f888f02e0 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 10:34:01 +0800 Subject: [PATCH 035/109] Wifi (SunOS): adds basic Wifi detection impl --- CMakeLists.txt | 2 +- src/detection/wifi/wifi_sunos.c | 210 ++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 src/detection/wifi/wifi_sunos.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 13a6fa83a3..52d42dde04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1235,7 +1235,7 @@ elseif(SunOS) src/detection/uptime/uptime_sunos.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c - src/detection/wifi/wifi_nosupport.c + src/detection/wifi/wifi_sunos.c src/detection/wm/wm_nosupport.c src/detection/de/de_linux.c src/detection/wmtheme/wmtheme_linux.c diff --git a/src/detection/wifi/wifi_sunos.c b/src/detection/wifi/wifi_sunos.c new file mode 100644 index 0000000000..bf0cca369d --- /dev/null +++ b/src/detection/wifi/wifi_sunos.c @@ -0,0 +1,210 @@ +#include "wifi.h" +#include "common/io.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include +#include + +#include + +static bool getWifiParam(int fd, uint32_t id, size_t minLength, wldp_t* buffer) { + memset(buffer, 0, MAX_BUF_LEN); + buffer->wldp_type = NET_802_11; + buffer->wldp_id = id; + + struct strioctl request = { + .ic_cmd = WLAN_GET_PARAM, + .ic_timout = 0, + .ic_len = MAX_BUF_LEN, + .ic_dp = (char*) buffer, + }; + + return ioctl(fd, I_STR, &request) == 0 + && buffer->wldp_result == WL_SUCCESS + && buffer->wldp_length >= WIFI_BUF_OFFSET + minLength + && buffer->wldp_length <= MAX_BUF_LEN; +} + +static bool getWifiValue(int fd, uint32_t id, void* value, size_t valueSize, wldp_t* buffer) { + if (!getWifiParam(fd, id, valueSize, buffer)) { + return false; + } + + memcpy(value, buffer->wldp_buf, valueSize); + return true; +} + +static void initWifiResult(FFWifiResult* item, const char* name) { + ffStrbufInitS(&item->inf.description, name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; +} + +static void setWifiProtocol(FFstrbuf* protocol, uint32_t subtype, bool htEnabled) { + switch (subtype) { + case WL_FHSS: ffStrbufSetStatic(protocol, "802.11 (FHSS)"); break; + case WL_DSSS: ffStrbufSetStatic(protocol, "802.11 (DSSS)"); break; + case WL_IRBASE: ffStrbufSetStatic(protocol, "802.11 (IR)"); break; + case WL_OFDM: ffStrbufSetStatic(protocol, "802.11a"); break; + case WL_HRDS: ffStrbufSetStatic(protocol, "802.11b"); break; + case WL_ERP: ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11g"); break; + default: break; + } +} + +static void setWifiSecurity(FFstrbuf* security, uint32_t encryption, bool haveAuthMode, uint32_t authMode) { + switch (encryption) { + case WL_NOENCRYPTION: + ffStrbufSetStatic(security, "Insecure"); + break; + case WL_ENC_WEP: + ffStrbufSetStatic(security, "WEP"); + break; + case WL_ENC_WPA: + ffStrbufSetStatic(security, haveAuthMode && authMode == WL_SHAREDKEY ? "WPA Shared Key" : "WPA"); + break; + default: + break; + } +} + +const char* ffDetectWifi(FFlist* result) { + FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); + if (!directory) { + return nullptr; + } + + FF_AUTO_FREE void* bufferMemory = malloc(MAX_BUF_LEN); + if (!bufferMemory) { + return "malloc() failed"; + } + wldp_t* buffer = (wldp_t*) bufferMemory; + + struct dirent* entry; + while ((entry = readdir(directory)) != nullptr) { + size_t nameLength = strlen(entry->d_name); + if (nameLength == 0 || entry->d_name[nameLength - 1] < '0' || entry->d_name[nameLength - 1] > '9') { + continue; + } + + char devicePath[PATH_MAX]; + int pathLength = snprintf(devicePath, sizeof(devicePath), "/dev/wifi/%s", entry->d_name); + if (pathLength < 0 || (size_t) pathLength >= sizeof(devicePath)) { + continue; + } + + FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); + if (fd < 0) { + continue; + } + + FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); + initWifiResult(item, entry->d_name); + + wl_vendor_t vendor = {}; + wl_product_t product = {}; + if (getWifiParam(fd, WL_VENDOR_ID, sizeof(vendor), buffer)) { + memcpy(vendor, buffer->wldp_buf, sizeof(vendor)); + vendor[sizeof(vendor) - 1] = '\0'; + } + if (getWifiParam(fd, WL_PRODUCT_ID, sizeof(product), buffer)) { + memcpy(product, buffer->wldp_buf, sizeof(product)); + product[sizeof(product) - 1] = '\0'; + } + if (vendor[0]) { + ffStrbufSetS(&item->inf.driver, vendor); + } + if (product[0]) { + if (item->inf.driver.length) { + ffStrbufAppendC(&item->inf.driver, ' '); + } + ffStrbufAppendS(&item->inf.driver, product); + } + + wl_radio_t radio; + if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { + ffStrbufSetStatic(&item->inf.status, radio ? "Up" : "Down"); + } else { + ffStrbufSetStatic(&item->inf.status, "Unknown"); + } + + wl_linkstatus_t linkStatus; + if (!getWifiValue(fd, WL_LINKSTATUS, &linkStatus, sizeof(linkStatus), buffer)) { + ffStrbufSetStatic(&item->conn.status, "Unknown"); + continue; + } + if (linkStatus != WL_CONNECTED) { + ffStrbufSetStatic(&item->conn.status, "Not connected"); + continue; + } + ffStrbufSetStatic(&item->conn.status, "Connected"); + + wl_essid_t essid; + if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) + && essid.wl_essid_length < sizeof(essid.wl_essid_essid) + && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { + ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); + } + + wl_bssid_t bssid; + if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { + ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + + wl_rssi_t rssi; + if (getWifiValue(fd, WL_RSSI, &rssi, sizeof(rssi), buffer)) { + item->conn.signalQuality = rssi >= MAX_RSSI ? 100.0 : ((double) rssi / MAX_RSSI) * 100.0; + } + + wl_phy_conf_t phy; + if (getWifiValue(fd, WL_PHY_CONFIG, &phy, sizeof(phy), buffer)) { + uint32_t subtype = phy.wl_phy_dsss_conf.wl_dsss_subtype; + switch (subtype) { + case WL_FHSS: + item->conn.channel = (uint16_t) phy.wl_phy_fhss_conf.wl_fhss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_DSSS: + item->conn.channel = (uint16_t) phy.wl_phy_dsss_conf.wl_dsss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_OFDM: + item->conn.frequency = (uint16_t) phy.wl_phy_ofdm_conf.wl_ofdm_frequency; + item->conn.channel = ffWifiFreqToChannel(item->conn.frequency); + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_ofdm_conf.wl_ofdm_ht_enabled); + break; + case WL_ERP: + item->conn.channel = (uint16_t) phy.wl_phy_erp_conf.wl_erp_channel; + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_erp_conf.wl_erp_ht_enabled); + break; + default: + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + } + } + + wl_encryption_t encryption; + wl_authmode_t authMode; + bool haveEncryption = getWifiValue(fd, WL_ENCRYPTION, &encryption, sizeof(encryption), buffer); + bool haveAuthMode = getWifiValue(fd, WL_AUTH_MODE, &authMode, sizeof(authMode), buffer); + if (haveEncryption) { + setWifiSecurity(&item->conn.security, encryption, haveAuthMode, authMode); + } + } + + return nullptr; +} From db8ee8159d775f750661e67d25c7d2ad9016a879 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 11:05:35 +0800 Subject: [PATCH 036/109] Wifi (Haiku): adds basic Wifi detection impl --- CMakeLists.txt | 2 +- src/detection/wifi/wifi_haiku.cpp | 102 ++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 src/detection/wifi/wifi_haiku.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 52d42dde04..9f6b0629fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1305,7 +1305,7 @@ elseif(Haiku) src/detection/uptime/uptime_haiku.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_haiku.cpp - src/detection/wifi/wifi_nosupport.c + src/detection/wifi/wifi_haiku.cpp src/detection/wm/wm_nosupport.c src/detection/de/de_nosupport.c src/detection/wmtheme/wmtheme_haiku.cpp diff --git a/src/detection/wifi/wifi_haiku.cpp b/src/detection/wifi/wifi_haiku.cpp new file mode 100644 index 0000000000..c5669caa56 --- /dev/null +++ b/src/detection/wifi/wifi_haiku.cpp @@ -0,0 +1,102 @@ +extern "C" { + #include "wifi.h" +} + +#include +#include +#include + +static void initWifiResult(FFWifiResult* item, const char* name) { + ffStrbufInitS(&item->inf.description, name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->inf.driver); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; +} + +static void setWifiSecurity(FFstrbuf* security, const wireless_network& network) { + switch (network.authentication_mode) { + case B_NETWORK_AUTHENTICATION_NONE: + if (network.flags & B_NETWORK_IS_ENCRYPTED) { + ffStrbufSetStatic(security, "Encrypted"); + } else { + ffStrbufSetStatic(security, "Insecure"); + } + break; + case B_NETWORK_AUTHENTICATION_WEP: + ffStrbufSetStatic(security, "WEP"); + break; + case B_NETWORK_AUTHENTICATION_WPA: + ffStrbufSetStatic(security, "WPA"); + break; + case B_NETWORK_AUTHENTICATION_WPA2: + ffStrbufSetStatic(security, "WPA2"); + break; + case B_NETWORK_AUTHENTICATION_EAP: + ffStrbufSetStatic(security, "WPA Enterprise"); + break; + default: + ffStrbufSetF(security, "Unknown (%lu)", (unsigned long) network.authentication_mode); + break; + } +} + +static void setWifiBssid(FFstrbuf* bssid, const wireless_network& network) { + const uint8* address = network.address.LinkLevelAddress(); + if (address == nullptr || network.address.LinkLevelAddressLength() < 6) { + return; + } + + ffStrbufSetF(bssid, "%02X:%02X:%02X:%02X:%02X:%02X", + address[0], address[1], address[2], address[3], address[4], address[5]); +} + +const char* ffDetectWifi(FFlist* result) { + BNetworkRoster& roster = BNetworkRoster::Default(); + BNetworkInterface interface; + uint32 cookie = 0; + + while (roster.GetNextInterface(&cookie, interface) == B_OK) { + if (!interface.Exists()) { + continue; + } + + BNetworkDevice device(interface.Name()); + if (!device.Exists() || !device.IsWireless()) { + continue; + } + + FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); + initWifiResult(item, interface.Name()); + + ffStrbufSetStatic(&item->inf.status, interface.HasLink() ? "Up" : "Down"); + if (!interface.HasLink() || !device.HasLink()) { + ffStrbufSetStatic(&item->conn.status, "Not connected"); + continue; + } + + ffStrbufSetStatic(&item->conn.status, "Connected"); + + uint32 networkCookie = 0; + wireless_network network = {}; + if (device.GetNextAssociatedNetwork(networkCookie, network) != B_OK) { + continue; + } + + ffStrbufSetNS(&item->conn.ssid, strnlen(network.name, sizeof(network.name)), network.name); + setWifiBssid(&item->conn.bssid, network); + item->conn.signalQuality = network.signal_strength > 100 ? 100 : network.signal_strength; + setWifiSecurity(&item->conn.security, network); + } + + return nullptr; +} From cafe82b462ad13aff25a7b19f82c6f1ac56f838e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 13:24:05 +0800 Subject: [PATCH 037/109] Battery (SunOS): adds basic detection impl --- CMakeLists.txt | 2 +- src/detection/battery/battery_sunos.c | 113 ++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/detection/battery/battery_sunos.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f6b0629fa..9d4070af95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1169,7 +1169,7 @@ elseif(SunOS) src/common/impl/FFPlatform_unix.c src/common/impl/binary_linux.c src/common/impl/kmod_sunos.c - src/detection/battery/battery_nosupport.c + src/detection/battery/battery_sunos.c src/detection/bios/bios_windows.c src/detection/board/board_windows.c src/detection/bootmgr/bootmgr_nosupport.c diff --git a/src/detection/battery/battery_sunos.c b/src/detection/battery/battery_sunos.c new file mode 100644 index 0000000000..e31b7bb9f4 --- /dev/null +++ b/src/detection/battery/battery_sunos.c @@ -0,0 +1,113 @@ +#include "battery.h" + +#include + +static inline void kstatFreeWrap(kstat_ctl_t** pkc) { + assert(pkc); + if (*pkc) { + kstat_close(*pkc); + } +} + +static bool getUint32(kstat_t* ksp, const char* name, uint32_t* value) { + kstat_named_t* stat = kstat_data_lookup(ksp, name); + if (!stat) { + return false; + } + + switch (stat->data_type) { + case KSTAT_DATA_UINT32: + *value = stat->value.ui32; + return true; + case KSTAT_DATA_INT32: + if (stat->value.i32 >= 0) { + *value = (uint32_t) stat->value.i32; + return true; + } + break; +#ifdef _INT64_TYPE + case KSTAT_DATA_UINT64: + if (stat->value.ui64 <= UINT32_MAX) { + *value = (uint32_t) stat->value.ui64; + return true; + } + break; + case KSTAT_DATA_INT64: + if (stat->value.i64 >= 0 && (uint64_t) stat->value.i64 <= UINT32_MAX) { + *value = (uint32_t) stat->value.i64; + return true; + } + break; +#endif + default: + break; + } + + return false; +} + +const char* ffDetectBattery([[maybe_unused]] FFBatteryOptions* options, FFlist* results) { + // https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/powertop/common/battery.c + [[gnu::cleanup(kstatFreeWrap)]] kstat_ctl_t* kc = kstat_open(); + if (!kc) { + return "kstat_open() failed"; + } + + // illumos exposes battery information through either of these modules. + const char* modules[] = { "battery", "acpi_drv" }; + kstat_t* bif = nullptr; + kstat_t* bst = nullptr; + for (size_t i = 0; i < ARRAY_SIZE(modules); ++i) { + bif = kstat_lookup(kc, modules[i], 0, "battery BIF0"); + bst = kstat_lookup(kc, modules[i], 0, "battery BST0"); + if (bif && bst) { + break; + } + bif = nullptr; + bst = nullptr; + } + + if (!bif || !bst || kstat_read(kc, bif, nullptr) < 0 || kstat_read(kc, bst, nullptr) < 0) { + return nullptr; + } + + uint32_t lastCapacity, remainingCapacity, rate, state; + if (!getUint32(bif, "bif_last_cap", &lastCapacity) || + !getUint32(bst, "bst_rem_cap", &remainingCapacity) || + !getUint32(bst, "bst_state", &state)) { + return "kstat_data_lookup() failed"; + } + + if (lastCapacity == 0 || remainingCapacity == UINT32_MAX) { + return nullptr; + } + + FFBatteryResult* battery = FF_LIST_ADD(FFBatteryResult, *results); + ffStrbufInit(&battery->manufacturer); + ffStrbufInit(&battery->manufactureDate); + ffStrbufInit(&battery->modelName); + ffStrbufInit(&battery->technology); + ffStrbufInit(&battery->serial); + battery->status = FF_BATTERY_STATUS_NONE; + battery->capacity = (double) remainingCapacity * 100.0 / (double) lastCapacity; + battery->temperature = FF_BATTERY_TEMP_UNSET; + battery->cycleCount = 0; + battery->timeRemaining = -1; + + // illumos BST state: bit 0 discharging, bit 1 charging, bit 2 critical. + if (state & (1u << 0)) { + battery->status |= FF_BATTERY_STATUS_DISCHARGING; + } + if (state & (1u << 1)) { + battery->status |= FF_BATTERY_STATUS_CHARGING; + } + if (state & (1u << 2)) { + battery->status |= FF_BATTERY_STATUS_CRITICAL; + } + + if ((state & (1u << 0)) && getUint32(bst, "bst_rate", &rate) && rate > 0 && rate != UINT32_MAX) { + battery->timeRemaining = (int32_t) (((uint64_t) remainingCapacity * 3600) / rate); + } + + return nullptr; +} From 2a269bfd4c1807f51df7c193f61ce95d37249060 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 19 Aug 2026 16:10:11 +0800 Subject: [PATCH 038/109] Wifi: removes driver detection support --- src/detection/wifi/wifi.h | 1 - src/detection/wifi/wifi_android.c | 1 - src/detection/wifi/wifi_apple.m | 44 ++-- src/detection/wifi/wifi_bsd.c | 1 - src/detection/wifi/wifi_haiku.cpp | 3 +- src/detection/wifi/wifi_linux.c | 15 -- src/detection/wifi/wifi_nbsd.c | 1 - src/detection/wifi/wifi_obsd.c | 1 - src/detection/wifi/wifi_sunos.c | 352 ++++++++++++++---------------- src/detection/wifi/wifi_windows.c | 57 ----- src/modules/wifi/wifi.c | 5 - 11 files changed, 184 insertions(+), 297 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index 7ad22855d4..a7ea62d489 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -6,7 +6,6 @@ struct FFWifiInterface { FFstrbuf description; FFstrbuf status; - FFstrbuf driver; }; struct FFWifiConnection { diff --git a/src/detection/wifi/wifi_android.c b/src/detection/wifi/wifi_android.c index 12f7ac747a..0fd5b3a9d5 100644 --- a/src/detection/wifi/wifi_android.c +++ b/src/detection/wifi/wifi_android.c @@ -33,7 +33,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 24ed6deba9..3807ef0e8a 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -26,7 +26,6 @@ @interface CWNetworkProfile () FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInit(&item->inf.description); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -42,34 +41,6 @@ @interface CWNetworkProfile () ffStrbufSetS(&item->inf.description, inf.interfaceName.UTF8String); ffStrbufSetStatic(&item->inf.status, inf.powerOn ? "Power On" : "Power Off"); - FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); - FF_IOOBJECT_AUTO_RELEASE io_object_t parentService = IO_OBJECT_NULL; - FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency; - // Note: IO80211ChannelFrequency is only available when the interface is connected - while (!(frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions))) { - if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { - IOObjectRelease(service); - service = parentService; - parentService = IO_OBJECT_NULL; - } else { - IOObjectRelease(service); - service = IO_OBJECT_NULL; - break; - } - } - - if (service != IO_OBJECT_NULL) { - if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { // AppleBCMWLANCore - FF_CFTYPE_AUTO_RELEASE CFStringRef driverName = nullptr; // Chipsets other than Broadcom? - if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("AppleBCMWLAN.BuildTag"), nullptr, kNilOptions)) || (driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("IO80211Family.BuildTag"), nullptr, kNilOptions))) { - ffCfStrGetString(driverName, &item->inf.driver); - ffStrbufReplaceAllC(&item->inf.driver, '-', ' '); - } else if ((driverName = IORegistryEntryCreateCFProperty(parentService, CFSTR("CFBundleIdentifier"), nullptr, kNilOptions))) { - ffCfStrGetString(driverName, &item->inf.driver); - } - } - } - if (!inf.powerOn) { continue; } @@ -195,6 +166,21 @@ @interface CWNetworkProfile () case kCWChannelWidth160MHz: item->conn.channelWidth = 160; break; default: item->conn.channelWidth = 0; break; } + + FF_IOOBJECT_AUTO_RELEASE io_object_t service = IOServiceGetMatchingService(MACH_PORT_NULL, IOBSDNameMatching(MACH_PORT_NULL, 0, item->inf.description.chars)); + FF_CFTYPE_AUTO_RELEASE CFNumberRef frequency; + // Note: IO80211ChannelFrequency is only available when the interface is connected + while (!(frequency = IORegistryEntryCreateCFProperty(service, CFSTR("IO80211ChannelFrequency"), nullptr, kNilOptions))) { + io_object_t parentService = IO_OBJECT_NULL; + if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService) == KERN_SUCCESS) { + IOObjectRelease(service); + service = parentService; + } else { + IOObjectRelease(service); + service = IO_OBJECT_NULL; + break; + } + } if (frequency) { int64_t value; if (ffCfNumGetInt64(frequency, &value) == nil) { diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index ce634637ee..4b55d0257a 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -27,7 +27,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->inf.status); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); diff --git a/src/detection/wifi/wifi_haiku.cpp b/src/detection/wifi/wifi_haiku.cpp index c5669caa56..309cfcd5a1 100644 --- a/src/detection/wifi/wifi_haiku.cpp +++ b/src/detection/wifi/wifi_haiku.cpp @@ -9,7 +9,6 @@ extern "C" { static void initWifiResult(FFWifiResult* item, const char* name) { ffStrbufInitS(&item->inf.description, name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -92,7 +91,7 @@ const char* ffDetectWifi(FFlist* result) { continue; } - ffStrbufSetNS(&item->conn.ssid, strnlen(network.name, sizeof(network.name)), network.name); + ffStrbufSetNS(&item->conn.ssid, (uint32_t) strnlen(network.name, sizeof(network.name)), network.name); setWifiBssid(&item->conn.bssid, network); item->conn.signalQuality = network.signal_strength > 100 ? 100 : network.signal_strength; setWifiSecurity(&item->conn.security, network); diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 1fe21b0c46..87e8e73788 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1067,7 +1067,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -1080,20 +1079,6 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channelWidth = 0; item->conn.frequency = 0; - { - ffStrbufSetF(&buffer, "/sys/class/net/%s/device/driver", i->if_name); - char pathBuf[PATH_MAX]; - ssize_t resultLength = readlink(buffer.chars, pathBuf, ARRAY_SIZE(pathBuf)); - if (resultLength > 0) { - const char* p = memrchr(pathBuf, '/', (size_t) resultLength); - if (p) { - ++p; - ffStrbufSetNS(&item->inf.driver, (uint32_t) (resultLength - (p - pathBuf)), p); - } - } - } - - char operstate; ffStrbufSetF(&buffer, "/sys/class/net/%s/operstate", i->if_name); if (!ffReadFileData(buffer.chars, 1, &operstate)) { diff --git a/src/detection/wifi/wifi_nbsd.c b/src/detection/wifi/wifi_nbsd.c index 8265873ef4..e2b0836790 100644 --- a/src/detection/wifi/wifi_nbsd.c +++ b/src/detection/wifi/wifi_nbsd.c @@ -38,7 +38,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); diff --git a/src/detection/wifi/wifi_obsd.c b/src/detection/wifi/wifi_obsd.c index 18e46566f6..6def7b63bc 100644 --- a/src/detection/wifi/wifi_obsd.c +++ b/src/detection/wifi/wifi_obsd.c @@ -28,7 +28,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitS(&item->inf.description, i->if_name); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); diff --git a/src/detection/wifi/wifi_sunos.c b/src/detection/wifi/wifi_sunos.c index bf0cca369d..ad58f19222 100644 --- a/src/detection/wifi/wifi_sunos.c +++ b/src/detection/wifi/wifi_sunos.c @@ -10,201 +10,185 @@ #include -static bool getWifiParam(int fd, uint32_t id, size_t minLength, wldp_t* buffer) { - memset(buffer, 0, MAX_BUF_LEN); - buffer->wldp_type = NET_802_11; - buffer->wldp_id = id; - - struct strioctl request = { - .ic_cmd = WLAN_GET_PARAM, - .ic_timout = 0, - .ic_len = MAX_BUF_LEN, - .ic_dp = (char*) buffer, - }; - - return ioctl(fd, I_STR, &request) == 0 - && buffer->wldp_result == WL_SUCCESS - && buffer->wldp_length >= WIFI_BUF_OFFSET + minLength - && buffer->wldp_length <= MAX_BUF_LEN; -} - static bool getWifiValue(int fd, uint32_t id, void* value, size_t valueSize, wldp_t* buffer) { - if (!getWifiParam(fd, id, valueSize, buffer)) { - return false; - } - - memcpy(value, buffer->wldp_buf, valueSize); - return true; + memset(buffer, 0, MAX_BUF_LEN); + buffer->wldp_type = NET_802_11; + buffer->wldp_id = id; + + struct strioctl request = { + .ic_cmd = WLAN_GET_PARAM, + .ic_timout = 0, + .ic_len = MAX_BUF_LEN, + .ic_dp = (char*) buffer, + }; + + if (ioctl(fd, I_STR, &request) != 0 || buffer->wldp_result != WL_SUCCESS || buffer->wldp_length < WIFI_BUF_OFFSET + valueSize || buffer->wldp_length > MAX_BUF_LEN) { + return false; + } + + memcpy(value, buffer->wldp_buf, valueSize); + return true; } static void initWifiResult(FFWifiResult* item, const char* name) { - ffStrbufInitS(&item->inf.description, name); - ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); - ffStrbufInit(&item->conn.status); - ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.bssid); - ffStrbufInit(&item->conn.protocol); - ffStrbufInit(&item->conn.security); - item->conn.signalQuality = -DBL_MAX; - item->conn.rxRate = -DBL_MAX; - item->conn.txRate = -DBL_MAX; - item->conn.channel = 0; - item->conn.channelWidth = 0; - item->conn.frequency = 0; + ffStrbufInitS(&item->inf.description, name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; } static void setWifiProtocol(FFstrbuf* protocol, uint32_t subtype, bool htEnabled) { - switch (subtype) { - case WL_FHSS: ffStrbufSetStatic(protocol, "802.11 (FHSS)"); break; - case WL_DSSS: ffStrbufSetStatic(protocol, "802.11 (DSSS)"); break; - case WL_IRBASE: ffStrbufSetStatic(protocol, "802.11 (IR)"); break; - case WL_OFDM: ffStrbufSetStatic(protocol, "802.11a"); break; - case WL_HRDS: ffStrbufSetStatic(protocol, "802.11b"); break; - case WL_ERP: ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11g"); break; - default: break; - } + switch (subtype) { + case WL_FHSS: + ffStrbufSetStatic(protocol, "802.11 (FHSS)"); + break; + case WL_DSSS: + ffStrbufSetStatic(protocol, "802.11 (DSSS)"); + break; + case WL_IRBASE: + ffStrbufSetStatic(protocol, "802.11 (IR)"); + break; + case WL_OFDM: + ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11a"); + break; + case WL_HRDS: + ffStrbufSetStatic(protocol, "802.11b"); + break; + case WL_ERP: + ffStrbufSetStatic(protocol, htEnabled ? "802.11n (Wi-Fi 4)" : "802.11g"); + break; + default: + break; + } } static void setWifiSecurity(FFstrbuf* security, uint32_t encryption, bool haveAuthMode, uint32_t authMode) { - switch (encryption) { - case WL_NOENCRYPTION: - ffStrbufSetStatic(security, "Insecure"); - break; - case WL_ENC_WEP: - ffStrbufSetStatic(security, "WEP"); - break; - case WL_ENC_WPA: - ffStrbufSetStatic(security, haveAuthMode && authMode == WL_SHAREDKEY ? "WPA Shared Key" : "WPA"); - break; - default: - break; - } + switch (encryption) { + case WL_NOENCRYPTION: + ffStrbufSetStatic(security, "Insecure"); + break; + case WL_ENC_WEP: + ffStrbufSetStatic(security, "WEP"); + break; + case WL_ENC_WPA: + ffStrbufSetStatic(security, haveAuthMode && authMode == WL_SHAREDKEY ? "WPA Shared Key" : "WPA"); + break; + default: + ffStrbufSetStatic(security, "Unknown"); + break; + } } const char* ffDetectWifi(FFlist* result) { - FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); - if (!directory) { - return nullptr; - } - - FF_AUTO_FREE void* bufferMemory = malloc(MAX_BUF_LEN); - if (!bufferMemory) { - return "malloc() failed"; - } - wldp_t* buffer = (wldp_t*) bufferMemory; - - struct dirent* entry; - while ((entry = readdir(directory)) != nullptr) { - size_t nameLength = strlen(entry->d_name); - if (nameLength == 0 || entry->d_name[nameLength - 1] < '0' || entry->d_name[nameLength - 1] > '9') { - continue; - } - - char devicePath[PATH_MAX]; - int pathLength = snprintf(devicePath, sizeof(devicePath), "/dev/wifi/%s", entry->d_name); - if (pathLength < 0 || (size_t) pathLength >= sizeof(devicePath)) { - continue; - } - - FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); - if (fd < 0) { - continue; - } - - FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); - initWifiResult(item, entry->d_name); - - wl_vendor_t vendor = {}; - wl_product_t product = {}; - if (getWifiParam(fd, WL_VENDOR_ID, sizeof(vendor), buffer)) { - memcpy(vendor, buffer->wldp_buf, sizeof(vendor)); - vendor[sizeof(vendor) - 1] = '\0'; - } - if (getWifiParam(fd, WL_PRODUCT_ID, sizeof(product), buffer)) { - memcpy(product, buffer->wldp_buf, sizeof(product)); - product[sizeof(product) - 1] = '\0'; - } - if (vendor[0]) { - ffStrbufSetS(&item->inf.driver, vendor); - } - if (product[0]) { - if (item->inf.driver.length) { - ffStrbufAppendC(&item->inf.driver, ' '); - } - ffStrbufAppendS(&item->inf.driver, product); - } - - wl_radio_t radio; - if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { - ffStrbufSetStatic(&item->inf.status, radio ? "Up" : "Down"); - } else { - ffStrbufSetStatic(&item->inf.status, "Unknown"); - } - - wl_linkstatus_t linkStatus; - if (!getWifiValue(fd, WL_LINKSTATUS, &linkStatus, sizeof(linkStatus), buffer)) { - ffStrbufSetStatic(&item->conn.status, "Unknown"); - continue; - } - if (linkStatus != WL_CONNECTED) { - ffStrbufSetStatic(&item->conn.status, "Not connected"); - continue; - } - ffStrbufSetStatic(&item->conn.status, "Connected"); - - wl_essid_t essid; - if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) - && essid.wl_essid_length < sizeof(essid.wl_essid_essid) - && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { - ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); - } - - wl_bssid_t bssid; - if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { - ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); - } - - wl_rssi_t rssi; - if (getWifiValue(fd, WL_RSSI, &rssi, sizeof(rssi), buffer)) { - item->conn.signalQuality = rssi >= MAX_RSSI ? 100.0 : ((double) rssi / MAX_RSSI) * 100.0; - } - - wl_phy_conf_t phy; - if (getWifiValue(fd, WL_PHY_CONFIG, &phy, sizeof(phy), buffer)) { - uint32_t subtype = phy.wl_phy_dsss_conf.wl_dsss_subtype; - switch (subtype) { - case WL_FHSS: - item->conn.channel = (uint16_t) phy.wl_phy_fhss_conf.wl_fhss_channel; - setWifiProtocol(&item->conn.protocol, subtype, false); - break; - case WL_DSSS: - item->conn.channel = (uint16_t) phy.wl_phy_dsss_conf.wl_dsss_channel; - setWifiProtocol(&item->conn.protocol, subtype, false); - break; - case WL_OFDM: - item->conn.frequency = (uint16_t) phy.wl_phy_ofdm_conf.wl_ofdm_frequency; - item->conn.channel = ffWifiFreqToChannel(item->conn.frequency); - setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_ofdm_conf.wl_ofdm_ht_enabled); - break; - case WL_ERP: - item->conn.channel = (uint16_t) phy.wl_phy_erp_conf.wl_erp_channel; - setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_erp_conf.wl_erp_ht_enabled); - break; - default: - setWifiProtocol(&item->conn.protocol, subtype, false); - break; - } - } - - wl_encryption_t encryption; - wl_authmode_t authMode; - bool haveEncryption = getWifiValue(fd, WL_ENCRYPTION, &encryption, sizeof(encryption), buffer); - bool haveAuthMode = getWifiValue(fd, WL_AUTH_MODE, &authMode, sizeof(authMode), buffer); - if (haveEncryption) { - setWifiSecurity(&item->conn.security, encryption, haveAuthMode, authMode); - } - } - - return nullptr; + FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); + if (!directory) { + return nullptr; + } + + FF_AUTO_FREE void* bufferMemory = malloc(MAX_BUF_LEN); + if (!bufferMemory) { + return "malloc() failed"; + } + wldp_t* buffer = (wldp_t*) bufferMemory; + + struct dirent* entry; + while ((entry = readdir(directory)) != nullptr) { + size_t nameLength = strlen(entry->d_name); + if (nameLength == 0 || entry->d_name[nameLength - 1] < '0' || entry->d_name[nameLength - 1] > '9') { + continue; + } + + char devicePath[PATH_MAX]; + int pathLength = snprintf(devicePath, sizeof(devicePath), "/dev/wifi/%s", entry->d_name); + if (pathLength < 0 || (size_t) pathLength >= sizeof(devicePath)) { + continue; + } + + FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); + if (fd < 0) { + continue; + } + + FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); + initWifiResult(item, entry->d_name); + + wl_radio_t radio; + if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { + ffStrbufSetStatic(&item->inf.status, radio ? "Up" : "Down"); + } else { + ffStrbufSetStatic(&item->inf.status, "Unknown"); + } + + wl_linkstatus_t linkStatus; + if (!getWifiValue(fd, WL_LINKSTATUS, &linkStatus, sizeof(linkStatus), buffer)) { + ffStrbufSetStatic(&item->conn.status, "Unknown"); + continue; + } + if (linkStatus != WL_CONNECTED) { + ffStrbufSetStatic(&item->conn.status, "Not connected"); + continue; + } + ffStrbufSetStatic(&item->conn.status, "Connected"); + + wl_essid_t essid; + if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) && essid.wl_essid_length < sizeof(essid.wl_essid_essid) && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { + ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); + } + + wl_bssid_t bssid; + if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { + ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + } + + wl_rssi_t rssi; + if (getWifiValue(fd, WL_RSSI, &rssi, sizeof(rssi), buffer)) { + item->conn.signalQuality = rssi >= MAX_RSSI ? 100.0 : ((double) rssi / MAX_RSSI) * 100.0; + } + + wl_phy_conf_t phy; + if (getWifiValue(fd, WL_PHY_CONFIG, &phy, sizeof(phy), buffer)) { + uint32_t subtype = phy.wl_phy_dsss_conf.wl_dsss_subtype; + switch (subtype) { + case WL_FHSS: + item->conn.channel = (uint16_t) phy.wl_phy_fhss_conf.wl_fhss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_DSSS: + item->conn.channel = (uint16_t) phy.wl_phy_dsss_conf.wl_dsss_channel; + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + case WL_OFDM: + item->conn.frequency = (uint16_t) phy.wl_phy_ofdm_conf.wl_ofdm_frequency; + item->conn.channel = ffWifiFreqToChannel(item->conn.frequency); + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_ofdm_conf.wl_ofdm_ht_enabled); + break; + case WL_ERP: + item->conn.channel = (uint16_t) phy.wl_phy_erp_conf.wl_erp_channel; + setWifiProtocol(&item->conn.protocol, subtype, phy.wl_phy_erp_conf.wl_erp_ht_enabled); + break; + default: + setWifiProtocol(&item->conn.protocol, subtype, false); + break; + } + } + + wl_encryption_t encryption; + wl_authmode_t authMode; + bool haveEncryption = getWifiValue(fd, WL_ENCRYPTION, &encryption, sizeof(encryption), buffer); + bool haveAuthMode = getWifiValue(fd, WL_AUTH_MODE, &authMode, sizeof(authMode), buffer); + if (haveEncryption) { + setWifiSecurity(&item->conn.security, encryption, haveAuthMode, authMode); + } + } + + return nullptr; } diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 51adcdc338..8382954840 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -1,7 +1,6 @@ #include "wifi.h" #include "common/library.h" #include "common/windows/unicode.h" -#include "common/windows/registry.h" #include #include @@ -59,60 +58,6 @@ typedef struct _WLAN_REALTIME_CONNECTION_QUALITY { enum { wlan_intf_opcode_realtime_connection_quality = 19 }; -#define WIFI_DRIVER_REG_PATH L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" - -static bool detectWifiDriver(const GUID* interfaceGuid, FFstrbuf* driver) { - char interfaceGuidA[64]; - snprintf(interfaceGuidA, sizeof(interfaceGuidA), - "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", - (unsigned) interfaceGuid->Data1, - (unsigned) interfaceGuid->Data2, - (unsigned) interfaceGuid->Data3, - (unsigned) interfaceGuid->Data4[0], (unsigned) interfaceGuid->Data4[1], - (unsigned) interfaceGuid->Data4[2], (unsigned) interfaceGuid->Data4[3], - (unsigned) interfaceGuid->Data4[4], (unsigned) interfaceGuid->Data4[5], - (unsigned) interfaceGuid->Data4[6], (unsigned) interfaceGuid->Data4[7]); - - FF_AUTO_CLOSE_FD HANDLE hClassKey = nullptr; - if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, WIFI_DRIVER_REG_PATH, &hClassKey, nullptr)) { - return false; - } - - wchar_t subKeyW[16]; - - for (uint32_t i = 0;; ++i) { - _snwprintf(subKeyW, ARRAY_SIZE(subKeyW), L"%04u", i); - - FF_AUTO_CLOSE_FD HANDLE hDeviceKey = nullptr; - if (!ffRegOpenSubkeyForRead(hClassKey, subKeyW, &hDeviceKey, nullptr)) { - return false; - } - - FF_STRBUF_AUTO_DESTROY netCfgInstanceId = ffStrbufCreate(); - if (!ffRegReadStrbuf(hDeviceKey, L"NetCfgInstanceId", &netCfgInstanceId, nullptr)) { - continue; - } - - if (!ffStrbufEqualS(&netCfgInstanceId, interfaceGuidA)) { - continue; - } - - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - if (ffRegReadStrbuf(hDeviceKey, L"ProviderName", &buffer, nullptr)) { - ffStrbufSet(driver, &buffer); - } - - if (ffRegReadStrbuf(hDeviceKey, L"DriverVersion", &buffer, nullptr)) { - if (driver->length) { - ffStrbufAppendC(driver, ' '); - } - ffStrbufAppend(driver, &buffer); - } - - return true; - } -} - const char* ffDetectWifi(FFlist* result) { FF_LIBRARY_LOAD_MESSAGE(wlanapi, "wlanapi" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(wlanapi, WlanOpenHandle) @@ -143,7 +88,6 @@ const char* ffDetectWifi(FFlist* result) { FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); ffStrbufInitWS(&item->inf.description, ifInfo->strInterfaceDescription); ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->inf.driver); ffStrbufInit(&item->conn.status); ffStrbufInit(&item->conn.ssid); ffStrbufInit(&item->conn.bssid); @@ -156,7 +100,6 @@ const char* ffDetectWifi(FFlist* result) { item->conn.channelWidth = 0; item->conn.frequency = 0; - detectWifiDriver(&ifInfo->InterfaceGuid, &item->inf.driver); convertIfStateToString(ifInfo->isState, &item->inf.status); if (ifInfo->isState != wlan_interface_state_connected) { diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index f96d58e0bc..a9462418d4 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -98,7 +98,6 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Wifi), moduleIndex, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(item->inf.description, "inf-desc"), FF_ARG(item->inf.status, "inf-status"), - FF_ARG(item->inf.driver, "inf-driver"), FF_ARG(item->conn.status, "status"), FF_ARG(item->conn.ssid, "ssid"), FF_ARG(item->conn.bssid, "bssid"), @@ -118,7 +117,6 @@ bool ffPrintWifi(FFWifiOptions* options) { FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); - ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -166,7 +164,6 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu yyjson_mut_val* inf = yyjson_mut_obj_add_obj(doc, obj, "inf"); yyjson_mut_obj_add_strbuf(doc, inf, "description", &wifi->inf.description); yyjson_mut_obj_add_strbuf(doc, inf, "status", &wifi->inf.status); - yyjson_mut_obj_add_strbuf(doc, inf, "driver", &wifi->inf.driver); yyjson_mut_val* conn = yyjson_mut_obj_add_obj(doc, obj, "conn"); yyjson_mut_obj_add_strbuf(doc, conn, "status", &wifi->conn.status); @@ -197,7 +194,6 @@ bool ffGenerateWifiJsonResult([[maybe_unused]] FFWifiOptions* options, yyjson_mu FF_LIST_FOR_EACH (FFWifiResult, item, result) { ffStrbufDestroy(&item->inf.description); ffStrbufDestroy(&item->inf.status); - ffStrbufDestroy(&item->inf.driver); ffStrbufDestroy(&item->conn.status); ffStrbufDestroy(&item->conn.ssid); ffStrbufDestroy(&item->conn.bssid); @@ -246,7 +242,6 @@ FFModuleBaseInfo ffWifiModuleInfo = { .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { { "Interface description", "inf-desc" }, { "Interface status", "inf-status" }, - { "Interface driver", "inf-driver" }, { "Connection status", "status" }, { "Connection SSID", "ssid" }, { "Connection BSSID", "bssid" }, From d8452f71ede84613a839193dfb9c87bdac1a41ef Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 15:03:56 +0800 Subject: [PATCH 039/109] Wifi (SunOS): fortifies code --- src/detection/wifi/wifi_sunos.c | 41 +++++++++++++++++---------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/detection/wifi/wifi_sunos.c b/src/detection/wifi/wifi_sunos.c index ad58f19222..0b2e24ae21 100644 --- a/src/detection/wifi/wifi_sunos.c +++ b/src/detection/wifi/wifi_sunos.c @@ -30,22 +30,6 @@ static bool getWifiValue(int fd, uint32_t id, void* value, size_t valueSize, wld return true; } -static void initWifiResult(FFWifiResult* item, const char* name) { - ffStrbufInitS(&item->inf.description, name); - ffStrbufInit(&item->inf.status); - ffStrbufInit(&item->conn.status); - ffStrbufInit(&item->conn.ssid); - ffStrbufInit(&item->conn.bssid); - ffStrbufInit(&item->conn.protocol); - ffStrbufInit(&item->conn.security); - item->conn.signalQuality = -DBL_MAX; - item->conn.rxRate = -DBL_MAX; - item->conn.txRate = -DBL_MAX; - item->conn.channel = 0; - item->conn.channelWidth = 0; - item->conn.frequency = 0; -} - static void setWifiProtocol(FFstrbuf* protocol, uint32_t subtype, bool htEnabled) { switch (subtype) { case WL_FHSS: @@ -89,6 +73,8 @@ static void setWifiSecurity(FFstrbuf* security, uint32_t encryption, bool haveAu } const char* ffDetectWifi(FFlist* result) { + // https://github.com/illumos/illumos-gate/blob/master/usr/src/cmd/cmd-inet/usr.sbin/wificonfig/wificonfig.c + FF_AUTO_CLOSE_DIR DIR* directory = opendir("/dev/wifi"); if (!directory) { return nullptr; @@ -113,13 +99,28 @@ const char* ffDetectWifi(FFlist* result) { continue; } - FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR); + FF_AUTO_CLOSE_FD int fd = open(devicePath, O_RDWR | O_CLOEXEC); if (fd < 0) { continue; } + if (!isastream(fd)) { + continue; + } FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); - initWifiResult(item, entry->d_name); + ffStrbufInitS(&item->inf.description, entry->d_name); + ffStrbufInit(&item->inf.status); + ffStrbufInit(&item->conn.status); + ffStrbufInit(&item->conn.ssid); + ffStrbufInit(&item->conn.bssid); + ffStrbufInit(&item->conn.protocol); + ffStrbufInit(&item->conn.security); + item->conn.signalQuality = -DBL_MAX; + item->conn.rxRate = -DBL_MAX; + item->conn.txRate = -DBL_MAX; + item->conn.channel = 0; + item->conn.channelWidth = 0; + item->conn.frequency = 0; wl_radio_t radio; if (getWifiValue(fd, WL_RADIO, &radio, sizeof(radio), buffer)) { @@ -140,13 +141,13 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufSetStatic(&item->conn.status, "Connected"); wl_essid_t essid; - if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) && essid.wl_essid_length < sizeof(essid.wl_essid_essid) && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { + if (getWifiValue(fd, WL_ESSID, &essid, sizeof(essid), buffer) && essid.wl_essid_length > 0 && essid.wl_essid_length < sizeof(essid.wl_essid_essid) && essid.wl_essid_length <= MAX_ESSID_LENGTH - 1) { ffStrbufSetNS(&item->conn.ssid, essid.wl_essid_length, essid.wl_essid_essid); } wl_bssid_t bssid; if (getWifiValue(fd, WL_BSSID, bssid, sizeof(bssid), buffer)) { - ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", (uint8_t) bssid[0], (uint8_t) bssid[1], (uint8_t) bssid[2], (uint8_t) bssid[3], (uint8_t) bssid[4], (uint8_t) bssid[5]); } wl_rssi_t rssi; From b1f2bf35269be84098e376e7a53a76ba8568e2db Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 15:23:21 +0800 Subject: [PATCH 040/109] WM: uses full name in EN, as DE and LM modules do --- src/modules/wm/wm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 8b7d8ec263..e1868120b1 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -123,7 +123,7 @@ FFModuleBaseInfo ffWMModuleInfo = { .name = "WM", .description = "Print the window manager name and version", .displayName = { - .en = "WM", + .en = "Window Manager", .ar = "مدير النوافذ", .de = "Fenstermanager", .es = "Gestor de ventanas", From 8b40117c08236b71acc2d2caea899e981efc12eb Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 16:04:00 +0800 Subject: [PATCH 041/109] Wifi (OpenBSD): fortifies detection and adds channel to frequency helper --- src/detection/wifi/wifi.h | 17 +++++++++- src/detection/wifi/wifi_obsd.c | 58 +++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/detection/wifi/wifi.h b/src/detection/wifi/wifi.h index a7ea62d489..faee5de46a 100644 --- a/src/detection/wifi/wifi.h +++ b/src/detection/wifi/wifi.h @@ -19,7 +19,7 @@ struct FFWifiConnection { double txRate; uint16_t channel; uint16_t channelWidth; // MHz - uint16_t frequency; // MHz + uint16_t frequency; // MHz }; typedef struct FFWifiResult { @@ -61,3 +61,18 @@ static inline uint16_t ffWifiFreqToChannel(uint16_t frequency) { return 0; } + +static inline uint16_t ffWifiChannelToFreq(uint16_t channel) { + // Inverse of ffWifiFreqToChannel for the common 2.4 GHz and 5 GHz bands. + // 4.9 GHz and 6 GHz channels overlap numerically, so they are not handled here. + if (channel == 14) { + return 2484; + } + if (channel >= 1 && channel <= 13) { + return (uint16_t) (2407 + 5 * channel); + } + if (channel >= 36 && channel <= 177) { // 5 GHz: 5000 + 5*channel covers 36..177 + return (uint16_t) (5000 + 5 * channel); + } + return 0; +} diff --git a/src/detection/wifi/wifi_obsd.c b/src/detection/wifi/wifi_obsd.c index 6def7b63bc..a9817c0511 100644 --- a/src/detection/wifi/wifi_obsd.c +++ b/src/detection/wifi/wifi_obsd.c @@ -1,6 +1,5 @@ #include "wifi.h" #include "common/io.h" -#include "common/strutil.h" #include #include @@ -17,12 +16,20 @@ const char* ffDetectWifi(FFlist* result) { FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { + if_freenameindex(infs); return "socket() failed"; } for (struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == nullptr); ++i) { - if (!ffStrStartsWith(i->if_name, "iwm")) { - continue; + struct ieee80211_nodereq nr = {}; + strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname)); + + int err = 0; + if (ioctl(sock, SIOCG80211NODE, &nr) < 0) { + err = errno; + if (err == ENXIO || err == ENODEV || err == EINVAL || err == ENOTTY) { + continue; // Not a Wi-Fi interface + } } FFWifiResult* item = FF_LIST_ADD(FFWifiResult, *result); @@ -37,12 +44,9 @@ const char* ffDetectWifi(FFlist* result) { item->conn.rxRate = -DBL_MAX; item->conn.txRate = -DBL_MAX; item->conn.channel = 0; - item->conn.channelWidth = 0; + item->conn.channelWidth = 0; // not exposed by ieee80211_nodereq item->conn.frequency = 0; - struct ieee80211_nodereq nr = {}; - strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname)); - struct ifreq ifr = {}; strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name)); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { @@ -51,31 +55,34 @@ const char* ffDetectWifi(FFlist* result) { ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down"); } - if (ioctl(sock, SIOCG80211NODE, &nr) < 0) { - ffStrbufSetStatic(&item->conn.status, "Not associated"); - continue; - } - - if (nr.nr_nwid_len > 0) { - ffStrbufSetStatic(&item->conn.status, "Associated"); - ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid); - } else { + if (err != 0 || nr.nr_nwid_len == 0) { ffStrbufSetStatic(&item->conn.status, "Not associated"); continue; } + ffStrbufSetStatic(&item->conn.status, "Associated"); + ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*) nr.nr_nwid); ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X", nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2], nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]); item->conn.channel = nr.nr_channel; + if (item->conn.channel == 0) { + struct ieee80211chanreq chreq = {}; + strlcpy(chreq.i_name, i->if_name, sizeof(chreq.i_name)); + if (ioctl(sock, SIOCG80211CHANNEL, &chreq) >= 0) { + item->conn.channel = chreq.i_channel; + } + } + item->conn.frequency = ffWifiChannelToFreq(item->conn.channel); if (nr.nr_max_rssi) { - item->conn.signalQuality = ((float) nr.nr_rssi / nr.nr_max_rssi) * 100.0; + item->conn.signalQuality = ((double) nr.nr_rssi / (double) nr.nr_max_rssi) * 100.0; } - if (nr.nr_flags & IEEE80211_NODEREQ_HT) { - ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)"); - } else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) { + // VHT implies HT, so test VHT first + if (nr.nr_flags & IEEE80211_NODEREQ_VHT) { ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); + } else if (nr.nr_flags & IEEE80211_NODEREQ_HT) { + ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)"); } else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) { ffStrbufSetStatic(&item->conn.protocol, "802.11a"); } else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) { @@ -86,15 +93,22 @@ const char* ffDetectWifi(FFlist* result) { strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name)); if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) { - if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) { + if (wpa.i_akms & IEEE80211_WPA_AKM_SAE) { + if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) { + ffStrbufSetStatic(&item->conn.security, "WPA2/WPA3"); + } else { + ffStrbufSetStatic(&item->conn.security, "WPA3"); + } + } else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2) { ffStrbufSetStatic(&item->conn.security, "WPA2"); } else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1) { ffStrbufSetStatic(&item->conn.security, "WPA"); + } else { + ffStrbufSetStatic(&item->conn.security, "Unknown"); } } else { struct ieee80211_nwkey nwkey = {}; strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name)); - if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) { if (nwkey.i_wepon) { ffStrbufSetStatic(&item->conn.security, "WEP"); From 5d11b65d533fe98a91213c9c6ef99fd6bdfeb188 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 20 Aug 2026 16:18:07 +0800 Subject: [PATCH 042/109] TerminalFont (Android): adds font size detection --- src/detection/terminalfont/terminalfont_android.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 666cf3e2b2..7ef0f52506 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -2,6 +2,7 @@ #include "terminalfont.h" #include "detection/terminalshell/terminalshell.h" #include "common/io.h" +#include "common/properties.h" #ifdef FF_HAVE_FREETYPE #include "common/library.h" @@ -10,10 +11,17 @@ #endif #define FF_TERMUX_FONT_PATH FASTFETCH_TARGET_DIR_HOME "/.termux/font.ttf" +#define FF_TERMUX_PREF_PATH "/data/data/com.termux/shared_prefs/com.termux_preferences.xml" const char* detectTermux(FFTerminalFontResult* terminalFont) { + FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); + // SharedPreferences XML: 14, in px + if (ffParsePropFile(FF_TERMUX_PREF_PATH, "", &fontSize)) { + ffStrbufAppendS(&fontSize, "px"); + } + if (!ffPathExists(FF_TERMUX_FONT_PATH, FF_PATHTYPE_FILE)) { - ffFontInitCopy(&terminalFont->font, "monospace"); + ffFontInitValues(&terminalFont->font, "monospace", fontSize.length ? fontSize.chars : nullptr); return nullptr; } @@ -39,7 +47,7 @@ const char* detectTermux(FFTerminalFontResult* terminalFont) { goto exit; } - ffFontInitCopy(&terminalFont->font, face->family_name); + ffFontInitValues(&terminalFont->font, face->family_name, fontSize.length ? fontSize.chars : nullptr); exit: if (face) { @@ -53,7 +61,7 @@ const char* detectTermux(FFTerminalFontResult* terminalFont) { #else - FF_UNUSED(terminalFont); + ffFontInitValues(&terminalFont->font, "monospace", fontSize.length ? fontSize.chars : nullptr); return "Fastfetch was built without freetype2 support"; #endif From 0c4ec62cac9eb68936f93a9df5a1b2c179b0ee90 Mon Sep 17 00:00:00 2001 From: Samuel Torres Date: Thu, 20 Aug 2026 16:25:32 +0000 Subject: [PATCH 043/109] L10n: (gl) Added Galician Support --- doc/help.json | 1 + doc/json_schema.json | 5 +++++ src/common/option.h | 1 + src/modules/battery/battery.c | 1 + src/modules/bios/bios.c | 1 + src/modules/bluetooth/bluetooth.c | 1 + src/modules/bluetoothradio/bluetoothradio.c | 1 + src/modules/board/board.c | 1 + src/modules/bootmgr/bootmgr.c | 1 + src/modules/break/break.c | 1 + src/modules/brightness/brightness.c | 1 + src/modules/btrfs/btrfs.c | 1 + src/modules/camera/camera.c | 1 + src/modules/chassis/chassis.c | 1 + src/modules/codec/codec.c | 1 + src/modules/colors/colors.c | 1 + src/modules/command/command.c | 1 + src/modules/cpu/cpu.c | 1 + src/modules/cpucache/cpucache.c | 1 + src/modules/cpuusage/cpuusage.c | 1 + src/modules/cursor/cursor.c | 1 + src/modules/datetime/datetime.c | 1 + src/modules/de/de.c | 1 + src/modules/disk/disk.c | 1 + src/modules/diskio/diskio.c | 1 + src/modules/display/display.c | 1 + src/modules/dns/dns.c | 1 + src/modules/editor/editor.c | 1 + src/modules/font/font.c | 1 + src/modules/gamepad/gamepad.c | 1 + src/modules/gpu/gpu.c | 1 + src/modules/host/host.c | 1 + src/modules/icons/icons.c | 1 + src/modules/initsystem/initsystem.c | 1 + src/modules/kernel/kernel.c | 1 + src/modules/keyboard/keyboard.c | 1 + src/modules/lm/lm.c | 1 + src/modules/loadavg/loadavg.c | 1 + src/modules/locale/locale.c | 1 + src/modules/localip/localip.c | 1 + src/modules/logo/logo.c | 1 + src/modules/media/media.c | 1 + src/modules/memory/memory.c | 1 + src/modules/monitor/monitor.c | 1 + src/modules/mouse/mouse.c | 1 + src/modules/netio/netio.c | 1 + src/modules/opencl/opencl.c | 1 + src/modules/opengl/opengl.c | 1 + src/modules/os/os.c | 1 + src/modules/packages/packages.c | 1 + src/modules/physicaldisk/physicaldisk.c | 1 + src/modules/physicalmemory/physicalmemory.c | 1 + src/modules/player/player.c | 1 + src/modules/poweradapter/poweradapter.c | 1 + src/modules/processes/processes.c | 1 + src/modules/publicip/publicip.c | 1 + src/modules/separator/separator.c | 1 + src/modules/shell/shell.c | 1 + src/modules/sound/sound.c | 1 + src/modules/swap/swap.c | 1 + src/modules/terminal/terminal.c | 1 + src/modules/terminalfont/terminalfont.c | 1 + src/modules/terminaltheme/terminaltheme.c | 1 + src/modules/theme/theme.c | 1 + src/modules/title/title.c | 1 + src/modules/tpm/tpm.c | 1 + src/modules/uptime/uptime.c | 1 + src/modules/users/users.c | 1 + src/modules/version/version.c | 1 + src/modules/vulkan/vulkan.c | 1 + src/modules/wallpaper/wallpaper.c | 1 + src/modules/weather/weather.c | 1 + src/modules/wifi/wifi.c | 1 + src/modules/wm/wm.c | 1 + src/modules/wmtheme/wmtheme.c | 1 + src/modules/zpool/zpool.c | 1 + src/options/display.c | 4 ++++ 77 files changed, 84 insertions(+) diff --git a/doc/help.json b/doc/help.json index b575aa47bc..4e056a5c8f 100644 --- a/doc/help.json +++ b/doc/help.json @@ -599,6 +599,7 @@ "de": "German", "es": "Spanish", "fr": "French", + "gl": "Galician", "he": "Hebrew", "it": "Italian", "ja": "Japanese", diff --git a/doc/json_schema.json b/doc/json_schema.json index 3dbc06e988..d1db924938 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1090,6 +1090,11 @@ "const": "fr", "description": "French" }, + { + "type": "string", + "const": "gl", + "description": "Galician" + }, { "type": "string", "const": "he", diff --git a/src/common/option.h b/src/common/option.h index e8f2dca1d2..1980e80515 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -25,6 +25,7 @@ typedef struct FFModuleDisplayName { const char* de; // German const char* es; // Spanish const char* fr; // French + const char* gl; // Galician const char* he; // Hebrew const char* it; // Italian const char* ja; // Japanese diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 9fd8c4572e..ad71499aaa 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -305,6 +305,7 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .de = "Akku", .es = "Batería", .fr = "Batterie", + .gl = "Batería", .he = "סוללה", .it = "Batteria", .ja = "バッテリー", diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 6b129213ce..9809067175 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -138,6 +138,7 @@ FFModuleBaseInfo ffBiosModuleInfo = { .de = "BIOS", .es = "BIOS", .fr = "BIOS", + .gl = "BIOS", .he = "BIOS", .it = "BIOS", .ja = "BIOS", diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index d4adae8215..bd90ec8870 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -159,6 +159,7 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .de = "Bluetooth", .es = "Bluetooth", .fr = "Bluetooth", + .gl = "Bluetooth", .he = "בלוטות'", .it = "Bluetooth", .ja = "ブルートゥース", diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 5a6b47d715..23284244f4 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -196,6 +196,7 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .de = "Bluetooth-Adapter", .es = "Adaptador Bluetooth", .fr = "Adaptateur Bluetooth", + .gl = "Adaptador Bluetooth", .he = "רדיו בלוטות'", .it = "Adattatore Bluetooth", .ja = "ブルートゥースアダプター", diff --git a/src/modules/board/board.c b/src/modules/board/board.c index b82d90bc5a..9436c7071f 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -116,6 +116,7 @@ FFModuleBaseInfo ffBoardModuleInfo = { .de = "Mainboard", .es = "Placa base", .fr = "Carte mère", + .gl = "Placa base", .he = "לוח אם", .it = "Scheda madre", .ja = "マザーボード", diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index db7a9c473e..e4059356d9 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -111,6 +111,7 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .de = "Boot-Manager", .es = "Administrador de arranque", .fr = "Gestionnaire de démarrage", + .gl = "Xestor de arranque", .he = "מנהל אתחול", .it = "Gestore di avvio", .ja = "ブートマネージャー", diff --git a/src/modules/break/break.c b/src/modules/break/break.c index f0ef529bcb..751694abdf 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -35,6 +35,7 @@ FFModuleBaseInfo ffBreakModuleInfo = { .de = "Umbruch", .es = "Salto de línea", .fr = "Saut de ligne", + .gl = "Salto de liña", .he = "מעבר שורה", .it = "Interruzione", .ja = "改行", diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 16ff8e8b02..d018a4dcd8 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -198,6 +198,7 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .de = "Helligkeit", .es = "Brillo", .fr = "Luminosité", + .gl = "Brillo", .he = "בהירות", .it = "Luminosità", .ja = "明るさ", diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index bbba974e8b..fc41ef402c 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -206,6 +206,7 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .de = "BTRFS", .es = "BTRFS", .fr = "BTRFS", + .gl = "BTRFS", .he = "BTRFS", .it = "BTRFS", .ja = "BTRFS", diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 82cf79c033..1dcc89e193 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -123,6 +123,7 @@ FFModuleBaseInfo ffCameraModuleInfo = { .de = "Kamera", .es = "Cámara", .fr = "Caméra", + .gl = "Cámara", .he = "מצלמה", .it = "Fotocamera", .ja = "カメラ", diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index ae99ba9c5d..7ba77a0d05 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -118,6 +118,7 @@ FFModuleBaseInfo ffChassisModuleInfo = { .de = "Gehäuse", .es = "Chasis", .fr = "Châssis", + .gl = "Chasis", .he = "מארז", .it = "Telaio", .ja = "シャーシ", diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index 6f7a3a1bbb..d5c1d0e960 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -259,6 +259,7 @@ FFModuleBaseInfo ffCodecModuleInfo = { .de = "Codec", .es = "Códec", .fr = "Codec", + .gl = "Códec", .he = "קודק", .it = "Codec", .ja = "コーデック", diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 38ce77ce66..2f33f91623 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -303,6 +303,7 @@ FFModuleBaseInfo ffColorsModuleInfo = { .de = "Farben", .es = "Colores", .fr = "Couleurs", + .gl = "Cores", .he = "צבעים", .it = "Colori", .ja = "色", diff --git a/src/modules/command/command.c b/src/modules/command/command.c index a8e1b3f648..6878af3f21 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -161,6 +161,7 @@ FFModuleBaseInfo ffCommandModuleInfo = { .de = "Befehl", .es = "Comando", .fr = "Commande", + .gl = "Comando", .he = "פקודה", .it = "Comando", .ja = "コマンド", diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index ec14dd363f..23f652b772 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -259,6 +259,7 @@ FFModuleBaseInfo ffCPUModuleInfo = { .de = "CPU", .es = "CPU", .fr = "CPU", + .gl = "CPU", .he = "מעבד", .it = "CPU", .ja = "CPU", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index bf78de62d3..97881382fc 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -229,6 +229,7 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .de = "CPU-Cache", .es = "Caché de CPU", .fr = "Cache CPU", + .gl = "Caché da CPU", .he = "מטמון מעבד", .it = "Cache CPU", .ja = "CPUキャッシュ", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index e2b09a03aa..bab07de659 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -187,6 +187,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .de = "CPU-Auslastung", .es = "Uso del CPU", .fr = "Utilisation du CPU", + .gl = "Uso da CPU", .he = "שימוש במעבד", .it = "Utilizzo della CPU", .ja = "CPU使用率", diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index f2c133bb6f..54f605bb65 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -108,6 +108,7 @@ FFModuleBaseInfo ffCursorModuleInfo = { .de = "Mauszeiger", .es = "Cursor", .fr = "Curseur", + .gl = "Cursor", .he = "סמן", .it = "Cursore", .ja = "カーソル", diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 1fb7ab9c55..46131bcd5d 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -158,6 +158,7 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .de = "Datum & Uhrzeit", .es = "Fecha y hora", .fr = "Date et heure", + .gl = "Data e hora", .he = "תאריך ושעה", .it = "Data e ora", .ja = "日付と時刻", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index c8b188d48f..ec5445d341 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -90,6 +90,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .de = "Desktop-Umgebung", .es = "Entorno de Escritorio", .fr = "Environnement de Bureau", + .gl = "Contorno do Escritorio", .he = "סביבת שולחן עבודה", .it = "Ambiente Desktop", .ja = "デスクトップ環境", diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index fddd4580f9..2d80a18a54 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -459,6 +459,7 @@ FFModuleBaseInfo ffDiskModuleInfo = { .de = "Festplatte", .es = "Disco", .fr = "Disque", + .gl = "Disco", .he = "דיסק", .it = "Disco", .ja = "ディスク", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 3ebb8ce305..033317d66a 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -178,6 +178,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .de = "Festplatten I/O", .es = "E/S de disco", .fr = "Entrée/Sortie disque", + .gl = "E/S do disco", .he = "קלט/פלט דיסק", .it = "I/O del disco", .ja = "ディスク I/O", diff --git a/src/modules/display/display.c b/src/modules/display/display.c index b7f0eefe5c..4eda352331 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -419,6 +419,7 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .de = "Anzeige", .es = "Pantalla", .fr = "Écran", + .gl = "Pantalla", .he = "תצוגה", .it = "Display", .ja = "ディスプレイ", diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index 7067de9ca2..c0f20d2c54 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -142,6 +142,7 @@ FFModuleBaseInfo ffDNSModuleInfo = { .de = "DNS", .es = "DNS", .fr = "DNS", + .gl = "DNS", .he = "DNS", .it = "DNS", .ja = "DNS", diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 09cc37238a..7d04c8445a 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -111,6 +111,7 @@ FFModuleBaseInfo ffEditorModuleInfo = { .de = "Editor", .es = "Editor", .fr = "Éditeur", + .gl = "Editor", .he = "עורך", .it = "Editor", .ja = "エディター", diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 22a4645634..dfbdd712fe 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -103,6 +103,7 @@ FFModuleBaseInfo ffFontModuleInfo = { .de = "Schriftart", .es = "Fuente", .fr = "Police", + .gl = "Fonte", .he = "גופן", .it = "Carattere", .ja = "フォント", diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 7273156de8..ae31b96cbf 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -197,6 +197,7 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .de = "Gamepad", .es = "Gamepad", .fr = "Manette", + .gl = "Gamepad", .he = "משטח משחק", .it = "Gamepad", .ja = "ゲームパッド", diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index f030795dad..1292a62568 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -487,6 +487,7 @@ FFModuleBaseInfo ffGPUModuleInfo = { .de = "GPU", .es = "GPU", .fr = "GPU", + .gl = "GPU", .he = "מעבד גרפי", .it = "GPU", .ja = "GPU", diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 0159423bf1..a79fbdc3b3 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -144,6 +144,7 @@ FFModuleBaseInfo ffHostModuleInfo = { .de = "Rechner", .es = "Host", .fr = "Hôte", + .gl = "Host", .he = "מארח", .it = "Host", .ja = "ホスト", diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 5da212d33e..c8b9d8cb4b 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -102,6 +102,7 @@ FFModuleBaseInfo ffIconsModuleInfo = { .de = "Symbole", .es = "Iconos", .fr = "Icônes", + .gl = "Iconas", .he = "סמלים", .it = "Icone", .ja = "アイコン", diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index edd3d8fdce..f5f4238fdf 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -109,6 +109,7 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .de = "Init-System", .es = "Sistema de inicio", .fr = "Système d'init", + .gl = "Sistema de inicio", .he = "מערכת אתחול", .it = "Sistema di init", .ja = "initシステム", diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index f0deb47278..3e8334e2c1 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -70,6 +70,7 @@ FFModuleBaseInfo ffKernelModuleInfo = { .de = "Kernel", .es = "Kernel", .fr = "Kernel", + .gl = "Kernel", .he = "ליבה", .it = "Kernel", .ja = "カーネル", diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index 998e04262a..df7b2cef68 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -157,6 +157,7 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .de = "Tastatur", .es = "Teclado", .fr = "Clavier", + .gl = "Teclado", .he = "מקלדת", .it = "Tastiera", .ja = "キーボード", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 0b7d68649b..4f96fb4570 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -114,6 +114,7 @@ FFModuleBaseInfo ffLMModuleInfo = { .de = "Anmeldemanager", .es = "Administrador de inicio de sesión", .fr = "Gestionnaire de connexion", + .gl = "Xestor de inicio de sesión", .he = "מנהל התחברות", .it = "Gestore di accesso", .ja = "ログインマネージャー", diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index cfa36f857e..a23c3edf6f 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -156,6 +156,7 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .de = "Systemlast", .es = "Promedio de carga", .fr = "Charge moyenne", + .gl = "Carga media", .he = "עומס ממוצע", .it = "Carico medio", .ja = "ロードアベレージ", diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index ca523c90ca..835937a0e6 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -75,6 +75,7 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .de = "Sprachraum", .es = "Configuración regional", .fr = "Paramètres régionaux", + .gl = "Configuración rexional", .he = "לוקאל", .it = "Impostazioni locali", .ja = "ロケール", diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index accff5f47a..13a4692c70 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -429,6 +429,7 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .de = "Lokale IP", .es = "IP local", .fr = "IP locale", + .gl = "IP local", .he = "IP מקומי", .it = "IP locale", .ja = "ローカル IP", diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 860960b6ec..4f73084f99 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -85,6 +85,7 @@ FFModuleBaseInfo ffLogoModuleInfo = { .de = "Logo", .es = "Logo", .fr = "Logo", + .gl = "Logo", .he = "לוגו", .it = "Logo", .ja = "ロゴ", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 5e7188905e..4f6a81c556 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -261,6 +261,7 @@ FFModuleBaseInfo ffMediaModuleInfo = { .de = "Medien", .es = "Medios", .fr = "Médias", + .gl = "Multimedia", .he = "מדיה", .it = "Media", .ja = "メディア", diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index d375bd9cc3..d338d177e9 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -126,6 +126,7 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .de = "Speicher", .es = "Memoria", .fr = "Mémoire", + .gl = "Memoria", .he = "זיכרון", .it = "Memoria", .ja = "メモリ", diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index a9959187bd..13cf741249 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -112,6 +112,7 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .de = "Monitor", .es = "Monitor", .fr = "Moniteur", + .gl = "Monitor", .he = "צג", .it = "Monitor", .ja = "モニター", diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index b6db692436..f8f06a9374 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -160,6 +160,7 @@ FFModuleBaseInfo ffMouseModuleInfo = { .de = "Maus", .es = "Ratón", .fr = "Souris", + .gl = "Rato", .he = "עכבר", .it = "Mouse", .ja = "マウス", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 328cc36135..6d2a72cef7 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -205,6 +205,7 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .de = "Netzwerk I/O", .es = "E/S de red", .fr = "E/S réseau", + .gl = "E/S da rede", .he = "קלט/פלט רשת", .it = "I/O di rete", .ja = "ネットワークI/O", diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 78352f306c..c13c8c2d9a 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -128,6 +128,7 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .de = "OpenCL", .es = "OpenCL", .fr = "OpenCL", + .gl = "OpenCL", .he = "OpenCL", .it = "OpenCL", .ja = "OpenCL", diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 8093e135df..4b325cbecf 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -135,6 +135,7 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .de = "OpenGL", .es = "OpenGL", .fr = "OpenGL", + .gl = "OpenGL", .he = "OpenGL", .it = "OpenGL", .ja = "OpenGL", diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 3e0fecc756..51c89cbba5 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -180,6 +180,7 @@ FFModuleBaseInfo ffOSModuleInfo = { .de = "Betriebssystem", .es = "Sistema operativo", .fr = "Système d'exploitation", + .gl = "Sistema operativo", .he = "מערכת הפעלה", .it = "Sistema operativo", .ja = "オペレーティングシステム", diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 2c6143189c..fc39603b47 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -518,6 +518,7 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .de = "Pakete", .es = "Paquetes", .fr = "Paquets", + .gl = "Paquetes", .he = "חבילות", .it = "Pacchetti", .ja = "パッケージ", diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 929ca4b69a..a4e7bb0f81 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -271,6 +271,7 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .de = "Physische Festplatte", .es = "Disco físico", .fr = "Disque physique", + .gl = "Disco físico", .he = "דיסק פיזי", .it = "Disco fisico", .ja = "物理ディスク", diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 5c0d6ecec7..4c9ee7001a 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -165,6 +165,7 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .de = "Physischer Speicher", .es = "Memoria física", .fr = "Mémoire physique", + .gl = "Memoria física", .he = "זיכרון פיזי", .it = "Memoria fisica", .ja = "物理メモリ", diff --git a/src/modules/player/player.c b/src/modules/player/player.c index c12da175d9..c5bdfcf13d 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -115,6 +115,7 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .de = "Medienplayer", .es = "Reproductor multimedia", .fr = "Lecteur multimédia", + .gl = "Reprodutor multimedia", .he = "נגן מדיה", .it = "Lettore multimediale", .ja = "メディアプレイヤー", diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index d9506c41be..5d8d2e2c15 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -116,6 +116,7 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .de = "Netzteil", .es = "Adaptador de corriente", .fr = "Adaptateur secteur", + .gl = "Adaptador de corrente", .he = "מתאם מתח", .it = "Alimentatore", .ja = "電源アダプター", diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 824fd89d66..a73c2c4639 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -71,6 +71,7 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .de = "Prozesse", .es = "Procesos", .fr = "Processus", + .gl = "Procesos", .he = "תהליכים", .it = "Processi", .ja = "プロセス", diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index afad49017d..110b0dfc84 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -116,6 +116,7 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .de = "Öffentliche IP", .es = "IP pública", .fr = "IP publique", + .gl = "IP pública", .he = "IP ציבורי", .it = "IP pubblica", .ja = "パブリックIP", diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 34af6a2867..0c19a89cca 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -129,6 +129,7 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .de = "Trennlinie", .es = "Separador", .fr = "Séparateur", + .gl = "Separador", .he = "מפריד", .it = "Separatore", .ja = "セパレーター", diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 8abd01d523..bce575b2a0 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -97,6 +97,7 @@ FFModuleBaseInfo ffShellModuleInfo = { .de = "Shell", .es = "Shell", .fr = "Shell", + .gl = "Shell", .he = "מעטפת", .it = "Shell", .ja = "シェル", diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index fa87482f1a..0c6436833b 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -207,6 +207,7 @@ FFModuleBaseInfo ffSoundModuleInfo = { .de = "Sound", .es = "Sonido", .fr = "Son", + .gl = "Son", .he = "קול", .it = "Audio", .ja = "サウンド", diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 796cf7271b..3848b62d0f 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -190,6 +190,7 @@ FFModuleBaseInfo ffSwapModuleInfo = { .de = "Swap", .es = "Swap", .fr = "Swap", + .gl = "Swap", .he = "זיכרון החלפה", .it = "Swap", .ja = "スワップ", diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 58e6ae9cfb..80c9016935 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -91,6 +91,7 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .de = "Terminal", .es = "Terminal", .fr = "Terminal", + .gl = "Terminal", .he = "טרמינל", .it = "Terminale", .ja = "ターミナル", diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index ae792843be..d9e5a81f5d 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -111,6 +111,7 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .de = "Terminalschriftart", .es = "Fuente del terminal", .fr = "Police du terminal", + .gl = "Fonte do terminal", .he = "גופן טרמינל", .it = "Carattere del terminale", .ja = "ターミナルフォント", diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 52e3feebfe..faa1ef2852 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -99,6 +99,7 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .de = "Terminalthema", .es = "Tema del terminal", .fr = "Thème du terminal", + .gl = "Tema do terminal", .he = "ערכת נושא של טרמינל", .it = "Tema del terminale", .ja = "ターミナルテーマ", diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 4ceaf14cbe..263dd9875f 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -95,6 +95,7 @@ FFModuleBaseInfo ffThemeModuleInfo = { .de = "Thema", .es = "Tema", .fr = "Thème", + .gl = "Tema", .he = "ערכת נושא", .it = "Tema", .ja = "テーマ", diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 788ab2eec6..3cad3941dc 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -184,6 +184,7 @@ FFModuleBaseInfo ffTitleModuleInfo = { .de = "Titel", .es = "Título", .fr = "Titre", + .gl = "Título", .he = "כותרת", .it = "Titolo", .ja = "タイトル", diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 3ff4a4e8d0..1e2e03f105 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -91,6 +91,7 @@ FFModuleBaseInfo ffTPMModuleInfo = { .de = "TPM", .es = "TPM", .fr = "TPM", + .gl = "TPM", .he = "TPM", .it = "TPM", .ja = "TPM", diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index d7ee69e05a..5937711bf7 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -91,6 +91,7 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .de = "Betriebszeit", .es = "Tiempo de actividad", .fr = "Temps de fonctionnement", + .gl = "Tempo de actividade", .he = "זמן פעילות", .it = "Tempo di attività", .ja = "稼働時間", diff --git a/src/modules/users/users.c b/src/modules/users/users.c index e355f40d74..e381297ece 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -188,6 +188,7 @@ FFModuleBaseInfo ffUsersModuleInfo = { .de = "Benutzer", .es = "Usuarios", .fr = "Utilisateurs", + .gl = "Usuarios", .he = "משתמשים", .it = "Utenti", .ja = "ユーザー", diff --git a/src/modules/version/version.c b/src/modules/version/version.c index f90585a73e..04fb1a6ffb 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -102,6 +102,7 @@ FFModuleBaseInfo ffVersionModuleInfo = { .de = "Version", .es = "Versión", .fr = "Version", + .gl = "Versión", .he = "גרסה", .it = "Versione", .ja = "バージョン", diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 990b56f1ac..4c2c8c85f6 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -140,6 +140,7 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .de = "Vulkan", .es = "Vulkan", .fr = "Vulkan", + .gl = "Vulkan", .he = "Vulkan", .it = "Vulkan", .ja = "Vulkan", diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index 9ed7d40146..472587d9a7 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -83,6 +83,7 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .de = "Hintergrundbild", .es = "Fondo de pantalla", .fr = "Fond d'écran", + .gl = "Fondo de escritorio", .he = "טפט", .it = "Sfondo", .ja = "壁紙", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 5eab9a6c71..d630de1410 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -100,6 +100,7 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .de = "Wetter", .es = "Clima", .fr = "Météo", + .gl = "Tempo", .he = "מזג אוויר", .it = "Meteo", .ja = "天気", diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index a9462418d4..a7ad22c228 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -223,6 +223,7 @@ FFModuleBaseInfo ffWifiModuleInfo = { .de = "WLAN", .es = "Wi-Fi", .fr = "Wi-Fi", + .gl = "Wi-Fi", .he = "Wi-Fi", .it = "Wi-Fi", .ja = "Wi-Fi", diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index e1868120b1..2812a97ce0 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -128,6 +128,7 @@ FFModuleBaseInfo ffWMModuleInfo = { .de = "Fenstermanager", .es = "Gestor de ventanas", .fr = "Gestionnaire de fenêtres", + .gl = "Xestor de xanelas", .he = "מנהל חלונות", .it = "Gestore finestre", .ja = "ウィンドウマネージャー", diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 5394b09638..f6f40979a2 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -67,6 +67,7 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .de = "Fenstermanager-Thema", .es = "Tema del gestor de ventanas", .fr = "Thème du gestionnaire de fenêtres", + .gl = "Tema do xestor de xanelas", .he = "ערכת נושא של מנהל חלונות", .it = "Tema del gestore finestre", .ja = "ウィンドウマネージャのテーマ", diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index aafb5d4d90..7657c94898 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -200,6 +200,7 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .de = "Zpool", .es = "Zpool", .fr = "Zpool", + .gl = "Zpool", .he = "Zpool", .it = "Zpool", .ja = "Zpool", diff --git a/src/options/display.c b/src/options/display.c index a352af7192..0e6b7141cb 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -68,6 +68,7 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { case 'de': return offsetof(FFModuleDisplayName, de); case 'es': return offsetof(FFModuleDisplayName, es); case 'fr': return offsetof(FFModuleDisplayName, fr); + case 'gl': return offsetof(FFModuleDisplayName, gl); case 'he': return offsetof(FFModuleDisplayName, he); case 'it': return offsetof(FFModuleDisplayName, it); case 'ja': return offsetof(FFModuleDisplayName, ja); @@ -1284,6 +1285,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, fr): yyjson_mut_obj_add_str(doc, key, "language", "fr"); break; + case offsetof(FFModuleDisplayName, gl): + yyjson_mut_obj_add_str(doc, key, "language", "gl"); + break; case offsetof(FFModuleDisplayName, he): yyjson_mut_obj_add_str(doc, key, "language", "he"); break; From 6570a7accc91417c123e4fc59bf828b4a630a86c Mon Sep 17 00:00:00 2001 From: Samuel Torres Date: Fri, 21 Aug 2026 00:31:42 +0000 Subject: [PATCH 044/109] L10n (ES): fixes Spanish translations (#2537) --- src/modules/bootmgr/bootmgr.c | 2 +- src/modules/cpucache/cpucache.c | 2 +- src/modules/cpuusage/cpuusage.c | 2 +- src/modules/de/de.c | 2 +- src/modules/diskio/diskio.c | 2 +- src/modules/lm/lm.c | 2 +- src/modules/media/media.c | 2 +- src/modules/netio/netio.c | 2 +- src/modules/weather/weather.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index e4059356d9..8ad60faf23 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -109,7 +109,7 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .en = "Boot Manager", .ar = "مدير الإقلاع", .de = "Boot-Manager", - .es = "Administrador de arranque", + .es = "Gestor de arranque", .fr = "Gestionnaire de démarrage", .gl = "Xestor de arranque", .he = "מנהל אתחול", diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 97881382fc..55d92baa33 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -227,7 +227,7 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .en = "CPU Cache", .ar = "ذاكرة المعالج المؤقتة", .de = "CPU-Cache", - .es = "Caché de CPU", + .es = "Caché de la CPU", .fr = "Cache CPU", .gl = "Caché da CPU", .he = "מטמון מעבד", diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index bab07de659..3670ced0da 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -185,7 +185,7 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .en = "CPU Usage", .ar = "استخدام المعالج", .de = "CPU-Auslastung", - .es = "Uso del CPU", + .es = "Uso de la CPU", .fr = "Utilisation du CPU", .gl = "Uso da CPU", .he = "שימוש במעבד", diff --git a/src/modules/de/de.c b/src/modules/de/de.c index ec5445d341..b1942d6948 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -88,7 +88,7 @@ FFModuleBaseInfo ffDEModuleInfo = { .en = "Desktop Environment", .ar = "بيئة سطح المكتب", .de = "Desktop-Umgebung", - .es = "Entorno de Escritorio", + .es = "Entorno de escritorio", .fr = "Environnement de Bureau", .gl = "Contorno do Escritorio", .he = "סביבת שולחן עבודה", diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 033317d66a..e76f093647 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -176,7 +176,7 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .en = "Disk I/O", .ar = "إدخال/إخراج القرص", .de = "Festplatten I/O", - .es = "E/S de disco", + .es = "E/S del disco", .fr = "Entrée/Sortie disque", .gl = "E/S do disco", .he = "קלט/פלט דיסק", diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 4f96fb4570..88b7b0ed41 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -112,7 +112,7 @@ FFModuleBaseInfo ffLMModuleInfo = { .en = "Login Manager", .ar = "مدير تسجيل الدخول", .de = "Anmeldemanager", - .es = "Administrador de inicio de sesión", + .es = "Gestor de inicio de sesión", .fr = "Gestionnaire de connexion", .gl = "Xestor de inicio de sesión", .he = "מנהל התחברות", diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 4f6a81c556..da5c13c423 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -259,7 +259,7 @@ FFModuleBaseInfo ffMediaModuleInfo = { .en = "Media", .ar = "الوسائط", .de = "Medien", - .es = "Medios", + .es = "Multimedia", .fr = "Médias", .gl = "Multimedia", .he = "מדיה", diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 6d2a72cef7..2bc95d6158 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -203,7 +203,7 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .en = "Network I/O", .ar = "إدخال/إخراج الشبكة", .de = "Netzwerk I/O", - .es = "E/S de red", + .es = "E/S de la red", .fr = "E/S réseau", .gl = "E/S da rede", .he = "קלט/פלט רשת", diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index d630de1410..6878ab8d9a 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -98,7 +98,7 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .en = "Weather", .ar = "الطقس", .de = "Wetter", - .es = "Clima", + .es = "Tiempo", .fr = "Météo", .gl = "Tempo", .he = "מזג אוויר", From e0c239729b22b702542d262b2f8991149c616b54 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Aug 2026 10:19:06 +0800 Subject: [PATCH 045/109] L10n: adds `cs` `id` `tr` `uk` `vi` Assisted-By: LLM --- .codespellrc | 2 +- doc/help.json | 5 +++++ doc/json_schema.json | 25 +++++++++++++++++++++ src/common/option.h | 5 +++++ src/modules/battery/battery.c | 5 +++++ src/modules/bios/bios.c | 5 +++++ src/modules/bluetooth/bluetooth.c | 5 +++++ src/modules/bluetoothradio/bluetoothradio.c | 5 +++++ src/modules/board/board.c | 5 +++++ src/modules/bootmgr/bootmgr.c | 5 +++++ src/modules/break/break.c | 5 +++++ src/modules/brightness/brightness.c | 5 +++++ src/modules/btrfs/btrfs.c | 5 +++++ src/modules/camera/camera.c | 5 +++++ src/modules/chassis/chassis.c | 5 +++++ src/modules/codec/codec.c | 5 +++++ src/modules/colors/colors.c | 5 +++++ src/modules/command/command.c | 5 +++++ src/modules/cpu/cpu.c | 5 +++++ src/modules/cpucache/cpucache.c | 5 +++++ src/modules/cpuusage/cpuusage.c | 5 +++++ src/modules/cursor/cursor.c | 5 +++++ src/modules/custom/custom.c | 5 +++++ src/modules/datetime/datetime.c | 5 +++++ src/modules/de/de.c | 5 +++++ src/modules/disk/disk.c | 5 +++++ src/modules/diskio/diskio.c | 5 +++++ src/modules/display/display.c | 5 +++++ src/modules/dns/dns.c | 5 +++++ src/modules/editor/editor.c | 5 +++++ src/modules/font/font.c | 5 +++++ src/modules/gamepad/gamepad.c | 5 +++++ src/modules/gpu/gpu.c | 5 +++++ src/modules/host/host.c | 5 +++++ src/modules/icons/icons.c | 5 +++++ src/modules/initsystem/initsystem.c | 5 +++++ src/modules/kernel/kernel.c | 5 +++++ src/modules/keyboard/keyboard.c | 5 +++++ src/modules/lm/lm.c | 5 +++++ src/modules/loadavg/loadavg.c | 5 +++++ src/modules/locale/locale.c | 5 +++++ src/modules/localip/localip.c | 5 +++++ src/modules/logo/logo.c | 5 +++++ src/modules/media/media.c | 5 +++++ src/modules/memory/memory.c | 5 +++++ src/modules/monitor/monitor.c | 5 +++++ src/modules/mouse/mouse.c | 5 +++++ src/modules/netio/netio.c | 5 +++++ src/modules/opencl/opencl.c | 5 +++++ src/modules/opengl/opengl.c | 5 +++++ src/modules/os/os.c | 5 +++++ src/modules/packages/packages.c | 5 +++++ src/modules/physicaldisk/physicaldisk.c | 5 +++++ src/modules/physicalmemory/physicalmemory.c | 5 +++++ src/modules/player/player.c | 5 +++++ src/modules/poweradapter/poweradapter.c | 5 +++++ src/modules/processes/processes.c | 5 +++++ src/modules/publicip/publicip.c | 5 +++++ src/modules/separator/separator.c | 5 +++++ src/modules/shell/shell.c | 5 +++++ src/modules/sound/sound.c | 5 +++++ src/modules/swap/swap.c | 5 +++++ src/modules/terminal/terminal.c | 5 +++++ src/modules/terminalfont/terminalfont.c | 5 +++++ src/modules/terminalsize/terminalsize.c | 5 +++++ src/modules/terminaltheme/terminaltheme.c | 5 +++++ src/modules/theme/theme.c | 5 +++++ src/modules/title/title.c | 5 +++++ src/modules/tpm/tpm.c | 5 +++++ src/modules/uptime/uptime.c | 5 +++++ src/modules/users/users.c | 5 +++++ src/modules/version/version.c | 5 +++++ src/modules/vulkan/vulkan.c | 5 +++++ src/modules/wallpaper/wallpaper.c | 5 +++++ src/modules/weather/weather.c | 5 +++++ src/modules/wifi/wifi.c | 5 +++++ src/modules/wm/wm.c | 5 +++++ src/modules/wmtheme/wmtheme.c | 5 +++++ src/modules/zpool/zpool.c | 5 +++++ src/options/display.c | 20 +++++++++++++++++ 80 files changed, 431 insertions(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index 1554e62701..d07ab39fa9 100644 --- a/.codespellrc +++ b/.codespellrc @@ -2,4 +2,4 @@ check-filenames = builtin = clear,rare,usage,informal skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h,./src/detection/cpu/cpu_x86.c,./src/detection/gpu/gpu_bsddrm.c,./src/detection/displayserver/linux/wayland/*-protocol.*,./build,./build-*,./build_*,./src/common/impl/genconfig.c -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu,renderD,SME,Carmel,kinda,symbole,connexion,comando,processus,lokale,adres,titel,som,environnement,Sistem,Lokal,Lokal,Sistem,Paket,Hava diff --git a/doc/help.json b/doc/help.json index 4e056a5c8f..1d882d1330 100644 --- a/doc/help.json +++ b/doc/help.json @@ -596,17 +596,22 @@ "enum": { "en": "English", "ar": "Arabic", + "cs": "Czech", "de": "German", "es": "Spanish", "fr": "French", "gl": "Galician", "he": "Hebrew", + "id": "Indonesian", "it": "Italian", "ja": "Japanese", "ko": "Korean", "pl": "Polish", "pt": "Portuguese", "ru": "Russian", + "tr": "Turkish", + "uk": "Ukrainian", + "vi": "Vietnamese", "zh_CN": "Simplified Chinese", "zh_TW": "Traditional Chinese" } diff --git a/doc/json_schema.json b/doc/json_schema.json index d1db924938..9e0aabc34f 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1075,6 +1075,11 @@ "const": "ar", "description": "Arabic" }, + { + "type": "string", + "const": "cs", + "description": "Czech" + }, { "type": "string", "const": "de", @@ -1100,6 +1105,11 @@ "const": "he", "description": "Hebrew" }, + { + "type": "string", + "const": "id", + "description": "Indonesian" + }, { "type": "string", "const": "it", @@ -1130,6 +1140,21 @@ "const": "ru", "description": "Russian" }, + { + "type": "string", + "const": "tr", + "description": "Turkish" + }, + { + "type": "string", + "const": "uk", + "description": "Ukrainian" + }, + { + "type": "string", + "const": "vi", + "description": "Vietnamese" + }, { "type": "string", "const": "zh_CN", diff --git a/src/common/option.h b/src/common/option.h index 1980e80515..0afaa449d1 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -22,17 +22,22 @@ typedef struct FFModuleDisplayName { const char* en; // English const char* ar; // Arabic + const char* cs; // Czech const char* de; // German const char* es; // Spanish const char* fr; // French const char* gl; // Galician const char* he; // Hebrew + const char* id; // Indonesian const char* it; // Italian const char* ja; // Japanese const char* ko; // Korean const char* pl; // Polish const char* pt; // (Brazilian) Portuguese const char* ru; // Russian + const char* tr; // Turkish + const char* uk; // Ukrainian + const char* vi; // Vietnamese const char* zh_CN; // Simplified Chinese const char* zh_TW; // Traditional Chinese } FFModuleDisplayName; diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index ad71499aaa..33e969436b 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -302,17 +302,22 @@ FFModuleBaseInfo ffBatteryModuleInfo = { .displayName = { .en = "Battery", .ar = "البطارية", + .cs = "Baterie", .de = "Akku", .es = "Batería", .fr = "Batterie", .gl = "Batería", .he = "סוללה", + .id = "Baterai", .it = "Batteria", .ja = "バッテリー", .ko = "배터리", .pl = "Bateria", .pt = "Bateria", .ru = "Батарея", + .tr = "Pil", + .uk = "Батарея", + .vi = "Pin", .zh_CN = "电池", .zh_TW = "電池", }, diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 9809067175..fc4f7ac738 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -135,17 +135,22 @@ FFModuleBaseInfo ffBiosModuleInfo = { .displayName = { .en = "BIOS", .ar = "BIOS", + .cs = "BIOS", .de = "BIOS", .es = "BIOS", .fr = "BIOS", .gl = "BIOS", .he = "BIOS", + .id = "BIOS", .it = "BIOS", .ja = "BIOS", .ko = "BIOS", .pl = "BIOS", .pt = "BIOS", .ru = "BIOS", + .tr = "BIOS", + .uk = "BIOS", + .vi = "BIOS", .zh_CN = "BIOS", .zh_TW = "BIOS", }, diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index bd90ec8870..9f69863920 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -156,17 +156,22 @@ FFModuleBaseInfo ffBluetoothModuleInfo = { .displayName = { .en = "Bluetooth", .ar = "بلوتوث", + .cs = "Bluetooth", .de = "Bluetooth", .es = "Bluetooth", .fr = "Bluetooth", .gl = "Bluetooth", .he = "בלוטות'", + .id = "Bluetooth", .it = "Bluetooth", .ja = "ブルートゥース", .ko = "블루투스", .pl = "Bluetooth", .pt = "Bluetooth", .ru = "Bluetooth", + .tr = "Bluetooth", + .uk = "Bluetooth", + .vi = "Bluetooth", .zh_CN = "蓝牙设备", .zh_TW = "藍牙裝置", }, diff --git a/src/modules/bluetoothradio/bluetoothradio.c b/src/modules/bluetoothradio/bluetoothradio.c index 23284244f4..0596fb47eb 100644 --- a/src/modules/bluetoothradio/bluetoothradio.c +++ b/src/modules/bluetoothradio/bluetoothradio.c @@ -193,17 +193,22 @@ FFModuleBaseInfo ffBluetoothRadioModuleInfo = { .displayName = { .en = "Bluetooth Radio", .ar = "راديو بلوتوث", + .cs = "Bluetooth rádio", .de = "Bluetooth-Adapter", .es = "Adaptador Bluetooth", .fr = "Adaptateur Bluetooth", .gl = "Adaptador Bluetooth", .he = "רדיו בלוטות'", + .id = "Radio Bluetooth", .it = "Adattatore Bluetooth", .ja = "ブルートゥースアダプター", .ko = "블루투스 어댑터", .pl = "Adapter Bluetooth", .pt = "Adaptador Bluetooth", .ru = "Bluetooth-адаптер", + .tr = "Bluetooth Radyosu", + .uk = "Радіомодуль Bluetooth", + .vi = "Radio Bluetooth", .zh_CN = "蓝牙适配器", .zh_TW = "藍牙配接器", }, diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 9436c7071f..c0f49baaab 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -113,17 +113,22 @@ FFModuleBaseInfo ffBoardModuleInfo = { .displayName = { .en = "Board", .ar = "اللوحة الأم", + .cs = "Základní deska", .de = "Mainboard", .es = "Placa base", .fr = "Carte mère", .gl = "Placa base", .he = "לוח אם", + .id = "Papan Induk", .it = "Scheda madre", .ja = "マザーボード", .ko = "메인보드", .pl = "Płyta główna", .pt = "Placa-mãe", .ru = "Материнская плата", + .tr = "Anakart", + .uk = "Материнська плата", + .vi = "Bo mạch chủ", .zh_CN = "主板", .zh_TW = "主機板", }, diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 8ad60faf23..45e29bbbb3 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -108,17 +108,22 @@ FFModuleBaseInfo ffBootmgrModuleInfo = { .displayName = { .en = "Boot Manager", .ar = "مدير الإقلاع", + .cs = "Správce spouštění", .de = "Boot-Manager", .es = "Gestor de arranque", .fr = "Gestionnaire de démarrage", .gl = "Xestor de arranque", .he = "מנהל אתחול", + .id = "Manajer Boot", .it = "Gestore di avvio", .ja = "ブートマネージャー", .ko = "부트 매니저", .pl = "Menedżer rozruchu", .pt = "Gerenciador de inicialização", .ru = "Менеджер загрузки", + .tr = "Önyükleme Yöneticisi", + .uk = "Менеджер завантаження", + .vi = "Trình quản lý khởi động", .zh_CN = "启动管理器", .zh_TW = "啟動管理器", }, diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 751694abdf..5a6f356732 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -32,17 +32,22 @@ FFModuleBaseInfo ffBreakModuleInfo = { .displayName = { .en = "Break", .ar = "فاصل", + .cs = "Konec řádku", .de = "Umbruch", .es = "Salto de línea", .fr = "Saut de ligne", .gl = "Salto de liña", .he = "מעבר שורה", + .id = "Baris Baru", .it = "Interruzione", .ja = "改行", .ko = "줄 바꿈", .pl = "Przerwa", .pt = "Quebra", .ru = "Разрыв", + .tr = "Satır Sonu", + .uk = "Розрив рядка", + .vi = "Xuống dòng", .zh_CN = "换行", .zh_TW = "換行", }, diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index d018a4dcd8..5c6fc15449 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -195,17 +195,22 @@ FFModuleBaseInfo ffBrightnessModuleInfo = { .displayName = { .en = "Brightness", .ar = "السطوع", + .cs = "Jas", .de = "Helligkeit", .es = "Brillo", .fr = "Luminosité", .gl = "Brillo", .he = "בהירות", + .id = "Kecerahan", .it = "Luminosità", .ja = "明るさ", .ko = "밝기", .pl = "Jasność", .pt = "Brilho", .ru = "Яркость", + .tr = "Parlaklık", + .uk = "Яскравість", + .vi = "Độ sáng", .zh_CN = "亮度", .zh_TW = "亮度", }, diff --git a/src/modules/btrfs/btrfs.c b/src/modules/btrfs/btrfs.c index fc41ef402c..052cf32dcb 100644 --- a/src/modules/btrfs/btrfs.c +++ b/src/modules/btrfs/btrfs.c @@ -203,17 +203,22 @@ FFModuleBaseInfo ffBtrfsModuleInfo = { .displayName = { .en = "BTRFS", .ar = "BTRFS", + .cs = "BTRFS", .de = "BTRFS", .es = "BTRFS", .fr = "BTRFS", .gl = "BTRFS", .he = "BTRFS", + .id = "BTRFS", .it = "BTRFS", .ja = "BTRFS", .ko = "BTRFS", .pl = "BTRFS", .pt = "BTRFS", .ru = "BTRFS", + .tr = "BTRFS", + .uk = "BTRFS", + .vi = "BTRFS", .zh_CN = "BTRFS", .zh_TW = "BTRFS", }, diff --git a/src/modules/camera/camera.c b/src/modules/camera/camera.c index 1dcc89e193..95101c23db 100644 --- a/src/modules/camera/camera.c +++ b/src/modules/camera/camera.c @@ -120,17 +120,22 @@ FFModuleBaseInfo ffCameraModuleInfo = { .displayName = { .en = "Camera", .ar = "الكاميرا", + .cs = "Kamera", .de = "Kamera", .es = "Cámara", .fr = "Caméra", .gl = "Cámara", .he = "מצלמה", + .id = "Kamera", .it = "Fotocamera", .ja = "カメラ", .ko = "카메라", .pl = "Kamera", .pt = "Câmera", .ru = "Камера", + .tr = "Kamera", + .uk = "Камера", + .vi = "Máy ảnh", .zh_CN = "摄像头", .zh_TW = "攝像頭", }, diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 7ba77a0d05..6049d533d5 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -115,17 +115,22 @@ FFModuleBaseInfo ffChassisModuleInfo = { .displayName = { .en = "Chassis", .ar = "الهيكل", + .cs = "Skříň", .de = "Gehäuse", .es = "Chasis", .fr = "Châssis", .gl = "Chasis", .he = "מארז", + .id = "Casing", .it = "Telaio", .ja = "シャーシ", .ko = "섀시", .pl = "Obudowa", .pt = "Chassi", .ru = "Корпус", + .tr = "Kasa", + .uk = "Корпус", + .vi = "Vỏ máy", .zh_CN = "机箱", .zh_TW = "機箱", }, diff --git a/src/modules/codec/codec.c b/src/modules/codec/codec.c index d5c1d0e960..2e5b87983b 100644 --- a/src/modules/codec/codec.c +++ b/src/modules/codec/codec.c @@ -256,17 +256,22 @@ FFModuleBaseInfo ffCodecModuleInfo = { .displayName = { .en = "Codec", .ar = "الترميز", + .cs = "Kodek", .de = "Codec", .es = "Códec", .fr = "Codec", .gl = "Códec", .he = "קודק", + .id = "Kodek", .it = "Codec", .ja = "コーデック", .ko = "코덱", .pl = "Kodek", .pt = "Codec", .ru = "Кодек", + .tr = "Kodek", + .uk = "Кодек", + .vi = "Codec", .zh_CN = "编解码器", .zh_TW = "編解碼器", }, diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 2f33f91623..b9fa813e72 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -300,17 +300,22 @@ FFModuleBaseInfo ffColorsModuleInfo = { .displayName = { .en = "Colors", .ar = "الألوان", + .cs = "Barvy", .de = "Farben", .es = "Colores", .fr = "Couleurs", .gl = "Cores", .he = "צבעים", + .id = "Warna", .it = "Colori", .ja = "色", .ko = "색상", .pl = "Kolory", .pt = "Cores", .ru = "Цвета", + .tr = "Renkler", + .uk = "Кольори", + .vi = "Màu sắc", .zh_CN = "颜色", .zh_TW = "顏色", }, diff --git a/src/modules/command/command.c b/src/modules/command/command.c index 6878af3f21..21ac4378c5 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -158,17 +158,22 @@ FFModuleBaseInfo ffCommandModuleInfo = { .displayName = { .en = "Command", .ar = "الأمر", + .cs = "Příkaz", .de = "Befehl", .es = "Comando", .fr = "Commande", .gl = "Comando", .he = "פקודה", + .id = "Perintah", .it = "Comando", .ja = "コマンド", .ko = "명령어", .pl = "Polecenie", .pt = "Comando", .ru = "Команда", + .tr = "Komut", + .uk = "Команда", + .vi = "Lệnh", .zh_CN = "命令", .zh_TW = "命令", }, diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 23f652b772..9d52576873 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -256,17 +256,22 @@ FFModuleBaseInfo ffCPUModuleInfo = { .displayName = { .en = "CPU", .ar = "المعالج", + .cs = "CPU", .de = "CPU", .es = "CPU", .fr = "CPU", .gl = "CPU", .he = "מעבד", + .id = "CPU", .it = "CPU", .ja = "CPU", .ko = "CPU", .pl = "CPU", .pt = "CPU", .ru = "Процессор", + .tr = "CPU", + .uk = "CPU", + .vi = "CPU", .zh_CN = "CPU", .zh_TW = "CPU", }, diff --git a/src/modules/cpucache/cpucache.c b/src/modules/cpucache/cpucache.c index 55d92baa33..efb9407e45 100644 --- a/src/modules/cpucache/cpucache.c +++ b/src/modules/cpucache/cpucache.c @@ -226,17 +226,22 @@ FFModuleBaseInfo ffCPUCacheModuleInfo = { .displayName = { .en = "CPU Cache", .ar = "ذاكرة المعالج المؤقتة", + .cs = "Mezipaměť CPU", .de = "CPU-Cache", .es = "Caché de la CPU", .fr = "Cache CPU", .gl = "Caché da CPU", .he = "מטמון מעבד", + .id = "Cache CPU", .it = "Cache CPU", .ja = "CPUキャッシュ", .ko = "CPU 캐시", .pl = "Pamięć podręczna CPU", .pt = "Cache da CPU", .ru = "Кэш процессора", + .tr = "CPU Önbelleği", + .uk = "Кеш ЦП", + .vi = "Bộ nhớ đệm CPU", .zh_CN = "CPU缓存", .zh_TW = "CPU快取記憶體", }, diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 3670ced0da..96c45c28d2 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -184,17 +184,22 @@ FFModuleBaseInfo ffCPUUsageModuleInfo = { .displayName = { .en = "CPU Usage", .ar = "استخدام المعالج", + .cs = "Využití CPU", .de = "CPU-Auslastung", .es = "Uso de la CPU", .fr = "Utilisation du CPU", .gl = "Uso da CPU", .he = "שימוש במעבד", + .id = "Penggunaan CPU", .it = "Utilizzo della CPU", .ja = "CPU使用率", .ko = "CPU 사용량", .pl = "Użycie CPU", .pt = "Uso da CPU", .ru = "Использование процессора", + .tr = "CPU Kullanımı", + .uk = "Використання ЦП", + .vi = "Mức sử dụng CPU", .zh_CN = "CPU使用率", .zh_TW = "CPU使用率", }, diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 54f605bb65..7bc274802c 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -105,17 +105,22 @@ FFModuleBaseInfo ffCursorModuleInfo = { .displayName = { .en = "Cursor", .ar = "المؤشر", + .cs = "Kurzor", .de = "Mauszeiger", .es = "Cursor", .fr = "Curseur", .gl = "Cursor", .he = "סמן", + .id = "Kursor", .it = "Cursore", .ja = "カーソル", .ko = "커서", .pl = "Kursor", .pt = "Cursor", .ru = "Курсор", + .tr = "İmleç", + .uk = "Курсор", + .vi = "Con trỏ", .zh_CN = "光标", .zh_TW = "游標", }, diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index c29bea05cd..79c3d02f80 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -40,16 +40,21 @@ FFModuleBaseInfo ffCustomModuleInfo = { .displayName = { .en = "Custom", .ar = "مخصص", + .cs = "Vlastní", .de = "Benutzerdefiniert", .es = "Personalizado", .fr = "Personnalisé", .he = "מותאם אישית", + .id = "Kustom", .it = "Personalizzato", .ja = "カスタム", .ko = "사용자 정의", .pl = "Niestandardowy", .pt = "Personalizado", .ru = "Пользовательский", + .tr = "Özel", + .uk = "Власний", + .vi = "Tùy chỉnh", .zh_CN = "自定义", .zh_TW = "自訂", }, diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 46131bcd5d..1a7b12f253 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -155,17 +155,22 @@ FFModuleBaseInfo ffDateTimeModuleInfo = { .displayName = { .en = "Date & Time", .ar = "التاريخ والوقت", + .cs = "Datum a čas", .de = "Datum & Uhrzeit", .es = "Fecha y hora", .fr = "Date et heure", .gl = "Data e hora", .he = "תאריך ושעה", + .id = "Tanggal & Waktu", .it = "Data e ora", .ja = "日付と時刻", .ko = "날짜/시간", .pl = "Data i godzina", .pt = "Data e hora", .ru = "Дата и время", + .tr = "Tarih ve Saat", + .uk = "Дата й час", + .vi = "Ngày giờ", .zh_CN = "日期时间", .zh_TW = "日期時間", }, diff --git a/src/modules/de/de.c b/src/modules/de/de.c index b1942d6948..a7bb99c3a2 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -87,17 +87,22 @@ FFModuleBaseInfo ffDEModuleInfo = { .displayName = { .en = "Desktop Environment", .ar = "بيئة سطح المكتب", + .cs = "Pracovní prostředí", .de = "Desktop-Umgebung", .es = "Entorno de escritorio", .fr = "Environnement de Bureau", .gl = "Contorno do Escritorio", .he = "סביבת שולחן עבודה", + .id = "Lingkungan Desktop", .it = "Ambiente Desktop", .ja = "デスクトップ環境", .ko = "데스크탑 환경", .pl = "Środowisko graficzne", .pt = "Ambiente de desktop", .ru = "Рабочее окружение", + .tr = "Masaüstü Ortamı", + .uk = "Стільниче середовище", + .vi = "Môi trường desktop", .zh_CN = "桌面环境", .zh_TW = "桌面環境", }, diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 2d80a18a54..da6fe9faba 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -456,17 +456,22 @@ FFModuleBaseInfo ffDiskModuleInfo = { .displayName = { .en = "Disk", .ar = "القرص", + .cs = "Disk", .de = "Festplatte", .es = "Disco", .fr = "Disque", .gl = "Disco", .he = "דיסק", + .id = "Disk", .it = "Disco", .ja = "ディスク", .ko = "디스크", .pl = "Dysk", .pt = "Disco", .ru = "Диск", + .tr = "Disk", + .uk = "Диск", + .vi = "Ổ đĩa", .zh_CN = "磁盘分区", .zh_TW = "硬碟分割", }, diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index e76f093647..71f6970d8c 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -175,17 +175,22 @@ FFModuleBaseInfo ffDiskIOModuleInfo = { .displayName = { .en = "Disk I/O", .ar = "إدخال/إخراج القرص", + .cs = "Diskové I/O", .de = "Festplatten I/O", .es = "E/S del disco", .fr = "Entrée/Sortie disque", .gl = "E/S do disco", .he = "קלט/פלט דיסק", + .id = "I/O Disk", .it = "I/O del disco", .ja = "ディスク I/O", .ko = "디스크 I/O", .pl = "Dysk I/O", .pt = "Disco I/O", .ru = "Дисковый I/O", + .tr = "Disk G/Ç", + .uk = "Диск В/В", + .vi = "Đĩa I/O", .zh_CN = "磁盘 I/O", .zh_TW = "磁碟 I/O", }, diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 4eda352331..8d169d7db2 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -416,17 +416,22 @@ FFModuleBaseInfo ffDisplayModuleInfo = { .displayName = { .en = "Display", .ar = "الشاشة", + .cs = "Displej", .de = "Anzeige", .es = "Pantalla", .fr = "Écran", .gl = "Pantalla", .he = "תצוגה", + .id = "Tampilan", .it = "Display", .ja = "ディスプレイ", .ko = "디스플레이", .pl = "Wyświetlacz", .pt = "Tela", .ru = "Дисплей", + .tr = "Ekran", + .uk = "Дисплей", + .vi = "Hiển thị", .zh_CN = "显示器", .zh_TW = "顯示器", }, diff --git a/src/modules/dns/dns.c b/src/modules/dns/dns.c index c0f20d2c54..517deb4add 100644 --- a/src/modules/dns/dns.c +++ b/src/modules/dns/dns.c @@ -139,17 +139,22 @@ FFModuleBaseInfo ffDNSModuleInfo = { .displayName = { .en = "DNS", .ar = "DNS", + .cs = "DNS", .de = "DNS", .es = "DNS", .fr = "DNS", .gl = "DNS", .he = "DNS", + .id = "DNS", .it = "DNS", .ja = "DNS", .ko = "DNS", .pl = "DNS", .pt = "DNS", .ru = "DNS", + .tr = "DNS", + .uk = "DNS", + .vi = "DNS", .zh_CN = "DNS", .zh_TW = "DNS", }, diff --git a/src/modules/editor/editor.c b/src/modules/editor/editor.c index 7d04c8445a..b55a24c69d 100644 --- a/src/modules/editor/editor.c +++ b/src/modules/editor/editor.c @@ -108,17 +108,22 @@ FFModuleBaseInfo ffEditorModuleInfo = { .displayName = { .en = "Editor", .ar = "المحرر", + .cs = "Editor", .de = "Editor", .es = "Editor", .fr = "Éditeur", .gl = "Editor", .he = "עורך", + .id = "Editor", .it = "Editor", .ja = "エディター", .ko = "편집기", .pl = "Edytor", .pt = "Editor", .ru = "Редактор", + .tr = "Düzenleyici", + .uk = "Редактор", + .vi = "Trình soạn thảo", .zh_CN = "编辑器", .zh_TW = "編輯器", }, diff --git a/src/modules/font/font.c b/src/modules/font/font.c index dfbdd712fe..47b6d8f2d2 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -100,17 +100,22 @@ FFModuleBaseInfo ffFontModuleInfo = { .displayName = { .en = "Font", .ar = "الخط", + .cs = "Písmo", .de = "Schriftart", .es = "Fuente", .fr = "Police", .gl = "Fonte", .he = "גופן", + .id = "Font", .it = "Carattere", .ja = "フォント", .ko = "글꼴", .pl = "Czcionka", .pt = "Fonte", .ru = "Шрифт", + .tr = "Yazı Tipi", + .uk = "Шрифт", + .vi = "Phông chữ", .zh_CN = "字体", .zh_TW = "字型", }, diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index ae31b96cbf..470abd8e32 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -194,17 +194,22 @@ FFModuleBaseInfo ffGamepadModuleInfo = { .displayName = { .en = "Gamepad", .ar = "يد التحكم", + .cs = "Gamepad", .de = "Gamepad", .es = "Gamepad", .fr = "Manette", .gl = "Gamepad", .he = "משטח משחק", + .id = "Gamepad", .it = "Gamepad", .ja = "ゲームパッド", .ko = "게임패드", .pl = "Gamepad", .pt = "Gamepad", .ru = "Геймпад", + .tr = "Oyun Kumandası", + .uk = "Геймпад", + .vi = "Tay cầm chơi game", .zh_CN = "游戏手柄", .zh_TW = "遊戲手把", }, diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 1292a62568..159cbaf6b2 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -484,17 +484,22 @@ FFModuleBaseInfo ffGPUModuleInfo = { .displayName = { .en = "GPU", .ar = "معالج الرسوميات", + .cs = "GPU", .de = "GPU", .es = "GPU", .fr = "GPU", .gl = "GPU", .he = "מעבד גרפי", + .id = "GPU", .it = "GPU", .ja = "GPU", .ko = "GPU", .pl = "GPU", .pt = "GPU", .ru = "Видеокарта", + .tr = "GPU", + .uk = "GPU", + .vi = "GPU", .zh_CN = "显卡", .zh_TW = "顯卡", }, diff --git a/src/modules/host/host.c b/src/modules/host/host.c index a79fbdc3b3..ef72887766 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -141,17 +141,22 @@ FFModuleBaseInfo ffHostModuleInfo = { .displayName = { .en = "Host", .ar = "المضيف", + .cs = "Hostitel", .de = "Rechner", .es = "Host", .fr = "Hôte", .gl = "Host", .he = "מארח", + .id = "Host", .it = "Host", .ja = "ホスト", .ko = "호스트", .pl = "Host", .pt = "Host", .ru = "Модель", + .tr = "Ana Bilgisayar", + .uk = "Хост", + .vi = "Máy chủ", .zh_CN = "主机", .zh_TW = "主機", }, diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index c8b9d8cb4b..358cc3dbaa 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -99,17 +99,22 @@ FFModuleBaseInfo ffIconsModuleInfo = { .displayName = { .en = "Icons", .ar = "الأيقونات", + .cs = "Ikony", .de = "Symbole", .es = "Iconos", .fr = "Icônes", .gl = "Iconas", .he = "סמלים", + .id = "Ikon", .it = "Icone", .ja = "アイコン", .ko = "아이콘", .pl = "Ikony", .pt = "Ícones", .ru = "Иконки", + .tr = "Simgeler", + .uk = "Піктограми", + .vi = "Biểu tượng", .zh_CN = "图标", .zh_TW = "圖示", }, diff --git a/src/modules/initsystem/initsystem.c b/src/modules/initsystem/initsystem.c index f5f4238fdf..3b5db0d8b1 100644 --- a/src/modules/initsystem/initsystem.c +++ b/src/modules/initsystem/initsystem.c @@ -106,17 +106,22 @@ FFModuleBaseInfo ffInitSystemModuleInfo = { .displayName = { .en = "Init System", .ar = "نظام الإقلاع", + .cs = "Init systém", .de = "Init-System", .es = "Sistema de inicio", .fr = "Système d'init", .gl = "Sistema de inicio", .he = "מערכת אתחול", + .id = "Sistem Init", .it = "Sistema di init", .ja = "initシステム", .ko = "초기화 시스템", .pl = "System init", .pt = "Sistema de inicialização", .ru = "Система инициализации", + .tr = "Init Sistemi", + .uk = "Init-система", + .vi = "Hệ thống init", .zh_CN = "Init 系统", .zh_TW = "Init 系統", }, diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 3e8334e2c1..7c3165ac38 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -67,17 +67,22 @@ FFModuleBaseInfo ffKernelModuleInfo = { .displayName = { .en = "Kernel", .ar = "النواة", + .cs = "Jádro", .de = "Kernel", .es = "Kernel", .fr = "Kernel", .gl = "Kernel", .he = "ליבה", + .id = "Kernel", .it = "Kernel", .ja = "カーネル", .ko = "커널", .pl = "Jądro", .pt = "Kernel", .ru = "Ядро", + .tr = "Çekirdek", + .uk = "Ядро", + .vi = "Nhân", .zh_CN = "内核", .zh_TW = "核心", }, diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c index df7b2cef68..b1ff758717 100644 --- a/src/modules/keyboard/keyboard.c +++ b/src/modules/keyboard/keyboard.c @@ -154,17 +154,22 @@ FFModuleBaseInfo ffKeyboardModuleInfo = { .displayName = { .en = "Keyboard", .ar = "لوحة المفاتيح", + .cs = "Klávesnice", .de = "Tastatur", .es = "Teclado", .fr = "Clavier", .gl = "Teclado", .he = "מקלדת", + .id = "Papan Ketik", .it = "Tastiera", .ja = "キーボード", .ko = "키보드", .pl = "Klawiatura", .pt = "Teclado", .ru = "Клавиатура", + .tr = "Klavye", + .uk = "Клавіатура", + .vi = "Bàn phím", .zh_CN = "键盘", .zh_TW = "鍵盤", }, diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 88b7b0ed41..ca9debe115 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -111,17 +111,22 @@ FFModuleBaseInfo ffLMModuleInfo = { .displayName = { .en = "Login Manager", .ar = "مدير تسجيل الدخول", + .cs = "Správce přihlášení", .de = "Anmeldemanager", .es = "Gestor de inicio de sesión", .fr = "Gestionnaire de connexion", .gl = "Xestor de inicio de sesión", .he = "מנהל התחברות", + .id = "Manajer Login", .it = "Gestore di accesso", .ja = "ログインマネージャー", .ko = "로그인 관리자", .pl = "Menedżer logowania", .pt = "Gerenciador de login", .ru = "Менеджер входа", + .tr = "Oturum Açma Yöneticisi", + .uk = "Менеджер входу", + .vi = "Trình quản lý đăng nhập", .zh_CN = "登录管理器", .zh_TW = "登入管理器", }, diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index a23c3edf6f..40aa8115bb 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -153,17 +153,22 @@ FFModuleBaseInfo ffLoadavgModuleInfo = { .displayName = { .en = "Load Average", .ar = "متوسط الحمل", + .cs = "Průměrná zátěž", .de = "Systemlast", .es = "Promedio de carga", .fr = "Charge moyenne", .gl = "Carga media", .he = "עומס ממוצע", + .id = "Beban Rata-rata", .it = "Carico medio", .ja = "ロードアベレージ", .ko = "시스템 부하 평균", .pl = "Średnie obciążenie", .pt = "Média de carga", .ru = "Средняя нагрузка", + .tr = "Sistem Yükü", + .uk = "Середнє навантаження", + .vi = "Tải trung bình", .zh_CN = "系统负载", .zh_TW = "系統負載", }, diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 835937a0e6..4c91a04f56 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -72,17 +72,22 @@ FFModuleBaseInfo ffLocaleModuleInfo = { .displayName = { .en = "Locale", .ar = "اللغة", + .cs = "Národní prostředí", .de = "Sprachraum", .es = "Configuración regional", .fr = "Paramètres régionaux", .gl = "Configuración rexional", .he = "לוקאל", + .id = "Lokal", .it = "Impostazioni locali", .ja = "ロケール", .ko = "로케일", .pl = "Ustawienia regionalne", .pt = "Configuração regional", .ru = "Локаль", + .tr = "Yerel Ayar", + .uk = "Локаль", + .vi = "Bản địa", .zh_CN = "语言环境", .zh_TW = "語言環境", }, diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 13a4692c70..c1c53be23a 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -426,17 +426,22 @@ FFModuleBaseInfo ffLocalIPModuleInfo = { .displayName = { .en = "Local IP", .ar = "عنوان IP المحلي", + .cs = "Místní IP", .de = "Lokale IP", .es = "IP local", .fr = "IP locale", .gl = "IP local", .he = "IP מקומי", + .id = "IP Lokal", .it = "IP locale", .ja = "ローカル IP", .ko = "로컬 IP", .pl = "Lokalny adres IP", .pt = "IP local", .ru = "Локальный IP", + .tr = "Yerel IP", + .uk = "Локальна IP", + .vi = "IP cục bộ", .zh_CN = "本地 IP", .zh_TW = "區域 IP", }, diff --git a/src/modules/logo/logo.c b/src/modules/logo/logo.c index 4f73084f99..dfa92ce06d 100644 --- a/src/modules/logo/logo.c +++ b/src/modules/logo/logo.c @@ -82,17 +82,22 @@ FFModuleBaseInfo ffLogoModuleInfo = { .displayName = { .en = "Logo", .ar = "الشعار", + .cs = "Logo", .de = "Logo", .es = "Logo", .fr = "Logo", .gl = "Logo", .he = "לוגו", + .id = "Logo", .it = "Logo", .ja = "ロゴ", .ko = "로고", .pl = "Logo", .pt = "Logo", .ru = "Логотип", + .tr = "Logo", + .uk = "Логотип", + .vi = "Logo", .zh_CN = "徽标", .zh_TW = "標誌", }, diff --git a/src/modules/media/media.c b/src/modules/media/media.c index da5c13c423..6090e6eca2 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -258,17 +258,22 @@ FFModuleBaseInfo ffMediaModuleInfo = { .displayName = { .en = "Media", .ar = "الوسائط", + .cs = "Média", .de = "Medien", .es = "Multimedia", .fr = "Médias", .gl = "Multimedia", .he = "מדיה", + .id = "Media", .it = "Media", .ja = "メディア", .ko = "미디어", .pl = "Media", .pt = "Mídia", .ru = "Медиа", + .tr = "Medya", + .uk = "Медіа", + .vi = "Phương tiện", .zh_CN = "媒体", .zh_TW = "媒體", }, diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index d338d177e9..6e4092d224 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -123,17 +123,22 @@ FFModuleBaseInfo ffMemoryModuleInfo = { .displayName = { .en = "Memory", .ar = "الذاكرة", + .cs = "Paměť", .de = "Speicher", .es = "Memoria", .fr = "Mémoire", .gl = "Memoria", .he = "זיכרון", + .id = "Memori", .it = "Memoria", .ja = "メモリ", .ko = "메모리", .pl = "Pamięć", .pt = "Memória", .ru = "Память", + .tr = "Bellek", + .uk = "Пам'ять", + .vi = "Bộ nhớ", .zh_CN = "内存", .zh_TW = "記憶體", }, diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 13cf741249..b5ac69f696 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -109,17 +109,22 @@ FFModuleBaseInfo ffMonitorModuleInfo = { .displayName = { .en = "Monitor", .ar = "الشاشة", + .cs = "Monitor", .de = "Monitor", .es = "Monitor", .fr = "Moniteur", .gl = "Monitor", .he = "צג", + .id = "Monitor", .it = "Monitor", .ja = "モニター", .ko = "모니터", .pl = "Monitor", .pt = "Monitor", .ru = "Монитор", + .tr = "Monitör", + .uk = "Монітор", + .vi = "Màn hình", .zh_CN = "监视器", .zh_TW = "監視器", }, diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c index f8f06a9374..293f319312 100644 --- a/src/modules/mouse/mouse.c +++ b/src/modules/mouse/mouse.c @@ -157,17 +157,22 @@ FFModuleBaseInfo ffMouseModuleInfo = { .displayName = { .en = "Mouse", .ar = "الفأرة", + .cs = "Myš", .de = "Maus", .es = "Ratón", .fr = "Souris", .gl = "Rato", .he = "עכבר", + .id = "Tetikus", .it = "Mouse", .ja = "マウス", .ko = "마우스", .pl = "Mysz", .pt = "Mouse", .ru = "Мышь", + .tr = "Fare", + .uk = "Миша", + .vi = "Chuột", .zh_CN = "鼠标", .zh_TW = "滑鼠", }, diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 2bc95d6158..0729b444e7 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -202,17 +202,22 @@ FFModuleBaseInfo ffNetIOModuleInfo = { .displayName = { .en = "Network I/O", .ar = "إدخال/إخراج الشبكة", + .cs = "Síťové I/O", .de = "Netzwerk I/O", .es = "E/S de la red", .fr = "E/S réseau", .gl = "E/S da rede", .he = "קלט/פלט רשת", + .id = "I/O Jaringan", .it = "I/O di rete", .ja = "ネットワークI/O", .ko = "네트워크 I/O", .pl = "I/O sieciowe", .pt = "E/S de rede", .ru = "Сетевой I/O", + .tr = "Ağ G/Ç", + .uk = "Мережа В/В", + .vi = "Mạng I/O", .zh_CN = "网络 I/O", .zh_TW = "網路 I/O", }, diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index c13c8c2d9a..c483c430d1 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -125,17 +125,22 @@ FFModuleBaseInfo ffOpenCLModuleInfo = { .displayName = { .en = "OpenCL", .ar = "OpenCL", + .cs = "OpenCL", .de = "OpenCL", .es = "OpenCL", .fr = "OpenCL", .gl = "OpenCL", .he = "OpenCL", + .id = "OpenCL", .it = "OpenCL", .ja = "OpenCL", .ko = "OpenCL", .pl = "OpenCL", .pt = "OpenCL", .ru = "OpenCL", + .tr = "OpenCL", + .uk = "OpenCL", + .vi = "OpenCL", .zh_CN = "OpenCL", .zh_TW = "OpenCL", }, diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 4b325cbecf..0ef5472c88 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -132,17 +132,22 @@ FFModuleBaseInfo ffOpenGLModuleInfo = { .displayName = { .en = "OpenGL", .ar = "OpenGL", + .cs = "OpenGL", .de = "OpenGL", .es = "OpenGL", .fr = "OpenGL", .gl = "OpenGL", .he = "OpenGL", + .id = "OpenGL", .it = "OpenGL", .ja = "OpenGL", .ko = "OpenGL", .pl = "OpenGL", .pt = "OpenGL", .ru = "OpenGL", + .tr = "OpenGL", + .uk = "OpenGL", + .vi = "OpenGL", .zh_CN = "OpenGL", .zh_TW = "OpenGL", }, diff --git a/src/modules/os/os.c b/src/modules/os/os.c index 51c89cbba5..12dd2740aa 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -177,17 +177,22 @@ FFModuleBaseInfo ffOSModuleInfo = { .displayName = { .en = "OS", .ar = "نظام التشغيل", + .cs = "OS", .de = "Betriebssystem", .es = "Sistema operativo", .fr = "Système d'exploitation", .gl = "Sistema operativo", .he = "מערכת הפעלה", + .id = "OS", .it = "Sistema operativo", .ja = "オペレーティングシステム", .ko = "운영 체제", .pl = "System operacyjny", .pt = "Sistema operacional", .ru = "Операционная система", + .tr = "İşletim Sistemi", + .uk = "ОС", + .vi = "Hệ điều hành", .zh_CN = "操作系统", .zh_TW = "操作系統", }, diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index fc39603b47..f31275a86a 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -515,17 +515,22 @@ FFModuleBaseInfo ffPackagesModuleInfo = { .displayName = { .en = "Packages", .ar = "الحزم", + .cs = "Balíčky", .de = "Pakete", .es = "Paquetes", .fr = "Paquets", .gl = "Paquetes", .he = "חבילות", + .id = "Paket", .it = "Pacchetti", .ja = "パッケージ", .ko = "패키지", .pl = "Pakiety", .pt = "Pacotes", .ru = "Пакеты", + .tr = "Paketler", + .uk = "Пакети", + .vi = "Gói phần mềm", .zh_CN = "软件包", .zh_TW = "軟體包", }, diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index a4e7bb0f81..3b396d1f74 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -268,17 +268,22 @@ FFModuleBaseInfo ffPhysicalDiskModuleInfo = { .displayName = { .en = "Physical Disk", .ar = "القرص الفعلي", + .cs = "Fyzický disk", .de = "Physische Festplatte", .es = "Disco físico", .fr = "Disque physique", .gl = "Disco físico", .he = "דיסק פיזי", + .id = "Disk Fisik", .it = "Disco fisico", .ja = "物理ディスク", .ko = "물리 디스크", .pl = "Dysk fizyczny", .pt = "Disco físico", .ru = "Физический диск", + .tr = "Fiziksel Disk", + .uk = "Фізичний диск", + .vi = "Ổ đĩa vật lý", .zh_CN = "物理磁盘", .zh_TW = "物理磁碟", }, diff --git a/src/modules/physicalmemory/physicalmemory.c b/src/modules/physicalmemory/physicalmemory.c index 4c9ee7001a..a374422e65 100644 --- a/src/modules/physicalmemory/physicalmemory.c +++ b/src/modules/physicalmemory/physicalmemory.c @@ -162,17 +162,22 @@ FFModuleBaseInfo ffPhysicalMemoryModuleInfo = { .displayName = { .en = "Physical Memory", .ar = "الذاكرة الفعلية", + .cs = "Fyzická paměť", .de = "Physischer Speicher", .es = "Memoria física", .fr = "Mémoire physique", .gl = "Memoria física", .he = "זיכרון פיזי", + .id = "Memori Fisik", .it = "Memoria fisica", .ja = "物理メモリ", .ko = "물리 메모리", .pl = "Pamięć fizyczna", .pt = "Memória física", .ru = "Физическая память", + .tr = "Fiziksel Bellek", + .uk = "Фізична пам'ять", + .vi = "Bộ nhớ vật lý", .zh_CN = "物理内存", .zh_TW = "實體記憶體", }, diff --git a/src/modules/player/player.c b/src/modules/player/player.c index c5bdfcf13d..1474494c2e 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -112,17 +112,22 @@ FFModuleBaseInfo ffPlayerModuleInfo = { .displayName = { .en = "Media Player", .ar = "مشغل الوسائط", + .cs = "Přehrávač médií", .de = "Medienplayer", .es = "Reproductor multimedia", .fr = "Lecteur multimédia", .gl = "Reprodutor multimedia", .he = "נגן מדיה", + .id = "Pemutar Media", .it = "Lettore multimediale", .ja = "メディアプレイヤー", .ko = "미디어 플레이어", .pl = "Odtwarzacz multimediów", .pt = "Reprodutor de mídia", .ru = "Медиаплеер", + .tr = "Medya Oynatıcı", + .uk = "Медіаплеєр", + .vi = "Trình phát phương tiện", .zh_CN = "媒体播放器", .zh_TW = "媒體播放器", }, diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 5d8d2e2c15..2174a1b266 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -113,17 +113,22 @@ FFModuleBaseInfo ffPowerAdapterModuleInfo = { .displayName = { .en = "Power Adapter", .ar = "محول الطاقة", + .cs = "Napájecí adaptér", .de = "Netzteil", .es = "Adaptador de corriente", .fr = "Adaptateur secteur", .gl = "Adaptador de corrente", .he = "מתאם מתח", + .id = "Adaptor Daya", .it = "Alimentatore", .ja = "電源アダプター", .ko = "전원 어댑터", .pl = "Zasilacz", .pt = "Fonte de alimentação", .ru = "Адаптер питания", + .tr = "Güç Adaptörü", + .uk = "Блок живлення", + .vi = "Bộ chuyển đổi nguồn", .zh_CN = "电源适配器", .zh_TW = "電源轉接器", }, diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index a73c2c4639..4281204562 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -68,17 +68,22 @@ FFModuleBaseInfo ffProcessesModuleInfo = { .displayName = { .en = "Processes", .ar = "العمليات", + .cs = "Procesy", .de = "Prozesse", .es = "Procesos", .fr = "Processus", .gl = "Procesos", .he = "תהליכים", + .id = "Proses", .it = "Processi", .ja = "プロセス", .ko = "프로세스", .pl = "Procesy", .pt = "Processos", .ru = "Процессы", + .tr = "Süreçler", + .uk = "Процеси", + .vi = "Tiến trình", .zh_CN = "进程数", .zh_TW = "進程數", }, diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 110b0dfc84..e93f34e091 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -113,17 +113,22 @@ FFModuleBaseInfo ffPublicIPModuleInfo = { .displayName = { .en = "Public IP", .ar = "عنوان IP العام", + .cs = "Veřejná IP", .de = "Öffentliche IP", .es = "IP pública", .fr = "IP publique", .gl = "IP pública", .he = "IP ציבורי", + .id = "IP Publik", .it = "IP pubblica", .ja = "パブリックIP", .ko = "공용 IP", .pl = "Publiczne IP", .pt = "IP público", .ru = "Внешний IP", + .tr = "Genel IP", + .uk = "Публічна IP", + .vi = "IP công khai", .zh_CN = "公网 IP", .zh_TW = "公網 IP", }, diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 0c19a89cca..60ab8e1cea 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -126,17 +126,22 @@ FFModuleBaseInfo ffSeparatorModuleInfo = { .displayName = { .en = "Separator", .ar = "الفاصل", + .cs = "Oddělovač", .de = "Trennlinie", .es = "Separador", .fr = "Séparateur", .gl = "Separador", .he = "מפריד", + .id = "Pemisah", .it = "Separatore", .ja = "セパレーター", .ko = "구분선", .pl = "Separator", .pt = "Separador", .ru = "Разделитель", + .tr = "Ayraç", + .uk = "Роздільник", + .vi = "Dấu phân cách", .zh_CN = "分隔线", .zh_TW = "分隔線", }, diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index bce575b2a0..849a905bec 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -94,17 +94,22 @@ FFModuleBaseInfo ffShellModuleInfo = { .displayName = { .en = "Shell", .ar = "الصدفة", + .cs = "Shell", .de = "Shell", .es = "Shell", .fr = "Shell", .gl = "Shell", .he = "מעטפת", + .id = "Shell", .it = "Shell", .ja = "シェル", .ko = "셸", .pl = "Powłoka", .pt = "Shell", .ru = "Оболочка", + .tr = "Kabuk", + .uk = "Оболонка", + .vi = "Shell", .zh_CN = "命令行解释器", .zh_TW = "命令列直譯器", }, diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 0c6436833b..dc506efb1d 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -204,17 +204,22 @@ FFModuleBaseInfo ffSoundModuleInfo = { .displayName = { .en = "Sound", .ar = "الصوت", + .cs = "Zvuk", .de = "Sound", .es = "Sonido", .fr = "Son", .gl = "Son", .he = "קול", + .id = "Suara", .it = "Audio", .ja = "サウンド", .ko = "사운드", .pl = "Dźwięk", .pt = "Som", .ru = "Звук", + .tr = "Ses", + .uk = "Звук", + .vi = "Âm thanh", .zh_CN = "声音", .zh_TW = "聲音", }, diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 3848b62d0f..7fe8b900b1 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -187,17 +187,22 @@ FFModuleBaseInfo ffSwapModuleInfo = { .displayName = { .en = "Swap", .ar = "الذاكرة التبادلية", + .cs = "Odkládací prostor", .de = "Swap", .es = "Swap", .fr = "Swap", .gl = "Swap", .he = "זיכרון החלפה", + .id = "Swap", .it = "Swap", .ja = "スワップ", .ko = "스왑", .pl = "Swap", .pt = "Swap", .ru = "Подкачка", + .tr = "Takas", + .uk = "Своп", + .vi = "Swap", .zh_CN = "交换空间", .zh_TW = "交換空間", }, diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 80c9016935..b13e32e9e2 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -88,17 +88,22 @@ FFModuleBaseInfo ffTerminalModuleInfo = { .displayName = { .en = "Terminal", .ar = "الطرفية", + .cs = "Terminál", .de = "Terminal", .es = "Terminal", .fr = "Terminal", .gl = "Terminal", .he = "טרמינל", + .id = "Terminal", .it = "Terminale", .ja = "ターミナル", .ko = "터미널", .pl = "Terminal", .pt = "Terminal", .ru = "Терминал", + .tr = "Terminal", + .uk = "Термінал", + .vi = "Terminal", .zh_CN = "终端", .zh_TW = "終端機", }, diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index d9e5a81f5d..ecfb58548a 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -108,17 +108,22 @@ FFModuleBaseInfo ffTerminalFontModuleInfo = { .displayName = { .en = "Terminal Font", .ar = "خط الطرفية", + .cs = "Písmo terminálu", .de = "Terminalschriftart", .es = "Fuente del terminal", .fr = "Police du terminal", .gl = "Fonte do terminal", .he = "גופן טרמינל", + .id = "Font Terminal", .it = "Carattere del terminale", .ja = "ターミナルフォント", .ko = "터미널 글꼴", .pl = "Czcionka terminala", .pt = "Fonte do terminal", .ru = "Шрифт терминала", + .tr = "Terminal Yazı Tipi", + .uk = "Шрифт терміналу", + .vi = "Phông chữ Terminal", .zh_CN = "终端字体", .zh_TW = "終端機字型", }, diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 08c2c9de01..12470cd7ae 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -79,16 +79,21 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .displayName = { .en = "Terminal Size", .ar = "حجم الطرفية", + .cs = "Velikost terminálu", .de = "Terminalgröße", .es = "Tamaño del terminal", .fr = "Taille du terminal", .he = "גודל טרמינל", + .id = "Ukuran Terminal", .it = "Dimensioni terminale", .ja = "ターミナルサイズ", .ko = "터미널 크기", .pl = "Rozmiar terminala", .pt = "Tamanho do terminal", .ru = "Размер терминала", + .tr = "Terminal Boyutu", + .uk = "Розмір терміналу", + .vi = "Kích thước Terminal", .zh_CN = "终端大小", .zh_TW = "終端機大小", }, diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index faa1ef2852..a3daf4f428 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -96,17 +96,22 @@ FFModuleBaseInfo ffTerminalThemeModuleInfo = { .displayName = { .en = "Terminal Theme", .ar = "سمة الطرفية", + .cs = "Motiv terminálu", .de = "Terminalthema", .es = "Tema del terminal", .fr = "Thème du terminal", .gl = "Tema do terminal", .he = "ערכת נושא של טרמינל", + .id = "Tema Terminal", .it = "Tema del terminale", .ja = "ターミナルテーマ", .ko = "터미널 테마", .pl = "Motyw terminala", .pt = "Tema do terminal", .ru = "Тема терминала", + .tr = "Terminal Teması", + .uk = "Тема терміналу", + .vi = "Chủ đề Terminal", .zh_CN = "终端主题", .zh_TW = "終端機主題", }, diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 263dd9875f..1f79179308 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -92,17 +92,22 @@ FFModuleBaseInfo ffThemeModuleInfo = { .displayName = { .en = "Theme", .ar = "السمة", + .cs = "Motiv", .de = "Thema", .es = "Tema", .fr = "Thème", .gl = "Tema", .he = "ערכת נושא", + .id = "Tema", .it = "Tema", .ja = "テーマ", .ko = "테마", .pl = "Motyw", .pt = "Tema", .ru = "Тема", + .tr = "Tema", + .uk = "Тема", + .vi = "Chủ đề", .zh_CN = "主题", .zh_TW = "主題", }, diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 3cad3941dc..b5a7acacee 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -181,17 +181,22 @@ FFModuleBaseInfo ffTitleModuleInfo = { .displayName = { .en = "Title", .ar = "العنوان", + .cs = "Titulek", .de = "Titel", .es = "Título", .fr = "Titre", .gl = "Título", .he = "כותרת", + .id = "Judul", .it = "Titolo", .ja = "タイトル", .ko = "제목", .pl = "Tytuł", .pt = "Título", .ru = "Заголовок", + .tr = "Başlık", + .uk = "Заголовок", + .vi = "Tiêu đề", .zh_CN = "标题", .zh_TW = "標題", }, diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index 1e2e03f105..8902efe70a 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -88,17 +88,22 @@ FFModuleBaseInfo ffTPMModuleInfo = { .displayName = { .en = "TPM", .ar = "TPM", + .cs = "TPM", .de = "TPM", .es = "TPM", .fr = "TPM", .gl = "TPM", .he = "TPM", + .id = "TPM", .it = "TPM", .ja = "TPM", .ko = "TPM", .pl = "TPM", .pt = "TPM", .ru = "TPM", + .tr = "TPM", + .uk = "TPM", + .vi = "TPM", .zh_CN = "TPM", .zh_TW = "TPM", }, diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 5937711bf7..25b8d1f45e 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -88,17 +88,22 @@ FFModuleBaseInfo ffUptimeModuleInfo = { .displayName = { .en = "Uptime", .ar = "مدة التشغيل", + .cs = "Doba běhu", .de = "Betriebszeit", .es = "Tiempo de actividad", .fr = "Temps de fonctionnement", .gl = "Tempo de actividade", .he = "זמן פעילות", + .id = "Waktu Aktif", .it = "Tempo di attività", .ja = "稼働時間", .ko = "업타임", .pl = "Czas pracy", .pt = "Tempo de atividade", .ru = "Время работы", + .tr = "Çalışma Süresi", + .uk = "Час роботи", + .vi = "Thời gian hoạt động", .zh_CN = "运行时间", .zh_TW = "運行時間", }, diff --git a/src/modules/users/users.c b/src/modules/users/users.c index e381297ece..6f24527ed2 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -185,17 +185,22 @@ FFModuleBaseInfo ffUsersModuleInfo = { .displayName = { .en = "Users", .ar = "المستخدمون", + .cs = "Uživatelé", .de = "Benutzer", .es = "Usuarios", .fr = "Utilisateurs", .gl = "Usuarios", .he = "משתמשים", + .id = "Pengguna", .it = "Utenti", .ja = "ユーザー", .ko = "사용자", .pl = "Użytkownicy", .pt = "Usuários", .ru = "Пользователи", + .tr = "Kullanıcılar", + .uk = "Користувачі", + .vi = "Người dùng", .zh_CN = "用户", .zh_TW = "使用者", }, diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 04fb1a6ffb..13e6f52b02 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -99,17 +99,22 @@ FFModuleBaseInfo ffVersionModuleInfo = { .displayName = { .en = "Version", .ar = "الإصدار", + .cs = "Verze", .de = "Version", .es = "Versión", .fr = "Version", .gl = "Versión", .he = "גרסה", + .id = "Versi", .it = "Versione", .ja = "バージョン", .ko = "버전", .pl = "Wersja", .pt = "Versão", .ru = "Версия", + .tr = "Sürüm", + .uk = "Версія", + .vi = "Phiên bản", .zh_CN = "版本", .zh_TW = "版本", }, diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 4c2c8c85f6..938c67e23e 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -137,17 +137,22 @@ FFModuleBaseInfo ffVulkanModuleInfo = { .displayName = { .en = "Vulkan", .ar = "Vulkan", + .cs = "Vulkan", .de = "Vulkan", .es = "Vulkan", .fr = "Vulkan", .gl = "Vulkan", .he = "Vulkan", + .id = "Vulkan", .it = "Vulkan", .ja = "Vulkan", .ko = "Vulkan", .pl = "Vulkan", .pt = "Vulkan", .ru = "Vulkan", + .tr = "Vulkan", + .uk = "Vulkan", + .vi = "Vulkan", .zh_CN = "Vulkan", .zh_TW = "Vulkan", }, diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index 472587d9a7..38c7b204a5 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -80,17 +80,22 @@ FFModuleBaseInfo ffWallpaperModuleInfo = { .displayName = { .en = "Wallpaper", .ar = "الخلفية", + .cs = "Tapeta", .de = "Hintergrundbild", .es = "Fondo de pantalla", .fr = "Fond d'écran", .gl = "Fondo de escritorio", .he = "טפט", + .id = "Wallpaper", .it = "Sfondo", .ja = "壁紙", .ko = "배경화면", .pl = "Tapeta", .pt = "Papel de parede", .ru = "Обои", + .tr = "Duvar Kağıdı", + .uk = "Шпалери", + .vi = "Hình nền", .zh_CN = "壁纸", .zh_TW = "桌布", }, diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 6878ab8d9a..17753251c1 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -97,17 +97,22 @@ FFModuleBaseInfo ffWeatherModuleInfo = { .displayName = { .en = "Weather", .ar = "الطقس", + .cs = "Počasí", .de = "Wetter", .es = "Tiempo", .fr = "Météo", .gl = "Tempo", .he = "מזג אוויר", + .id = "Cuaca", .it = "Meteo", .ja = "天気", .ko = "날씨", .pl = "Pogoda", .pt = "Clima", .ru = "Погода", + .tr = "Hava Durumu", + .uk = "Погода", + .vi = "Thời tiết", .zh_CN = "天气", .zh_TW = "天氣", }, diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index a7ad22c228..c48e46f517 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -220,17 +220,22 @@ FFModuleBaseInfo ffWifiModuleInfo = { .displayName = { .en = "Wi-Fi", .ar = "واي فاي", + .cs = "Wi-Fi", .de = "WLAN", .es = "Wi-Fi", .fr = "Wi-Fi", .gl = "Wi-Fi", .he = "Wi-Fi", + .id = "Wi-Fi", .it = "Wi-Fi", .ja = "Wi-Fi", .ko = "와이파이", .pl = "Wi-Fi", .pt = "Wi-Fi", .ru = "Wi-Fi", + .tr = "Wi-Fi", + .uk = "Wi-Fi", + .vi = "Wi-Fi", .zh_CN = "无线网络", .zh_TW = "無線網路", }, diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 2812a97ce0..c094e45c6b 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -125,17 +125,22 @@ FFModuleBaseInfo ffWMModuleInfo = { .displayName = { .en = "Window Manager", .ar = "مدير النوافذ", + .cs = "Správce oken", .de = "Fenstermanager", .es = "Gestor de ventanas", .fr = "Gestionnaire de fenêtres", .gl = "Xestor de xanelas", .he = "מנהל חלונות", + .id = "Manajer Jendela", .it = "Gestore finestre", .ja = "ウィンドウマネージャー", .ko = "윈도우 관리자", .pl = "Menedżer okien", .pt = "Gerenciador de janelas", .ru = "Менеджер окон", + .tr = "Pencere Yöneticisi", + .uk = "Менеджер вікон", + .vi = "Trình quản lý cửa sổ", .zh_CN = "窗口管理器", .zh_TW = "視窗管理員", }, diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index f6f40979a2..89caff3888 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -64,17 +64,22 @@ FFModuleBaseInfo ffWMThemeModuleInfo = { .displayName = { .en = "WM Theme", .ar = "سمة مدير النوافذ", + .cs = "Motiv správce oken", .de = "Fenstermanager-Thema", .es = "Tema del gestor de ventanas", .fr = "Thème du gestionnaire de fenêtres", .gl = "Tema do xestor de xanelas", .he = "ערכת נושא של מנהל חלונות", + .id = "Tema Manajer Jendela", .it = "Tema del gestore finestre", .ja = "ウィンドウマネージャのテーマ", .ko = "윈도우 관리자 테마", .pl = "Motyw menedżera okien", .pt = "Tema do gerenciador de janelas", .ru = "Тема менеджера окон", + .tr = "WM Teması", + .uk = "Тема менеджера вікон", + .vi = "Chủ đề trình quản lý cửa sổ", .zh_CN = "窗口管理器主题", .zh_TW = "視窗管理員主題", }, diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 7657c94898..c974f96306 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -197,17 +197,22 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .displayName = { .en = "Zpool", .ar = "Zpool", + .cs = "Zpool", .de = "Zpool", .es = "Zpool", .fr = "Zpool", .gl = "Zpool", .he = "Zpool", + .id = "Zpool", .it = "Zpool", .ja = "Zpool", .ko = "Zpool", .pl = "Zpool", .pt = "Zpool", .ru = "Zpool", + .tr = "Zpool", + .uk = "Zpool", + .vi = "Zpool", .zh_CN = "Zpool", .zh_TW = "Zpool", }, diff --git a/src/options/display.c b/src/options/display.c index 0e6b7141cb..3dbfce1ecf 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -65,17 +65,22 @@ static uint32_t optionParseLanguageString(FFstrbuf* language) { switch (language->chars[0] << 8 | language->chars[1]) { case 'en': return offsetof(FFModuleDisplayName, en); case 'ar': return offsetof(FFModuleDisplayName, ar); + case 'cs': return offsetof(FFModuleDisplayName, cs); case 'de': return offsetof(FFModuleDisplayName, de); case 'es': return offsetof(FFModuleDisplayName, es); case 'fr': return offsetof(FFModuleDisplayName, fr); case 'gl': return offsetof(FFModuleDisplayName, gl); case 'he': return offsetof(FFModuleDisplayName, he); + case 'id': return offsetof(FFModuleDisplayName, id); case 'it': return offsetof(FFModuleDisplayName, it); case 'ja': return offsetof(FFModuleDisplayName, ja); case 'ko': return offsetof(FFModuleDisplayName, ko); case 'pl': return offsetof(FFModuleDisplayName, pl); case 'pt': return offsetof(FFModuleDisplayName, pt); case 'ru': return offsetof(FFModuleDisplayName, ru); + case 'tr': return offsetof(FFModuleDisplayName, tr); + case 'uk': return offsetof(FFModuleDisplayName, uk); + case 'vi': return offsetof(FFModuleDisplayName, vi); case 'zh': { if (ffStrbufEqualS(language, "zh_cn")) { return offsetof(FFModuleDisplayName, zh_CN); @@ -1276,6 +1281,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, ar): yyjson_mut_obj_add_str(doc, key, "language", "ar"); break; + case offsetof(FFModuleDisplayName, cs): + yyjson_mut_obj_add_str(doc, key, "language", "cs"); + break; case offsetof(FFModuleDisplayName, de): yyjson_mut_obj_add_str(doc, key, "language", "de"); break; @@ -1291,6 +1299,9 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, he): yyjson_mut_obj_add_str(doc, key, "language", "he"); break; + case offsetof(FFModuleDisplayName, id): + yyjson_mut_obj_add_str(doc, key, "language", "id"); + break; case offsetof(FFModuleDisplayName, it): yyjson_mut_obj_add_str(doc, key, "language", "it"); break; @@ -1309,6 +1320,15 @@ void ffOptionsGenerateDisplayJsonConfig(FFdata* data, FFOptionsDisplay* options) case offsetof(FFModuleDisplayName, ru): yyjson_mut_obj_add_str(doc, key, "language", "ru"); break; + case offsetof(FFModuleDisplayName, tr): + yyjson_mut_obj_add_str(doc, key, "language", "tr"); + break; + case offsetof(FFModuleDisplayName, uk): + yyjson_mut_obj_add_str(doc, key, "language", "uk"); + break; + case offsetof(FFModuleDisplayName, vi): + yyjson_mut_obj_add_str(doc, key, "language", "vi"); + break; case offsetof(FFModuleDisplayName, zh_CN): yyjson_mut_obj_add_str(doc, key, "language", "zh_CN"); break; From e7ecba4460e16b823c7036ecd5030482943884d9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Aug 2026 10:40:50 +0800 Subject: [PATCH 046/109] Doc: updates README [ci skip] --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eab173fc3..ed5407df9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +# Unreleased + +Changes: +* The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations. + +Features: +* Added module key localization support. (General) + * Added a new option `--key-language ` (`display.key.language: ""` in JSON config). When left empty, it defaults to the system locale. + * See `fastfetch -h key-language` for all supported languages. +* Improved Wi-Fi module + * Added Wifi channel width detection, exposed via `{channel-width}` in custom format (reports 0 when not supported). + * Improved Wifi channel frequency accuracy and fortified detection on Windows, macOS. + * Added Wifi detection support on SunOS, Haiku. +* Added Battery detection support on SunOS. (Battery, SunOS) +* Added terminal font size detection support on Termux. (TerminalFont, Android) +* Improved GTK theme/icons/font detection on standalone WMs such as Hyprland, sway, niri and i3. (Theme, Linux) +* Improved fish completion scripts to print enum descriptions. (Completion) + +Bugfixes: +* Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO) +* Some internal cleanups and optimizations. + # 2.67.1 Bugfixes: From 6d5cb520eded8ce5be4343755a364e116b287f93 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 21 Aug 2026 13:38:44 +0800 Subject: [PATCH 047/109] Logo (Builtin): adds artix2 in --- src/logo/ascii/a.inc | 12 +++++++++++ src/logo/ascii/a/artix2.txt | 40 ++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/logo/ascii/a.inc b/src/logo/ascii/a.inc index dfda555db6..38ebae9b33 100644 --- a/src/logo/ascii/a.inc +++ b/src/logo/ascii/a.inc @@ -633,6 +633,18 @@ static const FFlogo A[] = { .colorTitle = FF_COLOR_FG_CYAN, }, #endif + #ifdef FASTFETCH_DATATEXT_LOGO_ARTIX2 + // Artix2 + { + .names = { "artix2" }, + .lines = FASTFETCH_DATATEXT_LOGO_ARTIX2, + .colors = { + FF_COLOR_FG_CYAN, + }, + .colorKeys = FF_COLOR_FG_CYAN, + .colorTitle = FF_COLOR_FG_CYAN, + }, + #endif #ifdef FASTFETCH_DATATEXT_LOGO_ARTIX_SMALL // ArtixSmall { diff --git a/src/logo/ascii/a/artix2.txt b/src/logo/ascii/a/artix2.txt index 0e87beb2e4..68d8399522 100644 --- a/src/logo/ascii/a/artix2.txt +++ b/src/logo/ascii/a/artix2.txt @@ -1,20 +1,20 @@ - .: - .==: - .====: - .======: - .========: - .==========: - .============: - .-===========: - .:-========: - .-:. .:======: - .======:.. :-===. - .============:.. .:=. - .==================:.. - .=======================: - .====================::. . - ================::. :-=== - ============-:. .:======== - ========-:. :-========== - =====:. ..:-===== - =::. ..:: + .: + .==: + .====: + .======: + .========: + .==========: + .============: + .-===========: + .:-========: + .-:. .:======: + .======:.. :-===. + .============:.. .:=. + .==================:.. + .=======================: + .====================::. . + ================::. :-=== + ============-:. .:======== + ========-:. :-========== + =====:. ..:-===== + =::. ..:: \ No newline at end of file From 5edda068f2e703508789e39ef643c89efada6529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 24 Aug 2026 20:58:33 +0800 Subject: [PATCH 048/109] =?UTF-8?q?PhysicalDisk=20(DragonFly):=20eliminate?= =?UTF-8?q?s=E2=80=8C=20compiler=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/detection/physicaldisk/physicaldisk_bsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index cda7adda55..d17905388b 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -122,6 +122,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) } #else const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { + FF_UNUSED(result, options); return "Fastfetch was compiled without libgeom support"; } #endif From 83cc7a94a41266d315908a1afdb7f3dac4dd063c Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 24 Aug 2026 16:05:36 +0800 Subject: [PATCH 049/109] Top: adds new module --- CMakeLists.txt | 13 ++ doc/json_schema.json | 77 ++++++++++- src/common/impl/commandoption.c | 8 ++ src/common/impl/jsonconfig.c | 10 ++ src/detection/top/top.c | 117 ++++++++++++++++ src/detection/top/top.h | 27 ++++ src/detection/top/top_apple.c | 57 ++++++++ src/detection/top/top_bsd.c | 67 ++++++++++ src/detection/top/top_dbsd.c | 67 ++++++++++ src/detection/top/top_gnu.c | 78 +++++++++++ src/detection/top/top_haiku.c | 47 +++++++ src/detection/top/top_linux.c | 126 ++++++++++++++++++ src/detection/top/top_nbsd.c | 65 +++++++++ src/detection/top/top_obsd.c | 44 ++++++ src/detection/top/top_sunos.c | 66 +++++++++ src/detection/top/top_windows.c | 48 +++++++ src/modules/modules.c | 3 + src/modules/modules.h | 1 + src/modules/options.h | 1 + src/modules/top/option.h | 23 ++++ src/modules/top/top.c | 229 ++++++++++++++++++++++++++++++++ src/modules/top/top.h | 11 ++ 22 files changed, 1183 insertions(+), 2 deletions(-) create mode 100644 src/detection/top/top.c create mode 100644 src/detection/top/top.h create mode 100644 src/detection/top/top_apple.c create mode 100644 src/detection/top/top_bsd.c create mode 100644 src/detection/top/top_dbsd.c create mode 100644 src/detection/top/top_gnu.c create mode 100644 src/detection/top/top_haiku.c create mode 100644 src/detection/top/top_linux.c create mode 100644 src/detection/top/top_nbsd.c create mode 100644 src/detection/top/top_obsd.c create mode 100644 src/detection/top/top_sunos.c create mode 100644 src/detection/top/top_windows.c create mode 100644 src/modules/top/option.h create mode 100644 src/modules/top/top.c create mode 100644 src/modules/top/top.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d4070af95..d8313c345a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -484,6 +484,7 @@ set(LIBFASTFETCH_SRC src/detection/physicalmemory/physicalmemory.c src/detection/publicip/publicip.c src/detection/terminaltheme/terminaltheme.c + src/detection/top/top.c src/detection/terminalfont/terminalfont.c src/detection/terminalshell/terminalshell.c src/detection/version/version.c @@ -559,6 +560,7 @@ set(LIBFASTFETCH_SRC src/modules/terminalsize/terminalsize.c src/modules/theme/theme.c src/modules/title/title.c + src/modules/top/top.c src/modules/tpm/tpm.c src/modules/uptime/uptime.c src/modules/users/users.c @@ -651,6 +653,7 @@ if(LINUX) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_linux.c src/detection/tpm/tpm_linux.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c @@ -822,11 +825,13 @@ elseif(FreeBSD) if(DragonFly) list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_nosupport.c + src/detection/top/top_dbsd.c src/detection/wifi/wifi_nosupport.c ) else() list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_bsd.c + src/detection/top/top_bsd.c src/detection/wifi/wifi_bsd.c ) endif() @@ -904,6 +909,7 @@ elseif(NetBSD) src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c src/detection/tpm/tpm_nosupport.c + src/detection/top/top_nbsd.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -990,6 +996,7 @@ elseif(OpenBSD) src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c src/detection/tpm/tpm_nosupport.c + src/detection/top/top_obsd.c src/detection/uptime/uptime_bsd.c src/detection/users/users_obsd.c src/detection/wallpaper/wallpaper_linux.c @@ -1057,6 +1064,7 @@ elseif(APPLE) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_apple.c + src/detection/top/top_apple.c src/detection/tpm/tpm_apple.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c @@ -1149,6 +1157,7 @@ elseif(WIN32) src/detection/terminalshell/terminalshell_windows.c src/detection/terminalsize/terminalsize_windows.c src/detection/theme/theme_windows.c + src/detection/top/top_windows.c src/detection/tpm/tpm_windows.c src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c @@ -1231,6 +1240,7 @@ elseif(SunOS) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_sunos.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_sunos.c src/detection/users/users_linux.c @@ -1301,6 +1311,7 @@ elseif(Haiku) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/top/top_haiku.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_haiku.c src/detection/users/users_linux.c @@ -1385,6 +1396,7 @@ elseif(GNU) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_gnu.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c @@ -1995,6 +2007,7 @@ elseif(SunOS) elseif(GNU) target_link_libraries(libfastfetch PRIVATE "m" + PRIVATE "ps" ) elseif(ANDROID) target_link_libraries(libfastfetch diff --git a/doc/json_schema.json b/doc/json_schema.json index 9e0aabc34f..411cb9ce09 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -322,7 +322,7 @@ "type": "string" }, "cpuFormat": { - "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count\n 13. {code-name}: CPU code name\n 14. {technology}: CPU technology", + "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count", "type": "string" }, "cpucacheFormat": { @@ -505,6 +505,10 @@ "description": "Output format for the `Title` module. See Wiki for formatting syntax\n 1. {user-name}: User name\n 2. {host-name}: Host name\n 3. {home-dir}: Home directory\n 4. {exe-path}: Executable path of current process\n 5. {user-shell}: User's default shell\n 6. {user-name-colored}: User name (colored)\n 7. {at-symbol-colored}: @ symbol (colored)\n 8. {host-name-colored}: Host name (colored)\n 9. {full-user-name}: Full user name\n 10. {user-id}: UID (*nix) / SID (Windows)\n 11. {pid}: PID of current process\n 12. {cwd}: CWD with home dir replaced by `~`", "type": "string" }, + "topFormat": { + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second\n 7. {disk-write}: Disk write bytes per second\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", + "type": "string" + }, "themeFormat": { "description": "Output format for the `Theme` module. See Wiki for formatting syntax\n 1. {theme1}: Theme part 1\n 2. {theme2}: Theme part 2", "type": "string" @@ -542,7 +546,7 @@ "type": "string" }, "wifiFormat": { - "description": "Output format for the `Wifi` module. See Wiki for formatting syntax\n 1. {inf-desc}: Interface description\n 2. {inf-status}: Interface status\n 3. {status}: Connection status\n 4. {ssid}: Connection SSID\n 5. {bssid}: Connection BSSID\n 6. {protocol}: Connection protocol\n 7. {signal-quality}: Connection signal quality (percentage num)\n 8. {rx-rate}: Connection RX rate\n 9. {tx-rate}: Connection TX rate\n 10. {security}: Connection Security algorithm\n 11. {signal-quality-bar}: Connection signal quality (percentage bar)\n 12. {channel}: Connection channel number\n 13. {band}: Connection channel band in GHz", + "description": "Output format for the `Wifi` module. See Wiki for formatting syntax\n 1. {inf-desc}: Interface description\n 2. {inf-status}: Interface status\n 3. {status}: Connection status\n 4. {ssid}: Connection SSID\n 5. {bssid}: Connection BSSID\n 6. {protocol}: Connection protocol\n 7. {signal-quality}: Connection signal quality (percentage num)\n 8. {rx-rate}: Connection RX rate\n 9. {tx-rate}: Connection TX rate\n 10. {security}: Connection Security algorithm\n 11. {signal-quality-bar}: Connection signal quality (percentage bar)\n 12. {channel}: Connection channel number\n 13. {channel-width}: Connection channel width in MHz\n 14. {band}: Connection channel band in GHz", "type": "string" }, "wmthemeFormat": { @@ -1592,6 +1596,7 @@ "poweradapter", "processes", "publicip", + "top", "separator", "shell", "sound", @@ -4424,6 +4429,74 @@ } } }, + { + "title": "Top", + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "const": "top", + "description": "Print processes with the highest CPU or memory usage" + }, + "sort": { + "type": "string", + "description": "Sort processes by CPU, memory or disk IO usage", + "enum": [ + "cpu", + "memory", + "disk-read", + "disk-write" + ], + "default": "cpu" + }, + "processes": { + "type": "integer", + "description": "Number of top processes to print", + "minimum": 1, + "default": 5 + }, + "waitTime": { + "type": "integer", + "description": "Wait time between process samples, in milliseconds", + "minimum": 1, + "default": 500 + }, + "compact": { + "type": "boolean", + "description": "Print all process on a single line", + "default": false + }, + "kernelTask": { + "type": "boolean", + "description": "Whether to include kernel tasks (kworker, System, kernel_task) in the process list", + "default": false + }, + "percent": { + "$ref": "#/$defs/percent" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyIcon": { + "$ref": "#/$defs/keyIcon" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "outputColor": { + "$ref": "#/$defs/outputColor" + }, + "format": { + "$ref": "#/$defs/topFormat" + }, + "condition": { + "$ref": "#/$defs/conditions" + } + } + }, { "title": "TPM", "type": "object", diff --git a/src/common/impl/commandoption.c b/src/common/impl/commandoption.c index a8764d610c..d8922a48ef 100644 --- a/src/common/impl/commandoption.c +++ b/src/common/impl/commandoption.c @@ -111,6 +111,14 @@ void ffPrepareCommandOption(FFdata* data) { break; #endif + #if !FF_MODULE_DISABLE_TOP + case 'T': + case 't': + FF_IF_MODULE_MATCH(ffTopModuleInfo.name) + ffPrepareTopProcesses(); + break; + #endif + #if !FF_MODULE_DISABLE_WEATHER case 'W': case 'w': diff --git a/src/common/impl/jsonconfig.c b/src/common/impl/jsonconfig.c index 7c9d44a88d..3d26e922e3 100644 --- a/src/common/impl/jsonconfig.c +++ b/src/common/impl/jsonconfig.c @@ -195,6 +195,16 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { } #endif + #if !FF_MODULE_DISABLE_TOP + case 't': + case 'T': { + if (ffStrEqualsIgnCase(type, ffTopModuleInfo.name)) { + ffPrepareTopProcesses(); + } + break; + } + #endif + #if !FF_MODULE_DISABLE_WEATHER case 'w': case 'W': { diff --git a/src/detection/top/top.c b/src/detection/top/top.c new file mode 100644 index 0000000000..659b47f0ec --- /dev/null +++ b/src/detection/top/top.c @@ -0,0 +1,117 @@ +#include "top.h" + +#include "common/time.h" + +static FFlist first; +static double startTick; + +void ffPrepareTopProcesses(void) { + if (startTick != 0) { + return; // Already prepared + } + + ffListInit(&first); + startTick = ffTimeGetTick(); + ffTopGetProcessSnapshot(&first); +} + +// clang-format off +static int compareCpuResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->cpuPercent < b->cpuPercent) return 1; + if (a->cpuPercent > b->cpuPercent) return -1; + return (int) (a->pid - b->pid); +} + +static int compareMemoryResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->memBytes < b->memBytes) return 1; + if (a->memBytes > b->memBytes) return -1; + return (int) (a->pid - b->pid); +} + +static int compareDiskReadResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->bytesRead < b->bytesRead) return 1; + if (a->bytesRead > b->bytesRead) return -1; + return (int) (a->pid - b->pid); +} + +static int compareDiskWriteResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->bytesWritten < b->bytesWritten) return 1; + if (a->bytesWritten > b->bytesWritten) return -1; + return (int) (a->pid - b->pid); +} +// clang-format on + +const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { + ffListClear(result); + if (options->nProcesses == 0) { + return nullptr; + } + + if (startTick == 0) { + ffPrepareTopProcesses(); + } + + double elapsedTime = ffTimeGetTick() - startTick; + if (elapsedTime < (double) options->waitTime) { + ffTimeSleep(options->waitTime - (uint32_t) elapsedTime); + } + + if (first.length == 0) { + return "No processes found"; + } + + FF_LIST_AUTO_DESTROY second = ffListCreate(); + const char* error = ffTopGetProcessSnapshot(&second); + const double elapsed = ffTimeGetTick() - startTick; + + if (error || elapsed <= 0) { + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + ffStrbufDestroy(&item->name); + } + return error ?: "Invalid process sampling interval"; + } + + ffListInitA(result, sizeof(FFTopProcessResult), first.length < options->nProcesses ? first.length : options->nProcesses); + FF_LIST_FOR_EACH (FFTopProcessSnapshot, oldItem, first) { + FFTopProcessSnapshot* newItem = nullptr; + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + if (item->pid == oldItem->pid) { + newItem = item; + break; + } + } + if (!newItem || newItem->startTime != oldItem->startTime || newItem->cpuTime < oldItem->cpuTime || newItem->bytesRead < oldItem->bytesRead || newItem->bytesWritten < oldItem->bytesWritten) { + ffStrbufDestroy(&oldItem->name); + continue; + } + + FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); + item->pid = newItem->pid; + item->memBytes = newItem->memBytes; + item->bytesRead = (newItem->bytesRead - oldItem->bytesRead) * 1000u / (uint64_t) elapsed; + item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; + item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; + item->startTime = newItem->startTime; + ffStrbufInitMove(&item->name, &oldItem->name); + } + + const void* compare = options->sort == FF_TOP_SORT_DISK_WRITE ? (void*) compareDiskWriteResults + : options->sort == FF_TOP_SORT_DISK_READ ? (void*) compareDiskReadResults + : options->sort == FF_TOP_SORT_MEMORY ? (void*) compareMemoryResults + : (void*) compareCpuResults; + ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); + if (result->length > options->nProcesses) { + FFTopProcessResult* items = (FFTopProcessResult*) result->data; + for (uint32_t i = options->nProcesses; i < result->length; ++i) { + ffStrbufDestroy(&items[i].name); + } + result->length = options->nProcesses; + } + + // Reuse `second` as the baseline of the next call + ffListDestroy(&first); + ffListInitMove(&first, &second); + startTick = ffTimeGetTick(); + + return nullptr; +} diff --git a/src/detection/top/top.h b/src/detection/top/top.h new file mode 100644 index 0000000000..b732a1fd6f --- /dev/null +++ b/src/detection/top/top.h @@ -0,0 +1,27 @@ +#pragma once + +#include "fastfetch.h" +#include "modules/top/option.h" + +typedef struct FFTopProcessResult { + FFstrbuf name; + uint64_t startTime; + double cpuPercent; + uint64_t memBytes; + uint64_t bytesRead; + uint64_t bytesWritten; + uint32_t pid; +} FFTopProcessResult; + +typedef struct FFTopProcessSnapshot { + FFstrbuf name; // comm + uint64_t cpuTime; // user_time + system_time + uint64_t memBytes; // RSS + uint64_t bytesRead; // Physical storage read + uint64_t bytesWritten; // Physical storage written + uint64_t startTime; // Differs between platforms + uint32_t pid; +} FFTopProcessSnapshot; + +const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result); +const char* ffTopGetProcessSnapshot(FFlist* snapshots); diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c new file mode 100644 index 0000000000..0fdcb00bec --- /dev/null +++ b/src/detection/top/top_apple.c @@ -0,0 +1,57 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc); + struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + pid_t pid = proc->kp_proc.p_pid; + if (pid <= 0) { + continue; + } + + struct rusage_info_v2 rusage; + if (proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t*) &rusage) != 0) { + continue; // The process may have exited + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + ffStrbufInitS(&item->name, proc->kp_proc.p_comm); + item->pid = (uint32_t) pid; + item->cpuTime = (rusage.ri_user_time + rusage.ri_system_time) / 1000000u; // ns -> ms + item->memBytes = rusage.ri_resident_size; + item->bytesRead = rusage.ri_diskio_bytesread; + item->bytesWritten = rusage.ri_diskio_byteswritten; + item->startTime = rusage.ri_proc_start_abstime; + } + + return nullptr; +} diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c new file mode 100644 index 0000000000..87a67bba2c --- /dev/null +++ b/src/detection/top/top_bsd.c @@ -0,0 +1,67 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc); + struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + + if (proc->ki_flag & P_KPROC) { + continue; + } + + uint32_t pid = (uint32_t) proc->ki_pid; + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, proc->ki_comm); + item->pid = pid; + + uint64_t userMs = (uint64_t) proc->ki_rusage.ru_utime.tv_sec * 1000 + + (uint64_t) proc->ki_rusage.ru_utime.tv_usec / 1000; + uint64_t sysMs = (uint64_t) proc->ki_rusage.ru_stime.tv_sec * 1000 + + (uint64_t) proc->ki_rusage.ru_stime.tv_usec / 1000; + item->cpuTime = userMs + sysMs; + + item->memBytes = (uint64_t) proc->ki_rssize * (uint64_t) pageSize; + + item->startTime = (uint64_t) proc->ki_start.tv_sec * 1000 + + (uint64_t) proc->ki_start.tv_usec / 1000; + + item->bytesRead = (uint64_t) proc->ki_rusage.ru_inblock * DEV_BSIZE; + item->bytesWritten = (uint64_t) proc->ki_rusage.ru_oublock * DEV_BSIZE; + } + + return NULL; +} diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c new file mode 100644 index 0000000000..872ba97f88 --- /dev/null +++ b/src/detection/top/top_dbsd.c @@ -0,0 +1,67 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc); + struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + + // Kernel threads are reported with P_SYSTEM flags and pid -1. + if ((proc->kp_flags & P_SYSTEM) || proc->kp_stat == SZOMB) { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, proc->kp_comm); + item->pid = (uint32_t) proc->kp_pid; + + // kp_ru only accounts for exited lwps; the cpu times of live lwps are + // kept in microseconds in kp_lwp.kl_uticks/kl_sticks (see calcru(9)). + uint64_t exitedMs = (uint64_t) (proc->kp_ru.ru_utime.tv_sec + proc->kp_ru.ru_stime.tv_sec) * 1000 + + (uint64_t) (proc->kp_ru.ru_utime.tv_usec + proc->kp_ru.ru_stime.tv_usec) / 1000; + uint64_t liveMs = (proc->kp_lwp.kl_uticks + proc->kp_lwp.kl_sticks) / 1000; + item->cpuTime = exitedMs + liveMs; + + item->memBytes = (uint64_t) proc->kp_vm_rssize * pageSize; + + item->startTime = (uint64_t) proc->kp_start.tv_sec * 1000 + + (uint64_t) proc->kp_start.tv_usec / 1000; + + item->bytesRead = (uint64_t) (proc->kp_ru.ru_inblock + proc->kp_lwp.kl_ru.ru_inblock) * DEV_BSIZE; + item->bytesWritten = (uint64_t) (proc->kp_ru.ru_oublock + proc->kp_lwp.kl_ru.ru_oublock) * DEV_BSIZE; + } + + return nullptr; +} diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c new file mode 100644 index 0000000000..3545ddac0f --- /dev/null +++ b/src/detection/top/top_gnu.c @@ -0,0 +1,78 @@ +#include "top.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + struct ps_context* context = nullptr; + if (ps_context_create(getproc(), &context) != 0) { + return "ps_context_create(getproc()) failed"; + } + + const char* error = nullptr; + struct proc_stat_list* list = nullptr; + if (proc_stat_list_create(context, &list) != 0) { + error = "proc_stat_list_create() failed"; + goto done; + } + + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + error = "proc_stat_list_add_all() failed"; + goto done; + } + + // Flags that cannot be fetched for some process are simply left unset; + // each field must be checked before use. + if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { + error = "proc_stat_list_set_flags() failed"; + goto done; + } + + for (unsigned i = 0; i < list->num_procs; ++i) { + struct proc_stat* stat = list->proc_stats[i]; + + if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) { + continue; + } + if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + // There is no kernel-side comm on the Hurd; use the first argument. + ffStrbufInit(&item->name); + if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) { + size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat)); + ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat)); + } + if (item->name.length == 0) { + ffStrbufAppendS(&item->name, "(unknown)"); + } + + item->pid = (uint32_t) proc_stat_pid(stat); + + if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { + const task_basic_info_t info = proc_stat_task_basic_info(stat); + item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + + (uint64_t) info->user_time.microseconds / 1000 + + (uint64_t) info->system_time.seconds * 1000 + + (uint64_t) info->system_time.microseconds / 1000; + item->memBytes = (uint64_t) info->resident_size; + } + + // Neither process start times nor storage io counters are exposed by + // the Hurd; leave them zeroed. + item->startTime = 0; + item->bytesRead = 0; + item->bytesWritten = 0; + } + +done: + if (list) { + proc_stat_list_free(list); + } + ps_context_free(context); + return error; +} diff --git a/src/detection/top/top_haiku.c b/src/detection/top/top_haiku.c new file mode 100644 index 0000000000..39efdb2b04 --- /dev/null +++ b/src/detection/top/top_haiku.c @@ -0,0 +1,47 @@ +#include "top.h" + +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int32 cookie = 0; + team_info team; + while (get_next_team_info(&cookie, &team) == B_OK) { + if (team.team == B_SYSTEM_TEAM) { + continue; // The kernel team + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, team.name); + + item->pid = (uint32_t) team.team; + + // User and kernel time of all threads of the team combined in microseconds. + item->cpuTime = 0; + team_usage_info usage; + if (get_team_usage_info(team.team, B_TEAM_USAGE_SELF, &usage) == B_OK) { + item->cpuTime = ((uint64_t) usage.user_time + (uint64_t) usage.kernel_time) / 1000; + } + + // Sum up the physically resident memory of all areas of the team; + // ram_size is the amount of physical pages committed to an area, + // whereas size is just its virtual reservation. + uint64_t memBytes = 0; + ssize_t areaCookie = 0; + area_info area; + while (get_next_area_info(team.team, &areaCookie, &area) == B_OK) { + memBytes += area.ram_size; + } + item->memBytes = memBytes; + + // start_time is microseconds since boot. + item->startTime = (uint64_t) team.start_time; + + // Storage io counters are not exposed by Haiku; leave them zeroed. + item->bytesRead = 0; + item->bytesWritten = 0; + } + + return nullptr; +} diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c new file mode 100644 index 0000000000..81b53c9571 --- /dev/null +++ b/src/detection/top/top_linux.c @@ -0,0 +1,126 @@ +#include "top.h" + +#include "common/io.h" +#include "common/memrchr.h" +#include "common/strutil.h" + +#include + +#define PF_KTHREAD 0x00200000 // defined in kernel include/linux/sched.h + +static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* result) { + const char* open = strchr(buffer, '('); + const char* close = (const char*) memrchr(buffer, ')', length); + if (!open || !close || close <= open || close + 2 >= buffer + length) { + return false; + } + + ffStrbufSetNS(&result->name, (uint32_t) (close - open - 1), open + 1); + const char* cursor = close + 2; // state, then fields 4.. + if (*cursor == '\0') { + return false; + } + ++cursor; + + uint64_t values[19]; + for (uint32_t field = 4; field <= 22; ++field) { + while (*cursor == ' ') { + ++cursor; + } + if (*cursor == '\0') { + return false; + } + char* end; + errno = 0; + unsigned long long value = strtoull(cursor, &end, 10); + if (end == cursor || errno == ERANGE) { + return false; + } + values[field - 4] = (uint64_t) value; + cursor = end; + } + + if (values[5] & PF_KTHREAD) { // values[5] is field 9 (flags) + return false; + } + + result->cpuTime = values[11] + values[12]; // user + system + result->startTime = values[18]; + return true; +} + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + const long ticks = sysconf(_SC_CLK_TCK); + const long pageSize = instance.state.platform.sysinfo.pageSize; + if (ticks <= 0 || pageSize <= 0) { + return "sysconf(_SC_CLK_TCK or _SC_PAGESIZE) failed"; + } + + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); + if (!dir) { + return "opendir(\"/proc\") failed"; + } + + int procfd = dirfd(dir); + + struct dirent* entry; + char statBuffer[4096]; + char statmBuffer[256]; + while ((entry = readdir(dir))) { + if (!entry->d_name[0] || !ffCharIsDigit(entry->d_name[0])) { + continue; + } + + unsigned long pid = strtoul(entry->d_name, nullptr, 10); + if (pid == 0 || pid > UINT32_MAX) { + continue; + } + + FF_AUTO_CLOSE_FD int subfd = openat(procfd, entry->d_name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) { + continue; + } + + ssize_t statLength; + if ((statLength = ffReadFileDataRelative(subfd, "stat", sizeof(statBuffer) - 1, statBuffer)) < 0) { + continue; + } + statBuffer[statLength] = '\0'; + + ssize_t statmLength; + if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { + continue; + } + statmBuffer[statmLength] = '\0'; + + char ioBuffer[512]; + ssize_t ioLength; + if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { + continue; + } + ioBuffer[ioLength] = '\0'; + + auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + ffStrbufInit(&snapshot->name); + if (!parseStat(statBuffer, (size_t) statLength, snapshot)) { + ffStrbufDestroy(&snapshot->name); + --snapshots->length; + continue; + } + + unsigned long long rssPages; + if (__builtin_expect(sscanf(statmBuffer, "%*llu %llu", &rssPages) != 1, false)) { + ffStrbufDestroy(&snapshot->name); + --snapshots->length; + continue; + } + + snapshot->pid = (uint32_t) pid; + snapshot->memBytes = rssPages * (uint64_t) pageSize; + snapshot->bytesRead = 0; + snapshot->bytesWritten = 0; + sscanf(ioBuffer, "rchar: %*" SCNu64 "\nwchar: %*" SCNu64 "\nsyscr: %*" SCNu64 "\nsyscw: %*" SCNu64 "\nread_bytes: %" SCNu64 "\nwrite_bytes: %" SCNu64, &snapshot->bytesRead, &snapshot->bytesWritten); + snapshot->cpuTime = snapshot->cpuTime * 1000u / (uint64_t) ticks; + } + return nullptr; +} diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c new file mode 100644 index 0000000000..3fee77049d --- /dev/null +++ b/src/detection/top/top_nbsd.c @@ -0,0 +1,65 @@ +#include "top.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + FF_AUTO_FREE struct kinfo_proc2* processes = nullptr; + for (int attempts = 0;; ++attempts) { + length += length / 8 + sizeof(struct kinfo_proc2); + struct kinfo_proc2* newProcesses = (struct kinfo_proc2*) realloc(processes, length); + if (!newProcesses) { + return "realloc(struct kinfo_proc2[]) failed"; + } + processes = newProcesses; + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { + break; + } + if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + } + } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc2)); + + uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc2* proc = &processes[i]; + + if ((proc->p_flag & P_SYSTEM) || !proc->p_uvalid) { // Kernel process or zombie + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, proc->p_comm); + item->pid = (uint32_t) proc->p_pid; + + uint64_t userMs = (uint64_t) proc->p_uutime_sec * 1000 + + (uint64_t) proc->p_uutime_usec / 1000; + uint64_t sysMs = (uint64_t) proc->p_ustime_sec * 1000 + + (uint64_t) proc->p_ustime_usec / 1000; + item->cpuTime = userMs + sysMs; + + item->memBytes = (uint64_t) proc->p_vm_rssize * (uint64_t) pageSize; + + item->startTime = (uint64_t) proc->p_ustart_sec * 1000 + + (uint64_t) proc->p_ustart_usec / 1000; + + item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; + item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + } + + return NULL; +} diff --git a/src/detection/top/top_obsd.c b/src/detection/top/top_obsd.c new file mode 100644 index 0000000000..99d7b0a8f9 --- /dev/null +++ b/src/detection/top/top_obsd.c @@ -0,0 +1,44 @@ +#include "top.h" + +#include +#include // DEV_BSIZE +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + if (!kd) { + return "kvm_open() failed"; + } + + int count = 0; + // KERN_PROC_ALL returns all user-level processes, excluding kernel processes and threads + const struct kinfo_proc* processes = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count); + if (!processes) { + kvm_close(kd); + return "kvm_getprocs() failed"; + } + + const uint32_t pageSize = instance.state.platform.sysinfo.pageSize; + + for (int i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + + if (!proc->p_uvalid) { // Zombie process; p_u* members are invalid + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + ffStrbufInitS(&item->name, proc->p_comm); + item->pid = (uint32_t) proc->p_pid; + item->cpuTime = ((uint64_t) proc->p_uutime_sec * 1000 + (uint64_t) proc->p_uutime_usec / 1000) + + ((uint64_t) proc->p_ustime_sec * 1000 + (uint64_t) proc->p_ustime_usec / 1000); + item->memBytes = (uint64_t) proc->p_vm_rssize * pageSize; + item->startTime = (uint64_t) proc->p_ustart_sec * 1000 + (uint64_t) proc->p_ustart_usec / 1000; + item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; + item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + } + + kvm_close(kd); + return nullptr; +} diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c new file mode 100644 index 0000000000..b00ce50ce9 --- /dev/null +++ b/src/detection/top/top_sunos.c @@ -0,0 +1,66 @@ +#include "top.h" + +#include "common/io.h" +#include "common/strutil.h" + +#include +#include +#include // DEV_BSIZE + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/proc"); + if (!dirp) { + return "opendir(\"/proc\") failed"; + } + + int procfd = dirfd(dirp); + + struct dirent* dp; + while ((dp = readdir(dirp))) { + if (!ffCharIsDigit(dp->d_name[0])) { // Skip "." and ".." + continue; + } + + FF_AUTO_CLOSE_FD int subfd = openat(procfd, dp->d_name, O_RDONLY | O_DIRECTORY); + if (subfd < 0) { + continue; + } + + // The data model of the returned structure depends on the data model of + // the calling process, not of the observed process. + psinfo_t psinfo; + if (ffReadFileDataRelative(subfd, "psinfo", sizeof(psinfo), &psinfo) != (ssize_t) sizeof(psinfo)) { + continue; // The process may have exited + } + + // pr_nlwp is zero for system processes and zombies + if (psinfo.pr_nlwp == 0 || psinfo.pr_lwp.pr_sname == 'Z') { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + ffStrbufInitS(&item->name, psinfo.pr_fname); + + item->pid = (uint32_t) psinfo.pr_pid; + + item->cpuTime = (uint64_t) psinfo.pr_time.tv_sec * 1000 + + (uint64_t) psinfo.pr_time.tv_nsec / 1000000; + + item->memBytes = (uint64_t) psinfo.pr_rssize * 1024; + + item->startTime = (uint64_t) psinfo.pr_start.tv_sec * 1000 + + (uint64_t) psinfo.pr_start.tv_nsec / 1000000; + + prusage_t usage; + if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { + item->bytesRead = (uint64_t) usage.pr_inblk * DEV_BSIZE; + item->bytesWritten = (uint64_t) usage.pr_oublk * DEV_BSIZE; + } else { + item->bytesRead = 0; + item->bytesWritten = 0; + } + } + + return nullptr; +} diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c new file mode 100644 index 0000000000..b27ad962eb --- /dev/null +++ b/src/detection/top/top_windows.c @@ -0,0 +1,48 @@ +#include "top.h" + +#include "common/mallocHelper.h" +#include "common/windows/unicode.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots) { + FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; + + // Multiple attempts in case processes change while + // we are in the middle of querying them. + ULONG size = 0; + for (int attempts = 0;; ++attempts) { + if (size) { + pstart = (SYSTEM_PROCESS_INFORMATION*) realloc(pstart, size); + assert(pstart); + } + NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, pstart, size, &size); + if (NT_SUCCESS(status)) { + break; + } else if (status == STATUS_INFO_LENGTH_MISMATCH && attempts < 4) { + size += sizeof(SYSTEM_PROCESS_INFORMATION) * 5; + } else { + return "NtQuerySystemInformation(SystemProcessInformation) failed"; + } + } + + for (SYSTEM_PROCESS_INFORMATION* info = pstart;; info = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) info + info->NextEntryOffset)) { + uintptr_t pidValue = (uintptr_t) info->UniqueProcessId; + if (pidValue <= UINT32_MAX && info->CreateTime.QuadPart > 0) { + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + item->pid = (uint32_t) pidValue; + item->startTime = info->CreateTime.QuadPart > 0 ? (uint64_t) info->CreateTime.QuadPart : 0; + item->cpuTime = ((uint64_t) info->UserTime.QuadPart + (uint64_t) info->KernelTime.QuadPart) / 10000u; + item->memBytes = (uint64_t) info->VirtualMemoryCounters.WorkingSetSize; + item->bytesRead = (uint64_t) info->IoCounters.ReadTransferCount; + item->bytesWritten = (uint64_t) info->IoCounters.WriteTransferCount; + ffStrbufInitNWS(&item->name, info->ImageName.Length / sizeof(wchar_t), info->ImageName.Buffer); + } + if (info->NextEntryOffset == 0) { + break; + } + } + return nullptr; +} diff --git a/src/modules/modules.c b/src/modules/modules.c index bcc4afdf45..ba4c95536f 100644 --- a/src/modules/modules.c +++ b/src/modules/modules.c @@ -271,6 +271,9 @@ static FFModuleBaseInfo* T[] = { #if !FF_MODULE_DISABLE_TITLE &ffTitleModuleInfo, #endif +#if !FF_MODULE_DISABLE_TOP + &ffTopModuleInfo, +#endif #if !FF_MODULE_DISABLE_THEME &ffThemeModuleInfo, #endif diff --git a/src/modules/modules.h b/src/modules/modules.h index 37ee242f0c..5d2cd99e88 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -64,6 +64,7 @@ #include "modules/terminaltheme/terminaltheme.h" #include "modules/theme/theme.h" #include "modules/title/title.h" +#include "modules/top/top.h" #include "modules/tpm/tpm.h" #include "modules/uptime/uptime.h" #include "modules/users/users.h" diff --git a/src/modules/options.h b/src/modules/options.h index 7cf98c1274..3c0bd6ee80 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -64,6 +64,7 @@ #include "modules/terminaltheme/option.h" #include "modules/theme/option.h" #include "modules/title/option.h" +#include "modules/top/option.h" #include "modules/tpm/option.h" #include "modules/uptime/option.h" #include "modules/users/option.h" diff --git a/src/modules/top/option.h b/src/modules/top/option.h new file mode 100644 index 0000000000..d40cff6fcb --- /dev/null +++ b/src/modules/top/option.h @@ -0,0 +1,23 @@ +#pragma once + +#include "common/option.h" +#include "common/percent.h" + +typedef enum FFTopSortType { + FF_TOP_SORT_CPU = 0, + FF_TOP_SORT_MEMORY, + FF_TOP_SORT_DISK_READ, + FF_TOP_SORT_DISK_WRITE, +} FFTopSortType; + +typedef struct FFTopOptions { + FFModuleArgs moduleArgs; + FFTopSortType sort; + uint32_t nProcesses; + uint32_t waitTime; + FFPercentageModuleConfig percent; + bool compact; + bool kernelTask; // Whether to include kernel tasks (kworker, System, kernel_task) in the process list +} FFTopOptions; + +static_assert(sizeof(FFTopOptions) <= FF_OPTION_MAX_SIZE, "FFTopOptions size exceeds maximum allowed size"); diff --git a/src/modules/top/top.c b/src/modules/top/top.c new file mode 100644 index 0000000000..a8b924fe3b --- /dev/null +++ b/src/modules/top/top.c @@ -0,0 +1,229 @@ +#include "common/jsonconfig.h" +#include "common/percent.h" +#include "common/printing.h" +#include "common/size.h" +#include "detection/top/top.h" +#include "modules/top/top.h" + +static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total, FFTopProcessResult* process) { + FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; + if (options->moduleArgs.outputFormat.length == 0) { + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); + ffStrbufAppendF(&output, "%s (%u) - ", process->name.chars, process->pid); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { + ffStrbufAppendS(&output, "CPU "); + ffPercentAppendNum(&output, process->cpuPercent, options->percent, false, &options->moduleArgs); + } + if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { + ffStrbufAppendS(&output, " - MEM "); + ffSizeAppendNum(process->memBytes, &output); + ffStrbufAppendS(&output, " - DSK "); + ffSizeAppendNum(process->bytesRead, &output); + ffStrbufAppendS(&output, "/s / "); + ffSizeAppendNum(process->bytesWritten, &output); + ffStrbufAppendS(&output, "/s"); + } + ffStrbufPutTo(&output, stdout); + } else { + FF_STRBUF_AUTO_DESTROY cpuFormatted = ffStrbufCreate(); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { + ffPercentAppendNum(&cpuFormatted, process->cpuPercent, options->percent, false, &options->moduleArgs); + } + FF_STRBUF_AUTO_DESTROY memFormatted = ffStrbufCreate(); + ffSizeAppendNum(process->memBytes, &memFormatted); + FF_STRBUF_AUTO_DESTROY diskReadFormatted = ffStrbufCreate(); + ffSizeAppendNum(process->bytesRead, &diskReadFormatted); + ffStrbufAppendS(&diskReadFormatted, "/s"); + FF_STRBUF_AUTO_DESTROY diskWriteFormatted = ffStrbufCreate(); + ffSizeAppendNum(process->bytesWritten, &diskWriteFormatted); + ffStrbufAppendS(&diskWriteFormatted, "/s"); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), (uint8_t) index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ + FF_ARG(process->name, "name"), + FF_ARG(process->pid, "pid"), + FF_ARG(process->cpuPercent, "cpu"), + FF_ARG(process->memBytes, "mem"), + FF_ARG(process->bytesRead, "disk-read"), + FF_ARG(process->bytesWritten, "disk-write"), + FF_ARG(cpuFormatted, "cpu-percentage"), + FF_ARG(memFormatted, "mem-formatted"), + FF_ARG(diskReadFormatted, "disk-read-formatted"), + FF_ARG(diskWriteFormatted, "disk-write-formatted"), + })); + } +} + +bool ffPrintTop(FFTopOptions* options) { + FF_LIST_AUTO_DESTROY results = ffListCreate(); + const char* error = ffDetectTopProcesses(options, &results); + if (error) { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return false; + } + + if (!options->compact) { + FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { + printTopResult(options, (uint32_t) (process - (FFTopProcessResult*) results.data), results.length, process); + } + } else { + ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { + ffStrbufWriteTo(&process->name, stdout); + if ((void*) process != results.data) { + putchar(' '); + } + } + } + + FF_LIST_FOR_EACH (FFTopProcessResult, item, results) { + ffStrbufDestroy(&item->name); + } + return true; +} + +void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { + yyjson_val *key, *val; + size_t idx, max; + yyjson_obj_foreach (module, idx, max, key, val) { + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) { + continue; + } + if (unsafe_yyjson_equals_str(key, "sort")) { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){ + { "cpu", FF_TOP_SORT_CPU }, + { "memory", FF_TOP_SORT_MEMORY }, + { "disk-read", FF_TOP_SORT_DISK_READ }, + { "disk-write", FF_TOP_SORT_DISK_WRITE }, + {}, + }); + if (error) { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + } else { + options->sort = (FFTopSortType) value; + } + continue; + } else if (unsafe_yyjson_equals_str(key, "processes")) { + options->nProcesses = (uint32_t) yyjson_get_uint(val); + } else if (unsafe_yyjson_equals_str(key, "waitTime")) { + options->waitTime = (uint32_t) yyjson_get_uint(val); + } else if (unsafe_yyjson_equals_str(key, "compact")) { + options->compact = yyjson_get_bool(val); + } else if (ffPercentParseJsonObject(key, val, &options->percent)) { + continue; + } else { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); + } + } +} + +void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { + ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + yyjson_mut_obj_add_str(doc, module, "type", "top"); + switch (options->sort) { + case FF_TOP_SORT_CPU: + yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); + break; + case FF_TOP_SORT_MEMORY: + yyjson_mut_obj_add_str(doc, module, "sort", "memory"); + break; + case FF_TOP_SORT_DISK_READ: + yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); + break; + case FF_TOP_SORT_DISK_WRITE: + yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); + break; + } + yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); + yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); + yyjson_mut_obj_add_bool(doc, module, "kernelTask", options->kernelTask); + ffPercentGenerateJsonConfig(doc, module, options->percent); +} + +bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { + FF_LIST_AUTO_DESTROY results = ffListCreate(); + const char* error = ffDetectTopProcesses(options, &results); + if (error) { + yyjson_mut_obj_add_str(doc, module, "error", error); + return false; + } + yyjson_mut_val* array = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { + yyjson_mut_val* item = yyjson_mut_arr_add_obj(doc, array); + yyjson_mut_obj_add_strbuf(doc, item, "name", &process->name); + yyjson_mut_obj_add_uint(doc, item, "pid", process->pid); + yyjson_mut_obj_add_real(doc, item, "cpuPercent", process->cpuPercent); + yyjson_mut_obj_add_uint(doc, item, "mem", process->memBytes); + yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); + yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); + yyjson_mut_obj_add_uint(doc, item, "startTime", process->startTime); + } + + FF_LIST_FOR_EACH (FFTopProcessResult, item, results) { + ffStrbufDestroy(&item->name); + } + return true; +} + +void ffInitTopOptions(FFTopOptions* options) { + ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); + options->sort = FF_TOP_SORT_CPU; + options->nProcesses = 5; + options->waitTime = 500; + options->compact = false; + options->kernelTask = false; + options->percent = (FFPercentageModuleConfig){ 50, 80, 0 }; +} + +void ffDestroyTopOptions(FFTopOptions* options) { + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +FFModuleBaseInfo ffTopModuleInfo = { + .name = "Top", + .description = "Print processes with the highest CPU, memory or disk I/O usage", + .displayName = { + .en = "Top Processes", + .ar = "أعلى العمليات", + .cs = "Nejvytíženější procesy", + .de = "Top-Prozesse", + .es = "Procesos principales", + .fr = "Processus principaux", + .gl = "Procesos principais", + .he = "התהליכים המובילים", + .id = "Proses teratas", + .it = "Processi principali", + .ja = "上位プロセス", + .ko = "상위 프로세스", + .pl = "Najaktywniejsze procesy", + .pt = "Processos principais", + .ru = "Топ процессов", + .tr = "En yoğun işlemler", + .uk = "Найактивніші процеси", + .vi = "Tiến trình hàng đầu", + .zh_CN = "进程排行", + .zh_TW = "進程排行", + }, + .initOptions = (void*) ffInitTopOptions, + .destroyOptions = (void*) ffDestroyTopOptions, + .parseJsonObject = (void*) ffParseTopJsonObject, + .printModule = (void*) ffPrintTop, + .generateJsonResult = (void*) ffGenerateTopJsonResult, + .generateJsonConfig = (void*) ffGenerateTopJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]){ + { "Process name", "name" }, + { "Executable path", "path" }, + { "Process ID", "pid" }, + { "CPU usage", "cpu" }, + { "Memory usage (RSS) in bytes", "mem" }, + { "Disk read bytes per second", "disk-read" }, + { "Disk write bytes per second", "disk-write" }, + { "CPU usage percentage", "cpu-percentage" }, + { "Memory usage (RSS) formatted", "mem-formatted" }, + { "Disk read formatted", "disk-read-formatted" }, + { "Disk write formatted", "disk-write-formatted" }, + })), + .defaultOrder = 36, +}; diff --git a/src/modules/top/top.h b/src/modules/top/top.h new file mode 100644 index 0000000000..144130fd66 --- /dev/null +++ b/src/modules/top/top.h @@ -0,0 +1,11 @@ +#pragma once + +#include "option.h" + +void ffPrepareTopProcesses(void); + +bool ffPrintTop(FFTopOptions* options); +void ffInitTopOptions(FFTopOptions* options); +void ffDestroyTopOptions(FFTopOptions* options); + +extern FFModuleBaseInfo ffTopModuleInfo; From b5897f784f2f87eeb98d2974b479bcacf09d7205 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 24 Aug 2026 22:43:37 +0800 Subject: [PATCH 050/109] Processes (GNU): uses native impl --- CMakeLists.txt | 2 +- src/detection/processes/processes_gnu.c | 33 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/detection/processes/processes_gnu.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d8313c345a..94177dc51a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1388,7 +1388,7 @@ elseif(GNU) src/detection/packages/packages_linux.c src/detection/packages/packages_nix.c src/detection/poweradapter/poweradapter_nosupport.c - src/detection/processes/processes_linux.c + src/detection/processes/processes_gnu.c src/detection/gtk_qt/qt.c src/detection/sound/sound_linux.c src/detection/swap/swap_linux.c diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c new file mode 100644 index 0000000000..7dc739d2ba --- /dev/null +++ b/src/detection/processes/processes_gnu.c @@ -0,0 +1,33 @@ +#include "processes.h" + +#include +#include + +const char* ffDetectProcesses(uint32_t* result) { + struct ps_context* context = nullptr; + if (ps_context_create(getproc(), &context) != 0) { + return "ps_context_create(getproc()) failed"; + } + + const char* error = nullptr; + struct proc_stat_list* list = nullptr; + if (proc_stat_list_create(context, &list) != 0) { + error = "proc_stat_list_create() failed"; + goto done; + } + + // No flags are needed; we only count the processes. + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + error = "proc_stat_list_add_all() failed"; + goto done; + } + + *result = (uint32_t) list->num_procs; + +done: + if (list) { + proc_stat_list_free(list); + } + ps_context_free(context); + return error; +} From a979d8ae818a310e900d509a17aaea857ad11a4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 18:07:14 +0000 Subject: [PATCH 051/109] CI: Bump the github-actions group with 4 updates Bumps the github-actions group with 4 updates: [cross-platform-actions/action](https://github.com/cross-platform-actions/action), [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [signpath/github-action-submit-signing-request](https://github.com/signpath/github-action-submit-signing-request). Updates `cross-platform-actions/action` from 1.3.0 to 1.4.0 - [Release notes](https://github.com/cross-platform-actions/action/releases) - [Changelog](https://github.com/cross-platform-actions/action/blob/master/changelog.md) - [Commits](https://github.com/cross-platform-actions/action/compare/5ea7e8e4677bd726033a10b094ba1c5762b15dee...24ef01df165c76df1ed2b9f9e9212e78dc2fc963) Updates `github/codeql-action/init` from 4.37.6 to 4.37.7 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd) Updates `github/codeql-action/analyze` from 4.37.6 to 4.37.7 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd) Updates `signpath/github-action-submit-signing-request` from 2.2 to 2.3 - [Release notes](https://github.com/signpath/github-action-submit-signing-request/releases) - [Commits](https://github.com/signpath/github-action-submit-signing-request/compare/b9d91eadd323de506c0c81cf0c7fe7438f3360fd...c92b958760219087e01f8d67a1669ed57afe2627) --- updated-dependencies: - dependency-name: cross-platform-actions/action dependency-version: 1.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: github/codeql-action/init dependency-version: 4.37.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/analyze dependency-version: 4.37.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: signpath/github-action-submit-signing-request dependency-version: '2.3' dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-dragonfly-amd64.yml | 2 +- .github/workflows/build-freebsd-amd64.yml | 2 +- .github/workflows/build-haiku-amd64.yml | 2 +- .github/workflows/build-linux-hosts.yml | 4 ++-- .github/workflows/build-netbsd-amd64.yml | 2 +- .github/workflows/build-omnios-amd64.yml | 2 +- .github/workflows/build-openbsd-amd64.yml | 2 +- .github/workflows/build-windows-hosts.yml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-dragonfly-amd64.yml b/.github/workflows/build-dragonfly-amd64.yml index c036d0d9d7..c3aec5d6e3 100644 --- a/.github/workflows/build-dragonfly-amd64.yml +++ b/.github/workflows/build-dragonfly-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: dragonflybsd version: '6.4.2' diff --git a/.github/workflows/build-freebsd-amd64.yml b/.github/workflows/build-freebsd-amd64.yml index b75d67be89..1cbbcae4cf 100644 --- a/.github/workflows/build-freebsd-amd64.yml +++ b/.github/workflows/build-freebsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: freebsd version: '15.1' diff --git a/.github/workflows/build-haiku-amd64.yml b/.github/workflows/build-haiku-amd64.yml index b85fef26e5..41aa30680c 100644 --- a/.github/workflows/build-haiku-amd64.yml +++ b/.github/workflows/build-haiku-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: haiku version: 'r1beta5' diff --git a/.github/workflows/build-linux-hosts.yml b/.github/workflows/build-linux-hosts.yml index bcd5069c42..612e7165f3 100644 --- a/.github/workflows/build-linux-hosts.yml +++ b/.github/workflows/build-linux-hosts.yml @@ -52,7 +52,7 @@ jobs: - name: Initialize CodeQL if: inputs.arch == 'amd64' - uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 with: languages: c @@ -64,7 +64,7 @@ jobs: - name: perform CodeQL analysis if: inputs.arch == 'amd64' - uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6 + uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 - name: list features run: ./fastfetch --list-features diff --git a/.github/workflows/build-netbsd-amd64.yml b/.github/workflows/build-netbsd-amd64.yml index 9a6283a067..87a8dc497e 100644 --- a/.github/workflows/build-netbsd-amd64.yml +++ b/.github/workflows/build-netbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: netbsd version: '10.1' diff --git a/.github/workflows/build-omnios-amd64.yml b/.github/workflows/build-omnios-amd64.yml index a473b0817a..a721080880 100644 --- a/.github/workflows/build-omnios-amd64.yml +++ b/.github/workflows/build-omnios-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: omnios version: 'r151058' diff --git a/.github/workflows/build-openbsd-amd64.yml b/.github/workflows/build-openbsd-amd64.yml index a22919f69d..9db8c4cef2 100644 --- a/.github/workflows/build-openbsd-amd64.yml +++ b/.github/workflows/build-openbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@5ea7e8e4677bd726033a10b094ba1c5762b15dee # v1.3.0 + uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 with: operating_system: openbsd version: '7.9' diff --git a/.github/workflows/build-windows-hosts.yml b/.github/workflows/build-windows-hosts.yml index fa1b3b3748..2ef399f97e 100644 --- a/.github/workflows/build-windows-hosts.yml +++ b/.github/workflows/build-windows-hosts.yml @@ -94,7 +94,7 @@ jobs: - if: github.event_name == 'push' && github.repository == 'fastfetch-cli/fastfetch' name: submit signing request - uses: signpath/github-action-submit-signing-request@b9d91eadd323de506c0c81cf0c7fe7438f3360fd # v2.2 + uses: signpath/github-action-submit-signing-request@c92b958760219087e01f8d67a1669ed57afe2627 # v2.3 with: api-token: '${{ secrets.SIGNPATH_API_TOKEN }}' organization-id: '${{ vars.SIGNPATH_ORG_ID }}' From 143939f19b61ae65feaec12c7c95a2f3d813bf00 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 09:08:35 +0800 Subject: [PATCH 052/109] DE (Android): adds asus zenfone support Fixes #2541 --- src/detection/displayserver/displayserver_android.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index 13f5fab0ef..d847c82ea1 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -174,6 +174,11 @@ static bool detectDE(FFDisplayServerResult* ds) { ffStrbufPrependS(&ds->dePrettyName, "OxygenOS"); return true; } + if (ffSettingsGetAndroidProperty("ro.product.brand", &ds->dePrettyName) && ffStrbufEqualS(&ds->dePrettyName, "asus")) { + ffStrbufClear(&ds->dePrettyName); + ffSettingsGetAndroidProperty("ro.build.version.incremental", &ds->dePrettyName); + return true; + } if (ffSettingsGetAndroidProperty("ro.build.display.id", &ds->dePrettyName)) { if (ffStrbufStartsWithS(&ds->dePrettyName, "RedMagicOS")) { ffStrbufInsertNC(&ds->dePrettyName, strlen("RedMagicOS"), 1, ' '); From 880284fa9c308f01497f440390e617b4780cd2f4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 13:32:28 +0800 Subject: [PATCH 053/109] DisplayServer (Android): enables Wayland support Fixes #2530 --- CMakeLists.txt | 9 ++++++- .../displayserver/displayserver_android.c | 24 +++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 94177dc51a..c921b5501e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ endif() include(CMakeDependentOption) cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR NetBSD OR WIN32 OR ANDROID OR SunOS OR Haiku OR GNU" OFF) -cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF) +cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "ANDROID OR LINUX OR FreeBSD OR OpenBSD OR NetBSD" OFF) cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF) cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR GNU" OFF) cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS OR GNU" OFF) @@ -694,6 +694,13 @@ elseif(ANDROID) src/detection/physicalmemory/physicalmemory_nosupport.c src/detection/diskio/diskio_linux.c src/detection/displayserver/displayserver_android.c + src/detection/displayserver/linux/wayland/wayland.c + src/detection/displayserver/linux/wayland/global-output.c + src/detection/displayserver/linux/wayland/kde-output.c + src/detection/displayserver/linux/wayland/wl-output-protocol.c + src/detection/displayserver/linux/wayland/wp-color-management-v1-protocol.c + src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c + src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c src/detection/displayserver/linux/common.c src/detection/displayserver/linux/wmde.c src/detection/displayserver/linux/xcb.c diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index d847c82ea1..4e666eb1d3 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -192,13 +192,23 @@ static bool detectDE(FFDisplayServerResult* ds) { } void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) { - const char* error = ffdsConnectXcbRandr(ds); - if (error) { - error = ffdsConnectXrandr(ds); - } - if (!error) { - ffdsDetectWMDE(ds); - return; + // Keep the same display-server preference as Linux: Wayland provides the + // richest output information, followed by XCB and XRandR. + if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) { + ffdsConnectWayland(ds); + + if (ds->displays.length == 0) { + ffdsConnectXcbRandr(ds); + } + + if (ds->displays.length == 0) { + ffdsConnectXrandr(ds); + } + + if (ds->displays.length > 0) { + ffdsDetectWMDE(ds); + return; + } } // https://source.android.com/docs/core/graphics/surfaceflinger-windowmanager From 55bfcd6d866e407df9776fc0612c61810bbaf934 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 13:35:32 +0800 Subject: [PATCH 054/109] Top (Android): fixes building --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c921b5501e..7f4605509f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -736,6 +736,7 @@ elseif(ANDROID) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/top/top_linux.c src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c From f15a1e96ce7b7a12853c832561e2817421acb29b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 16:27:53 +0800 Subject: [PATCH 055/109] Top (Linux): don't error out when reading `/proc/pid/io` fails --- src/detection/top/top_linux.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 81b53c9571..1c78c5e2b1 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -1,5 +1,6 @@ #include "top.h" +#include "common/debug.h" #include "common/io.h" #include "common/memrchr.h" #include "common/strutil.h" @@ -12,12 +13,14 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r const char* open = strchr(buffer, '('); const char* close = (const char*) memrchr(buffer, ')', length); if (!open || !close || close <= open || close + 2 >= buffer + length) { + FF_DEBUG("parseStat: malformed stat content"); return false; } ffStrbufSetNS(&result->name, (uint32_t) (close - open - 1), open + 1); const char* cursor = close + 2; // state, then fields 4.. if (*cursor == '\0') { + FF_DEBUG("parseStat(%s): truncated after state field", result->name.chars); return false; } ++cursor; @@ -28,12 +31,14 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r ++cursor; } if (*cursor == '\0') { + FF_DEBUG("parseStat(%s): truncated at field %u", result->name.chars, field); return false; } char* end; errno = 0; unsigned long long value = strtoull(cursor, &end, 10); if (end == cursor || errno == ERANGE) { + FF_DEBUG("parseStat(%s): invalid number at field %u", result->name.chars, field); return false; } values[field - 4] = (uint64_t) value; @@ -41,6 +46,7 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r } if (values[5] & PF_KTHREAD) { // values[5] is field 9 (flags) + FF_DEBUG("Skip kernel thread: %s", result->name.chars); return false; } @@ -52,12 +58,14 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r const char* ffTopGetProcessSnapshot(FFlist* snapshots) { const long ticks = sysconf(_SC_CLK_TCK); const long pageSize = instance.state.platform.sysinfo.pageSize; + FF_DEBUG("Scanning /proc: clk_tck=%ld, pageSize=%ld", ticks, pageSize); if (ticks <= 0 || pageSize <= 0) { return "sysconf(_SC_CLK_TCK or _SC_PAGESIZE) failed"; } FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (!dir) { + FF_DEBUG("opendir(\"/proc\") failed: %s", strerror(errno)); return "opendir(\"/proc\") failed"; } @@ -73,22 +81,26 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { unsigned long pid = strtoul(entry->d_name, nullptr, 10); if (pid == 0 || pid > UINT32_MAX) { + FF_DEBUG("Skip invalid pid directory: %s", entry->d_name); continue; } FF_AUTO_CLOSE_FD int subfd = openat(procfd, entry->d_name, O_RDONLY | O_DIRECTORY); if (subfd < 0) { + FF_DEBUG("openat(/proc/%s) failed: %s", entry->d_name, strerror(errno)); continue; } ssize_t statLength; if ((statLength = ffReadFileDataRelative(subfd, "stat", sizeof(statBuffer) - 1, statBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/stat: %s", entry->d_name, strerror(errno)); continue; } statBuffer[statLength] = '\0'; ssize_t statmLength; if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/statm: %s", entry->d_name, strerror(errno)); continue; } statmBuffer[statmLength] = '\0'; @@ -96,7 +108,8 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { char ioBuffer[512]; ssize_t ioLength; if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { - continue; + FF_DEBUG("Failed to read /proc/%s/io: %s", entry->d_name, strerror(errno)); + ioLength = 0; } ioBuffer[ioLength] = '\0'; @@ -108,8 +121,9 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { continue; } - unsigned long long rssPages; - if (__builtin_expect(sscanf(statmBuffer, "%*llu %llu", &rssPages) != 1, false)) { + uint64_t rssPages; + if (__builtin_expect(sscanf(statmBuffer, "%*u %" SCNu64, &rssPages) != 1, false)) { + FF_DEBUG("Failed to parse statm of /proc/%lu", pid); ffStrbufDestroy(&snapshot->name); --snapshots->length; continue; @@ -119,8 +133,14 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { snapshot->memBytes = rssPages * (uint64_t) pageSize; snapshot->bytesRead = 0; snapshot->bytesWritten = 0; - sscanf(ioBuffer, "rchar: %*" SCNu64 "\nwchar: %*" SCNu64 "\nsyscr: %*" SCNu64 "\nsyscw: %*" SCNu64 "\nread_bytes: %" SCNu64 "\nwrite_bytes: %" SCNu64, &snapshot->bytesRead, &snapshot->bytesWritten); + if (ioLength > 0) { + sscanf(ioBuffer, "rchar: %*u\nwchar: %*u\nsyscr: %*u\nsyscw: %*u\nread_bytes: %" SCNu64 "\nwrite_bytes: %" SCNu64, &snapshot->bytesRead, &snapshot->bytesWritten); + } snapshot->cpuTime = snapshot->cpuTime * 1000u / (uint64_t) ticks; + FF_DEBUG( + "Captured process %u (%s): cpuTime=%" PRIu64 "ms, mem=%" PRIu64 "B, diskRead=%" PRIu64 "B, diskWrite=%" PRIu64 "B", + snapshot->pid, snapshot->name.chars, snapshot->cpuTime, snapshot->memBytes, snapshot->bytesRead, snapshot->bytesWritten); } + FF_DEBUG("Captured %u process snapshots in total", snapshots->length); return nullptr; } From 63d16ca854fc8795e9b1314baaf715b78525a5a9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 25 Aug 2026 16:30:04 +0800 Subject: [PATCH 056/109] Top: removes option `kernelTask` (never implemented) --- doc/json_schema.json | 5 ----- src/modules/top/option.h | 1 - src/modules/top/top.c | 6 ++---- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 411cb9ce09..a34d00fcfd 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -4466,11 +4466,6 @@ "description": "Print all process on a single line", "default": false }, - "kernelTask": { - "type": "boolean", - "description": "Whether to include kernel tasks (kworker, System, kernel_task) in the process list", - "default": false - }, "percent": { "$ref": "#/$defs/percent" }, diff --git a/src/modules/top/option.h b/src/modules/top/option.h index d40cff6fcb..3b58118a24 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -17,7 +17,6 @@ typedef struct FFTopOptions { uint32_t waitTime; FFPercentageModuleConfig percent; bool compact; - bool kernelTask; // Whether to include kernel tasks (kworker, System, kernel_task) in the process list } FFTopOptions; static_assert(sizeof(FFTopOptions) <= FF_OPTION_MAX_SIZE, "FFTopOptions size exceeds maximum allowed size"); diff --git a/src/modules/top/top.c b/src/modules/top/top.c index a8b924fe3b..b36a3a1cc4 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -138,7 +138,6 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); - yyjson_mut_obj_add_bool(doc, module, "kernelTask", options->kernelTask); ffPercentGenerateJsonConfig(doc, module, options->percent); } @@ -173,7 +172,6 @@ void ffInitTopOptions(FFTopOptions* options) { options->nProcesses = 5; options->waitTime = 500; options->compact = false; - options->kernelTask = false; options->percent = (FFPercentageModuleConfig){ 50, 80, 0 }; } @@ -218,8 +216,8 @@ FFModuleBaseInfo ffTopModuleInfo = { { "Process ID", "pid" }, { "CPU usage", "cpu" }, { "Memory usage (RSS) in bytes", "mem" }, - { "Disk read bytes per second", "disk-read" }, - { "Disk write bytes per second", "disk-write" }, + { "Disk read bytes per second (0 if unsupported)", "disk-read" }, + { "Disk write bytes per second (0 if unsupported)", "disk-write" }, { "CPU usage percentage", "cpu-percentage" }, { "Memory usage (RSS) formatted", "mem-formatted" }, { "Disk read formatted", "disk-read-formatted" }, From b7d8c120150535fc4c0a26fa223f3fa3cfb02e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 18:23:02 +0800 Subject: [PATCH 057/109] CI: adds `top` module --- presets/all.jsonc | 1 + presets/ci.jsonc | 1 + 2 files changed, 2 insertions(+) diff --git a/presets/all.jsonc b/presets/all.jsonc index c9f951659e..fdb33ac2b6 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -19,6 +19,7 @@ "uptime", "loadavg", "processes", + "top", "packages", "shell", "editor", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 52eb9b4427..bbc03613f5 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -21,6 +21,7 @@ "uptime", "loadavg", "processes", + "top", "packages", "shell", "editor", From 4344aa2ff1c3943ac6aea6c78e1a2e3342cd5b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 20:08:06 +0800 Subject: [PATCH 058/109] Top: adds option `showType: ` --- doc/json_schema.json | 32 ++++++- src/common/impl/commandoption.c | 7 +- src/common/impl/jsonconfig.c | 7 +- src/detection/top/top.c | 138 ++++++++++++++++++---------- src/detection/top/top.h | 4 +- src/detection/top/top_apple.c | 2 +- src/detection/top/top_bsd.c | 2 +- src/detection/top/top_gnu.c | 156 ++++++++++++++++---------------- src/detection/top/top_haiku.c | 2 +- src/detection/top/top_linux.c | 30 +++--- src/detection/top/top_nbsd.c | 2 +- src/detection/top/top_obsd.c | 2 +- src/detection/top/top_sunos.c | 17 ++-- src/detection/top/top_windows.c | 2 +- src/modules/top/option.h | 17 ++-- src/modules/top/top.c | 121 ++++++++++++++++++------- src/modules/top/top.h | 2 +- 17 files changed, 344 insertions(+), 199 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index a34d00fcfd..e948d92859 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -4449,6 +4449,36 @@ ], "default": "cpu" }, + "showTypes": { + "description": "Specify which resource usages are detected and displayed.\nIf memory is enabled is enabled alone, only a single process snapshot is taken and `waitTime` sampling wait is skipped", + "default": [ + "cpu", + "memory", + "disk" + ], + "oneOf": [ + { + "type": "string", + "enum": [ + "cpu", + "memory", + "disk" + ] + }, + { + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "enum": [ + "cpu", + "memory", + "disk" + ] + } + } + ] + }, "processes": { "type": "integer", "description": "Number of top processes to print", @@ -4457,7 +4487,7 @@ }, "waitTime": { "type": "integer", - "description": "Wait time between process samples, in milliseconds", + "description": "Wait time between process samples, in milliseconds. Ignored when showTypes contains \"memory\" only", "minimum": 1, "default": 500 }, diff --git a/src/common/impl/commandoption.c b/src/common/impl/commandoption.c index d8922a48ef..fbbcc18db8 100644 --- a/src/common/impl/commandoption.c +++ b/src/common/impl/commandoption.c @@ -114,8 +114,11 @@ void ffPrepareCommandOption(FFdata* data) { #if !FF_MODULE_DISABLE_TOP case 'T': case 't': - FF_IF_MODULE_MATCH(ffTopModuleInfo.name) - ffPrepareTopProcesses(); + FF_IF_MODULE_MATCH(ffTopModuleInfo.name) { + [[gnu::cleanup(ffDestroyTopOptions)]] FFTopOptions options; + ffInitTopOptions(&options); + ffPrepareTopProcesses(options.showTypes); + } break; #endif diff --git a/src/common/impl/jsonconfig.c b/src/common/impl/jsonconfig.c index 3d26e922e3..a7597ca408 100644 --- a/src/common/impl/jsonconfig.c +++ b/src/common/impl/jsonconfig.c @@ -199,7 +199,12 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) { case 't': case 'T': { if (ffStrEqualsIgnCase(type, ffTopModuleInfo.name)) { - ffPrepareTopProcesses(); + [[gnu::cleanup(ffDestroyTopOptions)]] FFTopOptions options; + ffInitTopOptions(&options); + if (module) { + ffTopModuleInfo.parseJsonObject(&options, module); + } + ffPrepareTopProcesses(options.showTypes); } break; } diff --git a/src/detection/top/top.c b/src/detection/top/top.c index 659b47f0ec..5c1b8b645e 100644 --- a/src/detection/top/top.c +++ b/src/detection/top/top.c @@ -4,15 +4,29 @@ static FFlist first; static double startTick; +static FFTopTypes preparedShowTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; -void ffPrepareTopProcesses(void) { - if (startTick != 0) { +void ffPrepareTopProcesses(FFTopTypes showTypes) { + if ((showTypes & (FF_TOP_TYPE_CPU | FF_TOP_TYPE_DISK)) == 0) { + return; // Memory usage is instantaneous; no baseline snapshot is needed + } + + if (startTick != 0 && preparedShowTypes == showTypes) { return; // Already prepared } + if (startTick != 0) { + // The set of requested types changed; discard the stale baseline + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, first) { + ffStrbufDestroy(&item->name); + } + ffListDestroy(&first); + } + ffListInit(&first); startTick = ffTimeGetTick(); - ffTopGetProcessSnapshot(&first); + preparedShowTypes = showTypes; + ffTopGetProcessSnapshot(&first, showTypes); } // clang-format off @@ -47,57 +61,92 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { return nullptr; } - if (startTick == 0) { - ffPrepareTopProcesses(); - } + // Memory usage is instantaneous; when neither CPU time nor disk IO counters + // are requested, a single snapshot suffices and no sampling wait is needed. + const bool sampleOnce = (options->showTypes & (FF_TOP_TYPE_CPU | FF_TOP_TYPE_DISK)) == 0; - double elapsedTime = ffTimeGetTick() - startTick; - if (elapsedTime < (double) options->waitTime) { - ffTimeSleep(options->waitTime - (uint32_t) elapsedTime); - } + if (sampleOnce) { + FF_LIST_AUTO_DESTROY snapshots = ffListCreate(); + const char* error = ffTopGetProcessSnapshot(&snapshots, options->showTypes); + if (error) { + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, snapshots) { + ffStrbufDestroy(&item->name); + } + return error; + } + if (snapshots.length == 0) { + return "No processes found"; + } - if (first.length == 0) { - return "No processes found"; - } + FF_LIST_FOR_EACH (FFTopProcessSnapshot, snap, snapshots) { + FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); + item->pid = snap->pid; + item->memBytes = snap->memBytes; + item->bytesRead = 0; + item->bytesWritten = 0; + item->cpuPercent = 0; + item->startTime = snap->startTime; + ffStrbufInitMove(&item->name, &snap->name); + } + } else { + if (startTick == 0 || preparedShowTypes != options->showTypes) { + ffPrepareTopProcesses(options->showTypes); + } - FF_LIST_AUTO_DESTROY second = ffListCreate(); - const char* error = ffTopGetProcessSnapshot(&second); - const double elapsed = ffTimeGetTick() - startTick; + double elapsedTime = ffTimeGetTick() - startTick; + if (elapsedTime < (double) options->waitTime) { + ffTimeSleep(options->waitTime - (uint32_t) elapsedTime); + } - if (error || elapsed <= 0) { - FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { - ffStrbufDestroy(&item->name); + if (first.length == 0) { + return "No processes found"; } - return error ?: "Invalid process sampling interval"; - } - ffListInitA(result, sizeof(FFTopProcessResult), first.length < options->nProcesses ? first.length : options->nProcesses); - FF_LIST_FOR_EACH (FFTopProcessSnapshot, oldItem, first) { - FFTopProcessSnapshot* newItem = nullptr; - FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { - if (item->pid == oldItem->pid) { - newItem = item; - break; + ffListReserve(result, sizeof(FFTopProcessResult), first.length < options->nProcesses ? first.length : options->nProcesses); + + FF_LIST_AUTO_DESTROY second = ffListCreateA(sizeof(FFTopProcessSnapshot), first.length); + const char* error = ffTopGetProcessSnapshot(&second, options->showTypes); + const double elapsed = ffTimeGetTick() - startTick; + + if (error || elapsed <= 0) { + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + ffStrbufDestroy(&item->name); } + return error ?: "Invalid process sampling interval"; } - if (!newItem || newItem->startTime != oldItem->startTime || newItem->cpuTime < oldItem->cpuTime || newItem->bytesRead < oldItem->bytesRead || newItem->bytesWritten < oldItem->bytesWritten) { - ffStrbufDestroy(&oldItem->name); - continue; + + FF_LIST_FOR_EACH (FFTopProcessSnapshot, oldItem, first) { + FFTopProcessSnapshot* newItem = nullptr; + FF_LIST_FOR_EACH (FFTopProcessSnapshot, item, second) { + if (item->pid == oldItem->pid) { + newItem = item; + break; + } + } + if (!newItem || newItem->startTime != oldItem->startTime || newItem->cpuTime < oldItem->cpuTime || newItem->bytesRead < oldItem->bytesRead || newItem->bytesWritten < oldItem->bytesWritten) { + ffStrbufDestroy(&oldItem->name); + continue; + } + + FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); + item->pid = newItem->pid; + item->memBytes = newItem->memBytes; + item->bytesRead = (newItem->bytesRead - oldItem->bytesRead) * 1000u / (uint64_t) elapsed; + item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; + item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; + item->startTime = newItem->startTime; + ffStrbufInitMove(&item->name, &oldItem->name); } - FFTopProcessResult* item = FF_LIST_ADD(FFTopProcessResult, *result); - item->pid = newItem->pid; - item->memBytes = newItem->memBytes; - item->bytesRead = (newItem->bytesRead - oldItem->bytesRead) * 1000u / (uint64_t) elapsed; - item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; - item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; - item->startTime = newItem->startTime; - ffStrbufInitMove(&item->name, &oldItem->name); + // Reuse `second` as the baseline of the next call + ffListDestroy(&first); + ffListInitMove(&first, &second); + startTick = ffTimeGetTick(); } - const void* compare = options->sort == FF_TOP_SORT_DISK_WRITE ? (void*) compareDiskWriteResults - : options->sort == FF_TOP_SORT_DISK_READ ? (void*) compareDiskReadResults - : options->sort == FF_TOP_SORT_MEMORY ? (void*) compareMemoryResults + const void* compare = options->sort == FF_TOP_TYPE_DISK_WRITE ? (void*) compareDiskWriteResults + : options->sort == FF_TOP_TYPE_DISK_READ ? (void*) compareDiskReadResults + : options->sort == FF_TOP_TYPE_MEMORY ? (void*) compareMemoryResults : (void*) compareCpuResults; ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); if (result->length > options->nProcesses) { @@ -108,10 +157,5 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { result->length = options->nProcesses; } - // Reuse `second` as the baseline of the next call - ffListDestroy(&first); - ffListInitMove(&first, &second); - startTick = ffTimeGetTick(); - return nullptr; } diff --git a/src/detection/top/top.h b/src/detection/top/top.h index b732a1fd6f..de1289b4ae 100644 --- a/src/detection/top/top.h +++ b/src/detection/top/top.h @@ -5,11 +5,11 @@ typedef struct FFTopProcessResult { FFstrbuf name; - uint64_t startTime; double cpuPercent; uint64_t memBytes; uint64_t bytesRead; uint64_t bytesWritten; + uint64_t startTime; uint32_t pid; } FFTopProcessResult; @@ -24,4 +24,4 @@ typedef struct FFTopProcessSnapshot { } FFTopProcessSnapshot; const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result); -const char* ffTopGetProcessSnapshot(FFlist* snapshots); +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes); diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index 0fdcb00bec..fc8f5c998d 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c index 87a67bba2c..620b234b14 100644 --- a/src/detection/top/top_bsd.c +++ b/src/detection/top/top_bsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; size_t length; diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 3545ddac0f..9bbe37aff9 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -1,78 +1,78 @@ -#include "top.h" - -#include -#include -#include - -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { - struct ps_context* context = nullptr; - if (ps_context_create(getproc(), &context) != 0) { - return "ps_context_create(getproc()) failed"; - } - - const char* error = nullptr; - struct proc_stat_list* list = nullptr; - if (proc_stat_list_create(context, &list) != 0) { - error = "proc_stat_list_create() failed"; - goto done; - } - - if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { - error = "proc_stat_list_add_all() failed"; - goto done; - } - - // Flags that cannot be fetched for some process are simply left unset; - // each field must be checked before use. - if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { - error = "proc_stat_list_set_flags() failed"; - goto done; - } - - for (unsigned i = 0; i < list->num_procs; ++i) { - struct proc_stat* stat = list->proc_stats[i]; - - if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) { - continue; - } - if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) { - continue; - } - - FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); - - // There is no kernel-side comm on the Hurd; use the first argument. - ffStrbufInit(&item->name); - if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) { - size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat)); - ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat)); - } - if (item->name.length == 0) { - ffStrbufAppendS(&item->name, "(unknown)"); - } - - item->pid = (uint32_t) proc_stat_pid(stat); - - if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { - const task_basic_info_t info = proc_stat_task_basic_info(stat); - item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + - (uint64_t) info->user_time.microseconds / 1000 + - (uint64_t) info->system_time.seconds * 1000 + - (uint64_t) info->system_time.microseconds / 1000; - item->memBytes = (uint64_t) info->resident_size; - } - - // Neither process start times nor storage io counters are exposed by - // the Hurd; leave them zeroed. - item->startTime = 0; - item->bytesRead = 0; - item->bytesWritten = 0; - } - -done: - if (list) { - proc_stat_list_free(list); - } - ps_context_free(context); - return error; -} +#include "top.h" + +#include +#include +#include + +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { + struct ps_context* context = nullptr; + if (ps_context_create(getproc(), &context) != 0) { + return "ps_context_create(getproc()) failed"; + } + + const char* error = nullptr; + struct proc_stat_list* list = nullptr; + if (proc_stat_list_create(context, &list) != 0) { + error = "proc_stat_list_create() failed"; + goto done; + } + + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + error = "proc_stat_list_add_all() failed"; + goto done; + } + + // Flags that cannot be fetched for some process are simply left unset; + // each field must be checked before use. + if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { + error = "proc_stat_list_set_flags() failed"; + goto done; + } + + for (unsigned i = 0; i < list->num_procs; ++i) { + struct proc_stat* stat = list->proc_stats[i]; + + if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) { + continue; + } + if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) { + continue; + } + + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); + + // There is no kernel-side comm on the Hurd; use the first argument. + ffStrbufInit(&item->name); + if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) { + size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat)); + ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat)); + } + if (item->name.length == 0) { + ffStrbufAppendS(&item->name, "(unknown)"); + } + + item->pid = (uint32_t) proc_stat_pid(stat); + + if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { + const task_basic_info_t info = proc_stat_task_basic_info(stat); + item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + + (uint64_t) info->user_time.microseconds / 1000 + + (uint64_t) info->system_time.seconds * 1000 + + (uint64_t) info->system_time.microseconds / 1000; + item->memBytes = (uint64_t) info->resident_size; + } + + // Neither process start times nor storage io counters are exposed by + // the Hurd; leave them zeroed. + item->startTime = 0; + item->bytesRead = 0; + item->bytesWritten = 0; + } + +done: + if (list) { + proc_stat_list_free(list); + } + ps_context_free(context); + return error; +} diff --git a/src/detection/top/top_haiku.c b/src/detection/top/top_haiku.c index 39efdb2b04..78310737a7 100644 --- a/src/detection/top/top_haiku.c +++ b/src/detection/top/top_haiku.c @@ -3,7 +3,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int32 cookie = 0; team_info team; while (get_next_team_info(&cookie, &team) == B_OK) { diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 1c78c5e2b1..28349a17d6 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -55,7 +55,7 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r return true; } -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { const long ticks = sysconf(_SC_CLK_TCK); const long pageSize = instance.state.platform.sysinfo.pageSize; FF_DEBUG("Scanning /proc: clk_tck=%ld, pageSize=%ld", ticks, pageSize); @@ -98,20 +98,24 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { } statBuffer[statLength] = '\0'; - ssize_t statmLength; - if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { - FF_DEBUG("Failed to read /proc/%s/statm: %s", entry->d_name, strerror(errno)); - continue; + ssize_t statmLength = 0; + if (showTypes & FF_TOP_TYPE_MEMORY) { + if ((statmLength = ffReadFileDataRelative(subfd, "statm", sizeof(statmBuffer) - 1, statmBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/statm: %s", entry->d_name, strerror(errno)); + statmLength = 0; + } + statmBuffer[statmLength] = '\0'; } - statmBuffer[statmLength] = '\0'; char ioBuffer[512]; - ssize_t ioLength; - if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { - FF_DEBUG("Failed to read /proc/%s/io: %s", entry->d_name, strerror(errno)); - ioLength = 0; + ssize_t ioLength = 0; + if (showTypes & FF_TOP_TYPE_DISK) { + if ((ioLength = ffReadFileDataRelative(subfd, "io", sizeof(ioBuffer) - 1, ioBuffer)) < 0) { + FF_DEBUG("Failed to read /proc/%s/io: %s", entry->d_name, strerror(errno)); + ioLength = 0; + } + ioBuffer[ioLength] = '\0'; } - ioBuffer[ioLength] = '\0'; auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInit(&snapshot->name); @@ -121,8 +125,8 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { continue; } - uint64_t rssPages; - if (__builtin_expect(sscanf(statmBuffer, "%*u %" SCNu64, &rssPages) != 1, false)) { + uint64_t rssPages = 0; + if (__builtin_expect((showTypes & FF_TOP_TYPE_MEMORY) && sscanf(statmBuffer, "%*u %" SCNu64, &rssPages) != 1, false)) { FF_DEBUG("Failed to parse statm of /proc/%lu", pid); ffStrbufDestroy(&snapshot->name); --snapshots->length; diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c index 3fee77049d..277354ed3a 100644 --- a/src/detection/top/top_nbsd.c +++ b/src/detection/top/top_nbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length; diff --git a/src/detection/top/top_obsd.c b/src/detection/top/top_obsd.c index 99d7b0a8f9..f7519bd00c 100644 --- a/src/detection/top/top_obsd.c +++ b/src/detection/top/top_obsd.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); if (!kd) { return "kvm_open() failed"; diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c index b00ce50ce9..f7e6a5f688 100644 --- a/src/detection/top/top_sunos.c +++ b/src/detection/top/top_sunos.c @@ -7,7 +7,7 @@ #include #include // DEV_BSIZE -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/proc"); if (!dirp) { return "opendir(\"/proc\") failed"; @@ -52,13 +52,14 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots) { item->startTime = (uint64_t) psinfo.pr_start.tv_sec * 1000 + (uint64_t) psinfo.pr_start.tv_nsec / 1000000; - prusage_t usage; - if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { - item->bytesRead = (uint64_t) usage.pr_inblk * DEV_BSIZE; - item->bytesWritten = (uint64_t) usage.pr_oublk * DEV_BSIZE; - } else { - item->bytesRead = 0; - item->bytesWritten = 0; + item->bytesRead = 0; + item->bytesWritten = 0; + if (showTypes & FF_TOP_TYPE_DISK) { + prusage_t usage; + if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { + item->bytesRead = (uint64_t) usage.pr_inblk * DEV_BSIZE; + item->bytesWritten = (uint64_t) usage.pr_oublk * DEV_BSIZE; + } } } diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index b27ad962eb..59a5ab98db 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -7,7 +7,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; // Multiple attempts in case processes change while diff --git a/src/modules/top/option.h b/src/modules/top/option.h index 3b58118a24..82a1382731 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -3,16 +3,19 @@ #include "common/option.h" #include "common/percent.h" -typedef enum FFTopSortType { - FF_TOP_SORT_CPU = 0, - FF_TOP_SORT_MEMORY, - FF_TOP_SORT_DISK_READ, - FF_TOP_SORT_DISK_WRITE, -} FFTopSortType; +typedef enum FFTopTypes: uint8_t { + FF_TOP_TYPE_CPU = 1 << 0, + FF_TOP_TYPE_MEMORY = 1 << 1, + FF_TOP_TYPE_DISK_READ = 1 << 2, + FF_TOP_TYPE_DISK_WRITE = 1 << 3, + + FF_TOP_TYPE_DISK = FF_TOP_TYPE_DISK_READ | FF_TOP_TYPE_DISK_WRITE, +} FFTopTypes; typedef struct FFTopOptions { FFModuleArgs moduleArgs; - FFTopSortType sort; + FFTopTypes sort; + FFTopTypes showTypes; // bitfields uint32_t nProcesses; uint32_t waitTime; FFPercentageModuleConfig percent; diff --git a/src/modules/top/top.c b/src/modules/top/top.c index b36a3a1cc4..60ecda8a0c 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -11,19 +11,23 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); - ffStrbufAppendF(&output, "%s (%u) - ", process->name.chars, process->pid); - if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) { - ffStrbufAppendS(&output, "CPU "); + ffStrbufAppendF(&output, "%s (%u)", process->name.chars, process->pid); + if ((options->showTypes & FF_TOP_TYPE_CPU) && (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)) { + ffStrbufAppendS(&output, " - CPU "); ffPercentAppendNum(&output, process->cpuPercent, options->percent, false, &options->moduleArgs); } if (!(percentType & FF_PERCENTAGE_TYPE_HIDE_OTHERS_BIT)) { - ffStrbufAppendS(&output, " - MEM "); - ffSizeAppendNum(process->memBytes, &output); - ffStrbufAppendS(&output, " - DSK "); - ffSizeAppendNum(process->bytesRead, &output); - ffStrbufAppendS(&output, "/s / "); - ffSizeAppendNum(process->bytesWritten, &output); - ffStrbufAppendS(&output, "/s"); + if (options->showTypes & FF_TOP_TYPE_MEMORY) { + ffStrbufAppendS(&output, " - MEM "); + ffSizeAppendNum(process->memBytes, &output); + } + if (options->showTypes & FF_TOP_TYPE_DISK) { + ffStrbufAppendS(&output, " - DSK "); + ffSizeAppendNum(process->bytesRead, &output); + ffStrbufAppendS(&output, "/s / "); + ffSizeAppendNum(process->bytesWritten, &output); + ffStrbufAppendS(&output, "/s"); + } } ffStrbufPutTo(&output, stdout); } else { @@ -92,16 +96,54 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "sort")) { int value; const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){ - { "cpu", FF_TOP_SORT_CPU }, - { "memory", FF_TOP_SORT_MEMORY }, - { "disk-read", FF_TOP_SORT_DISK_READ }, - { "disk-write", FF_TOP_SORT_DISK_WRITE }, + { "cpu", FF_TOP_TYPE_CPU }, + { "memory", FF_TOP_TYPE_MEMORY }, + { "disk-read", FF_TOP_TYPE_DISK_READ }, + { "disk-write", FF_TOP_TYPE_DISK_WRITE }, {}, }); if (error) { ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); } else { - options->sort = (FFTopSortType) value; + options->sort = (FFTopTypes) value; + } + continue; + } else if (unsafe_yyjson_equals_str(key, "showTypes")) { + if (yyjson_is_arr(val)) { + options->showTypes = 0; + yyjson_val* item; + size_t aidx, amax; + yyjson_arr_foreach (val, aidx, amax, item) { + int value; + const char* error = ffJsonConfigParseEnum(item, &value, (FFKeyValuePair[]){ + { "cpu", FF_TOP_TYPE_CPU }, + { "memory", FF_TOP_TYPE_MEMORY }, + { "disk", FF_TOP_TYPE_DISK }, + {}, + }); + if (error == nullptr) { + options->showTypes |= (FFTopTypes) value; + } + if (error) { + options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + break; + } + } + } else { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]){ + { "cpu", FF_TOP_TYPE_CPU }, + { "memory", FF_TOP_TYPE_MEMORY }, + { "disk", FF_TOP_TYPE_DISK }, + {}, + }); + if (error == nullptr) { + options->showTypes = (FFTopTypes) value; + } + if (error) { + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", unsafe_yyjson_get_str(key), error); + } } continue; } else if (unsafe_yyjson_equals_str(key, "processes")) { @@ -121,19 +163,25 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); yyjson_mut_obj_add_str(doc, module, "type", "top"); - switch (options->sort) { - case FF_TOP_SORT_CPU: - yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); - break; - case FF_TOP_SORT_MEMORY: - yyjson_mut_obj_add_str(doc, module, "sort", "memory"); - break; - case FF_TOP_SORT_DISK_READ: - yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); - break; - case FF_TOP_SORT_DISK_WRITE: - yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); - break; + yyjson_mut_val* showTypes = yyjson_mut_arr(doc); + if (options->showTypes & FF_TOP_TYPE_CPU) { + yyjson_mut_arr_add_str(doc, showTypes, "cpu"); + } + if (options->showTypes & FF_TOP_TYPE_MEMORY) { + yyjson_mut_arr_add_str(doc, showTypes, "memory"); + } + if (options->showTypes & FF_TOP_TYPE_DISK) { + yyjson_mut_arr_add_str(doc, showTypes, "disk"); + } + yyjson_mut_obj_add_val(doc, module, "showTypes", showTypes); + if (options->sort == FF_TOP_TYPE_CPU) { + yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); + } else if (options->sort == FF_TOP_TYPE_MEMORY) { + yyjson_mut_obj_add_str(doc, module, "sort", "memory"); + } else if (options->sort == FF_TOP_TYPE_DISK_READ) { + yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); + } else if (options->sort == FF_TOP_TYPE_DISK_WRITE) { + yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); } yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); @@ -153,10 +201,16 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_val* item = yyjson_mut_arr_add_obj(doc, array); yyjson_mut_obj_add_strbuf(doc, item, "name", &process->name); yyjson_mut_obj_add_uint(doc, item, "pid", process->pid); - yyjson_mut_obj_add_real(doc, item, "cpuPercent", process->cpuPercent); - yyjson_mut_obj_add_uint(doc, item, "mem", process->memBytes); - yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); - yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); + if (options->showTypes & FF_TOP_TYPE_CPU) { + yyjson_mut_obj_add_real(doc, item, "cpuPercent", process->cpuPercent); + } + if (options->showTypes & FF_TOP_TYPE_MEMORY) { + yyjson_mut_obj_add_uint(doc, item, "mem", process->memBytes); + } + if (options->showTypes & FF_TOP_TYPE_DISK) { + yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); + yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); + } yyjson_mut_obj_add_uint(doc, item, "startTime", process->startTime); } @@ -168,7 +222,8 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ void ffInitTopOptions(FFTopOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); - options->sort = FF_TOP_SORT_CPU; + options->sort = FF_TOP_TYPE_CPU; + options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; options->nProcesses = 5; options->waitTime = 500; options->compact = false; diff --git a/src/modules/top/top.h b/src/modules/top/top.h index 144130fd66..48c13d6df3 100644 --- a/src/modules/top/top.h +++ b/src/modules/top/top.h @@ -2,7 +2,7 @@ #include "option.h" -void ffPrepareTopProcesses(void); +void ffPrepareTopProcesses(FFTopTypes showTypes); bool ffPrintTop(FFTopOptions* options); void ffInitTopOptions(FFTopOptions* options); From 71728247abd2aa5ee1dbb63681d18a76253e0c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 23:24:31 +0800 Subject: [PATCH 059/109] Common (Sysctl): handle varying data lengths in integer retrieval functions --- src/common/impl/sysctl.c | 56 ++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/common/impl/sysctl.c b/src/common/impl/sysctl.c index e17b5c348e..122a790918 100644 --- a/src/common/impl/sysctl.c +++ b/src/common/impl/sysctl.c @@ -22,21 +22,41 @@ const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result) { } int ffSysctlGetInt(int mib1, int mib2, int defaultValue) { - int result; + alignas(int) uint8_t result[sizeof(int)]; size_t neededLength = sizeof(result); if (sysctl((int[]) { mib1, mib2 }, 2, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue) { - int64_t result; + alignas(int64_t) uint8_t result[sizeof(int64_t)]; size_t neededLength = sizeof(result); if (sysctl((int[]) { mib1, mib2 }, 2, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int64_t): + return *(int64_t*)result; + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } #else const char* ffSysctlGetString(const char* propName, FFstrbuf* result) { @@ -59,21 +79,41 @@ const char* ffSysctlGetString(const char* propName, FFstrbuf* result) { } int ffSysctlGetInt(const char* propName, int defaultValue) { - int result; + alignas(int) uint8_t result[sizeof(int)]; size_t neededLength = sizeof(result); if (sysctlbyname(propName, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue) { - int64_t result; + alignas(int64_t) uint8_t result[sizeof(int64_t)]; size_t neededLength = sizeof(result); if (sysctlbyname(propName, &result, &neededLength, nullptr, 0) != 0) { return defaultValue; } - return result; + switch (neededLength) { + case sizeof(int64_t): + return *(int64_t*)result; + case sizeof(int32_t): + return *(int32_t*)result; + case sizeof(int16_t): + return *(int16_t*)result; + case sizeof(int8_t): + return *(int8_t*)result; + default: + return defaultValue; + } } #endif // OpenBSD From 6c19a8b4ecb561ce7e863bd545286e579f89e595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 23:27:24 +0800 Subject: [PATCH 060/109] Top (DragonFly): fixes building --- src/detection/top/top_dbsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 872ba97f88..1a9bbb8883 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; From 1b1df2e731d5f59a635a1507dac421f3ab960e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 25 Aug 2026 23:27:36 +0800 Subject: [PATCH 061/109] Common (Settings): tidy --- src/common/impl/settings.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/common/impl/settings.c b/src/common/impl/settings.c index 0f00054df2..11dbac6705 100644 --- a/src/common/impl/settings.c +++ b/src/common/impl/settings.c @@ -450,12 +450,10 @@ bool ffSettingsGetSQLite3String(const char* dbPath, const char* query, FFstrbuf* return true; } #else // FF_HAVE_SQLITE3 -int ffSettingsGetSQLite3Int(const char* dbPath, const char* query) { - FF_UNUSED(dbPath, query) +int ffSettingsGetSQLite3Int(const char*, const char*) { return 0; } -bool ffSettingsGetSQLite3String(const char* dbPath, const char* query, FFstrbuf* result) { - FF_UNUSED(dbPath, query, result) +bool ffSettingsGetSQLite3String(const char*, const char*, FFstrbuf*) { return false; } #endif // FF_HAVE_SQLITE3 From 3b76ade662f34f70074c45601ac1ac3c13950006 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 08:50:08 +0800 Subject: [PATCH 062/109] Shell: fixes the fast path of ash version detection --- src/detection/terminalshell/terminalshell.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index fa323aa9eb..4eccf6d490 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -194,6 +194,9 @@ static bool extractBusyboxVersion(const char* line, uint32_t len, void* userdata static bool getShellVersionAsh(FFstrbuf* exe, FFstrbuf* version) { ffBinaryExtractStrings(exe->chars, extractBusyboxVersion, version, (uint32_t) strlen("BusyBox v0.0.0")); + if (version->length > 0) { + return true; + } const char* error = ffStrbufEndsWithS(exe, "busybox") ? ffProcessAppendStdErr(version, (char* const[]) { exe->chars, "ash", "--help", nullptr }) From 9670b585fbc0498b13a14d1466d2e27aac3cfa4d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 10:50:16 +0800 Subject: [PATCH 063/109] LM: detects LM from processes list if systemd is not available 2. removes type field 3. small optimizations --- CMakeLists.txt | 4 +- src/detection/lm/lm.h | 1 - src/detection/lm/lm_linux.c | 278 +++++++++++++++++++++++++++++++++--- src/modules/lm/lm.c | 10 -- 4 files changed, 260 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f4605509f..33e72853b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -978,7 +978,7 @@ elseif(OpenBSD) src/detection/gpu/gpu_bsddrm.c src/detection/gtk_qt/gtk.c src/detection/host/host_obsd.c - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c src/detection/keyboard/keyboard_nosupport.c @@ -1227,7 +1227,7 @@ elseif(SunOS) src/detection/initsystem/initsystem_linux.c src/detection/keyboard/keyboard_nosupport.c src/detection/libc/libc_nosupport.c - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_linux.c src/detection/loadavg/loadavg_sunos.c src/detection/locale/locale_linux.c src/detection/localip/localip_linux.c diff --git a/src/detection/lm/lm.h b/src/detection/lm/lm.h index d30229a79f..8bedf8e5c2 100644 --- a/src/detection/lm/lm.h +++ b/src/detection/lm/lm.h @@ -5,7 +5,6 @@ typedef struct FFLMResult { FFstrbuf service; - FFstrbuf type; FFstrbuf version; } FFLMResult; diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 1623c72775..d208a26415 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -1,18 +1,35 @@ #include "lm.h" +#include "common/io.h" +#include "common/mallocHelper.h" #include "common/properties.h" -#include "common/dbus.h" #include "common/processing.h" +#include "common/strutil.h" #include "detection/displayserver/displayserver.h" #include +#if __FreeBSD__ + #include + #include + #include +#elif __OpenBSD__ + #include + #include + #include +#elif __sun + #include +#elif __NetBSD__ + #include + #include +#endif + #define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/" #define FF_SYSTEMD_USERS_PATH "/run/systemd/users/" static const char* getGdmVersion(FFstrbuf* version) { - const char* error = ffProcessAppendStdOut(version, (char* const[]) { "gdm", "--version", nullptr }); + const char* error = ffProcessAppendStdOut(version, (char* const[]) { "gdm3", "--version", nullptr }); if (error || version->length == 0) { - error = ffProcessAppendStdOut(version, (char* const[]) { "gdm3", "--version", nullptr }); + error = ffProcessAppendStdOut(version, (char* const[]) { "gdm", "--version", nullptr }); if (error || version->length == 0) { return "Failed to get GDM version"; } @@ -112,34 +129,264 @@ static const char* getLightdmVersion(FFstrbuf* version) { return nullptr; } -const char* ffDetectLM(FFLMResult* result) { +#if __linux__ && !__ANDROID__ +static const char* detectBySystemd(FFLMResult* result) { FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY sessionId = ffStrbufCreateS(getenv("XDG_SESSION_ID")); if (sessionId.length == 0) { // On some incorrectly configured systems, $XDG_SESSION_ID is not set. Try finding it ourself // WARNING: This is private data. Do not parse - ffStrbufSetF(&path, FF_SYSTEMD_USERS_PATH "%d", instance.state.platform.uid); + ffStrbufAppendS(&path, FF_SYSTEMD_USERS_PATH); + ffStrbufAppendUInt(&path, instance.state.platform.uid); // This is actually buggy, and assumes current user is using DE // `sd_pid_get_session` can be a better option, but we need to find a pid to use - if (!ffParsePropFileValues(path.chars, 1, (FFpropquery[]) { + if (!ffParsePropFileValues(path.chars, 1, (FFpropquery[]){ { "DISPLAY=", &sessionId }, })) { return "Failed to get $XDG_SESSION_ID"; } } - ffStrbufSetS(&path, FF_SYSTEMD_SESSIONS_PATH); + ffStrbufClear(&path); + ffStrbufAppendS(&path, FF_SYSTEMD_SESSIONS_PATH); ffStrbufAppend(&path, &sessionId); // WARNING: This is private data. Do not parse - if (!ffParsePropFileValues(path.chars, 2, (FFpropquery[]) { - { "SERVICE=", &result->service }, - { "TYPE=", &result->type }, - })) { + if (!ffParsePropFile(path.chars, "SERVICE=", &result->service)) { return "Failed to parse " FF_SYSTEMD_SESSIONS_PATH "$XDG_SESSION_ID"; } + return nullptr; +} +#endif + +static const char* testLms(const char* psName) { + static const char* A[] = { + "atrium", + }; + static const char* C[] = { + "cdm", + }; + static const char* E[] = { + "entrance", + }; + static const char* G[] = { + "gdm", + "gdm3", + "greetd", + }; + static const char* L[] = { + "lemurs", + "lightdm", + "lxdm", + "ly", + }; + static const char* P[] = { + "plasmalogin", + }; + static const char* S[] = { + "sddm", + "slim", + }; + static const char* T[] = { + "tbsm", + }; + static const char* X[] = { + "xdm", + }; + + switch (psName[0]) { + #define PS_CASE(letter, array) \ + case letter: \ + for (uint32_t i = 0; i < ARRAY_SIZE(array); ++i) { \ + if (ffStrEqualsIgnCase(psName, array[i])) { \ + return array[i]; \ + } \ + } \ + break; + PS_CASE('a', A) + PS_CASE('c', C) + PS_CASE('e', E) + PS_CASE('g', G) + PS_CASE('l', L) + PS_CASE('p', P) + PS_CASE('s', S) + PS_CASE('t', T) + PS_CASE('x', X) + } + return nullptr; +} + +const char* detectByProcesses(FFLMResult* result) { +#if __FreeBSD__ + #ifdef __DragonFly__ + #define ki_comm kp_comm + #endif + + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, 0 }; + size_t length = 0; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, nullptr) failed"; + } + + FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, procs) failed"; + } + + length /= sizeof(*procs); + + for (struct kinfo_proc* proc = procs; proc < procs + length; ++proc) { + const char* lm = testLms(proc->ki_comm); + if (lm) { + ffStrbufSetStatic(&result->service, lm); + break; + } + } +#elif __OpenBSD__ + kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + int count = 0; + const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, 0, sizeof(*proc), &count); + if (proc) { + for (int i = 0; i < count; ++i) { + const char* lm = testLms(proc[i].p_comm); + if (lm) { + ffStrbufSetStatic(&result->service, lm); + break; + } + } + } + kvm_close(kd); +#elif __sun + FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); + if (procdir == nullptr) { + return "opendir(\"/proc\") failed"; + } + + FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64); + ffStrbufAppendS(&procPath, "/proc/"); + + uint32_t procPathLength = procPath.length; + + struct dirent* dirent; + while ((dirent = readdir(procdir)) != nullptr) { + if (!ffCharIsDigit(dirent->d_name[0])) { + continue; + } + + ffStrbufAppendS(&procPath, dirent->d_name); + ffStrbufAppendS(&procPath, "/psinfo"); + psinfo_t proc; + if (ffReadFileData(procPath.chars, sizeof(proc), &proc) == sizeof(proc)) { + ffStrbufSubstrBefore(&procPath, procPathLength); + + if (proc.pr_uid != 0) { + continue; + } + + const char* lm = testLms(proc.pr_fname); + if (lm) { + ffStrbufSetS(&result->service, lm); + break; + } + } + } +#elif __linux__ || __GNU__ + FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); + if (procdir == nullptr) { + return "opendir(\"/proc\") failed"; + } + + FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64); + int procfd = dirfd(procdir); + + struct dirent* dirent; + while ((dirent = readdir(procdir)) != nullptr) { + // Match only folders starting with a number (the pid folders) + if (dirent->d_type != DT_DIR || !ffCharIsDigit(dirent->d_name[0])) { + continue; + } + + ffStrbufSetS(&procPath, dirent->d_name); + uint32_t procFolderPathLength = procPath.length; + + // Don't check for processes not owned by root (login managers run as root). + char loginuid[32]; + ffStrbufAppendS(&procPath, "/loginuid"); + ssize_t bytesRead = ffReadFileDataRelative(procfd, procPath.chars, sizeof(loginuid) - 1, loginuid); + if (bytesRead <= 0) { + continue; + } + loginuid[bytesRead] = '\0'; + + if (strtol(loginuid, nullptr, 10) != (long) (uint32_t) -1 /* no loginuid */) { + continue; + } + + ffStrbufSubstrBefore(&procPath, procFolderPathLength); + + ffStrbufAppendS(&procPath, "/comm"); + char comm[256]; + bytesRead = ffReadFileDataRelative(procfd, procPath.chars, sizeof(comm) - 1, comm); + if (bytesRead <= 0) { + continue; + } + if (comm[bytesRead - 1] == '\n') { + --bytesRead; + } + comm[bytesRead] = '\0'; + + const char* lm = testLms(comm); + if (lm) { + ffStrbufSetS(&result->service, lm); + break; + } + } +#elif __NetBSD__ + int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_UID, 0, sizeof(struct kinfo_proc2), INT_MAX }; + + size_t size = 0; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &size, nullptr, 0) != 0) { + return "sysctl(KERN_PROC_UID, nullptr) failed"; + } + + FF_AUTO_FREE struct kinfo_proc2* procs = malloc(size); + + if (sysctl(request, ARRAY_SIZE(request), procs, &size, nullptr, 0) != 0) { + return "sysctl(KERN_PROC_UID, procs) failed"; + } + + for (struct kinfo_proc2* proc = procs; proc < procs + (size / sizeof(struct kinfo_proc2)); proc++) { + const char* lm = testLms(proc->p_comm); + if (lm) { + ffStrbufSetStatic(&result->service, lm); + break; + } + } +#endif + + if (result->service.length == 0) { + return "Failed to detect login manager by processes"; + } + + return nullptr; +} + +const char* ffDetectLM(FFLMResult* result) { + const char* error = ""; +#if __linux__ && !__ANDROID__ + error = detectBySystemd(result); +#endif + + if (error != nullptr) { + error = detectByProcesses(result); + } + + if (error != nullptr) { + return error; + } if (instance.config.general.detectVersion) { if (ffStrbufStartsWithS(&result->service, "gdm")) { @@ -155,14 +402,5 @@ const char* ffDetectLM(FFLMResult* result) { } } - // Correct char cases - if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_WAYLAND)) { - ffStrbufSetS(&result->type, FF_WM_PROTOCOL_WAYLAND); - } else if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_X11)) { - ffStrbufSetS(&result->type, FF_WM_PROTOCOL_X11); - } else if (ffStrbufIgnCaseEqualS(&result->type, FF_WM_PROTOCOL_TTY)) { - ffStrbufSetS(&result->type, FF_WM_PROTOCOL_TTY); - } - return nullptr; } diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index ca9debe115..2ce541eede 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -8,7 +8,6 @@ bool ffPrintLM(FFLMOptions* options) { bool success = false; FFLMResult result; ffStrbufInit(&result.service); - ffStrbufInit(&result.type); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -28,14 +27,10 @@ bool ffPrintLM(FFLMOptions* options) { if (result.version.length) { printf(" %s", result.version.chars); } - if (result.type.length) { - printf(" (%s)", result.type.chars); - } putchar('\n'); } else { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.service, "service"), - FF_ARG(result.type, "type"), FF_ARG(result.version, "version"), })); } @@ -43,7 +38,6 @@ bool ffPrintLM(FFLMOptions* options) { exit: ffStrbufDestroy(&result.service); - ffStrbufDestroy(&result.type); ffStrbufDestroy(&result.version); return success; @@ -69,7 +63,6 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do bool success = false; FFLMResult result; ffStrbufInit(&result.service); - ffStrbufInit(&result.type); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -85,13 +78,11 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "service", &result.service); - yyjson_mut_obj_add_strbuf(doc, obj, "type", &result.type); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); success = true; exit: ffStrbufDestroy(&result.service); - ffStrbufDestroy(&result.type); ffStrbufDestroy(&result.version); return success; @@ -138,7 +129,6 @@ FFModuleBaseInfo ffLMModuleInfo = { .generateJsonConfig = (void*) ffGenerateLMJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { { "LM service", "service" }, - { "LM type", "type" }, { "LM version", "version" }, })), .defaultOrder = 20, From 8b162e89de39a78609bbc8ebb4f5a5299f50b69e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 14:14:24 +0800 Subject: [PATCH 064/109] WMDE: improves performance --- src/detection/displayserver/linux/wmde.c | 55 +++++++++++++++--------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 8044c4a95a..6984d1d0c3 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -7,6 +7,7 @@ #include #include #include +#include #if __FreeBSD__ #include @@ -376,48 +377,60 @@ static const char* getFromProcesses(FFDisplayServerResult* result) { } FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64); - ffStrbufAppendS(&procPath, "/proc/"); - - uint32_t procPathLength = procPath.length; - - FF_STRBUF_AUTO_DESTROY loginuid = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY processName = ffStrbufCreateA(256); // Some processes have large command lines (looking at you chrome) + int procfd = dirfd(procdir); struct dirent* dirent; while ((dirent = readdir(procdir)) != nullptr) { // Match only folders starting with a number (the pid folders) - if (dirent->d_type != DT_DIR || !ffCharIsDigit(dirent->d_name[0])) { + if ((dirent->d_type != DT_DIR && dirent->d_type != DT_UNKNOWN) || !ffCharIsDigit(dirent->d_name[0])) { continue; } - ffStrbufAppendS(&procPath, dirent->d_name); + ffStrbufSetS(&procPath, dirent->d_name); uint32_t procFolderPathLength = procPath.length; // Don't check for processes not owned by the current user. + char loginuid[32]; ffStrbufAppendS(&procPath, "/loginuid"); - ffReadFileBuffer(procPath.chars, &loginuid); - if (ffStrbufToUInt(&loginuid, (uint64_t) -1) != userId) { - ffStrbufSubstrBefore(&procPath, procPathLength); + ssize_t bytesRead = ffReadFileDataRelative(procfd, procPath.chars, sizeof(loginuid) - 1, loginuid); + if (bytesRead <= 0) { + continue; + } + loginuid[bytesRead] = '\0'; + if (strtol(loginuid, nullptr, 10) != (long) userId) { continue; } ffStrbufSubstrBefore(&procPath, procFolderPathLength); - // We check the cmdline for the process name, because it is not trimmed. - ffStrbufAppendS(&procPath, "/cmdline"); - ffReadFileBuffer(procPath.chars, &processName); - ffStrbufTrimRightSpace(&processName); - ffStrbufSubstrBeforeFirstC(&processName, '\0'); // Trim the arguments - ffStrbufSubstrAfterLastC(&processName, '/'); - - ffStrbufSubstrBefore(&procPath, procPathLength); + // We check the realpath for the process name + ffStrbufAppendS(&procPath, "/exe"); + char exePath[PATH_MAX]; + ssize_t exePathLength = readlinkat(procfd, procPath.chars, exePath, sizeof(exePath) - 1); + const char* processName; + if (exePathLength >= 0) { + exePath[exePathLength] = '\0'; + processName = basename(exePath); + } else { + ffStrbufSubstrBefore(&procPath, procFolderPathLength); + ffStrbufAppendS(&procPath, "/comm"); + exePathLength = ffReadFileDataRelative(procfd, procPath.chars, sizeof(exePath) - 1, exePath); + if (exePathLength <= 0) { + continue; + } + if (exePath[exePathLength - 1] == '\n') { + --exePathLength; + } + exePath[exePathLength] = '\0'; + processName = exePath; + } if (result->dePrettyName.length == 0) { - applyPrettyNameIfDE(result, processName.chars); + applyPrettyNameIfDE(result, processName); } if (result->wmPrettyName.length == 0) { - applyNameIfWM(result, processName.chars); + applyNameIfWM(result, processName); } if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) { From fb309134b5bcc6349f53eca3d404afda1bd44b60 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 14:43:16 +0800 Subject: [PATCH 065/109] LM (Linux): queries systemd session info via dbus --- src/detection/lm/lm_linux.c | 50 +++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index d208a26415..0bdab580a4 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -4,7 +4,10 @@ #include "common/properties.h" #include "common/processing.h" #include "common/strutil.h" -#include "detection/displayserver/displayserver.h" + +#ifdef FF_HAVE_DBUS + #include "common/dbus.h" +#endif #include @@ -23,9 +26,6 @@ #include #endif -#define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/" -#define FF_SYSTEMD_USERS_PATH "/run/systemd/users/" - static const char* getGdmVersion(FFstrbuf* version) { const char* error = ffProcessAppendStdOut(version, (char* const[]) { "gdm3", "--version", nullptr }); if (error || version->length == 0) { @@ -130,7 +130,33 @@ static const char* getLightdmVersion(FFstrbuf* version) { } #if __linux__ && !__ANDROID__ -static const char* detectBySystemd(FFLMResult* result) { +#ifdef FF_HAVE_DBUS +static const char* detectBySystemdDbus(FFLMResult* result) { + // This is the standard way to query the systemd session service name, + // and requires no $XDG_SESSION_ID being available + FF_DBUS_AUTO_DESTROY_DATA FFDBusData dbus = {}; + if (ffDBusLoadData(DBUS_BUS_SYSTEM, &dbus) != nullptr) { + return "Failed to load system DBus"; + } + + if (!ffDBusGetPropertyString( + &dbus, + "org.freedesktop.login1", + "/org/freedesktop/login1/session/auto", + "org.freedesktop.login1.Session", + "Service", + &result->service)) { + return "Failed to get systemd session Service property"; + } + + return nullptr; +} +#endif + +#define FF_SYSTEMD_SESSIONS_PATH "/run/systemd/sessions/" +#define FF_SYSTEMD_USERS_PATH "/run/systemd/users/" + +static const char* detectBySystemdPrivate(FFLMResult* result) { FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY sessionId = ffStrbufCreateS(getenv("XDG_SESSION_ID")); @@ -142,9 +168,7 @@ static const char* detectBySystemd(FFLMResult* result) { // This is actually buggy, and assumes current user is using DE // `sd_pid_get_session` can be a better option, but we need to find a pid to use - if (!ffParsePropFileValues(path.chars, 1, (FFpropquery[]){ - { "DISPLAY=", &sessionId }, - })) { + if (!ffParsePropFile(path.chars, "DISPLAY=", &sessionId)) { return "Failed to get $XDG_SESSION_ID"; } } @@ -157,6 +181,7 @@ static const char* detectBySystemd(FFLMResult* result) { if (!ffParsePropFile(path.chars, "SERVICE=", &result->service)) { return "Failed to parse " FF_SYSTEMD_SESSIONS_PATH "$XDG_SESSION_ID"; } + return nullptr; } #endif @@ -376,8 +401,13 @@ const char* detectByProcesses(FFLMResult* result) { const char* ffDetectLM(FFLMResult* result) { const char* error = ""; -#if __linux__ && !__ANDROID__ - error = detectBySystemd(result); +#if __linux__ + #ifdef FF_HAVE_DBUS + error = detectBySystemdDbus(result); + #endif + if (error != nullptr) { + error = detectBySystemdPrivate(result); + } #endif if (error != nullptr) { From 203cd7cbcfdc04feacb16e6f7a2423deeadb6aae Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 15:19:57 +0800 Subject: [PATCH 066/109] LM (Linux): adds pretty name --- src/detection/lm/lm.h | 1 + src/detection/lm/lm_linux.c | 62 +++++++++++++++++++++++++++++++++++++ src/modules/lm/lm.c | 11 +++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/detection/lm/lm.h b/src/detection/lm/lm.h index 8bedf8e5c2..d2c3299f6d 100644 --- a/src/detection/lm/lm.h +++ b/src/detection/lm/lm.h @@ -5,6 +5,7 @@ typedef struct FFLMResult { FFstrbuf service; + FFstrbuf prettyName; FFstrbuf version; } FFLMResult; diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 0bdab580a4..8e197b31f1 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -418,6 +418,68 @@ const char* ffDetectLM(FFLMResult* result) { return error; } + switch (result->service.chars[0]) { + case 'a': + if (ffStrEqualsIgnCase(result->service.chars, "atrium")) { + ffStrbufSetStatic(&result->prettyName, "Atrium"); + } + break; + case 'c': + if (ffStrEqualsIgnCase(result->service.chars, "cdm")) { + ffStrbufSetStatic(&result->prettyName, "CDM"); + } + break; + case 'e': + if (ffStrEqualsIgnCase(result->service.chars, "entrance")) { + ffStrbufSetStatic(&result->prettyName, "Entrance"); + } + break; + case 'g': + if (ffStrbufStartsWithIgnCaseS(&result->service, "gdm")) { + ffStrbufSetStatic(&result->prettyName, "GDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "greetd")) { + ffStrbufSetStatic(&result->prettyName, "greetd"); + } + break; + case 'l': + if (ffStrEqualsIgnCase(result->service.chars, "lemurs")) { + ffStrbufSetStatic(&result->prettyName, "Lemurs"); + } else if (ffStrEqualsIgnCase(result->service.chars, "lightdm")) { + ffStrbufSetStatic(&result->prettyName, "LightDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "lxdm")) { + ffStrbufSetStatic(&result->prettyName, "LXDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "ly")) { + ffStrbufSetStatic(&result->prettyName, "Ly"); + } + break; + case 'p': + if (ffStrEqualsIgnCase(result->service.chars, "plasmalogin")) { + ffStrbufSetStatic(&result->prettyName, "Plasma Login"); + } + break; + case 's': + if (ffStrEqualsIgnCase(result->service.chars, "sddm")) { + ffStrbufSetStatic(&result->prettyName, "SDDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "slim")) { + ffStrbufSetStatic(&result->prettyName, "SLiM"); + } + break; + case 't': + if (ffStrEqualsIgnCase(result->service.chars, "tbsm")) { + ffStrbufSetStatic(&result->prettyName, "TBSM"); + } + break; + case 'x': + if (ffStrEqualsIgnCase(result->service.chars, "xdm")) { + ffStrbufSetStatic(&result->prettyName, "XDM"); + } + break; + } + + if (result->prettyName.length == 0) { + ffStrbufSet(&result->prettyName, &result->service); + } + if (instance.config.general.detectVersion) { if (ffStrbufStartsWithS(&result->service, "gdm")) { getGdmVersion(&result->version); diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 2ce541eede..ece31fb0ec 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -8,6 +8,7 @@ bool ffPrintLM(FFLMOptions* options) { bool success = false; FFLMResult result; ffStrbufInit(&result.service); + ffStrbufInit(&result.prettyName); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -23,7 +24,7 @@ bool ffPrintLM(FFLMOptions* options) { if (options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufWriteTo(&result.service, stdout); + ffStrbufWriteTo(&result.prettyName, stdout); if (result.version.length) { printf(" %s", result.version.chars); } @@ -31,6 +32,7 @@ bool ffPrintLM(FFLMOptions* options) { } else { FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(LM), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.service, "service"), + FF_ARG(result.prettyName, "pretty-name"), FF_ARG(result.version, "version"), })); } @@ -38,6 +40,7 @@ bool ffPrintLM(FFLMOptions* options) { exit: ffStrbufDestroy(&result.service); + ffStrbufDestroy(&result.prettyName); ffStrbufDestroy(&result.version); return success; @@ -63,6 +66,7 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do bool success = false; FFLMResult result; ffStrbufInit(&result.service); + ffStrbufInit(&result.prettyName); ffStrbufInit(&result.version); const char* error = ffDetectLM(&result); @@ -78,11 +82,13 @@ bool ffGenerateLMJsonResult([[maybe_unused]] FFLMOptions* options, yyjson_mut_do yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "service", &result.service); + yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result.prettyName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); success = true; exit: ffStrbufDestroy(&result.service); + ffStrbufDestroy(&result.prettyName); ffStrbufDestroy(&result.version); return success; @@ -128,7 +134,8 @@ FFModuleBaseInfo ffLMModuleInfo = { .generateJsonResult = (void*) ffGenerateLMJsonResult, .generateJsonConfig = (void*) ffGenerateLMJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - { "LM service", "service" }, + { "LM service / process name", "service" }, + { "LM pretty name", "pretty-name" }, { "LM version", "version" }, })), .defaultOrder = 20, From c5598d23619a72dbf62ad6ee0d35e3e652457340 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 15:21:04 +0800 Subject: [PATCH 067/109] LM (macOS): adds support --- CMakeLists.txt | 2 +- src/detection/lm/lm_apple.m | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/detection/lm/lm_apple.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 33e72853b2..be5f4d7648 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1050,7 +1050,7 @@ elseif(APPLE) src/detection/icons/icons_nosupport.c src/detection/initsystem/initsystem_linux.c src/detection/keyboard/keyboard_apple.c - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_apple.m src/detection/loadavg/loadavg_bsd.c src/detection/libc/libc_apple.c src/detection/locale/locale_linux.c diff --git a/src/detection/lm/lm_apple.m b/src/detection/lm/lm_apple.m new file mode 100644 index 0000000000..d600058d47 --- /dev/null +++ b/src/detection/lm/lm_apple.m @@ -0,0 +1,18 @@ +#include "lm.h" + +#import + +const char* ffDetectLM(FFLMResult* result) { + ffStrbufSetStatic(&result->service, "loginwindow"); + ffStrbufSetStatic(&result->prettyName, "Login Window"); + + NSError* error; + NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL fileURLWithPath:@"/System/Library/CoreServices/loginwindow.app/Contents/Info.plist" isDirectory:NO] + error:&error]; + + if (dict) { + ffStrbufSetS(&result->version, ((NSString*) dict[@"CFBundleShortVersionString"]).UTF8String); + } + + return nullptr; +} From 32757b0e43d952ab1b303b345cd950ac27823716 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 15:21:22 +0800 Subject: [PATCH 068/109] LM (Windows): adds support --- CMakeLists.txt | 2 +- src/detection/lm/lm_windows.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/detection/lm/lm_windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index be5f4d7648..9ba505650d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1144,7 +1144,7 @@ elseif(WIN32) src/detection/initsystem/initsystem_windows.c src/detection/keyboard/keyboard_windows.c src/detection/libc/libc_windows.cpp - src/detection/lm/lm_nosupport.c + src/detection/lm/lm_windows.c src/detection/loadavg/loadavg_nosupport.c src/detection/locale/locale_windows.c src/detection/localip/localip_windows.c diff --git a/src/detection/lm/lm_windows.c b/src/detection/lm/lm_windows.c new file mode 100644 index 0000000000..79cffba2b2 --- /dev/null +++ b/src/detection/lm/lm_windows.c @@ -0,0 +1,19 @@ +#include "lm.h" + +#include "common/windows/version.h" +#include "common/windows/nt.h" + +#include + +const char* ffDetectLM(FFLMResult* result) { + ffStrbufSetStatic(&result->service, "LogonUI"); + ffStrbufSetStatic(&result->prettyName, "Logon User Interface"); + + if (instance.config.general.detectVersion) { + wchar_t exePath[MAX_PATH]; + _snwprintf(exePath, ARRAY_SIZE(exePath), L"%ls\\system32\\%ls", (const wchar_t*) SharedUserData->NtSystemRoot, L"LogonUI.exe"); + ffGetFileVersion(exePath, nullptr, &result->version); + } + + return nullptr; +} From 2b42db58dadaf07115896d4eaa718d1294c954bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 26 Aug 2026 17:35:33 +0800 Subject: [PATCH 069/109] LM (OpenBSD): adds support --- src/detection/lm/lm_linux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 8e197b31f1..8b34d86c09 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -219,6 +219,7 @@ static const char* testLms(const char* psName) { }; static const char* X[] = { "xdm", + "xenodm", }; switch (psName[0]) { @@ -472,6 +473,8 @@ const char* ffDetectLM(FFLMResult* result) { case 'x': if (ffStrEqualsIgnCase(result->service.chars, "xdm")) { ffStrbufSetStatic(&result->prettyName, "XDM"); + } else if (ffStrEqualsIgnCase(result->service.chars, "xenodm")) { + ffStrbufSetStatic(&result->prettyName, "Xenodm"); } break; } From c9ad429a1b01f835750991badce38f7478daf9b0 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 26 Aug 2026 23:12:25 +0800 Subject: [PATCH 070/109] Global: introduces global macro `FF_PATH_PKG_BASE` to replace `_PATH_LOCALBASE` --- src/common/impl/FFPlatform_unix.c | 6 ++---- src/common/path.h | 16 ++++++++++++++++ src/detection/de/de_linux.c | 21 ++------------------- src/detection/gpu/gpu_pci.c | 17 +++-------------- src/detection/lm/lm_linux.c | 4 +++- src/detection/terminalshell/terminalshell.c | 13 ++----------- src/detection/wm/wm_linux.c | 5 ++--- 7 files changed, 30 insertions(+), 52 deletions(-) diff --git a/src/common/impl/FFPlatform_unix.c b/src/common/impl/FFPlatform_unix.c index ec2ef1699d..e3ea77f51e 100644 --- a/src/common/impl/FFPlatform_unix.c +++ b/src/common/impl/FFPlatform_unix.c @@ -3,7 +3,7 @@ #include "common/arrutil.h" #include "common/strutil.h" #include "common/io.h" -#include "fastfetch_config.h" +#include "common/path.h" #include #include @@ -238,9 +238,7 @@ static void getDataDirs(FFPlatform* platform) { ffPlatformPathAddHome(&platform->dataDirs, platform, ""); platformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); -#ifdef _PATH_LOCALBASE - ffPlatformPathAddAbsolute(&platform->dataDirs, _PATH_LOCALBASE "/share/"); -#endif + ffPlatformPathAddAbsolute(&platform->dataDirs, FF_PATH_PKG_BASE "/share/"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/"); } diff --git a/src/common/path.h b/src/common/path.h index 705b1c0948..0d292d8689 100644 --- a/src/common/path.h +++ b/src/common/path.h @@ -2,6 +2,7 @@ #include "common/FFstrbuf.h" #include "common/strutil.h" +#include "fastfetch_config.h" const char* ffFindExecutableInPath(const char* name, FFstrbuf* result); static inline bool ffIsAbsolutePath(const char* path) { @@ -19,3 +20,18 @@ char* realpath(const char* __restrict file_name, char* __restrict resolved_name ssize_t freadlink(void* hFile, char* buf, size_t bufsiz); ssize_t readlink(const char* path, char* buf, size_t bufsiz); #endif + +#ifdef __FreeBSD__ + #include + #ifdef _PATH_LOCALBASE + #define FF_PATH_PKG_BASE _PATH_LOCALBASE + #else + #define FF_PATH_PKG_BASE "/usr/local" + #endif +#elif __OpenBSD__ + #define FF_PATH_PKG_BASE "/usr/local" +#elif __NetBSD__ + #define FF_PATH_PKG_BASE "/usr/pkg" +#else + #define FF_PATH_PKG_BASE FASTFETCH_TARGET_DIR_USR +#endif \ No newline at end of file diff --git a/src/detection/de/de_linux.c b/src/detection/de/de_linux.c index e79c3f4183..719d81fe83 100644 --- a/src/detection/de/de_linux.c +++ b/src/detection/de/de_linux.c @@ -11,29 +11,12 @@ #include "detection/displayserver/displayserver.h" #include -#ifdef __FreeBSD__ - #include - #ifndef _PATH_LOCALBASE - #define _PATH_LOCALBASE "/usr/local" - #endif -#elif __OpenBSD__ - #define _PATH_LOCALBASE "/usr/local" -#elif __NetBSD__ - #define _PATH_LOCALBASE "/usr/pkg" -#endif static void getKDE(FFstrbuf* result, [[maybe_unused]] FFDEOptions* options) { -#ifdef _PATH_LOCALBASE - ffParsePropFile(_PATH_LOCALBASE "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); + ffParsePropFile(FF_PATH_PKG_BASE "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); if (result->length == 0) { - ffParsePropFile(_PATH_LOCALBASE "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result); + ffParsePropFile(FF_PATH_PKG_BASE "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result); } -#else - ffParsePropFile(FASTFETCH_TARGET_DIR_USR "/share/wayland-sessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); - if (result->length == 0) { - ffParsePropFile(FASTFETCH_TARGET_DIR_USR "/share/xsessions/plasmax11.desktop", "X-KDE-PluginInfo-Version =", result); - } -#endif if (result->length == 0) { ffParsePropFileData("xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", result); diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index c3772fd911..b1bd08836d 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -1,21 +1,10 @@ #include "gpu.h" #include "common/io.h" +#include "common/path.h" #include "common/properties.h" #include "common/memrchr.h" #include "common/strutil.h" -#include -#ifdef __FreeBSD__ - #include - #ifndef _PATH_LOCALBASE - #define _PATH_LOCALBASE "/usr/local" - #endif -#elif __OpenBSD__ - #define _PATH_LOCALBASE "/usr/local" -#elif __NetBSD__ - #define _PATH_LOCALBASE "/usr/pkg" -#endif - #if FF_HAVE_EMBEDDED_PCIIDS #include "fastfetch_pciids.c.inc" #endif @@ -46,9 +35,9 @@ static const FFstrbuf* loadPciIds() { } } #elif __OpenBSD__ || __FreeBSD__ || __NetBSD__ - ffReadFileBuffer(_PATH_LOCALBASE "/share/hwdata/pci.ids", &pciids); + ffReadFileBuffer(FF_PATH_PKG_BASE "/share/hwdata/pci.ids", &pciids); if (pciids.length == 0) { - ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids); + ffReadFileBuffer(FF_PATH_PKG_BASE "/share/pciids/pci.ids", &pciids); } #elif __sun ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index 8b34d86c09..e4f18c19e0 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -54,6 +54,8 @@ static const char* getSshdVersion(FFstrbuf* version) { #ifdef FF_HAVE_ZLIB #include "common/library.h" + #include "common/path.h" + #include #include @@ -66,7 +68,7 @@ static const char* getSddmVersion(FFstrbuf* version) { FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzrewind) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(zlib, gzclose) - gzFile file = ffgzopen(FASTFETCH_TARGET_DIR_USR "/share/man/man1/sddm.1.gz", "rb"); + gzFile file = ffgzopen(FF_PATH_PKG_BASE "/share/man/man1/sddm.1.gz", "rb"); if (file == Z_NULL) { return "ffgzopen(\"/usr/share/man/man1/sddm.1.gz\", \"rb\") failed"; } diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 4eccf6d490..1844d51637 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -8,17 +8,8 @@ #include #include -#ifdef __FreeBSD__ - #include - #ifndef _PATH_LOCALBASE - #define _PATH_LOCALBASE "/usr/local" - #endif -#elif __OpenBSD__ - #define _PATH_LOCALBASE "/usr/local" -#elif __NetBSD__ - #define _PATH_LOCALBASE "/usr/pkg" -#elif _WIN32 +#if _WIN32 #include "common/windows/registry.h" #include "common/windows/version.h" #include @@ -663,7 +654,7 @@ static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib64/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) || ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) #else - ffReadFileData(_PATH_LOCALBASE "/share/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) + ffReadFileData(FF_PATH_PKG_BASE "/share/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) #endif ) { // Starts from version 0.17.0 diff --git a/src/detection/wm/wm_linux.c b/src/detection/wm/wm_linux.c index 5e3fff085c..a22a513fb4 100644 --- a/src/detection/wm/wm_linux.c +++ b/src/detection/wm/wm_linux.c @@ -43,9 +43,8 @@ static const char* getHyprland(FFstrbuf* result) { FF_DEBUG("Detecting Hyprland version"); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - FF_DEBUG("Checking for " FASTFETCH_TARGET_DIR_USR "/include/hyprland/src/version.h" - " file"); - if (ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/include/hyprland/src/version.h", result)) { + FF_DEBUG("Checking for " FF_PATH_PKG_BASE "/include/hyprland/src/version.h file"); + if (ffReadFileBuffer(FF_PATH_PKG_BASE "/include/hyprland/src/version.h", result)) { FF_DEBUG("Found version.h file, extracting version"); if (ffStrbufSubstrAfterFirstS(result, "\n#define GIT_TAG ")) { ffStrbufSubstrAfterFirstC(result, '"'); From 04f26a29eb9614dc7c253528b55122a3d3f5d235 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 09:45:58 +0800 Subject: [PATCH 071/109] CI: enables bluetooth module on platforms other than macOS --- .github/workflows/build-macos-hosts.yml | 4 ++-- presets/ci.jsonc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-macos-hosts.yml b/.github/workflows/build-macos-hosts.yml index 66c1666b79..5731655181 100644 --- a/.github/workflows/build-macos-hosts.yml +++ b/.github/workflows/build-macos-hosts.yml @@ -41,10 +41,10 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan --stat false + run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan --format json + run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json - name: run flashfetch run: time ./flashfetch diff --git a/presets/ci.jsonc b/presets/ci.jsonc index bbc03613f5..5499e12941 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -95,8 +95,8 @@ "opengl", "opencl", "users", - // "bluetooth", // doesn't work on macOS because it requires bluetooth permissions - // "bluetoothradio", + "bluetooth", + "bluetoothradio", "sound", "camera", "gamepad", From 5936c1cef4d8aac668dfa7278ab8d4810af3e130 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 10:15:25 +0800 Subject: [PATCH 072/109] CI: adds benchmark job --- .github/workflows/benchmark-index.html | 405 ++++++++++++++++++++++ .github/workflows/build-benchmark.yml | 56 +++ .github/workflows/build-linux-hosts.yml | 32 +- .github/workflows/build-macos-hosts.yml | 32 +- .github/workflows/build-windows-hosts.yml | 32 +- .github/workflows/ci.yml | 11 + 6 files changed, 562 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/benchmark-index.html create mode 100644 .github/workflows/build-benchmark.yml diff --git a/.github/workflows/benchmark-index.html b/.github/workflows/benchmark-index.html new file mode 100644 index 0000000000..a2b9e309a5 --- /dev/null +++ b/.github/workflows/benchmark-index.html @@ -0,0 +1,405 @@ + + + + + + Fastfetch · Benchmark + + + + + +
+
+

Fastfetch Benchmark

+ +
+

Performance history grouped by CPU family. Each chart contains all modules and total process time for one operating system and architecture. Module curves are available from the legend and hidden by default.

+ +
+ +
+ + + diff --git a/.github/workflows/build-benchmark.yml b/.github/workflows/build-benchmark.yml new file mode 100644 index 0000000000..827d81c399 --- /dev/null +++ b/.github/workflows/build-benchmark.yml @@ -0,0 +1,56 @@ +name: Reusable Benchmark + +on: + workflow_call: + +permissions: + contents: write + +jobs: + benchmark: + runs-on: ubuntu-latest + concurrency: + group: benchmark + cancel-in-progress: false + steps: + - name: checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: download benchmark data + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: benchmark-* + path: benchmarks + + - name: merge benchmark data + run: jq -s 'add' benchmarks/*/benchmark.json > benchmark.json + + - name: save benchmark dashboard + run: cp .github/benchmark-index.html "$RUNNER_TEMP/benchmark-index.html" + + - name: store benchmark result + uses: benchmark-action/github-action-benchmark@52576c92bccf6ac60c8223ec7eb2565637cae9ba # v1.22.1 + with: + name: Fastfetch + tool: customSmallerIsBetter + output-file-path: benchmark.json + github-token: ${{ secrets.GITHUB_TOKEN }} + ref: ${{ github.sha }} + auto-push: true + summary-always: true + fail-on-alert: true + benchmark-data-dir-path: dev/bench + + - name: publish benchmark dashboard + run: | + git fetch origin gh-pages + git switch --force-create gh-pages FETCH_HEAD + mkdir -p dev/bench + cp "$RUNNER_TEMP/benchmark-index.html" dev/bench/index.html + git config user.name github-action-benchmark + git config user.email github@users.noreply.github.com + git add dev/bench/index.html + if ! git diff --cached --quiet; then + git commit -m "Update benchmark dashboard" + git push origin gh-pages + fi diff --git a/.github/workflows/build-linux-hosts.yml b/.github/workflows/build-linux-hosts.yml index 612e7165f3..19aec15b0b 100644 --- a/.github/workflows/build-linux-hosts.yml +++ b/.github/workflows/build-linux-hosts.yml @@ -43,7 +43,7 @@ jobs: 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 liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build + run: sudo apt-get update && sudo apt-get install -y gcc-13 jq 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 liblua5.4-dev libvdpau-dev libva-dev rpm ninja-build - name: install linuxbrew packages run: | @@ -73,7 +73,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "linux" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -105,3 +127,9 @@ jobs: with: name: fastfetch-linux-${{ inputs.arch }} path: ./fastfetch-*.* + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-linux-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/build-macos-hosts.yml b/.github/workflows/build-macos-hosts.yml index 5731655181..d805bf70dd 100644 --- a/.github/workflows/build-macos-hosts.yml +++ b/.github/workflows/build-macos-hosts.yml @@ -29,7 +29,7 @@ jobs: - name: install required packages run: | HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew update - HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa lua quickjs-ng + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install --overwrite vulkan-loader vulkan-headers molten-vk imagemagick chafa lua quickjs-ng jq - name: configure project run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . @@ -44,7 +44,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --structure-disabled vulkan:bluetooth:bluetoothradio --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "macos" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -60,3 +82,9 @@ jobs: with: name: fastfetch-macos-${{ inputs.arch }} path: ./fastfetch-*.* + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-macos-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/build-windows-hosts.yml b/.github/workflows/build-windows-hosts.yml index 2ef399f97e..2518c25d6f 100644 --- a/.github/workflows/build-windows-hosts.yml +++ b/.github/workflows/build-windows-hosts.yml @@ -49,7 +49,7 @@ jobs: 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 }}-lua mingw-w64-clang-${{ inputs.msys-arch }}-quickjs-ng mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers + 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 }}-jq 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 }}-lua mingw-w64-clang-${{ inputs.msys-arch }}-quickjs-ng mingw-w64-clang-${{ inputs.msys-arch }}-directx-headers - name: print msys version run: uname -a @@ -70,7 +70,29 @@ jobs: run: time ./fastfetch -c presets/ci.jsonc --stat false - name: run fastfetch --format json - run: time ./fastfetch -c presets/ci.jsonc --format json + run: | + { time -p ./fastfetch -c presets/ci.jsonc --format json > fastfetch.raw.json 2> fastfetch.error; } 2> fastfetch.time + sed -n '/^[[:space:]]*\[/,$p' fastfetch.raw.json > fastfetch.json + cat fastfetch.json + cat fastfetch.error >&2 + cat fastfetch.time >&2 + + - name: prepare benchmark data + run: | + real_seconds=$(awk '$1 == "real" { print $2 }' fastfetch.time) + jq -e 'type == "array"' fastfetch.json > /dev/null + jq --arg platform "windows" --arg arch "${{ inputs.arch }}" --argjson real_seconds "$real_seconds" ' + map(select(.stat | type == "number") | { + name: ("fastfetch " + $platform + " " + $arch + " module " + .type), + unit: "ms", + value: .stat + }) + [{ + name: ("fastfetch " + $platform + " " + $arch + " total process time"), + unit: "ms", + value: ($real_seconds * 1000) + }] + ' fastfetch.json > benchmark.json + cat benchmark.json - name: run flashfetch run: time ./flashfetch @@ -116,3 +138,9 @@ jobs: name: fastfetch-windows-${{ inputs.arch }} path: ./fastfetch-windows-${{ inputs.arch }}.* overwrite: true + + - name: upload benchmark data + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: benchmark-windows-${{ inputs.arch }} + path: benchmark.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0081e62d88..8f63fdc049 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,6 +176,17 @@ jobs: secrets: SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }} + benchmark: + if: github.event_name == 'push' && github.ref == 'refs/heads/dev' && github.repository == 'fastfetch-cli/fastfetch' + name: Benchmark + needs: + - linux-hosts + - macos-hosts + - windows-hosts + permissions: + contents: write + uses: ./.github/workflows/build-benchmark.yml + release: if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch' name: Release From 1dc794fac04954f2717e4cee4b437ec544cd9f3a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 11:09:55 +0800 Subject: [PATCH 073/109] Doc: updates changelog [ci skip] --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed5407df9b..577aafa8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Changes: * The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations. Features: +* Improved Login Manager (LM) module + * Added support on macOS, Windows and POSIX systems without systemd (by process list enumeration). + * Reports pretty name on Linux. +* Added Top module to print processes with the highest CPU, memory or disk I/O usage. (Top) * Added module key localization support. (General) * Added a new option `--key-language ` (`display.key.language: ""` in JSON config). When left empty, it defaults to the system locale. * See `fastfetch -h key-language` for all supported languages. @@ -15,9 +19,14 @@ Features: * Added terminal font size detection support on Termux. (TerminalFont, Android) * Improved GTK theme/icons/font detection on standalone WMs such as Hyprland, sway, niri and i3. (Theme, Linux) * Improved fish completion scripts to print enum descriptions. (Completion) +* Enabled Wayland support on Android. (DisplayServer, Android) +* Added DE detection support for ASUS Zenfone. (DE, Android) Bugfixes: * Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO) +* Fixed the fast path of ash version detection. (Shell) +* Fixed memory usage detection support on x86-32 FreeBSD (Memory, FreeBSD) + * Note: Although 32-bit systems are still supported, they are deprecated and barely tested. Users are encouraged to upgrade to 64-bit systems. * Some internal cleanups and optimizations. # 2.67.1 From 191c5f2ef5435be1fc43ae281fed0fb48a425882 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 14:29:17 +0800 Subject: [PATCH 074/109] Doc: updates README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 84ec8e9752..b3e66cee84 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Fastfetch +[![Benchmark](https://img.shields.io/badge/GitHub%20Pages-live-blue?logo=github)](https://fastfetch-cli.github.io/fastfetch/dev/bench) [![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/fastfetch-cli/fastfetch/ci.yml)](https://github.com/fastfetch-cli/fastfetch/actions) [![GitHub license](https://img.shields.io/github/license/fastfetch-cli/fastfetch)](https://github.com/fastfetch-cli/fastfetch/blob/dev/LICENSE) [![GitHub contributors](https://img.shields.io/github/contributors/fastfetch-cli/fastfetch)](https://github.com/fastfetch-cli/fastfetch/graphs/contributors) From dcce4ccdb042b5199acf1c194602739c52587481 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 14:57:22 +0800 Subject: [PATCH 075/109] CI: moves `benchmark-index` to `/.github` as required by the script --- .github/{workflows => }/benchmark-index.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{workflows => }/benchmark-index.html (100%) diff --git a/.github/workflows/benchmark-index.html b/.github/benchmark-index.html similarity index 100% rename from .github/workflows/benchmark-index.html rename to .github/benchmark-index.html From d80fe3f0043538031c70b2c059973436bbeeb923 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 14:58:32 +0800 Subject: [PATCH 076/109] Logo (Builtin): adds macOS_old --- CHANGELOG.md | 3 +++ src/logo/ascii/m.inc | 13 +++++++++++++ src/logo/ascii/m/macos_old.txt | 17 +++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/logo/ascii/m/macos_old.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 577aafa8a0..f6165db0d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,9 @@ Bugfixes: * Note: Although 32-bit systems are still supported, they are deprecated and barely tested. Users are encouraged to upgrade to 64-bit systems. * Some internal cleanups and optimizations. +Logos: +* Added macOS_old + # 2.67.1 Bugfixes: diff --git a/src/logo/ascii/m.inc b/src/logo/ascii/m.inc index 68faf3b9db..68bc8cc0eb 100644 --- a/src/logo/ascii/m.inc +++ b/src/logo/ascii/m.inc @@ -103,6 +103,19 @@ static const FFlogo M[] = { .colorTitle = FF_COLOR_FG_GREEN, }, #endif + #ifdef FASTFETCH_DATATEXT_LOGO_MACOS_OLD + // MacOS_old + { + .names = { "macOS_old" }, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_MACOS_OLD, + .colors = { + FF_COLOR_FG_CYAN, + FF_COLOR_FG_BLUE, + FF_COLOR_FG_DEFAULT, + }, + }, + #endif #ifdef FASTFETCH_DATATEXT_LOGO_MAINSAILOS // MainsailOS { diff --git a/src/logo/ascii/m/macos_old.txt b/src/logo/ascii/m/macos_old.txt new file mode 100644 index 0000000000..c5cf0c70da --- /dev/null +++ b/src/logo/ascii/m/macos_old.txt @@ -0,0 +1,17 @@ + $3@@ + $3@@ +$2((((((((((((((((((((($3@@$1****************** +$2(((((((((((((((((((($3@@$1******************* +$2(((((((((($3%%$2((((((($3@@$1********$3@@$1********** +$2(((((((((($3%%$2(((((($3@@$1*********$3@@$1********** +$2((((((((((((((((($3@@$1********************** +$2(((((((((((((((($3@@$1*********************** +$2((((((((((((((($3@@$1************************ +$2(((((((((((((($3@@@@@@@@$1******************* +$2(((((((((((((((((((($3@@$1******************* +$2(((((((($3%%%%%%%%%%%@@@@@@@@@@@@@@$1******** +$2(((((((((((((((((((($3@@$1******************* +$2((((((((((((((((((((($3@@$1****************** + $3@@ + @@ + @@ \ No newline at end of file From d7de7c41ca113c3a68a6f60060084b896ea8de4b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 27 Aug 2026 15:28:18 +0800 Subject: [PATCH 077/109] CI: disables fail on alert --- .github/workflows/build-benchmark.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build-benchmark.yml b/.github/workflows/build-benchmark.yml index 827d81c399..ebead8bf38 100644 --- a/.github/workflows/build-benchmark.yml +++ b/.github/workflows/build-benchmark.yml @@ -38,7 +38,6 @@ jobs: ref: ${{ github.sha }} auto-push: true summary-always: true - fail-on-alert: true benchmark-data-dir-path: dev/bench - name: publish benchmark dashboard From 4d00dc6802f1a45a0f5c1fba55da3cd5db6410cc Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 09:48:39 +0800 Subject: [PATCH 078/109] Logo (Builtin): adds omarchy --- CHANGELOG.md | 1 + src/logo/ascii/o.inc | 25 +++++++++++++++++++++++++ src/logo/ascii/o/omarchy.txt | 15 +++++++++++++++ src/logo/ascii/o/omarchy2.txt | 10 ++++++++++ 4 files changed, 51 insertions(+) create mode 100644 src/logo/ascii/o/omarchy.txt create mode 100644 src/logo/ascii/o/omarchy2.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index f6165db0d7..c1e1744285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Bugfixes: Logos: * Added macOS_old +* Added Omarchy, Omarchy2 # 2.67.1 diff --git a/src/logo/ascii/o.inc b/src/logo/ascii/o.inc index b5b32a9025..54b9282f05 100644 --- a/src/logo/ascii/o.inc +++ b/src/logo/ascii/o.inc @@ -37,6 +37,31 @@ static const FFlogo O[] = { }, }, #endif + #ifdef FASTFETCH_DATATEXT_LOGO_OMARCHY + // Omarchy + { + .names = { "Omarchy" }, + .lines = FASTFETCH_DATATEXT_LOGO_OMARCHY, + .colors = { + FF_COLOR_FG_256 "149", + }, + .colorKeys = FF_COLOR_FG_256 "149", + .colorTitle = FF_COLOR_FG_256 "111", + }, + #endif + #ifdef FASTFETCH_DATATEXT_LOGO_OMARCHY2 + // Omarchy2 + { + .names = { "Omarchy2" }, + .lines = FASTFETCH_DATATEXT_LOGO_OMARCHY2, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, + .colors = { + FF_COLOR_FG_256 "149", + }, + .colorKeys = FF_COLOR_FG_256 "149", + .colorTitle = FF_COLOR_FG_256 "111", + }, + #endif #ifdef FASTFETCH_DATATEXT_LOGO_OMNIOS // OmniOS { diff --git a/src/logo/ascii/o/omarchy.txt b/src/logo/ascii/o/omarchy.txt new file mode 100644 index 0000000000..05998ae4df --- /dev/null +++ b/src/logo/ascii/o/omarchy.txt @@ -0,0 +1,15 @@ +██████████████████████████████████ +██ ██ ██ +██ █████████████ ████ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +███████ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ██ ██ ██ +██ ████████████████████████ ██ +██ ██ ██ +██████████████████ █████████████ \ No newline at end of file diff --git a/src/logo/ascii/o/omarchy2.txt b/src/logo/ascii/o/omarchy2.txt new file mode 100644 index 0000000000..c06e6802c6 --- /dev/null +++ b/src/logo/ascii/o/omarchy2.txt @@ -0,0 +1,10 @@ + ▄▄▄ + ▄█████▄ ▄███████████▄ ▄███████ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄ +███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ +███ ███ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ +███ ███ ███ ███ ███ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███ +███ ███ ███ ███ ███ ▀███▀▀▀███ ▀███▀▀▀▀ ███ ▀▀███▀▀▀███ ▀▀▀▀▀▀███ +███ ███ ███ ███ ███ ███ ███ ██████████ ███ █▄ ███ ███ ▄██ ███ +███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ + ▀█████▀ ▀█ ███ █▀ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀ + ███ █▀ \ No newline at end of file From 14cf6bfdc1137384adaa62884c64cce667c7b355 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 15:36:25 +0800 Subject: [PATCH 079/109] Top (macOS): adds comments --- src/detection/top/top_apple.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index fc8f5c998d..3c82505261 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -46,6 +46,17 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInitS(&item->name, proc->kp_proc.p_comm); item->pid = (uint32_t) pid; + // Note: Do NOT use proc->kp_proc.p_pctcpu for CPU usage. p_pctcpu is a + // decaying average (fixpt_t with FSCALE=2048) updated roughly once per + // second by the kernel. It is heavily smoothed, lags short bursts, has + // low resolution, and its multicore scaling (>100%) is inconsistent + // across XNU versions. It also breaks the unified model where + // FFTopProcessSnapshot.cpuTime is cumulative time and top.c computes + // (new - old) / elapsed * 100 for all platforms. proc_pid_rusage with + // RUSAGE_INFO_V2 provides precise cumulative ri_user_time + + // ri_system_time in nanoseconds and is the modern recommended API on + // Darwin, consistent with Linux/BSD differential sampling and accurate + // for the short waitTime interval (e.g. 100ms). item->cpuTime = (rusage.ri_user_time + rusage.ri_system_time) / 1000000u; // ns -> ms item->memBytes = rusage.ri_resident_size; item->bytesRead = rusage.ri_diskio_bytesread; From 51b370a10576faedf0acccd88a5352999d0eac70 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 15:21:52 +0800 Subject: [PATCH 080/109] Processes: adds total thread count detection --- CMakeLists.txt | 4 +- src/detection/processes/processes.h | 8 ++- src/detection/processes/processes_apple.c | 21 ++++++++ src/detection/processes/processes_bsd.c | 28 +++++----- src/detection/processes/processes_gnu.c | 19 +++++-- src/detection/processes/processes_haiku.c | 5 +- src/detection/processes/processes_linux.c | 51 +++++++++++++++---- src/detection/processes/processes_nbsd.c | 27 ++++++++-- src/detection/processes/processes_nosupport.c | 2 +- src/detection/processes/processes_obsd.c | 27 +++++++--- src/detection/processes/processes_sunos.c | 38 ++++++++++++++ src/detection/processes/processes_windows.c | 15 ++++-- src/modules/processes/processes.c | 13 ++--- 13 files changed, 203 insertions(+), 55 deletions(-) create mode 100644 src/detection/processes/processes_apple.c create mode 100644 src/detection/processes/processes_sunos.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ba505650d..a072980985 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1065,7 +1065,7 @@ elseif(APPLE) src/detection/packages/packages_apple.c src/detection/packages/packages_nix.c src/detection/poweradapter/poweradapter_apple.c - src/detection/processes/processes_bsd.c + src/detection/processes/processes_apple.c src/detection/sound/sound_apple.c src/detection/swap/swap_apple.c src/detection/terminalfont/terminalfont_apple.m @@ -1240,7 +1240,7 @@ elseif(SunOS) src/detection/os/os_sunos.c src/detection/packages/packages_sunos.c src/detection/poweradapter/poweradapter_nosupport.c - src/detection/processes/processes_linux.c + src/detection/processes/processes_sunos.c src/detection/gtk_qt/qt.c src/detection/sound/sound_sunos.c src/detection/swap/swap_sunos.c diff --git a/src/detection/processes/processes.h b/src/detection/processes/processes.h index 69cf46381e..f9dc380cbe 100644 --- a/src/detection/processes/processes.h +++ b/src/detection/processes/processes.h @@ -2,4 +2,10 @@ #include "fastfetch.h" -const char* ffDetectProcesses(uint32_t* result); +typedef struct FFProcessesResult +{ + uint32_t processes; + uint32_t threads; +} FFProcessesResult; + +const char* ffDetectProcesses(FFProcessesResult* result); diff --git a/src/detection/processes/processes_apple.c b/src/detection/processes/processes_apple.c new file mode 100644 index 0000000000..6866c64fea --- /dev/null +++ b/src/detection/processes/processes_apple.c @@ -0,0 +1,21 @@ +#include "processes.h" +#include "common/mallocHelper.h" + +#import + +const char* ffDetectProcesses(FFProcessesResult* result) { + FF_AUTO_FREE pid_t* pids = malloc(sizeof(pid_t) * 0x1000); + int count = proc_listallpids(pids, 0x1000); + int trdCount = 0; + for (int index = 0; index < count; ++index) { + struct proc_taskinfo taskInfo; + if (proc_pidinfo(pids[index], PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) != sizeof(taskInfo)) { + continue; + } + trdCount += taskInfo.pti_threadnum; + } + + result->processes = (uint32_t) count; + result->threads = (uint32_t) trdCount; + return nullptr; +} diff --git a/src/detection/processes/processes_bsd.c b/src/detection/processes/processes_bsd.c index 4d16bc3af2..8410e29011 100644 --- a/src/detection/processes/processes_bsd.c +++ b/src/detection/processes/processes_bsd.c @@ -1,23 +1,23 @@ #include "processes.h" #include -#ifdef __FreeBSD__ - #include - #include -#endif +#include +#include -#ifndef KERN_PROC_PROC - #define KERN_PROC_PROC KERN_PROC_ALL // Apple -#endif - -const char* ffDetectProcesses(uint32_t* result) { - int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; - size_t length; - - if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { +const char* ffDetectProcesses(FFProcessesResult* result) { + int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; + size_t procLength; + if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; } - *result = (uint32_t) (length / sizeof(struct kinfo_proc)); + int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t threadLength; + if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); + result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); return nullptr; } diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c index 7dc739d2ba..73d287d5d5 100644 --- a/src/detection/processes/processes_gnu.c +++ b/src/detection/processes/processes_gnu.c @@ -3,7 +3,7 @@ #include #include -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { struct ps_context* context = nullptr; if (ps_context_create(getproc(), &context) != 0) { return "ps_context_create(getproc()) failed"; @@ -16,15 +16,26 @@ const char* ffDetectProcesses(uint32_t* result) { goto done; } - // No flags are needed; we only count the processes. - if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { + struct proc_stat **stats = nullptr; + unsigned int numProcs = 0; + if (proc_stat_list_add_all(list, &stats, &numProcs) != 0) { error = "proc_stat_list_add_all() failed"; goto done; } - *result = (uint32_t) list->num_procs; + uint32_t nthread = 0; + for (unsigned int i = 0; i < numProcs; i++) { + proc_stat_get_basic_info(stats[i]); + nthread += proc_stat_thread_count(stats[i]); + } + + result->processes = (uint32_t) numProcs; + result->threads = nthread; done: + if (stats) { + proc_stat_list_free_stats(stats, numProcs); + } if (list) { proc_stat_list_free(list); } diff --git a/src/detection/processes/processes_haiku.c b/src/detection/processes/processes_haiku.c index 0d960ab39e..8b0c1cd4bb 100644 --- a/src/detection/processes/processes_haiku.c +++ b/src/detection/processes/processes_haiku.c @@ -2,13 +2,14 @@ #include -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { system_info info; if (get_system_info(&info) != B_OK) { return "Error getting system info"; } - *result = info.used_teams; + result->processes = info.used_teams; + result->threads = info.used_threads; return nullptr; } diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 78790c2ebc..05048d55ab 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -1,27 +1,60 @@ #include "processes.h" #include "common/io.h" +#include "common/memrchr.h" #include "common/strutil.h" -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (dir == nullptr) { return "opendir(\"/proc\") failed"; } - uint32_t num = 0; + uint32_t processes = 0; + uint32_t threads = 0; + + int procfd = dirfd(dir); struct dirent* entry; while ((entry = readdir(dir)) != nullptr) { - if ( -#ifdef _DIRENT_HAVE_D_TYPE - (entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) && -#endif - ffCharIsDigit(entry->d_name[0])) - ++num; + if ((entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) && ffCharIsDigit(entry->d_name[0])) { + ++processes; + + char statPath[32]; + strcpy(ffStrCopy(statPath, entry->d_name, sizeof(statPath)), "/stat"); + + char statBuffer[256]; + ssize_t statLength = ffReadFileDataRelative(procfd, statPath, sizeof(statBuffer) - 1, statBuffer); + if (statLength < 0) { + continue; + } + statBuffer[statLength] = '\0'; + + const char* cursor = (const char*) memrchr(statBuffer, ')', (size_t) statLength); + if (!cursor) { + continue; + } + ++cursor; + + for (uint32_t field = 2 /*comm*/; field < 20 /*num_threads*/; ++field) { + while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { + ++cursor; + } + ++cursor; + if (__builtin_expect(*cursor == '\0', false)) { + break; + } + } + if (__builtin_expect(*cursor == '\0', false)) { + continue; + } + + threads += (uint32_t) strtoul(cursor, nullptr, 10); + } } - *result = num; + result->processes = processes; + result->threads = threads; return nullptr; } diff --git a/src/detection/processes/processes_nbsd.c b/src/detection/processes/processes_nbsd.c index c3e7d047f1..8e89ab3a18 100644 --- a/src/detection/processes/processes_nbsd.c +++ b/src/detection/processes/processes_nbsd.c @@ -1,15 +1,34 @@ #include "processes.h" +#include "common/mallocHelper.h" #include -const char* ffDetectProcesses(uint32_t* result) { - int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), 0 }; +const char* ffDetectProcesses(FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length = 0; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, nullptr}) failed"; } - *result = (uint32_t) (length / sizeof(struct kinfo_proc2)); + FF_AUTO_FREE struct kinfo_proc2* procs = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, procs}) failed"; + } + + uint32_t procCount = (uint32_t) (length / sizeof(struct kinfo_proc2)); + result->processes = procCount; + + uint32_t threads = 0; + for (uint32_t i = 0; i < procCount; ++i) { + int lwpRequest[] = { CTL_KERN, KERN_LWP, procs[i].p_pid, sizeof(struct kinfo_lwp), 0 }; + size_t lwpLength = 0; + + if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) { + threads += (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); + } + } + + result->threads = threads; return nullptr; } diff --git a/src/detection/processes/processes_nosupport.c b/src/detection/processes/processes_nosupport.c index 7da208ec4c..e7218a5c26 100644 --- a/src/detection/processes/processes_nosupport.c +++ b/src/detection/processes/processes_nosupport.c @@ -1,5 +1,5 @@ #include "processes.h" -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses([[maybe_unused]] FFProcessesResult* result) { return "Not supported on this platform"; } diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c index 5a5ba31f46..cb960ce57e 100644 --- a/src/detection/processes/processes_obsd.c +++ b/src/detection/processes/processes_obsd.c @@ -2,14 +2,25 @@ #include #include -#include - -const char* ffDetectProcesses(uint32_t* result) { - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - const void* ret = kvm_getprocs(kd, KERN_PROC_ALL, 0, 1, result); - kvm_close(kd); - if (!ret) { - return "kvm_getprocs() failed"; + +const char* ffDetectProcesses(FFProcessesResult* result) { + int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0 }; + size_t procLength = 0; + + if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); + + int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), 0 }; + size_t threadLength = 0; + + if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS}) failed"; } + + result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); + return nullptr; } diff --git a/src/detection/processes/processes_sunos.c b/src/detection/processes/processes_sunos.c new file mode 100644 index 0000000000..ce0da325cb --- /dev/null +++ b/src/detection/processes/processes_sunos.c @@ -0,0 +1,38 @@ +#include "processes.h" + +#include "common/io.h" +#include "common/strutil.h" + +#include + +const char* ffDetectProcesses(FFProcessesResult* result) { + FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); + if (dir == nullptr) { + return "opendir(\"/proc\") failed"; + } + + uint32_t processes = 0; + uint32_t threads = 0; + + int procfd = dirfd(dir); + + struct dirent* entry; + while ((entry = readdir(dir)) != nullptr) { + if (ffCharIsDigit(entry->d_name[0])) { + ++processes; + + char psinfoPath[32]; + strcpy(ffStrCopy(psinfoPath, entry->d_name, sizeof(psinfoPath)), "/psinfo"); + + psinfo_t info; + if (ffReadFileDataRelative(procfd, psinfoPath, sizeof(info), &info) == (ssize_t) sizeof(info)) { + threads += info.pr_nlwp; + } + } + } + + result->processes = processes; + result->threads = threads; + + return nullptr; +} diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index 78ed840b46..cb617099ed 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -4,7 +4,7 @@ #include #include -const char* ffDetectProcesses(uint32_t* result) { +const char* ffDetectProcesses(FFProcessesResult* result) { FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; // Multiple attempts in case processes change while @@ -25,10 +25,17 @@ const char* ffDetectProcesses(uint32_t* result) { } } - *result = 1; // Init with 1 because we test for ptr->NextEntryOffset - for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - ++*result; + uint32_t processes = 0; + uint32_t threads = 0; + for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { + ++processes; + threads += ptr->NumberOfThreads; + if (ptr->NextEntryOffset == 0) { + break; + } } + result->processes = processes; + result->threads = threads; return nullptr; } diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 4281204562..9bb68239ca 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -5,8 +5,8 @@ #include "modules/processes/processes.h" bool ffPrintProcesses(FFProcessesOptions* options) { - uint32_t numProcesses = 0; - const char* error = ffDetectProcesses(&numProcesses); + FFProcessesResult result = {}; + const char* error = ffDetectProcesses(&result); if (error) { ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); @@ -16,9 +16,9 @@ bool ffPrintProcesses(FFProcessesOptions* options) { if (options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - printf("%u\n", numProcesses); + printf("%u (%u threads)\n", result.processes, result.threads); } else { - FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(numProcesses, "result") })); + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.processes, "result") })); } return true; @@ -41,7 +41,7 @@ void ffGenerateProcessesJsonConfig(FFProcessesOptions* options, yyjson_mut_doc* } bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - uint32_t result; + FFProcessesResult result = {}; const char* error = ffDetectProcesses(&result); if (error) { @@ -49,7 +49,8 @@ bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, return false; } - yyjson_mut_obj_add_uint(doc, module, "result", result); + yyjson_mut_obj_add_uint(doc, module, "processes", result.processes); + yyjson_mut_obj_add_uint(doc, module, "threads", result.threads); return true; } From 2c4caf8e0d74fa9f3e50de50c115b45e5d7c0f53 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 16:22:33 +0800 Subject: [PATCH 081/109] Top: removes realloc retries --- src/detection/top/top_apple.c | 26 +++++++++----------------- src/detection/top/top_bsd.c | 18 ++++-------------- src/detection/top/top_dbsd.c | 21 ++++++--------------- src/detection/top/top_nbsd.c | 21 ++++++--------------- 4 files changed, 25 insertions(+), 61 deletions(-) diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index 3c82505261..8624313818 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -10,33 +10,25 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { size_t length; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc); - struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; } + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); for (uint32_t i = 0; i < count; ++i) { const struct kinfo_proc* proc = &processes[i]; - pid_t pid = proc->kp_proc.p_pid; - if (pid <= 0) { + if (proc->kp_proc.p_flag & P_SYSTEM) { continue; } + pid_t pid = proc->kp_proc.p_pid; struct rusage_info_v2 rusage; if (proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t*) &rusage) != 0) { diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c index 620b234b14..6c0f620189 100644 --- a/src/detection/top/top_bsd.c +++ b/src/detection/top/top_bsd.c @@ -15,20 +15,10 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc); - struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; } uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 1a9bbb8883..858cc616d7 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -11,24 +11,15 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { size_t length; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc); - struct kinfo_proc* newProcesses = (struct kinfo_proc*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc); + + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; } uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c index 277354ed3a..1bc8e6543f 100644 --- a/src/detection/top/top_nbsd.c +++ b/src/detection/top/top_nbsd.c @@ -11,24 +11,15 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { size_t length; if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, nullptr}) failed"; } // The process table may change between the two sysctl calls; retry with a larger buffer. - FF_AUTO_FREE struct kinfo_proc2* processes = nullptr; - for (int attempts = 0;; ++attempts) { - length += length / 8 + sizeof(struct kinfo_proc2); - struct kinfo_proc2* newProcesses = (struct kinfo_proc2*) realloc(processes, length); - if (!newProcesses) { - return "realloc(struct kinfo_proc2[]) failed"; - } - processes = newProcesses; - if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) == 0) { - break; - } - if ((errno != ENOMEM && errno != EINVAL) || attempts >= 4) { - return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed"; - } + length += length / 8 + sizeof(struct kinfo_proc2); + + FF_AUTO_FREE struct kinfo_proc2* processes = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, processes}) failed"; } uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc2)); From f169165599d4d97684e7d9bd2bb46351d10cd890 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 18:45:16 +0800 Subject: [PATCH 082/109] Top (Linux): improves performance of `stat` parsing --- src/detection/top/top_linux.c | 64 ++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 28349a17d6..2436e3ce78 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -18,40 +18,49 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r } ffStrbufSetNS(&result->name, (uint32_t) (close - open - 1), open + 1); - const char* cursor = close + 2; // state, then fields 4.. - if (*cursor == '\0') { - FF_DEBUG("parseStat(%s): truncated after state field", result->name.chars); + + const char* cursor = close + 2; // skip ") " + if (__builtin_expect(cursor >= buffer + length, false)) { return false; } - ++cursor; - uint64_t values[19]; - for (uint32_t field = 4; field <= 22; ++field) { - while (*cursor == ' ') { - ++cursor; - } - if (*cursor == '\0') { - FF_DEBUG("parseStat(%s): truncated at field %u", result->name.chars, field); - return false; + result->cpuTime = 0; + + char* p; + for (uint32_t field = 3; field <= 22 /*start time*/; ++field) { + switch (field) { + case 9: // flags + if ((strtoul(cursor, &p, 10) & PF_KTHREAD)) { + FF_DEBUG("parseStat: skipping kernel task %s", result->name.chars); + return false; + } + cursor = p; + break; + + case 14: // user + case 15: // system + result->cpuTime += (uint64_t) strtoull(cursor, &p, 10); + cursor = p; + break; + + case 22: // start time + result->startTime = (uint64_t) strtoull(cursor, &p, 10); + cursor = p; + break; + + default: + while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { + ++cursor; + } + break; } - char* end; - errno = 0; - unsigned long long value = strtoull(cursor, &end, 10); - if (end == cursor || errno == ERANGE) { - FF_DEBUG("parseStat(%s): invalid number at field %u", result->name.chars, field); + + ++cursor; + if (__builtin_expect(cursor >= buffer + length, false)) { return false; } - values[field - 4] = (uint64_t) value; - cursor = end; } - if (values[5] & PF_KTHREAD) { // values[5] is field 9 (flags) - FF_DEBUG("Skip kernel thread: %s", result->name.chars); - return false; - } - - result->cpuTime = values[11] + values[12]; // user + system - result->startTime = values[18]; return true; } @@ -72,7 +81,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int procfd = dirfd(dir); struct dirent* entry; - char statBuffer[4096]; + char statBuffer[1024]; char statmBuffer[256]; while ((entry = readdir(dir))) { if (!entry->d_name[0] || !ffCharIsDigit(entry->d_name[0])) { @@ -119,6 +128,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInit(&snapshot->name); + if (!parseStat(statBuffer, (size_t) statLength, snapshot)) { ffStrbufDestroy(&snapshot->name); --snapshots->length; From 41da49f5797c0672681dc601260cd8a0e2384598 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 18:53:56 +0800 Subject: [PATCH 083/109] Top (SunOS / Hurd): skips kernel tasks --- src/detection/top/top_dbsd.c | 4 ++-- src/detection/top/top_gnu.c | 7 ++++++- src/detection/top/top_sunos.c | 12 +++++++++--- src/detection/top/top_windows.c | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 858cc616d7..56a572e65b 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -28,8 +28,8 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { for (uint32_t i = 0; i < count; ++i) { const struct kinfo_proc* proc = &processes[i]; - // Kernel threads are reported with P_SYSTEM flags and pid -1. - if ((proc->kp_flags & P_SYSTEM) || proc->kp_stat == SZOMB) { + // KERN_PROC_ALL won't return kernel threads + if (proc->kp_stat == SZOMB) { // Ignore zombie processes continue; } diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 9bbe37aff9..670f7f0770 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -39,6 +39,11 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { continue; } + uint32_t pid = (uint32_t) proc_stat_pid(stat); + if (pid == 2) { // Kernel Task + continue; + } + FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); // There is no kernel-side comm on the Hurd; use the first argument. @@ -51,7 +56,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { ffStrbufAppendS(&item->name, "(unknown)"); } - item->pid = (uint32_t) proc_stat_pid(stat); + item->pid = pid; if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c index f7e6a5f688..7dc9c880ca 100644 --- a/src/detection/top/top_sunos.c +++ b/src/detection/top/top_sunos.c @@ -26,15 +26,21 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { continue; } + pstatus_t status; + if (ffReadFileDataRelative(subfd, "status", sizeof(status), &status) != (ssize_t) sizeof(status) || + status.pr_flags & PR_ISSYS) { + continue; // The process may have exited, no permission or is a kernel process + } + // The data model of the returned structure depends on the data model of // the calling process, not of the observed process. psinfo_t psinfo; if (ffReadFileDataRelative(subfd, "psinfo", sizeof(psinfo), &psinfo) != (ssize_t) sizeof(psinfo)) { - continue; // The process may have exited + continue; } - // pr_nlwp is zero for system processes and zombies - if (psinfo.pr_nlwp == 0 || psinfo.pr_lwp.pr_sname == 'Z') { + // zombies + if (psinfo.pr_lwp.pr_sname == 'Z') { continue; } diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index 59a5ab98db..6040964039 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -33,7 +33,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { if (pidValue <= UINT32_MAX && info->CreateTime.QuadPart > 0) { FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); item->pid = (uint32_t) pidValue; - item->startTime = info->CreateTime.QuadPart > 0 ? (uint64_t) info->CreateTime.QuadPart : 0; + item->startTime = (uint64_t) info->CreateTime.QuadPart; item->cpuTime = ((uint64_t) info->UserTime.QuadPart + (uint64_t) info->KernelTime.QuadPart) / 10000u; item->memBytes = (uint64_t) info->VirtualMemoryCounters.WorkingSetSize; item->bytesRead = (uint64_t) info->IoCounters.ReadTransferCount; From 7fe08bddd04a7ae69f4236670b0e1a3af1d3b841 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 28 Aug 2026 17:40:57 +0800 Subject: [PATCH 084/109] Processes: adds option `countKprocs` --- CMakeLists.txt | 3 +- doc/json_schema.json | 7 ++- src/detection/processes/processes.h | 3 +- src/detection/processes/processes_apple.c | 38 +++++++++++---- src/detection/processes/processes_bsd.c | 32 +++++++++---- src/detection/processes/processes_dbsd.c | 38 +++++++++++++++ src/detection/processes/processes_gnu.c | 27 ++++++----- src/detection/processes/processes_haiku.c | 2 +- src/detection/processes/processes_linux.c | 53 +++++++++++++-------- src/detection/processes/processes_nbsd.c | 13 +++-- src/detection/processes/processes_obsd.c | 36 +++++++++----- src/detection/processes/processes_sunos.c | 28 ++++++----- src/detection/processes/processes_windows.c | 13 +++-- src/modules/processes/option.h | 2 + src/modules/processes/processes.c | 14 ++++-- 15 files changed, 212 insertions(+), 97 deletions(-) create mode 100644 src/detection/processes/processes_dbsd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a072980985..e181366301 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -813,7 +813,6 @@ elseif(FreeBSD) src/detection/os/os_linux.c src/detection/packages/packages_bsd.c src/detection/poweradapter/poweradapter_nosupport.c - src/detection/processes/processes_bsd.c src/detection/gtk_qt/qt.c src/detection/sound/sound_bsd.c src/detection/swap/swap_bsd.c @@ -833,12 +832,14 @@ elseif(FreeBSD) if(DragonFly) list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_nosupport.c + src/detection/processes/processes_dbsd.c src/detection/top/top_dbsd.c src/detection/wifi/wifi_nosupport.c ) else() list(APPEND LIBFASTFETCH_SRC src/detection/bluetooth/bluetooth_bsd.c + src/detection/processes/processes_bsd.c src/detection/top/top_bsd.c src/detection/wifi/wifi_bsd.c ) diff --git a/doc/json_schema.json b/doc/json_schema.json index e948d92859..2768b13df9 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -3984,7 +3984,12 @@ "properties": { "type": { "const": "processes", - "description": "Print the number of running processes" + "description": "Print the number of running processes and threads" + }, + "countKprocs": { + "description": "Whether to take kernel processes and threads into account", + "type": "boolean", + "default": false }, "key": { "$ref": "#/$defs/key" diff --git a/src/detection/processes/processes.h b/src/detection/processes/processes.h index f9dc380cbe..fdc7ceedb9 100644 --- a/src/detection/processes/processes.h +++ b/src/detection/processes/processes.h @@ -1,6 +1,7 @@ #pragma once #include "fastfetch.h" +#include "modules/processes/option.h" typedef struct FFProcessesResult { @@ -8,4 +9,4 @@ typedef struct FFProcessesResult uint32_t threads; } FFProcessesResult; -const char* ffDetectProcesses(FFProcessesResult* result); +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result); diff --git a/src/detection/processes/processes_apple.c b/src/detection/processes/processes_apple.c index 6866c64fea..8ed1472b20 100644 --- a/src/detection/processes/processes_apple.c +++ b/src/detection/processes/processes_apple.c @@ -1,21 +1,41 @@ #include "processes.h" #include "common/mallocHelper.h" +#include #import -const char* ffDetectProcesses(FFProcessesResult* result) { - FF_AUTO_FREE pid_t* pids = malloc(sizeof(pid_t) * 0x1000); - int count = proc_listallpids(pids, 0x1000); - int trdCount = 0; - for (int index = 0; index < count; ++index) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t length; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &processes[i]; + if (!options->countKprocs && (proc->kp_proc.p_flag & P_SYSTEM)) { + continue; + } + result->processes++; + + pid_t pid = proc->kp_proc.p_pid; struct proc_taskinfo taskInfo; - if (proc_pidinfo(pids[index], PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) != sizeof(taskInfo)) { + if (proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) != sizeof(taskInfo)) { continue; } - trdCount += taskInfo.pti_threadnum; + result->threads += taskInfo.pti_threadnum; } - result->processes = (uint32_t) count; - result->threads = (uint32_t) trdCount; return nullptr; } diff --git a/src/detection/processes/processes_bsd.c b/src/detection/processes/processes_bsd.c index 8410e29011..32ee53736c 100644 --- a/src/detection/processes/processes_bsd.c +++ b/src/detection/processes/processes_bsd.c @@ -1,23 +1,35 @@ #include "processes.h" +#include "common/mallocHelper.h" #include #include #include -const char* ffDetectProcesses(FFProcessesResult* result) { - int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; - size_t procLength; - if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; + size_t length; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; } - int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - size_t threadLength; - if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* procs = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &procs[i]; + + if (!options->countKprocs && (proc->ki_flag & P_KPROC)) { + continue; + } + + result->processes++; + result->threads += (uint32_t) proc->ki_numthreads; } - result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); - result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); return nullptr; } diff --git a/src/detection/processes/processes_dbsd.c b/src/detection/processes/processes_dbsd.c new file mode 100644 index 0000000000..c0fa246dea --- /dev/null +++ b/src/detection/processes/processes_dbsd.c @@ -0,0 +1,38 @@ +#include "processes.h" +#include "common/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | (options->countKprocs ? KERN_PROC_FLAG_LWKT : 0) }; + size_t length; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* procs = malloc(length); + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + for (uint32_t i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &procs[i]; + + if (proc->kp_pid == -1) { + // Kernel thread, only returned when countKprocs is set via KERN_PROC_FLAG_LWKT + result->threads++; + continue; + } + + result->processes++; + result->threads += (uint32_t) proc->kp_nthreads; + } + + return nullptr; +} diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c index 73d287d5d5..ba4351f5e1 100644 --- a/src/detection/processes/processes_gnu.c +++ b/src/detection/processes/processes_gnu.c @@ -3,7 +3,7 @@ #include #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { struct ps_context* context = nullptr; if (ps_context_create(getproc(), &context) != 0) { return "ps_context_create(getproc()) failed"; @@ -16,26 +16,27 @@ const char* ffDetectProcesses(FFProcessesResult* result) { goto done; } - struct proc_stat **stats = nullptr; - unsigned int numProcs = 0; - if (proc_stat_list_add_all(list, &stats, &numProcs) != 0) { + if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) { error = "proc_stat_list_add_all() failed"; goto done; } - uint32_t nthread = 0; - for (unsigned int i = 0; i < numProcs; i++) { - proc_stat_get_basic_info(stats[i]); - nthread += proc_stat_thread_count(stats[i]); + proc_stat_list_set_flags(list, PSTAT_NUM_THREADS); + + for (uint32_t i = 0; i < list->num_procs; i++) { + struct proc_stat* stat = list->proc_stats[i]; + if (!options->countKprocs && proc_stat_pid(stat) == 2) { // Kernel Task + continue; + } + + if (proc_stat_has(stat, PSTAT_NUM_THREADS)) { + result->threads += proc_stat_num_threads(stat); + } } - result->processes = (uint32_t) numProcs; - result->threads = nthread; + result->processes = (uint32_t) list->num_procs; done: - if (stats) { - proc_stat_list_free_stats(stats, numProcs); - } if (list) { proc_stat_list_free(list); } diff --git a/src/detection/processes/processes_haiku.c b/src/detection/processes/processes_haiku.c index 8b0c1cd4bb..484a321199 100644 --- a/src/detection/processes/processes_haiku.c +++ b/src/detection/processes/processes_haiku.c @@ -2,7 +2,7 @@ #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions*, FFProcessesResult* result) { system_info info; if (get_system_info(&info) != B_OK) { return "Error getting system info"; diff --git a/src/detection/processes/processes_linux.c b/src/detection/processes/processes_linux.c index 05048d55ab..68f819481b 100644 --- a/src/detection/processes/processes_linux.c +++ b/src/detection/processes/processes_linux.c @@ -4,26 +4,23 @@ #include "common/memrchr.h" #include "common/strutil.h" -const char* ffDetectProcesses(FFProcessesResult* result) { +#define PF_KTHREAD 0x00200000 // defined in kernel include/linux/sched.h + +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (dir == nullptr) { return "opendir(\"/proc\") failed"; } - uint32_t processes = 0; - uint32_t threads = 0; - int procfd = dirfd(dir); struct dirent* entry; while ((entry = readdir(dir)) != nullptr) { if ((entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) && ffCharIsDigit(entry->d_name[0])) { - ++processes; - char statPath[32]; strcpy(ffStrCopy(statPath, entry->d_name, sizeof(statPath)), "/stat"); - char statBuffer[256]; + char statBuffer[512]; ssize_t statLength = ffReadFileDataRelative(procfd, statPath, sizeof(statBuffer) - 1, statBuffer); if (statLength < 0) { continue; @@ -34,27 +31,43 @@ const char* ffDetectProcesses(FFProcessesResult* result) { if (!cursor) { continue; } - ++cursor; + cursor += 2; // skip ") " + if (__builtin_expect(cursor >= statBuffer + statLength, false)) { + goto skip_process; + } + + char* p; + for (uint32_t field = 3; field <= 20 /*num_threads*/; ++field) { + switch (field) { + case 9: // flags + if ((strtoul(cursor, &p, 10) & PF_KTHREAD) && !options->countKprocs) { + goto skip_process; + } + cursor = p; + break; - for (uint32_t field = 2 /*comm*/; field < 20 /*num_threads*/; ++field) { - while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { - ++cursor; + case 20: // num_threads + result->threads += (uint32_t) strtoul(cursor, &p, 10); + cursor = p; + break; + + default: + while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) { + ++cursor; + } + break; } + ++cursor; - if (__builtin_expect(*cursor == '\0', false)) { - break; + if (__builtin_expect(cursor >= statBuffer + statLength, false)) { + goto skip_process; } } - if (__builtin_expect(*cursor == '\0', false)) { - continue; - } - threads += (uint32_t) strtoul(cursor, nullptr, 10); + ++result->processes; } + skip_process:; } - result->processes = processes; - result->threads = threads; - return nullptr; } diff --git a/src/detection/processes/processes_nbsd.c b/src/detection/processes/processes_nbsd.c index 8e89ab3a18..cb91db096f 100644 --- a/src/detection/processes/processes_nbsd.c +++ b/src/detection/processes/processes_nbsd.c @@ -3,7 +3,7 @@ #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length = 0; @@ -17,18 +17,21 @@ const char* ffDetectProcesses(FFProcessesResult* result) { } uint32_t procCount = (uint32_t) (length / sizeof(struct kinfo_proc2)); - result->processes = procCount; - uint32_t threads = 0; for (uint32_t i = 0; i < procCount; ++i) { + const struct kinfo_proc2* proc = &procs[i]; + if (!options->countKprocs && (proc->p_flag & P_SYSTEM)) { + continue; + } + ++result->processes; + int lwpRequest[] = { CTL_KERN, KERN_LWP, procs[i].p_pid, sizeof(struct kinfo_lwp), 0 }; size_t lwpLength = 0; if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) { - threads += (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); + result->threads += (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); } } - result->threads = threads; return nullptr; } diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c index cb960ce57e..d0de8170d4 100644 --- a/src/detection/processes/processes_obsd.c +++ b/src/detection/processes/processes_obsd.c @@ -1,26 +1,36 @@ #include "processes.h" +#include "common/mallocHelper.h" + #include #include +#include -const char* ffDetectProcesses(FFProcessesResult* result) { - int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0 }; - size_t procLength = 0; - - if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed"; +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { + kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); + if (!kd) { + return "kvm_open() failed"; } - result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc)); + int count = 0; + // KERN_PROC_ALL returns all user-level processes, excluding kernel processes and threads + const struct kinfo_proc* procs = kvm_getprocs(kd, + (options->countKprocs ? KERN_PROC_KTHREAD : KERN_PROC_ALL) | KERN_PROC_SHOW_THREADS, + 0, sizeof(struct kinfo_proc), &count); + if (!procs) { + kvm_close(kd); + return "kvm_getprocs() failed"; + } - int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), 0 }; - size_t threadLength = 0; + for (int i = 0; i < count; ++i) { + const struct kinfo_proc* proc = &procs[i]; - if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) { - return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS}) failed"; + ++result->threads; + if (proc->p_tid == -1) { + ++result->processes; + } } - result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc)); - + kvm_close(kd); return nullptr; } diff --git a/src/detection/processes/processes_sunos.c b/src/detection/processes/processes_sunos.c index ce0da325cb..a815390bb5 100644 --- a/src/detection/processes/processes_sunos.c +++ b/src/detection/processes/processes_sunos.c @@ -5,34 +5,36 @@ #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc"); if (dir == nullptr) { return "opendir(\"/proc\") failed"; } - uint32_t processes = 0; - uint32_t threads = 0; - int procfd = dirfd(dir); struct dirent* entry; while ((entry = readdir(dir)) != nullptr) { if (ffCharIsDigit(entry->d_name[0])) { - ++processes; - - char psinfoPath[32]; - strcpy(ffStrCopy(psinfoPath, entry->d_name, sizeof(psinfoPath)), "/psinfo"); + char path[32]; + char* pidEnd = ffStrCopy(path, entry->d_name, sizeof(path)); + if (!options->countKprocs) { + pstatus_t status; + strcpy(pidEnd, "/status"); + if (ffReadFileDataRelative(procfd, path, sizeof(status), &status) != (ssize_t) sizeof(status) || + status.pr_flags & PR_ISSYS) { + continue; // The process may have exited, no permission or is a kernel process + } + } + strcpy(pidEnd, "/psinfo"); psinfo_t info; - if (ffReadFileDataRelative(procfd, psinfoPath, sizeof(info), &info) == (ssize_t) sizeof(info)) { - threads += info.pr_nlwp; + if (ffReadFileDataRelative(procfd, path, sizeof(info), &info) == (ssize_t) sizeof(info)) { + ++result->processes; + result->threads += (uint32_t) info.pr_nlwp; } } } - result->processes = processes; - result->threads = threads; - return nullptr; } diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index cb617099ed..7ccd13149d 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -4,7 +4,7 @@ #include #include -const char* ffDetectProcesses(FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr; // Multiple attempts in case processes change while @@ -25,17 +25,16 @@ const char* ffDetectProcesses(FFProcessesResult* result) { } } - uint32_t processes = 0; - uint32_t threads = 0; for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - ++processes; - threads += ptr->NumberOfThreads; + if (!options->countKprocs && ptr->CreateTime.QuadPart == 0) { + continue; + } + ++result->processes; + result->threads += ptr->NumberOfThreads; if (ptr->NextEntryOffset == 0) { break; } } - result->processes = processes; - result->threads = threads; return nullptr; } diff --git a/src/modules/processes/option.h b/src/modules/processes/option.h index 2ee25634df..9ef218135b 100644 --- a/src/modules/processes/option.h +++ b/src/modules/processes/option.h @@ -4,6 +4,8 @@ typedef struct FFProcessesOptions { FFModuleArgs moduleArgs; + + bool countKprocs; } FFProcessesOptions; static_assert(sizeof(FFProcessesOptions) <= FF_OPTION_MAX_SIZE, "FFProcessesOptions size exceeds maximum allowed size"); diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 9bb68239ca..e0838a9253 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -6,7 +6,7 @@ bool ffPrintProcesses(FFProcessesOptions* options) { FFProcessesResult result = {}; - const char* error = ffDetectProcesses(&result); + const char* error = ffDetectProcesses(options, &result); if (error) { ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); @@ -32,17 +32,23 @@ void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module) continue; } + if (unsafe_yyjson_equals_str(key, "countKprocs")) { + options->countKprocs = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", unsafe_yyjson_get_str(key)); } } void ffGenerateProcessesJsonConfig(FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { ffJsonConfigGenerateModuleArgsConfig(doc, module, &options->moduleArgs); + yyjson_mut_obj_add_bool(doc, module, "countKprocs", options->countKprocs); } bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FFProcessesResult result = {}; - const char* error = ffDetectProcesses(&result); + const char* error = ffDetectProcesses(options, &result); if (error) { yyjson_mut_obj_add_str(doc, module, "error", error); @@ -57,6 +63,8 @@ bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, void ffInitProcessesOptions(FFProcessesOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, ""); + + options->countKprocs = false; } void ffDestroyProcessesOptions(FFProcessesOptions* options) { @@ -65,7 +73,7 @@ void ffDestroyProcessesOptions(FFProcessesOptions* options) { FFModuleBaseInfo ffProcessesModuleInfo = { .name = "Processes", - .description = "Print number of running processes", + .description = "Print number of running processes and threads", .displayName = { .en = "Processes", .ar = "العمليات", From 1c9e52177522a90b93fd2423bfb0144e0b9897b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 29 Aug 2026 10:32:04 +0800 Subject: [PATCH 085/109] Top: disables `FF_TOP_TYPE_DISK` on Hurd and Haiku --- src/modules/top/top.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 60ecda8a0c..60b5a614ee 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -223,7 +223,11 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ void ffInitTopOptions(FFTopOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); options->sort = FF_TOP_TYPE_CPU; - options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY | FF_TOP_TYPE_DISK; + options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY + #if !__GNU__ && !__HAIKU__ + | FF_TOP_TYPE_DISK + #endif + ; options->nProcesses = 5; options->waitTime = 500; options->compact = false; From af8a42270c641df4911cbe0aa2ebc497484cfbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 29 Aug 2026 10:29:39 +0800 Subject: [PATCH 086/109] Top (Hurd): reports `startTime`; uses `time_value64_t` --- src/detection/top/top_gnu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 670f7f0770..0407124fbe 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -60,16 +60,16 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); - item->cpuTime = (uint64_t) info->user_time.seconds * 1000 + - (uint64_t) info->user_time.microseconds / 1000 + - (uint64_t) info->system_time.seconds * 1000 + - (uint64_t) info->system_time.microseconds / 1000; + item->cpuTime = (uint64_t) info->user_time64.seconds * 1000 + + (uint64_t) info->user_time64.nanoseconds / 1000000 + + (uint64_t) info->system_time64.seconds * 1000 + + (uint64_t) info->system_time64.nanoseconds / 1000000; item->memBytes = (uint64_t) info->resident_size; + item->startTime = (uint64_t) info->creation_time64.seconds * 1000 + + (uint64_t) info->creation_time64.nanoseconds / 1000000; } - // Neither process start times nor storage io counters are exposed by - // the Hurd; leave them zeroed. - item->startTime = 0; + // Storage io counters aren't exposed by kernel; leave them zeroed. item->bytesRead = 0; item->bytesWritten = 0; } From 3abcf4195ff506c0c0d7eb26b72f99c0217a8509 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 29 Aug 2026 12:14:09 +0800 Subject: [PATCH 087/109] Processes: corrects the structure of JSON result --- src/modules/processes/processes.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index e0838a9253..d6220aa03f 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -55,8 +55,9 @@ bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, return false; } - yyjson_mut_obj_add_uint(doc, module, "processes", result.processes); - yyjson_mut_obj_add_uint(doc, module, "threads", result.threads); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_uint(doc, obj, "processes", result.processes); + yyjson_mut_obj_add_uint(doc, obj, "threads", result.threads); return true; } From b04587e0cbfa2c1ad940f4bee754101b176d9a4b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 29 Aug 2026 13:03:49 +0800 Subject: [PATCH 088/109] Presets: moves `top` to the bottom of running modules [ci skip] --- presets/all.jsonc | 10 +++++----- presets/ci.jsonc | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/presets/all.jsonc b/presets/all.jsonc index fdb33ac2b6..73901ca30b 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -19,7 +19,6 @@ "uptime", "loadavg", "processes", - "top", "packages", "shell", "editor", @@ -100,16 +99,17 @@ "gamepad", "mouse", "keyboard", - { - "type": "weather", - "timeout": 1000 - }, + "top", "netio", "diskio", { "type": "physicaldisk", "temp": true }, + { + "type": "weather", + "timeout": 1000 + }, "tpm", "version", "break", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 5499e12941..c18994df06 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -21,7 +21,6 @@ "uptime", "loadavg", "processes", - "top", "packages", "shell", "editor", @@ -102,16 +101,17 @@ "gamepad", "mouse", "keyboard", - { - "type": "weather", - "timeout": 1000 - }, + "top", "netio", "diskio", { "type": "physicaldisk", "temp": true }, + { + "type": "weather", + "timeout": 1000 + }, "tpm", "version", "logo", From 753ddec3c573b5079adf90c556c67f185165f0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 29 Aug 2026 20:09:48 +0800 Subject: [PATCH 089/109] Memory (Windows): prefers `NQSI` --- src/common/windows/nt.h | 56 +++++++++++++++++++++++++++ src/detection/memory/memory_windows.c | 29 ++++++++------ 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index 4a61b8226a..ceecbf9c86 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -11,6 +11,7 @@ enum { SystemFirmwareTableInformation = 76, SystemBootEnvironmentInformation = 90, SystemLogicalProcessorAndGroupInformation = 107, + SystemBasicPerformanceInformation = 123, SystemSecureBootInformation = 146, }; @@ -198,6 +199,13 @@ typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION { _Field_size_bytes_(TableBufferLength) UCHAR TableBuffer[]; } SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; +typedef struct _SYSTEM_BASIC_PERFORMANCE_INFORMATION { + SIZE_T AvailablePages; + SIZE_T CommittedPages; + SIZE_T CommitLimit; + SIZE_T PeakCommitment; +} SYSTEM_BASIC_PERFORMANCE_INFORMATION, *PSYSTEM_BASIC_PERFORMANCE_INFORMATION; + NTSYSAPI NTSTATUS NTAPI NtDelayExecution(_In_ BOOLEAN Alertable, _In_ PLARGE_INTEGER DelayInterval); /** @@ -599,6 +607,54 @@ typedef struct _KUSER_SHARED_DATA { }; }; + // + // Reserved padding field to preserve structure alignment and compatibility. + // + + ULONG DataFlagsPad[1]; + + // + // Depending on the processor, the code for fast system call will differ, + // Stub code is provided pointers below to access the appropriate code. + // + // N.B. The following field is only used on 32-bit systems. + // + + ULONGLONG TestRetInstruction; + + // + // Query-performance counter (QPC) frequency, in counts per second. + // + // N.B. This value represents the fixed frequency of the system's high-resolution + // performance counter. It is used by user-mode time routines to convert QPC + // ticks into elapsed time without requiring a system call. The frequency is + // constant for the lifetime of the system and reflects the hardware or + // virtualized timer source selected by the kernel. + // + + LONGLONG QpcFrequency; + + // + // On AMD64, this value is initialized to a nonzero value if the system + // operates with an altered view of the system service call mechanism. + // + + ULONG SystemCall; + + // + // Reserved field - do not use. Used to be UserCetAvailableEnvironments. + // + + ULONG Reserved2; + + // + // Full 64 bit version of the number of physical pages in the system. + // This can dynamically change as physical memory can be added or removed + // from a running system. + // + + ULONGLONG FullNumberOfPhysicalPages; + // ... more fields follow, but we don't need them } KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; diff --git a/src/detection/memory/memory_windows.c b/src/detection/memory/memory_windows.c index da689621d2..c86189ae65 100644 --- a/src/detection/memory/memory_windows.c +++ b/src/detection/memory/memory_windows.c @@ -1,19 +1,26 @@ #include "memory.h" -#include +#include "common/windows/nt.h" const char* ffDetectMemory(FFMemoryResult* ram) { - MEMORYSTATUSEX statex = { - .dwLength = sizeof(statex), - }; - // GlobalMemoryStatusEx() internally uses - // NtQuerySystemInformation(SystemBasicPerformanceInformation) in Win 7, and - // NtQuerySystemInformation(SystemMemoryUsageInformation) in Win 10 - if (!GlobalMemoryStatusEx(&statex)) { - return "GlobalMemoryStatusEx() failed"; + // Note: GlobalMemoryStatusEx() internally uses SystemMemoryUsageInformation in Win 10 + + SYSTEM_BASIC_PERFORMANCE_INFORMATION sbpi; + if (!NT_SUCCESS(NtQuerySystemInformation(SystemBasicPerformanceInformation, &sbpi, sizeof(sbpi), NULL))) + return "Failed to query memory information"; + + uint64_t phyPages = + #if _WIN64 + SharedUserData->FullNumberOfPhysicalPages; + if (__builtin_expect(phyPages == 0, false)) { // Not supported on Windows 8.1 + phyPages = SharedUserData->NumberOfPhysicalPages; // ULONG, maximum 16 TB } + #else + SharedUserData->NumberOfPhysicalPages; + #endif - ram->bytesTotal = statex.ullTotalPhys; - ram->bytesUsed = statex.ullTotalPhys - statex.ullAvailPhys; + uint64_t pageSize = instance.state.platform.sysinfo.pageSize; + ram->bytesTotal = phyPages * pageSize; + ram->bytesUsed = (phyPages - sbpi.AvailablePages) * pageSize; return nullptr; } From 4dba32aabb888e4cb58ba3383ca29a829ed7448e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 30 Aug 2026 19:03:54 +0800 Subject: [PATCH 090/109] WM (macOS): improves reliability of WM plugin detection --- src/common/impl/sysctl.c | 15 --------------- src/common/sysctl.h | 1 - src/detection/wm/wm_apple.m | 21 ++++++++++++++------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/common/impl/sysctl.c b/src/common/impl/sysctl.c index 122a790918..29d4a3afca 100644 --- a/src/common/impl/sysctl.c +++ b/src/common/impl/sysctl.c @@ -116,18 +116,3 @@ int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue) { } } #endif // OpenBSD - -void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength) { - if (sysctl(request, requestLength, nullptr, resultLength, nullptr, 0) != 0) { - return nullptr; - } - - void* data = malloc(*resultLength); - - if (sysctl(request, requestLength, data, resultLength, nullptr, 0) != 0) { - free(data); - return nullptr; - } - - return data; -} diff --git a/src/common/sysctl.h b/src/common/sysctl.h index 7e59ec663c..9d12df6fcb 100644 --- a/src/common/sysctl.h +++ b/src/common/sysctl.h @@ -14,4 +14,3 @@ const char* ffSysctlGetString(const char* propName, FFstrbuf* result); [[nodiscard]] int ffSysctlGetInt(const char* propName, int defaultValue); [[nodiscard]] int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue); #endif -[[nodiscard]] void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength); diff --git a/src/detection/wm/wm_apple.m b/src/detection/wm/wm_apple.m index c4bc780a21..e02c089bb7 100644 --- a/src/detection/wm/wm_apple.m +++ b/src/detection/wm/wm_apple.m @@ -11,16 +11,23 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - u_int requestLength = ARRAY_SIZE(request); + size_t length; - size_t length = 0; - FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length); - if (processes == nullptr) { - return "sysctl(CTL_KERN, KERN_PROC, KERN_PROC_ALL) failed"; + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed"; } - assert(length % sizeof(struct kinfo_proc) == 0); - for (size_t i = 0; i < length / sizeof(struct kinfo_proc); i++) { + // The process table may change between the two sysctl calls; retry with a larger buffer. + length += length / 8 + sizeof(struct kinfo_proc); + FF_AUTO_FREE struct kinfo_proc* processes = malloc(length); + + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed"; + } + + uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc)); + + for (size_t i = 0; i < count; i++) { const struct kinfo_proc* proc = &processes[i]; if (proc->kp_eproc.e_ppid != 1) { continue; From 39024abae958ff0cef8a5bd7ab83740ba3e61148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 30 Aug 2026 19:41:18 +0800 Subject: [PATCH 091/109] Processes (Haiku): honors `options->countKprocs` --- src/detection/processes/processes_haiku.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/detection/processes/processes_haiku.c b/src/detection/processes/processes_haiku.c index 484a321199..feecc34e58 100644 --- a/src/detection/processes/processes_haiku.c +++ b/src/detection/processes/processes_haiku.c @@ -2,7 +2,7 @@ #include -const char* ffDetectProcesses(const FFProcessesOptions*, FFProcessesResult* result) { +const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { system_info info; if (get_system_info(&info) != B_OK) { return "Error getting system info"; @@ -11,5 +11,13 @@ const char* ffDetectProcesses(const FFProcessesOptions*, FFProcessesResult* resu result->processes = info.used_teams; result->threads = info.used_threads; + if (!options->countKprocs) { + team_info ti; + if (get_team_info(B_SYSTEM_TEAM, &ti) == B_OK) { + result->processes--; + result->threads -= (uint32_t) ti.thread_count; + } + } + return nullptr; } From 5b1ad1008dff9d53596460bf05d37ba7bf78e9c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 Aug 2026 18:07:08 +0000 Subject: [PATCH 092/109] CI: Bump the github-actions group with 3 updates Bumps the github-actions group with 3 updates: [uraimo/run-on-arch-action](https://github.com/uraimo/run-on-arch-action), [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action). Updates `uraimo/run-on-arch-action` from 3.1.0 to 3.2.0 - [Release notes](https://github.com/uraimo/run-on-arch-action/releases) - [Commits](https://github.com/uraimo/run-on-arch-action/compare/f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9...460cb8e6d9f726a588fc9b5e681c8a6cab09ae41) Updates `github/codeql-action/init` from 4.37.7 to 4.37.8 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28) Updates `github/codeql-action/analyze` from 4.37.7 to 4.37.8 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28) --- updated-dependencies: - dependency-name: uraimo/run-on-arch-action dependency-version: 3.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: github/codeql-action/init dependency-version: 4.37.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/analyze dependency-version: 4.37.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/build-linux-armv7l.yml | 2 +- .github/workflows/build-linux-hosts.yml | 4 ++-- .github/workflows/build-linux-vms.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-linux-armv7l.yml b/.github/workflows/build-linux-armv7l.yml index 981ab48c47..16d239c5de 100644 --- a/.github/workflows/build-linux-armv7l.yml +++ b/.github/workflows/build-linux-armv7l.yml @@ -17,7 +17,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: run VM - uses: uraimo/run-on-arch-action@f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9 # v3.1.0 + uses: uraimo/run-on-arch-action@460cb8e6d9f726a588fc9b5e681c8a6cab09ae41 # v3.2.0 id: runcmd with: arch: armv7 diff --git a/.github/workflows/build-linux-hosts.yml b/.github/workflows/build-linux-hosts.yml index 19aec15b0b..51fe44c27a 100644 --- a/.github/workflows/build-linux-hosts.yml +++ b/.github/workflows/build-linux-hosts.yml @@ -52,7 +52,7 @@ jobs: - name: Initialize CodeQL if: inputs.arch == 'amd64' - uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 + uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: languages: c @@ -64,7 +64,7 @@ jobs: - name: perform CodeQL analysis if: inputs.arch == 'amd64' - uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 + uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 - name: list features run: ./fastfetch --list-features diff --git a/.github/workflows/build-linux-vms.yml b/.github/workflows/build-linux-vms.yml index e61a2c52cb..73bfd9c667 100644 --- a/.github/workflows/build-linux-vms.yml +++ b/.github/workflows/build-linux-vms.yml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: run VM - uses: uraimo/run-on-arch-action@f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9 # v3.1.0 + uses: uraimo/run-on-arch-action@460cb8e6d9f726a588fc9b5e681c8a6cab09ae41 # v3.2.0 id: runcmd with: arch: ${{ inputs.arch }} From df992414242d579ef91b3dbb13cfd07fa489e0fa Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 13:11:00 +0800 Subject: [PATCH 093/109] L10n (gl): adds missing missing Galician translations --- src/modules/custom/custom.c | 1 + src/modules/terminalsize/terminalsize.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 79c3d02f80..13a1fed0e6 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -44,6 +44,7 @@ FFModuleBaseInfo ffCustomModuleInfo = { .de = "Benutzerdefiniert", .es = "Personalizado", .fr = "Personnalisé", + .gl = "Personalizado", .he = "מותאם אישית", .id = "Kustom", .it = "Personalizzato", diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index 12470cd7ae..cfea3bd2bf 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -83,6 +83,7 @@ FFModuleBaseInfo ffTerminalSizeModuleInfo = { .de = "Terminalgröße", .es = "Tamaño del terminal", .fr = "Taille du terminal", + .gl = "Tamaño do terminal", .he = "גודל טרמינל", .id = "Ukuran Terminal", .it = "Dimensioni terminale", From a33d6326f1b0bee58c9a35a2ee1ec225a0f7021a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 13:31:21 +0800 Subject: [PATCH 094/109] CMake: enables `CONFIGURE_DEPENDS` to `FF_MODULE_DIRS` globbing --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e181366301..0d526dbb78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,7 +128,7 @@ if(APPLE) option(ENABLE_APPLE_MEMSIZE_USABLE "Use usable memory size as total memory size in Memory module, to match other systems" OFF) endif() -file(GLOB FF_MODULE_DIRS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/modules" "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/*/") +file(GLOB FF_MODULE_DIRS CONFIGURE_DEPENDS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/modules" "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/*/") foreach(FF_MODULE_DIR ${FF_MODULE_DIRS}) if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/modules/${FF_MODULE_DIR}") string(TOUPPER "${FF_MODULE_DIR}" FF_MODULE_UPPER) From d5214af189e45f800d8260f86938007002097fb8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 13:44:19 +0800 Subject: [PATCH 095/109] Global: fixes British spellings and typos found by AI --- CHANGELOG.md | 2 +- presets/examples/14.jsonc | 2 +- src/common/impl/genconfig.c | 2 +- src/common/impl/settings.c | 4 ++-- src/detection/displayserver/linux/xcb.c | 2 +- src/detection/gtk_qt/gtk.c | 2 +- src/fastfetch.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e1744285..c8cde2812c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3314,7 +3314,7 @@ Features: * Enhance `--percent-type` to allow hiding other texts (#387) * Add Wifi module support for Linux * Detect scaled resolutions (Windows, macOS) -* Optimise font module printing (Windows) +* Optimize font module printing (Windows) * Detect pacman package count inside MSYS2 environment (Windows) * Add Wifi / Battery module support for Android * Disk name support for Linux diff --git a/presets/examples/14.jsonc b/presets/examples/14.jsonc index b20c544775..e85e7bfb49 100644 --- a/presets/examples/14.jsonc +++ b/presets/examples/14.jsonc @@ -12,7 +12,7 @@ }, "modules": [ { - // draw borders first to make colors of left and right border consistant + // draw borders first to make colors of left and right border consistent "key": " user", "type": "title", "format": "{user-name}", diff --git a/src/common/impl/genconfig.c b/src/common/impl/genconfig.c index fbc10d874f..e819508166 100644 --- a/src/common/impl/genconfig.c +++ b/src/common/impl/genconfig.c @@ -996,7 +996,7 @@ bool ffGenConfigInteractive(FFdata* data) { success = true; } } else { - fputs("\nConfig generation cancelled.\n", stderr); + fputs("\nConfig generation canceled.\n", stderr); } ffListDestroy(&ui.items); diff --git a/src/common/impl/settings.c b/src/common/impl/settings.c index 11dbac6705..dcbd8893e2 100644 --- a/src/common/impl/settings.c +++ b/src/common/impl/settings.c @@ -507,8 +507,8 @@ typedef struct E_Config { Eina_List* font_defaults; } E_Config; // Must be the same name as the top level struct in e.cfg - #define FF_EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(clas, type) \ - (ffeet_eina_file_data_descriptor_class_set(clas, sizeof(*(clas)), #type, sizeof(type))) + #define FF_EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(klass, type) \ + (ffeet_eina_file_data_descriptor_class_set(klass, sizeof(*(klass)), #type, sizeof(type))) #define FF_EET_DATA_DESCRIPTOR_ADD_BASIC(edd, struct_type, member, type) \ do { \ struct_type ___ett; \ diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index f3c3711370..32b20ab27e 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -331,7 +331,7 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen) { } static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) { - // With all the initialisation done, start the detection + // With all the initialization done, start the detection if (xcbRandrHandleMonitors(data, screen)) { return; } diff --git a/src/detection/gtk_qt/gtk.c b/src/detection/gtk_qt/gtk.c index 1740630e16..7c9638dbdf 100644 --- a/src/detection/gtk_qt/gtk.c +++ b/src/detection/gtk_qt/gtk.c @@ -111,7 +111,7 @@ static void detectGTKFromSettings(FFGTKResult* result) { } else { // Standalone WMs (Hyprland, sway, niri, i3, ...) report no DE and have no settings // daemon, but GTK apps on them still read org.gnome.desktop.interface. - // Read via DConf, not GSettings: GSettings synthesises the schema default for keys + // Read via DConf, not GSettings: GSettings synthesizes the schema default for keys // the user never set, DConf returns nothing. Runs last; applyGTKSettings() only // fills still-empty fields, so config files always win. themeName = ffSettingsGetDConf("/org/gnome/desktop/interface/gtk-theme", FF_VARIANT_TYPE_STRING).strValue; diff --git a/src/fastfetch.c b/src/fastfetch.c index b6c2ea2018..3a936fb766 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -910,7 +910,7 @@ int main(int argc, char** argv) { ffStrbufSetS(&data.structure, FASTFETCH_DATATEXT_STRUCTURE); // Cannot use `ffStrbufSetStatic` here because we will modify the string } if (data.genConfigInteractive && !ffGenConfigInteractive(&data)) { - // User cancelled the interactive config generation + // User canceled the interactive config generation ffStrbufDestroy(&data.structure); ffStrbufDestroy(&data.structureDisabled); yyjson_doc_free(data.configDoc); From ef7f5aeac32d0173220c7466b35b6489eb40e6d8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 14:09:57 +0800 Subject: [PATCH 096/109] CPU (Android): adds pretty names of new SoCs --- src/detection/cpu/cpu_linux.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index e41aeabe8a..904533e4df 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -214,9 +214,15 @@ static void detectQualcomm(FFCPUResult* cpu) { const char* name = nullptr; switch (code) { + case 8975: + name = "8 Elite Extreme Gen 6"; + break; + case 8950: + name = "8 Elite Gen 6"; + break; case 8845: name = "8 Gen 5"; - break; // ? + break; case 8850: name = "8 Elite Gen 5"; break; @@ -238,6 +244,9 @@ static void detectQualcomm(FFCPUResult* cpu) { case 8475: name = "8+ Gen 1"; break; + case 8425: + name = "8+ Gen 1 4G"; + break; case 8450: name = "8 Gen 1"; break; @@ -271,12 +280,18 @@ static void detectQualcomm(FFCPUResult* cpu) { case 6475: name = "6 Gen 3"; break; + case 6225: + name = "6s 4G Gen 2"; + break; case 6115: - name = "6s Gen 1"; + name = "6s 4G Gen 1"; break; case 6450: name = "6 Gen 1"; break; + case 4850: + name = "4 Gen 5"; + break; case 4635: name = "4s Gen 2"; break; @@ -305,6 +320,9 @@ static void detectMediaTek(FFCPUResult* cpu) { switch (code) // The SOC code of MTK Dimensity series is full of mess { + case 6995: + name = "9600"; + break; case 6993: name = "9500"; break; @@ -357,6 +375,9 @@ static void detectExynos(FFCPUResult* cpu) { const char* name = nullptr; switch (code) { + case 9975: + name = "2700"; + break; case 9965: name = "2600"; break; @@ -374,6 +395,9 @@ static void detectExynos(FFCPUResult* cpu) { name = "2100"; break; + case 8865: + name = "1680"; + break; case 8855: name = "1580"; break; From 42002a6240ce00756f2bfa03418fa6c08687f9be Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 14:26:50 +0800 Subject: [PATCH 097/109] CPU (Linux): supports more Snapdragon X SoCs --- CHANGELOG.md | 1 + src/detection/cpu/cpu_linux.c | 67 +++++++++++++++++++++++++++-------- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8cde2812c..a18be3800f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Features: * Improved fish completion scripts to print enum descriptions. (Completion) * Enabled Wayland support on Android. (DisplayServer, Android) * Added DE detection support for ASUS Zenfone. (DE, Android) +* Added new ARM SoCs (CPU, Linux / Android) Bugfixes: * Fixed I/O rate calculation precision in DiskIO and NetIO, and prevented division by zero. (DiskIO / NetIO) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 904533e4df..589d0ac01b 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -837,6 +837,46 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) { return nullptr; } +[[maybe_unused]] static bool detectSnapdragonX(FFstrbuf* name, const char* model) { + // SoC models are enumerated in the form of `x[e|p]`, e.g. `x1e80100`, + // which is marketed as `X1E-80-100`, where `e` stands for Elite and `p` for Plus. + // https://en.wikipedia.org/wiki/List_of_Qualcomm_Snapdragon_systems_on_chips#Snapdragon_X_series + const char* prefix; + uint32_t prefixLen; + + if (ffStrStartsWith(model, "x1e")) { + prefix = "Qualcomm Snapdragon X Elite"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x1p")) { + prefix = "Qualcomm Snapdragon X Plus"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x2e")) { + // Only X2E-94-100 and X2E-96-100 are branded as Extreme + prefix = model[3] == '9' ? "Qualcomm Snapdragon X2 Elite Extreme" : "Qualcomm Snapdragon X2 Elite"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x2p")) { + prefix = "Qualcomm Snapdragon X2 Plus"; + prefixLen = 3; + } else if (ffStrStartsWith(model, "x1")) { + prefix = "Qualcomm Snapdragon X"; + prefixLen = 2; + } else { + return false; + } + + uint32_t length = (uint32_t) strlen(model); + bool splitCode = length - prefixLen == 5; + + ffStrbufSetF(name, "%s X", prefix); + for (uint32_t i = 1; i < length; ++i) { + if (i == prefixLen || (splitCode && i == length - 3)) { + ffStrbufAppendC(name, '-'); + } + ffStrbufAppendC(name, (char) toupper(model[i])); + } + return true; +} + [[maybe_unused]] static void parseIsa(FFstrbuf* cpuIsa) { // Always use the last part of the ISA string. Ref: #590 #1204 ffStrbufSubstrAfterLastC(cpuIsa, ' '); @@ -938,22 +978,19 @@ static const char* detectPhysicalCores(FFCPUResult* cpu) { } #endif else if (ffStrEquals(vendor, "qcom")) { - // https://elixir.bootlin.com/linux/v6.11/source/arch/arm64/boot/dts/qcom - if (ffStrStartsWith(model, "x")) { - ffStrbufSetS(&cpu->name, "Qualcomm Snapdragon X Elite "); - for (const char* p = model + 1; *p; ++p) { - ffStrbufAppendC(&cpu->name, (char) toupper(*p)); - } - } else if (ffStrStartsWith(model, "sc")) { - const char* code = model + 2; - uint32_t deviceId = (uint32_t) strtoul(code, nullptr, 10); - ffStrbufSetStatic(&cpu->name, ffCPUQualcommCodeToName(deviceId)); - if (!cpu->name.length) { - ffStrbufAppendS(&cpu->name, "Qualcomm Snapdragon SC"); - ffStrbufAppendS(&cpu->name, code); + // https://elixir.bootlin.com/linux/latest/source/arch/arm64/boot/dts/qcom + if (!detectSnapdragonX(&cpu->name, model)) { + if (ffStrStartsWith(model, "sc")) { + const char* code = model + 2; + uint32_t deviceId = (uint32_t) strtoul(code, nullptr, 10); + ffStrbufSetStatic(&cpu->name, ffCPUQualcommCodeToName(deviceId)); + if (!cpu->name.length) { + ffStrbufAppendS(&cpu->name, "Qualcomm Snapdragon SC"); + ffStrbufAppendS(&cpu->name, code); + } + } else { + ffStrbufSetS(&cpu->name, model); } - } else { - ffStrbufSetS(&cpu->name, model); } ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); From 76b676814176a3bd0929e504302f9760623157ee Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 14:33:43 +0800 Subject: [PATCH 098/109] JsonSchema: regenerates `moduleFormat` --- doc/json_schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 2768b13df9..b2f07370dd 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -398,7 +398,7 @@ "type": "string" }, "lmFormat": { - "description": "Output format for the `LM` module. See Wiki for formatting syntax\n 1. {service}: LM service\n 2. {type}: LM type\n 3. {version}: LM version", + "description": "Output format for the `LM` module. See Wiki for formatting syntax\n 1. {service}: LM service / process name\n 2. {pretty-name}: LM pretty name\n 3. {version}: LM version", "type": "string" }, "loadavgFormat": { @@ -506,7 +506,7 @@ "type": "string" }, "topFormat": { - "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second\n 7. {disk-write}: Disk write bytes per second\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second (0 if unsupported)\n 7. {disk-write}: Disk write bytes per second (0 if unsupported)\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", "type": "string" }, "themeFormat": { From 9c791b2c127467278a28c241ba9fbd3ecd04ae06 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 15:24:48 +0800 Subject: [PATCH 099/109] Doc: adds `CONTRIBUTING.md` --- .gitignore | 2 + CONTRIBUTING.md | 724 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 726 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/.gitignore b/.gitignore index 1394fe9317..9fe9c7bfb4 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ fastfetch.kdev4 *.user.* *.swp *.log +/*.zh.md +/.*-ai/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..0da08c892c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,724 @@ +# Contributing to fastfetch + +
+ + Note + + + This document is generated by AI, and mainly for AI use. It is not a substitute for human review, and may contain errors or omissions. Please verify any information before relying on it. +
+ +Thanks for your interest in fastfetch. This document covers building, architecture, how to add a module or a logo, code style, commit conventions, and the pull request workflow. + +fastfetch is a system information tool written in C23, supporting Linux, macOS, Windows, the BSDs, Solaris, Haiku and Android. The project is borderline obsessive about **startup time** and **optional dependencies** — many design decisions only make sense under that constraint, and this document keeps coming back to it. + +--- + +## Table of contents + +- [Contributor quick reference](#contributor-quick-reference) +- [Getting started](#getting-started) +- [Code map](#code-map) +- [Core architecture: modules vs. detection](#core-architecture-modules-vs-detection) +- [Module registration](#module-registration) +- [Walkthrough: adding a module](#walkthrough-adding-a-module) +- [Walkthrough: adding a logo](#walkthrough-adding-a-logo) +- [Platform conventions](#platform-conventions) +- [Code style](#code-style) +- [Commit messages](#commit-messages) +- [Changelog](#changelog) +- [Tests](#tests) +- [Pull requests](#pull-requests) +- [Gotchas](#gotchas) + +--- + +## Contributor quick reference + +| Task | Start here | Verify with | +|---|---|---| +| Build and run fastfetch | `run.sh`, `CMakeLists.txt` | `./run.sh` | +| Add a module | `src/modules//`, `src/detection//`, `src/modules/modules.c` | `cmake -B build && cmake --build build -j` | +| Add a platform implementation | `src/detection//_.c` | Build on the target platform or CI | +| Add an ASCII logo | `src/logo/ascii//.txt`, matching `.inc` | `./build/fastfetch --logo ` | +| Change formatting or JSON output | `src/modules//.c` | `./build/fastfetch -s --format json` | +| Change shared formatting or containers | `src/common/format.h`, `src/common/color.h`, `src/common/FFstrbuf.h` | Build and run the matching test | +| Run the test suite | `tests/`, `build/` | `cd build && ctest --output-on-failure` | + +For a normal code change, the shortest useful loop is: configure, build the `fastfetch` target, run the affected module, then run the tests. If you add a directory or a generated input, re-run `cmake -B build` so CMake refreshes its file globs. + +--- + +## Getting started + +### Building + +The quickest way is `run.sh` in the repository root — it creates `build/`, configures, compiles and runs the binary: + +```sh +./run.sh # build and run +./run.sh --format json # arguments are forwarded to fastfetch +``` + +Manual build: + +```sh +cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo +cmake --build build --target fastfetch -j$(nproc) +./build/fastfetch +``` + +The default build type is `RelWithDebInfo`. LTO is enabled whenever `ENABLE_LTO=ON` **and** `CMAKE_BUILD_TYPE != Debug` — so the default already has it, and only `Debug` builds lack it. This matters because LTO here is not merely an optimization: it is what strips the code of disabled modules. See [Gotchas](#gotchas). + +### Common build options + +| Option | Default | Notes | +|---|---|---| +| `CMAKE_BUILD_TYPE` | `RelWithDebInfo` | LTO is on for anything but `Debug` | +| `BUILD_TESTS` | `OFF` | Builds the unit tests in `tests/` | +| `BUILD_FLASHFETCH` | `ON` | Also builds the stripped-down `flashfetch` | +| `BINARY_LINK_TYPE` | `dlopen` | `dlopen` / `dynamic` / `static` | +| `ENABLE_ASAN` | `OFF` | Address Sanitizer | +| `ENABLE_LTO` | `ON` | Link-time optimization | +| `MODULE_DISABLE_` | `OFF` | Disable a module, e.g. `MODULE_DISABLE_GPU=ON` | +| `SET_TWEAK` | `ON` | Appends a tweak to the dev version; turned off for releases | + +`BINARY_LINK_TYPE=dlopen` (the default) is a deliberate design choice: optional dependencies (Vulkan, Wayland, DBus, ImageMagick, chafa, …) are loaded at runtime, so a missing library never prevents startup. When adding a third-party dependency, use the dlopen helpers in `common/library.h` — do not link it directly. + +For a minimal-dependency build, see `.github/workflows/build-no-features-test.yml`: + +```sh +cmake -DBUILD_TESTS=On -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_X11=OFF \ + -DENABLE_DBUS=OFF -DENABLE_ZLIB=OFF ... . +``` + +### Dependencies + +Required: CMake ≥ 3.21 and a C23 compiler (GCC, Clang or MSVC). Everything else is optional. + +Optional dependencies are auto-detected: libpci, libdrm, vulkan, wayland, xcb, xrandr, dbus, sqlite3, rpm, imagemagick{6,7}, chafa, zlib, egl, glx, opencl, freetype, pulse, ddcutil, elf, libzfs, and more. + +--- + +## Code map + +``` +src/ +├── fastfetch.c entry point: CLI parsing, module dispatch, main loop (36 KB) +├── flashfetch.c entry point for the stripped-down build +├── options/ global (non-module) config: general / display / logo +├── modules/ module layer — module formatting and output +├── detection/ detection layer — platform-specific data retrieval +├── common/ infrastructure: FFstrbuf, FFlist, formatting, printing, networking +├── logo/ 530 ASCII logos plus the image logo backends +└── 3rdparty/ yyjson, widecharwidth, display-library +``` + +Flow of control: + +``` +fastfetch.c → options/ (global configuration) + → modules/ (76 modules, formatting and output) + → detection/ (one platform implementation each, raw data) + → common/ (infrastructure) +``` + +The number of module directories and detection directories does not match, and that is expected. The following relationships are structural rather than a fixed inventory: + +- **13 modules have no detection directory** — they are either pure layout (`break`, `separator`, `colors`, `title`, `logo`) or reuse someone else's detection result (`display`, `monitor`, `kernel`, `shell`, `terminal`, `player`, `custom`, `datetime`). +- **4 detection directories serve modules with different names** — `displayserver` (→ `display`, `monitor`), `gtk_qt` (→ `theme`, `icons`, `font`, `cursor`), `terminalshell` (→ `terminal`, `shell`) and `libc`. + +So do not assume `modules//` always has a matching `detection//`. + +### Layer boundaries + +| Layer | Owns | Must not | +|---|---|---| +| `options/` | **Global** config (colors, logo, threading, timeouts) | hold per-module options | +| `modules/` | formatting, printing, JSON serialization | read `/proc`, call Win32 APIs, parse sysfs | +| `detection/` | cross-platform data retrieval, clean result structs | print anything, read display config | +| `common/` | general-purpose utilities, no business logic | depend on a specific module | + +The test is simple: **no file under `detection/` should contain `printf` or read `instance.config`.** Symmetrically, no file under `modules/` should contain `#ifdef __linux__`. + +--- + +## Core architecture: modules vs. detection + +This is the single most important convention in the codebase. Every feature is a fixed set of files — using CPU as the example: + +``` +modules/cpu/option.h module option struct +modules/cpu/cpu.c formatting and output +detection/cpu/cpu.h platform-independent interface +detection/cpu/cpu_linux.c ┐ +detection/cpu/cpu_apple.c │ +detection/cpu/cpu_windows.c ├─ platform implementations, one linked per build +detection/cpu/cpu_bsd.c │ +detection/cpu/cpu_nosupport.c ┘ +``` + +The interface is deliberately minimal — usually just two things: + +```c +typedef struct FFCPUResult { ... } FFCPUResult; // result struct +const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu); +``` + +The `const char*` return value is an **error string**; `nullptr` means success. This pattern is used throughout `detection/` — please keep it consistent. + +Helper functions are only exposed when they are genuinely shared between platform implementations (as in `cpu.h`: `ffCPUAppleCodeToName`, `ffCPUDetectByCpuid`). + +**The payoff:** adding a platform never touches `modules/`; fixing output formatting never touches `detection/`. + +--- + +## Module registration + +### The descriptor + +Every module exports one `FFModuleBaseInfo` (defined in `common/option.h:46`) — essentially a hand-written vtable: + +```c +typedef struct FFModuleBaseInfo { + const char* name; // lookup key, e.g. "cpu" + const char* description; // help text + FFModuleDisplayName displayName; // module name in 20 languages + + void (*initOptions)(void* options); + void (*destroyOptions)(void* options); + void (*parseJsonObject)(void* options, struct yyjson_val* module); + bool (*printModule)(void* options); + bool (*generateJsonResult)(void* options, yyjson_mut_doc*, yyjson_mut_val*); + void (*generateJsonConfig)(void* options, yyjson_mut_doc*, yyjson_mut_val*); + + FFModuleFormatArgList formatArgs; // format placeholder table + const uint8_t defaultOrder; // sort weight +} FFModuleBaseInfo; +``` + +The source comment openly admits this is UB — `void*` is not compatible with `FF*Options*`. It is a pragmatic compromise to get polymorphism in C. Don't try to "fix" it. + +### The registry: a first-letter hash bucket + +`src/modules/modules.c` defines 26 `static FFModuleBaseInfo*` arrays (`A[]` through `Z[]`), each terminated by `nullptr`, collected into `ffModuleInfos[26]`: + +```c +FFModuleBaseInfo** modules = ffModuleInfos[toupper(name[0]) - 'A']; // O(1) bucket lookup +for (; *modules; ++modules) { // linear scan in the bucket + if (ffStrEqualsIgnCase(name, (*modules)->name)) { ... } +} +``` + +The registry is small enough that a subtraction plus a few string comparisons is preferable to a general-purpose hash table. When adding a module, place its descriptor in the bucket matching the first letter of `.name`; keep the existing `nullptr` terminator at the end. + +### The calling convention: zero heap allocation + +Every dispatch site (`jsonconfig.c:98`, `commandoption.c:189`) follows the same pattern: + +```c +alignas(uint64_t) uint8_t optionBuf[FF_OPTION_MAX_SIZE]; // 256 bytes, on the stack +baseInfo->initOptions(optionBuf); +baseInfo->parseJsonObject(optionBuf, jsonVal); // JSONC path only +baseInfo->printModule(optionBuf); // or generateJsonResult +baseInfo->destroyOptions(optionBuf); +``` + +`FF_OPTION_MAX_SIZE = 1 << 8` (256 bytes). Every module's `option.h` must end with: + +```c +static_assert(sizeof(FFCPUOptions) <= FF_OPTION_MAX_SIZE, "FFCPUOptions size exceeds maximum allowed size"); +``` + +**Meaning: no module option struct may exceed 256 bytes.** Hard constraint, enforced at compile time. + +The three dispatch entry points: + +| Entry point | Location | Used for | +|---|---|---| +| `parseModuleJsonObject` | `common/impl/jsonconfig.c:90` | the `modules[]` array in a JSONC config | +| `parseStructureCommand` | `common/impl/commandoption.c:181` | the colon-separated structure string | +| `ffParseModuleOptions` | `common/impl/commandoption.c:13` | **deprecated** — see [Gotchas](#4-cli-module-options-are-removed) | + +### Build-time module discovery + +`CMakeLists.txt:131` globs `src/modules/*/` and generates a `MODULE_DISABLE_` option per directory: + +```cmake +file(GLOB FF_MODULE_DIRS RELATIVE "..." ".../src/modules/*/") +foreach(FF_MODULE_DIR ${FF_MODULE_DIRS}) + option(MODULE_DISABLE_${FF_MODULE_UPPER} "Disable module ${FF_MODULE_DIR}" OFF) +endforeach() +``` + +**Adding a module requires no CMake change.** The same trick generates the package manager switches (`:146` regex-scans `src/modules/packages/option.h` for `FF_PACKAGES_FLAG_*_BIT`). + +--- + +## Walkthrough: adding a module + +Adding a `Foo` module, step by step. + +### 1. Define the option struct + +`src/modules/foo/option.h`: + +```c +#pragma once + +#include "common/option.h" + +typedef struct FFFooOptions { + FFModuleArgs moduleArgs; // must be the first field + bool showBar; +} FFFooOptions; + +static_assert(sizeof(FFFooOptions) <= FF_OPTION_MAX_SIZE, "FFFooOptions size exceeds maximum allowed size"); +``` + +`FFModuleArgs` must come first. It provides `key`, `format`, `outputColor`, `keyColor`, `keyIcon` and `keyWidth`; because it is the first field, `ffJsonConfigParseModuleArgs()` can handle these generically and you get them **for free — no parsing code to write**. + +Note these fields can only be set through the JSON config; CLI module options have been removed (see [Gotchas](#4-cli-module-options-are-removed)). + +### 2. Implement detection + +`src/detection/foo/foo.h`: + +```c +#pragma once +#include "fastfetch.h" + +typedef struct FFFooResult { + FFstrbuf name; + uint32_t count; +} FFFooResult; + +const char* ffDetectFoo(const FFFooOptions* options, FFFooResult* result); +``` + +`src/detection/foo/foo_linux.c`: + +```c +#include "foo.h" + +const char* ffDetectFoo(const FFFooOptions* options, FFFooResult* result) { + // read /sys, /proc, sysfs, dbus, ... + return nullptr; // success; return an error string on failure +} +``` + +**Write one file per target platform, and a `foo_nosupport.c` fallback for the rest.** There are already 45 `*_nosupport.c` files doing exactly this. + +### 3. Implement the module + +`src/modules/foo/foo.c` — implement the six functions, then define the descriptor: + +```c +FFModuleBaseInfo ffFooModuleInfo = { + .name = "Foo", + .description = "Print foo information", + .displayName = { + .en = "Foo", .ar = "Foo", .cs = "Foo", .de = "Foo", .es = "Foo", + .fr = "Foo", .gl = "Foo", .he = "Foo", .id = "Foo", .it = "Foo", + .ja = "Foo", .ko = "Foo", .pl = "Foo", .pt = "Foo", .ru = "Foo", + .tr = "Foo", .uk = "Foo", .vi = "Foo", .zh_CN = "Foo", .zh_TW = "Foo", + }, + .initOptions = (void*) ffInitFooOptions, + .destroyOptions = (void*) ffDestroyFooOptions, + .parseJsonObject = (void*) ffParseFooJsonObject, + .printModule = (void*) ffPrintFoo, + .generateJsonResult = (void*) ffGenerateFooJsonResult, + .generateJsonConfig = (void*) ffGenerateFooJsonConfig, + .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { + { "Name", "name" }, + { "Count", "count" }, + })), + .defaultOrder = 73, +}; +``` + +Points to note: + +- **`displayName`** is a literal block of all 20 language fields — there is no shortcut macro, so copy the layout from a neighboring module: **`en`, `ar`, `cs`, `de`, `es`, `fr`, `gl`, `he`, `id`, `it`, `ja`, `ko`, `pl`, `pt`, `ru`, `tr`, `uk`, `vi`, `zh_CN`, `zh_TW`**. + **Fill in all 20.** The struct is read by byte offset (see [Gotchas](#6-localization-uses-byte-offsets-not-enums)) and there is **no fallback** — a missing field means the key prints empty in that language. +- **`formatArgs`** must be exhaustive. It drives the placeholder list printed by `fastfetch -h foo-format`; **anything you omit is invisible and unusable to the user.** +- The `moduleFormat` section in `doc/json_schema.json` is generated by `fastfetch -h format-json`. Its metadata comes from `FFModuleBaseInfo::formatArgs`. To keep the schema and module descriptors consistent, do not edit the `moduleFormat` section in `doc/json_schema.json` by hand; update the module metadata and regenerate it instead. +- **`defaultOrder`**: use the current maximum plus 1. Search the existing descriptors for `.defaultOrder =` before choosing a value; do not copy a hard-coded value from this document. Leaving it out, or setting it to `0`, makes the module **disappear** from the interactive `--gen-config` picker. Only `logo`, `command` and `custom` do this deliberately, because they need user arguments or are invoked directly by the display layer. + +### 4. Register it + +- Add `#include "modules/foo/foo.h"` to `src/modules/modules.h` +- Insert into the `F[]` array in `src/modules/modules.c`: + +```c +#if !FF_MODULE_DISABLE_FOO + &ffFooModuleInfo, +#endif +``` + +`FF_MODULE_DISABLE_FOO` is generated by CMake — you do not define it yourself. + +### 5. Modules that need warm-up + +If your module needs a sampling interval (CPU usage) or a network round-trip (public IP, weather), also implement `ffPrepareFoo()` and register it in the switch inside `ffPrepareCommandOption()` in `common/impl/commandoption.c`, under the right first-letter `case`. Six modules do this today: CPUUsage, DiskIO, NetIO, PublicIP, Top and Weather. + +### 6. Verify + +```sh +cmake -B build && cmake --build build -j +./build/fastfetch -s foo --format json # JSON output +./build/fastfetch -h foo-format # list formatArgs placeholders +./build/fastfetch --gen-config # confirm it appears in the picker +``` + +Note the `-format` suffix on the help flag: `fastfetch -h foo` does not work, only `fastfetch -h foo-format`. + +--- + +## Walkthrough: adding a logo + +A new logo **must** have a corresponding "Logo Request" issue, linked from the PR with `Closes #1234`. Logo PRs without a linked issue are not accepted. + +### 1. Drop in the ASCII file + +``` +src/logo/ascii//.txt +``` + +For example `src/logo/ascii/o/omarchy.txt`. Directories are already split by first letter (`a/` … `z/`, plus `_/`). + +The file is plain ASCII art with `$1` … `$9` as color placeholders: + +``` + $3 ,-^-___ +$3 /\\\/// +$2refined.$1 /\\\\// +``` + +- `$1` … `$9` map to palette slots 1–9; at most 9 (`FASTFETCH_LOGO_MAX_COLORS = 9`) +- `$$` is a literal `$` +- Characters without a placeholder inherit the current color. Of the 530 existing logos, 239 use no placeholders at all (monochrome) and 291 do — **new logos should use placeholders**; monochrome is a legacy style +- Tabs are expanded to 4 spaces +- Colors can be overridden with `--logo-color-1` … `--logo-color-9` + +### 2. Register it in the `.inc` + +CMake turns each `.txt` into a `FASTFETCH_DATATEXT_LOGO_` macro (`CMakeLists.txt:418`), but **the registry itself is maintained by hand**. Edit `src/logo/ascii/.inc`: + +```c +#ifdef FASTFETCH_DATATEXT_LOGO_OMARCHY +// Omarchy +{ + .names = { "omarchy", "Omarchy" }, + .lines = FASTFETCH_DATATEXT_LOGO_OMARCHY, + .colors = { + FF_COLOR_FG_BLUE, + FF_COLOR_FG_WHITE, + FF_COLOR_FG_CYAN, + }, +}, +#endif +``` + +- `names` is matched case-insensitively. Do not add names that differ only by case, because they can never be distinguished. Every name is also shown by `--list-logos`, so use user-friendly spelling such as an initial capital where appropriate. +- For a new logo, use exactly one name unless there is a specific compatibility reason to add more. That name should first be the `ID` from `/etc/os-release`. If the ID cannot distinguish this logo from another logo for the same OS, use the `NAME` value instead. `logoGetBuiltinDetected` in `src/logo/logo.c` documents the detection order: `ID`, then `NAME`, then tokens from `ID_LIKE`, then the platform name fallback. Manual `logo-source` selection uses the name directly. +- `colors` is positional — entry 0 is `$1`, entry 1 is `$2`, and so on +- `colors[0]` also becomes the title color and `colors[1]` the key color, unless the user overrides them + +If the same OS has multiple logo variants, mark the variant explicitly with `.type`: + +```c +.type = FF_LOGO_LINE_TYPE_SMALL_BIT, +``` + +Use `FF_LOGO_LINE_TYPE_ALTER_BIT` for an alternate logo, `FF_LOGO_LINE_TYPE_SMALL_BIT` for a small logo, or combine the flags when both apply. This is also a lookup optimization: a logo marked `FF_LOGO_LINE_TYPE_SMALL_BIT` is considered only for `type = small`, while a logo marked `FF_LOGO_LINE_TYPE_ALTER_BIT` is never selected by automatic detection. Alternate logos are available only when explicitly requested through `--logo `. + +### 3. Verify + +```sh +./build/fastfetch --logo omarchy +./build/fastfetch --list-logos | grep -i omarchy +``` + +--- + +## Platform conventions + +The `detection/` layer picks its implementation by **filename suffix**; the choice is made at build time from `CMAKE_SYSTEM_NAME`: + +| Suffix | Platform | +|---|---| +| `_linux.c` | Linux | +| `_apple.c` / `_apple.m` | macOS / iOS (`.m` for Objective-C) | +| `_windows.c` / `_windows.cpp` | Windows (`.cpp` for WinRT / WMI) | +| `_bsd.c` | FreeBSD | +| `_nbsd.c` | NetBSD | +| `_obsd.c` | OpenBSD | +| `_sunos.c` | Solaris / illumos | +| `_haiku.c` / `.cpp` | Haiku | +| `_android.c` | Android (Termux) | +| `_gnu.c` | GNU/Hurd | +| `_nosupport.c` | Empty fallback | + +Current distribution of platform files in `detection/`: + +| Suffix | Files | Suffix | Files | +|---|---|---|---| +| `_linux` | 58 | `_obsd` | 16 | +| `_windows` | 47 | `_haiku` | 13 | +| `_apple` | 46 | `_android` | 12 | +| `_nosupport` | 45 | `_gnu` | 3 | +| `_bsd` | 29 | | | +| `_sunos` | 19 | | | +| `_nbsd` | 17 | | | + +(These are repository inventory figures, counting `.c`, `.m`, `.cpp`, and `.h`; they may change as platforms and modules are added.) + +**Don't pile `#ifdef __linux__` into one file.** When adding platform support, copy the closest existing implementation and change the suffix. + +`common/` uses the same idea: `common/impl/` contains `io_unix.c` / `io_windows.c`, `netif_linux.c` / `netif_apple.c` / `netif_bsd.c` and so on, with `common/apple/`, `common/windows/` and `common/haiku/` holding platform-specific helpers. + +When several platform suffixes could apply, use the most specific implementation supported by the build system (for example, `_nbsd.c` instead of the generic `_bsd.c` on NetBSD). Keep the generic file as the fallback for platforms that share its conventions. + +--- + +## Code style + +### Formatting + +The project uses clang-format with `BasedOnStyle: LLVM` plus these key overrides: + +```yaml +IndentWidth: 4 +UseTab: Never +ColumnLimit: 0 # never wrap +InsertBraces: true # braces even on single-statement ifs +PointerAlignment: Left # char* p, not char *p +SortIncludes: Never # include order is managed by hand +AlignAfterOpenBracket: DontAlign +BinPackParameters: false # all params on one line, or one per line +``` + +Before committing: + +```sh +clang-format -i src/modules/foo/*.c src/modules/foo/*.h +``` + +`src/3rdparty/**`, `build/**` and `src/logo/builtin.c` are listed in `.clang-format-ignore` — **do not reformat them.** + +`.editorconfig` adds LF line endings, 4-space indent, a final newline, and trailing whitespace trimmed (except in Markdown). + +### Naming + +| Kind | Convention | Example | +|---|---|---| +| Functions | `ff` + PascalCase | `ffDetectCPU`, `ffPrintCPU` | +| Types | `FF` + PascalCase | `FFCPUResult`, `FFModuleBaseInfo` | +| Variables / fields | camelCase | `coresPhysical`, `keyWidth` | +| Macros | SCREAMING_SNAKE_CASE | `FF_OPTION_MAX_SIZE` | +| Module options | `FFOptions` | `FFCPUOptions` | +| Detection results | `FFResult` | `FFCPUResult` | + +### Spelling + +CI runs codespell (`.codespellrc`). Known false positives live in `ignore-words-list` (`iterm`, `compiletime`, and various non-English distro words). Add new words there rather than changing the code. + +### Compiler warnings + +The build enables `-Wall -Wextra -Wconversion` plus several `-Werror`s: + +``` +-Werror=uninitialized -Werror=return-type -Werror=vla +-Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion +``` + +**`-Wconversion` is strict**: every implicit narrowing conversion needs an explicit cast. + +--- + +## Commit messages + +Format: + +``` +[ (Platform)]: +``` + +Scope is the module or subsystem name; Platform is optional. Use the third-person singular present tense, capitalize the first letter, no trailing period. + +Real examples from recent history: + +``` +Processes (Haiku): honors `options->countKprocs` +WM (macOS): improves reliability of WM plugin detection +Memory (Windows): prefers `NQSI` +Top (Linux): improves performance of `stat` parsing +Logo (Builtin): adds omarchy +Global: introduces global macro `FF_PATH_PKG_BASE` to replace `_PATH_LOCALBASE` +LM (OpenBSD): adds support +CI: disables fail on alert +Doc: updates README +Presets: moves `top` to the bottom of running modules [ci skip] +``` + +Common verbs: `adds`, `removes`, `fixes`, `improves`, `updates`, `corrects`, `prefers`, `honors`, `disables`, `enables`, `introduces`, `detects`, `reports`, `skips`, `uses`. + +Scopes in use: `Top`, `Processes`, `Memory`, `Logo (Builtin)`, `CI`, `Doc`, `Presets`, `Global`, plus individual module names. + +Documentation-only changes get a `[ci skip]` suffix. + +--- + +## Changelog + +User-visible changes go into `CHANGELOG.md`, under the topmost version heading: + +```markdown +# Unreleased + +Changes: +* The DE / WM / LM modules now reports the full name ... + +Features: +* Added Top module to print processes with the highest CPU, memory or disk I/O usage. (Top) +* Improved Wi-Fi module + * Added Wifi channel width detection, exposed via `{channel-width}` in custom format. + * Improved Wifi channel frequency accuracy on Windows, macOS. +* Added Battery detection support on SunOS. (Battery, SunOS) + +Bugfixes: +* Fixed I/O rate calculation precision in DiskIO and NetIO. (DiskIO / NetIO) +``` + +Rules: + +- Three sections: `Changes:` (behavior changes), `Features:`, `Bugfixes:` +- Past tense: `Added` / `Fixed` / `Improved` +- End each entry with its scope: `(Module, Platform)` or `(ModuleA / ModuleB)` +- Sub-bullets are indented 4 spaces + +--- + +## Tests + +Tests are standalone executables in `tests/` using a `VERIFY` macro that exits non-zero on failure: + +```c +#define VERIFY(expression) \ + if (!(expression)) testFailed(&strbuf, #expression, __LINE__) +``` + +Current tests: `strbuf.c`, `list.c`, `format.c`, `color.c`, `duration.c`, `strutil.c`. + +```sh +cmake -B build -DBUILD_TESTS=On +cmake --build build +cd build && ctest --output-on-failure +``` + +Coverage focuses on the core data structures and the formatting engine in `common/`. The `detection/` layer has no automated tests (it depends too heavily on a real system) and is instead covered by the CI matrix — 20 workflows under `.github/workflows/` spanning Linux (including musl, loong64, armv7l, i686), macOS, Windows, FreeBSD, NetBSD, OpenBSD, DragonFly, Solaris, OmniOS and Haiku, plus spellcheck and benchmark jobs. + +**If you touch `common/FFstrbuf.h`, `common/format.h` or `common/color.h`, please extend the matching test.** + +--- + +## Pull requests + +1. **Open an issue first** (feature request / bug report / logo request) so you don't waste effort. Templates are in `.github/ISSUE_TEMPLATE/`. +2. Branch off `dev` — **`dev` is the main development branch**, not `master`. +3. Follow the [commit message convention](#commit-messages). +4. Update `CHANGELOG.md` for user-visible changes. +5. Open the PR against `dev` and fill in `.github/pull_request_template.md`: + - Summary + - Related issue (**required for new logos**, otherwise the PR won't be accepted) + - Changes + - Screenshots (required for visual changes) + - Checklist: confirm you tested locally + +### Pre-submit checklist + +```sh +clang-format -i # format +codespell # spelling +cmake -B build -DBUILD_TESTS=On && cmake --build build -j +cd build && ctest --output-on-failure # tests +./build/fastfetch --format json # verify JSON output is well-formed +./build/fastfetch -c presets/all.jsonc --stat false # smoke-test every module +``` + +--- + +## Gotchas + +Things that are easy to get wrong when reading this codebase. Most of them follow from the "obsessively fast startup" goal. + +### 1. Option structs must not exceed 256 bytes + +`FF_OPTION_MAX_SIZE = 1 << 8`. Exceeding it is caught at compile time by `static_assert`. Don't try to raise the value — it determines the stack cost of every module invocation. + +### 2. `FF_MODULE_DISABLE_*` controls registration, not compilation + +```c +// verbatim from the top of modules/modules.c: +// FF_MODULE_DISABLE_ only controls if the module is registered, +// the module code itself is still compiled. +// We rely `LTO` to remove the unused code (only enabled in Release mode) +``` + +**Disabling modules in a Debug build does not shrink the binary.** LTO is enabled whenever `CMAKE_BUILD_TYPE != Debug`, and the default `RelWithDebInfo` already satisfies that — so measure size with `RelWithDebInfo` or `Release`, never with `Debug`. (The "Release mode" wording in the comment above is imprecise.) + +### 3. CMake globs don't trigger reconfiguration + +Both the module directories and the logo files are discovered by glob. CMake will not notice new files on its own — you need to re-run `cmake -B build` (or delete `build/CMakeCache.txt` and start over). This is the classic CMake footgun. + +### 4. CLI module options are removed + +Per-module command-line flags such as `--cpu-temp` are **no longer supported**. The only job of `ffParseModuleOptions` now is to translate the flag into a JSON key, then `exit(477)` with a pointer to the config file: + +``` +Error: Unsupported module option: --cpu-temp + Support of module options has been removed. Please add the flag to the JSON config instead. + Example (demonstration only): `{ "modules": [ { "type": "cpu", "temp": true } ] }` +``` + +**JSONC is the first-class configuration interface; the command line is not.** When adding module options, implement `parseJsonObject` only — do not add a CLI branch. + +### 5. `defaultOrder = 0` hides a module from `--gen-config` + +`collectModuleInfos` (`genconfig.c:186`) skips any module whose `defaultOrder` is `0`. C zero-initializes the field, so **omitting it is the same as setting it to 0**. Only `logo`, `command` and `custom` do this on purpose. + +`defaultOrder` affects only the ordering in the interactive `--gen-config` picker; it has no effect on runtime output order. + +### 6. Localization uses byte offsets, not enums + +`instance.config.display.keyLanguage` does not hold a language enum — it holds a **byte offset** such as `offsetof(FFModuleDisplayName, zh_CN)`. The macro `FF_MODULE_GET_DISPLAY_NAME` (`common/option.h:123`) does plain pointer arithmetic with it: + +```c +#define FF_MODULE_GET_DISPLAY_NAME(moduleName) \ + (*(const char**) ((uint8_t*) &ff ## moduleName ## ModuleInfo.displayName + instance.config.display.keyLanguage)) +``` + +Consequence: **the field order of `FFModuleDisplayName` must never change** — reordering silently scrambles every language. + +### 7. The `multithreading` switch barely does anything + +The global `multithreading` option currently takes effect in exactly one place: `common/impl/networking_linux.c:339`. Modules are still printed sequentially. Modules that need concurrency go through the `ffPrepare*` warm-up hooks instead, which start sampling or fire off requests before the print loop begins. + +### 8. Don't print or read config inside `detection/` + +The `detection/` layer must stay pure: read system state, fill a struct, return an error string. Any `printf` or any read of `instance.config` there is a design error. + +### 9. `src/logo/builtin.c` and `3rdparty/` are formatting-exempt + +The former is a large generated/hand-maintained data table, the latter is upstream code. Both are excluded via `.clang-format-ignore` — leave them alone. + +--- + +## Reference + +- Configuration guide: +- JSON schema: `doc/json_schema.json` +- Example presets: `presets/` (`all.jsonc`, `neofetch.jsonc`, `ci.jsonc`, …) +- Man page source: `doc/fastfetch.1.in` +- Code generation scripts: `scripts/` (`gen-pciids.py`, `gen-amdgpuids.py`, `gen-man.py`) From b9e4d04d6578acdcb31c64aeecbd26e265769a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 19:08:33 +0800 Subject: [PATCH 100/109] Global: addresses review comments generated by CI --- CHANGELOG.md | 2 +- CMakeLists.txt | 2 +- doc/json_schema.json | 4 ++-- src/common/impl/FFPlatform_unix.c | 2 ++ src/detection/processes/processes_gnu.c | 3 +-- src/detection/processes/processes_nosupport.c | 2 +- src/detection/terminalfont/terminalfont_android.c | 3 ++- src/detection/top/top_gnu.c | 3 +++ src/modules/diskio/diskio.c | 3 +++ src/modules/netio/netio.c | 3 +++ src/modules/top/top.c | 6 +++--- 11 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a18be3800f..6e90211313 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# Unreleased +# 2.68.0 Changes: * The DE / WM / LM modules now reports the full name "Desktop Environment" / "Window Manager" / "Login Manager" instead of the abbreviations. diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d526dbb78..995c2049d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.21.0) # C_STANDARD project(fastfetch - VERSION 2.67.1 + VERSION 2.68.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" diff --git a/doc/json_schema.json b/doc/json_schema.json index b2f07370dd..1ec527f38a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -322,7 +322,7 @@ "type": "string" }, "cpuFormat": { - "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count", + "description": "Output format for the `CPU` module. See Wiki for formatting syntax\n 1. {name}: Name\n 2. {vendor}: Vendor\n 3. {cores-physical}: Physical core count\n 4. {cores-logical}: Logical core count\n 5. {cores-online}: Online core count\n 6. {freq-base}: Base frequency (formatted)\n 7. {freq-max}: Max frequency (formatted)\n 8. {temperature}: Temperature (formatted)\n 9. {core-types}: Logical core count grouped by frequency\n 10. {packages}: Processor package count\n 11. {march}: CPU microarchitecture\n 12. {numa-nodes}: NUMA node count\n 13. {code-name}: CPU code name\n 14. {technology}: CPU technology", "type": "string" }, "cpucacheFormat": { @@ -506,7 +506,7 @@ "type": "string" }, "topFormat": { - "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {path}: Executable path\n 3. {pid}: Process ID\n 4. {cpu}: CPU usage\n 5. {mem}: Memory usage (RSS) in bytes\n 6. {disk-read}: Disk read bytes per second (0 if unsupported)\n 7. {disk-write}: Disk write bytes per second (0 if unsupported)\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {pid}: Process ID\n 3. {cpu}: CPU usage\n 4. {mem}: Memory usage (RSS) in bytes\n 5. {disk-read}: Disk read bytes per second (0 if unsupported)\n 6. {disk-write}: Disk write bytes per second (0 if unsupported)\n 7. {cpu-percentage}: CPU usage percentage\n 8. {mem-formatted}: Memory usage (RSS) formatted\n 9. {disk-read-formatted}: Disk read formatted\n 10. {disk-write-formatted}: Disk write formatted", "type": "string" }, "themeFormat": { diff --git a/src/common/impl/FFPlatform_unix.c b/src/common/impl/FFPlatform_unix.c index e3ea77f51e..92f0e86349 100644 --- a/src/common/impl/FFPlatform_unix.c +++ b/src/common/impl/FFPlatform_unix.c @@ -238,7 +238,9 @@ static void getDataDirs(FFPlatform* platform) { ffPlatformPathAddHome(&platform->dataDirs, platform, ""); platformPathAddEnv(&platform->dataDirs, "XDG_DATA_DIRS"); +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) ffPlatformPathAddAbsolute(&platform->dataDirs, FF_PATH_PKG_BASE "/share/"); +#endif ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/local/share/"); ffPlatformPathAddAbsolute(&platform->dataDirs, FASTFETCH_TARGET_DIR_USR "/share/"); } diff --git a/src/detection/processes/processes_gnu.c b/src/detection/processes/processes_gnu.c index ba4351f5e1..53c9781c65 100644 --- a/src/detection/processes/processes_gnu.c +++ b/src/detection/processes/processes_gnu.c @@ -29,13 +29,12 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu continue; } + ++result->processes; if (proc_stat_has(stat, PSTAT_NUM_THREADS)) { result->threads += proc_stat_num_threads(stat); } } - result->processes = (uint32_t) list->num_procs; - done: if (list) { proc_stat_list_free(list); diff --git a/src/detection/processes/processes_nosupport.c b/src/detection/processes/processes_nosupport.c index e7218a5c26..04a5eafd83 100644 --- a/src/detection/processes/processes_nosupport.c +++ b/src/detection/processes/processes_nosupport.c @@ -1,5 +1,5 @@ #include "processes.h" -const char* ffDetectProcesses([[maybe_unused]] FFProcessesResult* result) { +const char* ffDetectProcesses([[maybe_unused]] const FFProcessesOptions* options, [[maybe_unused]] FFProcessesResult* result) { return "Not supported on this platform"; } diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index 7ef0f52506..494dcee1f7 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -16,7 +16,8 @@ const char* detectTermux(FFTerminalFontResult* terminalFont) { FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); // SharedPreferences XML: 14, in px - if (ffParsePropFile(FF_TERMUX_PREF_PATH, "", &fontSize)) { + ffParsePropFile(FF_TERMUX_PREF_PATH, "", &fontSize); + if (fontSize.length > 0) { ffStrbufAppendS(&fontSize, "px"); } diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 0407124fbe..37845a640e 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -57,6 +57,9 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { } item->pid = pid; + item->cpuTime = 0; + item->memBytes = 0; + item->startTime = 0; if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 71f6970d8c..61ed83001c 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -111,6 +111,9 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "waitTime")) { options->waitTime = (uint32_t) yyjson_get_uint(val); + if (options->waitTime == 0) { + options->waitTime = 1; + } continue; } diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index 0729b444e7..0ffe4f1d32 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -126,6 +126,9 @@ void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module) { if (unsafe_yyjson_equals_str(key, "waitTime")) { options->waitTime = (uint32_t) yyjson_get_uint(val); + if (options->waitTime == 0) { + options->waitTime = 1; + } continue; } diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 60b5a614ee..7087e38ed5 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -43,7 +43,7 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total FF_STRBUF_AUTO_DESTROY diskWriteFormatted = ffStrbufCreate(); ffSizeAppendNum(process->bytesWritten, &diskWriteFormatted); ffStrbufAppendS(&diskWriteFormatted, "/s"); - FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), (uint8_t) index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ + FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ FF_ARG(process->name, "name"), FF_ARG(process->pid, "pid"), FF_ARG(process->cpuPercent, "cpu"), @@ -73,11 +73,12 @@ bool ffPrintTop(FFTopOptions* options) { } else { ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_LIST_FOR_EACH (FFTopProcessResult, process, results) { - ffStrbufWriteTo(&process->name, stdout); if ((void*) process != results.data) { putchar(' '); } + ffStrbufWriteTo(&process->name, stdout); } + putchar('\n'); } FF_LIST_FOR_EACH (FFTopProcessResult, item, results) { @@ -271,7 +272,6 @@ FFModuleBaseInfo ffTopModuleInfo = { .generateJsonConfig = (void*) ffGenerateTopJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]){ { "Process name", "name" }, - { "Executable path", "path" }, { "Process ID", "pid" }, { "CPU usage", "cpu" }, { "Memory usage (RSS) in bytes", "mem" }, From 6eef800ea299a51aaebb9fbd8dc17e28c451ec5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 19:47:14 +0800 Subject: [PATCH 101/109] Top: supports sorting by `start-time` --- doc/json_schema.json | 7 ++++--- src/detection/top/top.c | 7 +++++++ src/modules/top/option.h | 1 + src/modules/top/top.c | 3 +++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 1ec527f38a..3d43ca94e0 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -4441,16 +4441,17 @@ "properties": { "type": { "const": "top", - "description": "Print processes with the highest CPU or memory usage" + "description": "Print processes with the highest CPU, memory, disk I/O usage or latest start time" }, "sort": { "type": "string", - "description": "Sort processes by CPU, memory or disk IO usage", + "description": "Sort processes by CPU, memory, disk IO usage or start time", "enum": [ "cpu", "memory", "disk-read", - "disk-write" + "disk-write", + "start-time" ], "default": "cpu" }, diff --git a/src/detection/top/top.c b/src/detection/top/top.c index 5c1b8b645e..26b5b76db2 100644 --- a/src/detection/top/top.c +++ b/src/detection/top/top.c @@ -53,6 +53,12 @@ static int compareDiskWriteResults(const FFTopProcessResult* a, const FFTopProce if (a->bytesWritten > b->bytesWritten) return -1; return (int) (a->pid - b->pid); } + +static int compareStartTimeResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->startTime < b->startTime) return 1; + if (a->startTime > b->startTime) return -1; + return (int) (a->pid - b->pid); +} // clang-format on const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { @@ -147,6 +153,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { const void* compare = options->sort == FF_TOP_TYPE_DISK_WRITE ? (void*) compareDiskWriteResults : options->sort == FF_TOP_TYPE_DISK_READ ? (void*) compareDiskReadResults : options->sort == FF_TOP_TYPE_MEMORY ? (void*) compareMemoryResults + : options->sort == FF_TOP_TYPE_START_TIME ? (void*) compareStartTimeResults : (void*) compareCpuResults; ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); if (result->length > options->nProcesses) { diff --git a/src/modules/top/option.h b/src/modules/top/option.h index 82a1382731..0422d3a8a6 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -8,6 +8,7 @@ typedef enum FFTopTypes: uint8_t { FF_TOP_TYPE_MEMORY = 1 << 1, FF_TOP_TYPE_DISK_READ = 1 << 2, FF_TOP_TYPE_DISK_WRITE = 1 << 3, + FF_TOP_TYPE_START_TIME = 1 << 4, FF_TOP_TYPE_DISK = FF_TOP_TYPE_DISK_READ | FF_TOP_TYPE_DISK_WRITE, } FFTopTypes; diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 7087e38ed5..cc39c9977c 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -101,6 +101,7 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { { "memory", FF_TOP_TYPE_MEMORY }, { "disk-read", FF_TOP_TYPE_DISK_READ }, { "disk-write", FF_TOP_TYPE_DISK_WRITE }, + { "start-time", FF_TOP_TYPE_START_TIME }, {}, }); if (error) { @@ -183,6 +184,8 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_str(doc, module, "sort", "disk-read"); } else if (options->sort == FF_TOP_TYPE_DISK_WRITE) { yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); + } else if (options->sort == FF_TOP_TYPE_START_TIME) { + yyjson_mut_obj_add_str(doc, module, "sort", "start-time"); } yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); From 4ff931c06fe44a950830d9ec20e75d2e86e17548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 20:27:22 +0800 Subject: [PATCH 102/109] Top: adds thread count detection --- doc/json_schema.json | 17 +++++++------ src/detection/top/top.c | 13 ++++++++-- src/detection/top/top.h | 2 ++ src/detection/top/top_apple.c | 9 ++++++- src/detection/top/top_bsd.c | 3 ++- src/detection/top/top_dbsd.c | 3 ++- src/detection/top/top_gnu.c | 11 +++++++-- src/detection/top/top_haiku.c | 3 ++- src/detection/top/top_linux.c | 10 ++++++-- src/detection/top/top_nbsd.c | 10 +++++++- src/detection/top/top_obsd.c | 19 ++++++++++++++- src/detection/top/top_sunos.c | 1 + src/detection/top/top_windows.c | 1 + src/modules/top/option.h | 1 + src/modules/top/top.c | 43 ++++++++++++++++++++++----------- 15 files changed, 113 insertions(+), 33 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 3d43ca94e0..0aeba6de29 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -506,7 +506,7 @@ "type": "string" }, "topFormat": { - "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {pid}: Process ID\n 3. {cpu}: CPU usage\n 4. {mem}: Memory usage (RSS) in bytes\n 5. {disk-read}: Disk read bytes per second (0 if unsupported)\n 6. {disk-write}: Disk write bytes per second (0 if unsupported)\n 7. {cpu-percentage}: CPU usage percentage\n 8. {mem-formatted}: Memory usage (RSS) formatted\n 9. {disk-read-formatted}: Disk read formatted\n 10. {disk-write-formatted}: Disk write formatted", + "description": "Output format for the `Top` module. See Wiki for formatting syntax\n 1. {name}: Process name\n 2. {pid}: Process ID\n 3. {cpu}: CPU usage\n 4. {mem}: Memory usage (RSS) in bytes\n 5. {disk-read}: Disk read bytes per second (0 if unsupported)\n 6. {disk-write}: Disk write bytes per second (0 if unsupported)\n 7. {threads}: Number of threads\n 8. {cpu-percentage}: CPU usage percentage\n 9. {mem-formatted}: Memory usage (RSS) formatted\n 10. {disk-read-formatted}: Disk read formatted\n 11. {disk-write-formatted}: Disk write formatted", "type": "string" }, "themeFormat": { @@ -4441,22 +4441,23 @@ "properties": { "type": { "const": "top", - "description": "Print processes with the highest CPU, memory, disk I/O usage or latest start time" + "description": "Print processes with the highest CPU, memory, disk I/O usage, latest start time or thread count" }, "sort": { "type": "string", - "description": "Sort processes by CPU, memory, disk IO usage or start time", + "description": "Sort processes by CPU, memory, disk IO usage, start time or thread count", "enum": [ "cpu", "memory", "disk-read", "disk-write", - "start-time" + "start-time", + "threads" ], "default": "cpu" }, "showTypes": { - "description": "Specify which resource usages are detected and displayed.\nIf memory is enabled is enabled alone, only a single process snapshot is taken and `waitTime` sampling wait is skipped", + "description": "Specify which resource usages are detected and displayed.\nIf memory or threads is enabled is enabled alone, only a single process snapshot is taken and `waitTime` sampling wait is skipped", "default": [ "cpu", "memory", @@ -4468,7 +4469,8 @@ "enum": [ "cpu", "memory", - "disk" + "disk", + "threads" ] }, { @@ -4479,7 +4481,8 @@ "enum": [ "cpu", "memory", - "disk" + "disk", + "threads" ] } } diff --git a/src/detection/top/top.c b/src/detection/top/top.c index 26b5b76db2..dd4442a7ee 100644 --- a/src/detection/top/top.c +++ b/src/detection/top/top.c @@ -59,6 +59,12 @@ static int compareStartTimeResults(const FFTopProcessResult* a, const FFTopProce if (a->startTime > b->startTime) return -1; return (int) (a->pid - b->pid); } + +static int compareThreadsResults(const FFTopProcessResult* a, const FFTopProcessResult* b) { + if (a->threads < b->threads) return 1; + if (a->threads > b->threads) return -1; + return (int) (a->pid - b->pid); +} // clang-format on const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { @@ -67,8 +73,8 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { return nullptr; } - // Memory usage is instantaneous; when neither CPU time nor disk IO counters - // are requested, a single snapshot suffices and no sampling wait is needed. + // Memory usage and thread count are instantaneous; when neither CPU time nor disk IO + // counters are requested, a single snapshot suffices and no sampling wait is needed. const bool sampleOnce = (options->showTypes & (FF_TOP_TYPE_CPU | FF_TOP_TYPE_DISK)) == 0; if (sampleOnce) { @@ -92,6 +98,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { item->bytesWritten = 0; item->cpuPercent = 0; item->startTime = snap->startTime; + item->threads = snap->threads; ffStrbufInitMove(&item->name, &snap->name); } } else { @@ -141,6 +148,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { item->bytesWritten = (newItem->bytesWritten - oldItem->bytesWritten) * 1000u / (uint64_t) elapsed; item->cpuPercent = (double) (newItem->cpuTime - oldItem->cpuTime) / elapsed * 100.0; item->startTime = newItem->startTime; + item->threads = newItem->threads; ffStrbufInitMove(&item->name, &oldItem->name); } @@ -154,6 +162,7 @@ const char* ffDetectTopProcesses(FFTopOptions* options, FFlist* result) { : options->sort == FF_TOP_TYPE_DISK_READ ? (void*) compareDiskReadResults : options->sort == FF_TOP_TYPE_MEMORY ? (void*) compareMemoryResults : options->sort == FF_TOP_TYPE_START_TIME ? (void*) compareStartTimeResults + : options->sort == FF_TOP_TYPE_THREADS ? (void*) compareThreadsResults : (void*) compareCpuResults; ffListSort(result, sizeof(FFTopProcessResult), (void*) compare); if (result->length > options->nProcesses) { diff --git a/src/detection/top/top.h b/src/detection/top/top.h index de1289b4ae..26f05d549b 100644 --- a/src/detection/top/top.h +++ b/src/detection/top/top.h @@ -10,6 +10,7 @@ typedef struct FFTopProcessResult { uint64_t bytesRead; uint64_t bytesWritten; uint64_t startTime; + uint32_t threads; uint32_t pid; } FFTopProcessResult; @@ -20,6 +21,7 @@ typedef struct FFTopProcessSnapshot { uint64_t bytesRead; // Physical storage read uint64_t bytesWritten; // Physical storage written uint64_t startTime; // Differs between platforms + uint32_t threads; uint32_t pid; } FFTopProcessSnapshot; diff --git a/src/detection/top/top_apple.c b/src/detection/top/top_apple.c index 8624313818..6a1692b0e8 100644 --- a/src/detection/top/top_apple.c +++ b/src/detection/top/top_apple.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; @@ -54,6 +54,13 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = rusage.ri_diskio_bytesread; item->bytesWritten = rusage.ri_diskio_byteswritten; item->startTime = rusage.ri_proc_start_abstime; + item->threads = 0; + if (showTypes & FF_TOP_TYPE_THREADS) { + struct proc_taskinfo taskInfo; + if (proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) == sizeof(taskInfo)) { + item->threads = (uint32_t) taskInfo.pti_threadnum; + } + } } return nullptr; diff --git a/src/detection/top/top_bsd.c b/src/detection/top/top_bsd.c index 6c0f620189..108e5e97e4 100644 --- a/src/detection/top/top_bsd.c +++ b/src/detection/top/top_bsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC }; size_t length; @@ -51,6 +51,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = (uint64_t) proc->ki_rusage.ru_inblock * DEV_BSIZE; item->bytesWritten = (uint64_t) proc->ki_rusage.ru_oublock * DEV_BSIZE; + item->threads = (uint32_t) proc->ki_numthreads; } return NULL; diff --git a/src/detection/top/top_dbsd.c b/src/detection/top/top_dbsd.c index 56a572e65b..9896b6f54e 100644 --- a/src/detection/top/top_dbsd.c +++ b/src/detection/top/top_dbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; size_t length; @@ -52,6 +52,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = (uint64_t) (proc->kp_ru.ru_inblock + proc->kp_lwp.kl_ru.ru_inblock) * DEV_BSIZE; item->bytesWritten = (uint64_t) (proc->kp_ru.ru_oublock + proc->kp_lwp.kl_ru.ru_oublock) * DEV_BSIZE; + item->threads = (uint32_t) proc->kp_nthreads; } return nullptr; diff --git a/src/detection/top/top_gnu.c b/src/detection/top/top_gnu.c index 37845a640e..9f93422162 100644 --- a/src/detection/top/top_gnu.c +++ b/src/detection/top/top_gnu.c @@ -4,7 +4,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { struct ps_context* context = nullptr; if (ps_context_create(getproc(), &context) != 0) { return "ps_context_create(getproc()) failed"; @@ -24,7 +24,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { // Flags that cannot be fetched for some process are simply left unset; // each field must be checked before use. - if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC) != 0) { + if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC | ((showTypes & FF_TOP_TYPE_THREADS) ? PSTAT_NUM_THREADS : 0)) != 0) { error = "proc_stat_list_set_flags() failed"; goto done; } @@ -60,6 +60,13 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->cpuTime = 0; item->memBytes = 0; item->startTime = 0; + item->threads = 0; + + if (showTypes & FF_TOP_TYPE_THREADS) { + if (proc_stat_has(stat, PSTAT_NUM_THREADS)) { + item->threads = (uint32_t) proc_stat_num_threads(stat); + } + } if (proc_stat_has(stat, PSTAT_TASK_BASIC)) { const task_basic_info_t info = proc_stat_task_basic_info(stat); diff --git a/src/detection/top/top_haiku.c b/src/detection/top/top_haiku.c index 78310737a7..32f73d686b 100644 --- a/src/detection/top/top_haiku.c +++ b/src/detection/top/top_haiku.c @@ -3,7 +3,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int32 cookie = 0; team_info team; while (get_next_team_info(&cookie, &team) == B_OK) { @@ -41,6 +41,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { // Storage io counters are not exposed by Haiku; leave them zeroed. item->bytesRead = 0; item->bytesWritten = 0; + item->threads = (uint32_t) team.thread_count; } return nullptr; diff --git a/src/detection/top/top_linux.c b/src/detection/top/top_linux.c index 2436e3ce78..be71ab5a8f 100644 --- a/src/detection/top/top_linux.c +++ b/src/detection/top/top_linux.c @@ -24,8 +24,6 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r return false; } - result->cpuTime = 0; - char* p; for (uint32_t field = 3; field <= 22 /*start time*/; ++field) { switch (field) { @@ -43,6 +41,11 @@ static bool parseStat(const char* buffer, size_t length, FFTopProcessSnapshot* r cursor = p; break; + case 20: // number of threads + result->threads = (uint32_t) strtoul(cursor, &p, 10); + cursor = p; + break; + case 22: // start time result->startTime = (uint64_t) strtoull(cursor, &p, 10); cursor = p; @@ -128,6 +131,9 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { auto snapshot = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); ffStrbufInit(&snapshot->name); + snapshot->threads = 0; + snapshot->cpuTime = 0; + snapshot->startTime = 0; if (!parseStat(statBuffer, (size_t) statLength, snapshot)) { ffStrbufDestroy(&snapshot->name); diff --git a/src/detection/top/top_nbsd.c b/src/detection/top/top_nbsd.c index 1bc8e6543f..8c9c4968de 100644 --- a/src/detection/top/top_nbsd.c +++ b/src/detection/top/top_nbsd.c @@ -6,7 +6,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX }; size_t length; @@ -50,6 +50,14 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + item->threads = 0; + if (showTypes & FF_TOP_TYPE_THREADS) { + int lwpRequest[] = { CTL_KERN, KERN_LWP, proc->p_pid, sizeof(struct kinfo_lwp), 0 }; + size_t lwpLength = 0; + if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) { + item->threads = (uint32_t) (lwpLength / sizeof(struct kinfo_lwp)); + } + } } return NULL; diff --git a/src/detection/top/top_obsd.c b/src/detection/top/top_obsd.c index f7519bd00c..365ecfe7f3 100644 --- a/src/detection/top/top_obsd.c +++ b/src/detection/top/top_obsd.c @@ -5,7 +5,7 @@ #include #include -const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { +const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); if (!kd) { return "kvm_open() failed"; @@ -37,6 +37,23 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->startTime = (uint64_t) proc->p_ustart_sec * 1000 + (uint64_t) proc->p_ustart_usec / 1000; item->bytesRead = (uint64_t) proc->p_uru_inblock * DEV_BSIZE; item->bytesWritten = (uint64_t) proc->p_uru_oublock * DEV_BSIZE; + item->threads = 0; + } + + if (showTypes & FF_TOP_TYPE_THREADS) { + int threadCount = 0; + const struct kinfo_proc* threads = kvm_getprocs(kd, + KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), &threadCount); + if (threads) { + for (uint32_t i = 0; i < snapshots->length; ++i) { + FFTopProcessSnapshot* item = FF_LIST_GET(FFTopProcessSnapshot, *snapshots, i); + for (int j = 0; j < threadCount; ++j) { + if (threads[j].p_pid == (pid_t) item->pid && threads[j].p_tid != -1) { + ++item->threads; + } + } + } + } } kvm_close(kd); diff --git a/src/detection/top/top_sunos.c b/src/detection/top/top_sunos.c index 7dc9c880ca..0054ae79a8 100644 --- a/src/detection/top/top_sunos.c +++ b/src/detection/top/top_sunos.c @@ -60,6 +60,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { item->bytesRead = 0; item->bytesWritten = 0; + item->threads = (uint32_t) psinfo.pr_nlwp; if (showTypes & FF_TOP_TYPE_DISK) { prusage_t usage; if (ffReadFileDataRelative(subfd, "usage", sizeof(usage), &usage) == (ssize_t) sizeof(usage)) { diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index 6040964039..2f1e5d66d1 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -38,6 +38,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { item->memBytes = (uint64_t) info->VirtualMemoryCounters.WorkingSetSize; item->bytesRead = (uint64_t) info->IoCounters.ReadTransferCount; item->bytesWritten = (uint64_t) info->IoCounters.WriteTransferCount; + item->threads = info->NumberOfThreads; ffStrbufInitNWS(&item->name, info->ImageName.Length / sizeof(wchar_t), info->ImageName.Buffer); } if (info->NextEntryOffset == 0) { diff --git a/src/modules/top/option.h b/src/modules/top/option.h index 0422d3a8a6..0c3ff406d1 100644 --- a/src/modules/top/option.h +++ b/src/modules/top/option.h @@ -9,6 +9,7 @@ typedef enum FFTopTypes: uint8_t { FF_TOP_TYPE_DISK_READ = 1 << 2, FF_TOP_TYPE_DISK_WRITE = 1 << 3, FF_TOP_TYPE_START_TIME = 1 << 4, + FF_TOP_TYPE_THREADS = 1 << 5, FF_TOP_TYPE_DISK = FF_TOP_TYPE_DISK_READ | FF_TOP_TYPE_DISK_WRITE, } FFTopTypes; diff --git a/src/modules/top/top.c b/src/modules/top/top.c index cc39c9977c..8ba755a835 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -28,6 +28,9 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffSizeAppendNum(process->bytesWritten, &output); ffStrbufAppendS(&output, "/s"); } + if (options->showTypes & FF_TOP_TYPE_THREADS) { + ffStrbufAppendF(&output, " - THR %u", process->threads); + } } ffStrbufPutTo(&output, stdout); } else { @@ -44,17 +47,18 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffSizeAppendNum(process->bytesWritten, &diskWriteFormatted); ffStrbufAppendS(&diskWriteFormatted, "/s"); FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ - FF_ARG(process->name, "name"), - FF_ARG(process->pid, "pid"), - FF_ARG(process->cpuPercent, "cpu"), - FF_ARG(process->memBytes, "mem"), - FF_ARG(process->bytesRead, "disk-read"), - FF_ARG(process->bytesWritten, "disk-write"), - FF_ARG(cpuFormatted, "cpu-percentage"), - FF_ARG(memFormatted, "mem-formatted"), - FF_ARG(diskReadFormatted, "disk-read-formatted"), - FF_ARG(diskWriteFormatted, "disk-write-formatted"), - })); + FF_ARG(process->name, "name"), + FF_ARG(process->pid, "pid"), + FF_ARG(process->cpuPercent, "cpu"), + FF_ARG(process->memBytes, "mem"), + FF_ARG(process->bytesRead, "disk-read"), + FF_ARG(process->bytesWritten, "disk-write"), + FF_ARG(process->threads, "threads"), + FF_ARG(cpuFormatted, "cpu-percentage"), + FF_ARG(memFormatted, "mem-formatted"), + FF_ARG(diskReadFormatted, "disk-read-formatted"), + FF_ARG(diskWriteFormatted, "disk-write-formatted"), + })); } } @@ -121,6 +125,7 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { { "cpu", FF_TOP_TYPE_CPU }, { "memory", FF_TOP_TYPE_MEMORY }, { "disk", FF_TOP_TYPE_DISK }, + { "threads", FF_TOP_TYPE_THREADS }, {}, }); if (error == nullptr) { @@ -138,6 +143,7 @@ void ffParseTopJsonObject(FFTopOptions* options, yyjson_val* module) { { "cpu", FF_TOP_TYPE_CPU }, { "memory", FF_TOP_TYPE_MEMORY }, { "disk", FF_TOP_TYPE_DISK }, + { "threads", FF_TOP_TYPE_THREADS }, {}, }); if (error == nullptr) { @@ -175,6 +181,9 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ if (options->showTypes & FF_TOP_TYPE_DISK) { yyjson_mut_arr_add_str(doc, showTypes, "disk"); } + if (options->showTypes & FF_TOP_TYPE_THREADS) { + yyjson_mut_arr_add_str(doc, showTypes, "threads"); + } yyjson_mut_obj_add_val(doc, module, "showTypes", showTypes); if (options->sort == FF_TOP_TYPE_CPU) { yyjson_mut_obj_add_str(doc, module, "sort", "cpu"); @@ -186,6 +195,8 @@ void ffGenerateTopJsonConfig(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_str(doc, module, "sort", "disk-write"); } else if (options->sort == FF_TOP_TYPE_START_TIME) { yyjson_mut_obj_add_str(doc, module, "sort", "start-time"); + } else if (options->sort == FF_TOP_TYPE_THREADS) { + yyjson_mut_obj_add_str(doc, module, "sort", "threads"); } yyjson_mut_obj_add_uint(doc, module, "processes", options->nProcesses); yyjson_mut_obj_add_uint(doc, module, "waitTime", options->waitTime); @@ -215,6 +226,9 @@ bool ffGenerateTopJsonResult(FFTopOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_uint(doc, item, "bytesRead", process->bytesRead); yyjson_mut_obj_add_uint(doc, item, "bytesWritten", process->bytesWritten); } + if (options->showTypes & FF_TOP_TYPE_THREADS) { + yyjson_mut_obj_add_uint(doc, item, "threads", process->threads); + } yyjson_mut_obj_add_uint(doc, item, "startTime", process->startTime); } @@ -228,10 +242,10 @@ void ffInitTopOptions(FFTopOptions* options) { ffOptionInitModuleArg(&options->moduleArgs, "󰍛"); options->sort = FF_TOP_TYPE_CPU; options->showTypes = FF_TOP_TYPE_CPU | FF_TOP_TYPE_MEMORY - #if !__GNU__ && !__HAIKU__ +#if !__GNU__ && !__HAIKU__ | FF_TOP_TYPE_DISK - #endif - ; +#endif + ; options->nProcesses = 5; options->waitTime = 500; options->compact = false; @@ -280,6 +294,7 @@ FFModuleBaseInfo ffTopModuleInfo = { { "Memory usage (RSS) in bytes", "mem" }, { "Disk read bytes per second (0 if unsupported)", "disk-read" }, { "Disk write bytes per second (0 if unsupported)", "disk-write" }, + { "Number of threads", "threads" }, { "CPU usage percentage", "cpu-percentage" }, { "Memory usage (RSS) formatted", "mem-formatted" }, { "Disk read formatted", "disk-read-formatted" }, From b5ffc32b804a91a9f2a1f31a44ebfbd2903b9f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 20:29:06 +0800 Subject: [PATCH 103/109] Top / Processes (Windows): improves detection of system / kernel processes detection --- src/detection/processes/processes_windows.c | 2 +- src/detection/top/top_windows.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index 7ccd13149d..af09f6a910 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -26,7 +26,7 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu } for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - if (!options->countKprocs && ptr->CreateTime.QuadPart == 0) { + if (!options->countKprocs && (uintptr_t) ptr->InheritedFromUniqueProcessId > 0) { continue; } ++result->processes; diff --git a/src/detection/top/top_windows.c b/src/detection/top/top_windows.c index 2f1e5d66d1..33a430af73 100644 --- a/src/detection/top/top_windows.c +++ b/src/detection/top/top_windows.c @@ -30,7 +30,7 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes) { for (SYSTEM_PROCESS_INFORMATION* info = pstart;; info = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) info + info->NextEntryOffset)) { uintptr_t pidValue = (uintptr_t) info->UniqueProcessId; - if (pidValue <= UINT32_MAX && info->CreateTime.QuadPart > 0) { + if (pidValue <= UINT32_MAX && (uintptr_t) info->InheritedFromUniqueProcessId > 0) { FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots); item->pid = (uint32_t) pidValue; item->startTime = (uint64_t) info->CreateTime.QuadPart; From 43d01f26ea31485821075ba49932a1d649eb063b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 20:32:29 +0800 Subject: [PATCH 104/109] Top: handle unknown process names gracefully in output --- src/modules/top/top.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/top/top.c b/src/modules/top/top.c index 8ba755a835..9edbc394d8 100644 --- a/src/modules/top/top.c +++ b/src/modules/top/top.c @@ -11,7 +11,12 @@ static void printTopResult(FFTopOptions* options, uint32_t index, uint32_t total ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Top), total == 1 ? 0 : (uint8_t) (index + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY output = ffStrbufCreate(); - ffStrbufAppendF(&output, "%s (%u)", process->name.chars, process->pid); + if (process->name.length == 0) { + ffStrbufAppendS(&output, ""); + } else { + ffStrbufAppend(&output, &process->name); + } + ffStrbufAppendF(&output, " (%u)", process->pid); if ((options->showTypes & FF_TOP_TYPE_CPU) && (percentType & FF_PERCENTAGE_TYPE_NUM_BIT)) { ffStrbufAppendS(&output, " - CPU "); ffPercentAppendNum(&output, process->cpuPercent, options->percent, false, &options->moduleArgs); From b0ba084b5ef80c7ca87f6a60185295caec2d7514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 31 Aug 2026 21:53:32 +0800 Subject: [PATCH 105/109] Global: address review comments v2 --- src/detection/processes/processes_obsd.c | 3 ++- src/detection/processes/processes_windows.c | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c index d0de8170d4..8c50065a07 100644 --- a/src/detection/processes/processes_obsd.c +++ b/src/detection/processes/processes_obsd.c @@ -13,7 +13,8 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu } int count = 0; - // KERN_PROC_ALL returns all user-level processes, excluding kernel processes and threads + // KERN_PROC_ALL returns all user-level processes + // KERN_PROC_KTHREAD returns all processes, including user-level processes (despite the name) const struct kinfo_proc* procs = kvm_getprocs(kd, (options->countKprocs ? KERN_PROC_KTHREAD : KERN_PROC_ALL) | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), &count); diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index af09f6a910..0a2ba2f41a 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -26,11 +26,10 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu } for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) { - if (!options->countKprocs && (uintptr_t) ptr->InheritedFromUniqueProcessId > 0) { - continue; + if (options->countKprocs || (uintptr_t) ptr->InheritedFromUniqueProcessId > 0) { + ++result->processes; + result->threads += ptr->NumberOfThreads; } - ++result->processes; - result->threads += ptr->NumberOfThreads; if (ptr->NextEntryOffset == 0) { break; } From 8ea4468eec60fb43dcb12a61afcc229e6103b2a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 1 Sep 2026 00:20:40 +0800 Subject: [PATCH 106/109] Common (Endian): adds new header --- src/common/endian.h | 17 +++++++++ src/common/impl/base64.c | 9 ++--- src/common/impl/smbios.c | 33 ++++++++--------- src/detection/battery/battery_windows.c | 20 +++++------ src/detection/chassis/chassis_linux.c | 3 +- src/detection/cpu/cpu_windows.c | 3 +- src/detection/cpucache/cpucache_shared.c | 13 ++++--- src/detection/host/host_windows.c | 10 +++++- .../physicalmemory/physicalmemory_linux.c | 36 +++++++++++-------- 9 files changed, 87 insertions(+), 57 deletions(-) create mode 100644 src/common/endian.h diff --git a/src/common/endian.h b/src/common/endian.h new file mode 100644 index 0000000000..2410911ee4 --- /dev/null +++ b/src/common/endian.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#if __BIG_ENDIAN__ + #define FF_READ_LE(x) _Generic((x), \ + uint16_t: __builtin_bswap16(x), \ + uint32_t: __builtin_bswap32(x), \ + uint64_t: __builtin_bswap64(x)) + #define FF_READ_BE(x) (x) +#else + #define FF_READ_LE(x) (x) + #define FF_READ_BE(x) _Generic((x), \ + uint16_t: __builtin_bswap16(x), \ + uint32_t: __builtin_bswap32(x), \ + uint64_t: __builtin_bswap64(x)) +#endif diff --git a/src/common/impl/base64.c b/src/common/impl/base64.c index fa987c303c..3d743691b1 100644 --- a/src/common/impl/base64.c +++ b/src/common/impl/base64.c @@ -1,4 +1,5 @@ #include "common/base64.h" +#include "common/endian.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) { @@ -7,12 +8,8 @@ void ffBase64EncodeRaw(uint32_t size, const char* str, uint32_t* out_size, char* const char* ends = str + (size - size % 3); while (str != ends) { uint32_t n = *(uint32_t*) str; - #if !__BIG_ENDIAN__ - // The 3 input bytes must be laid out big-endian (str[0] in the most - // significant position). On little-endian hosts swap; on big-endian - // hosts the word is already in the right order. - n = __builtin_bswap32(n); - #endif + // The 3 input bytes must be laid out big-endian (str[0] in the most significant position). + n = FF_READ_BE(n); *out++ = chars[(n >> 26) & 63]; *out++ = chars[(n >> 20) & 63]; *out++ = chars[(n >> 14) & 63]; diff --git a/src/common/impl/smbios.c b/src/common/impl/smbios.c index fc7df14b37..9a54003bc7 100644 --- a/src/common/impl/smbios.c +++ b/src/common/impl/smbios.c @@ -1,3 +1,4 @@ +#include "common/endian.h" #include "common/smbios.h" #include "common/io.h" #include "common/mallocHelper.h" @@ -81,9 +82,9 @@ static bool parseSmbiosTable(const uint8_t* data, uint32_t length) { break; } - if (header->Handle >= 0xFF00) { + if (FF_READ_LE(header->Handle) >= 0xFF00) { FF_DEBUG("Invalid SMBIOS structure handle 0x%04x at offset 0x%lx", - header->Handle, + FF_READ_LE(header->Handle), (unsigned long) ((const uint8_t*) header - data)); break; } @@ -103,25 +104,25 @@ static bool parseSmbiosTable(const uint8_t* data, uint32_t length) { smbiosTable[header->Type] = header; FF_DEBUG("Found SMBIOS structure type %u, handle 0x%04X, length %u", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); structureCount++; } else { FF_DEBUG("Duplicate SMBIOS structure type %u, handle 0x%04X, length %u", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); } } else if (header->Type == FF_SMBIOS_TYPE_END_OF_TABLE) { FF_DEBUG("Reached SMBIOS end of type %u, handle 0x%04X, length %u", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); break; } else { FF_DEBUG("Found custom SMBIOS structure type %u, handle 0x%04X, length %u; ignoring", header->Type, - header->Handle, + FF_READ_LE(header->Handle), header->Length); } } @@ -308,8 +309,8 @@ static bool fillTableBufferFallback(FFstrbuf* buffer) { sizeof(p->Smbios30)); return false; } - tableLength = p->Smbios30.StructureTableMaximumSize; - tableAddress = (off_t) p->Smbios30.StructureTableAddress; + tableLength = FF_READ_LE(p->Smbios30.StructureTableMaximumSize); + tableAddress = (off_t) FF_READ_LE(p->Smbios30.StructureTableAddress); FF_DEBUG("SMBIOS 3.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u.%u", tableLength, (unsigned long) tableAddress, @@ -325,8 +326,8 @@ static bool fillTableBufferFallback(FFstrbuf* buffer) { sizeof(p->Smbios20)); return false; } - tableLength = p->Smbios20.StructureTableLength; - tableAddress = (off_t) p->Smbios20.StructureTableAddress; + tableLength = FF_READ_LE(p->Smbios20.StructureTableLength); + tableAddress = (off_t) FF_READ_LE(p->Smbios20.StructureTableAddress); FF_DEBUG("SMBIOS 2.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u", tableLength, (unsigned long) tableAddress, @@ -369,9 +370,9 @@ static bool detectSmbiosTableLength(const uint8_t* data, uint32_t bufferLength, return false; } - if (header->Handle >= 0xFF00) { + if (FF_READ_LE(header->Handle) >= 0xFF00) { FF_DEBUG("Invalid SMBIOS structure handle 0x%04x at offset 0x%lx", - header->Handle, + FF_READ_LE(header->Handle), (unsigned long) (p - data)); return false; } @@ -614,8 +615,8 @@ static bool fillTableBufferPlatform(FFstrbuf* buffer) { sizeof(entryPoint.Smbios20)); return false; } - tableLength = entryPoint.Smbios20.StructureTableLength; - tableAddress = (off_t) entryPoint.Smbios20.StructureTableAddress; + tableLength = FF_READ_LE(entryPoint.Smbios20.StructureTableLength); + tableAddress = (off_t) FF_READ_LE(entryPoint.Smbios20.StructureTableAddress); FF_DEBUG("SMBIOS 2.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u", tableLength, (unsigned long) tableAddress, @@ -629,8 +630,8 @@ static bool fillTableBufferPlatform(FFstrbuf* buffer) { sizeof(entryPoint.Smbios30)); return false; } - tableLength = entryPoint.Smbios30.StructureTableMaximumSize; - tableAddress = (off_t) entryPoint.Smbios30.StructureTableAddress; + tableLength = FF_READ_LE(entryPoint.Smbios30.StructureTableMaximumSize); + tableAddress = (off_t) FF_READ_LE(entryPoint.Smbios30.StructureTableAddress); FF_DEBUG("SMBIOS 3.0: tableLength=0x%x, tableAddress=0x%lx, version=%u.%u.%u", tableLength, (unsigned long) tableAddress, diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 720d5cbd3b..cbede5d1ef 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -1,6 +1,7 @@ #define INITGUID #include "battery.h" +#include "common/endian.h" #include "common/debug.h" #include "common/mallocHelper.h" @@ -127,29 +128,24 @@ static void detectStaticData(FFlist* entries, FFlist* results) { FFBatteryWmiEntry* entry = getBatteryEntry(entries, results, data->Tag); FF_DEBUG("chemistry: %.4s", (const char*) &data->Chemistry); -#if __BIG_ENDIAN__ - #define htobe32(x) (x) // Should not happen on Windows, but just in case -#else - #define htobe32(x) __builtin_bswap32(x) -#endif switch (data->Chemistry) { - case htobe32('PbAc'): + case FF_READ_BE((uint32_t) 'PbAc'): ffStrbufSetStatic(&entry->result->technology, "Lead Acid"); break; - case htobe32('LION'): - case htobe32('Li-I'): + case FF_READ_BE((uint32_t) 'LION'): + case FF_READ_BE((uint32_t) 'Li-I'): ffStrbufSetStatic(&entry->result->technology, "Lithium Ion"); break; - case htobe32('NiCd'): + case FF_READ_BE((uint32_t) 'NiCd'): ffStrbufSetStatic(&entry->result->technology, "Nickel Cadmium"); break; - case htobe32('NiMH'): + case FF_READ_BE((uint32_t) 'NiMH'): ffStrbufSetStatic(&entry->result->technology, "Nickel Metal Hydride"); break; - case htobe32('NiZn'): + case FF_READ_BE((uint32_t) 'NiZn'): ffStrbufSetStatic(&entry->result->technology, "Nickel Zinc"); break; - case htobe32('RAM\0'): + case FF_READ_BE((uint32_t) 'RAM\0'): ffStrbufSetStatic(&entry->result->technology, "Rechargeable Alkaline-Manganese"); break; default: diff --git a/src/detection/chassis/chassis_linux.c b/src/detection/chassis/chassis_linux.c index 686fc67be9..e23f73463e 100644 --- a/src/detection/chassis/chassis_linux.c +++ b/src/detection/chassis/chassis_linux.c @@ -1,4 +1,5 @@ #include "chassis.h" +#include "common/endian.h" #include "common/io.h" #include "common/smbios.h" @@ -21,7 +22,7 @@ const char* ffDetectChassis(FFChassisResult* result) { uint32_t chassisType = 0; if (ffReadFileData("/sys/firmware/devicetree/base/smbios/smbios/chassis/chassis-type", sizeof(chassisType), &chassisType)) // big endian { - chassisType = __builtin_bswap32(chassisType); + chassisType = FF_READ_BE(chassisType); const char* typeStr = ffChassisTypeToString(chassisType); if (typeStr) { ffStrbufSetStatic(&result->type, typeStr); diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 82b656e4f0..8975775d07 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -1,4 +1,5 @@ #include "cpu.h" +#include "common/endian.h" #include "common/windows/registry.h" #include "common/windows/nt.h" #include "common/mallocHelper.h" @@ -205,7 +206,7 @@ static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu) { } } - uint32_t speed = data->MaxSpeed; + uint32_t speed = FF_READ_LE(data->MaxSpeed); // Sometimes SMBIOS reports invalid value. We assume that max speed is small than 2x of base if (speed < cpu->frequencyBase || speed > cpu->frequencyBase * 2) { return "Possible invalid CPU max speed in SMBIOS data. See #800"; diff --git a/src/detection/cpucache/cpucache_shared.c b/src/detection/cpucache/cpucache_shared.c index 58419a9632..f8888313ae 100644 --- a/src/detection/cpucache/cpucache_shared.c +++ b/src/detection/cpucache/cpucache_shared.c @@ -1,4 +1,5 @@ #include "cpucache.h" +#include "common/endian.h" #include "common/smbios.h" #include "common/strutil.h" @@ -43,24 +44,26 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result) { continue; } - bool enabled = !!(data->CacheConfiguration & (1 << 7)); + uint16_t cacheConfiguration = FF_READ_LE(data->CacheConfiguration); + uint16_t installedSize = FF_READ_LE(data->InstalledSize); + bool enabled = !!(cacheConfiguration & (1 << 7)); if (!enabled) { continue; } - uint32_t size = data->InstalledSize; + uint32_t size = installedSize; if (size == 0) { continue; } - if (data->InstalledSize != 0xFFFF) { + if (installedSize != 0xFFFF) { size *= (size >> 15 ? 64 : 1) * 1024u; } else if (data->Header.Length > offsetof(FFSmbiosCacheInfo, InstalledCacheSize2)) { - size = data->InstalledCacheSize2; + size = FF_READ_LE(data->InstalledCacheSize2); size *= (size >> 31 ? 64 : 1) * 1024u; } - uint32_t level = (data->CacheConfiguration & 0b111u) + 1; + uint32_t level = (cacheConfiguration & 0b111u) + 1; FFCPUCacheType type; switch (data->SystemCacheType) { diff --git a/src/detection/host/host_windows.c b/src/detection/host/host_windows.c index 13bf56e88d..a39a3041ef 100644 --- a/src/detection/host/host_windows.c +++ b/src/detection/host/host_windows.c @@ -1,4 +1,5 @@ #include "host.h" +#include "common/endian.h" #include "common/smbios.h" typedef struct [[gnu::packed]] FFSmbiosSystemInfo { @@ -52,7 +53,14 @@ const char* ffDetectHost(FFHostResult* host) { static_assert(offsetof(FFSmbiosSystemInfo, UUID) == 0x08, "FFSmbiosSystemInfo.UUID offset is wrong"); if (data->Header.Length > offsetof(FFSmbiosSystemInfo, UUID)) { - ffStrbufSetF(&host->uuid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", data->UUID.TimeLow, data->UUID.TimeMid, data->UUID.TimeHighAndVersion, data->UUID.ClockSeqHiAndReserved, data->UUID.ClockSeqLow, data->UUID.Node[0], data->UUID.Node[1], data->UUID.Node[2], data->UUID.Node[3], data->UUID.Node[4], data->UUID.Node[5]); + ffStrbufSetF(&host->uuid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + FF_READ_LE(data->UUID.TimeLow), + FF_READ_LE(data->UUID.TimeMid), + FF_READ_LE(data->UUID.TimeHighAndVersion), + data->UUID.ClockSeqHiAndReserved, + data->UUID.ClockSeqLow, + data->UUID.Node[0], data->UUID.Node[1], data->UUID.Node[2], + data->UUID.Node[3], data->UUID.Node[4], data->UUID.Node[5]); } static_assert(offsetof(FFSmbiosSystemInfo, SKUNumber) == 0x19, "FFSmbiosSystemInfo.SKUNumber offset is wrong"); diff --git a/src/detection/physicalmemory/physicalmemory_linux.c b/src/detection/physicalmemory/physicalmemory_linux.c index fe248be0c5..c3e3fae960 100644 --- a/src/detection/physicalmemory/physicalmemory_linux.c +++ b/src/detection/physicalmemory/physicalmemory_linux.c @@ -1,4 +1,5 @@ #include "physicalmemory.h" +#include "common/endian.h" #include "common/smbios.h" // 7.18 @@ -82,7 +83,8 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res } const char* strings = (const char*) data + data->Header.Length; - bool installed = data->Size != 0; + uint16_t size = FF_READ_LE(data->Size); + bool installed = size != 0; if (!installed && !options->showEmptySlots) { continue; @@ -101,19 +103,21 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res device->installed = installed; device->ecc = false; - if (installed && data->TotalWidth != 0xFFFF && data->DataWidth != 0xFFFF) { - device->ecc = data->TotalWidth > data->DataWidth; + uint16_t totalWidth = FF_READ_LE(data->TotalWidth); + uint16_t dataWidth = FF_READ_LE(data->DataWidth); + if (installed && totalWidth != 0xFFFF && dataWidth != 0xFFFF) { + device->ecc = totalWidth > dataWidth; } - if (installed && data->Size != 0xFFFF) { - if (data->Size == 0x7FFF) { - device->size = (data->ExtendedSize & ~(1ULL << 31)) * 1024ULL * 1024ULL; - } else if (data->Size & (1 << 15)) { + if (installed && size != 0xFFFF) { + if (size == 0x7FFF) { + device->size = (FF_READ_LE(data->ExtendedSize) & ~(1ULL << 31)) * 1024ULL * 1024ULL; + } else if (size & (1 << 15)) { // in kB - device->size = (data->Size & ~(1ULL << 15)) * 1024ULL; + device->size = (size & ~(1ULL << 15)) * 1024ULL; } else { // in MB - device->size = data->Size * 1024ULL * 1024ULL; + device->size = size * 1024ULL * 1024ULL; } } @@ -206,8 +210,9 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res if (installed && data->Header.Length > offsetof(FFSmbiosMemoryDevice, Speed)) // 2.3+ { - if (data->Speed) { - device->maxSpeed = data->Speed == 0xFFFF ? data->ExtendedSpeed : data->Speed; + uint16_t speed = FF_READ_LE(data->Speed); + if (speed) { + device->maxSpeed = speed == 0xFFFF ? FF_READ_LE(data->ExtendedSpeed) : speed; } ffStrbufSetStatic(&device->vendor, ffSmbiosLocateString(strings, data->Manufacturer)); @@ -223,10 +228,11 @@ const char* ffDetectPhysicalMemory(FFPhysicalMemoryOptions* options, FFlist* res if (installed && data->Header.Length > offsetof(FFSmbiosMemoryDevice, ConfiguredMemorySpeed)) // 2.7+ { - if (data->ConfiguredMemorySpeed) { - device->runningSpeed = data->ConfiguredMemorySpeed == 0xFFFF - ? data->ExtendedConfiguredSpeed - : data->ConfiguredMemorySpeed; + uint16_t configuredSpeed = FF_READ_LE(data->ConfiguredMemorySpeed); + if (configuredSpeed) { + device->runningSpeed = configuredSpeed == 0xFFFF + ? FF_READ_LE(data->ExtendedConfiguredSpeed) + : configuredSpeed; } } } From 4863a173e4cc3dbff76e8d993be5d81d6664364a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 1 Sep 2026 00:34:55 +0800 Subject: [PATCH 107/109] Wifi (linux): enables netlink on big-endian platforms --- src/detection/wifi/wifi_linux.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 87e8e73788..8de3ec64b3 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -1,4 +1,5 @@ #include "wifi.h" +#include "common/endian.h" #include "common/io.h" #include "common/debug.h" #include "common/strutil.h" @@ -11,12 +12,11 @@ #include #include -#if !__BIG_ENDIAN__ - #include - #include +#include +#include - // Silence warning of `NLA_HDRLEN` and `NLA_ALIGN` - #pragma GCC diagnostic ignored "-Wsign-conversion" +// Silence warning of `NLA_HDRLEN` and `NLA_ALIGN` +#pragma GCC diagnostic ignored "-Wsign-conversion" typedef struct FFWifiNlContext { int sockFd; @@ -459,7 +459,7 @@ static void ffWifiParseRsnIe(const uint8_t* ie, size_t len, FFWifiSecurityFlags* if (pos + 2 > len) { // pairwise cipher suite count field length return; } - uint16_t pairwiseCount = *(uint16_t*) (ie + pos); + uint16_t pairwiseCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2; // skip pairwise cipher suite count field size_t pairwiseLen = (size_t) pairwiseCount * 4; // each suite selector is 4 bytes @@ -471,7 +471,7 @@ static void ffWifiParseRsnIe(const uint8_t* ie, size_t len, FFWifiSecurityFlags* if (pos + 2 > len) { // AKM suite count field length return; } - uint16_t akmCount = *(uint16_t*) (ie + pos); + uint16_t akmCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2; // skip AKM suite count field for (uint16_t i = 0; i < akmCount && pos + 4 <= len; ++i, pos += 4) { // each AKM suite selector is 4 bytes @@ -528,13 +528,13 @@ static void ffWifiParseWpaVendorIe(const uint8_t* ie, size_t len, FFWifiSecurity if (pos + 2 > len) { // unicast cipher suite count field length return; } - uint16_t pairwiseCount = *(uint16_t*) (ie + pos); + uint16_t pairwiseCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2 + (size_t) pairwiseCount * 4; // count field(2) + N unicast suite selectors(4 each) if (pos + 2 > len) { // AKM suite count field length return; } - uint16_t akmCount = *(uint16_t*) (ie + pos); + uint16_t akmCount = FF_READ_LE(*(const uint16_t*) (ie + pos)); pos += 2; // skip AKM suite count field for (uint16_t i = 0; i < akmCount && pos + 4 <= len; ++i, pos += 4) { // each AKM suite selector is 4 bytes @@ -845,8 +845,6 @@ static const char* detectWithNetlink(FFWifiNlContext* ctx, FFWifiResult* item, u FF_DEBUG("Netlink wifi detection completed"); return nullptr; } -#endif - typedef struct FFWifiIcContext { int sockFd; } FFWifiIcContext; @@ -1049,9 +1047,7 @@ const char* ffDetectWifi(FFlist* result) { return "if_nameindex() failed"; } -#if !__BIG_ENDIAN__ FFWifiNlContext nl = { .sockFd = -1 }; -#endif FFWifiIcContext ic = { .sockFd = -1 }; FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); @@ -1090,9 +1086,7 @@ const char* ffDetectWifi(FFlist* result) { if (operstate == 'u') { ffStrbufSetStatic(&item->inf.status, "up"); -#if !__BIG_ENDIAN__ detectWithNetlink(&nl, item, i->if_index); -#endif detectWithIoctl(&ic, item, i->if_name); } else { ffStrbufSetStatic(&item->conn.status, "disconnected"); @@ -1116,11 +1110,9 @@ const char* ffDetectWifi(FFlist* result) { } if_freenameindex(infs); -#if !__BIG_ENDIAN__ if (nl.sockFd >= 0) { close(nl.sockFd); } -#endif if (ic.sockFd >= 0) { close(ic.sockFd); } From 3d107764fae5b79418d39320f05c1d80c379f94a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 1 Sep 2026 14:14:01 +0800 Subject: [PATCH 108/109] Wifi (Linux): fixes compatibility with old kernel headers --- src/detection/wifi/wifi_linux.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 8de3ec64b3..c0a56ede40 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -308,19 +308,19 @@ static uint16_t ffWifiChannelWidthToMhz(uint32_t width) { return 80; case NL80211_CHAN_WIDTH_160: return 160; - case NL80211_CHAN_WIDTH_5: + case 6 /* NL80211_CHAN_WIDTH_5 */: return 5; - case NL80211_CHAN_WIDTH_10: + case 7 /* NL80211_CHAN_WIDTH_10 */: return 10; - case NL80211_CHAN_WIDTH_1: + case 8 /* NL80211_CHAN_WIDTH_1 */: return 1; - case NL80211_CHAN_WIDTH_2: + case 9 /* NL80211_CHAN_WIDTH_2 */: return 2; - case NL80211_CHAN_WIDTH_4: + case 10 /* NL80211_CHAN_WIDTH_4 */: return 4; - case NL80211_CHAN_WIDTH_8: + case 11 /* NL80211_CHAN_WIDTH_8 */: return 8; - case NL80211_CHAN_WIDTH_16: + case 12 /* NL80211_CHAN_WIDTH_16 */: return 16; case 13 /* NL80211_CHAN_WIDTH_320 */: return 320; From 0b1bc5b527b958aabc62be06d89795e6d4325849 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 31 Aug 2026 09:26:22 +0800 Subject: [PATCH 109/109] CI: upgrades deps; reenables Haiku --- .github/workflows/build-dragonfly-amd64.yml | 2 +- .github/workflows/build-freebsd-amd64.yml | 2 +- .github/workflows/build-haiku-amd64.yml | 4 ++-- .github/workflows/build-netbsd-amd64.yml | 2 +- .github/workflows/build-omnios-amd64.yml | 2 +- .github/workflows/build-openbsd-amd64.yml | 2 +- .github/workflows/ci.yml | 3 +-- 7 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-dragonfly-amd64.yml b/.github/workflows/build-dragonfly-amd64.yml index c3aec5d6e3..f7e406f54d 100644 --- a/.github/workflows/build-dragonfly-amd64.yml +++ b/.github/workflows/build-dragonfly-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: dragonflybsd version: '6.4.2' diff --git a/.github/workflows/build-freebsd-amd64.yml b/.github/workflows/build-freebsd-amd64.yml index 1cbbcae4cf..1eb0c36c68 100644 --- a/.github/workflows/build-freebsd-amd64.yml +++ b/.github/workflows/build-freebsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: freebsd version: '15.1' diff --git a/.github/workflows/build-haiku-amd64.yml b/.github/workflows/build-haiku-amd64.yml index 41aa30680c..c6642b9b16 100644 --- a/.github/workflows/build-haiku-amd64.yml +++ b/.github/workflows/build-haiku-amd64.yml @@ -18,10 +18,10 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: haiku - version: 'r1beta5' + version: 'r1beta6' shell: bash cpu_count: 4 diff --git a/.github/workflows/build-netbsd-amd64.yml b/.github/workflows/build-netbsd-amd64.yml index 87a8dc497e..d55dbd0b50 100644 --- a/.github/workflows/build-netbsd-amd64.yml +++ b/.github/workflows/build-netbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: netbsd version: '10.1' diff --git a/.github/workflows/build-omnios-amd64.yml b/.github/workflows/build-omnios-amd64.yml index a721080880..f29c27dc46 100644 --- a/.github/workflows/build-omnios-amd64.yml +++ b/.github/workflows/build-omnios-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: omnios version: 'r151058' diff --git a/.github/workflows/build-openbsd-amd64.yml b/.github/workflows/build-openbsd-amd64.yml index 9db8c4cef2..7f7bd2102f 100644 --- a/.github/workflows/build-openbsd-amd64.yml +++ b/.github/workflows/build-openbsd-amd64.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Start VM - uses: cross-platform-actions/action@24ef01df165c76df1ed2b9f9e9212e78dc2fc963 # v1.4.0 + uses: cross-platform-actions/action@faa0c6197e94aacf1c5956460152c8380d3560a5 # v1.5.0 with: operating_system: openbsd version: '7.9' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f63fdc049..16f6ce34c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,7 +138,6 @@ jobs: uses: ./.github/workflows/build-dragonfly-amd64.yml haiku-amd64: - if: false # Disabled because the Haiku build is currently broken needs: no-features-test name: Haiku-amd64 permissions: @@ -204,7 +203,7 @@ jobs: - dragonfly-amd64 - solaris-amd64 - omnios-amd64 - # - haiku-amd64 + - haiku-amd64 - windows-hosts permissions: contents: write