Merge pull request #1215 from fastfetch-cli/dev

Release: v2.22.0
This commit is contained in:
Carter Li
2024-08-26 10:41:25 +08:00
committed by GitHub
47 changed files with 1274 additions and 240 deletions
+24
View File
@@ -1,3 +1,27 @@
# 2.22.0
Features:
* Small performance improvements (Terminal, Editor)
* Improve arm32 and loongarch support (CPU, Linux)
* Ignore the parent process if env `$FFTS_IGNORE_PARENT` is set to `1` (Shell)
* Add code name of Apple M4 (CPU, Linux)
* Add ethernet speed rate detection support (LocalIP)
* Add zsh completion script
* Add Linglong package manager detection support (Packages, Linux)
Bugfixes:
* Fix building on macOS 10.14
* Fix tmux in linux TTY (Colors)
* Fix hang in WSL when custom format is used (Disk, Linux)
* Fix `/proc/loadavg` parsing (Loadavg, Linux)
* Disable use of `LC_NUMERIC` locale settings to fix parsing of decimal numbers
* Fix possible segfault (DiskIO, Linux)
* Honor `preciseRefreshRate` in custom format (Display)
Logos:
* Add Lingmo OS
* Add Sleeper OS
# 2.21.3
Bugfixes:
+16 -5
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.21.3
VERSION 2.22.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -69,7 +69,7 @@ cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF)
cmake_dependent_option(ENABLE_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 FreeBSD OR SunOS" OFF)
cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR FreeBSD OR ANDROID" OFF)
cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF)
option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embedded) yyjson library" OFF)
@@ -401,6 +401,7 @@ set(LIBFASTFETCH_SRC
src/util/base64.c
src/util/FFlist.c
src/util/FFstrbuf.c
src/util/path.c
src/util/platform/FFPlatform.c
src/util/smbiosHelper.c
)
@@ -481,7 +482,7 @@ if(LINUX)
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c
src/util/linux/elf.c
src/util/binary_linux.c
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
@@ -543,6 +544,7 @@ elseif(ANDROID)
src/detection/wmtheme/wmtheme_nosupport.c
src/detection/camera/camera_android.c
src/util/platform/FFPlatform_unix.c
src/util/binary_linux.c
)
elseif(FreeBSD)
list(APPEND LIBFASTFETCH_SRC
@@ -621,7 +623,7 @@ elseif(FreeBSD)
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
src/util/platform/FFPlatform_unix.c
src/util/linux/elf.c
src/util/binary_linux.c
)
elseif(APPLE)
list(APPEND LIBFASTFETCH_SRC
@@ -687,6 +689,7 @@ elseif(APPLE)
src/util/apple/cf_helpers.c
src/util/apple/osascript.m
src/util/platform/FFPlatform_unix.c
src/util/binary_apple.c
)
elseif(WIN32)
list(APPEND LIBFASTFETCH_SRC
@@ -753,6 +756,7 @@ elseif(WIN32)
src/util/windows/unicode.c
src/util/windows/wmi.cpp
src/util/platform/FFPlatform_windows.c
src/util/binary_windows.c
)
elseif(SunOS)
list(APPEND LIBFASTFETCH_SRC
@@ -829,7 +833,7 @@ elseif(SunOS)
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_nosupport.c
src/util/platform/FFPlatform_unix.c
src/util/linux/elf.c
src/util/binary_linux.c
)
endif()
@@ -1135,6 +1139,7 @@ elseif(WIN32)
PRIVATE "setupapi"
PRIVATE "hid"
PRIVATE "wtsapi32"
PRIVATE "imagehlp"
)
elseif(FreeBSD)
target_link_libraries(libfastfetch
@@ -1332,6 +1337,12 @@ install(
RENAME "${CMAKE_PROJECT_NAME}"
)
install(
FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.zsh"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/zsh/site-functions"
RENAME "_${CMAKE_PROJECT_NAME}"
)
install(
FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.fish"
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/fish/vendor_completions.d"
+15 -8
View File
@@ -30,17 +30,23 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/
Some distros packaged an outdated fastfetch version. Older version receive no support, so please try always to use the latest version.
* Ubuntu: [`ppa:zhangsongcui3371/fastfetch`](https://launchpad.net/~zhangsongcui3371/+archive/ubuntu/fastfetch) (for Ubuntu 22.04 or newer)
* Debian: `sudo apt install fastfetch` (for Debian 13 or newer)
* Debian: `apt install fastfetch` (for Debian 13 or newer)
* Debian / Ubuntu: Download `fastfetch-linux-<proper architecture>.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and double-click it (for Ubuntu 20.04 or newer and Debian 11 or newer).
* Arch Linux: `sudo pacman -S fastfetch`
* Fedora: `sudo dnf install fastfetch`
* Gentoo: `sudo emerge --ask app-misc/fastfetch`
* Arch Linux: `pacman -S fastfetch`
* Fedora: `dnf install fastfetch`
* Gentoo: `emerge --ask app-misc/fastfetch`
* Alpine: `apk add --upgrade fastfetch`
* NixOS: `nix-shell -p fastfetch`
* openSUSE: `sudo zypper install fastfetch`
* ALT Linux: `sudo apt-get install fastfetch`
* openSUSE: `zypper install fastfetch`
* ALT Linux: `apt-get install fastfetch`
* Exherbo: `cave resolve --execute app-misc/fastfetch`
* GNU Guix: `guix install fastfetch`
* Solus: `eopkg install fastfetch`
* Slackware: `sbopkg -i fastfetch`
* Void Linux: `xbps-install fastfetch`
* Venom Linux: `scratch install fastfetch`
Replace sudo with doas depending on what you use.
You may need `sudo`, `doas` or `sup` to run these commands.
[See also if fastfetch has been packaged for your favorite Linux distro](#Packaging).
@@ -54,8 +60,9 @@ If fastfetch is not packaged for your distro or an outdated version is packaged,
### Windows
* [scoop](https://scoop.sh/#/apps?q=fastfetch): `scoop install fastfetch`
* [Chocolatey](https://community.chocolatey.org/packages/fastfetch): `choco install fastfetch`
* [winget](https://github.com/microsoft/winget-pkgs/tree/master/manifests/f/Fastfetch-cli/Fastfetch): `winget install fastfetch`
* [MSYS2 MinGW](https://github.com/msys2/MINGW-packages/tree/master/mingw-w64-fastfetch): `pacman -S mingw-w64-<subsystem>-<arch>-fastfetch`
* [MSYS2 MinGW](https://packages.msys2.org/base/mingw-w64-fastfetch): `pacman -S mingw-w64-<subsystem>-<arch>-fastfetch`
You may also download the program directly from [the GitHub releases page](https://github.com/fastfetch-cli/fastfetch/releases/latest) in the form of an archive file.
+97
View File
@@ -0,0 +1,97 @@
#compdef fastfetch
function _fastfetch() {
local state
local -a opts
opts=(${(f)"$(
python <<EOF
import json
import subprocess
import sys
def main():
data: dict[str, list[dict]] = json.loads(
subprocess.check_output(["fastfetch", "--help-raw"])
)
for key in data:
for flag in data[key]:
if flag.get("pseudo", False):
continue
if "short" in flag:
command_prefix = f"""-{flag["short"]}[{flag["desc"]}]"""
print_command(command_prefix, flag)
if "long" in flag:
command_prefix = f"""--{flag["long"]}[{flag["desc"]}]"""
print_command(command_prefix, flag)
def print_command(command_prefix: str, flag: dict):
if "arg" in flag:
type: str = flag["arg"]["type"]
if type == "bool":
print(f"{command_prefix}:bool:(true false)")
elif type == "color":
print(f"{command_prefix}:color:(black red green yellow blue magenta cyan white default)")
elif type == "command":
print(f"{command_prefix}:module:->modules")
elif type == "config":
print(f"{command_prefix}:presets:->presets")
elif type == "enum":
temp: str = " ".join(flag["arg"]["enum"])
print(f'{command_prefix}:type:( {temp} )')
elif type == "logo":
print(f"{command_prefix}:logo:->logo")
elif type == "structure":
print(f"{command_prefix}:structure:->structure")
elif type == "path":
print(f"{command_prefix}:path:_files -/")
else:
print(f"{command_prefix}:")
else:
print(f"{command_prefix}")
if __name__ == "__main__":
try:
main()
except Exception:
sys.exit(1)
EOF
)"})
_arguments -C "$opts[@]"
case $state in
modules)
local -a modules=( ${(f)"$(fastfetch --list-modules autocompletion)"} )
modules=( ${(L)^modules%%:*}-format format color )
_describe 'module' modules
;;
presets)
local -a presets=(
${$(fastfetch --list-presets autocompletion):#.*}
"none:Disable loading config file"
)
_describe 'preset' presets
;;
structure)
local -a structures=( ${(f)"$(fastfetch --list-modules autocompletion)"} )
_describe 'structure' structures
;;
logo)
local -a logos=(
$(fastfetch --list-logos autocompletion)
"none:Don't print logo"
"small:Print small ascii logo if available"
)
_describe 'logo' logos
;;
esac
}
_fastfetch "$@"
+6
View File
@@ -1,3 +1,9 @@
fastfetch (2.21.3) jammy; urgency=medium
* Update to 2.21.3
-- Carter Li <zhangsongcui@live.cn> Thu, 15 Aug 2024 16:14:52 +0800
fastfetch (2.21.2) jammy; urgency=medium
* Update to 2.21.2
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.21.2_source.buildinfo universe/utils optional
fastfetch_2.21.3_source.buildinfo universe/utils optional
+14 -8
View File
@@ -11,45 +11,51 @@
},
"separator": ""
},
"modules": [
"modules": [
{
"type": "kernel",
"key": "Vanilla ",
"key": "[_Kernel___> ",
"keyColor": "blue"
},
{
"type": "packages",
"outputColor": "white",
"key": " [_Packages_> ",
"keyColor": "green"
},
{
"type": "localip",
"outputColor": "white",
"key": " [_Local_IP_> ",
"keyColor": "green"
},
{
"type": "cpu",
"key": " [_CPU______> ",
"keyColor": "magenta"
},
{
"type": "memory",
"format": "[{3}] {1} / {2}",
"key": " [_RAM______> ",
"keyColor": "magenta"
},
{
"type": "swap",
"format": "[{3}] {1} / {2}",
"key": " [_SWAP_____> ",
"keyColor": "magenta"
},
{
"type": "disk",
"format": "[{3}] {1} / {2} {9}",
"key": " [_Disk_____> ",
"keyColor": "magenta"
},
{
"type": "battery",
"format": "[{4}] {5}",
"key": " [_Battery__> ",
"keyColor": "magenta"
},
"break",
{
"type":"colors",
"type": "colors",
"paddingLeft": 9,
"symbol": "circle"
}
-4
View File
@@ -54,10 +54,6 @@ void ffInitInstance(void)
#else
// Never use `setlocale(LC_ALL, "")`
setlocale(LC_TIME, "");
setlocale(LC_NUMERIC, "");
#ifdef LC_MESSAGES
setlocale(LC_MESSAGES, "");
#endif
#endif
initState(&instance.state);
+1
View File
@@ -36,6 +36,7 @@ const char* ffCPUAppleCodeToName(uint32_t code)
case 6030: return "Apple M3 Pro";
case 6031:
case 6034: return "Apple M3 Max";
case 8132: return "Apple M4";
default: return "Apple Silicon";
}
}
+27
View File
@@ -30,3 +30,30 @@ typedef struct FFCPUResult
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
const char* ffCPUAppleCodeToName(uint32_t code);
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
// WARNING: CPUID may report frequencies of efficient cores
inline static const char* ffCPUDetectSpeedByCpuid(FFCPUResult* cpu)
{
uint32_t base = 0, max = 0, bus = 0, unused = 0;
if (!__get_cpuid(0x16, &base, &max, &bus, &unused))
return "Unsupported instruction";
// cpuid returns 0 MHz when hyper-v is enabled
if (base) cpu->frequencyBase = base;
if (max) cpu->frequencyMax = max;
return NULL;
}
#else
inline static const char* ffCPUDetectSpeedByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
{
return "Unsupported platform";
}
#endif
+2
View File
@@ -39,6 +39,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
}
}
ffCPUDetectSpeedByCpuid(cpu);
for (uint16_t i = 0; i < cpu->coresLogical; ++i)
{
ffStrbufClear(&buffer);
+41 -22
View File
@@ -137,36 +137,52 @@ static void detectArmName(FILE* cpuinfo, FFCPUResult* cpu, uint32_t implId)
}
#endif
static const char* parseCpuInfo(FILE* cpuinfo, FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, FFstrbuf* cpuMHz, FFstrbuf* cpuIsa, FFstrbuf* cpuUarch, FFstrbuf* cpuImplementer)
static const char* parseCpuInfo(
FF_MAYBE_UNUSED FILE* cpuinfo,
FF_MAYBE_UNUSED FFCPUResult* cpu,
FF_MAYBE_UNUSED FFstrbuf* physicalCoresBuffer,
FF_MAYBE_UNUSED FFstrbuf* cpuMHz,
FF_MAYBE_UNUSED FFstrbuf* cpuIsa,
FF_MAYBE_UNUSED FFstrbuf* cpuUarch,
FF_MAYBE_UNUSED FFstrbuf* cpuImplementer)
{
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
while(getline(&line, &len, cpuinfo) != -1)
{
//Stop after the first CPU
if(*line == '\0' || *line == '\n')
//Stop after reasonable information is acquired
if((*line == '\0' || *line == '\n')
#if __arm__ || __loongarch__
&& cpu->name.length > 0 // #1202 #1204
#endif
)
break;
(void)(
ffParsePropLine(line, "model name :", &cpu->name) ||
ffParsePropLine(line, "vendor_id :", &cpu->vendor) ||
ffParsePropLine(line, "cpu cores :", physicalCoresBuffer) ||
ffParsePropLine(line, "cpu MHz :", cpuMHz) ||
ffParsePropLine(line, "isa :", cpuIsa) ||
ffParsePropLine(line, "uarch :", cpuUarch) ||
// 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__)
(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__
(cpu->vendor.length == 0 && ffParsePropLine(line, "CPU implementer :", cpuImplementer)) ||
#endif
#if __ANDROID__
(cpuImplementer->length == 0 && ffParsePropLine(line, "CPU implementer :", cpuImplementer)) ||
(cpu->name.length == 0 && ffParsePropLine(line, "Hardware :", &cpu->name)) || //For Android devices
#endif
#if __powerpc__ || __powerpc
(cpu->name.length == 0 && ffParsePropLine(line, "cpu :", &cpu->name)) || //For POWER
(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
(cpu->name.length == 0 && ffParsePropLine(line, "cpu model :", &cpu->name)) || //For MIPS
#endif
false
);
@@ -265,16 +281,19 @@ static double detectCPUTemp(void)
{
if(
ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length ||
ffStrbufCompS(&value->name, "k10temp") == 0 ||
ffStrbufCompS(&value->name, "coretemp") == 0
ffStrbufEqualS(&value->name, "k10temp") ||
ffStrbufEqualS(&value->name, "coretemp")
) return value->value;
}
return FF_CPU_TEMP_UNSET;
}
static void parseIsa(FFstrbuf* cpuIsa)
FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa)
{
// Always use the last part of the ISA string. Ref: #590 #1204
ffStrbufSubstrAfterLastC(cpuIsa, ' ');
if(ffStrbufStartsWithS(cpuIsa, "rv"))
{
// RISC-V ISA string example: "rv64imafdch_zicsr_zifencei".
@@ -290,13 +309,9 @@ static void parseIsa(FFstrbuf* cpuIsa)
}
// The final ISA output of the above example is "rv64gch".
}
if(ffStrbufStartsWithS(cpuIsa, "mips"))
{
ffStrbufSubstrAfterLastC(cpuIsa, ' ');
}
}
void detectAsahi(FFCPUResult* cpu)
FF_MAYBE_UNUSED static void detectAsahi(FFCPUResult* cpu)
{
// In Asahi Linux, reading /proc/device-tree/compatible gives
// information on the device model. It consists of 3 NUL terminated
@@ -340,9 +355,12 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
cpu->coresOnline = (uint16_t) get_nprocs();
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
// 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 !(__x86_64__ || __i386__ || __arm__ || __aarch64__)
if(cpuUarch.length > 0)
{
if(cpu->name.length > 0)
@@ -357,6 +375,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
ffStrbufAppendC(&cpu->name, ' ');
ffStrbufAppend(&cpu->name, &cpuIsa);
}
#endif
#if __arm__ || __aarch64__
uint32_t cpuImplementer = (uint32_t) strtoul(cpuImplementerStr.chars, NULL, 16);
+3 -3
View File
@@ -29,10 +29,10 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
kstat_named_t* kn = kstat_data_lookup(ks, "vendor_id");
ffStrbufSetNS(&cpu->vendor, KSTAT_NAMED_STR_BUFLEN(kn) - 1, KSTAT_NAMED_STR_PTR(kn));
}
{
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
ffCPUDetectSpeedByCpuid(cpu);
kstat_named_t* kn = kstat_data_lookup(ks, "clock_MHz");
if (kn->value.ui32 > cpu->frequencyBase)
cpu->frequencyBase = kn->value.ui32;
}
ks = kstat_lookup(kc, "unix", -1, "system_misc");
if (ks && kstat_read(kc, ks, NULL) >= 0)
+1 -26
View File
@@ -54,31 +54,6 @@ typedef struct FFSmbiosProcessorInfo
static_assert(offsetof(FFSmbiosProcessorInfo, ThreadEnabled) == 0x30,
"FFSmbiosProcessorInfo: Wrong struct alignment");
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
inline static const char* detectSpeedByCpuid(FFCPUResult* cpu)
{
uint32_t base = 0, max = 0, bus = 0, unused = 0;
if (!__get_cpuid(0x16, &base, &max, &bus, &unused))
return "Unsupported instruction";
// cpuid returns 0 MHz when hyper-v is enabled
if (base) cpu->frequencyBase = base;
if (max) cpu->frequencyMax = max;
return NULL;
}
#else
inline static const char* detectSpeedByCpuid(FF_MAYBE_UNUSED FFCPUResult* cpu)
{
return "Unsupported platform";
}
#endif
static const char* detectMaxSpeedBySmbios(FFCPUResult* cpu)
{
const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable();
@@ -193,7 +168,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (error)
return error;
detectSpeedByCpuid(cpu);
ffCPUDetectSpeedByCpuid(cpu);
if (options->showPeCoreCount) detectCoreTypes(cpu);
if (cpu->frequencyMax == 0)
+11 -3
View File
@@ -72,7 +72,7 @@ static bool isPhysicalDevice(const struct mntent* device)
) return false;
// https://source.android.com/docs/core/ota/apex?hl=zh-cn
if(ffStrStartsWith(device->mnt_dir, "/apex/"))
if(ffStrStartsWith(device->mnt_dir, "/apex/"))
return false;
#endif // __ANDROID__
@@ -240,8 +240,16 @@ static void detectStats(FFDisk* disk)
disk->bytesAvailable = fs.f_bavail * fs.f_frsize;
disk->bytesUsed = 0; // To be filled in ./disk.c
disk->filesTotal = (uint32_t) fs.f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
if (fs.f_files >= fs.f_ffree)
{
disk->filesTotal = (uint32_t) fs.f_files;
disk->filesUsed = (uint32_t) (disk->filesTotal - fs.f_ffree);
}
else
{
// Windows filesystem in WSL
disk->filesTotal = disk->filesUsed = 0;
}
if(fs.f_flag & ST_RDONLY)
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
+13 -16
View File
@@ -37,24 +37,23 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
if (!ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY))
continue;
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInit(&device->name);
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
{
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName);
if (ffAppendFileBuffer(pathSysBlock, &device->name))
if (ffAppendFileBuffer(pathSysBlock, &name))
{
ffStrbufTrimRightSpace(&device->name);
if (device->name.length > 0)
ffStrbufAppendC(&device->name, ' ');
ffStrbufTrimRightSpace(&name);
if (name.length > 0)
ffStrbufAppendC(&name, ' ');
}
snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName);
ffAppendFileBuffer(pathSysBlock, &device->name);
ffStrbufTrimRightSpace(&device->name);
ffAppendFileBuffer(pathSysBlock, &name);
ffStrbufTrimRightSpace(&name);
if (device->name.length == 0)
ffStrbufSetS(&device->name, devName);
if (name.length == 0)
ffStrbufSetS(&name, devName);
else if (ffStrStartsWith(devName, "nvme"))
{
int devid, nsid;
@@ -69,17 +68,13 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
if (multiNs)
{
// In Asahi Linux, there are multiple namespaces for the same NVMe drive.
ffStrbufAppendF(&device->name, " - %d", nsid);
ffStrbufAppendF(&name, " - %d", nsid);
}
}
}
if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix))
{
ffStrbufDestroy(&device->name);
result->length--;
if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix))
continue;
}
}
// I/Os merges sectors ticks ...
@@ -94,6 +89,8 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options)
continue;
}
FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result);
ffStrbufInitMove(&device->name, &name);
ffStrbufInitF(&device->devPath, "/dev/%s", devName);
device->bytesRead = sectorRead * 512;
device->bytesWritten = sectorWritten * 512;
@@ -89,10 +89,12 @@ static void detectDisplays(FFDisplayServerResult* ds)
display->bitDepth = (uint8_t) bitDepth;
}
#ifdef MAC_OS_X_VERSION_10_15
if (CoreDisplay_Display_IsHDRModeEnabled)
{
display->hdrEnabled = CoreDisplay_Display_IsHDRModeEnabled(screen);
}
#endif
}
CGDisplayModeRelease(mode);
}
+56 -33
View File
@@ -1,17 +1,44 @@
#include "editor.h"
#include "common/processing.h"
#include "common/library.h"
#include "util/stringUtils.h"
#include "util/path.h"
#include "util/binary.h"
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
static inline char* realpath(const char* restrict file_name, char* restrict resolved_name)
{
return _fullpath(resolved_name, file_name, _MAX_PATH);
}
#endif
static bool extractNvimVersionFromBinary(const char* str, uint32_t len, void* userdata)
{
if (len < strlen("NVIM v0.0.0")) return true;
if (!ffStrStartsWith(str, "NVIM v")) return true;
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("NVIM v"));
return false;
}
static bool extractVimVersionFromBinary(const char* str, uint32_t len, void* userdata)
{
if (len < strlen("VIM - Vi IMproved 0.0")) return true;
if (!ffStrStartsWith(str, "VIM - Vi IMproved ")) return true;
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("VIM - Vi IMproved "));
ffStrbufSubstrBeforeFirstC(userdata, ' ');
return false;
}
static bool extractNanoVersionFromBinary(const char* str, uint32_t len, void* userdata)
{
if (len < strlen("GNU nano 0.0")) return true;
if (!ffStrStartsWith(str, "GNU nano ")) return true;
ffStrbufSetS((FFstrbuf*) userdata, str + strlen("GNU nano "));
return false;
}
const char* ffDetectEditor(FFEditorResult* result)
{
ffStrbufSetS(&result->name, getenv("VISUAL"));
@@ -26,41 +53,26 @@ const char* ffDetectEditor(FFEditorResult* result)
return "$VISUAL or $EDITOR not set";
}
if (!instance.config.general.detectVersion) return NULL;
#ifndef _WIN32
if (result->name.chars[0] != '/')
{
if (ffProcessAppendStdOut(&result->path, (char* const[]){
FASTFETCH_TARGET_DIR_USR "/bin/which",
result->name.chars,
NULL,
}) != NULL || result->path.length == 0)
return NULL;
}
#else
if (!(result->name.length > 3 && ffCharIsEnglishAlphabet(result->name.chars[0]) && result->name.chars[1] == ':' && result->name.chars[2] == '\\'))
{
char buf[32];
uint32_t len = GetSystemDirectoryA(buf, sizeof(buf));
if (len < strlen("C:\\WINDOWS\\system32")) return NULL;
strncpy(buf + len, "\\where.exe", sizeof(buf) - len);
if (ffProcessAppendStdOut(&result->path, (char* const[]){
buf,
result->name.chars,
NULL,
}) != NULL || result->path.length == 0)
return NULL;
}
#endif
else
if (ffIsAbsolutePath(result->name.chars))
ffStrbufSet(&result->path, &result->name);
else
{
const char* error = ffFindExecutableInPath(result->name.chars, &result->path);
if (error) return NULL;
}
char buf[PATH_MAX + 1];
if (!realpath(result->path.chars, buf))
return NULL;
{
char buf[PATH_MAX + 1];
if (!realpath(result->path.chars, buf))
return NULL;
ffStrbufSetS(&result->path, buf);
// WIN32: Should we handle scoop shim exe here?
#ifdef __linux__
if (!ffStrEndsWith(buf, "/snap"))
#endif
ffStrbufSetS(&result->path, buf);
}
{
uint32_t index = ffStrbufLastIndexC(&result->path,
@@ -82,6 +94,17 @@ const char* ffDetectEditor(FFEditorResult* result)
#endif
}
if (!instance.config.general.detectVersion) return NULL;
if (ffStrbufEqualS(&result->exe, "nvim"))
ffBinaryExtractStrings(result->path.chars, extractNvimVersionFromBinary, &result->version);
else if (ffStrbufEqualS(&result->exe, "vim"))
ffBinaryExtractStrings(result->path.chars, extractVimVersionFromBinary, &result->version);
else if (ffStrbufEqualS(&result->exe, "nano"))
ffBinaryExtractStrings(result->path.chars, extractNanoVersionFromBinary, &result->version);
if (result->version.length > 0) return NULL;
const char* param = NULL;
if (
ffStrbufEqualS(&result->exe, "nano") ||
+2 -2
View File
@@ -1,6 +1,6 @@
#include "initsystem.h"
#include "common/processing.h"
#include "util/linux/elf.h"
#include "util/binary.h"
#include <unistd.h>
FF_MAYBE_UNUSED static bool elfExtractStringsCallBack(const char* str, uint32_t len, void* data)
@@ -49,7 +49,7 @@ const char* ffDetectInitSystem(FFInitSystemResult* result)
#if __linux__ && !__ANDROID__
if (ffStrbufEqualS(&result->name, "systemd"))
{
ffElfExtractStrings(result->exe.chars, elfExtractStringsCallBack, &result->version);
ffBinaryExtractStrings(result->exe.chars, elfExtractStringsCallBack, &result->version);
if (result->version.length == 0)
{
if (ffProcessAppendStdOut(&result->version, (char* const[]) {
+2 -2
View File
@@ -9,12 +9,12 @@ const char* ffDetectLoadavg(double result[3])
// Don't use syscall for container compatibility. #620
char buf[64];
ssize_t nRead = ffReadFileData("/proc/uptime", sizeof(buf) - 1, buf);
ssize_t nRead = ffReadFileData("/proc/loadavg", sizeof(buf) - 1, buf);
if (nRead > 0)
{
buf[nRead] = '\0';
if (sscanf(buf, "%lf %lf %lf", &result[0], &result[1], &result[2]) == 3)
if (sscanf(buf, "%lf%lf%lf", &result[0], &result[1], &result[2]) == 3)
return NULL;
}
-10
View File
@@ -8,19 +8,9 @@ void ffDetectLocale(FFstrbuf* result)
if(result->length > 0)
return;
ffStrbufAppendS(result, getenv("LC_MESSAGES"));
if(result->length > 0)
return;
ffStrbufAppendS(result, getenv("LANG"));
if(result->length > 0)
return;
#ifdef LC_MESSAGES
ffStrbufAppendS(result, setlocale(LC_MESSAGES, NULL));
if(result->length > 0)
return;
#endif
ffStrbufAppendS(result, setlocale(LC_TIME, NULL));
}
+1
View File
@@ -9,6 +9,7 @@ typedef struct FFLocalIpResult
FFstrbuf ipv6;
FFstrbuf mac;
int32_t mtu;
int32_t speed;
bool defaultRoute;
} FFLocalIpResult;
+386
View File
@@ -12,7 +12,13 @@
#include <stdio.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <linux/ethtool.h>
#include <linux/sockios.h>
#endif
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <net/if_media.h>
#include <net/if_dl.h>
#else
#include <netpacket/packet.h>
@@ -40,6 +46,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type,
ffStrbufInit(&ip->mac);
ip->defaultRoute = defaultRoute;
ip->mtu = -1;
ip->speed = -1;
}
switch (type)
@@ -172,9 +179,388 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, iface->name.chars, IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMTU, &ifr) == 0)
iface->mtu = (int32_t) ifr.ifr_mtu;
#ifdef __linux__
struct ethtool_cmd edata = { .cmd = ETHTOOL_GSET };
ifr.ifr_data = (void*) &edata;
if (ioctl(sockfd, SIOCETHTOOL, &ifr) == 0)
iface->speed = (edata.speed_hi << 16) | edata.speed; // ethtool_cmd_speed is not available on Android
#elif __FreeBSD__ || __APPLE__
struct ifmediareq ifmr = {};
strncpy(ifmr.ifm_name, iface->name.chars, IFNAMSIZ - 1);
if (ioctl(sockfd, SIOCGIFMEDIA, &ifmr) == 0)
{
switch (IFM_SUBTYPE(ifmr.ifm_active))
{
#ifdef IFM_HPNA_1
case IFM_HPNA_1:
#endif
iface->speed = 1; break;
#ifdef IFM_1000_CX
case IFM_1000_CX:
#endif
#ifdef IFM_1000_CX_SGMII
case IFM_1000_CX_SGMII:
#endif
#ifdef IFM_1000_KX
case IFM_1000_KX:
#endif
#ifdef IFM_1000_LX
case IFM_1000_LX:
#endif
#ifdef IFM_1000_SGMII
case IFM_1000_SGMII:
#endif
#ifdef IFM_1000_SX
case IFM_1000_SX:
#endif
#ifdef IFM_1000_T
case IFM_1000_T:
#endif
iface->speed = 1000; break;
#ifdef IFM_100G_AUI2
case IFM_100G_AUI2:
#endif
#ifdef IFM_100G_AUI2_AC
case IFM_100G_AUI2_AC:
#endif
#ifdef IFM_100G_AUI4
case IFM_100G_AUI4:
#endif
#ifdef IFM_100G_AUI4_AC
case IFM_100G_AUI4_AC:
#endif
#ifdef IFM_100G_CAUI2
case IFM_100G_CAUI2:
#endif
#ifdef IFM_100G_CAUI2_AC
case IFM_100G_CAUI2_AC:
#endif
#ifdef IFM_100G_CAUI4
case IFM_100G_CAUI4:
#endif
#ifdef IFM_100G_CAUI4_AC
case IFM_100G_CAUI4_AC:
#endif
#ifdef IFM_100G_CP2
case IFM_100G_CP2:
#endif
#ifdef IFM_100G_CR4
case IFM_100G_CR4:
#endif
#ifdef IFM_100G_CR_PAM4
case IFM_100G_CR_PAM4:
#endif
#ifdef IFM_100G_DR
case IFM_100G_DR:
#endif
#ifdef IFM_100G_KR2_PAM4
case IFM_100G_KR2_PAM4:
#endif
#ifdef IFM_100G_KR4
case IFM_100G_KR4:
#endif
#ifdef IFM_100G_KR_PAM4
case IFM_100G_KR_PAM4:
#endif
#ifdef IFM_100G_LR4
case IFM_100G_LR4:
#endif
#ifdef IFM_100G_SR2
case IFM_100G_SR2:
#endif
#ifdef IFM_100G_SR4
case IFM_100G_SR4:
#endif
iface->speed = 100000; break;
#ifdef IFM_100_FX
case IFM_100_FX:
#endif
#ifdef IFM_100_SGMII
case IFM_100_SGMII:
#endif
#ifdef IFM_100_T
case IFM_100_T:
#endif
#ifdef IFM_100_T2
case IFM_100_T2:
#endif
#ifdef IFM_100_T4
case IFM_100_T4:
#endif
#ifdef IFM_100_TX
case IFM_100_TX:
#endif
#ifdef IFM_100_VG
case IFM_100_VG:
#endif
iface->speed = 100; break;
#ifdef IFM_10G_AOC
case IFM_10G_AOC:
#endif
#ifdef IFM_10G_CR1
case IFM_10G_CR1:
#endif
#ifdef IFM_10G_CX4
case IFM_10G_CX4:
#endif
#ifdef IFM_10G_ER
case IFM_10G_ER:
#endif
#ifdef IFM_10G_KR
case IFM_10G_KR:
#endif
#ifdef IFM_10G_KX4
case IFM_10G_KX4:
#endif
#ifdef IFM_10G_LR
case IFM_10G_LR:
#endif
#ifdef IFM_10G_LRM
case IFM_10G_LRM:
#endif
#ifdef IFM_10G_SFI
case IFM_10G_SFI:
#endif
#ifdef IFM_10G_SR
case IFM_10G_SR:
#endif
#ifdef IFM_10G_T
case IFM_10G_T:
#endif
#ifdef IFM_10G_TWINAX
case IFM_10G_TWINAX:
#endif
#ifdef IFM_10G_TWINAX_LONG
case IFM_10G_TWINAX_LONG:
#endif
iface->speed = 10000; break;
#ifdef IFM_10_2
case IFM_10_2:
#endif
#ifdef IFM_10_5
case IFM_10_5:
#endif
#ifdef IFM_10_FL
case IFM_10_FL:
#endif
#ifdef IFM_10_STP
case IFM_10_STP:
#endif
#ifdef IFM_10_T
case IFM_10_T:
#endif
iface->speed = 10; break;
#ifdef IFM_200G_AUI4
case IFM_200G_AUI4:
#endif
#ifdef IFM_200G_AUI4_AC
case IFM_200G_AUI4_AC:
#endif
#ifdef IFM_200G_AUI8
case IFM_200G_AUI8:
#endif
#ifdef IFM_200G_AUI8_AC
case IFM_200G_AUI8_AC:
#endif
#ifdef IFM_200G_CR4_PAM4
case IFM_200G_CR4_PAM4:
#endif
#ifdef IFM_200G_DR4
case IFM_200G_DR4:
#endif
#ifdef IFM_200G_FR4
case IFM_200G_FR4:
#endif
#ifdef IFM_200G_KR4_PAM4
case IFM_200G_KR4_PAM4:
#endif
#ifdef IFM_200G_LR4
case IFM_200G_LR4:
#endif
#ifdef IFM_200G_SR4
case IFM_200G_SR4:
#endif
iface->speed = 200000; break;
#ifdef IFM_20G_KR2
case IFM_20G_KR2:
#endif
iface->speed = 20000; break;
#ifdef IFM_2500_KX
case IFM_2500_KX:
#endif
#ifdef IFM_2500_SX
case IFM_2500_SX:
#endif
#ifdef IFM_2500_T
case IFM_2500_T:
#endif
#ifdef IFM_2500_X
case IFM_2500_X:
#endif
iface->speed = 2500; break;
#ifdef IFM_25G_ACC
case IFM_25G_ACC:
#endif
#ifdef IFM_25G_AOC
case IFM_25G_AOC:
#endif
#ifdef IFM_25G_AUI
case IFM_25G_AUI:
#endif
#ifdef IFM_25G_CR
case IFM_25G_CR:
#endif
#ifdef IFM_25G_CR1
case IFM_25G_CR1:
#endif
#ifdef IFM_25G_CR_S
case IFM_25G_CR_S:
#endif
#ifdef IFM_25G_KR
case IFM_25G_KR:
#endif
#ifdef IFM_25G_KR1
case IFM_25G_KR1:
#endif
#ifdef IFM_25G_KR_S
case IFM_25G_KR_S:
#endif
#ifdef IFM_25G_LR
case IFM_25G_LR:
#endif
#ifdef IFM_25G_PCIE
case IFM_25G_PCIE:
#endif
#ifdef IFM_25G_SR
case IFM_25G_SR:
#endif
#ifdef IFM_25G_T
case IFM_25G_T:
#endif
iface->speed = 25000; break;
#ifdef IFM_400G_AUI8
case IFM_400G_AUI8:
#endif
#ifdef IFM_400G_AUI8_AC
case IFM_400G_AUI8_AC:
#endif
#ifdef IFM_400G_DR4
case IFM_400G_DR4:
#endif
#ifdef IFM_400G_FR8
case IFM_400G_FR8:
#endif
#ifdef IFM_400G_LR8
case IFM_400G_LR8:
#endif
iface->speed = 400000; break;
#ifdef IFM_40G_CR4
case IFM_40G_CR4:
#endif
#ifdef IFM_40G_ER4
case IFM_40G_ER4:
#endif
#ifdef IFM_40G_KR4
case IFM_40G_KR4:
#endif
#ifdef IFM_40G_LR4
case IFM_40G_LR4:
#endif
#ifdef IFM_40G_SR4
case IFM_40G_SR4:
#endif
#ifdef IFM_40G_XLAUI
case IFM_40G_XLAUI:
#endif
#ifdef IFM_40G_XLAUI_AC
case IFM_40G_XLAUI_AC:
#endif
#ifdef IFM_40G_XLPPI
case IFM_40G_XLPPI:
#endif
#ifdef IFM_40G_LM4
case IFM_40G_LM4:
#endif
iface->speed = 40000; break;
#ifdef IFM_5000_KR
case IFM_5000_KR:
#endif
#ifdef IFM_5000_KR1
case IFM_5000_KR1:
#endif
#ifdef IFM_5000_KR_S
case IFM_5000_KR_S:
#endif
#ifdef IFM_5000_T
case IFM_5000_T:
#endif
iface->speed = 5000; break;
#ifdef IFM_50G_AUI1
case IFM_50G_AUI1:
#endif
#ifdef IFM_50G_AUI1_AC
case IFM_50G_AUI1_AC:
#endif
#ifdef IFM_50G_AUI2
case IFM_50G_AUI2:
#endif
#ifdef IFM_50G_AUI2_AC
case IFM_50G_AUI2_AC:
#endif
#ifdef IFM_50G_CP
case IFM_50G_CP:
#endif
#ifdef IFM_50G_CR2
case IFM_50G_CR2:
#endif
#ifdef IFM_50G_FR
case IFM_50G_FR:
#endif
#ifdef IFM_50G_KR2
case IFM_50G_KR2:
#endif
#ifdef IFM_50G_KR_PAM4
case IFM_50G_KR_PAM4:
#endif
#ifdef IFM_50G_LAUI2
case IFM_50G_LAUI2:
#endif
#ifdef IFM_50G_LAUI2_AC
case IFM_50G_LAUI2_AC:
#endif
#ifdef IFM_50G_LR
case IFM_50G_LR:
#endif
#ifdef IFM_50G_LR2
case IFM_50G_LR2:
#endif
#ifdef IFM_50G_PCIE
case IFM_50G_PCIE:
#endif
#ifdef IFM_50G_SR
case IFM_50G_SR:
#endif
#ifdef IFM_50G_SR2
case IFM_50G_SR2:
#endif
#ifdef IFM_50G_KR4
case IFM_50G_KR4:
#endif
iface->speed = 50000; break;
#ifdef IFM_56G_R4
case IFM_56G_R4:
#endif
iface->speed = 56000; break;
default:
iface->speed = -1;
}
}
#endif
#ifdef __sun
if ((options->showType & FF_LOCALIP_TYPE_MAC_BIT) && ioctl(sockfd, SIOCGIFHWADDR, &ifr) == 0)
{
+6 -1
View File
@@ -18,6 +18,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type,
ffStrbufInit(&ip->ipv6);
ffStrbufInit(&ip->mac);
ip->defaultRoute = defaultRoute;
ip->speed = -1;
ip->mtu = -1;
}
else
@@ -150,7 +151,11 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results)
}
if (!newIp)
FF_LIST_GET(FFLocalIpResult, *results, results->length - 1)->mtu = (int32_t) adapter->Mtu;
{
FFLocalIpResult* result = FF_LIST_GET(FFLocalIpResult, *results, results->length - 1);
result->speed = (int32_t) (adapter->ReceiveLinkSpeed / 1000);
result->mtu = (int32_t) adapter->Mtu;
}
}
return NULL;
+1
View File
@@ -17,6 +17,7 @@ typedef struct FFPackagesResult
uint32_t guixHome;
uint32_t guixSystem;
uint32_t guixUser;
uint32_t linglong;
uint32_t lpkg;
uint32_t lpkgbuild;
uint32_t nixDefault;
+1
View File
@@ -471,6 +471,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
{
packageCounts->guixSystem += getGuixPackages(baseDir, "/run/current-system/profile");
}
if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", DT_DIR);
}
static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options)
@@ -8,7 +8,7 @@
#include "detection/displayserver/displayserver.h"
#include "util/mallocHelper.h"
#include "util/stringUtils.h"
#include "util/linux/elf.h"
#include "util/binary.h"
static const char* getSystemMonospaceFont(void)
{
@@ -315,7 +315,7 @@ static void detectSt(FFTerminalFontResult* terminalFont, const FFTerminalResult*
{
ffStrbufClear(&font);
const char* error = ffElfExtractStrings(terminal->exePath.chars, elfExtractStringsCallBack, &font);
const char* error = ffBinaryExtractStrings(terminal->exePath.chars, elfExtractStringsCallBack, &font);
if (error)
{
ffStrbufAppendS(&terminalFont->error, error);
+19 -2
View File
@@ -3,6 +3,7 @@
#include "common/processing.h"
#include "common/properties.h"
#include "util/stringUtils.h"
#include "util/binary.h"
#include <ctype.h>
#ifdef __FreeBSD__
@@ -250,8 +251,24 @@ FF_MAYBE_UNUSED static bool getTerminalVersionTermux(FFstrbuf* version)
return version->length > 0;
}
FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* version)
static bool extractGnomeTerminalVersion(const char *str, FF_MAYBE_UNUSED uint32_t len, void *userdata)
{
if (!ffCharIsDigit(str[0])) return true;
int count = 0;
sscanf(str, "%*d.%*d.%*d%n", &count);
if (count == 0) return true;
ffStrbufSetS((FFstrbuf*) userdata, str);
return false;
}
FF_MAYBE_UNUSED static bool getTerminalVersionGnome(FFstrbuf* exe, FFstrbuf* version)
{
if (exe->chars[0] == '/')
{
ffBinaryExtractStrings(exe->chars, extractGnomeTerminalVersion, version);
if (version->length) return true;
}
if(ffProcessAppendStdOut(version, (char* const[]){
"gnome-terminal",
"--version",
@@ -590,7 +607,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal"))
return getTerminalVersionGnome(version);
return getTerminalVersionGnome(exe, version);
if(ffStrbufIgnCaseEqualS(processName, "konsole"))
return getTerminalVersionKonsole(exe, version);
@@ -384,6 +384,14 @@ const FFShellResult* ffDetectShell()
result.tty = -1;
pid_t ppid = getppid();
const char* ignoreParent = getenv("FFTS_IGNORE_PARENT");
if (ignoreParent && ffStrEquals(ignoreParent, "1"))
{
FF_STRBUF_AUTO_DESTROY _ = ffStrbufCreate();
ffProcessGetBasicInfoLinux(ppid, &_, &ppid, NULL);
}
ppid = getShellInfo(&result, ppid);
getUserShellFromEnv(&result);
setShellInfoDetails(&result);
@@ -5,6 +5,7 @@
#include "util/mallocHelper.h"
#include "util/windows/registry.h"
#include "util/windows/unicode.h"
#include "util/stringUtils.h"
#include <windows.h>
#include <wchar.h>
@@ -345,6 +346,10 @@ const FFShellResult* ffDetectShell(void)
if(!ffProcessGetInfoWindows(0, &ppid, NULL, NULL, NULL, NULL, NULL))
return &result;
const char* ignoreParent = getenv("FFTS_IGNORE_PARENT");
if (ignoreParent && ffStrEquals(ignoreParent, "1"))
ffProcessGetInfoWindows(ppid, &ppid, NULL, NULL, NULL, NULL, NULL);
ppid = getShellInfo(&result, ppid);
if (result.processName.length > 0)
+4 -2
View File
@@ -1,8 +1,8 @@
#include "version.h"
#if defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64)
#if defined(__x86_64__)
#define FF_ARCHITECTURE "x86_64"
#elif defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(__i586__) || defined(__i586) || defined(__i686__) || defined(__i686)
#elif defined(__i386__)
#define FF_ARCHITECTURE "i386"
#elif defined(__aarch64__)
#define FF_ARCHITECTURE "aarch64"
@@ -16,6 +16,8 @@
#define FF_ARCHITECTURE "riscv"
#elif defined(__s390x__)
#define FF_ARCHITECTURE "s390x"
#elif defined(__loongarch__)
#define FF_ARCHITECTURE "loongarch"
#else
#define FF_ARCHITECTURE "unknown"
#endif
+20
View File
@@ -0,0 +1,20 @@
..',;;;;;;,,..
..,;;;;;;;;;;;;;;;;,..
.';;;;;;;;;;;;;;;;;;;;;;;;,.
.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'
.;;;;;;;;;$2clodddol:$1;;;;;;;;;;;;;;;;.
';;;;;;;$2ckXWWWNNWWWN0d:$1;;;;;;;;;;;;;;'
';;;;;;$2cOWWKxl:$1;;;:$2okXWXx$1;;;;;;;;;;;;;;,
;;;;;;$2:XWWo$1;;;;;;;;;;;$2ONNx$1;;;;;;;;;;;;;;.
,;;;;;;$2xWMk$1;;;;;;;;;;;;;$20NX:$1;;;;;;;;;;;;;;
;;;;;;;$2xMMk$1;;;;;;;;;;;;;$2oXNdcloooolc:$1;;;;;
,;;;;;;$2:NMWl$1;;;;;;;;;;;;$2ckodKK00000Oc$1;;;;;
.;;;;;;;$2cKMWOo:$1;;;;;$2cox0Xccdl:$1;;;;;:;;;;;'
;;;;;;;;;$2o0WWNK000KXXKkodKKo$1;;;;;;;;;;;;
,;;;;;;;;;$2:loxxxxdlc$1;;;;$2xKKxc$1;;;;;;;;;
,;;;;;;;;;;;;;;;;;;;;;;;$2ckK0o;$1;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;$2:l$1;;;;;;.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;.
;;;;;;;;;;;;;;;;;;;;;;.
';;;;;;;;;;;;,
';;'.
+16
View File
@@ -0,0 +1,16 @@
______________
/P$2aooooooooooooa$19\
H$2EEEEEEEEEEEEEEEE$1H
H$2EEEEEEEEEEEEEEEE$1H
\baaaaaaap;$2ZZZZ$1,/*
x%"$2ZZZZ$1,%^
>7'$2ZZZZ$1,%"
/7'$2ZZZZ$1/>'
,//$2ZZZZ$1,//
,%<$2ZZZZ$1,%<
>%^$2ZZZZ$1x%^_____
4>'$2ZZZZ$1---------9b
H$2EEEEEEEEEEEEEEEE$1H
H$2EEEEEEEEEEEEEEEE$1H
Yq$2^************^$1pY
``````````````
+7
View File
@@ -0,0 +1,7 @@
_____
[$2BBBBB$1]
`^^7$2&$1/`
,/$2&$1/`
,/$2&$1Z__
[$2BBBBB$1]
`^^^^^`
+30
View File
@@ -2332,6 +2332,17 @@ static const FFlogo L[] = {
.colorKeys = FF_COLOR_FG_GREEN,
.colorTitle = FF_COLOR_FG_YELLOW,
},
// Lingmo OS
{
.names = {"Lingmo", "lingmo", "LingmoOS", "lingmoos"},
.lines = FASTFETCH_DATATEXT_LOGO_LINGMO,
.colors = {
FF_COLOR_FG_BLUE,
FF_COLOR_FG_WHITE,
},
.colorKeys = FF_COLOR_FG_BLUE,
.colorTitle = FF_COLOR_FG_BLUE,
},
// Linspire
{
.names = {"Linspire", "Lindows"},
@@ -3959,6 +3970,25 @@ static const FFlogo S[] = {
FF_COLOR_FG_WHITE,
},
},
// SleeperOS
{
.names = {"SleeperOS"},
.lines = FASTFETCH_DATATEXT_LOGO_SLEEPEROS,
.colors = {
FF_COLOR_FG_CYAN,
FF_COLOR_FG_WHITE,
}
},
// SleeperOS
{
.names = {"SleeperOS_small"},
.type = FF_LOGO_LINE_TYPE_SMALL_BIT,
.lines = FASTFETCH_DATATEXT_LOGO_SLEEPEROS_SMALL,
.colors = {
FF_COLOR_FG_CYAN,
FF_COLOR_FG_WHITE,
}
},
// Slitaz
{
.names = {"Slitaz"},
+2 -1
View File
@@ -57,7 +57,8 @@ void ffPrintColors(FFColorsOptions* options)
if (options->symbol == FF_COLORS_SYMBOL_BACKGROUND)
{
const char* term = getenv("TERM");
if (term && ffStrEquals(term, "linux"))
// Should be "linux", however some terminal mulitplexer overrides $TERM
if (term && !ffStrStartsWith(term, "xterm"))
ffStrbufAppendS(&result, "\e[5m");
}
#endif
+12 -1
View File
@@ -140,10 +140,21 @@ void ffPrintDisplay(FFDisplayOptions* options)
{
double ppi = sqrt(result->width * result->width + result->height * result->height) / inch;
char refreshRate[16];
if(result->refreshRate > 0)
{
if(options->preciseRefreshRate)
snprintf(refreshRate, sizeof(refreshRate), "%g", ((int) (result->refreshRate * 1000 + 0.5)) / 1000.0);
else
snprintf(refreshRate, sizeof(refreshRate), "%i", (uint32_t) (result->refreshRate + 0.5));
}
else
refreshRate[0] = 0;
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISPLAY_NUM_FORMAT_ARGS, ((FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_UINT, &result->width, "width"},
{FF_FORMAT_ARG_TYPE_UINT, &result->height, "height"},
{FF_FORMAT_ARG_TYPE_DOUBLE, &result->refreshRate, "refresh-rate"},
{FF_FORMAT_ARG_TYPE_STRING, refreshRate, "refresh-rate"},
{FF_FORMAT_ARG_TYPE_UINT, &result->scaledWidth, "scaled-width"},
{FF_FORMAT_ARG_TYPE_UINT, &result->scaledHeight, "scaled-height"},
{FF_FORMAT_ARG_TYPE_STRBUF, &result->name, "name"},
+12 -1
View File
@@ -5,7 +5,7 @@
#include "util/stringUtils.h"
#define FF_LOCALIP_DISPLAY_NAME "Local IP"
#define FF_LOCALIP_NUM_FORMAT_ARGS 6
#define FF_LOCALIP_NUM_FORMAT_ARGS 7
#pragma GCC diagnostic ignored "-Wsign-conversion"
static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right)
@@ -111,6 +111,14 @@ void ffPrintLocalIp(FFLocalIpOptions* options)
}
else
{
FF_STRBUF_AUTO_DESTROY speedStr = ffStrbufCreate();
if (ip->speed > 0)
{
if (ip->speed >= 1000)
ffStrbufSetF(&speedStr, "%g Gbps", ip->speed / 1000.0);
else
ffStrbufSetF(&speedStr, "%u Mbps", (unsigned) ip->speed);
}
FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_LOCALIP_NUM_FORMAT_ARGS, ((FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &ip->ipv4, "ipv4"},
{FF_FORMAT_ARG_TYPE_STRBUF, &ip->ipv6, "ipv6"},
@@ -118,6 +126,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options)
{FF_FORMAT_ARG_TYPE_STRBUF, &ip->name, "ifname"},
{FF_FORMAT_ARG_TYPE_BOOL, &ip->defaultRoute, "is-default-route"},
{FF_FORMAT_ARG_TYPE_INT, &ip->mtu, "mtu"},
{FF_FORMAT_ARG_TYPE_STRBUF, &speedStr, "speed"},
}));
}
++index;
@@ -376,6 +385,7 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs
yyjson_mut_obj_add_strbuf(doc, obj, "mac", &ip->mac);
yyjson_mut_obj_add_strbuf(doc, obj, "name", &ip->name);
yyjson_mut_obj_add_int(doc, obj, "mtu", ip->mtu);
yyjson_mut_obj_add_int(doc, obj, "speed", ip->speed);
}
FF_LIST_FOR_EACH(FFLocalIpResult, ip, results)
@@ -396,6 +406,7 @@ void ffPrintLocalIpHelpFormat(void)
"Interface name - ifname",
"Is default route - is-default-route",
"MTU size in bytes - mtu",
"Link speed (formatted) - speed",
}));
}
+1
View File
@@ -31,6 +31,7 @@ typedef enum FFPackagesFlags
FF_PACKAGES_FLAG_LPKG_BIT = 1 << 21,
FF_PACKAGES_FLAG_LPKGBUILD_BIT = 1 << 22,
FF_PACKAGES_FLAG_GUIX_BIT = 1 << 23,
FF_PACKAGES_FLAG_LINGLONG_BIT = 1 << 24,
} FFPackagesFlags;
typedef struct FFPackagesOptions
+9 -2
View File
@@ -4,7 +4,7 @@
#include "modules/packages/packages.h"
#include "util/stringUtils.h"
#define FF_PACKAGES_NUM_FORMAT_ARGS 36
#define FF_PACKAGES_NUM_FORMAT_ARGS 37
void ffPrintPackages(FFPackagesOptions* options)
{
@@ -71,6 +71,7 @@ void ffPrintPackages(FFPackagesOptions* options)
FF_PRINT_PACKAGE_NAME(guixSystem, "guix-system")
FF_PRINT_PACKAGE_NAME(guixUser, "guix-user")
FF_PRINT_PACKAGE_NAME(guixHome, "guix-home")
FF_PRINT_PACKAGE(linglong)
putchar('\n');
}
@@ -113,6 +114,7 @@ void ffPrintPackages(FFPackagesOptions* options)
{FF_FORMAT_ARG_TYPE_UINT, &counts.guixSystem, "guix-system"},
{FF_FORMAT_ARG_TYPE_UINT, &counts.guixUser, "guix-user"},
{FF_FORMAT_ARG_TYPE_UINT, &counts.guixHome, "guix-home"},
{FF_FORMAT_ARG_TYPE_UINT, &counts.linglong, "linglong"},
{FF_FORMAT_ARG_TYPE_UINT, &nixAll, "nix-all"},
{FF_FORMAT_ARG_TYPE_UINT, &flatpakAll, "flatpak-all"},
{FF_FORMAT_ARG_TYPE_UINT, &brewAll, "brew-all"},
@@ -171,6 +173,7 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
case 'L': if (false);
FF_TEST_PACKAGE_NAME(LPKG)
FF_TEST_PACKAGE_NAME(LPKGBUILD)
FF_TEST_PACKAGE_NAME(LINGLONG)
break;
case 'M': if (false);
FF_TEST_PACKAGE_NAME(MACPORTS)
@@ -279,6 +282,7 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
case 'L': if (false);
FF_TEST_PACKAGE_NAME(LPKG)
FF_TEST_PACKAGE_NAME(LPKGBUILD)
FF_TEST_PACKAGE_NAME(LINGLONG)
break;
case 'M': if (false);
FF_TEST_PACKAGE_NAME(MACPORTS)
@@ -356,6 +360,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
FF_TEST_PACKAGE_NAME(AM)
FF_TEST_PACKAGE_NAME(SORCERY)
FF_TEST_PACKAGE_NAME(GUIX)
FF_TEST_PACKAGE_NAME(LINGLONG)
#undef FF_TEST_PACKAGE_NAME
}
}
@@ -406,12 +411,13 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
FF_APPEND_PACKAGE_COUNT(guixSystem)
FF_APPEND_PACKAGE_COUNT(guixUser)
FF_APPEND_PACKAGE_COUNT(guixHome)
FF_APPEND_PACKAGE_COUNT(linglong)
yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch);
}
void ffPrintPackagesHelpFormat(void)
{
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery), {28} (lpkg), {29} (lpkgbuild), {30} (guix-system), {31} (guix-user), {32} (guix-home)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery), {28} (lpkg), {29} (lpkgbuild), {30} (guix-system), {31} (guix-user), {32} (guix-home), {33} (linglong)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
"Number of all packages - all",
"Number of pacman packages - pacman",
"Pacman branch on manjaro - pacman-branch",
@@ -444,6 +450,7 @@ void ffPrintPackagesHelpFormat(void)
"Number of guix-system packages - guix-system",
"Number of guix-user packages - guix-user",
"Number of guix-home packages - guix-home",
"Number of linglong packages - linglong",
"Total number of all nix packages - nix-all",
"Total number of all flatpak app packages - flatpak-all",
"Total number of all brew packages - brew-all",
+1 -1
View File
@@ -2,4 +2,4 @@
#include "fastfetch.h"
const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata);
const char* ffBinaryExtractStrings(const char* file, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata);
+186
View File
@@ -0,0 +1,186 @@
#include "binary.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <mach-o/loader.h>
#include <mach-o/swap.h>
#include <mach-o/fat.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" // swap_fat_arch
// Ref: https://github.com/AlexDenisov/segment_dumper/blob/master/main.c
static inline bool readData(FILE *objFile, void *buf, size_t size, off_t offset)
{
fseek(objFile, offset, SEEK_SET);
return fread(buf, 1, size, objFile) == size;
}
static bool handleMachSection(FILE *objFile, const char *name, off_t offset, size_t size, bool (*cb)(const char *str, uint32_t len, void *userdata), void *userdata)
{
if (!ffStrEquals(name, "__cstring")) return true;
FF_AUTO_FREE char* data = (char*) malloc(size);
if (!readData(objFile, data, size, offset))
return true;
for (size_t off = 0; off < size; ++off)
{
const char* p = (const char*) data + off;
if (*p == '\0') continue;
uint32_t len = (uint32_t) strlen(p);
if (*p >= ' ' && *p <= '~') // Ignore control characters
{
if (!cb(p, len, userdata)) return false;
}
off += len;
}
return true;
}
static const char* dumpMachHeader(FILE *objFile, off_t offset, bool is_64, bool (*cb)(const char *str, uint32_t len, void *userdata), void *userdata)
{
uint32_t ncmds;
off_t loadCommandsOffset = offset;
if (is_64)
{
struct mach_header_64 header;
if (!readData(objFile, &header, sizeof(header), offset))
return "read mach header failed";
ncmds = header.ncmds;
loadCommandsOffset += sizeof(header);
}
else
{
struct mach_header header;
if (!readData(objFile, &header, sizeof(header), offset))
return "read mach header failed";
ncmds = header.ncmds;
loadCommandsOffset += sizeof(header);
}
off_t commandOffset = loadCommandsOffset;
struct load_command cmd = {};
for (uint32_t i = 0U; i < ncmds; i++, commandOffset += cmd.cmdsize)
{
if (!readData(objFile, &cmd, sizeof(cmd), commandOffset))
continue;
if (cmd.cmd == LC_SEGMENT_64)
{
struct segment_command_64 segment;
if (!readData(objFile, &segment, sizeof(segment), commandOffset))
continue;
if (!ffStrEquals(segment.segname, "__TEXT")) continue;
for (uint32_t j = 0U; j < segment.nsects; j++)
{
struct section_64 section;
if (!readData(objFile, &section, sizeof(section), (off_t) ((size_t) commandOffset + sizeof(segment) + j * sizeof(section))))
continue;
if (!handleMachSection(objFile, section.sectname, section.offset, section.size, cb, userdata))
return NULL;
}
}
else if (cmd.cmd == LC_SEGMENT)
{
struct segment_command segment;
if (!readData(objFile, &segment, sizeof(segment), commandOffset))
continue;
if (!ffStrEquals(segment.segname, "__TEXT")) continue;
for (uint32_t j = 0; j < segment.nsects; j++)
{
struct section section;
if (!readData(objFile, &section, sizeof(section), (off_t) ((size_t) commandOffset + sizeof(segment) + j * sizeof(section))))
continue;
if (!handleMachSection(objFile, section.sectname, section.offset, section.size, cb, userdata))
return NULL;
}
}
return NULL;
}
return NULL;
}
static const char* dumpFatHeader(FILE *objFile, bool (*cb)(const char *str, uint32_t len, void *userdata), void *userdata)
{
struct fat_header header;
if (!readData(objFile, &header, sizeof(header), 0))
return "read fat header failed";
bool needSwap = header.magic == FAT_CIGAM || header.magic == FAT_CIGAM_64;
if (needSwap) swap_fat_header(&header, NX_UnknownByteOrder);
for (uint32_t i = 0U; i < header.nfat_arch; i++)
{
off_t machHeaderOffset = 0;
if (header.magic == FAT_MAGIC)
{
struct fat_arch arch;
if (!readData(objFile, &arch, sizeof(arch), (off_t) (sizeof(header) + i * sizeof(arch))))
continue;
if (needSwap)
swap_fat_arch(&arch, 1, NX_UnknownByteOrder);
machHeaderOffset = (off_t)arch.offset;
}
else
{
struct fat_arch_64 arch;
if (!readData(objFile, &arch, sizeof(arch), (off_t) (sizeof(header) + i * sizeof(arch))))
continue;
if (needSwap)
swap_fat_arch_64(&arch, 1, NX_UnknownByteOrder);
machHeaderOffset = (off_t)arch.offset;
}
uint32_t magic;
if (!readData(objFile, &magic, sizeof(magic), machHeaderOffset))
continue;
if (magic == MH_MAGIC_64 || magic == MH_MAGIC)
{
dumpMachHeader(objFile, machHeaderOffset, magic == MH_MAGIC_64, cb, userdata);
return NULL;
}
}
return "Unsupported fat header";
}
const char *ffBinaryExtractStrings(const char *machoFile, bool (*cb)(const char *str, uint32_t len, void *userdata), void *userdata)
{
FF_AUTO_CLOSE_FILE FILE *objFile = fopen(machoFile, "rb");
if (objFile == NULL)
return "File could not be opened";
uint32_t magic;
if (!readData(objFile, &magic, sizeof(magic), 0))
return "read magic number failed";
// MH_CIGAM and MH_CIGAM_64 seem to be no longer used, as `swap_mach_header` is marked as deprecated.
// However FAT_CIGAM and FAT_CIGAM_64 are still used (/usr/bin/vim).
if (magic != MH_MAGIC && magic != MH_MAGIC_64 && magic != FAT_CIGAM && magic != FAT_CIGAM_64 && magic != FAT_MAGIC && magic != FAT_MAGIC_64)
return "Unsupported format or big endian mach-o file";
if (magic == FAT_MAGIC || magic == FAT_MAGIC_64 || magic == FAT_CIGAM || magic == FAT_CIGAM_64)
return dumpFatHeader(objFile, cb, userdata);
else
return dumpMachHeader(objFile, 0, magic == MH_MAGIC_64, cb, userdata);
}
+107
View File
@@ -0,0 +1,107 @@
#include "binary.h"
#if defined(FF_HAVE_ELF) || defined(__sun)
#include "common/io/io.h"
#include "common/library.h"
#include "util/stringUtils.h"
#include <libelf.h>
#include <fcntl.h>
struct FFElfData {
FF_LIBRARY_SYMBOL(elf_version)
FF_LIBRARY_SYMBOL(elf_begin)
FF_LIBRARY_SYMBOL(elf_getshdrstrndx)
FF_LIBRARY_SYMBOL(elf_nextscn)
FF_LIBRARY_SYMBOL(elf64_getshdr)
FF_LIBRARY_SYMBOL(elf32_getshdr)
FF_LIBRARY_SYMBOL(elf_getdata)
FF_LIBRARY_SYMBOL(elf_strptr)
FF_LIBRARY_SYMBOL(elf_end)
bool inited;
} elfData;
const char* ffBinaryExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata)
{
if (!elfData.inited)
{
elfData.inited = true;
FF_LIBRARY_LOAD(libelf, &instance.config.library.libelf, "dlopen libelf" FF_LIBRARY_EXTENSION " failed", "libelf" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_version)
if (elfData.ffelf_version(EV_CURRENT) == EV_NONE) return "elf_version() failed";
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_begin)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_getshdrstrndx)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_nextscn)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf64_getshdr)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf32_getshdr)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_getdata)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_strptr)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libelf, elfData, elf_end)
libelf = NULL;
}
if (elfData.ffelf_end == NULL)
return "load libelf failed";
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY, 0);
if (fd < 0) return "open() failed";
Elf* elf = elfData.ffelf_begin(fd, ELF_C_READ, NULL);
if (elf == NULL) return "elf_begin() failed";
size_t shstrndx = 0;
if (elfData.ffelf_getshdrstrndx(elf, &shstrndx) < 0)
{
elfData.ffelf_end(elf);
return "elf_getshdrstrndx() failed";
}
Elf_Scn* scn = NULL;
while ((scn = elfData.ffelf_nextscn(elf, scn)) != NULL)
{
Elf64_Shdr* shdr64 = elfData.ffelf64_getshdr(scn);
Elf32_Shdr* shdr32 = NULL;
if (shdr64 == NULL)
{
shdr32 = elfData.ffelf32_getshdr(scn);
if (shdr32 == NULL) continue;
}
const char* name = elfData.ffelf_strptr(elf, shstrndx, shdr64 ? shdr64->sh_name : shdr32->sh_name);
if (name == NULL || !ffStrEquals(name, ".rodata")) continue;
Elf_Data* data = elfData.ffelf_getdata(scn, NULL);
if (data == NULL) continue;
for (size_t off = 0; off < data->d_size; ++off)
{
const char* p = (const char*) data->d_buf + off;
if (*p == '\0') continue;
uint32_t len = (uint32_t) strlen(p);
if (*p >= ' ' && *p <= '~') // Ignore control characters
{
if (!cb(p, len, userdata)) break;
}
off += len;
}
break;
}
elfData.ffelf_end(elf);
return NULL;
}
#else
const char* ffBinaryExtractStrings(const char* file, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata)
{
FF_UNUSED(file, cb, userdata);
return "Fastfetch was built without libelf support";
}
#endif
+39
View File
@@ -0,0 +1,39 @@
#include "binary.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include <windows.h>
#include <imagehlp.h>
#include <stdlib.h>
#include <string.h>
const char* ffBinaryExtractStrings(const char *peFile, bool (*cb)(const char *str, uint32_t len, void *userdata), void *userdata)
{
__attribute__((__cleanup__(UnMapAndLoad))) LOADED_IMAGE loadedImage = {};
if (!MapAndLoad(peFile, NULL, &loadedImage, FALSE, TRUE))
return "File could not be loaded";
for (ULONG i = 0; i < loadedImage.NumberOfSections; ++i)
{
PIMAGE_SECTION_HEADER section = &loadedImage.Sections[i];
if ((section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) && ffStrEquals((const char*) section->Name, ".rdata"))
{
uint8_t *data = (uint8_t *) loadedImage.MappedAddress + section->PointerToRawData;
for (size_t off = 0; off < section->SizeOfRawData; ++off)
{
const char* p = (const char*) data + off;
if (*p == '\0') continue;
uint32_t len = (uint32_t) strlen(p);
if (*p >= ' ' && *p <= '~') // Ignore control characters
{
if (!cb(p, len, userdata)) break;
}
off += len;
}
}
}
return NULL;
}
-84
View File
@@ -1,84 +0,0 @@
#include "elf.h"
#ifdef FF_HAVE_ELF
#include "common/io/io.h"
#include "common/library.h"
#include "util/stringUtils.h"
#include <libelf.h>
#include <fcntl.h>
const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata)
{
FF_LIBRARY_LOAD(libelf, &instance.config.library.libelf, "dlopen libelf" FF_LIBRARY_EXTENSION " failed", "libelf" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_version)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_begin)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_getshdrstrndx)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_nextscn)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf64_getshdr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf32_getshdr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_getdata)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_strptr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libelf, elf_end)
if (ffelf_version(EV_CURRENT) == EV_NONE) return "elf_version() failed";
FF_AUTO_CLOSE_FD int fd = open(elfFile, O_RDONLY, 0);
if (fd < 0) return "open() failed";
Elf* elf = ffelf_begin(fd, ELF_C_READ, NULL);
if (elf == NULL) return "elf_begin() failed";
size_t shstrndx = 0;
if (ffelf_getshdrstrndx(elf, &shstrndx) < 0)
{
ffelf_end(elf);
return "elf_getshdrstrndx() failed";
}
Elf_Scn* scn = NULL;
while ((scn = ffelf_nextscn(elf, scn)) != NULL)
{
Elf64_Shdr* shdr64 = ffelf64_getshdr(scn);
Elf32_Shdr* shdr32 = NULL;
if (shdr64 == NULL)
{
shdr32 = ffelf32_getshdr(scn);
if (shdr32 == NULL) continue;
}
const char* name = ffelf_strptr(elf, shstrndx, shdr64 ? shdr64->sh_name : shdr32->sh_name);
if (name == NULL || !ffStrEquals(name, ".rodata")) continue;
Elf_Data* data = ffelf_getdata(scn, NULL);
if (data == NULL) continue;
for (size_t off = 0; off < data->d_size; ++off)
{
const char* p = (const char*) data->d_buf + off;
if (*p == '\0') continue;
uint32_t len = (uint32_t) strlen(p);
if (*p >= ' ' && *p <= '~') // Ignore control characters
{
if (!cb(p, len, userdata)) break;
}
off += len;
}
break;
}
ffelf_end(elf);
return NULL;
}
#else
const char* ffElfExtractStrings(const char* elfFile, bool (*cb)(const char* str, uint32_t len, void* userdata), void* userdata)
{
FF_UNUSED(elfFile, cb, userdata);
return "Fastfetch was built without libelf support";
}
#endif
+59
View File
@@ -0,0 +1,59 @@
#include "path.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result)
{
char* path = getenv("PATH");
if(!path)
return "$PATH not set";
#ifdef _WIN32
const bool appendExe = !ffStrEndsWithIgnCase(name, ".exe");
#endif
for (char* token = path; *token; path = token + 1)
{
token = strchr(path,
#ifdef _WIN32
';'
#else
':'
#endif
);
if (!token) token = path + strlen(path);
ffStrbufSetNS(result, (uint32_t)(token - path), path);
ffStrbufEnsureEndsWithC(result,
#ifdef _WIN32
'\\'
#else
'/'
#endif
);
ffStrbufAppendS(result, name);
#ifdef _WIN32
if (appendExe) ffStrbufAppendS(result, ".exe");
if (!ffPathExists(result->chars, FF_PATHTYPE_FILE))
continue;
#else
struct stat st;
if (stat(result->chars, &st) < 0 || !(st.st_mode & S_IXUSR))
continue;
#endif
return NULL;
}
ffStrbufClear(result);
return "Executable not found";
}
bool ffIsAbsolutePath(const char* path)
{
#ifdef _WIN32
return ffCharIsEnglishAlphabet(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/');
#else
return path[0] == '/';
#endif
}
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include "fastfetch.h"
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result);
bool ffIsAbsolutePath(const char* path);