diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3a9df9a7c..7b3260a5e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,7 +1,7 @@ --- name: Bug report about: Create a report to help us improve -title: '' +title: '[BUG] ' labels: bug assignees: '' @@ -24,12 +24,9 @@ The content of the configuration file you use (if any) //paste here ``` -Output of `env NO_CONFIG=1 fastfetch --load-config all --show-errors --stat --multithreading false --disable-linewrap false --hide-cursor false`: +Output of `fastfetch -c ci.jsonc --format json`: ``` diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 6a2a7bde0..febdba836 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,12 +1,14 @@ --- name: Feature request about: Suggest an idea for this project -title: '' +title: '[FEAT] ' labels: enhancement assignees: '' --- + + # Current state: # Wanted state: diff --git a/.github/ISSUE_TEMPLATE/logo_request.md b/.github/ISSUE_TEMPLATE/logo_request.md index 4c49dc893..223b86f0f 100644 --- a/.github/ISSUE_TEMPLATE/logo_request.md +++ b/.github/ISSUE_TEMPLATE/logo_request.md @@ -1,7 +1,7 @@ --- name: Logo request about: Request a new logo -title: '' +title: '[LOGO] ' labels: logo request assignees: '' @@ -9,10 +9,10 @@ assignees: '' # OS ``` -paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro. +Paste content of /etc/os-release here. If this file doesn't exist, describe a way to identify the distro. ``` # Ascii ``` -paste ascii art here. If you leave this empty, i will try to find the logo myself. +Paste ascii art here. ``` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f15eae60f..563936012 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -215,8 +215,8 @@ jobs: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . cmake --build . --target package --verbose ./fastfetch --list-features - time ./fastfetch -c presets/ci.jsonc - time ./fastfetch -c presets/ci.jsonc --format json + time ./fastfetch + time ./fastfetch --format json time ./flashfetch ldd fastfetch ctest diff --git a/.gitignore b/.gitignore index 94a0919c6..6a7a19529 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ cscope.* tags fastfetch.kdev4 +*.user diff --git a/CHANGELOG.md b/CHANGELOG.md index ff02b1cac..7d24f1742 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +# 2.4.0 + +**We are deprecating flags based config files (will be removed in v3.0.0). We suggest you migrate to json based config files.** One may use `-c /path/to/config.conf --gen-config` to migrate existing flag based config files. + +Changes: +* All flag based presets are removed + +Features: +* Improve performance of detecting rpm and pkg package count (Packages, Linux / FreeBSD) +* Support Apple M3X temperature detection (CPU / GPU, macOS) +* `--ds-force-drm` support a new option `sysfs-only` +* Improve xfce4 version detection +* Detect WM and DE by enumerating running processes (WM / DE, FreeBSD) +* Add a new module `Physical Disk`, which detects product name, full size, serial number and so on. + +Bugfixes: +* Fix crashes sometimes when `--logo-padding-top` is not set (Logo) +* Fix memory usage counting algorithm (Memory, macOS) +* Fix the behavior of `--no-buffer` in Windows +* Fix possible segfault in some devices (Display, Linux) +* Fix segfaults on first use of new images with Sixel flag (Image) + +Logo: +* Remove unnecessary escaping for Adelie logo +* Add EshanizedOS + # 2.3.4 Bugfixes: diff --git a/CMakeLists.txt b/CMakeLists.txt index 12807993e..b9072d5d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.3.4 + VERSION 2.4.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" @@ -340,6 +340,7 @@ set(LIBFASTFETCH_SRC src/modules/opengl/opengl.c src/modules/os/os.c src/modules/packages/packages.c + src/modules/physicaldisk/physicaldisk.c src/modules/processes/processes.c src/modules/player/player.c src/modules/poweradapter/poweradapter.c @@ -394,6 +395,7 @@ if(LINUX) src/detection/cursor/cursor_linux.c src/detection/bluetooth/bluetooth_linux.c src/detection/disk/disk_linux.c + src/detection/physicaldisk/physicaldisk_linux.c src/detection/diskio/diskio_linux.c src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/drm.c @@ -453,6 +455,7 @@ elseif(ANDROID) src/detection/cursor/cursor_nosupport.c src/detection/cpuusage/cpuusage_linux.c src/detection/disk/disk_linux.c + src/detection/physicaldisk/physicaldisk_linux.c src/detection/diskio/diskio_linux.c src/detection/displayserver/displayserver_android.c src/detection/font/font_nosupport.c @@ -506,6 +509,7 @@ elseif(BSD) src/detection/cpuusage/cpuusage_bsd.c src/detection/cursor/cursor_linux.c src/detection/disk/disk_bsd.c + src/detection/physicaldisk/physicaldisk_bsd.c src/detection/diskio/diskio_bsd.c src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/drm.c @@ -529,7 +533,7 @@ elseif(BSD) src/detection/netio/netio_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c - src/detection/packages/packages_linux.c + src/detection/packages/packages_bsd.c src/detection/poweradapter/poweradapter_nosupport.c src/detection/processes/processes_bsd.c src/detection/gtk_qt/qt.c @@ -566,6 +570,7 @@ elseif(APPLE) src/detection/cpuusage/cpuusage_apple.c src/detection/cursor/cursor_apple.m src/detection/disk/disk_bsd.c + src/detection/physicaldisk/physicaldisk_apple.c src/detection/diskio/diskio_apple.c src/detection/displayserver/displayserver_apple.c src/detection/font/font_apple.m @@ -619,6 +624,7 @@ elseif(WIN32) src/detection/cpuusage/cpuusage_windows.c src/detection/cursor/cursor_windows.c src/detection/disk/disk_windows.c + src/detection/physicaldisk/physicaldisk_windows.c src/detection/diskio/diskio_windows.c src/detection/displayserver/displayserver_windows.c src/detection/font/font_windows.c diff --git a/README.md b/README.md index a606dc872..254b4cff9 100644 --- a/README.md +++ b/README.md @@ -89,3 +89,15 @@ Q: Why do you need a very performant version of neofetch? Q: It does not display [*] correctly for me, what can I do? > This is most likely because your system is not implemented (yet). At the moment I am focusing more on making the core app better, than adding more configurations. Feel free to open a pull request if you want to add support for your configuration + +## Star History + +Give it a star to support us! + + + + + + Star History Chart + + diff --git a/doc/json_schema.json b/doc/json_schema.json index 091770f46..7b5516411 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -251,8 +251,24 @@ "description": "Set the path to the file containing OS information. Linux only" }, "dsForceDrm": { - "type": "boolean", - "description": "Force display detection to use `/sys/class/drm`. Linux only", + "description": "Force display detection to use DRM. Linux only", + "oneOf": [ + { + "type": "bool", + "const": false, + "description": "Try `wayland`, then `x11`, then `drm`" + }, + { + "type": "string", + "description": "Use `/sys/class/drm` only.", + "const": "sysfs-only" + }, + { + "type": "bool", + "const": true, + "description": "Try `libdrm` first, then `sysfs` if libdrm failed" + } + ], "default": false }, "wmiTimeout": { @@ -584,6 +600,7 @@ "opengl", "os", "packages", + "physicaldisk", "player", "poweradapter", "processes", @@ -1353,6 +1370,32 @@ } } }, + { + "title": "Physical Disk", + "properties": { + "type": { + "description": "Print physical disk information", + "const": "physicaldisk" + }, + "namePrefix": { + "description": "Show disks with given name prefix only", + "type": "string" + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, { "title": "Public IP", "properties": { diff --git a/presets/all b/presets/all deleted file mode 100644 index 20442e13f..000000000 --- a/presets/all +++ /dev/null @@ -1 +0,0 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:DiskIO:Version:Break:Colors diff --git a/presets/all.jsonc b/presets/all.jsonc index f26925af6..53b553aea 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -53,6 +53,7 @@ "weather", "netio", "diskio", + "physicaldisk", "version", "break", "colors" diff --git a/presets/btw b/presets/btw deleted file mode 100644 index 47a557979..000000000 --- a/presets/btw +++ /dev/null @@ -1,3 +0,0 @@ ---logo arch ---os-format "Arch Linux ({12})" ---packages-format "{} (pacman)" diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 766a08bb5..0283d9ec2 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -62,6 +62,7 @@ }, "netio", "diskio", + "physicaldisk", "version", "break", "colors" diff --git a/presets/examples/1 b/presets/examples/1 deleted file mode 100644 index 99a981ad3..000000000 --- a/presets/examples/1 +++ /dev/null @@ -1 +0,0 @@ -# Load with --load-config examples/1 diff --git a/presets/examples/2 b/presets/examples/2 deleted file mode 100644 index 6bd5a0ce3..000000000 --- a/presets/examples/2 +++ /dev/null @@ -1,24 +0,0 @@ -# Load with --load-config examples/2 -# Note that you must replace the image path to an existing image to display it. - ---kitty /home/linus/Bilder/Gentoo.png ---logo-width 28 - ---separator "  " - ---set-keyless HardwareStart=┌───────── \e[1mHardware Information\e[0m ─────────┐ ---set-keyless SoftwareStart=├───────── \e[1mSoftware Information\e[0m ─────────┤ ---set-keyless InformationEnd=└────────────────────────────────────────┘ ---set-keyless Colors= \e[38m \e[37m \e[36m \e[35m \e[34m \e[33m \e[32m \e[31m ---structure HardwareStart:Host:CPU:GPU:SoftwareStart:OS:Kernel:WM:Shell:Terminal:TerminalFont:Packages:InformationEnd:Colors - ---host-key " " ---cpu-key " " ---gpu-key " ﬙" ---os-key " " ---kernel-key " " ---wm-key " " ---shell-key " " ---terminal-key " " ---terminalfont-key " " ---packages-key " " diff --git a/presets/examples/3 b/presets/examples/3 deleted file mode 100644 index bd89f592f..000000000 --- a/presets/examples/3 +++ /dev/null @@ -1,7 +0,0 @@ -# Load with --load-config example/3 - ---logo debian_small ---structure Vulkan:OpenGL:OpenCL:Memory:Disk:LocalIP ---binary-prefix si ---localip-show-loop false ---disk-folders /:/home:/boot:/efi diff --git a/presets/examples/4 b/presets/examples/4 deleted file mode 100644 index f41e25a73..000000000 --- a/presets/examples/4 +++ /dev/null @@ -1,7 +0,0 @@ -# Load with --load-config examples/4 - ---color blue ---logo arch_small ---logo-padding-right 1 ---separator "  " ---structure DateTime:Break:Player:Media diff --git a/presets/examples/5 b/presets/examples/5 deleted file mode 100644 index 27180ca9c..000000000 --- a/presets/examples/5 +++ /dev/null @@ -1,11 +0,0 @@ -# Load with --load-config examples/5 - ---logo none ---color reset_magenta ---structure Theme:Icons:Font:Cursor ---theme-key T ---theme-format {7} ---icons-key I ---icons-format {5} ---font-key F ---cursor-key C diff --git a/presets/hardware b/presets/hardware deleted file mode 100644 index f93873197..000000000 --- a/presets/hardware +++ /dev/null @@ -1,4 +0,0 @@ ---structure Host:Display:CPU:GPU:Memory:Disk:Battery ---memory-format "{?2}{2}{?}" ---disk-format "{?2}{2}{?}" ---battery-format "{?1}{1} {?}{?2}{2} {?}{?3}({3}){?}" diff --git a/presets/neofetch b/presets/neofetch deleted file mode 100644 index 925f4705b..000000000 --- a/presets/neofetch +++ /dev/null @@ -1,9 +0,0 @@ ---structure "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Display:DE:WM:WMTheme:Theme:Icons:Terminal:TerminalFont:CPU:GPU:Memory:Break:Colors" ---host-format "{/2}{-}{/}{2}{?3} {3}{?}" ---os-format "{3} {12}" ---display-key Resolution ---display-compact-type original ---de-format "{2} {3}" ---theme-format "{?1}{1}{?3} {3}{?} [Plasma], {?}{7}" ---terminalfont-format "{/2}{-}{/}{2}{?3} {3}{?}" ---memory-format "{/1}{-}{/}{/2}{-}{/}{} / {}" diff --git a/presets/paleofetch b/presets/paleofetch deleted file mode 100644 index 66913e3dc..000000000 --- a/presets/paleofetch +++ /dev/null @@ -1,5 +0,0 @@ ---structure Title:Separator:OS:Host:Kernel:Uptime:Battery:Break:Packages:Shell:Display:Terminal:Break:CPU:GPU:Memory:Break:Colors ---host-format "{/2}{-}{/}{2}{?3} {3}{?}" ---battery-format "{/4}{-}{/}{4}%{?5} [{5}]{?}" ---display-key "Display" ---gpu-key "GPU" diff --git a/presets/software b/presets/software deleted file mode 100644 index dd78f7451..000000000 --- a/presets/software +++ /dev/null @@ -1 +0,0 @@ ---structure OS:Kernel:Shell:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont diff --git a/src/common/init.c b/src/common/init.c index 41a79b5ac..12724aa2d 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -94,7 +94,10 @@ void ffStart(void) ffHideCursor = instance.config.display.hideCursor && !instance.config.display.pipe && !instance.state.resultDoc; #ifdef _WIN32 - setvbuf(stdout, NULL, _IOFBF, instance.config.display.noBuffer ? 0 : 4096); + if (instance.config.display.noBuffer) + setvbuf(stdout, NULL, _IONBF, 0); + else + setvbuf(stdout, NULL, _IOFBF, 4096); SetConsoleCtrlHandler(consoleHandler, TRUE); HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); DWORD mode = 0; diff --git a/src/common/io/io.h b/src/common/io/io.h index c311feb76..257e9ce83 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -10,6 +10,7 @@ #else #include #include + #include typedef int FFNativeFD; // procfs's file can be changed between read calls such as /proc/meminfo and /proc/uptime. // one safe way to read correct data is reading the whole file in a single read syscall @@ -75,15 +76,45 @@ static inline bool ffReadFileBuffer(const char* fileName, FFstrbuf* buffer) //Bit flags, combine with | typedef enum FFPathType { - FF_PATHTYPE_REGULAR = 1, - FF_PATHTYPE_LINK = 2, - FF_PATHTYPE_DIRECTORY = 4 + FF_PATHTYPE_FILE = 1 << 0, + FF_PATHTYPE_DIRECTORY = 1 << 1, + FF_PATHTYPE_ANY = FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY, } FFPathType; -#define FF_PATHTYPE_FILE (FF_PATHTYPE_REGULAR | FF_PATHTYPE_LINK) -#define FF_PATHTYPE_ANY (FF_PATHTYPE_FILE | FF_PATHTYPE_DIRECTORY) +static inline bool ffPathExists(const char* path, FFPathType pathType) +{ + #ifdef _WIN32 + + DWORD attr = GetFileAttributesA(path); + + if(attr == INVALID_FILE_ATTRIBUTES) + return false; + + if(pathType & FF_PATHTYPE_FILE && !(attr & FILE_ATTRIBUTE_DIRECTORY)) + return true; + + if(pathType & FF_PATHTYPE_DIRECTORY && (attr & FILE_ATTRIBUTE_DIRECTORY)) + return true; + + #else + + struct stat fileStat; + if(stat(path, &fileStat) != 0) + return false; + + unsigned int mode = fileStat.st_mode & S_IFMT; + + if(pathType & FF_PATHTYPE_FILE && mode == S_IFREG) + return true; + + if(pathType & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR) + return true; + + #endif + + return false; +} -bool ffPathExists(const char* path, FFPathType pathType); bool ffPathExpandEnv(const char* in, FFstrbuf* out); #define FF_IO_TERM_RESP_WAIT_MS 100 // #554 diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index e4b9e62e1..546231198 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -3,10 +3,10 @@ #include "util/unused.h" #include -#include #include #include #include +#include #if __has_include() #include @@ -33,9 +33,14 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) int FF_AUTO_CLOSE_FD fd = open(fileName, openFlagsModes, openFlagsRights); if(fd == -1) { - createSubfolders(fileName); - fd = open(fileName, openFlagsModes, openFlagsRights); - if(fd == -1) + if (errno == ENOENT) + { + createSubfolders(fileName); + fd = open(fileName, openFlagsModes, openFlagsRights); + if(fd == -1) + return false; + } + else return false; } @@ -103,26 +108,6 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) return ffAppendFDBuffer(fd, buffer); } -bool ffPathExists(const char* path, FFPathType type) -{ - struct stat fileStat; - if(stat(path, &fileStat) != 0) - return false; - - unsigned int mode = fileStat.st_mode & S_IFMT; - - if(type & FF_PATHTYPE_REGULAR && mode == S_IFREG) - return true; - - if(type & FF_PATHTYPE_DIRECTORY && mode == S_IFDIR) - return true; - - if(type & FF_PATHTYPE_LINK && mode == S_IFLNK) - return true; - - return false; -} - bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* out) { bool result = false; diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index f4a3747aa..e53a1cee6 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -18,11 +18,16 @@ static void createSubfolders(const char* fileName) bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) { HANDLE FF_AUTO_CLOSE_FD handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if(handle == INVALID_HANDLE_VALUE) + if (handle == INVALID_HANDLE_VALUE) { - createSubfolders(fileName); - handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if(handle == INVALID_HANDLE_VALUE) + if (GetLastError() == ERROR_PATH_NOT_FOUND) + { + createSubfolders(fileName); + handle = CreateFileA(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) + return false; + } + else return false; } @@ -37,7 +42,7 @@ bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer) LARGE_INTEGER fileSize; if(!GetFileSizeEx(handle, &fileSize)) fileSize.QuadPart = 0; - + if (fileSize.QuadPart > 0) { // optimize for files has a fixed length, @@ -87,24 +92,6 @@ bool ffAppendFileBuffer(const char* fileName, FFstrbuf* buffer) return ffAppendFDBuffer(handle, buffer); } -bool ffPathExists(const char* path, FFPathType type) -{ - DWORD attr = GetFileAttributesA(path); - if(attr == INVALID_FILE_ATTRIBUTES) - return false; - - if(type & FF_PATHTYPE_REGULAR && !(attr & FILE_ATTRIBUTE_DIRECTORY)) - return true; - - if(type & FF_PATHTYPE_DIRECTORY && (attr & FILE_ATTRIBUTE_DIRECTORY)) - return true; - - if(type & FF_PATHTYPE_LINK && (attr & FILE_ATTRIBUTE_REPARSE_POINT)) - return true; - - return false; -} - bool ffPathExpandEnv(const char* in, FFstrbuf* out) { DWORD length = ExpandEnvironmentStringsA(in, NULL, 0); diff --git a/src/common/modules.c b/src/common/modules.c index a065bc625..580e946f6 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -96,6 +96,7 @@ static FFModuleBaseInfo* O[] = { static FFModuleBaseInfo* P[] = { (void*) &instance.config.modules.packages, + (void*) &instance.config.modules.physicalDisk, (void*) &instance.config.modules.player, (void*) &instance.config.modules.powerAdapter, (void*) &instance.config.modules.processes, diff --git a/src/data/help.json b/src/data/help.json index f72a94a2d..32f6ba73e 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -124,9 +124,14 @@ "desc": "Set if only DRM should be used to detect displays", "remark": "Use this option if you encountered problems with other detection method. Linux only", "arg": { - "type": "bool", + "type": "enum", "optional": true, - "default": false + "default": "false", + "enum": { + "true": "Try `libdrm` first, then `sysfs` if libdrm failed", + "sysfs-only": "Use `/sys/class/drm` only", + "false": "Try `wayland`, then `x11`, then `drm`" + } } } ], @@ -942,6 +947,13 @@ "type": "str" } }, + { + "long": "physicaldisk-name-prefix", + "desc": "Show disks with given name prefix only", + "arg": { + "type": "str" + } + }, { "long": "bluetooth-show-disconnected", "desc": "Set if disconnected bluetooth devices should be printed", diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 418ab2165..e75dbc1c8 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -7,10 +7,16 @@ static double detectCpuTemp(const FFstrbuf* cpuName) double result = 0; const char* error = NULL; - if(ffStrbufStartsWithS(cpuName, "Apple M1")) - error = ffDetectCoreTemps(FF_TEMP_CPU_M1X, &result); - else if(ffStrbufStartsWithS(cpuName, "Apple M2")) - error = ffDetectCoreTemps(FF_TEMP_CPU_M2X, &result); + if (ffStrbufStartsWithS(cpuName, "Apple M")) + { + switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10)) + { + case 1: error = ffDetectCoreTemps(FF_TEMP_CPU_M1X, &result); break; + case 2: error = ffDetectCoreTemps(FF_TEMP_CPU_M2X, &result); break; + case 3: error = ffDetectCoreTemps(FF_TEMP_CPU_M3X, &result); break; + default: error = "Unsupported Apple Silicon CPU"; + } + } else // PPC? error = ffDetectCoreTemps(FF_TEMP_CPU_X64, &result); diff --git a/src/detection/de/de_linux.c b/src/detection/de/de_linux.c index 1e800bc8f..90326c226 100644 --- a/src/detection/de/de_linux.c +++ b/src/detection/de/de_linux.c @@ -1,6 +1,7 @@ #include "de.h" #include "common/io/io.h" +#include "common/library.h" #include "common/parsing.h" #include "common/properties.h" #include "common/processing.h" @@ -87,26 +88,18 @@ static void getMate(FFstrbuf* result, FFDEOptions* options) } } +static const char* getXfce4ByLib(FFstrbuf* result) +{ + const char* xfce_version_string(void); // from `xfce4/libxfce4util/xfce-misutils.h + FF_LIBRARY_LOAD(xfce4util, NULL, "dlopen libxfce4util" FF_LIBRARY_EXTENSION "failed", "libxfce4util" FF_LIBRARY_EXTENSION, 7); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xfce4util, xfce_version_string); + ffStrbufSetS(result, ffxfce_version_string()); + return NULL; +} + static void getXFCE4(FFstrbuf* result, FFDEOptions* options) { - ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "

Version", result); - - #ifdef __FreeBSD__ - if(result->length == 0) - { - FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/"); - if (dirp) - { - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5])) - continue; - ffStrbufAppendS(result, &entry->d_name[5]); - } - } - } - #endif + getXfce4ByLib(result); if(result->length == 0 && options->slowVersionDetection) { @@ -117,8 +110,8 @@ static void getXFCE4(FFstrbuf* result, FFDEOptions* options) NULL }); - ffStrbufSubstrBeforeFirstC(result, '('); - ffStrbufSubstrAfterFirstC(result, ' '); + ffStrbufSubstrBeforeFirstC(result, ')'); + ffStrbufSubstrAfterLastC(result, ' '); ffStrbufTrim(result, ' '); } } diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 0cef2d64b..ae94117c2 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -106,14 +106,6 @@ static void detectName(FFDisk* disk) FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreate(); - //Detect USB devices. Code is put here to reuse deviceStat - //https://stackoverflow.com/a/73302717 - ffStrbufAppendS(&basePath, "/dev/disk/by-id/"); - detectNameFromPath(disk, &deviceStat, &basePath); - if (ffStrbufStartsWithS(&disk->name, "usb-")) - disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; - ffStrbufClear(&disk->name); - //Try label first ffStrbufSetS(&basePath, "/dev/disk/by-label/"); detectNameFromPath(disk, &deviceStat, &basePath); @@ -197,9 +189,6 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) static bool isRemovable(FFDisk* currentDisk) { - // https://stackoverflow.com/a/73302025 - // Note my USB mobile hard disk isn't detected as removable, but my USB flash disk does. - // USB devices should be handled in detectName FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreateS("/sys/block/"); FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath.chars); @@ -218,11 +207,10 @@ static bool isRemovable(FFDisk* currentDisk) if (!ffStrStartsWith(partitionName, entry->d_name)) continue; - // /sys/block/sdx/removable + // /sys/block/sdx/device/delete ffStrbufAppendS(&basePath, entry->d_name); - ffStrbufAppendS(&basePath, "/removable"); - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1"); + ffStrbufAppendS(&basePath, "/device/delete"); + return ffPathExists(basePath.chars, FF_PATHTYPE_FILE); } return false; @@ -230,14 +218,12 @@ static bool isRemovable(FFDisk* currentDisk) static void detectType(const FFlist* disks, FFDisk* currentDisk) { - if(currentDisk->type != FF_DISK_VOLUME_TYPE_NONE) return; - - if(isRemovable(currentDisk)) + if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) + currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; + else if(isRemovable(currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; - else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) - currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; else currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; } diff --git a/src/detection/diskio/diskio.c b/src/detection/diskio/diskio.c index cb452743e..efac624b9 100644 --- a/src/detection/diskio/diskio.c +++ b/src/detection/diskio/diskio.c @@ -47,8 +47,8 @@ const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) { FFDiskIOResult* icPrev = (FFDiskIOResult*)ffListGet(&ioCounters1, i); FFDiskIOResult* icCurr = (FFDiskIOResult*)ffListGet(result, i); - if (!ffStrbufEqual(&icPrev->name, &icCurr->name)) - return "Network interface name changed"; + if (!ffStrbufEqual(&icPrev->devPath, &icCurr->devPath)) + return "Physical disk device path changed"; static_assert(sizeof(FFDiskIOResult) - offsetof(FFDiskIOResult, bytesRead) == sizeof(uint64_t) * 4, "Unexpected struct FFDiskIOResult layout"); for (size_t off = offsetof(FFDiskIOResult, bytesRead); off < sizeof(FFDiskIOResult); off += sizeof(uint64_t)) diff --git a/src/detection/diskio/diskio.h b/src/detection/diskio/diskio.h index 0f8b39f56..0082b18b7 100644 --- a/src/detection/diskio/diskio.h +++ b/src/detection/diskio/diskio.h @@ -2,19 +2,9 @@ #include "fastfetch.h" -typedef enum FFDiskIOPhysicalType -{ - FF_DISKIO_PHYSICAL_TYPE_UNKNOWN, - FF_DISKIO_PHYSICAL_TYPE_HDD, - FF_DISKIO_PHYSICAL_TYPE_SSD, -} FFDiskIOPhysicalType; - typedef struct FFDiskIOResult { FFstrbuf name; - FFstrbuf interconnect; - FFDiskIOPhysicalType type; - uint64_t size; FFstrbuf devPath; uint64_t bytesRead; uint64_t readCount; diff --git a/src/detection/diskio/diskio_apple.c b/src/detection/diskio/diskio_apple.c index b733cbfc9..bc5d57f25 100644 --- a/src/detection/diskio/diskio_apple.c +++ b/src/detection/diskio/diskio_apple.c @@ -48,8 +48,6 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); ffStrbufInitS(&device->name, deviceName); ffStrbufInit(&device->devPath); - device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; - device->size = 0; ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey), (int64_t*) &device->bytesRead); ffCfDictGetInt64(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey), (int64_t*) &device->bytesWritten); @@ -62,34 +60,6 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) ffCfStrGetString(bsdName, &device->devPath); ffStrbufPrependS(&device->devPath, "/dev/"); } - - FF_CFTYPE_AUTO_RELEASE CFNumberRef mediaSize = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaSizeKey), kCFAllocatorDefault, kNilOptions); - if (mediaSize) - ffCfNumGetInt64(mediaSize, (int64_t*) &device->size); - else - device->size = 0; - - ffStrbufInit(&device->interconnect); - FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPhysical = 0; - if (IORegistryEntryGetParentEntry(entryDriver, kIOServicePlane, &entryPhysical) == KERN_SUCCESS) - { - FF_CFTYPE_AUTO_RELEASE CFDictionaryRef protocolCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kNilOptions); - if (protocolCharacteristics) - ffCfDictGetString(protocolCharacteristics, CFSTR("Physical Interconnect"), &device->interconnect); - - FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions); - if (deviceCharacteristics) - { - CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); - if (mediumType) - { - if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0) - device->type = FF_DISKIO_PHYSICAL_TYPE_SSD; - else if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0) - device->type = FF_DISKIO_PHYSICAL_TYPE_HDD; - } - } - } } return NULL; diff --git a/src/detection/diskio/diskio_bsd.c b/src/detection/diskio/diskio_bsd.c index a4a911b93..08ecb47cf 100644 --- a/src/detection/diskio/diskio_bsd.c +++ b/src/detection/diskio/diskio_bsd.c @@ -32,35 +32,25 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) if (provider->lg_geom->lg_rank != 1) continue; - FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(provider->lg_name); - FFDiskIOPhysicalType type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); for (struct gconfig* ptr = provider->lg_config.lh_first; ptr; ptr = ptr->lg_config.le_next) { if (ffStrEquals(ptr->lg_name, "descr")) ffStrbufSetS(&name, ptr->lg_val); - else if (ffStrEquals(ptr->lg_name, "rotationrate") && !ffStrEquals(ptr->lg_val, "unknown")) - type = ffStrEquals(ptr->lg_val, "0") ? FF_DISKIO_PHYSICAL_TYPE_SSD : FF_DISKIO_PHYSICAL_TYPE_HDD; } + if (name.length == 0) + ffStrbufSetS(&name, provider->lg_name); if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix)) continue; FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name); - ffStrbufInit(&device->interconnect); - switch (snapIter->device_type & DEVSTAT_TYPE_IF_MASK) - { - case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->interconnect, "SCSI"); break; - case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->interconnect, "IDE"); break; - case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break; - } device->bytesRead = snapIter->bytes[DEVSTAT_READ]; device->readCount = snapIter->operations[DEVSTAT_READ]; device->bytesWritten = snapIter->bytes[DEVSTAT_WRITE]; device->writeCount = snapIter->operations[DEVSTAT_WRITE]; - device->size = (uint64_t) provider->lg_mediasize; ffStrbufInitMove(&device->name, &name); - device->type = type; } geom_stats_snapshot_free(snap); diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c index 3737789be..e865581c2 100644 --- a/src/detection/diskio/diskio_linux.c +++ b/src/detection/diskio/diskio_linux.c @@ -1,5 +1,6 @@ #include "diskio.h" #include "common/io/io.h" +#include "common/properties.h" #include "util/stringUtils.h" #include @@ -7,107 +8,75 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) { - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateS("/dev/disk/by-id/"); - uint32_t baseDirLength = baseDir.length; + FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); + if(sysBlockDirp == NULL) + return "opendir(\"/sys/block/\") == NULL"; - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); - if(dirp == NULL) - return "opendir(batteryDir) == NULL"; - - struct dirent* entry; - while ((entry = readdir(dirp)) != NULL) + struct dirent* sysBlockEntry; + while ((sysBlockEntry = readdir(sysBlockDirp)) != NULL) { - if (entry->d_name[0] == '.') + const char* const devName = sysBlockEntry->d_name; + + if (devName[0] == '.') continue; - char* part = strstr(entry->d_name, "-part"); - if (part && isdigit(part[strlen("-part")])) - continue; - - if (ffStrStartsWith(entry->d_name, "nvme-eui.")) // NVMe drive identifier - continue; - - // Other exceptions? - - ffStrbufAppendS(&baseDir, entry->d_name); - char pathDev[PATH_MAX]; - ssize_t pathLen = readlink(baseDir.chars, pathDev, PATH_MAX); - ffStrbufSubstrBefore(&baseDir, baseDirLength); - - if (pathLen < 0) continue; - pathDev[pathLen] = '\0'; // ../../nvme0n1 - - char pathDev1[PATH_MAX]; - const char* devName = basename(pathDev); - snprintf(pathDev1, PATH_MAX, "/dev/%s", devName); - - // Avoid duplicated disks - bool flag = false; - FF_LIST_FOR_EACH(FFDiskIOResult, disk, *result) - { - if (ffStrbufEqualS(&disk->devPath, pathDev1)) - { - flag = true; - break; - } - } - if (flag) continue; - char pathSysBlock[PATH_MAX]; - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/stat", devName); + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s", devName); - FF_AUTO_CLOSE_FILE FILE* sysBlockStat = fopen(pathSysBlock, "r"); - if (!sysBlockStat) continue; + char pathSysDeviceReal[PATH_MAX]; + ssize_t pathLength = readlink(pathSysBlock, pathSysDeviceReal, sizeof(pathSysDeviceReal) - 1); + if (pathLength < 0) + continue; + pathSysDeviceReal[pathLength] = '\0'; - // I/Os merges sectors ticks ... - uint64_t nRead, sectorRead, nWritten, sectorWritten; - if (fscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, §orRead, &nWritten, §orWritten) == 0) + if (strstr(pathSysDeviceReal, "/virtual/")) // virtual device + continue; + + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device", devName); + if (!ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY)) continue; FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); - char* slash = strchr(entry->d_name, '-'); - if (slash) - { - char* slash2 = strchr(slash + 1, '-'); - if (slash2) - ffStrbufInitNS(&device->name, (uint32_t) (slash2 - slash - 1), slash + 1); - else - ffStrbufInitS(&device->name, slash + 1); - ffStrbufInitNS(&device->interconnect, (uint32_t) (slash - entry->d_name), entry->d_name); - } - else - { - ffStrbufInitS(&device->name, entry->d_name); - ffStrbufInit(&device->interconnect); - } - ffStrbufReplaceAllC(&device->name, '_', ' '); + ffStrbufInit(&device->name); - if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) { - ffStrbufDestroy(&device->name); - ffStrbufDestroy(&device->interconnect); - result->length--; - continue; + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName); + ffAppendFileBuffer(pathSysBlock, &device->name); + if (device->name.length > 0) + ffStrbufAppendC(&device->name, ' '); + + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName); + ffAppendFileBuffer(pathSysBlock, &device->name); + ffStrbufTrim(&device->name, ' '); + + if (device->name.length == 0) + ffStrbufSetS(&device->name, devName); + + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + result->length--; + continue; + } } - ffStrbufInitS(&device->devPath, pathDev1); + // I/Os merges sectors ticks ... + uint64_t nRead, sectorRead, nWritten, sectorWritten; + { + char sysBlockStat[PROC_FILE_BUFFSIZ]; + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/stat", devName); + ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(sysBlockStat) - 1, sysBlockStat); + if (fileSize <= 0) continue; + sysBlockStat[fileSize] = '\0'; + if (sscanf(sysBlockStat, "%lu%*u%lu%*u%lu%*u%lu%*u", &nRead, §orRead, &nWritten, §orWritten) <= 0) + continue; + } + + ffStrbufInitF(&device->devPath, "/dev/%s", devName); device->bytesRead = sectorRead * 512; device->bytesWritten = sectorWritten * 512; device->readCount = nRead; device->writeCount = nWritten; - - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/queue/rotational", devName); - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - if (ffReadFileBuffer(pathSysBlock, &buffer)) - device->type = ffStrbufEqualS(&buffer, "1") ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD; - else - device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; - - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/size", devName); - if (ffReadFileBuffer(pathSysBlock, &buffer)) - device->size = ffStrbufToUInt(&buffer, 0); - else - device->size = 0; } return NULL; diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index 0fe06faf7..de7ef5c1c 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -1,101 +1,82 @@ #include "diskio.h" #include "common/io/io.h" -#include "util/windows/registry.h" #include "util/windows/unicode.h" +#include #include const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) { - FF_HKEY_AUTO_DESTROY hKey = NULL; - if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", &hKey, NULL)) - return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"SYSTEM\\CurrentControlSet\\Services\\disk\\Enum\") failed"; - - uint32_t nDevices; - if (!ffRegReadUint(hKey, L"Count", &nDevices, NULL)) - return "ffRegReadUint(hKey, L\"Count\", &nDevices) failed"; - wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive"; wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive"); - for (uint32_t idev = 0; idev <= nDevices; ++idev) { + for (uint32_t idev = 0; ; ++idev) + { _ultow(idev, pNum, 10); FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hDevice == INVALID_HANDLE_VALUE) + break; + + DWORD retSize; + char sddBuffer[4096]; + if(!DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &sddBuffer, + sizeof(sddBuffer), + &retSize, + NULL + ) || retSize == 0) continue; - DISK_PERFORMANCE diskPerformance; - DWORD ioctrlSize = sizeof(diskPerformance); - DWORD dwSize; - if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance, ioctrlSize, &dwSize, NULL)) + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*) sddBuffer; + + ffStrbufInit(&device->name); + if (sdd->VendorIdOffset != 0) { - FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); - ffStrbufInit(&device->name); - ffStrbufInit(&device->interconnect); - if (ffRegReadStrbuf(hKey, pNum, &device->name, NULL)) - { - // SCSI\Disk&Ven_NVMe&Prod_WDC_PC_SN810_SDC\5&19cebb7&0&000000 - uint32_t index = ffStrbufFirstIndexC(&device->name, '\\'); - if (index != device->name.length) - { - ffStrbufAppendNS(&device->interconnect, index, device->name.chars); // SCSI - ffStrbufSubstrAfter(&device->name, index); - } - ffStrbufSubstrBeforeLastC(&device->name, '\\'); - ffStrbufSubstrAfterFirstS(&device->name, "&Ven_"); - ffStrbufRemoveS(&device->name, "&Prod"); - ffStrbufReplaceAllC(&device->name, '_', ' '); - ffStrbufTrim(&device->name, ' '); - } - else - ffStrbufSetWS(&device->name, szDevice); + ffStrbufSetS(&device->name, (const char*) sddBuffer + sdd->VendorIdOffset); + ffStrbufTrim(&device->name, ' '); + } + if (sdd->ProductIdOffset != 0) + { + if (device->name.length) + ffStrbufAppendC(&device->name, ' '); - if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) - { - ffStrbufDestroy(&device->name); - ffStrbufDestroy(&device->interconnect); - result->length--; - continue; - } + ffStrbufAppendS(&device->name, (const char*) sddBuffer + sdd->ProductIdOffset); + ffStrbufTrimRight(&device->name, ' '); + } - ffStrbufInitWS(&device->devPath, szDevice); - device->bytesRead = (uint64_t) diskPerformance.BytesRead.QuadPart; - device->readCount = (uint64_t) diskPerformance.ReadCount; - device->bytesWritten = (uint64_t) diskPerformance.BytesWritten.QuadPart; - device->writeCount = (uint64_t) diskPerformance.WriteCount; + if (!device->name.length) + ffStrbufAppendF(&device->name, "PhysicalDrive%u", (unsigned) idev); - DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; - DWORD retSize = 0; - if(DeviceIoControl( - hDevice, - IOCTL_STORAGE_QUERY_PROPERTY, - &(STORAGE_PROPERTY_QUERY) { - .PropertyId = StorageDeviceSeekPenaltyProperty, - .QueryType = PropertyStandardQuery, - }, - sizeof(STORAGE_PROPERTY_QUERY), - &dspd, - sizeof(dspd), - &retSize, - NULL - ) && retSize == sizeof(dspd)) - device->type = dspd.IncursSeekPenalty ? FF_DISKIO_PHYSICAL_TYPE_HDD : FF_DISKIO_PHYSICAL_TYPE_SSD; - else - device->type = FF_DISKIO_PHYSICAL_TYPE_UNKNOWN; + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + result->length--; + continue; + } - DISK_GEOMETRY_EX dge = {}; - if(DeviceIoControl( - hDevice, - IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, - NULL, - 0, - &dge, - sizeof(dge), - &retSize, - NULL)) - device->size = (uint64_t) dge.DiskSize.QuadPart; - else - device->size = 0; + ffStrbufInitWS(&device->devPath, szDevice); + + DISK_PERFORMANCE dp = {}; + if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &dp, sizeof(dp), &retSize, NULL)) + { + device->bytesRead = (uint64_t) dp.BytesRead.QuadPart; + device->readCount = (uint64_t) dp.ReadCount; + device->bytesWritten = (uint64_t) dp.BytesWritten.QuadPart; + device->writeCount = (uint64_t) dp.WriteCount; + } + else + { + ffStrbufDestroy(&device->name); + result->length--; + continue; } } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 7a5ebb8f8..b5655a84f 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -11,6 +11,7 @@ #define FF_DE_PRETTY_LXDE "LXDE" #define FF_DE_PRETTY_LXQT "LXQT" #define FF_DE_PRETTY_BUDGIE "Budgie" +#define FF_DE_PRETTY_CDE "CDE" #define FF_DE_PRETTY_UNITY "Unity" #define FF_WM_PRETTY_KWIN "KWin" @@ -32,6 +33,7 @@ #define FF_WM_PRETTY_HERBSTLUFTWM "herbstluftwm" #define FF_WM_PRETTY_ICEWM "IceWM" #define FF_WM_PRETTY_SPECTRWM "spectrwm" +#define FF_WM_PRETTY_DTWM "dtwm" #define FF_WM_PROTOCOL_TTY "TTY" diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index d6eb3da99..e75e311b0 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -10,7 +10,7 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) ffStrbufInit(&ds->dePrettyName); ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4); - if (!instance.config.general.dsForceDrm) + if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) { //We try wayland as our preferred display server, as it supports the most features. //This method can't detect the name of our WM / DE diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index baf4e4bdf..cf6bf3cde 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -27,10 +27,10 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) ffStrbufAppendS(&drmDir, entry->d_name); uint32_t drmDirWithDnameLength = drmDir.length; - ffStrbufAppendS(&drmDir, "/enabled"); - char enabled = 'd'; // disabled - ffReadFileData(drmDir.chars, sizeof(enabled), &enabled); - if (enabled != 'e') // enabled + ffStrbufAppendS(&drmDir, "/status"); + char status = 'd'; // disconnected + ffReadFileData(drmDir.chars, sizeof(status), &status); + if (status != 'c') // connected { ffStrbufSubstrBefore(&drmDir, drmDirLength); continue; @@ -152,6 +152,49 @@ static inline const char* drmType2Name(uint32_t connector_type) } } +static const char* drmGetNameByConnId(uint32_t connId, FFstrbuf* name) +{ + const char* drmDirPath = "/sys/class/drm/"; + + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); + if(dirp == NULL) + return "opendir(drmDirPath) failed"; + + FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64); + ffStrbufAppendS(&drmDir, drmDirPath); + + uint32_t drmDirLength = drmDir.length; + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) + continue; + + ffStrbufAppendS(&drmDir, entry->d_name); + uint32_t drmDirWithDnameLength = drmDir.length; + + ffStrbufAppendS(&drmDir, "/connector_id"); + ffReadFileBuffer(drmDir.chars, name); + if (ffStrbufToUInt(name, 0) != connId) + { + ffStrbufSubstrBefore(&drmDir, drmDirLength); + continue; + } + + ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); + ffStrbufClear(name); + ffStrbufAppendS(&drmDir, "/edid"); + uint8_t edidData[128]; + if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData)) + ffEdidGetName(edidData, name); + return NULL; + } + + ffStrbufClear(name); + return "Failed to match connector ID"; +} + static const char* drmConnectLibdrm(FFDisplayServerResult* result) { FF_LIBRARY_LOAD(libdrm, &instance.config.library.libdrm, "dlopen(libdrm)" FF_LIBRARY_EXTENSION " failed", "libdrm" FF_LIBRARY_EXTENSION, 2) @@ -162,6 +205,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetEncoder) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetProperty) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetPropertyBlob) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeResources) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeCrtc) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeEncoder) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeFreeConnector) @@ -196,18 +240,56 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) if (!conn) continue; - if (conn->connection != DRM_MODE_CONNECTED) - goto next_conn; - - drmModeEncoder* encoder = ffdrmModeGetEncoder(fd, conn->encoder_id); - if (!encoder) - goto next_conn; - - drmModeCrtc* crtc = ffdrmModeGetCrtc(fd, encoder->crtc_id); - if (!crtc) - goto next_encoder; - + if (conn->connection == DRM_MODE_CONNECTED) { + drmModeEncoder* encoder = ffdrmModeGetEncoder(fd, conn->encoder_id); + uint32_t width = 0, height = 0, refreshRate = 0; + + if (encoder) + { + drmModeCrtc* crtc = ffdrmModeGetCrtc(fd, encoder->crtc_id); + if (crtc) + { + width = crtc->mode.vdisplay; + height = crtc->mode.hdisplay; + refreshRate = crtc->mode.vrefresh; + if (refreshRate == 0) + { + // There are weird cases that we can't get the refresh rate from the CRTC but from the modes + for (int iMode = 0; iMode < conn->count_modes; ++iMode) + { + drmModeModeInfo* mode = &conn->modes[iMode]; + if (mode->clock == crtc->mode.clock && mode->htotal == crtc->mode.htotal) + { + refreshRate = mode->vrefresh; + break; + } + } + } + ffdrmModeFreeCrtc(crtc); + } + + ffdrmModeFreeEncoder(encoder); + } + + if (width == 0 || height == 0) + { + // NVIDIA DRM driver seems incomplete and conn->encoder_id == 0 + // Assume preferred resolution is used as what we do in drmParseSys + for (int iMode = 0; iMode < conn->count_modes; ++iMode) + { + drmModeModeInfo* mode = &conn->modes[iMode]; + + if (mode->type & DRM_MODE_TYPE_PREFERRED) + { + width = mode->hdisplay; + height = mode->vdisplay; + refreshRate = mode->vrefresh; + break; + } + } + } + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); for (int iProp = 0; iProp < conn->count_props; ++iProp) @@ -219,60 +301,58 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) uint32_t type = prop->flags & (DRM_MODE_PROP_LEGACY_TYPE | DRM_MODE_PROP_EXTENDED_TYPE); if (type == DRM_MODE_PROP_BLOB && ffStrEquals(prop->name, "EDID")) { - // Stangely, prop->count_blobs is 0 and prop->blob_ids is NULL - drmModePropertyBlobPtr blob = ffdrmModeGetPropertyBlob(fd, (uint32_t) conn->prop_values[iProp]); - if (blob->length >= 128) - ffEdidGetName(blob->data, &name); - ffdrmModeFreePropertyBlob(blob); + drmModePropertyBlobPtr blob = NULL; + + if (prop->count_blobs > 0 && prop->blob_ids != NULL) + blob = ffdrmModeGetPropertyBlob(fd, prop->blob_ids[0]); + else + blob = ffdrmModeGetPropertyBlob(fd, (uint32_t) conn->prop_values[iProp]); + + if (blob) + { + if (blob->length >= 128) + ffEdidGetName(blob->data, &name); + ffdrmModeFreePropertyBlob(blob); + } break; } ffdrmModeFreeProperty(prop); } + if (name.length == 0) + { + drmGetNameByConnId(conn->connector_id, &name); + } + if (name.length == 0) { const char* connectorTypeName = drmType2Name(conn->connector_type); if (connectorTypeName == NULL) connectorTypeName = "Unknown"; - ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn); + ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn + 1); } - uint32_t refreshRate = crtc->mode.vrefresh; - if (refreshRate == 0) - { - // There are weird cases that we can't get the refresh rate from the CRTC but from the modes - for (int iMode = 0; iMode < conn->count_modes; ++iMode) - { - drmModeModeInfo* mode = &conn->modes[iMode]; - if (mode->clock == crtc->mode.clock && mode->htotal == crtc->mode.htotal) - { - refreshRate = mode->vrefresh; - break; - } - } - } - - ffdsAppendDisplay( - result, - crtc->width, crtc->height, + ffdsAppendDisplay(result, + width, + height, refreshRate, - 0, 0, + 0, + 0, 0, &name, - FF_DISPLAY_TYPE_UNKNOWN, + conn->connector_type == DRM_MODE_CONNECTOR_eDP + ? FF_DISPLAY_TYPE_BUILTIN + : conn->connector_type == DRM_MODE_CONNECTOR_HDMIA || conn->connector_type == DRM_MODE_CONNECTOR_HDMIB + ? FF_DISPLAY_TYPE_EXTERNAL : FF_DISPLAY_TYPE_UNKNOWN, false, - 0 + conn->connector_id ); } - ffdrmModeFreeCrtc(crtc); - - next_encoder: - ffdrmModeFreeEncoder(encoder); - - next_conn: ffdrmModeFreeConnector(conn); } + + ffdrmModeFreeResources(res); } ffdrmFreeDevices(devices, nDevices); @@ -285,8 +365,11 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) void ffdsConnectDrm(FFDisplayServerResult* result) { #ifdef FF_HAVE_DRM - if (drmConnectLibdrm(result) == NULL) - return; + if (instance.config.general.dsForceDrm != FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY) + { + if (drmConnectLibdrm(result) == NULL) + return; + } #endif drmParseSysfs(result); diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 740050b46..971b14d29 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -1,14 +1,20 @@ #include "displayserver_linux.h" -#include "common/io/io.h" #include "common/properties.h" -#include "common/processing.h" #include "util/stringUtils.h" +#include "util/mallocHelper.h" #include #include #include #include -#include + +#ifdef __FreeBSD__ + #include + #include + #include +#else + #include "common/io/io.h" +#endif static const char* parseEnv(void) { @@ -46,10 +52,12 @@ static const char* parseEnv(void) if(getenv("TDE_FULL_SESSION") != NULL) return "Trinity"; + #ifdef __linux__ if( getenv("WAYLAND_DISPLAY") != NULL && ffPathExists("/mnt/wslg/", FF_PATHTYPE_DIRECTORY) ) return "WSLg"; + #endif return NULL; } @@ -60,52 +68,54 @@ static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name) return; if( - strcasecmp(name, "kwin_wayland") == 0 || - strcasecmp(name, "kwin_wayland_wrapper") == 0 || - strcasecmp(name, "kwin_x11") == 0 || - strcasecmp(name, "kwin_x11_wrapper") == 0 || - strcasecmp(name, "kwin") == 0 + ffStrEqualsIgnCase(name, "kwin_wayland") || + ffStrEqualsIgnCase(name, "kwin_wayland_wrapper") || + ffStrEqualsIgnCase(name, "kwin_x11") || + ffStrEqualsIgnCase(name, "kwin_x11_wrapper") || + ffStrEqualsIgnCase(name, "kwin") ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN); else if( - strcasecmp(name, "gnome-shell") == 0 || - strcasecmp(name, "gnome shell") == 0 || - strcasecmp(name, "gnome-session-binary") == 0 || - strcasecmp(name, "Mutter") == 0 + ffStrEqualsIgnCase(name, "gnome-shell") || + ffStrEqualsIgnCase(name, "gnome shell") || + ffStrEqualsIgnCase(name, "gnome-session-binary") || + ffStrEqualsIgnCase(name, "Mutter") ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER); else if( - strcasecmp(name, "cinnamon-session") == 0 || - strcasecmp(name, "Muffin") == 0 || - strcasecmp(name, "Mutter (Muffin)") == 0 + ffStrEqualsIgnCase(name, "cinnamon-session") || + ffStrEqualsIgnCase(name, "Muffin") || + ffStrEqualsIgnCase(name, "Mutter (Muffin)") ) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUFFIN); - else if(strcasecmp(name, "sway") == 0) + else if(ffStrEqualsIgnCase(name, "sway")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_SWAY); - else if(strcasecmp(name, "weston") == 0) + else if(ffStrEqualsIgnCase(name, "weston")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WESTON); - else if(strcasecmp(name, "wayfire") == 0) + else if(ffStrEqualsIgnCase(name, "wayfire")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WAYFIRE); - else if(strcasecmp(name, "openbox") == 0) + else if(ffStrEqualsIgnCase(name, "openbox")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_OPENBOX); - else if(strcasecmp(name, "xfwm4") == 0) + else if(ffStrEqualsIgnCase(name, "xfwm4")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XFWM4); - else if(strcasecmp(name, "Marco") == 0 || - strcasecmp(name, "Metacity (Marco)") == 0) + else if(ffStrEqualsIgnCase(name, "Marco") || + ffStrEqualsIgnCase(name, "Metacity (Marco)")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MARCO); - else if(strcasecmp(name, "xmonad") == 0) + else if(ffStrEqualsIgnCase(name, "xmonad")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XMONAD); - else if(strcasecmp(name, "WSLg") == 0) + else if(ffStrEqualsIgnCase(name, "WSLg")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WSLG); - else if(strcasecmp(name, "dwm") == 0) + else if(ffStrEqualsIgnCase(name, "dwm")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_DWM); - else if(strcasecmp(name, "bspwm") == 0) + else if(ffStrEqualsIgnCase(name, "bspwm")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_BSPWM); - else if(strcasecmp(name, "tinywm") == 0) + else if(ffStrEqualsIgnCase(name, "tinywm")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_TINYWM); - else if(strcasecmp(name, "qtile") == 0) + else if(ffStrEqualsIgnCase(name, "qtile")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_QTILE); - else if(strcasecmp(name, "herbstluftwm") == 0) + else if(ffStrEqualsIgnCase(name, "herbstluftwm")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_HERBSTLUFTWM); - else if(strcasecmp(name, "icewm") == 0) + else if(ffStrEqualsIgnCase(name, "icewm")) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_ICEWM); + else if(ffStrEqualsIgnCase(name, "dtwm")) + ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_DTWM); } static void applyNameIfWM(FFDisplayServerResult* result, const char* processName) @@ -136,10 +146,10 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name) return; else if( - strcasecmp(name, "KDE") == 0 || - strcasecmp(name, "plasma") == 0 || - strcasecmp(name, "plasmashell") == 0 || - strcasecmp(name, "plasmawayland") == 0 + ffStrEqualsIgnCase(name, "KDE") || + ffStrEqualsIgnCase(name, "plasma") || + ffStrEqualsIgnCase(name, "plasmashell") || + ffStrEqualsIgnCase(name, "plasmawayland") ) { ffStrbufSetStatic(&result->deProcessName, "plasmashell"); ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_PLASMA); @@ -147,10 +157,10 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name) } else if( - strcasecmp(name, "Gnome") == 0 || - strcasecmp(name, "ubuntu:GNOME") == 0 || - strcasecmp(name, "ubuntu") == 0 || - strcasecmp(name, "gnome-shell") == 0 + ffStrEqualsIgnCase(name, "Gnome") || + ffStrEqualsIgnCase(name, "ubuntu:GNOME") || + ffStrEqualsIgnCase(name, "ubuntu") || + ffStrEqualsIgnCase(name, "gnome-shell") ) { ffStrbufSetStatic(&result->deProcessName, "gnome-shell"); const char* sessionMode = getenv("GNOME_SHELL_SESSION_MODE"); @@ -161,37 +171,37 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name) } else if( - strcasecmp(name, "X-Cinnamon") == 0 || - strcasecmp(name, "Cinnamon") == 0 + ffStrEqualsIgnCase(name, "X-Cinnamon") || + ffStrEqualsIgnCase(name, "Cinnamon") ) { ffStrbufSetS(&result->deProcessName, "cinnamon"); ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON); } else if( - strcasecmp(name, "XFCE") == 0 || - strcasecmp(name, "X-XFCE") == 0 || - strcasecmp(name, "XFCE4") == 0 || - strcasecmp(name, "X-XFCE4") == 0 || - strcasecmp(name, "xfce4-session") == 0 + ffStrEqualsIgnCase(name, "XFCE") || + ffStrEqualsIgnCase(name, "X-XFCE") || + ffStrEqualsIgnCase(name, "XFCE4") || + ffStrEqualsIgnCase(name, "X-XFCE4") || + ffStrEqualsIgnCase(name, "xfce4-session") ) { ffStrbufSetS(&result->deProcessName, "xfce4-session"); ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4); } else if( - strcasecmp(name, "MATE") == 0 || - strcasecmp(name, "X-MATE") == 0 || - strcasecmp(name, "mate-session") == 0 + ffStrEqualsIgnCase(name, "MATE") || + ffStrEqualsIgnCase(name, "X-MATE") || + ffStrEqualsIgnCase(name, "mate-session") ) { ffStrbufSetS(&result->deProcessName, "mate-session"); ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE); } else if( - strcasecmp(name, "LXQt") == 0 || - strcasecmp(name, "X-LXQT") == 0 || - strcasecmp(name, "lxqt-session") == 0 + ffStrEqualsIgnCase(name, "LXQt") || + ffStrEqualsIgnCase(name, "X-LXQT") || + ffStrEqualsIgnCase(name, "lxqt-session") ) { ffStrbufSetS(&result->deProcessName, "lxqt-session"); ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT); @@ -201,14 +211,21 @@ static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name) } else if( - strcasecmp(name, "Budgie") == 0 || - strcasecmp(name, "X-Budgie") == 0 || - strcasecmp(name, "budgie-desktop") == 0 || - strcasecmp(name, "Budgie:GNOME") == 0 + ffStrEqualsIgnCase(name, "Budgie") || + ffStrEqualsIgnCase(name, "X-Budgie") || + ffStrEqualsIgnCase(name, "budgie-desktop") || + ffStrEqualsIgnCase(name, "Budgie:GNOME") ) { ffStrbufSetS(&result->deProcessName, "budgie-desktop"); ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE); } + + else if( + ffStrEqualsIgnCase(name, "dtsession") + ) { + ffStrbufSetS(&result->deProcessName, "dtsession"); + ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CDE); + } } static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) @@ -219,9 +236,9 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) const char* env = getenv("XDG_SESSION_TYPE"); if(ffStrSet(env)) { - if(strcasecmp(env, "x11") == 0) + if(ffStrEqualsIgnCase(env, "x11")) ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11); - else if(strcasecmp(env, "tty") == 0) + else if(ffStrEqualsIgnCase(env, "tty")) ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); else ffStrbufSetS(&result->wmProtocolName, env); @@ -237,30 +254,56 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) } env = getenv("TERM"); - if(ffStrSet(env) && strcasecmp(env, "linux") == 0) + if(ffStrSet(env) && ffStrEqualsIgnCase(env, "linux")) { ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY); return; } } -static void getFromProcDir(FFDisplayServerResult* result) +static const char* getFromProcesses(FFDisplayServerResult* result) { - DIR* proc = opendir("/proc"); - if(proc == NULL) - return; + uint32_t userId = getuid(); + +#ifdef __FreeBSD__ + int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_UID, (int) userId}; + size_t length = 0; + + if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0) + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, NULL) failed"; + + FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length); + if(sysctl(request, sizeof(request) / sizeof(*request), procs, &length, NULL, 0) != 0) + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, procs) failed"; + + length /= sizeof(*procs); + + for (struct kinfo_proc* proc = procs; proc < procs + length; ++proc) + { + if(result->dePrettyName.length == 0) + applyPrettyNameIfDE(result, proc->ki_comm); + + if(result->wmPrettyName.length == 0) + applyNameIfWM(result, proc->ki_comm); + + if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) + break; + } +#else + FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); + if(procdir == NULL) + return "opendir(\"/proc\") failed"; FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64); ffStrbufAppendS(&procPath, "/proc/"); uint32_t procPathLength = procPath.length; - FF_STRBUF_AUTO_DESTROY userID = ffStrbufCreateF("%i", getuid()); FF_STRBUF_AUTO_DESTROY loginuid = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY processName = ffStrbufCreateA(256); //Some processes have large command lines (looking at you chrome) struct dirent* dirent; - while((dirent = readdir(proc)) != NULL) + while((dirent = readdir(procdir)) != NULL) { //Match only folders starting with a number (the pid folders) if(dirent->d_type != DT_DIR || !isdigit(dirent->d_name[0])) @@ -272,7 +315,7 @@ static void getFromProcDir(FFDisplayServerResult* result) //Don't check for processes not owend by the current user. ffStrbufAppendS(&procPath, "/loginuid"); ffReadFileBuffer(procPath.chars, &loginuid); - if(ffStrbufComp(&userID, &loginuid) != 0) + if(ffStrbufToUInt(&loginuid, (uint64_t) -1) != userId) { ffStrbufSubstrBefore(&procPath, procPathLength); continue; @@ -297,8 +340,9 @@ static void getFromProcDir(FFDisplayServerResult* result) if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) break; } +#endif - closedir(proc); + return NULL; } void ffdsDetectWMDE(FFDisplayServerResult* result) @@ -338,7 +382,7 @@ void ffdsDetectWMDE(FFDisplayServerResult* result) return; //Get missing WM / DE from processes. - getFromProcDir(result); + getFromProcesses(result); //Return if both wm and de are set, or if env doesn't contain anything if( diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 616a62cc9..bb734596d 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -9,20 +9,26 @@ static double detectGpuTemp(const FFstrbuf* gpuName) { double result = 0; - const char* error; + const char* error = NULL; - if(ffStrbufStartsWithS(gpuName, "Apple M1")) - error = ffDetectCoreTemps(FF_TEMP_GPU_M1X, &result); - else if(ffStrbufStartsWithS(gpuName, "Apple M2")) - error = ffDetectCoreTemps(FF_TEMP_GPU_M2X, &result); - else if(ffStrbufStartsWithS(gpuName, "Intel")) + if (ffStrbufStartsWithS(gpuName, "Apple M")) + { + switch (strtol(gpuName->chars + strlen("Apple M"), NULL, 10)) + { + case 1: error = ffDetectCoreTemps(FF_TEMP_GPU_M1X, &result); break; + case 2: error = ffDetectCoreTemps(FF_TEMP_GPU_M2X, &result); break; + case 3: error = ffDetectCoreTemps(FF_TEMP_GPU_M3X, &result); break; + default: error = "Unsupported Apple Silicon GPU"; + } + } + else if (ffStrbufStartsWithS(gpuName, "Intel")) error = ffDetectCoreTemps(FF_TEMP_GPU_INTEL, &result); - else if(ffStrbufStartsWithS(gpuName, "Radeon") || ffStrbufStartsWithS(gpuName, "AMD")) + else if (ffStrbufStartsWithS(gpuName, "Radeon") || ffStrbufStartsWithS(gpuName, "AMD")) error = ffDetectCoreTemps(FF_TEMP_GPU_AMD, &result); else error = ffDetectCoreTemps(FF_TEMP_GPU_UNKNOWN, &result); - if(error) + if (error) return FF_GPU_TEMP_UNSET; return result; diff --git a/src/detection/memory/memory_apple.c b/src/detection/memory/memory_apple.c index b3a50a1eb..19e67f1a4 100644 --- a/src/detection/memory/memory_apple.c +++ b/src/detection/memory/memory_apple.c @@ -16,7 +16,16 @@ const char* ffDetectMemory(FFMemoryResult* ram) if(host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) (&vmstat), &count) != KERN_SUCCESS) return "Failed to read host_statistics64"; - ram->bytesUsed = ((uint64_t) vmstat.active_count + vmstat.wire_count) * instance.state.platform.pageSize; + // https://github.com/exelban/stats/blob/master/Modules/RAM/readers.swift#L56 + ram->bytesUsed = ((uint64_t) + + vmstat.active_count + + vmstat.inactive_count + + vmstat.speculative_count + + vmstat.wire_count + + vmstat.compressor_page_count + - vmstat.purgeable_count + - vmstat.external_page_count + ) * instance.state.platform.pageSize; return NULL; } diff --git a/src/detection/packages/packages_bsd.c b/src/detection/packages/packages_bsd.c new file mode 100644 index 000000000..cb9091457 --- /dev/null +++ b/src/detection/packages/packages_bsd.c @@ -0,0 +1,8 @@ +#include "packages.h" + +#include "common/settings.h" + +void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options) +{ + result->pkg = (uint32_t) ffSettingsGetSQLite3Int(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg/local.sqlite", "SELECT count(*) FROM packages"); +} diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index ef5d1162d..0b608497c 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -11,7 +11,7 @@ static uint32_t getNumElementsImpl(const char* dirname, unsigned char type) { - DIR* dirp = opendir(dirname); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(dirname); if(dirp == NULL) return 0; @@ -26,8 +26,6 @@ static uint32_t getNumElementsImpl(const char* dirname, unsigned char type) if(type == DT_DIR && num_elements >= 2) num_elements -= 2; // accounting for . and .. - closedir(dirp); - return num_elements; } @@ -265,9 +263,8 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts) packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default"); packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system"); packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR); - packageCounts->pkg += getSQLite3Int(baseDir, "/var/db/pkg/local.sqlite", "SELECT count(id) FROM packages"); packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", DT_REG); - packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(blob) FROM Packages"); + packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Packages"); packageCounts->snap += getSnap(baseDir); packageCounts->xbps += getXBPS(baseDir, "/var/db/xbps"); packageCounts->brewCask += getNumElements(baseDir, "/home/linuxbrew/.linuxbrew/Caskroom", DT_DIR); @@ -281,7 +278,7 @@ static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* package getPackageCounts(baseDir, packageCounts); uint32_t baseDirLength = baseDir->length; - ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ETC"/pacman-mirrors.conf"); + ffStrbufAppendS(baseDir, FASTFETCH_TARGET_DIR_ETC "/pacman-mirrors.conf"); if(ffParsePropFile(baseDir->chars, "Branch =", &packageCounts->pacmanBranch) && packageCounts->pacmanBranch.length == 0) ffStrbufAppendS(&packageCounts->pacmanBranch, "stable"); ffStrbufSubstrBefore(baseDir, baseDirLength); diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h new file mode 100644 index 000000000..eea569d2a --- /dev/null +++ b/src/detection/physicaldisk/physicaldisk.h @@ -0,0 +1,25 @@ +#include "fastfetch.h" + +typedef enum FFPhysicalDiskType +{ + FF_PHYSICALDISK_TYPE_NONE = 0, + + // If neither is set, it's unknown + FF_PHYSICALDISK_TYPE_HDD = 1 << 0, + FF_PHYSICALDISK_TYPE_SSD = 1 << 1, + + FF_PHYSICALDISK_TYPE_FIXED = 1 << 2, + FF_PHYSICALDISK_TYPE_REMOVABLE = 1 << 3, +} FFPhysicalDiskType; + +typedef struct FFPhysicalDiskResult +{ + FFstrbuf name; + FFstrbuf interconnect; + FFstrbuf serial; + FFstrbuf devPath; + FFPhysicalDiskType type; + uint64_t size; +} FFPhysicalDiskResult; + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options); diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c new file mode 100644 index 000000000..bd186fab1 --- /dev/null +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -0,0 +1,93 @@ +#include "physicaldisk.h" +#include "util/apple/cf_helpers.h" + +#include +#include +#include +#include +#include +#include + +static inline void wrapIoObjectRelease(io_service_t* service) +{ + assert(service); + if (*service) + IOObjectRelease(*service); +} +#define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease))) + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +{ + FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0; + if(IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOMediaClass), &iterator) != KERN_SUCCESS) + return "IOServiceGetMatchingServices() failed"; + + io_registry_entry_t registryEntry; + while((registryEntry = IOIteratorNext(iterator)) != 0) + { + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPartition = registryEntry; + + io_name_t deviceName; + if (IORegistryEntryGetName(registryEntry, deviceName) != KERN_SUCCESS) + continue; + + if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDriver = 0; + if (IORegistryEntryGetParentEntry(entryPartition, kIOServicePlane, &entryDriver) != KERN_SUCCESS) + continue; + + if (!IOObjectConformsTo(entryDriver, kIOBlockStorageDriverClass)) // physical disk only + continue; + + FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); + ffStrbufInit(&device->serial); + ffStrbufInitS(&device->name, deviceName); + ffStrbufInit(&device->devPath); + ffStrbufInit(&device->interconnect); + device->type = FF_PHYSICALDISK_TYPE_NONE; + device->size = 0; + + FF_CFTYPE_AUTO_RELEASE CFBooleanRef removable = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaRemovableKey), kCFAllocatorDefault, kNilOptions); + device->type |= CFBooleanGetValue(removable) ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; + + FF_CFTYPE_AUTO_RELEASE CFStringRef bsdName = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kNilOptions); + if (bsdName) + { + ffCfStrGetString(bsdName, &device->devPath); + ffStrbufPrependS(&device->devPath, "/dev/"); + } + + FF_CFTYPE_AUTO_RELEASE CFNumberRef mediaSize = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaSizeKey), kCFAllocatorDefault, kNilOptions); + if (mediaSize) + ffCfNumGetInt64(mediaSize, (int64_t*) &device->size); + else + device->size = 0; + + FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryPhysical = 0; + if (IORegistryEntryGetParentEntry(entryDriver, kIOServicePlane, &entryPhysical) == KERN_SUCCESS) + { + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef protocolCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyProtocolCharacteristicsKey), kCFAllocatorDefault, kNilOptions); + if (protocolCharacteristics) + ffCfDictGetString(protocolCharacteristics, CFSTR(kIOPropertyPhysicalInterconnectTypeKey), &device->interconnect); + + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef deviceCharacteristics = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyDeviceCharacteristicsKey), kCFAllocatorDefault, kNilOptions); + if (deviceCharacteristics) + { + ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductSerialNumberKey), &device->serial); + + CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); + if (mediumType) + { + if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeSolidStateKey), 0) == 0) + device->type |= FF_PHYSICALDISK_TYPE_SSD; + else if (CFStringCompare(mediumType, CFSTR(kIOPropertyMediumTypeRotationalKey), 0) == 0) + device->type |= FF_PHYSICALDISK_TYPE_HDD; + } + } + } + } + + return NULL; +} diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c new file mode 100644 index 000000000..c23b08aea --- /dev/null +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -0,0 +1,70 @@ +#include "physicaldisk.h" +#include "util/stringUtils.h" + +#include +#include +#include +#include +#include +#include + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +{ + struct gmesh geomTree; + if (geom_gettree(&geomTree) < 0) + return "geom_gettree() failed"; + + if (geom_stats_open() < 0) + return "geom_stats_open() failed"; + + void* snap = geom_stats_snapshot_get(); + struct devstat* snapIter; + while ((snapIter = geom_stats_snapshot_next(snap)) != NULL) + { + if (snapIter->device_type & DEVSTAT_TYPE_PASS) + continue; + struct gident* geomId = geom_lookupid(&geomTree, snapIter->id); + if (geomId == NULL) + continue; + if (geomId->lg_what != ISPROVIDER) + continue; + struct gprovider* provider = (struct gprovider*) geomId->lg_ptr; + if (provider->lg_geom->lg_rank != 1) + continue; + + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(provider->lg_name); + FF_STRBUF_AUTO_DESTROY identifier = ffStrbufCreate(); + FFPhysicalDiskType type = FF_PHYSICALDISK_TYPE_NONE; + for (struct gconfig* ptr = provider->lg_config.lh_first; ptr; ptr = ptr->lg_config.le_next) + { + if (ffStrEquals(ptr->lg_name, "descr")) + ffStrbufSetS(&name, ptr->lg_val); + else if (ffStrEquals(ptr->lg_name, "rotationrate") && !ffStrEquals(ptr->lg_val, "unknown")) + type |= ffStrEquals(ptr->lg_val, "0") ? FF_PHYSICALDISK_TYPE_SSD : FF_PHYSICALDISK_TYPE_HDD; + else if (ffStrEquals(ptr->lg_name, "ident")) + ffStrbufSetS(&identifier, ptr->lg_val); + } + + if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix)) + continue; + + FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); + ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name); + ffStrbufInitMove(&device->serial, &identifier); + ffStrbufInit(&device->interconnect); + switch (snapIter->device_type & DEVSTAT_TYPE_IF_MASK) + { + case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->interconnect, "SCSI"); break; + case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->interconnect, "IDE"); break; + case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break; + } + device->size = (uint64_t) provider->lg_mediasize; + ffStrbufInitMove(&device->name, &name); + device->type = type; + } + + geom_stats_snapshot_free(snap); + geom_stats_close(); + + return NULL; +} diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c new file mode 100644 index 000000000..b94667731 --- /dev/null +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -0,0 +1,117 @@ +#include "physicaldisk.h" +#include "common/io/io.h" +#include "common/properties.h" +#include "util/stringUtils.h" + +#include +#include + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +{ + FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); + if(sysBlockDirp == NULL) + return "opendir(\"/sys/block/\") == NULL"; + + struct dirent* sysBlockEntry; + while ((sysBlockEntry = readdir(sysBlockDirp)) != NULL) + { + const char* const devName = sysBlockEntry->d_name; + + if (devName[0] == '.') + continue; + + char pathSysBlock[PATH_MAX]; + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s", devName); + + char pathSysDeviceReal[PATH_MAX]; + ssize_t pathLength = readlink(pathSysBlock, pathSysDeviceReal, sizeof(pathSysDeviceReal) - 1); + if (pathLength < 0) + continue; + pathSysDeviceReal[pathLength] = '\0'; + + if (strstr(pathSysDeviceReal, "/virtual/")) // virtual device + continue; + + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device", devName); + if (!ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY)) + continue; + + FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); + device->type = FF_PHYSICALDISK_TYPE_NONE; + ffStrbufInit(&device->name); + + { + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName); + ffAppendFileBuffer(pathSysBlock, &device->name); + if (device->name.length > 0) + ffStrbufAppendC(&device->name, ' '); + + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName); + ffAppendFileBuffer(pathSysBlock, &device->name); + ffStrbufTrim(&device->name, ' '); + + if (device->name.length == 0) + ffStrbufSetS(&device->name, devName); + + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + result->length--; + continue; + } + } + + ffStrbufInitF(&device->devPath, "/dev/%s", devName); + + { + ffStrbufInit(&device->interconnect); + if (strstr(pathSysDeviceReal, "/usb") != NULL) + ffStrbufSetS(&device->interconnect, "usb"); + else + { + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/transport", devName); + if (!ffAppendFileBuffer(pathSysBlock, &device->interconnect)) + { + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/uevent", devName); + if (ffParsePropFile(pathSysBlock, "DEVTYPE=", &device->interconnect)) + ffStrbufSubstrBeforeLastC(&device->interconnect, '_'); + } + } + } + + { + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/queue/rotational", devName); + char isRotationalChar = '1'; + if (ffReadFileData(pathSysBlock, 1, &isRotationalChar) > 0) + device->type |= isRotationalChar == '1' ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; + } + + { + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/size", devName); + char blkSize[32]; + ssize_t fileSize = ffReadFileData(pathSysBlock, sizeof(blkSize) - 1, blkSize); + if (fileSize > 0) + { + blkSize[fileSize] = 0; + device->size = (uint64_t) strtoul(blkSize, NULL, 10) * 512; + } + else + device->size = 0; + } + + { + char removableChar = '0'; + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/removable", devName); + if (ffReadFileData(pathSysBlock, 1, &removableChar) > 0) + device->type |= removableChar == '1' ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; + } + + { + ffStrbufInit(&device->serial); + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/serial", devName); + ffReadFileBuffer(pathSysBlock, &device->serial); + } + } + + return NULL; +} diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c new file mode 100644 index 000000000..1ad1a5779 --- /dev/null +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -0,0 +1,131 @@ +#include "physicaldisk.h" +#include "common/io/io.h" +#include "util/windows/unicode.h" + +#include +#include + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +{ + wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive"; + wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive"); + for (uint32_t idev = 0; ; ++idev) + { + _ultow(idev, pNum, 10); + + FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + break; + + DWORD retSize; + char sddBuffer[4096]; + if(!DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &sddBuffer, + sizeof(sddBuffer), + &retSize, + NULL + ) || retSize == 0) + continue; + + FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); + device->type = FF_PHYSICALDISK_TYPE_NONE; + STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*) sddBuffer; + + ffStrbufInit(&device->name); + if (sdd->VendorIdOffset != 0) + { + ffStrbufSetS(&device->name, (const char*) sddBuffer + sdd->VendorIdOffset); + ffStrbufTrim(&device->name, ' '); + } + if (sdd->ProductIdOffset != 0) + { + if (device->name.length) + ffStrbufAppendC(&device->name, ' '); + + ffStrbufAppendS(&device->name, (const char*) sddBuffer + sdd->ProductIdOffset); + ffStrbufTrimRight(&device->name, ' '); + } + + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + result->length--; + continue; + } + + ffStrbufInitWS(&device->devPath, szDevice); + ffStrbufInit(&device->serial); + if (sdd->SerialNumberOffset != 0) + { + ffStrbufSetS(&device->serial, (const char*) sddBuffer + sdd->SerialNumberOffset); + ffStrbufTrim(&device->serial, ' '); + } + + device->type |= sdd->RemovableMedia ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; + + ffStrbufInit(&device->interconnect); + switch (sdd->BusType) + { + case BusTypeUnknown: ffStrbufSetStatic(&device->interconnect, "Unknown"); break; + case BusTypeScsi: ffStrbufSetStatic(&device->interconnect, "Scsi"); break; + case BusTypeAtapi: ffStrbufSetStatic(&device->interconnect, "Atapi"); break; + case BusTypeAta: ffStrbufSetStatic(&device->interconnect, "Ata"); break; + case BusType1394: ffStrbufSetStatic(&device->interconnect, "1394"); break; + case BusTypeSsa: ffStrbufSetStatic(&device->interconnect, "Ssa"); break; + case BusTypeFibre: ffStrbufSetStatic(&device->interconnect, "Fibra"); break; + case BusTypeUsb: ffStrbufSetStatic(&device->interconnect, "Usb"); break; + case BusTypeRAID: ffStrbufSetStatic(&device->interconnect, "RAID"); break; + case BusTypeiScsi: ffStrbufSetStatic(&device->interconnect, "iScsi"); break; + case BusTypeSas: ffStrbufSetStatic(&device->interconnect, "Sas"); break; + case BusTypeSata: ffStrbufSetStatic(&device->interconnect, "Sata"); break; + case BusTypeSd: ffStrbufSetStatic(&device->interconnect, "Sd"); break; + case BusTypeMmc: ffStrbufSetStatic(&device->interconnect, "Mmc"); break; + case BusTypeVirtual: ffStrbufSetStatic(&device->interconnect, "Virtual"); break; + case BusTypeFileBackedVirtual: ffStrbufSetStatic(&device->interconnect, "FileBackedVirtual"); break; + case BusTypeSpaces: ffStrbufSetStatic(&device->interconnect, "Spaces"); break; + case BusTypeNvme: ffStrbufSetStatic(&device->interconnect, "Nvme"); break; + case BusTypeSCM: ffStrbufSetStatic(&device->interconnect, "SCM"); break; + case BusTypeUfs: ffStrbufSetStatic(&device->interconnect, "Ufs"); break; + default: ffStrbufSetF(&device->interconnect, "Unknown (%d)", (int) sdd->BusType); break; + } + + DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; + if(DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceSeekPenaltyProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &dspd, + sizeof(dspd), + &retSize, + NULL + ) && retSize == sizeof(dspd)) + device->type |= dspd.IncursSeekPenalty ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; + + DISK_GEOMETRY_EX dge = {}; + if(DeviceIoControl( + hDevice, + IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, + NULL, + 0, + &dge, + sizeof(dge), + &retSize, + NULL)) + device->size = (uint64_t) dge.DiskSize.QuadPart; + else + device->size = 0; + } + + return NULL; +} diff --git a/src/detection/temps/temps_apple.c b/src/detection/temps/temps_apple.c index 7054a3ed3..b274c49e0 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/detection/temps/temps_apple.c @@ -333,6 +333,25 @@ const char *ffDetectCoreTemps(enum FFTempType type, double *result) count += detectTemp(conn, "Tp09", result); // CPU core 8 break; + case FF_TEMP_CPU_M3X: + count += detectTemp(conn, "Te05", result); // CPU efficiency core 1 + count += detectTemp(conn, "Te0L", result); // CPU efficiency core 2 + count += detectTemp(conn, "Te0P", result); // CPU efficiency core 3 + count += detectTemp(conn, "Te0S", result); // CPU efficiency core 4 + count += detectTemp(conn, "Tf04", result); // CPU performance core 1 + count += detectTemp(conn, "Tf09", result); // CPU performance core 2 + count += detectTemp(conn, "Tf0A", result); // CPU performance core 3 + count += detectTemp(conn, "Tf0B", result); // CPU performance core 4 + count += detectTemp(conn, "Tf0D", result); // CPU performance core 5 + count += detectTemp(conn, "Tf0E", result); // CPU performance core 6 + count += detectTemp(conn, "Tf44", result); // CPU performance core 7 + count += detectTemp(conn, "Tf49", result); // CPU performance core 8 + count += detectTemp(conn, "Tf4A", result); // CPU performance core 9 + count += detectTemp(conn, "Tf4B", result); // CPU performance core 10 + count += detectTemp(conn, "Tf4D", result); // CPU performance core 11 + count += detectTemp(conn, "Tf4E", result); // CPU performance core 12 + break; + case FF_TEMP_GPU_INTEL: count += detectTemp(conn, "TCGC", result); // GPU Intel Graphics goto gpu_unknown; @@ -359,12 +378,27 @@ const char *ffDetectCoreTemps(enum FFTempType type, double *result) count += detectTemp(conn, "Tg0j", result); // GPU 2 break; + case FF_TEMP_GPU_M3X: + count += detectTemp(conn, "Tf14", result); // GPU 1 + count += detectTemp(conn, "Tf18", result); // GPU 2 + count += detectTemp(conn, "Tf19", result); // GPU 3 + count += detectTemp(conn, "Tf1A", result); // GPU 4 + count += detectTemp(conn, "Tf24", result); // GPU 5 + count += detectTemp(conn, "Tf28", result); // GPU 6 + count += detectTemp(conn, "Tf29", result); // GPU 7 + count += detectTemp(conn, "Tf2A", result); // GPU 8 + break; + case FF_TEMP_BATTERY: count += detectTemp(conn, "TB1T", result); // Battery + count += detectTemp(conn, "TB2T", result); // Battery break; case FF_TEMP_MEMORY: - count += detectTemp(conn, "Tm02", result); // Memory + count += detectTemp(conn, "Tm02", result); // Memory 1 + count += detectTemp(conn, "Tm06", result); // Memory 2 + count += detectTemp(conn, "Tm08", result); // Memory 3 + count += detectTemp(conn, "Tm09", result); // Memory 4 break; } diff --git a/src/detection/temps/temps_apple.h b/src/detection/temps/temps_apple.h index 7d340ba22..ccf914311 100644 --- a/src/detection/temps/temps_apple.h +++ b/src/detection/temps/temps_apple.h @@ -15,12 +15,14 @@ enum FFTempType FF_TEMP_CPU_X64, FF_TEMP_CPU_M1X, FF_TEMP_CPU_M2X, + FF_TEMP_CPU_M3X, FF_TEMP_GPU_INTEL, FF_TEMP_GPU_AMD, FF_TEMP_GPU_UNKNOWN, FF_TEMP_GPU_M1X, FF_TEMP_GPU_M2X, + FF_TEMP_GPU_M3X, FF_TEMP_BATTERY, diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index d54e1cc61..68b963e07 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -4,6 +4,8 @@ #include "common/properties.h" #include "util/stringUtils.h" +#include + #ifdef _WIN32 #include "util/mallocHelper.h" @@ -162,6 +164,28 @@ static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version) NULL }) == NULL; } +#else +static bool getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf* version) +{ + FF_STRBUF_AUTO_DESTROY command = ffStrbufCreate(); + ffStrbufAppendS(&command, "printf \"%s\" \"$"); + ffStrbufAppendTransformS(&command, exeName, toupper); + ffStrbufAppendS(&command, "_VERSION\""); + + if (ffProcessAppendStdOut(version, (char* const[]) { + "env", + "-i", + exe->chars, + "-c", + command.chars, + NULL + }) != NULL) + return false; + + ffStrbufSubstrBeforeFirstC(version, '('); + ffStrbufRemoveStrings(version, 2, (const char*[]) { "-release", "release" }); + return true; +} #endif bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) @@ -198,7 +222,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) return getFileVersion(exe->chars, version); #else - return false; + return getShellVersionGeneric(exe, exeName, version); #endif } diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 7fa216f16..3fde133c4 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -5,7 +5,6 @@ #include "common/thread.h" #include "util/stringUtils.h" -#include #include #include #include @@ -68,8 +67,6 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid) { - const char* error = NULL; - #ifdef __linux__ char statFilePath[64]; @@ -86,20 +83,18 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid) !ffStrSet(name) || *ppid == 0 ) - error = "sscanf(stat) failed"; + return "sscanf(stat) failed"; #elif defined(__APPLE__) struct proc_bsdshortinfo proc; if(proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 0, &proc, PROC_PIDT_SHORTBSDINFO_SIZE) <= 0) - error = "proc_pidinfo(pid) failed"; - else - { - *ppid = (pid_t)proc.pbsi_ppid; - strncpy(name, proc.pbsi_comm, 16); //trancated to 16 chars - } + return "proc_pidinfo(pid) failed"; - #else + *ppid = (pid_t)proc.pbsi_ppid; + strncpy(name, proc.pbsi_comm, 16); //trancated to 16 chars + + #elif defined(__FreeBSD__) struct kinfo_proc proc; size_t size = sizeof(proc); @@ -108,16 +103,18 @@ static const char* getProcessNameAndPpid(pid_t pid, char* name, pid_t* ppid) &proc, &size, NULL, 0 )) - error = "sysctl(KERN_PROC_PID) failed"; - else - { - *ppid = (pid_t)proc.ki_ppid; - strncpy(name, proc.ki_comm, COMMLEN); - } + return "sysctl(KERN_PROC_PID) failed"; + + *ppid = (pid_t)proc.ki_ppid; + strncpy(name, proc.ki_comm, COMMLEN); + + #else + + return "Unsupported platform"; #endif - return error; + return NULL; } static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) @@ -286,34 +283,8 @@ static void getUserShellFromEnv(FFTerminalShellResult* result) } } -static void getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf* version) -{ - FF_STRBUF_AUTO_DESTROY command = ffStrbufCreate(); - ffStrbufAppendS(&command, "printf \"%s\" \"$"); - ffStrbufAppendTransformS(&command, exeName, toupper); - ffStrbufAppendS(&command, "_VERSION\""); - - ffProcessAppendStdOut(version, (char* const[]) { - "env", - "-i", - exe->chars, - "-c", - command.chars, - NULL - }); - ffStrbufSubstrBeforeFirstC(version, '('); - ffStrbufRemoveStrings(version, 2, (const char*[]) { "-release", "release" }); -} - bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version); -static void getShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) -{ - ffStrbufClear(version); - if(!fftsGetShellVersion(exe, exeName, version)) - getShellVersionGeneric(exe, exeName, version); -} - bool fftsGetTerminalVersion(FFstrbuf* processName, FFstrbuf* exe, FFstrbuf* version); const FFTerminalShellResult* ffDetectTerminalShell() @@ -350,7 +321,8 @@ const FFTerminalShellResult* ffDetectTerminalShell() getTerminalFromEnv(&result); getUserShellFromEnv(&result); - getShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion); + ffStrbufClear(&result.shellVersion); + fftsGetShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion); if(ffStrbufEqualS(&result.shellProcessName, "pwsh")) ffStrbufInitStatic(&result.shellPrettyName, "PowerShell"); diff --git a/src/detection/wifi/wifi_windows.c b/src/detection/wifi/wifi_windows.c index 3b7ac5a1c..18638c046 100644 --- a/src/detection/wifi/wifi_windows.c +++ b/src/detection/wifi/wifi_windows.c @@ -18,22 +18,22 @@ static void convertIfStateToString(WLAN_INTERFACE_STATE state, FFstrbuf* result) ffStrbufAppendS(result, "Connected"); break; case wlan_interface_state_ad_hoc_network_formed: - ffStrbufAppendS(result, "First node in a ad hoc network"); + ffStrbufAppendS(result, "Ad hoc network formed"); break; case wlan_interface_state_disconnecting: ffStrbufAppendS(result, "Disconnecting"); break; case wlan_interface_state_disconnected: - ffStrbufAppendS(result, "Not connected"); + ffStrbufAppendS(result, "Disconnected"); break; case wlan_interface_state_associating: - ffStrbufAppendS(result, "Attempting to associate with a network"); + ffStrbufAppendS(result, "Associating"); break; case wlan_interface_state_discovering: - ffStrbufAppendS(result, "Auto configuration is discovering settings for the network"); + ffStrbufAppendS(result, "Discovering"); break; case wlan_interface_state_authenticating: - ffStrbufAppendS(result, "In process of authenticating"); + ffStrbufAppendS(result, "Authenticating"); break; default: ffStrbufAppendS(result, "Unknown"); @@ -133,16 +133,16 @@ const char* ffDetectWifi(FFlist* result) case dot11_phy_type_ht: ffStrbufAppendS(&item->conn.protocol, "802.11n (Wi-Fi 4)"); break; - case 8 /*dot11_phy_type_vht*/: + case dot11_phy_type_vht: ffStrbufAppendS(&item->conn.protocol, "802.11ac (Wi-Fi 5)"); break; - case 9 /*dot11_phy_type_dmg*/: + case dot11_phy_type_dmg: ffStrbufAppendS(&item->conn.protocol, "802.11ad (WiGig)"); break; - case 10 /*dot11_phy_type_he*/: + case dot11_phy_type_he: ffStrbufAppendS(&item->conn.protocol, "802.11ax (Wi-Fi 6)"); break; - case 11 /*dot11_phy_type_eht*/: + case dot11_phy_type_eht: ffStrbufAppendS(&item->conn.protocol, "802.11be (Wi-Fi 7)"); break; default: @@ -179,10 +179,10 @@ const char* ffDetectWifi(FFlist* result) case DOT11_AUTH_ALGO_RSNA_PSK: ffStrbufAppendS(&item->conn.security, "WPA2-PSK"); break; - case 8 /* DOT11_AUTH_ALGO_WPA3 */: + case DOT11_AUTH_ALGO_WPA3: ffStrbufAppendS(&item->conn.security, "WPA3"); break; - case 9 /* DOT11_AUTH_ALGO_WPA3_SAE */: + case DOT11_AUTH_ALGO_WPA3_SAE: ffStrbufAppendS(&item->conn.security, "WPA3-SAE"); break; case 10 /* DOT11_AUTH_ALGO_OWE */: diff --git a/src/logo/ascii/adelie.txt b/src/logo/ascii/adelie.txt index df46e57a0..417b5eb04 100644 --- a/src/logo/ascii/adelie.txt +++ b/src/logo/ascii/adelie.txt @@ -1,16 +1,16 @@ ${c3} ,-^-___ -${c3} /\\\\\\/// -${c2}refined.${c1} /\\\\\\\\// -${c2}reliable.${c1} /\\\\\\/// -${c2}ready.${c1} /\\\\/////\\ - __///\\\\\\\\/////\\ -${c3} _//////\\\\\\\\\\\\\\//// -${c1} ///////${c3}\\\\\\\\\\\\\\\\\\\\// - //////${c1}\\\\\\\\\\/ - /////\\\\\\\\\\/ - /////${c3}\\\\\\\\/ - /\\\\///\\\\\\/ - /\\\\\\/${c1}\\\/ - /\\\\\\\\// +${c3} /\\\/// +${c2}refined.${c1} /\\\\// +${c2}reliable.${c1} /\\\/// +${c2}ready.${c1} /\\/////\ + __///\\\\/////\ +${c3} _//////\\\\\\\//// +${c1} ///////${c3}\\\\\\\\\\// + //////${c1}\\\\\/ + /////\\\\\/ + /////${c3}\\\\/ + /\\///\\\/ + /\\\/${c1}\\/ + /\\\\// ////// - /// ${c3}\\\\\\\\\\ + /// ${c3}\\\\\ diff --git a/src/logo/ascii/eshanizedos.txt b/src/logo/ascii/eshanizedos.txt new file mode 100644 index 000000000..26ec7422a --- /dev/null +++ b/src/logo/ascii/eshanizedos.txt @@ -0,0 +1,27 @@ + .:-==++++++++++++++++++++++-. + .:=+##############################+ + .=*###################################- + :+######################################: + :+######################################*- + .+#############*+--:::::::::::::::::::::. + :*##########*=: + -###########= + :##########+. + *#########= + =*********+ .::::::::::::::::. + **********. -*###################+: +:********** =#######################= +-*********+ +************************ +:*********+ :***********************: +.********** .=******************+- + +*********- + .**********. + =**********: + +**********=. + =***********=: + -*************+-. + :+****************+++++++++++++++++++++==: + :+**************************************+. + -+************************************- + .-+*********************************. + :-==+*************************=. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 9e80422f3..62d141fd1 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1348,6 +1348,15 @@ static const FFlogo E[] = { .colorKeys = FF_COLOR_FG_WHITE, .colorTitle = FF_COLOR_FG_WHITE, }, + // EshanizedOS + { + .names = {"EshanizedOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_ESHANIZEDOS, + .colors = { + FF_COLOR_FG_RED, + FF_COLOR_FG_WHITE, + }, + }, // EuroLinux { .names = {"EuroLinux"}, diff --git a/src/logo/image/im6.c b/src/logo/image/im6.c index a8820f53b..9694a797b 100644 --- a/src/logo/image/im6.c +++ b/src/logo/image/im6.c @@ -17,10 +17,13 @@ FFLogoImageResult ffLogoPrintImageIM6(FFLogoRequestData* requestData) FF_LIBRARY_LOAD(imageMagick, &instance.config.library.libImageMagick, FF_LOGO_IMAGE_RESULT_INIT_ERROR, "libMagickCore-6.Q16HDRI" FF_LIBRARY_EXTENSION, 8, "libMagickCore-6.Q16" FF_LIBRARY_EXTENSION, 8) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR); - return ffLogoPrintImageImpl(requestData, &(FFIMData) { + FFLogoImageResult result = ffLogoPrintImageImpl(requestData, &(FFIMData) { .resizeFunc = logoResize, .library = imageMagick, }); + + imageMagick = NULL; // leak imageMagick to prevent fastfetch from crashing #552 + return result; } #endif diff --git a/src/logo/image/im7.c b/src/logo/image/im7.c index 03229aacb..b0eeed2dc 100644 --- a/src/logo/image/im7.c +++ b/src/logo/image/im7.c @@ -21,10 +21,13 @@ FFLogoImageResult ffLogoPrintImageIM7(FFLogoRequestData* requestData) ) FF_LIBRARY_LOAD_SYMBOL_ADDRESS(imageMagick, ffResizeImage, ResizeImage, FF_LOGO_IMAGE_RESULT_INIT_ERROR); - return ffLogoPrintImageImpl(requestData, &(FFIMData) { + FFLogoImageResult result = ffLogoPrintImageImpl(requestData, &(FFIMData) { .resizeFunc = logoResize, .library = imageMagick, }); + + imageMagick = NULL; // leak imageMagick to prevent fastfetch from crashing #552 + return result; } #endif diff --git a/src/modules/diskio/diskio.c b/src/modules/diskio/diskio.c index ef15cef11..d92c21609 100644 --- a/src/modules/diskio/diskio.c +++ b/src/modules/diskio/diskio.c @@ -6,7 +6,7 @@ #include "util/stringUtils.h" #define FF_DISKIO_DISPLAY_NAME "Disk IO" -#define FF_DISKIO_NUM_FORMAT_ARGS 11 +#define FF_DISKIO_NUM_FORMAT_ARGS 8 static int sortDevices(const FFDiskIOResult* left, const FFDiskIOResult* right) { @@ -17,10 +17,7 @@ static void formatKey(const FFDiskIOOptions* options, FFDiskIOResult* dev, uint3 { if(options->moduleArgs.key.length == 0) { - if(!dev->name.length) - ffStrbufSetF(&dev->name, "unknown %u", (unsigned) index); - - ffStrbufSetF(key, FF_DISKIO_DISPLAY_NAME " (%s)", dev->name.chars); + ffStrbufSetF(key, FF_DISKIO_DISPLAY_NAME " (%s)", dev->name.length ? dev->name.chars : dev->devPath.chars); } else { @@ -74,34 +71,15 @@ void ffPrintDiskIO(FFDiskIOOptions* options) ffParseSize(dev->bytesWritten, &buffer2); ffStrbufAppendS(&buffer2, "/s"); - const char* physicalType; - switch(dev->type) - { - case FF_DISKIO_PHYSICAL_TYPE_HDD: - physicalType = "HDD"; - break; - case FF_DISKIO_PHYSICAL_TYPE_SSD: - physicalType = "SSD"; - break; - default: - physicalType = "Unknown"; - break; - } - FF_STRBUF_AUTO_DESTROY sizePretty = ffStrbufCreate(); - ffParseSize(dev->size, &sizePretty); - ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISKIO_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, - {FF_FORMAT_ARG_TYPE_STRBUF, &dev->interconnect}, - {FF_FORMAT_ARG_TYPE_STRING, physicalType}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesRead}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->bytesWritten}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->readCount}, {FF_FORMAT_ARG_TYPE_UINT64, &dev->writeCount}, - {FF_FORMAT_ARG_TYPE_STRBUF, &sizePretty}, }); } ++index; @@ -110,7 +88,6 @@ void ffPrintDiskIO(FFDiskIOOptions* options) FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) { ffStrbufDestroy(&dev->name); - ffStrbufDestroy(&dev->interconnect); ffStrbufDestroy(&dev->devPath); } } @@ -181,33 +158,16 @@ void ffGenerateDiskIOJsonResult(FFDiskIOOptions* options, yyjson_mut_doc* doc, y { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name); - yyjson_mut_obj_add_strbuf(doc, obj, "interconnectType", &dev->interconnect); yyjson_mut_obj_add_strbuf(doc, obj, "devPath", &dev->devPath); - - switch(dev->type) - { - case FF_DISKIO_PHYSICAL_TYPE_HDD: - yyjson_mut_obj_add_str(doc, obj, "physicalType", "HDD"); - break; - case FF_DISKIO_PHYSICAL_TYPE_SSD: - yyjson_mut_obj_add_str(doc, obj, "physicalType", "SSD"); - break; - default: - yyjson_mut_obj_add_null(doc, obj, "physicalType"); - break; - } - yyjson_mut_obj_add_uint(doc, obj, "bytesRead", dev->bytesRead); yyjson_mut_obj_add_uint(doc, obj, "bytesWritten", dev->bytesWritten); yyjson_mut_obj_add_uint(doc, obj, "readCount", dev->readCount); yyjson_mut_obj_add_uint(doc, obj, "writeCount", dev->writeCount); - yyjson_mut_obj_add_uint(doc, obj, "size", dev->size); } FF_LIST_FOR_EACH(FFDiskIOResult, dev, result) { ffStrbufDestroy(&dev->name); - ffStrbufDestroy(&dev->interconnect); ffStrbufDestroy(&dev->devPath); } } @@ -218,14 +178,11 @@ void ffPrintDiskIOHelpFormat(void) "Size of data read per second (formatted)", "Size of data written per second (formatted)", "Device name", - "Device interconnect type", - "Device physical type (SSD / HDD)", "Device raw file path", "Size of data read per second (in bytes)", "Size of data written per second (in bytes)", "Number of reads", "Number of writes", - "Device size (formatted)", }); } diff --git a/src/modules/modules.h b/src/modules/modules.h index 57632fb7d..35d6523c4 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -37,6 +37,7 @@ #include "modules/opencl/opencl.h" #include "modules/os/os.h" #include "modules/packages/packages.h" +#include "modules/physicaldisk/physicaldisk.h" #include "modules/player/player.h" #include "modules/poweradapter/poweradapter.h" #include "modules/processes/processes.h" diff --git a/src/modules/options.h b/src/modules/options.h index 191767c77..aa124c24a 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -37,6 +37,7 @@ #include "modules/opencl/option.h" #include "modules/os/option.h" #include "modules/packages/option.h" +#include "modules/physicaldisk/option.h" #include "modules/player/option.h" #include "modules/poweradapter/option.h" #include "modules/processes/option.h" diff --git a/src/modules/physicaldisk/option.h b/src/modules/physicaldisk/option.h new file mode 100644 index 000000000..243a98a6a --- /dev/null +++ b/src/modules/physicaldisk/option.h @@ -0,0 +1,13 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFPhysicalDiskOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; + + FFstrbuf namePrefix; +} FFPhysicalDiskOptions; diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c new file mode 100644 index 000000000..05911eb64 --- /dev/null +++ b/src/modules/physicaldisk/physicaldisk.c @@ -0,0 +1,241 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "common/parsing.h" +#include "detection/physicaldisk/physicaldisk.h" +#include "modules/physicaldisk/physicaldisk.h" +#include "util/stringUtils.h" + +#define FF_PHYSICALDISK_DISPLAY_NAME "Physical Disk" +#define FF_PHYSICALDISK_NUM_FORMAT_ARGS 7 + +static int sortDevices(const FFPhysicalDiskResult* left, const FFPhysicalDiskResult* right) +{ + return ffStrbufComp(&left->name, &right->name); +} + +static void formatKey(const FFPhysicalDiskOptions* options, FFPhysicalDiskResult* dev, uint32_t index, FFstrbuf* key) +{ + if(options->moduleArgs.key.length == 0) + { + ffStrbufSetF(key, FF_PHYSICALDISK_DISPLAY_NAME " (%s)", dev->name.length ? dev->name.chars : dev->devPath.chars); + } + else + { + ffStrbufClear(key); + ffParseFormatString(key, &options->moduleArgs.key, 2, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, + }); + } +} + +void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFPhysicalDiskResult)); + const char* error = ffDetectPhysicalDisk(&result, options); + + if(error) + { + ffPrintError(FF_PHYSICALDISK_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); + return; + } + + ffListSort(&result, (const void*) sortDevices); + + uint32_t index = 0; + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + + FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) + { + formatKey(options, dev, result.length == 1 ? 0 : index + 1, &key); + ffStrbufClear(&buffer); + ffParseSize(dev->size, &buffer); + + const char* physicalType = dev->type & FF_PHYSICALDISK_TYPE_HDD + ? "HDD" + : dev->type & FF_PHYSICALDISK_TYPE_SSD + ? "SSD" + : ""; + const char* removableType = dev->type & FF_PHYSICALDISK_TYPE_REMOVABLE + ? "Removable" + : dev->type & FF_PHYSICALDISK_TYPE_FIXED + ? "Fixed" + : ""; + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + if (physicalType[0] || removableType[0]) + { + ffStrbufAppendS(&buffer, " ["); + if (physicalType[0]) + ffStrbufAppendS(&buffer, physicalType); + if (removableType[0]) + { + if (physicalType[0]) + ffStrbufAppendS(&buffer, ", "); + ffStrbufAppendS(&buffer, removableType); + } + ffStrbufAppendC(&buffer, ']'); + } + ffStrbufPutTo(&buffer, stdout); + } + else + { + ffParseSize(dev->size, &buffer); + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_PHYSICALDISK_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->interconnect}, + {FF_FORMAT_ARG_TYPE_STRING, physicalType}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->serial}, + {FF_FORMAT_ARG_TYPE_STRING, removableType}, + }); + } + ++index; + } + + FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) + { + ffStrbufDestroy(&dev->name); + ffStrbufDestroy(&dev->interconnect); + ffStrbufDestroy(&dev->devPath); + ffStrbufDestroy(&dev->serial); + } +} + +bool ffParsePhysicalDiskCommandOptions(FFPhysicalDiskOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_PHYSICALDISK_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + if (ffStrEqualsIgnCase(subKey, "name-prefix")) + { + ffOptionParseString(key, value, &options->namePrefix); + return true; + } + + return false; +} + +void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + if (ffStrEqualsIgnCase(key, "namePrefix")) + { + ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + continue; + } + + ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); + } +} + +void ffGeneratePhysicalDiskJsonConfig(FFPhysicalDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyPhysicalDiskOptions))) FFPhysicalDiskOptions defaultOptions; + ffInitPhysicalDiskOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); + + if (!ffStrbufEqual(&options->namePrefix, &defaultOptions.namePrefix)) + yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); +} + +void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFPhysicalDiskResult)); + const char* error = ffDetectPhysicalDisk(&result, options); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &dev->name); + yyjson_mut_obj_add_strbuf(doc, obj, "devPath", &dev->devPath); + yyjson_mut_obj_add_strbuf(doc, obj, "interconnect", &dev->interconnect); + + if (dev->type & FF_PHYSICALDISK_TYPE_HDD) + yyjson_mut_obj_add_str(doc, obj, "kind", "HDD"); + else if (dev->type & FF_PHYSICALDISK_TYPE_SSD) + yyjson_mut_obj_add_str(doc, obj, "kind", "SSD"); + else + yyjson_mut_obj_add_null(doc, obj, "kind"); + + yyjson_mut_obj_add_uint(doc, obj, "size", dev->size); + yyjson_mut_obj_add_strbuf(doc, obj, "serial", &dev->serial); + + if (dev->type & FF_PHYSICALDISK_TYPE_REMOVABLE) + yyjson_mut_obj_add_bool(doc, obj, "removable", true); + else if (dev->type & FF_PHYSICALDISK_TYPE_FIXED) + yyjson_mut_obj_add_bool(doc, obj, "removable", false); + else + yyjson_mut_obj_add_null(doc, obj, "removable"); + } + + FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) + { + ffStrbufDestroy(&dev->name); + ffStrbufDestroy(&dev->interconnect); + ffStrbufDestroy(&dev->devPath); + } +} + +void ffPrintPhysicalDiskHelpFormat(void) +{ + ffPrintModuleFormatHelp(FF_PHYSICALDISK_MODULE_NAME, "{1}", FF_PHYSICALDISK_NUM_FORMAT_ARGS, (const char* []) { + "Device size (formatted)", + "Device name", + "Device interconnect type", + "Device raw file path", + "Serial number", + "Device kind (SSD or HDD)", + "Device kind (Removable or Fixed)", + }); +} + +void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_PHYSICALDISK_MODULE_NAME, + "Print physical disk information", + ffParsePhysicalDiskCommandOptions, + ffParsePhysicalDiskJsonObject, + ffPrintPhysicalDisk, + ffGeneratePhysicalDiskJsonResult, + ffPrintPhysicalDiskHelpFormat, + ffGeneratePhysicalDiskJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs); + + ffStrbufInit(&options->namePrefix); +} + +void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->namePrefix); +} diff --git a/src/modules/physicaldisk/physicaldisk.h b/src/modules/physicaldisk/physicaldisk.h new file mode 100644 index 000000000..d8216c140 --- /dev/null +++ b/src/modules/physicaldisk/physicaldisk.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_PHYSICALDISK_MODULE_NAME "PhysicalDisk" + +void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options); +void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options); +void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options); diff --git a/src/options/general.c b/src/options/general.c index 6357e04b8..7cec888f7 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -30,7 +30,24 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va else if (ffStrEqualsIgnCase(key, "osFile")) ffStrbufSetS(&options->osFile, yyjson_get_str(val)); else if (ffStrEqualsIgnCase(key, "dsForceDrm")) - options->dsForceDrm = yyjson_get_bool(val); + { + if (yyjson_is_str(val)) + { + int value; + const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) { + { "sysfs-only", FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY }, + { "false", FF_DS_FORCE_DRM_TYPE_FALSE }, + { "true", FF_DS_FORCE_DRM_TYPE_TRUE }, + {}, + }); + if (error) + return "Invalid enum value of `dsForceDrm`"; + else + options->dsForceDrm = (FFDsForceDrmType) value; + } + else + options->dsForceDrm = yyjson_get_bool(val) ? FF_DS_FORCE_DRM_TYPE_TRUE : FF_DS_FORCE_DRM_TYPE_FALSE; + } #elif defined(_WIN32) else if (ffStrEqualsIgnCase(key, "wmiTimeout")) options->wmiTimeout = (int32_t) yyjson_get_int(val); @@ -65,7 +82,14 @@ bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key else if (ffStrEqualsIgnCase(key, "--os-file")) ffOptionParseString(key, value, &options->osFile); else if(ffStrEqualsIgnCase(key, "--ds-force-drm")) - options->dsForceDrm = ffOptionParseBoolean(value); + { + if (ffOptionParseBoolean(value)) + options->dsForceDrm = FF_DS_FORCE_DRM_TYPE_TRUE; + else if (ffStrEqualsIgnCase(value, "sysfs-only")) + options->dsForceDrm = FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY; + else + options->dsForceDrm = FF_DS_FORCE_DRM_TYPE_FALSE; + } #elif defined(_WIN32) else if (ffStrEqualsIgnCase(key, "--wmi-timeout")) options->wmiTimeout = ffOptionParseInt32(key, value); @@ -86,7 +110,7 @@ void ffOptionsInitGeneral(FFOptionsGeneral* options) options->escapeBedrock = true; ffStrbufInit(&options->playerName); ffStrbufInit(&options->osFile); - options->dsForceDrm = false; + options->dsForceDrm = FF_DS_FORCE_DRM_TYPE_FALSE; #elif defined(_WIN32) options->wmiTimeout = 5000; #endif @@ -125,7 +149,20 @@ void ffOptionsGenerateGeneralJsonConfig(FFOptionsGeneral* options, yyjson_mut_do yyjson_mut_obj_add_strbuf(doc, obj, "osFile", &options->osFile); if (options->dsForceDrm != defaultOptions.dsForceDrm) - yyjson_mut_obj_add_bool(doc, obj, "dsForceDrm", options->dsForceDrm); + { + switch (options->dsForceDrm) + { + case FF_DS_FORCE_DRM_TYPE_FALSE: + yyjson_mut_obj_add_bool(doc, obj, "dsForceDrm", false); + break; + case FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY: + yyjson_mut_obj_add_str(doc, obj, "dsForceDrm", "sysfs-only"); + break; + case FF_DS_FORCE_DRM_TYPE_TRUE: + yyjson_mut_obj_add_bool(doc, obj, "dsForceDrm", true); + break; + } + } #elif defined(_WIN32) diff --git a/src/options/general.h b/src/options/general.h index 156991028..98667c2f8 100644 --- a/src/options/general.h +++ b/src/options/general.h @@ -2,6 +2,13 @@ #include "util/FFstrbuf.h" +typedef enum FFDsForceDrmType +{ + FF_DS_FORCE_DRM_TYPE_FALSE = 0, // Disable + FF_DS_FORCE_DRM_TYPE_TRUE = 1, // Try `libdrm`, then `sysfs` if libdrm failed + FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY, // Use `/sys/class/drm` only +} FFDsForceDrmType; + typedef struct FFOptionsGeneral { bool multithreading; @@ -12,7 +19,7 @@ typedef struct FFOptionsGeneral FFstrbuf playerName; FFstrbuf osFile; bool escapeBedrock; - bool dsForceDrm; + FFDsForceDrmType dsForceDrm; #elif defined(_WIN32) int32_t wmiTimeout; #endif diff --git a/src/options/modules.c b/src/options/modules.c index 2047abdde..68b835d82 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -38,6 +38,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitOpenCLOptions(&options->openCL); ffInitOpenGLOptions(&options->openGL); ffInitPackagesOptions(&options->packages); + ffInitPhysicalDiskOptions(&options->physicalDisk); ffInitPlayerOptions(&options->player); ffInitPowerAdapterOptions(&options->powerAdapter); ffInitProcessesOptions(&options->processes); @@ -98,6 +99,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyOSOptions(&options->os); ffDestroyOpenCLOptions(&options->openCL); ffDestroyOpenGLOptions(&options->openGL); + ffDestroyPhysicalDiskOptions(&options->physicalDisk); ffDestroyPackagesOptions(&options->packages); ffDestroyPlayerOptions(&options->player); ffDestroyPowerAdapterOptions(&options->powerAdapter); diff --git a/src/options/modules.h b/src/options/modules.h index 66b4203c6..e9836e140 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -39,6 +39,7 @@ typedef struct FFOptionsModules FFOpenCLOptions openCL; FFOpenGLOptions openGL; FFPackagesOptions packages; + FFPhysicalDiskOptions physicalDisk; FFPlayerOptions player; FFPowerAdapterOptions powerAdapter; FFProcessesOptions processes; diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 574324f7a..6dfe59589 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -59,9 +59,9 @@ void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) uint32_t oldFree = ffStrbufGetFree(strbuf); if (oldFree >= free && !(strbuf->allocated == 0 && strbuf->length > 0)) return; - + uint32_t newCap = strbuf->allocated + (free - oldFree); - + if(strbuf->allocated == 0) { newCap += strbuf->length + 1; // +1 for the NUL @@ -74,7 +74,7 @@ void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) } else strbuf->chars = realloc(strbuf->chars, sizeof(*strbuf->chars) * newCap); - + strbuf->allocated = newCap; } @@ -99,6 +99,8 @@ void ffStrbufAppendC(FFstrbuf* strbuf, char c) void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) { + if (num == 0) return; + ffStrbufEnsureFree(strbuf, num); memset(&strbuf->chars[strbuf->length], c, num); strbuf->length += num; diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 04687f0be..f224c84eb 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -20,7 +20,7 @@ static void getExePath(FFPlatform* platform) FFstrbuf* const exePath = &platform->exePath; ffStrbufEnsureFree(exePath, PATH_MAX); #ifdef __linux__ - ssize_t exePathLen = readlink("/proc/self/exe", exePath->chars, exePath->allocated); + ssize_t exePathLen = readlink("/proc/self/exe", exePath->chars, exePath->allocated - 1); #elif defined(__APPLE__) int exePathLen = proc_pidpath((int) getpid(), exePath->chars, exePath->allocated); #elif defined(__FreeBSD__) diff --git a/src/util/smbiosHelper.c b/src/util/smbiosHelper.c index 1033ec880..88249f6d8 100644 --- a/src/util/smbiosHelper.c +++ b/src/util/smbiosHelper.c @@ -18,6 +18,8 @@ bool ffIsSmbiosValueSet(FFstrbuf* value) !ffStrbufIgnCaseEqualS(value, "Undefined") && !ffStrbufIgnCaseEqualS(value, "Not Specified") && !ffStrbufIgnCaseEqualS(value, "Not Applicable") && + !ffStrbufIgnCaseEqualS(value, "Not Defined") && + !ffStrbufIgnCaseEqualS(value, "Not Available") && !ffStrbufIgnCaseEqualS(value, "INVALID") && !ffStrbufIgnCaseEqualS(value, "Type1ProductConfigId") && !ffStrbufIgnCaseEqualS(value, "All Series") &&