Global: addresses Copilot's review comments

This commit is contained in:
李通洲
2026-09-17 19:19:25 +08:00
parent c23c98a85a
commit f8fd708423
6 changed files with 82 additions and 8 deletions
+5
View File
@@ -790,6 +790,11 @@
],
"default": "left"
},
"animationFrame": {
"type": "integer",
"description": "Frame of an animated image to render:\n0 plays the animation (kitty image protocol only), a positive value is the 1-based frame number, and a negative value counts back from the end, so -1 is the last frame.\nOnly the JSON config can express a negative value, as the command line parser reads a leading `-` as another option",
"default": 1
},
"chafa": {
"type": "object",
"additionalProperties": false,
+6 -1
View File
@@ -2,7 +2,12 @@
#include <stdint.h>
#if __BIG_ENDIAN__
// `__BIG_ENDIAN__` alone is not enough: GCC does not define it, it documents only `__BYTE_ORDER__`
// and the `__ORDER_*_ENDIAN__` values. Testing the former silently selected the little-endian
// branch on s390x, where `FF_READ_BE` then byte-swapped values that were already big-endian.
// `defined(__BIG_ENDIAN__)` alone would not do either: a macro that is defined as 0 is not a
// big-endian platform.
#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__)
#define FF_READ_LE(x) _Generic((x), \
uint16_t: __builtin_bswap16(x), \
uint32_t: __builtin_bswap32(x), \
+31 -5
View File
@@ -102,14 +102,40 @@ static void getExePath(FFPlatform* platform) {
int fileMib[6] = { CTL_KERN, KERN_FILE, KERN_FILE_BYPID, (pid_t) platform->pid, (int) sizeof(struct kinfo_file), 0 };
size_t fileSize = 0;
if (sysctl(fileMib, ARRAY_SIZE(fileMib), nullptr, &fileSize, nullptr, 0) == 0) {
fileSize += fileSize / 8; // add ~10%
FF_AUTO_FREE struct kinfo_file* kf = (struct kinfo_file*) malloc(fileSize);
fileSize += fileSize / 8; // add 12.5% for the table growing between the two calls
size_t fileCapacity = fileSize;
FF_AUTO_FREE struct kinfo_file* kf = (struct kinfo_file*) malloc(fileCapacity);
if (kf) {
int rv;
do {
fileMib[5] = (int) (fileSize / sizeof(struct kinfo_file));
// The table only grows, so the loop terminates as long as it grows by less
// than 12.5% per retry. Cap it anyway: spinning on a pathological growth
// rate would hang fastfetch, and giving up only costs the executable check
// below, which already assumes the path is correct when the list is missing.
int retries = 5;
while (true) {
fileMib[5] = (int) (fileCapacity / sizeof(struct kinfo_file));
fileSize = fileCapacity; // sysctl takes the size of the buffer as input
rv = sysctl(fileMib, ARRAY_SIZE(fileMib), kf, &fileSize, nullptr, 0);
} while (rv == -1 && errno == ENOMEM);
if (rv == 0 || errno != ENOMEM || retries-- == 0) {
break;
}
// The file table grew between the two calls. The buffer has to grow
// before the retry: the next call advertises fileCapacity as the size
// of kf, and the kernel would copy that many bytes into the old
// allocation.
// OpenBSD writes back the size it needs, FreeBSD only the number of
// bytes it managed to copy, so take the larger one and add ~10% on
// top -- the growth libprocstat uses for this very sysctl.
size_t newCapacity = fileSize > fileCapacity ? fileSize : fileCapacity;
newCapacity += newCapacity / 8;
struct kinfo_file* newKf = (struct kinfo_file*) realloc(kf, newCapacity);
if (newKf == nullptr) {
rv = -1;
break;
}
kf = newKf;
fileCapacity = newCapacity;
}
if (rv == 0) {
int cntp = (int) (fileSize / sizeof(struct kinfo_file));
+12 -2
View File
@@ -10,8 +10,14 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) {
if (npids <= 0) {
return "proc_listallpids(nullptr, 0) failed";
}
FF_AUTO_FREE pid_t* pids = malloc((uint32_t) (npids + npids / 8 + 1) * sizeof(pid_t));
npids = proc_listallpids(pids, npids);
// `proc_listallpids` returns the number of pids, but it wants the size of the buffer in bytes:
// passing the count back would only let the kernel fill a quarter of it.
const int pidCapacity = npids + npids / 8 + 1;
FF_AUTO_FREE pid_t* pids = malloc((size_t) pidCapacity * sizeof(pid_t));
if (pids == nullptr) {
return "malloc() failed";
}
npids = proc_listallpids(pids, pidCapacity * (int) sizeof(pid_t));
if (npids <= 0) {
return "proc_listallpids(pids, bufferSize) failed";
}
@@ -41,6 +47,10 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) {
item->startTime = proc.pbsd.pbi_start_tvsec * 1000u + proc.pbsd.pbi_start_tvusec / 1000u; // convert to ms
item->threads = (uint32_t) proc.ptinfo.pti_threadnum;
// FF_LIST_ADD does not zero the element, and top.c subtracts both counters for every
// process it samples, whether or not they were collected.
item->bytesRead = 0;
item->bytesWritten = 0;
if (showTypes & FF_TOP_TYPE_DISK) {
struct rusage_info_v2 rusage;
if (proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t*) &rusage) == 0) {
@@ -118,6 +118,11 @@ const char* ffDetectWallpaper(FFstrbuf* result) {
if (@available(macOS 14.0, *)) {
error = detectFromPlist(result);
if (error) {
// The plist is the authoritative source on Sonoma and later, but when it can not be read
// at all, NSWorkspace can still resolve a user-picked static image.
error = detectFromNSWorkspace(result);
}
} else {
#ifdef FF_HAVE_SQLITE3
error = detectFromSQLite(result);
+23
View File
@@ -3,6 +3,7 @@
#include "image.h"
#include "common/library.h"
#include "common/mallocHelper.h"
#include "common/strutil.h"
#include <magick/MagickCore.h>
#include <stdlib.h>
@@ -98,6 +99,17 @@ static FFLogoImageResult im6EncodeImage(FFLogoRequestData* requestData, const ch
ffCopyMagickString(imageInfoOut->magick, magick, magickLength);
// The raw pixel coders write image->depth bits per sample, not 8: a 1-bit grayscale source comes
// back as columns*4/8 bytes per row and a 16-bit one as columns*8, while the RGBA caller hands
// the blob on as RGBA8 and derives its length from width*height*4. Pin the depth for the raw
// formats only -- the SIXEL coder quantises on its own, so it keeps the source depth and its
// output stays byte identical.
// ImageMagick 6 leaves no choice about where to pin it: AcquireQuantumInfo takes the depth from
// image->depth and never looks at image_info->depth.
if (ffStrEquals(magick, "RGBA")) {
image->depth = 8;
}
blob = ffImageToBlob(imageInfoOut, image, &length, exceptionInfo);
if (blob == nullptr || length == 0) {
goto cleanup;
@@ -142,6 +154,17 @@ bool ffImageCreateIM6(FFLogoRequestData* requestData, FFImageBuffer* out, const
return false;
}
// FFImageBuffer carries no length, so every consumer derives it from width*height*4. Refuse any
// other size rather than let them read past the blob -- the raw coder's depth scaling used to
// produce one (see the depth pin in im6EncodeImage).
if (length != (size_t) requestData->logoPixelWidth * requestData->logoPixelHeight * 4) {
if (error) {
*error = "Image Magick did not return an RGBA8 buffer";
}
free(blob);
return false;
}
out->data = blob;
out->width = requestData->logoPixelWidth;
out->height = requestData->logoPixelHeight;