Merge pull request #282 from CarterLi/msys2

Introduce Windows support
This commit is contained in:
Linus Dierheimer
2022-10-09 22:24:19 +02:00
committed by GitHub
109 changed files with 3781 additions and 1307 deletions
+99 -17
View File
@@ -15,8 +15,12 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Ll]inux.*")
set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel
elseif("${CMAKE_SYSTEM_NAME}" MATCHES ".*[Bb][Ss][Dd].*")
set(BSD TRUE CACHE BOOL "..." FORCE)
elseif(NOT APPLE AND NOT ANDROID)
message(FATAL_ERROR "Unsupported platform")
elseif(NOT APPLE AND NOT ANDROID AND NOT MSYS)
message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}")
endif()
if(MSYS)
enable_language(CXX)
endif()
#####################
@@ -26,7 +30,7 @@ endif()
include(CMakeDependentOption)
cmake_dependent_option(ENABLE_LIBPCI "Enable libpci" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD" OFF)
cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR BSD OR MSYS" OFF)
cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR BSD" OFF)
@@ -45,8 +49,8 @@ cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENAB
cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD" OFF)
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX" OFF)
cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR BSD OR MSYS" OFF)
cmake_dependent_option(ENABLE_LIBCJSON "Enable libcjson" ON "LINUX OR MSYS" OFF)
cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF)
option(BUILD_TESTS "Build tests" OFF) # Also create test executables
@@ -76,13 +80,21 @@ message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wconversion")
if(MSYS)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion -fno-exceptions -fno-rtti")
endif()
# Used for dlopen finding dylibs installed by homebrew
# `/opt/homebrew/lib` is not on in dlopen search path by default
if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,$ENV{HOMEBREW_PREFIX}/lib")
endif()
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined")
set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer")
if(NOT MSYS)
set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG} -rdynamic")
@@ -190,7 +202,6 @@ set(LIBFASTFETCH_SRC
src/common/caching.c
src/common/properties.c
src/common/font.c
src/common/processing.c
src/common/format.c
src/common/parsing.c
src/common/settings.c
@@ -201,15 +212,13 @@ set(LIBFASTFETCH_SRC
src/logo/image/image.c
src/logo/image/im7.c
src/logo/image/im6.c
src/detection/qt.c
src/detection/gtk.c
src/detection/terminalShell.c
src/detection/vulkan.c
src/detection/datetime.c
src/detection/title.c
src/detection/host/host.c
src/detection/os/os.c
src/detection/cpu/cpu.c
src/detection/cpuUsage/cpuUsage.c
src/detection/gpu/gpu.c
src/detection/memory/memory.c
src/detection/font/font.c
@@ -222,6 +231,8 @@ set(LIBFASTFETCH_SRC
src/modules/separator.c
src/modules/os.c
src/modules/host.c
src/modules/bios.c
src/modules/board.c
src/modules/kernel.c
src/modules/uptime.c
src/modules/processes.c
@@ -260,6 +271,18 @@ set(LIBFASTFETCH_SRC
src/modules/users.c
)
if(LINUX OR APPLE OR ANDROID OR BSD)
list(APPEND LIBFASTFETCH_SRC
src/detection/users/users_linux.c
src/common/processing_linux.c
src/detection/disk/disk.c
src/detection/terminalshell/terminalshell_linux.c
src/detection/packages/packages_linux.c
src/detection/kernel/kernel_linux.c
src/detection/localip/localip_linux.c
)
endif()
if(BSD OR APPLE)
list(APPEND LIBFASTFETCH_SRC
src/common/sysctl.c
@@ -277,14 +300,19 @@ if(LINUX OR ANDROID OR BSD)
list(APPEND LIBFASTFETCH_SRC
src/detection/cpuUsage/cpuUsage_linux.c
src/detection/disk/disk_linux.c
src/detection/poweradapter/poweradapter_linux.c
src/detection/temps/temps_linux.c
src/detection/opengl/opengl_linux.c
src/detection/processes/processes_linux.c
src/detection/poweradapter/poweradapter_nosupport.c
)
endif()
if(LINUX OR BSD)
list(APPEND LIBFASTFETCH_SRC
src/detection/host/host_linux.c
src/detection/bios/bios_linux.c
src/detection/board/board_linux.c
src/detection/os/os_linux.c
src/detection/gpu/gpu_linux.c
src/detection/battery/battery_linux.c
@@ -297,6 +325,42 @@ if(LINUX OR BSD)
src/detection/media/media_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/font/font_linux.c
src/detection/qt.c
src/detection/gtk.c
)
endif()
if(MSYS)
list(APPEND LIBFASTFETCH_SRC
src/common/processing_linux.c
src/detection/host/host_windows.cpp
src/detection/bios/bios_windows.cpp
src/detection/board/board_windows.cpp
src/detection/cpu/cpu_windows.cpp
src/detection/gpu/gpu_windows.cpp
src/detection/battery/battery_windows.cpp
src/detection/displayserver/displayserver_windows.c
src/detection/wmtheme/wmtheme_windows.c
src/detection/opengl/opengl_windows.c
src/detection/users/users_windows.cpp
src/detection/os/os_windows.cpp
src/detection/processes/processes_windows.cpp
src/detection/disk/disk_windows.c
src/detection/cpuUsage/cpuUsage_windows.c
src/detection/cpuUsage/cpuUsage_nowait_windows.cpp
src/detection/memory/memory_windows.cpp
src/detection/font/font_windows.cpp
src/detection/terminalshell/terminalshell_linux.c
src/detection/terminalshell/terminalshell_windows.cpp
src/detection/terminalfont/terminalfont_linux.c
src/detection/packages/packages_linux.c
src/detection/packages/packages_windows.c
src/detection/kernel/kernel_windows.cpp
src/detection/localip/localip_windows.c
src/util/windows/wmi.cpp
src/detection/poweradapter/poweradapter_nosupport.c
src/detection/media/media_nosupport.c
)
endif()
@@ -319,6 +383,11 @@ if(APPLE)
src/detection/wmtheme/wmtheme_apple.m
src/detection/temps/temps_apple.c
src/detection/font/font_apple.m
src/detection/opengl/opengl_apple.c
src/detection/processes/processes_apple.c
src/detection/bios/bios_nosupport.c
src/detection/board/board_nosupport.c
)
endif()
@@ -333,13 +402,16 @@ if(ANDROID)
list(APPEND LIBFASTFETCH_SRC
src/detection/host/host_android.c
src/detection/os/os_android.c
src/detection/gpu/gpu_android.c
src/detection/battery/battery_android.c
src/detection/displayserver/displayserver_android.c
src/detection/terminalfont/terminalfont_android.c
src/detection/media/media_android.c
src/detection/wmtheme/wmtheme_android.c
src/detection/font/font_android.c
src/detection/bios/bios_nosupport.c
src/detection/board/board_nosupport.c
src/detection/displayserver/displayserver_nosupport.c
src/detection/battery/battery_nosupport.c
src/detection/gpu/gpu_nosupport.c
src/detection/font/font_nosupport.c
src/detection/media/media_nosupport.c
src/detection/wmtheme/wmtheme_nosupport.c
)
endif()
@@ -417,6 +489,16 @@ if(APPLE)
PRIVATE "-framework Cocoa"
PRIVATE "-weak_framework MediaRemote -F /System/Library/PrivateFrameworks"
)
elseif(MSYS)
target_link_libraries(libfastfetch
PRIVATE "wbemuuid"
PRIVATE "ole32"
PRIVATE "oleaut32"
PRIVATE "dwmapi"
PRIVATE "opengl32"
PRIVATE "gdi32"
PRIVATE "iphlpapi"
)
endif()
target_include_directories(libfastfetch
+13 -7
View File
@@ -1,6 +1,6 @@
# Fastfetch
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, BSD and MacOS are supported.
Fastfetch is a [neofetch](https://github.com/dylanaraps/neofetch)-like tool for fetching system information and displaying them in a pretty way. It is written in pure c, with performance and customizability in mind. Currently Linux, Android, BSD, MacOS and Windows on [MSYS2](https://www.msys2.org/) are supported.
<img src="screenshots/example1.png" width="49%" align="left" />
<img src="https://upload.wikimedia.org/wikipedia/commons/2/24/Transparent_Square_Tiles_Texture.png" width="49%" height="16px" align="left" />
@@ -44,7 +44,7 @@ The following libraries are used if present at runtime:
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
* [`libsqlite3`](https://www.sqlite.org/index.html): Needed for pkg & rpm package count.
* [`librpm`](http://rpm.org/): Slower fallback for rpm package count. Needed on openSUSE.
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( WSL ).
* [`libcJSON`](https://github.com/DaveGamble/cJSON): Needed for Windows Terminal font ( Windows, WSL ).
* [`freetype`](https://www.freetype.org/): Needed for Termux font detection ( Android ).
## Support status
@@ -52,12 +52,12 @@ All categories not listed here should work without needing a specific implementa
##### Available Modules
```
Title, Separator, OS, Host, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
Title, Separator, OS, Host, Bios, Board, Kernel, Uptime, Processes, Packages, Shell, Resolution, DE, WM, WMTheme, Theme, Icons, Font, Cursor, Terminal, Terminal Font, CPU, CPUUsage, GPU, Memory, Swap, Disk, Battery, Power Adapter, Player, Media, Vulkan, OpenGL, OpenCL, LocalIP, PublicIP, DateTime, Date, Time, Locale, Colors, Break, Custom
```
##### Logos
```
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal, Debian, Devuan, Deepin, Endeavour, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Ubuntu, Void, Zorin
AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal, Debian, Devuan, Deepin, Endeavour, Fedora, FreeBSD, Garuda, Gentoo, KDE Neon, KISS, Kubuntu, LangitKetujuh, Linux, MacOS, Manjaro, Mint, MSYS2, NixOS, OpenSUSE, OpenSUSE Tumbleweed, OpenSUSE LEAP, Pop!_OS, RebornOS, RedstarOS, Rocky, Rosa, Slackware, Ubuntu, Void, Windows 11, Windows 8, Windows, Zorin
```
* Most of the logos have a small variant. Access it by appending _small to the logo name.
* Some logos have an old variant. Access it by appending _old to the logo name.
@@ -67,12 +67,12 @@ AlmaLinux, Alpine, Android, Arch, Arco, Artix, Bedrock, CachyOS, CentOS, Crystal
##### Package managers
```
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts
Pacman, dpkg, rpm, emerge, xbps, nix, Flatpak, Snap, apk, pkg, brew, MacPorts, scoop
```
##### WM themes
```
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS)
KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE), Quartz Compositor (macOS), DWM (Windows)
```
##### DE versions
@@ -82,7 +82,7 @@ KDE Plasma, Gnome, Cinnamon, Mate, XFCE4, LXQt
##### Terminal fonts
```
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal, Termux
Konsole, Gnome Terminal, Tilix, XFCE4 Terminal, Alacritty, LXTerminal, iTerm2, Apple Terminal, TTY, Windows Terminal, Termux, mintty
```
## Building
@@ -97,6 +97,12 @@ cmake --build . --target fastfetch --target flashfetch
If pkg-config fails to find the headers for a library listed in [dependencies](#dependencies), fastfetch will simply build without support for that specific feature. This means, it won't look for it at runtime and just act like it isn't available.
### Building on Windows
Currently [MSYS2](https://www.msys2.org/) is required to build fastfetch. Running fastfetch requires msys2 runtime library (`msys-2.0.dll`) but not full MSYS2 environment.
Full native Windows executable is planned.
## Packaging
### Repositories
+3
View File
@@ -99,7 +99,10 @@ static bool printCachedValue(FFinstance* instance, const char* moduleName, const
ffStrbufTrimRight(&content, '\0'); //Strbuf always appends a '\0' at the end. We want the last null byte to be at the position of the length
if(content.length == 0)
{
ffStrbufDestroy(&content);
return false;
}
uint8_t moduleCounter = 1;
+5 -1
View File
@@ -162,6 +162,8 @@ static void defaultConfig(FFinstance* instance)
initModuleArg(&instance->config.os);
initModuleArg(&instance->config.host);
initModuleArg(&instance->config.bios);
initModuleArg(&instance->config.board);
initModuleArg(&instance->config.kernel);
initModuleArg(&instance->config.uptime);
initModuleArg(&instance->config.processes);
@@ -257,7 +259,7 @@ void ffInitInstance(FFinstance* instance)
defaultConfig(instance);
}
#if !defined(__ANDROID__)
#if !defined(__ANDROID__) && !defined(_WIN32) && !defined(__MSYS__)
static void* connectDisplayServerThreadMain(void* instance)
{
@@ -416,6 +418,8 @@ static void destroyConfig(FFinstance* instance)
destroyModuleArg(&instance->config.os);
destroyModuleArg(&instance->config.host);
destroyModuleArg(&instance->config.bios);
destroyModuleArg(&instance->config.board);
destroyModuleArg(&instance->config.kernel);
destroyModuleArg(&instance->config.uptime);
destroyModuleArg(&instance->config.processes);
+2
View File
@@ -3,6 +3,8 @@
#ifndef FF_INCLUDED_common_io
#define FF_INCLUDED_common_io
#include "fastfetch.h"
#include <sys/types.h> //mode_t
bool ffWriteFDBuffer(int fd, const FFstrbuf* content);
+11
View File
@@ -19,6 +19,14 @@
static void* libraryLoad(const char* path, int maxVersion)
{
void* result = dlopen(path, FF_DLOPEN_FLAGS);
#if defined(_WIN32) || defined(__MSYS__)
// libX.dll.1 never exists on Windows, while libX-1.dll may exist
FF_UNUSED(maxVersion)
#else
if(result != NULL || maxVersion < 0)
return result;
@@ -40,6 +48,9 @@ static void* libraryLoad(const char* path, int maxVersion)
}
ffStrbufDestroy(&pathbuf);
#endif
return result;
}
+3 -1
View File
@@ -5,7 +5,9 @@
#include <dlfcn.h>
#ifdef __APPLE__
#if defined(_WIN32) || defined(__MSYS__)
#define FF_LIBRARY_EXTENSION ".dll"
#elif defined(__APPLE__)
#define FF_LIBRARY_EXTENSION ".dylib"
#else
#define FF_LIBRARY_EXTENSION ".so"
+69
View File
@@ -0,0 +1,69 @@
#include "fastfetch.h"
#include "common/processing.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
//We can't use this native version yet because we still use POSIX path ( eg /usr/bin/fish ) at a lot of places.
const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[])
{
SECURITY_ATTRIBUTES saAttr = {
.nLength = sizeof(SECURITY_ATTRIBUTES),
.lpSecurityDescriptor = NULL,
.bInheritHandle = TRUE,
};
HANDLE hChildStdoutRead, hChildStdoutWrite;
if (!CreatePipe(&hChildStdoutRead, &hChildStdoutWrite, &saAttr, 0))
return "CreatePipe() failed";
if (!SetHandleInformation(hChildStdoutRead, HANDLE_FLAG_INHERIT, 0))
return "SetHandleInformation(hChildStdoutRead) failed";
PROCESS_INFORMATION piProcInfo = {0};
STARTUPINFOA siStartInfo = {
.cb = sizeof(siStartInfo),
.dwFlags = STARTF_USESTDHANDLES,
.hStdOutput = hChildStdoutWrite,
};
FFstrbuf cmdline;
ffStrbufInit(&cmdline);
for(char* const* parg = argv; *parg; ++parg)
{
if(cmdline.length > 0)
ffStrbufAppendC(&cmdline, ' ');
ffStrbufAppendF(&cmdline, "\"%s\"", * parg);
}
BOOL success = CreateProcessA(
NULL, // application name
cmdline.chars, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
CloseHandle(hChildStdoutWrite);
if(!success)
{
CloseHandle(hChildStdoutRead);
return "CreateProcessA() failed";
}
char str[128];
DWORD nRead;
while(ReadFile(hChildStdoutRead, str, sizeof(str), &nRead, NULL) && nRead > 0)
{
ffStrbufAppendNS(buffer, nRead, str);
if(nRead < sizeof(str))
break;
}
CloseHandle(hChildStdoutRead);
return NULL;
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#ifndef FF_INCLUDED_common_time
#define FF_INCLUDED_common_time
#include <stdint.h>
#if defined(_WIN32) || defined(__MSYS__)
#include <synchapi.h>
#include <sysinfoapi.h>
#else
#include <sys/time.h>
#include <time.h>
#endif
static inline uint64_t ffTimeGetTick() //In msec
{
#if defined(_WIN32) || defined(__MSYS__)
return GetTickCount64();
#else
struct timeval timeNow;
gettimeofday(&timeNow, NULL);
return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000));
#endif
}
static inline void ffTimeSleep(uint32_t msec)
{
#if defined(_WIN32) || defined(__MSYS__)
SleepEx(msec, TRUE);
#else
nanosleep(&(struct timespec){ msec / 1000, (msec % 1000) * 1000000 }, NULL);
#endif
}
#endif
+2 -2
View File
@@ -5,7 +5,7 @@
# Whitespaces are trimmed at the beginning and the end.
# Empty lines or lines starting with # are ignored.
# This file was shipped with $"FASTFETCH_PROJECT_VERSION$".
# This file was shipped with $" FASTFETCH_PROJECT_VERSION $".
# Use fastfetch --print-config-user > ~/.config/fastfetch/config.conf to overwrite this file with the current defaults
# Below some often usefull options are listed. Uncomment and modify them so they take affect.
@@ -25,7 +25,7 @@
# Must be a list of module names, separated by colons.
# List available modules with "fastfetch --list-modules".
# Get the default structure with "fastfetch --print-structure".
#--structure $"FASTFETCH_DATATEXT_STRUCTURE$"
#--structure $" FASTFETCH_DATATEXT_STRUCTURE $"
# Multithreading option:
# Sets if fastfetch should use multiple threads to detect the values.
+1 -1
View File
@@ -90,7 +90,7 @@ Module specific options:
--title-fqdn <?value>: Sets if the title should use fully qualified domain name. Default is false.
--separator-string <str>: Set the string printed by the separator module
--os-file <path>: Set the path to the file containing OS informations
--disk-folders <folders>: A colon separated list of folder paths for the disk output. Default is "/:/home"
--disk-folders <folders>: A colon (semicolon on Windows) separated list of folder paths for the disk output. Default is "/:/home" ("C:\\;D:\\ ..." on Windows)
--disk-removable <?value>: Sets if removable volume should be printed. Default is false
--battery-dir <folder>: The directory where the battery folders are. Standard: /sys/class/power_supply/
--cpu-temp <?value>: Detect and display CPU temperature if supported. Default is false
@@ -1,10 +1,8 @@
#include "fastfetch.h"
#include "common/io.h"
#include "battery.h"
#include <dirent.h>
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) {
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
{
FF_UNUSED(instance, results)
return "Unimplemented";
return "Not supported on this platform";
}
+70
View File
@@ -0,0 +1,70 @@
extern "C" {
#include "battery.h"
}
#include "util/windows/wmi.hpp"
const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results)
{
FF_UNUSED(instance);
//https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-battery
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT SystemName, Name, Chemistry, EstimatedChargeRemaining, BatteryStatus FROM Win32_Battery", nullptr);
if(!pEnumerator)
return "Query WMI service failed";
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0)
{
BatteryResult* battery = (BatteryResult*)ffListAdd(results);
ffStrbufInit(&battery->manufacturer);
ffGetWmiObjString(pclsObj, L"SystemName", &battery->manufacturer);
ffStrbufInit(&battery->modelName);
ffGetWmiObjString(pclsObj, L"Name", &battery->modelName);
uint64_t chemistry;
ffGetWmiObjUnsigned(pclsObj, L"Chemistry", &chemistry);
switch(chemistry)
{
case 1: ffStrbufInitS(&battery->technology, "Other"); break;
case 2: ffStrbufInitS(&battery->technology, "Unknown"); break;
case 3: ffStrbufInitS(&battery->technology, "Lead Acid"); break;
case 4: ffStrbufInitS(&battery->technology, "Nickel Cadmium"); break;
case 5: ffStrbufInitS(&battery->technology, "Nickel Metal Hydride"); break;
case 6: ffStrbufInitS(&battery->technology, "Lithium-ion"); break;
case 7: ffStrbufInitS(&battery->technology, "Zinc air"); break;
case 8: ffStrbufInitS(&battery->technology, "Lithium Polymer"); break;
}
uint64_t capacity;
ffGetWmiObjUnsigned(pclsObj, L"EstimatedChargeRemaining", &capacity);
ffStrbufInitF(&battery->capacity, "%d", (int)capacity);
uint64_t batteryStatus;
ffGetWmiObjUnsigned(pclsObj, L"BatteryStatus", &batteryStatus);
switch(batteryStatus)
{
case 1: ffStrbufInitS(&battery->status, "Discharging"); break;
case 2: ffStrbufInitS(&battery->status, "AC Connected"); break;
case 3: ffStrbufInitS(&battery->status, "Fully Charged"); break;
case 4: ffStrbufInitS(&battery->status, "Low"); break;
case 5: ffStrbufInitS(&battery->status, "Critical"); break;
case 6: ffStrbufInitS(&battery->status, "Charging"); break;
case 7: ffStrbufInitS(&battery->status, "Charging and High"); break;
case 8: ffStrbufInitS(&battery->status, "Charging and Low"); break;
case 9: ffStrbufInitS(&battery->status, "Charging and Critical"); break;
case 10: ffStrbufInitS(&battery->status, "Undefined"); break;
case 11: ffStrbufInitS(&battery->status, "Partially Charged"); break;
}
battery->temperature = FF_BATTERY_TEMP_UNSET;
}
pclsObj->Release();
pEnumerator->Release();
return nullptr;
}
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#ifndef FF_INCLUDED_detection_bios_bios
#define FF_INCLUDED_detection_bios_bios
#include "fastfetch.h"
typedef struct FFBiosResult
{
FFstrbuf biosDate;
FFstrbuf biosRelease;
FFstrbuf biosVendor;
FFstrbuf biosVersion;
FFstrbuf error;
} FFBiosResult;
void ffDetectBios(FFBiosResult* bios);
#endif
+58
View File
@@ -0,0 +1,58 @@
#include "bios.h"
#include "common/io.h"
#include <stdlib.h>
static bool hostValueSet(FFstrbuf* value)
{
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(hostValueSet(buffer))
return;
ffReadFileBuffer(classPath, buffer);
if(hostValueSet(buffer))
return;
ffStrbufClear(buffer);
}
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->biosDate);
ffStrbufInit(&bios->biosRelease);
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->biosVersion);
}
+11
View File
@@ -0,0 +1,11 @@
#include "bios.h"
void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInitS(&bios->error, "Not supported on this platform");
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
}
+38
View File
@@ -0,0 +1,38 @@
extern "C" {
#include "bios.h"
}
#include "util/windows/wmi.hpp"
extern "C" void ffDetectBios(FFBiosResult* bios)
{
ffStrbufInit(&bios->error);
ffStrbufInit(&bios->biosDate);
ffStrbufInit(&bios->biosRelease);
ffStrbufInit(&bios->biosVendor);
ffStrbufInit(&bios->biosVersion);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, ReleaseDate, Version, Manufacturer FROM Win32_BIOS", &bios->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(uReturn == 0)
{
ffStrbufInitS(&bios->error, "No Wmi result returned");
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Name", &bios->biosRelease);
ffGetWmiObjString(pclsObj, L"ReleaseDate", &bios->biosDate);
ffGetWmiObjString(pclsObj, L"Version", &bios->biosVersion);
ffGetWmiObjString(pclsObj, L"Manufacturer", &bios->biosVendor);
pclsObj->Release();
pEnumerator->Release();
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifndef FF_INCLUDED_detection_board_board
#define FF_INCLUDED_detection_board_board
#include "fastfetch.h"
typedef struct FFBoardResult
{
FFstrbuf boardName;
FFstrbuf boardVendor;
FFstrbuf boardVersion;
FFstrbuf error;
} FFBoardResult;
void ffDetectBoard(FFBoardResult* result);
#endif
+55
View File
@@ -0,0 +1,55 @@
#include "board.h"
#include "common/io.h"
#include <stdlib.h>
static bool hostValueSet(FFstrbuf* value)
{
return
value->length > 0 &&
ffStrbufStartsWithIgnCaseS(value, "To be filled") != true &&
ffStrbufStartsWithIgnCaseS(value, "To be set") != true &&
ffStrbufStartsWithIgnCaseS(value, "OEM") != true &&
ffStrbufStartsWithIgnCaseS(value, "O.E.M.") != true &&
ffStrbufIgnCaseCompS(value, "None") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Product Version") != 0 &&
ffStrbufIgnCaseCompS(value, "System Name") != 0 &&
ffStrbufIgnCaseCompS(value, "System Version") != 0 &&
ffStrbufIgnCaseCompS(value, "Default string") != 0 &&
ffStrbufIgnCaseCompS(value, "Undefined") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Specified") != 0 &&
ffStrbufIgnCaseCompS(value, "Not Applicable") != 0 &&
ffStrbufIgnCaseCompS(value, "INVALID") != 0 &&
ffStrbufIgnCaseCompS(value, "Type1ProductConfigId") != 0 &&
ffStrbufIgnCaseCompS(value, "All Series") != 0
;
}
static void getHostValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer)
{
ffReadFileBuffer(devicesPath, buffer);
if(hostValueSet(buffer))
return;
ffReadFileBuffer(classPath, buffer);
if(hostValueSet(buffer))
return;
ffStrbufClear(buffer);
}
void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInit(&board->error);
ffStrbufInit(&board->boardName);
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->boardName);
ffStrbufInit(&board->boardVendor);
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->boardVendor);
ffStrbufInit(&board->boardVersion);
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->boardVersion);
}
+10
View File
@@ -0,0 +1,10 @@
#include "board.h"
void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInitS(&board->error, "Not supported on this platform");
ffStrbufInit(&board->boardName);
ffStrbufInit(&board->boardVendor);
ffStrbufInit(&board->boardVersion);
}
+36
View File
@@ -0,0 +1,36 @@
extern "C" {
#include "board.h"
}
#include "util/windows/wmi.hpp"
extern "C" void ffDetectBoard(FFBoardResult* board)
{
ffStrbufInit(&board->error);
ffStrbufInit(&board->boardName);
ffStrbufInit(&board->boardVendor);
ffStrbufInit(&board->boardVersion);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Product, Version, Manufacturer FROM Win32_BaseBoard", &board->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(uReturn == 0)
{
ffStrbufInitS(&board->error, "No Wmi result returned");
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Product", &board->boardName);
ffGetWmiObjString(pclsObj, L"Manufacturer", &board->boardVendor);
ffGetWmiObjString(pclsObj, L"Version", &board->boardVersion);
pclsObj->Release();
pEnumerator->Release();
}
+51
View File
@@ -0,0 +1,51 @@
extern "C" {
#include "cpu.h"
}
#include "util/windows/wmi.hpp"
extern "C"
void ffDetectCPUImpl(const FFinstance* instance, FFCPUResult* cpu, bool cached)
{
FF_UNUSED(instance);
cpu->temperature = FF_CPU_TEMP_UNSET;
if(cached)
return;
cpu->coresPhysical = cpu->coresLogical = cpu->coresOnline = 0;
ffStrbufInit(&cpu->name);
ffStrbufInit(&cpu->vendor);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, ThreadCount, CurrentClockSpeed, MaxClockSpeed FROM Win32_Processor WHERE ProcessorType = 3", nullptr);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Name", &cpu->name);
ffGetWmiObjString(pclsObj, L"Manufacturer", &cpu->vendor);
uint64_t value;
ffGetWmiObjUnsigned(pclsObj, L"NumberOfCores", &value);
cpu->coresPhysical = (uint16_t)value;
ffGetWmiObjUnsigned(pclsObj, L"NumberOfLogicalProcessors", &value);
cpu->coresLogical = (uint16_t)value;
ffGetWmiObjUnsigned(pclsObj, L"ThreadCount", &value);
cpu->coresOnline = (uint16_t)value;
ffGetWmiObjUnsigned(pclsObj, L"CurrentClockSpeed", &value); //There's no MinClockSpeed in Win32_Processor
cpu->frequencyMin = (double)value / 1000.0;
ffGetWmiObjUnsigned(pclsObj, L"MaxClockSpeed", &value);
cpu->frequencyMax = (double)value / 1000.0;
pclsObj->Release();
pEnumerator->Release();
}
+58
View File
@@ -0,0 +1,58 @@
#include "fastfetch.h"
#include "cpuUsage.h"
#if FF_DETECTION_CPUUSAGE_NOWAIT
const char* ffGetCpuUsageResultNoWait(double* result);
void ffPrepareCPUUsage() {}
const char* ffGetCpuUsageResult(double* result) {
return ffGetCpuUsageResultNoWait(result);
}
#else //FF_DETECTION_CPUUSAGE_NOWAIT
#include "common/time.h"
#include <stdint.h>
// We need to use uint64_t because sizeof(long) == 4 on Windows
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll);
static uint64_t inUseAll1, totalAll1, startTime;
void ffPrepareCPUUsage()
{
startTime = ffTimeGetTick();
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
}
const char* ffGetCpuUsageResult(double* result)
{
const char* error = NULL;
if(startTime == 0)
{
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
if(error)
return error;
ffTimeSleep(1000);
}
else
{
uint64_t duration = ffTimeGetTick() - startTime;
if(duration < 1000)
ffTimeSleep(1000 - (uint32_t) duration);
}
uint64_t inUseAll2, totalAll2;
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
if(error)
return error;
*result = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
return NULL;
}
#endif //FF_DETECTION_CPUUSAGE_NOWAIT
+6 -1
View File
@@ -3,6 +3,11 @@
#ifndef FF_INCLUDED_detection_cpu_cpuUsage
#define FF_INCLUDED_detection_cpu_cpuUsage
const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll);
#if defined(_WIN32) || defined(__MSYS__)
// Disabled by default because the result does need some time to generate
#define FF_DETECTION_CPUUSAGE_NOWAIT 0
#endif
const char* ffGetCpuUsageResult(double* result);
#endif
+3 -3
View File
@@ -4,7 +4,7 @@
#include <mach/processor_info.h>
#include <mach/mach_host.h>
const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll)
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
natural_t numCPUs = 0U;
processor_info_array_t cpuInfo;
@@ -21,8 +21,8 @@ const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll)
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_SYSTEM]
+ cpuInfo[CPU_STATE_MAX * i + CPU_STATE_NICE];
integer_t total = inUse + cpuInfo[CPU_STATE_MAX * i + CPU_STATE_IDLE];
*inUseAll += inUse;
*totalAll += total;
*inUseAll += (uint64_t)inUse;
*totalAll += (uint64_t)total;
}
return NULL;
}
+4 -3
View File
@@ -2,16 +2,17 @@
#include "cpuUsage.h"
#include <stdio.h>
#include <inttypes.h>
const char* ffGetCpuUsageInfo(long* inUseAll, long* totalAll)
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
long user, nice, system, idle, iowait, irq, softirq;
uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0;
FILE* procStat = fopen("/proc/stat", "r");
if(procStat == NULL)
return "fopen(\"""/proc/stat\", \"r\") == NULL";
if (fscanf(procStat, "cpu%ld%ld%ld%ld%ld%ld%ld", &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
if (fscanf(procStat, "cpu%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64, &user, &nice, &system, &idle, &iowait, &irq, &softirq) < 0)
{
fclose(procStat);
return "fscanf() failed";
@@ -0,0 +1,26 @@
extern "C" {
#include "cpuUsage.h"
}
#include "util/windows/wmi.hpp"
extern "C" const char* ffGetCpuUsageResultNoWait(double* result)
{
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT LoadPercentage FROM Win32_Processor", nullptr);
if(!pEnumerator)
return "Query WMI service failed";
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
pEnumerator->Release();
return "No WMI result returned";
}
ffGetWmiObjReal(pclsObj, L"LoadPercentage", result);
pclsObj->Release();
pEnumerator->Release();
return NULL;
}
+20
View File
@@ -0,0 +1,20 @@
#include "fastfetch.h"
#include "cpuUsage.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
static inline uint64_t fileTimeToUint64(const FILETIME* ft) {
return (((uint64_t)ft->dwHighDateTime) << 32) | ((uint64_t)ft->dwLowDateTime);
}
const char* ffGetCpuUsageInfo(uint64_t* inUseAll, uint64_t* totalAll)
{
FILETIME idleTime, kernelTime, userTime;
if(GetSystemTimes(&idleTime, &kernelTime, &userTime) == 0)
return "GetSystemTimes() failed";
*inUseAll = fileTimeToUint64(&userTime) + fileTimeToUint64(&kernelTime);
*totalAll = *inUseAll + fileTimeToUint64(&idleTime);
return NULL;
}
+56
View File
@@ -0,0 +1,56 @@
#include "fastfetch.h"
#include "disk.h"
#include <sys/statvfs.h>
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result)
{
ffStrbufInitS(&result->path, folderPath);
result->used = result->total = 0;
ffStrbufInit(&result->error);
struct statvfs newFs;
if(fs == NULL)
{
fs = &newFs;
int ret = statvfs(folderPath, fs);
if(ret != 0)
{
ffStrbufAppendF(&result->error, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
return;
}
}
result->total = fs->f_blocks * fs->f_frsize;
if(result->total == 0)
{
ffStrbufAppendF(&result->error, "statvfs for %s returned size 0", folderPath);
return;
}
result->used = result->total - (fs->f_bavail * fs->f_frsize);
result->files = (uint32_t) (fs->f_files - fs->f_ffree);
result->removable = false; //To be set at other place
}
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
{
ffStrbufTrim(&instance->config.diskFolders, ':');
if(instance->config.diskFolders.length == 0)
return false;
uint32_t startIndex = 0;
while(startIndex < instance->config.diskFolders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
instance->config.diskFolders.chars[colonIndex] = '\0';
ffDetectDiskWithStatvfs(instance->config.diskFolders.chars + startIndex, NULL, (FFDiskResult*)ffListAdd(folders));
startIndex = colonIndex + 1;
}
return true;
}
+11
View File
@@ -5,6 +5,17 @@
#include "fastfetch.h"
typedef struct FFDiskResult
{
FFstrbuf path;
uint64_t used;
uint64_t total;
uint32_t files;
bool removable;
FFstrbuf error;
} FFDiskResult;
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders);
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders);
#endif
+5 -1
View File
@@ -2,6 +2,8 @@
#import <Foundation/Foundation.h>
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
{
NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeNameKey, nil];
@@ -18,7 +20,9 @@ const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
if(removable.boolValue && !instance->config.diskRemovable)
continue;
ffStrbufInitS((FFstrbuf *)ffListAdd(folders), [url.relativePath cStringUsingEncoding:NSUTF8StringEncoding]);
FFDiskResult* folder = (FFDiskResult*)ffListAdd(folders);
ffDetectDiskWithStatvfs([url.relativePath cStringUsingEncoding:NSUTF8StringEncoding], NULL, folder);
folder->removable = removable.boolValue;
}
return NULL;
+4 -2
View File
@@ -2,6 +2,8 @@
#include <sys/statvfs.h>
void ffDetectDiskWithStatvfs(const char* folderPath, struct statvfs* fs, FFDiskResult* result);
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
{
FF_UNUSED(instance);
@@ -11,12 +13,12 @@ const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
if(rootRet != 0)
return "statvfs(\"/\") failed";
ffStrbufInitS((FFstrbuf *)ffListAdd(folders), FASTFETCH_TARGET_DIR_ROOT"/");
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_ROOT"/", &fsRoot, (FFDiskResult*)ffListAdd(folders));
struct statvfs fsHome;
int homeRet = statvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome);
if(homeRet == 0 && (fsRoot.f_fsid != fsHome.f_fsid))
ffStrbufInitS((FFstrbuf *)ffListAdd(folders), FASTFETCH_TARGET_DIR_HOME);
ffDetectDiskWithStatvfs(FASTFETCH_TARGET_DIR_HOME, &fsHome, (FFDiskResult*)ffListAdd(folders));
return NULL;
}
+66
View File
@@ -0,0 +1,66 @@
#include "disk.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
static void detectDrive(const char* folderPath, uint32_t pathLen, FFDiskResult* result)
{
ffStrbufInitNS(&result->path, pathLen, folderPath);
result->removable = false; //To be set at other place
result->files = 0; //Unsupported
//According to https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespaceexa
//GetDiskFreeSpaceExA does not have to specify the root directory on a disk. The function accepts any directory on a disk.
uint64_t freeBytes;
if(GetDiskFreeSpaceExA(folderPath, NULL, (PULARGE_INTEGER)&result->total, (PULARGE_INTEGER)&freeBytes)) {
result->used = result->total - freeBytes;
ffStrbufInit(&result->error);
}
else
ffStrbufInitS(&result->error, "GetDiskFreeSpaceExA() failed");
}
const char* ffDiskAutodetectFolders(FFinstance* instance, FFlist* folders)
{
FF_UNUSED(instance);
char buf[128]; // "C:\\\0D:\\\0"
uint32_t length = GetLogicalDriveStringsA(sizeof(buf) / sizeof(*buf), buf);
for(size_t i = 0; i < length;)
{
const char* drive = buf + i;
uint32_t driveLen = (uint32_t) strlen(drive);
i += driveLen + 1;
bool removable = GetDriveTypeA(drive) == DRIVE_REMOVABLE;
if(removable && !instance->config.diskRemovable)
continue;
FFDiskResult* folder = (FFDiskResult*)ffListAdd(folders);
detectDrive(drive, driveLen, folder);
folder->removable = removable;
}
return NULL;
}
bool ffDiskDetectDiskFolders(FFinstance* instance, FFlist* folders)
{
ffStrbufTrim(&instance->config.diskFolders, ';');
if(instance->config.diskFolders.length == 0)
return false;
uint32_t startIndex = 0;
while(startIndex < instance->config.diskFolders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ';');
instance->config.diskFolders.chars[colonIndex] = '\0';
detectDrive(instance->config.diskFolders.chars + startIndex, colonIndex - startIndex, (FFDiskResult*)ffListAdd(folders));
startIndex = colonIndex + 1;
}
return true;
}
@@ -0,0 +1,48 @@
#include "displayserver.h"
#include "detection/os/os.h"
#include <dwmapi.h>
#include <WinUser.h>
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds, const FFinstance* instance)
{
FF_UNUSED(instance);
BOOL enabled;
if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled == TRUE)
{
ffStrbufInitS(&ds->wmProcessName, "dwm.exe");
ffStrbufInitS(&ds->wmPrettyName, "Desktop Window Manager");
}
else
{
ffStrbufInitS(&ds->wmProcessName, "internal");
ffStrbufInitS(&ds->wmPrettyName, "internal");
}
ffStrbufInit(&ds->wmProtocolName);
ffStrbufInit(&ds->deProcessName);
ffStrbufInit(&ds->dePrettyName);
ffStrbufInit(&ds->deVersion);
ffListInit(&ds->resolutions, sizeof(FFResolutionResult));
DISPLAY_DEVICEW displayDevice = { .cb = sizeof(DISPLAY_DEVICEW) };
for(DWORD devNum = 0; EnumDisplayDevicesW(NULL, devNum, &displayDevice, 0) != 0; ++devNum)
{
if(!(displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE))
continue;
DEVMODEW devMode = { .dmSize = sizeof(DEVMODEW) };
if(EnumDisplaySettingsW(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode) == 0)
continue;
ffdsAppendResolution(ds, devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency);
}
//https://github.com/hykilpikonna/hyfetch/blob/master/neofetch#L2067
const FFOSResult* os = ffDetectOS(instance);
if(ffStrbufCompS(&os->version, "11") == 0 || ffStrbufCompS(&os->version, "10") == 0)
ffStrbufSetS(&ds->dePrettyName, "Fluent");
else if(ffStrbufCompS(&os->version, "8") == 0 || ffStrbufStartsWithS(&os->version, "8."))
ffStrbufSetS(&ds->dePrettyName, "Metro");
else
ffStrbufSetS(&ds->dePrettyName, "Aero");
}
+4 -3
View File
@@ -12,9 +12,10 @@ typedef struct FFFontResult
FFstrbuf error;
/**
* Linux / BSD: QT, GTK2, GTK3, GTK4
* MacOS: System, User, Monospace, Application
* Other: Unset, Unset, Unset, Unset
* Linux / BSD: QT, GTK2, GTK3, GTK4
* MacOS: System, User, Monospace, Application
* Windows: Desktop, Unset, Unset, Unset
* Other: Unset, Unset, Unset, Unset
*/
FFstrbuf fonts[FF_DETECT_FONT_NUM_FONTS];
} FFFontResult;
@@ -4,5 +4,5 @@
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
{
FF_UNUSED(instance);
ffStrbufAppendS(&result->error, "Not implemented");
ffStrbufAppendS(&result->error, "Not supported on this platform");
}
+44
View File
@@ -0,0 +1,44 @@
extern "C" {
#include "font.h"
#include "common/font.h"
}
#include "util/windows/wmi.hpp"
#include <wchar.h>
extern "C"
void ffDetectFontImpl(const FFinstance* instance, FFFontResult* result)
{
wchar_t query[256] = {};
swprintf(query, 256, L"SELECT IconTitleFaceName, IconTitleSize FROM Win32_Desktop WHERE Name LIKE '%%\\\\%s'", instance->state.passwd->pw_name);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(query, &result->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(uReturn == 0)
{
ffStrbufInitS(&result->error, "No WMI result returned");
pEnumerator->Release();
return;
}
FFstrbuf fontName;
ffStrbufInit(&fontName);
ffGetWmiObjString(pclsObj, L"IconTitleFaceName", &fontName);
uint64_t fontSize;
ffGetWmiObjUnsigned(pclsObj, L"IconTitleSize", &fontSize);
ffStrbufAppendF(&result->fonts[0], "%*s (%upt)", fontName.length, fontName.chars, (unsigned)fontSize);
ffStrbufDestroy(&fontName);
pclsObj->Release();
pEnumerator->Release();
}
@@ -3,5 +3,5 @@
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
{
FF_UNUSED(gpus, instance);
return "Unimplemented";
return "Not supported on this platform";
}
+44
View File
@@ -0,0 +1,44 @@
extern "C" {
#include "gpu.h"
}
#include "util/windows/wmi.hpp"
extern "C"
const char* ffDetectGPUImpl(FFlist* gpus, const FFinstance* instance)
{
FF_UNUSED(instance);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, AdapterCompatibility, DriverVersion FROM Win32_VideoController", nullptr);
if(!pEnumerator)
return "Query WMI service failed";
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0)
{
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
ffStrbufInit(&gpu->vendor);
ffGetWmiObjString(pclsObj, L"AdapterCompatibility", &gpu->vendor);
if(ffStrbufStartsWithS(&gpu->vendor, "Intel "))
{
//Intel returns "Intel Corporation", not sure about AMD
ffStrbufSetS(&gpu->vendor, "Intel");
}
ffStrbufInit(&gpu->name);
ffGetWmiObjString(pclsObj, L"Name", &gpu->name);
ffStrbufInit(&gpu->driver);
ffGetWmiObjString(pclsObj, L"DriverVersion", &gpu->driver);
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
}
pclsObj->Release();
pEnumerator->Release();
return nullptr;
}
+2 -7
View File
@@ -6,6 +6,7 @@
#include "fastfetch.h"
#define FF_HOST_PRODUCT_NAME_WSL "Windows Subsystem for Linux"
#define FF_HOST_PRODUCT_NAME_MSYS "Windows on MSYS"
typedef struct FFHostResult
{
@@ -13,17 +14,11 @@ typedef struct FFHostResult
FFstrbuf productName;
FFstrbuf productVersion;
FFstrbuf productSku;
FFstrbuf biosDate;
FFstrbuf biosRelease;
FFstrbuf biosVendor;
FFstrbuf biosVersion;
FFstrbuf boardName;
FFstrbuf boardVendor;
FFstrbuf boardVersion;
FFstrbuf chassisType;
FFstrbuf chassisVendor;
FFstrbuf chassisVersion;
FFstrbuf sysVendor;
FFstrbuf error;
} FFHostResult;
const FFHostResult* ffDetectHost();
+2 -7
View File
@@ -4,6 +4,8 @@
void ffDetectHostImpl(FFHostResult* host)
{
ffStrbufInit(&host->error);
//Family
ffStrbufInit(&host->productFamily);
@@ -32,13 +34,6 @@ void ffDetectHostImpl(FFHostResult* host)
ffStrbufInitA(&host->productVersion, 0);
ffStrbufInitA(&host->productSku, 0);
ffStrbufInitA(&host->biosDate, 0);
ffStrbufInitA(&host->biosRelease, 0);
ffStrbufInitA(&host->biosVendor, 0);
ffStrbufInitA(&host->biosVersion, 0);
ffStrbufInitA(&host->boardName, 0);
ffStrbufInitA(&host->boardVendor, 0);
ffStrbufInitA(&host->boardVersion, 0);
ffStrbufInitA(&host->chassisType, 0);
ffStrbufInitA(&host->chassisVendor, 0);
ffStrbufInitA(&host->chassisVersion, 0);
+4 -9
View File
@@ -112,19 +112,14 @@ static const char* getProductName(const FFstrbuf* hwModel)
void ffDetectHostImpl(FFHostResult* host)
{
ffStrbufInit(&host->error);
ffStrbufInit(&host->productName);
ffStrbufInit(&host->productFamily);
ffStrbufInit(&host->productVersion);
ffStrbufInit(&host->productSku);
ffStrbufInitA(&host->sysVendor, 0);
ffStrbufInitA(&host->productVersion, 0);
ffStrbufInitA(&host->productSku, 0);
ffStrbufInitA(&host->biosDate, 0);
ffStrbufInitA(&host->biosRelease, 0);
ffStrbufInitA(&host->biosVendor, 0);
ffStrbufInitA(&host->biosVersion, 0);
ffStrbufInitA(&host->boardName, 0);
ffStrbufInitA(&host->boardVendor, 0);
ffStrbufInitA(&host->boardVersion, 0);
ffStrbufInitA(&host->chassisType, 0);
ffStrbufInitA(&host->chassisVendor, 0);
ffStrbufInitA(&host->chassisVersion, 0);
+8 -27
View File
@@ -60,6 +60,8 @@ static void getHostProductName(FFstrbuf* name)
void ffDetectHostImpl(FFHostResult* host)
{
ffStrbufInit(&host->error);
ffStrbufInit(&host->productFamily);
getHostValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily);
@@ -72,27 +74,6 @@ void ffDetectHostImpl(FFHostResult* host)
ffStrbufInit(&host->productSku);
getHostValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku);
ffStrbufInit(&host->biosDate);
getHostValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &host->biosDate);
ffStrbufInit(&host->biosRelease);
getHostValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &host->biosRelease);
ffStrbufInit(&host->biosVendor);
getHostValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &host->biosVendor);
ffStrbufInit(&host->biosVersion);
getHostValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &host->biosVersion);
ffStrbufInit(&host->boardName);
getHostValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &host->boardName);
ffStrbufInit(&host->boardVendor);
getHostValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &host->boardVendor);
ffStrbufInit(&host->boardVersion);
getHostValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &host->boardVersion);
ffStrbufInit(&host->chassisType);
getHostValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &host->chassisType);
@@ -109,10 +90,10 @@ void ffDetectHostImpl(FFHostResult* host)
if(ffStrbufStartsWithS(&host->productName, "Standard PC"))
ffStrbufPrependS(&host->productName, "KVM/QEMU ");
//On WSL, the real host can't be detected. Instead use WSL as host.
if(host->productFamily.length == 0 && host->productName.length == 0 && (
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
)) ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
if(host->productFamily.length == 0 && host->productName.length == 0)
{
//On WSL, the real host can't be detected. Instead use WSL as host.
if(getenv("WSL_DISTRO") != NULL || getenv("WSL_INTEROP") != NULL)
ffStrbufAppendS(&host->productName, FF_HOST_PRODUCT_NAME_WSL);
}
}
+42
View File
@@ -0,0 +1,42 @@
extern "C" {
#include "host.h"
}
#include "util/windows/wmi.hpp"
extern "C" void ffDetectHostImpl(FFHostResult* host)
{
ffStrbufInit(&host->error);
ffStrbufInit(&host->productName);
ffStrbufInit(&host->productFamily);
ffStrbufInit(&host->productVersion);
ffStrbufInit(&host->productSku);
ffStrbufInit(&host->sysVendor);
ffStrbufInit(&host->chassisType);
ffStrbufInit(&host->chassisVendor);
ffStrbufInit(&host->chassisVersion);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Name, Version, SKUNumber, Vendor FROM Win32_ComputerSystemProduct", &host->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(uReturn == 0)
{
ffStrbufInitS(&host->error, "No Wmi result returned");
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Name", &host->productName);
ffGetWmiObjString(pclsObj, L"Version", &host->productVersion);
ffGetWmiObjString(pclsObj, L"SKUNumber", &host->productSku);
ffGetWmiObjString(pclsObj, L"Vendor", &host->sysVendor);
pclsObj->Release();
pEnumerator->Release();
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifndef FF_INCLUDED_detection_kernel_kernel
#define FF_INCLUDED_detection_kernel_kernel
#include "fastfetch.h"
typedef struct FFKernelResult
{
FFstrbuf sysname;
FFstrbuf release;
FFstrbuf version;
FFstrbuf error;
} FFKernelResult;
void ffDetectKernel(FFinstance* instance, FFKernelResult* result);
#endif
+9
View File
@@ -0,0 +1,9 @@
#include "kernel.h"
void ffDetectKernel(FFinstance* instance, FFKernelResult* result)
{
ffStrbufInit(&result->error);
ffStrbufInitS(&result->sysname, instance->state.utsname.sysname);
ffStrbufInitS(&result->release, instance->state.utsname.release);
ffStrbufInitS(&result->version, instance->state.utsname.version);
}
+34
View File
@@ -0,0 +1,34 @@
extern "C" {
#include "kernel.h"
}
#include "util/windows/wmi.hpp"
extern "C" void ffDetectKernel(FFinstance* instance, FFKernelResult* kernel)
{
FF_UNUSED(instance);
ffStrbufInit(&kernel->error);
ffStrbufInitS(&kernel->sysname, "Windows_NT");
ffStrbufInit(&kernel->release);
ffStrbufInit(&kernel->version);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Version FROM Win32_OperatingSystem", &kernel->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
ffStrbufInitS(&kernel->error, "No WMI result returned");
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Version", &kernel->release);
pclsObj->Release();
pEnumerator->Release();
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#ifndef FF_INCLUDED_detection_localip_localip
#define FF_INCLUDED_detection_localip_localip
#include "fastfetch.h"
typedef struct FFLocalIpResult
{
FFstrbuf name;
FFstrbuf addr;
bool ipv6;
} FFLocalIpResult;
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results);
#endif
+66
View File
@@ -0,0 +1,66 @@
#include "localip.h"
#include <string.h>
#include <ctype.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#ifdef __FreeBSD__
#include <sys/socket.h> // FreeBSD needs this for AF_INET
#endif
static void addNewIp(FFlist* list, const char* name, const char* addr, bool ipv6)
{
FFLocalIpResult* ip = (FFLocalIpResult*) ffListAdd(list);
ffStrbufInitS(&ip->name, name);
ffStrbufInitS(&ip->addr, addr);
ip->ipv6 = ipv6;
}
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
{
struct ifaddrs* ifAddrStruct = NULL;
if(getifaddrs(&ifAddrStruct) < 0)
return "getifaddrs(&ifAddrStruct) failed";
for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next)
{
if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING))
continue;
// loop back
if (strncmp(ifa->ifa_name, "lo", 2) == 0 && (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2])) && !instance->config.localIpShowLoop)
continue;
if (instance->config.localIpNamePrefix.length && strncmp(ifa->ifa_name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
continue;
if (ifa->ifa_addr->sa_family == AF_INET)
{
// IPv4
if (!instance->config.localIpShowIpV4)
continue;
struct sockaddr_in* ipv4 = (struct sockaddr_in*) ifa->ifa_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
addNewIp(results, ifa->ifa_name, addressBuffer, false);
}
else if (ifa->ifa_addr->sa_family == AF_INET6)
{
// IPv6
if (!instance->config.localIpShowIpV6)
continue;
struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)ifa->ifa_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
addNewIp(results, ifa->ifa_name, addressBuffer, true);
}
}
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
return NULL;
}
+89
View File
@@ -0,0 +1,89 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <wchar.h>
#include "localip.h"
static void addNewIp(FFlist* list, const wchar_t* name, const char* addr, bool ipv6)
{
FFLocalIpResult* ip = (FFLocalIpResult*) ffListAdd(list);
int len = (int)wcslen(name);
int size_needed = WideCharToMultiByte(CP_UTF8, 0, name, len, NULL, 0, NULL, NULL);
ffStrbufInitA(&ip->name, (uint32_t)size_needed + 1);
WideCharToMultiByte(CP_UTF8, 0, name, len, ip->name.chars, size_needed, NULL, NULL);
ip->name.length = (uint32_t)size_needed;
ip->name.chars[size_needed] = '\0';
ffStrbufInitS(&ip->addr, addr);
ip->ipv6 = ipv6;
}
const char* ffDetectLocalIps(const FFinstance* instance, FFlist* results)
{
IP_ADAPTER_ADDRESSES* adapter_addresses = NULL;
// Start with a 16 KB buffer and resize if needed -
// multiple attempts in case interfaces change while
// we are in the middle of querying them.
DWORD adapter_addresses_buffer_size = 16 * 1024;
for (int attempts = 0; attempts != 3; ++attempts)
{
adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size);
assert(adapter_addresses);
DWORD error = GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST |
GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_FRIENDLY_NAME,
NULL,
adapter_addresses,
&adapter_addresses_buffer_size);
if (error == ERROR_SUCCESS)
break;
else if (ERROR_BUFFER_OVERFLOW == error)
continue;
else
return "GetAdaptersAddresses() failed";
}
// Iterate through all of the adapters
for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next)
{
if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK && !instance->config.localIpShowLoop)
continue;
for (IP_ADAPTER_UNICAST_ADDRESS* ifa = adapter->FirstUnicastAddress; ifa; ifa = ifa->Next)
{
if (ifa->Address.lpSockaddr->sa_family == AF_INET)
{
// IPv4
if (!instance->config.localIpShowIpV4)
continue;
SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN);
addNewIp(results, adapter->FriendlyName, addressBuffer, false);
}
else if (ifa->Address.lpSockaddr->sa_family == AF_INET6)
{
// IPv6
if (!instance->config.localIpShowIpV6)
continue;
SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN);
addNewIp(results, adapter->FriendlyName, addressBuffer, false);
}
}
}
free(adapter_addresses);
return NULL;
}
@@ -3,5 +3,5 @@
void ffDetectMediaImpl(const FFinstance* instance, FFMediaResult* media)
{
FF_UNUSED(instance);
ffStrbufAppendS(&media->error, "Media not supported on Android");
ffStrbufAppendS(&media->error, "Not supported on this platform");
}
+67
View File
@@ -0,0 +1,67 @@
extern "C" {
#include "memory.h"
}
#include "util/windows/wmi.hpp"
void detectRam(FFMemoryStorage* ram)
{
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT TotalVisibleMemorySize, FreePhysicalMemory FROM Win32_OperatingSystem", &ram->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
ffStrbufInitS(&ram->error, "No WMI result returned");
pEnumerator->Release();
return;
}
//KB
ffGetWmiObjUnsigned(pclsObj, L"TotalVisibleMemorySize", &ram->bytesTotal);
uint64_t bytesFree;
ffGetWmiObjUnsigned(pclsObj, L"FreePhysicalMemory", &bytesFree);
ram->bytesUsed = ram->bytesTotal - bytesFree;
pclsObj->Release();
pEnumerator->Release();
ram->bytesTotal *= 1024;
ram->bytesUsed *= 1024;
}
void detectSwap(FFMemoryStorage* swap)
{
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT AllocatedBaseSize, CurrentUsage FROM Win32_PageFileUsage", &swap->error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
ffStrbufInitS(&swap->error, "No WMI result returned");
pEnumerator->Release();
return;
}
//MB
ffGetWmiObjUnsigned(pclsObj, L"AllocatedBaseSize", &swap->bytesTotal);
ffGetWmiObjUnsigned(pclsObj, L"CurrentUsage", &swap->bytesUsed);
pclsObj->Release();
pEnumerator->Release();
swap->bytesTotal *= 1024 * 1024;
swap->bytesUsed *= 1024 * 1024;
}
extern "C"
void ffDetectMemoryImpl(FFMemoryResult* memory)
{
detectRam(&memory->ram);
detectSwap(&memory->swap);
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifndef FF_INCLUDED_detection_opengl_opengl
#define FF_INCLUDED_detection_opengl_opengl
#include "fastfetch.h"
typedef struct FFOpenGLResult
{
FFstrbuf version;
FFstrbuf renderer;
FFstrbuf vendor;
FFstrbuf slv;
} FFOpenGLResult;
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result);
#endif
+56
View File
@@ -0,0 +1,56 @@
#include "fastfetch.h"
#include "opengl.h"
#define GL_SILENCE_DEPRECATION
#include <OpenGL/gl.h>
#include <OpenGL/OpenGL.h> // This brings in CGL, not GL
static const char* glHandleResult(FFOpenGLResult* result)
{
ffStrbufAppendS(&result->version, (const char*) glGetString(GL_VERSION));
ffStrbufAppendS(&result->renderer, (const char*) glGetString(GL_RENDERER));
ffStrbufAppendS(&result->vendor, (const char*) glGetString(GL_VENDOR));
ffStrbufAppendS(&result->slv, (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
return NULL;
}
static const char* cglHandleContext(FFOpenGLResult* result, CGLContextObj context)
{
if(CGLSetCurrentContext(context) != kCGLNoError)
return "CGLSetCurrentContext() failed";
return glHandleResult(result);
}
static const char* cglHandlePixelFormat(FFOpenGLResult* result, CGLPixelFormatObj pixelFormat)
{
CGLContextObj context;
if(CGLCreateContext(pixelFormat, NULL, &context) != kCGLNoError)
return "CGLCreateContext() failed";
const char* error = cglHandleContext(result, context);
CGLDestroyContext(context);
return error;
}
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result)
{
FF_UNUSED(instance);
CGLPixelFormatObj pixelFormat;
CGLPixelFormatAttribute attrs[] = {
kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
kCGLPFAAccelerated,
0
};
GLint num;
if (CGLChoosePixelFormat(attrs, &pixelFormat, &num) != kCGLNoError)
return "CGLChoosePixelFormat() failed";
const char* error = cglHandlePixelFormat(result, pixelFormat);
CGLDestroyPixelFormat(pixelFormat);
return error;
}
+369
View File
@@ -0,0 +1,369 @@
#include "fastfetch.h"
#include "opengl.h"
#include <string.h>
#if defined(FF_HAVE_EGL) || defined(FF_HAVE_GLX) || defined(FF_HAVE_OSMESA)
#define FF_HAVE_GL 1
#include "common/library.h"
#include <GL/gl.h>
#define FF_OPENGL_BUFFER_WIDTH 1
#define FF_OPENGL_BUFFER_HEIGHT 1
typedef struct GLData
{
FF_LIBRARY_SYMBOL(glGetString)
} GLData;
static const char* glHandleResult(FFOpenGLResult* result, const GLData* data)
{
ffStrbufAppendS(&result->version, (const char*) data->ffglGetString(GL_VERSION));
ffStrbufAppendS(&result->renderer, (const char*) data->ffglGetString(GL_RENDERER));
ffStrbufAppendS(&result->vendor, (const char*) data->ffglGetString(GL_VENDOR));
ffStrbufAppendS(&result->slv, (const char*) data->ffglGetString(GL_SHADING_LANGUAGE_VERSION));
return NULL;
}
#endif // FF_HAVE_GL
#ifdef FF_HAVE_EGL
#include <EGL/egl.h>
typedef struct EGLData
{
GLData glData;
FF_LIBRARY_SYMBOL(eglGetProcAddress)
FF_LIBRARY_SYMBOL(eglGetDisplay)
FF_LIBRARY_SYMBOL(eglInitialize)
FF_LIBRARY_SYMBOL(eglBindAPI)
FF_LIBRARY_SYMBOL(eglGetConfigs)
FF_LIBRARY_SYMBOL(eglCreatePbufferSurface)
FF_LIBRARY_SYMBOL(eglCreateContext)
FF_LIBRARY_SYMBOL(eglMakeCurrent)
FF_LIBRARY_SYMBOL(eglDestroyContext)
FF_LIBRARY_SYMBOL(eglDestroySurface)
FF_LIBRARY_SYMBOL(eglTerminate)
EGLDisplay display;
EGLConfig config;
EGLSurface surface;
EGLContext context;
} EGLData;
static const char* eglHandleContext(FFOpenGLResult* result, EGLData* data)
{
if(data->ffeglMakeCurrent(data->display, data->surface, data->surface, data->context) != EGL_TRUE)
return "eglMakeCurrent returned EGL_FALSE";
return glHandleResult(result, &data->glData);
}
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data)
{
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
if(data->context == EGL_NO_CONTEXT)
return "eglCreateContext returned EGL_NO_CONTEXT";
const char* error = eglHandleContext(result, data);
data->ffeglDestroyContext(data->display, data->context);
return error;
}
static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
{
if(data->ffeglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
return "eglBindAPI returned EGL_FALSE";
EGLint eglConfigCount;
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
if(eglConfigCount == 0)
return "eglGetConfigs returned 0 configs";
data->surface = data->ffeglCreatePbufferSurface(data->display, data->config, (EGLint[]){
EGL_WIDTH, FF_OPENGL_BUFFER_WIDTH,
EGL_HEIGHT, FF_OPENGL_BUFFER_HEIGHT,
EGL_NONE
});
if(data->surface == EGL_NO_SURFACE)
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
const char* error = eglHandleSurface(result, data);
data->ffeglDestroySurface(data->display, data->surface);
return error;
}
static const char* eglHandleData(FFOpenGLResult* result, EGLData* data)
{
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffeglGetProcAddress("glGetString");
if(!data->glData.ffglGetString)
return "eglGetProcAddress(glGetString) returned NULL";
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
if(data->display == EGL_NO_DISPLAY)
return "eglGetDisplay returned EGL_NO_DISPLAY";
EGLint major, minor;
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
return "eglInitialize returned EGL_FALSE";
const char* error = eglHandleDisplay(result, data);
data->ffeglTerminate(data->display);
return error;
}
static const char* eglPrint(FFinstance* instance, FFOpenGLResult* result)
{
EGLData eglData;
FF_LIBRARY_LOAD(egl, &instance->config.libEGL, "dlopen egl failed", "libEGL.so", 1);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetProcAddress);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetDisplay);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglInitialize);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglBindAPI);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglGetConfigs);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreatePbufferSurface);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglCreateContext);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglMakeCurrent);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroyContext);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
const char* error = eglHandleData(result, &eglData);
dlclose(egl);
return error;
}
#endif //FF_HAVE_EGL
#ifdef FF_HAVE_GLX
#include <GL/glx.h>
typedef struct GLXData
{
GLData glData;
FF_LIBRARY_SYMBOL(glXGetProcAddress)
FF_LIBRARY_SYMBOL(XOpenDisplay)
FF_LIBRARY_SYMBOL(glXChooseVisual)
FF_LIBRARY_SYMBOL(XCreatePixmap);
FF_LIBRARY_SYMBOL(glXCreateGLXPixmap)
FF_LIBRARY_SYMBOL(glXCreateContext)
FF_LIBRARY_SYMBOL(glXMakeCurrent)
FF_LIBRARY_SYMBOL(glXDestroyContext)
FF_LIBRARY_SYMBOL(glXDestroyGLXPixmap)
FF_LIBRARY_SYMBOL(XFreePixmap)
FF_LIBRARY_SYMBOL(XCloseDisplay)
Display* display;
XVisualInfo* visualInfo;
Pixmap pixmap;
GLXPixmap glxPixmap;
GLXContext context;
} GLXData;
static const char* glxHandleContext(FFOpenGLResult* result, GLXData* data)
{
if(data->ffglXMakeCurrent(data->display, data->glxPixmap, data->context) != True)
return "glXMakeCurrent returned False";
return glHandleResult(result, &data->glData);
}
static const char* glxHandleGLXPixmap(FFOpenGLResult* result, GLXData* data)
{
data->context = data->ffglXCreateContext(data->display, data->visualInfo, NULL, True);
if(data->context == NULL)
return "glXCreateContext returned NULL";
const char* error = glxHandleContext(result, data);
data->ffglXDestroyContext(data->display, data->context);
return error;
}
static const char* glxHandlePixmap(FFOpenGLResult* result, GLXData* data)
{
data->glxPixmap = data->ffglXCreateGLXPixmap(data->display, data->visualInfo, data->pixmap);
if(data->glxPixmap == None)
return "glXCreateGLXPixmap returned None";
const char* error = glxHandleGLXPixmap(result, data);
data->ffglXDestroyGLXPixmap(data->display, data->glxPixmap);
return error;
}
static const char* glxHandleVisualInfo(FFOpenGLResult* result, GLXData* data)
{
data->pixmap = data->ffXCreatePixmap(data->display, DefaultRootWindow(data->display), FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT, (unsigned int) data->visualInfo->depth);
if(data->pixmap == None)
return "XCreatePixmap returned None";
const char* error = glxHandlePixmap(result, data);
data->ffXFreePixmap(data->display, data->pixmap);
return error;
}
static const char* glxHandleDisplay(FFOpenGLResult* result, GLXData* data)
{
data->visualInfo = data->ffglXChooseVisual(data->display, DefaultScreen(data->display), (int[]){None});
if(data->visualInfo == NULL)
return "glXChooseVisual returned NULL";
return glxHandleVisualInfo(result, data);
}
static const char* glxHandleData(FFOpenGLResult* result, GLXData* data)
{
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) data->ffglXGetProcAddress((const GLubyte*) "glGetString");
if(data->glData.ffglGetString == NULL)
return "glXGetProcAddress(glGetString) returned NULL";
data->display = data->ffXOpenDisplay(NULL);
if(data->display == NULL)
return "XOpenDisplay returned NULL";
const char* error = glxHandleDisplay(result, data);
data->ffXCloseDisplay(data->display);
return error;
}
static const char* glxPrint(FFinstance* instance, FFOpenGLResult* result)
{
GLXData data;
FF_LIBRARY_LOAD(glx, &instance->config.libGLX, "dlopen glx failed", "libGLX.so", 1);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXChooseVisual);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCreatePixmap);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXCreateGLXPixmap);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXCreateContext);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXMakeCurrent);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXDestroyContext);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXDestroyGLXPixmap);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XFreePixmap);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XCloseDisplay);
const char* error = glxHandleData(result, &data);
dlclose(glx);
return error;
}
#endif //FF_HAVE_GLX
#ifdef FF_HAVE_OSMESA
#include <GL/osmesa.h>
typedef struct OSMesaData
{
GLData glData;
FF_LIBRARY_SYMBOL(OSMesaGetProcAddress)
FF_LIBRARY_SYMBOL(OSMesaCreateContext)
FF_LIBRARY_SYMBOL(OSMesaMakeCurrent)
FF_LIBRARY_SYMBOL(OSMesaDestroyContext)
OSMesaContext context;
} OSMesaData;
static const char* osMesaHandleContext(FFOpenGLResult* result, OSMesaData* data)
{
unsigned char buffer[FF_OPENGL_BUFFER_WIDTH * FF_OPENGL_BUFFER_HEIGHT * sizeof(uint32_t)]; // 4 bytes per pixel (RGBA)
if(data->ffOSMesaMakeCurrent(data->context, buffer, GL_UNSIGNED_BYTE, FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT) != GL_TRUE)
return "OSMesaMakeCurrent returned GL_FALSE";
return glHandleResult(result, &data->glData);
}
static const char* osMesaHandleData(FFOpenGLResult* result, OSMesaData* data)
{
//The case to void* is required here, because OSMESAproc can't be cast to (__typeof__(data->glData.ffglGetString)) without a warning, even though it is the actual type.
data->glData.ffglGetString = (__typeof__(data->glData.ffglGetString)) (void*) data->ffOSMesaGetProcAddress("glGetString");
if(data->glData.ffglGetString == NULL)
return "OSMesaGetProcAddress(glGetString) returned NULL";
data->context = data->ffOSMesaCreateContext(OSMESA_RGBA, NULL);
if(data->context == NULL)
return "OSMesaCreateContext returned NULL";
const char* error = osMesaHandleContext(result, data);
data->ffOSMesaDestroyContext(data->context);
return error;
}
static const char* osMesaPrint(FFinstance* instance, FFOpenGLResult* result)
{
OSMesaData data;
FF_LIBRARY_LOAD(osmesa, &instance->config.libOSMesa, "dlopen osmesa failed", "libOSMesa.so", 8);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaGetProcAddress);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaCreateContext);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaMakeCurrent);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(osmesa, data, OSMesaDestroyContext);
const char* error = osMesaHandleData(result, &data);
dlclose(osmesa);
return error;
}
#endif //FF_HAVE_OSMESA
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result)
{
#if FF_HAVE_GL
if(instance->config.glType == FF_GL_TYPE_GLX)
{
#ifdef FF_HAVE_GLX
return glxPrint(instance, result);
#else
return "fastfetch was compiled without glx support";
#endif
}
if(instance->config.glType == FF_GL_TYPE_EGL)
{
#ifdef FF_HAVE_EGL
return eglPrint(instance, result);
#else
return "fastfetch was compiled without egl support";
#endif
}
if(instance->config.glType == FF_GL_TYPE_OSMESA)
{
#ifdef FF_HAVE_OSMESA
return osMesaPrint(instance, result);
#else
return "fastfetch was compiled without osmesa support";
#endif
}
const char* error = ""; // not NULL dummy value
#ifdef FF_HAVE_EGL
error = eglPrint(instance, result);
#endif
#ifdef FF_HAVE_GLX
if(error != NULL)
error = glxPrint(instance, result);
#endif
//We don't use osmesa in auto mode here, because it is a software implementation,
//that doesn't reflect the opengl supported by the hardware
return error;
#else
FF_UNUSED(instance, result);
return "Fastfetch was built without gl support.";
#endif //FF_HAVE_GL
}
+108
View File
@@ -0,0 +1,108 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "opengl.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#include <GL/gl.h>
#ifndef GL_SHADING_LANGUAGE_VERSION // For WGL
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#endif
static const char* glHandleResult(FFOpenGLResult* result)
{
ffStrbufAppendS(&result->version, (const char*) glGetString(GL_VERSION));
ffStrbufAppendS(&result->renderer, (const char*) glGetString(GL_RENDERER));
ffStrbufAppendS(&result->vendor, (const char*) glGetString(GL_VENDOR));
ffStrbufAppendS(&result->slv, (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
return NULL;
}
const char* wglHandleContext(FFOpenGLResult* result, HDC hdc, HGLRC context)
{
if(wglMakeCurrent(hdc, context) == FALSE)
return "wglMakeCurrent() failed";
return glHandleResult(result);
}
const char* wglHandlePixelFormat(FFOpenGLResult* result, HWND hWnd)
{
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
32, // Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24, // Number of bits for the depthbuffer
8, // Number of bits for the stencilbuffer
0, // Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};
HDC hdc = GetDC(hWnd);
if(SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd) == FALSE)
return "SetPixelFormat() failed";
HGLRC context = wglCreateContext(hdc);
if(context == NULL)
return "wglCreateContext() failed";
const char* error = wglHandleContext(result, hdc, context);
wglDeleteContext(context);
return error;
}
typedef struct WGLData
{
FFOpenGLResult* result;
const char* error;
} WGLData;
LRESULT CALLBACK wglHandleWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE: {
WGLData* wglData = (WGLData*)((CREATESTRUCT*)lParam)->lpCreateParams;
wglData->error = wglHandlePixelFormat(wglData->result, hWnd);
PostQuitMessage(0);
return 0;
}
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
}
const char* ffDetectOpenGL(FFinstance* instance, FFOpenGLResult* result)
{
FF_UNUSED(instance);
MSG msg = {0};
WNDCLASSW wc = {
.lpfnWndProc = wglHandleWndProc,
.hInstance = NULL,
.hbrBackground = (HBRUSH)COLOR_BACKGROUND,
.lpszClassName = L"ogl_version_check",
.style = CS_OWNDC,
};
if(!RegisterClassW(&wc))
return "RegisterClassW() failed";
WGLData data = { .result = result };
HWND hWnd = CreateWindowW(wc.lpszClassName, L"ogl_version_check", 0, 0, 0, 1, 1, NULL, NULL, NULL, &data);
while(GetMessageW(&msg, hWnd, 0, 0) > 0)
DispatchMessage(&msg);
return data.error;
}
+70
View File
@@ -0,0 +1,70 @@
extern "C" {
#include "os.h"
}
#include "util/windows/wmi.hpp"
extern "C"
void ffDetectOSImpl(FFOSResult* os, const FFinstance* instance)
{
ffStrbufInit(&os->name);
ffStrbufInit(&os->prettyName);
ffStrbufInit(&os->id);
ffStrbufInit(&os->idLike);
ffStrbufInit(&os->variant);
ffStrbufInit(&os->variantID);
ffStrbufInit(&os->version);
ffStrbufInit(&os->versionID);
ffStrbufInit(&os->codename);
ffStrbufInit(&os->buildID);
ffStrbufInit(&os->systemName);
ffStrbufInit(&os->architecture);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Caption, Version, BuildNumber, OSArchitecture FROM Win32_OperatingSystem", nullptr);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
pEnumerator->Release();
return;
}
ffGetWmiObjString(pclsObj, L"Caption", &os->variant); // Microsoft Windows 11 家庭中文版
if(ffStrbufStartsWithS(&os->variant, "Microsoft Windows "))
{
ffStrbufAppendS(&os->name, "Microsoft Windows");
ffStrbufAppendS(&os->prettyName, "Windows");
ffStrbufSubstrAfter(&os->variant, strlen("Microsoft Windows ") - 1); // 11 家庭中文版
uint32_t index = ffStrbufFirstIndexC(&os->variant, ' ');
ffStrbufAppendNS(&os->version, index, os->variant.chars);
ffStrbufSubstrAfter(&os->variant, index);
}
else
{
// Unknown Windows name, please report this
ffStrbufAppend(&os->name, &os->variant);
ffStrbufClear(&os->variant);
}
if(getenv("MSYSTEM"))
ffStrbufAppendS(&os->id, "MSYS2");
else
ffStrbufAppendF(&os->id, "Windows %*s", os->version.length, os->version.chars);
ffGetWmiObjString(pclsObj, L"BuildNumber", &os->buildID);
ffGetWmiObjString(pclsObj, L"OSArchitecture", &os->architecture);
#ifdef __MSYS__
ffStrbufSetS(&os->systemName, instance->state.utsname.sysname);
#else
ffStrbufSetS(&os->systemName, "Windows");
#endif
pclsObj->Release();
pEnumerator->Release();
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#ifndef FF_INCLUDED_detection_packages_packages
#define FF_INCLUDED_detection_packages_packages
#include "fastfetch.h"
typedef struct FFPackageCounts
{
uint32_t pacman;
uint32_t dpkg;
uint32_t rpm;
uint32_t emerge;
uint32_t xbps;
uint32_t nixSystem;
uint32_t nixDefault;
uint32_t apk;
uint32_t pkg;
uint32_t flatpak;
uint32_t snap;
uint32_t brew;
uint32_t port;
uint32_t scoop;
FFstrbuf pacmanBranch;
uint32_t nixUser;
} FFPackageCounts;
void ffDetectPackages(FFinstance* instance, FFPackageCounts* counts);
#endif
+448
View File
@@ -0,0 +1,448 @@
#include "common/io.h"
#include "common/properties.h"
#include "common/settings.h"
#include "common/processing.h"
#include "common/parsing.h"
#include "detection/os/os.h"
#include "packages.h"
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
static uint32_t getNumElements(const char* dirname, unsigned char type)
{
DIR* dirp = opendir(dirname);
if(dirp == NULL)
return 0;
uint32_t num_elements = 0;
struct dirent *entry;
while((entry = readdir(dirp)) != NULL) {
if(entry->d_type == type)
++num_elements;
}
if(type == DT_DIR)
num_elements -= 2; // accounting for . and ..
closedir(dirp);
return num_elements;
}
#ifndef __APPLE__
static uint32_t getNumStrings(const char* filename, const char* needle)
{
FILE* file = fopen(filename, "r");
if(file == NULL)
return 0;
uint32_t count = 0;
char* line = NULL;
size_t len = 0;
while(getline(&line, &len, file) != EOF)
{
if(strstr(line, needle) != NULL)
++count;
}
if(line != NULL)
free(line);
fclose(file);
return count;
}
#ifndef __ANDROID__
static uint32_t countFilesRecursive(FFstrbuf* baseDirPath, const char* filename)
{
uint32_t baseDirPathLength = baseDirPath->length;
ffStrbufAppendC(baseDirPath, '/');
ffStrbufAppendS(baseDirPath, filename);
bool exists = ffFileExists(baseDirPath->chars, S_IFREG);
ffStrbufSubstrBefore(baseDirPath, baseDirPathLength);
if(exists)
return 1;
DIR* dirp = opendir(baseDirPath->chars);
if(dirp == NULL)
return 0;
ffStrbufAppendC(baseDirPath, '/');
baseDirPathLength = baseDirPath->length;
uint32_t sum = 0;
struct dirent *entry;
while((entry = readdir(dirp)) != NULL) {
// According to the PMS, neither category nor package name can begin with '.', so no need to check for . or .. specifically
if(entry->d_type != DT_DIR || entry->d_name[0] == '.')
continue;
ffStrbufAppendS(baseDirPath, entry->d_name);
sum += countFilesRecursive(baseDirPath, filename);
ffStrbufSubstrBefore(baseDirPath, baseDirPathLength);
}
closedir(dirp);
return sum;
}
static uint32_t getNixPackages(char* path)
{
//Nix detection is kinda slow, so we only do it if the dir exists
if(!ffFileExists(path, S_IFDIR))
return 0;
FFstrbuf output;
ffStrbufInitA(&output, 128);
//https://github.com/LinusDierheimer/fastfetch/issues/195#issuecomment-1191748222
FFstrbuf command;
ffStrbufInitA(&command, 255);
ffStrbufAppendS(&command, "for x in $(nix-store --query --requisites ");
ffStrbufAppendS(&command, path);
ffStrbufAppendS(&command, "); do if [ -d $x ]; then echo $x ; fi ; done | cut -d- -f2- | egrep '([0-9]{1,}\\.)+[0-9]{1,}' | egrep -v '\\-doc$|\\-man$|\\-info$|\\-dev$|\\-bin$|^nixos-system-nixos-' | uniq");
ffProcessAppendStdOut(&output, (char* const[]) {
"sh",
"-c",
command.chars,
NULL
});
//Each package is a new line in the output. If at least one line is found, add 1 for the last line.
uint32_t result = ffStrbufCountC(&output, '\n');
if(result > 0)
result++;
ffStrbufDestroy(&output);
return result;
}
static uint32_t getXBPS(FFstrbuf* baseDir)
{
DIR* dir = opendir(baseDir->chars);
if(dir == NULL)
return 0;
uint32_t result = 0;
struct dirent *entry;
while((entry = readdir(dir)) != NULL)
{
if(entry->d_type != DT_REG || strncasecmp(entry->d_name, "pkgdb-", 6) != 0)
continue;
ffStrbufAppendC(baseDir, '/');
ffStrbufAppendS(baseDir, entry->d_name);
result = getNumStrings(baseDir->chars, "<string>installed</string>");
break;
}
closedir(dir);
return result;
}
#endif // !__ANDROID__
#else // !__APPLE__
static uint32_t countBrewPackages(FFstrbuf* baseDir)
{
uint32_t result = 0;
uint32_t baseDirLength = baseDir->length;
ffStrbufAppendS(baseDir, "/Caskroom");
result += getNumElements(baseDir->chars, DT_DIR);
ffStrbufSubstrBefore(baseDir, baseDirLength);
ffStrbufAppendS(baseDir, "/Cellar");
result += getNumElements(baseDir->chars, DT_DIR);
ffStrbufSubstrBefore(baseDir, baseDirLength);
return result;
}
static uint32_t getBrewPackages(FFstrbuf* baseDir)
{
uint32_t result = 0;
uint32_t baseDirLength = baseDir->length;
const char* prefix = getenv("HOMEBREW_PREFIX");
bool prefixSet = ffStrSet(prefix);
if(prefixSet)
{
ffStrbufAppendS(baseDir, prefix);
result += countBrewPackages(baseDir);
ffStrbufSubstrBefore(baseDir, baseDirLength);
}
ffStrbufAppendS(baseDir, "/opt/homebrew");
if(!prefixSet || strcasecmp(baseDir->chars, prefix) != 0)
result += countBrewPackages(baseDir);
ffStrbufSubstrBefore(baseDir, baseDirLength);
ffStrbufAppendS(baseDir, "/usr/local");
if(!prefixSet || strcasecmp(baseDir->chars, prefix) != 0)
result += countBrewPackages(baseDir);
ffStrbufSubstrBefore(baseDir, baseDirLength);
return result;
}
static uint32_t countMacPortsPackages(FFstrbuf* baseDir)
{
uint32_t result = 0;
uint32_t baseDirLength = baseDir->length;
ffStrbufAppendS(baseDir, "/var/macports/software");
result += getNumElements(baseDir->chars, DT_DIR);
ffStrbufSubstrBefore(baseDir, baseDirLength);
return result;
}
static uint32_t getMacPortsPackages(FFstrbuf* baseDir)
{
uint32_t result = 0;
uint32_t baseDirLength = baseDir->length;
const char* prefix = getenv("MACPORTS_PREFIX");
bool prefixSet = ffStrSet(prefix);
if(prefixSet)
{
ffStrbufAppendS(baseDir, prefix);
result += countMacPortsPackages(baseDir);
ffStrbufSubstrBefore(baseDir, baseDirLength);
}
ffStrbufAppendS(baseDir, "/opt/local");
if(!prefixSet || strcasecmp(baseDir->chars, prefix) != 0)
result += countMacPortsPackages(baseDir);
ffStrbufSubstrBefore(baseDir, baseDirLength);
return result;
}
#endif // __APPLE__
#ifdef FF_HAVE_RPM
#include "common/library.h"
#include <rpm/rpmlib.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmlog.h>
static uint32_t getRpmFromLibrpm(const FFinstance* instance)
{
FF_LIBRARY_LOAD(rpm, &instance->config.librpm, 0, "librpm.so", 12)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmReadConfigFiles, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsCreate, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsInitIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbGetIteratorCount, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmdbFreeIterator, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmtsFree, 0)
FF_LIBRARY_LOAD_SYMBOL(rpm, rpmlogSetMask, 0)
// Don't print any error messages
ffrpmlogSetMask(RPMLOG_MASK(RPMLOG_EMERG));
if(ffrpmReadConfigFiles(NULL, NULL) != 0)
{
dlclose(rpm);
return 0;
}
rpmts ts = ffrpmtsCreate();
if(ts == NULL)
{
dlclose(rpm);
return 0;
}
rpmdbMatchIterator mi = ffrpmtsInitIterator(ts, RPMDBI_LABEL, NULL, 0);
if(mi == NULL)
{
ffrpmtsFree(ts);
dlclose(rpm);
return 0;
}
int count = ffrpmdbGetIteratorCount(mi);
ffrpmdbFreeIterator(mi);
ffrpmtsFree(ts);
dlclose(rpm);
return count > 0 ? (uint32_t) count : 0;
}
#endif //FF_HAVE_RPM
static void getPackageCounts(const FFinstance* instance, FFstrbuf* baseDir, FFPackageCounts* packageCounts)
{
#if defined(__APPLE__) || defined(__ANDROID__)
FF_UNUSED(instance);
#endif
#ifndef __APPLE__ //Linux desktop and Android
uint32_t baseDirLength = baseDir->length;
//pacman
ffStrbufAppendS(baseDir, "/var/lib/pacman/local");
packageCounts->pacman += getNumElements(baseDir->chars, DT_DIR);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//dpkg
ffStrbufAppendS(baseDir, "/var/lib/dpkg/status");
packageCounts->dpkg += getNumStrings(baseDir->chars, "Status: ");
ffStrbufSubstrBefore(baseDir, baseDirLength);
#ifndef __ANDROID__ //Linux Desktop
//rpm
ffStrbufAppendS(baseDir, "/var/lib/rpm/rmpdb.sqlite");
packageCounts->rpm += (uint32_t) ffSettingsGetSQLite3Int(instance, baseDir->chars, "SELECT count(blob) FROM Packages");
ffStrbufSubstrBefore(baseDir, baseDirLength);
//emerge
ffStrbufAppendS(baseDir, "/var/db/pkg");
packageCounts->emerge += countFilesRecursive(baseDir, "SIZE");
ffStrbufSubstrBefore(baseDir, baseDirLength);
//xps
ffStrbufAppendS(baseDir, "/var/db/xbps");
packageCounts->xbps += getXBPS(baseDir);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//nix system
ffStrbufAppendS(baseDir, "/run/current-system");
packageCounts->nixSystem += getNixPackages(baseDir->chars);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//nix default
ffStrbufAppendS(baseDir, "/nix/var/nix/profiles/default");
packageCounts->nixDefault += getNixPackages(baseDir->chars);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//apk
ffStrbufAppendS(baseDir, "/lib/apk/db/installed");
packageCounts->apk += getNumStrings(baseDir->chars, "C:Q");
ffStrbufSubstrBefore(baseDir, baseDirLength);
//flatpak
ffStrbufAppendS(baseDir, "/var/lib/flatpak/app");
packageCounts->flatpak += getNumElements(baseDir->chars, DT_DIR);
ffStrbufSubstrBefore(baseDir, baseDirLength);
//snap
ffStrbufAppendS(baseDir, "/snap");
uint32_t snap = getNumElements(baseDir->chars, DT_DIR);
if(snap > 0)
packageCounts->snap += (snap - 1); //Accounting for the /snap/bin folder
ffStrbufSubstrBefore(baseDir, baseDirLength);
//pacman branch
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);
#endif // !__ANDROID__
#else // !__APPLE__
//brew
packageCounts->brew += getBrewPackages(baseDir);
packageCounts->port += getMacPortsPackages(baseDir);
#endif // __APPLE__
#ifdef __FreeBSD__
ffStrbufAppendS(baseDir, "/var/db/pkg/local.sqlite");
packageCounts->pkg += (uint32_t) ffSettingsGetSQLite3Int(instance, baseDir->chars, "SELECT count(id) FROM packages");
ffStrbufSubstrBefore(baseDir, baseDirLength);
#endif // __FreeBSD__
}
static void getPackageCountsBedrock(const FFinstance* instance, FFstrbuf* baseDir, FFPackageCounts* packageCounts)
{
uint32_t baseDirLength = baseDir->length;
ffStrbufAppendS(baseDir, "/bedrock/strata");
DIR* dir = opendir(baseDir->chars);
if(dir == NULL)
{
ffStrbufSubstrBefore(baseDir, baseDirLength);
getPackageCounts(instance, baseDir, packageCounts);
return;
}
ffStrbufAppendC(baseDir, '/');
baseDirLength = baseDir->length;
struct dirent* entry;
while((entry = readdir(dir)) != NULL)
{
if(entry->d_type != DT_DIR)
continue;
ffStrbufAppendS(baseDir, entry->d_name);
getPackageCounts(instance, baseDir, packageCounts);
ffStrbufSubstrBefore(baseDir, baseDirLength);
}
closedir(dir);
}
void
#ifdef __MSYS__
ffDetectPackagesPosix
#else
ffDetectPackages
#endif
(FFinstance* instance, FFPackageCounts* counts)
{
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 512);
ffStrbufAppendS(&baseDir, FASTFETCH_TARGET_DIR_ROOT);
if(ffStrbufIgnCaseCompS(&ffDetectOS(instance)->id, "bedrock") == 0)
getPackageCountsBedrock(instance, &baseDir, counts);
else
getPackageCounts(instance, &baseDir, counts);
// If SQL failed, we can still try with librpm.
// This is needed on openSUSE, which seems to use a proprietary database file
// This method doesn't work on bedrock, so we do it here.
#ifdef FF_HAVE_RPM
if(counts->rpm == 0)
counts->rpm = getRpmFromLibrpm(instance);
#endif
#if !defined(__ANDROID__) && !defined(__APPLE__)
//nix user
ffStrbufSetS(&baseDir, instance->state.passwd->pw_dir);
ffStrbufAppendS(&baseDir, "/.nix-profile");
counts->nixUser = getNixPackages(baseDir.chars);
#endif
ffStrbufDestroy(&baseDir);
}
+41
View File
@@ -0,0 +1,41 @@
#include "packages.h"
#include <handleapi.h>
#include <fileapi.h>
static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type)
{
uint32_t counter = 0;
WIN32_FIND_DATAA wfd;
HANDLE hFind = FindFirstFileA(searchPath, &wfd);
if (hFind != INVALID_HANDLE_VALUE)
{
do // Managed to locate and create an handle to that folder.
{
if(wfd.dwFileAttributes & type)
counter++;
} while (FindNextFileA(hFind, &wfd) == TRUE);
FindClose(hFind);
}
return counter;
}
#ifdef __MSYS__
void ffDetectPackagesPosix(const FFinstance* instance, FFPackageCounts* counts);
#endif
void ffDetectPackages(FFinstance* instance, FFPackageCounts* counts)
{
#ifdef __MSYS__
//We have pacman and maybe others in MSYS, but not package managers for Windows
if(getenv("MSYSTEM"))
return ffDetectPackagesPosix(instance, counts);
#endif
FFstrbuf scoopPath;
ffStrbufInitF(&scoopPath, "%s/scoop/apps/*", getenv("USERPROFILE"));
counts->scoop = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY) - 3; // . .. scoop
ffStrbufDestroy(&scoopPath);
}
@@ -3,5 +3,5 @@
const char* ffDetectPowerAdapterImpl(FFinstance* instance, FFlist* results)
{
FF_UNUSED(instance, results);
return "Unimplemented";
return "Not supported on this platform";
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#ifndef FF_INCLUDED_detection_processes_processes
#define FF_INCLUDED_detection_processes_processes
#include "fastfetch.h"
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error);
#endif
+18
View File
@@ -0,0 +1,18 @@
#include "processes.h"
#include <sys/sysctl.h>
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error)
{
FF_UNUSED(instance);
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
size_t length;
if(sysctl(request, sizeof(request) / sizeof(*request), NULL, &length, NULL, 0) != 0)
{
ffStrbufAppend(error, "sysctl() failed");
return 0;
}
return (uint32_t)(length / sizeof(struct kinfo_proc));
}
+12
View File
@@ -0,0 +1,12 @@
#include "processes.h"
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error)
{
#if FF_HAVE_SYSINFO_H
FF_UNUSED(error);
return (uint32_t) instance->state.sysinfo.procs;
#else
ffStrbufAppendS(error, "Unimplemented");
return 0;
#endif
}
@@ -0,0 +1,30 @@
extern "C" {
#include "processes.h"
}
#include "util/windows/wmi.hpp"
uint32_t ffDetectProcesses(FFinstance* instance, FFstrbuf* error)
{
FF_UNUSED(instance);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT NumberOfProcesses FROM Win32_OperatingSystem", error);
if(!pEnumerator)
return 0;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
ffStrbufAppendS(error, "No Wmi result returned");
pEnumerator->Release();
return 0;
}
uint64_t result = 0;
ffGetWmiObjUnsigned(pclsObj, L"NumberOfProcesses", &result);
pclsObj->Release();
pEnumerator->Release();
return (uint32_t)result;
}
+1 -1
View File
@@ -2,7 +2,7 @@
#include "common/properties.h"
#include "common/processing.h"
#include "detection/internal.h"
#include "detection/terminalshell.h"
#include "detection/terminalshell/terminalshell.h"
static void detectAlacritty(const FFinstance* instance, FFTerminalFontResult* terminalFont) {
FFstrbuf fontName;
@@ -1,6 +1,6 @@
#include "fastfetch.h"
#include "terminalfont.h"
#include "detection/terminalshell.h"
#include "detection/terminalshell/terminalshell.h"
#include "common/io.h"
#include <sys/stat.h>
@@ -1,6 +1,6 @@
#include "terminalfont.h"
#include "common/font.h"
#include "detection/terminalshell.h"
#include "detection/terminalshell/terminalshell.h"
#include "util/apple/osascript.h"
#include <stdlib.h>
@@ -2,7 +2,7 @@
#include "common/settings.h"
#include "common/properties.h"
#include "common/parsing.h"
#include "detection/terminalshell.h"
#include "detection/terminalshell/terminalshell.h"
#include "detection/displayserver/displayserver.h"
static const char* getSystemMonospaceFont(const FFinstance* instance)
@@ -189,7 +189,7 @@ static const char* detectFromWTImpl(const FFinstance* instance, FFstrbuf* conten
{
CJSONData cjsonData;
FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson failed", "libcjson"FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD(libcjson, &instance->config.libcJSON, "dlopen libcjson"FF_LIBRARY_EXTENSION" failed", "libcjson"FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_Parse)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_IsObject)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libcjson, cjsonData, cJSON_GetObjectItemCaseSensitive)
@@ -292,12 +292,17 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFon
FFstrbuf name;
ffStrbufInit(&name);
int size = -1;
detectFromWTImpl(instance, &json, &name, &size);
error = detectFromWTImpl(instance, &json, &name, &size);
ffStrbufDestroy(&json);
char sizeStr[16];
snprintf(sizeStr, sizeof(sizeStr), "%d", size);
ffFontInitValues(&terminalFont->font, name.chars, sizeStr);
if(error)
ffStrbufAppendS(&terminalFont->error, error);
else
{
char sizeStr[16];
snprintf(sizeStr, sizeof(sizeStr), "%d", size);
ffFontInitValues(&terminalFont->font, name.chars, sizeStr);
}
ffStrbufDestroy(&name);
}
@@ -312,6 +317,82 @@ static void detectFromWindowsTeriminal(const FFinstance* instance, FFTerminalFon
#endif
#if defined(_WIN32) || defined(__MSYS__)
// TODO: move to a separate file
static void detectMintty(const FFinstance* instance, FFTerminalFontResult* terminalFont)
{
FFstrbuf fontName;
ffStrbufInit(&fontName);
FFstrbuf fontSize;
ffStrbufInit(&fontSize);
ffParsePropFileHomeValues(instance, ".minttyrc", 2, (FFpropquery[]) {
{"Font=", &fontName},
{"FontHeight=", &fontSize}
});
if(fontName.length == 0)
ffStrbufAppendS(&fontName, "Lucida Console");
if(fontSize.length == 0)
ffStrbufAppendC(&fontSize, '9');
ffFontInitValues(&terminalFont->font, fontName.chars, fontSize.chars);
ffStrbufDestroy(&fontName);
ffStrbufDestroy(&fontSize);
}
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
static void detectConhost(const FFinstance* instance, FFTerminalFontResult* terminalFont)
{
FF_UNUSED(instance);
//Current font of conhost doesn't seem to be detectable, we detect default font instead
HKEY hKey;
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW() failed");
return;
}
DWORD bufSize;
wchar_t fontNameW[64];
bufSize = sizeof(fontNameW);
if(RegQueryValueExW(hKey, L"FaceName", NULL, NULL, (LPBYTE)fontNameW, &bufSize) != ERROR_SUCCESS)
{
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(FaceName) failed");
goto exit;
}
fontNameW[bufSize] = '\0';
char fontNameA[128];
int fontNameALen = WideCharToMultiByte(CP_UTF8, 0, fontNameW, (int)(bufSize / 2), fontNameA, sizeof(fontNameA), NULL, NULL);
fontNameA[fontNameALen] = '\0';
uint32_t fontSizeNum = 0;
bufSize = sizeof(fontSizeNum);
if(RegQueryValueExW(hKey, L"fontSize", NULL, NULL, (LPBYTE)&fontSizeNum, &bufSize) != ERROR_SUCCESS)
{
ffStrbufAppendS(&terminalFont->error, "RegOpenKeyExW(fontSize) failed");
goto exit;
}
char fontSize[16];
snprintf(fontSize, sizeof(fontSize), "%u", (fontSizeNum >> 16));
ffFontInitValues(&terminalFont->font, fontNameA, fontSize);
exit:
RegCloseKey(hKey);
}
#endif //defined(_WIN32) || defined(__MSYS__)
void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont)
{
if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "konsole") == 0)
@@ -324,6 +405,14 @@ void ffDetectTerminalFontPlatform(const FFinstance* instance, const FFTerminalSh
detectFromGSettings(instance, "/com/gexperts/Tilix/profiles/", "com.gexperts.Tilix.ProfilesList", "com.gexperts.Tilix.Profile", terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "gnome-terminal-") == 0)
detectFromGSettings(instance, "/org/gnome/terminal/legacy/profiles:/:", "org.gnome.Terminal.ProfilesList", "org.gnome.Terminal.Legacy.Profile", terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0)
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "Windows Terminal") == 0 ||
ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "WindowsTerminal.exe") == 0)
detectFromWindowsTeriminal(instance, terminalFont);
#if defined(_WIN32) || defined(__MSYS__)
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "mintty") == 0)
detectMintty(instance, terminalFont);
else if(ffStrbufIgnCaseCompS(&terminalShell->terminalProcessName, "conhost.exe") == 0)
detectConhost(instance, terminalFont);
#endif
}
@@ -10,10 +10,12 @@ typedef struct FFTerminalShellResult
FFstrbuf shellProcessName;
FFstrbuf shellExe;
const char* shellExeName; //pointer to a char in shellExe
FFstrbuf shellPrettyName;
FFstrbuf shellVersion;
FFstrbuf terminalProcessName;
FFstrbuf terminalExe;
FFstrbuf terminalPrettyName;
const char* terminalExeName; //pointer to a char in terminalExe
FFstrbuf userShellExe;
@@ -1,8 +1,9 @@
#include "fastfetch.h"
#include "detection/terminalshell.h"
#include "detection/host/host.h"
#include "common/io.h"
#include "common/parsing.h"
#include "common/processing.h"
#include "terminalshell.h"
#include <ctype.h>
#include <string.h>
@@ -12,6 +13,7 @@
static void setExeName(FFstrbuf* exe, const char** exeName)
{
assert(exe->length > 0);
uint32_t lastSlashIndex = ffStrbufLastIndexC(exe, '/');
if(lastSlashIndex < exe->length)
*exeName = exe->chars + lastSlashIndex + 1;
@@ -19,15 +21,20 @@ static void setExeName(FFstrbuf* exe, const char** exeName)
static void getProcessInformation(const char* pid, FFstrbuf* processName, FFstrbuf* exe, const char** exeName)
{
assert(processName->length > 0);
FFstrbuf cmdlineFilePath;
ffStrbufInit(&cmdlineFilePath);
ffStrbufAppendS(&cmdlineFilePath, "/proc/");
ffStrbufAppendS(&cmdlineFilePath, pid);
ffStrbufAppendS(&cmdlineFilePath, "/cmdline");
ffReadFileBuffer(cmdlineFilePath.chars, exe);
ffStrbufSubstrBeforeFirstC(exe, '\0'); //Trim the arguments
ffStrbufTrimLeft(exe, '-'); //Happens in TTY
ffStrbufClear(exe);
if(ffAppendFileBuffer(cmdlineFilePath.chars, exe))
{
ffStrbufSubstrBeforeFirstC(exe, '\0'); //Trim the arguments
ffStrbufTrimLeft(exe, '-'); //Happens in TTY
}
if(exe->length == 0)
ffStrbufSet(exe, processName);
@@ -93,16 +100,17 @@ static void getTerminalShell(FFTerminalShellResult* result, const char* pid)
strcasecmp(name, "ksh") == 0 ||
strcasecmp(name, "fish") == 0 ||
strcasecmp(name, "dash") == 0 ||
strcasecmp(name, "pwsh") == 0 ||
strcasecmp(name, "git-shell") == 0
) {
ffStrbufAppendS(&result->shellProcessName, name);
ffStrbufSetS(&result->shellProcessName, name); // prevent from `fishbash`
getProcessInformation(pid, &result->shellProcessName, &result->shellExe, &result->shellExeName);
getTerminalShell(result, ppid);
return;
}
ffStrbufAppendS(&result->terminalProcessName, name);
ffStrbufSetS(&result->terminalProcessName, name);
getProcessInformation(pid, &result->terminalProcessName, &result->terminalExe, &result->terminalExeName);
}
@@ -149,17 +157,18 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
getenv("KONSOLE_VERSION") != NULL
)) term = "konsole";
//MacOS
//MacOS, mintty
if(!ffStrSet(term))
term = getenv("TERM_PROGRAM");
//We are in WSL but not in Windows Terminal
if(!ffStrSet(term) && (
getenv("WSLENV") != NULL ||
getenv("WSL_DISTRO") != NULL ||
getenv("WSL_INTEROP") != NULL
))
if(!ffStrSet(term))
{
const FFHostResult* host = ffDetectHost();
if(ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_WSL) == 0 ||
ffStrbufCompS(&host->productName, FF_HOST_PRODUCT_NAME_MSYS) == 0) //TODO better WSL or MSYS detection
term = "conhost";
}
//Normal Terminal
if(!ffStrSet(term))
@@ -169,14 +178,19 @@ static void getTerminalFromEnv(FFTerminalShellResult* result)
if(!ffStrSet(term) || strcasecmp(term, "linux") == 0)
term = ttyname(STDIN_FILENO);
ffStrbufSetS(&result->terminalProcessName, term);
ffStrbufSetS(&result->terminalExe, term);
setExeName(&result->terminalExe, &result->terminalExeName);
if(ffStrSet(term))
{
ffStrbufSetS(&result->terminalProcessName, term);
ffStrbufSetS(&result->terminalExe, term);
setExeName(&result->terminalExe, &result->terminalExeName);
}
}
static void getUserShellFromEnv(FFTerminalShellResult* result)
{
ffStrbufAppendS(&result->userShellExe, getenv("SHELL"));
if(result->userShellExe.length == 0)
return;
setExeName(&result->userShellExe, &result->userShellExeName);
//If shell detection via processes failed
@@ -250,17 +264,24 @@ static void getShellVersionGeneric(FFstrbuf* exe, const char* exeName, FFstrbuf*
static void getShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version)
{
ffStrbufClear(version);
if(strcasecmp(exeName, "bash") == 0)
getShellVersionBash(exe, version);
else if(strcasecmp(exeName, "zsh") == 0)
getShellVersionZsh(exe, version);
else if(strcasecmp(exeName, "fish") == 0)
else if(strcasecmp(exeName, "fish") == 0 || strcasecmp(exeName, "pwsh") == 0)
getShellVersionFish(exe, version);
else
getShellVersionGeneric(exe, exeName, version);
}
const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
const FFTerminalShellResult*
#if defined(__MSYS__) || defined(_WIN32)
ffDetectTerminalShellPosix
#else
ffDetectTerminalShell
#endif
(const FFinstance* instance)
{
FF_UNUSED(instance);
@@ -301,6 +322,14 @@ const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
else
ffStrbufSet(&result.userShellVersion, &result.shellVersion);
// https://github.com/LinusDierheimer/fastfetch/discussions/280#discussioncomment-3831734
ffStrbufInitS(&result.shellPrettyName, result.shellExeName);
if(strncmp(result.terminalExeName, result.terminalProcessName.chars, result.terminalProcessName.length) == 0) // if exeName starts with processName, print it. Otherwise print processName
ffStrbufInitS(&result.terminalPrettyName, result.terminalExeName);
else
ffStrbufInitCopy(&result.terminalPrettyName, &result.terminalProcessName);
pthread_mutex_unlock(&mutex);
return &result;
}
@@ -0,0 +1,158 @@
extern "C" {
#include "terminalshell.h"
#include "common/processing.h"
}
#include "util/windows/wmi.hpp"
#include <inttypes.h>
#include <processthreadsapi.h>
#include <wchar.h>
struct ProcessInfo
{
uint32_t pid;
FFstrbuf psName;
};
static bool getProcessInfo(uint32_t pid, uint32_t* ppid, FFstrbuf* pname, FFstrbuf* exe)
{
wchar_t query[256] = {};
swprintf(query, 256, L"SELECT Name, ParentProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId = %" PRIu32, pid);
IEnumWbemClassObject* pEnumerator = ffQueryWmi(query, nullptr);
if(!pEnumerator)
return false;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
if(FAILED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) || uReturn == 0)
{
pEnumerator->Release();
return false;
}
if(ppid)
{
uint64_t value;
ffGetWmiObjUnsigned(pclsObj, L"ParentProcessId", &value);
*ppid = (uint32_t) value;
}
if(pname)
ffGetWmiObjString(pclsObj, L"Name", pname);
if(exe)
ffGetWmiObjString(pclsObj, L"ExecutablePath", exe);
pclsObj->Release();
pEnumerator->Release();
return true;
}
static void getShellVersion(FFstrbuf* exe, FFstrbuf* version)
{
char* const argv[] = { exe->chars, (char*)"--version", NULL };
ffProcessAppendStdOut(version, argv);
ffStrbufTrimRight(version, '\n');
ffStrbufSubstrAfterLastC(version, ' ');
}
static uint32_t getShellInfo(FFTerminalShellResult* result, uint32_t pid)
{
uint32_t ppid;
if(!getProcessInfo(pid, &ppid, &result->shellProcessName, &result->shellExe))
return 0;
result->shellExeName = result->shellExe.chars + ffStrbufLastIndexC(&result->shellExe, '\\') + 1;
ffStrbufSet(&result->shellPrettyName, &result->shellProcessName);
if(ffStrbufEndsWithIgnCaseS(&result->shellPrettyName, ".exe"))
ffStrbufSubstrBefore(&result->shellPrettyName, result->shellPrettyName.length - 4);
if(ffStrbufIgnCaseCompS(&result->shellPrettyName, "pwsh") == 0)
{
ffStrbufSetS(&result->shellPrettyName, "PowerShell");
getShellVersion(&result->shellExe, &result->shellVersion);
}
else if(ffStrbufIgnCaseCompS(&result->shellPrettyName, "powershell") == 0)
ffStrbufSetS(&result->shellPrettyName, "Windows PowerShell");
else if(ffStrbufIgnCaseCompS(&result->shellPrettyName, "cmd") == 0)
ffStrbufSetS(&result->shellPrettyName, "Command Prompt");
return ppid;
}
static uint32_t getTerminalInfo(FFTerminalShellResult* result, uint32_t pid)
{
uint32_t ppid;
if(!getProcessInfo(pid, &ppid, &result->terminalProcessName, &result->terminalExe))
return 0;
result->terminalExeName = result->terminalExe.chars + ffStrbufLastIndexC(&result->terminalExe, '\\');
ffStrbufSet(&result->terminalPrettyName, &result->terminalProcessName);
if(ffStrbufEndsWithIgnCaseS(&result->terminalPrettyName, ".exe"))
ffStrbufSubstrBefore(&result->terminalPrettyName, result->terminalPrettyName.length - 4);
if(ffStrbufIgnCaseCompS(&result->terminalPrettyName, "WindowsTerminal") == 0)
ffStrbufSetS(&result->terminalPrettyName, "Windows Terminal");
else if(ffStrbufIgnCaseCompS(&result->terminalPrettyName, "conhost") == 0)
ffStrbufSetS(&result->terminalPrettyName, "Console Window Host");
return ppid;
}
#ifdef __MSYS__
extern "C"
const FFTerminalShellResult* ffDetectTerminalShellPosix(const FFinstance* instance);
#endif
const FFTerminalShellResult* ffDetectTerminalShell(const FFinstance* instance)
{
#ifdef __MSYS__
// This is hacky.
// When running inside of MSYS2, the real Windows parent process doesn't exist and we must find it in Linux way ( /proc/self/xxx )
// When running outside of MSYS2, /proc/self/xxx doesn't exist and we must find it in Windows way
if(getenv("MSYSTEM"))
return ffDetectTerminalShellPosix(instance);
#endif
static FFTerminalShellResult result;
static bool init = false;
if(init)
return &result;
init = true;
ffStrbufInit(&result.shellProcessName);
ffStrbufInitA(&result.shellExe, 128);
result.shellExeName = result.shellExe.chars;
ffStrbufInit(&result.shellPrettyName);
ffStrbufInit(&result.shellVersion);
ffStrbufInit(&result.terminalProcessName);
ffStrbufInitA(&result.terminalExe, 128);
result.terminalExeName = result.terminalExe.chars;
ffStrbufInit(&result.terminalPrettyName);
ffStrbufInit(&result.userShellExe);
result.userShellExeName = result.userShellExe.chars;
ffStrbufInit(&result.userShellVersion);
uint32_t ppid = GetCurrentProcessId();
if(!getProcessInfo(ppid, &ppid, nullptr, nullptr))
return &result;
ppid = getShellInfo(&result, ppid);
if(ppid == 0)
return &result;
// TODO: handle nested shells
// TODO: handle running without shells ( dblclick exe in Windows Explorer )
ppid = getTerminalInfo(&result, ppid);
if(ppid == 0)
return &result;
return &result;
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#ifndef FF_INCLUDED_detection_users_users
#define FF_INCLUDED_detection_users_users
#include "fastfetch.h"
void ffDetectUsers(FFlist* users /* List of FFstrbuf */, FFstrbuf* error);
#endif
+36
View File
@@ -0,0 +1,36 @@
#include "fastfetch.h"
#include "users.h"
#if FF_HAVE_UTMPX_H
#include <utmpx.h>
#else
//for Android compatibility
#include <utmp.h>
#define utmpx utmp
#define setutxent setutent
#define getutxent getutent
#endif
void ffDetectUsers(FFlist* users, FFstrbuf* error)
{
struct utmpx* n = NULL;
setutxent();
next:
while((n = getutxent()))
{
if(n->ut_type != USER_PROCESS)
continue;
for(uint32_t i = 0; i < users->length; ++i)
{
if(ffStrbufCompS((FFstrbuf*)ffListGet(users, i), n->ut_user) == 0)
goto next;
}
ffStrbufInitS((FFstrbuf*)ffListAdd(users), n->ut_user);
}
if(users->length == 0)
ffStrbufAppendS(error, "Unable to detect users");
}
+42
View File
@@ -0,0 +1,42 @@
extern "C" {
#include "users.h"
}
#include "util/windows/wmi.hpp"
void ffDetectUsers(FFlist* users, FFstrbuf* error)
{
IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT Antecedent FROM Win32_LoggedOnUser", error);
if(!pEnumerator)
return;
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
next:
while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0)
{
FFstrbuf antecedent;
ffStrbufInit(&antecedent);
ffGetWmiObjString(pclsObj, L"Antecedent", &antecedent); // \\.\root\cimv2:Win32_Account.Domain="DOMAIN",Name="NAME"
ffStrbufTrimRight(&antecedent, '"'); // \\.\root\cimv2:Win32_Account.Domain="DOMAIN",Name="NAME
ffStrbufSubstrAfterFirstC(&antecedent, '"'); // DOMAIN",Name="NAME
uint32_t index = ffStrbufFirstIndexC(&antecedent, '"');
ffStrbufRemoveSubstr(&antecedent, index, ffStrbufLastIndexC(&antecedent, '"')); // DOMAIN"NAME
antecedent.chars[index] = '\\';
for(uint32_t i = 0; i < users->length; ++i)
{
if(ffStrbufComp((FFstrbuf*)ffListGet(users, i), &antecedent) == 0)
goto next;
}
*(FFstrbuf*)ffListAdd(users) = antecedent;
}
if(users->length == 0)
ffStrbufAppendS(error, "Unable to detect users");
pclsObj->Release();
pEnumerator->Release();
}
+1 -1
View File
@@ -35,7 +35,7 @@ static void applyDriverName(VkPhysicalDeviceDriverProperties* properties, FFstrb
static const char* detectVulkan(const FFinstance* instance, FFVulkanResult* result)
{
FF_LIBRARY_LOAD(vulkan, &instance->config.libVulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed", "libvulkan"FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD(vulkan, &instance->config.libVulkan, "dlopen libvulkan"FF_LIBRARY_EXTENSION " failed", "libvulkan"FF_LIBRARY_EXTENSION, 2, "vulkan-1"FF_LIBRARY_EXTENSION, -1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkGetInstanceProcAddr)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkCreateInstance)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(vulkan, vkDestroyInstance)
+1 -1
View File
@@ -224,6 +224,6 @@ bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError)
return detectOpenbox(instance, &wm->dePrettyName, themeOrError);
ffStrbufAppendS(themeOrError, "Unknown WM: ");
ffStrbufAppend(themeOrError, &wm->dePrettyName);
ffStrbufAppend(themeOrError, &wm->wmPrettyName);
return false;
}
@@ -5,6 +5,6 @@
bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError)
{
FF_UNUSED(instance);
ffStrbufAppendS(themeOrError, "WM theme detection is not supported on Android");
ffStrbufAppendS(themeOrError, "Not supported on this platform");
return false;
}
+41
View File
@@ -0,0 +1,41 @@
#include "fastfetch.h"
#include "wmtheme.h"
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
bool ffDetectWmTheme(FFinstance* instance, FFstrbuf* themeOrError)
{
FF_UNUSED(instance);
HKEY hKey;
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
ffStrbufAppendS(themeOrError, "RegOpenKeyExW() failed");
return false;
}
bool result = true;
int SystemUsesLightTheme = 1;
DWORD bufSize = sizeof(SystemUsesLightTheme);
if(RegQueryValueExW(hKey, L"SystemUsesLightTheme", NULL, NULL, (LPBYTE)&SystemUsesLightTheme, &bufSize) != ERROR_SUCCESS)
{
ffStrbufAppendS(themeOrError, "RegOpenKeyExW(SystemUsesLightTheme) failed");
goto exit;
}
int AppsUsesLightTheme = 1;
bufSize = sizeof(AppsUsesLightTheme);
if(RegQueryValueExW(hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&AppsUsesLightTheme, &bufSize) != ERROR_SUCCESS)
{
ffStrbufAppendS(themeOrError, "RegOpenKeyExW(AppsUseLightTheme) failed");
goto exit;
}
ffStrbufAppendF(themeOrError, "System - %s, Apps - %s", SystemUsesLightTheme ? "Light" : "Dark", AppsUsesLightTheme ? "Light" : "Dark");
exit:
RegCloseKey(hKey);
return result;
}
+30 -9
View File
@@ -71,24 +71,34 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "host-format") == 0)
{
constructAndPrintCommandHelpFormat("host", "{2} {3}", 15,
constructAndPrintCommandHelpFormat("host", "{2} {3}", 8,
"product family",
"product name",
"product version",
"product sku",
"bios date",
"bios release",
"bios vendor",
"bios version",
"board name",
"board vendor",
"board version",
"chassis type",
"chassis vendor",
"chassis version",
"sys vendor"
);
}
else if(strcasecmp(command, "bios-format") == 0)
{
constructAndPrintCommandHelpFormat("bios", "{2} {3}", 4,
"bios date",
"bios release",
"bios vendor",
"bios version"
);
}
else if(strcasecmp(command, "board-format") == 0)
{
constructAndPrintCommandHelpFormat("board", "{2} {3}", 3,
"board name",
"board vendor",
"board version"
);
}
else if(strcasecmp(command, "kernel-format") == 0)
{
constructAndPrintCommandHelpFormat("kernel", "{2}", 3,
@@ -114,7 +124,7 @@ static inline void printCommandHelp(const char* command)
}
else if(strcasecmp(command, "packages-format") == 0)
{
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-system), {9} (nix-user), {10} (nix-default), {11} (apk), {12} (pkg), {13} (flatpak), {14} (snap), {15} (brew), {16} (port)", 16,
constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (xbps), {8} (nix-system), {9} (nix-user), {10} (nix-default), {11} (apk), {12} (pkg), {13} (flatpak), {14} (snap), {15} (brew), {16} (port), {17} (scoop)", 17,
"Number of all packages",
"Number of pacman packages",
"Pacman branch on manjaro",
@@ -131,6 +141,7 @@ static inline void printCommandHelp(const char* command)
"Number of snap packages",
"Number of brew packages",
"Number of macports packages"
"Number of scoop packages"
);
}
else if(strcasecmp(command, "shell-format") == 0)
@@ -978,6 +989,12 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
optionParseString(key, value, &instance->config.host.outputFormat);
else if(strcasecmp(key, "--host-error") == 0)
optionParseString(key, value, &instance->config.host.errorFormat);
else if(strcasecmp(key, "--bios-key") == 0)
optionParseString(key, value, &instance->config.bios.key);
else if(strcasecmp(key, "--bios-format") == 0)
optionParseString(key, value, &instance->config.bios.outputFormat);
else if(strcasecmp(key, "--bios-error") == 0)
optionParseString(key, value, &instance->config.bios.errorFormat);
else if(strcasecmp(key, "--kernel-key") == 0)
optionParseString(key, value, &instance->config.kernel.key);
else if(strcasecmp(key, "--kernel-format") == 0)
@@ -1367,6 +1384,10 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char
ffPrintOS(instance);
else if(strcasecmp(line, "host") == 0)
ffPrintHost(instance);
else if(strcasecmp(line, "bios") == 0)
ffPrintBios(instance);
else if(strcasecmp(line, "board") == 0)
ffPrintBoard(instance);
else if(strcasecmp(line, "kernel") == 0)
ffPrintKernel(instance);
else if(strcasecmp(line, "uptime") == 0)
+4
View File
@@ -94,6 +94,8 @@ typedef struct FFconfig
FFModuleArgs os;
FFModuleArgs host;
FFModuleArgs bios;
FFModuleArgs board;
FFModuleArgs kernel;
FFModuleArgs uptime;
FFModuleArgs processes;
@@ -249,6 +251,8 @@ void ffPrintTitle(FFinstance* instance);
void ffPrintSeparator(FFinstance* instance);
void ffPrintOS(FFinstance* instance);
void ffPrintHost(FFinstance* instance);
void ffPrintBios(FFinstance* instance);
void ffPrintBoard(FFinstance* instance);
void ffPrintKernel(FFinstance* instance);
void ffPrintUptime(FFinstance* instance);
void ffPrintProcesses(FFinstance* instance);
+1 -1
View File
@@ -16,7 +16,7 @@
#define FASTFETCH_TARGET_DIR_INSTALL_SYSCONF "@CMAKE_INSTALL_SYSCONFDIR@"
#define FASTFETCH_DATATEXT_STRUCTURE "@DATATEXT_STRUCTURE@"
#define FASTFETCH_DATATEXT_CONFIG_SYSTEM "@DATATEXT_CONFIG_SYSTEM@" //Requires FASTFETCH_PROJECT_VERSION to be set
#define FASTFETCH_DATATEXT_CONFIG_SYSTEM "@DATATEXT_CONFIG_SYSTEM@"
#define FASTFETCH_DATATEXT_CONFIG_USER "@DATATEXT_CONFIG_USER@" //Requires FASTFETCH_PROJECT_VERSION and FASTFETCH_DATATEXT_STRUCTURE to be set
#define FASTFETCH_DATATEXT_MODULES "@DATATEXT_MODULES@"
#define FASTFETCH_DATATEXT_HELP "@DATATEXT_HELP@"
+2
View File
@@ -22,6 +22,8 @@ int main(int argc, char** argv)
ffPrintSeparator(&instance);
ffPrintOS(&instance);
ffPrintHost(&instance);
//ffPrintBios(&instance);
//ffPrintBoard(&instance);
ffPrintKernel(&instance);
ffPrintUptime(&instance);
//ffPrintProcesses(&instance);
+99
View File
@@ -1277,6 +1277,102 @@ static const FFlogo* getLogoMsys2()
FF_LOGO_RETURN
}
static const FFlogo* getLogoWindows11()
{
FF_LOGO_INIT
FF_LOGO_NAMES("Windows 11")
FF_LOGO_LINES(
"$1\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################\n"
"################ ################"
)
FF_LOGO_COLORS(
"34" //blue
)
FF_LOGO_COLOR_KEYS("34"); //blue
FF_LOGO_COLOR_TITLE("36"); //cyan
FF_LOGO_RETURN
}
static const FFlogo* getLogoWindows8()
{
FF_LOGO_INIT
FF_LOGO_NAMES("Windows 8", "Windows 8.1", "Windows 10")
FF_LOGO_LINES(
"$1 ..,\n"
" ....,,:;+ccllll\n"
" ...,,+:; cllllllllllllllllll\n"
",cclllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"llllllllllllll lllllllllllllllllll\n"
"`'ccllllllllll lllllllllllllllllll\n"
" `' \\*:: :ccllllllllllllllll\n"
" ````''*::cll\n"
" ``"
)
FF_LOGO_COLORS(
"36" //cyan
)
FF_LOGO_COLOR_KEYS("36"); //cyan
FF_LOGO_COLOR_TITLE("37"); //white
FF_LOGO_RETURN
}
static const FFlogo* getLogoWindows()
{
FF_LOGO_INIT
FF_LOGO_NAMES("Windows")
FF_LOGO_LINES(
"$1 ,.=:!!t3Z3z.,\n"
" :tt:::tt333EE3\n"
"$1 Et:::ztt33EEEL$2 @Ee., ..,\n"
"$1 ;tt:::tt333EE7$2 ;EEEEEEttttt33#\n"
"$1 :Et:::zt333EEQ.$2 $EEEEEttttt33QL\n"
"$1 it::::tt333EEF$2 @EEEEEEttttt33F\n"
"$1 ;3=*^```\"*4EEV$2 :EEEEEEttttt33@.\n"
"$3 ,.=::::!t=., $1`$2 @EEEEEEtttz33QF\n"
"$3 ;::::::::zt33)$2 \"4EEEtttji3P*\n"
"$3 :t::::::::tt33.$4:Z3z..$2 ``$4 ,..g.\n"
"$3 i::::::::zt33F$4 AEEEtttt::::ztF\n"
"$3 ;:::::::::t33V$4 ;EEEttttt::::t3\n"
"$3 E::::::::zt33L$4 @EEEtttt::::z3F\n"
"$3{3=*^```\"*4E3)$4 ;EEEtttt:::::tZ`\n"
"$3 `$4 :EEEEtttt::::z7\n"
" \"VEzjt:;;z>*`"
)
FF_LOGO_COLORS(
"31", //red
"32", //green
"34", //blue
"33" //yellow
)
FF_LOGO_COLOR_KEYS("34"); //blue
FF_LOGO_COLOR_TITLE("32"); //green
FF_LOGO_RETURN
}
static const FFlogo* getLogoNixOS()
{
FF_LOGO_INIT
@@ -2016,6 +2112,9 @@ GetLogoMethod* ffLogoBuiltinGetAll()
getLogoMintSmall,
getLogoMintOld,
getLogoMsys2,
getLogoWindows11,
getLogoWindows8,
getLogoWindows,
getLogoNixOS,
getLogoNixOsOld,
getLogoNixOsSmall,
+1 -1
View File
@@ -2,7 +2,7 @@
#include "common/io.h"
#include "common/printing.h"
#include "detection/os/os.h"
#include "detection/terminalshell.h"
#include "detection/terminalshell/terminalshell.h"
#include <ctype.h>
#include <string.h>
+42
View File
@@ -0,0 +1,42 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "common/caching.h"
#include "detection/bios/bios.h"
#define FF_BIOS_MODULE_NAME "Bios"
#define FF_BIOS_NUM_FORMAT_ARGS 4
void ffPrintBios(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_BIOS_MODULE_NAME, &instance->config.bios, FF_BIOS_NUM_FORMAT_ARGS))
return;
FFBiosResult result;
ffDetectBios(&result);
if(result.error.length > 0)
{
ffPrintError(instance, FF_BIOS_MODULE_NAME, 0, &instance->config.bios, "%*s", result.error.length, result.error.chars);
goto exit;
}
if(result.biosRelease.length == 0)
{
ffPrintError(instance, FF_BIOS_MODULE_NAME, 0, &instance->config.bios, "bios_release is not set.");
goto exit;
}
ffPrintAndWriteToCache(instance, FF_BIOS_MODULE_NAME, &instance->config.bios, &result.biosRelease, FF_BIOS_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosDate},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosRelease},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.biosVersion},
});
exit:
ffStrbufDestroy(&result.biosDate);
ffStrbufDestroy(&result.biosRelease);
ffStrbufDestroy(&result.biosVendor);
ffStrbufDestroy(&result.biosVersion);
ffStrbufDestroy(&result.error);
}
+40
View File
@@ -0,0 +1,40 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "common/caching.h"
#include "detection/board/board.h"
#define FF_BOARD_MODULE_NAME "Board"
#define FF_BOARD_NUM_FORMAT_ARGS 3
void ffPrintBoard(FFinstance* instance)
{
if(ffPrintFromCache(instance, FF_BOARD_MODULE_NAME, &instance->config.board, FF_BOARD_NUM_FORMAT_ARGS))
return;
FFBoardResult result;
ffDetectBoard(&result);
if(result.error.length > 0)
{
ffPrintError(instance, FF_BOARD_MODULE_NAME, 0, &instance->config.board, "%*s", result.error.length, result.error.chars);
goto exit;
}
if(result.boardName.length == 0)
{
ffPrintError(instance, FF_BOARD_MODULE_NAME, 0, &instance->config.board, "board_name is not set.");
goto exit;
}
ffPrintAndWriteToCache(instance, FF_BOARD_MODULE_NAME, &instance->config.board, &result.boardName, FF_BOARD_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &result.boardName},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.boardVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.boardVersion},
});
exit:
ffStrbufDestroy(&result.boardName);
ffStrbufDestroy(&result.boardVendor);
ffStrbufDestroy(&result.boardVersion);
ffStrbufDestroy(&result.error);
}
+2 -37
View File
@@ -1,56 +1,21 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "detection/cpuUsage/cpuUsage.h"
#include <sys/time.h>
#include <time.h>
#define FF_CPU_USAGE_MODULE_NAME "CPU Usage"
#define FF_CPU_USAGE_NUM_FORMAT_ARGS 1
time_t getTimeInMs()
{
struct timeval timeNow;
gettimeofday(&timeNow, NULL);
return (timeNow.tv_sec * 1000) + (timeNow.tv_usec / 1000);
}
static long inUseAll1, totalAll1, startTime;
void ffPrepareCPUUsage()
{
startTime = getTimeInMs();
ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
}
void ffPrintCPUUsage(FFinstance* instance)
{
const char* error = NULL;
if(startTime == 0)
{
error = ffGetCpuUsageInfo(&inUseAll1, &totalAll1);
if(error)
goto error;
nanosleep(&(struct timespec){ 1, 0 }, NULL);
}
else
{
time_t duration = getTimeInMs() - startTime;
if(duration < 1000)
nanosleep(&(struct timespec){ 0, (1000 - duration) * 1000000L }, NULL);
}
long inUseAll2, totalAll2;
error = ffGetCpuUsageInfo(&inUseAll2, &totalAll2);
double cpuPercent = 0.0/0.0;
const char* error = ffGetCpuUsageResult(&cpuPercent);
if(error)
{
error:
ffPrintError(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpu, "%s", error);
return;
}
double cpuPercent = (double)(inUseAll2 - inUseAll1) / (double)(totalAll2 - totalAll1) * 100;
if(instance->config.cpuUsage.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_CPU_USAGE_MODULE_NAME, 0, &instance->config.cpuUsage.key);
+2 -2
View File
@@ -11,7 +11,7 @@
#define FF_CURSOR_MODULE_NAME "Cursor"
#define FF_CURSOR_NUM_FORMAT_ARGS 2
#if !(defined(__ANDROID__) || defined(__APPLE__))
#if !(defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32) || defined(__MSYS__))
static void printCursor(FFinstance* instance, FFstrbuf* cursorTheme, const FFstrbuf* cursorSize)
{
@@ -196,7 +196,7 @@ static bool printCursorFromEnv(FFinstance* instance)
void ffPrintCursor(FFinstance* instance)
{
#if defined(__ANDROID__) || defined(__APPLE__)
#if defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32) || defined(__MSYS__)
FF_UNUSED(instance);
ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor detection is not supported");
+32 -67
View File
@@ -8,111 +8,76 @@
#define FF_DISK_MODULE_NAME "Disk"
#define FF_DISK_NUM_FORMAT_ARGS 4
static void createKey(FFinstance* instance, const char* folderPath, FFstrbuf* key)
static void printFolder(FFinstance* instance, FFDiskResult* folder)
{
FFstrbuf key;
ffStrbufInit(&key);
if(instance->config.disk.key.length == 0)
{
ffStrbufAppendS(key, FF_DISK_MODULE_NAME);
if(folderPath != NULL)
ffStrbufAppendF(key, " (%s)", folderPath);
ffStrbufAppendF(&key, "%s (%*s)", FF_DISK_MODULE_NAME, folder->path.length, folder->path.chars);
}
else
{
ffParseFormatString(key, &instance->config.disk.key, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, folderPath}
ffParseFormatString(&key, &instance->config.disk.key, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &folder->path}
});
}
}
static void printStatvfs(FFinstance* instance, const FFstrbuf* key, const char* folderPath, struct statvfs* fs)
{
uint64_t total = fs->f_blocks * fs->f_frsize;
if(total == 0)
{
ffPrintErrorString(instance, key->chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs for %s returned size 0", folderPath);
return;
}
uint64_t used = total - (fs->f_bavail * fs->f_frsize);
uint32_t files = (uint32_t) (fs->f_files - fs->f_ffree);
uint8_t percentage = (uint8_t) ((used / (long double) total) * 100.0);
uint8_t percentage = (uint8_t) ((folder->used / (long double) folder->total) * 100.0);
FFstrbuf usedPretty;
ffStrbufInit(&usedPretty);
ffParseSize(used, instance->config.binaryPrefixType, &usedPretty);
ffParseSize(folder->used, instance->config.binaryPrefixType, &usedPretty);
FFstrbuf totalPretty;
ffStrbufInit(&totalPretty);
ffParseSize(total, instance->config.binaryPrefixType, &totalPretty);
ffParseSize(folder->total, instance->config.binaryPrefixType, &totalPretty);
if(instance->config.disk.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, key->chars, 0, NULL);
printf("%s / %s (%u%%)\n", usedPretty.chars, totalPretty.chars, percentage);
ffPrintLogoAndKey(instance, key.chars, 0, NULL);
printf("%s / %s (%u%%)%s\n", usedPretty.chars, totalPretty.chars, percentage, folder->removable ? " [Removable]" : "");
}
else
{
ffPrintFormatString(instance, key->chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){
ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.disk.outputFormat, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty},
{FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty},
{FF_FORMAT_ARG_TYPE_UINT8, &percentage},
{FF_FORMAT_ARG_TYPE_UINT, &files},
{FF_FORMAT_ARG_TYPE_UINT, &folder->files},
});
}
ffStrbufDestroy(&key);
ffStrbufDestroy(&totalPretty);
ffStrbufDestroy(&usedPretty);
}
static void printFolder(FFinstance* instance, const char* folderPath)
{
FFstrbuf key;
ffStrbufInit(&key);
createKey(instance, folderPath, &key);
struct statvfs fs;
int ret = statvfs(folderPath, &fs);
if(ret != 0)
{
ffPrintErrorString(instance, key.chars, 0, NULL, &instance->config.disk.errorFormat, "statvfs(\"%s\", &fs) != 0 (%i)", folderPath, ret);
ffStrbufDestroy(&key);
return;
}
printStatvfs(instance, &key, folderPath, &fs);
ffStrbufDestroy(&key);
}
void ffPrintDisk(FFinstance* instance)
{
ffStrbufTrim(&instance->config.diskFolders, ':');
FFlist folders;
ffListInit(&folders, sizeof(FFDiskResult));
if(instance->config.diskFolders.length == 0)
const char* error = NULL;
if(!ffDiskDetectDiskFolders(instance, &folders))
error = ffDiskAutodetectFolders(instance, &folders);
if(error)
{
ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "%s", error);
}
else
{
FFlist folders;
ffListInit(&folders, sizeof(FFstrbuf));
const char* error = ffDiskAutodetectFolders(instance, &folders);
if(error)
ffPrintError(instance, FF_DISK_MODULE_NAME, 0, &instance->config.disk, "%s", error);
for(uint32_t i = 0; i < folders.length; ++i)
{
FFstrbuf* folder = (FFstrbuf*)ffListGet(&folders, i);
printFolder(instance, folder->chars);
ffStrbufDestroy(folder);
FFDiskResult* folder = (FFDiskResult*)ffListGet(&folders, i);
printFolder(instance, folder);
ffStrbufDestroy(&folder->path);
ffStrbufDestroy(&folder->error);
}
ffListDestroy(&folders);
return;
}
uint32_t startIndex = 0;
while(startIndex < instance->config.diskFolders.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&instance->config.diskFolders, startIndex, ':');
instance->config.diskFolders.chars[colonIndex] = '\0';
printFolder(instance, instance->config.diskFolders.chars + startIndex);
startIndex = colonIndex + 1;
}
ffListDestroy(&folders);
}
+10
View File
@@ -40,6 +40,16 @@ static void printFont(const FFFontResult* font)
printf("%s [User]", font->fonts[1].chars);
}
#elif defined(_WIN32) || defined(__MSYS__)
static void printFont(const FFFontResult* font)
{
if(font->fonts[0].length > 0)
{
printf("%s [Desktop]", font->fonts[0].chars);
}
}
#else
static void printFont(const FFFontResult* font)
+1 -1
View File
@@ -14,7 +14,7 @@ static void printGPUResult(FFinstance* instance, uint8_t index, FFcache* cache,
FFstrbuf output;
ffStrbufInitA(&output, gpu->vendor.length + 1 + gpu->name.length);
if(gpu->vendor.length > 0)
if(gpu->vendor.length > 0 && !ffStrbufStartsWith(&gpu->name, &gpu->vendor))
{
ffStrbufAppend(&output, &gpu->vendor);
ffStrbufAppendC(&output, ' ');
+7 -8
View File
@@ -4,7 +4,7 @@
#include "detection/host/host.h"
#define FF_HOST_MODULE_NAME "Host"
#define FF_HOST_NUM_FORMAT_ARGS 15
#define FF_HOST_NUM_FORMAT_ARGS 8
void ffPrintHost(FFinstance* instance)
{
@@ -13,6 +13,12 @@ void ffPrintHost(FFinstance* instance)
const FFHostResult* host = ffDetectHost();
if(host->error.length > 0)
{
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.host, "%*s", host->error.length, host->error.chars);
return;
}
if(host->productFamily.length == 0 && host->productName.length == 0)
{
ffPrintError(instance, FF_HOST_MODULE_NAME, 0, &instance->config.host, "neither product_family nor product_name is set by O.E.M.");
@@ -38,13 +44,6 @@ void ffPrintHost(FFinstance* instance)
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productName},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->productSku},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosDate},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosRelease},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->biosVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardName},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->boardVersion},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisType},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVendor},
{FF_FORMAT_ARG_TYPE_STRBUF, &host->chassisVersion},
+1 -1
View File
@@ -10,7 +10,7 @@
void ffPrintIcons(FFinstance* instance)
{
#if defined(__ANDROID__) || defined(__APPLE__)
#if defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32) || defined(__MSYS__)
FF_UNUSED(instance);
ffPrintError(instance, FF_ICONS_MODULE_NAME, 0, &instance->config.icons, "Icons detection is not supported");
+20 -4
View File
@@ -1,22 +1,38 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "detection/kernel/kernel.h"
#define FF_KERNEL_MODULE_NAME "Kernel"
#define FF_KERNEL_NUM_FORMAT_ARGS 3
void ffPrintKernel(FFinstance* instance)
{
FFKernelResult result;
ffDetectKernel(instance, &result);
if(result.error.length > 0)
{
ffPrintError(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel, "%*s", result.error.length, result.error.chars);
goto exit;
}
if(instance->config.kernel.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel.key);
puts(instance->state.utsname.release);
ffStrbufPutTo(&result.release, stdout);
}
else
{
ffPrintFormat(instance, FF_KERNEL_MODULE_NAME, 0, &instance->config.kernel, FF_KERNEL_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.sysname},
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.release},
{FF_FORMAT_ARG_TYPE_STRING, instance->state.utsname.version}
{FF_FORMAT_ARG_TYPE_STRBUF, &result.sysname},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.release},
{FF_FORMAT_ARG_TYPE_STRBUF, &result.version}
});
}
exit:
ffStrbufDestroy(&result.error);
ffStrbufDestroy(&result.sysname);
ffStrbufDestroy(&result.release);
ffStrbufDestroy(&result.version);
}
-1
View File
@@ -2,7 +2,6 @@
#include "common/properties.h"
#include "common/printing.h"
#include "common/caching.h"
#include "common/processing.h"
#include "common/parsing.h"
#include <stdlib.h>
+50 -74
View File
@@ -1,90 +1,66 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "detection/localip/localip.h"
#define FF_LOCALIP_MODULE_NAME "Local IP"
#define FF_LOCALIP_NUM_FORMAT_ARGS 1
#include <string.h>
#include <ctype.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef __FreeBSD__
#include <sys/socket.h> // FreeBSD needs this for AF_INET
#endif
static void printValue(FFinstance* instance, const char* ifaName, const char* addressBuffer)
{
FFstrbuf key;
ffStrbufInit(&key);
if (instance->config.localIP.key.length == 0)
{
ffStrbufAppendF(&key, FF_LOCALIP_MODULE_NAME " (%s)", ifaName);
}
else
{
ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, ifaName}
});
}
if (instance->config.localIP.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, key.chars, 0, NULL);
puts(addressBuffer);
}
else
{
ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.localIP.outputFormat, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRING, addressBuffer}
});
}
ffStrbufDestroy(&key);
}
#define FF_LOCALIP_NUM_FORMAT_ARGS 2
void ffPrintLocalIp(FFinstance* instance)
{
struct ifaddrs* ifAddrStruct = NULL;
int ret = getifaddrs(&ifAddrStruct);
if (ret < 0) {
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "getifaddrs(&ifAddrStruct) < 0 (%i)", ret);
return;
FFlist results;
ffListInit(&results, sizeof(FFLocalIpResult));
const char* error = ffDetectLocalIps(instance, &results);
if(error)
{
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "%s", error);
goto exit;
}
for (struct ifaddrs* ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
continue;
if(results.length == 0)
{
ffPrintError(instance, FF_LOCALIP_MODULE_NAME, 0, &instance->config.localIP, "Failed to detect any IPs");
goto exit;
}
// loop back
if (strncmp(ifa->ifa_name, "lo", 2) == 0 && (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2])) && !instance->config.localIpShowLoop)
continue;
FFstrbuf key;
ffStrbufInit(&key);
if (instance->config.localIpNamePrefix.length && strncmp(ifa->ifa_name, instance->config.localIpNamePrefix.chars, instance->config.localIpNamePrefix.length) != 0)
continue;
for(uint32_t i = 0; i < results.length; ++i)
{
FFLocalIpResult* ip = (FFLocalIpResult*) ffListGet(&results, i);
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
// is a valid IP4 Address
if (!instance->config.localIpShowIpV4)
continue;
void* tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
printValue(instance, ifa->ifa_name, addressBuffer);
} else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
// is a valid IP6 Address
if (!instance->config.localIpShowIpV6)
continue;
void* tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
printValue(instance, ifa->ifa_name, addressBuffer);
if(instance->config.localIP.key.length == 0)
{
ffStrbufSetF(&key, FF_LOCALIP_MODULE_NAME " (%*s)", ip->name.length, ip->name.chars);
}
else
{
ffParseFormatString(&key, &instance->config.localIP.key, 1, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &ip->name}
});
}
if(instance->config.localIP.outputFormat.length == 0)
{
ffPrintLogoAndKey(instance, key.chars, 0, NULL);
ffStrbufPutTo(&ip->addr, stdout);
}
else
{
ffPrintFormatString(instance, key.chars, 0, NULL, &instance->config.localIP.outputFormat, FF_LOCALIP_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_STRBUF, &ip->addr},
{FF_FORMAT_ARG_TYPE_STRING, ip->ipv6 ? "IPv6" : "IPv4"}
});
}
ffStrbufDestroy(&ip->name);
ffStrbufDestroy(&ip->addr);
}
if (ifAddrStruct) freeifaddrs(ifAddrStruct);
ffStrbufDestroy(&key);
exit:
ffListDestroy(&results);
}
+1 -1
View File
@@ -83,7 +83,7 @@ static const char* printOpenCL(FFinstance* instance)
{
OpenCLData data;
FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL.so failed", "libOpenCL.so", 1);
FF_LIBRARY_LOAD(opencl, &instance->config.libOpenCL, "dlopen libOpenCL"FF_LIBRARY_EXTENSION" failed", "libOpenCL"FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo);

Some files were not shown because too many files have changed in this diff Show More