diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85ba828ee..d046a3e5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,9 @@ jobs: - name: checkout repository uses: actions/checkout@v4 + - name: uname -a + run: uname -a + - name: install required packages run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev @@ -35,7 +38,7 @@ jobs: env: CC: ${{ matrix.compiler.cc }} CXX: ${{ matrix.compiler.cxx }} - run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} . + run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} . - name: build project run: cmake --build . @@ -43,6 +46,9 @@ jobs: - name: run tests run: ctest + - name: run fastfetch --list-features + run: ./fastfetch --list-features + - name: run fastfetch run: time ./fastfetch -c presets/ci @@ -64,19 +70,27 @@ jobs: - name: checkout repository uses: actions/checkout@v4 + - name: uname -a + run: uname -a + - name: install required packages run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev + - name: install linuxbrew packages + run: | + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + /home/linuxbrew/.linuxbrew/bin/brew install imagemagick --ignore-dependencies + - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: c - name: configure project - run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . - name: build project - run: cmake --build . --target package + run: cmake --build . --target package --verbose - name: perform CodeQL analysis uses: github/codeql-action/analyze@v2 @@ -119,8 +133,13 @@ jobs: - name: checkout repository uses: actions/checkout@v4 + - name: uname -a + run: uname -a + - name: install required packages - run: brew install vulkan-loader molten-vk imagemagick chafa + run: | + brew update + brew install vulkan-loader vulkan-headers molten-vk imagemagick chafa - name: Initialize CodeQL uses: github/codeql-action/init@v2 @@ -131,7 +150,7 @@ jobs: run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_OSX_ARCHITECTURES='arm64;x86_64' . - name: build project - run: cmake --build . --target package + run: cmake --build . --target package --verbose - name: perform CodeQL analysis uses: github/codeql-action/analyze@v2 @@ -171,14 +190,16 @@ jobs: uses: actions/checkout@v4 - name: run VM - uses: cross-platform-actions/action@v0.21.0 + uses: cross-platform-actions/action@v0.21.1 with: operating_system: freebsd version: '13.2' run: | + uname -a + sudo pkg update sudo pkg install -y cmake git pkgconf binutils pciutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 glib dconf dbus sqlite3-tcl xfce4-conf ImageMagick6 ImageMagick7 chafa egl libosmesa opencl ocl-icd pulseaudio cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . - cmake --build . --target package + cmake --build . --target package --verbose ./fastfetch --list-features time ./fastfetch -c presets/ci time ./fastfetch -c presets/ci --format json @@ -215,19 +236,11 @@ jobs: - name: print msys version run: uname -a - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: c, cpp - - name: configure project run: env PKG_CONFIG_PATH=/clang64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . - name: build project - run: cmake --build . - - - name: perform CodeQL analysis - uses: github/codeql-action/analyze@v2 + run: cmake --build . --verbose - name: copy necessary dlls run: cp /clang64/bin/{OpenCL,vulkan-1}.dll . @@ -294,7 +307,7 @@ jobs: run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . - name: build project - run: cmake --build . + run: cmake --build . --verbose - name: perform CodeQL analysis uses: github/codeql-action/analyze@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 86d4600d9..1e61c081f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +# 2.2.2 + +Changes: +* `--percent-type` now defaults to 9 (colored percentage numbers) +* `fastfetch` now prints LocalIp module by default + +Features: +* LocalIP module now prints netmask in CIDR format for IPv4 (LocalIP) +* Bios module now detects system firmware type (Bios) +* Improve detection of `Battery` + * Detect cycle count on supported platforms + * Detect temperature on Linux when supported + * Status detection on macOS has been adjusted to be consistant with other platforms +* Linux binaries are built with imagemagick7 support + +Bugfixes: +* Fix unitialized variables (#609) +* Fix spelling of `--preserve-aspect-ratio` (#614) + +Logos: + +* Update NixOS_small + # 2.2.1 Hotfix release for #606 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4678b1871..759797071 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.2.1 + VERSION 2.2.2 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -234,14 +234,11 @@ endif() function(fastfetch_load_raw_text FILENAME OUTVAR) file(READ "${FILENAME}" TEMP) - string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline - string(JSON TEMP SET "{}" "${TEMP}" "0") # Encode raw strings using JSON_SET - string(REGEX REPLACE "^\\{[ \t\r\n]*" "" TEMP "${TEMP}") # Remove JSON braces - string(REGEX REPLACE "[ \t\r\n]*:[ \t\r\n]*0[ \t\r\n]*\\}$" "" TEMP "${TEMP}") # Remove trailing ` : 0 }` - if(NOT "${TEMP}" MATCHES "^\"[^\n]*\"") - message(FATAL_ERROR "Internal error: unexpected output: '${TEMP}'") - endif() - set(${OUTVAR} "${TEMP}" PARENT_SCOPE) + string(REGEX REPLACE "\n$" "" TEMP "${TEMP}") # Remove trailing newline + string(REPLACE "\\" "\\\\" TEMP "${TEMP}") # Escape backslashes + string(REPLACE "\n" "\\n" TEMP "${TEMP}") # Replace newlines with \n + string(REPLACE "\"" "\\\"" TEMP "${TEMP}") # Replace quotes with \" + set(${OUTVAR} "\"${TEMP}\"" PARENT_SCOPE) endfunction(fastfetch_load_raw_text) file(GLOB LOGO_FILES "src/logo/ascii/*.txt") diff --git a/README.md b/README.md index a5e243cd9..a2b283864 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ See Wiki: https://github.com/fastfetch-cli/fastfetch/wiki/Building * Run it with [all supported modules](https://github.com/fastfetch-cli/fastfetch/wiki/Support+Status#available-modules) and find what you interest: `fastfetch -c all.jsonc` * Find all data that fastfetch detects: `fastfetch -s --format json` * Display help messages: `fastfetch --help` -* Generate config file based on command line arguments: `fastfetch --arg1 --arg2 --mirgrate-config` +* Generate config file based on command line arguments: `fastfetch --arg1 --arg2 --migrate-config` ## Customization diff --git a/doc/json_schema.json b/doc/json_schema.json index 558d442eb..886823d5a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -156,7 +156,7 @@ "description": "Whether to print the remaining logo, if it has more lines than modules to display", "default": false }, - "preserveAspectRadio": { + "preserveAspectRatio": { "type": "boolean", "description": "Whether to preserve the aspect ratio of the logo. Supported by iTerm image protocol", "default": false @@ -415,7 +415,7 @@ "description": "Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number", "minimum": 0, "maximum": 255, - "default": 1 + "default": 9 }, "ndigits": { "type": "number", diff --git a/presets/examples/11.jsonc b/presets/examples/11.jsonc index 018cfd882..b235b05f5 100644 --- a/presets/examples/11.jsonc +++ b/presets/examples/11.jsonc @@ -4,9 +4,6 @@ "type": "small" }, "display": { - "percent": { - "type": 9 - }, "separator": "\u001b[31m-> " }, "modules": [ diff --git a/presets/examples/8.jsonc b/presets/examples/8.jsonc index 3aea80971..cc7b47407 100644 --- a/presets/examples/8.jsonc +++ b/presets/examples/8.jsonc @@ -11,9 +11,6 @@ "size": { "ndigits": 0, "maxPrefix": "MB" - }, - "percent": { - "type": 9 } }, "modules": [ diff --git a/presets/examples/9.jsonc b/presets/examples/9.jsonc index abdc69bd7..e2801c248 100644 --- a/presets/examples/9.jsonc +++ b/presets/examples/9.jsonc @@ -9,9 +9,6 @@ "charElapsed": "=", "charTotal": "-", "width": 13 - }, - "percent": { - "type": 9 } }, "modules": [ diff --git a/src/data/config_user.jsonc b/src/data/config_user.jsonc index 07148cdac..029f768e5 100644 --- a/src/data/config_user.jsonc +++ b/src/data/config_user.jsonc @@ -8,11 +8,6 @@ "top": 2 } }, - "display": { - "percent": { - "type": 9 - } // colored percent number - }, "modules": [ "title", "separator", @@ -36,6 +31,7 @@ "gpu", "memory", "disk", + "localip", "battery", "poweradapter", "locale", diff --git a/src/data/help.txt b/src/data/help.txt index c04e58a1d..27f29d6a3 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -35,7 +35,7 @@ Logo options: --logo-type : Set the type of the logo given; must be auto, builtin, file, file-raw, data, data-raw, sixel, kitty, iterm or chafa --logo-width : Set the width of the logo (in characters), if it is an image. Required for iTerm image protocol --logo-height : Set the height of the logo (in characters), if it is an image. Required for iTerm image protocol - --logo-preserve-aspect-radio : Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol + --logo-preserve-aspect-ratio : Set if the logo should fill the specified width and height as much as possible without stretching. Supported by iTerm image protocol --logo-color-[1-9] : Overwrite a color in the logo --logo-padding : Set the padding on the left and the right of the logo --logo-padding-left : Set the padding on the left of the logo @@ -74,7 +74,7 @@ Display options: --disable-linewrap : Whether to disable line wrap during the run --hide-cursor : Whether to hide the cursor during the run --binary-prefix : Set the binary prefix to used. Must be IEC, SI or JEDEC. Default is IEC - --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 1 + --percent-type : Set the percentage output type. 1 for percentage number, 2 for bar, 3 for both, 6 for bar only, 9 for colored number. Default is 9 --percent-ndigits : Set the number of digits to keep after the decimal point when formatting percentage numbers. Default is 0 --bar-char-elapsed : Set the character to use in elapsed part. Default is '■' --bar-char-total : Set the character to use in total part. Default is '-' diff --git a/src/data/structure.txt b/src/data/structure.txt index 22b859add..717e3a3a3 100644 --- a/src/data/structure.txt +++ b/src/data/structure.txt @@ -1 +1 @@ -Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Locale:Break:Colors +Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Swap:Disk:LocalIp:Battery:PowerAdapter:Locale:Break:Colors diff --git a/src/detection/battery/battery.h b/src/detection/battery/battery.h index 7df622ea2..8f94e93a8 100644 --- a/src/detection/battery/battery.h +++ b/src/detection/battery/battery.h @@ -15,6 +15,7 @@ typedef struct FFBatteryResult double capacity; FFstrbuf status; double temperature; + uint32_t cycleCount; } FFBatteryResult; const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results); diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c index 16dce83d0..7b3a2e084 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -35,6 +35,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results) FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; + battery->cycleCount = 0; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); ffStrbufInit(&battery->status); diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index c0950c0ee..602a61fc7 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -5,16 +5,6 @@ #include -static double detectBatteryTemp(void) -{ - double result = 0; - - if(ffDetectCoreTemps(FF_TEMP_BATTERY, &result)) - return FF_BATTERY_TEMP_UNSET; - - return result; -} - const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) { io_iterator_t iterator; @@ -24,7 +14,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) io_registry_entry_t registryEntry; while((registryEntry = IOIteratorNext(iterator)) != 0) { - CFMutableDictionaryRef properties; + FF_CFTYPE_AUTO_RELEASE CFMutableDictionaryRef properties = NULL; if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) { IOObjectRelease(registryEntry); @@ -35,7 +25,13 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) const char* error; FFBatteryResult* battery = ffListAdd(results); + battery->temperature = FF_BATTERY_TEMP_UNSET; + ffStrbufInit(&battery->manufacturer); + ffStrbufInit(&battery->modelName); + ffStrbufInit(&battery->technology); + ffStrbufInit(&battery->status); battery->capacity = 0.0/0.0; + int currentCapacity, maxCapacity; if ((error = ffCfDictGetInt(properties, CFSTR("MaxCapacity"), &maxCapacity))) @@ -50,33 +46,38 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) battery->capacity = currentCapacity * 100.0 / maxCapacity; - ffStrbufInit(&battery->manufacturer); - ffStrbufInit(&battery->modelName); - ffStrbufInit(&battery->technology); + ffCfDictGetString(properties, CFSTR("DeviceName"), &battery->modelName); + if (!ffCfDictGetBool(properties, CFSTR("built-in"), &boolValue) && boolValue) { ffStrbufAppendS(&battery->manufacturer, "Apple Inc."); - ffStrbufAppendS(&battery->modelName, "Builtin"); ffStrbufAppendS(&battery->technology, "Lithium"); + if (!battery->modelName.length) + ffStrbufAppendS(&battery->modelName, "Built-in"); } + + ffCfDictGetInt(properties, CFSTR("CycleCount"), (int32_t*) &battery->cycleCount); + + if (!ffCfDictGetBool(properties, CFSTR("ExternalConnected"), &boolValue) && boolValue) + ffStrbufAppendS(&battery->status, "AC connected, "); else + ffStrbufAppendS(&battery->status, "Discharging, "); + if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue) + ffStrbufAppendS(&battery->status, "Charging, "); + if (!ffCfDictGetBool(properties, CFSTR("AtCriticalLevel"), &boolValue) && boolValue) + ffStrbufAppendS(&battery->status, "Critical, "); + ffStrbufTrimRight(&battery->status, ' '); + ffStrbufTrimRight(&battery->status, ','); + + if (options->temp) { - ffStrbufAppendS(&battery->manufacturer, "Unknown"); - ffStrbufAppendS(&battery->modelName, "Unknown"); - ffStrbufAppendS(&battery->technology, "Unknown"); + int64_t temp; + if (!ffCfDictGetInt64(properties, CFSTR("Temperature"), &temp)) + battery->temperature = (double) temp / 10 - 273.15; + else + ffDetectCoreTemps(FF_TEMP_BATTERY, &battery->temperature); } - ffStrbufInit(&battery->status); - if (!ffCfDictGetBool(properties, CFSTR("FullyCharged"), &boolValue) && boolValue) - ffStrbufAppendS(&battery->status, "Fully charged"); - else if (!ffCfDictGetBool(properties, CFSTR("IsCharging"), &boolValue) && boolValue) - ffStrbufAppendS(&battery->status, "Charging"); - else - ffStrbufAppendS(&battery->status, ""); - - battery->temperature = options->temp ? detectBatteryTemp() : FF_BATTERY_TEMP_UNSET; - - CFRelease(properties); IOObjectRelease(registryEntry); } diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c index 8675ab099..52ce13d01 100644 --- a/src/detection/battery/battery_bsd.c +++ b/src/detection/battery/battery_bsd.c @@ -34,6 +34,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; + battery->cycleCount = 0; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); ffStrbufInit(&battery->status); diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index a0bbf85f6..c655f34b4 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -1,11 +1,11 @@ -#include "fastfetch.h" -#include "common/io/io.h" #include "battery.h" +#include "common/io/io.h" +#include "detection/temps/temps_linux.h" #include "util/stringUtils.h" #include -static void parseBattery(FFstrbuf* dir, FFlist* results) +static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results) { uint32_t dirLength = dir->length; @@ -65,7 +65,26 @@ static void parseBattery(FFstrbuf* dir, FFlist* results) ffReadFileBuffer(dir->chars, &result->status); ffStrbufSubstrBefore(dir, dirLength); + ffStrbufAppendS(dir, "/cycle_count"); + ffReadFileBuffer(dir->chars, &testBatteryBuffer); + ffStrbufSubstrBefore(dir, dirLength); + if(dir->length) + result->cycleCount = (uint32_t) ffStrbufToUInt(&testBatteryBuffer, 0); + result->temperature = FF_BATTERY_TEMP_UNSET; + if (options->temp) + { + const FFlist* tempsResult = ffDetectTemps(); + + FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) + { + if (ffStrbufEqualS(&value->name, id)) + { + result->temperature = value->value; + break; + } + } + } } const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) @@ -84,7 +103,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) uint32_t baseDirLength = baseDir.length; - DIR* dirp = opendir(baseDir.chars); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); if(dirp == NULL) return "opendir(batteryDir) == NULL"; @@ -95,12 +114,10 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) continue; ffStrbufAppendS(&baseDir, entry->d_name); - parseBattery(&baseDir, results); + parseBattery(&baseDir, entry->d_name, options, results); ffStrbufSubstrBefore(&baseDir, baseDirLength); } - closedir(dirp); - if(results->length == 0) return "batteryDir doesn't contain any battery folder"; diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index ea30df791..283ccc135 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -30,137 +30,146 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev) SetupDiDestroyDeviceInfoList(*hdev); } -const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) +static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results) { - if(options->useSetupApi) + //https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices + HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) = + SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); + if(hdev == INVALID_HANDLE_VALUE) + return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed"; + + SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) }; + for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++) { - //https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices - HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) = - SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if(hdev == INVALID_HANDLE_VALUE) - return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed"; + DWORD cbRequired = 0; + SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer + SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired); + if(!pdidd) + break; //Out of memory + + pdidd->cbSize = sizeof(*pdidd); + if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL)) + continue; + + HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery = + CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if(hBattery == INVALID_HANDLE_VALUE) + continue; + + BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation }; + + DWORD dwWait = 0; + DWORD dwOut; + + if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag) + continue; + + BATTERY_INFORMATION bi = {0}; + if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL)) + continue; + + if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY)) + continue; + + FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results); + + if(memcmp(bi.Chemistry, "PbAc", 4) == 0) + ffStrbufInitS(&battery->technology, "Lead Acid"); + else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0) + ffStrbufInitS(&battery->technology, "Lithium Ion"); + else if(memcmp(bi.Chemistry, "NiCd", 4) == 0) + ffStrbufInitS(&battery->technology, "Nickel Cadmium"); + else if(memcmp(bi.Chemistry, "NiMH", 4) == 0) + ffStrbufInitS(&battery->technology, "Nickel Metal Hydride"); + else if(memcmp(bi.Chemistry, "NiZn", 4) == 0) + ffStrbufInitS(&battery->technology, "Nickel Zinc"); + else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0) + ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese"); + else + ffStrbufInitS(&battery->technology, "Unknown"); - SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) }; - for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++) { - DWORD cbRequired = 0; - SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer - SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired); - if(!pdidd) - break; //Out of memory - - pdidd->cbSize = sizeof(*pdidd); - if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL)) - continue; - - HANDLE __attribute__((__cleanup__(wrapCloseHandle))) hBattery = - CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if(hBattery == INVALID_HANDLE_VALUE) - continue; - - BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation }; - - DWORD dwWait = 0; - DWORD dwOut; - - if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_TAG, &dwWait, sizeof(dwWait), &bqi.BatteryTag, sizeof(bqi.BatteryTag), &dwOut, NULL) && bqi.BatteryTag) - continue; - - BATTERY_INFORMATION bi = {0}; - if(!DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &bi, sizeof(bi), &dwOut, NULL)) - continue; - - if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY)) - continue; - - FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results); - - if(memcmp(bi.Chemistry, "PbAc", 4) == 0) - ffStrbufInitS(&battery->technology, "Lead Acid"); - else if(memcmp(bi.Chemistry, "LION", 4) == 0 || memcmp(bi.Chemistry, "Li-I", 4) == 0) - ffStrbufInitS(&battery->technology, "Lithium Ion"); - else if(memcmp(bi.Chemistry, "NiCd", 4) == 0) - ffStrbufInitS(&battery->technology, "Nickel Cadmium"); - else if(memcmp(bi.Chemistry, "NiMH", 4) == 0) - ffStrbufInitS(&battery->technology, "Nickel Metal Hydride"); - else if(memcmp(bi.Chemistry, "NiZn", 4) == 0) - ffStrbufInitS(&battery->technology, "Nickel Zinc"); - else if(memcmp(bi.Chemistry, "RAM\0", 4) == 0) - ffStrbufInitS(&battery->technology, "Rechargeable Alkaline-Manganese"); - else - ffStrbufInitS(&battery->technology, "Unknown"); - - { - ffStrbufInit(&battery->modelName); - bqi.InformationLevel = BatteryDeviceName; - wchar_t name[64]; - if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL)) - ffStrbufSetWS(&battery->modelName, name); - } - - { - ffStrbufInit(&battery->manufacturer); - bqi.InformationLevel = BatteryManufactureName; - wchar_t name[64]; - if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL)) - ffStrbufSetWS(&battery->manufacturer, name); - } - - battery->temperature = 0.0/0.0; - if(options->temp) - { - bqi.InformationLevel = BatteryTemperature; - ULONG temp; - if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL)) - battery->temperature = temp; - } - - { - BATTERY_STATUS bs; - BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag }; - if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY) - battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity; - else - battery->capacity = 0; - - ffStrbufInit(&battery->status); - if(bs.PowerState & BATTERY_POWER_ON_LINE) - ffStrbufAppendS(&battery->status, "AC Connected, "); - if(bs.PowerState & BATTERY_DISCHARGING) - ffStrbufAppendS(&battery->status, "Discharging, "); - if(bs.PowerState & BATTERY_CHARGING) - ffStrbufAppendS(&battery->status, "Charging"); - if(bs.PowerState & BATTERY_CRITICAL) - ffStrbufAppendS(&battery->status, "Critical, "); - ffStrbufTrimRight(&battery->status, ' '); - ffStrbufTrimRight(&battery->status, ','); - } - } - } - else - { - SYSTEM_BATTERY_STATE info; - if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent) - { - FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results); ffStrbufInit(&battery->modelName); - ffStrbufInit(&battery->manufacturer); - ffStrbufInit(&battery->technology); - ffStrbufInit(&battery->status); - battery->temperature = 0.0/0.0; + bqi.InformationLevel = BatteryDeviceName; + wchar_t name[64]; + if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL)) + ffStrbufSetWS(&battery->modelName, name); + } - battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity; - if(info.AcOnLine) - { - ffStrbufAppendS(&battery->status, "AC Connected"); - if(info.Charging) - ffStrbufAppendS(&battery->status, ", Charging"); - } - else if(info.Discharging) - ffStrbufAppendS(&battery->status, "Discharging"); + { + ffStrbufInit(&battery->manufacturer); + bqi.InformationLevel = BatteryManufactureName; + wchar_t name[64]; + if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), name, sizeof(name), &dwOut, NULL)) + ffStrbufSetWS(&battery->manufacturer, name); + } + + battery->cycleCount = bi.CycleCount; + + battery->temperature = 0.0/0.0; + if(options->temp) + { + bqi.InformationLevel = BatteryTemperature; + ULONG temp; + if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &temp, sizeof(temp), &dwOut, NULL)) + battery->temperature = temp; + } + + { + BATTERY_STATUS bs; + BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag }; + if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY) + battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity; + else + battery->capacity = 0; + + ffStrbufInit(&battery->status); + if(bs.PowerState & BATTERY_POWER_ON_LINE) + ffStrbufAppendS(&battery->status, "AC Connected, "); + if(bs.PowerState & BATTERY_DISCHARGING) + ffStrbufAppendS(&battery->status, "Discharging, "); + if(bs.PowerState & BATTERY_CHARGING) + ffStrbufAppendS(&battery->status, "Charging, "); + if(bs.PowerState & BATTERY_CRITICAL) + ffStrbufAppendS(&battery->status, "Critical, "); + ffStrbufTrimRight(&battery->status, ' '); + ffStrbufTrimRight(&battery->status, ','); } } - return NULL; } + +static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* results) +{ + SYSTEM_BATTERY_STATE info; + if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent) + { + FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results); + ffStrbufInit(&battery->modelName); + ffStrbufInit(&battery->manufacturer); + ffStrbufInit(&battery->technology); + ffStrbufInit(&battery->status); + battery->temperature = 0.0/0.0; + battery->cycleCount = 0; + + battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity; + if(info.AcOnLine) + { + ffStrbufAppendS(&battery->status, "AC Connected"); + if(info.Charging) + ffStrbufAppendS(&battery->status, ", Charging"); + } + else if(info.Discharging) + ffStrbufAppendS(&battery->status, "Discharging"); + return NULL; + } + return "NtPowerInformation(SystemBatteryState) failed"; +} + +const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) +{ + return true + ? detectWithSetupApi(options, results) + : detectWithNtApi(options, results); +} diff --git a/src/detection/bios/bios.h b/src/detection/bios/bios.h index 84046ad40..04d55811c 100644 --- a/src/detection/bios/bios.h +++ b/src/detection/bios/bios.h @@ -11,6 +11,7 @@ typedef struct FFBiosResult FFstrbuf release; FFstrbuf vendor; FFstrbuf version; + FFstrbuf type; } FFBiosResult; const char* ffDetectBios(FFBiosResult* bios); diff --git a/src/detection/bios/bios_android.c b/src/detection/bios/bios_android.c index 737df08de..b2b20aaf9 100644 --- a/src/detection/bios/bios_android.c +++ b/src/detection/bios/bios_android.c @@ -9,5 +9,7 @@ const char* ffDetectBios(FFBiosResult* bios) if (ffStrbufIgnCaseEqualS(&bios->version, "unknown")) ffStrbufClear(&bios->version); + ffStrbufSetStatic(&bios->type, "Bootloader"); + return NULL; } diff --git a/src/detection/bios/bios_apple.c b/src/detection/bios/bios_apple.c index 3ebc1f468..34b7da1d4 100644 --- a/src/detection/bios/bios_apple.c +++ b/src/detection/bios/bios_apple.c @@ -23,7 +23,7 @@ const char* ffDetectBios(FFBiosResult* bios) ffCfDictGetString(properties, CFSTR("vendor"), &bios->vendor); ffCfDictGetString(properties, CFSTR("version"), &bios->version); ffCfDictGetString(properties, CFSTR("release-date"), &bios->date); - ffStrbufAppendS(&bios->release, "Efi"); + ffStrbufSetStatic(&bios->type, "UEFI"); CFRelease(properties); IOObjectRelease(registryEntry); @@ -54,12 +54,12 @@ const char* ffDetectBios(FFBiosResult* bios) uint32_t index = ffStrbufFirstIndexC(&bios->version, '-'); if (index != bios->version.length) { - ffStrbufAppendNS(&bios->release, index, bios->version.chars); + ffStrbufAppendNS(&bios->type, index, bios->version.chars); ffStrbufRemoveSubstr(&bios->version, 0, index + 1); } else { - ffStrbufAppendS(&bios->release, "iBoot"); + ffStrbufSetStatic(&bios->type, "iBoot"); } CFRelease(properties); } diff --git a/src/detection/bios/bios_bsd.c b/src/detection/bios/bios_bsd.c index 26c0dd1b5..6111b4315 100644 --- a/src/detection/bios/bios_bsd.c +++ b/src/detection/bios/bios_bsd.c @@ -1,6 +1,7 @@ #include "bios.h" #include "common/settings.h" +#include "common/sysctl.h" #include "util/smbiosHelper.h" const char* ffDetectBios(FFBiosResult* result) @@ -13,5 +14,6 @@ const char* ffDetectBios(FFBiosResult* result) ffCleanUpSmbiosValue(&result->vendor); ffSettingsGetFreeBSDKenv("smbios.bios.version", &result->version); ffCleanUpSmbiosValue(&result->version); + ffSysctlGetString("machdep.bootmethod", &result->type); return NULL; } diff --git a/src/detection/bios/bios_linux.c b/src/detection/bios/bios_linux.c index fc8cba62b..2c7402c90 100644 --- a/src/detection/bios/bios_linux.c +++ b/src/detection/bios/bios_linux.c @@ -23,5 +23,9 @@ const char* ffDetectBios(FFBiosResult* bios) getSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release); getSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor); getSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version); + if (ffPathExists("/sys/firmware/efi", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE)) + ffStrbufSetStatic(&bios->type, "UEFI"); + else + ffStrbufSetStatic(&bios->type, "BIOS"); return NULL; } diff --git a/src/detection/bios/bios_windows.c b/src/detection/bios/bios_windows.c index 69930a178..5adfbdd0d 100644 --- a/src/detection/bios/bios_windows.c +++ b/src/detection/bios/bios_windows.c @@ -2,6 +2,30 @@ #include "util/windows/registry.h" #include "util/smbiosHelper.h" +#include +#include + +typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION +{ + GUID BootIdentifier; + FIRMWARE_TYPE FirmwareType; + union + { + ULONGLONG BootFlags; + struct + { + ULONGLONG DbgMenuOsSelection : 1; // REDSTONE4 + ULONGLONG DbgHiberBoot : 1; + ULONGLONG DbgSoftBoot : 1; + ULONGLONG DbgMeasuredLaunch : 1; + ULONGLONG DbgMeasuredLaunchCapable : 1; // 19H1 + ULONGLONG DbgSystemHiveReplace : 1; + ULONGLONG DbgMeasuredLaunchSmmProtections : 1; + ULONGLONG DbgMeasuredLaunchSmmLevel : 7; // 20H1 + }; + }; +} SYSTEM_BOOT_ENVIRONMENT_INFORMATION; + const char* ffDetectBios(FFBiosResult* bios) { FF_HKEY_AUTO_DESTROY hKey = NULL; @@ -24,5 +48,18 @@ const char* ffDetectBios(FFBiosResult* bios) ) ffStrbufAppendF(&bios->release, "%u.%u", (unsigned)major, (unsigned)minor); + // Same as GetFirmwareType, but support (?) Windows 7 + // https://ntdoc.m417z.com/system_information_class + SYSTEM_BOOT_ENVIRONMENT_INFORMATION sbei; + if (NT_SUCCESS(NtQuerySystemInformation(90 /*SystemBootEnvironmentInformation*/, &sbei, sizeof(sbei), NULL))) + { + switch (sbei.FirmwareType) + { + case FirmwareTypeBios: ffStrbufSetStatic(&bios->type, "BIOS"); break; + case FirmwareTypeUefi: ffStrbufSetStatic(&bios->type, "UEFI"); break; + default: break; + } + } + return NULL; } diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 9acae0aa8..4b190cfc7 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -83,12 +83,10 @@ static double getFrequency(const char* info, const char* scaling) static double detectCPUTemp(void) { - const FFTempsResult* temps = ffDetectTemps(); + const FFlist* tempsResult = ffDetectTemps(); - for(uint32_t i = 0; i < temps->values.length; i++) + FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) { - FFTempValue* value = ffListGet(&temps->values, i); - if( ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length || ffStrbufCompS(&value->name, "k10temp") == 0 || diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index e6056d744..0404a5fef 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -138,12 +138,10 @@ static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* device) { - const FFTempsResult* tempsResult = ffDetectTemps(); + const FFlist* tempsResult = ffDetectTemps(); - for(uint32_t i = 0; i < tempsResult->values.length; i++) + FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult) { - FFTempValue* tempValue = ffListGet(&tempsResult->values, i); - //The kernel exposes the device class multiplied by 256 for some reason if(tempValue->deviceClass == device->device_class * 256) { diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 1f319ad34..afc97e28d 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -80,8 +80,17 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) continue; struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr; - char addressBuffer[INET_ADDRSTRLEN]; + char addressBuffer[INET_ADDRSTRLEN + 4]; inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN); + + struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask; + int cidr = __builtin_popcount(inet_netof(netmask->sin_addr)); + if (cidr != 0) + { + size_t len = strlen(addressBuffer); + snprintf(addressBuffer + len, 4, "/%d", cidr); + } + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute); } else if (ifa->ifa_addr->sa_family == AF_INET6) diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index bb39b4325..3bbdddd8b 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -105,8 +105,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (ifa->Address.lpSockaddr->sa_family == AF_INET) { SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr; - char addressBuffer[INET_ADDRSTRLEN]; + char addressBuffer[INET_ADDRSTRLEN + 4]; inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN); + + if (ifa->OnLinkPrefixLength) + { + size_t len = strlen(addressBuffer); + snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength); + } + addNewIp(results, name, addressBuffer, AF_INET, newIp, isDefaultRoute); newIp = false; } diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index 1599321f1..e9b51215a 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -41,23 +41,21 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) return value->name.length > 0 || value->deviceClass > 0; } -const FFTempsResult* ffDetectTemps(void) +const FFlist* ffDetectTemps(void) { - static FFTempsResult result; - static bool init = false; + static FFlist result; - if(init) + if(result.elementSize > 0) return &result; - init = true; - ffListInitA(&result.values, sizeof(FFTempValue), 16); + ffListInitA(&result, sizeof(FFTempValue), 16); FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); ffStrbufAppendS(&baseDir, "/sys/class/hwmon/"); uint32_t baseDirLength = baseDir.length; - DIR* dirp = opendir(baseDir.chars); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); if(dirp == NULL) return &result; @@ -70,19 +68,17 @@ const FFTempsResult* ffDetectTemps(void) ffStrbufAppendS(&baseDir, entry->d_name); ffStrbufAppendC(&baseDir, '/'); - FFTempValue* temp = ffListAdd(&result.values); + FFTempValue* temp = ffListAdd(&result); ffStrbufInit(&temp->name); temp->deviceClass = 0; if(!parseHwmonDir(&baseDir, temp)) { ffStrbufDestroy(&temp->name); - --result.values.length; + --result.length; } ffStrbufSubstrBefore(&baseDir, baseDirLength); } - closedir(dirp); - return &result; } diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h index 569bd0401..f99dd4138 100644 --- a/src/detection/temps/temps_linux.h +++ b/src/detection/temps/temps_linux.h @@ -12,11 +12,6 @@ typedef struct FFTempValue double value; } FFTempValue; -typedef struct FFTempsResult -{ - FFlist values; //List of FFTempValue -} FFTempsResult; - -const FFTempsResult* ffDetectTemps(); +const FFlist* /* List of FFTempValue */ ffDetectTemps(); #endif diff --git a/src/flashfetch.c b/src/flashfetch.c index 72e93cf56..e35b84c93 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -45,13 +45,13 @@ int main(void) ffPrintMemory(&options->memory); ffPrintSwap(&options->swap); ffPrintDisk(&options->disk); + ffPrintLocalIp(&options->localIP); + // ffPrintPublicIp(&options->publicIP); + //ffPrintWifi(&options->wifi); ffPrintBattery(&options->battery); ffPrintPowerAdapter(&options->powerAdapter); //ffPrintPlayer(&options->player); //ffPrintMedia(&options->media); - //ffPrintLocalIp(&options->localIp); - //ffPrintPublicIp(&options->publicIp); - //ffPrintWifi(&options->wifi); //ffPrintCPUUsage(&options->cpuUsage); ffPrintLocale(&options->locale); //ffPrintDateTime(&options->dateTime); diff --git a/src/logo/ascii/nixos_old_small.txt b/src/logo/ascii/nixos_old_small.txt new file mode 100644 index 000000000..4ca2f52c5 --- /dev/null +++ b/src/logo/ascii/nixos_old_small.txt @@ -0,0 +1,7 @@ +$1 \\ $2\\ // +$1 ==\\__$2\\/ $1// +$2 // $2\\$1// +$2==// $1//== +$2 //$1\\$2___$1// +$2// $1/\\ $2\\== + $1// \\ $2\\ diff --git a/src/logo/ascii/nixos_small.txt b/src/logo/ascii/nixos_small.txt index be1b628a3..3e46ea598 100644 --- a/src/logo/ascii/nixos_small.txt +++ b/src/logo/ascii/nixos_small.txt @@ -1,7 +1,7 @@ - \\ \\ // - ==\\__\\/ // - // \\// -==// //== - //\\___// -// /\\ \\== - // \\ \\ +$1 ▗▄ $2▗▄ ▄▖ +$1 ▄▄🬸█▄▄▄$2🬸█▛ $1▃ +$2 ▟▛ ▜$1▃▟🬕 +$2🬋🬋🬫█ $1█🬛🬋🬋 +$2 🬷▛🮃$1▙ ▟▛ +$2 🮃 $1▟█🬴$2▀▀▀█🬴▀▀ +$1 ▝▀ ▀▘ $2▀▘ diff --git a/src/logo/builtin.c b/src/logo/builtin.c index d9252f561..9f1c051cf 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -2596,48 +2596,41 @@ static const FFlogo N[] = { }, // NixOS { - .names = {"NixOS", "nix", "nixos-linux", "nix-linux", "nix-os", "nix_os", "nix_os_linux"}, + .names = {"NixOS", "nix", "nixos-linux", "nix-linux"}, .lines = FASTFETCH_DATATEXT_LOGO_NIXOS, .colors = { FF_COLOR_FG_BLUE, FF_COLOR_FG_CYAN, }, - .colorKeys = FF_COLOR_FG_CYAN, - .colorTitle = FF_COLOR_FG_BLUE, }, - // NixOS_small + // NixOSSmall { - .names = {"NixOS_small", "nix_small"}, + .names = {"NixOS_small", "nix_small", "nixos-linux-small", "nix-linux-small"}, .lines = FASTFETCH_DATATEXT_LOGO_NIXOS_SMALL, .colors = { FF_COLOR_FG_BLUE, FF_COLOR_FG_CYAN, }, - .colorKeys = FF_COLOR_FG_CYAN, - .colorTitle = FF_COLOR_FG_BLUE, }, - // NixOsOld + // NixOSOld { - .names = {"nixos_old", "nix-old", "nixos-old", "nix_old", "nix-os-old", "nix_os_old"}, + .names = {"nixos_old", "nix-old", "nixos-old", "nix_old"}, .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .lines = FASTFETCH_DATATEXT_LOGO_NIXOS_OLD, .colors = { FF_COLOR_FG_BLUE, FF_COLOR_FG_CYAN, }, - .colorKeys = FF_COLOR_FG_CYAN, - .colorTitle = FF_COLOR_FG_BLUE, }, - // NixOsSmall + // NixOsOldSmall { - .names = {"nixos_small", "nix-small", "nixos-small", "nix_small", "nix-os-small", "nix_os_small"}, - .type = FF_LOGO_LINE_TYPE_SMALL_BIT, - .lines = FASTFETCH_DATATEXT_LOGO_NIXOS_SMALL, + .names = {"nixos_old_small", "nix-old-small", "nixos-old-small", "nix_old_small"}, + .type = FF_LOGO_LINE_TYPE_SMALL_BIT | FF_LOGO_LINE_TYPE_ALTER_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_NIXOS_OLD_SMALL, .colors = { FF_COLOR_FG_BLUE, + FF_COLOR_FG_CYAN, }, - .colorKeys = FF_COLOR_FG_BLUE, - .colorTitle = FF_COLOR_FG_BLUE, }, // NetBSD { diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 6164585f5..ac5d405b4 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -95,7 +95,7 @@ static bool printImageIterm(void) ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\n", (unsigned) options->width, (unsigned) options->height, - (unsigned) options->preserveAspectRadio, + (unsigned) options->preserveAspectRatio, base64.chars ); diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index afa0e2e60..1ad586f79 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -6,7 +6,7 @@ #include "modules/battery/battery.h" #include "util/stringUtils.h" -#define FF_BATTERY_NUM_FORMAT_ARGS 5 +#define FF_BATTERY_NUM_FORMAT_ARGS 7 static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uint8_t index) { @@ -70,6 +70,7 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin {FF_FORMAT_ARG_TYPE_STRBUF, &capacityStr}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->status}, {FF_FORMAT_ARG_TYPE_DOUBLE, &result->temperature}, + {FF_FORMAT_ARG_TYPE_UINT, &result->cycleCount}, }); } } @@ -215,6 +216,7 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "status", &battery->status); yyjson_mut_obj_add_strbuf(doc, obj, "technology", &battery->technology); yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature); + yyjson_mut_obj_add_uint(doc, obj, "cycleCount", battery->cycleCount); } FF_LIST_FOR_EACH(FFBatteryResult, battery, results) @@ -233,7 +235,9 @@ void ffPrintBatteryHelpFormat(void) "Battery model", "Battery technology", "Battery capacity (percentage)", - "Battery status" + "Battery status", + "Battery temperature", + "Battery cycle count", }); } diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index e9b7e3a2b..bc7d9bec1 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -4,7 +4,7 @@ #include "modules/bios/bios.h" #include "util/stringUtils.h" -#define FF_BIOS_NUM_FORMAT_ARGS 4 +#define FF_BIOS_NUM_FORMAT_ARGS 5 void ffPrintBios(FFBiosOptions* options) { @@ -13,9 +13,12 @@ void ffPrintBios(FFBiosOptions* options) ffStrbufInit(&bios.release); ffStrbufInit(&bios.vendor); ffStrbufInit(&bios.version); + ffStrbufInit(&bios.type); const char* error = ffDetectBios(&bios); + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + if(error) { ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, "%s", error); @@ -28,21 +31,40 @@ void ffPrintBios(FFBiosOptions* options) goto exit; } - if(options->moduleArgs.outputFormat.length == 0) + if(options->moduleArgs.key.length == 0) { - ffPrintLogoAndKey(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufWriteTo(&bios.version, stdout); - if (bios.release.length) - printf(" (%s)", bios.release.chars); - putchar('\n'); + if(bios.type.length == 0) + ffStrbufSetStatic(&bios.type, "Unknown"); + else if (ffStrbufIgnCaseEqualS(&bios.type, "BIOS")) + ffStrbufSetStatic(&bios.type, "Legacy"); + + ffStrbufSetF(&key, FF_BIOS_MODULE_NAME " (%s)", bios.type.chars); } else { - ffPrintFormat(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, FF_BIOS_NUM_FORMAT_ARGS, (FFformatarg[]) { + ffStrbufClear(&key); + ffParseFormatString(&key, &options->moduleArgs.key, 3, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &bios.type}, + }); + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufWriteTo(&bios.version, stdout); + if (bios.release.length) + printf(" (%s)\n", bios.release.chars); + else + putchar('\n'); + } + else + { + ffPrintFormat(key.chars, 0, &options->moduleArgs, FF_BIOS_NUM_FORMAT_ARGS, (FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &bios.date}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.release}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.vendor}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.version}, + {FF_FORMAT_ARG_TYPE_STRBUF, &bios.type}, }); } @@ -51,6 +73,7 @@ exit: ffStrbufDestroy(&bios.release); ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); + ffStrbufDestroy(&bios.type); } bool ffParseBiosCommandOptions(FFBiosOptions* options, const char* key, const char* value) @@ -95,6 +118,7 @@ void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut ffStrbufInit(&bios.release); ffStrbufInit(&bios.vendor); ffStrbufInit(&bios.version); + ffStrbufInit(&bios.type); const char* error = ffDetectBios(&bios); @@ -115,12 +139,14 @@ void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, obj, "release", &bios.release); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &bios.vendor); yyjson_mut_obj_add_strbuf(doc, obj, "version", &bios.version); + yyjson_mut_obj_add_strbuf(doc, obj, "type", &bios.type); exit: ffStrbufDestroy(&bios.date); ffStrbufDestroy(&bios.release); ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); + ffStrbufDestroy(&bios.type); } void ffPrintBiosHelpFormat(void) @@ -129,7 +155,8 @@ void ffPrintBiosHelpFormat(void) "bios date", "bios release", "bios vendor", - "bios version" + "bios version", + "firmware type", }); } diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 14bbf7afc..398536261 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -180,6 +180,7 @@ void ffInitCPUUsageOptions(FFCPUUsageOptions* options) ffGenerateCPUUsageJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs); + options->separate = false; } void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 0e2811c96..442875590 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -148,6 +148,7 @@ void ffInitWMOptions(FFWMOptions* options) ffGenerateWMJsonConfig ); ffOptionInitModuleArg(&options->moduleArgs); + options->detectPlugin = false; } void ffDestroyWMOptions(FFWMOptions* options) diff --git a/src/options/display.c b/src/options/display.c index a25dd1ca1..3236a7b1d 100644 --- a/src/options/display.c +++ b/src/options/display.c @@ -303,7 +303,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) ffStrbufInitStatic(&options->barCharTotal, "-"); options->barWidth = 10; options->barBorder = true; - options->percentType = 1; + options->percentType = 9; options->percentNdigits = 0; } diff --git a/src/options/logo.c b/src/options/logo.c index 1d305e3b9..0e78bf0c1 100644 --- a/src/options/logo.c +++ b/src/options/logo.c @@ -15,7 +15,7 @@ void ffOptionsInitLogo(FFOptionsLogo* options) options->paddingLeft = 0; options->paddingRight = 4; options->printRemaining = true; - options->preserveAspectRadio = false; + options->preserveAspectRatio = false; options->recache = false; options->separate = false; @@ -113,8 +113,8 @@ logoType: options->paddingRight = ffOptionParseUInt32(key, value); else if(strcasecmp(subKey, "print-remaining") == 0) options->printRemaining = ffOptionParseBoolean(value); - else if(strcasecmp(subKey, "preserve-aspect-radio") == 0) - options->preserveAspectRadio = ffOptionParseBoolean(value); + else if(strcasecmp(subKey, "preserve-aspect-ratio") == 0) + options->preserveAspectRatio = ffOptionParseBoolean(value); else if(strcasecmp(subKey, "recache") == 0) options->recache = ffOptionParseBoolean(value); else if(strcasecmp(subKey, "separate") == 0) @@ -327,9 +327,9 @@ const char* ffOptionsParseLogoJsonConfig(FFOptionsLogo* options, yyjson_val* roo options->printRemaining = yyjson_get_bool(val); continue; } - else if (strcasecmp(key, "preserveAspectRadio") == 0) + else if (strcasecmp(key, "preserveAspectRatio") == 0) { - options->preserveAspectRadio = yyjson_get_bool(val); + options->preserveAspectRatio = yyjson_get_bool(val); continue; } else if (strcasecmp(key, "recache") == 0) @@ -504,8 +504,8 @@ void ffOptionsGenerateLogoJsonConfig(FFOptionsLogo* options, yyjson_mut_doc* doc if (options->printRemaining != defaultOptions.printRemaining) yyjson_mut_obj_add_bool(doc, obj, "printRemaining", options->printRemaining); - if (options->preserveAspectRadio != defaultOptions.preserveAspectRadio) - yyjson_mut_obj_add_bool(doc, obj, "preserveAspectRadio", options->preserveAspectRadio); + if (options->preserveAspectRatio != defaultOptions.preserveAspectRatio) + yyjson_mut_obj_add_bool(doc, obj, "preserveAspectRatio", options->preserveAspectRatio); if (options->recache != defaultOptions.recache) yyjson_mut_obj_add_bool(doc, obj, "recache", options->recache); diff --git a/src/options/logo.h b/src/options/logo.h index dd370471e..c5bb6fb3e 100644 --- a/src/options/logo.h +++ b/src/options/logo.h @@ -34,7 +34,7 @@ typedef struct FFOptionsLogo uint32_t paddingLeft; uint32_t paddingRight; bool printRemaining; - bool preserveAspectRadio; + bool preserveAspectRatio; bool recache; bool separate;