mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-30 00:37:23 +01:00
@@ -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
@@ -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"
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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 "$@"
|
||||
Vendored
+6
@@ -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
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
fastfetch_2.21.2_source.buildinfo universe/utils optional
|
||||
fastfetch_2.21.3_source.buildinfo universe/utils optional
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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") ||
|
||||
|
||||
@@ -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[]) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ typedef struct FFLocalIpResult
|
||||
FFstrbuf ipv6;
|
||||
FFstrbuf mac;
|
||||
int32_t mtu;
|
||||
int32_t speed;
|
||||
bool defaultRoute;
|
||||
} FFLocalIpResult;
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;;;;;;.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;.
|
||||
;;;;;;;;;;;;;;;;;;;;;;.
|
||||
';;;;;;;;;;;;,
|
||||
';;'.
|
||||
@@ -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
|
||||
``````````````
|
||||
@@ -0,0 +1,7 @@
|
||||
_____
|
||||
[$2BBBBB$1]
|
||||
`^^7$2&$1/`
|
||||
,/$2&$1/`
|
||||
,/$2&$1Z__
|
||||
[$2BBBBB$1]
|
||||
`^^^^^`
|
||||
@@ -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"},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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",
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
@@ -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, §ion, 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, §ion, 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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
const char* ffFindExecutableInPath(const char* name, FFstrbuf* result);
|
||||
bool ffIsAbsolutePath(const char* path);
|
||||
Reference in New Issue
Block a user