Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
69418cb
Packaging: updates debian stuff [ci skip]
CarterLi Jun 29, 2026
4897152
Logo: adds chimera linux small logo (#2426)
weedy-gdrnt Jun 29, 2026
5ab192e
Common (Thread): adds `ffThreadGetCurrentId`
CarterLi Jun 29, 2026
195e148
Common: inlines more functions
CarterLi Jun 29, 2026
0e257f2
Platform (Windows): one less syscall
CarterLi Jun 29, 2026
3ae1bfd
Media (macOS): uses perl for faster startup
CarterLi Jun 30, 2026
08d419d
Global: adds a simple `tracer`
CarterLi Jun 29, 2026
4cf060e
Logo (Image): improves performance of DLL searching on WIndows
CarterLi Jun 30, 2026
9f446bd
Common (Library): adds fast path for loading only one lib
CarterLi Jun 30, 2026
a447928
FFstrbuf: don't try to inline functions with varargs
CarterLi Jun 30, 2026
78874ae
Logo: add chimera2, parabola2_small, postmarketos2, qubes_small (#2430)
6erezka Jul 1, 2026
1b36c3c
Logo (Builtin): updates `c.inc`
CarterLi Jul 1, 2026
6251300
Logo (Builtin): adds Flatcar
CarterLi Jul 1, 2026
113f7d3
OS (Linux): Add Astra Linux version detection
CarterLi Jul 1, 2026
81738aa
WM (Linux): fixes compatibility with WSL 2.9.3+
CarterLi Jul 2, 2026
22c4620
Logo (Builtin): adds Azure Linux
CarterLi Jul 3, 2026
35af768
Shell (Windows): improves performance of Windows PowerShell version d…
CarterLi Jul 3, 2026
d031d6c
FFPlatform (Windows): hard codes i686 CPU arch
CarterLi Jul 3, 2026
225d9e7
Release: v2.65.3
CarterLi Jul 3, 2026
52c9730
Tracer: query tid only when threading is enabled
CarterLi Jul 3, 2026
e12f363
OS (Linux): fixes potencial issue
CarterLi Jul 3, 2026
827bc26
Trace: removes useless empty lines
CarterLi Jul 3, 2026
2ea6c37
Logo (Builtin): cleanup a lot of distro names
CarterLi Jul 3, 2026
8b6a74f
Doc: update changelog
CarterLi Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# 2.65.3

Changes:
* Fixed compatibility with WSL 2.9.3 (#2433, WM, Linux)

Features:
* Added Astra Linux version detection (OS, Linux)
* Improved performance of Windows PowerShell version detection (Shell, Windows)
* Improved performance of Media module on macOS (Media, macOS)

Logos:
* Added Flatcar, Azure Linux
* Added Chimera_small, Chimera2, Parabola2_small, PostmarketOS2, Qubes_small
* Cleaned up a lot of distro names

# 2.65.2

Changes:
Expand All @@ -10,7 +25,7 @@ Bugfixes:
* Fixed a crash when detecting hardware codec support with the `amdgpu` driver on Linux. (#2419, Codec, Linux)

Logos:
* Updated CachyOS_small
* Updated CachyOS_small; fixed CachyOS logo colors to match the official logo better
* Added Turkish

# 2.65.1
Expand Down
24 changes: 23 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url

project(fastfetch
VERSION 2.65.2
VERSION 2.65.3
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
Expand Down Expand Up @@ -105,6 +105,7 @@ cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND"
option(ENABLE_ZLIB "Enable zlib" ON)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
option(ENABLE_ASAN "Build fastfetch with ASAN (address sanitizer)" OFF)
option(ENABLE_TRACER "Build fastfetch with function tracing" OFF)
option(ENABLE_LTO "Enable link-time optimization in release mode if supported" ON)
option(BUILD_FLASHFETCH "Build flashfetch" ON) # Also build the flashfetch binary
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
Expand Down Expand Up @@ -1365,6 +1366,22 @@ elseif(GNU)
)
endif()

if(ENABLE_TRACER)
message(STATUS "Tracer is enabled")
list(APPEND LIBFASTFETCH_SRC src/common/impl/tracer.c)
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions-after-inlining")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finstrument-functions -Dinline=\"__attribute__((no_instrument_function)) inline\"")
endif()
if(NOT WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic")
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gcodeview -fuse-ld=lld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--pdb=${CMAKE_BINARY_DIR}/fastfetch.pdb")
endif()
endif()

# Proprietary GPU driver APIs
if(LINUX OR FreeBSD OR WIN32)
list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_nvidia.c)
Expand Down Expand Up @@ -1889,6 +1906,11 @@ elseif(WIN32)
PRIVATE "runtimeobject"
)
endif()
if(ENABLE_TRACER)
target_link_libraries(libfastfetch
PRIVATE "dbghelp"
)
endif()
elseif(FreeBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
Expand Down
6 changes: 6 additions & 0 deletions debian/changelog.tpl
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
fastfetch (2.65.2~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium

* Update to 2.65.2

-- Carter Li <zhangsongcui@live.cn> Mon, 29 Jun 2026 10:05:47 +0800
Comment on lines +1 to +5

fastfetch (2.65.1~#UBUNTU_CODENAME#) #UBUNTU_CODENAME#; urgency=medium

* Update to 2.65.1
Expand Down
11 changes: 9 additions & 2 deletions src/common/FFlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ typedef struct FFlist {
uint32_t capacity;
} FFlist;

void* ffListAdd(FFlist* list, uint32_t elementSize);

// Removes the first element, and copy its value to `*result`
bool ffListShift(FFlist* list, uint32_t elementSize, void* __restrict result);
// Removes the last element, and copy its value to `*result`
Expand Down Expand Up @@ -105,6 +103,15 @@ static inline void ffListReserve(FFlist* list, uint32_t elementSize, uint32_t ne
list->capacity = newCapacity;
}

static inline void* ffListAdd(FFlist* list, uint32_t elementSize) {
if (__builtin_expect(list->length == list->capacity, false)) {
ffListReserve(list, elementSize, list->capacity == 0 ? FF_LIST_DEFAULT_ALLOC : list->capacity * 2);
}

++list->length;
return ffListGet(list, elementSize, list->length - 1);
}

#define FF_LIST_FOR_EACH(itemType, itemVarName, listVar) \
for (itemType* itemVarName = (itemType*) (listVar).data; \
itemVarName - (itemType*) (listVar).data < (intptr_t) (listVar).length; \
Expand Down
146 changes: 100 additions & 46 deletions src/common/FFstrbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,13 @@
void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate);
void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments);
void ffStrbufInitMoveNS(FFstrbuf* strbuf, uint32_t length, char* heapStr);
FF_A_PRINTF(2, 3) void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...);
FF_A_PRINTF(1, 2) FF_A_NODISCARD FFstrbuf ffStrbufCreateF(const char* format, ...);

void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free);
void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free);

void ffStrbufClear(FFstrbuf* strbuf);
void ffStrbufEnsureFreeNoCheck(FFstrbuf* strbuf, uint32_t free);

static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value);
void ffStrbufAppendC(FFstrbuf* strbuf, char c);
void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c);
void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value);
void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int (*transformFunc)(int));
FF_A_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...);
void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments);
Expand Down Expand Up @@ -88,13 +85,6 @@

bool ffStrbufEnsureEndsWithC(FFstrbuf* strbuf, char c);

void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file);
void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file);

FF_A_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue);
FF_A_NODISCARD int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue);
FF_A_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue);

void ffStrbufUpperCase(FFstrbuf* strbuf);
void ffStrbufLowerCase(FFstrbuf* strbuf);

Expand Down Expand Up @@ -182,31 +172,6 @@
return strbuf;
}

FF_A_NODISCARD static inline FFstrbuf ffStrbufCreateVF(const char* format, va_list arguments) {
FFstrbuf strbuf;
ffStrbufInitVF(&strbuf, format, arguments);
return strbuf;
}

FF_A_PRINTF(2, 3) static inline void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...) {
va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(strbuf, format, arguments);
va_end(arguments);
}

FF_A_PRINTF(1, 2) FF_A_NODISCARD static inline FFstrbuf
ffStrbufCreateF(const char* format, ...) {
FFstrbuf strbuf;

va_list arguments;
va_start(arguments, format);
ffStrbufInitVF(&strbuf, format, arguments);
va_end(arguments);

return strbuf;
}

static inline void ffStrbufInitMoveS(FFstrbuf* strbuf, char* heapStr) {
ffStrbufInitMoveNS(strbuf, (uint32_t) strlen(heapStr), heapStr);
}
Expand All @@ -229,6 +194,76 @@
return strbuf->allocated - strbuf->length - 1; // - 1 for the null byte
}

static inline void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) {
if (__builtin_expect(free == 0, false)) {
if (__builtin_expect(!(strbuf->allocated == 0 && strbuf->length > 0), true)) {
return;
}
} else {
if (__builtin_expect(ffStrbufGetFree(strbuf) >= free, true)) {
return;
}
}

ffStrbufEnsureFreeNoCheck(strbuf, free);
}


static inline void ffStrbufClear(FFstrbuf* strbuf) {
assert(strbuf != NULL);
extern char* CHAR_NULL_PTR;

if (strbuf->allocated == 0) {
strbuf->chars = CHAR_NULL_PTR;
} else {
strbuf->chars[0] = '\0';
}

strbuf->length = 0;
}

static inline void ffStrbufAppendC(FFstrbuf* strbuf, char c) {
if (__builtin_expect(ffStrbufGetFree(strbuf) == 0, false)) {
ffStrbufEnsureFreeNoCheck(strbuf, 1);
}
strbuf->chars[strbuf->length++] = c;
strbuf->chars[strbuf->length] = '\0';
}

static inline void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) {
if (__builtin_expect(num == 0, false)) {
return;
}
if (__builtin_expect(ffStrbufGetFree(strbuf) < num, false)) {
ffStrbufEnsureFreeNoCheck(strbuf, num);
}

memset(&strbuf->chars[strbuf->length], c, num);
strbuf->length += num;
strbuf->chars[strbuf->length] = '\0';
}

static inline void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) {
if (__builtin_expect(value == NULL || length == 0, false)) {
return;
}
if (__builtin_expect(ffStrbufGetFree(strbuf) < length, false)) {
ffStrbufEnsureFreeNoCheck(strbuf, length);
}

memcpy(&strbuf->chars[strbuf->length], value, length);

Check failure on line 254 in src/common/FFstrbuf.h

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/common/FFstrbuf.h#L254

Does not check for buffer overflows when copying to destination (CWE-120). Make sure destination can always hold the source data.

Check failure on line 254 in src/common/FFstrbuf.h

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/common/FFstrbuf.h#L254

The `memcpy` family of functions require the developer to validate that the destination buffer is the same size or larger than the source buffer.
strbuf->length += length;
strbuf->chars[strbuf->length] = '\0';
}

static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
assert(value != strbuf);
if (value == NULL) {
return;
}
ffStrbufAppendNS(strbuf, value->length, value->chars);
}

static inline void ffStrbufRecalculateLength(FFstrbuf* strbuf) {
strbuf->length = (uint32_t) strlen(strbuf->chars);
}
Expand Down Expand Up @@ -338,14 +373,6 @@
return strbuf;
}

static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value) {
assert(value != strbuf);
if (value == NULL) {
return;
}
ffStrbufAppendNS(strbuf, value->length, value->chars);
}

static inline void ffStrbufPrepend(FFstrbuf* strbuf, FFstrbuf* value) {
if (value == NULL) {
return;
Expand Down Expand Up @@ -578,6 +605,33 @@
return ffStrbufSeparatedContainIgnCaseNS(strbuf, comp->length, comp->chars, separator);
}

static inline void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file) {
fwrite(strbuf->chars, sizeof(*strbuf->chars), strbuf->length, file);
}

static inline void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file) {
ffStrbufWriteTo(strbuf, file);
fputc('\n', file);
}

FF_A_NODISCARD static inline double ffStrbufToDouble(const FFstrbuf* strbuf, double defaultValue) {
char* str_end;
double result = strtod(strbuf->chars, &str_end);
return str_end == strbuf->chars ? defaultValue : result;
}

FF_A_NODISCARD static inline uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) {
char* str_end;
unsigned long long result = strtoull(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (uint64_t) result;
}

FF_A_NODISCARD static inline int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue) {
char* str_end;
long long result = strtoll(strbuf->chars, &str_end, 10);
return str_end == strbuf->chars ? defaultValue : (int64_t) result;
}

// Returns true if the strbuf is modified
bool ffStrbufDecodeHexEscapeSequences(FFstrbuf* strbuf);

Expand Down
80 changes: 32 additions & 48 deletions src/common/impl/FFPlatform_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,54 +236,38 @@ static void getSystemPageSize(FFPlatformSysinfo* info) {
}

static void getSystemArchitecture(FFPlatformSysinfo* info) {
SYSTEM_PROCESSOR_INFORMATION spi;
if (NT_SUCCESS(NtQuerySystemInformation(SystemProcessorInformation, &spi, sizeof(spi), NULL))) {
switch (spi.ProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
ffStrbufSetStatic(&info->architecture, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA64:
ffStrbufSetStatic(&info->architecture, "ia64");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
switch (spi.ProcessorLevel) {
case 4:
ffStrbufSetStatic(&info->architecture, "i486");
break;
case 5:
ffStrbufSetStatic(&info->architecture, "i586");
break;
case 6:
ffStrbufSetStatic(&info->architecture, "i686");
break;
default:
ffStrbufSetStatic(&info->architecture, "i386");
break;
}
break;
case PROCESSOR_ARCHITECTURE_ARM64:
ffStrbufSetStatic(&info->architecture, "aarch64");
break;
case PROCESSOR_ARCHITECTURE_ARM:
ffStrbufSetStatic(&info->architecture, "arm");
break;
case PROCESSOR_ARCHITECTURE_PPC:
ffStrbufSetStatic(&info->architecture, "ppc");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
ffStrbufSetStatic(&info->architecture, "mips");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
ffStrbufSetStatic(&info->architecture, "alpha");
break;
case PROCESSOR_ARCHITECTURE_ALPHA64:
ffStrbufSetStatic(&info->architecture, "alpha64");
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
ffStrbufSetStatic(&info->architecture, "unknown");
break;
}
switch (SharedUserData->NativeProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64:
ffStrbufSetStatic(&info->architecture, "x86_64");
break;
case PROCESSOR_ARCHITECTURE_IA64:
ffStrbufSetStatic(&info->architecture, "ia64");
break;
case PROCESSOR_ARCHITECTURE_INTEL:
ffStrbufSetStatic(&info->architecture, "i686");
break;
case PROCESSOR_ARCHITECTURE_ARM64:
ffStrbufSetStatic(&info->architecture, "aarch64");
break;
case PROCESSOR_ARCHITECTURE_ARM:
ffStrbufSetStatic(&info->architecture, "arm");
break;
case PROCESSOR_ARCHITECTURE_PPC:
ffStrbufSetStatic(&info->architecture, "ppc");
break;
case PROCESSOR_ARCHITECTURE_MIPS:
ffStrbufSetStatic(&info->architecture, "mips");
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
ffStrbufSetStatic(&info->architecture, "alpha");
break;
case PROCESSOR_ARCHITECTURE_ALPHA64:
ffStrbufSetStatic(&info->architecture, "alpha64");
break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default:
ffStrbufSetStatic(&info->architecture, "unknown");
break;
}
}

Expand Down
Loading
Loading