diff --git a/.codespellrc b/.codespellrc index 9e972389e..2de890a80 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 -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73d7a20c7..7de15b0a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -272,47 +272,6 @@ jobs: name: fastfetch-musl-amd64 path: ./fastfetch-*.* - musl-aarch64: - name: Musl-aarch64 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: setup alpine linux - uses: jirutka/setup-alpine@master - with: - branch: v3.19 - arch: aarch64 - - - name: install dependencies - run: | - cat /etc/alpine-release - uname -a - apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++ - shell: alpine.sh --root {0} - - - name: build - run: | - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -GNinja . - cmake --build . --target package --verbose -j4 - shell: alpine.sh {0} - - - name: run - run: | - ./fastfetch --list-features - time ./fastfetch -c presets/ci.jsonc --stat false - time ./fastfetch -c presets/ci.jsonc --format json - time ./flashfetch - ldd fastfetch - ctest - shell: alpine.sh {0} - - - name: upload artifacts - uses: actions/upload-artifact@v4 - with: - name: fastfetch-musl-aarch64 - path: ./fastfetch-*.* - macos-universal: name: macOS-universal runs-on: macos-12 @@ -555,9 +514,9 @@ jobs: - name: setup-msys2 uses: msys2/setup-msys2@v2 with: - msystem: CLANG32 + msystem: MINGW32 update: true - install: git p7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd mingw-w64-clang-i686-opencl-headers + install: git p7zip mingw-w64-i686-cmake mingw-w64-i686-clang mingw-w64-i686-vulkan-loader mingw-w64-i686-vulkan-headers mingw-w64-i686-opencl-icd mingw-w64-i686-opencl-headers - name: print msys version run: uname -a @@ -568,7 +527,7 @@ jobs: languages: c, cpp - name: configure project - run: env PKG_CONFIG_PATH=/clang32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + run: env PKG_CONFIG_PATH=/mingw32/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . - name: build project run: cmake --build . --verbose -j4 @@ -577,7 +536,7 @@ jobs: uses: github/codeql-action/analyze@v3 - name: copy necessary dlls - run: cp /clang32/bin/{OpenCL,vulkan-1}.dll . + run: cp /mingw32/bin/{OpenCL,vulkan-1}.dll . - name: download amd_ags run: curl -LO https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/raw/master/ags_lib/lib/amd_ags_x86.dll @@ -619,7 +578,6 @@ jobs: - linux-armv7 - linux-riscv64 - musl-amd64 - - musl-aarch64 - macos-universal - freebsd-amd64 - openbsd-amd64 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1388995f6..556a6a852 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +# 2.28.0 + +Features: +* Add new module `Mouse` and `Keyboard` which display connected mice and keyboards +* Support remaining time detection (Battery) +* Report if AC is connected (Battery, Linux) +* Report platform API used for display detection for debugging (Display) +* Report Wine version when running in Wine (Kernel, Windows) +* Add option `waitTime` in modules `CPUUsage`, `DiskIO` and `NetIO` + +Bugfixes: +* Fix used memory size detection (Memory, OpenBSD) +* Don't report invalid fragmentation percentage when fails to detect it (Zpool) +* Fix unexpected errors when running fastfetch in parallel (#1346, Windows) +* Don't report obviously invalid temperature values (PhysicalDisk, Linux) + +Logos: +* Add eweOS +* Add MidOS +* Update XeroArch + # 2.27.1 Bugfixes: @@ -8,7 +29,7 @@ Bugfixes: Changes: * We now print `"` instead of `″` when displaying diagonal length in inches, so that the character can be correctly displayed in Linux console (Display) * All detection code of `monitor` module is merged into `display` module. Now `monitor` just prints the same information as `display` with different format. Notably: - * The resolution reported by `monitor` module is now current resolution instead of native / maximum resolution. PPI is calcuated based on current resolution too. + * The resolution reported by `monitor` module is now current resolution instead of native / maximum resolution. PPI is calculated based on current resolution too. * The refresh rate reported by `monitor` module is the current refresh rate. Features: @@ -24,7 +45,7 @@ Bugfixes: * Remove trailing newline in GPU name for Raspberry pi (#1303, GPU, Linux) * Fix a possible buffer overflow (GPU, Linux) * Fix CPU temp incorrectly reported as 0 celsius (#1308, CPU, Linux) -* Corrently report `TPM device is not found` error (#1314, TPM, Windows) +* Correctly report `TPM device is not found` error (#1314, TPM, Windows) * Fix errors when triggering shell completion with python3 uninstalled (#1310) * To package managers: as shell completion scripts of fastfetch use python3, it should be added as an optional dependency of fastfetch * Fix possible crashes when detecting term font of kitty (#1321, TerminalFont, Linux) diff --git a/CMakeLists.txt b/CMakeLists.txt index b30be6d45..3a63bb64d 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.27.1 + VERSION 2.28.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -379,6 +379,7 @@ set(LIBFASTFETCH_SRC src/modules/initsystem/initsystem.c src/modules/gamepad/gamepad.c src/modules/kernel/kernel.c + src/modules/keyboard/keyboard.c src/modules/lm/lm.c src/modules/loadavg/loadavg.c src/modules/locale/locale.c @@ -402,6 +403,7 @@ set(LIBFASTFETCH_SRC src/modules/sound/sound.c src/modules/swap/swap.c src/modules/media/media.c + src/modules/mouse/mouse.c src/modules/terminal/terminal.c src/modules/terminaltheme/terminaltheme.c src/modules/terminalfont/terminalfont.c @@ -478,6 +480,7 @@ if(LINUX) src/detection/host/host_linux.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_linux.c src/detection/libc/libc_linux.c src/detection/lm/lm_linux.c src/detection/loadavg/loadavg_linux.c @@ -486,6 +489,7 @@ if(LINUX) src/detection/gamepad/gamepad_linux.c src/detection/media/media_linux.c src/detection/memory/memory_linux.c + src/detection/mouse/mouse_linux.c src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -542,6 +546,7 @@ elseif(ANDROID) src/detection/host/host_android.c src/detection/icons/icons_nosupport.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_nosupport.c src/detection/libc/libc_android.c src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_linux.c @@ -550,6 +555,7 @@ elseif(ANDROID) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_nosupport.c src/detection/memory/memory_linux.c + src/detection/mouse/mouse_nosupport.c src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_android.c @@ -622,6 +628,7 @@ elseif(FreeBSD) src/detection/lm/lm_linux.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_bsd.c src/detection/libc/libc_bsd.c src/detection/loadavg/loadavg_bsd.c src/detection/locale/locale_linux.c @@ -629,6 +636,7 @@ elseif(FreeBSD) src/detection/gamepad/gamepad_bsd.c src/detection/media/media_linux.c src/detection/memory/memory_bsd.c + src/detection/mouse/mouse_bsd.c src/detection/netio/netio_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -701,6 +709,7 @@ elseif(OpenBSD) src/detection/lm/lm_nosupport.c src/detection/icons/icons_linux.c src/detection/initsystem/initsystem_linux.c + src/detection/keyboard/keyboard_nosupport.c src/detection/libc/libc_nosupport.c src/detection/loadavg/loadavg_bsd.c src/detection/locale/locale_linux.c @@ -708,6 +717,7 @@ elseif(OpenBSD) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_obsd.c + src/detection/mouse/mouse_nosupport.c src/detection/netio/netio_nosupport.c src/detection/opengl/opengl_linux.c src/detection/os/os_obsd.c @@ -766,6 +776,7 @@ elseif(APPLE) src/detection/host/host_apple.c 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/loadavg/loadavg_bsd.c src/detection/libc/libc_apple.c @@ -774,6 +785,7 @@ elseif(APPLE) src/detection/gamepad/gamepad_apple.c src/detection/media/media_apple.m src/detection/memory/memory_apple.c + src/detection/mouse/mouse_apple.c src/detection/netio/netio_bsd.c src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m @@ -832,6 +844,7 @@ elseif(WIN32) src/detection/host/host_windows.c src/detection/icons/icons_windows.c src/detection/initsystem/initsystem_nosupport.c + src/detection/keyboard/keyboard_windows.c src/detection/libc/libc_windows.cpp src/detection/lm/lm_nosupport.c src/detection/loadavg/loadavg_nosupport.c @@ -840,10 +853,11 @@ elseif(WIN32) src/detection/gamepad/gamepad_windows.c src/detection/media/media_windows.c src/detection/memory/memory_windows.c + src/detection/mouse/mouse_windows.c src/detection/physicalmemory/physicalmemory_linux.c src/detection/netio/netio_windows.c src/detection/opengl/opengl_windows.c - src/detection/os/os_windows.cpp + src/detection/os/os_windows.c src/detection/packages/packages_windows.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_windows.c @@ -916,6 +930,7 @@ elseif(SunOS) src/detection/host/host_windows.c src/detection/icons/icons_linux.c 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/loadavg/loadavg_sunos.c @@ -924,6 +939,7 @@ elseif(SunOS) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_sunos.c + src/detection/mouse/mouse_nosupport.c src/detection/netio/netio_sunos.c src/detection/opengl/opengl_linux.c src/detection/os/os_sunos.c @@ -1026,10 +1042,12 @@ if(FreeBSD AND EXISTS "/usr/local/bin/objdump") endif() endif() -if(LINUX OR ANDROID) - target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1 _FILE_OFFSET_BITS=64) +if(LINUX) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _ATFILE_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64) # "$<$:_FORTIFY_SOURCE=3>" +elseif(ANDROID) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _FILE_OFFSET_BITS=64 "$<$:__BIONIC_FORTIFY>" "$<$:__BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED>") elseif(WIN32) - target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00) # "$<$:_FORTIFY_SOURCE=3>" elseif(APPLE) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _DARWIN_C_SOURCE) elseif(OpenBSD) @@ -1298,6 +1316,8 @@ elseif(WIN32) PRIVATE "hid" PRIVATE "wtsapi32" PRIVATE "imagehlp" + PRIVATE "cfgmgr32" + PRIVATE "winbrand" ) elseif(FreeBSD) target_link_libraries(libfastfetch diff --git a/debian/changelog b/debian/changelog index 3eff4467a..42685d71b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fastfetch (2.27.1) jammy; urgency=medium + + * Update to 2.27.1 + + -- Carter Li Sun, 06 Oct 2024 12:55:18 +0800 + fastfetch (2.26.1ubuntu1) jammy; urgency=medium * Update correct code diff --git a/debian/files b/debian/files index 8a4ba4133..a5daf6ddf 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.26.1ubuntu1_source.buildinfo universe/utils optional +fastfetch_2.27.1_source.buildinfo universe/utils optional diff --git a/doc/json_schema.json b/doc/json_schema.json index c9bf60831..6c30442c4 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1181,6 +1181,12 @@ "description": "Display CPU usage per CPU logical core, instead of an average result", "default": false }, + "waitTime": { + "type": "integer", + "description": "Wait time (in ms). CPU usage = (inUseEnd - inUseStart) / waitTime", + "default": 200, + "minimum": 1 + }, "key": { "$ref": "#/$defs/key" }, @@ -1472,6 +1478,12 @@ "type": "boolean", "default": false }, + "waitTime": { + "type": "integer", + "description": "Wait time (in ms). Disk I/O = (totalBytesEnd - totalBytesStart) / waitTime", + "default": 200, + "minimum": 1 + }, "key": { "$ref": "#/$defs/key" }, @@ -1841,6 +1853,12 @@ "type": "boolean", "default": false }, + "waitTime": { + "type": "integer", + "description": "Wait time (in ms). Disk I/O = (totalBytesEnd - totalBytesStart) / waitTime", + "default": 200, + "minimum": 1 + }, "key": { "$ref": "#/$defs/key" }, diff --git a/presets/all.jsonc b/presets/all.jsonc index 8e4da85d6..6b5469272 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -74,7 +74,8 @@ "showSpeed": true, "showMtu": true, "showLoop": true, - "showFlags": true + "showFlags": true, + "showAllIps": true }, "dns", "wifi", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 6431509c2..438054135 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -76,7 +76,8 @@ "showSpeed": true, "showMtu": true, "showLoop": true, - "showFlags": true + "showFlags": true, + "showAllIps": true }, "dns", "wifi", diff --git a/run.sh b/run.sh index aebcfc9d9..55071e400 100755 --- a/run.sh +++ b/run.sh @@ -5,18 +5,22 @@ set -e mkdir -p build/ cd build/ -if [ -z "${CMAKE_BUILD_TYPE}" ]; then - CMAKE_BUILD_TYPE=Release -fi -cmake "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" .. +cmake .. -if [ -z "$OSTYPE" ] || [ "$OSTYPE" = "linux-gnu" ]; then - cmake_build_args="-j$(nproc)" -elif [ "$OSTYPE" = "darwin" ]; then - cmake_build_args="-j$(sysctl -n hw.ncpu)" -else - cmake_build_args="" -fi -cmake --build . --target fastfetch ${cmake_build_args} +kernel_name="$(uname -s)" + +case "${kernel_name}" in + "Linux" | "MINGW"*) + cmake_build_args="-j$(nproc)" + ;; + "Darwin" | *"BSD" | "DragonFly") + cmake_build_args="-j$(sysctl -n hw.ncpu)" + ;; + *) + cmake_build_args="" + ;; +esac + +cmake --build . --target fastfetch "${cmake_build_args}" ./fastfetch "$@" diff --git a/src/common/format.h b/src/common/format.h index 580fc06c2..79e1c90f4 100644 --- a/src/common/format.h +++ b/src/common/format.h @@ -43,6 +43,6 @@ typedef struct FFformatarg void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg); void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t numArgs, const FFformatarg* arguments); #define FF_PARSE_FORMAT_STRING_CHECKED(buffer, formatstr, numArgs, arguments) do {\ - static_assert(sizeof(arguments) / sizeof(*(arguments)) == (numArgs), "Invalid number of format arguments");\ + static_assert(sizeof(arguments) / sizeof(*arguments) == (numArgs), "Invalid number of format arguments");\ ffParseFormatString((buffer), (formatstr), (numArgs), (arguments));\ } while (0) diff --git a/src/common/io/io.h b/src/common/io/io.h index 9a76838f4..84b3ec988 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -13,6 +13,8 @@ #include #include #include + #include + #include typedef int FFNativeFD; #define FF_INVALID_FD (-1) // procfs's file can be changed between read calls such as /proc/meminfo and /proc/uptime. @@ -66,9 +68,11 @@ static inline ssize_t ffReadFDData(FFNativeFD fd, size_t dataSize, void* data) } ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data); +ssize_t ffReadFileDataRelative(FFNativeFD dfd, const char* fileName, size_t dataSize, void* data); bool ffAppendFDBuffer(FFNativeFD fd, FFstrbuf* buffer); bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer); +bool ffAppendFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer); static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer) { @@ -76,6 +80,12 @@ static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer) return ffAppendFileBuffer(fileName, buffer); } +static inline bool ffReadFileBufferRelative(FFNativeFD dfd, const char* fileName, FFstrbuf* buffer) +{ + ffStrbufClear(buffer); + return ffAppendFileBufferRelative(dfd, fileName, buffer); +} + //Bit flags, combine with | typedef enum FFPathType { @@ -108,17 +118,22 @@ static inline bool ffPathExists(const char* path, FFPathType pathType) } else { - struct stat fileStat; - if(stat(path, &fileStat) != 0) - return false; - - unsigned int mode = fileStat.st_mode & S_IFMT; - - if(pathType & FF_PATHTYPE_FILE && mode != S_IFDIR) - return true; - - if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR) - return true; + size_t len = strlen(path); + assert(len < PATH_MAX); + if (len == 0) return false; + + int ret; + if (path[len - 1] != '/') + { + char buf[PATH_MAX + 1]; + memcpy(buf, path, len); + buf[len] = '/'; + buf[len + 1] = 0; + ret = access(buf, F_OK); + } + else + ret = access(path, F_OK); + return pathType == FF_PATHTYPE_DIRECTORY ? ret == 0 : ret == -1 && errno == ENOTDIR; } #endif @@ -211,3 +226,8 @@ static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char* return false; } + +#ifdef _WIN32 +// Only O_RDONLY is supported +HANDLE openat(HANDLE dfd, const char* fileName, bool directory); +#endif diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 54689ffae..4cb946d0e 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -37,7 +37,7 @@ static void createSubfolders(const char* fileName) bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) { int openFlagsModes = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC; - int openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + mode_t openFlagsRights = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; int FF_AUTO_CLOSE_FD fd = open(fileName, openFlagsModes, openFlagsRights); if(fd == -1) @@ -108,6 +108,15 @@ ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) return ffReadFDData(fd, dataSize, data); } +ssize_t ffReadFileDataRelative(int dfd, const char* fileName, size_t dataSize, void* data) +{ + int FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, O_RDONLY | O_CLOEXEC); + if(fd == -1) + return -1; + + return ffReadFDData(fd, dataSize, data); +} + bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) { int FF_AUTO_CLOSE_FD fd = open(fileName, O_RDONLY | O_CLOEXEC); @@ -117,6 +126,15 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) return ffAppendFDBuffer(fd, buffer); } +bool ffAppendFileBufferRelative(int dfd, const char* fileName, FFstrbuf* buffer) +{ + int FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, O_RDONLY | O_CLOEXEC); + if(fd == -1) + return false; + + return ffAppendFDBuffer(fd, buffer); +} + bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* out) { bool result = false; diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 632530ccc..9f1a96ce5 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -3,6 +3,8 @@ #include "util/stringUtils.h" #include +#include +#include static void createSubfolders(const char* fileName) { @@ -38,7 +40,7 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) static inline void readWithLength(HANDLE handle, FFstrbuf* buffer, uint32_t length) { - ffStrbufEnsureFixedLengthFree(buffer, length); + ffStrbufEnsureFree(buffer, length); DWORD bytesRead = 0; while( length > 0 && @@ -100,6 +102,49 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) return ffAppendFDBuffer(handle, buffer); } +HANDLE openat(HANDLE dfd, const char* fileName, bool directory) +{ + NTSTATUS ret; + UNICODE_STRING fileNameW; + ret = RtlAnsiStringToUnicodeString(&fileNameW, &(ANSI_STRING) { + .Length = (USHORT) strlen(fileName), + .Buffer = (PCHAR) fileName + }, TRUE); + if (!NT_SUCCESS(ret)) return INVALID_HANDLE_VALUE; + + FF_AUTO_CLOSE_FD HANDLE hFile; + IO_STATUS_BLOCK iosb = {}; + ret = NtOpenFile(&hFile, FILE_READ_DATA | SYNCHRONIZE, &(OBJECT_ATTRIBUTES) { + .Length = sizeof(OBJECT_ATTRIBUTES), + .RootDirectory = dfd, + .ObjectName = &fileNameW, + }, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | (directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE)); + RtlFreeUnicodeString(&fileNameW); + + if(!NT_SUCCESS(ret) || iosb.Information != FILE_OPENED) + return INVALID_HANDLE_VALUE; + + return hFile; +} + +bool ffAppendFileBufferRelative(HANDLE dfd, const char* fileName, FFstrbuf* buffer) +{ + HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false); + if(fd == INVALID_HANDLE_VALUE) + return false; + + return ffAppendFDBuffer(fd, buffer); +} + +ssize_t ffReadFileDataRelative(HANDLE dfd, const char* fileName, size_t dataSize, void* data) +{ + HANDLE FF_AUTO_CLOSE_FD fd = openat(dfd, fileName, false); + if(fd == INVALID_HANDLE_VALUE) + return -1; + + return ffReadFDData(fd, dataSize, data); +} + bool ffPathExpandEnv(const char* in, FFstrbuf* out) { DWORD length = ExpandEnvironmentStringsA(in, NULL, 0); diff --git a/src/common/modules.c b/src/common/modules.c index 4e8ae69e4..ce649cfc9 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -73,6 +73,7 @@ static FFModuleBaseInfo* J[] = { static FFModuleBaseInfo* K[] = { (void*) &instance.config.modules.kernel, + (void*) &instance.config.modules.keyboard, NULL, }; @@ -88,6 +89,7 @@ static FFModuleBaseInfo* M[] = { (void*) &instance.config.modules.media, (void*) &instance.config.modules.memory, (void*) &instance.config.modules.monitor, + (void*) &instance.config.modules.mouse, NULL, }; diff --git a/src/common/netif/netif_linux.c b/src/common/netif/netif_linux.c index f645b0a0b..1845ee0e2 100644 --- a/src/common/netif/netif_linux.c +++ b/src/common/netif/netif_linux.c @@ -13,11 +13,9 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) if (!netRoute) return false; // skip first line - flockfile(netRoute); - while (getc_unlocked(netRoute) != '\n'); - funlockfile(netRoute); - unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, + FF_UNUSED(fscanf(netRoute, "%*[^\n]\n")); + unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2) { if (destination != 0) continue; diff --git a/src/common/parsing.c b/src/common/parsing.c index ec58f9fa2..50f1a54aa 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -190,6 +190,48 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co } } +void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result) +{ + if(days == 0 && hours == 0 && minutes == 0) + { + ffStrbufAppendF(result, "%u seconds", seconds); + return; + } + + if(days > 0) + { + ffStrbufAppendF(result, "%u day", days); + + if(days > 1) + ffStrbufAppendC(result, 's'); + + if(days >= 100) + ffStrbufAppendS(result, "(!)"); + + if(hours > 0 || minutes > 0) + ffStrbufAppendS(result, ", "); + } + + if(hours > 0) + { + ffStrbufAppendF(result, "%u hour", hours); + + if(hours > 1) + ffStrbufAppendC(result, 's'); + + if(minutes > 0) + ffStrbufAppendS(result, ", "); + } + + if(minutes > 0) + { + ffStrbufAppendF(result, "%u min", minutes); + + if(minutes > 1) + ffStrbufAppendC(result, 's'); + } +} + #ifdef _WIN32 #pragma GCC diagnostic pop #endif diff --git a/src/common/parsing.h b/src/common/parsing.h index 722969ffb..bc04cf2f0 100644 --- a/src/common/parsing.h +++ b/src/common/parsing.h @@ -27,3 +27,4 @@ int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2); void ffParseSize(uint64_t bytes, FFstrbuf* result); bool ffParseFrequency(uint32_t mhz, FFstrbuf* result); +void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result); diff --git a/src/common/printing.h b/src/common/printing.h index 7ccc645f2..2060337c5 100644 --- a/src/common/printing.h +++ b/src/common/printing.h @@ -14,7 +14,7 @@ typedef enum FFPrintType { void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType); void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, uint32_t numArgs, const FFformatarg* arguments); #define FF_PRINT_FORMAT_CHECKED(moduleName, moduleIndex, moduleArgs, printType, numArgs, arguments) do {\ - static_assert(sizeof(arguments) / sizeof(*(arguments)) == (numArgs), "Invalid number of format arguments");\ + static_assert(sizeof(arguments) / sizeof(*arguments) == (numArgs), "Invalid number of format arguments");\ ffPrintFormat((moduleName), (moduleIndex), (moduleArgs), (printType), (numArgs), (arguments));\ } while (0) FF_C_PRINTF(5, 6) void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...); @@ -23,6 +23,6 @@ void ffPrintCharTimes(char c, uint32_t times); void ffPrintModuleFormatHelp(const char* name, const char* def, uint32_t numArgs, const char* args[]); #define FF_PRINT_MODULE_FORMAT_HELP_CHECKED(moduleName, def, numArgs, args) do {\ - static_assert(sizeof(args) / sizeof(*(args)) == (numArgs), "Invalid number of format arguments");\ + static_assert(sizeof(args) / sizeof(*args) == (numArgs), "Invalid number of format arguments");\ ffPrintModuleFormatHelp((moduleName), (def), (numArgs), (args));\ } while (0) diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index ca7059417..0e6a243ce 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -139,12 +139,13 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons if (exePath) { snprintf(filePath, sizeof(filePath), "/proc/%d/exe", (int)pid); - ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX); - ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1); + char buf[PATH_MAX]; + ssize_t length = readlink(filePath, buf, PATH_MAX - 1); if (length > 0) // doesn't contain trailing NUL { - exePath->chars[length] = '\0'; - exePath->length = (uint32_t) length; + buf[length] = '\0'; + ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length + 1); // +1 for the NUL + ffStrbufAppendNS(exePath, (uint32_t)length, buf); } } @@ -152,14 +153,14 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons size_t len = 0; int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid }; - if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), NULL, &len, NULL, 0) == 0) + if (sysctl(mibs, ARRAY_SIZE(mibs), NULL, &len, NULL, 0) == 0) {// try get arg0 #ifndef MAC_OS_X_VERSION_10_15 //don't know why if don't let len longer, proArgs2 and len will change during the following sysctl() in old MacOS version. len++; #endif FF_AUTO_FREE char* const procArgs2 = malloc(len); - if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), procArgs2, &len, NULL, 0) == 0) + if (sysctl(mibs, ARRAY_SIZE(mibs), procArgs2, &len, NULL, 0) == 0) { // https://gist.github.com/nonowarn/770696#file-getargv-c-L46 uint32_t argc = *(uint32_t*) procArgs2; @@ -242,7 +243,7 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons #elif defined(__sun) - char filePath[PATH_MAX]; + char filePath[128]; snprintf(filePath, sizeof(filePath), "/proc/%d/psinfo", (int) pid); psinfo_t proc; if (ffReadFileData(filePath, sizeof(proc), &proc) == sizeof(proc)) @@ -254,12 +255,13 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons if (exePath) { snprintf(filePath, sizeof(filePath), "/proc/%d/path/a.out", (int) pid); - ffStrbufEnsureFixedLengthFree(exePath, PATH_MAX); - ssize_t length = readlink(filePath, exePath->chars, exePath->allocated - 1); + char buf[PATH_MAX]; + ssize_t length = readlink(filePath, buf, PATH_MAX - 1); if (length > 0) // doesn't contain trailing NUL { - exePath->chars[length] = '\0'; - exePath->length = (uint32_t) length; + buf[length] = '\0'; + ffStrbufEnsureFixedLengthFree(exePath, (uint32_t)length + 1); // +1 for the NUL + ffStrbufAppendNS(exePath, (uint32_t)length, buf); } } diff --git a/src/common/processing_windows.c b/src/common/processing_windows.c index c2d2b10fa..e5f7086d3 100644 --- a/src/common/processing_windows.c +++ b/src/common/processing_windows.c @@ -49,8 +49,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use { int timeout = instance.config.general.processingTimeout; + wchar_t pipeName[32]; + swprintf(pipeName, ARRAY_SIZE(pipeName), L"\\\\.\\pipe\\FASTFETCH-%u", GetCurrentProcessId()); + FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = CreateNamedPipeW( - L"\\\\.\\pipe\\LOCAL\\", + pipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | (timeout < 0 ? 0 : FILE_FLAG_OVERLAPPED), 0, 1, @@ -60,10 +63,10 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use NULL ); if (hChildPipeRead == INVALID_HANDLE_VALUE) - return "CreateNamedPipeW(L\"\\\\.\\pipe\\LOCAL\\\") failed"; + return "CreateNamedPipeW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed"; HANDLE hChildPipeWrite = CreateFileW( - L"\\\\.\\pipe\\LOCAL\\", + pipeName, GENERIC_WRITE, 0, &(SECURITY_ATTRIBUTES){ @@ -76,7 +79,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use NULL ); if (hChildPipeWrite == INVALID_HANDLE_VALUE) - return "CreateFileW(L\"\\\\.\\pipe\\LOCAL\\\") failed"; + return "CreateFileW(L\"\\\\.\\pipe\\FASTFETCH-$(PID)\") failed"; PROCESS_INFORMATION piProcInfo = {0}; diff --git a/src/common/properties.c b/src/common/properties.c index fbf11416e..746727d9c 100644 --- a/src/common/properties.c +++ b/src/common/properties.c @@ -100,7 +100,7 @@ bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquer bool valueStorage[32]; bool* unsetValues = valueStorage; - if (numQueries > sizeof(valueStorage) / sizeof(valueStorage[0])) + if (numQueries > ARRAY_SIZE(valueStorage)) unsetValues = malloc(sizeof(bool) * numQueries); bool allSet = true; diff --git a/src/data/help.json b/src/data/help.json index bdce5411f..c7e4a88ec 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -916,6 +916,14 @@ "type": "str" } }, + { + "long": "diskio-wait-time", + "desc": "Set the wait time (in ms) when detecting disk usage", + "arg": { + "type": "num", + "default": 1000 + } + }, { "long": "physicaldisk-name-prefix", "desc": "Show disks with given name prefix only", @@ -1070,6 +1078,14 @@ "default": false } }, + { + "long": "cpuusage-wait-time", + "desc": "Set the wait time (in ms) when detecting CPU usage", + "arg": { + "type": "num", + "default": 200 + } + }, { "long": "de-slow-version-detection", "desc": "Set if DE version should be detected with slow operations", @@ -1305,6 +1321,14 @@ "default": false } }, + { + "long": "netio-wait-time", + "desc": "Set the wait time (in ms) when detecting network usage", + "arg": { + "type": "num", + "default": 1000 + } + }, { "long": "publicip-timeout", "desc": "Time in milliseconds to wait for the public ip server to respond", diff --git a/src/detection/battery/battery.h b/src/detection/battery/battery.h index 2f4c8e3f1..d31a7ef71 100644 --- a/src/detection/battery/battery.h +++ b/src/detection/battery/battery.h @@ -15,6 +15,7 @@ typedef struct FFBatteryResult double capacity; double temperature; uint32_t cycleCount; + int32_t timeRemaining; } 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 6a5e807ea..da2cb8f21 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -1,6 +1,6 @@ #include "fastfetch.h" #include "battery.h" - +#include "util/stringUtils.h" #include "common/processing.h" #include "common/properties.h" @@ -36,6 +36,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results) FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; battery->cycleCount = 0; + battery->timeRemaining = -1; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); ffStrbufInit(&battery->status); @@ -44,7 +45,27 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results) ffStrbufInit(&battery->manufactureDate); battery->capacity = yyjson_get_num(yyjson_obj_get(root, "percentage")); - ffStrbufAppendS(&battery->status, yyjson_get_str(yyjson_obj_get(root, "status"))); + const char* acStatus = yyjson_get_str(yyjson_obj_get(root, "plugged")); + if (acStatus) + { + if (ffStrEquals(acStatus, "PLUGGED_AC")) + ffStrbufAppendS(&battery->status, "AC Connected, "); + else if (ffStrEquals(acStatus, "PLUGGED_USB")) + ffStrbufAppendS(&battery->status, "USB Connected, "); + else if (ffStrEquals(acStatus, "PLUGGED_WIRELESS")) + ffStrbufAppendS(&battery->status, "Wireless Connected, "); + } + const char* status = yyjson_get_str(yyjson_obj_get(root, "status")); + if (status) + { + if (ffStrEquals(status, "CHARGING")) + ffStrbufAppendS(&battery->status, "Charging"); + else if (ffStrEquals(status, "DISCHARGING")) + ffStrbufAppendS(&battery->status, "Discharging"); + } + ffStrbufTrimRight(&battery->status, ' '); + ffStrbufTrimRight(&battery->status, ','); + if(options->temp) battery->temperature = yyjson_get_num(yyjson_obj_get(root, "temperature")); @@ -74,6 +95,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; battery->cycleCount = 0; + battery->timeRemaining = -1; 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 4f3d809b6..4573ec181 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -57,13 +57,24 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) ffCfDictGetInt(properties, CFSTR(kIOPMPSCycleCountKey), &cycleCount); battery->cycleCount = cycleCount < 0 ? 0 : (uint32_t) cycleCount; - if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) && boolValue) - ffStrbufAppendS(&battery->status, "AC connected, "); - else - ffStrbufAppendS(&battery->status, "Discharging, "); - if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) && boolValue) + battery->timeRemaining = -1; + if (ffCfDictGetBool(properties, CFSTR(kIOPMPSExternalConnectedKey), &boolValue) == NULL) + { + if (boolValue) + ffStrbufAppendS(&battery->status, "AC connected, "); + else + { + ffStrbufAppendS(&battery->status, "Discharging, "); + ffCfDictGetInt(properties, CFSTR("AvgTimeToEmpty"), &battery->timeRemaining); // in minutes + if (battery->timeRemaining < 0 || battery->timeRemaining >= 0xFFFF) + battery->timeRemaining = -1; + else + battery->timeRemaining *= 60; + } + } + if (ffCfDictGetBool(properties, CFSTR(kIOPMPSIsChargingKey), &boolValue) == NULL && boolValue) ffStrbufAppendS(&battery->status, "Charging, "); - if (!ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) && boolValue) + if (ffCfDictGetBool(properties, CFSTR(kIOPMPSAtCriticalLevelKey), &boolValue) == NULL && boolValue) ffStrbufAppendS(&battery->status, "Critical, "); ffStrbufTrimRight(&battery->status, ' '); ffStrbufTrimRight(&battery->status, ','); diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c index 76b057a74..228d6aa36 100644 --- a/src/detection/battery/battery_bsd.c +++ b/src/detection/battery/battery_bsd.c @@ -41,7 +41,9 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r ffStrbufInit(&battery->technology); ffStrbufInit(&battery->serial); ffStrbufInit(&battery->manufactureDate); - + battery->timeRemaining = -1; + if (battio.battinfo.min > 0) + battery->timeRemaining = battio.battinfo.min * 60; battery->capacity = battio.battinfo.cap; if(battio.battinfo.state == ACPI_BATT_STAT_INVALID) { @@ -74,6 +76,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r ffStrbufAppendS(&battery->manufacturer, battio.bix.oeminfo); ffStrbufAppendS(&battery->modelName, battio.bix.model); ffStrbufAppendS(&battery->technology, battio.bix.type); + battery->cycleCount = battio.bix.cycles; } } return NULL; diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 0d76871c5..940b9d719 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -3,39 +3,45 @@ #include "util/stringUtils.h" #include +#include +#include // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-power -static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* options, FFlist* results) +static bool checkAc(const char* id, FFstrbuf* tmpBuffer) { - uint32_t dirLength = dir->length; + if (ffStrStartsWith(id, "BAT")) + ffStrbufSetS(tmpBuffer, "/sys/class/power_supply/ADP1/online"); + else if (ffStrStartsWith(id, "macsmc-battery")) + ffStrbufSetS(tmpBuffer, "/sys/class/power_supply/macsmc-ac/online"); + else + ffStrbufClear(tmpBuffer); + + char online = '\0'; + return ffReadFileData(tmpBuffer->chars, 1, &online) == 1 && online == '1'; +} +static void parseBattery(int dfd, const char* id, FFBatteryOptions* options, FFlist* results) +{ FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate(); - //type must exist and be "Battery" - ffStrbufAppendS(dir, "/type"); - if (ffReadFileBuffer(dir->chars, &tmpBuffer)) - ffStrbufTrimRightSpace(&tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); - + // type must exist and be "Battery" + if (!ffReadFileBufferRelative(dfd, "type", &tmpBuffer)) + return; + ffStrbufTrimRightSpace(&tmpBuffer); if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Battery")) return; - //scope may not exist or must not be "Device" - ffStrbufAppendS(dir, "/scope"); - if (ffReadFileBuffer(dir->chars, &tmpBuffer)) + // scope may not exist or must not be "Device" + if (ffReadFileBufferRelative(dfd, "scope", &tmpBuffer)) ffStrbufTrimRightSpace(&tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device")) return; - //capacity must exist and be not empty - ffStrbufAppendS(dir, "/capacity"); - bool available = ffReadFileBuffer(dir->chars, &tmpBuffer); // This is expensive in my laptop - ffStrbufSubstrBefore(dir, dirLength); - - if (!available) + // capacity must exist and be not empty + // This is expensive in my laptop + if (!ffReadFileBufferRelative(dfd, "capacity", &tmpBuffer)) return; FFBatteryResult* result = ffListAdd(results); @@ -44,39 +50,63 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option //At this point, we have a battery. Try to get as much values as possible. ffStrbufInit(&result->manufacturer); - ffStrbufAppendS(dir, "/manufacturer"); - if (ffReadFileBuffer(dir->chars, &result->manufacturer)) + if (ffReadFileBufferRelative(dfd, "manufacturer", &result->manufacturer)) ffStrbufTrimRightSpace(&result->manufacturer); else if (ffStrEquals(id, "macsmc-battery")) // asahi ffStrbufSetStatic(&result->manufacturer, "Apple Inc."); - ffStrbufSubstrBefore(dir, dirLength); ffStrbufInit(&result->modelName); - ffStrbufAppendS(dir, "/model_name"); - if (ffReadFileBuffer(dir->chars, &result->modelName)) + if (ffReadFileBufferRelative(dfd, "model_name", &result->modelName)) ffStrbufTrimRightSpace(&result->modelName); - ffStrbufSubstrBefore(dir, dirLength); ffStrbufInit(&result->technology); - ffStrbufAppendS(dir, "/technology"); - if (ffReadFileBuffer(dir->chars, &result->technology)) + if (ffReadFileBufferRelative(dfd, "technology", &result->technology)) ffStrbufTrimRightSpace(&result->technology); - ffStrbufSubstrBefore(dir, dirLength); ffStrbufInit(&result->status); - ffStrbufAppendS(dir, "/status"); - if (ffReadFileBuffer(dir->chars, &result->status)) + if (ffReadFileBufferRelative(dfd, "status", &result->status)) ffStrbufTrimRightSpace(&result->status); - ffStrbufSubstrBefore(dir, dirLength); // Unknown, Charging, Discharging, Not charging, Full - if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full")) + + result->timeRemaining = -1; + if (ffStrbufEqualS(&result->status, "Discharging")) + { + if (ffReadFileBufferRelative(dfd, "time_to_empty_now", &tmpBuffer)) + result->timeRemaining = (int32_t) ffStrbufToSInt(&tmpBuffer, 0); + else + { + if (ffReadFileBufferRelative(dfd, "charge_now", &tmpBuffer)) + { + int64_t chargeNow = ffStrbufToSInt(&tmpBuffer, 0); + if (chargeNow > 0) + { + if (ffReadFileBufferRelative(dfd, "current_now", &tmpBuffer)) + { + int64_t currentNow = ffStrbufToSInt(&tmpBuffer, INT64_MIN); + if (currentNow < 0) currentNow = -currentNow; + if (currentNow > 0) + result->timeRemaining = (int32_t) ((chargeNow * 3600) / currentNow); + } + } + } + } + + if (checkAc(id, &tmpBuffer)) + ffStrbufAppendS(&result->status, ", AC Connected"); + } + else if (ffStrbufEqualS(&result->status, "Not charging") || ffStrbufEqualS(&result->status, "Full")) ffStrbufSetStatic(&result->status, "AC Connected"); + else if (ffStrbufEqualS(&result->status, "Charging")) + ffStrbufAppendS(&result->status, ", AC Connected"); else if (ffStrbufEqualS(&result->status, "Unknown")) + { ffStrbufClear(&result->status); + if (checkAc(id, &tmpBuffer)) + ffStrbufAppendS(&result->status, "AC Connected"); + } - ffStrbufAppendS(dir, "/capacity_level"); - if (ffReadFileBuffer(dir->chars, &tmpBuffer)) + if (ffReadFileBufferRelative(dfd, "capacity_level", &tmpBuffer)) { ffStrbufTrimRightSpace(&result->manufacturer); if (ffStrbufEqualS(&tmpBuffer, "Critical")) @@ -87,50 +117,33 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option ffStrbufSetStatic(&result->status, "Critical"); } } - ffStrbufSubstrBefore(dir, dirLength); ffStrbufInit(&result->serial); - ffStrbufAppendS(dir, "/serial_number"); - if (ffReadFileBuffer(dir->chars, &result->serial)) + if (ffReadFileBufferRelative(dfd, "serial_number", &result->serial)) ffStrbufTrimRightSpace(&result->serial); - ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "/cycle_count"); - available = ffReadFileBuffer(dir->chars, &tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); - if (available) + if (ffReadFileBufferRelative(dfd, "cycle_count", &tmpBuffer)) { int64_t cycleCount = ffStrbufToSInt(&tmpBuffer, 0); result->cycleCount = cycleCount < 0 || cycleCount > UINT32_MAX ? 0 : (uint32_t) cycleCount; } ffStrbufInit(&result->manufactureDate); - ffStrbufAppendS(dir, "/manufacture_year"); - available = ffReadFileBuffer(dir->chars, &tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); - if (available) + if (ffReadFileBufferRelative(dfd, "manufacture_year", &tmpBuffer)) { int year = (int) ffStrbufToSInt(&tmpBuffer, 0); if (year > 0) { - ffStrbufAppendS(dir, "/manufacture_month"); - available = ffReadFileBuffer(dir->chars, &tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); - if (available) + if (ffReadFileBufferRelative(dfd, "manufacture_month", &tmpBuffer)) { int month = (int) ffStrbufToSInt(&tmpBuffer, 0); if (month > 0) { - ffStrbufAppendS(dir, "/manufacture_day"); - available = ffReadFileBuffer(dir->chars, &tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); - if (available) + if (ffReadFileBufferRelative(dfd, "manufacture_day", &tmpBuffer)) { int day = (int) ffStrbufToSInt(&tmpBuffer, 0); if (day > 0) - { ffStrbufSetF(&result->manufactureDate, "%.4d-%.2d-%.2d", year, month, day); - } } } } @@ -140,33 +153,25 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option result->temperature = FF_BATTERY_TEMP_UNSET; if (options->temp) { - ffStrbufAppendS(dir, "/temp"); - if (ffReadFileBuffer(dir->chars, &tmpBuffer)) + if (ffReadFileBufferRelative(dfd, "temp", &tmpBuffer)) result->temperature = ffStrbufToDouble(&tmpBuffer) / 10; - ffStrbufSubstrBefore(dir, dirLength); } } const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) { - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); - ffStrbufAppendS(&baseDir, "/sys/class/power_supply/"); - - uint32_t baseDirLength = baseDir.length; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/power_supply/"); if(dirp == NULL) return "opendir(\"/sys/class/power_supply/\") == NULL"; struct dirent* entry; while((entry = readdir(dirp)) != NULL) { - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) + if(entry->d_name[0] == '.') continue; - ffStrbufAppendS(&baseDir, entry->d_name); - parseBattery(&baseDir, entry->d_name, options, results); - ffStrbufSubstrBefore(&baseDir, baseDirLength); + FF_AUTO_CLOSE_FD int dfd = openat(dirfd(dirp), entry->d_name, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (dfd > 0) parseBattery(dfd, entry->d_name, options, results); } return NULL; diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 6c7298231..101bd6dea 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -121,6 +121,13 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results battery->temperature = temp / 10.0 - 273.15; } + { + bqi.InformationLevel = BatteryEstimatedTime; + ULONG time; + if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &time, sizeof(time), &dwOut, NULL)) + battery->timeRemaining = time == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) time; + } + { BATTERY_STATUS bs; BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag }; @@ -241,6 +248,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF ffStrbufInit(&battery->serial); battery->temperature = FF_BATTERY_TEMP_UNSET; battery->cycleCount = 0; + battery->timeRemaining = info.EstimatedTime == BATTERY_UNKNOWN_TIME ? -1 : (int32_t) info.EstimatedTime; battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity; if(info.AcOnLine) @@ -252,6 +260,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF else if(info.Discharging) ffStrbufAppendS(&battery->status, "Discharging"); + detectBySmbios(battery); return NULL; diff --git a/src/detection/bios/bios_bsd.c b/src/detection/bios/bios_bsd.c index aa115de21..11f762099 100644 --- a/src/detection/bios/bios_bsd.c +++ b/src/detection/bios/bios_bsd.c @@ -25,7 +25,7 @@ const char* ffDetectBios(FFBiosResult* result) { ffStrbufSetStatic(&result->type, ffPathExists("/dev/efi" /*efidev*/, FF_PATHTYPE_FILE) || - ffPathExists("/boot/efi/efi" /*efi partition*/, FF_PATHTYPE_DIRECTORY) + ffPathExists("/boot/efi/efi/" /*efi partition*/, FF_PATHTYPE_DIRECTORY) ? "UEFI" : "BIOS"); } } diff --git a/src/detection/bios/bios_linux.c b/src/detection/bios/bios_linux.c index 86342c159..98bb40c38 100644 --- a/src/detection/bios/bios_linux.c +++ b/src/detection/bios/bios_linux.c @@ -10,7 +10,7 @@ const char *ffDetectBios(FFBiosResult *bios) ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release); ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor); ffGetSmbiosValue("/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)) + 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"); diff --git a/src/detection/bios/bios_nosupport.c b/src/detection/bios/bios_nosupport.c index 76abc7a12..ac544fd3e 100644 --- a/src/detection/bios/bios_nosupport.c +++ b/src/detection/bios/bios_nosupport.c @@ -1,6 +1,6 @@ #include "bios.h" -const char* ffDetectBios(FFBiosResult* bios) +const char* ffDetectBios(FF_MAYBE_UNUSED FFBiosResult* bios) { return "Not supported on this platform"; } diff --git a/src/detection/bluetoothradio/bluetoothradio_linux.c b/src/detection/bluetoothradio/bluetoothradio_linux.c index 6157ee16b..05b77523c 100644 --- a/src/detection/bluetoothradio/bluetoothradio_linux.c +++ b/src/detection/bluetoothradio/bluetoothradio_linux.c @@ -202,6 +202,7 @@ const char* ffDetectBluetoothRadio(FFlist* devices /* FFBluetoothRadioResult */) #ifdef FF_HAVE_DBUS return detectBluetooth(devices); #else + FF_UNUSED(devices) return "Fastfetch was compiled without DBus support"; #endif } diff --git a/src/detection/bootmgr/bootmgr_windows.c b/src/detection/bootmgr/bootmgr_windows.c index 19484a7ed..54314bbad 100644 --- a/src/detection/bootmgr/bootmgr_windows.c +++ b/src/detection/bootmgr/bootmgr_windows.c @@ -38,9 +38,9 @@ const char* ffDetectBootmgr(FFBootmgrResult* result) uint8_t buffer[2048]; wchar_t key[16]; - swprintf(key, sizeof(key) / sizeof(*key), L"Boot%04X", value); + swprintf(key, ARRAY_SIZE(key), L"Boot%04X", value); uint32_t size = GetFirmwareEnvironmentVariableW(key, L"{" FF_EFI_GLOBAL_GUID L"}", buffer, sizeof(buffer)); - if (size < sizeof(FFEfiLoadOption) || size == sizeof(buffer)) + if (size < sizeof(FFEfiLoadOption) || size == ARRAY_SIZE(buffer)) return "GetFirmwareEnvironmentVariableW(Boot####) failed"; ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result); diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index a9f8daf0c..e10d912be 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -92,13 +92,13 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* for (uint32_t i = 0; i < 2; ++i) { - IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, sizeof(i2cIn)); + IOAVServiceWriteI2C(service, 0x37, 0x51, i2cIn, ARRAY_SIZE(i2cIn)); usleep(options->ddcciSleep * 1000); } } uint8_t i2cOut[12] = {}; - if (IOAVServiceReadI2C(service, 0x37, 0x51, i2cOut, sizeof(i2cOut)) == KERN_SUCCESS) + if (IOAVServiceReadI2C(service, 0x37, 0x51, i2cOut, ARRAY_SIZE(i2cOut)) == KERN_SUCCESS) { if (i2cOut[2] != 0x02 || i2cOut[3] != 0x00) continue; @@ -113,7 +113,7 @@ static const char* detectWithDdcci(FF_MAYBE_UNUSED const FFDisplayServerResult* ffStrbufInit(&brightness->name); uint8_t edid[128] = {}; - if (IOAVServiceReadI2C(service, 0x50, 0x00, edid, sizeof(edid)) == KERN_SUCCESS) + if (IOAVServiceReadI2C(service, 0x50, 0x00, edid, ARRAY_SIZE(edid)) == KERN_SUCCESS) ffEdidGetName(edid, &brightness->name); } } @@ -155,12 +155,12 @@ static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, F .sendAddress = 0x6e, .sendTransactionType = kIOI2CSimpleTransactionType, .sendBuffer = (vm_address_t) i2cIn, - .sendBytes = sizeof(i2cIn) / sizeof(i2cIn[0]), + .sendBytes = ARRAY_SIZE(i2cIn), .minReplyDelay = options->ddcciSleep, .replyAddress = 0x6F, .replySubAddress = 0x51, .replyTransactionType = kIOI2CDDCciReplyTransactionType, - .replyBytes = sizeof(i2cOut) / sizeof(i2cOut[0]), + .replyBytes = ARRAY_SIZE(i2cOut), .replyBuffer = (vm_address_t) i2cOut, }; IOReturn ret = IOI2CSendRequest(connect, kNilOptions, &request); diff --git a/src/detection/brightness/brightness_bsd.c b/src/detection/brightness/brightness_bsd.c index 22b3772fb..b71f1074f 100644 --- a/src/detection/brightness/brightness_bsd.c +++ b/src/detection/brightness/brightness_bsd.c @@ -16,7 +16,7 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFBrightnessOptions* options, FFl for (char i = '0'; i <= '9'; ++i) { - path[sizeof(path) - 2] = i; + path[ARRAY_SIZE(path) - 2] = i; FF_AUTO_CLOSE_FD int blfd = open(path, O_RDONLY | O_CLOEXEC); if (blfd < 0) diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index e5d4e608a..9682a7598 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -25,7 +25,7 @@ static const char* detectWithBacklight(FFlist* result) struct dirent* entry; while((entry = readdir(dirp)) != NULL) { - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) + if(entry->d_name[0] == '.') continue; ffStrbufAppendS(&backlightDir, entry->d_name); @@ -48,7 +48,7 @@ static const char* detectWithBacklight(FFlist* result) // if we managed to get edid, use it ffStrbufAppendS(&brightness->name, "/edid"); uint8_t edidData[128]; - if(ffReadFileData(brightness->name.chars, sizeof(edidData), edidData) == sizeof(edidData)) + if(ffReadFileData(brightness->name.chars, ARRAY_SIZE(edidData), edidData) == ARRAY_SIZE(edidData)) { ffStrbufClear(&brightness->name); ffEdidGetName(edidData, &brightness->name); diff --git a/src/detection/btrfs/btrfs_linux.c b/src/detection/btrfs/btrfs_linux.c index 993300bac..3685a153d 100644 --- a/src/detection/btrfs/btrfs_linux.c +++ b/src/detection/btrfs/btrfs_linux.c @@ -1,16 +1,18 @@ #include "btrfs.h" #include "common/io/io.h" +#include enum { uuidLen = (uint32_t) __builtin_strlen("00000000-0000-0000-0000-000000000000") }; -static const char* enumerateDevices(FFBtrfsResult* item, FFstrbuf* path, FFstrbuf* buffer) +static const char* enumerateDevices(FFBtrfsResult* item, int dfd, FFstrbuf* buffer) { - ffStrbufAppendS(path, "devices/"); - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path->chars); + int subfd = openat(dfd, "devices", O_RDONLY | O_CLOEXEC | O_DIRECTORY); + if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/devices\") == -1"; + + FF_AUTO_CLOSE_DIR DIR* dirp = fdopendir(subfd); if(dirp == NULL) - return "opendir(\"/sys/fs/btrfs/UUID/devices\") == NULL"; - const uint32_t devicesPathLen = path->length; + return "fdopendir(\"/sys/fs/btrfs/UUID/devices\") == NULL"; struct dirent* entry; while ((entry = readdir(dirp)) != NULL) @@ -21,25 +23,25 @@ static const char* enumerateDevices(FFBtrfsResult* item, FFstrbuf* path, FFstrbu if (item->devices.length) ffStrbufAppendC(&item->devices, ','); ffStrbufAppendS(&item->devices, entry->d_name); - ffStrbufAppendS(path, entry->d_name); - ffStrbufAppendS(path, "/size"); - if (ffReadFileBuffer(path->chars, buffer)) - item->totalSize += ffStrbufToUInt(buffer, 0) * 512; + char path[ARRAY_SIZE(entry->d_name) + ARRAY_SIZE("/size") + 1]; + snprintf(path, ARRAY_SIZE(path), "%s/size", entry->d_name); - ffStrbufSubstrBefore(path, devicesPathLen); + if (ffReadFileBufferRelative(subfd, path, buffer)) + item->totalSize += ffStrbufToUInt(buffer, 0) * 512; } return NULL; } -static const char* enumerateFeatures(FFBtrfsResult* item, FFstrbuf* path) +static const char* enumerateFeatures(FFBtrfsResult* item, int dfd) { - ffStrbufAppendS(path, "features/"); - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path->chars); + int subfd = openat(dfd, "features", O_RDONLY | O_CLOEXEC | O_DIRECTORY); + if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/features\") == -1"; + + FF_AUTO_CLOSE_DIR DIR* dirp = fdopendir(subfd); if(dirp == NULL) - return "opendir(\"/sys/fs/btrfs/UUID/features\") == NULL"; - const uint32_t featuresPathLen = path->length; + return "fdopendir(\"/sys/fs/btrfs/UUID/features\") == NULL"; struct dirent* entry; while ((entry = readdir(dirp)) != NULL) @@ -49,45 +51,33 @@ static const char* enumerateFeatures(FFBtrfsResult* item, FFstrbuf* path) if (item->features.length) ffStrbufAppendC(&item->features, ','); ffStrbufAppendS(&item->features, entry->d_name); - - ffStrbufSubstrBefore(path, featuresPathLen); } return NULL; } -static const char* detectAllocation(FFBtrfsResult* item, FFstrbuf* path, FFstrbuf* buffer) +static const char* detectAllocation(FFBtrfsResult* item, int dfd, FFstrbuf* buffer) { - ffStrbufAppendS(path, "allocation/"); - const uint32_t AllocationPathLen = path->length; + FF_AUTO_CLOSE_FD int subfd = openat(dfd, "allocation", O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (subfd < 0) return "openat(\"/sys/fs/btrfs/UUID/allocation\") == -1"; - ffStrbufAppendS(path, "global_rsv_size"); - if (ffReadFileBuffer(path->chars, buffer)) + if (ffReadFileBufferRelative(subfd, "global_rsv_size", buffer)) item->globalReservationTotal = ffStrbufToUInt(buffer, 0); else return "ffReadFileBuffer(\"/sys/fs/btrfs/UUID/allocation/global_rsv_size\") == NULL"; - ffStrbufSubstrBefore(path, AllocationPathLen); - ffStrbufAppendS(path, "global_rsv_reserved"); - if (ffReadFileBuffer(path->chars, buffer)) + if (ffReadFileBufferRelative(subfd, "global_rsv_reserved", buffer)) item->globalReservationUsed = ffStrbufToUInt(buffer, 0); - ffStrbufSubstrBefore(path, AllocationPathLen); item->globalReservationUsed = item->globalReservationTotal - item->globalReservationUsed; #define FF_BTRFS_DETECT_TYPE(index, _type) \ - ffStrbufAppendS(path, #_type "/total_bytes"); \ - if (ffReadFileBuffer(path->chars, buffer)) \ + if (ffReadFileBufferRelative(subfd, #_type "/total_bytes", buffer)) \ item->allocation[index].total = ffStrbufToUInt(buffer, 0); \ - ffStrbufSubstrBefore(path, AllocationPathLen); \ \ - ffStrbufAppendS(path, #_type "/bytes_used"); \ - if (ffReadFileBuffer(path->chars, buffer)) \ + if (ffReadFileBufferRelative(subfd, #_type "/bytes_used", buffer)) \ item->allocation[index].used = ffStrbufToUInt(buffer, 0); \ - ffStrbufSubstrBefore(path, AllocationPathLen); \ \ - ffStrbufAppendS(path, #_type "/dup"); \ - item->allocation[index].dup = ffPathExists(path->chars, FF_PATHTYPE_DIRECTORY); \ - ffStrbufSubstrBefore(path, AllocationPathLen); \ + item->allocation[index].dup = faccessat(subfd, #_type "/dup/", F_OK, 0) == 0; \ \ item->allocation[index].type = #_type; @@ -102,10 +92,7 @@ static const char* detectAllocation(FFBtrfsResult* item, FFstrbuf* path, FFstrbu const char* ffDetectBtrfs(FFlist* result) { - FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/fs/btrfs/"); - const uint32_t basePathLen = path.length; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path.chars); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/fs/btrfs/"); if(dirp == NULL) return "opendir(\"/sys/fs/btrfs\") == NULL"; @@ -120,46 +107,33 @@ const char* ffDetectBtrfs(FFlist* result) continue; FFBtrfsResult* item = ffListAdd(result); - (*item) = (FFBtrfsResult){}; - ffStrbufInitNS(&item->uuid, uuidLen, entry->d_name); - ffStrbufInit(&item->name); - ffStrbufInit(&item->devices); - ffStrbufInit(&item->features); - - ffStrbufAppendNS(&path, uuidLen, entry->d_name); - ffStrbufAppendC(&path, '/'); - const uint32_t itemPathLen = path.length; - - ffStrbufAppendS(&path, "label"); - if (ffAppendFileBuffer(path.chars, &item->name)) + (*item) = (FFBtrfsResult){ + .uuid = ffStrbufCreateNS(uuidLen, entry->d_name), + .name = ffStrbufCreate(), + .devices = ffStrbufCreate(), + .features = ffStrbufCreate(), + }; + + FF_AUTO_CLOSE_FD int dfd = openat(dirfd(dirp), entry->d_name, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (dfd < 0) continue; + + if (ffAppendFileBufferRelative(dfd, "label", &item->name)) ffStrbufTrimRightSpace(&item->name); - ffStrbufSubstrBefore(&path, itemPathLen); - enumerateDevices(item, &path, &buffer); - ffStrbufSubstrBefore(&path, itemPathLen); + enumerateDevices(item, dfd, &buffer); - enumerateFeatures(item, &path); - ffStrbufSubstrBefore(&path, itemPathLen); + enumerateFeatures(item, dfd); - ffStrbufAppendS(&path, "generation"); - if (ffReadFileBuffer(path.chars, &buffer)) + if (ffReadFileBufferRelative(dfd, "generation", &buffer)) item->generation = (uint32_t) ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, itemPathLen); - ffStrbufAppendS(&path, "nodesize"); - if (ffReadFileBuffer(path.chars, &buffer)) + if (ffReadFileBufferRelative(dfd, "nodesize", &buffer)) item->nodeSize = (uint32_t) ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, itemPathLen); - ffStrbufAppendS(&path, "sectorsize"); - if (ffReadFileBuffer(path.chars, &buffer)) + if (ffReadFileBufferRelative(dfd, "sectorsize", &buffer)) item->sectorSize = (uint32_t) ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, itemPathLen); - - detectAllocation(item, &path, &buffer); - // finally - ffStrbufSubstrBefore(&path, basePathLen); + detectAllocation(item, dfd, &buffer); } return NULL; diff --git a/src/detection/camera/camera_linux.c b/src/detection/camera/camera_linux.c index e7f5c925f..6e9658845 100644 --- a/src/detection/camera/camera_linux.c +++ b/src/detection/camera/camera_linux.c @@ -16,7 +16,7 @@ const char* ffDetectCamera(FFlist* result) for (uint32_t i = 0; i <= 9; ++i) { - path[sizeof(path) - 2] = (char) (i + '0'); + path[ARRAY_SIZE(path) - 2] = (char) (i + '0'); FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY); if (fd < 0) break; diff --git a/src/detection/camera/camera_windows.cpp b/src/detection/camera/camera_windows.cpp index b0f9112f2..6f19ce932 100644 --- a/src/detection/camera/camera_windows.cpp +++ b/src/detection/camera/camera_windows.cpp @@ -52,7 +52,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result) wchar_t buffer[256]; uint32_t length = 0; - if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, sizeof(buffer), &length)) || length == 0) + if (FAILED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, buffer, ARRAY_SIZE(buffer), &length)) || length == 0) continue; FFCameraResult* camera = (FFCameraResult*) ffListAdd(result); @@ -63,7 +63,7 @@ const char* ffDetectCamera(FF_MAYBE_UNUSED FFlist* result) camera->width = 0; camera->height = 0; - if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, sizeof(buffer), &length)) && length > 0) + if (SUCCEEDED(device->GetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, buffer, ARRAY_SIZE(buffer), &length)) && length > 0) ffStrbufSetNWS(&camera->id, length, buffer); IMFMediaSource* FF_AUTO_RELEASE_COM_OBJECT source = nullptr; diff --git a/src/detection/cpu/cpu.c b/src/detection/cpu/cpu.c index 298eb5bfe..774e747ae 100644 --- a/src/detection/cpu/cpu.c +++ b/src/detection/cpu/cpu.c @@ -13,7 +13,7 @@ const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu) " 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core", " with Radeon Graphics" }; - ffStrbufRemoveStrings(&cpu->name, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings); + ffStrbufRemoveStrings(&cpu->name, ARRAY_SIZE(removeStrings), removeStrings); ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it return NULL; diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index b08a8b5bc..3c5f45940 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -85,8 +85,8 @@ static const char* detectCoreCount(FFCPUResult* cpu) if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed"; char sysctlKey[] = "hw.perflevelN.logicalcpu"; - if (nPerfLevels > sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0])) - nPerfLevels = sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0]); + if (nPerfLevels > ARRAY_SIZE(cpu->coreTypes)) + nPerfLevels = ARRAY_SIZE(cpu->coreTypes); for (uint32_t i = 0; i < nPerfLevels; ++i) { sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i); diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index fe08272f2..9533effd5 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -389,7 +389,7 @@ FF_MAYBE_UNUSED static void detectArmSoc(FFCPUResult* cpu) // device-vendor,device-model\0soc-vendor,soc-model\0 char content[256]; - ssize_t length = ffReadFileData("/proc/device-tree/compatible", sizeof(content), content); + ssize_t length = ffReadFileData("/proc/device-tree/compatible", ARRAY_SIZE(content), content); if (length <= 2) return; // get the second NUL terminated string if it exists diff --git a/src/detection/cpu/cpu_nosupport.c b/src/detection/cpu/cpu_nosupport.c index 2a06915d2..49e125b5a 100644 --- a/src/detection/cpu/cpu_nosupport.c +++ b/src/detection/cpu/cpu_nosupport.c @@ -1,6 +1,6 @@ #include "cpu.h" -const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) +const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FF_MAYBE_UNUSED FFCPUResult* cpu) { return "Not supported on this platform"; } diff --git a/src/detection/cpucache/cpucache_apple.c b/src/detection/cpucache/cpucache_apple.c index 261e46551..363733f8b 100644 --- a/src/detection/cpucache/cpucache_apple.c +++ b/src/detection/cpucache/cpucache_apple.c @@ -1,5 +1,6 @@ #include "cpucache.h" #include "common/sysctl.h" +#include "util/stringUtils.h" const char* ffDetectCPUCache(FFCPUCacheResult* result) { @@ -10,44 +11,44 @@ const char* ffDetectCPUCache(FFCPUCacheResult* result) // macOS provides the global system cache line size uint32_t lineSize = (uint32_t) ffSysctlGetInt("hw.cachelinesize", 0); - char sysctlKey[256] = "hw.perflevelN."; + char sysctlKey[128] = "hw.perflevelN."; char* pNum = sysctlKey + strlen("hw.perflevel"); char* pSubkey = sysctlKey + strlen("hw.perflevelN."); - const size_t lenLeft = sizeof(sysctlKey) - strlen("hw.perflevelN."); + const size_t lenLeft = ARRAY_SIZE(sysctlKey) - strlen("hw.perflevelN."); for (uint32_t i = 0; i < nPerfLevels; ++i) { *pNum = (char) ('0' + i); - strncpy(pSubkey, "physicalcpu", lenLeft); + ffStrCopyN(pSubkey, "physicalcpu", lenLeft); uint32_t ncpu = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (ncpu <= 0) continue; - strncpy(pSubkey, "l1icachesize", lenLeft); + ffStrCopyN(pSubkey, "l1icachesize", lenLeft); uint32_t size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_INSTRUCTION)->num = ncpu; - strncpy(pSubkey, "l1dcachesize", lenLeft); + ffStrCopyN(pSubkey, "l1dcachesize", lenLeft); size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) ffCPUCacheAddItem(result, 1, size, lineSize, FF_CPU_CACHE_TYPE_DATA)->num = ncpu; - strncpy(pSubkey, "l2cachesize", lenLeft); + ffStrCopyN(pSubkey, "l2cachesize", lenLeft); size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) { - strncpy(pSubkey, "cpusperl2", lenLeft); + ffStrCopyN(pSubkey, "cpusperl2", lenLeft); uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (cpuSper) ffCPUCacheAddItem(result, 2, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper; } - strncpy(pSubkey, "l3cachesize", lenLeft); + ffStrCopyN(pSubkey, "l3cachesize", lenLeft); size = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (size) { - strncpy(pSubkey, "cpusperl3", lenLeft); + ffStrCopyN(pSubkey, "cpusperl3", lenLeft); uint32_t cpuSper = (uint32_t) ffSysctlGetInt(sysctlKey, 0); if (cpuSper) ffCPUCacheAddItem(result, 3, size, lineSize, FF_CPU_CACHE_TYPE_UNIFIED)->num = ncpu / cpuSper; diff --git a/src/detection/cpuusage/cpuusage.c b/src/detection/cpuusage/cpuusage.c index 292a91a28..f6cfd37ce 100644 --- a/src/detection/cpuusage/cpuusage.c +++ b/src/detection/cpuusage/cpuusage.c @@ -13,7 +13,7 @@ void ffPrepareCPUUsage(void) ffGetCpuUsageInfo(&cpuTimes1); } -const char* ffGetCpuUsageResult(FFlist* result) +const char* ffGetCpuUsageResult(FFCPUUsageOptions* options, FFlist* result) { const char* error = NULL; if(cpuTimes1.elementSize == 0) @@ -21,7 +21,7 @@ const char* ffGetCpuUsageResult(FFlist* result) ffListInit(&cpuTimes1, sizeof(FFCpuUsageInfo)); error = ffGetCpuUsageInfo(&cpuTimes1); if(error) return error; - ffTimeSleep(200); + ffTimeSleep(options->waitTime); } if(cpuTimes1.length == 0) return "No CPU cores found"; @@ -43,7 +43,7 @@ const char* ffGetCpuUsageResult(FFlist* result) if (++retryCount <= 3) { ffListClear(&cpuTimes2); - ffTimeSleep(200); + ffTimeSleep(options->waitTime); goto retry; } } diff --git a/src/detection/cpuusage/cpuusage.h b/src/detection/cpuusage/cpuusage.h index 839902e6e..7950d452b 100644 --- a/src/detection/cpuusage/cpuusage.h +++ b/src/detection/cpuusage/cpuusage.h @@ -8,4 +8,4 @@ typedef struct FFCpuUsageInfo { } FFCpuUsageInfo; const char* ffGetCpuUsageInfo(FFlist* cpuTimes); -const char* ffGetCpuUsageResult(FFlist* result); // list of double +const char* ffGetCpuUsageResult(FFCPUUsageOptions* options, FFlist* result); // list of double diff --git a/src/detection/cpuusage/cpuusage_linux.c b/src/detection/cpuusage/cpuusage_linux.c index b91d6eeb1..5136b3489 100644 --- a/src/detection/cpuusage/cpuusage_linux.c +++ b/src/detection/cpuusage/cpuusage_linux.c @@ -8,13 +8,13 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { char buf[PROC_FILE_BUFFSIZ]; - ssize_t nRead = ffReadFileData("/proc/stat", sizeof(buf) - 1, buf); + ssize_t nRead = ffReadFileData("/proc/stat", ARRAY_SIZE(buf) - 1, buf); if(nRead < 0) { #ifdef __ANDROID__ return "Accessing \"/proc/stat\" is restricted on Android O+"; #else - return "ffReadFileData(\"/proc/stat\", sizeof(buf) - 1, buf) failed"; + return "ffReadFileData(\"/proc/stat\", ARRAY_SIZE(buf) - 1, buf) failed"; #endif } buf[nRead] = '\0'; diff --git a/src/detection/cpuusage/cpuusage_nosupport.c b/src/detection/cpuusage/cpuusage_nosupport.c index 72770e3be..da8bbdddd 100644 --- a/src/detection/cpuusage/cpuusage_nosupport.c +++ b/src/detection/cpuusage/cpuusage_nosupport.c @@ -1,7 +1,7 @@ #include "fastfetch.h" #include "detection/cpuusage/cpuusage.h" -const char* ffGetCpuUsageInfo(FFlist* cpuTimes) +const char* ffGetCpuUsageInfo(FF_MAYBE_UNUSED FFlist* cpuTimes) { return "Not support on this platform"; } diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 3836f6eb8..41600e7ef 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -149,7 +149,7 @@ static void detectName(FFDisk* disk) #ifdef __ANDROID__ -static void detectType(FF_MAYBE_UNUSED const FFlist* disks, FFDisk* currentDisk) +static void detectType(FF_MAYBE_UNUSED const FFlist* disks, FFDisk* currentDisk, FF_MAYBE_UNUSED struct mntent* device) { if(ffStrbufEqualS(¤tDisk->mountpoint, "/") || ffStrbufEqualS(¤tDisk->mountpoint, "/storage/emulated")) currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; @@ -204,7 +204,7 @@ static bool isRemovable(FFDisk* currentDisk) return false; char sysBlockPartition[64]; - snprintf(sysBlockPartition, sizeof(sysBlockPartition), "/sys/class/block/%s", currentDisk->mountFrom.chars + strlen("/dev/")); + snprintf(sysBlockPartition, ARRAY_SIZE(sysBlockPartition), "/sys/class/block/%s", currentDisk->mountFrom.chars + strlen("/dev/")); char sysBlockVolume[PATH_MAX]; // /sys/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1 if (realpath(sysBlockPartition, sysBlockVolume) == NULL) @@ -215,7 +215,7 @@ static bool isRemovable(FFDisk* currentDisk) return ffReadFileData(sysBlockVolume, 1, &removableChar) > 0 && removableChar == '1'; } -static void detectType(const FFlist* disks, FFDisk* currentDisk) +static void detectType(const FFlist* disks, FFDisk* currentDisk, struct mntent* device) { if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; @@ -225,6 +225,8 @@ static void detectType(const FFlist* disks, FFDisk* currentDisk) currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; + if (hasmntopt(device, MNTOPT_RO)) + currentDisk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; } #endif @@ -233,7 +235,7 @@ static void detectStats(FFDisk* disk) { struct statvfs fs; if(statvfs(disk->mountpoint.chars, &fs) != 0) - memset(&fs, 0, sizeof(struct statvfs)); //Set all values to 0, so our values get initialized to 0 too + memset(&fs, 0, sizeof(fs)); //Set all values to 0, so our values get initialized to 0 too disk->bytesTotal = fs.f_blocks * fs.f_frsize; disk->bytesFree = fs.f_bfree * fs.f_frsize; @@ -251,15 +253,17 @@ static void detectStats(FFDisk* disk) disk->filesTotal = disk->filesUsed = 0; } - if(fs.f_flag & ST_RDONLY) - disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; - disk->createTime = 0; #ifdef FF_HAVE_STATX struct statx stx; if (statx(0, disk->mountpoint.chars, 0, STATX_BTIME, &stx) == 0 && (stx.stx_mask & STATX_BTIME)) disk->createTime = (uint64_t)((stx.stx_btime.tv_sec * 1000) + (stx.stx_btime.tv_nsec / 1000000)); #endif + + #ifdef __ANDROID__ // hasmntopt requires a higher Android API level + if(fs.f_flag & ST_RDONLY) + disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; + #endif } const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) @@ -298,7 +302,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) detectName(disk); // Also detects external devices //detect type - detectType(disks, disk); + detectType(disks, disk, device); //Detects stats detectStats(disk); diff --git a/src/detection/disk/disk_nosupport.c b/src/detection/disk/disk_nosupport.c index cd224572a..c680c549e 100644 --- a/src/detection/disk/disk_nosupport.c +++ b/src/detection/disk/disk_nosupport.c @@ -1,6 +1,6 @@ #include "disk.h" -const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) +const char* ffDetectDisksImpl(FF_MAYBE_UNUSED FFDiskOptions* options, FF_MAYBE_UNUSED FFlist* disks) { return "Not supported on this platform"; } diff --git a/src/detection/disk/disk_sunos.c b/src/detection/disk/disk_sunos.c index 91cde2333..e2d6d714e 100644 --- a/src/detection/disk/disk_sunos.c +++ b/src/detection/disk/disk_sunos.c @@ -72,19 +72,21 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) static void detectType(const FFlist* disks, FFDisk* currentDisk, struct mnttab* device) { - if(ffStrContains(device->mnt_mntopts, MNTOPT_NOBROWSE)) + if(hasmntopt(device, MNTOPT_NOBROWSE)) currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; else if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; else currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; + if (hasmntopt(device, MNTOPT_RO)) + currentDisk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; } static void detectStats(FFDisk* disk) { struct statvfs fs; if(statvfs(disk->mountpoint.chars, &fs) != 0) - memset(&fs, 0, sizeof(struct statvfs)); + memset(&fs, 0, sizeof(fs)); disk->bytesTotal = fs.f_blocks * fs.f_frsize; disk->bytesFree = fs.f_bfree * fs.f_frsize; @@ -94,9 +96,6 @@ static void detectStats(FFDisk* disk) disk->filesTotal = (uint32_t) fs.f_files; disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree); - if(fs.f_flag & ST_RDONLY) - disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; - ffStrbufSetS(&disk->name, fs.f_fstr); disk->createTime = 0; diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index 9c0e06760..48c595ca0 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -22,9 +22,9 @@ static unsigned __stdcall testRemoteVolumeAccessible(void* mountpoint) const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) { wchar_t buf[MAX_PATH + 1]; - uint32_t length = GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf); - if (length == 0 || length >= sizeof(buf) / sizeof(*buf)) - return "GetLogicalDriveStringsW(sizeof(buf) / sizeof(*buf), buf) failed"; + uint32_t length = GetLogicalDriveStringsW(ARRAY_SIZE(buf), buf); + if (length == 0 || length >= ARRAY_SIZE(buf)) + return "GetLogicalDriveStringsW(ARRAY_SIZE(buf), buf) failed"; FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); @@ -32,7 +32,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) if (__builtin_expect(options->folders.length == 1 && options->folders.chars[0] == '/', 0)) { wchar_t path[MAX_PATH + 1]; - GetSystemWindowsDirectoryW(path, sizeof(path) / sizeof(*path)); + GetSystemWindowsDirectoryW(path, ARRAY_SIZE(path)); ffStrbufSetF(&options->folders, "%c:\\", (char) path[0]); } @@ -76,7 +76,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) { wchar_t volumeName[MAX_PATH + 1]; mountpoint[2] = L'\0'; - if(QueryDosDeviceW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName))) + if(QueryDosDeviceW(mountpoint, volumeName, ARRAY_SIZE(volumeName))) ffStrbufSetWS(&disk->mountFrom, volumeName); mountpoint[2] = L'\\'; } @@ -104,11 +104,11 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) DWORD diskFlags; BOOL result = GetVolumeInformationW(mountpoint, - diskName, sizeof(diskName) / sizeof(*diskName), //Volume name + diskName, ARRAY_SIZE(diskName), //Volume name NULL, //Serial number NULL, //Max component length &diskFlags, //File system flags - diskFileSystem, sizeof(diskFileSystem) / sizeof(*diskFileSystem) + diskFileSystem, ARRAY_SIZE(diskFileSystem) ); SetErrorMode(errorMode); diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c index 11c8dc26d..4c129d794 100644 --- a/src/detection/diskio/diskio.c +++ b/src/detection/diskio/diskio.c @@ -41,9 +41,9 @@ const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) return "No physical disk found"; uint64_t time2 = ffTimeGetNow(); - while (time2 - time1 < 1000) + while (time2 - time1 < options->waitTime) { - ffTimeSleep((uint32_t) (1000 - (time2 - time1))); + ffTimeSleep((uint32_t) (options->waitTime - (time2 - time1))); time2 = ffTimeGetNow(); } diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c index 456ff39d5..9bddb27ee 100644 --- a/src/detection/diskio/diskio_linux.c +++ b/src/detection/diskio/diskio_linux.c @@ -6,96 +6,87 @@ #include #include #include +#include -const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +static void parseDiskIOCounters(int dfd, const char* devName, FFlist* result, FFDiskIOOptions* options) { - FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); - if(sysBlockDirp == NULL) - return "opendir(\"/sys/block/\") == NULL"; - - struct dirent* sysBlockEntry; - while ((sysBlockEntry = readdir(sysBlockDirp)) != NULL) - { - const char* const devName = sysBlockEntry->d_name; - - if (devName[0] == '.') - continue; - - char pathSysBlock[PATH_MAX]; - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s", devName); + FF_AUTO_CLOSE_FD int devfd = openat(dfd, "device", O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (devfd < 0) return; // virtual device - char pathSysDeviceReal[PATH_MAX]; - ssize_t pathLength = readlink(pathSysBlock, pathSysDeviceReal, sizeof(pathSysDeviceReal) - 1); - if (pathLength < 0) - continue; - pathSysDeviceReal[pathLength] = '\0'; - - if (strstr(pathSysDeviceReal, "/virtual/")) // virtual device - continue; - - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device", devName); - if (!ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY)) - continue; - - FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + { + if (ffAppendFileBufferRelative(devfd, "vendor", &name)) { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName); - if (ffAppendFileBuffer(pathSysBlock, &name)) - { - ffStrbufTrimRightSpace(&name); - if (name.length > 0) - ffStrbufAppendC(&name, ' '); - } + ffStrbufTrimRightSpace(&name); + if (name.length > 0) + ffStrbufAppendC(&name, ' '); + } - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName); - ffAppendFileBuffer(pathSysBlock, &name); + if (ffAppendFileBufferRelative(devfd, "model", &name)) ffStrbufTrimRightSpace(&name); - if (name.length == 0) - ffStrbufSetS(&name, devName); - else if (ffStrStartsWith(devName, "nvme")) + if (name.length == 0) + ffStrbufSetS(&name, devName); + else if (ffStrStartsWith(devName, "nvme")) + { + int devid, nsid; + if (sscanf(devName, "nvme%dn%d", &devid, &nsid) == 2) { - int devid, nsid; - if (sscanf(devName, "nvme%dn%d", &devid, &nsid) == 2) + bool multiNs = nsid > 1; + if (!multiNs) + { + char pathSysBlock[16]; + snprintf(pathSysBlock, ARRAY_SIZE(pathSysBlock), "nvme%dn2", devid); + multiNs = faccessat(devfd, pathSysBlock, F_OK, 0) == 0; + } + if (multiNs) { - bool multiNs = nsid > 1; - if (!multiNs) - { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/nvme%dn2", devName, devid); - multiNs = ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY); - } - if (multiNs) - { - // In Asahi Linux, there are multiple namespaces for the same NVMe drive. - ffStrbufAppendF(&name, " - %d", nsid); - } + // In Asahi Linux, there are multiple namespaces for the same NVMe drive. + ffStrbufAppendF(&name, " - %d", nsid); } } - - if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix)) - continue; } - // I/Os merges sectors ticks ... - uint64_t nRead, sectorRead, nWritten, sectorWritten; - { - char sysBlockStat[PROC_FILE_BUFFSIZ]; - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/stat", devName); - ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(sysBlockStat) - 1, sysBlockStat); - if (fileSize <= 0) continue; - sysBlockStat[fileSize] = '\0'; - if (sscanf(sysBlockStat, "%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u", &nRead, §orRead, &nWritten, §orWritten) <= 0) - continue; - } + if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix)) + return; + } + + // I/Os merges sectors ticks ... + uint64_t nRead, sectorRead, nWritten, sectorWritten; + { + char sysBlockStat[PROC_FILE_BUFFSIZ]; + ssize_t fileSize = ffReadFileDataRelative(dfd, "stat", ARRAY_SIZE(sysBlockStat) - 1, sysBlockStat); + if (fileSize <= 0) return; + sysBlockStat[fileSize] = '\0'; + if (sscanf(sysBlockStat, "%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u%" PRIu64 "%*u", &nRead, §orRead, &nWritten, §orWritten) <= 0) + return; + } + + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + ffStrbufInitMove(&device->name, &name); + ffStrbufInitF(&device->devPath, "/dev/%s", devName); + device->bytesRead = sectorRead * 512; + device->bytesWritten = sectorWritten * 512; + device->readCount = nRead; + device->writeCount = nWritten; +} + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); + if(sysBlockDirp == NULL) + return "opendir(\"/sys/block/\") == NULL"; + + struct dirent* sysBlockEntry; + while ((sysBlockEntry = readdir(sysBlockDirp)) != NULL) + { + const char* const devName = sysBlockEntry->d_name; + + if (devName[0] == '.') continue;; - FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); - ffStrbufInitMove(&device->name, &name); - ffStrbufInitF(&device->devPath, "/dev/%s", devName); - device->bytesRead = sectorRead * 512; - device->bytesWritten = sectorWritten * 512; - device->readCount = nRead; - device->writeCount = nWritten; + FF_AUTO_CLOSE_FD int dfd = openat(dirfd(sysBlockDirp), devName, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (dfd > 0) parseDiskIOCounters(dfd, devName, result, options); } return NULL; diff --git a/src/detection/diskio/diskio_nosupport.c b/src/detection/diskio/diskio_nosupport.c index 2e165c0c5..338c6e361 100644 --- a/src/detection/diskio/diskio_nosupport.c +++ b/src/detection/diskio/diskio_nosupport.c @@ -1,6 +1,6 @@ #include "diskio.h" -const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +const char* ffDiskIOGetIoCounters(FF_MAYBE_UNUSED FFlist* result, FF_MAYBE_UNUSED FFDiskIOOptions* options) { return "Not supported on this platform"; } diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index 1317057d2..da9bf8daf 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -22,7 +22,7 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFDiskIO }, sizeof(STORAGE_PROPERTY_QUERY), &sddBuffer, - sizeof(sddBuffer), + ARRAY_SIZE(sddBuffer), &retSize, NULL ) || retSize == 0) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 74898721b..235c00dc2 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -13,7 +13,8 @@ FFDisplayResult* ffdsAppendDisplay( bool primary, uint64_t id, uint32_t physicalWidth, - uint32_t physicalHeight) + uint32_t physicalHeight, + const char* platformApi) { if(width == 0 || height == 0) return NULL; @@ -31,6 +32,7 @@ FFDisplayResult* ffdsAppendDisplay( display->physicalWidth = physicalWidth; display->physicalHeight = physicalHeight; display->primary = primary; + display->platformApi = platformApi; display->bitDepth = 0; display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 5a030b12a..d1d21839e 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -70,6 +70,7 @@ typedef struct FFDisplayResult uint32_t physicalWidth; uint32_t physicalHeight; bool primary; + const char* platformApi; uint8_t bitDepth; FFDisplayHdrStatus hdrStatus; uint16_t manufactureYear; @@ -102,4 +103,5 @@ FFDisplayResult* ffdsAppendDisplay( bool primary, uint64_t id, uint32_t physicalWidth, - uint32_t physicalHeight); + uint32_t physicalHeight, + const char* platformApi); diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index a51d850f4..88e5b23d3 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -66,7 +66,8 @@ static void detectWithDumpsys(FFDisplayServerResult* ds) false, 0, 0, - 0 + 0, + "dumpsys" ); } @@ -100,7 +101,8 @@ static bool detectWithGetprop(FFDisplayServerResult* ds) false, 0, 0, - 0 + 0, + "getprop" ); } diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 8522ea477..d51584923 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -9,9 +9,9 @@ #include #include +#ifdef MAC_OS_X_VERSION_10_15 extern Boolean CoreDisplay_Display_SupportsHDRMode(CGDirectDisplayID display) __attribute__((weak_import)); extern Boolean CoreDisplay_Display_IsHDRModeEnabled(CGDirectDisplayID display) __attribute__((weak_import)); -#ifdef MAC_OS_X_VERSION_10_15 extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); #else #include @@ -21,7 +21,7 @@ static void detectDisplays(FFDisplayServerResult* ds) { CGDirectDisplayID screens[128]; uint32_t screenCount; - if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess) + if(CGGetOnlineDisplayList(ARRAY_SIZE(screens), screens, &screenCount) != kCGErrorSuccess) return; FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); @@ -94,7 +94,8 @@ static void detectDisplays(FFDisplayServerResult* ds) CGDisplayIsMain(screen), (uint64_t)screen, physicalWidth, - physicalHeight + physicalHeight, + "CoreGraphics" ); if (display) { @@ -111,6 +112,7 @@ static void detectDisplays(FFDisplayServerResult* ds) if (display->type == FF_DISPLAY_TYPE_BUILTIN) display->hdrStatus = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + #ifdef MAC_OS_X_VERSION_10_15 else if (CoreDisplay_Display_SupportsHDRMode) { if (CoreDisplay_Display_SupportsHDRMode(screen)) @@ -122,6 +124,7 @@ static void detectDisplays(FFDisplayServerResult* ds) else display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; } + #endif display->serial = CGDisplaySerialNumber(screen); int value; diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 11d9a5de7..d0825dbc6 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -36,9 +36,9 @@ static void detectDisplays(FFDisplayServerResult* ds) EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM) &monitors); DISPLAYCONFIG_PATH_INFO paths[128]; - uint32_t pathCount = sizeof(paths) / sizeof(paths[0]); + uint32_t pathCount = ARRAY_SIZE(paths); DISPLAYCONFIG_MODE_INFO modes[256]; - uint32_t modeCount = sizeof(modes) / sizeof(modes[0]); + uint32_t modeCount = ARRAY_SIZE(modes); if (QueryDisplayConfig( QDC_ONLY_ACTIVE_PATHS, @@ -66,7 +66,7 @@ static void detectDisplays(FFDisplayServerResult* ds) { FF_LIST_FOR_EACH(FFMonitorInfo, item, monitors) { - if (wcsncmp(item->info.szDevice, sourceName.viewGdiDeviceName, sizeof(sourceName.viewGdiDeviceName) / sizeof(wchar_t)) == 0) + if (wcsncmp(item->info.szDevice, sourceName.viewGdiDeviceName, ARRAY_SIZE(sourceName.viewGdiDeviceName)) == 0) { monitorInfo = item; break; @@ -102,11 +102,11 @@ static void detectDisplays(FFDisplayServerResult* ds) *pRegPath = *pDevPath; ++pRegPath; ++pDevPath; - assert(pRegPath < regPath + sizeof(regPath) / sizeof(wchar_t) + strlen("Device Parameters")); + assert(pRegPath < regPath + ARRAY_SIZE(regPath) + strlen("Device Parameters")); } wcscpy(pRegPath, L"Device Parameters"); - edidLength = sizeof(edidData); + edidLength = ARRAY_SIZE(edidData); if (RegGetValueW(HKEY_LOCAL_MACHINE, regPath, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidLength) == ERROR_SUCCESS && edidLength > 0 && edidLength % 128 == 0) { @@ -165,7 +165,8 @@ static void detectDisplays(FFDisplayServerResult* ds) !!(monitorInfo->info.dwFlags & MONITORINFOF_PRIMARY), (uint64_t)(uintptr_t) monitorInfo->handle, physicalWidth, - physicalHeight + physicalHeight, + "GDI" ); if (display) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index a84177650..cc4e07b21 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -86,7 +86,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) if (ffSettingsGetFreeBSDKenv("screen.height", &buf)) { uint32_t height = (uint32_t) ffStrbufToUInt(&buf, 0); - ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0, 0, 0); + ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0, 0, 0, "kenv"); } } } diff --git a/src/detection/displayserver/linux/displayserver_linux.h b/src/detection/displayserver/linux/displayserver_linux.h index b52b35b45..5452711e7 100644 --- a/src/detection/displayserver/linux/displayserver_linux.h +++ b/src/detection/displayserver/linux/displayserver_linux.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_DISPLAYSERVER -#define FASTFETCH_INCLUDED_DISPLAYSERVER - #include "detection/displayserver/displayserver.h" const char* ffdsConnectWayland(FFDisplayServerResult* result); @@ -18,5 +15,3 @@ const char* ffdsConnectDrm(FFDisplayServerResult* result); void ffdsDetectWMDE(FFDisplayServerResult* result); FFDisplayType ffdsGetDisplayType(const char* drmConnectorName); - -#endif diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 56a16d3f7..fb837e4a8 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -22,7 +22,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) struct dirent* entry; while((entry = readdir(dirp)) != NULL) { - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) + if(entry->d_name[0] == '.') continue; ffStrbufAppendS(&drmDir, entry->d_name); @@ -58,7 +58,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) } uint8_t edidData[512]; - ssize_t edidLength = ffReadFileData(drmDir.chars, sizeof(edidData), edidData); + ssize_t edidLength = ffReadFileData(drmDir.chars, ARRAY_SIZE(edidData), edidData); if(edidLength <= 0 || edidLength % 128 != 0) { edidLength = 0; @@ -66,7 +66,7 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) ffStrbufAppendS(&drmDir, "/modes"); char modes[32]; - if (ffReadFileData(drmDir.chars, sizeof(modes), modes) >= 3) + if (ffReadFileData(drmDir.chars, ARRAY_SIZE(modes), modes) >= 3) { sscanf(modes, "%ux%u", &width, &height); ffStrbufAppendS(&name, plainName); @@ -90,7 +90,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) false, 0, physicalWidth, - physicalHeight + physicalHeight, + "sysfs-drm" ); if (item && edidLength) { @@ -184,7 +185,7 @@ FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* struct dirent* entry; while((entry = readdir(dirp)) != NULL) { - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) + if(entry->d_name[0] == '.') continue; ffStrbufAppendS(&drmDir, entry->d_name); @@ -193,7 +194,7 @@ FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* char connectorId[16] = {}; ffStrbufAppendS(&drmDir, "/connector_id"); - ffReadFileData(drmDir.chars, sizeof(connectorId), connectorId); + ffReadFileData(drmDir.chars, ARRAY_SIZE(connectorId), connectorId); if (strtoul(connectorId, NULL, 10) != connId) { ffStrbufSubstrBefore(&drmDir, drmDirLength); @@ -228,7 +229,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeDevices) drmDevice* devices[64]; - int nDevices = ffdrmGetDevices(devices, sizeof(devices) / sizeof(devices[0])); + int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices)); if (nDevices <= 0) return "drmGetDevices() failed"; @@ -390,7 +391,8 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) false, conn->connector_id, conn->mmWidth, - conn->mmHeight + conn->mmHeight, + "libdrm" ); if (item) diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index 20227be36..ab9fc5c2f 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -129,7 +129,8 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist false, display.id, (uint32_t) display.physicalWidth, - (uint32_t) display.physicalHeight + (uint32_t) display.physicalHeight, + "wayland-global" ); if (item) { diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index 0993f72a5..1c4576dd4 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -112,6 +112,7 @@ static void waylandKdeNameListener(void* data, FF_MAYBE_UNUSED struct kde_output { WaylandDisplay* display = data; display->type = ffdsGetDisplayType(name); + // As display->id is used as an internal identifier, we don't need it to be NUL terminated strncpy((char*) &display->id, name, sizeof(display->id)); ffStrbufAppendS(&display->name, name); } @@ -194,7 +195,8 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, false, display.id, (uint32_t) display.physicalWidth, - (uint32_t) display.physicalHeight + (uint32_t) display.physicalHeight, + "wayland-kde" ); if (item) { diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index 457b334ee..e4b387a51 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -22,7 +22,7 @@ static bool waylandDetectWM(int fd, FFDisplayServerResult* result) { struct ucred ucred; - socklen_t len = sizeof(struct ucred); + socklen_t len = sizeof(ucred); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1 || ucred.pid <= 0) return false; @@ -108,7 +108,7 @@ static bool matchDrmConnector(const char* connName, WaylandDisplay* wldata) FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s%s/edid", drmDirPath, entry->d_name); uint8_t edidData[512]; - ssize_t edidLength = ffReadFileData(path.chars, sizeof(edidData), edidData); + ssize_t edidLength = ffReadFileData(path.chars, ARRAY_SIZE(edidData), edidData); if (edidLength > 0 && edidLength % 128 == 0) { ffEdidGetName(edidData, &wldata->edidName); @@ -249,7 +249,7 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result) FF_LIST_FOR_EACH(FFstrbuf, basePath, instance.state.platform.configDirs) { char path[1024]; - snprintf(path, sizeof(path) - 1, "%s%s", basePath->chars, fileName); + snprintf(path, ARRAY_SIZE(path) - 1, "%s%s", basePath->chars, fileName); if (ffReadFileBuffer(path, &monitorsXml)) break; } diff --git a/src/detection/displayserver/linux/wayland/zwlr-output.c b/src/detection/displayserver/linux/wayland/zwlr-output.c index 7e23d593e..c54818a64 100644 --- a/src/detection/displayserver/linux/wayland/zwlr-output.c +++ b/src/detection/displayserver/linux/wayland/zwlr-output.c @@ -138,7 +138,8 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output false, display.id, (uint32_t) display.physicalWidth, - (uint32_t) display.physicalHeight + (uint32_t) display.physicalHeight, + "wayland-zwlr" ); if (item) { diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index b9d6c3248..5502da78a 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -260,11 +260,11 @@ static const char* getFromProcesses(FFDisplayServerResult* result) int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_UID, (int) userId}; size_t length = 0; - if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0) + if(sysctl(request, ARRAY_SIZE(request), NULL, &length, NULL, 0) != 0) return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, NULL) failed"; FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length); - if(sysctl(request, sizeof(request) / sizeof(*request), procs, &length, NULL, 0) != 0) + if(sysctl(request, ARRAY_SIZE(request), procs, &length, NULL, 0) != 0) return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, procs) failed"; length /= sizeof(*procs); @@ -283,7 +283,7 @@ static const char* getFromProcesses(FFDisplayServerResult* result) #elif __OpenBSD__ kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); int count = 0; - const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, userId, sizeof(struct kinfo_proc), &count); + const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, userId, sizeof(*proc), &count); if (proc) { for (int i = 0; i < count; ++i) diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 18592a4c2..a9e4b8d79 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -118,7 +118,8 @@ const char* ffdsConnectXcb(FFDisplayServerResult* result) false, 0, (uint32_t) screen->width_in_millimeters, - (uint32_t) screen->height_in_millimeters + (uint32_t) screen->height_in_millimeters, + "xcb" ); ffxcb_screen_next(&iterator); } @@ -239,7 +240,8 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb primary, 0, (uint32_t) output->mm_width, - (uint32_t) output->mm_height + (uint32_t) output->mm_height, + "xcb-randr-crtc" ); if (item && edidLength) { @@ -327,7 +329,8 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* !!monitor->primary, 0, (uint32_t) monitor->width_in_millimeters, - (uint32_t) monitor->height_in_millimeters + (uint32_t) monitor->height_in_millimeters, + "xcb-randr-monitor" ); } @@ -381,7 +384,8 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) false, 0, (uint32_t) screen->width_in_millimeters, - (uint32_t) screen->height_in_millimeters + (uint32_t) screen->height_in_millimeters, + "xcb-randr-screen" ); } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 471961195..00ef3ce7c 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -89,7 +89,8 @@ const char* ffdsConnectXlib(FFDisplayServerResult* result) false, 0, (uint32_t) WidthMMOfScreen(screen), - (uint32_t) HeightMMOfScreen(screen) + (uint32_t) HeightMMOfScreen(screen), + "xlib" ); } @@ -193,7 +194,8 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* primary, 0, (uint32_t) output->mm_width, - (uint32_t) output->mm_height + (uint32_t) output->mm_height, + "xlib-randr-crtc" ); if (edidLength) @@ -268,7 +270,8 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo) !!monitorInfo->primary, 0, (uint32_t) monitorInfo->mwidth, - (uint32_t) monitorInfo->mheight + (uint32_t) monitorInfo->mheight, + "xlib-randr-monitor" ); } @@ -318,7 +321,8 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen) false, 0, (uint32_t) WidthMMOfScreen(screen), - (uint32_t) HeightMMOfScreen(screen) + (uint32_t) HeightMMOfScreen(screen), + "xlib_randr_screen" ); } diff --git a/src/detection/font/font_linux.c b/src/detection/font/font_linux.c index 7a7acfe43..4d58392c9 100644 --- a/src/detection/font/font_linux.c +++ b/src/detection/font/font_linux.c @@ -11,7 +11,7 @@ static void generateString(FFFontResult* font) ffStrbufAppend(&font->display, &font->fonts[0]); ffStrbufAppendS(&font->display, " [Qt]"); - for(uint8_t i = 1; i < sizeof(font->fonts) / sizeof(font->fonts[0]); i++) + for(uint8_t i = 1; i < ARRAY_SIZE(font->fonts); i++) { if(font->fonts[i].length > 0) { diff --git a/src/detection/font/font_windows.c b/src/detection/font/font_windows.c index 46a63f520..eb5446006 100644 --- a/src/detection/font/font_windows.c +++ b/src/detection/font/font_windows.c @@ -6,7 +6,7 @@ static void generateString(FFFontResult* font) { const char* types[] = { "Caption", "Menu", "Message", "Status" }; - for(uint32_t i = 0; i < sizeof(types) / sizeof(types[0]); ++i) + for(uint32_t i = 0; i < ARRAY_SIZE(types); ++i) { if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i])) { @@ -31,7 +31,7 @@ const char* ffDetectFontImpl(FFFontResult* result) LOGFONTW* fonts[4] = { &info.lfCaptionFont, &info.lfMenuFont, &info.lfMessageFont, &info.lfStatusFont }; - for(uint32_t i = 0; i < sizeof(fonts) / sizeof(fonts[0]); ++i) + for(uint32_t i = 0; i < ARRAY_SIZE(fonts); ++i) { ffStrbufSetWS(&result->fonts[i], fonts[i]->lfFaceName); if(fonts[i]->lfHeight < 0) diff --git a/src/detection/gamepad/gamepad_bsd.c b/src/detection/gamepad/gamepad_bsd.c index 340ff1165..a84f4f42c 100644 --- a/src/detection/gamepad/gamepad_bsd.c +++ b/src/detection/gamepad/gamepad_bsd.c @@ -13,7 +13,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) char path[16]; for (int i = 0; i < MAX_UHID_JOYS; i++) { - snprintf(path, sizeof(path), "/dev/uhid%d", i); + snprintf(path, ARRAY_SIZE(path), "/dev/uhid%d", i); FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) continue; @@ -31,8 +31,9 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) if (HID_PAGE(hItem.usage) != 1) continue; switch (HID_USAGE(hItem.usage)) { - case 1: // FreeBSD returns 1 for my Pro Controller for some reason - case 5: + case 1: // Pointer. FreeBSD returns 1 for my Pro Controller for some reason + case 4: // Joystick + case 5: // Gamepad break; default: continue; diff --git a/src/detection/gamepad/gamepad_linux.c b/src/detection/gamepad/gamepad_linux.c index 50d04df5e..d8dacb40e 100644 --- a/src/detection/gamepad/gamepad_linux.c +++ b/src/detection/gamepad/gamepad_linux.c @@ -28,7 +28,7 @@ static void detectGamepad(FFlist* devices, FFstrbuf* name, FFstrbuf* path) ffStrbufAppendS(path, entry->d_name); ffStrbufAppendS(path, "/capacity"); // /sys/class/input/jsX/device/device/power_supply/XXX/capacity char capacity[32]; - ssize_t nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity); + ssize_t nRead = ffReadFileData(path->chars, ARRAY_SIZE(capacity) - 1, capacity); if (nRead > 0) // Tested with a PS4 controller { capacity[nRead] = '\0'; @@ -37,7 +37,7 @@ static void detectGamepad(FFlist* devices, FFstrbuf* name, FFstrbuf* path) } ffStrbufAppendS(path, "_level"); - nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity); + nRead = ffReadFileData(path->chars, ARRAY_SIZE(capacity) - 1, capacity); if (nRead > 0) // Tested with a NS Pro controller { // https://github.com/torvalds/linux/blob/52b1853b080a082ec3749c3a9577f6c71b1d4a90/drivers/power/supply/power_supply_sysfs.c#L124 @@ -68,7 +68,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) { if (!ffStrStartsWith(entry->d_name, "js")) continue; - if (!ffCharIsDigit(entry->d_name[2])) + if (!ffCharIsDigit(entry->d_name[strlen("js")])) continue; ffStrbufAppendS(&path, entry->d_name); diff --git a/src/detection/gamepad/gamepad_windows.c b/src/detection/gamepad/gamepad_windows.c index ab4540af0..d441b01ef 100644 --- a/src/detection/gamepad/gamepad_windows.c +++ b/src/detection/gamepad/gamepad_windows.c @@ -78,7 +78,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) for (UINT i = 0; i < nDevices; ++i) { - if (pRawInputDeviceList[i].dwType != 2) continue; + if (pRawInputDeviceList[i].dwType != RIM_TYPEHID) continue; HANDLE hDevice = pRawInputDeviceList[i].hDevice; @@ -87,7 +87,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1) continue; - if (rdi.hid.usUsagePage != 1 || rdi.hid.usUsage != 5) // Gamepad + if (rdi.hid.usUsagePage != 1 || (rdi.hid.usUsage != 4/*Joystick*/ && rdi.hid.usUsage != 5/*Gamepad*/)) continue; WCHAR devName[MAX_PATH] = L""; @@ -104,7 +104,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) if (knownGamepad) ffStrbufSetS(&device->name, knownGamepad); HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (!hHidFile) + if (hHidFile == INVALID_HANDLE_VALUE) { if (!knownGamepad) ffStrbufSetF(&device->name, "Unknown gamepad %04X-%04X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId); @@ -114,10 +114,10 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) if (!knownGamepad) { wchar_t displayName[126]; - if (HidD_GetProductString(hHidFile, displayName, sizeof(displayName))) + if (HidD_GetProductString(hHidFile, displayName, sizeof(displayName) /*in bytes*/)) { wchar_t manufacturer[126]; - if (HidD_GetManufacturerString(hHidFile, manufacturer, sizeof(manufacturer))) + if (HidD_GetManufacturerString(hHidFile, manufacturer, sizeof(manufacturer) /*in bytes*/)) { ffStrbufSetWS(&device->name, manufacturer); FF_STRBUF_AUTO_DESTROY displayNameStr = ffStrbufCreateWS(displayName); @@ -131,6 +131,10 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) } } + wchar_t serialNumber[127] = L""; + if (HidD_GetSerialNumberString(hHidFile, serialNumber, sizeof(serialNumber) /*in bytes*/)) + ffStrbufSetWS(&device->serial, serialNumber); + PHIDP_PREPARSED_DATA preparsedData = NULL; if (HidD_GetPreparsedData(hHidFile, &preparsedData)) { @@ -140,10 +144,6 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) if (!NT_SUCCESS(capsResult)) continue; - wchar_t serialNumber[127] = L""; - if (HidD_GetSerialNumberString(hHidFile, serialNumber, sizeof(serialNumber))) - ffStrbufSetWS(&device->serial, serialNumber); - if ( (rdi.hid.dwVendorId == 0x054C && ( rdi.hid.dwProductId == 0x05C4 || // PS4 Gen1 diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 99195af20..b64935df4 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -76,7 +76,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { char query[32]; - snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid); + snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid); ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); } if (gpu->name.length == 0) diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index ffa04ccb8..c01c80ab4 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -128,7 +128,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe if (result.memory) { ctl_mem_handle_t memoryModules[16]; - uint32_t memoryCount = sizeof(memoryModules) / sizeof(memoryModules[0]); + uint32_t memoryCount = ARRAY_SIZE(memoryModules); if (igclData.ffctlEnumMemoryModules(device, &memoryCount, memoryModules) == CTL_RESULT_SUCCESS && memoryCount > 0) { result.memory->used = 0; @@ -157,7 +157,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe if (result.temp) { ctl_temp_handle_t sensors[16]; - uint32_t sensorCount = sizeof(sensors) / sizeof(sensors[0]); + uint32_t sensorCount = ARRAY_SIZE(sensors); if (igclData.ffctlEnumTemperatureSensors(device, &sensorCount, sensors) == CTL_RESULT_SUCCESS && sensorCount > 0) { double sumValue = 0; @@ -178,7 +178,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe if (result.frequency) { ctl_freq_handle_t domains[16]; - uint32_t domainCount = sizeof(domains) / sizeof(domains[0]); + uint32_t domainCount = ARRAY_SIZE(domains); if (igclData.ffctlEnumFrequencyDomains(device, &domainCount, domains) == CTL_RESULT_SUCCESS && domainCount > 0) { double maxValue = 0; diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index c3678d6e6..a915a25e9 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -32,7 +32,7 @@ static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer uint32_t pciDirLength = pciDir->length; ffStrbufAppendS(pciDir, "/driver"); char pathBuf[PATH_MAX]; - ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf)); + ssize_t resultLength = readlink(pciDir->chars, pathBuf, ARRAY_SIZE(pathBuf)); if(resultLength <= 0) return false; const char* slash = memrchr(pathBuf, '/', (size_t) resultLength); @@ -78,7 +78,7 @@ static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer return true; } -static const char* drmFindRenderFromCard(const char* drmCardKey, FFstrbuf* result) +FF_MAYBE_UNUSED static const char* drmFindRenderFromCard(const char* drmCardKey, FFstrbuf* result) { char path[PATH_MAX]; sprintf(path, "/sys/class/drm/%s/device/drm", drmCardKey); @@ -395,6 +395,7 @@ static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, } return NULL; #else + FF_UNUSED(gpu, drmKey, buffer); return "Fastfetch is not compiled with drm support"; #endif } @@ -414,7 +415,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf const char* pPciPath = NULL; if (drmKey) { - ssize_t pathLength = readlink(deviceDir->chars, pciPath, sizeof(pciPath) - 1); + ssize_t pathLength = readlink(deviceDir->chars, pciPath, ARRAY_SIZE(pciPath) - 1); if (pathLength <= 0) return "Unable to get PCI device path"; pciPath[pathLength] = '\0'; @@ -459,8 +460,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf { if (ffStrStartsWith(entry->d_name, "card")) { - strncpy(drmKeyBuffer, entry->d_name, sizeof(drmKeyBuffer) - 1); - drmKeyBuffer[sizeof(drmKeyBuffer) - 1] = '\0'; + ffStrCopyN(drmKeyBuffer, entry->d_name, ARRAY_SIZE(drmKeyBuffer)); drmKey = drmKeyBuffer; break; } @@ -493,7 +493,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf if (pend != buffer->chars) { char query[32]; - snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); + snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); #ifdef FF_CUSTOM_AMDGPU_IDS_PATH ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name); #else diff --git a/src/detection/gpu/gpu_mthreads.c b/src/detection/gpu/gpu_mthreads.c index 80164320d..ff1347851 100644 --- a/src/detection/gpu/gpu_mthreads.c +++ b/src/detection/gpu/gpu_mthreads.c @@ -86,7 +86,7 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) { char pciBusIdStr[32]; - snprintf(pciBusIdStr, sizeof(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func); + snprintf(pciBusIdStr, ARRAY_SIZE(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func); MtmlReturn ret = mtmlData.ffmtmlLibraryInitDeviceByPciSbdf(mtmlData.lib, pciBusIdStr, &device); if (ret != MTML_SUCCESS) @@ -195,7 +195,7 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive if (result.name) { char name[MTML_DEVICE_NAME_BUFFER_SIZE]; - if (mtmlData.ffmtmlDeviceGetName(device, name, sizeof(name)) == MTML_SUCCESS) + if (mtmlData.ffmtmlDeviceGetName(device, name, ARRAY_SIZE(name)) == MTML_SUCCESS) ffStrbufSetS(result.name, name); } diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index c2cc33d1d..e91d7eeec 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -59,7 +59,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) { char pciBusIdStr[32]; - snprintf(pciBusIdStr, sizeof(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func); + snprintf(pciBusIdStr, ARRAY_SIZE(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func); nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(pciBusIdStr, &device); if (ret != NVML_SUCCESS) @@ -148,7 +148,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR if (result.name) { char name[NVML_DEVICE_NAME_V2_BUFFER_SIZE]; - if (nvmlData.ffnvmlDeviceGetName(device, name, sizeof(name)) == NVML_SUCCESS) + if (nvmlData.ffnvmlDeviceGetName(device, name, ARRAY_SIZE(name)) == NVML_SUCCESS) ffStrbufSetS(result.name, name); } diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index 5397f0fe6..fe0f0c939 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -55,7 +55,7 @@ static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t char buffer[32]; // Search for vendor - uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor); + uint32_t len = (uint32_t) snprintf(buffer, ARRAY_SIZE(buffer), "\n%04x ", vendor); char* start = (char*) memmem(content->chars, content->length, buffer, len); char* end = content->chars + content->length; if (start) @@ -83,7 +83,7 @@ static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t } // Search for device - len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device); + len = (uint32_t) snprintf(buffer, ARRAY_SIZE(buffer), "\n\t%04x ", device); start = memmem(start, (size_t) (end - start), buffer, len); if (start) { @@ -138,7 +138,7 @@ static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FF if (!gpu->vendor.length) ffStrbufSetS(&gpu->vendor, pvendor->name); - const FFPciDevice* pdevice = (const FFPciDevice*) bsearch(&device, pvendor->devices, pvendor->nDevices, sizeof(FFPciDevice), (void*) pciDeviceCmp); + const FFPciDevice* pdevice = (const FFPciDevice*) bsearch(&device, pvendor->devices, pvendor->nDevices, sizeof(*pdevice), (void*) pciDeviceCmp); if (pdevice) { diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index 6e8d19460..4edfb7fb0 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -67,7 +67,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { char query[32]; - snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); + snprintf(query, ARRAY_SIZE(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); } diff --git a/src/detection/host/host_nosupport.c b/src/detection/host/host_nosupport.c index 6f3934823..29a54ebc9 100644 --- a/src/detection/host/host_nosupport.c +++ b/src/detection/host/host_nosupport.c @@ -1,6 +1,6 @@ #include "host.h" -const char* ffDetectHost(FFHostResult* host) +const char* ffDetectHost(FF_MAYBE_UNUSED FFHostResult* host) { return "Not supported on this platform"; } diff --git a/src/detection/keyboard/keyboard.h b/src/detection/keyboard/keyboard.h new file mode 100644 index 000000000..8f0a8a85e --- /dev/null +++ b/src/detection/keyboard/keyboard.h @@ -0,0 +1,9 @@ +#include "fastfetch.h" + +typedef struct FFKeyboardDevice +{ + FFstrbuf serial; + FFstrbuf name; +} FFKeyboardDevice; + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */); diff --git a/src/detection/keyboard/keyboard_apple.c b/src/detection/keyboard/keyboard_apple.c new file mode 100644 index 000000000..46278c5aa --- /dev/null +++ b/src/detection/keyboard/keyboard_apple.c @@ -0,0 +1,42 @@ +#include "keyboard.h" +#include "util/apple/cf_helpers.h" +#include "util/mallocHelper.h" + +#include +#include + +static void enumSet(IOHIDDeviceRef value, FFlist* results) +{ + FFKeyboardDevice* device = (FFKeyboardDevice*) ffListAdd(results); + ffStrbufInit(&device->serial); + ffStrbufInit(&device->name); + + CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey)); + ffCfStrGetString(product, &device->name); + + CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey)); + ffCfStrGetString(serialNumber, &device->serial); +} + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */) +{ + IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) + return "IOHIDManagerOpen() failed"; + + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ + CFSTR(kIOHIDDeviceUsagePageKey), + CFSTR(kIOHIDDeviceUsageKey) + }, (const void **)(CFNumberRef[]){ + ffCfCreateInt(kHIDPage_GenericDesktop), + ffCfCreateInt(kHIDUsage_GD_Keyboard) + }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + IOHIDManagerSetDeviceMatching(manager, matching1); + + CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager); + if (set) + CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices); + IOHIDManagerClose(manager, kIOHIDOptionsTypeNone); + + return NULL; +} diff --git a/src/detection/keyboard/keyboard_bsd.c b/src/detection/keyboard/keyboard_bsd.c new file mode 100644 index 000000000..4f424ba70 --- /dev/null +++ b/src/detection/keyboard/keyboard_bsd.c @@ -0,0 +1,47 @@ +#include "keyboard.h" +#include "common/io/io.h" + +#include +#include +#include +#include + +#define MAX_UHID_JOYS 64 + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */) +{ + char path[16]; + for (int i = 0; i < MAX_UHID_JOYS; i++) + { + snprintf(path, ARRAY_SIZE(path), "/dev/uhid%d", i); + FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) continue; + + report_desc_t repDesc = hid_get_report_desc(fd); + if (!repDesc) continue; + + int reportId = hid_get_report_id(fd); + + struct hid_data* hData = hid_start_parse(repDesc, 0, reportId); + if (hData) + { + struct hid_item hItem; + while (hid_get_item(hData, &hItem) > 0) + { + if (HID_PAGE(hItem.usage) != 1 || HID_USAGE(hItem.usage) != 6) continue; + + struct usb_device_info di; + if (ioctl(fd, USB_GET_DEVICEINFO, &di) != -1) + { + FFKeyboardDevice* device = (FFKeyboardDevice*) ffListAdd(devices); + ffStrbufInitS(&device->serial, di.udi_serial); + ffStrbufInitS(&device->name, di.udi_product); + } + } + } + + hid_dispose_report_desc(repDesc); + } + + return NULL; +} diff --git a/src/detection/keyboard/keyboard_linux.c b/src/detection/keyboard/keyboard_linux.c new file mode 100644 index 000000000..8952ca674 --- /dev/null +++ b/src/detection/keyboard/keyboard_linux.c @@ -0,0 +1,57 @@ +#include "keyboard.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */) +{ + // There is no /sys/class/input/kbd* on Linux + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/dev/input/by-path/"); + if (dirp == NULL) + return "opendir(\"/dev/input/by-path/\") == NULL"; + + uint64_t flags = 0; + + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); + + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (!ffStrEndsWith(entry->d_name, "-event-kbd")) + continue; + + char buffer[32]; // `../eventX` + ssize_t len = readlinkat(dirfd(dirp), entry->d_name, buffer, ARRAY_SIZE(buffer) - 1); + if (len != strlen("../eventX") || !ffStrStartsWith(buffer, "../event")) continue; + buffer[len] = 0; + + const char* eventid = buffer + strlen("../event"); + + char* pend = NULL; + uint32_t index = (uint32_t) strtoul(eventid, &pend, 10); + if (pend == eventid) continue; + + // Ignore duplicate entries + if (flags & (1 << index)) + continue; + flags |= (1 << index); + + ffStrbufSetF(&path, "/sys/class/input/event%s/device/name", eventid); + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + if (ffAppendFileBuffer(path.chars, &name)) + { + ffStrbufTrimRightSpace(&name); + ffStrbufSubstrBefore(&path, path.length - 4); + + FFKeyboardDevice* device = (FFKeyboardDevice*) ffListAdd(devices); + ffStrbufInitMove(&device->name, &name); + ffStrbufInit(&device->serial); + + ffStrbufAppendS(&path, "uniq"); + if (ffAppendFileBuffer(path.chars, &device->serial)) + ffStrbufTrimRightSpace(&device->serial); + } + } + + return NULL; +} diff --git a/src/detection/keyboard/keyboard_nosupport.c b/src/detection/keyboard/keyboard_nosupport.c new file mode 100644 index 000000000..c6431c8fb --- /dev/null +++ b/src/detection/keyboard/keyboard_nosupport.c @@ -0,0 +1,6 @@ +#include "keyboard.h" + +const char* ffDetectKeyboard(FF_MAYBE_UNUSED FFlist* devices /* List of FFKeyboardDevice */) +{ + return "No mouse support on this platform"; +} diff --git a/src/detection/keyboard/keyboard_windows.c b/src/detection/keyboard/keyboard_windows.c new file mode 100644 index 000000000..24cd8a452 --- /dev/null +++ b/src/detection/keyboard/keyboard_windows.c @@ -0,0 +1,82 @@ +#define INITGUID + +#include "keyboard.h" +#include "common/io/io.h" +#include "util/mallocHelper.h" +#include "util/windows/unicode.h" + +#include +#include +#include +#include +#include + +const char* ffDetectKeyboard(FFlist* devices /* List of FFKeyboardDevice */) +{ + UINT nDevices = 0; + if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST))) + return "GetRawInputDeviceList(NULL) failed"; + if (nDevices == 0) + return "No HID devices found"; + + RAWINPUTDEVICELIST* FF_AUTO_FREE pRawInputDeviceList = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices); + if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1) + return "GetRawInputDeviceList(pRawInputDeviceList) failed"; + + + for (UINT i = 0; i < nDevices; ++i) + { + if (pRawInputDeviceList[i].dwType != RIM_TYPEKEYBOARD) continue; + + HANDLE hDevice = pRawInputDeviceList[i].hDevice; + + RID_DEVICE_INFO rdi; + UINT rdiSize = sizeof(rdi); + if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1) + continue; + + WCHAR devName[MAX_PATH]; + UINT nameSize = MAX_PATH; + if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, devName, &nameSize) == (UINT) -1) + continue; + + FFKeyboardDevice* device = (FFKeyboardDevice*) ffListAdd(devices); + ffStrbufInit(&device->serial); + ffStrbufInit(&device->name); + + wchar_t buffer[MAX_PATH]; + + HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, 0 /* must be 0 instead of GENERIC_READ */, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hHidFile != INVALID_HANDLE_VALUE) + { + if (HidD_GetProductString(hHidFile, buffer, (ULONG) sizeof(buffer))) + ffStrbufSetWS(&device->name, buffer); + + if (HidD_GetSerialNumberString(hHidFile, buffer, sizeof(buffer))) + ffStrbufSetWS(&device->serial, buffer); + } + + if (!device->name.length) + { + // https://stackoverflow.com/a/64321096/9976392 + DEVPROPTYPE propertyType; + ULONG propertySize = sizeof(buffer); + + if (CM_Get_Device_Interface_PropertyW(devName, &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE) buffer, &propertySize, 0) == CR_SUCCESS) + { + DEVINST devInst; + if (CM_Locate_DevNodeW(&devInst, buffer, CM_LOCATE_DEVNODE_NORMAL) == CR_SUCCESS) + { + propertySize = sizeof(buffer); + if (CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_NAME, &propertyType, (PBYTE) buffer, &propertySize, 0) == CR_SUCCESS) + ffStrbufSetWS(&device->name, buffer); + } + } + } + + if (!device->name.length) + ffStrbufSetF(&device->name, "Unknown device %04X-%04X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId); + } + + return NULL; +} diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 243091ddf..adf5713da 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -198,7 +198,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) char addressBuffer[32]; uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr); - snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", + snprintf(addressBuffer, ARRAY_SIZE(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); } @@ -210,7 +210,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) char addressBuffer[32]; uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr; - snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", + snprintf(addressBuffer, ARRAY_SIZE(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); } @@ -231,7 +231,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) FF_LIST_FOR_EACH(FFLocalIpResult, iface, *results) { struct ifreq ifr; - strncpy(ifr.ifr_name, iface->name.chars, IFNAMSIZ - 1); + ffStrCopyN(ifr.ifr_name, iface->name.chars, IFNAMSIZ); if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) { @@ -248,7 +248,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) iface->speed = (edata.speed_hi << 16) | edata.speed; // ethtool_cmd_speed is not available on Android #elif __FreeBSD__ || __APPLE__ || __OpenBSD__ struct ifmediareq ifmr = {}; - strncpy(ifmr.ifm_name, iface->name.chars, IFNAMSIZ - 1); + ffStrCopyN(ifmr.ifm_name, iface->name.chars, IFNAMSIZ); if (ioctl(sockfd, SIOCGIFMEDIA, &ifmr) == 0 && (IFM_TYPE(ifmr.ifm_active) & IFM_ETHER)) { switch (IFM_SUBTYPE(ifmr.ifm_active)) diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 00fee43ed..7d5091699 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -106,7 +106,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) bool newIp = true; char name[128]; - WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, sizeof(name), NULL, NULL); + WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, ARRAY_SIZE(name), NULL, NULL); if (options->namePrefix.length && strncmp(name, options->namePrefix.chars, options->namePrefix.length) != 0) continue; @@ -114,7 +114,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) { char addressBuffer[32]; uint8_t* ptr = adapter->PhysicalAddress; - snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", + snprintf(addressBuffer, ARRAY_SIZE(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); addNewIp(results, name, addressBuffer, -1, newIp, isDefaultRoute); newIp = false; diff --git a/src/detection/media/media_apple.m b/src/detection/media/media_apple.m index e17ab48e2..c576c7e08 100644 --- a/src/detection/media/media_apple.m +++ b/src/detection/media/media_apple.m @@ -67,7 +67,7 @@ if(result->playerId.length > 0) { char buf[128]; - snprintf(buf, sizeof(buf), "name of app id \"%s\"", result->playerId.chars); + snprintf(buf, ARRAY_SIZE(buf), "name of app id \"%s\"", result->playerId.chars); ffOsascript(buf, &result->player); } diff --git a/src/detection/memory/memory_linux.c b/src/detection/memory/memory_linux.c index 6f9e87a0f..14c86bf93 100644 --- a/src/detection/memory/memory_linux.c +++ b/src/detection/memory/memory_linux.c @@ -7,9 +7,9 @@ const char* ffDetectMemory(FFMemoryResult* ram) { char buf[PROC_FILE_BUFFSIZ]; - ssize_t nRead = ffReadFileData("/proc/meminfo", sizeof(buf) - 1, buf); + ssize_t nRead = ffReadFileData("/proc/meminfo", ARRAY_SIZE(buf) - 1, buf); if(nRead < 0) - return "ffReadFileData(\"/proc/meminfo\", sizeof(buf)-1, buf)"; + return "ffReadFileData(\"/proc/meminfo\", ARRAY_SIZE(buf)-1, buf)"; buf[nRead] = '\0'; uint64_t memTotal = 0, diff --git a/src/detection/memory/memory_nosupport.c b/src/detection/memory/memory_nosupport.c index 76cd7f828..180a276aa 100644 --- a/src/detection/memory/memory_nosupport.c +++ b/src/detection/memory/memory_nosupport.c @@ -1,6 +1,6 @@ #include "memory.h" -const char* ffDetectMemory(FFMemoryResult* ram) +const char* ffDetectMemory(FF_MAYBE_UNUSED FFMemoryResult* ram) { return "Not supported on this platform"; } diff --git a/src/detection/memory/memory_obsd.c b/src/detection/memory/memory_obsd.c index c4119efb3..9efc21ead 100644 --- a/src/detection/memory/memory_obsd.c +++ b/src/detection/memory/memory_obsd.c @@ -1,20 +1,17 @@ #include "memory.h" #include "common/sysctl.h" -#include +#include const char* ffDetectMemory(FFMemoryResult* ram) { - size_t length = sizeof(ram->bytesTotal); - if (sysctl((int[]){ CTL_HW, HW_PHYSMEM }, 2, &ram->bytesTotal, &length, NULL, 0) < 0) - return "Failed to read hw.physmem"; + struct uvmexp buf; + size_t length = sizeof(buf); + if (sysctl((int[]){ CTL_VM, VM_UVMEXP }, 2, &buf, &length, NULL, 0) < 0) + return "sysctl(CTL_VM, VM_UVMEXP) failed"; - struct vmtotal vmtotal; - length = sizeof(vmtotal); - if (sysctl((int[]) {CTL_VM, VM_METER}, 2, &vmtotal, &length, NULL, 0) < 0) - return "sysctl(VM_METER) failed"; - - ram->bytesUsed = ram->bytesTotal - vmtotal.t_free * instance.state.platform.sysinfo.pageSize; + ram->bytesTotal = (uint64_t) buf.npages * instance.state.platform.sysinfo.pageSize; + ram->bytesUsed = ram->bytesTotal - (uint64_t) buf.free * instance.state.platform.sysinfo.pageSize; return NULL; } diff --git a/src/detection/memory/memory_sunos.c b/src/detection/memory/memory_sunos.c index 4633eb6c0..1df271055 100644 --- a/src/detection/memory/memory_sunos.c +++ b/src/detection/memory/memory_sunos.c @@ -1,34 +1,10 @@ #include "memory.h" -#include - -static inline void kstatFreeWrap(kstat_ctl_t** pkc) -{ - assert(pkc); - if (*pkc) - kstat_close(*pkc); -} +#include const char* ffDetectMemory(FFMemoryResult* ram) { - __attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open(); - if (!kc) - return "kstat_open() failed"; - - kstat_t* ks = kstat_lookup(kc, "unix", -1, "system_pages"); - if (!ks) - return "kstat_lookup() failed"; - - if (kstat_read(kc, ks, NULL) < 0) - return "kstat_read() failed"; - - { - kstat_named_t* kn = kstat_data_lookup(ks, "pagestotal"); - ram->bytesTotal = kn->value.ui64 * instance.state.platform.sysinfo.pageSize; - } - { - kstat_named_t* kn = kstat_data_lookup(ks, "pagesfree"); - ram->bytesUsed = ram->bytesTotal - kn->value.ui64 * instance.state.platform.sysinfo.pageSize; - } + ram->bytesTotal = sysconf(_SC_PHYS_PAGES) * instance.state.platform.sysinfo.pageSize; + ram->bytesUsed = ram->bytesTotal - sysconf(_SC_AVPHYS_PAGES) * instance.state.platform.sysinfo.pageSize; return NULL; } diff --git a/src/detection/mouse/mouse.h b/src/detection/mouse/mouse.h new file mode 100644 index 000000000..710b4f8df --- /dev/null +++ b/src/detection/mouse/mouse.h @@ -0,0 +1,9 @@ +#include "fastfetch.h" + +typedef struct FFMouseDevice +{ + FFstrbuf serial; + FFstrbuf name; +} FFMouseDevice; + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */); diff --git a/src/detection/mouse/mouse_apple.c b/src/detection/mouse/mouse_apple.c new file mode 100644 index 000000000..feadff649 --- /dev/null +++ b/src/detection/mouse/mouse_apple.c @@ -0,0 +1,42 @@ +#include "mouse.h" +#include "util/apple/cf_helpers.h" +#include "util/mallocHelper.h" + +#include +#include + +static void enumSet(IOHIDDeviceRef value, FFlist* results) +{ + FFMouseDevice* device = (FFMouseDevice*) ffListAdd(results); + ffStrbufInit(&device->serial); + ffStrbufInit(&device->name); + + CFStringRef product = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDProductKey)); + ffCfStrGetString(product, &device->name); + + CFStringRef serialNumber = IOHIDDeviceGetProperty(value, CFSTR(kIOHIDSerialNumberKey)); + ffCfStrGetString(serialNumber, &device->serial); +} + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) +{ + IOHIDManagerRef FF_CFTYPE_AUTO_RELEASE manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (IOHIDManagerOpen(manager, kIOHIDOptionsTypeNone) != kIOReturnSuccess) + return "IOHIDManagerOpen() failed"; + + CFDictionaryRef FF_CFTYPE_AUTO_RELEASE matching1 = CFDictionaryCreate(kCFAllocatorDefault, (const void **)(CFStringRef[]){ + CFSTR(kIOHIDDeviceUsagePageKey), + CFSTR(kIOHIDDeviceUsageKey) + }, (const void **)(CFNumberRef[]){ + ffCfCreateInt(kHIDPage_GenericDesktop), + ffCfCreateInt(kHIDUsage_GD_Mouse) + }, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + IOHIDManagerSetDeviceMatching(manager, matching1); + + CFSetRef FF_CFTYPE_AUTO_RELEASE set = IOHIDManagerCopyDevices(manager); + if (set) + CFSetApplyFunction(set, (CFSetApplierFunction) &enumSet, devices); + IOHIDManagerClose(manager, kIOHIDOptionsTypeNone); + + return NULL; +} diff --git a/src/detection/mouse/mouse_bsd.c b/src/detection/mouse/mouse_bsd.c new file mode 100644 index 000000000..6018d1893 --- /dev/null +++ b/src/detection/mouse/mouse_bsd.c @@ -0,0 +1,47 @@ +#include "mouse.h" +#include "common/io/io.h" + +#include +#include +#include +#include + +#define MAX_UHID_JOYS 64 + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) +{ + char path[16]; + for (int i = 0; i < MAX_UHID_JOYS; i++) + { + snprintf(path, ARRAY_SIZE(path), "/dev/uhid%d", i); + FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) continue; + + report_desc_t repDesc = hid_get_report_desc(fd); + if (!repDesc) continue; + + int reportId = hid_get_report_id(fd); + + struct hid_data* hData = hid_start_parse(repDesc, 0, reportId); + if (hData) + { + struct hid_item hItem; + while (hid_get_item(hData, &hItem) > 0) + { + if (HID_PAGE(hItem.usage) != 1 || HID_USAGE(hItem.usage) != 2) continue; + + struct usb_device_info di; + if (ioctl(fd, USB_GET_DEVICEINFO, &di) != -1) + { + FFMouseDevice* device = (FFMouseDevice*) ffListAdd(devices); + ffStrbufInitS(&device->serial, di.udi_serial); + ffStrbufInitS(&device->name, di.udi_product); + } + } + } + + hid_dispose_report_desc(repDesc); + } + + return NULL; +} diff --git a/src/detection/mouse/mouse_linux.c b/src/detection/mouse/mouse_linux.c new file mode 100644 index 000000000..d03a3e7e5 --- /dev/null +++ b/src/detection/mouse/mouse_linux.c @@ -0,0 +1,44 @@ +#include "mouse.h" +#include "common/io/io.h" +#include "util/stringUtils.h" + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/input/"); + if (dirp == NULL) + return "opendir(\"/sys/class/input/\") == NULL"; + + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/input/"); + uint32_t baseLen = path.length; + + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (!ffStrStartsWith(entry->d_name, "mouse")) + continue; + if (!ffCharIsDigit(entry->d_name[strlen("mouse")])) + continue; + + ffStrbufAppendS(&path, entry->d_name); + ffStrbufAppendS(&path, "/device/name"); + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + if (ffAppendFileBuffer(path.chars, &name)) + { + ffStrbufTrimRightSpace(&name); + ffStrbufSubstrBefore(&path, path.length - 4); + + FFMouseDevice* device = (FFMouseDevice*) ffListAdd(devices); + ffStrbufInitMove(&device->name, &name); + ffStrbufInit(&device->serial); + + ffStrbufAppendS(&path, "uniq"); + if (ffAppendFileBuffer(path.chars, &device->serial)) + ffStrbufTrimRightSpace(&device->serial); + } + + ffStrbufSubstrBefore(&path, baseLen); + } + + return NULL; +} diff --git a/src/detection/mouse/mouse_nosupport.c b/src/detection/mouse/mouse_nosupport.c new file mode 100644 index 000000000..ba5a6c157 --- /dev/null +++ b/src/detection/mouse/mouse_nosupport.c @@ -0,0 +1,6 @@ +#include "mouse.h" + +const char* ffDetectMouse(FF_MAYBE_UNUSED FFlist* devices /* List of FFMouseDevice */) +{ + return "No mouse support on this platform"; +} diff --git a/src/detection/mouse/mouse_windows.c b/src/detection/mouse/mouse_windows.c new file mode 100644 index 000000000..08002e550 --- /dev/null +++ b/src/detection/mouse/mouse_windows.c @@ -0,0 +1,80 @@ +#define INITGUID + +#include "mouse.h" +#include "common/io/io.h" +#include "util/mallocHelper.h" +#include "util/windows/unicode.h" + +#include +#include +#include +#include +#include + +const char* ffDetectMouse(FFlist* devices /* List of FFMouseDevice */) +{ + UINT nDevices = 0; + if (GetRawInputDeviceList(NULL, &nDevices, sizeof(RAWINPUTDEVICELIST))) + return "GetRawInputDeviceList(NULL) failed"; + if (nDevices == 0) + return "No HID devices found"; + RAWINPUTDEVICELIST* FF_AUTO_FREE pRawInputDeviceList = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * nDevices); + if ((nDevices = GetRawInputDeviceList(pRawInputDeviceList, &nDevices, sizeof(RAWINPUTDEVICELIST))) == (UINT) -1) + return "GetRawInputDeviceList(pRawInputDeviceList) failed"; + + for (UINT i = 0; i < nDevices; ++i) + { + if (pRawInputDeviceList[i].dwType != RIM_TYPEMOUSE) continue; + + HANDLE hDevice = pRawInputDeviceList[i].hDevice; + + RID_DEVICE_INFO rdi; + UINT rdiSize = sizeof(rdi); + if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) == (UINT) -1) + continue; + + WCHAR devName[MAX_PATH]; + UINT nameSize = MAX_PATH; + if (GetRawInputDeviceInfoW(hDevice, RIDI_DEVICENAME, devName, &nameSize) == (UINT) -1) + continue; + + FFMouseDevice* device = (FFMouseDevice*) ffListAdd(devices); + ffStrbufInit(&device->serial); + ffStrbufInit(&device->name); + + wchar_t buffer[MAX_PATH]; + + HANDLE FF_AUTO_CLOSE_FD hHidFile = CreateFileW(devName, 0 /* must be 0 instead of GENERIC_READ */, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hHidFile != INVALID_HANDLE_VALUE) + { + if (HidD_GetProductString(hHidFile, buffer, (ULONG) sizeof(buffer))) + ffStrbufSetWS(&device->name, buffer); + + if (HidD_GetSerialNumberString(hHidFile, buffer, sizeof(buffer))) + ffStrbufSetWS(&device->serial, buffer); + } + + if (!device->name.length) + { + // https://stackoverflow.com/a/64321096/9976392 + DEVPROPTYPE propertyType; + ULONG propertySize = sizeof(buffer); + + if (CM_Get_Device_Interface_PropertyW(devName, &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE) buffer, &propertySize, 0) == CR_SUCCESS) + { + DEVINST devInst; + if (CM_Locate_DevNodeW(&devInst, buffer, CM_LOCATE_DEVNODE_NORMAL) == CR_SUCCESS) + { + propertySize = sizeof(buffer); + if (CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_NAME, &propertyType, (PBYTE) buffer, &propertySize, 0) == CR_SUCCESS) + ffStrbufSetWS(&device->name, buffer); + } + } + } + + if (!device->name.length) + ffStrbufSetF(&device->name, "Unknown device %04X-%04X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId); + } + + return NULL; +} diff --git a/src/detection/netio/netio.c b/src/detection/netio/netio.c index f72ecb452..bcb64bca0 100644 --- a/src/detection/netio/netio.c +++ b/src/detection/netio/netio.c @@ -41,9 +41,9 @@ const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options) return "No network interfaces found"; uint64_t time2 = ffTimeGetNow(); - while (time2 - time1 < 1000) + while (time2 - time1 < options->waitTime) { - ffTimeSleep((uint32_t) (1000 - (time2 - time1))); + ffTimeSleep((uint32_t) (options->waitTime - (time2 - time1))); time2 = ffTimeGetNow(); } diff --git a/src/detection/netio/netio_nosupport.c b/src/detection/netio/netio_nosupport.c index 254f22860..be9a30b6c 100644 --- a/src/detection/netio/netio_nosupport.c +++ b/src/detection/netio/netio_nosupport.c @@ -1,6 +1,6 @@ #include "netio.h" -const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) +const char* ffNetIOGetIoCounters(FF_MAYBE_UNUSED FFlist* result, FF_MAYBE_UNUSED FFNetIOOptions* options) { return "Not supported on this platform"; } diff --git a/src/detection/netio/netio_windows.c b/src/detection/netio/netio_windows.c index 4291df3d4..1d3ab8fbe 100644 --- a/src/detection/netio/netio_windows.c +++ b/src/detection/netio/netio_windows.c @@ -47,7 +47,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) continue; char name[128]; - WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, sizeof(name), NULL, NULL); + WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, ARRAY_SIZE(name), NULL, NULL); if (options->namePrefix.length && strncmp(name, options->namePrefix.chars, options->namePrefix.length) != 0) continue; diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index cb5176257..56f86215f 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -15,8 +15,10 @@ #define CL_TARGET_OPENCL_VERSION 110 #ifndef __APPLE__ #include + #include #else #include + #include #endif typedef struct OpenCLData @@ -31,8 +33,23 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) { cl_platform_id platforms[32]; cl_uint numPlatforms = 0; - if (data->ffclGetPlatformIDs(sizeof(platforms) / sizeof(platforms[0]), platforms, &numPlatforms) != CL_SUCCESS) - return "clGetPlatformIDs() failed"; + cl_int ret = data->ffclGetPlatformIDs(ARRAY_SIZE(platforms), platforms, &numPlatforms); + if (ret != CL_SUCCESS) + { + switch (ret) + { + #ifdef CL_PLATFORM_NOT_FOUND_KHR // not available on macOS + case CL_PLATFORM_NOT_FOUND_KHR: + return "clGetPlatformIDs() failed: CL_PLATFORM_NOT_FOUND_KHR"; + #endif + case CL_INVALID_VALUE: + return "clGetPlatformIDs() failed: CL_INVALID_VALUE"; + case CL_OUT_OF_HOST_MEMORY: + return "clGetPlatformIDs() failed: CL_OUT_OF_HOST_MEMORY"; + default: + return "clGetPlatformIDs() failed: unknown error"; + } + } if (numPlatforms == 0) return "clGetPlatformIDs returned 0 platforms"; @@ -60,7 +77,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) } cl_device_id deviceIDs[32]; - cl_uint numDevices = (cl_uint) (sizeof(deviceIDs) / sizeof(deviceIDs[0])); + cl_uint numDevices = (cl_uint) ARRAY_SIZE(deviceIDs); if (data->ffclGetDeviceIDs(platforms[iplat], CL_DEVICE_TYPE_GPU, numDevices, deviceIDs, &numDevices) != CL_SUCCESS) continue; diff --git a/src/detection/opengl/opengl_windows.c b/src/detection/opengl/opengl_windows.c index 529e841ac..cc251c188 100644 --- a/src/detection/opengl/opengl_windows.c +++ b/src/detection/opengl/opengl_windows.c @@ -31,7 +31,7 @@ static const char* wglHandlePixelFormat(WGLData* wglData, HWND hWnd) { PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), + sizeof(pfd), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 862d95819..c7ede9b16 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -179,7 +179,7 @@ static bool detectDebianDerived(FFOSResult* result) ffStrbufSetS(&result->idLike, "debian"); return true; } - else if (ffPathExists("/usr/bin/pveversion", FF_PATHTYPE_FILE)) + else if (access("/usr/bin/pveversion", X_OK) == 0) { ffStrbufSetS(&result->id, "pve"); ffStrbufSetS(&result->idLike, "debian"); diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.c similarity index 65% rename from src/detection/os/os_windows.cpp rename to src/detection/os/os_windows.c index ef93ff40c..dda2004c5 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.c @@ -1,51 +1,18 @@ -extern "C" { #include "os.h" #include "common/library.h" -} -#include "util/windows/unicode.hpp" -#include "util/windows/wmi.hpp" +#include "util/windows/unicode.h" #include "util/stringUtils.h" -static const char* getOsNameByWmi(FFstrbuf* osName) -{ - FFWmiQuery query(L"SELECT Caption FROM Win32_OperatingSystem"); - if(!query) - return "Query WMI service failed"; - - if(FFWmiRecord record = query.next()) - { - if(auto vtCaption = record.get(L"Caption")) - { - ffStrbufSetWSV(osName, vtCaption.get()); - ffStrbufTrimRight(osName, ' '); - return NULL; - } - return "Get Caption failed"; - } - - return "No WMI result returned"; -} +#include PWSTR WINAPI BrandingFormatString(PCWSTR format); -static const char* getOsNameByWinbrand(FFstrbuf* osName) +void ffDetectOSImpl(FFOSResult* os) { //https://dennisbabkin.com/blog/?t=how-to-tell-the-real-version-of-windows-your-app-is-running-on#ver_string - FF_LIBRARY_LOAD(winbrand, "dlopen winbrand" FF_LIBRARY_EXTENSION " failed", "winbrand" FF_LIBRARY_EXTENSION, 1); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(winbrand, BrandingFormatString); - - const wchar_t* rawName = ffBrandingFormatString(L"%WINDOWS_LONG%"); - ffStrbufSetWS(osName, rawName); + const wchar_t* rawName = BrandingFormatString(L"%WINDOWS_LONG%"); + ffStrbufSetWS(&os->variant, rawName); GlobalFree((HGLOBAL)rawName); - return NULL; -} - -extern "C" -void ffDetectOSImpl(FFOSResult* os) -{ - if(getOsNameByWinbrand(&os->variant) && getOsNameByWmi(&os->variant)) - return; - ffStrbufTrimRight(&os->variant, ' '); //WMI returns the "Microsoft" prefix while BrandingFormatString doesn't. Make them consistent. diff --git a/src/detection/packages/packages_apple.c b/src/detection/packages/packages_apple.c index 385926626..e708eee25 100644 --- a/src/detection/packages/packages_apple.c +++ b/src/detection/packages/packages_apple.c @@ -66,7 +66,7 @@ static uint32_t getMacPortsPackages() return countMacPortsPackages(FASTFETCH_TARGET_DIR_ROOT "/opt/local"); } -static uint32_t getNixPackagesImpl(char* path) +static uint32_t getNixPackagesImpl(const char* path) { //Nix detection is kinda slow, so we only do it if the dir exists if(!ffPathExists(path, FF_PATHTYPE_DIRECTORY)) @@ -87,7 +87,7 @@ static uint32_t getNixPackagesImpl(char* path) NULL }); - return (uint32_t) strtol(output.chars, NULL, 10); + return (uint32_t) strtoul(output.chars, NULL, 10); } static uint32_t getNixPackages(FFstrbuf* baseDir, const char* dirname) diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 187b0bdf2..a978929c4 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -610,7 +610,7 @@ static void getPackageCountsBedrock(FFstrbuf* baseDir, FFPackagesResult* package { if(entry->d_type != DT_DIR) continue; - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) + if(entry->d_name[0] == '.') continue; ffStrbufAppendS(baseDir, entry->d_name); diff --git a/src/detection/packages/packages_nosupport.c b/src/detection/packages/packages_nosupport.c index 87f65a8eb..a6d9a7b90 100644 --- a/src/detection/packages/packages_nosupport.c +++ b/src/detection/packages/packages_nosupport.c @@ -1,5 +1,5 @@ #include "packages.h" -void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) +void ffDetectPackagesImpl(FF_MAYBE_UNUSED FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options) { } diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index 3d613f89c..afa2b12e9 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -58,8 +58,8 @@ static void detectChoco(FF_MAYBE_UNUSED FFPackagesResult* result) return; char chocoPath[MAX_PATH + 3]; - strcpy(chocoPath, chocoInstall); - strncat(chocoPath, "/lib/*", sizeof(chocoPath) - 1 - strlen(chocoPath)); + char* pend = ffStrCopyN(chocoPath, chocoInstall, ARRAY_SIZE(chocoPath)); + ffStrCopyN(pend, "/lib/*", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath)); result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco"); } @@ -71,8 +71,8 @@ static void detectPacman(FFPackagesResult* result) // MSYS2 char pacmanPath[MAX_PATH + 3]; - strcpy(pacmanPath, msystemPrefix); - strncat(pacmanPath, "/../var/lib/pacman/local/*", sizeof(pacmanPath) - 1 - strlen(pacmanPath)); + char* pend = ffStrCopyN(pacmanPath, msystemPrefix, ARRAY_SIZE(pacmanPath)); + ffStrCopyN(pend, "/../var/lib/pacman/local/*", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath)); result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL); } diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 1b12d70fb..6a41ada24 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -5,110 +5,87 @@ #include #include +#include +#include -static double detectNvmeTemp(const char* devName) +static double detectNvmeTemp(int devfd) { - char pathSysBlock[PATH_MAX]; - int index = snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/hwmon$/temp1_input", devName); - if (index <= 0) return FF_PHYSICALDISK_TEMP_UNSET; - index -= (int) sizeof("/temp1_input"); + char pathHwmon[] = "hwmon$/temp1_input"; for (char c = '0'; c <= '9'; c++) // hopefully there's only one digit { - pathSysBlock[index] = c; + pathHwmon[strlen("hwmon")] = c; char buffer[64]; - ssize_t size = ffReadFileData(pathSysBlock, sizeof(buffer), buffer); + ssize_t size = ffReadFileDataRelative(devfd, pathHwmon, ARRAY_SIZE(buffer), buffer); if (size > 0) { buffer[size] = '\0'; double temp = strtod(buffer, NULL); - return temp > 0 ? temp / 1000 : FF_PHYSICALDISK_TEMP_UNSET; + return temp > 0 && temp < 10000000 /*VMware*/ ? temp / 1000 : FF_PHYSICALDISK_TEMP_UNSET; } } return FF_PHYSICALDISK_TEMP_UNSET; } -const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOptions* options, FFlist* result) { - FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); - if(sysBlockDirp == NULL) - return "opendir(\"/sys/block/\") == NULL"; + int devfd = openat(dfd, "device", O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (devfd < 0) return; // virtual device - struct dirent* sysBlockEntry; - while ((sysBlockEntry = readdir(sysBlockDirp)) != NULL) - { - const char* const devName = sysBlockEntry->d_name; - - if (devName[0] == '.') - continue; + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); - char pathSysBlock[PATH_MAX]; - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s", devName); - - char pathSysDeviceReal[PATH_MAX]; - ssize_t pathLength = readlink(pathSysBlock, pathSysDeviceReal, sizeof(pathSysDeviceReal) - 1); - if (pathLength < 0) - continue; - pathSysDeviceReal[pathLength] = '\0'; - - if (strstr(pathSysDeviceReal, "/virtual/")) // virtual device - continue; + { + if (ffAppendFileBufferRelative(devfd, "vendor", &name)) + { + ffStrbufTrimRightSpace(&name); + if (name.length > 0) + ffStrbufAppendC(&name, ' '); + } - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device", devName); - if (!ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY)) - continue; + ffAppendFileBufferRelative(devfd, "model", &name); + ffStrbufTrimRightSpace(&name); - FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); - device->type = FF_PHYSICALDISK_TYPE_NONE; - ffStrbufInit(&device->name); + if (name.length == 0) + ffStrbufSetS(&name, devName); + if (ffStrStartsWith(devName, "nvme")) { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName); - if (ffAppendFileBuffer(pathSysBlock, &device->name)) + int devid, nsid; + if (sscanf(devName, "nvme%dn%d", &devid, &nsid) == 2) { - ffStrbufTrimRightSpace(&device->name); - if (device->name.length > 0) - ffStrbufAppendC(&device->name, ' '); - } - - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName); - ffAppendFileBuffer(pathSysBlock, &device->name); - ffStrbufTrimRightSpace(&device->name); - - if (device->name.length == 0) - ffStrbufSetS(&device->name, devName); - else if (ffStrStartsWith(devName, "nvme")) - { - int devid, nsid; - if (sscanf(devName, "nvme%dn%d", &devid, &nsid) == 2) + bool multiNs = nsid > 1; + if (!multiNs) { - bool multiNs = nsid > 1; - if (!multiNs) - { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/nvme%dn2", devName, devid); - multiNs = ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY); - } - if (multiNs) - { - // In Asahi Linux, there are multiple namespaces for the same NVMe drive. - ffStrbufAppendF(&device->name, " - %d", nsid); - } + char pathSysBlock[32]; + snprintf(pathSysBlock, ARRAY_SIZE(pathSysBlock), "/dev/nvme%dn2", devid); + multiNs = access(pathSysBlock, F_OK) == 0; + } + if (multiNs) + { + // In Asahi Linux, there are multiple namespaces for the same NVMe drive. + ffStrbufAppendF(&name, " - %d", nsid); } - } - - if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) - { - ffStrbufDestroy(&device->name); - result->length--; - continue; } } - ffStrbufInitF(&device->devPath, "/dev/%s", devName); + if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix)) + return; + } + + FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); + device->type = FF_PHYSICALDISK_TYPE_NONE; + ffStrbufInitMove(&device->name, &name); + ffStrbufInitF(&device->devPath, "/dev/%s", devName); + { + ffStrbufInit(&device->interconnect); + char pathSysDeviceReal[PATH_MAX]; + ssize_t pathLength = readlinkat(dfd, "device", pathSysDeviceReal, ARRAY_SIZE(pathSysDeviceReal) - 1); + if (pathLength > 0) { - ffStrbufInit(&device->interconnect); + pathSysDeviceReal[pathLength] = '\0'; + if (strstr(pathSysDeviceReal, "/usb") != NULL) ffStrbufSetS(&device->interconnect, "USB"); else if (strstr(pathSysDeviceReal, "/nvme") != NULL) @@ -119,70 +96,84 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) ffStrbufSetS(&device->interconnect, "SCSI"); else { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/transport", devName); - if (ffAppendFileBuffer(pathSysBlock, &device->interconnect)) + if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect)) ffStrbufTrimRightSpace(&device->interconnect); } } + } - { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/queue/rotational", devName); - char isRotationalChar = '1'; - if (ffReadFileData(pathSysBlock, 1, &isRotationalChar) > 0) - device->type |= isRotationalChar == '1' ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; - } + { + char isRotationalChar = '1'; + if (ffReadFileDataRelative(dfd, "queue/rotational", 1, &isRotationalChar) > 0) + device->type |= isRotationalChar == '1' ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; + } + { + char blkSize[32]; + ssize_t fileSize = ffReadFileDataRelative(dfd, "size", ARRAY_SIZE(blkSize) - 1, blkSize); + if (fileSize > 0) { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/size", devName); - char blkSize[32]; - ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(blkSize) - 1, blkSize); - if (fileSize > 0) - { - blkSize[fileSize] = 0; - device->size = (uint64_t) strtoul(blkSize, NULL, 10) * 512; - } - else - device->size = 0; + blkSize[fileSize] = 0; + device->size = (uint64_t) strtoul(blkSize, NULL, 10) * 512; } + else + device->size = 0; + } - { - char removableChar = '0'; - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/removable", devName); - if (ffReadFileData(pathSysBlock, 1, &removableChar) > 0) - device->type |= removableChar == '1' ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; - } + { + char removableChar = '0'; + if (ffReadFileDataRelative(dfd, "removable", 1, &removableChar) > 0) + device->type |= removableChar == '1' ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; + } - { - char roChar = '0'; - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/ro", devName); - if (ffReadFileData(pathSysBlock, 1, &roChar) > 0) - device->type |= roChar == '1' ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE; - } + { + char roChar = '0'; + if (ffReadFileDataRelative(dfd, "ro", 1, &roChar) > 0) + device->type |= roChar == '1' ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE; + } - { - ffStrbufInit(&device->serial); - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/serial", devName); - if (ffReadFileBuffer(pathSysBlock, &device->serial)) - ffStrbufTrimRightSpace(&device->serial); - } + { + ffStrbufInit(&device->serial); + if (ffReadFileBufferRelative(devfd, "serial", &device->serial)) + ffStrbufTrimRightSpace(&device->serial); + } + { + ffStrbufInit(&device->revision); + if (ffReadFileBufferRelative(devfd, "firmware_rev", &device->revision)) + ffStrbufTrimRightSpace(&device->revision); + else { - ffStrbufInit(&device->revision); - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/firmware_rev", devName); - if (ffReadFileBuffer(pathSysBlock, &device->revision)) + if (ffReadFileBufferRelative(devfd, "rev", &device->revision)) ffStrbufTrimRightSpace(&device->revision); - else - { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/rev", devName); - if (ffReadFileBuffer(pathSysBlock, &device->revision)) - ffStrbufTrimRightSpace(&device->revision); - } } + } - if (options->temp) - device->temperature = detectNvmeTemp(devName); - else - device->temperature = FF_PHYSICALDISK_TEMP_UNSET; + if (options->temp) + device->temperature = detectNvmeTemp(devfd); + else + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; +} + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +{ + FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); + if(sysBlockDirp == NULL) + return "opendir(\"/sys/block/\") == NULL"; + + struct dirent* sysBlockEntry; + while ((sysBlockEntry = readdir(sysBlockDirp)) != NULL) + { + const char* const devName = sysBlockEntry->d_name; + + if (devName[0] == '.') + continue; + + char pathSysBlock[ARRAY_SIZE("/sys/block/") + ARRAY_SIZE(sysBlockEntry->d_name)]; + snprintf(pathSysBlock, ARRAY_SIZE(pathSysBlock), "/sys/block/%s", devName); + + int dfd = openat(dirfd(sysBlockDirp), devName, O_RDONLY | O_CLOEXEC | O_PATH | O_DIRECTORY); + if (dfd > 0) parsePhysicalDisk(dfd, devName, options, result); } return NULL; diff --git a/src/detection/poweradapter/poweradapter_linux.c b/src/detection/poweradapter/poweradapter_linux.c index 5c5a3f997..2dd03e73c 100644 --- a/src/detection/poweradapter/poweradapter_linux.c +++ b/src/detection/poweradapter/poweradapter_linux.c @@ -3,46 +3,37 @@ #include "util/stringUtils.h" #include +#include +#include -static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFlist* results) +static void parsePowerAdapter(int dfd, FF_MAYBE_UNUSED const char* id, FFlist* results) { - uint32_t dirLength = dir->length; - FF_STRBUF_AUTO_DESTROY tmpBuffer = ffStrbufCreate(); //type must exist and be "Mains" - ffStrbufAppendS(dir, "/type"); - if (ffReadFileBuffer(dir->chars, &tmpBuffer)) + if (ffReadFileBufferRelative(dfd, "type", &tmpBuffer)) ffStrbufTrimRightSpace(&tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); if(!ffStrbufIgnCaseEqualS(&tmpBuffer, "Mains")) return; //scope may not exist or must not be "Device" (?) - ffStrbufAppendS(dir, "/scope"); - if (ffReadFileBuffer(dir->chars, &tmpBuffer)) + if (ffReadFileBufferRelative(dfd, "scope", &tmpBuffer)) ffStrbufTrimRightSpace(&tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); if(ffStrbufIgnCaseEqualS(&tmpBuffer, "Device")) return; - ffStrbufAppendS(dir, "/online"); - char online = '1'; - ffReadFileData(dir->chars, sizeof(online), &online); - ffStrbufSubstrBefore(dir, dirLength); + char online = '\0'; + ffReadFileDataRelative(dfd, "online", sizeof(online), &online); - if (online == '0') + if (online != '1') return; //input_power_limit must exist and be not empty - ffStrbufAppendS(dir, "/input_power_limit"); - bool available = ffReadFileBuffer(dir->chars, &tmpBuffer); - ffStrbufSubstrBefore(dir, dirLength); - - if (!available) + if (!ffReadFileBufferRelative(dfd, "input_power_limit", &tmpBuffer)) return; + FFPowerAdapterResult* result = ffListAdd(results); ffStrbufInit(&result->name); ffStrbufInit(&result->description); @@ -51,44 +42,32 @@ static void parsePowerAdapter(FFstrbuf* dir, FF_MAYBE_UNUSED const char* id, FFl ffStrbufInit(&result->modelName); ffStrbufInit(&result->serial); - ffStrbufAppendS(dir, "/manufacturer"); - if (ffReadFileBuffer(dir->chars, &result->manufacturer)) + if (ffReadFileBufferRelative(dfd, "manufacturer", &result->manufacturer)) ffStrbufTrimRightSpace(&result->manufacturer); else if (ffStrEquals(id, "macsmc-ac")) // asahi ffStrbufSetStatic(&result->manufacturer, "Apple Inc."); - ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "/model_name"); - if (ffReadFileBuffer(dir->chars, &result->modelName)) + if (ffReadFileBufferRelative(dfd, "model_name", &result->modelName)) ffStrbufTrimRightSpace(&result->modelName); - ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "/serial_number"); - if (ffReadFileBuffer(dir->chars, &result->serial)) + if (ffReadFileBufferRelative(dfd, "serial_number", &result->serial)) ffStrbufTrimRightSpace(&result->serial); - ffStrbufSubstrBefore(dir, dirLength); } const char* ffDetectPowerAdapter(FFlist* results) { - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); - ffStrbufAppendS(&baseDir, "/sys/class/power_supply/"); - - uint32_t baseDirLength = baseDir.length; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/power_supply/"); if(dirp == NULL) return "opendir(\"/sys/class/power_supply/\") == NULL"; struct dirent* entry; while((entry = readdir(dirp)) != NULL) { - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) + if(entry->d_name[0] == '.') continue; - ffStrbufAppendS(&baseDir, entry->d_name); - parsePowerAdapter(&baseDir, entry->d_name, results); - ffStrbufSubstrBefore(&baseDir, baseDirLength); + FF_AUTO_CLOSE_FD int dfd = openat(dirfd(dirp), entry->d_name, O_RDONLY | O_CLOEXEC); + if (dfd > 0) parsePowerAdapter(dfd, entry->d_name, results); } return NULL; diff --git a/src/detection/processes/processes_bsd.c b/src/detection/processes/processes_bsd.c index 0cd169cfa..47d8d5166 100644 --- a/src/detection/processes/processes_bsd.c +++ b/src/detection/processes/processes_bsd.c @@ -15,7 +15,7 @@ const char* ffDetectProcesses(uint32_t* result) int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_PROC}; size_t length; - if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0) + if(sysctl(request, ARRAY_SIZE(request), NULL, &length, NULL, 0) != 0) return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed"; *result = (uint32_t)(length / sizeof(struct kinfo_proc)); diff --git a/src/detection/swap/swap_bsd.c b/src/detection/swap/swap_bsd.c index 7cbb2a1fe..c50885bc9 100644 --- a/src/detection/swap/swap_bsd.c +++ b/src/detection/swap/swap_bsd.c @@ -6,7 +6,7 @@ const char* ffDetectSwap(FFSwapResult* swap) { int mib[16]; - size_t mibsize = sizeof(mib) / sizeof(*mib); + size_t mibsize = ARRAY_SIZE(mib); if (sysctlnametomib("vm.swap_info", mib, &mibsize) < 0) return "sysctlnametomib(\"vm.swap_info\") failed"; diff --git a/src/detection/swap/swap_linux.c b/src/detection/swap/swap_linux.c index 77d95d589..15f8fd24d 100644 --- a/src/detection/swap/swap_linux.c +++ b/src/detection/swap/swap_linux.c @@ -9,9 +9,9 @@ const char* ffDetectSwap(FFSwapResult* swap) { // #620 char buf[PROC_FILE_BUFFSIZ]; - ssize_t nRead = ffReadFileData("/proc/meminfo", sizeof(buf) - 1, buf); + ssize_t nRead = ffReadFileData("/proc/meminfo", ARRAY_SIZE(buf) - 1, buf); if(nRead < 0) - return "ffReadFileData(\"/proc/meminfo\", sizeof(buf)-1, buf)"; + return "ffReadFileData(\"/proc/meminfo\", ARRAY_SIZE(buf)-1, buf)"; buf[nRead] = '\0'; uint64_t swapTotal = 0, swapFree = 0; @@ -19,7 +19,7 @@ const char* ffDetectSwap(FFSwapResult* swap) char *token = NULL; if ((token = strstr(buf, "SwapTotal:")) != NULL) swapTotal = strtoul(token + strlen("SwapTotal:"), NULL, 10); - + if ((token = strstr(buf, "SwapFree:")) != NULL) swapFree = strtoul(token + strlen("SwapFree:"), NULL, 10); diff --git a/src/detection/terminalfont/terminalfont_windows.c b/src/detection/terminalfont/terminalfont_windows.c index cf82da291..6e59cbdfb 100644 --- a/src/detection/terminalfont/terminalfont_windows.c +++ b/src/detection/terminalfont/terminalfont_windows.c @@ -4,6 +4,7 @@ #include "common/properties.h" #include "detection/terminalshell/terminalshell.h" #include "util/windows/unicode.h" +#include "util/stringUtils.h" #include "terminalfont.h" #include @@ -97,19 +98,18 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon if(terminalExe && terminalExe->length > 0 && !ffStrbufEqualS(terminalExe, "Windows Terminal")) { char jsonPath[MAX_PATH + 1]; - strncpy(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1); - char* pathEnd = jsonPath + strlen(jsonPath); - strncpy(pathEnd, ".portable", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); + char* pathEnd = ffStrCopyN(jsonPath, terminalExe->chars, ffStrbufLastIndexC(terminalExe, '\\') + 1); + ffStrCopyN(pathEnd, ".portable", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); if(ffPathExists(jsonPath, FF_PATHTYPE_ANY)) { - strncpy(pathEnd, "settings\\settings.json", sizeof(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); + ffStrCopyN(pathEnd, "settings\\settings.json", ARRAY_SIZE(jsonPath) - (size_t) (pathEnd - jsonPath) - 1); if(!ffAppendFileBuffer(jsonPath, &json)) error = "Error reading Windows Terminal portable settings JSON file"; } else if(SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, jsonPath))) { - size_t remaining = sizeof(jsonPath) - strlen(jsonPath) - 1; + size_t remaining = ARRAY_SIZE(jsonPath) - strlen(jsonPath) - 1; if(ffStrbufContainIgnCaseS(terminalExe, "_8wekyb3d8bbwe\\")) { // Microsoft Store version @@ -175,7 +175,7 @@ static void detectFromWindowsTerminal(const FFstrbuf* terminalExe, FFTerminalFon else { char sizeStr[16]; - snprintf(sizeStr, sizeof(sizeStr), "%g", size); + snprintf(sizeStr, ARRAY_SIZE(sizeStr), "%g", size); ffFontInitValues(&terminalFont->font, name.chars, sizeStr); } } @@ -226,7 +226,7 @@ static void detectConEmu(FFTerminalFontResult* terminalFont) FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); const char* paths[] = { "ConEmuDir", "ConEmuBaseDir", "APPDATA" }; - for (uint32_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) + for (uint32_t i = 0; i < ARRAY_SIZE(paths); ++i) { ffStrbufSetS(&path, getenv(paths[i])); if(path.length > 0) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 45e4bb75f..a68e33517 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -521,7 +521,7 @@ static bool getTerminalVersionScreen(FFstrbuf* exe, FFstrbuf* version) { if(!getExeVersionRaw(exe, version)) return false; // Screen version 4.09.01 (GNU) 20-Aug-23 - ffStrbufSubstrAfter(version, strlen("Screen version ") - 1); + ffStrbufSubstrAfter(version, (uint32_t) strlen("Screen version ") - 1); ffStrbufSubstrBeforeFirstC(version, ' '); return version->length > 0; } @@ -579,16 +579,16 @@ static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) char buffer[1024] = {}; if ( #ifdef __linux__ - ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib64/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer) || - ffReadFileData(FASTFETCH_TARGET_DIR_USR "/lib/kitty/kitty/constants.py", sizeof(buffer) - 1, buffer) + 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", sizeof(buffer) - 1, buffer) + ffReadFileData(_PATH_LOCALBASE "/share/kitty/kitty/constants.py", ARRAY_SIZE(buffer) - 1, buffer) #endif ) { // Starts from version 0.17.0 // https://github.com/kovidgoyal/kitty/blob/master/kitty/constants.py#L25 - const char* p = memmem(buffer, sizeof(buffer) - 1, "version: Version = Version(", strlen("version: Version = Version(")); + const char* p = memmem(buffer, ARRAY_SIZE(buffer) - 1, "version: Version = Version(", strlen("version: Version = Version(")); if (p) { p += strlen("version: Version = Version("); diff --git a/src/detection/tpm/tpm_linux.c b/src/detection/tpm/tpm_linux.c index 2547339c6..90c7cf7c1 100644 --- a/src/detection/tpm/tpm_linux.c +++ b/src/detection/tpm/tpm_linux.c @@ -3,9 +3,9 @@ const char* ffDetectTPM(FFTPMResult* result) { - if (!ffPathExists("/sys/class/tpm/tpm0", FF_PATHTYPE_DIRECTORY)) + if (!ffPathExists("/sys/class/tpm/tpm0/", FF_PATHTYPE_DIRECTORY)) { - if (!ffPathExists("/sys/class/tpm", FF_PATHTYPE_DIRECTORY)) + if (!ffPathExists("/sys/class/tpm/", FF_PATHTYPE_DIRECTORY)) return "TPM is not supported by kernel"; return "TPM device is not found"; } diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c index 7a77eb3a7..4f381889c 100644 --- a/src/detection/tpm/tpm_windows.c +++ b/src/detection/tpm/tpm_windows.c @@ -1,37 +1,8 @@ #include "tpm.h" #include "common/library.h" -// #include - -typedef UINT32 TBS_RESULT; -#define TBS_SUCCESS 0u -#define TBS_E_TPM_NOT_FOUND ((TBS_RESULT) 0x8028400Fu) - -#define TPM_VERSION_UNKNOWN 0 -#define TPM_VERSION_12 1 -#define TPM_VERSION_20 2 - -#define TPM_IFTYPE_UNKNOWN 0 -#define TPM_IFTYPE_1 1 // for 1.2 - use I/O-port or MMIO -#define TPM_IFTYPE_TRUSTZONE 2 // 2.0: Trustzone -#define TPM_IFTYPE_HW 3 // 2.0: HW TPM -#define TPM_IFTYPE_EMULATOR 4 // 2.0: SW-emulator -#define TPM_IFTYPE_SPB 5 // 2.0: SPB attached - -typedef struct _TPM_DEVICE_INFO -{ - UINT32 structVersion; // = 1 for now - UINT32 tpmVersion; // 1.2 / 2.0 - UINT32 tpmInterfaceType; // HW, simulator, ... - UINT32 tpmImpRevision; // code-drop revision, - // implenmentation-specific -} TPM_DEVICE_INFO, *PTPM_DEVICE_INFO; -typedef const TPM_DEVICE_INFO *PCTPM_DEVICE_INFO; - -TBS_RESULT WINAPI -Tbsi_GetDeviceInfo( - _In_ UINT32 Size, - _Out_writes_bytes_(Size) PVOID Info); +#include +#include const char* ffDetectTPM(FFTPMResult* result) { @@ -41,7 +12,7 @@ const char* ffDetectTPM(FFTPMResult* result) TPM_DEVICE_INFO deviceInfo = {}; TBS_RESULT code = ffTbsi_GetDeviceInfo(sizeof(deviceInfo), &deviceInfo); if (code != TBS_SUCCESS) - return code == TBS_E_TPM_NOT_FOUND ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; + return code == (TBS_RESULT) TBS_E_TPM_NOT_FOUND ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; switch (deviceInfo.tpmVersion) { diff --git a/src/detection/uptime/uptime_linux.c b/src/detection/uptime/uptime_linux.c index 0e4532492..44705a5fc 100644 --- a/src/detection/uptime/uptime_linux.c +++ b/src/detection/uptime/uptime_linux.c @@ -7,10 +7,10 @@ const char* ffDetectUptime(FFUptimeResult* result) { #ifndef __ANDROID__ // cat: /proc/uptime: Permission denied - + // #620 char buf[64]; - ssize_t nRead = ffReadFileData("/proc/uptime", sizeof(buf) - 1, buf); + ssize_t nRead = ffReadFileData("/proc/uptime", ARRAY_SIZE(buf) - 1, buf); if(nRead > 0) { buf[nRead] = '\0'; diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index eb4c05ac8..caa6e68d3 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -123,7 +123,7 @@ static const char* detectVulkan(FFVulkanResult* result) instanceVersion.major = 1; VkPhysicalDevice physicalDevices[128]; - uint32_t physicalDeviceCount = (uint32_t) (sizeof(physicalDevices) / sizeof(*physicalDevices)); + uint32_t physicalDeviceCount = (uint32_t) ARRAY_SIZE(physicalDevices); res = ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices); if(res != VK_SUCCESS) { diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index b2e6e464f..732c5afc8 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -190,7 +190,7 @@ static const char* detectWifiWithIoctls(FFWifiResult* item) return "socket() failed"; struct iwreq iwr; - strncpy(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ); + ffStrCopyN(iwr.ifr_name, item->inf.description.chars, IFNAMSIZ); ffStrbufEnsureFree(&item->conn.ssid, IW_ESSID_MAX_SIZE); iwr.u.essid.pointer = (caddr_t) item->conn.ssid.chars; iwr.u.essid.length = IW_ESSID_MAX_SIZE + 1; @@ -274,7 +274,7 @@ const char* ffDetectWifi(FF_MAYBE_UNUSED FFlist* result) for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i) { - ffStrbufSetF(&buffer, "/sys/class/net/%s/phy80211", i->if_name); + ffStrbufSetF(&buffer, "/sys/class/net/%s/phy80211/", i->if_name); if(!ffPathExists(buffer.chars, FF_PATHTYPE_DIRECTORY)) continue; diff --git a/src/detection/wm/wm_apple.c b/src/detection/wm/wm_apple.c index 30f8e91e4..29b5497f8 100644 --- a/src/detection/wm/wm_apple.c +++ b/src/detection/wm/wm_apple.c @@ -9,7 +9,7 @@ const char* ffDetectWMPlugin(FFstrbuf* pluginName) { int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; - u_int requestLength = sizeof(request) / sizeof(*request); + u_int requestLength = ARRAY_SIZE(request); size_t length = 0; FF_AUTO_FREE struct kinfo_proc* processes = ffSysctlGetData(request, requestLength, &length); diff --git a/src/detection/wmtheme/wmtheme.h b/src/detection/wmtheme/wmtheme.h index baf3e1ede..a737a7aea 100644 --- a/src/detection/wmtheme/wmtheme.h +++ b/src/detection/wmtheme/wmtheme.h @@ -1,10 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_detection_wmtheme -#define FASTFETCH_INCLUDED_detection_wmtheme - #include "fastfetch.h" bool ffDetectWmTheme(FFstrbuf* themeOrError); - -#endif diff --git a/src/detection/zpool/zpool.h b/src/detection/zpool/zpool.h index 8cd53da36..aa8bee03e 100644 --- a/src/detection/zpool/zpool.h +++ b/src/detection/zpool/zpool.h @@ -9,7 +9,7 @@ typedef struct FFZpoolResult uint64_t used; uint64_t total; uint64_t version; - uint64_t fragmentation; + double fragmentation; } FFZpoolResult; const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */); diff --git a/src/detection/zpool/zpool_linux.c b/src/detection/zpool/zpool_linux.c index 59890990b..6c28def6d 100644 --- a/src/detection/zpool/zpool_linux.c +++ b/src/detection/zpool/zpool_linux.c @@ -73,7 +73,8 @@ static int enumZpoolCallback(zpool_handle_t* zpool, void* param) item->version = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_VERSION, &source); item->total = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_SIZE, &source); item->used = item->total - data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FREE, &source); - item->fragmentation = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FRAGMENTATION, &source); + uint64_t fragmentation = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FRAGMENTATION, &source); + item->fragmentation = fragmentation == UINT64_MAX ? 0.0/0.0 : (double) fragmentation; return 0; } diff --git a/src/fastfetch.c b/src/fastfetch.c index 23a00611d..8be2ab211 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -266,10 +266,13 @@ static void listAvailablePresets(bool pretty) ffListFilesRecursively(path->chars, pretty); } - FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateCopy(&instance.state.platform.exePath); - ffStrbufSubstrBeforeLastC(&absolutePath, '/'); - ffStrbufAppendS(&absolutePath, "/presets/"); - ffListFilesRecursively(absolutePath.chars, pretty); + if (instance.state.platform.exePath.length) + { + FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateCopy(&instance.state.platform.exePath); + ffStrbufSubstrBeforeLastC(&absolutePath, '/'); + ffStrbufAppendS(&absolutePath, "/presets/"); + ffListFilesRecursively(absolutePath.chars, pretty); + } } static void listAvailableLogos(void) diff --git a/src/fastfetch.h b/src/fastfetch.h index dfc736434..ae9d0657f 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED -#define FASTFETCH_INCLUDED - #include "fastfetch_config.h" #include @@ -28,6 +25,16 @@ #include "options/display.h" #include "options/general.h" +#ifdef __has_builtin + #if __has_builtin(__builtin_types_compatible_p) + #define ARRAY_SIZE(x) ({ static_assert(!__builtin_types_compatible_p(__typeof__(x), __typeof__(&*(x))), "Must not be a pointer"); sizeof(x) / sizeof(*(x)); }) + #endif +#endif +#ifndef ARRAY_SIZE + #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) +#endif + + typedef struct FFconfig { FFOptionsLogo logo; @@ -80,5 +87,3 @@ void ffLogoPrintLine(); void ffLogoBuiltinPrint(); void ffLogoBuiltinList(); void ffLogoBuiltinListAutocompletion(); - -#endif diff --git a/src/fastfetch_config.h.in b/src/fastfetch_config.h.in index 6d86f3e0b..03b8f57a0 100644 --- a/src/fastfetch_config.h.in +++ b/src/fastfetch_config.h.in @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INDLUDED_fastfetch_config_h_in -#define FASTFETCH_INDLUDED_fastfetch_config_h_in - #define FASTFETCH_PROJECT_NAME "@PROJECT_NAME@" #define FASTFETCH_PROJECT_VERSION "@PROJECT_VERSION@" #define FASTFETCH_PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ @@ -22,5 +19,3 @@ #define FASTFETCH_TARGET_DIR_ETC "@TARGET_DIR_ETC@" #define FASTFETCH_TARGET_DIR_INSTALL_SYSCONF "@CMAKE_INSTALL_SYSCONFDIR@" - -#endif // FASTFETCH_INDLUDED_fastfetch_config_h_in diff --git a/src/fastfetch_datatext.h.in b/src/fastfetch_datatext.h.in index 647c7c7b0..894f34488 100644 --- a/src/fastfetch_datatext.h.in +++ b/src/fastfetch_datatext.h.in @@ -1,13 +1,8 @@ #pragma once -#ifndef FASTFETCH_INDLUDED_fastfetch_datatext_h_in -#define FASTFETCH_INDLUDED_fastfetch_datatext_h_in - #define FASTFETCH_DATATEXT_JSON_HELP @DATATEXT_JSON_HELP@ #define FASTFETCH_DATATEXT_STRUCTURE @DATATEXT_STRUCTURE@ #define FASTFETCH_DATATEXT_HELP_FOOTER @DATATEXT_HELP_FOOTER@ #define FASTFETCH_DATATEXT_HELP_COLOR @DATATEXT_HELP_COLOR@ #define FASTFETCH_DATATEXT_HELP_FORMAT @DATATEXT_HELP_FORMAT@ #define FASTFETCH_DATATEXT_HELP_CONFIG @DATATEXT_HELP_CONFIG@ - -#endif diff --git a/src/flashfetch.c b/src/flashfetch.c index 2ec8f21bb..6aeb31bfe 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -49,7 +49,7 @@ int main(void) &options->colors, }; - for (size_t i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) + for (size_t i = 0; i < ARRAY_SIZE(modules); i++) ((const FFModuleBaseInfo*) modules[i])->printModule(modules[i]); ffFinish(); diff --git a/src/logo/ascii/eweos.txt b/src/logo/ascii/eweos.txt new file mode 100644 index 000000000..0723acbc3 --- /dev/null +++ b/src/logo/ascii/eweos.txt @@ -0,0 +1,15 @@ +${c2} #####%%% +${c2} ##%%${c3}////${c2}%%%%%${c3}/// +${c2} #%%%%${c3}////((((////${c2}% +${c1} *@@@@@@@${c3}/${c5},,,${c3}/////${c5},,,${c2}%${c1}@@@@@@@ + .@@@@@@@@@@@${c3}////////${c2}%%%${c1}@@@@@@@@@@@@ +@@@${c4}...${c1}@@@@@@${c3}////${c2}%%${c3}////${c1}@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@@@@@@@@@@@@@@@@@@ + @@@@@@ @@@@@@ + @@@ @@@ diff --git a/src/logo/ascii/midos.txt b/src/logo/ascii/midos.txt new file mode 100644 index 000000000..479070828 --- /dev/null +++ b/src/logo/ascii/midos.txt @@ -0,0 +1,20 @@ + .:=+*#%%@@@@@@%%#*+=:. + .=*%@@@@@@@@@@@@@@@@@@@@@@%*=: + .=%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+. + :*@@@@@@@@@@@@@@@@@$2++$1%@@@@@@@@@@@@@@@@#- + .*@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@#. + -%@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@- + -@@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@@= +:@@@@@@@@@@@@@@@@@%%@@@%$2..$1#@@@@#@@@@@@@@@@@@@@@@@: +*@@@@@@@@@@@@#$2*=:..$1*@@@%$2..$1#@@@#$2..:=+$1#@@@@@@@@@@@@* +%@@@@@@@#+$2=:...-+$1#@@@@@%$2..$1#@@@@@#$2+=:..:-$1+#@@@@@@@% +%@@@@@$2:..:=+-..-+$1#@@@@@%$2..$1#@@@@@%$2+-..-+=:..:$1@@@@@@ +*@@@@@$2*%$1@@@@@@%$2+-..$1#@@@%$2..$1#@@@%$2..-+$1#@@@@@@$2%*$1@@@@@* +:@@@@@@@@@@@@@@@@@$2#%$1@@@%$2..$1#@@@$2%#$1@@@@@@@@@@@@@@@@@: + =@@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@@= + -@@@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@@@= + .*@@@@@@@@@@@@@@@@@@%$2..$1#@@@@@@@@@@@@@@@@@@#: + :*@@@@@@@@@@@@@@@@@$2==$1%@@@@@@@@@@@@@@@@#-. + .+%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%+: + :=*%@@@@@@@@@@@@@@@@@@@@@@%*=:. + .-=+*#%%@@@@@@%%#*+=-. \ No newline at end of file diff --git a/src/logo/ascii/xeroarch.txt b/src/logo/ascii/xeroarch.txt index 1f094ea06..890c2b278 100644 --- a/src/logo/ascii/xeroarch.txt +++ b/src/logo/ascii/xeroarch.txt @@ -1,19 +1,19 @@ -${c1} ████ -${c1} ███${c2}▓▓${c1}███ -${c1} ███${c2}▓▓▓▓${c1}███ -${c1} ███${c2}▓▓▓▓▓▓${c1}███ -${c1} ███${c2}▓▓▓▓▓▓▓▓${c1}███ -${c1} ███${c2}▓▓▓▓▓▓▓▓▓▓${c1}███ -${c1} ███${c2}▓▓▓▓▓▓▓▓▓▓▓▓${c1}███ -${c1} ███${c2}▓▓▓▓▓▓${c1}██${c2}▓▓▓▓▓▓${c1}▓██ -${c1} ███${c2}▓▓▓▓▓▓${c1}████${c2}▓▓▓▓▓▓${c1}▓██ -${c1} ██▓${c2}▓▓▓▓▓▓${c1}█▓${c3}▓▓${c1}▓█${c2}▓▓▓▓▓▓${c1}▓██ -${c1} █████▓▒▒▒██${c3}▓${c4}▒▒${c3}▓${c1}██▒▒▒▓█████ -${c1} ███${c6}▓▓▓▓▓${c1}████${c3}▓${c4}▒▒▒▒${c3}▓${c1}▓███${c6}▓▓▓▓▓${c1}███ -${c1} ███${c6}▓▓▓▓▓▓▓▓▓${c1}███▓▓███${c6}▓▓▓▓▓▓▓▓▓${c1}███ -${c1} ███${c6}▓▓▓▓▓▓▓${c2}▓▓${c6}▓▓▓▓▓${c1}█${c6}▓▓▓▓▓▓▓▓▓▓▓▓▓${c1}███ -${c1} ███${c6}▓▓▓▓▓▓${c2}▓▓${c5}▒▒${c6}${c2}▓▓${c6}▓▓▓${c1}▓${c6}▓▓▓▓${c4}()${c6}▓▓▓▓▓▓▓▓${c1}███ -${c1} ███${c6}▓▓▓▓▓${c2}▓▓${c5}▒▒▒▒▒▒${c6}${c2}▓▓${c6}▓${c1}▓${c6}▓▓${c3}()${c6}▓▓${c3}()${c6}▓▓▓▓▓▓▓${c1}███ -${c1}███${c6}▓▓▓▓▓▓▓▓${c2}▓▓${c5}▒▒${c6}${c2}▓▓${c6}▓▓▓${c1}▓${c6}▓▓▓▓${c4}()${c6}▓▓▓▓▓▓▓▓▓▓${c1}███ -${c1}██${c6}▓▓▓▓▓▓▓▓▓▓▓${c2}▓▓${c6}▓▓▓▓▓${c1}▓${c6}▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓${c1}██ -${c1}████████████████████████████████████████ \ No newline at end of file +${c5} ████ +${c5} ███${c2}▓▓${c5}███ +${c5} ███${c2}▓▓▓▓${c5}███ +${c5} ███${c2}▓▓▓▓▓▓${c5}███ +${c5} ███${c2}▓▓▓▓▓▓▓▓${c5}███ +${c5} ███${c2}▓▓▓▓▓▓▓▓▓▓${c5}███ +${c5} ███${c2}▓▓▓▓▓▓▓▓▓▓▓▓${c5}███ +${c5} ███${c2}▓▓▓▓▓▓${c5}██${c2}▓▓▓▓▓▓${c5}▓██ +${c5} ███${c2}▓▓▓▓▓▓${c5}████${c2}▓▓▓▓▓▓${c5}▓██ +${c5} ██▓${c2}▓▓▓▓▓▓${c5}█▓${c3}▓▓${c5}▓█${c2}▓▓▓▓▓▓${c5}▓██ +${c5} █████▓▒▒▒██${c3}▓${c4}▒▒${c3}▓${c5}██▒▒▒▓█████ +${c5} ███${c6}▓▓▓▓▓${c5}████${c3}▓${c4}▒▒▒▒${c3}▓${c5}▓███${c6}▓▓▓▓▓${c5}███ +${c5} ███${c6}▓▓▓▓▓▓▓▓▓${c5}███▓▓███${c6}▓▓▓▓▓▓▓▓▓${c5}███ +${c5} ███${c6}▓▓▓▓▓▓▓${c2}▓▓${c6}▓▓▓▓▓${c5}█${c6}▓▓▓▓▓▓▓▓▓▓▓▓▓${c5}███ +${c5} ███${c6}▓▓▓▓▓▓${c2}▓▓${c5}▒▒${c6}${c2}▓▓${c6}▓▓▓${c5}▓${c6}▓▓▓▓${c4}()${c6}▓▓▓▓▓▓▓▓${c5}███ +${c5} ███${c6}▓▓▓▓▓${c2}▓▓${c5}▒▒▒▒▒▒${c6}${c2}▓▓${c6}▓${c5}▓${c6}▓▓${c3}()${c6}▓▓${c3}()${c6}▓▓▓▓▓▓▓${c5}███ +${c5}███${c6}▓▓▓▓▓▓▓▓${c2}▓▓${c5}▒▒${c6}${c2}▓▓${c6}▓▓▓${c5}▓${c6}▓▓▓▓${c4}()${c6}▓▓▓▓▓▓▓▓▓▓${c5}███ +${c5}██${c6}▓▓▓▓▓▓▓▓▓▓▓${c2}▓▓${c6}▓▓▓▓▓${c5}▓${c6}▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓${c5}██ +${c5}████████████████████████████████████████ \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 014f93fa9..7ef6ce8fb 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1498,6 +1498,18 @@ static const FFlogo E[] = { FF_COLOR_FG_WHITE, }, }, + // eweOS + { + .names = {"eweOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_EWEOS, + .colors = { + FF_COLOR_FG_WHITE, + FF_COLOR_FG_LIGHT_YELLOW, + FF_COLOR_FG_LIGHT_RED, + FF_COLOR_FG_LIGHT_BLACK, + FF_COLOR_FG_RED, + }, + }, // Exherbo { .names = {"Exherbo", "exherbo-linux"}, @@ -2780,6 +2792,17 @@ static const FFlogo M[] = { .colorKeys = FF_COLOR_FG_BLUE, .colorTitle = FF_COLOR_FG_WHITE, }, + // MidOS + { + .names = {"MidOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_MIDOS, + .colors = { + FF_COLOR_FG_LIGHT_BLACK, + FF_COLOR_FG_WHITE, + }, + .colorKeys = FF_COLOR_FG_LIGHT_BLACK, + .colorTitle = FF_COLOR_FG_WHITE, + }, // Mint { .names = {"mint", "mint-linux"}, @@ -4801,11 +4824,11 @@ static const FFlogo X[] = { .names = {"XeroArch"}, .lines = FASTFETCH_DATATEXT_LOGO_XEROARCH, .colors = { - FF_COLOR_FG_256 "16", + FF_COLOR_FG_256 "50", FF_COLOR_FG_256 "14", FF_COLOR_FG_256 "50", FF_COLOR_FG_256 "93", - FF_COLOR_FG_256 "46", + FF_COLOR_FG_256 "16", FF_COLOR_FG_256 "15", } }, diff --git a/src/logo/logo.h b/src/logo/logo.h index bbdcdbe38..e9bea9788 100644 --- a/src/logo/logo.h +++ b/src/logo/logo.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_LOGO_logo -#define FASTFETCH_INCLUDED_LOGO_logo - #include "fastfetch.h" typedef enum FFLogoLineType @@ -31,5 +28,3 @@ extern const FFlogo ffLogoUnknown; //image/image.c bool ffLogoPrintImageIfExists(FFLogoType type, bool printError); - -#endif diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 743c098e2..f27ff29e7 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -7,7 +7,7 @@ #include "modules/battery/battery.h" #include "util/stringUtils.h" -#define FF_BATTERY_NUM_FORMAT_ARGS 10 +#define FF_BATTERY_NUM_FORMAT_ARGS 14 static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uint8_t index) { @@ -28,6 +28,17 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin })); } + + uint32_t timeRemaining = result->timeRemaining < 0 ? 0 : (uint32_t) result->timeRemaining; + + uint32_t seconds = timeRemaining % 60; + timeRemaining /= 60; + uint32_t minutes = timeRemaining % 60; + timeRemaining /= 60; + uint32_t hours = timeRemaining % 24; + timeRemaining /= 24; + uint32_t days = timeRemaining; + if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(key.chars, index, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); @@ -52,6 +63,15 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin ffPercentAppendNum(&str, result->capacity, options->percent, str.length > 0, &options->moduleArgs); } + + if(result->timeRemaining > 0) + { + if(str.length > 0) + ffStrbufAppendS(&str, " ("); + + ffParseDuration(days, hours, minutes, seconds, &str); + ffStrbufAppendS(&str, " remaining)"); + } } if(showStatus) @@ -91,6 +111,10 @@ static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uin FF_FORMAT_ARG(result->serial, "serial"), FF_FORMAT_ARG(result->manufactureDate, "manufacture-date"), FF_FORMAT_ARG(capacityBar, "capacity-bar"), + FF_FORMAT_ARG(days, "time-days"), + FF_FORMAT_ARG(hours, "time-hours"), + FF_FORMAT_ARG(minutes, "time-minutes"), + FF_FORMAT_ARG(seconds, "time-seconds"), })); } } @@ -226,6 +250,8 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_obj_add_strbuf(doc, obj, "serial", &battery->serial); yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature); yyjson_mut_obj_add_uint(doc, obj, "cycleCount", battery->cycleCount); + if (battery->timeRemaining > 0) + yyjson_mut_obj_add_int(doc, obj, "timeRemaining", battery->timeRemaining); } FF_LIST_FOR_EACH(FFBatteryResult, battery, results) @@ -241,7 +267,7 @@ void ffGenerateBatteryJsonResult(FFBatteryOptions* options, yyjson_mut_doc* doc, void ffPrintBatteryHelpFormat(void) { - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BATTERY_MODULE_NAME, "{4}, {5}", FF_BATTERY_NUM_FORMAT_ARGS, ((const char* []) { + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BATTERY_MODULE_NAME, "{4} ({12} hours {13} mins) [{5}]", FF_BATTERY_NUM_FORMAT_ARGS, ((const char* []) { "Battery manufacturer - manufacturer", "Battery model name - model-name", "Battery technology - technology", @@ -252,6 +278,10 @@ void ffPrintBatteryHelpFormat(void) "Battery serial number - serial", "Battery manufactor date - manufacture-date", "Battery capacity (percentage bar) - capacity-bar", + "Battery time remaining days - time-days", + "Battery time remaining hours - time-hours", + "Battery time remaining minutes - time-minutes", + "Battery time remaining seconds - time-seconds", })); } diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 0381b32f4..614b0bf26 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -39,7 +39,7 @@ void ffPrintCPU(FFCPUOptions* options) if (options->showPeCoreCount) { uint32_t typeCount = 0; - while (cpu.coreTypes[typeCount].count != 0 && typeCount < sizeof(cpu.coreTypes) / sizeof(cpu.coreTypes[0])) typeCount++; + while (cpu.coreTypes[typeCount].count != 0 && typeCount < ARRAY_SIZE(cpu.coreTypes)) typeCount++; if (typeCount > 0) { qsort(cpu.coreTypes, typeCount, sizeof(cpu.coreTypes[0]), (void*) sortCores); diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 873fd77b9..ab5e4b9d2 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -11,7 +11,7 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) { FF_LIST_AUTO_DESTROY percentages = ffListCreate(sizeof(double)); - const char* error = ffGetCpuUsageResult(&percentages); + const char* error = ffGetCpuUsageResult(options, &percentages); if(error) { @@ -111,6 +111,12 @@ bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, return true; } + if (ffStrEqualsIgnCase(subKey, "wait-time")) + { + options->waitTime = ffOptionParseUInt32(key, value); + return true; + } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) return true; @@ -136,6 +142,12 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "waitTime")) + { + options->waitTime = (uint32_t) yyjson_get_uint(val); + continue; + } + if (ffPercentParseJsonObject(key, val, &options->percent)) continue; @@ -156,10 +168,10 @@ void ffGenerateCPUUsageJsonConfig(FFCPUUsageOptions* options, yyjson_mut_doc* do ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); } -void ffGenerateCPUUsageJsonResult(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateCPUUsageJsonResult(FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FF_LIST_AUTO_DESTROY percentages = ffListCreate(sizeof(double)); - const char* error = ffGetCpuUsageResult(&percentages); + const char* error = ffGetCpuUsageResult(options, &percentages); if(error) { @@ -203,6 +215,7 @@ void ffInitCPUUsageOptions(FFCPUUsageOptions* options) ffOptionInitModuleArg(&options->moduleArgs, "󰓅"); options->separate = false; options->percent = (FFColorRangeConfig) { 50, 80 }; + options->waitTime = 200; } void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options) diff --git a/src/modules/cpuusage/option.h b/src/modules/cpuusage/option.h index 92d298f30..844828b94 100644 --- a/src/modules/cpuusage/option.h +++ b/src/modules/cpuusage/option.h @@ -12,4 +12,5 @@ typedef struct FFCPUUsageOptions bool separate; FFColorRangeConfig percent; + uint32_t waitTime; // in ms } FFCPUUsageOptions; diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index a79a31c49..897e2c056 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -107,7 +107,7 @@ void ffPrintDateTime(FFDateTimeOptions* options) } char buffer[32]; - if (strftime(buffer, sizeof(buffer), "%F %T", tm) == 0) //yyyy-MM-dd HH:mm:ss + 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"); return; diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index 086f46d9d..da4e8e607 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -115,6 +115,12 @@ bool ffParseDiskIOCommandOptions(FFDiskIOOptions* options, const char* key, cons return true; } + if (ffStrEqualsIgnCase(subKey, "wait-time")) + { + options->waitTime = ffOptionParseUInt32(key, value); + return true; + } + return false; } @@ -143,6 +149,12 @@ void ffParseDiskIOJsonObject(FFDiskIOOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "waitTime")) + { + options->waitTime = (uint32_t) yyjson_get_uint(val); + continue; + } + ffPrintError(FF_DISKIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); } } @@ -222,6 +234,7 @@ void ffInitDiskIOOptions(FFDiskIOOptions* options) ffStrbufInit(&options->namePrefix); options->detectTotal = false; + options->waitTime = 1000; } void ffDestroyDiskIOOptions(FFDiskIOOptions* options) diff --git a/src/modules/diskio/option.h b/src/modules/diskio/option.h index a8daa0b4b..c41e0428b 100644 --- a/src/modules/diskio/option.h +++ b/src/modules/diskio/option.h @@ -10,5 +10,6 @@ typedef struct FFDiskIOOptions FFModuleArgs moduleArgs; FFstrbuf namePrefix; + uint32_t waitTime; bool detectTotal; } FFDiskIOOptions; diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 53f39a467..e845ff164 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -6,7 +6,7 @@ #include -#define FF_DISPLAY_NUM_FORMAT_ARGS 18 +#define FF_DISPLAY_NUM_FORMAT_ARGS 19 static int sortByNameAsc(FFDisplayResult* a, FFDisplayResult* b) { @@ -146,9 +146,9 @@ void ffPrintDisplay(FFDisplayOptions* options) if(result->refreshRate > 0) { if(options->preciseRefreshRate) - snprintf(refreshRate, sizeof(refreshRate), "%g", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0); + snprintf(refreshRate, ARRAY_SIZE(refreshRate), "%g", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0); else - snprintf(refreshRate, sizeof(refreshRate), "%i", (uint32_t) (result->refreshRate + 0.5)); + snprintf(refreshRate, ARRAY_SIZE(refreshRate), "%i", (uint32_t) (result->refreshRate + 0.5)); } else refreshRate[0] = 0; @@ -157,7 +157,7 @@ void ffPrintDisplay(FFDisplayOptions* options) if (result->serial) { const uint8_t* nums = (uint8_t*) &result->serial; - snprintf(buf, sizeof(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); + snprintf(buf, ARRAY_SIZE(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); } else buf[0] = '\0'; @@ -181,6 +181,7 @@ void ffPrintDisplay(FFDisplayOptions* options) FF_FORMAT_ARG(result->manufactureYear, "manufacture-year"), FF_FORMAT_ARG(result->manufactureWeek, "manufacture-week"), FF_FORMAT_ARG(buf, "serial"), + FF_FORMAT_ARG(result->platformApi, "platform-api"), })); } } @@ -395,6 +396,8 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_uint(doc, obj, "serial", item->serial); else yyjson_mut_obj_add_null(doc, obj, "serial"); + + yyjson_mut_obj_add_str(doc, obj, "platformApi", item->platformApi); } } @@ -419,6 +422,7 @@ void ffPrintDisplayHelpFormat(void) "Year of manufacturing - manufacture-year", "Nth week of manufacturing in the year - manufacture-week", "Serial number - serial", + "The platform API used when detecting the display - platform-api", })); } diff --git a/src/modules/keyboard/keyboard.c b/src/modules/keyboard/keyboard.c new file mode 100644 index 000000000..fcf5eba8b --- /dev/null +++ b/src/modules/keyboard/keyboard.c @@ -0,0 +1,142 @@ +#include "common/percent.h" +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/keyboard/keyboard.h" +#include "modules/keyboard/keyboard.h" +#include "util/stringUtils.h" + +#define FF_KEYBOARD_NUM_FORMAT_ARGS 2 + +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); + ffStrbufPutTo(&device->name, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_KEYBOARD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_KEYBOARD_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_FORMAT_ARG(device->name, "name"), + FF_FORMAT_ARG(device->serial, "serial"), + })); + } +} + +void ffPrintKeyboard(FFKeyboardOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFKeyboardDevice)); + + const char* error = ffDetectKeyboard(&result); + + if(error) + { + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(!result.length) + { + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + return; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) + { + printDevice(options, device, result.length > 1 ? ++index : 0); + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +bool ffParseKeyboardCommandOptions(FFKeyboardOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_KEYBOARD_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseKeyboardJsonObject(FFKeyboardOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_KEYBOARD_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateKeyboardJsonConfig(FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyKeyboardOptions))) FFKeyboardOptions defaultOptions; + ffInitKeyboardOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateKeyboardJsonResult(FF_MAYBE_UNUSED FFKeyboardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFKeyboardDevice)); + + const char* error = ffDetectKeyboard(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + } + + FF_LIST_FOR_EACH(FFKeyboardDevice, device, result) + { + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +void ffPrintKeyboardHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_KEYBOARD_MODULE_NAME, "{1} ({3})", FF_KEYBOARD_NUM_FORMAT_ARGS, ((const char* []) { + "Name - name", + "Serial number - serial", + })); +} + +void ffInitKeyboardOptions(FFKeyboardOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_KEYBOARD_MODULE_NAME, + "List connected keyboards", + ffParseKeyboardCommandOptions, + ffParseKeyboardJsonObject, + ffPrintKeyboard, + ffGenerateKeyboardJsonResult, + ffPrintKeyboardHelpFormat, + ffGenerateKeyboardJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, ""); +} + +void ffDestroyKeyboardOptions(FFKeyboardOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/keyboard/keyboard.h b/src/modules/keyboard/keyboard.h new file mode 100644 index 000000000..b54a3ccba --- /dev/null +++ b/src/modules/keyboard/keyboard.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_KEYBOARD_MODULE_NAME "Keyboard" + +void ffPrintKeyboard(FFKeyboardOptions* options); +void ffInitKeyboardOptions(FFKeyboardOptions* options); +void ffDestroyKeyboardOptions(FFKeyboardOptions* options); diff --git a/src/modules/keyboard/option.h b/src/modules/keyboard/option.h new file mode 100644 index 000000000..4f39eee19 --- /dev/null +++ b/src/modules/keyboard/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFKeyboardOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFKeyboardOptions; diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 6c7ac2c8e..a495c9dd4 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -63,7 +63,7 @@ void ffPrintMedia(FFMediaOptions* options) "[Lyric Video]", "[Official Lyric Video]", "[Lyrics]", "| Lyric Video", "| Official Lyric Video", "| Lyrics", }; - ffStrbufRemoveStrings(&songPretty, sizeof(removeStrings) / sizeof(removeStrings[0]), removeStrings); + ffStrbufRemoveStrings(&songPretty, ARRAY_SIZE(removeStrings), removeStrings); ffStrbufTrimRight(&songPretty, ' '); if(songPretty.length == 0) diff --git a/src/modules/modules.h b/src/modules/modules.h index 4f9fa7a40..e6594f030 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -34,6 +34,7 @@ #include "modules/icons/icons.h" #include "modules/initsystem/initsystem.h" #include "modules/kernel/kernel.h" +#include "modules/keyboard/keyboard.h" #include "modules/lm/lm.h" #include "modules/loadavg/loadavg.h" #include "modules/locale/locale.h" @@ -41,6 +42,7 @@ #include "modules/media/media.h" #include "modules/memory/memory.h" #include "modules/monitor/monitor.h" +#include "modules/mouse/mouse.h" #include "modules/netio/netio.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" diff --git a/src/modules/mouse/mouse.c b/src/modules/mouse/mouse.c new file mode 100644 index 000000000..27b749f47 --- /dev/null +++ b/src/modules/mouse/mouse.c @@ -0,0 +1,142 @@ +#include "common/percent.h" +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/mouse/mouse.h" +#include "modules/mouse/mouse.h" +#include "util/stringUtils.h" + +#define FF_MOUSE_NUM_FORMAT_ARGS 2 + +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); + ffStrbufPutTo(&device->name, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_MOUSE_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_MOUSE_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_FORMAT_ARG(device->name, "name"), + FF_FORMAT_ARG(device->serial, "serial"), + })); + } +} + +void ffPrintMouse(FFMouseOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFMouseDevice)); + + const char* error = ffDetectMouse(&result); + + if(error) + { + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(!result.length) + { + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No devices detected"); + return; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFMouseDevice, device, result) + { + printDevice(options, device, result.length > 1 ? ++index : 0); + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +bool ffParseMouseCommandOptions(FFMouseOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_MOUSE_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseMouseJsonObject(FFMouseOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_MOUSE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateMouseJsonConfig(FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyMouseOptions))) FFMouseOptions defaultOptions; + ffInitMouseOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateMouseJsonResult(FF_MAYBE_UNUSED FFMouseOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFMouseDevice)); + + const char* error = ffDetectMouse(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFMouseDevice, device, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "serial", &device->serial); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + } + + FF_LIST_FOR_EACH(FFMouseDevice, device, result) + { + ffStrbufDestroy(&device->serial); + ffStrbufDestroy(&device->name); + } +} + +void ffPrintMouseHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_MOUSE_MODULE_NAME, "{1} ({3})", FF_MOUSE_NUM_FORMAT_ARGS, ((const char* []) { + "Name - name", + "Serial number - serial", + })); +} + +void ffInitMouseOptions(FFMouseOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_MOUSE_MODULE_NAME, + "List connected mouses", + ffParseMouseCommandOptions, + ffParseMouseJsonObject, + ffPrintMouse, + ffGenerateMouseJsonResult, + ffPrintMouseHelpFormat, + ffGenerateMouseJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰍽"); +} + +void ffDestroyMouseOptions(FFMouseOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/mouse/mouse.h b/src/modules/mouse/mouse.h new file mode 100644 index 000000000..d78a375ae --- /dev/null +++ b/src/modules/mouse/mouse.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_MOUSE_MODULE_NAME "Mouse" + +void ffPrintMouse(FFMouseOptions* options); +void ffInitMouseOptions(FFMouseOptions* options); +void ffDestroyMouseOptions(FFMouseOptions* options); diff --git a/src/modules/mouse/option.h b/src/modules/mouse/option.h new file mode 100644 index 000000000..db9ea1866 --- /dev/null +++ b/src/modules/mouse/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFMouseOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFMouseOptions; diff --git a/src/modules/netio/netio.c b/src/modules/netio/netio.c index e6eebd4df..89113c375 100644 --- a/src/modules/netio/netio.c +++ b/src/modules/netio/netio.c @@ -129,6 +129,12 @@ bool ffParseNetIOCommandOptions(FFNetIOOptions* options, const char* key, const return true; } + if (ffStrEqualsIgnCase(subKey, "wait-time")) + { + options->waitTime = ffOptionParseUInt32(key, value); + return true; + } + return false; } @@ -163,6 +169,12 @@ void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "waitTime")) + { + options->waitTime = (uint32_t) yyjson_get_uint(val); + continue; + } + ffPrintError(FF_NETIO_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); } } @@ -259,6 +271,7 @@ void ffInitNetIOOptions(FFNetIOOptions* options) #endif ; options->detectTotal = false; + options->waitTime = 1000; } void ffDestroyNetIOOptions(FFNetIOOptions* options) diff --git a/src/modules/netio/option.h b/src/modules/netio/option.h index 3cd0ad5fb..7709b21e1 100644 --- a/src/modules/netio/option.h +++ b/src/modules/netio/option.h @@ -10,6 +10,7 @@ typedef struct FFNetIOOptions FFModuleArgs moduleArgs; FFstrbuf namePrefix; + uint32_t waitTime; bool defaultRouteOnly; bool detectTotal; } FFNetIOOptions; diff --git a/src/modules/options.h b/src/modules/options.h index 783757d3a..7cf98c127 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -34,6 +34,7 @@ #include "modules/icons/option.h" #include "modules/initsystem/option.h" #include "modules/kernel/option.h" +#include "modules/keyboard/option.h" #include "modules/loadavg/option.h" #include "modules/locale/option.h" #include "modules/lm/option.h" @@ -41,6 +42,7 @@ #include "modules/media/option.h" #include "modules/memory/option.h" #include "modules/monitor/option.h" +#include "modules/mouse/option.h" #include "modules/netio/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" diff --git a/src/modules/terminaltheme/terminaltheme.c b/src/modules/terminaltheme/terminaltheme.c index 93e702918..5ff7e720e 100644 --- a/src/modules/terminaltheme/terminaltheme.c +++ b/src/modules/terminaltheme/terminaltheme.c @@ -32,8 +32,8 @@ void ffPrintTerminalTheme(FFTerminalThemeOptions* options) char fg[32], bg[32]; const char* fgType = result.fg.dark ? "Dark" : "Light"; const char* bgType = result.bg.dark ? "Dark" : "Light"; - snprintf(fg, sizeof(fg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.fg.r, result.fg.g, result.fg.b); - snprintf(bg, sizeof(bg), "#%02" PRIX16 "%02" PRIX16 "%02" PRIX16, result.bg.r, result.bg.g, result.bg.b); + 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, FF_TERMINALTHEME_NUM_FORMAT_ARGS, ((FFformatarg[]){ FF_FORMAT_ARG(fg, "fg-color"), FF_FORMAT_ARG(fgType, "fg-type"), diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index caccc1f86..935957df1 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -34,47 +34,10 @@ void ffPrintUptime(FFUptimeOptions* options) if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + ffParseDuration(days, hours, minutes, seconds, &buffer); - if(days == 0 && hours == 0 && minutes == 0) - { - printf("%u seconds\n", seconds); - return; - } - - if(days > 0) - { - printf("%u day", days); - - if(days > 1) - putchar('s'); - - if(days >= 100) - fputs("(!)", stdout); - - if(hours > 0 || minutes > 0) - fputs(", ", stdout); - } - - if(hours > 0) - { - printf("%u hour", hours); - - if(hours > 1) - putchar('s'); - - if(minutes > 0) - fputs(", ", stdout); - } - - if(minutes > 0) - { - printf("%u min", minutes); - - if(minutes > 1) - putchar('s'); - } - - putchar('\n'); + ffStrbufPutTo(&buffer, stdout); } else { diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 7288a03dd..719d411bf 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -34,7 +34,6 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i ffParseSize(result->total, &totalPretty); double bytesPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0; - double fragPercentage = (double) result->fragmentation; if(options->moduleArgs.outputFormat.length == 0) { @@ -44,7 +43,7 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i ffStrbufSetF(&buffer, "%s / %s (", usedPretty.chars, totalPretty.chars); ffPercentAppendNum(&buffer, bytesPercentage, options->percent, false, &options->moduleArgs); ffStrbufAppendS(&buffer, ", "); - ffPercentAppendNum(&buffer, fragPercentage, options->percent, false, &options->moduleArgs); + ffPercentAppendNum(&buffer, result->fragmentation, options->percent, false, &options->moduleArgs); ffStrbufAppendF(&buffer, " frag) - %s", result->state.chars); ffStrbufPutTo(&buffer, stdout); } @@ -56,9 +55,9 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY fragPercentageNum = ffStrbufCreate(); - ffPercentAppendNum(&fragPercentageNum, fragPercentage, options->percent, false, &options->moduleArgs); + ffPercentAppendNum(&fragPercentageNum, result->fragmentation, options->percent, false, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY fragPercentageBar = ffStrbufCreate(); - ffPercentAppendBar(&fragPercentageBar, fragPercentage, options->percent, &options->moduleArgs); + ffPercentAppendBar(&fragPercentageBar, result->fragmentation, options->percent, &options->moduleArgs); FF_PRINT_FORMAT_CHECKED(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_ZPOOL_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(result->name, "name"), @@ -168,7 +167,7 @@ void ffGenerateZpoolJsonResult(FF_MAYBE_UNUSED FFZpoolOptions* options, yyjson_m yyjson_mut_obj_add_uint(doc, obj, "used", zpool->used); yyjson_mut_obj_add_uint(doc, obj, "total", zpool->total); yyjson_mut_obj_add_uint(doc, obj, "version", zpool->version); - yyjson_mut_obj_add_uint(doc, obj, "fragmentation", zpool->fragmentation); + yyjson_mut_obj_add_real(doc, obj, "fragmentation", zpool->fragmentation); } FF_LIST_FOR_EACH(FFZpoolResult, zpool, results) diff --git a/src/options/modules.c b/src/options/modules.c index cea3c7af0..755f65a87 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -35,6 +35,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitIconsOptions(&options->icons); ffInitInitSystemOptions(&options->initSystem); ffInitKernelOptions(&options->kernel); + ffInitKeyboardOptions(&options->keyboard); ffInitLMOptions(&options->lm); ffInitLoadavgOptions(&options->loadavg); ffInitLocalIpOptions(&options->localIP); @@ -42,6 +43,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitMediaOptions(&options->media); ffInitMemoryOptions(&options->memory); ffInitMonitorOptions(&options->monitor); + ffInitMouseOptions(&options->mouse); ffInitNetIOOptions(&options->netIo); ffInitOSOptions(&options->os); ffInitOpenCLOptions(&options->openCL); @@ -110,6 +112,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyIconsOptions(&options->icons); ffDestroyInitSystemOptions(&options->initSystem); ffDestroyKernelOptions(&options->kernel); + ffDestroyKeyboardOptions(&options->keyboard); ffDestroyLMOptions(&options->lm); ffDestroyLoadavgOptions(&options->loadavg); ffDestroyLocalIpOptions(&options->localIP); @@ -117,6 +120,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyMediaOptions(&options->media); ffDestroyMemoryOptions(&options->memory); ffDestroyMonitorOptions(&options->monitor); + ffDestroyMouseOptions(&options->mouse); ffDestroyNetIOOptions(&options->netIo); ffDestroyOSOptions(&options->os); ffDestroyOpenCLOptions(&options->openCL); diff --git a/src/options/modules.h b/src/options/modules.h index 919d92408..4ff82f972 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -36,6 +36,7 @@ typedef struct FFOptionsModules FFIconsOptions icons; FFInitSystemOptions initSystem; FFKernelOptions kernel; + FFKeyboardOptions keyboard; FFLMOptions lm; FFLoadavgOptions loadavg; FFLocalIpOptions localIP; @@ -43,6 +44,7 @@ typedef struct FFOptionsModules FFMediaOptions media; FFMemoryOptions memory; FFMonitorOptions monitor; + FFMouseOptions mouse; FFNetIOOptions netIo; FFOSOptions os; FFOpenCLOptions openCL; diff --git a/src/util/FFcheckmacros.h b/src/util/FFcheckmacros.h index 9eb45f78c..4a6243a72 100644 --- a/src/util/FFcheckmacros.h +++ b/src/util/FFcheckmacros.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_FFCHECKMACROS -#define FASTFETCH_INCLUDED_FFCHECKMACROS - #ifdef _MSC_VER #include #endif @@ -26,5 +23,3 @@ #else #define FF_C_SCANF(formatStrIndex, argsStartIndex) #endif - -#endif diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index a79ba2cc1..fa4a9da87 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_FFSTRBUF -#define FASTFETCH_INCLUDED_FFSTRBUF - #include "FFcheckmacros.h" #include @@ -491,5 +488,3 @@ static inline void ffStrbufTrim(FFstrbuf* strbuf, char c) } #define FF_STRBUF_AUTO_DESTROY FFstrbuf __attribute__((__cleanup__(ffStrbufDestroy))) - -#endif diff --git a/src/util/apple/cf_helpers.h b/src/util/apple/cf_helpers.h index fbfa47383..c509bd574 100644 --- a/src/util/apple/cf_helpers.h +++ b/src/util/apple/cf_helpers.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_cf_helpers -#define FASTFETCH_INCLUDED_cf_helpers - #include "fastfetch.h" #include #include @@ -38,5 +35,3 @@ static inline void wrapIoObjectRelease(io_service_t* service) IOObjectRelease(*service); } #define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease))) - -#endif diff --git a/src/util/apple/osascript.h b/src/util/apple/osascript.h index 2c9fe8306..164d8d708 100644 --- a/src/util/apple/osascript.h +++ b/src/util/apple/osascript.h @@ -1,10 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_osascript -#define FASTFETCH_INCLUDED_osascript - #include "fastfetch.h" bool ffOsascript(const char* input, FFstrbuf* result); - -#endif diff --git a/src/util/mallocHelper.h b/src/util/mallocHelper.h index cacba8ecd..8e314841e 100644 --- a/src/util/mallocHelper.h +++ b/src/util/mallocHelper.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_UTIL_MALLOC_HELPER -#define FASTFETCH_INCLUDED_UTIL_MALLOC_HELPER - #include #include @@ -14,5 +11,3 @@ static inline void ffWrapFree(const void* pPtr) } #define FF_AUTO_FREE __attribute__((__cleanup__(ffWrapFree))) - -#endif diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 961f88237..5357bde3d 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -1,5 +1,6 @@ #include "FFPlatform_private.h" #include "common/io/io.h" +#include "common/library.h" #include "util/stringUtils.h" #include "util/windows/unicode.h" #include "util/windows/registry.h" @@ -138,7 +139,7 @@ static void getUserName(FFPlatform* platform) else { wchar_t buffer[128]; - DWORD len = sizeof(buffer) / sizeof(*buffer); + DWORD len = ARRAY_SIZE(buffer); if(GetUserNameW(buffer, &len)) ffStrbufSetWS(&platform->userName, buffer); } @@ -147,7 +148,7 @@ static void getUserName(FFPlatform* platform) static void getHostName(FFPlatform* platform) { wchar_t buffer[128]; - DWORD len = sizeof(buffer) / sizeof(*buffer); + DWORD len = ARRAY_SIZE(buffer); if(GetComputerNameExW(ComputerNameDnsHostname, buffer, &len)) ffStrbufSetWS(&platform->hostName, buffer); } @@ -159,6 +160,17 @@ static void getUserShell(FFPlatform* platform) ffStrbufReplaceAllC(&platform->userShell, '\\', '/'); } +static void detectWine(FFstrbuf* buf) +{ + static const char *(__cdecl *pwine_get_version)(void); + HMODULE hntdll = GetModuleHandleW(L"ntdll.dll"); + if (!hntdll) return; + pwine_get_version = (void *)GetProcAddress(hntdll, "wine_get_version"); + if (!pwine_get_version) return; + ffStrbufAppendS(buf, buf->length ? " - wine " : "wine "); + ffStrbufAppendS(buf, pwine_get_version()); +} + static void getSystemReleaseAndVersion(FFPlatformSysinfo* info) { RTL_OSVERSIONINFOW osVersion = { .dwOSVersionInfoSize = sizeof(osVersion) }; @@ -187,6 +199,7 @@ static void getSystemReleaseAndVersion(FFPlatformSysinfo* info) else ffRegReadStrbuf(hKey, L"ReleaseId", &info->displayVersion, NULL); // For old Windows 10 } + detectWine(&info->displayVersion); ffRegReadStrbuf(hKey, L"BuildLabEx", &info->version, NULL); diff --git a/src/util/smbiosHelper.h b/src/util/smbiosHelper.h index 7d7a4b18d..1bce70b48 100644 --- a/src/util/smbiosHelper.h +++ b/src/util/smbiosHelper.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_SMBIOSVALUEHELPER -#define FASTFETCH_INCLUDED_SMBIOSVALUEHELPER - #include "util/FFstrbuf.h" bool ffIsSmbiosValueSet(FFstrbuf* value); @@ -95,5 +92,3 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable(); #ifdef __linux__ bool ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer); #endif - -#endif diff --git a/src/util/stringUtils.h b/src/util/stringUtils.h index a7dea3fbe..6c641517b 100644 --- a/src/util/stringUtils.h +++ b/src/util/stringUtils.h @@ -79,3 +79,14 @@ static inline bool ffCharIsDigit(char c) { return '0' <= c && c <= '9'; } + +static inline char* ffStrCopyN(char* __restrict__ dst, const char* __restrict__ src, size_t nDst) +{ + assert(dst != NULL); + if (__builtin_expect(dst == NULL, false)) return dst; + + size_t len = strnlen(src, nDst - 1); + memcpy(dst, src, len); + dst[len] = '\0'; + return dst + len; +} diff --git a/src/util/textModifier.h b/src/util/textModifier.h index 3ff9db082..dbc4338cd 100644 --- a/src/util/textModifier.h +++ b/src/util/textModifier.h @@ -1,10 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_TEXT_MODIFIER -#define FASTFETCH_INCLUDED_TEXT_MODIFIER - #define FASTFETCH_TEXT_MODIFIER_BOLT "\033[1m" #define FASTFETCH_TEXT_MODIFIER_ERROR "\033[1;31m" #define FASTFETCH_TEXT_MODIFIER_RESET "\033[m" - -#endif diff --git a/src/util/unused.h b/src/util/unused.h index faef70d09..937ac9bf9 100644 --- a/src/util/unused.h +++ b/src/util/unused.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_UNUSED -#define FASTFETCH_INCLUDED_UNUSED - static inline void ffUnused(int dummy, ...) { (void) dummy; } #define FF_UNUSED(...) ffUnused(0, __VA_ARGS__); #if defined(__GNUC__) || defined(__clang__) @@ -10,5 +7,3 @@ static inline void ffUnused(int dummy, ...) { (void) dummy; } #else #define FF_MAYBE_UNUSED #endif - -#endif diff --git a/src/util/windows/getline.h b/src/util/windows/getline.h index e4f48a4cf..0c0e9ec70 100644 --- a/src/util/windows/getline.h +++ b/src/util/windows/getline.h @@ -1,11 +1,6 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_UTIL_GETLINE -#define FASTFETCH_INCLUDED_UTIL_GETLINE - #include #include ssize_t getline(char **lineptr, size_t *n, FILE *stream); - -#endif diff --git a/src/util/windows/registry.h b/src/util/windows/registry.h index 959fea5e3..1c3f7f46f 100644 --- a/src/util/windows/registry.h +++ b/src/util/windows/registry.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_REGISTER_H -#define FASTFETCH_INCLUDED_REGISTER_H - #include "fastfetch.h" #include @@ -22,5 +19,3 @@ bool ffRegReadUint(HKEY hKey, const wchar_t* valueNameW, uint32_t* result, FFstr bool ffRegReadUint64(HKEY hKey, const wchar_t* valueNameW, uint64_t* result, FFstrbuf* error); bool ffRegGetSubKey(HKEY hKey, uint32_t index, FFstrbuf* result, FFstrbuf* error); bool ffRegGetNSubKeys(HKEY hKey, uint32_t* result, FFstrbuf* error); - -#endif diff --git a/src/util/windows/unicode.h b/src/util/windows/unicode.h index a25d4a7b4..783cf6787 100644 --- a/src/util/windows/unicode.h +++ b/src/util/windows/unicode.h @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_UNICODE_H -#define FASTFETCH_INCLUDED_UNICODE_H - #include "util/FFstrbuf.h" #include @@ -34,5 +31,3 @@ static inline FFstrbuf ffStrbufCreateWS(const wchar_t* source) if (!source) return ffStrbufCreate(); return ffStrbufCreateNWS((uint32_t)wcslen(source), source); } - -#endif diff --git a/src/util/windows/unicode.hpp b/src/util/windows/unicode.hpp index b6745572b..f3bca6f48 100644 --- a/src/util/windows/unicode.hpp +++ b/src/util/windows/unicode.hpp @@ -1,8 +1,5 @@ #pragma once -#ifndef FASTFETCH_INCLUDED_UNICODE_HPP -#define FASTFETCH_INCLUDED_UNICODE_HPP - #ifdef __cplusplus extern "C" { @@ -26,5 +23,3 @@ static inline void ffStrbufSetWSV(FFstrbuf* result, const std::wstring_view sour #error Must be included in C++ source file #endif - -#endif