diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f3879baea..89afea2e25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: run: ldd fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure linux-amd64: name: Linux-amd64 @@ -111,7 +111,7 @@ jobs: run: ldd fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure - name: get fastfetch version id: ffversion @@ -150,7 +150,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -189,7 +189,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -225,7 +225,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -260,7 +260,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -295,7 +295,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -303,6 +303,41 @@ jobs: name: fastfetch-linux-ppc64le path: ./fastfetch-*.* + linux-s390x: + name: Linux-s390x + runs-on: ubuntu-22.04 + permissions: + security-events: write + contents: read + steps: + - name: checkout repository + uses: actions/checkout@v4 + + - name: run VM + uses: uraimo/run-on-arch-action@v2 + id: runcmd + with: + arch: s390x + distro: ubuntu20.04 + githubToken: ${{ github.token }} + run: | + uname -a + apt-get update && apt-get install -y cmake make g++ libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libchafa-dev libelf-dev directx-headers-dev rpm + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + cmake --build . --target package --verbose -j4 + ./fastfetch --list-features + time ./fastfetch -c presets/ci.jsonc --stat false + time ./fastfetch -c presets/ci.jsonc --format json + time ./flashfetch + ldd fastfetch + ctest --output-on-failure + + - name: upload artifacts + uses: actions/upload-artifact@v4 + with: + name: fastfetch-linux-s390x + path: ./fastfetch-*.* + musl-amd64: name: Musl-amd64 runs-on: ubuntu-latest @@ -334,7 +369,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure shell: alpine.sh {0} - name: upload artifacts @@ -390,7 +425,7 @@ jobs: run: otool -L fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -422,7 +457,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure cpack - name: upload artifacts @@ -460,7 +495,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -495,7 +530,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -531,7 +566,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -567,7 +602,7 @@ jobs: time ./fastfetch -c presets/ci.jsonc --format json time ./flashfetch ldd fastfetch - ctest + ctest --output-on-failure - name: upload artifacts uses: actions/upload-artifact@v4 @@ -626,7 +661,7 @@ jobs: run: ldd fastfetch - name: run tests - run: ctest + run: ctest --output-on-failure - name: create zip archive run: 7z a -tzip -mx9 -bd -y fastfetch-windows-amd64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets @@ -651,6 +686,7 @@ jobs: - linux-armv6 - linux-riscv64 - linux-ppc64le + - linux-s390x - musl-amd64 - macos-universal - freebsd-amd64 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c978cb524..68385e8159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,31 @@ +# 2.36.0 + +Bugfixes: +* Trim leading slash for login shells (Shell, OpenBSD) +* Prefer SOC name if available over CPU name (CPU, Linux) + +Features: +* Use kernel API to detect sound devices (Sound, NetBSD) +* Use sndio for sound server detection on OpenBSD (Sound, OpenBSD) +* Add minimal implementation for Haiku (#1538, Haiku) +* Support CPU & GPU temperature detection for M4x (CPU / GPU, macOS) +* Support VMEM size detection for old Nvidia cards (GPU, Linux) +* Use [recommendedMaxWorkingSetSize](https://developer.apple.com/documentation/metal/mtldevice/recommendedmaxworkingsetsize) as total GPU mem size (GPU, macOS) +* Support Physical core count and CPU package count detection for loongarch (CPU, Linux) +* Split ID_LIKE when used for distro matching (#1540, Logo) +* Capitalize `{type}`'s first letter in custom format (#1543, Display) +* Support model name detection for s390x (CPU, Linux) +* Support more Armbian variants detection (#1547, OS, Linux) +* Support the syntax of `{$ENV_VAR}` in custom format, which will be replaced by the value of the environment variable `ENV_VAR` (#1541) + * This is another way to pass 3rd-party data to fastfetch besides `Custom` module. +* Improve performance of Tilix version detection (Terminal, Linux) + +Logo: +* Update arch_old +* Add Nexa Linux +* Add filotimo +* Update some distro names + # 2.35.0 Bugfixes: diff --git a/CMakeLists.txt b/CMakeLists.txt index 785b340f54..426cd0e0ea 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.35.0 + VERSION 2.36.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -30,6 +30,8 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly") set(DragonFly TRUE CACHE BOOL "..." FORCE) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") set(SunOS TRUE CACHE BOOL "..." FORCE) +elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Haiku") + set(Haiku TRUE CACHE BOOL "..." FORCE) elseif(NOT APPLE AND NOT WIN32) message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}") endif() @@ -70,12 +72,12 @@ cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR F cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD 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 OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS" OFF) -cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS" OFF) +cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR WIN32 OR SunOS OR Haiku" OFF) +cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR ANDROID OR SunOS OR Haiku" OFF) cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR NetBSD 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 OpenBSD OR NetBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX 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 OR DragonFly" OFF) @@ -139,7 +141,7 @@ set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=retu set(CMAKE_C_STANDARD 11) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration -Werror=int-conversion") -if(WIN32 OR ENABLE_DIRECTX_HEADERS) +if(WIN32 OR HAIKU OR ENABLE_DIRECTX_HEADERS) enable_language(CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}") @@ -761,7 +763,7 @@ elseif(NetBSD) src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_nbsd.c src/detection/gtk_qt/qt.c - src/detection/sound/sound_linux.c + src/detection/sound/sound_nbsd.c src/detection/swap/swap_obsd.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c @@ -843,7 +845,7 @@ elseif(OpenBSD) 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/sound/sound_obsd.c src/detection/swap/swap_obsd.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c @@ -1088,6 +1090,74 @@ elseif(SunOS) src/util/platform/FFPlatform_unix.c src/util/binary_linux.c ) +elseif(Haiku) + list(APPEND LIBFASTFETCH_SRC + src/common/io/io_unix.c + src/common/netif/netif_haiku.c + src/common/networking_linux.c + src/common/processing_linux.c + src/detection/battery/battery_nosupport.c + src/detection/bios/bios_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_nosupport.c + src/detection/cpucache/cpucache_nosupport.c + src/detection/cpuusage/cpuusage_nosupport.c + src/detection/cursor/cursor_nosupport.c + src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c + src/detection/disk/disk_nosupport.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/displayserver_haiku.cpp + src/detection/font/font_haiku.cpp + src/detection/gpu/gpu_nosupport.c + src/detection/gpu/gpu_pci.c + src/detection/gtk_qt/gtk.c + src/detection/host/host_nosupport.c + src/detection/icons/icons_nosupport.c + src/detection/initsystem/initsystem_nosupport.c + src/detection/keyboard/keyboard_nosupport.c + src/detection/libc/libc_nosupport.c + src/detection/lm/lm_nosupport.c + src/detection/loadavg/loadavg_nosupport.c + src/detection/locale/locale_linux.c + src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c + src/detection/media/media_nosupport.c + src/detection/memory/memory_haiku.c + src/detection/mouse/mouse_nosupport.c + src/detection/netio/netio_nosupport.c + src/detection/opengl/opengl_linux.c + src/detection/os/os_haiku.c + src/detection/packages/packages_haiku.c + src/detection/poweradapter/poweradapter_nosupport.c + src/detection/processes/processes_haiku.c + src/detection/gtk_qt/qt.c + src/detection/sound/sound_nosupport.c + src/detection/swap/swap_haiku.c + src/detection/terminalfont/terminalfont_linux.c + src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c + src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_nosupport.c + src/detection/uptime/uptime_haiku.c + src/detection/users/users_linux.c + src/detection/wallpaper/wallpaper_nosupport.c + src/detection/wifi/wifi_nosupport.c + src/detection/wm/wm_nosupport.c + src/detection/de/de_nosupport.c + src/detection/wmtheme/wmtheme_nosupport.c + src/detection/camera/camera_nosupport.c + src/detection/zpool/zpool_nosupport.c + src/util/platform/FFPlatform_unix.c + src/util/binary_linux.c + ) endif() if(ENABLE_DIRECTX_HEADERS) @@ -1112,6 +1182,9 @@ endif() if(LINUX) check_function_exists(statx HAVE_STATX) endif() +if(NOT WIN32) + check_function_exists(pipe2 HAVE_PIPE2) +endif() if(ENABLE_SYSTEM_YYJSON) find_package(yyjson) @@ -1226,6 +1299,10 @@ if(HAVE_WCWIDTH) target_compile_definitions(libfastfetch PUBLIC FF_HAVE_WCWIDTH) endif() +if(HAVE_PIPE2) + target_compile_definitions(libfastfetch PUBLIC FF_HAVE_PIPE2) +endif() + if(NOT "${CUSTOM_PCI_IDS_PATH}" STREQUAL "") message(STATUS "Custom file path of pci.ids: ${CUSTOM_PCI_IDS_PATH}") target_compile_definitions(libfastfetch PRIVATE FF_CUSTOM_PCI_IDS_PATH=${CUSTOM_PCI_IDS_PATH}) @@ -1504,6 +1581,7 @@ elseif(OpenBSD) target_link_libraries(libfastfetch PRIVATE "m" PRIVATE "kvm" + PRIVATE "sndio" ) elseif(NetBSD) target_link_libraries(libfastfetch @@ -1533,6 +1611,12 @@ elseif(ANDROID) ) endif() endif() +elseif(Haiku) + target_link_libraries(libfastfetch + PRIVATE "network" + PRIVATE "be" + PRIVATE "gnu" + ) endif() target_include_directories(libfastfetch diff --git a/LICENSE b/LICENSE index ac6f147eaf..3a3b50b1c0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ MIT License Copyright (c) 2021-2023 Linus Dierheimer -Copyright (c) 2022-2024 Carter Li +Copyright (c) 2022-2025 Carter Li Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/debian/changelog b/debian/changelog index 0e146b63c0..5ebb8ed7ae 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fastfetch (2.35.0) jammy; urgency=medium + + * Update to 2.35.0 + + -- Carter Li Sun, 26 Jan 2025 10:15:22 +0800 + fastfetch (2.34.1) jammy; urgency=medium * Update to 2.34.1 diff --git a/debian/files b/debian/files index b5d98ece54..45ff9c2606 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.34.1_source.buildinfo universe/utils optional +fastfetch_2.35.0_source.buildinfo universe/utils optional diff --git a/doc/json_schema.json b/doc/json_schema.json index 05b27b9fe0..61308e83c5 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -179,7 +179,7 @@ "type": "string" }, "displayFormat": { - "description": "Output format of the module `Display`. See `-h format` for formatting syntax\n 1. {width}: Screen configured width (in pixels)\n 2. {height}: Screen configured height (in pixels)\n 3. {refresh-rate}: Screen configured refresh rate (in Hz)\n 4. {scaled-width}: Screen scaled width (in pixels)\n 5. {scaled-height}: Screen scaled height (in pixels)\n 6. {name}: Screen name\n 7. {type}: Screen type (builtin, external or unknown)\n 8. {rotation}: Screen rotation (in degrees)\n 9. {is-primary}: True if being the primary screen\n 10. {physical-width}: Screen physical width (in millimeters)\n 11. {physical-height}: Screen physical height (in millimeters)\n 12. {inch}: Physical diagonal length in inches\n 13. {ppi}: Pixels per inch (PPI)\n 14. {bit-depth}: Bits per color channel\n 15. {hdr-enabled}: True if high dynamic range (HDR) mode is enabled\n 16. {manufacture-year}: Year of manufacturing\n 17. {manufacture-week}: Nth week of manufacturing in the year\n 18. {serial}: Serial number\n 19. {platform-api}: The platform API used when detecting the display\n 20. {hdr-compatible}: True if the display is HDR compatible\n 21. {scale-factor}: HiDPI scale factor\n 22. {preferred-width}: Screen preferred width (in pixels)\n 23. {preferred-height}: Screen preferred height (in pixels)\n 24. {preferred-refresh-rate}: Screen preferred refresh rate (in Hz)", + "description": "Output format of the module `Display`. See `-h format` for formatting syntax\n 1. {width}: Screen configured width (in pixels)\n 2. {height}: Screen configured height (in pixels)\n 3. {refresh-rate}: Screen configured refresh rate (in Hz)\n 4. {scaled-width}: Screen scaled width (in pixels)\n 5. {scaled-height}: Screen scaled height (in pixels)\n 6. {name}: Screen name\n 7. {type}: Screen type (Built-in or External)\n 8. {rotation}: Screen rotation (in degrees)\n 9. {is-primary}: True if being the primary screen\n 10. {physical-width}: Screen physical width (in millimeters)\n 11. {physical-height}: Screen physical height (in millimeters)\n 12. {inch}: Physical diagonal length in inches\n 13. {ppi}: Pixels per inch (PPI)\n 14. {bit-depth}: Bits per color channel\n 15. {hdr-enabled}: True if high dynamic range (HDR) mode is enabled\n 16. {manufacture-year}: Year of manufacturing\n 17. {manufacture-week}: Nth week of manufacturing in the year\n 18. {serial}: Serial number\n 19. {platform-api}: The platform API used when detecting the display\n 20. {hdr-compatible}: True if the display is HDR compatible\n 21. {scale-factor}: HiDPI scale factor\n 22. {preferred-width}: Screen preferred width (in pixels)\n 23. {preferred-height}: Screen preferred height (in pixels)\n 24. {preferred-refresh-rate}: Screen preferred refresh rate (in Hz)", "type": "string" }, "diskFormat": { diff --git a/src/common/format.c b/src/common/format.c index 19564a3fb6..204c1d8d74 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -259,24 +259,33 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n continue; } - //test for constant, if so evaluate it + //test for constant or env var, if so evaluate it if (firstChar == '$') { char* pend = NULL; int32_t indexSigned = (int32_t) strtol(placeholderValue.chars + 1, &pend, 10); - uint32_t index = (uint32_t) indexSigned; - bool backward = indexSigned < 0; - - if (indexSigned == 0 || *pend != '\0' || instance.config.display.constants.length < index) + if (pend == placeholderValue.chars + 1) { - appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length); - continue; + // treat placeholder as an environment variable + char* envValue = getenv(placeholderValue.chars + 1); + if (envValue) + ffStrbufAppendS(buffer, envValue); + else + appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length); } + else + { + // treat placeholder as a constant + uint32_t index = (uint32_t) (indexSigned < 0 ? (int32_t) instance.config.display.constants.length + indexSigned : indexSigned - 1); - FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, backward - ? instance.config.display.constants.length - index - : index - 1); - ffStrbufAppend(buffer, item); + if (*pend != '\0' || instance.config.display.constants.length <= index) + appendInvalidPlaceholder(buffer, "{", &placeholderValue, i, formatstr->length); + else + { + FFstrbuf* item = FF_LIST_GET(FFstrbuf, instance.config.display.constants, index); + ffStrbufAppend(buffer, item); + } + } continue; } diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 69b6fbca61..5623d2dc99 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -310,7 +310,7 @@ void listFilesRecursively(uint32_t baseLength, FFstrbuf* folder, uint8_t indenta continue; bool isDir = false; -#ifndef __sun +#if !defined(__sun) && !defined(__HAIKU__) if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK) isDir = entry->d_type == DT_DIR; else diff --git a/src/common/netif/netif_haiku.c b/src/common/netif/netif_haiku.c new file mode 100644 index 0000000000..07185a7e94 --- /dev/null +++ b/src/common/netif/netif_haiku.c @@ -0,0 +1,63 @@ +#include "netif.h" +#include "common/io/io.h" +#include "util/mallocHelper.h" + +#include +#include +#include +#include +#include +#include + +// loosely based on Haiku's src/bin/network/route/route.cpp + +bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) +{ + // TODO: AF_INET6 + FF_AUTO_CLOSE_FD int pfRoute = socket(AF_INET, SOCK_RAW, AF_INET); + if (pfRoute < 0) + return false; + + struct ifconf config; + config.ifc_len = sizeof(config.ifc_value); + if (ioctl(pfRoute, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0) + return false; + + int size = config.ifc_value; + if (size == 0) + return false; + + FF_AUTO_FREE void *buffer = malloc(size); + if (buffer == NULL) { + return false; + } + + config.ifc_len = size; + config.ifc_buf = buffer; + if (ioctl(pfRoute, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0) + return false; + + struct ifreq *interface = (struct ifreq*)buffer; + struct ifreq *end = (struct ifreq*)((uint8_t*)buffer + size); + + while (interface < end) { + if (interface->ifr_route.flags & RTF_DEFAULT) { + strlcpy(iface, interface->ifr_name, IF_NAMESIZE); + *ifIndex = if_nametoindex(interface->ifr_name); + return true; + } + + size_t addressSize = 0; + if (interface->ifr_route.destination != NULL) + addressSize += interface->ifr_route.destination->sa_len; + if (interface->ifr_route.mask != NULL) + addressSize += interface->ifr_route.mask->sa_len; + if (interface->ifr_route.gateway != NULL) + addressSize += interface->ifr_route.gateway->sa_len; + + interface = (struct ifreq*)((addr_t)interface + IF_NAMESIZE + + sizeof(struct route_entry) + addressSize); + } + + return false; +} diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index 63d3951147..b865805c1c 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -32,9 +32,9 @@ enum { FF_PIPE_BUFSIZ = 8192 }; -static inline int ffPipe2(int *fds, int flags) +static inline int ffPipe2(int* fds, int flags) { - #ifdef __APPLE__ + #ifndef FF_HAVE_PIPE2 if(pipe(fds) == -1) return -1; fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | flags); @@ -301,7 +301,12 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons if (proc) { char** argv = kvm_getargv(kd, proc, 0); - if (argv) ffStrbufSetS(exe, argv[0]); + if (argv) + { + const char* arg0 = argv[0]; + if (arg0[0] == '-') arg0++; + ffStrbufSetS(exe, arg0); + } } kvm_close(kd); diff --git a/src/data/help_format.txt b/src/data/help_format.txt index 0c77ba8632..5a66086e3a 100644 --- a/src/data/help_format.txt +++ b/src/data/help_format.txt @@ -21,6 +21,8 @@ In 2.24.0 or newer, `{~startIndex,endIndex}` can be specified to slice a string. If an index is omitted, 0 is used. For example, both `{~,0}` `{~0,}` and `{~,}` are same as `{~0,0}` and will always generate a empty string. If `,endIndex` is omitted or greater than the length of the string, the length of string is used. +In 2.36.0 or newer, `{$NUM}` can be specified to reference a constant defined in `display.constants`. `{$ENV_VAR}` can be specified to reference an environment variable. + If the value index is missing, meaning the placeholder is "{}", an internal counter sets the value index. This means that the format string "Values: {1} ({2})" is equivalent to "Values: {} ({})". Note that this counter only counts empty placeholders, so the format string "{2} {} {}" will contain the second value, then the first, and then the second again. diff --git a/src/detection/camera/camera_apple.m b/src/detection/camera/camera_apple.m index ab15fb99e5..45da1246fe 100644 --- a/src/detection/camera/camera_apple.m +++ b/src/detection/camera/camera_apple.m @@ -6,6 +6,11 @@ // warning: 'AVCaptureDeviceTypeExternalUnknown' is deprecated #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#ifdef MAC_OS_VERSION_14_0 +// To make fastfetch compiled on newer macOS versions runs on older ones +AVF_EXPORT __attribute__((weak_import)) AVCaptureDeviceType const AVCaptureDeviceTypeExternal; +#endif + const char* ffDetectCamera(FFlist* result) { #ifdef MAC_OS_X_VERSION_10_15 diff --git a/src/detection/cpu/cpu.c b/src/detection/cpu/cpu.c index 2b9d41dced..40ae66ac9c 100644 --- a/src/detection/cpu/cpu.c +++ b/src/detection/cpu/cpu.c @@ -10,10 +10,14 @@ const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu) const char* removeStrings[] = { " CPU", " FPU", " APU", " Processor", " Dual-Core", " Quad-Core", " Six-Core", " Eight-Core", " Ten-Core", - " 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core", - " with Radeon Graphics" + " 2-Core", " 4-Core", " 6-Core", " 8-Core", " 10-Core", " 12-Core", " 14-Core", " 16-Core" }; ffStrbufRemoveStrings(&cpu->name, ARRAY_SIZE(removeStrings), removeStrings); + uint32_t radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " w/ Radeon "); // w/ Radeon 780M Graphics + if (radeonGraphics >= cpu->name.length) + radeonGraphics = ffStrbufFirstIndexS(&cpu->name, " with Radeon "); + if (radeonGraphics < cpu->name.length) + ffStrbufSubstrBefore(&cpu->name, radeonGraphics); ffStrbufSubstrBeforeFirstC(&cpu->name, '@'); //Cut the speed output in the name as we append our own ffStrbufTrimRight(&cpu->name, ' '); //If we removed the @ in previous step there was most likely a space before it ffStrbufRemoveDupWhitespaces(&cpu->name); diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 8d5cbf0a4f..1226131e53 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -15,6 +15,7 @@ static double detectCpuTemp(const FFstrbuf* cpuName) case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break; case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break; case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break; + case 4: error = ffDetectSmcTemps(FF_TEMP_CPU_M4X, &result); break; default: error = "Unsupported Apple Silicon CPU"; } } diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 1df2ef57f8..a621418178 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -10,6 +10,8 @@ #include #include +#define FF_CPUINFO_PATH "/proc/cpuinfo" + static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) { //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface @@ -283,11 +285,7 @@ static const char* parseCpuInfo( while(ffStrbufGetline(&line, &len, cpuinfo)) { //Stop after reasonable information is acquired - if((*line == '\0' || *line == '\n') - #if __arm__ || __aarch64__ || __loongarch__ - && cpu->name.length > 0 // #1202 #1204 - #endif - ) + if((*line == '\0' || *line == '\n') && cpu->name.length > 0) { ffStrbufGetlineRestore(&line, &len, cpuinfo); break; @@ -296,28 +294,37 @@ static const char* parseCpuInfo( (void)( // arm64 doesn't have "model name"; arm32 does have "model name" but its value is not useful. // "Hardware" should always be used in this case - #if !(__arm__ || __aarch64__) + #if __x86_64__ || __i386__ (cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) || (cpu->vendor.length == 0 && ffParsePropLine(line, "vendor_id :", &cpu->vendor)) || (physicalCoresBuffer->length == 0 && ffParsePropLine(line, "cpu cores :", physicalCoresBuffer)) || (cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz :", cpuMHz)) || - #endif - - #if !(__x86_64__ || __i386__ || __arm__ || __aarch64__) + #elif __arm__ || __aarch64__ + (cpuImplementer->length == 0 && ffParsePropLine(line, "CPU implementer :", cpuImplementer)) || + (cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices + #elif __powerpc__ || __powerpc + (cpuMHz->length == 0 && ffParsePropLine(line, "clock :", cpuMHz)) || + (cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || + #elif __mips__ || __mips + (cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) || + #elif __loongarch__ + (cpu->name.length == 0 && ffParsePropLine(line, "Model Name :", &cpu->name)) || + (cpuMHz->length == 0 && ffParsePropLine(line, "CPU MHz :", cpuMHz)) || + #elif __riscv__ || __riscv (cpuIsa->length == 0 && ffParsePropLine(line, "isa :", cpuIsa)) || (cpuUarch->length == 0 && ffParsePropLine(line, "uarch :", cpuUarch)) || + #elif __s390x__ + (cpu->name.length == 0 && ffParsePropLine(line, "processor 0:", &cpu->name)) || + (cpu->vendor.length == 0 && ffParsePropLine(line, "vendor_id :", &cpu->vendor)) || + (cpuMHz->length == 0 && ffParsePropLine(line, "cpu MHz static :", cpuMHz)) || // This one cannot be detected because of early return + #else + (cpu->name.length == 0 && ffParsePropLine(line, "model name :", &cpu->name)) || + (cpu->name.length == 0 && ffParsePropLine(line, "model :", &cpu->name)) || + (cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) || + (cpu->name.length == 0 && ffParsePropLine(line, "hardware :", &cpu->name)) || + (cpu->name.length == 0 && ffParsePropLine(line, "processor :", &cpu->name)) || #endif - #if __arm__ || __aarch64__ - (cpuImplementer->length == 0 && ffParsePropLine(line, "CPU implementer :", cpuImplementer)) || - (cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices - #endif - #if __powerpc__ || __powerpc - (cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER - #endif - #if __mips__ - (cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) || //For MIPS - #endif false ); } @@ -414,6 +421,59 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) return true; } +#if __i386__ || __x86_64__ + +FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo) +{ + const char* p = cpuinfo->chars; + uint64_t low = 0, high = 0; + + while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), "\nphysical id\t:", strlen("\nphysical id\t:")))) + { + if (!p) break; + p += strlen("\nphysical id\t:"); + char* pend; + unsigned long id = strtoul(p, &pend, 10); + if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist? + high |= 1 << (id - 64); + else + low |= 1 << id; + p = pend; + } + + return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high)); +} + +FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFCPUResult* cpu) +{ + FF_STRBUF_AUTO_DESTROY cpuinfo = ffStrbufCreateA(PROC_FILE_BUFFSIZ); + if (!ffReadFileBuffer(FF_CPUINFO_PATH, &cpuinfo) || cpuinfo.length == 0) + return "ffReadFileBuffer(\"" FF_CPUINFO_PATH "\") failed"; + + FF_STRBUF_AUTO_DESTROY physicalCoresBuffer = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate(); + const char* error = parseCpuInfo(&cpuinfo, cpu, &physicalCoresBuffer, &cpuMHz, NULL,NULL, NULL); + if (error) return error; + + cpu->coresLogical = (uint16_t) get_nprocs_conf(); + cpu->coresOnline = (uint16_t) get_nprocs(); + cpu->packages = getPackageCount(&cpuinfo); + cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 0); // physical cores in single package + if (cpu->coresPhysical == 0) + cpu->coresPhysical = cpu->coresLogical; + else if (cpu->packages > 1) + cpu->coresPhysical *= cpu->packages; + + // Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252 + ffCPUDetectSpeedByCpuid(cpu); + if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0) + cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0); + + return NULL; +} + +#else + FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa) { // Always use the last part of the ISA string. Ref: #590 #1204 @@ -517,18 +577,20 @@ FF_MAYBE_UNUSED static void detectSocName(FFCPUResult* cpu) } } -FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo) +#ifdef __loongarch__ +FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const char* key) { const char* p = cpuinfo->chars; uint64_t low = 0, high = 0; + uint32_t keylen = (uint32_t) strlen(key); - while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), "\nphysical id\t:", strlen("\nphysical id\t:")))) + while ((p = memmem(p, cpuinfo->length - (uint32_t) (p - cpuinfo->chars), key, keylen))) { if (!p) break; - p += strlen("\nphysical id\t:"); + p += keylen; char* pend; unsigned long id = strtoul(p, &pend, 10); - if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist? + if (__builtin_expect(id > 64, false)) high |= 1 << (id - 64); else low |= 1 << id; @@ -537,69 +599,83 @@ FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo) return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high)); } +#endif -const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) +FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options, FFCPUResult* cpu) { - FF_STRBUF_AUTO_DESTROY cpuinfo = ffStrbufCreateA(PROC_FILE_BUFFSIZ); - if (!ffReadFileBuffer("/proc/cpuinfo", &cpuinfo) || cpuinfo.length == 0) - return "ffReadFileBuffer(\"/proc/cpuinfo\") failed"; - - cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET; - - FF_STRBUF_AUTO_DESTROY physicalCoresBuffer = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY cpuIsa = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY cpuUarch = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY cpuImplementerStr = ffStrbufCreate(); - - const char* error = parseCpuInfo(&cpuinfo, cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch, &cpuImplementerStr); - if (error) return error; - - cpu->coresLogical = (uint16_t) get_nprocs_conf(); + cpu->coresPhysical = cpu->coresLogical = (uint16_t) get_nprocs_conf(); cpu->coresOnline = (uint16_t) get_nprocs(); - cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical); - #if __x86_64__ || __i386__ - cpu->packages = getPackageCount(&cpuinfo); - if (cpu->packages > 1) - cpu->coresPhysical *= cpu->packages; // https://github.com/hykilpikonna/hyfetch/issues/374#issuecomment-2571578914 - #endif - - // Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252 - ffCPUDetectSpeedByCpuid(cpu); - if (!detectFrequency(cpu, options) || cpu->frequencyBase == 0) - cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0); #if __ANDROID__ detectAndroid(cpu); - #elif !(__x86_64__ || __i386__) + #else detectSocName(cpu); #endif - #if __arm__ || __aarch64__ - uint32_t cpuImplementer = (uint32_t) strtoul(cpuImplementerStr.chars, NULL, 16); - ffStrbufSetStatic(&cpu->vendor, hwImplId2Vendor(cpuImplementer)); + detectFrequency(cpu, options); - if (cpu->name.length == 0) - detectArmName(&cpuinfo, cpu, cpuImplementer); - #elif !(__x86_64__ || __i386__) if (cpu->name.length == 0) { - if(cpuUarch.length > 0) - { - if(cpu->name.length > 0) - ffStrbufAppendC(&cpu->name, ' '); - ffStrbufAppend(&cpu->name, &cpuUarch); - } + FF_STRBUF_AUTO_DESTROY cpuinfo = ffStrbufCreateA(PROC_FILE_BUFFSIZ); + if (!ffReadFileBuffer(FF_CPUINFO_PATH, &cpuinfo) || cpuinfo.length == 0) + return "ffReadFileBuffer(\"" FF_CPUINFO_PATH "\") failed"; + + FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY cpuIsa = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY cpuUarch = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY cpuImplementerStr = ffStrbufCreate(); - if(cpuIsa.length > 0) + const char* error = parseCpuInfo(&cpuinfo, cpu, NULL, &cpuMHz, &cpuIsa, &cpuUarch, &cpuImplementerStr); + if (error) return error; + + if (cpu->frequencyBase == 0) + cpu->frequencyBase = (uint32_t) ffStrbufToUInt(&cpuMHz, 0); + + #if __arm__ || __aarch64__ + uint32_t cpuImplementer = (uint32_t) strtoul(cpuImplementerStr.chars, NULL, 16); + ffStrbufSetStatic(&cpu->vendor, hwImplId2Vendor(cpuImplementer)); + + if (cpu->name.length == 0) + detectArmName(&cpuinfo, cpu, cpuImplementer); + #elif __riscv__ || __riscv + if (cpu->name.length == 0) { - parseIsa(&cpuIsa); - if(cpu->name.length > 0) - ffStrbufAppendC(&cpu->name, ' '); - ffStrbufAppend(&cpu->name, &cpuIsa); + if(cpuUarch.length > 0) + { + if(cpu->name.length > 0) + ffStrbufAppendC(&cpu->name, ' '); + ffStrbufAppend(&cpu->name, &cpuUarch); + } + + if(cpuIsa.length > 0) + { + parseIsa(&cpuIsa); + if(cpu->name.length > 0) + ffStrbufAppendC(&cpu->name, ' '); + ffStrbufAppend(&cpu->name, &cpuIsa); + } } + #elif __loongarch__ + cpu->packages = getLoongarchPropCount(&cpuinfo, "\npackage\t\t\t:"); + cpu->coresPhysical = getLoongarchPropCount(&cpuinfo, "\ncore\t\t\t:"); + if (cpu->packages > 1) cpu->coresPhysical *= cpu->packages; + #elif __s390x__ + if (ffStrbufSubstrAfterFirstS(&cpu->name, "machine = ")) + ffStrbufPrependS(&cpu->name, "Machine "); + #endif } - #endif return NULL; } +#endif + +const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) +{ + cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET; + + #if __x86_64__ || __i386__ + return detectCPUX86(options, cpu); + #else + return detectCPUOthers(options, cpu); + #endif +} diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 3ad7e745b0..b3ddf2e4e1 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -143,7 +143,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) for(struct statfs* fs = buf; fs < buf + size; ++fs) { - if(__builtin_expect(options->folders.length, 0)) + if(__builtin_expect(options->folders.length > 0, 0)) { if(!ffDiskMatchMountpoint(options, fs->f_mntonname)) continue; diff --git a/src/detection/displayserver/displayserver_haiku.cpp b/src/detection/displayserver/displayserver_haiku.cpp new file mode 100644 index 0000000000..b6f2e869de --- /dev/null +++ b/src/detection/displayserver/displayserver_haiku.cpp @@ -0,0 +1,72 @@ +extern "C" { +#include "displayserver.h" +#include "common/settings.h" +#include "common/processing.h" +} + +#include + +#include +#include + +extern "C" void ffConnectDisplayServerImpl(FFDisplayServerResult* ds); + +static void detectDisplays(FFDisplayServerResult* ds) +{ + // We need a valid be_app to query the app_server here. + BApplication app("application/x-vnd.fastfetch-cli-fastfetch"); + BScreen s{}; // default screen is the main one + bool main = true; + + do + { + if (!s.IsValid()) + continue; + + display_mode mode; + if (s.GetMode(&mode) != B_OK) + continue; + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateA(128); + monitor_info monitor; + // WARNING: This is experimental new Haiku API + status_t err = s.GetMonitorInfo(&monitor); + if (err == B_OK) { + ffStrbufSetF(&name, "%s %s", monitor.vendor, monitor.name); + } + + uint32_t width = (uint32_t) s.Frame().Width() + 1; + uint32_t height = (uint32_t) (uint32_t)s.Frame().Height() + 1; + double scaleFactor = (double) 1.0; + ffdsAppendDisplay(ds, + width, + height, + (double)mode.timing.pixel_clock * 1000 / (mode.timing.v_total * mode.timing.h_total), + (uint32_t) (width / scaleFactor + .5), + (uint32_t) (height / scaleFactor + .5), + 0, + 0, + 0, + 0, + &name, + FF_DISPLAY_TYPE_UNKNOWN, + main, + s.ID().id, + 0, + 0, + "BScreen" + ); + main = false; + } while (s.SetToNext() == B_OK); + + return; +} + +void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) +{ + ffStrbufSetStatic(&ds->wmProcessName, "app_server"); + ffStrbufSetStatic(&ds->wmPrettyName, "Application Server"); + ffStrbufSetStatic(&ds->dePrettyName, "Application Kit"); + + detectDisplays(ds); +} diff --git a/src/detection/dns/dns_linux.c b/src/detection/dns/dns_linux.c index 1179ea4a96..8bf1da0c2e 100644 --- a/src/detection/dns/dns_linux.c +++ b/src/detection/dns/dns_linux.c @@ -4,9 +4,15 @@ #include "util/mallocHelper.h" #include "util/stringUtils.h" +#ifdef __HAIKU__ +#define RESOLV_CONF "/system/settings/network/resolv.conf" +#else +#define RESOLV_CONF "/etc/resolv.conf" +#endif + const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) { - FF_AUTO_CLOSE_FILE FILE* file = fopen(FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf", "r"); + FF_AUTO_CLOSE_FILE FILE* file = fopen(FASTFETCH_TARGET_DIR_ROOT RESOLV_CONF, "r"); if (!file) return "fopen (" FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf) failed"; diff --git a/src/detection/font/font.h b/src/detection/font/font.h index f0c59bba7c..0f0e28d1f8 100644 --- a/src/detection/font/font.h +++ b/src/detection/font/font.h @@ -10,6 +10,7 @@ typedef struct FFFontResult * Linux / BSD: Qt, GTK2, GTK3, GTK4 * MacOS: System, User, System Mono, User Mono * Windows: Caption, Menu, Message, Status + * Haiku: Plain, Menu, Bold, Mono * Other: Unset, Unset, Unset, Unset */ FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS]; diff --git a/src/detection/font/font_haiku.cpp b/src/detection/font/font_haiku.cpp new file mode 100644 index 0000000000..5f64aecd8f --- /dev/null +++ b/src/detection/font/font_haiku.cpp @@ -0,0 +1,65 @@ +extern "C" { +#include "common/font.h" +#include "common/parsing.h" +#include "font.h" +} + +#include +#include +#include + +extern "C" { + const char* ffDetectFontImpl(FFFontResult* result); +} + +static void generateString(FFFontResult* font) +{ + const char* types[] = { "Plain", "Menu", "Bold", "Mono" }; + for(uint32_t i = 0; i < ARRAY_SIZE(types); ++i) + { + if(i == 0 || !ffStrbufEqual(&font->fonts[i - 1], &font->fonts[i])) + { + if(i > 0) + ffStrbufAppendS(&font->display, "], "); + ffStrbufAppendF(&font->display, "%s [%s", font->fonts[i].chars, types[i]); + } + else + { + ffStrbufAppendS(&font->display, " / "); + ffStrbufAppendS(&font->display, types[i]); + } + } + ffStrbufAppendC(&font->display, ']'); +} + +const char* ffDetectFontImpl(FFFontResult* result) +{ + struct menu_info menuInfo; + const BFont *f; + // We need a valid be_app to query the app_server here. + BApplication app("application/x-vnd.fastfetch-cli-fastfetch"); + + if ((f = be_plain_font) != NULL) + { + f->GetFamilyAndStyle(&menuInfo.f_family, &menuInfo.f_style); + ffStrbufAppendF(&result->fonts[0], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)f->Size()); + } + if (get_menu_info(&menuInfo) == B_OK) + { + ffStrbufAppendF(&result->fonts[1], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)menuInfo.font_size); + } + if ((f = be_bold_font) != NULL) + { + f->GetFamilyAndStyle(&menuInfo.f_family, &menuInfo.f_style); + ffStrbufAppendF(&result->fonts[2], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)f->Size()); + } + if ((f = be_fixed_font) != NULL) + { + f->GetFamilyAndStyle(&menuInfo.f_family, &menuInfo.f_style); + ffStrbufAppendF(&result->fonts[3], "%s %s (%dpt)", menuInfo.f_family, menuInfo.f_style, (int)f->Size()); + } + + generateString(result); + + return NULL; +} diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 551b8bffe7..793db62a7e 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -21,6 +21,7 @@ static double detectGpuTemp(const FFstrbuf* gpuName) case 1: error = ffDetectSmcTemps(FF_TEMP_GPU_M1X, &result); break; case 2: error = ffDetectSmcTemps(FF_TEMP_GPU_M2X, &result); break; case 3: error = ffDetectSmcTemps(FF_TEMP_GPU_M3X, &result); break; + case 4: error = ffDetectSmcTemps(FF_TEMP_GPU_M4X, &result); break; default: error = "Unsupported Apple Silicon GPU"; } } diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index 95e4c30587..9334c68402 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -68,6 +68,9 @@ gpu->type = device.location == MTLDeviceLocationBuiltIn ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; gpu->index = (uint32_t) device.locationNumber; #endif + + if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0) + gpu->shared.total = device.recommendedMaxWorkingSetSize; } return NULL; } diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index e91d7eeec3..d9539ba5f7 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -10,6 +10,7 @@ struct FFNvmlData { FF_LIBRARY_SYMBOL(nvmlDeviceGetPciInfo_v3) FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature) FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2) + FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo) FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores) FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo) FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates) @@ -36,6 +37,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetPciInfo_v3) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates) @@ -130,6 +132,15 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR result.memory->total = memory.used + memory.free; result.memory->used = memory.used; } + else + { + nvmlMemory_t memory_v1; + if (nvmlData.ffnvmlDeviceGetMemoryInfo(device, &memory_v1) == NVML_SUCCESS) + { + result.memory->total = memory_v1.total; + result.memory->used = memory_v1.used; + } + } } if (result.coreCount) diff --git a/src/detection/gpu/nvml.h b/src/detection/gpu/nvml.h index 693f9bff8c..40ff3a4955 100644 --- a/src/detection/gpu/nvml.h +++ b/src/detection/gpu/nvml.h @@ -56,6 +56,18 @@ typedef struct { // https://github.com/NVIDIA/nvidia-settings/issues/78#issuecomment-1012837988 enum { nvmlMemory_v2 = (unsigned int)(sizeof(nvmlMemory_v2_t) | (2 << 24U)) }; +// https://docs.nvidia.com/deploy/nvml-api/structnvmlMemory__t.html#structnvmlMemory__t +// Memory allocation information for a device (v1) +typedef struct +{ + // Total physical device memory (in bytes) + unsigned long long total; + // Unallocated device memory (in bytes) + unsigned long long free; + // Sum of Reserved and Allocated device memory (in bytes) + unsigned long long used; +} nvmlMemory_t; + // https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceEnumvs.html#group__nvmlDeviceEnumvs_1g805c0647be9996589fc5e3f6ff680c64 // Clock types typedef enum { @@ -124,6 +136,8 @@ extern nvmlReturn_t nvmlDeviceGetPciInfo_v3(nvmlDevice_t device, nvmlPciInfo_t* extern nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int* temp); // Retrieves the amount of used, free, reserved and total memory available on the device, in bytes. The reserved amount is supported on version 2 only extern nvmlReturn_t nvmlDeviceGetMemoryInfo_v2(nvmlDevice_t device, nvmlMemory_v2_t* memory); +// Retrieves the amount of used, free, total memory available on the device, in bytes. +extern nvmlReturn_t nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t *memory); // Gets the device's core count extern nvmlReturn_t nvmlDeviceGetNumGpuCores(nvmlDevice_t device, unsigned int* numCores); // Retrieves the maximum clock speeds for the device diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 7a8552811d..f9cc343d6f 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -18,23 +18,27 @@ #include #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined(__HAIKU__) #include #include #else #include #endif -#ifdef __sun +#if defined(__sun) || defined(__HAIKU__) #include #endif static const FFLocalIpNIFlag niFlagOptions[] = { { IFF_UP, "UP" }, { IFF_BROADCAST, "BROADCAST" }, +#ifdef IFF_DEBUG { IFF_DEBUG, "DEBUG" }, +#endif { IFF_LOOPBACK, "LOOPBACK" }, { IFF_POINTOPOINT, "POINTOPOINT" }, +#ifdef IFF_RUNNING { IFF_RUNNING, "RUNNING" }, +#endif { IFF_NOARP, "NOARP" }, { IFF_PROMISC, "PROMISC" }, { IFF_ALLMULTI, "ALLMULTI" }, @@ -64,6 +68,13 @@ static const FFLocalIpNIFlag niFlagOptions[] = { #endif #ifdef IFF_CANTCONFIG { IFF_CANTCONFIG, "CANTCONFIG" }, +#endif +#ifdef __HAIKU__ + { IFF_AUTOUP, "IAUTOUP" }, + { IFF_SIMPLEX, "SIMPLEX" }, + { IFF_LINK, "LINK" }, + { IFF_AUTO_CONFIGURED, "AUTO_CONFIGURED" }, + { IFF_CONFIGURING, "CONFIGURING" }, #endif // sentinel {}, @@ -128,8 +139,12 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING)) + if (!ifa->ifa_addr) + continue; +#ifdef IFF_RUNNING + if (!(ifa->ifa_flags & IFF_RUNNING)) continue; +#endif bool isDefaultRoute = ffStrEquals(defaultRouteIfName, ifa->ifa_name); if ((options->showType & FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT) && !isDefaultRoute) @@ -190,7 +205,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } - #if __FreeBSD__ || __OpenBSD__ || __APPLE__ || __NetBSD__ + #if __FreeBSD__ || __OpenBSD__ || __APPLE__ || __NetBSD__ || __HAIKU__ else if (ifa->ifa_addr->sa_family == AF_LINK) { if (!(options->showType & FF_LOCALIP_TYPE_MAC_BIT)) diff --git a/src/detection/memory/memory_haiku.c b/src/detection/memory/memory_haiku.c new file mode 100644 index 0000000000..b69ddfa346 --- /dev/null +++ b/src/detection/memory/memory_haiku.c @@ -0,0 +1,15 @@ +#include "memory.h" + +#include + +const char* ffDetectMemory(FFMemoryResult* ram) +{ + system_info info; + if (get_system_info(&info) != B_OK) + return "Error getting system info"; + + ram->bytesTotal = B_PAGE_SIZE * info.max_pages; + ram->bytesUsed = B_PAGE_SIZE * info.used_pages; + + return NULL; +} diff --git a/src/detection/os/os_haiku.c b/src/detection/os/os_haiku.c new file mode 100644 index 0000000000..f31fb28fbc --- /dev/null +++ b/src/detection/os/os_haiku.c @@ -0,0 +1,20 @@ +#include "os.h" +#include "common/io/io.h" + +#include + +void ffDetectOSImpl(FFOSResult* os) +{ + system_info info; + + ffStrbufSetStatic(&os->name, "Haiku"); + ffStrbufSetStatic(&os->prettyName, "Haiku"); + + ffStrbufSetStatic(&os->id, "haiku"); + + if (get_system_info(&info) != B_OK) + return; + ffStrbufAppendF(&os->version, "R%lld", info.kernel_version); + + // TODO: check kernel resources? +} diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 65e5670a5b..487c651a50 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -41,10 +41,13 @@ static bool parseOsRelease(const char* fileName, FFOSResult* result) // Common logic for detecting Armbian image version FF_MAYBE_UNUSED static bool detectArmbianVersion(FFOSResult* result) { - if (ffStrbufStartsWithS(&result->prettyName, "Armbian ")) // Official Armbian release images + // Possible values `PRETTY_NAME` starts with on Armbian: + // - `Armbian` for official releases + // - `Armbian_community` for community releases + // - `Armbian_Security` for images with kali repo added + // - `Armbian-unofficial` for an unofficial image built from source, e.g. during development and testing + if (ffStrbufStartsWithS(&result->prettyName, "Armbian")) ffStrbufSetS(&result->name, "Armbian"); - else if (ffStrbufStartsWithS(&result->prettyName, "Armbian-unofficial ")) // Unofficial Armbian image built from source - ffStrbufSetS(&result->name, "Armbian (custom build)"); else return false; ffStrbufSet(&result->idLike, &result->id); diff --git a/src/detection/packages/packages.c b/src/detection/packages/packages.c index 47cf99b6c5..373256568b 100644 --- a/src/detection/packages/packages.c +++ b/src/detection/packages/packages.c @@ -100,7 +100,7 @@ uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir) { bool ok = false; -#ifndef __sun +#if !defined(__sun) && !defined(__HAIKU__) if(entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK) ok = entry->d_type == (isdir ? DT_DIR : DT_REG); else diff --git a/src/detection/packages/packages_haiku.c b/src/detection/packages/packages_haiku.c new file mode 100644 index 0000000000..b66edefbbd --- /dev/null +++ b/src/detection/packages/packages_haiku.c @@ -0,0 +1,13 @@ +#include "packages.h" + +#include "common/io/io.h" + +void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) +{ + // TODO: Use the Package Kit C++ API instead (would account for disabled packages) + + if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT)) + result->pkg = ffPackagesGetNumElements(FASTFETCH_TARGET_DIR_ROOT "/system/packages", false); + if (!(options->disabled & FF_PACKAGES_FLAG_PKGSRC_BIT)) + result->pkgsrc = ffPackagesGetNumElements(FASTFETCH_TARGET_DIR_ROOT "/boot/home/config/packages", false); +} diff --git a/src/detection/processes/processes_haiku.c b/src/detection/processes/processes_haiku.c new file mode 100644 index 0000000000..8e373729e5 --- /dev/null +++ b/src/detection/processes/processes_haiku.c @@ -0,0 +1,14 @@ +#include "processes.h" + +#include + +const char* ffDetectProcesses(uint32_t* result) +{ + system_info info; + if (get_system_info(&info) != B_OK) + return "Error getting system info"; + + *result = info.used_teams; + + return NULL; +} diff --git a/src/detection/sound/sound_bsd.c b/src/detection/sound/sound_bsd.c index fcc2730ad5..fd6236cf15 100644 --- a/src/detection/sound/sound_bsd.c +++ b/src/detection/sound/sound_bsd.c @@ -4,29 +4,54 @@ #include #include +#include const char* ffDetectSound(FFlist* devices) { - char path[] = "/dev/mixer0"; + #ifndef __NetBSD__ int defaultDev = ffSysctlGetInt("hw.snd.default_unit", -1); - if (defaultDev == -1) return "sysctl(hw.snd.default_unit) failed"; + #else + int defaultDev; + { + char mixerp[12]; + ssize_t plen = readlink("/dev/mixer", mixerp, ARRAY_SIZE(mixerp)); + if (plen < 6) + return "readlink(/dev/mixer) failed"; + defaultDev = mixerp[plen - 1] - '0'; + if (defaultDev < 0 || defaultDev > 9) + return "Invalid mixer device"; + } + #endif - for (int idev = 0; idev <= 9; ++idev) + char path[] = "/dev/mixer0"; + + struct oss_sysinfo info = { .nummixers = 9 }; + + for (int idev = 0; idev <= info.nummixers; ++idev) { path[strlen("/dev/mixer")] = (char) ('0' + idev); FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR); if (fd < 0) break; + if (idev == 0) + { + if (ioctl(fd, SNDCTL_SYSINFO, &info) != 0) + return "ioctl(SNDCTL_SYSINFO) failed"; + } + uint32_t devmask = 0; if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) continue; if (!(devmask & SOUND_MASK_VOLUME)) continue; + #if defined(SOUND_MIXER_MUTE) && (SOUND_MIXER_MUTE != SOUND_MIXER_NONE) + #define FF_SOUND_HAVE_MIXER_MUTE 1 uint32_t mutemask = 0; - ioctl(fd, SOUND_MIXER_READ_MUTE, &mutemask); // doesn't seem to be available on DragonFly + ioctl(fd, SOUND_MIXER_READ_MUTE, &mutemask); + #endif struct oss_card_info ci = { .card = idev }; if (ioctl(fd, SNDCTL_CARDINFO, &ci) < 0) @@ -40,10 +65,12 @@ const char* ffDetectSound(FFlist* devices) ffStrbufInitS(&device->identifier, path); ffStrbufInitF(&device->name, "%s %s", ci.longname, ci.hw_info); ffStrbufTrimRightSpace(&device->name); - ffStrbufInitStatic(&device->platformApi, "OSS"); - device->volume = mutemask & SOUND_MASK_VOLUME - ? 0 - : ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2; + ffStrbufInitF(&device->platformApi, "%s %s", info.product, info.version); + device->volume = + #ifdef FF_SOUND_HAVE_MIXER_MUTE + mutemask & SOUND_MASK_VOLUME ? 0 : + #endif + ((uint8_t) volume /*left*/ + (uint8_t) (volume >> 8) /*right*/) / 2; device->active = true; device->main = defaultDev == idev; } diff --git a/src/detection/sound/sound_nbsd.c b/src/detection/sound/sound_nbsd.c new file mode 100644 index 0000000000..03d76ac861 --- /dev/null +++ b/src/detection/sound/sound_nbsd.c @@ -0,0 +1,50 @@ +#include "sound.h" +#include "common/io/io.h" + +#include +#include +#include +#include +#include + +const char* ffDetectSound(FFlist* devices) +{ + int defaultDev; + { + char audiop[12]; + ssize_t plen = readlink("/dev/audio", audiop, ARRAY_SIZE(audiop)); + if (plen < (ssize_t) strlen("audioN")) + return "readlink(/dev/audio) failed"; + defaultDev = audiop[plen - 1] - '0'; + if (defaultDev < 0 || defaultDev > 9) + return "Invalid audio device"; + } + + char path[] = "/dev/audio0"; + + for (int idev = 0; idev < 9; ++idev) + { + path[strlen("/dev/audio")] = (char) ('0' + idev); + FF_AUTO_CLOSE_FD int fd = open(path, O_RDWR); + if (fd < 0) break; + + audio_device_t ad; + if (ioctl(fd, AUDIO_GETDEV, &ad) < 0) + continue; + + audio_info_t ai; + if (ioctl(fd, AUDIO_GETINFO, &ai) < 0) + continue; + + FFSoundDevice* device = ffListAdd(devices); + ffStrbufInitS(&device->identifier, path); + ffStrbufInitS(&device->name, ad.name); + ffStrbufTrimRightSpace(&device->name); + ffStrbufInitF(&device->platformApi, "%s", "SunAudio"); + device->volume = (uint8_t) (ai.play.gain * 100 / AUDIO_MAX_GAIN); + device->active = true; + device->main = defaultDev == idev; + } + + return NULL; +} diff --git a/src/detection/sound/sound_obsd.c b/src/detection/sound/sound_obsd.c new file mode 100644 index 0000000000..baac25dd52 --- /dev/null +++ b/src/detection/sound/sound_obsd.c @@ -0,0 +1,86 @@ +#include "sound.h" +#include "util/stringUtils.h" + +#include +#include + +static void close_hdl(struct sioctl_hdl** phdl) +{ + assert(phdl); + if (*phdl) sioctl_close(*phdl); +} + +enum { MAX_CHANNEL_NUM = 8 }; + +typedef struct FFSoundDeviceBundle +{ + char name[SIOCTL_DISPLAYMAX]; + double level[MAX_CHANNEL_NUM]; + uint8_t iLevel; + bool mute[MAX_CHANNEL_NUM]; + uint8_t iMute; +} FFSoundDeviceBundle; + +static void enumerate_props(FFSoundDeviceBundle* bundle, struct sioctl_desc* desc, int val) +{ + if (!desc) return; + + if (desc->type == SIOCTL_SEL) + { + if (desc->display[0] != '\0' && ffStrEquals(desc->node0.name, "server")) + ffStrCopy(bundle->name, desc->display, SIOCTL_DISPLAYMAX); + return; + } + + if (desc->type != SIOCTL_NUM && desc->type != SIOCTL_SW) + return; + + if (!ffStrEquals(desc->node0.name, "output")) + return; + + if (ffStrEquals(desc->func, "level")) + { + if (__builtin_expect(bundle->iLevel == MAX_CHANNEL_NUM, false)) + return; + bundle->level[bundle->iLevel] = (double) val / (double) desc->maxval; + ++bundle->iLevel; + } + else if (ffStrEquals(desc->func, "mute")) + { + if (__builtin_expect(bundle->iMute == MAX_CHANNEL_NUM, false)) + return; + bundle->mute[bundle->iMute] = !!val; + ++bundle->iMute; + } +} + +const char* ffDetectSound(FFlist* devices) +{ + __attribute__((__cleanup__(close_hdl))) struct sioctl_hdl* hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0); + if (!hdl) return "sio_open() failed"; + + FFSoundDeviceBundle bundle = {}; + if (sioctl_ondesc(hdl, (void*) enumerate_props, &bundle) == 0) + return "sioctl_ondesc() failed"; + + if (bundle.iLevel != bundle.iMute || bundle.iLevel == 0) + return "Unexpecd sioctl_ondesc() result"; + + FFSoundDevice* device = ffListAdd(devices); + ffStrbufInitS(&device->name, bundle.name); + ffStrbufInitS(&device->identifier, SIO_DEVANY); + ffStrbufInitStatic(&device->platformApi, "sndio"); + device->active = true; + device->main = true; + device->volume = 0; + + double totalLevel = 0; + for (uint8_t i = 0; i < bundle.iLevel; ++i) + { + if (!bundle.mute[i]) + totalLevel += bundle.level[i]; + } + device->volume = (uint8_t) (totalLevel * 100 / bundle.iLevel); + + return NULL; +} diff --git a/src/detection/swap/swap_haiku.c b/src/detection/swap/swap_haiku.c new file mode 100644 index 0000000000..b61f213e77 --- /dev/null +++ b/src/detection/swap/swap_haiku.c @@ -0,0 +1,17 @@ +#include "swap.h" + +#include + +enum { FFMaxNSwap = 8 }; + +const char* ffDetectSwap(FFSwapResult* swap) +{ + system_info info; + if (get_system_info(&info) != B_OK) + return "Error getting system info"; + + swap->bytesTotal = B_PAGE_SIZE * info.max_swap_pages; + swap->bytesUsed = B_PAGE_SIZE * (info.max_swap_pages - info.free_swap_pages); + + return NULL; +} diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index f29902727d..21c1144887 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -669,6 +669,12 @@ FF_MAYBE_UNUSED static bool getTerminalVersionPtyxis(FF_MAYBE_UNUSED FFstrbuf* e FF_MAYBE_UNUSED static bool getTerminalVersionTilix(FFstrbuf* exe, FFstrbuf* version) { + if (exe->chars[0] == '/') + { + ffBinaryExtractStrings(exe->chars, extractGeneralVersion, version, (uint32_t) strlen("0.0.0")); + if (version->length) return true; + } + if(ffProcessAppendStdOut(version, (char* const[]) { exe->chars, "--version", diff --git a/src/detection/uptime/uptime_haiku.c b/src/detection/uptime/uptime_haiku.c new file mode 100644 index 0000000000..46af1115ec --- /dev/null +++ b/src/detection/uptime/uptime_haiku.c @@ -0,0 +1,11 @@ +#include "uptime.h" +#include "common/time.h" + +#include + +const char* ffDetectUptime(FFUptimeResult* result) +{ + result->uptime = system_time() / 1000; + result->bootTime = (real_time_clock_usecs() / 1000) - result->uptime; + return NULL; +} diff --git a/src/detection/version/version.c b/src/detection/version/version.c index a979bde5f5..ce493344a8 100644 --- a/src/detection/version/version.c +++ b/src/detection/version/version.c @@ -42,6 +42,8 @@ #define FF_SYSNAME "OpenBSD" #elif defined(__NetBSD__) #define FF_SYSNAME "NetBSD" +#elif defined(__HAIKU__) + #define FF_SYSNAME "Haiku" #else #define FF_SYSNAME "unknown" #endif diff --git a/src/logo/ascii/endeavour.txt b/src/logo/ascii/endeavouros.txt similarity index 100% rename from src/logo/ascii/endeavour.txt rename to src/logo/ascii/endeavouros.txt diff --git a/src/logo/ascii/endeavour_small.txt b/src/logo/ascii/endeavouros_small.txt similarity index 100% rename from src/logo/ascii/endeavour_small.txt rename to src/logo/ascii/endeavouros_small.txt diff --git a/src/logo/ascii/filotimo.txt b/src/logo/ascii/filotimo.txt new file mode 100644 index 0000000000..48ebb26d81 --- /dev/null +++ b/src/logo/ascii/filotimo.txt @@ -0,0 +1,20 @@ +O ' +lk: ;xX. .0K ' +lodk ;lldK' .lld0O :okX; +lloo0 ;lllld0: .lllllxKx :clllkKk +llllo, ;llllloox .clllllloxK :cclllllx0N +lllll, ;llllllll .cclllllllo' :cccclllllld +cllll, ;cclllllc .ccccllllll' :cccccclllll +cllll, ;cccllllc ccccccllll' ::cccccclllc +ccccl, ;cccccllc :cccccccll' :::ccccccclc +ccccc, ;cccccccc ::cccccccl' :::::ccccccc +:cccc, ;:ccccccc ::::cccccc' :::::::ccccc +:cccc, ;:::ccccc ::::::cccc' :;::::::ccc: +:::cc, ;:::::ccc ;:::::::cc' :;;:::::::c: +:::::, ;:::::::c ;;:::::::c' :;;;;::::::: +:::::, ;;::::::c ;;;;::::::' :;;;;;:::::: +;::::, ,;;;::::c ,;;;;;::::' ';;;;;;:::: +';;::, ;;;;::: .;;;;;::' .;;;;;:: + ;;;, ;;;;: .;;;:' ;;;: + ,;, ,;: ';' + ., \ No newline at end of file diff --git a/src/logo/ascii/kde.txt b/src/logo/ascii/kdeneon.txt similarity index 100% rename from src/logo/ascii/kde.txt rename to src/logo/ascii/kdeneon.txt diff --git a/src/logo/ascii/nexalinux.txt b/src/logo/ascii/nexalinux.txt new file mode 100644 index 0000000000..4372a75077 --- /dev/null +++ b/src/logo/ascii/nexalinux.txt @@ -0,0 +1,19 @@ + ******** + ***************** + ********************** + ************************** +********** ********** +******* ********* +****** ******** +******* ******* +********* ****** ******* + ***************** ****** + *************** ******* + *********** ******* + ******** + ******** + ********* + ********** + ********* + ******* + *** diff --git a/src/logo/ascii/reborn.txt b/src/logo/ascii/rebornos.txt similarity index 100% rename from src/logo/ascii/reborn.txt rename to src/logo/ascii/rebornos.txt diff --git a/src/logo/ascii/reborn_small.txt b/src/logo/ascii/rebornos_small.txt similarity index 100% rename from src/logo/ascii/reborn_small.txt rename to src/logo/ascii/rebornos_small.txt diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 18ab417ec3..f847c230ac 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -384,11 +384,11 @@ static const FFlogo A[] = { .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .lines = FASTFETCH_DATATEXT_LOGO_ARCH_OLD, .colors = { - FF_COLOR_FG_CYAN, + FF_COLOR_FG_BLUE, FF_COLOR_FG_WHITE, }, .colorTitle = FF_COLOR_FG_DEFAULT, - .colorKeys = FF_COLOR_FG_CYAN, + .colorKeys = FF_COLOR_FG_BLUE, }, // Archlabs { @@ -1428,10 +1428,10 @@ static const FFlogo E[] = { .colorKeys = FF_COLOR_FG_MAGENTA, .colorTitle = FF_COLOR_FG_GREEN, }, - // Endeavour + // EndeavourOS { - .names = {"Endeavour", "endeavour-linux", "endeavouros", "endeavouros-linux"}, - .lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR, + .names = {"EndeavourOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUROS, .colors = { FF_COLOR_FG_MAGENTA, FF_COLOR_FG_RED, @@ -1440,11 +1440,11 @@ static const FFlogo E[] = { .colorKeys = FF_COLOR_FG_MAGENTA, .colorTitle = FF_COLOR_FG_RED, }, - // EndeavourSmall + // EndeavourOSSmall { - .names = {"Endeavour_small", "endeavour-linux_small", "endeavouros_small", "endeavouros-linux_small"}, + .names = {"EndeavourOS_small"}, .type = FF_LOGO_LINE_TYPE_SMALL_BIT, - .lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUR_SMALL, + .lines = FASTFETCH_DATATEXT_LOGO_ENDEAVOUROS_SMALL, .colors = { FF_COLOR_FG_RED, FF_COLOR_FG_MAGENTA, @@ -1690,6 +1690,16 @@ static const FFlogo F[] = { .colorKeys = FF_COLOR_FG_BLUE, .colorTitle = FF_COLOR_FG_WHITE, }, + // Filotimo + { + .names = {"filotimo"}, + .lines = FASTFETCH_DATATEXT_LOGO_FILOTIMO, + .colors = { + FF_COLOR_FG_BLUE, + }, + .colorKeys = FF_COLOR_FG_BLUE, + .colorTitle = FF_COLOR_FG_WHITE, + }, // Finnix { .names = {"Finnix"}, @@ -1998,7 +2008,7 @@ static const FFlogo H[] = { .colors = { FF_COLOR_FG_RED, FF_COLOR_FG_YELLOW, - FF_COLOR_FG_WHITE, + FF_COLOR_FG_DEFAULT, FF_COLOR_FG_GREEN, }, .colorKeys = FF_COLOR_FG_RED, @@ -2294,12 +2304,13 @@ static const FFlogo K[] = { FF_COLOR_FG_WHITE } }, - // KDENeon + // KDE Neon { - .names = {"KDE", "kde-neon", "kde neon"}, - .lines = FASTFETCH_DATATEXT_LOGO_KDE, + .names = {"KDE Neon"}, // Distro ID is `neon`; Distro name is `KDE Neon` + .lines = FASTFETCH_DATATEXT_LOGO_KDENEON, .colors = { FF_COLOR_FG_GREEN, + FF_COLOR_FG_DEFAULT, }, }, // Kibojoe @@ -2560,7 +2571,7 @@ static const FFlogo L[] = { }, // LinuxMintOld { - .names = {"linux-mint_old", "linux-mint-old"}, + .names = {"linuxmint_old", "linux-mint_old"}, .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .lines = FASTFETCH_DATATEXT_LOGO_MINT_OLD, .colors = { @@ -3056,6 +3067,15 @@ static const FFlogo N[] = { FF_COLOR_FG_WHITE, }, }, + // NexaLinux + { + .names = {"nexalinux"}, + .lines = FASTFETCH_DATATEXT_LOGO_NEXALINUX, + .colors = { + FF_COLOR_FG_LIGHT_BLUE, + FF_COLOR_FG_LIGHT_BLUE, + }, + }, // Nitrux { .names = {"Nitrux"}, @@ -3288,7 +3308,7 @@ static const FFlogo O[] = { }, // OpenSuse { - .names = {"opensuse", "open_suse", "open-suse"}, + .names = {"opensuse"}, .lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE, .colors = { FF_COLOR_FG_GREEN, @@ -3299,7 +3319,7 @@ static const FFlogo O[] = { }, // OpenSuseSmall { - .names = {"opensuse_small", "open_suse_small", "open-suse_small"}, + .names = {"opensuse_small"}, .type = FF_LOGO_LINE_TYPE_SMALL_BIT, .lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE_SMALL, .colors = { @@ -3318,7 +3338,7 @@ static const FFlogo O[] = { }, // OpenSuseLeap { - .names = {"opensuse_leap", "opensuse leap"}, + .names = {"opensuse-leap", "opensuse leap"}, .lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE_LEAP, .colors = { FF_COLOR_FG_WHITE, @@ -3328,7 +3348,7 @@ static const FFlogo O[] = { }, // OpenSuseLeapOld { - .names = {"opensuse_leap_old", "opensuse leap_old"}, + .names = {"opensuse-leap_old", "opensuse leap_old"}, .lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE_LEAP_OLD, .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .colors = { @@ -3339,7 +3359,7 @@ static const FFlogo O[] = { }, // OpenSuseTumbleweed { - .names = {"opensuse-tumbleweed", "opensuse_tumbleweed"}, + .names = {"opensuse-tumbleweed"}, .lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE_TUMBLEWEED, .colors = { FF_COLOR_FG_WHITE, @@ -3349,7 +3369,7 @@ static const FFlogo O[] = { }, // OpenSuseTumbleweedOld { - .names = {"opensuse-tumbleweed-old", "opensuse_tumbleweed-old"}, + .names = {"opensuse-tumbleweed-old"}, .lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE_TUMBLEWEED_OLD, .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .colors = { @@ -3360,7 +3380,7 @@ static const FFlogo O[] = { }, // openSUSESlowroll { - .names = {"opensuse_slowroll", "opensuse-slowroll", "opensuse-tumbleweed-slowroll"}, + .names = {"opensuse-slowroll", "opensuse-tumbleweed-slowroll"}, .lines = FASTFETCH_DATATEXT_LOGO_OPENSUSE_SLOWROLL, .colors = { FF_COLOR_FG_WHITE, @@ -3677,7 +3697,7 @@ static const FFlogo P[] = { }, // Pop { - .names = {"pop", "popos", "pop_os", "pop-linux"}, + .names = {"pop", "popos"}, .lines = FASTFETCH_DATATEXT_LOGO_POP, .colors = { FF_COLOR_FG_CYAN, @@ -3688,7 +3708,7 @@ static const FFlogo P[] = { }, // PopSmall { - .names = {"pop_small", "popos_small", "pop_os_small", "pop-linux-small"}, + .names = {"pop_small", "popos_small"}, .type = FF_LOGO_LINE_TYPE_SMALL_BIT, .lines = FASTFETCH_DATATEXT_LOGO_POP_SMALL, .colors = { @@ -3881,10 +3901,10 @@ static const FFlogo R[] = { FF_COLOR_FG_WHITE, }, }, - // Reborn + // RebornOS { - .names = {"Reborn", "Reborn OS", "reborn-os", "rebornos", "rebornos-linux", "reborn-os-linux"}, - .lines = FASTFETCH_DATATEXT_LOGO_REBORN, + .names = {"RebornOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_REBORNOS, .colors = { FF_COLOR_FG_BLACK, FF_COLOR_FG_BLUE, @@ -3895,9 +3915,9 @@ static const FFlogo R[] = { }, // RebornSmall { - .names = {"Reborn_small", "Reborn OS_small", "reborn-os-small", "rebornos_small", "rebornos-linux-small", "reborn-os-linux-small"}, + .names = {"RebornOS_small"}, .type = FF_LOGO_LINE_TYPE_SMALL_BIT, - .lines = FASTFETCH_DATATEXT_LOGO_REBORN_SMALL, + .lines = FASTFETCH_DATATEXT_LOGO_REBORNOS_SMALL, .colors = { FF_COLOR_FG_BLUE, }, @@ -3960,7 +3980,7 @@ static const FFlogo R[] = { }, // RedstarOS { - .names = {"redstar", "redstar-os", "redstaros", "redstaros-linux", "redstar-os-linux"}, + .names = {"redstar", "redstar-os", "redstaros"}, .lines = FASTFETCH_DATATEXT_LOGO_REDSTAR, .colors = { FF_COLOR_FG_RED, @@ -4264,7 +4284,7 @@ static const FFlogo S[] = { }, // Slackware { - .names = {"slackware", "slackware-linux", "slackwarelinux"}, + .names = {"Slackware"}, .lines = FASTFETCH_DATATEXT_LOGO_SLACKWARE, .colors = { FF_COLOR_FG_BLUE, @@ -4275,7 +4295,7 @@ static const FFlogo S[] = { }, // SlackwareSmall { - .names = {"slackware-small", "slackware-linux-small", "slackware_small", "slackwarelinux_small"}, + .names = {"Slackware_small"}, .type = FF_LOGO_LINE_TYPE_SMALL_BIT, .lines = FASTFETCH_DATATEXT_LOGO_SLACKWARE_SMALL, .colors = { @@ -4334,7 +4354,7 @@ static const FFlogo S[] = { }, // SolarisSmall { - .names = {"solaris-small", "solaris_small", "sunos-small", "sunos_small"}, + .names = {"solaris_small", "sunos_small"}, .type = FF_LOGO_LINE_TYPE_SMALL_BIT, .lines = FASTFETCH_DATATEXT_LOGO_SOLARIS_SMALL, .colors = { @@ -4345,7 +4365,7 @@ static const FFlogo S[] = { }, // Solus { - .names = {"solus", "solus-linux"}, + .names = {"Solus", "solus-linux"}, .lines = FASTFETCH_DATATEXT_LOGO_SOLUS, .colors = { FF_COLOR_FG_BLUE, diff --git a/src/logo/logo.c b/src/logo/logo.c index c1c2b38d68..8e95f86207 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -387,13 +387,30 @@ static const FFlogo* logoGetBuiltinDetected(FFLogoSize size) if(logo != NULL) return logo; - logo = logoGetBuiltin(&os->prettyName, size); - if(logo != NULL) - return logo; + if (ffStrbufContainC(&os->idLike, ' ')) + { + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + for ( + uint32_t start = 0, end = ffStrbufFirstIndexC(&os->idLike, ' '); + true; + start = end + 1, end = ffStrbufNextIndexC(&os->idLike, start, ' ') + ) + { + ffStrbufSetNS(&buf, end - start, os->idLike.chars + start); + logo = logoGetBuiltin(&buf, size); + if(logo != NULL) + return logo; - logo = logoGetBuiltin(&os->idLike, size); - if(logo != NULL) - return logo; + if (end >= os->idLike.length) + break; + } + } + else + { + logo = logoGetBuiltin(&os->idLike, size); + if(logo != NULL) + return logo; + } logo = logoGetBuiltin(&instance.state.platform.sysinfo.name, size); if(logo != NULL) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index fdf4276822..604f17615f 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -75,7 +75,7 @@ void ffPrintDisplay(FFDisplayOptions* options) { FFDisplayResult* result = FF_LIST_GET(FFDisplayResult, dsResult->displays, i); uint32_t moduleIndex = dsResult->displays.length == 1 ? 0 : i + 1; - const char* displayType = result->type == FF_DISPLAY_TYPE_UNKNOWN ? NULL : result->type == FF_DISPLAY_TYPE_BUILTIN ? "built-in" : "external"; + const char* displayType = result->type == FF_DISPLAY_TYPE_UNKNOWN ? NULL : result->type == FF_DISPLAY_TYPE_BUILTIN ? "Built-in" : "External"; ffStrbufClear(&key); if(options->moduleArgs.key.length == 0) @@ -448,7 +448,7 @@ static FFModuleBaseInfo ffModuleInfo = { {"Screen scaled width (in pixels)", "scaled-width"}, {"Screen scaled height (in pixels)", "scaled-height"}, {"Screen name", "name"}, - {"Screen type (builtin, external or unknown)", "type"}, + {"Screen type (Built-in or External)", "type"}, {"Screen rotation (in degrees)", "rotation"}, {"True if being the primary screen", "is-primary"}, {"Screen physical width (in millimeters)", "physical-width"}, diff --git a/src/util/apple/smc_temps.c b/src/util/apple/smc_temps.c index 1f9d8179dc..483d51e8d5 100644 --- a/src/util/apple/smc_temps.c +++ b/src/util/apple/smc_temps.c @@ -269,7 +269,7 @@ static const char *smcReadValue(io_connect_t conn, const UInt32Char_t key, doubl return NULL; } -static bool detectTemp(io_connect_t conn, const char *sensor, double* sum) +static bool detectTemp(io_connect_t conn, const char* sensor, double* sum) { double temp = 0; const char* error = smcReadValue(conn, sensor, &temp); @@ -280,7 +280,7 @@ static bool detectTemp(io_connect_t conn, const char *sensor, double* sum) return true; } -const char *ffDetectSmcTemps(enum FFTempType type, double *result) +const char* ffDetectSmcTemps(enum FFTempType type, double* result) { static io_connect_t conn; if (!conn) @@ -353,6 +353,21 @@ const char *ffDetectSmcTemps(enum FFTempType type, double *result) count += detectTemp(conn, "Tf4E", result); // CPU performance core 12 break; + case FF_TEMP_CPU_M4X: + count += detectTemp(conn, "Te05", result); // CPU efficiency core 1 + count += detectTemp(conn, "Te0S", result); // CPU efficiency core 2 + count += detectTemp(conn, "Te09", result); // CPU efficiency core 3 + count += detectTemp(conn, "Te0H", result); // CPU efficiency core 4 + count += detectTemp(conn, "Tp01", result); // CPU performance core 1 + count += detectTemp(conn, "Tp05", result); // CPU performance core 2 + count += detectTemp(conn, "Tp09", result); // CPU performance core 3 + count += detectTemp(conn, "Tp0D", result); // CPU performance core 4 + count += detectTemp(conn, "Tp0V", result); // CPU performance core 5 + count += detectTemp(conn, "Tp0Y", result); // CPU performance core 6 + count += detectTemp(conn, "Tp0b", result); // CPU performance core 7 + count += detectTemp(conn, "Tp0e", result); // CPU performance core 8 + break; + case FF_TEMP_GPU_INTEL: count += detectTemp(conn, "TCGC", result); // GPU Intel Graphics goto gpu_unknown; @@ -390,6 +405,19 @@ const char *ffDetectSmcTemps(enum FFTempType type, double *result) count += detectTemp(conn, "Tf2A", result); // GPU 8 break; + case FF_TEMP_GPU_M4X: + count += detectTemp(conn, "Tg0G", result); // GPU 1 (Basic) + count += detectTemp(conn, "Tg0H", result); // GPU 2 (Basic) + count += detectTemp(conn, "Tg1U", result); // GPU 1 (Pro / Max) + count += detectTemp(conn, "Tg1k", result); // GPU 2 (Pro / Max) + count += detectTemp(conn, "Tg0K", result); // GPU 3 + count += detectTemp(conn, "Tg0L", result); // GPU 4 + count += detectTemp(conn, "Tg0d", result); // GPU 5 + count += detectTemp(conn, "Tg0e", result); // GPU 6 + count += detectTemp(conn, "Tg0j", result); // GPU 7 + count += detectTemp(conn, "Tg0k", result); // GPU 8 + break; + case FF_TEMP_BATTERY: count += detectTemp(conn, "TB1T", result); // Battery count += detectTemp(conn, "TB2T", result); // Battery diff --git a/src/util/apple/smc_temps.h b/src/util/apple/smc_temps.h index 0d6e104c10..4adc7a607b 100644 --- a/src/util/apple/smc_temps.h +++ b/src/util/apple/smc_temps.h @@ -15,6 +15,7 @@ enum FFTempType FF_TEMP_CPU_M1X, FF_TEMP_CPU_M2X, FF_TEMP_CPU_M3X, + FF_TEMP_CPU_M4X, FF_TEMP_GPU_INTEL, FF_TEMP_GPU_AMD, @@ -22,10 +23,11 @@ enum FFTempType FF_TEMP_GPU_M1X, FF_TEMP_GPU_M2X, FF_TEMP_GPU_M3X, + FF_TEMP_GPU_M4X, FF_TEMP_BATTERY, FF_TEMP_MEMORY, }; -const char *ffDetectSmcTemps(enum FFTempType type, double* result); +const char* ffDetectSmcTemps(enum FFTempType type, double* result); diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index c8b5c7c65a..fbf59d85fe 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -14,6 +14,9 @@ #include #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #include +#elif defined(__HAIKU__) + #include + #include #endif static void getExePath(FFPlatform* platform) @@ -47,6 +50,17 @@ static void getExePath(FFPlatform* platform) ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1); if (exePathLen >= 0) exePath[exePathLen] = '\0'; + #elif defined(__HAIKU__) + size_t exePathLen = 0; + image_info info; + int32 cookie = 0; + + while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { + if (info.type == B_APP_IMAGE) { + exePathLen = strlcpy(exePath, info.name, PATH_MAX); + break; + } + } #endif if (exePathLen > 0) { @@ -117,6 +131,9 @@ static void getConfigDirs(FFPlatform* platform) ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Preferences/"); ffPlatformPathAddHome(&platform->configDirs, platform, "Library/Application Support/"); #endif + #if defined(__HAIKU__) + ffPlatformPathAddHome(&platform->configDirs, platform, "config/settings/"); + #endif ffPlatformPathAddHome(&platform->configDirs, platform, ""); platformPathAddEnv(&platform->configDirs, "XDG_CONFIG_DIRS"); @@ -185,6 +202,12 @@ static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts) ffStrbufAppendS(&info->name, uts->sysname); ffStrbufAppendS(&info->release, uts->release); ffStrbufAppendS(&info->version, uts->version); + #ifdef __HAIKU__ + /* historical reason */ + if (ffStrEquals(uts->machine, "BePC")) + ffStrbufSetStatic(&info->architecture, "i386"); + else + #endif ffStrbufAppendS(&info->architecture, uts->machine); ffStrbufInit(&info->displayVersion); diff --git a/tests/format.c b/tests/format.c index 6b7d0a727a..0e94cec87f 100644 --- a/tests/format.c +++ b/tests/format.c @@ -2,6 +2,8 @@ #include "util/textModifier.h" #include "fastfetch.h" +#include + static void verify(const char* format, const char* arg, const char* expected, int lineNo) { FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); @@ -113,6 +115,26 @@ int main(void) VERIFY("output({?1}OK{?}{/1}NOT OK{/})", "", "output(NOT OK)"); } + #ifndef _WIN32 // Windows doesn't have setenv + { + ffListInit(&instance.config.display.constants, sizeof(FFstrbuf)); + ffStrbufInitStatic(ffListAdd(&instance.config.display.constants), "CONST1"); + ffStrbufInitStatic(ffListAdd(&instance.config.display.constants), "CONST2"); + setenv("FF_TEST", "ENVVAR", 1); + VERIFY("output({$FF_TEST})", "", "output(ENVVAR)"); + VERIFY("output({$1})", "", "output(CONST1)"); + VERIFY("output({$FF_TEST}{$1})", "", "output(ENVVARCONST1)"); + VERIFY("output({$1}{$FF_TEST})", "", "output(CONST1ENVVAR)"); + VERIFY("output({$FF_TEST}{$FF_TEST})", "", "output(ENVVARENVVAR)"); + VERIFY("output({$1}{$-1})", "", "output(CONST1CONST2)"); + + VERIFY("output({$FF_INVAL})", "", "output({$FF_INVAL})"); + VERIFY("output({$9}{$0}${-9})", "", "output({$9}{$0}${-9})"); + VERIFY("output({$1NO})", "", "output({$1NO})"); + ffListDestroy(&instance.config.display.constants); + } + #endif + //Success puts("\033[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); }