Merge pull request #1551 from fastfetch-cli/dev
Some checks are pending
CI / spellcheck (push) Waiting to run
CI / No-features-test (push) Waiting to run
CI / Linux-amd64 (push) Waiting to run
CI / Linux-aarch64 (push) Waiting to run
CI / Linux-armv7 (push) Waiting to run
CI / Linux-armv6 (push) Waiting to run
CI / Linux-riscv64 (push) Waiting to run
CI / Linux-ppc64le (push) Waiting to run
CI / Linux-s390x (push) Waiting to run
CI / Musl-amd64 (push) Waiting to run
CI / macOS-universal (push) Waiting to run
CI / SunOS-amd64 (push) Waiting to run
CI / FreeBSD-amd64 (push) Waiting to run
CI / DragonFly-amd64 (push) Waiting to run
CI / OpenBSD-amd64 (push) Waiting to run
CI / NetBSD-amd64 (push) Waiting to run
CI / Windows-amd64 (push) Waiting to run
CI / Release (push) Blocked by required conditions

Release: v2.36.0
This commit is contained in:
Carter Li 2025-02-10 10:07:31 +08:00 committed by GitHub
commit 9d8a83349c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 1096 additions and 174 deletions

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
fastfetch (2.35.0) jammy; urgency=medium
* Update to 2.35.0
-- Carter Li <zhangsongcui@live.cn> Sun, 26 Jan 2025 10:15:22 +0800
fastfetch (2.34.1) jammy; urgency=medium
* Update to 2.34.1

2
debian/files vendored
View File

@ -1 +1 @@
fastfetch_2.34.1_source.buildinfo universe/utils optional
fastfetch_2.35.0_source.buildinfo universe/utils optional

View File

@ -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": {

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1,63 @@
#include "netif.h"
#include "common/io/io.h"
#include "util/mallocHelper.h"
#include <arpa/inet.h>
#include <net/if.h>
#include <net/route.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <stdio.h>
// 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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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";
}
}

View File

@ -10,6 +10,8 @@
#include <unistd.h>
#include <dirent.h>
#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__)
(cpuIsa->length == 0 && ffParsePropLine(line, "isa :", cpuIsa)) ||
(cpuUarch->length == 0 && ffParsePropLine(line, "uarch :", cpuUarch)) ||
#endif
#if __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 __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";
if(cpuIsa.length > 0)
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, 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
}

View File

@ -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;

View File

@ -0,0 +1,72 @@
extern "C" {
#include "displayserver.h"
#include "common/settings.h"
#include "common/processing.h"
}
#include <math.h>
#include <Application.h>
#include <Screen.h>
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);
}

View File

@ -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";

View File

@ -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];

View File

@ -0,0 +1,65 @@
extern "C" {
#include "common/font.h"
#include "common/parsing.h"
#include "font.h"
}
#include <Application.h>
#include <Font.h>
#include <Menu.h>
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;
}

View File

@ -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";
}
}

View File

@ -68,6 +68,9 @@ const char* ffGpuDetectMetal(FFlist* gpus)
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;
}

View File

@ -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)

View File

@ -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

View File

@ -18,23 +18,27 @@
#include <linux/if.h>
#endif
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined(__HAIKU__)
#include <net/if_media.h>
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
#endif
#ifdef __sun
#if defined(__sun) || defined(__HAIKU__)
#include <sys/sockio.h>
#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))

View File

@ -0,0 +1,15 @@
#include "memory.h"
#include <OS.h>
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;
}

View File

@ -0,0 +1,20 @@
#include "os.h"
#include "common/io/io.h"
#include <OS.h>
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?
}

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -0,0 +1,14 @@
#include "processes.h"
#include <OS.h>
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;
}

View File

@ -4,29 +4,54 @@
#include <fcntl.h>
#include <sys/soundcard.h>
#include <unistd.h>
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;
}

View File

@ -0,0 +1,50 @@
#include "sound.h"
#include "common/io/io.h"
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/audioio.h>
#include <sys/ioctl.h>
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;
}

View File

@ -0,0 +1,86 @@
#include "sound.h"
#include "util/stringUtils.h"
#include <fcntl.h>
#include <sndio.h>
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;
}

View File

@ -0,0 +1,17 @@
#include "swap.h"
#include <OS.h>
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;
}

View File

@ -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",

View File

@ -0,0 +1,11 @@
#include "uptime.h"
#include "common/time.h"
#include <OS.h>
const char* ffDetectUptime(FFUptimeResult* result)
{
result->uptime = system_time() / 1000;
result->bootTime = (real_time_clock_usecs() / 1000) - result->uptime;
return NULL;
}

View File

@ -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

View File

@ -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 ,;;;;;::::' ';;;;;;::::
';;::, ;;;;::: .;;;;;::' .;;;;;::
;;;, ;;;;: .;;;:' ;;;:
,;, ,;: ';'
.,

View File

@ -0,0 +1,19 @@
********
*****************
**********************
**************************
********** **********
******* *********
****** ********
******* *******
********* ****** *******
***************** ******
*************** *******
*********** *******
********
********
*********
**********
*********
*******
***

View File

@ -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,

View File

@ -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)

View File

@ -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"},

View File

@ -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

View File

@ -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);

View File

@ -14,6 +14,9 @@
#include <sys/sysctl.h>
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/sysctl.h>
#elif defined(__HAIKU__)
#include <image.h>
#include <OS.h>
#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);

View File

@ -2,6 +2,8 @@
#include "util/textModifier.h"
#include "fastfetch.h"
#include <stdlib.h>
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);
}