diff --git a/.codespellrc b/.codespellrc index 087150a6d5..9e972389e7 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,sur,doas,conexant +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1745a789d3..73d7a20c77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -438,6 +438,42 @@ jobs: name: fastfetch-freebsd-amd64 path: ./fastfetch-*.* + openbsd-amd64: + name: OpenBSD-amd64 + runs-on: ubuntu-latest + permissions: + security-events: write + contents: read + steps: + - name: checkout repository + uses: actions/checkout@v4 + + - name: run VM + uses: cross-platform-actions/action@master + with: + operating_system: openbsd + architecture: x86-64 + cpu_count: 4 + shell: bash + version: '7.5' + run: | + uname -a + sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + cmake --build . --target package --verbose -j4 + ./fastfetch --list-features + time ./fastfetch -c presets/ci.jsonc --stat false + time ./fastfetch -c presets/ci.jsonc --format json + time ./flashfetch + ldd fastfetch + ctest + + - name: upload artifacts + uses: actions/upload-artifact@v4 + with: + name: fastfetch-openbsd-amd64 + path: ./fastfetch-*.* + windows-amd64: name: Windows-amd64 runs-on: windows-latest @@ -586,6 +622,7 @@ jobs: - musl-aarch64 - macos-universal - freebsd-amd64 + - openbsd-amd64 - sunos-amd64 - windows-amd64 - windows-i686 diff --git a/CHANGELOG.md b/CHANGELOG.md index 57eda8efec..3614d0370c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +# 2.27.0 + +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 refresh rate reported by `monitor` module is the current refresh rate. + +Features: +* Add basic, highly experimental support of OpenBSD (OpenBSD) +* Improve support for Raspberry pi (CPU / GPU, Linux) +* Detect SOC name, instead of displaying components used in the SOC, if available (CPU, Linux) +* Add option `--brightness-compact` to display multiple brightness values in one line (Brightness) +* Add `day-pretty` (#1305, DateTime) +* Support network interface adapter flag detection (#1315, LocalIP) + * Enable it with `--localip-show-flags` + +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) +* 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) + +Logos: +* Add XeroArch +* Add ValhallaOS + # 2.26.1 Features: diff --git a/CMakeLists.txt b/CMakeLists.txt index bbd9964dc7..065c241599 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.26.1 + VERSION 2.27.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -18,6 +18,8 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") set(FreeBSD TRUE CACHE BOOL "..." FORCE) +elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD") + set(OpenBSD TRUE CACHE BOOL "..." FORCE) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") set(SunOS TRUE CACHE BOOL "..." FORCE) elseif(NOT APPLE AND NOT WIN32) @@ -44,30 +46,30 @@ include(CheckIncludeFile) include(CMakeDependentOption) -cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF) -cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD" OFF) -cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR WIN32 OR ANDROID OR SunOS" OFF) +cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD" OFF) +cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF) -cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF) +cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR OpenBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR APPLE OR WIN32 OR SunOS" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR APPLE OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR APPLE OR SunOS" OFF) cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) -cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR WIN32 OR SunOS" OFF) -cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF) +cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR WIN32 OR ANDROID OR SunOS" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) -cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF) +cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR OpenBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF) cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID" OFF) @@ -484,7 +486,6 @@ if(LINUX) src/detection/gamepad/gamepad_linux.c src/detection/media/media_linux.c src/detection/memory/memory_linux.c - src/detection/monitor/monitor_linux.c src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -549,7 +550,6 @@ elseif(ANDROID) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_nosupport.c src/detection/memory/memory_linux.c - src/detection/monitor/monitor_nosupport.c src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_android.c @@ -629,7 +629,6 @@ elseif(FreeBSD) src/detection/gamepad/gamepad_bsd.c src/detection/media/media_linux.c src/detection/memory/memory_bsd.c - src/detection/monitor/monitor_linux.c src/detection/netio/netio_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -656,6 +655,85 @@ elseif(FreeBSD) src/util/platform/FFPlatform_unix.c src/util/binary_linux.c ) +elseif(OpenBSD) + list(APPEND LIBFASTFETCH_SRC + src/common/dbus.c + src/common/io/io_unix.c + src/common/netif/netif_bsd.c + src/common/networking_linux.c + src/common/processing_linux.c + src/common/sysctl.c + src/detection/battery/battery_nosupport.c + src/detection/bios/bios_nosupport.c + src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c + src/detection/board/board_nosupport.c + src/detection/bootmgr/bootmgr_nosupport.c + src/detection/brightness/brightness_nosupport.c + src/detection/btrfs/btrfs_nosupport.c + src/detection/chassis/chassis_nosupport.c + src/detection/cpu/cpu_obsd.c + src/detection/cpucache/cpucache_nosupport.c + src/detection/cpuusage/cpuusage_bsd.c + src/detection/cursor/cursor_linux.c + src/detection/disk/disk_bsd.c + src/detection/dns/dns_linux.c + src/detection/physicaldisk/physicaldisk_nosupport.c + src/detection/physicalmemory/physicalmemory_nosupport.c + src/detection/diskio/diskio_nosupport.c + src/detection/displayserver/linux/displayserver_linux.c + src/detection/displayserver/linux/drm.c + src/detection/displayserver/linux/wayland/wayland.c + src/detection/displayserver/linux/wayland/global-output.c + src/detection/displayserver/linux/wayland/zwlr-output.c + src/detection/displayserver/linux/wayland/kde-output.c + src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c + src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c + src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c + src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c + src/detection/displayserver/linux/wmde.c + src/detection/displayserver/linux/xcb.c + src/detection/displayserver/linux/xlib.c + src/detection/font/font_linux.c + src/detection/gpu/gpu_nosupport.c + src/detection/gtk_qt/gtk.c + src/detection/host/host_obsd.c + src/detection/lm/lm_nosupport.c + src/detection/icons/icons_linux.c + src/detection/initsystem/initsystem_linux.c + src/detection/libc/libc_nosupport.c + src/detection/loadavg/loadavg_bsd.c + src/detection/locale/locale_linux.c + src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c + src/detection/media/media_linux.c + src/detection/memory/memory_obsd.c + src/detection/netio/netio_nosupport.c + src/detection/opengl/opengl_linux.c + src/detection/os/os_obsd.c + src/detection/packages/packages_obsd.c + src/detection/poweradapter/poweradapter_nosupport.c + src/detection/processes/processes_obsd.c + src/detection/gtk_qt/qt.c + src/detection/sound/sound_linux.c + src/detection/swap/swap_obsd.c + src/detection/terminalfont/terminalfont_linux.c + src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c + src/detection/theme/theme_linux.c + src/detection/tpm/tpm_nosupport.c + src/detection/uptime/uptime_bsd.c + src/detection/users/users_nosupport.c + src/detection/wallpaper/wallpaper_linux.c + src/detection/wifi/wifi_nosupport.c + src/detection/wm/wm_nosupport.c + src/detection/de/de_linux.c + src/detection/wmtheme/wmtheme_linux.c + src/detection/camera/camera_nosupport.c + src/detection/zpool/zpool_nosupport.c + src/util/platform/FFPlatform_unix.c + src/util/binary_linux.c + ) elseif(APPLE) list(APPEND LIBFASTFETCH_SRC src/common/io/io_unix.c @@ -696,7 +774,6 @@ elseif(APPLE) src/detection/gamepad/gamepad_apple.c src/detection/media/media_apple.m src/detection/memory/memory_apple.c - src/detection/monitor/monitor_apple.m src/detection/netio/netio_bsd.c src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m @@ -764,7 +841,6 @@ elseif(WIN32) src/detection/media/media_windows.c src/detection/memory/memory_windows.c src/detection/physicalmemory/physicalmemory_linux.c - src/detection/monitor/monitor_windows.c src/detection/netio/netio_windows.c src/detection/opengl/opengl_windows.c src/detection/os/os_windows.cpp @@ -848,7 +924,6 @@ elseif(SunOS) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_sunos.c - src/detection/monitor/monitor_linux.c src/detection/netio/netio_sunos.c src/detection/opengl/opengl_linux.c src/detection/os/os_sunos.c @@ -951,13 +1026,16 @@ if(FreeBSD AND EXISTS "/usr/local/bin/objdump") endif() endif() -target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1 _FILE_OFFSET_BITS=64) -if(WIN32) - target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1) +if(LINUX OR ANDROID) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1 _FILE_OFFSET_BITS=64) +elseif(WIN32) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00) elseif(APPLE) - target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _DARWIN_C_SOURCE) +elseif(OpenBSD) + target_compile_definitions(libfastfetch PUBLIC _XOPEN_SOURCE=700 _FILE_OFFSET_BITS=64 _BSD_SOURCE) elseif(SunOS) - target_compile_definitions(libfastfetch PUBLIC __EXTENSIONS__ _POSIX_C_SOURCE=1) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 __EXTENSIONS__ _POSIX_C_SOURCE) endif() if(HAVE_STATX) @@ -1103,10 +1181,17 @@ ff_lib_enable(EGL "egl" "EGL" ) -ff_lib_enable(GLX - "glx" - "GLX" -) +if(NOT OpenBSD) + ff_lib_enable(GLX + "glx" + "GLX" + ) +else() + ff_lib_enable(GLX + "gl" + "GL" + ) +endif() ff_lib_enable(OSMESA "osmesa" "OSMesa" @@ -1200,7 +1285,6 @@ elseif(APPLE) PRIVATE "-weak_framework Apple80211" ) elseif(WIN32) - target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0A00) target_link_libraries(libfastfetch PRIVATE "dwmapi" PRIVATE "gdi32" @@ -1221,6 +1305,11 @@ elseif(FreeBSD) PRIVATE "usbhid" PRIVATE "geom" ) +elseif(OpenBSD) + target_link_libraries(libfastfetch + PRIVATE "m" + PRIVATE "kvm" + ) elseif(SunOS) target_link_libraries(libfastfetch PRIVATE "m" @@ -1296,6 +1385,10 @@ if(NOT WIN32) if(HAVE_WORDEXP) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1) endif() + CHECK_INCLUDE_FILE("glob.h" HAVE_GLOB) + if(HAVE_GLOB) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLOB=1) + endif() if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT) CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP) if(HAVE_PTHREAD_NP) @@ -1521,4 +1614,4 @@ fastfetch is a neofetch-like tool for fetching system information and displaying It is written mostly in C to achieve much better performance.\ ") -include(CPack) +include(CPack) \ No newline at end of file diff --git a/README.md b/README.md index 2d6e8e3d05..6487d0e70e 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,10 @@ pyfiglet -s -f small_slant $(fastfetch -s os --format json | jq -r '.[0].result. ![image](https://github.com/fastfetch-cli/fastfetch/assets/6134068/6466524e-ab8c-484f-848d-eec7ddeb7df2) +### Q: My image logo behaves weird. How can I fix it? + +See troubleshooting section: + ### Q: Fastfetch runs in white and black on shell startup. Why? This issue usually happens when using fastfetch with `p10k`. There are known incompatibility between fastfetch and p10k instant prompt. @@ -186,9 +190,19 @@ You can always use `fastfetch --pipe false` to force fastfetch running in colorf See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096). +### Q: Fastfetch shows less dpkg packages than neofetch, is it a bug? + +Neofetch incorrectly counts `rc` packages ( the package has been removed, but that the configuration files remain ). Bug https://github.com/dylanaraps/neofetch/issues/2278 + ### Q: I use Debian / Ubuntu / Debian deserved distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug? -See [#1282](https://github.com/fastfetch-cli/fastfetch/issues/1282) +Try upgrading `pci.ids`: Download and overwrite file `/usr/share/hwdata/pci.ids`. For AMD GPUs, you should also upgrade `amdgpu.ids`: Download and overwrite file `/usr/share/libdrm/amdgpu.ids` + +Alternatively, you may try to use `fastfetch --gpu-driver-specific`, so that `fastfetch` will try to ask the driver for GPU name if supported. + +### Q: Fastfetch cannot detect my awesome 3rd-party macOS window manager! + +Try `fastfetch --wm-detect-plugin`. See also [#984](https://github.com/fastfetch-cli/fastfetch/issues/984) ### Q: I want feature A / B / C. Will fastfetch support it? diff --git a/completions/fastfetch.bash b/completions/fastfetch.bash index 76e43859a7..0e7464d6b7 100644 --- a/completions/fastfetch.bash +++ b/completions/fastfetch.bash @@ -183,7 +183,10 @@ __fastfetch_completion() "--display-precise-refresh-rate" "--localip-show-ipv4" "--localip-show-ipv6" + "--localip-show-flags" "--localip-show-loop" + "--localip-show-mtu" + "--localip-show-speed" "--localip-name-prefix" "--localip-compact-type" "--escape-bedrock" diff --git a/completions/fastfetch.fish b/completions/fastfetch.fish index 494de27308..7badab3881 100755 --- a/completions/fastfetch.fish +++ b/completions/fastfetch.fish @@ -2,6 +2,11 @@ if not type -q fastfetch exit end +command -q python3 +if test $status -ne 0 + exit +end + complete -c fastfetch -f function __fastfetch_complete_bool diff --git a/completions/fastfetch.zsh b/completions/fastfetch.zsh index a6ce692798..5688c17458 100644 --- a/completions/fastfetch.zsh +++ b/completions/fastfetch.zsh @@ -1,6 +1,13 @@ #compdef fastfetch function _fastfetch() { + + whence python3 &> /dev/null + if [ $? -ne 0 ] + then + return + fi + local state local -a opts=("${(f)$( diff --git a/debian/changelog b/debian/changelog index 3a6b98854b..3eff4467a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +fastfetch (2.26.1ubuntu1) jammy; urgency=medium + + * Update correct code + + -- Carter Li Mon, 30 Sep 2024 00:21:20 +0800 + +fastfetch (2.26.1) jammy; urgency=medium + + * Update to 2.26.1 + + -- Carter Li Sun, 29 Sep 2024 16:15:31 +0800 + fastfetch (2.26.0) jammy; urgency=medium * Update to 2.26.0 diff --git a/debian/files b/debian/files index 1d7ec558e0..8a4ba4133c 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.26.0_source.buildinfo universe/utils optional +fastfetch_2.26.1ubuntu1_source.buildinfo universe/utils optional diff --git a/doc/json_schema.json b/doc/json_schema.json index 04266e3833..c9bf608317 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -344,7 +344,7 @@ "description": "Set the command to be executed before printing logos", "default": "" }, - "showVersion": { + "detectVersion": { "type": "boolean", "description": "Whether to detect and display component versions. Mainly for benchmarking", "default": true @@ -816,7 +816,7 @@ }, { "const": "monitor", - "description": "Print connected physical monitor information" + "description": "Alias of Display module" }, { "const": "opencl", @@ -1041,6 +1041,11 @@ "maximum": 400, "default": 10 }, + "compact": { + "description": "Set if multiple results should be printed in one line", + "type": "boolean", + "default": false + }, "key": { "$ref": "#/$defs/key" }, @@ -1698,6 +1703,11 @@ "type": "boolean", "default": false }, + "showFlags": { + "description": "Show the interface's flags", + "type": "boolean", + "default": false + }, "compact": { "description": "Show all IPs in one line", "type": "boolean", diff --git a/presets/all.jsonc b/presets/all.jsonc index 9b27615e04..8e4da85d62 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -72,7 +72,9 @@ "showIpv6": true, "showMac": true, "showSpeed": true, - "showMtu": true + "showMtu": true, + "showLoop": true, + "showFlags": true }, "dns", "wifi", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 3027010d8f..6431509c28 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -74,7 +74,9 @@ "showIpv6": true, "showMac": true, "showSpeed": true, - "showMtu": true + "showMtu": true, + "showLoop": true, + "showFlags": true }, "dns", "wifi", diff --git a/presets/examples/19.jsonc b/presets/examples/19.jsonc index 17db60c262..d6ef2a904a 100644 --- a/presets/examples/19.jsonc +++ b/presets/examples/19.jsonc @@ -119,9 +119,10 @@ "keyColor": "blue" }, { - "type": "monitor", + "type": "display", "key": "MONITOR ({name})", - "keyColor": "blue" + "keyColor": "blue", + "format": "{width}x{height} @ {refresh-rate} Hz - {physical-width}x{physical-height} mm ({inch} inches, {ppi} ppi)" }, { "type": "custom", // DesignInfo diff --git a/src/common/init.c b/src/common/init.c index 514b9fb6af..643f94a944 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -245,7 +245,7 @@ void ffListFeatures(void) #if FF_HAVE_DDCUTIL "libddcutil\n" #endif - #if FF_HAVE_ELF || __sun || __FreeBSD__ + #if FF_HAVE_ELF || __sun || __FreeBSD__ || __OpenBSD__ "libelf\n" #endif #if FF_HAVE_LIBZFS diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index facc03a56f..54689ffaec 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -14,8 +14,11 @@ #if FF_HAVE_WORDEXP #include +#elif FF_HAVE_GLOB + #warning " is not available, use instead" + #include #else - #warning " not available" + #warning "Neither nor is available" #endif static void createSubfolders(const char* fileName) @@ -121,7 +124,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o #if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056 wordexp_t exp; - if(wordexp(in, &exp, 0) != 0) + if (wordexp(in, &exp, 0) != 0) return false; if (exp.we_wordc == 1) @@ -132,6 +135,20 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o wordfree(&exp); + #elif FF_HAVE_GLOB + + glob_t gb; + if (glob(in, GLOB_NOSORT | GLOB_TILDE, NULL, &gb) != 0) + return false; + + if (gb.gl_matchc == 1) + { + result = true; + ffStrbufSetS(out, gb.gl_pathv[0]); + } + + globfree(&gb); + #endif return result; @@ -191,14 +208,24 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char* ssize_t nRead = read(ftty, buffer + bytesRead, sizeof(buffer) - bytesRead - 1); if (nRead <= 0) + { + va_end(args); return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed"; + } bytesRead += (size_t) nRead; buffer[bytesRead] = '\0'; - int ret = vsscanf(buffer, format, args); + va_list cargs; + va_copy(cargs, args); + int ret = vsscanf(buffer, format, cargs); + va_end(cargs); + if (ret <= 0) + { + va_end(args); return "vsscanf(buffer, format, args) failed"; + } if (ret >= nParams) break; } diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 6f2465da64..632530ccc8 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -266,14 +266,24 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char* { DWORD bytes = 0; if (!ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL) || bytes == 0) + { + va_end(args); return "ReadFile() failed"; + } bytesRead += bytes; buffer[bytesRead] = '\0'; + va_list cargs; + va_copy(cargs, args); int ret = vsscanf(buffer, format, args); + va_end(cargs); + if (ret <= 0) + { + va_end(args); return "vsscanf(buffer, format, args) failed"; + } if (ret >= nParams) break; } diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index af3f4ebf50..ca7059417d 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -22,6 +22,10 @@ #include #elif defined(__sun) #include +#elif defined(__OpenBSD__) +#include +#include +#include #endif enum { FF_PIPE_BUFSIZ = 8192 }; @@ -259,6 +263,18 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons } } + #elif defined(__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_PID, pid, sizeof(struct kinfo_proc), &count); + if (proc) + { + char** argv = kvm_getargv(kd, proc, 0); + if (argv) ffStrbufSetS(exe, argv[0]); + } + kvm_close(kd); + #endif if(exe->length == 0) @@ -373,6 +389,23 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i if (tty) *tty = (int) proc.pr_ttydev; + #elif defined(__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_PID, pid, sizeof(struct kinfo_proc), &count); + if (proc) + { + ffStrbufSetS(name, proc->p_comm); + if (ppid) + *ppid = proc->p_ppid; + if (tty) + *tty = (int) proc->p_tdev; + } + kvm_close(kd); + if (!proc) + return "kvm_getprocs() failed"; + #else return "Unsupported platform"; diff --git a/src/common/sysctl.c b/src/common/sysctl.c index 4f0f3b65ce..42a5875a6a 100644 --- a/src/common/sysctl.c +++ b/src/common/sysctl.c @@ -2,6 +2,41 @@ #include +#ifdef __OpenBSD__ +const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result) +{ + size_t neededLength; + if (sysctl((int[]) {mib1, mib2}, 2, NULL, &neededLength, NULL, 0) != 0 || neededLength == 1) //neededLength is 1 for empty strings, because of the null terminator + return "sysctlbyname() failed"; + + ffStrbufEnsureFree(result, (uint32_t) neededLength - 1); + + if (sysctl((int[]) {mib1, mib2}, 2, result->chars + result->length, &neededLength, NULL, 0) == 0) + result->length += (uint32_t) neededLength - 1; + + result->chars[result->length] = '\0'; + + return NULL; +} + +int ffSysctlGetInt(int mib1, int mib2, int defaultValue) +{ + int result; + size_t neededLength = sizeof(result); + if (sysctl((int[]) {mib1, mib2}, 2, &result, &neededLength, NULL, 0) != 0) + return defaultValue; + return result; +} + +int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue) +{ + int64_t result; + size_t neededLength = sizeof(result); + if(sysctl((int[]) {mib1, mib2}, 2, &result, &neededLength, NULL, 0) != 0) + return defaultValue; + return result; +} +#else const char* ffSysctlGetString(const char* propName, FFstrbuf* result) { size_t neededLength; @@ -35,6 +70,7 @@ int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue) return defaultValue; return result; } +#endif // OpenBSD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength) { diff --git a/src/common/sysctl.h b/src/common/sysctl.h index 2a210de862..1d5cc503a6 100644 --- a/src/common/sysctl.h +++ b/src/common/sysctl.h @@ -6,7 +6,13 @@ #include #include +#ifdef __OpenBSD__ +const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result); +FF_C_NODISCARD int ffSysctlGetInt(int mib1, int mib2, int defaultValue); +FF_C_NODISCARD int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue); +#else const char* ffSysctlGetString(const char* propName, FFstrbuf* result); FF_C_NODISCARD int ffSysctlGetInt(const char* propName, int defaultValue); FF_C_NODISCARD int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue); +#endif FF_C_NODISCARD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength); diff --git a/src/data/help.json b/src/data/help.json index 0d3424adbe..bdce5411fe 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1000,6 +1000,14 @@ "default": 10 } }, + { + "long": "brightness-compact", + "desc": "Set if multiple results should be printed in one line", + "arg": { + "type": "bool", + "default": false + } + }, { "long": "sound-type", "desc": "Set what type of sound devices should be printed", @@ -1188,6 +1196,24 @@ "default": false } }, + { + "long": "localip-show-mtu", + "desc": "Show net interface's MTU (Maximum Transmission Unit) size in bytes", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, + { + "long": "localip-show-speed", + "desc": "Show net interface's link speed with human-readable format (or an 1Mb units integer in JSON format)", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "localip-show-prefix-len", "desc": "Show network prefix length (/N) in local ip module", @@ -1223,6 +1249,15 @@ "default": false } }, + { + "long": "localip-show-flags", + "desc": "Show net interface flags in local ip module", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "localip-compact", "desc": "Show all IPs in one line", diff --git a/src/detection/board/board_linux.c b/src/detection/board/board_linux.c index 0165df2e1f..70cd54034a 100644 --- a/src/detection/board/board_linux.c +++ b/src/detection/board/board_linux.c @@ -12,13 +12,17 @@ const char* ffDetectBoard(FFBoardResult* board) ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor); ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version); } + else if (ffReadFileBuffer("/proc/device-tree/board", &board->name)) + { + ffStrbufTrimRightSpace(&board->name); + } else if (ffReadFileBuffer("/proc/device-tree/compatible", &board->vendor)) { - // use model name as board name uint32_t comma = ffStrbufFirstIndexC(&board->vendor, ','); if (comma < board->vendor.length) { ffStrbufSetS(&board->name, board->vendor.chars + comma + 1); + ffStrbufTrimRightSpace(&board->name); ffStrbufSubstrBefore(&board->vendor, comma); } } diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index ffc6d835dc..fe08272f2a 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -47,7 +47,7 @@ static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) ffStrbufEqualS(buffer, "coretemp") // Intel ) return value / 1000.; - return false; + return 0.0/0.0; } static double detectCPUTemp(void) @@ -388,38 +388,53 @@ FF_MAYBE_UNUSED static void detectArmSoc(FFCPUResult* cpu) return; // device-vendor,device-model\0soc-vendor,soc-model\0 - char content[64]; + char content[256]; ssize_t length = ffReadFileData("/proc/device-tree/compatible", sizeof(content), content); if (length <= 2) return; - // get the second NUL terminated string - char* modelName = memchr(content, '\0', (size_t) length) + 1; - if (!modelName || modelName - content >= length) return; + // get the second NUL terminated string if it exists + char* vendor = memchr(content, '\0', (size_t) length) + 1; + if (!vendor || vendor - content >= length) vendor = content; + + char* model = strchr(vendor, ','); + if (!model) return; + *model = '\0'; + ++model; - if (ffStrStartsWith(modelName, "apple,t")) + if (false) {} + #if __aarch64__ + else if (ffStrEquals(vendor, "apple")) { - // https://elixir.bootlin.com/linux/v6.11-rc7/source/arch/arm64/boot/dts/apple - const char* code = modelName + strlen("apple,t"); - uint32_t deviceId = (uint32_t) strtoul(code, NULL, 10); - ffStrbufSetStatic(&cpu->name, ffCPUAppleCodeToName(deviceId)); - if (!cpu->name.length) + // https://elixir.bootlin.com/linux/v6.11/source/arch/arm64/boot/dts/apple + if (model[0] == 't') { - ffStrbufAppendS(&cpu->name, "Apple Silicon T"); - ffStrbufAppendS(&cpu->name, code); + uint32_t deviceId = (uint32_t) strtoul(model + 1, NULL, 10); + ffStrbufSetStatic(&cpu->name, ffCPUAppleCodeToName(deviceId)); + + if (!cpu->name.length) + { + ffStrbufSetS(&cpu->name, "Apple Silicon "); + ffStrbufAppendS(&cpu->name, model); + } } + else + ffStrbufSetS(&cpu->name, model); + + ffStrbufSetStatic(&cpu->vendor, "Apple"); } - else if (ffStrStartsWith(modelName, "qcom,")) + #endif + else if (ffStrEquals(vendor, "qcom")) { - // https://elixir.bootlin.com/linux/v6.11-rc7/source/arch/arm64/boot/dts/qcom - if (ffStrStartsWith(modelName + strlen("qcom,"), "x")) + // https://elixir.bootlin.com/linux/v6.11/source/arch/arm64/boot/dts/qcom + if (ffStrStartsWith(model, "x")) { ffStrbufSetS(&cpu->name, "Qualcomm Snapdragon X Elite "); - for (const char* p = modelName + strlen("qcom,"); *p; ++p) + for (const char* p = model + 1; *p; ++p) ffStrbufAppendC(&cpu->name, (char) toupper(*p)); } - else if (ffStrStartsWith(modelName + strlen("qcom,"), "sc")) + else if (ffStrStartsWith(model, "sc")) { - const char* code = modelName + strlen("qcom,sc"); + const char* code = model + 2; uint32_t deviceId = (uint32_t) strtoul(code, NULL, 10); ffStrbufSetStatic(&cpu->name, ffCPUQualcommCodeToName(deviceId)); if (!cpu->name.length) @@ -428,6 +443,23 @@ FF_MAYBE_UNUSED static void detectArmSoc(FFCPUResult* cpu) ffStrbufAppendS(&cpu->name, code); } } + else + ffStrbufSetS(&cpu->name, model); + + ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); + } + else if (ffStrEquals(vendor, "brcm")) + { + // Raspberry Pi + ffStrbufSetStatic(&cpu->vendor, "Broadcom"); + for (const char* p = model; *p; ++p) + ffStrbufAppendC(&cpu->name, (char) toupper(*p)); + } + else + { + ffStrbufSetS(&cpu->name, model); + ffStrbufSetS(&cpu->vendor, vendor); + cpu->vendor.chars[0] = (char) toupper(vendor[0]); } } @@ -480,7 +512,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) #if __ANDROID__ detectAndroid(cpu); - #elif __aarch64__ + #else detectArmSoc(cpu); #endif diff --git a/src/detection/cpu/cpu_obsd.c b/src/detection/cpu/cpu_obsd.c new file mode 100644 index 0000000000..04d5501989 --- /dev/null +++ b/src/detection/cpu/cpu_obsd.c @@ -0,0 +1,19 @@ +#include "cpu.h" +#include "common/sysctl.h" + +const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) +{ + if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name)) + return "sysctl(hw.model) failed"; + + cpu->coresPhysical = (uint16_t) ffSysctlGetInt(CTL_HW, HW_NCPU, 1); + cpu->coresLogical = cpu->coresPhysical; + cpu->coresOnline = (uint16_t) ffSysctlGetInt(CTL_HW, HW_NCPUONLINE, cpu->coresLogical); + + ffCPUDetectSpeedByCpuid(cpu); + + cpu->frequencyBase = (uint32_t) ffSysctlGetInt(CTL_HW, HW_CPUSPEED, 0); + cpu->temperature = FF_CPU_TEMP_UNSET; // HW_SENSORS? + + return NULL; +} diff --git a/src/detection/cpuusage/cpuusage_bsd.c b/src/detection/cpuusage/cpuusage_bsd.c index af513878ff..a04c05b75d 100644 --- a/src/detection/cpuusage/cpuusage_bsd.c +++ b/src/detection/cpuusage/cpuusage_bsd.c @@ -6,18 +6,34 @@ #include #include +#ifdef __OpenBSD__ + #include +#endif + const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { size_t neededLength = 0; +#ifdef __OpenBSD__ + int ctls[] = {CTL_KERN, KERN_CPTIME}; + if (sysctl(ctls, 2, NULL, &neededLength, NULL, 0) != 0) + return "sysctl({CTL_KERN, KERN_CPTIME}, 2, NULL) failed"; +#else if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0) return "sysctlbyname(kern.cp_times, NULL) failed"; +#endif uint32_t coreCount = (uint32_t) (neededLength / (CPUSTATES * sizeof(uint64_t))); assert(coreCount > 0); FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength); + +#ifdef __OpenBSD__ + if (sysctl(ctls, 2, cpTimes, &neededLength, NULL, 0) != 0) + return "sysctl({CTL_KERN, KERN_CPTIME}, 2, NULL) failed"; +#else if(sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0) return "sysctlbyname(kern.cp_times, cpTime) failed"; +#endif for (uint32_t i = 0; i < coreCount; ++i) { diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 81be9c83fc..4060669c33 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -92,6 +92,11 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk) }, &attrBuf, sizeof(attrBuf), 0) == 0) ffStrbufInitNS(&disk->name, attrBuf.nameRef.attr_length - 1 /* excluding '\0' */, attrBuf.nameSpace); } +#else +static void detectFsInfo(struct statfs* fs, FFDisk* disk) +{ + FF_UNUSED(fs, disk); +} #endif const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) @@ -143,6 +148,10 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) if(fs->f_flags & MNT_RDONLY) disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; + #ifdef __OpenBSD__ + #define st_birthtimespec __st_birthtim + #endif + struct stat st; if(stat(fs->f_mntonname, &st) == 0 && st.st_birthtimespec.tv_sec > 0) disk->createTime = (uint64_t)((st.st_birthtimespec.tv_sec * 1000) + (st.st_birthtimespec.tv_nsec / 1000000)); diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index ddc973962f..74898721bc 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -33,7 +33,10 @@ FFDisplayResult* ffdsAppendDisplay( display->primary = primary; display->bitDepth = 0; - display->hdrEnabled = false; + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + display->manufactureYear = 0; + display->manufactureWeek = 0; + display->serial = 0; return display; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 127dbc5fe9..5a030b12ab 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -48,6 +48,14 @@ typedef enum FFDisplayType { FF_DISPLAY_TYPE_EXTERNAL, } FFDisplayType; +typedef enum FFDisplayHdrStatus +{ + FF_DISPLAY_HDR_STATUS_UNKNOWN, + FF_DISPLAY_HDR_STATUS_UNSUPPORTED, + FF_DISPLAY_HDR_STATUS_SUPPORTED, + FF_DISPLAY_HDR_STATUS_ENABLED, +} FFDisplayHdrStatus; + typedef struct FFDisplayResult { uint32_t width; @@ -63,7 +71,10 @@ typedef struct FFDisplayResult uint32_t physicalHeight; bool primary; uint8_t bitDepth; - bool hdrEnabled; + FFDisplayHdrStatus hdrStatus; + uint16_t manufactureYear; + uint16_t manufactureWeek; + uint32_t serial; } FFDisplayResult; typedef struct FFDisplayServerResult diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index ab2abe5e29..8522ea4772 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -1,6 +1,7 @@ #include "displayserver.h" #include "util/apple/cf_helpers.h" #include "util/stringUtils.h" +#include "util/edidHelper.h" #include #include @@ -8,9 +9,10 @@ #include #include +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)); -extern Boolean CoreDisplay_Display_IsHDRModeEnabled(CGDirectDisplayID display) __attribute__((weak_import)); #else #include #endif @@ -22,6 +24,7 @@ static void detectDisplays(FFDisplayServerResult* ds) if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess) return; + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); for(uint32_t i = 0; i < screenCount; i++) { CGDirectDisplayID screen = screens[i]; @@ -43,7 +46,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } } - FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + ffStrbufClear(&buffer); CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = NULL; #ifdef MAC_OS_X_VERSION_10_15 if(CoreDisplay_DisplayCreateInfoDictionary) @@ -54,14 +57,30 @@ static void detectDisplays(FFDisplayServerResult* ds) displayInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName); } #endif + uint32_t physicalWidth = 0, physicalHeight = 0; if(displayInfo) { CFDictionaryRef productNames; if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames)) - ffCfDictGetString(productNames, CFSTR("en_US"), &name); + ffCfDictGetString(productNames, CFSTR("en_US"), &buffer); + + // CGDisplayScreenSize reports invalid result for external displays on old Intel MacBook Pro + CFDataRef edidRef = (CFDataRef) CFDictionaryGetValue(displayInfo, CFSTR(kIODisplayEDIDKey)); + if (edidRef && CFGetTypeID(edidRef) == CFDataGetTypeID()) + { + const uint8_t* edidData = CFDataGetBytePtr(edidRef); + uint32_t edidLength = (uint32_t) CFDataGetLength(edidRef); + if (edidLength >= 128) + ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); + } } - CGSize size = CGDisplayScreenSize(screen); + if (!physicalWidth || !physicalHeight) + { + CGSize size = CGDisplayScreenSize(screen); + physicalWidth = (uint32_t) (size.width + 0.5); + physicalHeight = (uint32_t) (size.height + 0.5); + } FFDisplayResult* display = ffdsAppendDisplay(ds, (uint32_t)CGDisplayModeGetPixelWidth(mode), @@ -70,12 +89,12 @@ static void detectDisplays(FFDisplayServerResult* ds) (uint32_t)CGDisplayModeGetWidth(mode), (uint32_t)CGDisplayModeGetHeight(mode), (uint32_t)CGDisplayRotation(screen), - &name, + &buffer, CGDisplayIsBuiltin(screen) ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL, CGDisplayIsMain(screen), (uint64_t)screen, - (uint32_t) (size.width + 0.5), - (uint32_t) (size.height + 0.5) + physicalWidth, + physicalHeight ); if (display) { @@ -89,12 +108,27 @@ static void detectDisplays(FFDisplayServerResult* ds) display->bitDepth = (uint8_t) bitDepth; } - #ifdef MAC_OS_X_VERSION_10_15 - if (CoreDisplay_Display_IsHDRModeEnabled) + if (display->type == FF_DISPLAY_TYPE_BUILTIN) + display->hdrStatus = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) + ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else if (CoreDisplay_Display_SupportsHDRMode) { - display->hdrEnabled = CoreDisplay_Display_IsHDRModeEnabled(screen); + if (CoreDisplay_Display_SupportsHDRMode(screen)) + { + display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + if (CoreDisplay_Display_IsHDRModeEnabled && CoreDisplay_Display_IsHDRModeEnabled(screen)) + display->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED; + } + else + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; } - #endif + + display->serial = CGDisplaySerialNumber(screen); + int value; + if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayYearOfManufacture), &value) == NULL) + display->manufactureYear = (uint16_t) value; + if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayWeekOfManufacture), &value) == NULL) + display->manufactureWeek = (uint16_t) value; } CGDisplayModeRelease(mode); } diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 3c685e2878..11d9a5de76 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -86,6 +86,9 @@ static void detectDisplays(FFDisplayServerResult* ds) .id = path->targetInfo.id, }, }; + uint8_t edidData[1024]; + DWORD edidLength = 0; + if(DisplayConfigGetDeviceInfo(&targetName.header) == ERROR_SUCCESS) { wchar_t regPath[256] = L"SYSTEM\\CurrentControlSet\\Enum"; @@ -103,8 +106,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } wcscpy(pRegPath, L"Device Parameters"); - uint8_t edidData[1024]; - DWORD edidLength = sizeof(edidData); + edidLength = sizeof(edidData); if (RegGetValueW(HKEY_LOCAL_MACHINE, regPath, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidLength) == ERROR_SUCCESS && edidLength > 0 && edidLength % 128 == 0) { @@ -113,6 +115,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } else { + edidLength = 0; if (targetName.flags.friendlyNameFromEdid) ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName); else @@ -177,9 +180,18 @@ static void detectDisplays(FFDisplayServerResult* ds) }; if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS) { - display->hdrEnabled = !!advColorInfo.advancedColorEnabled; + if (advColorInfo.advancedColorEnabled) + display->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED; + else if (advColorInfo.advancedColorSupported) + display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; display->bitDepth = (uint8_t) advColorInfo.bitsPerColorChannel; } + else + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + if (edidLength > 0) + ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); } } } diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index de006c56b4..a841776503 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -1,6 +1,5 @@ #include "displayserver_linux.h" #include "common/io/io.h" -#include "util/edidHelper.h" #include "util/stringUtils.h" #ifdef __FreeBSD__ @@ -104,44 +103,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) } } -bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName) -{ - // https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name - // The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc." - // However I can't find a better method to get the edid data - const char* drmDirPath = "/sys/class/drm/"; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); - if(dirp == NULL) - return false; - - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - const char* plainName = entry->d_name; - if (ffStrStartsWith(plainName, "card")) - { - const char* tmp = strchr(plainName + strlen("card"), '-'); - if (tmp) plainName = tmp + 1; - } - if (ffStrEquals(plainName, connName)) - { - ffStrbufAppendF(edidName, "%s%s/edid", drmDirPath, entry->d_name); - - uint8_t edidData[128]; - if(ffReadFileData(edidName->chars, sizeof(edidData), edidData) == sizeof(edidData)) - { - ffStrbufClear(edidName); - ffEdidGetName(edidData, edidName); - return true; - } - break; - } - } - ffStrbufClear(edidName); - return false; -} - FFDisplayType ffdsGetDisplayType(const char* name) { if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-")) diff --git a/src/detection/displayserver/linux/displayserver_linux.h b/src/detection/displayserver/linux/displayserver_linux.h index 99cad927fb..b52b35b453 100644 --- a/src/detection/displayserver/linux/displayserver_linux.h +++ b/src/detection/displayserver/linux/displayserver_linux.h @@ -5,8 +5,6 @@ #include "detection/displayserver/displayserver.h" -bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName); - const char* ffdsConnectWayland(FFDisplayServerResult* result); const char* ffdsConnectXcbRandr(FFDisplayServerResult* result); diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 48949266d6..56a16d3f75 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -50,15 +50,18 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); ffStrbufAppendS(&drmDir, "/edid"); - uint8_t edidData[128]; - if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData)) + const char* plainName = entry->d_name; + if (ffStrStartsWith(plainName, "card")) { - ffEdidGetName(edidData, &name); - ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate); - ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); + const char* tmp = strchr(plainName + strlen("card"), '-'); + if (tmp) plainName = tmp + 1; } - else + + uint8_t edidData[512]; + ssize_t edidLength = ffReadFileData(drmDir.chars, sizeof(edidData), edidData); + if(edidLength <= 0 || edidLength % 128 != 0) { + edidLength = 0; ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); ffStrbufAppendS(&drmDir, "/modes"); @@ -66,29 +69,34 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) if (ffReadFileData(drmDir.chars, sizeof(modes), modes) >= 3) { sscanf(modes, "%ux%u", &width, &height); - const char* plainName = entry->d_name; - if (ffStrStartsWith(plainName, "card")) - { - const char* tmp = strchr(plainName + strlen("card"), '-'); - if (tmp) plainName = tmp + 1; - } ffStrbufAppendS(&name, plainName); } } + else + { + ffEdidGetName(edidData, &name); + ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate); + ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); + } - ffdsAppendDisplay( + FFDisplayResult* item = ffdsAppendDisplay( result, width, height, refreshRate, 0, 0, 0, &name, - FF_DISPLAY_TYPE_UNKNOWN, + ffdsGetDisplayType(plainName), false, 0, physicalWidth, physicalHeight ); + if (item && edidLength) + { + item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + } ffStrbufSubstrBefore(&drmDir, drmDirLength); } @@ -160,7 +168,7 @@ static inline const char* drmType2Name(uint32_t connector_type) } } -static const char* drmGetNameByConnId(uint32_t connId, FFstrbuf* name) +FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edidData, ssize_t* edidLength) { const char* drmDirPath = "/sys/class/drm/"; @@ -182,24 +190,22 @@ static const char* drmGetNameByConnId(uint32_t connId, FFstrbuf* name) ffStrbufAppendS(&drmDir, entry->d_name); uint32_t drmDirWithDnameLength = drmDir.length; + char connectorId[16] = {}; + ffStrbufAppendS(&drmDir, "/connector_id"); - ffReadFileBuffer(drmDir.chars, name); - if (ffStrbufToUInt(name, 0) != connId) + ffReadFileData(drmDir.chars, sizeof(connectorId), connectorId); + if (strtoul(connectorId, NULL, 10) != connId) { ffStrbufSubstrBefore(&drmDir, drmDirLength); continue; } ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); - ffStrbufClear(name); ffStrbufAppendS(&drmDir, "/edid"); - uint8_t edidData[128]; - if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData)) - ffEdidGetName(edidData, name); + *edidLength = ffReadFileData(drmDir.chars, (uint32_t) *edidLength, edidData); return NULL; } - ffStrbufClear(name); return "Failed to match connector ID"; } @@ -223,7 +229,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) drmDevice* devices[64]; int nDevices = ffdrmGetDevices(devices, sizeof(devices) / sizeof(devices[0])); - if (nDevices < 0) + if (nDevices <= 0) return "drmGetDevices() failed"; FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); @@ -237,11 +243,13 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) const char* path = dev->nodes[DRM_NODE_PRIMARY]; + #if __linux__ ffStrbufSetF(&name, "/sys/class/drm/%s/device/power/runtime_status", strrchr(path, '/') + 1); char buffer[8] = ""; if (ffReadFileData(name.chars, strlen("suspend"), buffer) > 0 && ffStrStartsWith(buffer, "suspend")) continue; + #endif FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) @@ -309,6 +317,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffStrbufClear(&name); + uint16_t myear = 0, mweak = 0; + uint32_t serial = 0; + FFDisplayHdrStatus hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; for (int iProp = 0; iProp < conn->count_props; ++iProp) { @@ -329,7 +340,11 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) if (blob) { if (blob->length >= 128) + { ffEdidGetName(blob->data, &name); + hdrStatus = ffEdidGetHdrCompatible(blob->data, blob->length) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(blob->data, &serial, &myear, &mweak); + } ffdrmModeFreePropertyBlob(blob); } break; @@ -337,10 +352,20 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffdrmModeFreeProperty(prop); } + #if __linux__ if (name.length == 0) { - drmGetNameByConnId(conn->connector_id, &name); + uint8_t edidData[512]; + ssize_t edidLength = 0; + drmGetEdidByConnId(conn->connector_id, edidData, &edidLength); + if (edidLength > 0 && edidLength % 128 == 0) + { + ffEdidGetName(edidData, &name); + hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &serial, &myear, &mweak); + } } + #endif if (name.length == 0) { @@ -350,7 +375,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn + 1); } - ffdsAppendDisplay(result, + FFDisplayResult* item = ffdsAppendDisplay(result, width, height, refreshRate, @@ -367,6 +392,14 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) conn->mmWidth, conn->mmHeight ); + + if (item) + { + item->hdrStatus = hdrStatus; + item->serial = serial; + item->manufactureYear = myear; + item->manufactureWeek = mweak; + } } ffdrmModeFreeConnector(conn); diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index a8299d16d7..20227be364 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -112,7 +112,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist uint32_t rotation = ffWaylandHandleRotation(&display); - ffdsAppendDisplay(wldata->result, + FFDisplayResult* item = ffdsAppendDisplay(wldata->result, (uint32_t) display.width, (uint32_t) display.height, display.refreshRate / 1000.0, @@ -131,6 +131,19 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist (uint32_t) display.physicalWidth, (uint32_t) display.physicalHeight ); + if (item) + { + if (display.hdrSupported) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else if (display.hdrInfoAvailable) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + + item->manufactureYear = display.myear; + item->manufactureWeek = display.mweek; + item->serial = display.serial; + } ffStrbufDestroy(&display.description); ffStrbufDestroy(&display.name); diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index fd0d4809ba..0993f72a5f 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -80,6 +80,9 @@ static void waylandKdeEdidListener(void* data, FF_MAYBE_UNUSED struct kde_output FF_STRBUF_AUTO_DESTROY edid = ffBase64DecodeStrbuf(&b64); if (edid.length < 128) return; ffEdidGetName((const uint8_t*) edid.chars, &wldata->edidName); + wldata->hdrSupported = ffEdidGetHdrCompatible((const uint8_t*) edid.chars, edid.length); + ffEdidGetSerialAndManufactureDate((const uint8_t*) edid.chars, &wldata->serial, &wldata->myear, &wldata->mweek); + wldata->hdrInfoAvailable = true; } static void waylandKdeEnabledListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, int32_t enabled) @@ -195,7 +198,18 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, ); if (item) { - item->hdrEnabled = display.hdrEnabled; + if (display.hdrEnabled) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED; + else if (display.hdrSupported) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else if (display.hdrInfoAvailable) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + + item->manufactureYear = display.myear; + item->manufactureWeek = display.mweek; + item->serial = display.serial; } ffStrbufDestroy(&display.description); diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index a0472ae742..5a67f7887f 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -1,5 +1,6 @@ #include "../displayserver_linux.h" #include "common/io/io.h" +#include "util/edidHelper.h" #include "util/stringUtils.h" #include @@ -82,6 +83,46 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u } } +static bool matchDrmConnector(const char* connName, WaylandDisplay* wldata) +{ + // https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name + // The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc." + // However I can't find a better method to get the edid data + const char* drmDirPath = "/sys/class/drm/"; + + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); + if(dirp == NULL) + return false; + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + const char* plainName = entry->d_name; + if (ffStrStartsWith(plainName, "card")) + { + const char* tmp = strchr(plainName + strlen("card"), '-'); + if (tmp) plainName = tmp + 1; + } + if (ffStrEquals(plainName, connName)) + { + 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); + if (edidLength <= 0 || edidLength % 128 != 0) + { + ffEdidGetName(edidData, &wldata->edidName); + ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); + ffEdidGetSerialAndManufactureDate(edidData, &wldata->serial, &wldata->myear, &wldata->mweek); + wldata->hdrInfoAvailable = true; + return true; + } + break; + } + } + return false; +} + void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name) { WaylandDisplay* display = data; @@ -89,7 +130,7 @@ void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const display->type = ffdsGetDisplayType(name); if (!display->edidName.length) - ffdsMatchDrmConnector(name, &display->edidName); + matchDrmConnector(name, display); display->id = ffWaylandGenerateIdFromName(name); ffStrbufAppendS(&display->name, name); } diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index df7056a7b1..3c3b64a94b 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -46,7 +46,12 @@ typedef struct WaylandDisplay FFstrbuf description; FFstrbuf edidName; uint64_t id; + bool hdrInfoAvailable; + bool hdrSupported; bool hdrEnabled; + uint16_t myear; + uint16_t mweek; + uint32_t serial; void* internal; } WaylandDisplay; diff --git a/src/detection/displayserver/linux/wayland/zwlr-output.c b/src/detection/displayserver/linux/wayland/zwlr-output.c index dd31b91b0a..7e23d593e8 100644 --- a/src/detection/displayserver/linux/wayland/zwlr-output.c +++ b/src/detection/displayserver/linux/wayland/zwlr-output.c @@ -122,7 +122,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output uint32_t rotation = ffWaylandHandleRotation(&display); - ffdsAppendDisplay(wldata->result, + FFDisplayResult* item = ffdsAppendDisplay(wldata->result, (uint32_t) display.width, (uint32_t) display.height, display.refreshRate / 1000.0, @@ -140,6 +140,19 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output (uint32_t) display.physicalWidth, (uint32_t) display.physicalHeight ); + if (item) + { + if (display.hdrSupported) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else if (display.hdrInfoAvailable) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + + item->manufactureYear = display.myear; + item->manufactureWeek = display.mweek; + item->serial = display.serial; + } ffStrbufDestroy(&display.description); ffStrbufDestroy(&display.name); diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 9d174b5ea7..b9d6c32485 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -12,6 +12,10 @@ #include #include #include +#elif defined(__OpenBSD__) + #include + #include + #include #elif defined(__sun) #include #endif @@ -252,7 +256,7 @@ static const char* getFromProcesses(FFDisplayServerResult* result) { uint32_t userId = getuid(); -#ifdef __FreeBSD__ +#if __FreeBSD__ int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_UID, (int) userId}; size_t length = 0; @@ -276,7 +280,26 @@ static const char* getFromProcesses(FFDisplayServerResult* result) if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) break; } -#elif defined(__sun) +#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); + if (proc) + { + for (int i = 0; i < count; ++i) + { + if(result->dePrettyName.length == 0) + applyPrettyNameIfDE(result, proc->p_comm); + + if(result->wmPrettyName.length == 0) + applyNameIfWM(result, proc->p_comm); + + if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) + break; + } + } + kvm_close(kd); +#elif __sun FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); if(procdir == NULL) return "opendir(\"/proc\") failed"; @@ -312,7 +335,7 @@ static const char* getFromProcesses(FFDisplayServerResult* result) break; } } -#else +#elif __linux__ FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); if(procdir == NULL) return "opendir(\"/proc\") failed"; diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 6bf82e14bc..18592a4c2e 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -180,47 +180,29 @@ typedef struct XcbRandrData xcb_randr_get_screen_resources_current_reply_t* screenResources; } XcbRandrData; -static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) -{ - double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); - - return ffdsAppendDisplay( - data->result, - (uint32_t) modeInfo->width, - (uint32_t) modeInfo->height, - refreshRate, - (uint32_t) modeInfo->width, - (uint32_t) modeInfo->height, - rotation, - name, - displayType, - primary, - 0, - (uint32_t) output->mm_width, - (uint32_t) output->mm_height - ); -} - -static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) +static double xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) - return false; + return 0; xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources); while(modesIterator.rem > 0) { if(modesIterator.data->id == mode) - return xcbRandrHandleModeInfo(data, modesIterator.data, name, rotation, primary, output, displayType); + { + xcb_randr_mode_info_t* modeInfo = modesIterator.data; + return (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); + } data->ffxcb_randr_mode_info_next(&modesIterator); } - return false; + return 0; } -static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) +static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength) { xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME); FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL); @@ -243,12 +225,12 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb rotation = 0; break; } - bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation, primary, output, displayType); - res = res ? true : !!ffdsAppendDisplay( + + FFDisplayResult* item = ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, - 0, + xcbRandrHandleMode(data, crtcInfoReply->mode), (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, rotation, @@ -259,8 +241,14 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb (uint32_t) output->mm_width, (uint32_t) output->mm_height ); + if (item && edidLength) + { + item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetPhysicalSize(edidData, &item->physicalWidth, &item->physicalHeight); + } - return res; + return !!item; } static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType) @@ -272,21 +260,27 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen("EDID"), "EDID"); FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL); + FF_AUTO_FREE xcb_randr_get_output_property_reply_t* outputPropertyReply = NULL; + uint8_t* edidData = NULL; + uint32_t edidLength = 0; if(requestAtomReply) { xcb_randr_get_output_property_cookie_t outputPropertyCookie = data->ffxcb_randr_get_output_property(data->connection, output, requestAtomReply->atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 100, false, false); - FF_AUTO_FREE xcb_randr_get_output_property_reply_t* outputPropertyReply = data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL); + outputPropertyReply = data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL); if(outputPropertyReply) { - if(data->ffxcb_randr_get_output_property_data_length(outputPropertyReply) >= 128) + int len = data->ffxcb_randr_get_output_property_data_length(outputPropertyReply); + if(len >= 128) { ffStrbufClear(name); - ffEdidGetName(data->ffxcb_randr_get_output_property_data(outputPropertyReply), name); + edidData = data->ffxcb_randr_get_output_property_data(outputPropertyReply); + ffEdidGetName(edidData, name); + edidLength = (uint32_t) len; } } } - bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType); + bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType, edidData, edidLength); return res; } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 4a6a370802..4719611959 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -153,13 +153,13 @@ static double xrandrHandleMode(XrandrData* data, RRMode mode) return 0; } -static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool primary, XRROutputInfo* output, FFDisplayType displayType) +static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) return false; - XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, crtc); + XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, output->crtc); if(crtcInfo == NULL) return false; @@ -180,7 +180,7 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool break; } - bool res = ffdsAppendDisplay( + FFDisplayResult* item = ffdsAppendDisplay( data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, @@ -196,8 +196,15 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool (uint32_t) output->mm_height ); + if (edidLength) + { + item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetPhysicalSize(edidData, &item->physicalWidth, &item->physicalHeight); + } + data->ffXRRFreeCrtcInfo(crtcInfo); - return res; + return !!item; } static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType) @@ -206,26 +213,30 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name if(outputInfo == NULL) return false; + uint8_t* edidData = NULL; + unsigned long edidLength = 0; Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true); if (atomEdid != None) { int actual_format = 0; - unsigned long nitems = 0, bytes_after = 0; + unsigned long bytes_after = 0; Atom actual_type = None; - uint8_t* edidData = NULL; - if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success) + if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &edidLength, &bytes_after, &edidData) == Success) { - if (nitems >= 128) + if (edidLength >= 128) { ffStrbufClear(name); ffEdidGetName(edidData, name); } + else + edidLength = 0; } - if (edidData) - data->ffXFree(edidData); } - bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary, outputInfo, displayType); + bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength); + + if (edidData) + data->ffXFree(edidData); data->ffXRRFreeOutputInfo(outputInfo); return res; diff --git a/src/detection/dns/dns_linux.c b/src/detection/dns/dns_linux.c index 84b2f91790..1179ea4a96 100644 --- a/src/detection/dns/dns_linux.c +++ b/src/detection/dns/dns_linux.c @@ -17,11 +17,14 @@ const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) { if (ffStrStartsWith(line, "nameserver")) { - const char* nameserver = line + strlen("nameserver"); + char* nameserver = line + strlen("nameserver"); while (*nameserver == ' ' || *nameserver == '\t') nameserver++; if (*nameserver == '\0') continue; + char* comment = strchr(nameserver, '#'); + if (comment) *comment = '\0'; + if ((ffStrContainsC(nameserver, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) || (ffStrContainsC(nameserver, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT))) continue; diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 2862f73c0a..c3678d6e60 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -625,7 +625,7 @@ FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, cons static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) { char compatible[256]; // vendor,model-name - if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%256[^C]", compatible) != 1) + if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%255[^C]", compatible) != 1) return "Failed to parse of modalias or not a GPU device"; char* name = strchr(compatible, ','); @@ -657,11 +657,19 @@ static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, co #endif if (!gpu->name.length) + { ffStrbufSetS(&gpu->name, name ? name : compatible); + ffStrbufTrimRightSpace(&gpu->name); + } if (!gpu->vendor.length && name) { - compatible[0] = (char) toupper(compatible[0]); - ffStrbufSetS(&gpu->vendor, compatible); + if (ffStrEquals(compatible, "brcm")) + ffStrbufSetStatic(&gpu->vendor, "Broadcom"); // Raspberry Pi + else + { + ffStrbufSetS(&gpu->vendor, compatible); + gpu->vendor.chars[0] = (char) toupper(compatible[0]); + } } return NULL; diff --git a/src/detection/host/host_obsd.c b/src/detection/host/host_obsd.c new file mode 100644 index 0000000000..960248ab3a --- /dev/null +++ b/src/detection/host/host_obsd.c @@ -0,0 +1,19 @@ +#include "host.h" +#include "common/sysctl.h" +#include "util/smbiosHelper.h" + +const char* ffDetectHost(FFHostResult* host) +{ + const char* error = NULL; + if ((error = ffSysctlGetString(CTL_HW, HW_PRODUCT, &host->name))) + return error; + ffCleanUpSmbiosValue(&host->name); + if (ffSysctlGetString(CTL_HW, HW_VENDOR, &host->vendor) == NULL) + ffCleanUpSmbiosValue(&host->vendor); + if (ffSysctlGetString(CTL_HW, HW_VERSION, &host->version) == NULL) + ffCleanUpSmbiosValue(&host->version); + if (ffSysctlGetString(CTL_HW, HW_SERIALNO, &host->serial) == NULL) + ffCleanUpSmbiosValue(&host->serial); + + return NULL; +} diff --git a/src/detection/loadavg/loadavg_bsd.c b/src/detection/loadavg/loadavg_bsd.c index 71c4304c13..3a0b6bca57 100644 --- a/src/detection/loadavg/loadavg_bsd.c +++ b/src/detection/loadavg/loadavg_bsd.c @@ -2,10 +2,12 @@ #include -#ifdef __FreeBSD__ +#if __FreeBSD__ || __OpenBSD__ #include #include - #include + #if __FreeBSD__ + #include + #endif #endif const char* ffDetectLoadavg(double result[3]) diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index 859d5340fa..11ac50e558 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -8,9 +8,30 @@ typedef struct FFLocalIpResult FFstrbuf ipv4; FFstrbuf ipv6; FFstrbuf mac; + FFstrbuf flags; int32_t mtu; int32_t speed; bool defaultRoute; } FFLocalIpResult; +typedef struct FFLocalIpNIFlag +{ + uint32_t flag; + const char *name; +} FFLocalIpNIFlag; + +static inline void ffLocalIpFillNIFlags(FFstrbuf *buf, uint32_t flag, const FFLocalIpNIFlag names[]) +{ + for (const FFLocalIpNIFlag *nf = names; flag && nf->name; ++nf) + { + if (flag & nf->flag) + { + if (buf->length > 0) + ffStrbufAppendC(buf, ','); + ffStrbufAppendS(buf, nf->name); + flag &= ~nf->flag; + } + } +} + const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results); diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 9dd8aaeacd..243091ddfb 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -15,9 +15,10 @@ #ifdef __linux__ #include #include +#include #endif -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #include #include #else @@ -27,7 +28,48 @@ #include #endif -static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, bool firstOnly) +static const FFLocalIpNIFlag niFlagOptions[] = { + { IFF_UP, "UP" }, + { IFF_BROADCAST, "BROADCAST" }, + { IFF_DEBUG, "DEBUG" }, + { IFF_LOOPBACK, "LOOPBACK" }, + { IFF_POINTOPOINT, "POINTOPOINT" }, + { IFF_RUNNING, "RUNNING" }, + { IFF_NOARP, "NOARP" }, + { IFF_PROMISC, "PROMISC" }, + { IFF_ALLMULTI, "ALLMULTI" }, + { IFF_MULTICAST, "MULTICAST" }, +#if defined(__linux__) || defined(__APPLE__) || defined(__sun) + { IFF_NOTRAILERS, "NOTRAILERS" }, +#endif +#ifdef __linux__ + { IFF_MASTER, "MASTER" }, + { IFF_SLAVE, "SLAVE" }, + { IFF_PORTSEL, "PORTSEL" }, + { IFF_AUTOMEDIA, "AUTOMEDIA" }, + { IFF_DYNAMIC, "DYNAMIC" }, + { IFF_LOWER_UP, "LOWER_UP" }, + { IFF_DORMANT, "DORMANT" }, + { IFF_ECHO, "ECHO" }, +#endif +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) + { IFF_OACTIVE, "OACTIVE" }, + { IFF_SIMPLEX, "SIMPLEX" }, + { IFF_LINK0, "LINK0" }, + { IFF_LINK1, "LINK1" }, + { IFF_LINK2, "LINK2" }, +#endif +#if defined(__FreeBSD__) || defined(__APPLE__) + { IFF_ALTPHYS, "ALTPHYS" }, +#endif +#ifdef __FreeBSD__ + { IFF_CANTCONFIG, "CANTCONFIG" }, +#endif + // sentinel + {}, +}; + +static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, uint32_t flags, bool firstOnly) { FFLocalIpResult* ip = NULL; @@ -44,9 +86,12 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, ffStrbufInit(&ip->ipv4); ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); + ffStrbufInit(&ip->flags); ip->defaultRoute = defaultRoute; ip->mtu = -1; ip->speed = -1; + + ffLocalIpFillNIFlags(&ip->flags, flags, niFlagOptions); } switch (type) @@ -96,6 +141,8 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (options->namePrefix.length && strncmp(ifa->ifa_name, options->namePrefix.chars, options->namePrefix.length) != 0) continue; + uint32_t flags = options->showType & FF_LOCALIP_TYPE_FLAGS_BIT ? ifa->ifa_flags : 0; + if (ifa->ifa_addr->sa_family == AF_INET) { if (!(options->showType & FF_LOCALIP_TYPE_IPV4_BIT)) @@ -116,7 +163,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } else if (ifa->ifa_addr->sa_family == AF_INET6) { @@ -141,9 +188,9 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } - #if defined(__FreeBSD__) || defined(__APPLE__) + #if __FreeBSD__ || __OpenBSD__ || __APPLE__ else if (ifa->ifa_addr->sa_family == AF_LINK) { if (!(options->showType & FF_LOCALIP_TYPE_MAC_BIT)) @@ -153,7 +200,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr); snprintf(addressBuffer, sizeof(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, false); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); } #else else if (ifa->ifa_addr->sa_family == AF_PACKET) @@ -165,7 +212,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr; snprintf(addressBuffer, sizeof(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, false); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); } #endif } @@ -199,7 +246,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) ifr.ifr_data = (void*) &edata; if (ioctl(sockfd, SIOCETHTOOL, &ifr) == 0) iface->speed = (edata.speed_hi << 16) | edata.speed; // ethtool_cmd_speed is not available on Android - #elif __FreeBSD__ || __APPLE__ + #elif __FreeBSD__ || __APPLE__ || __OpenBSD__ struct ifmediareq ifmr = {}; strncpy(ifmr.ifm_name, iface->name.chars, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFMEDIA, &ifmr) == 0 && (IFM_TYPE(ifmr.ifm_active) & IFM_ETHER)) diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index a24d38591b..00fee43ed0 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -6,6 +6,21 @@ #include "util/windows/unicode.h" #include "localip.h" +static const FFLocalIpNIFlag niFlagOptions[] = { + { IP_ADAPTER_DDNS_ENABLED, "DDNS_ENABLED" }, + { IP_ADAPTER_REGISTER_ADAPTER_SUFFIX, "REGISTER_ADAPTER_SUFFIX" }, + { IP_ADAPTER_DHCP_ENABLED, "DHCP_ENABLED" }, + { IP_ADAPTER_RECEIVE_ONLY, "RECEIVE_ONLY" }, + { IP_ADAPTER_NO_MULTICAST, "NO_MULTICAST" }, + { IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG, "IPV6_OTHER_STATEFUL_CONFIG" }, + { IP_ADAPTER_NETBIOS_OVER_TCPIP_ENABLED, "NETBIOS_OVER_TCPIP_ENABLED" }, + { IP_ADAPTER_IPV4_ENABLED, "IPV4_ENABLED" }, + { IP_ADAPTER_IPV6_ENABLED, "IPV6_ENABLED" }, + { IP_ADAPTER_IPV6_MANAGE_ADDRESS_CONFIG, "IPV6_MANAGE_ADDRESS_CONFIG" }, + // sentinel + {}, +}; + static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool newIp, bool defaultRoute) { FFLocalIpResult* ip = NULL; @@ -17,6 +32,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, ffStrbufInit(&ip->ipv4); ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); + ffStrbufInit(&ip->flags); ip->defaultRoute = defaultRoute; ip->speed = -1; ip->mtu = -1; @@ -113,13 +129,13 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (!(typesToAdd & (FF_LOCALIP_TYPE_IPV4_BIT | FF_LOCALIP_TYPE_ALL_IPS_BIT))) continue; SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr; - char addressBuffer[INET_ADDRSTRLEN + 4]; + char addressBuffer[INET_ADDRSTRLEN + 6]; inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN); if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength) { size_t len = strlen(addressBuffer); - snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength); + snprintf(addressBuffer + len, 6, "/%u", (unsigned) ifa->OnLinkPrefixLength); } addNewIp(results, name, addressBuffer, AF_INET, newIp, isDefaultRoute); @@ -133,13 +149,13 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (!(typesToAdd & (FF_LOCALIP_TYPE_IPV6_BIT | FF_LOCALIP_TYPE_ALL_IPS_BIT))) continue; SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr; - char addressBuffer[INET6_ADDRSTRLEN + 4]; + char addressBuffer[INET6_ADDRSTRLEN + 6]; inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN); if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength) { size_t len = strlen(addressBuffer); - snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength); + snprintf(addressBuffer + len, 6, "/%u", (unsigned) ifa->OnLinkPrefixLength); } addNewIp(results, name, addressBuffer, AF_INET6, newIp, isDefaultRoute); @@ -157,6 +173,8 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) result->speed = (int32_t) (adapter->ReceiveLinkSpeed / 1000); if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) result->mtu = (int32_t) adapter->Mtu; + if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) + ffLocalIpFillNIFlags(&result->flags, adapter->Flags, niFlagOptions); } } diff --git a/src/detection/memory/memory_obsd.c b/src/detection/memory/memory_obsd.c new file mode 100644 index 0000000000..c4119efb3f --- /dev/null +++ b/src/detection/memory/memory_obsd.c @@ -0,0 +1,20 @@ +#include "memory.h" +#include "common/sysctl.h" + +#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 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; + + return NULL; +} diff --git a/src/detection/monitor/monitor.h b/src/detection/monitor/monitor.h deleted file mode 100644 index 4066f1178d..0000000000 --- a/src/detection/monitor/monitor.h +++ /dev/null @@ -1,17 +0,0 @@ -#include "fastfetch.h" - -typedef struct FFMonitorResult -{ - FFstrbuf name; - uint32_t width; // native / maximum resolution, in pixels - uint32_t height; // native / maximum resolution, in pixels - double refreshRate;// maximum refresh rate in native resolution, in Hz - uint32_t physicalWidth; // in mm - uint32_t physicalHeight; // in mm - bool hdrCompatible; - uint16_t manufactureYear; - uint16_t manufactureWeek; - uint32_t serial; -} FFMonitorResult; - -const char* ffDetectMonitor(FFlist* results); diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m deleted file mode 100644 index 04163bc7cb..0000000000 --- a/src/detection/monitor/monitor_apple.m +++ /dev/null @@ -1,125 +0,0 @@ -#include "monitor.h" -#include "detection/displayserver/displayserver.h" -#include "util/apple/cf_helpers.h" -#include "util/edidHelper.h" - -#import -#import -#import - -#ifdef MAC_OS_X_VERSION_10_15 -extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); -#else -#include -#endif - -static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) -{ - NSScreen* mainScreen = NSScreen.mainScreen; - if (display->primary) - { - #ifdef MAC_OS_X_VERSION_10_15 - return mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; - #else - return mainScreen.maximumExtendedDynamicRangeColorComponentValue > 1; - #endif - } - else - { - for (NSScreen* screen in NSScreen.screens) - { - if (screen == mainScreen) continue; - NSNumber* screenNumber = screen.deviceDescription[@"NSScreenNumber"]; - if (screenNumber && screenNumber.longValue == (long) display->id) - { - #ifdef MAC_OS_X_VERSION_10_15 - return screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; - #else - return screen.maximumExtendedDynamicRangeColorComponentValue > 1; - #endif - } - } - } - return false; -} - -const char* ffDetectMonitor(FFlist* results) -{ - #ifdef MAC_OS_X_VERSION_10_15 - if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available"; - #endif - const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); - - FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) - { - #ifdef MAC_OS_X_VERSION_10_15 - CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id); - #else - io_service_t servicePort = CGDisplayIOServicePort((CGDirectDisplayID) display->id); - CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName); - #endif - if(!displayInfo) continue; - - bool isVirtual = false; - if (ffCfDictGetBool(displayInfo, CFSTR("kCGDisplayIsVirtualDevice"), &isVirtual) == NULL && isVirtual) - continue; - - uint8_t edidData[128] = {}; - uint32_t edidLength = 0; - if (ffCfDictGetData(displayInfo, CFSTR(kIODisplayEDIDKey), 0, sizeof(edidData), edidData, &edidLength) == NULL) - { - uint32_t width, height; - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width > 0 && height > 0) - { - FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); - ffStrbufInitCopy(&monitor->name, &display->name); - monitor->width = width; - monitor->height = height; - ffEdidGetPhysicalSize(edidData, &monitor->physicalWidth, &monitor->physicalHeight); - monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || - detectHdrSupportWithNSScreen(display); - continue; - } - } - - int width, height; - if (ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), &width) || // Default resolution (limited by connectors, GPUs, etc.) - ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), &height) || - width <= 0 || height <= 0) - continue; - - FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); - monitor->width = (uint32_t) width; - monitor->height = (uint32_t) height; - ffStrbufInitCopy(&monitor->name, &display->name); - - CGSize size = CGDisplayScreenSize((CGDirectDisplayID) display->id); - monitor->physicalWidth = (uint32_t) (size.width + 0.5); - monitor->physicalHeight = (uint32_t) (size.height + 0.5); - monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || - detectHdrSupportWithNSScreen(display); - monitor->serial = CGDisplaySerialNumber((CGDirectDisplayID) display->id); - - FF_CFTYPE_AUTO_RELEASE CFArrayRef modes = CGDisplayCopyAllDisplayModes((CGDirectDisplayID) display->id, NULL); - double maxRefreshRate = 0; - for (uint32_t j = 0; j < CFArrayGetCount(modes); ++j) - { - CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, j); - if (CGDisplayModeGetWidth(mode) == (uint32_t) width && CGDisplayModeGetHeight(mode) == (uint32_t) height) - { - double refreshRate = CGDisplayModeGetRefreshRate(mode); - if (refreshRate > maxRefreshRate) maxRefreshRate = refreshRate; - } - } - monitor->refreshRate = maxRefreshRate; - - int64_t year, week; - if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayYearManufacture"), &year) == NULL) - monitor->manufactureYear = (uint16_t) year; - if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayWeekManufacture"), &week) == NULL) - monitor->manufactureWeek = (uint16_t) week; - } - - return NULL; -} diff --git a/src/detection/monitor/monitor_linux.c b/src/detection/monitor/monitor_linux.c deleted file mode 100644 index 48d52d0b0b..0000000000 --- a/src/detection/monitor/monitor_linux.c +++ /dev/null @@ -1,254 +0,0 @@ -#include "monitor.h" - -#include "common/io/io.h" -#include "common/library.h" -#include "util/edidHelper.h" -#include "util/stringUtils.h" - -#ifdef FF_HAVE_XRANDR - -#include -#include - -typedef struct XrandrData -{ - FF_LIBRARY_SYMBOL(XInternAtom) - FF_LIBRARY_SYMBOL(XGetAtomName); - FF_LIBRARY_SYMBOL(XFree); - FF_LIBRARY_SYMBOL(XRRGetMonitors) - FF_LIBRARY_SYMBOL(XRRGetOutputInfo) - FF_LIBRARY_SYMBOL(XRRGetOutputProperty) - FF_LIBRARY_SYMBOL(XRRFreeOutputInfo) - FF_LIBRARY_SYMBOL(XRRFreeMonitors) - - //Init once - Display* display; - - //Init per screen - XRRScreenResources* screenResources; -} XrandrData; - -static const char* xrandrHandleMonitors(XrandrData* data, Screen* screen, FFlist* results) -{ - int numberOfMonitors; - XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, RootWindowOfScreen(screen), True, &numberOfMonitors); - if(monitorInfos == NULL) - return "XRRGetMonitors() failed"; - - for(int i = 0; i < numberOfMonitors; i++) - { - XRRMonitorInfo* monitorInfo = &monitorInfos[i]; - for(int i = 0; i < monitorInfo->noutput; i++) - { - RROutput output = monitorInfo->outputs[i]; - XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output); - if(outputInfo == NULL) - continue; - - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - ffStrbufInit(&display->name); - display->width = 0; - display->height = 0; - display->manufactureYear = 0; - display->manufactureWeek = 0; - display->serial = 0; - display->hdrCompatible = false; - display->refreshRate = 0; - - bool edidOk = false; - Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true); - if (atomEdid != None) - { - int actual_format = 0; - unsigned long nitems = 0, bytes_after = 0; - Atom actual_type = None; - uint8_t* edidData = NULL; - if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success) - { - if (nitems > 0 && nitems % 128 == 0) - { - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalResolution(edidData, &display->width, &display->height); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) nitems); - edidOk = true; - } - } - if (edidData) - data->ffXFree(edidData); - } - - if (!edidOk) - { - ffStrbufSetS(&display->name, data->ffXGetAtomName(data->display, monitorInfo->name)); - display->physicalWidth = (uint32_t) monitorInfo->mwidth; - display->physicalHeight = (uint32_t) monitorInfo->mheight; - display->width = (uint32_t) monitorInfo->width; - display->height = (uint32_t) monitorInfo->height; - } - - for(int i = 0; i < data->screenResources->nmode; i++) - { - bool found = false; - for (int j = 0; j < outputInfo->nmode; ++j) - { - if (data->screenResources->modes[i].id == outputInfo->modes[j]) - { - found = true; - break; - } - } - - if(found) - { - XRRModeInfo* modeInfo = &data->screenResources->modes[i]; - double refreshRate = (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); - if (edidOk) - { - if (display->width != modeInfo->width || display->height != modeInfo->height) - continue; - } - else - { - if (display->width < modeInfo->width || display->height < modeInfo->height) - { - display->width = (uint32_t) modeInfo->width; - display->height = (uint32_t) modeInfo->height; - display->refreshRate = refreshRate; - continue; - } - else if (display->width != modeInfo->width || display->height != modeInfo->height) - continue; - } - if (display->refreshRate < refreshRate) - display->refreshRate = refreshRate; - } - } - data->ffXRRFreeOutputInfo(outputInfo); - } - } - - data->ffXRRFreeMonitors(monitorInfos); - return NULL; -} - -static const char* detectByXrandr(FFlist* results) -{ - FF_LIBRARY_LOAD(xrandr, "dlopen libXrandr" FF_LIBRARY_EXTENSION " failed", "libXrandr" FF_LIBRARY_EXTENSION, 3) - - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XOpenDisplay) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XCloseDisplay) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XRRGetScreenResourcesCurrent); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XRRFreeScreenResources); - - XrandrData data; - - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XInternAtom); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XGetAtomName); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XFree); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetMonitors); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetOutputInfo); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetOutputProperty); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeOutputInfo); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeMonitors); - - data.display = ffXOpenDisplay(NULL); - if(data.display == NULL) - return "XOpenDisplay() failed"; - - for(int i = 0; i < ScreenCount(data.display); i++) - { - Screen* screen = ScreenOfDisplay(data.display, i); - data.screenResources = ffXRRGetScreenResourcesCurrent(data.display, RootWindowOfScreen(screen)); - xrandrHandleMonitors(&data, screen, results); - ffXRRFreeScreenResources(data.screenResources); - } - - ffXCloseDisplay(data.display); - - return NULL; -} -#endif // FF_HAVE_XRANDR - -#ifdef __linux__ -FF_MAYBE_UNUSED static const char* detectByDrm(FFlist* results) -{ - const char* drmDirPath = "/sys/class/drm/"; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); - if(dirp == NULL) - return "opendir(drmDirPath) == NULL"; - - FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64); - ffStrbufAppendS(&drmDir, drmDirPath); - - uint32_t drmDirLength = drmDir.length; - - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) - continue; - - ffStrbufAppendS(&drmDir, entry->d_name); - uint32_t drmDirWithDnameLength = drmDir.length; - - ffStrbufAppendS(&drmDir, "/status"); - char status = 'd'; // disconnected - ffReadFileData(drmDir.chars, sizeof(status), &status); - if (status != 'c') // connected - { - ffStrbufSubstrBefore(&drmDir, drmDirLength); - continue; - } - - ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); - ffStrbufAppendS(&drmDir, "/edid"); - - uint8_t edidData[512]; - ssize_t edidLength = ffReadFileData(drmDir.chars, sizeof(edidData), edidData); - if(edidLength <= 0 || edidLength % 128 != 0) - { - ffStrbufSubstrBefore(&drmDir, drmDirLength); - continue; - } - - uint32_t width, height; - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width != 0 && height != 0) - { - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - display->width = width; - display->height = height; - ffStrbufInit(&display->name); - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); - display->refreshRate = 0; - } - - ffStrbufSubstrBefore(&drmDir, drmDirLength); - } - - return NULL; -} -#endif // __linux__ - -const char* ffDetectMonitor(FFlist* results) -{ - const char* error = NULL; - - #if defined(__linux__) - error = detectByDrm(results); - if (!error && results->length > 0) return NULL; - #endif - - #ifdef FF_HAVE_XRANDR - error = detectByXrandr(results); - if (!error) return NULL; - #endif - - return "Fastfetch was compiled without xrandr support"; -} diff --git a/src/detection/monitor/monitor_nosupport.c b/src/detection/monitor/monitor_nosupport.c deleted file mode 100644 index c5bd0547a9..0000000000 --- a/src/detection/monitor/monitor_nosupport.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "monitor.h" - -const char* ffDetectMonitor(FF_MAYBE_UNUSED FFlist* results) -{ - return "Not supported on this platform"; -} diff --git a/src/detection/monitor/monitor_windows.c b/src/detection/monitor/monitor_windows.c deleted file mode 100644 index 4d9ebed2b6..0000000000 --- a/src/detection/monitor/monitor_windows.c +++ /dev/null @@ -1,116 +0,0 @@ -#include "monitor.h" - -#include "util/edidHelper.h" -#include "util/windows/registry.h" - -#include - -const char* ffDetectMonitor(FFlist* results) -{ - DISPLAYCONFIG_PATH_INFO paths[128]; - uint32_t pathCount = sizeof(paths) / sizeof(paths[0]); - DISPLAYCONFIG_MODE_INFO modes[256]; - uint32_t modeCount = sizeof(modes) / sizeof(modes[0]); - - if (QueryDisplayConfig( - QDC_ONLY_ACTIVE_PATHS, - &pathCount, - paths, - &modeCount, - modes, - NULL) != ERROR_SUCCESS) - return "QueryDisplayConfig() failed"; - - if (pathCount == 0) - return "QueryDisplayConfig() returns 0 paths"; - - for (uint32_t i = 0; i < pathCount; ++i) - { - DISPLAYCONFIG_PATH_INFO* path = &paths[i]; - - DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = { - .header = { - .type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME, - .size = sizeof(targetName), - .adapterId = path->targetInfo.adapterId, - .id = path->targetInfo.id, - }, - }; - if (DisplayConfigGetDeviceInfo(&targetName.header) != ERROR_SUCCESS) - continue; - - wchar_t regPath[256] = L"SYSTEM\\CurrentControlSet\\Enum"; - wchar_t* pRegPath = regPath + strlen("SYSTEM\\CurrentControlSet\\Enum"); - wchar_t* pDevPath = targetName.monitorDevicePath + strlen("\\\\?"); - while (*pDevPath && *pDevPath != L'{') - { - if (*pDevPath == L'#') - *pRegPath = L'\\'; - else - *pRegPath = *pDevPath; - ++pRegPath; - ++pDevPath; - assert(pRegPath < regPath + sizeof(regPath) / sizeof(wchar_t) + strlen("Device Parameters")); - } - wcscpy(pRegPath, L"Device Parameters"); - - uint8_t edidData[1024]; - DWORD edidLength = sizeof(edidData); - - if (RegGetValueW(HKEY_LOCAL_MACHINE, regPath, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidLength) == ERROR_SUCCESS && - edidLength > 0 && edidLength % 128 == 0) - { - uint32_t width, height; - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width == 0 || height == 0) continue; - - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - display->width = width; - display->height = height; - ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - ffStrbufInit(&display->name); - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - display->refreshRate = 0; - display->hdrCompatible = false; - - DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = { - .header = { - .type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO, - .size = sizeof(advColorInfo), - .adapterId = path->targetInfo.adapterId, - .id = path->targetInfo.id, - } - }; - if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS) - display->hdrCompatible = !!advColorInfo.advancedColorSupported; - else - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); - - DISPLAYCONFIG_TARGET_PREFERRED_MODE preferredMode = { - .header = { - .type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE, - .size = sizeof(preferredMode), - .adapterId = path->targetInfo.adapterId, - .id = path->targetInfo.id, - } - }; - if (DisplayConfigGetDeviceInfo(&preferredMode.header) == ERROR_SUCCESS) - { - if (preferredMode.width == width && preferredMode.height == height) - { - DISPLAYCONFIG_RATIONAL freq = preferredMode.targetMode.targetVideoSignalInfo.vSyncFreq; - display->refreshRate = freq.Numerator / (double) freq.Denominator; - } - } - - DISPLAYCONFIG_VIDEO_SIGNAL_INFO current = modes[path->targetInfo.modeInfoIdx].targetMode.targetVideoSignalInfo; - if (current.activeSize.cx == width && current.activeSize.cy == height) - { - double refreshRate = current.vSyncFreq.Numerator / (double) current.vSyncFreq.Denominator; - if (refreshRate > display->refreshRate) display->refreshRate = refreshRate; - } - } - } - return NULL; -} diff --git a/src/detection/opengl/opengl_linux.c b/src/detection/opengl/opengl_linux.c index 051107bece..05a72bf25c 100644 --- a/src/detection/opengl/opengl_linux.c +++ b/src/detection/opengl/opengl_linux.c @@ -14,7 +14,6 @@ void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglG #endif // FF_HAVE_GL - #ifdef FF_HAVE_GLX #include @@ -25,7 +24,7 @@ typedef struct GLXData FF_LIBRARY_SYMBOL(glXQueryVersion) FF_LIBRARY_SYMBOL(XOpenDisplay) FF_LIBRARY_SYMBOL(glXChooseVisual) - FF_LIBRARY_SYMBOL(XCreatePixmap); + FF_LIBRARY_SYMBOL(XCreatePixmap) FF_LIBRARY_SYMBOL(glXCreateGLXPixmap) FF_LIBRARY_SYMBOL(glXCreateContext) FF_LIBRARY_SYMBOL(glXMakeCurrent) @@ -120,7 +119,13 @@ static const char* detectByGlx(FFOpenGLResult* result) { GLXData data; - FF_LIBRARY_LOAD(glx, "dlopen glx failed", "libGLX" FF_LIBRARY_EXTENSION, 1); + FF_LIBRARY_LOAD(glx, "dlopen glx failed", + #if !__OpenBSD__ + "libGLX" + #else + "libGL" + #endif + FF_LIBRARY_EXTENSION, 1); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXQueryVersion); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay); diff --git a/src/detection/os/os_obsd.c b/src/detection/os/os_obsd.c new file mode 100644 index 0000000000..10a0bfd812 --- /dev/null +++ b/src/detection/os/os_obsd.c @@ -0,0 +1,7 @@ +#include "os.h" + +void ffDetectOSImpl(FFOSResult* os) +{ + ffStrbufSetStatic(&os->name, "OpenBSD"); + ffStrbufSet(&os->version, &instance.state.platform.sysinfo.release); +} diff --git a/src/detection/packages/packages_bsd.c b/src/detection/packages/packages_bsd.c index 8212229270..511af569b1 100644 --- a/src/detection/packages/packages_bsd.c +++ b/src/detection/packages/packages_bsd.c @@ -18,7 +18,7 @@ static uint32_t getSQLite3Int(const char* dbPath, const char* query, const char* return num_elements; } -void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options) +void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) { if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT)) { diff --git a/src/detection/packages/packages_obsd.c b/src/detection/packages/packages_obsd.c new file mode 100644 index 0000000000..c7fadcbdff --- /dev/null +++ b/src/detection/packages/packages_obsd.c @@ -0,0 +1,31 @@ +#include "packages.h" + +#include "common/io/io.h" + +static uint32_t getNumElementsImpl(const char* dirname, unsigned char type) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(dirname); + if(dirp == NULL) + return 0; + + uint32_t num_elements = 0; + + struct dirent *entry; + while((entry = readdir(dirp)) != NULL) { + if(entry->d_type == type) + ++num_elements; + } + + if(type == DT_DIR && num_elements >= 2) + num_elements -= 2; // accounting for . and .. + + return num_elements; +} + +void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) +{ + if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT)) + { + result->pkg = getNumElementsImpl(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg", DT_DIR); + } +} diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c new file mode 100644 index 0000000000..75db1c4d09 --- /dev/null +++ b/src/detection/processes/processes_obsd.c @@ -0,0 +1,14 @@ +#include "processes.h" + +#include +#include +#include + +const char* ffDetectProcesses(uint32_t* result) +{ + kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + const void* ret = kvm_getprocs(kd, KERN_PROC_ALL, 0, 1, result); + kvm_close(kd); + if (!ret) return "kvm_getprocs() failed"; + return NULL; +} diff --git a/src/detection/swap/swap_obsd.c b/src/detection/swap/swap_obsd.c new file mode 100644 index 0000000000..b64900c9fa --- /dev/null +++ b/src/detection/swap/swap_obsd.c @@ -0,0 +1,30 @@ +#include "swap.h" +#include "util/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffDetectSwap(FFSwapResult* swap) +{ + int nswap = swapctl(SWAP_NSWAP, 0, 0); + if (nswap < 0) return "swapctl(SWAP_NSWAP) failed"; + if (nswap == 0) NULL; + + struct swapent* swdev = malloc((uint32_t) nswap * sizeof(*swdev)); + + if (swapctl(SWAP_STATS, swdev, nswap) < 0) + return "swapctl(SWAP_STATS) failed"; + + for (int i = 0; i < nswap; i++) + { + if (swdev[i].se_flags & SWF_ENABLE) + { + swap->bytesUsed += (uint64_t) swdev[i].se_inuse * DEV_BSIZE; + swap->bytesTotal += (uint64_t) swdev[i].se_nblks * DEV_BSIZE; + } + } + + return NULL; +} diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index e992f78929..c933937bf9 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -82,7 +82,7 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul if (ffGetTerminalResponse( "\eP+q6b697474792d71756572792d666f6e745f66616d696c79;6b697474792d71756572792d666f6e745f73697a65\e\\", // kitty-query-font_family;kitty-query-font_size 2, - "\eP1+r%*[^=]=%512[^\e]\e\\\eP1+r%*[^=]=%512[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) + "\eP1+r%*[^=]=%511[^\e]\e\\\eP1+r%*[^=]=%511[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) { // decode hex string for (const char* p = fontHex; p[0] && p[1]; p += 2) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 4280f20df2..45e4bb75f9 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -8,6 +8,8 @@ #include #ifdef __FreeBSD__ #include +#elif __OpenBSD__ + #define _PATH_LOCALBASE "/usr/local" #endif #ifdef _WIN32 @@ -119,6 +121,19 @@ static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version) static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version) { +#if __OpenBSD__ + if(ffProcessAppendStdOut(version, (char* const[]) { + exe->chars, + "-c", + "echo $KSH_VERSION", + NULL + }) != NULL) + return false; + + // @(#)PD KSH v5.2.14 99/07/13.2 + ffStrbufSubstrAfterFirstC(version, 'v'); + ffStrbufSubstrBeforeFirstC(version, ' '); +#else if(ffProcessAppendStdErr(version, (char* const[]) { exe->chars, "--version", @@ -129,6 +144,7 @@ static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version) // version sh (AT&T Research) 93u+ 2012-08-01 ffStrbufSubstrAfterLastC(version, ')'); ffStrbufTrim(version, ' '); +#endif return true; } @@ -559,7 +575,7 @@ static bool getTerminalVersionZed(FFstrbuf* exe, FFstrbuf* version) #ifndef _WIN32 static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { - #if defined(__linux__) || defined(__FreeBSD__) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) char buffer[1024] = {}; if ( #ifdef __linux__ @@ -662,7 +678,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe #endif - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal")) return getTerminalVersionGnome(exe, version); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 0355e25636..c29d97742d 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -161,23 +161,30 @@ static bool getTerminalInfoByPidEnv(FFTerminalResult* result, const char* pidEnv static void getTerminalFromEnv(FFTerminalResult* result) { - if( - result->processName.length > 0 && - !ffStrbufStartsWithS(&result->processName, "login") && - !ffStrbufEqualS(&result->processName, "(login)") && + if (result->processName.length > 0) + { + if (!ffStrbufStartsWithS(&result->processName, "login") && + !ffStrbufEqualS(&result->processName, "(login)") && + + #ifdef __APPLE__ + !ffStrbufEqualS(&result->processName, "launchd") && + !ffStrbufEqualS(&result->processName, "stable") && //for WarpTerminal + #else + !ffStrbufEqualS(&result->processName, "systemd") && + !ffStrbufEqualS(&result->processName, "init") && + !ffStrbufEqualS(&result->processName, "(init)") && + !ffStrbufEqualS(&result->processName, "SessionLeader") && // #750 + #endif - #ifdef __APPLE__ - !ffStrbufEqualS(&result->processName, "launchd") && - !ffStrbufEqualS(&result->processName, "stable") && //for WarpTerminal - #else - !ffStrbufEqualS(&result->processName, "systemd") && - !ffStrbufEqualS(&result->processName, "init") && - !ffStrbufEqualS(&result->processName, "(init)") && - !ffStrbufEqualS(&result->processName, "SessionLeader") && // #750 - #endif + !ffStrbufEqualS(&result->processName, "0") + ) return; - !ffStrbufEqualS(&result->processName, "0") - ) return; + ffStrbufClear(&result->processName); + ffStrbufClear(&result->exe); + result->exeName = result->exe.chars; + ffStrbufClear(&result->exePath); + result->pid = result->ppid = 0; + } const char* term = NULL; diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c index a63a93f5f2..7a77eb3a78 100644 --- a/src/detection/tpm/tpm_windows.c +++ b/src/detection/tpm/tpm_windows.c @@ -3,10 +3,9 @@ // #include -#define TBS_SUCCESS 0u -#define TBS_E_INTERNAL_ERROR 0x80284001u -#define TBS_E_INVALID_CONTEXT 0x80284004u 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 @@ -42,7 +41,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_RESULT) TBS_E_INVALID_CONTEXT ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; + return code == TBS_E_TPM_NOT_FOUND ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; switch (deviceInfo.tpmVersion) { diff --git a/src/detection/users/users_nosupport.c b/src/detection/users/users_nosupport.c new file mode 100644 index 0000000000..d7893ba463 --- /dev/null +++ b/src/detection/users/users_nosupport.c @@ -0,0 +1,7 @@ +#include "fastfetch.h" +#include "users.h" + +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/version/version.c b/src/detection/version/version.c index fe87e2e778..6e89c3b660 100644 --- a/src/detection/version/version.c +++ b/src/detection/version/version.c @@ -22,8 +22,9 @@ #define FF_ARCHITECTURE "unknown" #endif - -#if defined(__linux__) +#if defined(__ANDROID__) + #define FF_SYSNAME "Android" +#elif defined(__linux__) #define FF_SYSNAME "Linux" #elif defined(__FreeBSD__) #define FF_SYSNAME "FreeBSD" @@ -33,6 +34,8 @@ #define FF_SYSNAME "WIN32" #elif defined(__sun) #define FF_SYSNAME "SunOS" +#elif defined(__OpenBSD__) + #define FF_SYSNAME "OpenBSD" #else #define FF_SYSNAME "unknown" #endif diff --git a/src/logo/ascii/center.txt b/src/logo/ascii/center.txt index a4c365d0bb..58d64f79a7 100644 --- a/src/logo/ascii/center.txt +++ b/src/logo/ascii/center.txt @@ -1,13 +1,13 @@ - . - o, - . d, . - ';' ..d;.. .cl' - .:; 'oldO,.oo. - ..,:,xKXxoo;'. - ,;;;;;ldxkONMMMXxkxc;;;;;. - .....':oddXWMNOxlcl:...... - .:dlxk0c;:. . - :d:.,xcld,.,:. - ;l, .l; ';' - .o; - l, \ No newline at end of file + . + o, + . d, . + ';' ..d;.. .cl' + .:; 'oldO,.oo. + ..,:,xKXxoo;'. +,;;;;;ldxkONMMMXxkxc;;;;;. +.....':oddXWMNOxlcl:...... + .:dlxk0c;:. . + :d:.,xcld,.,:. + ;l, .l; ';' + .o; + l, \ No newline at end of file diff --git a/src/logo/ascii/cyberos.txt b/src/logo/ascii/cyberos.txt index c47301fd3a..0dea1b5331 100644 --- a/src/logo/ascii/cyberos.txt +++ b/src/logo/ascii/cyberos.txt @@ -1,15 +1,15 @@ -${c3} !M$EEEEEEEEEEEP - .MMMMM000000Nr. - ${c3}&MMMMMM${c2}MMMMMMMMMMMMM9 - ${c3}~MMM${c1}MMMM${c2}MMMMMMMMMMMMC - ${c1}" ${c3}M${c1}MMMMMMM${c2}MMMMMMMMMMs - ${c1}iM${c2}MMM&&${c1}MMMMMMMM${c2}MMMMMMMM\\ - ${c1}BMMM${c2}MMMMM${c1}MMMMMMM${c2}MMMMMM${c3}" - ${c1}9MMMMM${c2}MMMMMMM${c1}MMMM${c2}MMMM${c3}MMMf- - ${c2}sMMMMMMMM${c1}MM${c2}M${c3}MMMMMMMMM3_ - ${c2}+ffffffff${c1}P${c3}MMMMMMMMMMMM0 - ${c2}CMMMMMMMMMMM - }MMMMMMMMM - ~MMMMMMM - "RMMMM - .PMB \ No newline at end of file +${c3} !M$EEEEEEEEEEEP + .MMMMM000000Nr. + ${c3}&MMMMMM${c2}MMMMMMMMMMMMM9 + ${c3}~MMM${c1}MMMM${c2}MMMMMMMMMMMMC + ${c1}" ${c3}M${c1}MMMMMMM${c2}MMMMMMMMMMs + ${c1}iM${c2}MMM&&${c1}MMMMMMMM${c2}MMMMMMMM\\ + ${c1}BMMM${c2}MMMMM${c1}MMMMMMM${c2}MMMMMM${c3}" +${c1}9MMMMM${c2}MMMMMMM${c1}MMMM${c2}MMMM${c3}MMMf- + ${c2}sMMMMMMMM${c1}MM${c2}M${c3}MMMMMMMMM3_ + ${c2}+ffffffff${c1}P${c3}MMMMMMMMMMMM0 + ${c2}CMMMMMMMMMMM + }MMMMMMMMM + ~MMMMMMM + "RMMMM + .PMB \ No newline at end of file diff --git a/src/logo/ascii/valhalla.txt b/src/logo/ascii/valhalla.txt new file mode 100644 index 0000000000..e9611793b0 --- /dev/null +++ b/src/logo/ascii/valhalla.txt @@ -0,0 +1,10 @@ + .:~: + !55P&#: + ^@G?G!&Y + !GYYGP55P: Y5J777!^:. +.GY?J#G!Y?5. ....P#7Y!##Y??57 +.5JY5PPY5GBBBPYYPBBGBYYP5PJP5: +^#J?Y@5?J5@@&!GG!&@@YJ?5@PJ7B? +5PY55G5YY5P!55YY5P7P5JJY5YYJ5Y +#G?J5@PJJP@~&55Y5@7@5JJG@5J?GB + .:.^:^^:!.!:!!:!:!:^^:^.:. \ No newline at end of file diff --git a/src/logo/ascii/xeroarch.txt b/src/logo/ascii/xeroarch.txt new file mode 100644 index 0000000000..1f094ea061 --- /dev/null +++ b/src/logo/ascii/xeroarch.txt @@ -0,0 +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 diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 62f8291cad..014f93fa99 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3088,6 +3088,7 @@ static const FFlogo O[] = { FF_COLOR_FG_WHITE, FF_COLOR_FG_CYAN, FF_COLOR_FG_RED, + FF_COLOR_FG_LIGHT_BLACK, }, .colorKeys = FF_COLOR_FG_YELLOW, .colorTitle = FF_COLOR_FG_WHITE, @@ -4574,6 +4575,16 @@ static const FFlogo U[] = { }; static const FFlogo V[] = { + // Valhalla + { + .names = {"Valhalla", "valhallaos", "valhalla-linux"}, + .lines = FASTFETCH_DATATEXT_LOGO_VALHALLA, + .colors = { + FF_COLOR_FG_WHITE, + }, + .colorKeys = FF_COLOR_FG_WHITE, + .colorTitle = FF_COLOR_FG_WHITE, + }, // Vanilla { .names = {"vanilla", "vanilla-os", "vanilla-linux"}, @@ -4785,12 +4796,25 @@ static const FFlogo X[] = { FF_COLOR_FG_CYAN, }, }, + //XeroArch + { + .names = {"XeroArch"}, + .lines = FASTFETCH_DATATEXT_LOGO_XEROARCH, + .colors = { + FF_COLOR_FG_256 "16", + FF_COLOR_FG_256 "14", + FF_COLOR_FG_256 "50", + FF_COLOR_FG_256 "93", + FF_COLOR_FG_256 "46", + FF_COLOR_FG_256 "15", + } + }, //Xray_OS { .names = {"Xray_OS"}, .lines = FASTFETCH_DATATEXT_LOGO_XRAY_OS, .colors = { - FF_COLOR_FG_256 "15", + FF_COLOR_FG_256 "16", FF_COLOR_FG_256 "14", FF_COLOR_FG_256 "16", } diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index ca989d35b5..c5740bc57a 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -25,6 +25,24 @@ void ffPrintBrightness(FFBrightnessOptions* options) return; } + if (options->compact) + { + FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); + + FF_LIST_FOR_EACH(FFBrightnessResult, item, result) + { + if(str.length > 0) + ffStrbufAppendC(&str, ' '); + + const double percent = (item->current - item->min) / (item->max - item->min) * 100; + ffPercentAppendNum(&str, percent, options->percent, false, &options->moduleArgs); + } + + ffPrintLogoAndKey(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&str, stdout); + return; + } + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); uint32_t index = 0; @@ -101,6 +119,12 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k return true; } + if (ffStrEqualsIgnCase(subKey, "compact")) + { + options->compact = ffOptionParseBoolean(value); + return true; + } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) return true; @@ -126,6 +150,12 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul continue; } + if (ffStrEqualsIgnCase(key, "compact")) + { + options->compact = (uint32_t) yyjson_get_bool(val); + continue; + } + if (ffPercentParseJsonObject(key, val, &options->percent)) continue; @@ -144,6 +174,9 @@ void ffGenerateBrightnessJsonConfig(FFBrightnessOptions* options, yyjson_mut_doc yyjson_mut_obj_add_uint(doc, module, "ddcciSleep", options->ddcciSleep); ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + + if (defaultOptions.compact != options->compact) + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); } void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -205,6 +238,7 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options) options->ddcciSleep = 10; options->percent = (FFColorRangeConfig) { 100, 100 }; + options->compact = false; } void ffDestroyBrightnessOptions(FFBrightnessOptions* options) diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index 2623d0aead..e359cdc3e8 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -12,4 +12,5 @@ typedef struct FFBrightnessOptions uint32_t ddcciSleep; // ms FFColorRangeConfig percent; + bool compact; } FFBrightnessOptions; diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 67bded503f..a79a31c49c 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -9,7 +9,7 @@ #pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format #define FF_DATETIME_DISPLAY_NAME "Date & Time" -#define FF_DATETIME_NUM_FORMAT_ARGS 22 +#define FF_DATETIME_NUM_FORMAT_ARGS 23 typedef struct FFDateTimeResult { @@ -26,6 +26,7 @@ typedef struct FFDateTimeResult uint16_t dayInYear; //52 uint8_t dayInMonth; //21 uint8_t dayInWeek; //1 + char dayPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //01 uint8_t hour; //15 char hourPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //15 uint8_t hour12; //3 @@ -54,6 +55,7 @@ void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) result.dayInYear = (uint8_t) (tm->tm_yday + 1); result.dayInMonth = (uint8_t) tm->tm_mday; result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday; + strftime(result.dayPretty, sizeof(result.dayPretty), "%0d", tm); result.hour = (uint8_t) tm->tm_hour; strftime(result.hourPretty, sizeof(result.hourPretty), "%H", tm); result.hour12 = (uint8_t) (result.hour % 12); @@ -88,6 +90,7 @@ void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) FF_FORMAT_ARG(result.secondPretty, "second-pretty"), // 20 FF_FORMAT_ARG(result.offsetFromUtc, "offset-from-utc"), // 21 FF_FORMAT_ARG(result.timezoneName, "timezone-name"), // 22 + FF_FORMAT_ARG(result.dayPretty, "day-pretty"), // 23 })); } @@ -157,7 +160,7 @@ void ffGenerateDateTimeJsonResult(FF_MAYBE_UNUSED FFDateTimeOptions* options, yy void ffPrintDateTimeHelpFormat(void) { - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_DATETIME_MODULE_NAME, "{1}-{4}-{11} {14}:{18}:{20}", FF_DATETIME_NUM_FORMAT_ARGS, ((const char* []) { + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_DATETIME_MODULE_NAME, "{1}-{4}-{23} {14}:{18}:{20}", FF_DATETIME_NUM_FORMAT_ARGS, ((const char* []) { "year - year", "last two digits of year - year-short", "month - month", @@ -180,6 +183,7 @@ void ffPrintDateTimeHelpFormat(void) "second with leading zero - second-pretty", "offset from UTC in the ISO 8601 format - offset-from-utc", "locale-dependent timezone name or abbreviation - timezone-name", + "day in month with leading zero - day-pretty", })); } diff --git a/src/modules/display/display.c b/src/modules/display/display.c index ff1c93528b..53f39a467b 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -6,7 +6,7 @@ #include -#define FF_DISPLAY_NUM_FORMAT_ARGS 15 +#define FF_DISPLAY_NUM_FORMAT_ARGS 18 static int sortByNameAsc(FFDisplayResult* a, FFDisplayResult* b) { @@ -100,7 +100,7 @@ void ffPrintDisplay(FFDisplayOptions* options) } FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - uint32_t inch = (uint32_t) (sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4 + 0.5); + double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4; if(options->moduleArgs.outputFormat.length == 0) { @@ -122,12 +122,12 @@ void ffPrintDisplay(FFDisplayOptions* options) ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight); if (inch > 1) - ffStrbufAppendF(&buffer, " in %i″", inch); + ffStrbufAppendF(&buffer, " in %i\"", (uint32_t) (inch + 0.5)); if(result->type != FF_DISPLAY_TYPE_UNKNOWN) ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); - if (result->hdrEnabled) + if (result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED) ffStrbufAppendS(&buffer, " [HDR]"); if(moduleIndex > 0 && result->primary) @@ -139,6 +139,8 @@ void ffPrintDisplay(FFDisplayOptions* options) else { double ppi = sqrt(result->width * result->width + result->height * result->height) / inch; + bool hdrEnabled = result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; + uint32_t iInch = (uint32_t) (inch + 0.5), iPpi = (uint32_t) (ppi + 0.5); char refreshRate[16]; if(result->refreshRate > 0) @@ -151,6 +153,15 @@ void ffPrintDisplay(FFDisplayOptions* options) else refreshRate[0] = 0; + char buf[32]; + 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]); + } + else + buf[0] = '\0'; + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISPLAY_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(result->width, "width"), FF_FORMAT_ARG(result->height, "height"), @@ -163,10 +174,13 @@ void ffPrintDisplay(FFDisplayOptions* options) FF_FORMAT_ARG(result->primary, "is-primary"), FF_FORMAT_ARG(result->physicalWidth, "physical-width"), FF_FORMAT_ARG(result->physicalHeight, "physical-height"), - FF_FORMAT_ARG(inch, "inch"), - FF_FORMAT_ARG(ppi, "ppi"), + FF_FORMAT_ARG(iInch, "inch"), + FF_FORMAT_ARG(iPpi, "ppi"), FF_FORMAT_ARG(result->bitDepth, "bit-depth"), - FF_FORMAT_ARG(result->hdrEnabled, "hdr-enabled"), + FF_FORMAT_ARG(hdrEnabled, "hdr-enabled"), + FF_FORMAT_ARG(result->manufactureYear, "manufacture-year"), + FF_FORMAT_ARG(result->manufactureWeek, "manufacture-week"), + FF_FORMAT_ARG(buf, "serial"), })); } } @@ -335,7 +349,23 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_real(doc, obj, "refreshRate", item->refreshRate); yyjson_mut_obj_add_uint(doc, obj, "rotation", item->rotation); yyjson_mut_obj_add_uint(doc, obj, "bitDepth", item->bitDepth); - yyjson_mut_obj_add_bool(doc, obj, "hdrEnabled", item->hdrEnabled); + if (item->hdrStatus == FF_DISPLAY_HDR_STATUS_UNKNOWN) + yyjson_mut_obj_add_null(doc, obj, "hdrStatus"); + else switch (item->hdrStatus) + { + case FF_DISPLAY_HDR_STATUS_UNSUPPORTED: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Unsupported"); + break; + case FF_DISPLAY_HDR_STATUS_SUPPORTED: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Supported"); + break; + case FF_DISPLAY_HDR_STATUS_ENABLED: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Enabled"); + break; + default: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Unknown"); + break; + } switch (item->type) { @@ -349,6 +379,22 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_str(doc, obj, "type", "Unknown"); break; } + + if (item->manufactureYear) + { + yyjson_mut_val* manufactureDate = yyjson_mut_obj_add_obj(doc, obj, "manufactureDate"); + yyjson_mut_obj_add_uint(doc, manufactureDate, "year", item->manufactureYear); + yyjson_mut_obj_add_uint(doc, manufactureDate, "week", item->manufactureWeek); + } + else + { + yyjson_mut_obj_add_null(doc, obj, "manufactureDate"); + } + + if (item->serial) + yyjson_mut_obj_add_uint(doc, obj, "serial", item->serial); + else + yyjson_mut_obj_add_null(doc, obj, "serial"); } } @@ -369,7 +415,10 @@ void ffPrintDisplayHelpFormat(void) "Physical diagonal length in inches - inch", "Pixels per inch (PPI) - ppi", "Bits per color channel - bit-depth", - "True if high dynamic range (HDR) is enabled - hdr-enabled", + "True if high dynamic range (HDR) mode is enabled - hdr-enabled", + "Year of manufacturing - manufacture-year", + "Nth week of manufacturing in the year - manufacture-week", + "Serial number - serial", })); } diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 0ca38374f7..a6bcd261ad 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -5,7 +5,7 @@ #include "util/stringUtils.h" #define FF_LOCALIP_DISPLAY_NAME "Local IP" -#define FF_LOCALIP_NUM_FORMAT_ARGS 7 +#define FF_LOCALIP_NUM_FORMAT_ARGS 8 #pragma GCC diagnostic ignored "-Wsign-conversion" static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) @@ -77,6 +77,12 @@ static void printIp(FFLocalIpResult* ip, bool markDefaultRoute) putchar(']'); flag = true; } + if (ip->flags.length) { + if (flag) fputs(" <", stdout); + ffStrbufWriteTo(&ip->flags, stdout); + putchar('>'); + flag = true; + } if (markDefaultRoute && flag && ip->defaultRoute) fputs(" *", stdout); } @@ -151,6 +157,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) FF_FORMAT_ARG(ip->defaultRoute, "is-default-route"), FF_FORMAT_ARG(ip->mtu, "mtu"), FF_FORMAT_ARG(speedStr, "speed"), + FF_FORMAT_ARG(ip->flags, "flags"), })); } ++index; @@ -163,6 +170,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) ffStrbufDestroy(&ip->ipv4); ffStrbufDestroy(&ip->ipv6); ffStrbufDestroy(&ip->mac); + ffStrbufDestroy(&ip->flags); } } @@ -236,6 +244,15 @@ bool ffParseLocalIpCommandOptions(FFLocalIpOptions* options, const char* key, co return true; } + if (ffStrEqualsIgnCase(subKey, "show-flags")) + { + if (ffOptionParseBoolean(value)) + options->showType |= FF_LOCALIP_TYPE_FLAGS_BIT; + else + options->showType &= ~FF_LOCALIP_TYPE_FLAGS_BIT; + return true; + } + if(ffStrEqualsIgnCase(subKey, "compact")) { if (ffOptionParseBoolean(value)) @@ -348,6 +365,15 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "showFlags")) + { + if (yyjson_get_bool(val)) + options->showType |= FF_LOCALIP_TYPE_FLAGS_BIT; + else + options->showType &= ~FF_LOCALIP_TYPE_FLAGS_BIT; + continue; + } + if (ffStrEqualsIgnCase(key, "compact")) { if (yyjson_get_bool(val)) @@ -415,6 +441,9 @@ void ffGenerateLocalIpJsonConfig(FFLocalIpOptions* options, yyjson_mut_doc* doc, if (options->showType & FF_LOCALIP_TYPE_SPEED_BIT) yyjson_mut_obj_add_bool(doc, module, "showSpeed", true); + if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) + yyjson_mut_obj_add_bool(doc, module, "showFlags", true); + if (options->showType & FF_LOCALIP_TYPE_COMPACT_BIT) yyjson_mut_obj_add_bool(doc, module, "compact", true); @@ -445,13 +474,20 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", ip->defaultRoute); - yyjson_mut_obj_add_strbuf(doc, obj, "ipv4", &ip->ipv4); - yyjson_mut_obj_add_strbuf(doc, obj, "ipv6", &ip->ipv6); - yyjson_mut_obj_add_strbuf(doc, obj, "mac", &ip->mac); yyjson_mut_obj_add_strbuf(doc, obj, "name", &ip->name); - yyjson_mut_obj_add_int(doc, obj, "mtu", ip->mtu); - yyjson_mut_obj_add_int(doc, obj, "speed", ip->speed); + yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", ip->defaultRoute); + if (options->showType & FF_LOCALIP_TYPE_IPV4_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "ipv4", &ip->ipv4); + if (options->showType & FF_LOCALIP_TYPE_IPV6_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "ipv6", &ip->ipv6); + if (options->showType & FF_LOCALIP_TYPE_MAC_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "mac", &ip->mac); + if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) + yyjson_mut_obj_add_int(doc, obj, "mtu", ip->mtu); + if (options->showType & FF_LOCALIP_TYPE_SPEED_BIT) + yyjson_mut_obj_add_int(doc, obj, "speed", ip->speed); + if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "flags", &ip->flags); } FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) @@ -460,6 +496,7 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs ffStrbufDestroy(&ip->ipv4); ffStrbufDestroy(&ip->ipv6); ffStrbufDestroy(&ip->mac); + ffStrbufDestroy(&ip->flags); } } @@ -473,6 +510,7 @@ void ffPrintLocalIpHelpFormat(void) "Is default route - is-default-route", "MTU size in bytes - mtu", "Link speed (formatted) - speed", + "Interface flags - flags", })); } @@ -492,7 +530,7 @@ void ffInitLocalIpOptions(FFLocalIpOptions* options) ffOptionInitModuleArg(&options->moduleArgs, "󰩟"); options->showType = FF_LOCALIP_TYPE_IPV4_BIT | FF_LOCALIP_TYPE_PREFIX_LEN_BIT - #ifndef __ANDROID__ + #if !__ANDROID__ /*Permission denied*/ && !__OpenBSD__ /*Report invalid argument for some reason*/ | FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT #endif ; diff --git a/src/modules/localip/option.h b/src/modules/localip/option.h index 1a01611528..511ec729db 100644 --- a/src/modules/localip/option.h +++ b/src/modules/localip/option.h @@ -14,6 +14,7 @@ typedef enum FFLocalIpType FF_LOCALIP_TYPE_PREFIX_LEN_BIT = 1 << 4, FF_LOCALIP_TYPE_MTU_BIT = 1 << 5, FF_LOCALIP_TYPE_SPEED_BIT = 1 << 6, + FF_LOCALIP_TYPE_FLAGS_BIT = 1 << 7, FF_LOCALIP_TYPE_COMPACT_BIT = 1 << 10, FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT = 1 << 11, diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 1ce5ab8fd9..05f58a0e75 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -10,7 +10,7 @@ void ffPrintMemory(FFMemoryOptions* options) { - FFMemoryResult storage; + FFMemoryResult storage = {}; const char* error = ffDetectMemory(&storage); if(error) diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index a2d43cff7d..701444c294 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -1,37 +1,30 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "detection/monitor/monitor.h" +#include "detection/displayserver/displayserver.h" #include "modules/monitor/monitor.h" #include "util/stringUtils.h" #include -#define FF_MONITOR_NUM_FORMAT_ARGS 11 +#define FF_MONITOR_NUM_FORMAT_ARGS 12 void ffPrintMonitor(FFMonitorOptions* options) { - FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFMonitorResult)); + const FFDisplayServerResult* result = ffConnectDisplayServer(); - const char* error = ffDetectMonitor(&result); - - if(error) - { - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); - return; - } - - if(!result.length) + if(!result->displays.length) { - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical display detected"); + ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No display detected"); return; } FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); uint32_t index = 0; - FF_LIST_FOR_EACH(FFMonitorResult, display, result) + FF_LIST_FOR_EACH(FFDisplayResult, display, result->displays) { double inch = sqrt(display->physicalWidth * display->physicalWidth + display->physicalHeight * display->physicalHeight) / 25.4; double ppi = sqrt(display->width * display->width + display->height * display->height) / inch; + bool hdrCompatible = display->hdrStatus == FF_DISPLAY_HDR_STATUS_SUPPORTED || display->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; ffStrbufClear(&key); if(options->moduleArgs.key.length == 0) @@ -40,7 +33,7 @@ void ffPrintMonitor(FFMonitorOptions* options) } else { - uint32_t moduleIndex = result.length == 1 ? 0 : index + 1; + uint32_t moduleIndex = result->displays.length == 1 ? 0 : index + 1; FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 3, ((FFformatarg[]){ FF_FORMAT_ARG(moduleIndex, "index"), FF_FORMAT_ARG(display->name, "name"), @@ -56,9 +49,10 @@ void ffPrintMonitor(FFMonitorOptions* options) if (display->refreshRate > 0) printf(" @ %g Hz", ((int) (display->refreshRate * 1000 + 0.5)) / 1000.0); if (inch > 0) - printf(" - %ux%u mm (%.2f inches, %.2f ppi)\n", display->physicalWidth, display->physicalHeight, inch, ppi); - else - putchar('\n'); + printf(" - %ux%u mm (%.2f inches, %.2f ppi)", display->physicalWidth, display->physicalHeight, inch, ppi); + if (hdrCompatible) + fputs(" [HDR Compatible]", stdout); + putchar('\n'); } else { @@ -83,6 +77,7 @@ void ffPrintMonitor(FFMonitorOptions* options) FF_FORMAT_ARG(display->manufactureWeek, "manufacture-week"), FF_FORMAT_ARG(buf, "serial"), FF_FORMAT_ARG(display->refreshRate, "refresh-rate"), + FF_FORMAT_ARG(hdrCompatible, "hdr-compatible"), })); } @@ -128,59 +123,7 @@ void ffGenerateMonitorJsonConfig(FFMonitorOptions* options, yyjson_mut_doc* doc, void ffGenerateMonitorJsonResult(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFMonitorResult)); - - const char* error = ffDetectMonitor(&results); - - if (error) - { - yyjson_mut_obj_add_str(doc, module, "error", error); - } - else if(results.length == 0) - { - yyjson_mut_obj_add_str(doc, module, "error", "No monitors found"); - } - else - { - yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); - FF_LIST_FOR_EACH(FFMonitorResult, item, results) - { - yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - yyjson_mut_obj_add_bool(doc, obj, "hdrCompatible", item->hdrCompatible); - yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); - - yyjson_mut_val* resolution = yyjson_mut_obj_add_obj(doc, obj, "resolution"); - yyjson_mut_obj_add_uint(doc, resolution, "width", item->width); - yyjson_mut_obj_add_uint(doc, resolution, "height", item->height); - - yyjson_mut_val* physical = yyjson_mut_obj_add_obj(doc, obj, "physical"); - yyjson_mut_obj_add_uint(doc, physical, "height", item->physicalHeight); - yyjson_mut_obj_add_uint(doc, physical, "width", item->physicalWidth); - - yyjson_mut_obj_add_real(doc, obj, "refreshRate", item->refreshRate); - - if (item->manufactureYear) - { - yyjson_mut_val* manufactureDate = yyjson_mut_obj_add_obj(doc, obj, "manufactureDate"); - yyjson_mut_obj_add_uint(doc, manufactureDate, "year", item->manufactureYear); - yyjson_mut_obj_add_uint(doc, manufactureDate, "week", item->manufactureWeek); - } - else - { - yyjson_mut_obj_add_null(doc, obj, "manufactureDate"); - } - - if (item->serial) - yyjson_mut_obj_add_uint(doc, obj, "serial", item->serial); - else - yyjson_mut_obj_add_null(doc, obj, "serial"); - } - } - - FF_LIST_FOR_EACH(FFMonitorResult, item, results) - { - ffStrbufDestroy(&item->name); - } + yyjson_mut_obj_add_str(doc, module, "error", "Monitor module is an alias of Display module"); } void ffPrintMonitorHelpFormat(void) @@ -197,6 +140,7 @@ void ffPrintMonitorHelpFormat(void) "Nth week of manufacturing in the year - manufacture-week", "Serial number - serial", "Maximum refresh rate in Hz - refresh-rate", + "True if the display is HDR compatible - hdr-compatible", })); } @@ -205,7 +149,7 @@ void ffInitMonitorOptions(FFMonitorOptions* options) ffOptionInitModuleBaseInfo( &options->moduleInfo, FF_MONITOR_MODULE_NAME, - "Print connected physical monitor information", + "Alias of Display module", ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, diff --git a/src/modules/os/os.c b/src/modules/os/os.c index c00676fced..8224b65c51 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -230,6 +230,8 @@ void ffInitOSOptions(FFOSOptions* options) "" #elif __sun "" + #elif __OpenBSD__ + "" #else "?" #endif diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 6666a9c6ee..210351631c 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -10,7 +10,7 @@ void ffPrintSwap(FFSwapOptions* options) { - FFSwapResult storage; + FFSwapResult storage = {}; const char* error = ffDetectSwap(&storage); if(error) diff --git a/src/options/general.c b/src/options/general.c index abb8d10546..a29c21960a 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -39,7 +39,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va else if (ffStrEqualsIgnCase(key, "detectVersion")) options->detectVersion = yyjson_get_bool(val); - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) else if (ffStrEqualsIgnCase(key, "escapeBedrock")) options->escapeBedrock = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "playerName")) @@ -84,7 +84,7 @@ bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key else if(ffStrEqualsIgnCase(key, "--detect-version")) options->detectVersion = ffOptionParseBoolean(value); - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) else if(ffStrEqualsIgnCase(key, "--escape-bedrock")) options->escapeBedrock = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(key, "--player-name")) diff --git a/src/options/general.h b/src/options/general.h index 8b14283d81..0a85df7672 100644 --- a/src/options/general.h +++ b/src/options/general.h @@ -16,7 +16,7 @@ typedef struct FFOptionsGeneral bool detectVersion; // Module options that cannot be put in module option structure - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) FFstrbuf playerName; bool escapeBedrock; FFDsForceDrmType dsForceDrm; diff --git a/src/util/binary_linux.c b/src/util/binary_linux.c index e5c7f5c982..b9c521ca9c 100644 --- a/src/util/binary_linux.c +++ b/src/util/binary_linux.c @@ -1,6 +1,6 @@ #include "binary.h" -#if defined(FF_HAVE_ELF) || defined(__sun) || defined(__FreeBSD__) +#if defined(FF_HAVE_ELF) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) #include "common/io/io.h" #include "common/library.h" diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index b442eed54f..9eaeae38a5 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -12,7 +12,7 @@ #ifdef __APPLE__ #include #include -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__OpenBSD__) #include #endif @@ -34,7 +34,9 @@ static void getExePath(FFPlatform* platform) exePathLen = 0; else exePathLen--; // remove terminating NUL - #else + #elif defined(__OpenBSD__) + size_t exePathLen = 0; + #elif defined(__sun) ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1); exePath[exePathLen] = '\0'; #endif @@ -177,7 +179,7 @@ static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts) ffStrbufAppendS(&info->architecture, uts->machine); ffStrbufInit(&info->displayVersion); - #if defined(__FreeBSD__) || defined(__APPLE__) + #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) size_t length = sizeof(info->pageSize); sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &info->pageSize, &length, NULL, 0); #else