From bddcb4772c997f0052d18d2313918b6d6fd68760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 29 Aug 2023 10:47:24 +0800 Subject: [PATCH 001/198] DE (FreeBSD): add fast path for xfce4 version detection --- CHANGELOG.md | 7 ++++++- src/common/io/io.h | 22 ++++++++++++++++++++++ src/detection/displayserver/linux/wmde.c | 17 +++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9defef35eb..e158640bc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 2.0.6 + +Features: +* Add fast path for xfce4 version detection (DE, FreeBSD) + # 2.0.5 Bugfixes: @@ -11,7 +16,7 @@ Features: # 2.0.4 Bugfixes: -* Fix building on 32-bit FreeBSD (Memory, BSD) +* Fix building on 32-bit FreeBSD (Memory, FreeBSD) * Fix `--file-raw` doesn't work (Logo) Features: diff --git a/src/common/io/io.h b/src/common/io/io.h index 8cca6e1475..b91ef7a01c 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -12,6 +12,7 @@ typedef HANDLE FFNativeFD; #else #include + #include typedef int FFNativeFD; #endif @@ -130,4 +131,25 @@ static inline bool wrapFclose(FILE** pfile) } #define FF_AUTO_CLOSE_FILE __attribute__((__cleanup__(wrapFclose))) +#ifndef _WIN32 +static inline bool wrapClosedir(DIR** pdir) +{ + assert(pdir); + if (!*pdir) + return false; + closedir(*pdir); + return true; +} +#else +static inline bool wrapClosedir(HANDLE* pdir) +{ + assert(pdir); + if (!*pdir) + return false; + FindClose(*pdir); + return true; +} +#endif +#define FF_AUTO_CLOSE_DIR __attribute__((__cleanup__(wrapClosedir))) + #endif // FF_INCLUDED_common_io_io diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index f1bcea4eee..b34c429f28 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -233,6 +233,23 @@ static void getXFCE4(FFDisplayServerResult* result) ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4); ffParsePropFileData("gtk-doc/html/libxfce4ui/index.html", "

Version", &result->deVersion); + #ifdef __FreeBSD__ + if(result->deVersion.length == 0) + { + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/usr/local/share/licenses/"); + if (dirp) + { + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + if(!ffStrStartsWith(entry->d_name, "xfce-") || !isdigit(entry->d_name[5])) + continue; + ffStrbufAppendS(&result->deVersion, &entry->d_name[5]); + } + } + } + #endif + if(result->deVersion.length == 0 && instance.config.allowSlowOperations) { //This is somewhat slow From a5ee51e1561437df9b57a32b2679813160044c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 28 Aug 2023 13:53:09 +0800 Subject: [PATCH 002/198] Global: use FF_LIST_AUTO_DESTROY --- src/modules/battery/battery.c | 5 +---- src/modules/poweradapter/poweradapter.c | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 4f239650ac..ee4bd5af77 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -76,8 +76,7 @@ static void printBattery(FFBatteryOptions* options, BatteryResult* result, uint8 void ffPrintBattery(FFBatteryOptions* options) { - FFlist results; - ffListInitA(&results, sizeof(BatteryResult), 0); + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(BatteryResult)); const char* error = ffDetectBattery(options, &results); @@ -100,8 +99,6 @@ void ffPrintBattery(FFBatteryOptions* options) if(results.length == 0) ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, "No batteries found"); } - - ffListDestroy(&results); } void ffInitBatteryOptions(FFBatteryOptions* options) diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index 7fcd772af4..efee4a7f32 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -9,8 +9,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) { - FFlist results; - ffListInit(&results, sizeof(PowerAdapterResult)); + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(PowerAdapterResult)); const char* error = ffDetectPowerAdapterImpl(&results); @@ -59,8 +58,6 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) ffStrbufDestroy(&result->name); } } - - ffListDestroy(&results); } void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options) From 21e5df28266e6e014ee8c88494ef39a71d318ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 29 Aug 2023 17:43:39 +0800 Subject: [PATCH 003/198] Global: replace `cpu-usage` to `cpuusage` --- CHANGELOG.md | 3 +++ completions/bash | 2 +- presets/verbose | 2 +- src/data/config_user.txt | 6 +++--- src/fastfetch.c | 4 ++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e158640bc0..1d2b3e3f16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ Features: * Add fast path for xfce4 version detection (DE, FreeBSD) +Bugfixes: +* Fix `fastfetch --config verbose` doesn't work (#547) + # 2.0.5 Bugfixes: diff --git a/completions/bash b/completions/bash index a8db1c6000..9a59d71163 100644 --- a/completions/bash +++ b/completions/bash @@ -24,7 +24,7 @@ __fastfetch_complete_help() "terminal-format" "terminalfont-format" "cpu-format" - "cpu-usage-format" + "cpuusage-format" "gpu-format" "memory-format" "swap-format" diff --git a/presets/verbose b/presets/verbose index 3ed020f193..44c0c3ee95 100644 --- a/presets/verbose +++ b/presets/verbose @@ -16,7 +16,7 @@ --terminal-format Process: {}; Path: {}; Exe: {} --terminalfont-format Pretty: {}; Name: {}; Size: {}; Styles: {} --cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {} ---cpu-usage-format Percentage: {} +--cpuusage-format Percentage: {} --gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}; Type: {} --memory-format Used: {}; Total: {}; Percentage: {} --disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; External: {}; Hidden: {}; Filesystem: {}; Name: {} diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 7bd07a49e0..3d6d0d0f1d 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -360,7 +360,7 @@ #--terminal-key Terminal #--terminalfont-key Terminal Font #--cpu-key CPU -#--cpu-usage-key CPU Usage +#--cpuusage-key CPU Usage #--gpu-key GPU {1} #--memory-key Memory #--swap-key Swap @@ -411,7 +411,7 @@ #--terminal-format #--terminalfont-format #--cpu-format -#--cpu-usage-format +#--cpuusage-format #--gpu-format #--memory-format #--swap-format @@ -459,7 +459,7 @@ #--terminal-key-color #--terminalfont-key-color #--cpu-key-color -#--cpu-usage-key-color +#--cpuusage-key-color #--gpu-key-color #--memory-key-color #--swap-key-color diff --git a/src/fastfetch.c b/src/fastfetch.c index 4c947d5628..e2ef0a7b52 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -307,9 +307,9 @@ static inline void printCommandHelp(const char* command) "Temperature" ); } - else if(ffStrEqualsIgnCase(command, "cpu-usage-format")) + else if(ffStrEqualsIgnCase(command, "cpuusage-format")) { - constructAndPrintCommandHelpFormat("cpu-usage", "{0}%", 1, + constructAndPrintCommandHelpFormat("cpuusage", "{0}%", 1, "CPU usage without percent mark" ); } From 7cb86df48d9e17bbcfb2319b22e015be64d3e756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 22:17:51 +0800 Subject: [PATCH 004/198] Logo: improve performance on Windows for iterm protocol --- src/logo/image/image.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 9277ee3a53..3248aa7563 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -56,11 +56,14 @@ static bool printImageIterm(void) FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&buf); instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; - printf("\033]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\033[9999999D\n\033[%uA", + printf("\033]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:", (unsigned) instance.config.logo.width, (unsigned) instance.config.logo.height, - (unsigned) instance.config.logo.preserveAspectRadio, - base64.chars, + (unsigned) instance.config.logo.preserveAspectRadio + ); + fflush(stdout); + ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &base64); + printf("\a\033[9999999D\n\033[%uA", (unsigned) instance.state.logoHeight ); From 0bda7d80c274aa75dda91acc47aacc0fa35f5c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 22:21:29 +0800 Subject: [PATCH 005/198] Doc: update README for image logo on Windows --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f1a1ebc31..832e0d9810 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ For the image logo, iTerm with iterm image protocol should work. Apple Terminal Note: In Windows 7, 8 and 8.1, [ConEmu](https://conemu.github.io/en/AnsiEscapeCodes.html) is required to run fastfetch due to [the lack of ASCII escape code native support](https://en.wikipedia.org/wiki/ANSI_escape_code#DOS,_OS/2,_and_Windows). In addition, as fastfetch for Windows targets [UCRT](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment) C runtime library, [it must be installed manually](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) as UCRT is only pre-installed in Windows 10 and later. -For the image logo, only chafa is supported due to [a design flaw of ConPTY](https://github.com/microsoft/terminal/issues/1173). In addition, chafa support is not included by default due to the massive dependencies of imagemagick. You must built it yourself. +For the image logo, WezTerm with iterm image protocol is known to work, surprisingly. ### Android From e5c4a6ed2cb50f18891705c2671f8a8918607e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 1 Sep 2023 23:29:23 -0400 Subject: [PATCH 006/198] Logo (Builtin): update EvolutionOS Closes #551 --- src/logo/ascii/evolutionos.txt | 27 +++++++++------------------ src/logo/ascii/evolutionos_old.txt | 18 ++++++++++++++++++ src/logo/builtin.c | 10 ++++++++++ 3 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 src/logo/ascii/evolutionos_old.txt diff --git a/src/logo/ascii/evolutionos.txt b/src/logo/ascii/evolutionos.txt index 7a6622d4a9..654f08cb85 100644 --- a/src/logo/ascii/evolutionos.txt +++ b/src/logo/ascii/evolutionos.txt @@ -1,18 +1,9 @@ - dddddddddddddddddddddddd -.dddd''''''''''''''''''''''dddd. -dd: dddddddddddddddddddd; dd: -dd: ldl:'''''''''''''''' dd: -dd: ldl: dd: -dd: ldl: dd: -dd: ldl: dd: -dd: ldl: dd: -dd: ldl: ddddddd; ddddd; dd: -dd: ldl: ''''''' ''''' dd: -dd: ldl: dd: -dd: ldl: dd: -dd: ldl: dd: -dd: ldl: dd: -dd: ldl: ddddddddddddddd; dd: -dddd:.''' ''''''''''''''' dddd: - dddddddddddddddddddddddddd;;' - ''''''''''''''''''''''''' + ,coddoc' + 'cddddddddddc' + 'ddd${c2}OWWXXXXXXK${c1}ddo. +.dddd${c2}OMX${c1}ddddddddddd. +odddd${c2}OMXk00OkOO${c1}ddddo +.dddd${c2}OMX${c1}kOOOxOkdddd. + .ddd${c2}OWWXXXXXXK${c1}ddd' + 'dddddddddddd' + 'cddddd, diff --git a/src/logo/ascii/evolutionos_old.txt b/src/logo/ascii/evolutionos_old.txt new file mode 100644 index 0000000000..7a6622d4a9 --- /dev/null +++ b/src/logo/ascii/evolutionos_old.txt @@ -0,0 +1,18 @@ + dddddddddddddddddddddddd +.dddd''''''''''''''''''''''dddd. +dd: dddddddddddddddddddd; dd: +dd: ldl:'''''''''''''''' dd: +dd: ldl: dd: +dd: ldl: dd: +dd: ldl: dd: +dd: ldl: dd: +dd: ldl: ddddddd; ddddd; dd: +dd: ldl: ''''''' ''''' dd: +dd: ldl: dd: +dd: ldl: dd: +dd: ldl: dd: +dd: ldl: dd: +dd: ldl: ddddddddddddddd; dd: +dddd:.''' ''''''''''''''' dddd: + dddddddddddddddddddddddddd;;' + ''''''''''''''''''''''''' diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 8793280626..4e838ad692 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1261,6 +1261,16 @@ static const FFlogo E[] = { { .names = {"EvolutionOS"}, .lines = FASTFETCH_DATATEXT_LOGO_EVOLUTIONOS, + .colors = { + FF_COLOR_FG_WHITE, + FF_COLOR_FG_LIGHT_GREEN, + }, + }, + // EvolutionOS_old + { + .names = {"EvolutionOS_old"}, + .lines = FASTFETCH_DATATEXT_LOGO_EVOLUTIONOS_OLD, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .colors = { FF_COLOR_FG_LIGHT_BLUE, FF_COLOR_FG_WHITE, From 3e880fedf78d188e1afe27c8fbd24c1590872b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 00:35:18 -0400 Subject: [PATCH 007/198] Logo: support `kitty-direct` / `iterm` without specifying logo width / height Fixes #550 --- src/logo/image/image.c | 107 ++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 3248aa7563..82be5667e4 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -37,12 +37,6 @@ static FFstrbuf base64Encode(FFstrbuf* in) static bool printImageIterm(void) { - if(instance.config.logo.width == 0 || instance.config.logo.height == 0) - { - fputs("Logo: `iterm` protocol only works when both `--logo-width` and `--logo-height` being specified\n", stderr); - return false; - } - FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); if(!ffAppendFileBuffer(instance.config.logo.source.chars, &buf)) { @@ -50,45 +44,90 @@ static bool printImageIterm(void) return false; } - ffPrintCharTimes('\n', instance.config.logo.paddingTop); - ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + fflush(stdout); FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&buf); - instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; - printf("\033]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:", - (unsigned) instance.config.logo.width, - (unsigned) instance.config.logo.height, - (unsigned) instance.config.logo.preserveAspectRadio - ); - fflush(stdout); - ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &base64); - printf("\a\033[9999999D\n\033[%uA", - (unsigned) instance.state.logoHeight - ); + ffStrbufClear(&buf); + + if (!instance.config.logo.width || !instance.config.logo.height) + { + ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH\e]1337;File=inline=1:%s\a", + (unsigned) instance.config.logo.paddingTop, + (unsigned) instance.config.logo.paddingLeft, + base64.chars + ); + ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); + + uint16_t X = 0, Y = 0; + const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); + if (error) + { + fprintf(stderr, "\nLogo (iterm): fail to query cursor position: %s\n", error); + return true; // We already printed image logo, don't print ascii logo then + } + instance.state.logoWidth = X + instance.config.logo.paddingRight; + instance.state.logoHeight = Y; + fputs("\e[H", stdout); + } + else + { + for (uint32_t i = 0; i < instance.config.logo.paddingTop; ++i) + ffStrbufAppendC(&buf, '\n'); + for (uint32_t i = 0; i < instance.config.logo.paddingLeft; ++i) + ffStrbufAppendC(&buf, ' '); + instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; + instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; + ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\e[9999999D\n\e[%uA", + (unsigned) instance.config.logo.width, + (unsigned) instance.config.logo.height, + (unsigned) instance.config.logo.preserveAspectRadio, + base64.chars, + (unsigned) instance.state.logoHeight + ); + ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); + } return true; } static bool printImageKittyDirect(void) { + FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&instance.config.logo.source); + if (!instance.config.logo.width || !instance.config.logo.height) { - fputs("Logo: `kitty-direct` protocol only works when both `--logo-width` and `--logo-height` being specified\n", stderr); - return false; + // We must clear the entre screen to make sure that terminal buffer won't scroll up + printf("\e[2J\e[3J\e[%u;%uH\e_Ga=T,f=100,t=f;%s\e\\", + (unsigned) instance.config.logo.paddingTop, + (unsigned) instance.config.logo.paddingLeft, + base64.chars + ); + fflush(stdout); + uint16_t X = 0, Y = 0; + const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); + if (error) + { + fprintf(stderr, "\nLogo (kitty-direct): fail to query cursor position: %s\n", error); + return true; // We already printed image logo, don't print ascii logo then + } + instance.state.logoWidth = X + instance.config.logo.paddingRight; + instance.state.logoHeight = Y; + fputs("\e[H", stdout); + } + else + { + ffPrintCharTimes('\n', instance.config.logo.paddingTop); + ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + + instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; + instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; + printf("\e_Ga=T,f=100,t=f,c=%u,r=%u;%s\e\\\e[9999999D\n\e[%uA", + (unsigned) instance.config.logo.width, + (unsigned) instance.config.logo.height, + base64.chars, + (unsigned) instance.state.logoHeight + ); } - ffPrintCharTimes('\n', instance.config.logo.paddingTop); - ffPrintCharTimes(' ', instance.config.logo.paddingLeft); - - FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&instance.config.logo.source); - instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; - printf("\033_Ga=T,f=100,t=f,c=%u,r=%u;%s\033\\\033[9999999D\n\033[%uA", - (unsigned) instance.config.logo.width, - (unsigned) instance.config.logo.height, - base64.chars, - (unsigned) instance.state.logoHeight - ); return true; } From 552e0f84aa3cb47aacdae21a238a65d635055199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 00:46:21 -0400 Subject: [PATCH 008/198] Doc: update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d2b3e3f16..d2b089d0b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ Features: Bugfixes: * Fix `fastfetch --config verbose` doesn't work (#547) +Logo: +* support `kitty-direct` / `iterm` without specifying logo width / height. Note: in this case, the entre screen will be cleared. +* Update EvolutionOS + # 2.0.5 Bugfixes: From 67d04a746e2ebb7b35c67b7c28d86e1e9e258b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 07:40:23 -0400 Subject: [PATCH 009/198] Terminal: support contour version detection --- src/detection/terminalshell/terminalshell.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 18a9b79c8b..72508c954c 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -263,6 +263,20 @@ FF_MAYBE_UNUSED static bool getTerminalVersionXterm(FFstrbuf* exe, FFstrbuf* ver return version->length > 0; } +static bool getTerminalVersionContour(FFstrbuf* exe, FFstrbuf* version) +{ + const char* env = getenv("TERMINAL_VERSION_STRING"); + if (env) + { + ffStrbufAppendS(version, env); + return true; + } + if(!getExeVersionRaw(exe, version)) return false; + // Contour Terminal Emulator 0.3.12.262 + ffStrbufSubstrAfterFirstC(version, ' '); + return version->length > 0; +} + #ifdef _WIN32 static bool getTerminalVersionWindowsTerminal(FFstrbuf* exe, FFstrbuf* version) @@ -361,6 +375,9 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe if(ffStrbufStartsWithIgnCaseS(processName, "alacritty")) return getExeVersionGeneral(exe, version); + if(ffStrbufStartsWithIgnCaseS(processName, "contour")) + return getTerminalVersionContour(exe, version); + const char* termProgramVersion = getenv("TERM_PROGRAM_VERSION"); if(termProgramVersion) { From 34417ae69299696e7325564c8df405d062cdbd22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 08:07:28 -0400 Subject: [PATCH 010/198] TerminalFont: support contour --- CHANGELOG.md | 1 + src/detection/terminalfont/terminalfont.c | 31 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2b089d0b9..7b9597dc75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Features: * Add fast path for xfce4 version detection (DE, FreeBSD) +* Add contour terminal version and font detection (Terminal / TerminalFont) Bugfixes: * Fix `fastfetch --config verbose` doesn't work (#547) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 8fcb7db6c7..01931b8610 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -338,6 +338,35 @@ static bool detectTabby(FFTerminalFontResult* result) return true; } +static bool detectContour(const FFstrbuf* exe, FFTerminalFontResult* result) +{ + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + if(ffProcessAppendStdOut(&buf, (char* const[]){ + exe->chars, + "font-locator", + NULL + })) + { + ffStrbufAppendS(&result->error, "`contour font-locator` failed"); + return false; + } + + //[error] Missing key .logging.enabled. Using default: false. + //[error] ... + //Matching fonts using : Fontconfig + //Font description : (family=Sarasa Term SC Nerd weight=Regular slant=Roman spacing=Monospace, strict_spacing=yes) + //Number of fonts found : 49 + // path /usr/share/fonts/google-noto/NotoSansMono-Regular.ttf Regular Roman + // path ... + + uint32_t index = ffStrbufFirstIndexS(&buf, "Font description : (family="); + if(index >= buf.length) return false; + index += strlen("Font description : (family="); + ffStrbufSubstrBefore(&buf, ffStrbufNextIndexS(&buf, index, " weight=")); + ffFontInitCopy(&result->font, buf.chars + index); + return true; +} + void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont); static bool detectTerminalFontCommon(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) @@ -350,6 +379,8 @@ static bool detectTerminalFontCommon(const FFTerminalShellResult* terminalShell, detectWezterm(terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "tabby")) detectTabby(terminalFont); + else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalProcessName, "contour")) + detectContour(&terminalShell->terminalExe, terminalFont); #ifndef _WIN32 else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/pts/")) From 04d56d9b6a0b92c5fc1016eb23c7e2069fefb44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 10:04:57 -0400 Subject: [PATCH 011/198] IO: fix short read when reading from pipe --- src/common/io/io_unix.c | 12 ++++-------- src/common/io/io_windows.c | 8 +++----- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 1941e6637a..fbfa55b56c 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -54,24 +54,20 @@ bool ffAppendFDBuffer(int fd, FFstrbuf* buffer) uint32_t free = ffStrbufGetFree(buffer); while( - (readed = read(fd, buffer->chars + buffer->length, free)) > 0 && - (uint32_t) readed == free + (readed = read(fd, buffer->chars + buffer->length, free)) > 0 ) { buffer->length += (uint32_t) readed; - ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. + if((uint32_t) readed == free) + ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. free = ffStrbufGetFree(buffer); } - // In case of failure, read returns -1. We don't want to substract the length of the buffer. - if(readed > 0) - buffer->length += (uint32_t) readed; - buffer->chars[buffer->length] = '\0'; ffStrbufTrimRight(buffer, '\n'); ffStrbufTrimRight(buffer, ' '); - return readed >= 0; + return buffer->length > 0; } ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 2cd916bd8d..c007060829 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -44,16 +44,14 @@ bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer) bool success; while( (success = !!ReadFile(handle, buffer->chars + buffer->length, free, &readed, NULL)) && - (uint32_t) readed == free + readed > 0 ) { buffer->length += (uint32_t) readed; - ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. + if((uint32_t) readed == free) + ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. free = ffStrbufGetFree(buffer); } - if(readed > 0) - buffer->length += (uint32_t) readed; - buffer->chars[buffer->length] = '\0'; ffStrbufTrimRight(buffer, '\n'); From 3692e49e9bdd92208978bfcba7da3d3a5795a3ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 10:05:30 -0400 Subject: [PATCH 012/198] TerminalShell: correctly set PATH_MAX on Linux --- src/detection/terminalshell/terminalshell_linux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 58e29f1f8e..9d30b2be08 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -331,6 +331,8 @@ const FFTerminalShellResult* ffDetectTerminalShell() const uint32_t exePathLen = PROC_PIDPATHINFO_MAXSIZE; #elif defined(MAXPATH) const uint32_t exePathLen = MAXPATH; + #elif defined(PATH_MAX) + const uint32_t exePathLen = PATH_MAX; #else const uint32_t exePathLen = 260; #endif From effb685fba19c6018435e311f4d8e6d203ef3742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 10:08:08 -0400 Subject: [PATCH 013/198] Logo: try improving performance for `image-raw` --- src/logo/logo.c | 50 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/logo/logo.c b/src/logo/logo.c index 9206a5ab17..fe068bad1e 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -19,16 +19,40 @@ typedef enum FFLogoSize static void ffLogoPrintCharsRaw(const char* data, size_t length) { FFLogoOptions* options = &instance.config.logo; + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); - if (instance.config.brightColor) - fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); - - ffPrintCharTimes('\n', options->paddingTop); - ffPrintCharTimes(' ', options->paddingLeft); - fwrite(data, length, 1, stdout); - instance.state.logoHeight = options->paddingTop + options->height; - instance.state.logoWidth = options->paddingLeft + options->width + options->paddingRight; - printf("\033[9999999D\n\033[%uA", instance.state.logoHeight); + if (!options->width || !options->height) + { + ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH", + (unsigned) options->paddingTop, + (unsigned) options->paddingLeft + ); + ffStrbufAppendNS(&buf, (uint32_t) length, data); + ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); + + uint16_t X = 0, Y = 0; + const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); + if (error) + { + fprintf(stderr, "\nLogo (image-raw): fail to query cursor position: %s\n", error); + return; + } + instance.state.logoWidth = X + instance.config.logo.paddingRight; + instance.state.logoHeight = Y; + fputs("\e[H", stdout); + } + else + { + for (uint32_t i = 0; i < options->paddingTop; ++i) + ffStrbufAppendC(&buf, '\n'); + for (uint32_t i = 0; i < options->paddingLeft; ++i) + ffStrbufAppendC(&buf, ' '); + ffStrbufAppendNS(&buf, (uint32_t) length, data); + instance.state.logoHeight = options->paddingTop + options->height; + instance.state.logoWidth = options->paddingLeft + options->width + options->paddingRight; + ffStrbufAppendF(&buf, "\e[9999999D\n\e[%uA", instance.state.logoHeight); + ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); + } } void ffLogoPrintChars(const char* data, bool doColorReplacement) @@ -417,15 +441,7 @@ static bool logoTryKnownType(void) return logoPrintFileIfExists(false, false); if(options->type == FF_LOGO_TYPE_IMAGE_RAW) - { - if(options->width == 0 || options->height == 0) - { - fputs("both `--logo-width` and `--logo-height` must be specified\n", stderr); - return false; - } - return logoPrintFileIfExists(false, true); - } return logoPrintImageIfExists(options->type, true); } From 4dfbc0f9098b3d822abad5afd810ebebba456def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 2 Sep 2023 22:32:34 +0800 Subject: [PATCH 014/198] Logo: try fixing #553 --- src/logo/image/image.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 82be5667e4..ee0fa35745 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -247,19 +247,16 @@ static void printImagePixels(FFLogoRequestData* requestData, const FFstrbuf* res { //Calculate character dimensions instance.state.logoWidth = requestData->logoCharacterWidth + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - - instance.state.logoHeight = requestData->logoCharacterHeight + instance.config.logo.paddingTop; - if(requestData->type == FF_LOGO_TYPE_IMAGE_KITTY) - instance.state.logoHeight -= 1; + instance.state.logoHeight = requestData->logoCharacterHeight + instance.config.logo.paddingTop - 1; //Write cache files writeCacheStrbuf(requestData, result, cacheFileName); if(instance.config.logo.width == 0) - writeCacheUint32(requestData, instance.state.logoWidth, FF_CACHE_FILE_WIDTH); + writeCacheUint32(requestData, requestData->logoCharacterWidth, FF_CACHE_FILE_WIDTH); if(instance.config.logo.height == 0) - writeCacheUint32(requestData, instance.state.logoHeight, FF_CACHE_FILE_HEIGHT); + writeCacheUint32(requestData, requestData->logoCharacterHeight, FF_CACHE_FILE_HEIGHT); //Write result to stdout ffPrintCharTimes('\n', instance.config.logo.paddingTop); @@ -575,10 +572,7 @@ static uint32_t readCachedUint32(FFLogoRequestData* requestData, const char* cac uint32_t result = 0; if(content.length != sizeof(result)) - { - ffStrbufDestroy(&content); return 0; - } memcpy(&result, content.chars, sizeof(result)); From 9500ca8f837cbd4083a1ccb18959197d2616225d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 17:49:29 +0800 Subject: [PATCH 015/198] Logo: fix `poll() timeout or failed` error when image is very large Fix #554 --- src/common/io/io.h | 2 ++ src/common/io/io_unix.c | 2 +- src/common/io/io_windows.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/io/io.h b/src/common/io/io.h index b91ef7a01c..78c94ad9f8 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -85,6 +85,8 @@ typedef enum FFPathType bool ffPathExists(const char* path, FFPathType pathType); bool ffPathExpandEnv(const char* in, FFstrbuf* out); +#define FF_IO_TERM_RESP_WAIT_MS 100 // #554 + FF_C_SCANF(2, 3) const char* ffGetTerminalResponse(const char* request, const char* format, ...); diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index fbfa55b56c..db5f3c65b7 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -146,7 +146,7 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...) fflush(stdout); //Give the terminal 35ms to respond - if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, 35) <= 0) + if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, FF_IO_TERM_RESP_WAIT_MS) <= 0) { tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm); return "poll() timeout or failed"; diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index c007060829..c4c26145b4 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -171,7 +171,7 @@ const char* ffGetTerminalResponse(const char* request, const char* format, ...) while (true) { - if (WaitForSingleObjectEx(hInput, 35, TRUE) != WAIT_OBJECT_0) + if (WaitForSingleObjectEx(hInput, FF_IO_TERM_RESP_WAIT_MS, TRUE) != WAIT_OBJECT_0) { SetConsoleMode(hInput, prev_mode); return "WaitForSingleObject() failed or timeout"; From 33f121d7fbb684d53417973da7ed8edd145dfbb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 19:01:52 +0800 Subject: [PATCH 016/198] JsonSchema: fix the name of property `defaultRouteOnly` --- doc/json_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 60c3c52592..dc6e284866 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -989,7 +989,7 @@ "title": "Show IPs with given name prefix only", "type": "string" }, - "showDefaultRouteOnly": { + "defaultRouteOnly": { "title": "Show ips that are used for default routing only", "type": "boolean", "default": false From 9e839d3b8bbd2f84279fe03bdc50142e60ac0dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 19:55:57 +0800 Subject: [PATCH 017/198] Logo: simplify code --- src/logo/image/image.c | 9 ++++----- src/logo/logo.c | 10 +++------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index ee0fa35745..dc0d7e0522 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -77,7 +77,7 @@ static bool printImageIterm(void) ffStrbufAppendC(&buf, ' '); instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; - ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\e[9999999D\n\e[%uA", + ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\n\e[%uA", (unsigned) instance.config.logo.width, (unsigned) instance.config.logo.height, (unsigned) instance.config.logo.preserveAspectRadio, @@ -121,7 +121,7 @@ static bool printImageKittyDirect(void) instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; - printf("\e_Ga=T,f=100,t=f,c=%u,r=%u;%s\e\\\e[9999999D\n\e[%uA", + printf("\e_Ga=T,f=100,t=f,c=%u,r=%u;%s\e\\\n\e[%uA", (unsigned) instance.config.logo.width, (unsigned) instance.config.logo.height, base64.chars, @@ -265,8 +265,7 @@ static void printImagePixels(FFLogoRequestData* requestData, const FFstrbuf* res ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), result); //Go to upper left corner - fputs("\033[9999999D", stdout); - printf("\033[%uA", instance.state.logoHeight); + printf("\e[1G\e[%uA", instance.state.logoHeight); } static bool printImageSixel(FFLogoRequestData* requestData, const ImageData* imageData) @@ -639,7 +638,7 @@ static bool printCachedPixel(FFLogoRequestData* requestData) instance.state.logoHeight = requestData->logoCharacterHeight + instance.config.logo.paddingTop; //Go to upper left corner - printf("\033[9999999D\033[%uA", instance.state.logoHeight); + printf("\e[1G\e[%uA", instance.state.logoHeight); return true; } diff --git a/src/logo/logo.c b/src/logo/logo.c index fe068bad1e..c0aa519f58 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -50,7 +50,7 @@ static void ffLogoPrintCharsRaw(const char* data, size_t length) ffStrbufAppendNS(&buf, (uint32_t) length, data); instance.state.logoHeight = options->paddingTop + options->height; instance.state.logoWidth = options->paddingLeft + options->width + options->paddingRight; - ffStrbufAppendF(&buf, "\e[9999999D\n\e[%uA", instance.state.logoHeight); + ffStrbufAppendF(&buf, "\n\e[%uA", instance.state.logoHeight); ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); } } @@ -197,12 +197,8 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) instance.state.logoWidth += options->paddingLeft + options->paddingRight; - //Go to the leftmost position - fputs("\033[9999999D", stdout); - - //If the logo height is > 1, go up the height - if(instance.state.logoHeight > 0) - printf("\033[%uA", instance.state.logoHeight); + //Go to the leftmost position and go up the height + printf("\e[1G\e[%uA", instance.state.logoHeight); } static void logoApplyColors(const FFlogo* logo) From 3483673ef72a2081c27dd161a9c4628361c56d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 20:49:46 +0800 Subject: [PATCH 018/198] Terminal (Android): fix termux detection --- src/detection/terminalfont/terminalfont_android.c | 2 +- src/detection/terminalshell/terminalshell.c | 2 +- src/detection/terminalshell/terminalshell_linux.c | 10 ++++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/detection/terminalfont/terminalfont_android.c b/src/detection/terminalfont/terminalfont_android.c index ae79a4517a..bced44147c 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -55,7 +55,7 @@ const char* detectTermux(FFTerminalFontResult* terminalFont) void ffDetectTerminalFontPlatform(const FFTerminalShellResult* terminalShell, FFTerminalFontResult* terminalFont) { - if(ffStrbufCompS(&terminalShell->terminalProcessName, "Termux") != 0) + if(ffStrbufCompS(&terminalShell->terminalProcessName, "com.termux") != 0) { ffStrbufSetS(&terminalFont->error, "Unsupported terminal"); return; diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 72508c954c..110ae7512a 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -310,7 +310,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe { #ifdef __ANDROID__ - if(ffStrbufEqualS(processName, "Termux")) + if(ffStrbufEqualS(processName, "com.termux")) return getTerminalVersionTermux(version); #endif diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 9d30b2be08..3eabaa6f66 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -237,7 +237,7 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) getenv("TERMUX_VERSION") != NULL || getenv("TERMUX_MAIN_PACKAGE_FORMAT") != NULL || getenv("TMUX_TMPDIR") != NULL - )) term = "Termux"; + )) term = "com.termux"; #endif #ifdef __linux__ @@ -390,7 +390,13 @@ const FFTerminalShellResult* ffDetectTerminalShell() if(ffStrbufEqualS(&result.terminalProcessName, "wezterm-gui")) ffStrbufInitStatic(&result.terminalPrettyName, "WezTerm"); - #if defined(__linux__) || defined(__FreeBSD__) + + #if defined(__ANDROID__) + + else if(ffStrbufEqualS(&result.terminalProcessName, "com.termux")) + ffStrbufInitStatic(&result.terminalPrettyName, "Termux"); + + #elif defined(__linux__) || defined(__FreeBSD__) else if(ffStrbufStartsWithS(&result.terminalProcessName, "gnome-terminal-")) ffStrbufInitStatic(&result.terminalPrettyName, "gnome-terminal"); From fc61f64630c2a1517685a27a084d55c59fcc8ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 22:20:11 +0800 Subject: [PATCH 019/198] Logo: add `--logo-separate true` --- doc/json_schema.json | 5 ++ src/logo/image/image.c | 111 ++++++++++++++++++++++++++++------------- src/logo/logo.c | 21 +++++--- src/logo/option.c | 8 +++ src/logo/option.h | 1 + 5 files changed, 104 insertions(+), 42 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index dc6e284866..b07bd08fb3 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -166,6 +166,11 @@ "title": "If true, regenerate image logo cache", "default": false }, + "separate": { + "type": "boolean", + "title": "If true, print modules at bottom of the logo", + "default": false + }, "chafa": { "type": "object", "title": "Chafa configuration. See chafa document for details", diff --git a/src/logo/image/image.c b/src/logo/image/image.c index dc0d7e0522..3cd7c62946 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -51,23 +51,36 @@ static bool printImageIterm(void) if (!instance.config.logo.width || !instance.config.logo.height) { - ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH\e]1337;File=inline=1:%s\a", - (unsigned) instance.config.logo.paddingTop, - (unsigned) instance.config.logo.paddingLeft, + if (!instance.config.logo.separate) + { + ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH", + (unsigned) instance.config.logo.paddingTop, + (unsigned) instance.config.logo.paddingLeft + ); + } + ffStrbufAppendF(&buf, "\e]1337;File=inline=1:%s\a", base64.chars ); ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); - uint16_t X = 0, Y = 0; - const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); - if (error) + if (!instance.config.logo.separate) { - fprintf(stderr, "\nLogo (iterm): fail to query cursor position: %s\n", error); - return true; // We already printed image logo, don't print ascii logo then + uint16_t X = 0, Y = 0; + const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); + if (error) + { + fprintf(stderr, "\nLogo (iterm): fail to query cursor position: %s\n", error); + return true; // We already printed image logo, don't print ascii logo then + } + instance.state.logoWidth = X + instance.config.logo.paddingRight; + instance.state.logoHeight = Y; + fputs("\e[H", stdout); + } + else + { + instance.state.logoWidth = instance.state.logoHeight = 0; + ffPrintCharTimes('\n', instance.config.logo.paddingRight); } - instance.state.logoWidth = X + instance.config.logo.paddingRight; - instance.state.logoHeight = Y; - fputs("\e[H", stdout); } else { @@ -75,15 +88,24 @@ static bool printImageIterm(void) ffStrbufAppendC(&buf, '\n'); for (uint32_t i = 0; i < instance.config.logo.paddingLeft; ++i) ffStrbufAppendC(&buf, ' '); - instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; - ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\n\e[%uA", + ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\n", (unsigned) instance.config.logo.width, (unsigned) instance.config.logo.height, (unsigned) instance.config.logo.preserveAspectRadio, - base64.chars, - (unsigned) instance.state.logoHeight + base64.chars ); + + if (!instance.config.logo.separate) + { + instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; + instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; + ffStrbufAppendF(&buf, "\e[%uA", (unsigned) instance.state.logoHeight); + } + else + { + instance.state.logoWidth = instance.state.logoHeight = 0; + ffPrintCharTimes('\n', instance.config.logo.paddingRight); + } ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); } @@ -96,37 +118,56 @@ static bool printImageKittyDirect(void) if (!instance.config.logo.width || !instance.config.logo.height) { - // We must clear the entre screen to make sure that terminal buffer won't scroll up - printf("\e[2J\e[3J\e[%u;%uH\e_Ga=T,f=100,t=f;%s\e\\", - (unsigned) instance.config.logo.paddingTop, - (unsigned) instance.config.logo.paddingLeft, - base64.chars - ); + if (!instance.config.logo.separate) + { + // We must clear the entre screen to make sure that terminal buffer won't scroll up + printf("\e[2J\e[3J\e[%u;%uH", + (unsigned) instance.config.logo.paddingTop, + (unsigned) instance.config.logo.paddingLeft + ); + } + printf("\e_Ga=T,f=100,t=f;%s\e\\", base64.chars); fflush(stdout); - uint16_t X = 0, Y = 0; - const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); - if (error) + if (!instance.config.logo.separate) + { + uint16_t X = 0, Y = 0; + const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); + if (error) + { + fprintf(stderr, "\nLogo (kitty-direct): fail to query cursor position: %s\n", error); + return true; // We already printed image logo, don't print ascii logo then + } + instance.state.logoWidth = X + instance.config.logo.paddingRight; + instance.state.logoHeight = Y; + fputs("\e[H", stdout); + } + else { - fprintf(stderr, "\nLogo (kitty-direct): fail to query cursor position: %s\n", error); - return true; // We already printed image logo, don't print ascii logo then + instance.state.logoWidth = instance.state.logoHeight = 0; + ffPrintCharTimes('\n', instance.config.logo.paddingRight); } - instance.state.logoWidth = X + instance.config.logo.paddingRight; - instance.state.logoHeight = Y; - fputs("\e[H", stdout); } else { ffPrintCharTimes('\n', instance.config.logo.paddingTop); ffPrintCharTimes(' ', instance.config.logo.paddingLeft); - instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; - printf("\e_Ga=T,f=100,t=f,c=%u,r=%u;%s\e\\\n\e[%uA", + printf("\e_Ga=T,f=100,t=f,c=%u,r=%u;%s\e\\\n", (unsigned) instance.config.logo.width, (unsigned) instance.config.logo.height, - base64.chars, - (unsigned) instance.state.logoHeight + base64.chars ); + if (!instance.config.logo.separate) + { + instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; + instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; + printf("\e[%uA", (unsigned) instance.state.logoHeight); + } + else + { + instance.state.logoWidth = instance.state.logoHeight = 0; + ffPrintCharTimes('\n', instance.config.logo.paddingRight); + } } return true; diff --git a/src/logo/logo.c b/src/logo/logo.c index c0aa519f58..af240c5493 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -188,17 +188,24 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) } } - ffPrintCharTimes(' ', options->paddingRight); fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); - //Happens if the last line is the longest - if(currentlineLength > instance.state.logoWidth) - instance.state.logoWidth = currentlineLength; + if(!options->separate) + { + //Happens if the last line is the longest + if(currentlineLength > instance.state.logoWidth) + instance.state.logoWidth = currentlineLength; - instance.state.logoWidth += options->paddingLeft + options->paddingRight; + instance.state.logoWidth += options->paddingLeft + options->paddingRight; - //Go to the leftmost position and go up the height - printf("\e[1G\e[%uA", instance.state.logoHeight); + //Go to the leftmost position and go up the height + printf("\e[1G\e[%uA", instance.state.logoHeight); + } + else + { + instance.state.logoWidth = instance.state.logoHeight = 0; + ffPrintCharTimes('\n', options->paddingRight); + } } static void logoApplyColors(const FFlogo* logo) diff --git a/src/logo/option.c b/src/logo/option.c index 59474a2d32..32114de227 100644 --- a/src/logo/option.c +++ b/src/logo/option.c @@ -17,6 +17,7 @@ void ffInitLogoOptions(FFLogoOptions* options) options->printRemaining = true; options->preserveAspectRadio = false; options->recache = false; + options->separate = false; options->chafaFgOnly = false; ffStrbufInitStatic(&options->chafaSymbols, "block+border+space-wide-inverted"); // Chafa default @@ -116,6 +117,8 @@ bool ffParseLogoCommandOptions(FFLogoOptions* options, const char* key, const ch options->preserveAspectRadio = ffOptionParseBoolean(value); else if(strcasecmp(subKey, "recache") == 0) options->recache = ffOptionParseBoolean(value); + else if(strcasecmp(subKey, "separate") == 0) + options->separate = ffOptionParseBoolean(value); else return false; } @@ -342,6 +345,11 @@ const char* ffParseLogoJsonConfig(void) options->recache = yyjson_get_bool(val); continue; } + else if (strcasecmp(key, "separate") == 0) + { + options->separate = yyjson_get_bool(val); + continue; + } else if (strcasecmp(key, "chafa") == 0) { if (!yyjson_is_obj(val)) diff --git a/src/logo/option.h b/src/logo/option.h index 1eb41c1e90..9273e2a3f2 100644 --- a/src/logo/option.h +++ b/src/logo/option.h @@ -36,6 +36,7 @@ typedef struct FFLogoOptions bool printRemaining; bool preserveAspectRadio; bool recache; + bool separate; bool chafaFgOnly; FFstrbuf chafaSymbols; From b863e65ea328021e91a30c92eef9be71aabf0c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 22:21:53 +0800 Subject: [PATCH 020/198] OpenGL: silence warnings --- src/detection/opengl/opengl_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/opengl/opengl_linux.c b/src/detection/opengl/opengl_linux.c index 8da49361b8..8ea44355d9 100644 --- a/src/detection/opengl/opengl_linux.c +++ b/src/detection/opengl/opengl_linux.c @@ -363,7 +363,7 @@ const char* ffDetectOpenGL(FFOpenGLOptions* options, FFOpenGLResult* result) #else - FF_UNUSED(result); + FF_UNUSED(options, result); return "Fastfetch was built without gl support."; #endif //FF_HAVE_GL From 591fd558e115b9b036baf339a1b52d98bddfb39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 22:39:09 +0800 Subject: [PATCH 021/198] Logo: fix `--logo-padding` for `--logo-separate` --- src/logo/image/image.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 3cd7c62946..16792842fb 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -58,6 +58,13 @@ static bool printImageIterm(void) (unsigned) instance.config.logo.paddingLeft ); } + else + { + for (uint32_t i = 0; i < instance.config.logo.paddingTop; ++i) + ffStrbufAppendC(&buf, '\n'); + for (uint32_t i = 0; i < instance.config.logo.paddingLeft; ++i) + ffStrbufAppendC(&buf, ' '); + } ffStrbufAppendF(&buf, "\e]1337;File=inline=1:%s\a", base64.chars ); @@ -126,6 +133,11 @@ static bool printImageKittyDirect(void) (unsigned) instance.config.logo.paddingLeft ); } + else + { + ffPrintCharTimes('\n', instance.config.logo.paddingTop); + ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + } printf("\e_Ga=T,f=100,t=f;%s\e\\", base64.chars); fflush(stdout); if (!instance.config.logo.separate) From 10853fdf3507cb55f8d2f87a578d0c4251936a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 3 Sep 2023 22:51:28 +0800 Subject: [PATCH 022/198] Doc: add note for image protocol support of Android --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 832e0d9810..ada5be426c 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,8 @@ For the image logo, WezTerm with iterm image protocol is known to work, surprisi * [`termux-api`](https://github.com/termux/termux-api-package): Used for Wifi / Battery detection. Read [the official doc](https://wiki.termux.com/wiki/Termux:API) for detail or if you hang on these modules (IMPORTANT). [`termux-api`](https://github.com/termux/termux-packages/tree/master/packages/termux-api) * [`libandroid-wordexp-static`](https://github.com/termux/termux-packages/tree/master/packages/libandroid-wordexp): `wordexp.h` support for Android. +For the image logo, [Termux Monet](https://github.com/HardcodedCat/termux-monet) supports iterm image protocol. + ## Support status All categories not listed here should work without needing a specific implementation. From 2f46a77ff213e2bf7e2d107ed7cf18fed51fef4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 4 Sep 2023 19:19:55 +0800 Subject: [PATCH 023/198] TerminalFont: better kitty font detection --- src/detection/terminalfont/terminalfont.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 01931b8610..7f26d402af 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -237,7 +237,7 @@ static void detectFromWindowsTeriminal(const FFstrbuf* terminalExe, FFTerminalFo #endif //defined(_WIN32) || defined(__linux__) -FF_MAYBE_UNUSED static bool detectKitty(FFTerminalFontResult* result) +FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResult* result) { FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); @@ -247,6 +247,23 @@ FF_MAYBE_UNUSED static bool detectKitty(FFTerminalFontResult* result) {"font_size ", &fontSize}, }; + if(instance.config.allowSlowOperations) + { + FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); + if(!ffProcessAppendStdOut(&buf, (char* const[]){ + exe->chars, + "+kitten", + "query-terminal", + NULL, + })) + { + ffParsePropLines(buf.chars, "font_family: ", &fontName); + ffParsePropLines(buf.chars, "font_size: ", &fontSize); + ffFontInitValues(&result->font, fontName.chars, fontSize.chars); + return true; + } + } + if(!ffParsePropFileConfigValues("kitty/kitty.conf", 2, fontQuery)) return false; @@ -386,7 +403,7 @@ static bool detectTerminalFontCommon(const FFTerminalShellResult* terminalShell, else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/pts/")) ffStrbufAppendS(&terminalFont->error, "Terminal font detection is not supported on PTS"); else if(ffStrbufIgnCaseEqualS(&terminalShell->terminalProcessName, "kitty")) - detectKitty(terminalFont); + detectKitty(&terminalShell->terminalExe, terminalFont); else if(ffStrbufStartsWithIgnCaseS(&terminalShell->terminalExe, "/dev/tty")) detectTTY(terminalFont); #endif From 14f26879deb34175695ab95a60965d0cb6f87dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 29 Aug 2023 11:13:55 +0800 Subject: [PATCH 024/198] Global: init `--format json` support (#527) --- src/common/commandoption.c | 95 +++++++++++++++++++- src/common/commandoption.h | 17 ++++ src/common/init.c | 8 +- src/common/jsonconfig.c | 40 +++++++-- src/common/jsonconfig.h | 7 ++ src/common/option.h | 7 +- src/fastfetch.c | 115 +++++++----------------- src/fastfetch.h | 1 + src/logo/logo.c | 2 +- src/modules/battery/battery.c | 36 +++++++- src/modules/battery/battery.h | 1 + src/modules/bios/bios.c | 38 +++++++- src/modules/bios/bios.h | 1 + src/modules/bluetooth/bluetooth.c | 2 +- src/modules/board/board.c | 2 +- src/modules/break/break.c | 2 +- src/modules/brightness/brightness.c | 2 +- src/modules/chassis/chassis.c | 2 +- src/modules/colors/colors.c | 2 +- src/modules/command/command.c | 2 +- src/modules/cpu/cpu.c | 2 +- src/modules/cpuusage/cpuusage.c | 2 +- src/modules/cursor/cursor.c | 2 +- src/modules/custom/custom.c | 2 +- src/modules/datetime/datetime.c | 2 +- src/modules/de/de.c | 2 +- src/modules/disk/disk.c | 2 +- src/modules/display/display.c | 2 +- src/modules/font/font.c | 2 +- src/modules/gamepad/gamepad.c | 2 +- src/modules/gpu/gpu.c | 2 +- src/modules/host/host.c | 2 +- src/modules/icons/icons.c | 2 +- src/modules/kernel/kernel.c | 2 +- src/modules/lm/lm.c | 2 +- src/modules/locale/locale.c | 2 +- src/modules/localip/localip.c | 2 +- src/modules/media/media.c | 2 +- src/modules/memory/memory.c | 2 +- src/modules/monitor/monitor.c | 2 +- src/modules/opencl/opencl.c | 2 +- src/modules/opengl/opengl.c | 2 +- src/modules/os/os.c | 2 +- src/modules/packages/packages.c | 2 +- src/modules/player/player.c | 2 +- src/modules/poweradapter/poweradapter.c | 2 +- src/modules/processes/processes.c | 2 +- src/modules/publicip/publicip.c | 2 +- src/modules/separator/separator.c | 2 +- src/modules/shell/shell.c | 2 +- src/modules/sound/sound.c | 2 +- src/modules/swap/swap.c | 2 +- src/modules/terminal/terminal.c | 2 +- src/modules/terminalfont/terminalfont.c | 2 +- src/modules/terminalsize/terminalsize.c | 2 +- src/modules/theme/theme.c | 2 +- src/modules/title/title.c | 2 +- src/modules/uptime/uptime.c | 2 +- src/modules/users/users.c | 2 +- src/modules/version/version.c | 2 +- src/modules/vulkan/vulkan.c | 2 +- src/modules/wallpaper/wallpaper.c | 2 +- src/modules/weather/weather.c | 2 +- src/modules/wifi/wifi.c | 2 +- src/modules/wm/wm.c | 2 +- src/modules/wmtheme/wmtheme.c | 2 +- 66 files changed, 321 insertions(+), 153 deletions(-) diff --git a/src/common/commandoption.c b/src/common/commandoption.c index 510ac61a9e..934c52ef1d 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -1,7 +1,26 @@ #include "commandoption.h" +#include "common/printing.h" +#include "common/time.h" +#include "fastfetch_datatext.h" +#include "modules/modules.h" #include "util/stringUtils.h" #include +#include + +static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo) +{ + yyjson_mut_doc* doc = instance.state.resultDoc; + if (__builtin_expect(!doc, true)) return NULL; + + yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root); + yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name); + if (baseInfo->generateJson) + baseInfo->generateJson(baseInfo, doc, module); + else + yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format"); + return module; +} bool ffParseModuleCommand(const char* type) { @@ -12,7 +31,8 @@ bool ffParseModuleCommand(const char* type) FFModuleBaseInfo* baseInfo = *modules; if (ffStrEqualsIgnCase(type, baseInfo->name)) { - baseInfo->printModule(baseInfo); + if (!genJson(baseInfo)) + baseInfo->printModule(baseInfo); return true; } } @@ -30,3 +50,76 @@ bool ffParseModuleOptions(const char* key, const char* value) } return false; } + +void ffPrepareCommandOption(FFdata* data) +{ + //If we don't have a custom structure, use the default one + if(data->structure.length == 0) + ffStrbufAppendS(&data->structure, FASTFETCH_DATATEXT_STRUCTURE); + + if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME)) + ffPrepareCPUUsage(); + + if(instance.config.multithreading) + { + if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME)) + ffPreparePublicIp(&instance.config.publicIP); + + if(ffStrbufContainIgnCaseS(&data->structure, FF_WEATHER_MODULE_NAME)) + ffPrepareWeather(&instance.config.weather); + } +} + +static void parseStructureCommand(const char* line, FFlist* customValues) +{ + // handle `--set` and `--set-keyless` + FF_LIST_FOR_EACH(FFCustomValue, customValue, *customValues) + { + if (ffStrbufEqualS(&customValue->key, line)) + { + __attribute__((__cleanup__(ffDestroyCustomOptions))) FFCustomOptions options; + ffInitCustomOptions(&options); + if (customValue->printKey) + ffStrbufAppend(&options.moduleArgs.key, &customValue->key); + ffStrbufAppend(&options.moduleArgs.outputFormat, &customValue->value); + ffPrintCustom(&options); + return; + } + } + + if(!ffParseModuleCommand(line)) + ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, ""); +} + +void ffPrintCommandOption(FFdata* data) +{ + //Parse the structure and call the modules + uint32_t startIndex = 0; + while (startIndex < data->structure.length) + { + uint32_t colonIndex = ffStrbufNextIndexC(&data->structure, startIndex, ':'); + data->structure.chars[colonIndex] = '\0'; + + uint64_t ms = 0; + if(__builtin_expect(instance.config.stat, false)) + ms = ffTimeGetTick(); + + parseStructureCommand(data->structure.chars + startIndex, &data->customValues); + + if(__builtin_expect(instance.config.stat, false)) + { + char str[32]; + int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms); + if(instance.config.pipe) + puts(str); + else + printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load + } + + #if defined(_WIN32) + if (!instance.config.noBuffer) fflush(stdout); + #endif + + startIndex = colonIndex + 1; + } +} diff --git a/src/common/commandoption.h b/src/common/commandoption.h index 3ae2a83111..c938fe2a81 100644 --- a/src/common/commandoption.h +++ b/src/common/commandoption.h @@ -5,7 +5,24 @@ #include "fastfetch.h" +typedef struct FFCustomValue +{ + bool printKey; + FFstrbuf key; + FFstrbuf value; +} FFCustomValue; + +// Things only needed by fastfetch +typedef struct FFdata +{ + FFstrbuf structure; + FFlist customValues; // List of FFCustomValue + bool loadUserConfig; +} FFdata; + bool ffParseModuleCommand(const char* type); bool ffParseModuleOptions(const char* key, const char* value); +void ffPrepareCommandOption(FFdata* data); +void ffPrintCommandOption(FFdata* data); #endif diff --git a/src/common/init.c b/src/common/init.c index dfe8b4d19d..8c5b60dcb1 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -27,6 +27,7 @@ static void initState(FFstate* state) ffPlatformInit(&state->platform); state->configDoc = NULL; + state->resultDoc = NULL; } static void defaultConfig(void) @@ -234,8 +235,8 @@ void ffStart(void) startDetectionThreads(); #endif - ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe; - ffHideCursor = instance.config.hideCursor && !instance.config.pipe; + ffDisableLinewrap = instance.config.disableLinewrap && !instance.config.pipe && !instance.state.resultDoc; + ffHideCursor = instance.config.hideCursor && !instance.config.pipe && !instance.state.resultDoc; #ifdef _WIN32 if (!instance.config.noBuffer) setvbuf(stdout, NULL, _IOFBF, 4096); @@ -254,7 +255,7 @@ void ffStart(void) #endif //reset everything to default before we start printing - if(!instance.config.pipe) + if(!instance.config.pipe && !instance.state.resultDoc) fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); if(ffHideCursor) @@ -375,6 +376,7 @@ static void destroyState(void) { ffPlatformDestroy(&instance.state.platform); yyjson_doc_free(instance.state.configDoc); + yyjson_mut_doc_free(instance.state.resultDoc); } void ffDestroyInstance(void) diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 71bc3cf8f8..0b257be53a 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -70,6 +70,20 @@ const char* ffJsonConfigParseEnum(yyjson_val* val, int* result, FFKeyValuePair p return "Invalid enum value type; must be a string or integer"; } +static inline yyjson_mut_val* genJson(FFModuleBaseInfo* baseInfo) +{ + yyjson_mut_doc* doc = instance.state.resultDoc; + if (__builtin_expect(!doc, true)) return NULL; + + yyjson_mut_val* module = yyjson_mut_arr_add_obj(doc, doc->root); + yyjson_mut_obj_add_str(doc, module, "type", baseInfo->name); + if (baseInfo->generateJson) + baseInfo->generateJson(baseInfo, doc, module); + else + yyjson_mut_obj_add_str(doc, module, "error", "Unsupported for JSON format"); + return module; +} + static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal) { if(!isalpha(type[0])) return false; @@ -80,7 +94,8 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* jsonVal) if (ffStrEqualsIgnCase(type, baseInfo->name)) { if (jsonVal) baseInfo->parseJsonObject(baseInfo, jsonVal); - baseInfo->printModule(baseInfo); + if (!genJson(baseInfo)) + baseInfo->printModule(baseInfo); return true; } } @@ -128,6 +143,8 @@ static const char* printJsonConfig(bool prepare) if (!modules) return NULL; if (!yyjson_is_arr(modules)) return "Property 'modules' must be an array of strings or objects"; + yyjson_mut_doc* resultDoc = instance.state.resultDoc; + yyjson_val* item; size_t idx, max; yyjson_arr_foreach(modules, idx, max, item) @@ -157,16 +174,25 @@ static const char* printJsonConfig(bool prepare) if(!prepare && instance.config.stat) { - char str[32]; - int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms); - if(instance.config.pipe) - puts(str); + ms = ffTimeGetTick() - ms; + if (resultDoc) + { + yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root); + yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms); + } else - printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load + { + char str[32]; + int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms); + if(instance.config.pipe) + puts(str); + else + printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load + } } #if defined(_WIN32) - if (!instance.config.noBuffer) fflush(stdout); + if (!instance.config.noBuffer && !resultDoc) fflush(stdout); #endif } diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index e701cae864..1e932cf98a 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -8,3 +8,10 @@ void ffPrintJsonConfig(bool prepare); const char* ffParseGeneralJsonConfig(void); const char* ffParseDisplayJsonConfig(void); const char* ffParseLibraryJsonConfig(void); + +yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *_key, + FFstrbuf* buf) { + return yyjson_mut_obj_add_strncpy(doc, obj, _key, buf->chars, buf->length); +} diff --git a/src/common/option.h b/src/common/option.h index 342b48083e..9414e9a47d 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -3,6 +3,8 @@ #include "util/FFstrbuf.h" struct yyjson_val; +struct yyjson_mut_doc; +struct yyjson_mut_val; // Must be the first field of FFModuleOptions typedef struct FFModuleBaseInfo @@ -11,6 +13,7 @@ typedef struct FFModuleBaseInfo bool (*parseCommandOptions)(void* options, const char* key, const char* value); void (*parseJsonObject)(void* options, struct yyjson_val *module); void (*printModule)(void* options); + void (*generateJson)(void* options, struct yyjson_mut_doc* doc, struct yyjson_mut_val* module); } FFModuleBaseInfo; static inline void ffOptionInitModuleBaseInfo( @@ -18,13 +21,15 @@ static inline void ffOptionInitModuleBaseInfo( const char* name, void* parseCommandOptions, // bool (*const parseCommandOptions)(void* options, const char* key, const char* value) void* parseJsonObject, // void (*const parseJsonObject)(void* options, yyjson_val *module) - void* printModule // void (*const printModule)(void* options) + void* printModule, // void (*const printModule)(void* options) + void* generateJson // void (*const generateJson)(void* options, yyjson_mut_doc* doc, yyjson_mut_val* obj) ) { baseInfo->name = name; baseInfo->parseCommandOptions = (__typeof__(baseInfo->parseCommandOptions)) parseCommandOptions; baseInfo->parseJsonObject = (__typeof__(baseInfo->parseJsonObject)) parseJsonObject; baseInfo->printModule = (__typeof__(baseInfo->printModule)) printModule; + baseInfo->generateJson = (__typeof__(baseInfo->generateJson)) generateJson; } typedef struct FFModuleArgs diff --git a/src/fastfetch.c b/src/fastfetch.c index e2ef0a7b52..ef041ae3be 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -21,21 +21,6 @@ #include "modules/modules.h" -typedef struct FFCustomValue -{ - bool printKey; - FFstrbuf key; - FFstrbuf value; -} FFCustomValue; - -// Things only needed by fastfetch -typedef struct FFdata -{ - FFstrbuf structure; - FFlist customValues; // List of FFCustomValue - bool loadUserConfig; -} FFdata; - static void constructAndPrintCommandHelpFormat(const char* name, const char* def, uint32_t numArgs, ...) { va_list argp; @@ -968,6 +953,30 @@ static void parseOption(FFdata* data, const char* key, const char* value) data->loadUserConfig = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(key, "--processing-timeout")) instance.config.processingTimeout = ffOptionParseInt32(key, value); + else if(ffStrEqualsIgnCase(key, "--format")) + { + switch (ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + { "default", 0}, + { "json", 1 }, + {}, + })) + { + case 0: + if (instance.state.resultDoc) + { + yyjson_mut_doc_free(instance.state.resultDoc); + instance.state.resultDoc = NULL; + } + break; + case 1: + if (!instance.state.resultDoc) + { + instance.state.resultDoc = yyjson_mut_doc_new(NULL); + yyjson_mut_doc_set_root(instance.state.resultDoc, yyjson_mut_arr(instance.state.resultDoc)); + } + break; + } + } #if defined(__linux__) || defined(__FreeBSD__) else if(ffStrEqualsIgnCase(key, "--player-name")) @@ -1219,27 +1228,6 @@ static void parseArguments(FFdata* data, int argc, const char** argv) } } -static void parseStructureCommand(const char* line, FFlist* customValues) -{ - // handle `--set` and `--set-keyless` - FF_LIST_FOR_EACH(FFCustomValue, customValue, *customValues) - { - if (ffStrbufEqualS(&customValue->key, line)) - { - __attribute__((__cleanup__(ffDestroyCustomOptions))) FFCustomOptions options; - ffInitCustomOptions(&options); - if (customValue->printKey) - ffStrbufAppend(&options.moduleArgs.key, &customValue->key); - ffStrbufAppend(&options.moduleArgs.outputFormat, &customValue->value); - ffPrintCustom(&options); - return; - } - } - - if(!ffParseModuleCommand(line)) - ffPrintErrorString(line, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, ""); -} - int main(int argc, const char** argv) { ffInitInstance(); @@ -1273,25 +1261,9 @@ int main(int argc, const char** argv) const bool useJsonConfig = data.structure.length == 0 && instance.state.configDoc; if(useJsonConfig) - ffPrintJsonConfig(true); + ffPrintJsonConfig(true /* prepare */); else - { - //If we don't have a custom structure, use the default one - if(data.structure.length == 0) - ffStrbufAppendS(&data.structure, FASTFETCH_DATATEXT_STRUCTURE); - - if(ffStrbufContainIgnCaseS(&data.structure, FF_CPUUSAGE_MODULE_NAME)) - ffPrepareCPUUsage(); - - if(instance.config.multithreading) - { - if(ffStrbufContainIgnCaseS(&data.structure, FF_PUBLICIP_MODULE_NAME)) - ffPreparePublicIp(&instance.config.publicIP); - - if(ffStrbufContainIgnCaseS(&data.structure, FF_WEATHER_MODULE_NAME)) - ffPrepareWeather(&instance.config.weather); - } - } + ffPrepareCommandOption(&data); ffStart(); @@ -1300,40 +1272,13 @@ int main(int argc, const char** argv) #endif if (useJsonConfig) - { ffPrintJsonConfig(false); - } else - { - //Parse the structure and call the modules - uint32_t startIndex = 0; - while (startIndex < data.structure.length) - { - uint32_t colonIndex = ffStrbufNextIndexC(&data.structure, startIndex, ':'); - data.structure.chars[colonIndex] = '\0'; - - uint64_t ms = 0; - if(__builtin_expect(instance.config.stat, false)) - ms = ffTimeGetTick(); - - parseStructureCommand(data.structure.chars + startIndex, &data.customValues); - - if(__builtin_expect(instance.config.stat, false)) - { - char str[32]; - int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms); - if(instance.config.pipe) - puts(str); - else - printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load - } - - #if defined(_WIN32) - if (!instance.config.noBuffer) fflush(stdout); - #endif + ffPrintCommandOption(&data); - startIndex = colonIndex + 1; - } + if (instance.state.resultDoc) + { + yyjson_mut_write_fp(stdout, instance.state.resultDoc, YYJSON_WRITE_ALLOW_INF_AND_NAN | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL); } ffFinish(); diff --git a/src/fastfetch.h b/src/fastfetch.h index a5f990912c..8ba9158e9c 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -169,6 +169,7 @@ typedef struct FFstate FFPlatform platform; yyjson_doc* configDoc; + yyjson_mut_doc* resultDoc; } FFstate; typedef struct FFinstance diff --git a/src/logo/logo.c b/src/logo/logo.c index af240c5493..613e9a99b1 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -460,7 +460,7 @@ void ffLogoPrint(void) //In pipe mode, we don't have a logo or padding. //We also don't need to set main color, because it won't be printed anyway. //So we can return quickly here. - if(instance.config.pipe) + if(instance.config.pipe || instance.state.resultDoc) { instance.state.logoHeight = 0; instance.state.logoWidth = 0; diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index ee4bd5af77..b0d95986ee 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -103,7 +103,7 @@ void ffPrintBattery(FFBatteryOptions* options) void ffInitBatteryOptions(FFBatteryOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BATTERY_MODULE_NAME, ffParseBatteryCommandOptions, ffParseBatteryJsonObject, ffPrintBattery); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BATTERY_MODULE_NAME, ffParseBatteryCommandOptions, ffParseBatteryJsonObject, ffPrintBattery, ffGenerateBatteryJson); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; @@ -175,3 +175,37 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) ffPrintError(FF_BATTERY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(BatteryResult)); + + const char* error = ffDetectBattery(options, &results); + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_arr(doc); + yyjson_mut_obj_add_val(doc, module, "result", arr); + + FF_LIST_FOR_EACH(BatteryResult, battery, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_real(doc, obj, "capacity", battery->capacity); + yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &battery->manufacturer); + yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &battery->modelName); + yyjson_mut_obj_add_strbuf(doc, obj, "status", &battery->status); + yyjson_mut_obj_add_strbuf(doc, obj, "technology", &battery->technology); + yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature); + } + + FF_LIST_FOR_EACH(BatteryResult, battery, results) + { + ffStrbufDestroy(&battery->manufacturer); + ffStrbufDestroy(&battery->modelName); + ffStrbufDestroy(&battery->technology); + ffStrbufDestroy(&battery->status); + } +} diff --git a/src/modules/battery/battery.h b/src/modules/battery/battery.h index 26312bca7d..adefbdeddf 100644 --- a/src/modules/battery/battery.h +++ b/src/modules/battery/battery.h @@ -10,3 +10,4 @@ void ffInitBatteryOptions(FFBatteryOptions* options); bool ffParseBatteryCommandOptions(FFBatteryOptions* options, const char* key, const char* value); void ffDestroyBatteryOptions(FFBatteryOptions* options); void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module); +void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index ee42017955..e1e7c6f964 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -55,7 +55,7 @@ void ffPrintBios(FFBiosOptions* options) void ffInitBiosOptions(FFBiosOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BIOS_MODULE_NAME, ffParseBiosCommandOptions, ffParseBiosJsonObject, ffPrintBios); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BIOS_MODULE_NAME, ffParseBiosCommandOptions, ffParseBiosJsonObject, ffPrintBios, ffGenerateBiosJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -90,3 +90,39 @@ void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module) ffPrintError(FF_BIOS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateBiosJson(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFBiosResult bios; + ffStrbufInit(&bios.date); + ffStrbufInit(&bios.release); + ffStrbufInit(&bios.vendor); + ffStrbufInit(&bios.version); + + const char* error = ffDetectBios(&bios); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + if (bios.version.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "bios_version is not set."); + goto exit; + } + + yyjson_mut_val* obj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_obj_add_strbuf(doc, obj, "date", &bios.date); + yyjson_mut_obj_add_strbuf(doc, obj, "release", &bios.release); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &bios.vendor); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &bios.version); + +exit: + ffStrbufDestroy(&bios.date); + ffStrbufDestroy(&bios.release); + ffStrbufDestroy(&bios.vendor); + ffStrbufDestroy(&bios.version); +} diff --git a/src/modules/bios/bios.h b/src/modules/bios/bios.h index aaaf15d650..a3bb81d8d1 100644 --- a/src/modules/bios/bios.h +++ b/src/modules/bios/bios.h @@ -9,3 +9,4 @@ void ffInitBiosOptions(FFBiosOptions* options); bool ffParseBiosCommandOptions(FFBiosOptions* options, const char* key, const char* value); void ffDestroyBiosOptions(FFBiosOptions* options); void ffParseBiosJsonObject(FFBiosOptions* options, yyjson_val* module); +void ffGenerateBiosJson(FFBiosOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index fa8b65d51b..569d61e405 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -75,7 +75,7 @@ void ffPrintBluetooth(FFBluetoothOptions* options) void ffInitBluetoothOptions(FFBluetoothOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, NULL); ffOptionInitModuleArg(&options->moduleArgs); options->showDisconnected = false; } diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 29a676ca83..7ec518c26a 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -51,7 +51,7 @@ void ffPrintBoard(FFBoardOptions* options) void ffInitBoardOptions(FFBoardOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BOARD_MODULE_NAME, ffParseBoardCommandOptions, ffParseBoardJsonObject, ffPrintBoard); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BOARD_MODULE_NAME, ffParseBoardCommandOptions, ffParseBoardJsonObject, ffPrintBoard, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/break/break.c b/src/modules/break/break.c index 87821ee001..59c39c1d72 100644 --- a/src/modules/break/break.c +++ b/src/modules/break/break.c @@ -9,7 +9,7 @@ void ffPrintBreak(FF_MAYBE_UNUSED FFBreakOptions* options) void ffInitBreakOptions(FF_MAYBE_UNUSED FFBreakOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BREAK_MODULE_NAME, ffParseBreakCommandOptions, ffParseBreakJsonObject, ffPrintBreak); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BREAK_MODULE_NAME, ffParseBreakCommandOptions, ffParseBreakJsonObject, ffPrintBreak, NULL); } bool ffParseBreakCommandOptions(FF_MAYBE_UNUSED FFBreakOptions* options, FF_MAYBE_UNUSED const char* key, FF_MAYBE_UNUSED const char* value) diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 560353749f..d13c4370c0 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -81,7 +81,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) void ffInitBrightnessOptions(FFBrightnessOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 02cd3e97d9..d685ceb0bc 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -52,7 +52,7 @@ void ffPrintChassis(FFChassisOptions* options) void ffInitChassisOptions(FFChassisOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 488413f214..2e20755823 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -57,7 +57,7 @@ void ffPrintColors(FFColorsOptions* options) void ffInitColorsOptions(FFColorsOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COLORS_MODULE_NAME, ffParseColorsCommandOptions, ffParseColorsJsonObject, ffPrintColors); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COLORS_MODULE_NAME, ffParseColorsCommandOptions, ffParseColorsJsonObject, ffPrintColors, NULL); options->symbol = FF_COLORS_SYMBOL_BLOCK; options->paddingLeft = 0; } diff --git a/src/modules/command/command.c b/src/modules/command/command.c index f19f1f27d9..ad429d2015 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -36,7 +36,7 @@ void ffPrintCommand(FFCommandOptions* options) void ffInitCommandOptions(FFCommandOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInitStatic(&options->shell, diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 00aec6ba84..d89a9a17e1 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -79,7 +79,7 @@ void ffPrintCPU(FFCPUOptions* options) void ffInitCPUOptions(FFCPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, NULL); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; } diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index 23b29e7918..c0f8cd68ca 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -46,7 +46,7 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) void ffInitCPUUsageOptions(FFCPUUsageOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index c33e13d266..5a0143df78 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -52,7 +52,7 @@ void ffPrintCursor(FFCursorOptions* options) void ffInitCursorOptions(FFCursorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index b9406dcd36..38dd4189a6 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -19,7 +19,7 @@ void ffPrintCustom(FFCustomOptions* options) void ffInitCustomOptions(FFCustomOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CUSTOM_MODULE_NAME, ffParseCustomCommandOptions, ffParseCustomJsonObject, ffPrintCustom); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CUSTOM_MODULE_NAME, ffParseCustomCommandOptions, ffParseCustomJsonObject, ffPrintCustom, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 9d6307a132..1c11f5ac3e 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -51,7 +51,7 @@ void ffPrintDateTime(FFDateTimeOptions* options) void ffInitDateTimeOptions(FFDateTimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/de/de.c b/src/modules/de/de.c index a44f437d7a..80e69b854c 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -42,7 +42,7 @@ void ffPrintDE(FFDEOptions* options) void ffInitDEOptions(FFDEOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 202d8e1a88..f5d2bae986 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -202,7 +202,7 @@ void ffPrintDisk(FFDiskOptions* options) void ffInitDiskOptions(FFDiskOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->folders); diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 31371de42a..fa758911d4 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -109,7 +109,7 @@ void ffPrintDisplay(FFDisplayOptions* options) void ffInitDisplayOptions(FFDisplayOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, NULL); ffOptionInitModuleArg(&options->moduleArgs); options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE; options->preciseRefreshRate = false; diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 97c77359bd..2d49fe3ee5 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -45,7 +45,7 @@ void ffPrintFont(FFFontOptions* options) void ffInitFontOptions(FFFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 3691b5ac87..5ba347ba2d 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -51,7 +51,7 @@ void ffPrintGamepad(FFGamepadOptions* options) void ffInitGamepadOptions(FFGamepadOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 5f71779a7d..4edca36b51 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -121,7 +121,7 @@ void ffPrintGPU(FFGPUOptions* options) void ffInitGPUOptions(FFGPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU, NULL); ffOptionInitModuleArg(&options->moduleArgs); options->forceVulkan = false; diff --git a/src/modules/host/host.c b/src/modules/host/host.c index d281ece1b7..4fa03cb64c 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -67,7 +67,7 @@ void ffPrintHost(FFHostOptions* options) void ffInitHostOptions(FFHostOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index aa1827a5fe..7d59c6bbff 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -32,7 +32,7 @@ void ffPrintIcons(FFIconsOptions* options) void ffInitIconsOptions(FFIconsOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index bc1bd21a8f..7e9fcf5589 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -32,7 +32,7 @@ void ffPrintKernel(FFKernelOptions* options) void ffInitKernelOptions(FFKernelOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index afef101a03..0cd896a53f 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -51,7 +51,7 @@ void ffPrintLM(FFLMOptions* options) void ffInitLMOptions(FFLMOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LM_MODULE_NAME, ffParseLMCommandOptions, ffParseLMJsonObject, ffPrintLM); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LM_MODULE_NAME, ffParseLMCommandOptions, ffParseLMJsonObject, ffPrintLM, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 4fa037b15d..3d783f79fb 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -32,7 +32,7 @@ void ffPrintLocale(FFLocaleOptions* options) void ffInitLocaleOptions(FFLocaleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 74b61c5803..9f3a1ca840 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -139,7 +139,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) void ffInitLocalIpOptions(FFLocalIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp, NULL); ffOptionInitModuleArg(&options->moduleArgs); options->showType = FF_LOCALIP_TYPE_IPV4_BIT; diff --git a/src/modules/media/media.c b/src/modules/media/media.c index 87b9b7f12c..ef227cb9f7 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -107,7 +107,7 @@ void ffPrintMedia(FFMediaOptions* options) void ffInitMediaOptions(FFMediaOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 410fb97f2b..3d7cb71391 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -68,7 +68,7 @@ void ffPrintMemory(FFMemoryOptions* options) void ffInitMemoryOptions(FFMemoryOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 688c62413f..15b801fa1d 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -77,7 +77,7 @@ void ffPrintMonitor(FFMonitorOptions* options) void ffInitMonitorOptions(FFMonitorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 6194b7a0b5..4218dbfd22 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -41,7 +41,7 @@ void ffPrintOpenCL(FFOpenCLOptions* options) void ffInitOpenCLOptions(FFOpenCLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index d94849cf50..56f03a0cb7 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -44,7 +44,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options) void ffInitOpenGLOptions(FFOpenGLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL, NULL); ffOptionInitModuleArg(&options->moduleArgs); #if defined(__linux__) || defined(__FreeBSD__) diff --git a/src/modules/os/os.c b/src/modules/os/os.c index e5e5d58ee3..b40dde0383 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -139,7 +139,7 @@ void ffPrintOS(FFOSOptions* options) void ffInitOSOptions(FFOSOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 21599e07a0..1c1b67140a 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -99,7 +99,7 @@ void ffPrintPackages(FFPackagesOptions* options) void ffInitPackagesOptions(FFPackagesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 4dca659169..5e4bf68897 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -75,7 +75,7 @@ void ffPrintPlayer(FFPlayerOptions* options) void ffInitPlayerOptions(FFPlayerOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index efee4a7f32..d847cb0cc4 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -62,7 +62,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index fa2fc89bd3..02cf45b382 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -33,7 +33,7 @@ void ffPrintProcesses(FFProcessesOptions* options) void ffInitProcessesOptions(FFProcessesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 6097b54a38..fdaf7b9f6b 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -97,7 +97,7 @@ void ffPrintPublicIp(FFPublicIpOptions* options) void ffInitPublicIpOptions(FFPublicIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->url); diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index 0eaceff6a8..fa2161228f 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -77,7 +77,7 @@ void ffPrintSeparator(FFSeparatorOptions* options) void ffInitSeparatorOptions(FFSeparatorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorCommandOptions, ffParseSeparatorJsonObject, ffPrintSeparator); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SEPARATOR_MODULE_NAME, ffParseSeparatorCommandOptions, ffParseSeparatorJsonObject, ffPrintSeparator, NULL); ffStrbufInit(&options->string); } diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index d7e2cfa6dd..1328c7acf1 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -45,7 +45,7 @@ void ffPrintShell(FFShellOptions* options) void ffInitShellOptions(FFShellOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index 707556360c..f8ddb13de2 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -85,7 +85,7 @@ void ffPrintSound(FFSoundOptions* options) void ffInitSoundOptions(FFSoundOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound, NULL); ffOptionInitModuleArg(&options->moduleArgs); options->soundType = FF_SOUND_TYPE_MAIN; diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index d4b08031df..1361009f91 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -75,7 +75,7 @@ void ffPrintSwap(FFSwapOptions* options) void ffInitSwapOptions(FFSwapOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 5afa31c190..3d0367a225 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -46,7 +46,7 @@ void ffPrintTerminal(FFTerminalOptions* options) void ffInitTerminalOptions(FFTerminalOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 755fc302dd..4d92ccc610 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -49,7 +49,7 @@ void ffPrintTerminalFont(FFTerminalFontOptions* options) void ffInitTerminalFontOptions(FFTerminalFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index f1ad620bc2..a6083f8edc 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -41,7 +41,7 @@ void ffPrintTerminalSize(FFTerminalSizeOptions* options) void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 025e2c78f6..268d7bf500 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -32,7 +32,7 @@ void ffPrintTheme(FFThemeOptions* options) void ffInitThemeOptions(FFThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 8374cd10b5..32d4b5ad9b 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -51,7 +51,7 @@ void ffPrintTitle(FFTitleOptions* options) void ffInitTitleOptions(FFTitleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, NULL); ffOptionInitModuleArg(&options->moduleArgs); options->fqdn = false; ffStrbufInit(&options->colorUser); diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 1574209e0a..89c93fd171 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -81,7 +81,7 @@ void ffPrintUptime(FFUptimeOptions* options) void ffInitUptimeOptions(FFUptimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/users/users.c b/src/modules/users/users.c index 0c12636208..6c63870821 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -45,7 +45,7 @@ void ffPrintUsers(FFUsersOptions* options) void ffInitUsersOptions(FFUsersOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 9cef899d24..0805c1ee47 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -31,7 +31,7 @@ void ffPrintVersion(FFVersionOptions* options) void ffInitVersionOptions(FFVersionOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index bb66ae6044..fe57fc9a07 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -45,7 +45,7 @@ void ffPrintVulkan(FFVulkanOptions* options) void ffInitVulkanOptions(FFVulkanOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index e51ba590a0..e6f49e18bc 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -44,7 +44,7 @@ void ffPrintWallpaper(FFWallpaperOptions* options) void ffInitWallpaperOptions(FFWallpaperOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 68d18d5507..1338f3286c 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -61,7 +61,7 @@ void ffPrintWeather(FFWeatherOptions* options) void ffInitWeatherOptions(FFWeatherOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather, NULL); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->location); diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index afa0269172..0e030bd7e3 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -72,7 +72,7 @@ void ffPrintWifi(FFWifiOptions* options) void ffInitWifiOptions(FFWifiOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index f02efbf4e1..3c7f532953 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -43,7 +43,7 @@ void ffPrintWM(FFWMOptions* options) void ffInitWMOptions(FFWMOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM, NULL); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 438e7f8326..9376b5475f 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -32,7 +32,7 @@ void ffPrintWMTheme(FFWMThemeOptions* options) void ffInitWMThemeOptions(FFWMThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme, NULL); ffOptionInitModuleArg(&options->moduleArgs); } From 3669f2aee4aa6fbdc6a4c0fa5957a08883796665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 11:17:51 +0800 Subject: [PATCH 025/198] Battery: rename `BatteryResult` to `FFBatteryResult` --- src/detection/battery/battery.h | 4 ++-- src/detection/battery/battery_android.c | 6 +++--- src/detection/battery/battery_apple.c | 2 +- src/detection/battery/battery_bsd.c | 2 +- src/detection/battery/battery_linux.c | 2 +- src/detection/battery/battery_windows.c | 4 ++-- src/modules/battery/battery.c | 12 ++++++------ 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/detection/battery/battery.h b/src/detection/battery/battery.h index 5667af76cf..7df622ea2e 100644 --- a/src/detection/battery/battery.h +++ b/src/detection/battery/battery.h @@ -7,7 +7,7 @@ #define FF_BATTERY_TEMP_UNSET (0/0.0) -typedef struct BatteryResult +typedef struct FFBatteryResult { FFstrbuf manufacturer; FFstrbuf modelName; @@ -15,7 +15,7 @@ typedef struct BatteryResult double capacity; FFstrbuf status; double temperature; -} BatteryResult; +} FFBatteryResult; const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results); diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c index b05cce111d..16dce83d0c 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -33,7 +33,7 @@ static const char* parseTermuxApi(FFBatteryOptions* options, FFlist* results) if (!yyjson_is_obj(root)) return "Battery info result is not a JSON object"; - BatteryResult* battery = ffListAdd(results); + FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); @@ -68,7 +68,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) return NULL; ffStrbufClear(&temp); - BatteryResult* battery = ffListAdd(results); + FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); @@ -78,7 +78,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) if (ffParsePropLines(start, "AC powered: ", &temp) && ffStrbufEqualS(&temp, "true")) ffStrbufAppendS(&battery->status, "AC powered"); ffStrbufClear(&temp); - + if (ffParsePropLines(start, "USB powered: ", &temp) && ffStrbufEqualS(&temp, "true")) { if (battery->status.length) ffStrbufAppendS(&battery->status, ", "); diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index dc1281ddab..52f1797803 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -38,7 +38,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) bool boolValue; const char* error; - BatteryResult* battery = ffListAdd(results); + FFBatteryResult* battery = ffListAdd(results); battery->capacity = 0.0/0.0; int currentCapacity, maxCapacity; diff --git a/src/detection/battery/battery_bsd.c b/src/detection/battery/battery_bsd.c index 287f004a13..8675ab0995 100644 --- a/src/detection/battery/battery_bsd.c +++ b/src/detection/battery/battery_bsd.c @@ -32,7 +32,7 @@ const char* ffDetectBattery(FF_MAYBE_UNUSED FFBatteryOptions* options, FFlist* r if(ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) < 0 || (battio.battinfo.state == ACPI_BATT_STAT_NOT_PRESENT)) continue; - BatteryResult* battery = ffListAdd(results); + FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 41d49db625..a0bbf85f63 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -27,7 +27,7 @@ static void parseBattery(FFstrbuf* dir, FFlist* results) if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0) return; - BatteryResult* result = ffListAdd(results); + FFBatteryResult* result = ffListAdd(results); //capacity must exist and be not empty ffStrbufAppendS(dir, "/capacity"); diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 66df36cf38..056bfd06ab 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -74,7 +74,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) if(!(bi.Capabilities & BATTERY_SYSTEM_BATTERY)) continue; - BatteryResult* battery = (BatteryResult*)ffListAdd(results); + FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results); if(memcmp(bi.Chemistry, "PbAc", 4) == 0) ffStrbufInitS(&battery->technology, "Lead Acid"); @@ -143,7 +143,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) SYSTEM_BATTERY_STATE info; if (NT_SUCCESS(NtPowerInformation(SystemBatteryState, NULL, 0, &info, sizeof(info))) && info.BatteryPresent) { - BatteryResult* battery = (BatteryResult*)ffListAdd(results); + FFBatteryResult* battery = (FFBatteryResult*)ffListAdd(results); ffStrbufInit(&battery->modelName); ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->technology); diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index b0d95986ee..8d622885d3 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -8,7 +8,7 @@ #define FF_BATTERY_NUM_FORMAT_ARGS 5 -static void printBattery(FFBatteryOptions* options, BatteryResult* result, uint8_t index) +static void printBattery(FFBatteryOptions* options, FFBatteryResult* result, uint8_t index) { if(options->moduleArgs.outputFormat.length == 0) { @@ -76,7 +76,7 @@ static void printBattery(FFBatteryOptions* options, BatteryResult* result, uint8 void ffPrintBattery(FFBatteryOptions* options) { - FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(BatteryResult)); + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBatteryResult)); const char* error = ffDetectBattery(options, &results); @@ -88,7 +88,7 @@ void ffPrintBattery(FFBatteryOptions* options) { for(uint8_t i = 0; i < (uint8_t) results.length; i++) { - BatteryResult* result = ffListGet(&results, i); + FFBatteryResult* result = ffListGet(&results, i); printBattery(options, result, i); ffStrbufDestroy(&result->manufacturer); @@ -178,7 +178,7 @@ void ffParseBatteryJsonObject(FFBatteryOptions* options, yyjson_val* module) void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(BatteryResult)); + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBatteryResult)); const char* error = ffDetectBattery(options, &results); if (error) @@ -190,7 +190,7 @@ void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjso yyjson_mut_val* arr = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, module, "result", arr); - FF_LIST_FOR_EACH(BatteryResult, battery, results) + FF_LIST_FOR_EACH(FFBatteryResult, battery, results) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_real(doc, obj, "capacity", battery->capacity); @@ -201,7 +201,7 @@ void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjso yyjson_mut_obj_add_real(doc, obj, "temperature", battery->temperature); } - FF_LIST_FOR_EACH(BatteryResult, battery, results) + FF_LIST_FOR_EACH(FFBatteryResult, battery, results) { ffStrbufDestroy(&battery->manufacturer); ffStrbufDestroy(&battery->modelName); From 757e5f8174fe64609e7e9810279199e934a06b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 11:21:57 +0800 Subject: [PATCH 026/198] Bluetooth: support Json printing --- src/modules/bluetooth/bluetooth.c | 36 ++++++++++++++++++++++++++++++- src/modules/bluetooth/bluetooth.h | 1 + 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 569d61e405..9b793e4045 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -75,7 +75,7 @@ void ffPrintBluetooth(FFBluetoothOptions* options) void ffInitBluetoothOptions(FFBluetoothOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BLUETOOTH_MODULE_NAME, ffParseBluetoothCommandOptions, ffParseBluetoothJsonObject, ffPrintBluetooth, ffGenerateBluetoothJson); ffOptionInitModuleArg(&options->moduleArgs); options->showDisconnected = false; } @@ -123,3 +123,37 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module) ffPrintError(FF_BLUETOOTH_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateBluetoothJson(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBluetoothDevice)); + + const char* error = ffDetectBluetooth(&results); + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + else + { + yyjson_mut_val* arr = yyjson_mut_arr(doc); + yyjson_mut_obj_add_val(doc, module, "result", arr); + + FF_LIST_FOR_EACH(FFBluetoothDevice, item, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address); + yyjson_mut_obj_add_uint(doc, obj, "battery", item->battery); + yyjson_mut_obj_add_bool(doc, obj, "connected", item->connected); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_strbuf(doc, obj, "type", &item->type); + } + } + + FF_LIST_FOR_EACH(FFBluetoothDevice, device, results) + { + ffStrbufDestroy(&device->name); + ffStrbufDestroy(&device->type); + ffStrbufDestroy(&device->address); + } +} diff --git a/src/modules/bluetooth/bluetooth.h b/src/modules/bluetooth/bluetooth.h index 411bb39651..b4d1f0a89f 100644 --- a/src/modules/bluetooth/bluetooth.h +++ b/src/modules/bluetooth/bluetooth.h @@ -9,3 +9,4 @@ void ffInitBluetoothOptions(FFBluetoothOptions* options); bool ffParseBluetoothCommandOptions(FFBluetoothOptions* options, const char* key, const char* value); void ffDestroyBluetoothOptions(FFBluetoothOptions* options); void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module); +void ffGenerateBluetoothJson(FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From fb3fb1bf99fcad437aa214db39311f56fc957529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 13:13:11 +0800 Subject: [PATCH 027/198] Bluetooth: rename `FFBluetoothDevice` to `FFBluetoothResult` --- src/detection/bluetooth/bluetooth.h | 6 +++--- src/detection/bluetooth/bluetooth_apple.m | 4 ++-- src/detection/bluetooth/bluetooth_linux.c | 8 ++++---- src/detection/bluetooth/bluetooth_nosupport.c | 2 +- src/detection/bluetooth/bluetooth_windows.c | 4 ++-- src/modules/bluetooth/bluetooth.c | 20 +++++++++---------- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/detection/bluetooth/bluetooth.h b/src/detection/bluetooth/bluetooth.h index 4aecdfc6f1..a9c07b161b 100644 --- a/src/detection/bluetooth/bluetooth.h +++ b/src/detection/bluetooth/bluetooth.h @@ -5,15 +5,15 @@ #include "fastfetch.h" -typedef struct FFBluetoothDevice +typedef struct FFBluetoothResult { FFstrbuf name; FFstrbuf address; FFstrbuf type; uint8_t battery; // 0-100% bool connected; -} FFBluetoothDevice; +} FFBluetoothResult; -const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */); +const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */); #endif diff --git a/src/detection/bluetooth/bluetooth_apple.m b/src/detection/bluetooth/bluetooth_apple.m index d6f3e98784..abd31a0c24 100644 --- a/src/detection/bluetooth/bluetooth_apple.m +++ b/src/detection/bluetooth/bluetooth_apple.m @@ -2,7 +2,7 @@ #import -const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */) +const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) { NSArray* ioDevices = IOBluetoothDevice.pairedDevices; if(!ioDevices) @@ -10,7 +10,7 @@ for(IOBluetoothDevice* ioDevice in ioDevices) { - FFBluetoothDevice* device = ffListAdd(devices); + FFBluetoothResult* device = ffListAdd(devices); ffStrbufInitS(&device->name, ioDevice.name.UTF8String); ffStrbufInitS(&device->address, ioDevice.addressString.UTF8String); ffStrbufInit(&device->type); diff --git a/src/detection/bluetooth/bluetooth_linux.c b/src/detection/bluetooth/bluetooth_linux.c index 79f61d5fbd..1ed712c90a 100644 --- a/src/detection/bluetooth/bluetooth_linux.c +++ b/src/detection/bluetooth/bluetooth_linux.c @@ -44,7 +44,7 @@ array [ //root ] */ -static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device) +static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device) { if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) return; @@ -72,7 +72,7 @@ static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBlue ffDBusGetBool(dbus, &dictIter, &device->connected); } -static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device) +static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothResult* device) { if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) return; @@ -130,7 +130,7 @@ static void detectBluetoothObject(FFlist* devices, FFDBusData* dbus, DBusMessage DBusMessageIter arrayIter; dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter); - FFBluetoothDevice* device = ffListAdd(devices); + FFBluetoothResult* device = ffListAdd(devices); ffStrbufInit(&device->name); ffStrbufInit(&device->address); ffStrbufInit(&device->type); @@ -193,7 +193,7 @@ static const char* detectBluetooth(FFlist* devices) #endif -const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothDevice */) +const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */) { #ifdef FF_HAVE_DBUS return detectBluetooth(devices); diff --git a/src/detection/bluetooth/bluetooth_nosupport.c b/src/detection/bluetooth/bluetooth_nosupport.c index 4ae74ac3e8..8db5a465cb 100644 --- a/src/detection/bluetooth/bluetooth_nosupport.c +++ b/src/detection/bluetooth/bluetooth_nosupport.c @@ -1,6 +1,6 @@ #include "bluetooth.h" -const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothDevice */) +const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */) { return "Not supported on this platform"; } diff --git a/src/detection/bluetooth/bluetooth_windows.c b/src/detection/bluetooth/bluetooth_windows.c index 0066cebb3a..9415ea5f43 100644 --- a/src/detection/bluetooth/bluetooth_windows.c +++ b/src/detection/bluetooth/bluetooth_windows.c @@ -7,7 +7,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpointer-sign" -const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */) +const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) { BLUETOOTH_DEVICE_SEARCH_PARAMS btsp = { .fReturnConnected = TRUE, @@ -25,7 +25,7 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */) return "BluetoothFindFirstDevice() failed or no devices found"; do { - FFBluetoothDevice* device = ffListAdd(devices); + FFBluetoothResult* device = ffListAdd(devices); ffStrbufInit(&device->name); ffStrbufInit(&device->address); ffStrbufInit(&device->type); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 9b793e4045..99b330fdbf 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -6,7 +6,7 @@ #define FF_BLUETOOTH_NUM_FORMAT_ARGS 4 -static void printDevice(FFBluetoothOptions* options, const FFBluetoothDevice* device, uint8_t index) +static void printDevice(FFBluetoothOptions* options, const FFBluetoothResult* device, uint8_t index) { if(options->moduleArgs.outputFormat.length == 0) { @@ -34,7 +34,7 @@ static void printDevice(FFBluetoothOptions* options, const FFBluetoothDevice* de void ffPrintBluetooth(FFBluetoothOptions* options) { - FF_LIST_AUTO_DESTROY devices = ffListCreate(sizeof (FFBluetoothDevice)); + FF_LIST_AUTO_DESTROY devices = ffListCreate(sizeof (FFBluetoothResult)); const char* error = ffDetectBluetooth(&devices); if(error) @@ -43,14 +43,14 @@ void ffPrintBluetooth(FFBluetoothOptions* options) } else { - FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFBluetoothDevice*)); + FF_LIST_AUTO_DESTROY filtered = ffListCreate(sizeof(FFBluetoothResult*)); - FF_LIST_FOR_EACH(FFBluetoothDevice, device, devices) + FF_LIST_FOR_EACH(FFBluetoothResult, device, devices) { if(!device->connected && !options->showDisconnected) continue; - *(FFBluetoothDevice**)ffListAdd(&filtered) = device; + *(FFBluetoothResult**)ffListAdd(&filtered) = device; } if(filtered.length == 0) @@ -61,11 +61,11 @@ void ffPrintBluetooth(FFBluetoothOptions* options) for(uint32_t i = 0; i < filtered.length; i++) { uint8_t index = (uint8_t) (filtered.length == 1 ? 0 : i + 1); - printDevice(options, *(FFBluetoothDevice**)ffListGet(&filtered, i), index); + printDevice(options, *(FFBluetoothResult**)ffListGet(&filtered, i), index); } } - FF_LIST_FOR_EACH(FFBluetoothDevice, device, devices) + FF_LIST_FOR_EACH(FFBluetoothResult, device, devices) { ffStrbufDestroy(&device->name); ffStrbufDestroy(&device->type); @@ -126,7 +126,7 @@ void ffParseBluetoothJsonObject(FFBluetoothOptions* options, yyjson_val* module) void ffGenerateBluetoothJson(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBluetoothDevice)); + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFBluetoothResult)); const char* error = ffDetectBluetooth(&results); if (error) @@ -139,7 +139,7 @@ void ffGenerateBluetoothJson(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson yyjson_mut_val* arr = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, module, "result", arr); - FF_LIST_FOR_EACH(FFBluetoothDevice, item, results) + FF_LIST_FOR_EACH(FFBluetoothResult, item, results) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "address", &item->address); @@ -150,7 +150,7 @@ void ffGenerateBluetoothJson(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson } } - FF_LIST_FOR_EACH(FFBluetoothDevice, device, results) + FF_LIST_FOR_EACH(FFBluetoothResult, device, results) { ffStrbufDestroy(&device->name); ffStrbufDestroy(&device->type); From 3d44514b24d3f4a519baedba3ca3a1eb8e9b14e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 13:20:00 +0800 Subject: [PATCH 028/198] Board: support Json printing --- src/modules/board/board.c | 33 +++++++++++++++++++++++++++++++++ src/modules/board/board.h | 1 + 2 files changed, 34 insertions(+) diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 7ec518c26a..4c94ac3bd5 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -86,3 +86,36 @@ void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module) ffPrintError(FF_BOARD_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateBoardJson(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFBoardResult board; + ffStrbufInit(&board.name); + ffStrbufInit(&board.vendor); + ffStrbufInit(&board.version); + + const char* error = ffDetectBoard(&board); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + if (board.name.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "board_name is not set."); + goto exit; + } + + yyjson_mut_val* obj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &board.name); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &board.vendor); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &board.version); + +exit: + ffStrbufDestroy(&board.name); + ffStrbufDestroy(&board.vendor); + ffStrbufDestroy(&board.version); +} diff --git a/src/modules/board/board.h b/src/modules/board/board.h index f5531368e7..0e1dabbaba 100644 --- a/src/modules/board/board.h +++ b/src/modules/board/board.h @@ -9,3 +9,4 @@ void ffInitBoardOptions(FFBoardOptions* options); bool ffParseBoardCommandOptions(FFBoardOptions* options, const char* key, const char* value); void ffDestroyBoardOptions(FFBoardOptions* options); void ffParseBoardJsonObject(FFBoardOptions* options, yyjson_val* module); +void ffGenerateBoardJson(FFBoardOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From c5d8d976f6be7024d655a5d7f4adaee02660a793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 14:13:08 +0800 Subject: [PATCH 029/198] Brightness: add Json printing support --- src/modules/brightness/brightness.c | 36 ++++++++++++++++++++++++++++- src/modules/brightness/brightness.h | 1 + 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index d13c4370c0..120459245d 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -81,7 +81,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) void ffInitBrightnessOptions(FFBrightnessOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_BRIGHTNESS_MODULE_NAME, ffParseBrightnessCommandOptions, ffParseBrightnessJsonObject, ffPrintBrightness, ffGenerateBrightnessJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -116,3 +116,37 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul ffPrintError(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateBrightnessJson(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFBrightnessResult)); + + const char* error = ffDetectBrightness(&result); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + if(result.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No result is detected."); + return; + } + + yyjson_mut_val* arr = yyjson_mut_arr(doc); + yyjson_mut_obj_add_val(doc, module, "result", arr); + + FF_LIST_FOR_EACH(FFBrightnessResult, item, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_real(doc, obj, "value", item->value); + } + + FF_LIST_FOR_EACH(FFBrightnessResult, item, result) + { + ffStrbufDestroy(&item->name); + } +} diff --git a/src/modules/brightness/brightness.h b/src/modules/brightness/brightness.h index 1272e5d0f4..6933c65009 100644 --- a/src/modules/brightness/brightness.h +++ b/src/modules/brightness/brightness.h @@ -9,3 +9,4 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options); bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* key, const char* value); void ffDestroyBrightnessOptions(FFBrightnessOptions* options); void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* module); +void ffGenerateBrightnessJson(FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From acd353b8b3c95db2672a18d67ada2e642afa074d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 14:13:26 +0800 Subject: [PATCH 030/198] Chassis: add Json printing support --- src/modules/chassis/chassis.c | 35 ++++++++++++++++++++++++++++++++++- src/modules/chassis/chassis.h | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index d685ceb0bc..93c91c942e 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -52,7 +52,7 @@ void ffPrintChassis(FFChassisOptions* options) void ffInitChassisOptions(FFChassisOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CHASSIS_MODULE_NAME, ffParseChassisCommandOptions, ffParseChassisJsonObject, ffPrintChassis, ffGenerateChassisJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -87,3 +87,36 @@ void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module) ffPrintError(FF_CHASSIS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateChassisJson(FF_MAYBE_UNUSED FFChassisOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFChassisResult result; + ffStrbufInit(&result.type); + ffStrbufInit(&result.vendor); + ffStrbufInit(&result.version); + + const char* error = ffDetectChassis(&result); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + if(result.type.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "chassis_type is not set by O.E.M."); + goto exit; + } + + yyjson_mut_val* obj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_obj_add_strbuf(doc, obj, "type", &result.type); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &result.vendor); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); + +exit: + ffStrbufDestroy(&result.type); + ffStrbufDestroy(&result.vendor); + ffStrbufDestroy(&result.version); +} diff --git a/src/modules/chassis/chassis.h b/src/modules/chassis/chassis.h index 5fe4bb62fd..c5553f7722 100644 --- a/src/modules/chassis/chassis.h +++ b/src/modules/chassis/chassis.h @@ -9,3 +9,4 @@ void ffInitChassisOptions(FFChassisOptions* options); bool ffParseChassisCommandOptions(FFChassisOptions* options, const char* key, const char* value); void ffDestroyChassisOptions(FFChassisOptions* options); void ffParseChassisJsonObject(FFChassisOptions* options, yyjson_val* module); +void ffGenerateChassisJson(FFChassisOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 01aa9b951661bcddd8885df52f4d9a86df0107e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 14:13:39 +0800 Subject: [PATCH 031/198] Command: add JSON printing support --- src/modules/command/command.c | 31 ++++++++++++++++++++++++++++++- src/modules/command/command.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/modules/command/command.c b/src/modules/command/command.c index ad429d2015..393aab97b7 100644 --- a/src/modules/command/command.c +++ b/src/modules/command/command.c @@ -36,7 +36,7 @@ void ffPrintCommand(FFCommandOptions* options) void ffInitCommandOptions(FFCommandOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COMMAND_MODULE_NAME, ffParseCommandCommandOptions, ffParseCommandJsonObject, ffPrintCommand, ffGenerateCommandJson); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInitStatic(&options->shell, @@ -107,3 +107,32 @@ void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module) ffPrintError(FF_COMMAND_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateCommandJson(FF_MAYBE_UNUSED FFCommandOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); + const char* error = ffProcessAppendStdOut(&result, (char* const[]){ + options->shell.chars, + #ifdef _WIN32 + "/c", + #else + "-c", + #endif + options->text.chars, + NULL + }); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + if(!result.length) + { + yyjson_mut_obj_add_str(doc, module, "error", "No result printed"); + return; + } + + yyjson_mut_obj_add_strbuf(doc, module, "result", &result); +} diff --git a/src/modules/command/command.h b/src/modules/command/command.h index 8ee5cc82c1..ec8e2bab37 100644 --- a/src/modules/command/command.h +++ b/src/modules/command/command.h @@ -9,3 +9,4 @@ void ffInitCommandOptions(FFCommandOptions* options); bool ffParseCommandCommandOptions(FFCommandOptions* options, const char* key, const char* value); void ffDestroyCommandOptions(FFCommandOptions* options); void ffParseCommandJsonObject(FFCommandOptions* options, yyjson_val* module); +void ffGenerateCommandJson(FFCommandOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 28e412b79d80bacf2e7e9e76ba9ef7ae00d1d764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 14:46:04 +0800 Subject: [PATCH 032/198] CPU: add JSON printing support --- src/detection/cpu/cpu_apple.c | 3 +++ src/modules/cpu/cpu.c | 36 ++++++++++++++++++++++++++++++++++- src/modules/cpu/cpu.h | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 9dcb07edd1..da55404ee7 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -35,7 +35,10 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL) return "sysctlbyname(machdep.cpu.brand_string) failed"; + ffSysctlGetString("machdep.cpu.vendor", &cpu->vendor); + if (cpu->vendor.length == 0 && ffStrbufStartsWithS(&cpu->name, "Apple ")) + ffStrbufAppendS(&cpu->vendor, "Apple"); cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.physicalcpu_max", 1); if(cpu->coresPhysical == 1) diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index d89a9a17e1..dc46d835b4 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -79,7 +79,7 @@ void ffPrintCPU(FFCPUOptions* options) void ffInitCPUOptions(FFCPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPU_MODULE_NAME, ffParseCPUCommandOptions, ffParseCPUJsonObject, ffPrintCPU, ffGenerateCPUJson); ffOptionInitModuleArg(&options->moduleArgs); options->temp = false; } @@ -127,3 +127,37 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module) ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFCPUResult cpu; + cpu.temperature = FF_CPU_TEMP_UNSET; + cpu.coresPhysical = cpu.coresLogical = cpu.coresOnline = 0; + cpu.frequencyMax = cpu.frequencyMin = 0; + ffStrbufInit(&cpu.name); + ffStrbufInit(&cpu.vendor); + + const char* error = ffDetectCPU(options, &cpu); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + } + else if(cpu.vendor.length == 0 && cpu.name.length == 0 && cpu.coresOnline <= 1) + { + yyjson_mut_obj_add_str(doc, module, "error", "No CPU detected"); + } + else + { + yyjson_mut_val* obj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_obj_add_strbuf(doc, obj, "cpu", &cpu.name); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &cpu.vendor); + yyjson_mut_obj_add_uint(doc, obj, "coresPhysical", cpu.coresPhysical); + yyjson_mut_obj_add_uint(doc, obj, "coresLogical", cpu.coresLogical); + yyjson_mut_obj_add_uint(doc, obj, "coresOnline", cpu.coresOnline); + yyjson_mut_obj_add_real(doc, obj, "frequencyMin", cpu.frequencyMin); + yyjson_mut_obj_add_real(doc, obj, "frequencyMax", cpu.frequencyMax); + yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); + } +} diff --git a/src/modules/cpu/cpu.h b/src/modules/cpu/cpu.h index acff0a13ce..0a3e7c4c62 100644 --- a/src/modules/cpu/cpu.h +++ b/src/modules/cpu/cpu.h @@ -9,3 +9,4 @@ void ffInitCPUOptions(FFCPUOptions* options); bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char* value); void ffDestroyCPUOptions(FFCPUOptions* options); void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module); +void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From ac8741d57daa0da3c82611903320bc54f3dac318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 30 Aug 2023 15:38:29 +0800 Subject: [PATCH 033/198] CPUUsage: add JSON printing support --- src/modules/cpuusage/cpuusage.c | 15 ++++++++++++++- src/modules/cpuusage/cpuusage.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/modules/cpuusage/cpuusage.c b/src/modules/cpuusage/cpuusage.c index c0f8cd68ca..ca0909377a 100644 --- a/src/modules/cpuusage/cpuusage.c +++ b/src/modules/cpuusage/cpuusage.c @@ -46,7 +46,7 @@ void ffPrintCPUUsage(FFCPUUsageOptions* options) void ffInitCPUUsageOptions(FFCPUUsageOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CPUUSAGE_MODULE_NAME, ffParseCPUUsageCommandOptions, ffParseCPUUsageJsonObject, ffPrintCPUUsage, ffGenerateCPUUsageJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,16 @@ void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module) ffPrintError(FF_CPUUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateCPUUsageJson(FF_MAYBE_UNUSED FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + double percentage = 0.0/0.0; + const char* error = ffGetCpuUsageResult(&percentage); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + yyjson_mut_obj_add_real(doc, module, "result", percentage); +} diff --git a/src/modules/cpuusage/cpuusage.h b/src/modules/cpuusage/cpuusage.h index 5a221f554c..e31bc14c78 100644 --- a/src/modules/cpuusage/cpuusage.h +++ b/src/modules/cpuusage/cpuusage.h @@ -11,3 +11,4 @@ void ffInitCPUUsageOptions(FFCPUUsageOptions* options); bool ffParseCPUUsageCommandOptions(FFCPUUsageOptions* options, const char* key, const char* value); void ffDestroyCPUUsageOptions(FFCPUUsageOptions* options); void ffParseCPUUsageJsonObject(FFCPUUsageOptions* options, yyjson_val* module); +void ffGenerateCPUUsageJson(FFCPUUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From a4fababb71dfd01843f6157294d3a070fa1b0aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 10:38:11 +0800 Subject: [PATCH 034/198] Cursor: add JSON format support --- src/modules/cursor/cursor.c | 23 ++++++++++++++++++++++- src/modules/cursor/cursor.h | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 5a0143df78..945f44b729 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -52,7 +52,7 @@ void ffPrintCursor(FFCursorOptions* options) void ffInitCursorOptions(FFCursorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CURSOR_MODULE_NAME, ffParseCursorCommandOptions, ffParseCursorJsonObject, ffPrintCursor, ffGenerateCursorJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -87,3 +87,24 @@ void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module) ffPrintError(FF_CURSOR_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateCursorJson(FF_MAYBE_UNUSED FFCursorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFCursorResult result; + ffStrbufInit(&result.error); + ffStrbufInit(&result.theme); + ffStrbufInit(&result.size); + + ffDetectCursor(&result); + + if (result.error.length) + { + yyjson_mut_obj_add_str(doc, module, "error", result.error.chars); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_obj_add_strbuf(doc, obj, "theme", &result.theme); + yyjson_mut_obj_add_strbuf(doc, obj, "size", &result.size); +} diff --git a/src/modules/cursor/cursor.h b/src/modules/cursor/cursor.h index ff849b5476..02ed47e8fd 100644 --- a/src/modules/cursor/cursor.h +++ b/src/modules/cursor/cursor.h @@ -9,3 +9,4 @@ void ffInitCursorOptions(FFCursorOptions* options); bool ffParseCursorCommandOptions(FFCursorOptions* options, const char* key, const char* value); void ffDestroyCursorOptions(FFCursorOptions* options); void ffParseCursorJsonObject(FFCursorOptions* options, yyjson_val* module); +void ffGenerateCursorJson(FFCursorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 632718e1d0a2a15f2ea0497067cce873f2097842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 11:24:15 +0800 Subject: [PATCH 035/198] DateTime: support JSON printing --- src/common/jsonconfig.h | 2 +- src/modules/datetime/datetime.c | 30 +++++++++++++++++++++++++++++- src/modules/datetime/datetime.h | 1 + 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index 1e932cf98a..5dbfcc68f8 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -12,6 +12,6 @@ const char* ffParseLibraryJsonConfig(void); yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, - FFstrbuf* buf) { + const FFstrbuf* buf) { return yyjson_mut_obj_add_strncpy(doc, obj, _key, buf->chars, buf->length); } diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 1c11f5ac3e..84188eb92c 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -51,7 +51,7 @@ void ffPrintDateTime(FFDateTimeOptions* options) void ffInitDateTimeOptions(FFDateTimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DATETIME_MODULE_NAME, ffParseDateTimeCommandOptions, ffParseDateTimeJsonObject, ffPrintDateTime, ffGenerateDateTimeJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -86,3 +86,31 @@ void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module) ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateDateTimeJson(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFDateTimeResult* result = ffDetectDateTime(); + + yyjson_mut_val* obj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_obj_add_uint(doc, obj, "year", result->year); + yyjson_mut_obj_add_uint(doc, obj, "yearShort", result->yearShort); + yyjson_mut_obj_add_uint(doc, obj, "month", result->month); + yyjson_mut_obj_add_strbuf(doc, obj, "monthPretty", &result->monthPretty); + yyjson_mut_obj_add_strbuf(doc, obj, "monthName", &result->monthName); + yyjson_mut_obj_add_strbuf(doc, obj, "monthNameShort", &result->monthNameShort); + yyjson_mut_obj_add_uint(doc, obj, "week", result->week); + yyjson_mut_obj_add_strbuf(doc, obj, "weekday", &result->weekday); + yyjson_mut_obj_add_strbuf(doc, obj, "weekdaySort", &result->weekdayShort); + yyjson_mut_obj_add_uint(doc, obj, "dayInYear", result->dayInYear); + yyjson_mut_obj_add_uint(doc, obj, "dayInMonth", result->dayInMonth); + yyjson_mut_obj_add_uint(doc, obj, "dayInWeek", result->dayInWeek); + yyjson_mut_obj_add_uint(doc, obj, "hour", result->hour); + yyjson_mut_obj_add_strbuf(doc, obj, "hourPretty", &result->hourPretty); + yyjson_mut_obj_add_uint(doc, obj, "hour12", result->hour12); + yyjson_mut_obj_add_strbuf(doc, obj, "hour12Pretty", &result->hour12Pretty); + yyjson_mut_obj_add_uint(doc, obj, "minute", result->minute); + yyjson_mut_obj_add_strbuf(doc, obj, "minutePretty", &result->minutePretty); + yyjson_mut_obj_add_uint(doc, obj, "second", result->second); + yyjson_mut_obj_add_strbuf(doc, obj, "secondPretty", &result->secondPretty); +} diff --git a/src/modules/datetime/datetime.h b/src/modules/datetime/datetime.h index 6ccb30b278..8f4ceb6908 100644 --- a/src/modules/datetime/datetime.h +++ b/src/modules/datetime/datetime.h @@ -9,3 +9,4 @@ void ffInitDateTimeOptions(FFDateTimeOptions* options); bool ffParseDateTimeCommandOptions(FFDateTimeOptions* options, const char* key, const char* value); void ffDestroyDateTimeOptions(FFDateTimeOptions* options); void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module); +void ffGenerateDateTimeJson(FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 76fce2c5a9dcbad6fcc58143708aab9aca22419e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 13:45:19 +0800 Subject: [PATCH 036/198] DE: add JSON printing support --- src/common/jsonconfig.h | 8 ++++++++ src/modules/de/de.c | 18 +++++++++++++++++- src/modules/de/de.h | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index 5dbfcc68f8..d66636d2a3 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -15,3 +15,11 @@ yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) { return yyjson_mut_obj_add_strncpy(doc, obj, _key, buf->chars, buf->length); } + +yyjson_api_inline yyjson_mut_val* yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *_key) { + yyjson_mut_val* newObj = yyjson_mut_obj(doc); + yyjson_mut_obj_add_val(doc, obj, _key, newObj); + return newObj; +} diff --git a/src/modules/de/de.c b/src/modules/de/de.c index 80e69b854c..a6d896d7ce 100644 --- a/src/modules/de/de.c +++ b/src/modules/de/de.c @@ -42,7 +42,7 @@ void ffPrintDE(FFDEOptions* options) void ffInitDEOptions(FFDEOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DE_MODULE_NAME, ffParseDECommandOptions, ffParseDEJsonObject, ffPrintDE, ffGenerateDEJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -77,3 +77,19 @@ void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module) ffPrintError(FF_DE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateDEJson(FF_MAYBE_UNUSED FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFDisplayServerResult* result = ffConnectDisplayServer(); + + if(result->dePrettyName.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No DE found"); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->deProcessName); + yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->dePrettyName); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->deVersion); +} diff --git a/src/modules/de/de.h b/src/modules/de/de.h index 0a4e145411..b8d122184f 100644 --- a/src/modules/de/de.h +++ b/src/modules/de/de.h @@ -9,3 +9,4 @@ void ffInitDEOptions(FFDEOptions* options); bool ffParseDECommandOptions(FFDEOptions* options, const char* key, const char* value); void ffDestroyDEOptions(FFDEOptions* options); void ffParseDEJsonObject(FFDEOptions* options, yyjson_val* module); +void ffGenerateDEJson(FFDEOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 639ad436a0f1e8539ee873cbec16fccb8da4ab08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 13:54:46 +0800 Subject: [PATCH 037/198] Global: code refactor --- src/common/jsonconfig.h | 8 ++++++++ src/modules/battery/battery.c | 3 +-- src/modules/bios/bios.c | 3 +-- src/modules/bluetooth/bluetooth.c | 3 +-- src/modules/board/board.c | 3 +-- src/modules/chassis/chassis.c | 3 +-- src/modules/cpu/cpu.c | 3 +-- src/modules/cursor/cursor.c | 3 +-- src/modules/datetime/datetime.c | 3 +-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index d66636d2a3..012caf0c16 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -23,3 +23,11 @@ yyjson_api_inline yyjson_mut_val* yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, yyjson_mut_obj_add_val(doc, obj, _key, newObj); return newObj; } + +yyjson_api_inline yyjson_mut_val* yyjson_mut_obj_add_arr(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *_key) { + yyjson_mut_val* newArr = yyjson_mut_arr(doc); + yyjson_mut_obj_add_val(doc, obj, _key, newArr); + return newArr; +} diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index 8d622885d3..85103b5c8b 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -187,8 +187,7 @@ void ffGenerateBatteryJson(FFBatteryOptions* options, yyjson_mut_doc* doc, yyjso return; } - yyjson_mut_val* arr = yyjson_mut_arr(doc); - yyjson_mut_obj_add_val(doc, module, "result", arr); + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); FF_LIST_FOR_EACH(FFBatteryResult, battery, results) { diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index e1e7c6f964..b3f3e598ce 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -113,8 +113,7 @@ void ffGenerateBiosJson(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut_doc* goto exit; } - yyjson_mut_val* obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "date", &bios.date); yyjson_mut_obj_add_strbuf(doc, obj, "release", &bios.release); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &bios.vendor); diff --git a/src/modules/bluetooth/bluetooth.c b/src/modules/bluetooth/bluetooth.c index 99b330fdbf..ade503bc1c 100644 --- a/src/modules/bluetooth/bluetooth.c +++ b/src/modules/bluetooth/bluetooth.c @@ -136,8 +136,7 @@ void ffGenerateBluetoothJson(FF_MAYBE_UNUSED FFBluetoothOptions* options, yyjson } else { - yyjson_mut_val* arr = yyjson_mut_arr(doc); - yyjson_mut_obj_add_val(doc, module, "result", arr); + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); FF_LIST_FOR_EACH(FFBluetoothResult, item, results) { diff --git a/src/modules/board/board.c b/src/modules/board/board.c index 4c94ac3bd5..17e187adee 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -108,8 +108,7 @@ void ffGenerateBoardJson(FF_MAYBE_UNUSED FFBoardOptions* options, yyjson_mut_doc goto exit; } - yyjson_mut_val* obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "name", &board.name); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &board.vendor); yyjson_mut_obj_add_strbuf(doc, obj, "version", &board.version); diff --git a/src/modules/chassis/chassis.c b/src/modules/chassis/chassis.c index 93c91c942e..28a0f557dc 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -109,8 +109,7 @@ void ffGenerateChassisJson(FF_MAYBE_UNUSED FFChassisOptions* options, yyjson_mut goto exit; } - yyjson_mut_val* obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "type", &result.type); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &result.vendor); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index dc46d835b4..bab69f8f2b 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -149,8 +149,7 @@ void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va } else { - yyjson_mut_val* obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "cpu", &cpu.name); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &cpu.vendor); yyjson_mut_obj_add_uint(doc, obj, "coresPhysical", cpu.coresPhysical); diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 945f44b729..58f0ff981c 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -103,8 +103,7 @@ void ffGenerateCursorJson(FF_MAYBE_UNUSED FFCursorOptions* options, yyjson_mut_d return; } - yyjson_mut_val* obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "theme", &result.theme); yyjson_mut_obj_add_strbuf(doc, obj, "size", &result.size); } diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 84188eb92c..a6e5e2245f 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -91,8 +91,7 @@ void ffGenerateDateTimeJson(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_m { const FFDateTimeResult* result = ffDetectDateTime(); - yyjson_mut_val* obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, module, "result", obj); + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_uint(doc, obj, "year", result->year); yyjson_mut_obj_add_uint(doc, obj, "yearShort", result->yearShort); yyjson_mut_obj_add_uint(doc, obj, "month", result->month); From d5ca6aa462c3b131c980055142045f3cbdb3b47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 14:13:14 +0800 Subject: [PATCH 038/198] Disk: add JSON printing support --- src/modules/disk/disk.c | 46 ++++++++++++++++++++++++++++++++++++++++- src/modules/disk/disk.h | 1 + 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index f5d2bae986..4f74a380af 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -202,7 +202,7 @@ void ffPrintDisk(FFDiskOptions* options) void ffInitDiskOptions(FFDiskOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISK_MODULE_NAME, ffParseDiskCommandOptions, ffParseDiskJsonObject, ffPrintDisk, ffGenerateDiskJson); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->folders); @@ -370,3 +370,47 @@ void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module) ffPrintError(FF_DISK_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY disks = ffListCreate(sizeof (FFDisk)); + const char* error = ffDetectDisks(options, &disks); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "result", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + + FF_LIST_FOR_EACH(FFDisk, item, disks) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_uint(doc, obj, "bytesAvailable", item->bytesAvailable); + yyjson_mut_obj_add_uint(doc, obj, "bytesFree", item->bytesFree); + yyjson_mut_obj_add_uint(doc, obj, "bytesTotal", item->bytesTotal); + yyjson_mut_obj_add_uint(doc, obj, "bytesUsed", item->bytesUsed); + yyjson_mut_obj_add_uint(doc, obj, "filesTotal", item->filesTotal); + yyjson_mut_obj_add_uint(doc, obj, "filesUsed", item->filesUsed); + yyjson_mut_obj_add_strbuf(doc, obj, "filesystem", &item->filesystem); + yyjson_mut_obj_add_strbuf(doc, obj, "mountpoint", &item->mountpoint); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_val* typeArr = yyjson_mut_obj_add_arr(doc, obj, "type"); + if(item->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT) + yyjson_mut_arr_add_str(doc, typeArr, "External"); + if(item->type & FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT) + yyjson_mut_arr_add_str(doc, typeArr, "Subvolume"); + if(item->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT) + yyjson_mut_arr_add_str(doc, typeArr, "Hidden"); + if(item->type & FF_DISK_VOLUME_TYPE_READONLY_BIT) + yyjson_mut_arr_add_str(doc, typeArr, "Read-only"); + } + + FF_LIST_FOR_EACH(FFDisk, item, disks) + { + ffStrbufDestroy(&item->mountpoint); + ffStrbufDestroy(&item->filesystem); + ffStrbufDestroy(&item->name); + } +} diff --git a/src/modules/disk/disk.h b/src/modules/disk/disk.h index 1f71f766be..eb4520b351 100644 --- a/src/modules/disk/disk.h +++ b/src/modules/disk/disk.h @@ -9,3 +9,4 @@ void ffInitDiskOptions(FFDiskOptions* options); bool ffParseDiskCommandOptions(FFDiskOptions* options, const char* key, const char* value); void ffDestroyDiskOptions(FFDiskOptions* options); void ffParseDiskJsonObject(FFDiskOptions* options, yyjson_val* module); +void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 34e2b0f89cec6ca3597560fbef0c94767cb6aac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 14:36:21 +0800 Subject: [PATCH 039/198] Display: add JSON printing support --- src/modules/display/display.c | 39 ++++++++++++++++++++++++++++++++++- src/modules/display/display.h | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index fa758911d4..2f99b132b3 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -109,7 +109,7 @@ void ffPrintDisplay(FFDisplayOptions* options) void ffInitDisplayOptions(FFDisplayOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_DISPLAY_MODULE_NAME, ffParseDisplayCommandOptions, ffParseDisplayJsonObject, ffPrintDisplay, ffGenerateDisplayJson); ffOptionInitModuleArg(&options->moduleArgs); options->compactType = FF_DISPLAY_COMPACT_TYPE_NONE; options->preciseRefreshRate = false; @@ -185,3 +185,40 @@ void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module) ffPrintError(FF_DISPLAY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateDisplayJson(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFDisplayServerResult* dsResult = ffConnectDisplayServer(); + + if(dsResult->displays.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect display"); + return; + } + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFDisplayResult, item, dsResult->displays) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_uint(doc, obj, "height", item->height); + yyjson_mut_obj_add_uint(doc, obj, "id", item->id); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_bool(doc, obj, "primary", item->primary); + yyjson_mut_obj_add_real(doc, obj, "refreshRate", item->refreshRate); + yyjson_mut_obj_add_uint(doc, obj, "rotation", item->rotation); + yyjson_mut_obj_add_uint(doc, obj, "scaledHeight", item->scaledHeight); + yyjson_mut_obj_add_uint(doc, obj, "scaledWidth", item->scaledWidth); + switch (item->type) + { + case FF_DISPLAY_TYPE_BUILTIN: + yyjson_mut_obj_add_str(doc, obj, "type", "Builtin"); + break; + case FF_DISPLAY_TYPE_EXTERNAL: + yyjson_mut_obj_add_str(doc, obj, "type", "External"); + break; + default: + yyjson_mut_obj_add_str(doc, obj, "type", "Unknown"); + break; + } + yyjson_mut_obj_add_uint(doc, obj, "scaledWidth", item->width); + } +} diff --git a/src/modules/display/display.h b/src/modules/display/display.h index b2f7570564..6c46dfb18c 100644 --- a/src/modules/display/display.h +++ b/src/modules/display/display.h @@ -9,3 +9,4 @@ void ffInitDisplayOptions(FFDisplayOptions* options); bool ffParseDisplayCommandOptions(FFDisplayOptions* options, const char* key, const char* value); void ffDestroyDisplayOptions(FFDisplayOptions* options); void ffParseDisplayJsonObject(FFDisplayOptions* options, yyjson_val* module); +void ffGenerateDisplayJson(FFDisplayOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 21f36b564f9d38fbfaa040dbbea860eb38b20cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 15:26:55 +0800 Subject: [PATCH 040/198] Font: add JSON printing support --- src/common/jsonconfig.h | 6 ++++++ src/modules/font/font.c | 28 +++++++++++++++++++++++++++- src/modules/font/font.h | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index 012caf0c16..ea8c589687 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -16,6 +16,12 @@ yyjson_api_inline bool yyjson_mut_obj_add_strbuf(yyjson_mut_doc *doc, return yyjson_mut_obj_add_strncpy(doc, obj, _key, buf->chars, buf->length); } +yyjson_api_inline bool yyjson_mut_arr_add_strbuf(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const FFstrbuf* buf) { + return yyjson_mut_arr_add_strncpy(doc, obj, buf->chars, buf->length); +} + yyjson_api_inline yyjson_mut_val* yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key) { diff --git a/src/modules/font/font.c b/src/modules/font/font.c index 2d49fe3ee5..a737c615e9 100644 --- a/src/modules/font/font.c +++ b/src/modules/font/font.c @@ -45,7 +45,7 @@ void ffPrintFont(FFFontOptions* options) void ffInitFontOptions(FFFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_FONT_MODULE_NAME, ffParseFontCommandOptions, ffParseFontJsonObject, ffPrintFont, ffGenerateFontJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -80,3 +80,29 @@ void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module) ffPrintError(FF_FONT_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateFontJson(FF_MAYBE_UNUSED FFFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFFontResult font; + for(uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i) + ffStrbufInit(&font.fonts[i]); + ffStrbufInit(&font.display); + + const char* error = ffDetectFont(&font); + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + } + else + { + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "display", &font.display); + yyjson_mut_val* fontsArr = yyjson_mut_obj_add_arr(doc, obj, "fonts"); + for (uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i) + yyjson_mut_arr_add_strbuf(doc, fontsArr, &font.fonts[i]); + } + + ffStrbufDestroy(&font.display); + for (uint32_t i = 0; i < FF_DETECT_FONT_NUM_FONTS; ++i) + ffStrbufDestroy(&font.fonts[i]); +} diff --git a/src/modules/font/font.h b/src/modules/font/font.h index a51f9d4471..dedb1dfb95 100644 --- a/src/modules/font/font.h +++ b/src/modules/font/font.h @@ -9,3 +9,4 @@ void ffInitFontOptions(FFFontOptions* options); bool ffParseFontCommandOptions(FFFontOptions* options, const char* key, const char* value); void ffDestroyFontOptions(FFFontOptions* options); void ffParseFontJsonObject(FFFontOptions* options, yyjson_val* module); +void ffGenerateFontJson(FFFontOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 97293ddee12eea3e439bb44eef67d884541385c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 31 Aug 2023 16:03:05 +0800 Subject: [PATCH 041/198] Gamepad: add JSON printing support --- src/modules/gamepad/gamepad.c | 35 ++++++++++++++++++++++++++++++++++- src/modules/gamepad/gamepad.h | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/modules/gamepad/gamepad.c b/src/modules/gamepad/gamepad.c index 5ba347ba2d..43818aa2fa 100644 --- a/src/modules/gamepad/gamepad.c +++ b/src/modules/gamepad/gamepad.c @@ -51,7 +51,7 @@ void ffPrintGamepad(FFGamepadOptions* options) void ffInitGamepadOptions(FFGamepadOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GAMEPAD_MODULE_NAME, ffParseGamepadCommandOptions, ffParseGamepadJsonObject, ffPrintGamepad, ffGenerateGamepadJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -86,3 +86,36 @@ void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module) ffPrintError(FF_GAMEPAD_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateGamepadJson(FF_MAYBE_UNUSED FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFGamepadDevice)); + + const char* error = ffDetectGamepad(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + if(!result.length) + { + yyjson_mut_obj_add_str(doc, module, "error", "No devices detected"); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFGamepadDevice, device, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &device->identifier); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &device->name); + } + + FF_LIST_FOR_EACH(FFGamepadDevice, device, result) + { + ffStrbufDestroy(&device->identifier); + ffStrbufDestroy(&device->name); + } +} diff --git a/src/modules/gamepad/gamepad.h b/src/modules/gamepad/gamepad.h index eae8a8a175..eff98e9925 100644 --- a/src/modules/gamepad/gamepad.h +++ b/src/modules/gamepad/gamepad.h @@ -9,3 +9,4 @@ void ffInitGamepadOptions(FFGamepadOptions* options); bool ffParseGamepadCommandOptions(FFGamepadOptions* options, const char* key, const char* value); void ffDestroyGamepadOptions(FFGamepadOptions* options); void ffParseGamepadJsonObject(FFGamepadOptions* options, yyjson_val* module); +void ffGenerateGamepadJson(FFGamepadOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 81c625e7c9d46076cd1ae3aa3247f8dbc70ed21b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 15:49:22 +0800 Subject: [PATCH 042/198] GPU: add JSON printing support --- src/modules/gpu/gpu.c | 70 ++++++++++++++++++++++++++++++++++++++++++- src/modules/gpu/gpu.h | 1 + 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 4edca36b51..18773e7f30 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -121,7 +121,7 @@ void ffPrintGPU(FFGPUOptions* options) void ffInitGPUOptions(FFGPUOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_GPU_MODULE_NAME, ffParseGPUCommandOptions, ffParseGPUJsonObject, ffPrintGPU, ffGenerateGPUJson); ffOptionInitModuleArg(&options->moduleArgs); options->forceVulkan = false; @@ -210,3 +210,71 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY gpus = ffListCreate(sizeof (FFGPUResult)); + const char* error = ffDetectGPU(options, &gpus); + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) + yyjson_mut_obj_add_int(doc, obj, "coreCount", gpu->coreCount); + else + yyjson_mut_obj_add_null(doc, obj, "coreCount"); + + yyjson_mut_val* dedicatedObj = yyjson_mut_obj_add_obj(doc, obj, "dedicated"); + if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedObj, "total", gpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedObj, "total"); + + if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedObj, "used", gpu->dedicated.used); + else + yyjson_mut_obj_add_null(doc, dedicatedObj, "used"); + + yyjson_mut_obj_add_strbuf(doc, obj, "driver", &gpu->driver); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &gpu->name); + + yyjson_mut_val* sharedObj = yyjson_mut_obj_add_obj(doc, obj, "shared"); + if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedObj, "total", gpu->shared.total); + else + yyjson_mut_obj_add_null(doc, sharedObj, "total"); + if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedObj, "used", gpu->shared.used); + else + yyjson_mut_obj_add_null(doc, sharedObj, "used"); + + if (gpu->temperature == gpu->temperature) + yyjson_mut_obj_add_real(doc, obj, "temperature", gpu->temperature); + else + yyjson_mut_obj_add_null(doc, obj, "temperature"); + + const char* type; + switch (gpu->type) + { + case FF_GPU_TYPE_INTEGRATED: type = "Integrated"; break; + case FF_GPU_TYPE_DISCRETE: type = "Discrete"; break; + default: type = "Unknown"; break; + } + yyjson_mut_obj_add_str(doc, obj, "type", type); + + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &gpu->vendor); + } + + FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus) + { + ffStrbufDestroy(&gpu->vendor); + ffStrbufDestroy(&gpu->name); + ffStrbufDestroy(&gpu->driver); + } +} diff --git a/src/modules/gpu/gpu.h b/src/modules/gpu/gpu.h index b5334730a0..73bd7fad51 100644 --- a/src/modules/gpu/gpu.h +++ b/src/modules/gpu/gpu.h @@ -9,3 +9,4 @@ void ffInitGPUOptions(FFGPUOptions* options); bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char* value); void ffDestroyGPUOptions(FFGPUOptions* options); void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module); +void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From fddf6ddf1ef9328e06be253b1260efc652e52490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 15:51:09 +0800 Subject: [PATCH 043/198] CPU: don't use NaN in JSON --- src/modules/cpu/cpu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index bab69f8f2b..7ff3ddf8f8 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -157,6 +157,9 @@ void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va yyjson_mut_obj_add_uint(doc, obj, "coresOnline", cpu.coresOnline); yyjson_mut_obj_add_real(doc, obj, "frequencyMin", cpu.frequencyMin); yyjson_mut_obj_add_real(doc, obj, "frequencyMax", cpu.frequencyMax); - yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); + if (cpu.temperature == cpu.temperature) + yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); + else + yyjson_mut_obj_add_null(doc, obj, "temperature"); } } From 971a69ad1b009feaabda4b7deb39d10040cb3729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 15:57:18 +0800 Subject: [PATCH 044/198] Host: add JSON formatting support --- src/modules/host/host.c | 39 ++++++++++++++++++++++++++++++++++++++- src/modules/host/host.h | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/modules/host/host.c b/src/modules/host/host.c index 4fa03cb64c..30df24f127 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -67,7 +67,7 @@ void ffPrintHost(FFHostOptions* options) void ffInitHostOptions(FFHostOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_HOST_MODULE_NAME, ffParseHostCommandOptions, ffParseHostJsonObject, ffPrintHost, ffGenerateHostJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -102,3 +102,40 @@ void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module) ffPrintError(FF_HOST_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateHostJson(FF_MAYBE_UNUSED FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFHostResult host; + ffStrbufInit(&host.productFamily); + ffStrbufInit(&host.productName); + ffStrbufInit(&host.productVersion); + ffStrbufInit(&host.productSku); + ffStrbufInit(&host.sysVendor); + const char* error = ffDetectHost(&host); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + if (host.productFamily.length == 0 && host.productName.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "neither product_family nor product_name is set by O.E.M."); + goto exit; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "family", &host.productFamily); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &host.productName); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &host.productVersion); + yyjson_mut_obj_add_strbuf(doc, obj, "sku", &host.productSku); + yyjson_mut_obj_add_strbuf(doc, obj, "sysVender", &host.sysVendor); + +exit: + ffStrbufDestroy(&host.productFamily); + ffStrbufDestroy(&host.productName); + ffStrbufDestroy(&host.productVersion); + ffStrbufDestroy(&host.productSku); + ffStrbufDestroy(&host.sysVendor); +} diff --git a/src/modules/host/host.h b/src/modules/host/host.h index 5a689288af..4ed4575a1c 100644 --- a/src/modules/host/host.h +++ b/src/modules/host/host.h @@ -9,3 +9,4 @@ void ffInitHostOptions(FFHostOptions* options); bool ffParseHostCommandOptions(FFHostOptions* options, const char* key, const char* value); void ffDestroyHostOptions(FFHostOptions* options); void ffParseHostJsonObject(FFHostOptions* options, yyjson_val* module); +void ffGenerateHostJson(FFHostOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From dfbfb88a45059a46c17c22fe8a928123b66b83d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 16:02:07 +0800 Subject: [PATCH 045/198] Icons: add JSON formatting support --- src/modules/icons/icons.c | 16 +++++++++++++++- src/modules/icons/icons.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/modules/icons/icons.c b/src/modules/icons/icons.c index 7d59c6bbff..720432b70a 100644 --- a/src/modules/icons/icons.c +++ b/src/modules/icons/icons.c @@ -32,7 +32,7 @@ void ffPrintIcons(FFIconsOptions* options) void ffInitIconsOptions(FFIconsOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_ICONS_MODULE_NAME, ffParseIconsCommandOptions, ffParseIconsJsonObject, ffPrintIcons, ffGenerateIconsJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -67,3 +67,17 @@ void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module) ffPrintError(FF_ICONS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateIconsJson(FF_MAYBE_UNUSED FFIconsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_STRBUF_AUTO_DESTROY icons = ffStrbufCreate(); + const char* error = ffDetectIcons(&icons); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_obj_add_strbuf(doc, module, "result", &icons); +} diff --git a/src/modules/icons/icons.h b/src/modules/icons/icons.h index 97533b096a..dab251e25e 100644 --- a/src/modules/icons/icons.h +++ b/src/modules/icons/icons.h @@ -9,3 +9,4 @@ void ffInitIconsOptions(FFIconsOptions* options); bool ffParseIconsCommandOptions(FFIconsOptions* options, const char* key, const char* value); void ffDestroyIconsOptions(FFIconsOptions* options); void ffParseIconsJsonObject(FFIconsOptions* options, yyjson_val* module); +void ffGenerateIconsJson(FFIconsOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 39b21f95b7e54018158c50e785ce609cc5dcb469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 16:09:46 +0800 Subject: [PATCH 046/198] Kernel: add JSON format support --- src/modules/kernel/kernel.c | 11 ++++++++++- src/modules/kernel/kernel.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index 7e9fcf5589..b8c9e31cff 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -32,7 +32,7 @@ void ffPrintKernel(FFKernelOptions* options) void ffInitKernelOptions(FFKernelOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_KERNEL_MODULE_NAME, ffParseKernelCommandOptions, ffParseKernelJsonObject, ffPrintKernel, ffGenerateKernelJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -67,3 +67,12 @@ void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module) ffPrintError(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateKernelJson(FF_MAYBE_UNUSED FFKernelOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "architecture", &instance.state.platform.systemArchitecture); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &instance.state.platform.systemName); + yyjson_mut_obj_add_strbuf(doc, obj, "release", &instance.state.platform.systemRelease); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &instance.state.platform.systemVersion); +} diff --git a/src/modules/kernel/kernel.h b/src/modules/kernel/kernel.h index 943641d602..419f2544a3 100644 --- a/src/modules/kernel/kernel.h +++ b/src/modules/kernel/kernel.h @@ -9,3 +9,4 @@ void ffInitKernelOptions(FFKernelOptions* options); bool ffParseKernelCommandOptions(FFKernelOptions* options, const char* key, const char* value); void ffDestroyKernelOptions(FFKernelOptions* options); void ffParseKernelJsonObject(FFKernelOptions* options, yyjson_val* module); +void ffGenerateKernelJson(FFKernelOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From f9cd032a5fe7f1dbdbf73d6bf47ef6febbcdffff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 16:22:37 +0800 Subject: [PATCH 047/198] LM: add JSON format support --- src/modules/lm/lm.c | 31 +++++++++++++++++++++++++++++++ src/modules/lm/lm.h | 1 + 2 files changed, 32 insertions(+) diff --git a/src/modules/lm/lm.c b/src/modules/lm/lm.c index 0cd896a53f..f84a422a34 100644 --- a/src/modules/lm/lm.c +++ b/src/modules/lm/lm.c @@ -86,3 +86,34 @@ void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module) ffPrintError(FF_LM_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateLMJson(FF_MAYBE_UNUSED FFLMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFLMResult result; + ffStrbufInit(&result.service); + ffStrbufInit(&result.type); + ffStrbufInit(&result.version); + const char* error = ffDetectLM(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + if(result.service.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No LM service found"); + goto exit; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "service", &result.service); + yyjson_mut_obj_add_strbuf(doc, obj, "type", &result.type); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); + +exit: + ffStrbufDestroy(&result.service); + ffStrbufDestroy(&result.type); + ffStrbufDestroy(&result.version); +} diff --git a/src/modules/lm/lm.h b/src/modules/lm/lm.h index 079f90e5f6..72509adcbd 100644 --- a/src/modules/lm/lm.h +++ b/src/modules/lm/lm.h @@ -9,3 +9,4 @@ void ffInitLMOptions(FFLMOptions* options); bool ffParseLMCommandOptions(FFLMOptions* options, const char* key, const char* value); void ffDestroyLMOptions(FFLMOptions* options); void ffParseLMJsonObject(FFLMOptions* options, yyjson_val* module); +void ffGenerateLMJson(FFLMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From e0ce520e0aa644c9c64aa30ed17d61918443d3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 16:25:08 +0800 Subject: [PATCH 048/198] Locale: add JSON format support --- src/modules/locale/locale.c | 16 +++++++++++++++- src/modules/locale/locale.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/modules/locale/locale.c b/src/modules/locale/locale.c index 3d783f79fb..10c53ba3db 100644 --- a/src/modules/locale/locale.c +++ b/src/modules/locale/locale.c @@ -32,7 +32,7 @@ void ffPrintLocale(FFLocaleOptions* options) void ffInitLocaleOptions(FFLocaleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALE_MODULE_NAME, ffParseLocaleCommandOptions, ffParseLocaleJsonObject, ffPrintLocale, ffGenerateLocaleJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -67,3 +67,17 @@ void ffParseLocaleJsonObject(FFLocaleOptions* options, yyjson_val* module) ffPrintError(FF_LOCALE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateLocaleJson(FF_MAYBE_UNUSED FFLocaleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_STRBUF_AUTO_DESTROY locale = ffStrbufCreate(); + + ffDetectLocale(&locale); + if(locale.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No locale found"); + return; + } + + yyjson_mut_obj_add_strbuf(doc, module, "result", &locale); +} diff --git a/src/modules/locale/locale.h b/src/modules/locale/locale.h index 405f697c9d..8570a3c8de 100644 --- a/src/modules/locale/locale.h +++ b/src/modules/locale/locale.h @@ -9,3 +9,4 @@ void ffInitLocaleOptions(FFLocaleOptions* options); bool ffParseLocaleCommandOptions(FFLocaleOptions* options, const char* key, const char* value); void ffDestroyLocaleOptions(FFLocaleOptions* options); void ffParseLocaleJsonObject(FFLocaleOptions* options, yyjson_val* module); +void ffGenerateLocaleJson(FFLocaleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 623c5d8eb95313ee8b18e793d877af5f3481a12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 5 Sep 2023 16:31:54 +0800 Subject: [PATCH 049/198] LocalIP: add JSON format support --- src/modules/localip/localip.c | 41 ++++++++++++++++++++++++++++++++++- src/modules/localip/localip.h | 1 + 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 9f3a1ca840..28139c1d6e 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -139,7 +139,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) void ffInitLocalIpOptions(FFLocalIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_LOCALIP_MODULE_NAME, ffParseLocalIpCommandOptions, ffParseLocalIpJsonObject, ffPrintLocalIp, ffGenerateLocalIpJson); ffOptionInitModuleArg(&options->moduleArgs); options->showType = FF_LOCALIP_TYPE_IPV4_BIT; @@ -293,3 +293,42 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) ffPrintError(FF_LOCALIP_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateLocalIpJson(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFLocalIpResult)); + + const char* error = ffDetectLocalIps(options, &results); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + if(results.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "Failed to detect any IPs"); + goto exit; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", ip->defaultRoute); + yyjson_mut_obj_add_strbuf(doc, obj, "ipv4", &ip->ipv4); + yyjson_mut_obj_add_strbuf(doc, obj, "ipv6", &ip->ipv6); + yyjson_mut_obj_add_strbuf(doc, obj, "mac", &ip->mac); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &ip->name); + } + +exit: + FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) + { + ffStrbufDestroy(&ip->name); + ffStrbufDestroy(&ip->ipv4); + ffStrbufDestroy(&ip->ipv6); + ffStrbufDestroy(&ip->mac); + } +} diff --git a/src/modules/localip/localip.h b/src/modules/localip/localip.h index 114459c6f5..799860a429 100644 --- a/src/modules/localip/localip.h +++ b/src/modules/localip/localip.h @@ -9,3 +9,4 @@ void ffInitLocalIpOptions(FFLocalIpOptions* options); bool ffParseLocalIpCommandOptions(FFLocalIpOptions* options, const char* key, const char* value); void ffDestroyLocalIpOptions(FFLocalIpOptions* options); void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module); +void ffGenerateLocalIpJson(FFLocalIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From dc29271987c1dddccc8b19cb17950b27cd81498d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Sep 2023 15:48:39 +0800 Subject: [PATCH 050/198] Media: add JSON format support --- src/modules/media/media.c | 19 ++++++++++++++++++- src/modules/media/media.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/modules/media/media.c b/src/modules/media/media.c index ef227cb9f7..7a0e01e770 100644 --- a/src/modules/media/media.c +++ b/src/modules/media/media.c @@ -107,7 +107,7 @@ void ffPrintMedia(FFMediaOptions* options) void ffInitMediaOptions(FFMediaOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEDIA_MODULE_NAME, ffParseMediaCommandOptions, ffParseMediaJsonObject, ffPrintMedia, ffGenerateMediaJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -142,3 +142,20 @@ void ffParseMediaJsonObject(FFMediaOptions* options, yyjson_val* module) ffPrintError(FF_MEDIA_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateMediaJson(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFMediaResult* media = ffDetectMedia(); + + if(media->error.length > 0) + { + yyjson_mut_obj_add_strbuf(doc, module, "error", &media->error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "song", &media->song); + yyjson_mut_obj_add_strbuf(doc, obj, "artist", &media->artist); + yyjson_mut_obj_add_strbuf(doc, obj, "album", &media->album); + yyjson_mut_obj_add_strbuf(doc, obj, "status", &media->status); +} diff --git a/src/modules/media/media.h b/src/modules/media/media.h index f5267e5794..853814d7e5 100644 --- a/src/modules/media/media.h +++ b/src/modules/media/media.h @@ -9,3 +9,4 @@ void ffInitMediaOptions(FFMediaOptions* options); bool ffParseMediaCommandOptions(FFMediaOptions* options, const char* key, const char* value); void ffDestroyMediaOptions(FFMediaOptions* options); void ffParseMediaJsonObject(FFMediaOptions* options, yyjson_val* module); +void ffGenerateMediaJson(FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 849ff951160cccc5a34927b5aa8f8fe9114d5b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Sep 2023 15:53:52 +0800 Subject: [PATCH 051/198] Player: JSON format support --- src/modules/player/player.c | 18 +++++++++++++++++- src/modules/player/player.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/modules/player/player.c b/src/modules/player/player.c index 5e4bf68897..5ca58ba279 100644 --- a/src/modules/player/player.c +++ b/src/modules/player/player.c @@ -75,7 +75,7 @@ void ffPrintPlayer(FFPlayerOptions* options) void ffInitPlayerOptions(FFPlayerOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PLAYER_MODULE_NAME, ffParsePlayerCommandOptions, ffParsePlayerJsonObject, ffPrintPlayer, ffGeneratePlayerJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -110,3 +110,19 @@ void ffParsePlayerJsonObject(FFPlayerOptions* options, yyjson_val* module) ffPrintError(FF_PLAYER_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGeneratePlayerJson(FF_MAYBE_UNUSED FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFMediaResult* media = ffDetectMedia(); + + if(media->error.length > 0) + { + yyjson_mut_obj_add_strbuf(doc, module, "error", &media->error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "player", &media->player); + yyjson_mut_obj_add_strbuf(doc, obj, "playerId", &media->playerId); + yyjson_mut_obj_add_strbuf(doc, obj, "url", &media->url); +} diff --git a/src/modules/player/player.h b/src/modules/player/player.h index f63e12250d..829b7857a4 100644 --- a/src/modules/player/player.h +++ b/src/modules/player/player.h @@ -10,3 +10,4 @@ void ffInitPlayerOptions(FFPlayerOptions* options); bool ffParsePlayerCommandOptions(FFPlayerOptions* options, const char* key, const char* value); void ffDestroyPlayerOptions(FFPlayerOptions* options); void ffParsePlayerJsonObject(FFPlayerOptions* options, yyjson_val* module); +void ffGeneratePlayerJson(FFMediaOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 8bb88d1806aea6df2aab4b1c61a2fd64a002e7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Sep 2023 15:58:43 +0800 Subject: [PATCH 052/198] Memory: JSON format support --- src/modules/memory/memory.c | 18 +++++++++++++++++- src/modules/memory/memory.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 3d7cb71391..1d2bba3913 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -68,7 +68,7 @@ void ffPrintMemory(FFMemoryOptions* options) void ffInitMemoryOptions(FFMemoryOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MEMORY_MODULE_NAME, ffParseMemoryCommandOptions, ffParseMemoryJsonObject, ffPrintMemory, ffGenerateMemoryJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -103,3 +103,19 @@ void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module) ffPrintError(FF_MEMORY_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateMemoryJson(FF_MAYBE_UNUSED FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFMemoryResult storage; + const char* error = ffDetectMemory(&storage); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_uint(doc, obj, "total", storage.bytesTotal); + yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed); +} diff --git a/src/modules/memory/memory.h b/src/modules/memory/memory.h index aec76b21f7..b4fefff5dc 100644 --- a/src/modules/memory/memory.h +++ b/src/modules/memory/memory.h @@ -9,3 +9,4 @@ void ffInitMemoryOptions(FFMemoryOptions* options); bool ffParseMemoryCommandOptions(FFMemoryOptions* options, const char* key, const char* value); void ffDestroyMemoryOptions(FFMemoryOptions* options); void ffParseMemoryJsonObject(FFMemoryOptions* options, yyjson_val* module); +void ffGenerateMemoryJson(FFMemoryOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From a7c6e1165c1a43522dc3238b19a0f6803b486900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Sep 2023 16:01:10 +0800 Subject: [PATCH 053/198] Swap: JSON format support --- src/modules/swap/swap.c | 18 +++++++++++++++++- src/modules/swap/swap.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 1361009f91..331cbf26dd 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -75,7 +75,7 @@ void ffPrintSwap(FFSwapOptions* options) void ffInitSwapOptions(FFSwapOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SWAP_MODULE_NAME, ffParseSwapCommandOptions, ffParseSwapJsonObject, ffPrintSwap, ffGenerateSwapJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -110,3 +110,19 @@ void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module) ffPrintError(FF_SWAP_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateSwapJson(FF_MAYBE_UNUSED FFSwapOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFSwapResult storage; + const char* error = ffDetectSwap(&storage); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_uint(doc, obj, "total", storage.bytesTotal); + yyjson_mut_obj_add_uint(doc, obj, "used", storage.bytesUsed); +} diff --git a/src/modules/swap/swap.h b/src/modules/swap/swap.h index 5921ad9c54..fbb125a449 100644 --- a/src/modules/swap/swap.h +++ b/src/modules/swap/swap.h @@ -9,3 +9,4 @@ void ffInitSwapOptions(FFSwapOptions* options); bool ffParseSwapCommandOptions(FFSwapOptions* options, const char* key, const char* value); void ffDestroySwapOptions(FFSwapOptions* options); void ffParseSwapJsonObject(FFSwapOptions* options, yyjson_val* module); +void ffGenerateSwapJson(FFSwapOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From eb4636b9476f900a36d77454dcb4853cb2cc35aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Sep 2023 16:23:57 +0800 Subject: [PATCH 054/198] PowerAdapter: JSON format support --- src/modules/poweradapter/poweradapter.c | 31 ++++++++++++++++++++++++- src/modules/poweradapter/poweradapter.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index d847cb0cc4..a35ecfad45 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -62,7 +62,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_POWERADAPTER_MODULE_NAME, ffParsePowerAdapterCommandOptions, ffParsePowerAdapterJsonObject, ffPrintPowerAdapter, ffGeneratePowerAdapterJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -97,3 +97,32 @@ void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* m ffPrintError(FF_POWERADAPTER_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGeneratePowerAdapterJson(FF_MAYBE_UNUSED FFPowerAdapterOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(PowerAdapterResult)); + + const char* error = ffDetectPowerAdapterImpl(&results); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + } + else if(results.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No power adapters found"); + } + else + { + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(PowerAdapterResult, item, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "description", &item->description); + yyjson_mut_obj_add_strbuf(doc, obj, "manufacturer", &item->manufacturer); + yyjson_mut_obj_add_strbuf(doc, obj, "modelName", &item->modelName); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_int(doc, obj, "watts", item->watts); + } + } +} diff --git a/src/modules/poweradapter/poweradapter.h b/src/modules/poweradapter/poweradapter.h index e9490c8323..a99d6acabb 100644 --- a/src/modules/poweradapter/poweradapter.h +++ b/src/modules/poweradapter/poweradapter.h @@ -9,3 +9,4 @@ void ffInitPowerAdapterOptions(FFPowerAdapterOptions* options); bool ffParsePowerAdapterCommandOptions(FFPowerAdapterOptions* options, const char* key, const char* value); void ffDestroyPowerAdapterOptions(FFPowerAdapterOptions* options); void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* module); +void ffGeneratePowerAdapterJson(FFPowerAdapterOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From f995d8d806e852ed6fdc886fab62ebeeb94b4eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Sep 2023 16:27:02 +0800 Subject: [PATCH 055/198] PowerAdapter: rename `PowerAdapterResult` to `FFPowerAdapterResult` --- src/detection/poweradapter/poweradapter.h | 4 ++-- src/detection/poweradapter/poweradapter_apple.c | 2 +- src/modules/poweradapter/poweradapter.c | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/detection/poweradapter/poweradapter.h b/src/detection/poweradapter/poweradapter.h index 9abdd48ecf..0c60d4d9fe 100644 --- a/src/detection/poweradapter/poweradapter.h +++ b/src/detection/poweradapter/poweradapter.h @@ -5,14 +5,14 @@ #include "fastfetch.h" -typedef struct PowerAdapterResult +typedef struct FFPowerAdapterResult { FFstrbuf description; FFstrbuf name; FFstrbuf modelName; FFstrbuf manufacturer; int watts; -} PowerAdapterResult; +} FFPowerAdapterResult; const char* ffDetectPowerAdapterImpl(FFlist* results); diff --git a/src/detection/poweradapter/poweradapter_apple.c b/src/detection/poweradapter/poweradapter_apple.c index de3025a40b..06d8a8df6b 100644 --- a/src/detection/poweradapter/poweradapter_apple.c +++ b/src/detection/poweradapter/poweradapter_apple.c @@ -24,7 +24,7 @@ const char* ffDetectPowerAdapterImpl(FFlist* results) continue; } - PowerAdapterResult* adapter = ffListAdd(results); + FFPowerAdapterResult* adapter = ffListAdd(results); ffStrbufInit(&adapter->name); ffStrbufInit(&adapter->description); diff --git a/src/modules/poweradapter/poweradapter.c b/src/modules/poweradapter/poweradapter.c index a35ecfad45..a5ce64002c 100644 --- a/src/modules/poweradapter/poweradapter.c +++ b/src/modules/poweradapter/poweradapter.c @@ -9,7 +9,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) { - FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(PowerAdapterResult)); + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFPowerAdapterResult)); const char* error = ffDetectPowerAdapterImpl(&results); @@ -25,7 +25,7 @@ void ffPrintPowerAdapter(FFPowerAdapterOptions* options) { for(uint8_t i = 0; i < (uint8_t) results.length; i++) { - PowerAdapterResult* result = ffListGet(&results, i); + FFPowerAdapterResult* result = ffListGet(&results, i); if(result->watts != FF_POWERADAPTER_UNSET) { @@ -100,7 +100,7 @@ void ffParsePowerAdapterJsonObject(FFPowerAdapterOptions* options, yyjson_val* m void ffGeneratePowerAdapterJson(FF_MAYBE_UNUSED FFPowerAdapterOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(PowerAdapterResult)); + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFPowerAdapterResult)); const char* error = ffDetectPowerAdapterImpl(&results); @@ -115,7 +115,7 @@ void ffGeneratePowerAdapterJson(FF_MAYBE_UNUSED FFPowerAdapterOptions* options, else { yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); - FF_LIST_FOR_EACH(PowerAdapterResult, item, results) + FF_LIST_FOR_EACH(FFPowerAdapterResult, item, results) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "description", &item->description); From 98833b4d7492c926abbc4b0d4e11a4c9abe81bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 6 Sep 2023 16:33:51 +0800 Subject: [PATCH 056/198] Monitor: add JSON support --- src/modules/monitor/monitor.c | 32 +++++++++++++++++++++++++++++++- src/modules/monitor/monitor.h | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 15b801fa1d..c7f76a0394 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -77,7 +77,7 @@ void ffPrintMonitor(FFMonitorOptions* options) void ffInitMonitorOptions(FFMonitorOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_MONITOR_MODULE_NAME, ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, ffGenerateMonitorJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -112,3 +112,33 @@ void ffParseMonitorJsonObject(FFMonitorOptions* options, yyjson_val* module) ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateMonitorJson(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFMonitorResult)); + + const char* error = ffDetectMonitor(&results); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + } + else if(results.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No monitors found"); + } + else + { + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFMonitorResult, item, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_bool(doc, obj, "hdrCompatible", item->hdrCompatible); + yyjson_mut_obj_add_uint(doc, obj, "width", item->width); + yyjson_mut_obj_add_uint(doc, obj, "height", item->height); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_uint(doc, obj, "physicalHeight", item->physicalHeight); + yyjson_mut_obj_add_uint(doc, obj, "physicalWidth", item->physicalWidth); + } + } +} diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h index ff03d26e96..8511442040 100644 --- a/src/modules/monitor/monitor.h +++ b/src/modules/monitor/monitor.h @@ -9,3 +9,4 @@ void ffInitMonitorOptions(FFMonitorOptions* options); bool ffParseMonitorCommandOptions(FFMonitorOptions* options, const char* key, const char* value); void ffDestroyMonitorOptions(FFMonitorOptions* options); void ffParseMonitorJsonObject(FFMonitorOptions* options, yyjson_val* module); +void ffGenerateMonitorJson(FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From cdaf5e9281499099ac8237e4718dbcc7fc4fb92d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 09:20:52 +0800 Subject: [PATCH 057/198] OpenCL: JSON format support --- src/detection/opencl/opencl.c | 3 +++ src/modules/opencl/opencl.c | 28 +++++++++++++++++++++++++++- src/modules/opencl/opencl.h | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index d8cb4a66b4..0526de2e22 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -49,14 +49,17 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) if(ffStrStartsWithIgnCase(version, "OpenCL ")) versionPretty = version + strlen("OpenCL "); ffStrbufSetS(&result->version, versionPretty); + ffStrbufTrim(&result->version, ' '); ffStrbufEnsureFree(&result->device, 128); data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, result->device.allocated, result->device.chars, NULL); ffStrbufRecalculateLength(&result->device); + ffStrbufTrim(&result->device, ' '); ffStrbufEnsureFree(&result->vendor, 32); data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, result->vendor.allocated, result->vendor.chars, NULL); ffStrbufRecalculateLength(&result->vendor); + ffStrbufTrim(&result->vendor, ' '); return NULL; } diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 4218dbfd22..afe3efa244 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -41,7 +41,7 @@ void ffPrintOpenCL(FFOpenCLOptions* options) void ffInitOpenCLOptions(FFOpenCLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENCL_MODULE_NAME, ffParseOpenCLCommandOptions, ffParseOpenCLJsonObject, ffPrintOpenCL, ffGenerateOpenCLJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -76,3 +76,29 @@ void ffParseOpenCLJsonObject(FFOpenCLOptions* options, yyjson_val* module) ffPrintError(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateOpenCLJson(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFOpenCLResult opencl; + ffStrbufInit(&opencl.version); + ffStrbufInit(&opencl.device); + ffStrbufInit(&opencl.vendor); + + const char* error = ffDetectOpenCL(&opencl); + + if(error != NULL) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + } + else + { + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &opencl.version); + yyjson_mut_obj_add_strbuf(doc, obj, "device", &opencl.device); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &opencl.vendor); + } + + ffStrbufDestroy(&opencl.version); + ffStrbufDestroy(&opencl.device); + ffStrbufDestroy(&opencl.vendor); +} diff --git a/src/modules/opencl/opencl.h b/src/modules/opencl/opencl.h index f5e2a32c2c..592f453bf1 100644 --- a/src/modules/opencl/opencl.h +++ b/src/modules/opencl/opencl.h @@ -9,3 +9,4 @@ void ffInitOpenCLOptions(FFOpenCLOptions* options); bool ffParseOpenCLCommandOptions(FFOpenCLOptions* options, const char* key, const char* value); void ffDestroyOpenCLOptions(FFOpenCLOptions* options); void ffParseOpenCLJsonObject(FFOpenCLOptions* options, yyjson_val* module); +void ffGenerateOpenCLJson(FFOpenCLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 34902db21c7675b9601f185c8196476c126d1b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 09:28:04 +0800 Subject: [PATCH 058/198] OpenGL: JSON format support --- src/modules/opengl/opengl.c | 30 +++++++++++++++++++++++++++++- src/modules/opengl/opengl.h | 1 + 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/modules/opengl/opengl.c b/src/modules/opengl/opengl.c index 56f03a0cb7..78bbf18428 100644 --- a/src/modules/opengl/opengl.c +++ b/src/modules/opengl/opengl.c @@ -44,7 +44,7 @@ void ffPrintOpenGL(FFOpenGLOptions* options) void ffInitOpenGLOptions(FFOpenGLOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OPENGL_MODULE_NAME, ffParseOpenGLCommandOptions, ffParseOpenGLJsonObject, ffPrintOpenGL, ffGenerateOpenGLJson); ffOptionInitModuleArg(&options->moduleArgs); #if defined(__linux__) || defined(__FreeBSD__) @@ -115,3 +115,31 @@ void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module) ffPrintError(FF_OPENGL_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateOpenGLJson(FF_MAYBE_UNUSED FFOpenGLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFOpenGLResult result; + ffStrbufInit(&result.version); + ffStrbufInit(&result.renderer); + ffStrbufInit(&result.vendor); + ffStrbufInit(&result.slv); + + const char* error = ffDetectOpenGL(options, &result); + if(error != NULL) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + } + else + { + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); + yyjson_mut_obj_add_strbuf(doc, obj, "renderer", &result.renderer); + yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &result.vendor); + yyjson_mut_obj_add_strbuf(doc, obj, "slv", &result.slv); + } + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.renderer); + ffStrbufDestroy(&result.vendor); + ffStrbufDestroy(&result.slv); +} diff --git a/src/modules/opengl/opengl.h b/src/modules/opengl/opengl.h index 5d0b1937bc..6c35ede54e 100644 --- a/src/modules/opengl/opengl.h +++ b/src/modules/opengl/opengl.h @@ -9,3 +9,4 @@ void ffInitOpenGLOptions(FFOpenGLOptions* options); bool ffParseOpenGLCommandOptions(FFOpenGLOptions* options, const char* key, const char* value); void ffDestroyOpenGLOptions(FFOpenGLOptions* options); void ffParseOpenGLJsonObject(FFOpenGLOptions* options, yyjson_val* module); +void ffGenerateOpenGLJson(FFOpenGLOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 9eb35d396781edb93d9acf05eb6d1decf63632c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 09:36:04 +0800 Subject: [PATCH 059/198] OS: JSON format support --- src/modules/os/os.c | 25 ++++++++++++++++++++++++- src/modules/os/os.h | 1 + 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/modules/os/os.c b/src/modules/os/os.c index b40dde0383..b905360e69 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -139,7 +139,7 @@ void ffPrintOS(FFOSOptions* options) void ffInitOSOptions(FFOSOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_OS_MODULE_NAME, ffParseOSCommandOptions, ffParseOSJsonObject, ffPrintOS, ffGenerateOSJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -174,3 +174,26 @@ void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module) ffPrintError(FF_OS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateOSJson(FF_MAYBE_UNUSED FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFOSResult* os = ffDetectOS(); + + if(os->name.length == 0 && os->prettyName.length == 0 && os->id.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "Could not detect OS"); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "buildID", &os->buildID); + yyjson_mut_obj_add_strbuf(doc, obj, "codename", &os->codename); + yyjson_mut_obj_add_strbuf(doc, obj, "id", &os->id); + yyjson_mut_obj_add_strbuf(doc, obj, "idLike", &os->idLike); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &os->name); + yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &os->prettyName); + yyjson_mut_obj_add_strbuf(doc, obj, "variant", &os->variant); + yyjson_mut_obj_add_strbuf(doc, obj, "variantID", &os->variantID); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &os->version); + yyjson_mut_obj_add_strbuf(doc, obj, "versionID", &os->versionID); +} diff --git a/src/modules/os/os.h b/src/modules/os/os.h index 07320194d3..b7ed39d0d4 100644 --- a/src/modules/os/os.h +++ b/src/modules/os/os.h @@ -9,3 +9,4 @@ void ffInitOSOptions(FFOSOptions* options); bool ffParseOSCommandOptions(FFOSOptions* options, const char* key, const char* value); void ffDestroyOSOptions(FFOSOptions* options); void ffParseOSJsonObject(FFOSOptions* options, yyjson_val* module); +void ffGenerateOSJson(FFOSOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 77d388ce1dba46d64810516c4cb280384bc08cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 15:00:22 +0800 Subject: [PATCH 060/198] Disk (BSD): use `getfsstat` instead of `getmntinfo` for thread safety --- src/detection/disk/disk_bsd.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index b6c656e8bd..69431950f4 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -1,4 +1,5 @@ #include "disk.h" +#include "util/mallocHelper.h" #include @@ -28,11 +29,14 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk); const char* ffDetectDisksImpl(FFlist* disks) { - struct statfs* buf; + int size = getfsstat(NULL, 0, MNT_WAIT); - int size = getmntinfo(&buf, MNT_WAIT); if(size <= 0) - return "getmntinfo(&buf, MNT_WAIT) failed"; + return "getfsstat(NULL, 0, MNT_WAIT) failed"; + + FF_AUTO_FREE struct statfs* buf = malloc(sizeof(*buf) * (unsigned) size); + if(getfsstat(buf, (int) (sizeof(*buf) * (unsigned) size), MNT_NOWAIT) <= 0) + return "getfsstat(buf, size, MNT_NOWAIT) failed"; for(struct statfs* fs = buf; fs < buf + size; ++fs) { From 598dfd2b0269316c7c6516efae306a6fb1a907d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 16:00:00 +0800 Subject: [PATCH 061/198] Disk (Apple): use `getattrlist` to detect volume name No functional changes --- CMakeLists.txt | 1 - src/detection/disk/disk_apple.m | 17 ----------------- src/detection/disk/disk_bsd.c | 30 +++++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 21 deletions(-) delete mode 100644 src/detection/disk/disk_apple.m diff --git a/CMakeLists.txt b/CMakeLists.txt index a799086bac..fc0562fa0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -515,7 +515,6 @@ elseif(APPLE) src/detection/cpu/cpu_apple.c src/detection/cpuusage/cpuusage_apple.c src/detection/cursor/cursor_apple.m - src/detection/disk/disk_apple.m src/detection/disk/disk_bsd.c src/detection/displayserver/displayserver_apple.c src/detection/font/font_apple.m diff --git a/src/detection/disk/disk_apple.m b/src/detection/disk/disk_apple.m deleted file mode 100644 index 81bcdeb482..0000000000 --- a/src/detection/disk/disk_apple.m +++ /dev/null @@ -1,17 +0,0 @@ -#include "disk.h" - -#include -#import - -void detectFsInfo(struct statfs* fs, FFDisk* disk) -{ - // FreeBSD doesn't support these flags - if(fs->f_flags & MNT_DONTBROWSE) - disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; - else if(fs->f_flags & MNT_REMOVABLE) - disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; - else - disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; - - ffStrbufInitS(&disk->name, [NSFileManager.defaultManager displayNameAtPath:@(fs->f_mntonname)].UTF8String); -} diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 69431950f4..efe98db9b1 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -20,11 +20,33 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk) disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; +} +#elif __APPLE__ +#include +#include + +struct VolAttrBuf { + uint32_t length; + attrreference_t volNameRef; + char volNameSpace[MAXPATHLEN]; +} __attribute__((aligned(4), packed)); + +void detectFsInfo(struct statfs* fs, FFDisk* disk) +{ + if(fs->f_flags & MNT_DONTBROWSE) + disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; + else if(fs->f_flags & MNT_REMOVABLE) + disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; + else + disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; - ffStrbufInit(&disk->name); + struct VolAttrBuf attrBuf; + if (getattrlist(fs->f_mntonname, &(struct attrlist) { + .bitmapcount = ATTR_BIT_MAP_COUNT, + .volattr = ATTR_VOL_INFO | ATTR_VOL_NAME, + }, &attrBuf, sizeof(attrBuf), 0) == 0) + ffStrbufInitNS(&disk->name, attrBuf.volNameRef.attr_length - 1 /* excluding '\0' */, attrBuf.volNameSpace); } -#else -void detectFsInfo(struct statfs* fs, FFDisk* disk); #endif const char* ffDetectDisksImpl(FFlist* disks) @@ -58,6 +80,8 @@ const char* ffDetectDisksImpl(FFlist* disks) ffStrbufInitS(&disk->mountpoint, fs->f_mntonname); ffStrbufInitS(&disk->filesystem, fs->f_fstypename); + ffStrbufInit(&disk->name); + disk->type = 0; detectFsInfo(fs, disk); if(fs->f_flags & MNT_RDONLY) From 904c9eb3c48dfb7d3f3657762860cec73e66ff56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 16:01:19 +0800 Subject: [PATCH 062/198] CPU (macOS): code refactor --- src/detection/cpu/cpu_apple.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index da55404ee7..792a9aaacc 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -2,17 +2,6 @@ #include "common/sysctl.h" #include "detection/temps/temps_apple.h" -static double getFrequency(const char* propName) -{ - double herz = (double) ffSysctlGetInt64(propName, 0); - if(herz <= 0.0) - return herz; - - herz /= 1000.0; //to KHz - herz /= 1000.0; //to MHz - return herz / 1000.0; //to GHz -} - static double detectCpuTemp(const FFstrbuf* cpuName) { double result = 0; @@ -52,10 +41,17 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if(cpu->coresOnline == 1) cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1); - cpu->frequencyMin = getFrequency("hw.cpufrequency_min"); - cpu->frequencyMax = getFrequency("hw.cpufrequency_max"); - if(cpu->frequencyMax == 0.0) - cpu->frequencyMax = getFrequency("hw.cpufrequency"); + cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0; + cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0); + if(cpu->frequencyMax > 0.0) + cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0; + else + { + unsigned current = 0; + size_t size = sizeof(current); + if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0) + cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0; + } cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET; From d8b215114308f46b8b9008cfa7119ab5ccd65d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 17:03:12 +0800 Subject: [PATCH 063/198] CPU (macOS): support Apple Silicon frequency detection --- src/detection/cpu/cpu_apple.c | 83 ++++++++++++++++++++++++++++++----- src/util/apple/cf_helpers.c | 21 +++++++++ src/util/apple/cf_helpers.h | 1 + 3 files changed, 94 insertions(+), 11 deletions(-) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 792a9aaacc..ded5e0d899 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -20,6 +20,77 @@ static double detectCpuTemp(const FFstrbuf* cpuName) return result; } +#ifdef __aarch64__ +#include "util/apple/cf_helpers.h" + +#include + +static const char* detectFrequency(FFCPUResult* cpu) +{ + // https://github.com/giampaolo/psutil/pull/2222/files + + CFMutableDictionaryRef matchDict = IOServiceMatching("AppleARMIODevice"); + if (matchDict == NULL) + return "IOServiceMatching(\"AppleARMIODevice\") failed"; + + io_iterator_t iterator; + if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess) + return "IOServiceGetMatchingServices() failed"; + + io_registry_entry_t registryEntry; + while((registryEntry = IOIteratorNext(iterator)) != 0) + { + CFMutableDictionaryRef properties; + if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) + { + IOObjectRelease(registryEntry); + continue; + } + + io_name_t name; + if (IORegistryEntryGetName(registryEntry, name) != KERN_SUCCESS) + continue; + if (strcmp(name, "pmgr") != 0) + continue; + + uint32_t pMin, eMin, aMax, pCoreLength; + ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), 0, 4, (uint8_t*) &pMin, &pCoreLength); // pCore + ffCfDictGetData(properties, CFSTR("voltage-states1-sram"), 0, 4, (uint8_t*) &eMin, NULL); // eCore + cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000); + + if (pCoreLength >= 8) + { + ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL); + cpu->frequencyMax = aMax / (1000.0 * 1000 * 1000); + } + else + cpu->frequencyMax = 0.0; + + CFRelease(properties); + IOObjectRelease(registryEntry); + } + + IOObjectRelease(iterator); + return NULL; +} +#else +static const char* detectFrequency(FFCPUResult* cpu) +{ + cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0; + cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0); + if(cpu->frequencyMax > 0.0) + cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0; + else + { + unsigned current = 0; + size_t size = sizeof(current); + if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0) + cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0; + } + return NULL; +} +#endif + const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL) @@ -41,17 +112,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if(cpu->coresOnline == 1) cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1); - cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0; - cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0); - if(cpu->frequencyMax > 0.0) - cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0; - else - { - unsigned current = 0; - size_t size = sizeof(current); - if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0) - cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0; - } + detectFrequency(cpu); cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET; diff --git a/src/util/apple/cf_helpers.c b/src/util/apple/cf_helpers.c index 797b51b591..2ce563d5ed 100644 --- a/src/util/apple/cf_helpers.c +++ b/src/util/apple/cf_helpers.c @@ -83,6 +83,27 @@ const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result) return "TypeID is neither 'CFNumber' nor 'CFData'"; } +const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length) +{ + CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key); + if(cf == NULL) + return "CFDictionaryGetValue() failed"; + + if(CFGetTypeID(cf) != CFDataGetTypeID()) + return "TypeID is not 'CFData'"; + + CFIndex trueLength = CFDataGetLength((CFDataRef)cf); + + if(trueLength < offset + size) + return "Data length is less than offset + size"; + + if(length) + *length = (uint32_t) trueLength; + + CFDataGetBytes((CFDataRef)cf, CFRangeMake(offset, size), result); + return NULL; +} + const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result) { CFDictionaryRef cf = (CFDictionaryRef)CFDictionaryGetValue(dict, key); diff --git a/src/util/apple/cf_helpers.h b/src/util/apple/cf_helpers.h index 52755bb8bc..a8d9804a3f 100644 --- a/src/util/apple/cf_helpers.h +++ b/src/util/apple/cf_helpers.h @@ -11,6 +11,7 @@ const char* ffCfStrGetString(CFStringRef str, FFstrbuf* result); const char* ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result); const char* ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result); const char* ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result); +const char* ffCfDictGetData(CFDictionaryRef dict, CFStringRef key, uint32_t offset, uint32_t size, uint8_t* result, uint32_t* length); const char* ffCfDictGetDict(CFDictionaryRef dict, CFStringRef key, CFDictionaryRef* result); static inline CFNumberRef ffCfCreateInt(int value) From fe9fcd603bacb1d4cefa86026c78761d6789dd06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 7 Sep 2023 17:03:24 +0800 Subject: [PATCH 064/198] CPU (Windows): fix possible memory errors --- src/detection/cpu/cpu_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 231ea342e4..59f07ab7ad 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -35,7 +35,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) return "GetLogicalProcessorInformationEx(RelationAll, pProcessorInfo, &length) failed"; } - FF_HKEY_AUTO_DESTROY hKey; + FF_HKEY_AUTO_DESTROY hKey = NULL; if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL)) return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed"; From a093ca200137f6b15b0547a602635081b6bdf9a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 00:07:14 +0800 Subject: [PATCH 065/198] Users: add more detailed information --- src/common/format.c | 2 + src/common/format.h | 1 + src/detection/users/users.h | 11 +++- src/detection/users/users_linux.c | 22 +++++-- src/detection/users/users_windows.c | 44 +++++++++---- src/modules/users/option.h | 2 + src/modules/users/users.c | 98 +++++++++++++++++++++++------ src/util/windows/unicode.h | 3 + 8 files changed, 147 insertions(+), 36 deletions(-) diff --git a/src/common/format.c b/src/common/format.c index 4ed096dc1c..8ccf09fa3f 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -12,6 +12,8 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg) ffStrbufAppendF(buffer, "%i", *(int*)formatarg->value); else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT) ffStrbufAppendF(buffer, "%" PRIu32, *(uint32_t*)formatarg->value); + else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT64) + ffStrbufAppendF(buffer, "%" PRIu64, *(uint64_t*)formatarg->value); else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT16) ffStrbufAppendF(buffer, "%" PRIu16, *(uint16_t*)formatarg->value); else if(formatarg->type == FF_FORMAT_ARG_TYPE_UINT8) diff --git a/src/common/format.h b/src/common/format.h index 57c8c680fe..3e7c751f23 100644 --- a/src/common/format.h +++ b/src/common/format.h @@ -7,6 +7,7 @@ typedef enum FFformatargtype { FF_FORMAT_ARG_TYPE_NULL = 0, FF_FORMAT_ARG_TYPE_UINT, + FF_FORMAT_ARG_TYPE_UINT64, FF_FORMAT_ARG_TYPE_UINT16, FF_FORMAT_ARG_TYPE_UINT8, FF_FORMAT_ARG_TYPE_INT, diff --git a/src/detection/users/users.h b/src/detection/users/users.h index 8842e16a2e..7248d83228 100644 --- a/src/detection/users/users.h +++ b/src/detection/users/users.h @@ -5,6 +5,15 @@ #include "fastfetch.h" -void ffDetectUsers(FFlist* users /* List of FFstrbuf */, FFstrbuf* error); +typedef struct FFUserResult +{ + FFstrbuf name; + FFstrbuf hostname; + FFstrbuf clientIp; + FFstrbuf tty; + uint64_t loginTime; // ms +} FFUserResult; + +const char* ffDetectUsers(FFlist* users); #endif diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index c17bf139c7..dbad1255d5 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -11,7 +11,7 @@ #define getutxent getutent #endif -void ffDetectUsers(FFlist* users, FFstrbuf* error) +const char* ffDetectUsers(FFlist* users) { struct utmpx* n = NULL; setutxent(); @@ -22,15 +22,25 @@ void ffDetectUsers(FFlist* users, FFstrbuf* error) if(n->ut_type != USER_PROCESS) continue; - FF_LIST_FOR_EACH(FFstrbuf, user, *users) + FF_LIST_FOR_EACH(FFUserResult, user, *users) { - if(ffStrbufEqualS(user, n->ut_user)) + if(ffStrbufEqualS(&user->name, n->ut_user)) goto next; } - ffStrbufInitS((FFstrbuf*)ffListAdd(users), n->ut_user); + FFUserResult* user = (FFUserResult*) ffListAdd(users); + ffStrbufInitS(&user->name, n->ut_user); + ffStrbufInitS(&user->hostname, n->ut_host); + ffStrbufInitS(&user->tty, n->ut_line); + #ifdef __linux__ + if(n->ut_addr_v6[0] || n->ut_addr_v6[1] || n->ut_addr_v6[2] || n->ut_addr_v6[3]) + ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", n->ut_addr_v6[0], n->ut_addr_v6[1], n->ut_addr_v6[2], n->ut_addr_v6[3]); + else + #else + ffStrbufInit(&user->clientIp); + #endif + user->loginTime = (uint64_t) n->ut_tv.tv_sec * 1000 + (uint64_t) n->ut_tv.tv_usec / 1000; } - if(users->length == 0) - ffStrbufAppendS(error, "Unable to detect users"); + return NULL; } diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index 01fab40a77..6ef9126703 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -4,17 +4,20 @@ #include #include -void ffDetectUsers(FFlist* users, FFstrbuf* error) +static uint64_t to_ms(uint64_t ret) +{ + ret -= 116444736000000000ull; + return ret / 10000ull; +} + +const char* ffDetectUsers(FFlist* users) { WTS_SESSION_INFO_1W* sessionInfo; DWORD sessionCount; DWORD level = 1; if(!WTSEnumerateSessionsExW(WTS_CURRENT_SERVER_HANDLE, &level, 0, &sessionInfo, &sessionCount)) - { - ffStrbufAppendS(error, "WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE) failed"); - return; - } + return "WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE) failed"; for (DWORD i = 0; i < sessionCount; i++) { @@ -22,14 +25,33 @@ void ffDetectUsers(FFlist* users, FFstrbuf* error) if(session->State != WTSActive) continue; - FF_STRBUF_AUTO_DESTROY domainName = ffStrbufCreateWS(session->pDomainName); - FF_STRBUF_AUTO_DESTROY userName = ffStrbufCreateWS(session->pUserName); - - ffStrbufInitF((FFstrbuf*)ffListAdd(users), "%s\\%s", domainName.chars, userName.chars); + FFUserResult* user = (FFUserResult*) ffListAdd(users); + ffStrbufInitWS(&user->name, session->pUserName); + ffStrbufInitWS(&user->hostname, session->pHostName); + + DWORD bytes = 0; + PWTS_CLIENT_ADDRESS address = NULL; + if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSClientAddress, (LPWSTR *) &address, &bytes)) + { + if (address->AddressFamily == 2 /*AF_INET*/) + ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", address->Address[2], address->Address[3], address->Address[4], address->Address[5]); + WTSFreeMemory(address); + } + else + ffStrbufInitS(&user->clientIp, "0.0.0.0"); + + bytes = 0; + PWTSINFOW wtsInfo = NULL; + if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session->SessionId, WTSSessionInfo, (LPWSTR *) &wtsInfo, &bytes)) + { + user->loginTime = to_ms(*(uint64_t*) &wtsInfo->LogonTime); + WTSFreeMemory(wtsInfo); + } + else + user->loginTime = 0; } WTSFreeMemoryExW(WTSTypeSessionInfoLevel1, sessionInfo, 1); - if(users->length == 0) - ffStrbufAppendS(error, "Unable to detect users"); + return NULL; } diff --git a/src/modules/users/option.h b/src/modules/users/option.h index 80bf876985..6883e8dd08 100644 --- a/src/modules/users/option.h +++ b/src/modules/users/option.h @@ -8,4 +8,6 @@ typedef struct FFUsersOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + + bool compact; } FFUsersOptions; diff --git a/src/modules/users/users.c b/src/modules/users/users.c index 6c63870821..764e738112 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -4,42 +4,90 @@ #include "modules/users/users.h" #include "util/stringUtils.h" +#include + #define FF_USERS_NUM_FORMAT_ARGS 1 void ffPrintUsers(FFUsersOptions* options) { - FF_LIST_AUTO_DESTROY users = ffListCreate(sizeof(FFstrbuf)); - - FF_STRBUF_AUTO_DESTROY error = ffStrbufCreate(); + FF_LIST_AUTO_DESTROY users = ffListCreate(sizeof(FFUserResult)); - ffDetectUsers(&users, &error); + const char* error = ffDetectUsers(&users); - if(error.length > 0) + if(error) { - ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "%*s", error.length, error.chars); + ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "%s", error); return; } - FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); - for(uint32_t i = 0; i < users.length; ++i) + if(users.length == 0) { - if(i > 0) - ffStrbufAppendS(&result, ", "); - FFstrbuf* user = (FFstrbuf*)ffListGet(&users, i); - ffStrbufAppend(&result, user); - ffStrbufDestroy(user); + ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "%s", "Unable to detect any users"); + return; } if(options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - puts(result.chars); + if(options->compact) + { + ffPrintLogoAndKey(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); + for(uint32_t i = 0; i < users.length; ++i) + { + if(i > 0) + ffStrbufAppendS(&result, ", "); + FFUserResult* user = (FFUserResult*)ffListGet(&users, i); + ffStrbufAppend(&result, &user->name); + } + ffStrbufPutTo(&result, stdout); + } + else + { + for(uint32_t i = 0; i < users.length; ++i) + { + FFUserResult* user = (FFUserResult*)ffListGet(&users, i); + + ffPrintLogoAndKey(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateCopy(&user->name); + if(user->hostname.length) + ffStrbufAppendF(&result, "@%s", user->hostname.chars); + + if(user->loginTime) + { + char buf[64]; + time_t time = (time_t) (user->loginTime / 1000); + strftime(buf, sizeof(buf), "%FT%T%z", localtime(&time)); + ffStrbufAppendF(&result, " - login time %s", buf); + } + + ffStrbufPutTo(&result, stdout); + } + } } else { - ffPrintFormat(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &result}, - }); + for(uint32_t i = 0; i < users.length; ++i) + { + FFUserResult* user = (FFUserResult*)ffListGet(&users, i); + + ffPrintFormat(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &user->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &user->hostname}, + {FF_FORMAT_ARG_TYPE_STRBUF, &user->tty}, + {FF_FORMAT_ARG_TYPE_STRBUF, &user->clientIp}, + {FF_FORMAT_ARG_TYPE_UINT64, &user->loginTime}, + }); + } + } + + FF_LIST_FOR_EACH(FFUserResult, user, users) + { + ffStrbufDestroy(&user->clientIp); + ffStrbufDestroy(&user->hostname); + ffStrbufDestroy(&user->tty); + ffStrbufDestroy(&user->name); } } @@ -47,6 +95,8 @@ void ffInitUsersOptions(FFUsersOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, NULL); ffOptionInitModuleArg(&options->moduleArgs); + + options->compact = true; } bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const char* value) @@ -56,6 +106,12 @@ bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if(ffStrEqualsIgnCase(subKey, "compact")) + { + options->compact = ffOptionParseBoolean(value); + return true; + } + return false; } @@ -77,6 +133,12 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffStrEqualsIgnCase(key, "compact")) + { + options->compact = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } diff --git a/src/util/windows/unicode.h b/src/util/windows/unicode.h index 6892134dc2..a25d4a7b48 100644 --- a/src/util/windows/unicode.h +++ b/src/util/windows/unicode.h @@ -10,6 +10,7 @@ void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source); static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source) { + if (!source) return ffStrbufClear(result); return ffStrbufSetNWS(result, (uint32_t)wcslen(source), source); } @@ -17,6 +18,7 @@ void ffStrbufInitNWS(FFstrbuf* result, uint32_t length, const wchar_t* source); static inline void ffStrbufInitWS(FFstrbuf* result, const wchar_t* source) { + if (!source) return ffStrbufInit(result); return ffStrbufInitNWS(result, (uint32_t)wcslen(source), source); } @@ -29,6 +31,7 @@ static inline FFstrbuf ffStrbufCreateNWS(uint32_t length, const wchar_t* source) static inline FFstrbuf ffStrbufCreateWS(const wchar_t* source) { + if (!source) return ffStrbufCreate(); return ffStrbufCreateNWS((uint32_t)wcslen(source), source); } From cde2ba2c18cce3f403d8d01444b33ed2fcfc946c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 11:08:29 +0800 Subject: [PATCH 066/198] Uptime: detect boot time --- src/detection/uptime/uptime.h | 8 ++++++- src/detection/uptime/uptime_bsd.c | 30 ++++++++++++++++++--------- src/detection/uptime/uptime_linux.c | 20 ++++++++++++------ src/detection/uptime/uptime_windows.c | 13 ++++++++++-- src/detection/users/users_windows.c | 2 +- src/modules/uptime/uptime.c | 24 ++++++++++++++------- 6 files changed, 70 insertions(+), 27 deletions(-) diff --git a/src/detection/uptime/uptime.h b/src/detection/uptime/uptime.h index 447b13d5b6..105e1bfa5c 100644 --- a/src/detection/uptime/uptime.h +++ b/src/detection/uptime/uptime.h @@ -5,6 +5,12 @@ #include "fastfetch.h" -const char* ffDetectUptime(uint64_t* result); +typedef struct FFUptimeResult +{ + uint64_t bootTime; + uint64_t uptime; +} FFUptimeResult; + +const char* ffDetectUptime(FFUptimeResult* result); #endif diff --git a/src/detection/uptime/uptime_bsd.c b/src/detection/uptime/uptime_bsd.c index 4e3a707c6e..0b1bf00c7f 100644 --- a/src/detection/uptime/uptime_bsd.c +++ b/src/detection/uptime/uptime_bsd.c @@ -4,18 +4,28 @@ #include #include -const char* ffDetectUptime(uint64_t* result) +const char* ffDetectUptime(FFUptimeResult* result) { - struct timeval bootTime; - size_t bootTimeSize = sizeof(bootTime); - if(sysctl( - (int[]) {CTL_KERN, KERN_BOOTTIME}, 2, - &bootTime, &bootTimeSize, - NULL, 0 - ) != 0) - return "sysctl({CTL_KERN, KERN_BOOTTIME}) failed"; + { + struct timeval bootTime; + size_t bootTimeSize = sizeof(bootTime); + if(sysctl( + (int[]) {CTL_KERN, KERN_BOOTTIME}, 2, + &bootTime, &bootTimeSize, + NULL, 0 + ) != 0) + return "sysctl({CTL_KERN, KERN_BOOTTIME}) failed"; - *result = (uint64_t) difftime(time(NULL), bootTime.tv_sec); + result->bootTime = (uint64_t) bootTime.tv_sec * 1000 + (uint64_t) bootTime.tv_usec / 1000; + } + + { + struct timespec realTime; + if(clock_gettime(CLOCK_REALTIME, &realTime) != 0) + return "clock_gettime(CLOCK_REALTIME) failed"; + uint64_t now = (uint64_t) realTime.tv_sec * 1000 + (uint64_t) realTime.tv_nsec / 1000000; + result->uptime = now - result->bootTime; + } return NULL; } diff --git a/src/detection/uptime/uptime_linux.c b/src/detection/uptime/uptime_linux.c index 0339bc7e65..039d550da2 100644 --- a/src/detection/uptime/uptime_linux.c +++ b/src/detection/uptime/uptime_linux.c @@ -1,12 +1,20 @@ #include "uptime.h" -#include +#include -const char* ffDetectUptime(uint64_t* result) +const char* ffDetectUptime(FFUptimeResult* result) { - struct sysinfo info; - if(sysinfo(&info) != 0) - return "sysinfo() failed"; - *result = (uint64_t) info.uptime; + struct timespec uptime; + if (clock_gettime(CLOCK_BOOTTIME, &uptime) != 0) + return "clock_gettime(CLOCK_BOOTTIME) failed"; + + result->uptime = (uint64_t) uptime.tv_sec * 1000 + (uint64_t) uptime.tv_nsec / 1000000; + + struct timespec realTime; + if(clock_gettime(CLOCK_REALTIME, &realTime) != 0) + return "clock_gettime(CLOCK_REALTIME) failed"; + + result->bootTime = (uint64_t) realTime.tv_sec * 1000 + (uint64_t) realTime.tv_nsec / 1000000 + result->uptime; + return NULL; } diff --git a/src/detection/uptime/uptime_windows.c b/src/detection/uptime/uptime_windows.c index 55053ab246..10f7157bbe 100644 --- a/src/detection/uptime/uptime_windows.c +++ b/src/detection/uptime/uptime_windows.c @@ -2,8 +2,17 @@ #include -const char* ffDetectUptime(uint64_t* result) +static inline uint64_t to_ms(uint64_t ret) { - *result = GetTickCount64() / 1000; + ret -= 116444736000000000ull; + return ret / 10000ull; +} + +const char* ffDetectUptime(FFUptimeResult* result) +{ + result->uptime = GetTickCount64(); + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + result->bootTime = to_ms(*(uint64_t*) &fileTime) - result->uptime; return NULL; } diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index 6ef9126703..0c222ef91c 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -4,7 +4,7 @@ #include #include -static uint64_t to_ms(uint64_t ret) +static inline uint64_t to_ms(uint64_t ret) { ret -= 116444736000000000ull; return ret / 10000ull; diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 89c93fd171..74bce2798d 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -8,9 +8,9 @@ void ffPrintUptime(FFUptimeOptions* options) { - uint64_t uptime; + FFUptimeResult result; - const char* error = ffDetectUptime(&uptime); + const char* error = ffDetectUptime(&result); if(error) { @@ -18,10 +18,17 @@ void ffPrintUptime(FFUptimeOptions* options) return; } - uint32_t days = (uint32_t) uptime / 86400; - uint32_t hours = (uint32_t) (uptime - (days * 86400)) / 3600; - uint32_t minutes = (uint32_t) (uptime - (days * 86400) - (hours * 3600)) / 60; - uint32_t seconds = (uint32_t) uptime - (days * 86400) - (hours * 3600) - (minutes * 60); + uint64_t uptime = result.uptime; + + uint32_t milliseconds = (uint32_t) (uptime % 1000); + uptime /= 1000; + uint32_t seconds = (uint32_t) (uptime % 60); + uptime /= 60; + uint32_t minutes = (uint32_t) (uptime % 60); + uptime /= 60; + uint32_t hours = (uint32_t) (uptime % 24); + uptime /= 24; + uint32_t days = (uint32_t) uptime; if(options->moduleArgs.outputFormat.length == 0) { @@ -74,7 +81,10 @@ void ffPrintUptime(FFUptimeOptions* options) {FF_FORMAT_ARG_TYPE_UINT, &days}, {FF_FORMAT_ARG_TYPE_UINT, &hours}, {FF_FORMAT_ARG_TYPE_UINT, &minutes}, - {FF_FORMAT_ARG_TYPE_UINT, &seconds} + {FF_FORMAT_ARG_TYPE_UINT, &seconds}, + {FF_FORMAT_ARG_TYPE_UINT, &milliseconds}, + {FF_FORMAT_ARG_TYPE_UINT64, &result.uptime}, + {FF_FORMAT_ARG_TYPE_UINT64, &result.bootTime}, }); } } From 7f1e2d2f03b6ec6de776f415c524f9ffecad952d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 15:25:22 +0800 Subject: [PATCH 067/198] Packages (Windows): support winget packages count Guarded behind `--allow-slow-operations` --- src/detection/packages/packages.h | 1 + src/detection/packages/packages_windows.c | 34 ++++++++++++++++++++++- src/fastfetch.c | 3 +- src/modules/packages/packages.c | 5 +++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index 77f8e68121..ae36b5078e 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -27,6 +27,7 @@ typedef struct FFPackagesResult uint32_t rpm; uint32_t scoop; uint32_t snap; + uint32_t winget; uint32_t xbps; uint32_t all; //Make sure this goes last diff --git a/src/detection/packages/packages_windows.c b/src/detection/packages/packages_windows.c index 5b5343f793..bfd6a4c793 100644 --- a/src/detection/packages/packages_windows.c +++ b/src/detection/packages/packages_windows.c @@ -1,4 +1,5 @@ #include "packages.h" +#include "common/processing.h" #include "util/stringUtils.h" #include @@ -62,7 +63,7 @@ static void detectChoco(FF_MAYBE_UNUSED FFPackagesResult* result) result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco"); } -static void detectPacman(FF_MAYBE_UNUSED FFPackagesResult* result) +static void detectPacman(FFPackagesResult* result) { const char* msystemPrefix = getenv("MSYSTEM_PREFIX"); if(!msystemPrefix) @@ -75,9 +76,40 @@ static void detectPacman(FF_MAYBE_UNUSED FFPackagesResult* result) result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL); } +static void detectWinget(FFPackagesResult* result) +{ + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (ffProcessAppendStdOut(&buffer, (char* []) { + "winget.exe", + "list", + "--disable-interactivity", + NULL, + })) + return; + + uint32_t index = ffStrbufFirstIndexS(&buffer, "--\r\n"); // Ignore garbage and table headers + if (index == buffer.length) + return; + + uint32_t count = 0; + for ( + index += strlen("--\r\n"); + (index = ffStrbufNextIndexC(&buffer, index, '\n')) < buffer.length; + ++index + ) + ++count; + + if (buffer.chars[buffer.length - 1] != '\n') // count last line + ++count; + + result->winget = count; +} + void ffDetectPackagesImpl(FFPackagesResult* result) { detectScoop(result); detectChoco(result); detectPacman(result); + if (instance.config.allowSlowOperations) + detectWinget(result); } diff --git a/src/fastfetch.c b/src/fastfetch.c index ef041ae3be..5bf30bfa57 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -129,7 +129,7 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "packages-format")) { - constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis)", 23, + constructAndPrintCommandHelpFormat("packages", "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (port), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget)", 24, "Number of all packages", "Number of pacman packages", "Pacman branch on manjaro", @@ -153,6 +153,7 @@ static inline void printCommandHelp(const char* command) "Number of choco packages", "Number of pkgtool packages", "Number of paludis packages" + "Number of winget packages" ); } else if(ffStrEqualsIgnCase(command, "shell-format")) diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 1c1b67140a..2129050fe7 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -4,7 +4,7 @@ #include "modules/packages/packages.h" #include "util/stringUtils.h" -#define FF_PACKAGES_NUM_FORMAT_ARGS 22 +#define FF_PACKAGES_NUM_FORMAT_ARGS 24 void ffPrintPackages(FFPackagesOptions* options) { @@ -63,6 +63,7 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE(choco) FF_PRINT_PACKAGE(pkgtool) FF_PRINT_PACKAGE(paludis) + FF_PRINT_PACKAGE(winget) putchar('\n'); } @@ -91,6 +92,8 @@ void ffPrintPackages(FFPackagesOptions* options) {FF_FORMAT_ARG_TYPE_UINT, &counts.scoop}, {FF_FORMAT_ARG_TYPE_UINT, &counts.choco}, {FF_FORMAT_ARG_TYPE_UINT, &counts.pkgtool}, + {FF_FORMAT_ARG_TYPE_UINT, &counts.paludis}, + {FF_FORMAT_ARG_TYPE_UINT, &counts.winget}, }); } From 4356974c5b9a941065c7995e3c76f82278ad8b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 14:20:42 +0800 Subject: [PATCH 068/198] Image: fix separated image printing --- src/logo/image/image.c | 3 ++- src/modules/uptime/uptime.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 16792842fb..6da5f4cfc3 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -111,7 +111,8 @@ static bool printImageIterm(void) else { instance.state.logoWidth = instance.state.logoHeight = 0; - ffPrintCharTimes('\n', instance.config.logo.paddingRight); + for (uint32_t i = 0; i < instance.config.logo.paddingRight; ++i) + ffStrbufAppendC(&buf, '\n'); } ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); } diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 74bce2798d..c8334fef06 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -4,7 +4,7 @@ #include "modules/uptime/uptime.h" #include "util/stringUtils.h" -#define FF_UPTIME_NUM_FORMAT_ARGS 4 +#define FF_UPTIME_NUM_FORMAT_ARGS 7 void ffPrintUptime(FFUptimeOptions* options) { From aafd773fe72adc2a273f5ff876fcceaed5279c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 14:25:17 +0800 Subject: [PATCH 069/198] Uptime: JSON format support --- src/modules/uptime/uptime.c | 18 +++++++++++++++++- src/modules/uptime/uptime.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index c8334fef06..96be154563 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -91,7 +91,7 @@ void ffPrintUptime(FFUptimeOptions* options) void ffInitUptimeOptions(FFUptimeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_UPTIME_MODULE_NAME, ffParseUptimeCommandOptions, ffParseUptimeJsonObject, ffPrintUptime, ffGenerateUptimeJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -126,3 +126,19 @@ void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module) ffPrintError(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateUptimeJson(FF_MAYBE_UNUSED FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFUptimeResult result; + const char* error = ffDetectUptime(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_uint(doc, obj, "uptime", result.uptime); + yyjson_mut_obj_add_uint(doc, obj, "bootTime", result.bootTime); +} diff --git a/src/modules/uptime/uptime.h b/src/modules/uptime/uptime.h index 3bc1fd55f8..2fa12e9638 100644 --- a/src/modules/uptime/uptime.h +++ b/src/modules/uptime/uptime.h @@ -9,3 +9,4 @@ void ffInitUptimeOptions(FFUptimeOptions* options); bool ffParseUptimeCommandOptions(FFUptimeOptions* options, const char* key, const char* value); void ffDestroyUptimeOptions(FFUptimeOptions* options); void ffParseUptimeJsonObject(FFUptimeOptions* options, yyjson_val* module); +void ffGenerateUptimeJson(FFUptimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 2c59a05dff887fdbc0d1a03a72c07ab44f1b1a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 14:32:01 +0800 Subject: [PATCH 070/198] Users: JSON format support --- src/detection/users/users.h | 2 +- src/detection/users/users_linux.c | 2 +- src/detection/users/users_windows.c | 2 +- src/modules/users/users.c | 43 +++++++++++++++++++++++++---- src/modules/users/users.h | 1 + 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/detection/users/users.h b/src/detection/users/users.h index 7248d83228..8ddc2a0cf4 100644 --- a/src/detection/users/users.h +++ b/src/detection/users/users.h @@ -8,7 +8,7 @@ typedef struct FFUserResult { FFstrbuf name; - FFstrbuf hostname; + FFstrbuf hostName; FFstrbuf clientIp; FFstrbuf tty; uint64_t loginTime; // ms diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index dbad1255d5..904cde08a9 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -30,7 +30,7 @@ const char* ffDetectUsers(FFlist* users) FFUserResult* user = (FFUserResult*) ffListAdd(users); ffStrbufInitS(&user->name, n->ut_user); - ffStrbufInitS(&user->hostname, n->ut_host); + ffStrbufInitS(&user->hostName, n->ut_host); ffStrbufInitS(&user->tty, n->ut_line); #ifdef __linux__ if(n->ut_addr_v6[0] || n->ut_addr_v6[1] || n->ut_addr_v6[2] || n->ut_addr_v6[3]) diff --git a/src/detection/users/users_windows.c b/src/detection/users/users_windows.c index 0c222ef91c..a891520b11 100644 --- a/src/detection/users/users_windows.c +++ b/src/detection/users/users_windows.c @@ -27,7 +27,7 @@ const char* ffDetectUsers(FFlist* users) FFUserResult* user = (FFUserResult*) ffListAdd(users); ffStrbufInitWS(&user->name, session->pUserName); - ffStrbufInitWS(&user->hostname, session->pHostName); + ffStrbufInitWS(&user->hostName, session->pHostName); DWORD bytes = 0; PWTS_CLIENT_ADDRESS address = NULL; diff --git a/src/modules/users/users.c b/src/modules/users/users.c index 764e738112..dee5a9bee9 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -51,8 +51,8 @@ void ffPrintUsers(FFUsersOptions* options) ffPrintLogoAndKey(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateCopy(&user->name); - if(user->hostname.length) - ffStrbufAppendF(&result, "@%s", user->hostname.chars); + if(user->hostName.length) + ffStrbufAppendF(&result, "@%s", user->hostName.chars); if(user->loginTime) { @@ -74,7 +74,7 @@ void ffPrintUsers(FFUsersOptions* options) ffPrintFormat(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_USERS_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &user->name}, - {FF_FORMAT_ARG_TYPE_STRBUF, &user->hostname}, + {FF_FORMAT_ARG_TYPE_STRBUF, &user->hostName}, {FF_FORMAT_ARG_TYPE_STRBUF, &user->tty}, {FF_FORMAT_ARG_TYPE_STRBUF, &user->clientIp}, {FF_FORMAT_ARG_TYPE_UINT64, &user->loginTime}, @@ -85,7 +85,7 @@ void ffPrintUsers(FFUsersOptions* options) FF_LIST_FOR_EACH(FFUserResult, user, users) { ffStrbufDestroy(&user->clientIp); - ffStrbufDestroy(&user->hostname); + ffStrbufDestroy(&user->hostName); ffStrbufDestroy(&user->tty); ffStrbufDestroy(&user->name); } @@ -93,7 +93,7 @@ void ffPrintUsers(FFUsersOptions* options) void ffInitUsersOptions(FFUsersOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, ffGenerateUsersJson); ffOptionInitModuleArg(&options->moduleArgs); options->compact = true; @@ -142,3 +142,36 @@ void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module) ffPrintError(FF_USERS_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateUsersJson(FF_MAYBE_UNUSED FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY results = ffListCreate(sizeof(FFUserResult)); + + const char* error = ffDetectUsers(&results); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + goto exit; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFUserResult, user, results) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "clientIp", &user->clientIp); + yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &user->hostName); + yyjson_mut_obj_add_uint(doc, obj, "loginTime", user->loginTime); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &user->name); + yyjson_mut_obj_add_strbuf(doc, obj, "tty", &user->tty); + } + +exit: + FF_LIST_FOR_EACH(FFUserResult, user, results) + { + ffStrbufDestroy(&user->clientIp); + ffStrbufDestroy(&user->hostName); + ffStrbufDestroy(&user->tty); + ffStrbufDestroy(&user->name); + } +} diff --git a/src/modules/users/users.h b/src/modules/users/users.h index 86d5f66f48..3ef57a1cf7 100644 --- a/src/modules/users/users.h +++ b/src/modules/users/users.h @@ -9,3 +9,4 @@ void ffInitUsersOptions(FFUsersOptions* options); bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const char* value); void ffDestroyUsersOptions(FFUsersOptions* options); void ffParseUsersJsonObject(FFUsersOptions* options, yyjson_val* module); +void ffGenerateUsersJson(FFUsersOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 826aa2e46dfd451e25c4a484cefff49f72a77a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 15:44:44 +0800 Subject: [PATCH 071/198] Packages: support JSON format --- src/modules/packages/packages.c | 45 ++++++++++++++++++++++++++++++++- src/modules/packages/packages.h | 1 + 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 2129050fe7..1d6ba534ab 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -102,7 +102,7 @@ void ffPrintPackages(FFPackagesOptions* options) void ffInitPackagesOptions(FFPackagesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PACKAGES_MODULE_NAME, ffParsePackagesCommandOptions, ffParsePackagesJsonObject, ffPrintPackages, ffGeneratePackagesJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -137,3 +137,46 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) ffPrintError(FF_PACKAGES_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGeneratePackagesJson(FF_MAYBE_UNUSED FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFPackagesResult counts = {}; + ffStrbufInit(&counts.pacmanBranch); + + const char* error = ffDetectPackages(&counts); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + + #define FF_APPEND_PACKAGE_COUNT(name) yyjson_mut_obj_add_uint(doc, obj, #name, counts.name); + + FF_APPEND_PACKAGE_COUNT(all) + FF_APPEND_PACKAGE_COUNT(apk) + FF_APPEND_PACKAGE_COUNT(brew) + FF_APPEND_PACKAGE_COUNT(brewCask) + FF_APPEND_PACKAGE_COUNT(choco) + FF_APPEND_PACKAGE_COUNT(dpkg) + FF_APPEND_PACKAGE_COUNT(emerge) + FF_APPEND_PACKAGE_COUNT(eopkg) + FF_APPEND_PACKAGE_COUNT(flatpakSystem) + FF_APPEND_PACKAGE_COUNT(flatpakUser) + FF_APPEND_PACKAGE_COUNT(nixDefault) + FF_APPEND_PACKAGE_COUNT(nixSystem) + FF_APPEND_PACKAGE_COUNT(nixUser) + FF_APPEND_PACKAGE_COUNT(pacman) + FF_APPEND_PACKAGE_COUNT(paludis) + FF_APPEND_PACKAGE_COUNT(pkg) + FF_APPEND_PACKAGE_COUNT(pkgtool) + FF_APPEND_PACKAGE_COUNT(port) + FF_APPEND_PACKAGE_COUNT(rpm) + FF_APPEND_PACKAGE_COUNT(scoop) + FF_APPEND_PACKAGE_COUNT(snap) + FF_APPEND_PACKAGE_COUNT(winget) + FF_APPEND_PACKAGE_COUNT(xbps) + yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); +} diff --git a/src/modules/packages/packages.h b/src/modules/packages/packages.h index 14fd7301d9..97b4ce239f 100644 --- a/src/modules/packages/packages.h +++ b/src/modules/packages/packages.h @@ -9,3 +9,4 @@ void ffInitPackagesOptions(FFPackagesOptions* options); bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, const char* value); void ffDestroyPackagesOptions(FFPackagesOptions* options); void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module); +void ffGeneratePackagesJson(FFPackagesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From aff4a570926e5a8f37277c1b9f956b636e5826b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 15:47:37 +0800 Subject: [PATCH 072/198] Processes: JSON format support --- src/modules/processes/processes.c | 16 +++++++++++++++- src/modules/processes/processes.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/modules/processes/processes.c b/src/modules/processes/processes.c index 02cf45b382..02a8bb53f1 100644 --- a/src/modules/processes/processes.c +++ b/src/modules/processes/processes.c @@ -33,7 +33,7 @@ void ffPrintProcesses(FFProcessesOptions* options) void ffInitProcessesOptions(FFProcessesOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PROCESSES_MODULE_NAME, ffParseProcessesCommandOptions, ffParseProcessesJsonObject, ffPrintProcesses, ffGenerateProcessesJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -68,3 +68,17 @@ void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module) ffPrintError(FF_PROCESSES_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateProcessesJson(FF_MAYBE_UNUSED FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + uint32_t result; + const char* error = ffDetectProcesses(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_obj_add_uint(doc, module, "result", result); +} diff --git a/src/modules/processes/processes.h b/src/modules/processes/processes.h index 724faf7fb0..8f14e00e44 100644 --- a/src/modules/processes/processes.h +++ b/src/modules/processes/processes.h @@ -9,3 +9,4 @@ void ffInitProcessesOptions(FFProcessesOptions* options); bool ffParseProcessesCommandOptions(FFProcessesOptions* options, const char* key, const char* value); void ffDestroyProcessesOptions(FFProcessesOptions* options); void ffParseProcessesJsonObject(FFProcessesOptions* options, yyjson_val* module); +void ffGenerateProcessesJson(FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From d97b16950c16c5424f39e2eca5700dce14e0dfcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 16:33:19 +0800 Subject: [PATCH 073/198] Shell: JSON format support --- src/modules/shell/shell.c | 22 +++++++++++++++++++++- src/modules/shell/shell.h | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index 1328c7acf1..e7f03e7306 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -45,7 +45,7 @@ void ffPrintShell(FFShellOptions* options) void ffInitShellOptions(FFShellOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SHELL_MODULE_NAME, ffParseShellCommandOptions, ffParseShellJsonObject, ffPrintShell, ffGenerateShellJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -80,3 +80,23 @@ void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module) ffPrintError(FF_SHELL_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateShellJson(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFTerminalShellResult* result = ffDetectTerminalShell(); + + if(result->shellProcessName.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect shell"); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->shellProcessName); + yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->shellExe); + yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->shellExeName); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->shellVersion); + yyjson_mut_obj_add_strbuf(doc, obj, "userShellExe", &result->userShellExe); + yyjson_mut_obj_add_strcpy(doc, obj, "userShellExeName", result->userShellExeName); + yyjson_mut_obj_add_strbuf(doc, obj, "userShellVersion", &result->userShellVersion); +} diff --git a/src/modules/shell/shell.h b/src/modules/shell/shell.h index 4e4f976bfe..354b512290 100644 --- a/src/modules/shell/shell.h +++ b/src/modules/shell/shell.h @@ -9,3 +9,4 @@ void ffInitShellOptions(FFShellOptions* options); bool ffParseShellCommandOptions(FFShellOptions* options, const char* key, const char* value); void ffDestroyShellOptions(FFShellOptions* options); void ffParseShellJsonObject(FFShellOptions* options, yyjson_val* module); +void ffGenerateShellJson(FFShellOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 1cdc99f32798293fc205f86ffd8d473b847fd28d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 20:03:26 +0800 Subject: [PATCH 074/198] JSON format: fix some memleaks --- src/detection/users/users_linux.c | 3 +-- src/modules/cpu/cpu.c | 3 +++ src/modules/cursor/cursor.c | 4 ++++ src/modules/display/display.c | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/detection/users/users_linux.c b/src/detection/users/users_linux.c index 904cde08a9..294c69b3e1 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -36,9 +36,8 @@ const char* ffDetectUsers(FFlist* users) if(n->ut_addr_v6[0] || n->ut_addr_v6[1] || n->ut_addr_v6[2] || n->ut_addr_v6[3]) ffStrbufInitF(&user->clientIp, "%u.%u.%u.%u", n->ut_addr_v6[0], n->ut_addr_v6[1], n->ut_addr_v6[2], n->ut_addr_v6[3]); else - #else - ffStrbufInit(&user->clientIp); #endif + ffStrbufInit(&user->clientIp); user->loginTime = (uint64_t) n->ut_tv.tv_sec * 1000 + (uint64_t) n->ut_tv.tv_usec / 1000; } diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 7ff3ddf8f8..1825747e40 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -162,4 +162,7 @@ void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va else yyjson_mut_obj_add_null(doc, obj, "temperature"); } + + ffStrbufDestroy(&cpu.name); + ffStrbufDestroy(&cpu.vendor); } diff --git a/src/modules/cursor/cursor.c b/src/modules/cursor/cursor.c index 58f0ff981c..555ec0374c 100644 --- a/src/modules/cursor/cursor.c +++ b/src/modules/cursor/cursor.c @@ -106,4 +106,8 @@ void ffGenerateCursorJson(FF_MAYBE_UNUSED FFCursorOptions* options, yyjson_mut_d yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "theme", &result.theme); yyjson_mut_obj_add_strbuf(doc, obj, "size", &result.size); + + ffStrbufDestroy(&result.error); + ffStrbufDestroy(&result.theme); + ffStrbufDestroy(&result.size); } diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 2f99b132b3..14acbcca45 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -199,6 +199,7 @@ void ffGenerateDisplayJson(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjson_mut FF_LIST_FOR_EACH(FFDisplayResult, item, dsResult->displays) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_uint(doc, obj, "width", item->width); yyjson_mut_obj_add_uint(doc, obj, "height", item->height); yyjson_mut_obj_add_uint(doc, obj, "id", item->id); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); @@ -219,6 +220,5 @@ void ffGenerateDisplayJson(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjson_mut yyjson_mut_obj_add_str(doc, obj, "type", "Unknown"); break; } - yyjson_mut_obj_add_uint(doc, obj, "scaledWidth", item->width); } } From 1526930e54c158beef89f3715c8b118e28f437bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 20:22:35 +0800 Subject: [PATCH 075/198] Logo (Builtin): update EvolutionOS Ref: #555 --- src/logo/ascii/evolutionos.txt | 30 +++++++++++++++++++--------- src/logo/ascii/evolutionos_small.txt | 9 +++++++++ src/logo/builtin.c | 13 +++++++++++- 3 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 src/logo/ascii/evolutionos_small.txt diff --git a/src/logo/ascii/evolutionos.txt b/src/logo/ascii/evolutionos.txt index 654f08cb85..18ca20e235 100644 --- a/src/logo/ascii/evolutionos.txt +++ b/src/logo/ascii/evolutionos.txt @@ -1,9 +1,21 @@ - ,coddoc' - 'cddddddddddc' - 'ddd${c2}OWWXXXXXXK${c1}ddo. -.dddd${c2}OMX${c1}ddddddddddd. -odddd${c2}OMXk00OkOO${c1}ddddo -.dddd${c2}OMX${c1}kOOOxOkdddd. - .ddd${c2}OWWXXXXXXK${c1}ddd' - 'dddddddddddd' - 'cddddd, + $2.':ldxxxxdo:,. + .lXMMMMMMMMMMMMMMMMNo' + dWMMMMMMMMMMMMMMMMMMMMMMWk + .OMMMMWWWWWWWWWWWWWWWWWWWMMMMM0; + kMMMMM$1XxxxxkkkkkkkkkkkkkkkK$2WMMMMMK. + .kMMMMMM$1Xddd0KKKKKKKKKKKKKKKN$2MMMMMMMN. + KMMMMMMM$1XdddX$2MMMMMMMMMMMMMMMMMMMMMMMMX. + cMMMMMMMM$1XdddX$2MMMMMMMMMMMMMMMMMMMMMMMMMo + KMMMMMMMM$1XdddX$2MMMMMMMMMMMMMMMMMMMMMMMMMN + XMMMMMMMM$1XdddX$2WO$1kkkkkkkK$2WK$1OOOX$2MMMMMMMMMW + XMMMMMMMM$1XdddX$2WO$1kkkkkkkK$2WK$1OOOX$2MMMMMMMMMW + 0MMMMMMMM$1XdddX$2MWWWWWWWWWMWWWWWMMMMMMMMMN + cMMMMMMMM$1XdddX$2MMMMMMMMMMMMMMMMMMMMMMMMMd + .kMMMMMMM$1XdddX$2MMMMMMMMMMMMMMMMMMMMMMMM0. + .kMMMMMM$1XxxxN$2W0$1OOOOOOOOOOOOOK$2MMMMMMMK. + oMMMMM$1XxxxN$2W0$1OOOOOOOOOOOOOK$2WMMMMMk. + '0MMMWNNNWMWWWWWWWWWWWWWWWMMMMX; + cWMMMMMMMMMMMMMMMMMMMMMMWd + :KWMMMMMMMMMMMMMMWXo. + .cdO0KK00xl' + .. diff --git a/src/logo/ascii/evolutionos_small.txt b/src/logo/ascii/evolutionos_small.txt new file mode 100644 index 0000000000..8692019a9e --- /dev/null +++ b/src/logo/ascii/evolutionos_small.txt @@ -0,0 +1,9 @@ + $2,coddoc' + 'cddddddddddc' + 'ddd$1OWWXXXXXXK$2ddo. +.dddd$1OMX$2ddddddddddd. +odddd$1OMX$2k$100O$2k$1OO$2ddddo +.dddd$1OMX$2kOOOxOkdddd. + .ddd$1OWW$2X$1XXXXXK$2ddd' + 'dddddddddddd' + 'cddddd, diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 4e838ad692..87885bbd57 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1262,13 +1262,24 @@ static const FFlogo E[] = { .names = {"EvolutionOS"}, .lines = FASTFETCH_DATATEXT_LOGO_EVOLUTIONOS, .colors = { + FF_COLOR_FG_GREEN, + FF_COLOR_FG_WHITE, + }, + }, + // EvolutionOSSmall + { + .names = {"EvolutionOS_small"}, + .type = FF_LOGO_LINE_TYPE_SMALL_BIT, + .lines = FASTFETCH_DATATEXT_LOGO_EVOLUTIONOS_SMALL, + .colors = { + FF_COLOR_FG_GREEN, FF_COLOR_FG_WHITE, - FF_COLOR_FG_LIGHT_GREEN, }, }, // EvolutionOS_old { .names = {"EvolutionOS_old"}, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .lines = FASTFETCH_DATATEXT_LOGO_EVOLUTIONOS_OLD, .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .colors = { From f662cc0aa29807b07eb3970633cc36541169648e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 21:07:10 +0800 Subject: [PATCH 076/198] Logo (Builtin): update AOSC OS Ref: https://github.com/hykilpikonna/hyfetch/pull/185 --- src/logo/ascii/aoscos.txt | 37 ++++++++++++++++------------------- src/logo/ascii/aoscos_old.txt | 20 +++++++++++++++++++ src/logo/builtin.c | 12 +++++++++++- 3 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 src/logo/ascii/aoscos_old.txt diff --git a/src/logo/ascii/aoscos.txt b/src/logo/ascii/aoscos.txt index 2886c092dd..8681218b45 100644 --- a/src/logo/ascii/aoscos.txt +++ b/src/logo/ascii/aoscos.txt @@ -1,20 +1,17 @@ - .:+syhhhhys+:. - .ohNMMMMMMMMMMMMMMNho. - `+mMMMMMMMMMMmdmNMMMMMMMMm+` - +NMMMMMMMMMMMM/ `./smMMMMMN+ - .mMMMMMMMMMMMMMMo -yMMMMMm. - :NMMMMMMMMMMMMMMMs .hMMMMN: - .NMMMMhmMMMMMMMMMMm+/- oMMMMN. - dMMMMs ./ymMMMMMMMMMMNy. sMMMMd --MMMMN` oMMMMMMMMMMMN: `NMMMM- -/MMMMh NMMMMMMMMMMMMm hMMMM/ -/MMMMh NMMMMMMMMMMMMm hMMMM/ --MMMMN` :MMMMMMMMMMMMy. `NMMMM- - dMMMMs .yNMMMMMMMMMMMNy/. sMMMMd - .NMMMMo -/+sMMMMMMMMMMMmMMMMN. - :NMMMMh. .MMMMMMMMMMMMMMMN: - .mMMMMMy- NMMMMMMMMMMMMMm. - +NMMMMMms/.` mMMMMMMMMMMMN+ - `+mMMMMMMMMNmddMMMMMMMMMMm+` - .ohNMMMMMMMMMMMMMMNho. - .:+syhhhhys+:. + ${c2}__ + ${c2}gpBBBBBBBBBP + ${c2}_gBBBBBBBBBRP + ${c2}4BBBBBBBBRP ${c4},_____ + ${c2}`"" ${c4}_g@@@@@@@@@@@@@%g> + ${c4}__@@@@@@@@@@@@@@@@P" ${c1}___ + ${c4}_g@@@@@@@@@@@@@@@N"` ${c1}_gN@@@@@N^ + ${c4}_w@@@@@@@@@@@@@@@@P" ${c1}_g@@@@@@@P" + ${c4}_g@@@@@@@@@@@@@@@N"` ${c1}VMNN@NNNM^` +${c4}^MMM@@@@@@@@@@@MP" ${c3},ggppww__ + ${c4}`""""" ${c3}_wNNNNNNNNNNNNNNNNNNN + ${c3}_gBNNNNNNNNNNNNNNNNNP" + ${c3}_wNNNNNNNNNNNNNNNNNNMP` + ${c3}_gBNNNNNNNNNNNNNNNNNP" + ${c3}_wNNNNNNNNNNNNNNNNNNNM^ + ${c3}""Y^^MNNNNNNNNNNNNP` + ${c3}`""""""" diff --git a/src/logo/ascii/aoscos_old.txt b/src/logo/ascii/aoscos_old.txt new file mode 100644 index 0000000000..2886c092dd --- /dev/null +++ b/src/logo/ascii/aoscos_old.txt @@ -0,0 +1,20 @@ + .:+syhhhhys+:. + .ohNMMMMMMMMMMMMMMNho. + `+mMMMMMMMMMMmdmNMMMMMMMMm+` + +NMMMMMMMMMMMM/ `./smMMMMMN+ + .mMMMMMMMMMMMMMMo -yMMMMMm. + :NMMMMMMMMMMMMMMMs .hMMMMN: + .NMMMMhmMMMMMMMMMMm+/- oMMMMN. + dMMMMs ./ymMMMMMMMMMMNy. sMMMMd +-MMMMN` oMMMMMMMMMMMN: `NMMMM- +/MMMMh NMMMMMMMMMMMMm hMMMM/ +/MMMMh NMMMMMMMMMMMMm hMMMM/ +-MMMMN` :MMMMMMMMMMMMy. `NMMMM- + dMMMMs .yNMMMMMMMMMMMNy/. sMMMMd + .NMMMMo -/+sMMMMMMMMMMMmMMMMN. + :NMMMMh. .MMMMMMMMMMMMMMMN: + .mMMMMMy- NMMMMMMMMMMMMMm. + +NMMMMMms/.` mMMMMMMMMMMMN+ + `+mMMMMMMMMNmddMMMMMMMMMMm+` + .ohNMMMMMMMMMMMMMMNho. + .:+syhhhhys+:. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 87885bbd57..e910c01301 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -195,6 +195,17 @@ static const FFlogo A[] = { .lines = FASTFETCH_DATATEXT_LOGO_AOSCOS, .colors = { FF_COLOR_FG_BLUE, + FF_COLOR_FG_BLACK, + FF_COLOR_FG_GREEN, + FF_COLOR_FG_YELLOW, + }, + }, + // AoscOS_old + { + .names = {"Aosc OS_old", "aoscos_old"}, + .lines = FASTFETCH_DATATEXT_LOGO_AOSCOS_OLD, + .type = FF_LOGO_LINE_TYPE_ALTER_BIT, + .colors = { FF_COLOR_FG_WHITE, }, .colorKeys = FF_COLOR_FG_BLUE, @@ -1281,7 +1292,6 @@ static const FFlogo E[] = { .names = {"EvolutionOS_old"}, .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .lines = FASTFETCH_DATATEXT_LOGO_EVOLUTIONOS_OLD, - .type = FF_LOGO_LINE_TYPE_ALTER_BIT, .colors = { FF_COLOR_FG_LIGHT_BLUE, FF_COLOR_FG_WHITE, From 94eb3b89e802ba78161d6986ae2f7836415d5232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 21:20:32 +0800 Subject: [PATCH 077/198] Logo (Builtin): use first color as title color As what neofetch does --- src/logo/logo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/logo/logo.c b/src/logo/logo.c index 613e9a99b1..75a395ae91 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -210,11 +210,11 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) static void logoApplyColors(const FFlogo* logo) { - if(instance.config.colorKeys.length == 0) - ffStrbufAppendS(&instance.config.colorKeys, logo->colorKeys ? logo->colorKeys : logo->colors[0]); - if(instance.config.colorTitle.length == 0) - ffStrbufAppendS(&instance.config.colorTitle, logo->colorTitle ? logo->colorTitle : logo->colors[1]); + ffStrbufAppendS(&instance.config.colorTitle, logo->colorTitle ? logo->colorTitle : logo->colors[0]); + + if(instance.config.colorKeys.length == 0) + ffStrbufAppendS(&instance.config.colorKeys, logo->colorKeys ? logo->colorKeys : logo->colors[1]); } static bool logoHasName(const FFlogo* logo, const FFstrbuf* name, bool small) From 82c300f7f6b9736ba8a2d050c17bc7e8e6be3622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 8 Sep 2023 21:21:11 +0800 Subject: [PATCH 078/198] Logo (Builtin): add Afterglow https://github.com/hykilpikonna/hyfetch/pull/ --- src/logo/ascii/afterglow.txt | 15 +++++++++++++++ src/logo/builtin.c | 11 +++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/logo/ascii/afterglow.txt diff --git a/src/logo/ascii/afterglow.txt b/src/logo/ascii/afterglow.txt new file mode 100644 index 0000000000..3b86a44d49 --- /dev/null +++ b/src/logo/ascii/afterglow.txt @@ -0,0 +1,15 @@ + ${c2}. + ${c1}. ${c2}.{! + ${c1}.L! ${c2}J@||* + ${c1}gJJJJL` ${c2}g@FFS" + ${c1},@FFFJF`${c2}_g@@LLP` + ${c1}_@FFFFF`${c2}_@@@@@P` ${c4}. + ${c1}J@@@LLF ${c2}_@@@@@P` ${c4}.J! + ${c1}g@@@@@" ${c2}_@@@@@P`${c3}. ${c4}.L|||* +${c1}g@@@@M" ${c2}"VP`${c3}.L! ${c4}<@JJJJ` + ${c1}"@N" ${c3}:||||! ${c4}JFFFFS" + ${c3}.{JJ||F`${c4}_gFFFF@' + ${c3}.@FJJJF`${c4},@LFFFF` + ${c3}_@FFFFF ${c4}VLLLP` + ${c3}J@@LL@" ${c4}`" + ${c3}V@@" diff --git a/src/logo/builtin.c b/src/logo/builtin.c index e910c01301..b61b9589bd 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -22,6 +22,17 @@ static const FFlogo A[] = { FF_COLOR_FG_CYAN, }, }, + // Afterglow + { + .names = {"Afterglow"}, + .lines = FASTFETCH_DATATEXT_LOGO_AFTERGLOW, + .colors = { + FF_COLOR_FG_MAGENTA, + FF_COLOR_FG_RED, + FF_COLOR_FG_YELLOW, + FF_COLOR_FG_BLUE, + }, + }, // AIX { .names = {"aix"}, From e2abe31fc17bf638d50f057cd67c232a423aee7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 10 Sep 2023 18:39:45 +0800 Subject: [PATCH 079/198] Monitor: fix memleaks --- src/modules/monitor/monitor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index c7f76a0394..be0e22830c 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -141,4 +141,9 @@ void ffGenerateMonitorJson(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut yyjson_mut_obj_add_uint(doc, obj, "physicalWidth", item->physicalWidth); } } + + FF_LIST_FOR_EACH(FFMonitorResult, item, results) + { + ffStrbufDestroy(&item->name); + } } From c7028653322c878a17329689b90617ec327941e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 11 Sep 2023 23:03:03 +0800 Subject: [PATCH 080/198] Presets: add a new example Ref: https://github.com/fastfetch-cli/fastfetch/discussions/556 --- presets/examples/10.jsonc | 150 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 presets/examples/10.jsonc diff --git a/presets/examples/10.jsonc b/presets/examples/10.jsonc new file mode 100644 index 0000000000..96ec3bb062 --- /dev/null +++ b/presets/examples/10.jsonc @@ -0,0 +1,150 @@ +// Load with --load-config examples/2.jsonc +// Note that you must replace the image path to an existing image to display it. + +{ + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "padding": { + "top": 2 + } + }, + "display": { + "separator": " -> " + }, + "modules": [ + { + "type": "custom", + "format": "\u001b[90m┌────────────────────────────────────────────────────────────┐" + }, + { + "type": "title", + "keyWidth": 10 + }, + { + "type": "custom", + "format": "\u001b[90m└────────────────────────────────────────────────────────────┘" + }, + { + "type": "custom", + "format": " \u001b[90m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[38m \u001b[39m  \u001b[38m \u001b[37m \u001b[36m \u001b[35m \u001b[34m \u001b[33m \u001b[32m \u001b[31m \u001b[90m" + }, + { + "type": "custom", + "format": "\u001b[90m┌────────────────────────────────────────────────────────────┐" + }, + { + "type": "os", + "key": " OS", + "keyColor": "yellow" + }, + { + "type": "kernel", + "key": "│ ├", + "keyColor": "yellow" + }, + { + "type": "packages", + "key": "│ ├󰏖", + "keyColor": "yellow" + }, + { + "type": "shell", + "key": "│ └", + "keyColor": "yellow" + }, + { + "type": "wm", + "key": " DE/WM", + "keyColor": "blue" + }, + { + "type": "lm", + "key": "│ ├󰧨", + "keyColor": "blue" + }, + { + "type": "wmtheme", + "key": "│ ├󰉼", + "keyColor": "blue" + }, + { + "type": "icons", + "key": "│ ├󰀻", + "keyColor": "blue" + }, + { + "type": "terminal", + "key": "│ ├", + "keyColor": "blue" + }, + { + "type": "wallpaper", + "key": "│ └󰸉", + "keyColor": "blue" + }, + { + "type": "host", + "key": " PC", + "keyColor": "green" + }, + { + "type": "cpu", + "key": "│ ├", + "keyColor": "green" + }, + { + "type": "gpu", + "key": "│ ├﬙", + "keyColor": "green" + }, + { + "type": "disk", + "key": "│ ├", + "keyColor": "green" + }, + { + "type": "memory", + "key": "│ ├󰑭", + "keyColor": "green" + }, + { + "type": "swap", + "key": "│ ├󰓡", + "keyColor": "green" + }, + { + "type": "uptime", + "key": "│ ├󰅐", + "keyColor": "green" + }, + { + "type": "display", + "key": "│ └󰍹", + "keyColor": "green" + }, + { + "type": "sound", + "key": " SND", + "keyColor": "cyan" + }, + { + "type": "player", + "key": "│ ├󰥠", + "keyColor": "cyan" + }, + { + "type": "media", + "key": "│ └󰝚", + "keyColor": "cyan" + }, + { + "type": "custom", + "format": "\u001b[90m└────────────────────────────────────────────────────────────┘" + }, + "break", + { + "type": "custom", + "format": " \u001b[90m \u001b[31m \u001b[32m \u001b[33m \u001b[34m \u001b[35m \u001b[36m \u001b[37m \u001b[38m \u001b[39m  \u001b[38m \u001b[37m \u001b[36m \u001b[35m \u001b[34m \u001b[33m \u001b[32m \u001b[31m \u001b[90m" + } + ] +} From 257439477e060f0dc58124e3c516b5262430f14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 09:01:00 +0800 Subject: [PATCH 081/198] CI: update deps --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 715ebbcdc4..d09568c55c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install required packages run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev @@ -54,7 +54,7 @@ jobs: ffversion: ${{ steps.ffversion.outputs.ffversion }} steps: - name: checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install required packages run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev @@ -103,7 +103,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: install required packages run: brew install vulkan-loader molten-vk imagemagick chafa @@ -148,7 +148,7 @@ jobs: contents: read steps: - name: checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: run VM uses: vmactions/freebsd-vm@v0 @@ -180,7 +180,7 @@ jobs: shell: msys2 {0} steps: - name: checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: setup-msys2 uses: msys2/setup-msys2@v2 @@ -244,7 +244,7 @@ jobs: shell: msys2 {0} steps: - name: checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: setup-msys2 uses: msys2/setup-msys2@v2 From f13b7713173cc3d3e543d194a200bdb9d55b3f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 09:37:24 +0800 Subject: [PATCH 082/198] Sound: support JSON format --- src/modules/sound/sound.c | 31 ++++++++++++++++++++++++++++++- src/modules/sound/sound.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index f8ddb13de2..f3efc6696d 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -85,7 +85,7 @@ void ffPrintSound(FFSoundOptions* options) void ffInitSoundOptions(FFSoundOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_SOUND_MODULE_NAME, ffParseSoundCommandOptions, ffParseSoundJsonObject, ffPrintSound, ffGenerateSoundJson); ffOptionInitModuleArg(&options->moduleArgs); options->soundType = FF_SOUND_TYPE_MAIN; @@ -149,3 +149,32 @@ void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module) ffPrintError(FF_SOUND_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateSoundJson(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFSoundDevice)); + const char* error = ffDetectSound(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + if(result.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No active sound devices found"); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFSoundDevice, item, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_bool(doc, obj, "active", item->active); + yyjson_mut_obj_add_bool(doc, obj, "main", item->main); + yyjson_mut_obj_add_uint(doc, obj, "volume", item->volume); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); + yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &item->identifier); + } +} diff --git a/src/modules/sound/sound.h b/src/modules/sound/sound.h index c35c168012..03ec8fe680 100644 --- a/src/modules/sound/sound.h +++ b/src/modules/sound/sound.h @@ -9,3 +9,4 @@ void ffInitSoundOptions(FFSoundOptions* options); bool ffParseSoundCommandOptions(FFSoundOptions* options, const char* key, const char* value); void ffDestroySoundOptions(FFSoundOptions* options); void ffParseSoundJsonObject(FFSoundOptions* options, yyjson_val* module); +void ffGenerateSoundJson(FFSoundOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 9447f1ca80ea9f4abcdecd4a6ca468a3d579bff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 09:49:36 +0800 Subject: [PATCH 083/198] Terminal: support JSON format --- src/modules/shell/shell.c | 3 ++- src/modules/terminal/terminal.c | 21 ++++++++++++++++++++- src/modules/terminal/terminal.h | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index e7f03e7306..a50607fff3 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -92,9 +92,10 @@ void ffGenerateShellJson(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_mut_doc } yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); - yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->shellProcessName); yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->shellExe); yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->shellExeName); + yyjson_mut_obj_add_uint(doc, obj, "pid", result->shellPid); + yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->shellProcessName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->shellVersion); yyjson_mut_obj_add_strbuf(doc, obj, "userShellExe", &result->userShellExe); yyjson_mut_obj_add_strcpy(doc, obj, "userShellExeName", result->userShellExeName); diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 3d0367a225..6009b1dbca 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -46,7 +46,7 @@ void ffPrintTerminal(FFTerminalOptions* options) void ffInitTerminalOptions(FFTerminalOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINAL_MODULE_NAME, ffParseTerminalCommandOptions, ffParseTerminalJsonObject, ffPrintTerminal, ffGenerateTerminalJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -81,3 +81,22 @@ void ffParseTerminalJsonObject(FFTerminalOptions* options, yyjson_val* module) ffPrintError(FF_TERMINAL_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateTerminalJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFTerminalShellResult* result = ffDetectTerminalShell(); + + if(result->terminalProcessName.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "Couldn't detect terminal"); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->terminalExe); + yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->terminalExeName); + yyjson_mut_obj_add_uint(doc, obj, "pid", result->terminalPid); + yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->terminalPrettyName); + yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->terminalProcessName); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->terminalVersion); +} diff --git a/src/modules/terminal/terminal.h b/src/modules/terminal/terminal.h index 09949b00d0..709b02e568 100644 --- a/src/modules/terminal/terminal.h +++ b/src/modules/terminal/terminal.h @@ -9,3 +9,4 @@ void ffInitTerminalOptions(FFTerminalOptions* options); bool ffParseTerminalCommandOptions(FFTerminalOptions* options, const char* key, const char* value); void ffDestroyTerminalOptions(FFTerminalOptions* options); void ffParseTerminalJsonObject(FFTerminalOptions* options, yyjson_val* module); +void ffGenerateTerminalJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 2251086c0f70a71ac240f81c3a534153bd18085d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 11:18:05 +0800 Subject: [PATCH 084/198] TerminalFont: support JSON format --- src/modules/terminalfont/terminalfont.c | 38 ++++++++++++++++++++++++- src/modules/terminalfont/terminalfont.h | 1 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 4d92ccc610..2b992912c2 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -49,7 +49,7 @@ void ffPrintTerminalFont(FFTerminalFontOptions* options) void ffInitTerminalFontOptions(FFTerminalFontOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontCommandOptions, ffParseTerminalFontJsonObject, ffPrintTerminalFont, ffGenerateTerminalFontJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -84,3 +84,39 @@ void ffParseTerminalFontJsonObject(FFTerminalFontOptions* options, yyjson_val* m ffPrintError(FF_TERMINALFONT_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateTerminalFontJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFTerminalFontResult result; + ffFontInit(&result.font); + ffFontInit(&result.fallback); + ffStrbufInit(&result.error); + + if(!ffDetectTerminalFont(&result)) + { + yyjson_mut_obj_add_strbuf(doc, module, "error", &result.error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + + yyjson_mut_val* font = yyjson_mut_obj_add_obj(doc, obj, "font"); + yyjson_mut_obj_add_strbuf(doc, font, "name", &result.font.name); + yyjson_mut_obj_add_strbuf(doc, font, "size", &result.font.size); + yyjson_mut_val* fontStyles = yyjson_mut_obj_add_arr(doc, font, "styles"); + FF_LIST_FOR_EACH(FFstrbuf, style, result.font.styles) + { + yyjson_mut_arr_add_strbuf(doc, fontStyles, style); + } + yyjson_mut_obj_add_strbuf(doc, font, "pretty", &result.font.pretty); + + yyjson_mut_val* fallback = yyjson_mut_obj_add_obj(doc, obj, "fallback"); + yyjson_mut_obj_add_strbuf(doc, fallback, "name", &result.fallback.name); + yyjson_mut_obj_add_strbuf(doc, fallback, "size", &result.fallback.size); + yyjson_mut_val* fallbackStyles = yyjson_mut_obj_add_arr(doc, fallback, "styles"); + FF_LIST_FOR_EACH(FFstrbuf, style, result.fallback.styles) + { + yyjson_mut_arr_add_strbuf(doc, fallbackStyles, style); + } + yyjson_mut_obj_add_strbuf(doc, fallback, "pretty", &result.fallback.pretty); +} diff --git a/src/modules/terminalfont/terminalfont.h b/src/modules/terminalfont/terminalfont.h index ac5953a367..434eb1a1f7 100644 --- a/src/modules/terminalfont/terminalfont.h +++ b/src/modules/terminalfont/terminalfont.h @@ -9,3 +9,4 @@ void ffInitTerminalFontOptions(FFTerminalFontOptions* options); bool ffParseTerminalFontCommandOptions(FFTerminalFontOptions* options, const char* key, const char* value); void ffDestroyTerminalFontOptions(FFTerminalFontOptions* options); void ffParseTerminalFontJsonObject(FFTerminalFontOptions* options, yyjson_val* module); +void ffGenerateTerminalFontJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From f3ec60a0618e9d6ca7835917a628a03169de9487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 14:50:38 +0800 Subject: [PATCH 085/198] Uptime: add `ffTimeGetNow()` and use it --- src/common/time.h | 14 ++++++++++++ src/detection/uptime/uptime_bsd.c | 32 +++++++++------------------ src/detection/uptime/uptime_linux.c | 9 ++------ src/detection/uptime/uptime_windows.c | 11 ++------- 4 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/common/time.h b/src/common/time.h index 797461cbd1..8da2494489 100644 --- a/src/common/time.h +++ b/src/common/time.h @@ -7,6 +7,7 @@ #ifdef _WIN32 #include #include + #include #else #include #endif @@ -26,6 +27,19 @@ static inline uint64_t ffTimeGetTick() //In msec #endif } +static inline uint64_t ffTimeGetNow() +{ + #ifdef _WIN32 + uint64_t timeNow; + GetSystemTimeAsFileTime((FILETIME*) &timeNow); + return (timeNow - 116444736000000000ull) / 10000ull; + #else + struct timespec timeNow; + clock_gettime(CLOCK_REALTIME, &timeNow); + return (uint64_t)((timeNow.tv_sec * 1000) + (timeNow.tv_nsec / 1000000)); + #endif +} + static inline void ffTimeSleep(uint32_t msec) { #ifdef _WIN32 diff --git a/src/detection/uptime/uptime_bsd.c b/src/detection/uptime/uptime_bsd.c index 0b1bf00c7f..90b986da7e 100644 --- a/src/detection/uptime/uptime_bsd.c +++ b/src/detection/uptime/uptime_bsd.c @@ -1,31 +1,21 @@ #include "uptime.h" +#include "common/time.h" -#include #include -#include const char* ffDetectUptime(FFUptimeResult* result) { - { - struct timeval bootTime; - size_t bootTimeSize = sizeof(bootTime); - if(sysctl( - (int[]) {CTL_KERN, KERN_BOOTTIME}, 2, - &bootTime, &bootTimeSize, - NULL, 0 - ) != 0) - return "sysctl({CTL_KERN, KERN_BOOTTIME}) failed"; + struct timeval bootTime; + size_t bootTimeSize = sizeof(bootTime); + if(sysctl( + (int[]) {CTL_KERN, KERN_BOOTTIME}, 2, + &bootTime, &bootTimeSize, + NULL, 0 + ) != 0) + return "sysctl({CTL_KERN, KERN_BOOTTIME}) failed"; - result->bootTime = (uint64_t) bootTime.tv_sec * 1000 + (uint64_t) bootTime.tv_usec / 1000; - } - - { - struct timespec realTime; - if(clock_gettime(CLOCK_REALTIME, &realTime) != 0) - return "clock_gettime(CLOCK_REALTIME) failed"; - uint64_t now = (uint64_t) realTime.tv_sec * 1000 + (uint64_t) realTime.tv_nsec / 1000000; - result->uptime = now - result->bootTime; - } + result->bootTime = (uint64_t) bootTime.tv_sec * 1000 + (uint64_t) bootTime.tv_usec / 1000; + result->uptime = ffTimeGetNow() - result->bootTime; return NULL; } diff --git a/src/detection/uptime/uptime_linux.c b/src/detection/uptime/uptime_linux.c index 039d550da2..bfa67215b7 100644 --- a/src/detection/uptime/uptime_linux.c +++ b/src/detection/uptime/uptime_linux.c @@ -1,6 +1,5 @@ #include "uptime.h" - -#include +#include "common/time.h" const char* ffDetectUptime(FFUptimeResult* result) { @@ -10,11 +9,7 @@ const char* ffDetectUptime(FFUptimeResult* result) result->uptime = (uint64_t) uptime.tv_sec * 1000 + (uint64_t) uptime.tv_nsec / 1000000; - struct timespec realTime; - if(clock_gettime(CLOCK_REALTIME, &realTime) != 0) - return "clock_gettime(CLOCK_REALTIME) failed"; - - result->bootTime = (uint64_t) realTime.tv_sec * 1000 + (uint64_t) realTime.tv_nsec / 1000000 + result->uptime; + result->bootTime = ffTimeGetNow() + result->uptime; return NULL; } diff --git a/src/detection/uptime/uptime_windows.c b/src/detection/uptime/uptime_windows.c index 10f7157bbe..6978a1163d 100644 --- a/src/detection/uptime/uptime_windows.c +++ b/src/detection/uptime/uptime_windows.c @@ -1,18 +1,11 @@ #include "uptime.h" +#include "common/time.h" #include -static inline uint64_t to_ms(uint64_t ret) -{ - ret -= 116444736000000000ull; - return ret / 10000ull; -} - const char* ffDetectUptime(FFUptimeResult* result) { result->uptime = GetTickCount64(); - FILETIME fileTime; - GetSystemTimeAsFileTime(&fileTime); - result->bootTime = to_ms(*(uint64_t*) &fileTime) - result->uptime; + result->bootTime = ffTimeGetNow() - result->uptime; return NULL; } From a927f4a04d902610266fe25d529aeb24afedc9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 15:53:58 +0800 Subject: [PATCH 086/198] DateTime: code refactor using `ffTimeGetNow` --- CMakeLists.txt | 3 +- src/detection/datetime/datetime.c | 71 ------------ src/detection/datetime/datetime.h | 35 ------ src/modules/datetime/datetime.c | 172 +++++++++++++++++++++--------- 4 files changed, 122 insertions(+), 159 deletions(-) delete mode 100644 src/detection/datetime/datetime.c delete mode 100644 src/detection/datetime/datetime.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fc0562fa0e..ed8a05f46a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -267,7 +267,6 @@ set(LIBFASTFETCH_SRC src/detection/chassis/chassis.c src/detection/cpu/cpu.c src/detection/cpuusage/cpuusage.c - src/detection/datetime/datetime.c src/detection/disk/disk.c src/detection/displayserver/displayserver.c src/detection/font/font.c @@ -627,7 +626,7 @@ if(yyjson_FOUND) target_link_libraries(libfastfetch PRIVATE yyjson) endif() -target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE) +target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1) if(WIN32) target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1) endif() diff --git a/src/detection/datetime/datetime.c b/src/detection/datetime/datetime.c deleted file mode 100644 index 60cc1f6582..0000000000 --- a/src/detection/datetime/datetime.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "fastfetch.h" -#include "detection/datetime/datetime.h" -#include "common/thread.h" - -#include - -const FFDateTimeResult* ffDetectDateTime(void) -{ - static FFDateTimeResult result; - static FFThreadMutex mutex = FF_THREAD_MUTEX_INITIALIZER; - static bool init = false; - - ffThreadMutexLock(&mutex); - if (init) - { - ffThreadMutexUnlock(&mutex); - return &result; - } - init = true; - - const time_t t = time(NULL); - struct tm* tm = localtime(&t); - - result.year = (uint16_t) (tm->tm_year + 1900); - result.yearShort = (uint8_t) (result.year % 100); - result.month = (uint8_t) (tm->tm_mon + 1); - - ffStrbufInitA(&result.monthPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm); - - ffStrbufInitA(&result.monthName, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.monthName.length = (uint32_t) strftime(result.monthName.chars, ffStrbufGetFree(&result.monthName), "%B", tm); - - ffStrbufInitA(&result.monthNameShort, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.monthNameShort.length = (uint32_t) strftime(result.monthNameShort.chars, ffStrbufGetFree(&result.monthNameShort), "%b", tm); - - result.week = (uint8_t) (tm->tm_yday / 7 + 1); - - ffStrbufInitA(&result.weekday, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.weekday.length = (uint32_t) strftime(result.weekday.chars, ffStrbufGetFree(&result.weekday), "%A", tm); - - ffStrbufInitA(&result.weekdayShort, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.weekdayShort.length = (uint32_t) strftime(result.weekdayShort.chars, ffStrbufGetFree(&result.weekdayShort), "%a", tm); - - result.dayInYear = (uint8_t) (tm->tm_yday + 1); - result.dayInMonth = (uint8_t) tm->tm_mday; - result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday; - - result.hour = (uint8_t) tm->tm_hour; - - ffStrbufInitA(&result.hourPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm); - - result.hour12 = (uint8_t) (result.hour % 12); - - ffStrbufInitA(&result.hour12Pretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm); - - result.minute = (uint8_t) tm->tm_min; - - ffStrbufInitA(&result.minutePretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm); - - result.second = (uint8_t) tm->tm_sec; - - ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); - result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm); - - ffThreadMutexUnlock(&mutex); - return &result; -} diff --git a/src/detection/datetime/datetime.h b/src/detection/datetime/datetime.h deleted file mode 100644 index fd47ba03bd..0000000000 --- a/src/detection/datetime/datetime.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#ifndef FF_INCLUDED_detection_datetime_datetime -#define FF_INCLUDED_detection_datetime_datetime - -#include "fastfetch.h" - -typedef struct FFDateTimeResult -{ - //Examples for 21.02.2022 - 15:18:37 - uint16_t year; //2022 - uint8_t yearShort; //22 - uint8_t month; //2 - FFstrbuf monthPretty; //02 - FFstrbuf monthName; //February - FFstrbuf monthNameShort; //Feb - uint8_t week; //8 - FFstrbuf weekday; //Monday - FFstrbuf weekdayShort; //Mon - uint16_t dayInYear; //52 - uint8_t dayInMonth; //21 - uint8_t dayInWeek; //1 - uint8_t hour; //15 - FFstrbuf hourPretty; //15 - uint8_t hour12; //3 - FFstrbuf hour12Pretty; //03 - uint8_t minute; //18 - FFstrbuf minutePretty; //18 - uint8_t second; //37 - FFstrbuf secondPretty; //37 -} FFDateTimeResult; - -const FFDateTimeResult* ffDetectDateTime(); - -#endif diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index a6e5e2245f..3c16442997 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -1,52 +1,144 @@ +#include "common/time.h" #include "common/printing.h" #include "common/jsonconfig.h" -#include "detection/datetime/datetime.h" #include "modules/datetime/datetime.h" #include "util/stringUtils.h" +#include + #define FF_DATETIME_DISPLAY_NAME "Date & Time" #define FF_DATETIME_NUM_FORMAT_ARGS 20 -void ffPrintDateTimeFormat(const char* moduleName, const FFModuleArgs* moduleArgs) +typedef struct FFDateTimeResult +{ + //Examples for 21.02.2022 - 15:18:37 + uint16_t year; //2022 + uint8_t yearShort; //22 + uint8_t month; //2 + FFstrbuf monthPretty; //02 + FFstrbuf monthName; //February + FFstrbuf monthNameShort; //Feb + uint8_t week; //8 + FFstrbuf weekday; //Monday + FFstrbuf weekdayShort; //Mon + uint16_t dayInYear; //52 + uint8_t dayInMonth; //21 + uint8_t dayInWeek; //1 + uint8_t hour; //15 + FFstrbuf hourPretty; //15 + uint8_t hour12; //3 + FFstrbuf hour12Pretty; //03 + uint8_t minute; //18 + FFstrbuf minutePretty; //18 + uint8_t second; //37 + FFstrbuf secondPretty; //37 +} FFDateTimeResult; + +void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) { - const FFDateTimeResult* result = ffDetectDateTime(); - ffPrintFormat(moduleName, 0, moduleArgs, FF_DATETIME_NUM_FORMAT_ARGS, (FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_UINT16, &result->year}, // 1 - {FF_FORMAT_ARG_TYPE_UINT8, &result->yearShort}, // 2 - {FF_FORMAT_ARG_TYPE_UINT8, &result->month}, // 3 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->monthPretty}, // 4 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->monthName}, // 5 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->monthNameShort}, // 6 - {FF_FORMAT_ARG_TYPE_UINT8, &result->week}, // 7 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->weekday}, // 8 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->weekdayShort}, // 9 - {FF_FORMAT_ARG_TYPE_UINT16, &result->dayInYear}, // 10 - {FF_FORMAT_ARG_TYPE_UINT8, &result->dayInMonth}, // 11 - {FF_FORMAT_ARG_TYPE_UINT8, &result->dayInWeek}, // 12 - {FF_FORMAT_ARG_TYPE_UINT8, &result->hour}, // 13 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->hourPretty}, // 14 - {FF_FORMAT_ARG_TYPE_UINT8, &result->hour12}, // 15 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->hour12Pretty}, // 16 - {FF_FORMAT_ARG_TYPE_UINT8, &result->minute}, // 17 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->minutePretty}, // 18 - {FF_FORMAT_ARG_TYPE_UINT8, &result->second}, // 19 - {FF_FORMAT_ARG_TYPE_STRBUF, &result->secondPretty} // 20 + FFDateTimeResult result; + + result.year = (uint16_t) (tm->tm_year + 1900); + result.yearShort = (uint8_t) (result.year % 100); + result.month = (uint8_t) (tm->tm_mon + 1); + + ffStrbufInitA(&result.monthPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.monthPretty.length = (uint32_t) strftime(result.monthPretty.chars, ffStrbufGetFree(&result.monthPretty), "%m", tm); + + ffStrbufInitA(&result.monthName, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.monthName.length = (uint32_t) strftime(result.monthName.chars, ffStrbufGetFree(&result.monthName), "%B", tm); + + ffStrbufInitA(&result.monthNameShort, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.monthNameShort.length = (uint32_t) strftime(result.monthNameShort.chars, ffStrbufGetFree(&result.monthNameShort), "%b", tm); + + result.week = (uint8_t) (tm->tm_yday / 7 + 1); + + ffStrbufInitA(&result.weekday, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.weekday.length = (uint32_t) strftime(result.weekday.chars, ffStrbufGetFree(&result.weekday), "%A", tm); + + ffStrbufInitA(&result.weekdayShort, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.weekdayShort.length = (uint32_t) strftime(result.weekdayShort.chars, ffStrbufGetFree(&result.weekdayShort), "%a", tm); + + result.dayInYear = (uint8_t) (tm->tm_yday + 1); + result.dayInMonth = (uint8_t) tm->tm_mday; + result.dayInWeek = tm->tm_wday == 0 ? 7 : (uint8_t) tm->tm_wday; + + result.hour = (uint8_t) tm->tm_hour; + + ffStrbufInitA(&result.hourPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.hourPretty.length = (uint32_t) strftime(result.hourPretty.chars, ffStrbufGetFree(&result.hourPretty), "%H", tm); + + result.hour12 = (uint8_t) (result.hour % 12); + + ffStrbufInitA(&result.hour12Pretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.hour12Pretty.length = (uint32_t) strftime(result.hour12Pretty.chars, ffStrbufGetFree(&result.hour12Pretty), "%I", tm); + + result.minute = (uint8_t) tm->tm_min; + + ffStrbufInitA(&result.minutePretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.minutePretty.length = (uint32_t) strftime(result.minutePretty.chars, ffStrbufGetFree(&result.minutePretty), "%M", tm); + + result.second = (uint8_t) tm->tm_sec; + + ffStrbufInitA(&result.secondPretty, FASTFETCH_STRBUF_DEFAULT_ALLOC); + result.secondPretty.length = (uint32_t) strftime(result.secondPretty.chars, ffStrbufGetFree(&result.secondPretty), "%S", tm); + + ffPrintFormat(FF_DATETIME_DISPLAY_NAME, 0, moduleArgs, FF_DATETIME_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_UINT16, &result.year}, // 1 + {FF_FORMAT_ARG_TYPE_UINT8, &result.yearShort}, // 2 + {FF_FORMAT_ARG_TYPE_UINT8, &result.month}, // 3 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.monthPretty}, // 4 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.monthName}, // 5 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.monthNameShort}, // 6 + {FF_FORMAT_ARG_TYPE_UINT8, &result.week}, // 7 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.weekday}, // 8 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.weekdayShort}, // 9 + {FF_FORMAT_ARG_TYPE_UINT16, &result.dayInYear}, // 10 + {FF_FORMAT_ARG_TYPE_UINT8, &result.dayInMonth}, // 11 + {FF_FORMAT_ARG_TYPE_UINT8, &result.dayInWeek}, // 12 + {FF_FORMAT_ARG_TYPE_UINT8, &result.hour}, // 13 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.hourPretty}, // 14 + {FF_FORMAT_ARG_TYPE_UINT8, &result.hour12}, // 15 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.hour12Pretty}, // 16 + {FF_FORMAT_ARG_TYPE_UINT8, &result.minute}, // 17 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.minutePretty}, // 18 + {FF_FORMAT_ARG_TYPE_UINT8, &result.second}, // 19 + {FF_FORMAT_ARG_TYPE_STRBUF, &result.secondPretty} // 20 }); + + ffStrbufDestroy(&result.hour12Pretty); + ffStrbufDestroy(&result.hourPretty); + ffStrbufDestroy(&result.minutePretty); + ffStrbufDestroy(&result.monthName); + ffStrbufDestroy(&result.monthNameShort); + ffStrbufDestroy(&result.monthPretty); + ffStrbufDestroy(&result.secondPretty); + ffStrbufDestroy(&result.weekday); + ffStrbufDestroy(&result.weekdayShort); } void ffPrintDateTime(FFDateTimeOptions* options) { + uint64_t msNow = ffTimeGetNow(); + time_t sNow = msNow / 1000; + struct tm* tm = localtime(&sNow); + if(options->moduleArgs.outputFormat.length > 0) { - ffPrintDateTimeFormat(FF_DATETIME_DISPLAY_NAME, &options->moduleArgs); + ffPrintDateTimeFormat(tm, &options->moduleArgs); + return; + } + + char buffer[32]; + if (strftime(buffer, sizeof(buffer), "%F %T", tm) == 0) //yyyy-MM-dd HH:mm:ss + { + ffPrintError(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, "strftime() failed"); return; } - const FFDateTimeResult* datetime = ffDetectDateTime(); ffPrintLogoAndKey(FF_DATETIME_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - //yyyy-MM-dd HH:mm:ss - printf("%u-%s-%02u %s:%s:%s\n", datetime->year, datetime->monthPretty.chars, datetime->dayInMonth, datetime->hourPretty.chars, datetime->minutePretty.chars, datetime->secondPretty.chars); + puts(buffer); } void ffInitDateTimeOptions(FFDateTimeOptions* options) @@ -89,27 +181,5 @@ void ffParseDateTimeJsonObject(FFDateTimeOptions* options, yyjson_val* module) void ffGenerateDateTimeJson(FF_MAYBE_UNUSED FFDateTimeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - const FFDateTimeResult* result = ffDetectDateTime(); - - yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); - yyjson_mut_obj_add_uint(doc, obj, "year", result->year); - yyjson_mut_obj_add_uint(doc, obj, "yearShort", result->yearShort); - yyjson_mut_obj_add_uint(doc, obj, "month", result->month); - yyjson_mut_obj_add_strbuf(doc, obj, "monthPretty", &result->monthPretty); - yyjson_mut_obj_add_strbuf(doc, obj, "monthName", &result->monthName); - yyjson_mut_obj_add_strbuf(doc, obj, "monthNameShort", &result->monthNameShort); - yyjson_mut_obj_add_uint(doc, obj, "week", result->week); - yyjson_mut_obj_add_strbuf(doc, obj, "weekday", &result->weekday); - yyjson_mut_obj_add_strbuf(doc, obj, "weekdaySort", &result->weekdayShort); - yyjson_mut_obj_add_uint(doc, obj, "dayInYear", result->dayInYear); - yyjson_mut_obj_add_uint(doc, obj, "dayInMonth", result->dayInMonth); - yyjson_mut_obj_add_uint(doc, obj, "dayInWeek", result->dayInWeek); - yyjson_mut_obj_add_uint(doc, obj, "hour", result->hour); - yyjson_mut_obj_add_strbuf(doc, obj, "hourPretty", &result->hourPretty); - yyjson_mut_obj_add_uint(doc, obj, "hour12", result->hour12); - yyjson_mut_obj_add_strbuf(doc, obj, "hour12Pretty", &result->hour12Pretty); - yyjson_mut_obj_add_uint(doc, obj, "minute", result->minute); - yyjson_mut_obj_add_strbuf(doc, obj, "minutePretty", &result->minutePretty); - yyjson_mut_obj_add_uint(doc, obj, "second", result->second); - yyjson_mut_obj_add_strbuf(doc, obj, "secondPretty", &result->secondPretty); + yyjson_mut_obj_add_uint(doc, module, "result", ffTimeGetNow()); } From 4124c12bacaf37eeabdaa75030b24d1da56266d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 16:17:17 +0800 Subject: [PATCH 087/198] TerminalSize: support JSON format --- src/modules/terminalsize/terminalsize.c | 19 ++++++++++++++++++- src/modules/terminalsize/terminalsize.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/modules/terminalsize/terminalsize.c b/src/modules/terminalsize/terminalsize.c index a6083f8edc..22ef849efe 100644 --- a/src/modules/terminalsize/terminalsize.c +++ b/src/modules/terminalsize/terminalsize.c @@ -41,7 +41,7 @@ void ffPrintTerminalSize(FFTerminalSizeOptions* options) void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeCommandOptions, ffParseTerminalSizeJsonObject, ffPrintTerminalSize, ffGenerateTerminalSizeJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -76,3 +76,20 @@ void ffParseTerminalSizeJsonObject(FFTerminalSizeOptions* options, yyjson_val* m ffPrintError(FF_TERMINALSIZE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateTerminalSizeJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFTerminalSizeResult result; + + if(!ffDetectTerminalSize(&result)) + { + yyjson_mut_obj_add_str(doc, module, "error", "Failed to detect terminal size"); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_uint(doc, obj, "columns", result.columns); + yyjson_mut_obj_add_uint(doc, obj, "rows", result.rows); + yyjson_mut_obj_add_uint(doc, obj, "width", result.width); + yyjson_mut_obj_add_uint(doc, obj, "height", result.height); +} diff --git a/src/modules/terminalsize/terminalsize.h b/src/modules/terminalsize/terminalsize.h index 1703c5944a..33699057d5 100644 --- a/src/modules/terminalsize/terminalsize.h +++ b/src/modules/terminalsize/terminalsize.h @@ -9,3 +9,4 @@ void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options); bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const char* key, const char* value); void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options); void ffParseTerminalSizeJsonObject(FFTerminalSizeOptions* options, yyjson_val* module); +void ffGenerateTerminalSizeJson(FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From e91d011c8c60907811c124c4983c85c88e2e182e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 20:23:58 +0800 Subject: [PATCH 088/198] Theme: support JSON format --- src/modules/theme/theme.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 268d7bf500..08b345fe7b 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -67,3 +67,17 @@ void ffParseThemeJsonObject(FFThemeOptions* options, yyjson_val* module) ffPrintError(FF_THEME_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateThemeJson(FF_MAYBE_UNUSED FFThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_STRBUF_AUTO_DESTROY theme = ffStrbufCreate(); + const char* error = ffDetectTheme(&theme); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_obj_add_strbuf(doc, module, "result", &theme); +} From 10a249d3a8a1e973bfdd59c217a91fc708138d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 20:31:19 +0800 Subject: [PATCH 089/198] Title: support JSON support --- src/modules/title/title.c | 12 +++++++++++- src/modules/title/title.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 32d4b5ad9b..dc67b6546b 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -51,7 +51,7 @@ void ffPrintTitle(FFTitleOptions* options) void ffInitTitleOptions(FFTitleOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, ffGenerateTitleJson); ffOptionInitModuleArg(&options->moduleArgs); options->fqdn = false; ffStrbufInit(&options->colorUser); @@ -140,3 +140,13 @@ void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module) ffPrintErrorString(FF_TITLE_MODULE_NAME, 0, NULL, FF_PRINT_TYPE_NO_CUSTOM_KEY, "Unknown JSON key %s", key); } } + +void ffGenerateTitleJson(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "userName", &instance.state.platform.userName); + yyjson_mut_obj_add_strbuf(doc, obj, "homeDir", &instance.state.platform.homeDir); + yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &instance.state.platform.hostName); + yyjson_mut_obj_add_strbuf(doc, obj, "domainName", &instance.state.platform.domainName); + yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &instance.state.platform.exePath); +} diff --git a/src/modules/title/title.h b/src/modules/title/title.h index fd7ae5e689..76bec364d9 100644 --- a/src/modules/title/title.h +++ b/src/modules/title/title.h @@ -9,3 +9,4 @@ void ffInitTitleOptions(FFTitleOptions* options); bool ffParseTitleCommandOptions(FFTitleOptions* options, const char* key, const char* value); void ffDestroyTitleOptions(FFTitleOptions* options); void ffParseTitleJsonObject(FFTitleOptions* options, yyjson_val* module); +void ffGenerateTitleJson(FFTitleOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 4449173b3dc5798a7f57f643f268f423f284da39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 12 Sep 2023 20:36:00 +0800 Subject: [PATCH 090/198] Version: support JSON config --- src/modules/version/version.c | 18 ++++++++++++++++-- src/modules/version/version.h | 1 + 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 0805c1ee47..34b8e06423 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -8,7 +8,7 @@ void ffPrintVersion(FFVersionOptions* options) { - FFVersionResult result = {}; + FFVersionResult result; ffDetectVersion(&result); if(options->moduleArgs.outputFormat.length == 0) @@ -31,7 +31,7 @@ void ffPrintVersion(FFVersionOptions* options) void ffInitVersionOptions(FFVersionOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VERSION_MODULE_NAME, ffParseVersionCommandOptions, ffParseVersionJsonObject, ffPrintVersion, ffGenerateVersionJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -66,3 +66,17 @@ void ffParseVersionJsonObject(FFVersionOptions* options, yyjson_val* module) ffPrintError(FF_VERSION_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateVersionJson(FF_MAYBE_UNUSED FFVersionOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFVersionResult result; + ffDetectVersion(&result); + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_str(doc, obj, "projectName", result.projectName); + yyjson_mut_obj_add_str(doc, obj, "architecture", result.architecture); + yyjson_mut_obj_add_str(doc, obj, "version", result.version); + yyjson_mut_obj_add_str(doc, obj, "versionTweak", result.versionTweak); + yyjson_mut_obj_add_str(doc, obj, "cmakeBuiltType", result.cmakeBuiltType); + yyjson_mut_obj_add_bool(doc, obj, "debugMode", result.debugMode); +} diff --git a/src/modules/version/version.h b/src/modules/version/version.h index ef423b36ed..bb1e4c15f7 100644 --- a/src/modules/version/version.h +++ b/src/modules/version/version.h @@ -9,3 +9,4 @@ void ffInitVersionOptions(FFVersionOptions* options); bool ffParseVersionCommandOptions(FFVersionOptions* options, const char* key, const char* value); void ffDestroyVersionOptions(FFVersionOptions* options); void ffParseVersionJsonObject(FFVersionOptions* options, yyjson_val* module); +void ffGenerateVersionJson(FFVersionOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 9b72971dc93c44b322bca60d4c7dd6a186a19b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 08:49:10 +0800 Subject: [PATCH 091/198] Uptime (FreeBSD): fix building --- src/detection/uptime/uptime_bsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/uptime/uptime_bsd.c b/src/detection/uptime/uptime_bsd.c index 90b986da7e..47202544ae 100644 --- a/src/detection/uptime/uptime_bsd.c +++ b/src/detection/uptime/uptime_bsd.c @@ -2,6 +2,7 @@ #include "common/time.h" #include +#include const char* ffDetectUptime(FFUptimeResult* result) { From c400261a1117ee6b447998d1da329c44c1deaff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 09:41:57 +0800 Subject: [PATCH 092/198] Deps: update yyjson --- src/3rdparty/yyjson/repo.json | 2 +- src/3rdparty/yyjson/yyjson.c | 264 +++++++++++++++++++++++++++------- src/3rdparty/yyjson/yyjson.h | 100 ++++++++++--- src/common/jsonconfig.h | 16 --- 4 files changed, 298 insertions(+), 84 deletions(-) diff --git a/src/3rdparty/yyjson/repo.json b/src/3rdparty/yyjson/repo.json index d9edbde014..ac57551034 100644 --- a/src/3rdparty/yyjson/repo.json +++ b/src/3rdparty/yyjson/repo.json @@ -1,6 +1,6 @@ { "home": "https://github.com/ibireme/yyjson", "license": "MIT ( embed in source )", - "version": "5e3b26d2659287d31e2f8e10f95f95feb7e5ab3a", + "version": "d50c9564b6cb22e0b24751941abcd36ad254cff8", "author": "ibireme" } diff --git a/src/3rdparty/yyjson/yyjson.c b/src/3rdparty/yyjson/yyjson.c index c669bab9bc..5934af7c1f 100644 --- a/src/3rdparty/yyjson/yyjson.c +++ b/src/3rdparty/yyjson/yyjson.c @@ -307,6 +307,9 @@ uint32_t yyjson_version(void) { #define YYJSON_MUT_DOC_VAL_POOL_INIT_SIZE (0x10 * sizeof(yyjson_mut_val)) #define YYJSON_MUT_DOC_VAL_POOL_MAX_SIZE (0x1000000 * sizeof(yyjson_mut_val)) +/* The minimum size of the dynamic allocator's chunk. */ +#define YYJSON_ALC_DYN_MIN_SIZE 0x1000 + /* Default value for compile-time options. */ #ifndef YYJSON_DISABLE_READER #define YYJSON_DISABLE_READER 0 @@ -966,6 +969,15 @@ static const yyjson_alc YYJSON_DEFAULT_ALC = { NULL }; + + +/*============================================================================== + * Null Memory Allocator + * + * This allocator is just a placeholder to ensure that the internal + * malloc/realloc/free function pointers are not null. + *============================================================================*/ + static void *null_malloc(void *ctx, usize size) { return NULL; } @@ -989,29 +1001,37 @@ static const yyjson_alc YYJSON_NULL_ALC = { /*============================================================================== * Pool Memory Allocator - * This is a simple memory allocator that uses linked list memory chunk. - * The following code will be executed only when the library user creates - * this allocator manually. + * + * This allocator is initialized with a fixed-size buffer. + * The buffer is split into multiple memory chunks for memory allocation. *============================================================================*/ -/** chunk header */ +/** memory chunk header */ typedef struct pool_chunk { - usize size; /* chunk memory size (include chunk header) */ - struct pool_chunk *next; + usize size; /* chunk memory size, include chunk header */ + struct pool_chunk *next; /* linked list, nullable */ + /* char mem[]; flexible array member */ } pool_chunk; -/** ctx header */ +/** allocator ctx header */ typedef struct pool_ctx { - usize size; /* total memory size (include ctx header) */ - pool_chunk *free_list; + usize size; /* total memory size, include ctx header */ + pool_chunk *free_list; /* linked list, nullable */ + /* pool_chunk chunks[]; flexible array member */ } pool_ctx; +/** align up the input size to chunk size */ +static_inline void pool_size_align(usize *size) { + *size = size_align_up(*size, sizeof(pool_chunk)) + sizeof(pool_chunk); +} + static void *pool_malloc(void *ctx_ptr, usize size) { + /* assert(size != 0) */ pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *next, *prev = NULL, *cur = ctx->free_list; - if (unlikely(size == 0 || size >= ctx->size)) return NULL; - size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); + if (unlikely(size >= ctx->size)) return NULL; + pool_size_align(&size); while (cur) { if (cur->size < size) { @@ -1038,6 +1058,7 @@ static void *pool_malloc(void *ctx_ptr, usize size) { } static void pool_free(void *ctx_ptr, void *ptr) { + /* assert(ptr != NULL) */ pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1; pool_chunk *prev = NULL, *next = ctx->free_list; @@ -1064,25 +1085,15 @@ static void pool_free(void *ctx_ptr, void *ptr) { static void *pool_realloc(void *ctx_ptr, void *ptr, usize old_size, usize size) { + /* assert(ptr != NULL && size != 0 && old_size < size) */ pool_ctx *ctx = (pool_ctx *)ctx_ptr; pool_chunk *cur = ((pool_chunk *)ptr) - 1, *prev, *next, *tmp; - usize free_size; - void *new_ptr; - if (unlikely(size == 0 || size >= ctx->size)) return NULL; - size = size_align_up(size, sizeof(pool_chunk)) + sizeof(pool_chunk); - - /* reduce size */ - if (unlikely(size <= cur->size)) { - free_size = cur->size - size; - if (free_size >= sizeof(pool_chunk) * 2) { - tmp = (pool_chunk *)(void *)((u8 *)cur + cur->size - free_size); - tmp->size = free_size; - pool_free(ctx_ptr, (void *)(tmp + 1)); - cur->size -= free_size; - } - return ptr; - } + /* check size */ + if (unlikely(size >= ctx->size)) return NULL; + pool_size_align(&old_size); + pool_size_align(&size); + if (unlikely(old_size == size)) return ptr; /* find next and prev chunk */ prev = NULL; @@ -1092,10 +1103,9 @@ static void *pool_realloc(void *ctx_ptr, void *ptr, next = next->next; } - /* merge to higher chunk if they are contiguous */ - if ((u8 *)cur + cur->size == (u8 *)next && - cur->size + next->size >= size) { - free_size = cur->size + next->size - size; + if ((u8 *)cur + cur->size == (u8 *)next && cur->size + next->size >= size) { + /* merge to higher chunk if they are contiguous */ + usize free_size = cur->size + next->size - size; if (free_size > sizeof(pool_chunk) * 2) { tmp = (pool_chunk *)(void *)((u8 *)cur + size); if (prev) prev->next = tmp; @@ -1109,15 +1119,15 @@ static void *pool_realloc(void *ctx_ptr, void *ptr, cur->size += next->size; } return ptr; + } else { + /* fallback to malloc and memcpy */ + void *new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk)); + if (new_ptr) { + memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk)); + pool_free(ctx_ptr, ptr); + } + return new_ptr; } - - /* fallback to malloc and memcpy */ - new_ptr = pool_malloc(ctx_ptr, size - sizeof(pool_chunk)); - if (new_ptr) { - memcpy(new_ptr, ptr, cur->size - sizeof(pool_chunk)); - pool_free(ctx_ptr, ptr); - } - return new_ptr; } bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { @@ -1147,6 +1157,161 @@ bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, usize size) { +/*============================================================================== + * Dynamic Memory Allocator + * + * This allocator allocates memory on demand and does not immediately release + * unused memory. Instead, it places the unused memory into a freelist for + * potential reuse in the future. It is only when the entire allocator is + * destroyed that all previously allocated memory is released at once. + *============================================================================*/ + +/** memory chunk header */ +typedef struct dyn_chunk { + usize size; /* chunk size, include header */ + struct dyn_chunk *next; + /* char mem[]; flexible array member */ +} dyn_chunk; + +/** allocator ctx header */ +typedef struct { + dyn_chunk free_list; /* dummy header, sorted from small to large */ + dyn_chunk used_list; /* dummy header */ +} dyn_ctx; + +/** align up the input size to chunk size */ +static_inline bool dyn_size_align(usize *size) { + usize alc_size = *size + sizeof(dyn_chunk); + alc_size = size_align_up(alc_size, YYJSON_ALC_DYN_MIN_SIZE); + if (unlikely(alc_size < *size)) return false; /* overflow */ + *size = alc_size; + return true; +} + +/** remove a chunk from list (the chunk must already be in the list) */ +static_inline void dyn_chunk_list_remove(dyn_chunk *list, dyn_chunk *chunk) { + dyn_chunk *prev = list, *cur; + for (cur = prev->next; cur; cur = cur->next) { + if (cur == chunk) { + prev->next = cur->next; + cur->next = NULL; + return; + } + prev = cur; + } +} + +/** add a chunk to list header (the chunk must not be in the list) */ +static_inline void dyn_chunk_list_add(dyn_chunk *list, dyn_chunk *chunk) { + chunk->next = list->next; + list->next = chunk; +} + +static void *dyn_malloc(void *ctx_ptr, usize size) { + /* assert(size != 0) */ + const yyjson_alc def = YYJSON_DEFAULT_ALC; + dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; + dyn_chunk *chunk, *prev, *next; + if (unlikely(!dyn_size_align(&size))) return NULL; + + /* freelist is empty, create new chunk */ + if (!ctx->free_list.next) { + chunk = (dyn_chunk *)def.malloc(def.ctx, size); + if (unlikely(!chunk)) return NULL; + chunk->size = size; + chunk->next = NULL; + dyn_chunk_list_add(&ctx->used_list, chunk); + return (void *)(chunk + 1); + } + + /* find a large enough chunk, or resize the largest chunk */ + prev = &ctx->free_list; + while (true) { + chunk = prev->next; + if (chunk->size >= size) { /* enough size, reuse this chunk */ + prev->next = chunk->next; + dyn_chunk_list_add(&ctx->used_list, chunk); + return (void *)(chunk + 1); + } + if (!chunk->next) { /* resize the largest chunk */ + chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size); + if (unlikely(!chunk)) return NULL; + prev->next = NULL; + chunk->size = size; + dyn_chunk_list_add(&ctx->used_list, chunk); + return (void *)(chunk + 1); + } + prev = chunk; + } +} + +static void *dyn_realloc(void *ctx_ptr, void *ptr, + usize old_size, usize size) { + /* assert(ptr != NULL && size != 0 && old_size < size) */ + const yyjson_alc def = YYJSON_DEFAULT_ALC; + dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; + dyn_chunk *prev, *next, *new_chunk; + dyn_chunk *chunk = (dyn_chunk *)ptr - 1; + if (unlikely(!dyn_size_align(&size))) return NULL; + if (chunk->size >= size) return ptr; + + dyn_chunk_list_remove(&ctx->used_list, chunk); + new_chunk = (dyn_chunk *)def.realloc(def.ctx, chunk, chunk->size, size); + if (likely(new_chunk)) { + new_chunk->size = size; + chunk = new_chunk; + } + dyn_chunk_list_add(&ctx->used_list, chunk); + return new_chunk ? (void *)(new_chunk + 1) : NULL; +} + +static void dyn_free(void *ctx_ptr, void *ptr) { + /* assert(ptr != NULL) */ + dyn_ctx *ctx = (dyn_ctx *)ctx_ptr; + dyn_chunk *chunk = (dyn_chunk *)ptr - 1, *prev; + + dyn_chunk_list_remove(&ctx->used_list, chunk); + for (prev = &ctx->free_list; prev; prev = prev->next) { + if (!prev->next || prev->next->size >= chunk->size) { + chunk->next = prev->next; + prev->next = chunk; + break; + } + } +} + +yyjson_alc *yyjson_alc_dyn_new(void) { + const yyjson_alc def = YYJSON_DEFAULT_ALC; + usize hdr_len = sizeof(yyjson_alc) + sizeof(dyn_ctx); + yyjson_alc *alc = (yyjson_alc *)def.malloc(def.ctx, hdr_len); + dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1); + if (unlikely(!alc)) return NULL; + alc->malloc = dyn_malloc; + alc->realloc = dyn_realloc; + alc->free = dyn_free; + alc->ctx = alc + 1; + memset(ctx, 0, sizeof(*ctx)); + return alc; +} + +void yyjson_alc_dyn_free(yyjson_alc *alc) { + const yyjson_alc def = YYJSON_DEFAULT_ALC; + dyn_ctx *ctx = (dyn_ctx *)(void *)(alc + 1); + dyn_chunk *chunk, *next; + if (unlikely(!alc)) return; + for (chunk = ctx->free_list.next; chunk; chunk = next) { + next = chunk->next; + def.free(def.ctx, chunk); + } + for (chunk = ctx->used_list.next; chunk; chunk = next) { + next = chunk->next; + def.free(def.ctx, chunk); + } + def.free(def.ctx, alc); +} + + + /*============================================================================== * JSON document and value *============================================================================*/ @@ -1305,7 +1470,6 @@ yyjson_mut_val *yyjson_val_mut_copy(yyjson_mut_doc *m_doc, We copy them to another contiguous memory as mutable values, then reconnect the mutable values with the original relationship. */ - usize i_vals_len; yyjson_mut_val *m_vals, *m_val; yyjson_val *i_val, *i_end; @@ -1375,7 +1539,6 @@ static yyjson_mut_val *unsafe_yyjson_mut_val_mut_copy(yyjson_mut_doc *m_doc, second to last item, which needs to be linked to the last item to close the circle. */ - yyjson_mut_val *m_val = unsafe_yyjson_mut_val(m_doc, 1); if (unlikely(!m_val)) return NULL; m_val->tag = m_vals->tag; @@ -1540,12 +1703,13 @@ static_inline bool unsafe_yyjson_num_equals(void *lhs, void *rhs) { yyjson_val_uni *runi = &((yyjson_val *)rhs)->uni; yyjson_subtype lt = unsafe_yyjson_get_subtype(lhs); yyjson_subtype rt = unsafe_yyjson_get_subtype(rhs); - if (lt == rt) - return luni->u64 == runi->u64; - if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) + if (lt == rt) return luni->u64 == runi->u64; + if (lt == YYJSON_SUBTYPE_SINT && rt == YYJSON_SUBTYPE_UINT) { return luni->i64 >= 0 && luni->u64 == runi->u64; - if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) + } + if (lt == YYJSON_SUBTYPE_UINT && rt == YYJSON_SUBTYPE_SINT) { return runi->i64 >= 0 && luni->u64 == runi->u64; + } return false; } @@ -1571,8 +1735,8 @@ bool unsafe_yyjson_equals(yyjson_val *lhs, yyjson_val *rhs) { while (len-- > 0) { rhs = yyjson_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); - if (!rhs || !unsafe_yyjson_equals(lhs + 1, rhs)) - return false; + if (!rhs) return false; + if (!unsafe_yyjson_equals(lhs + 1, rhs)) return false; lhs = unsafe_yyjson_get_next(lhs + 1); } } @@ -1626,8 +1790,8 @@ bool unsafe_yyjson_mut_equals(yyjson_mut_val *lhs, yyjson_mut_val *rhs) { while (len-- > 0) { rhs = yyjson_mut_obj_iter_getn(&iter, lhs->uni.str, unsafe_yyjson_get_len(lhs)); - if (!rhs || !unsafe_yyjson_mut_equals(lhs->next, rhs)) - return false; + if (!rhs) return false; + if (!unsafe_yyjson_mut_equals(lhs->next, rhs)) return false; lhs = lhs->next->next; } } @@ -2506,6 +2670,7 @@ yyjson_mut_val *yyjson_merge_patch(yyjson_mut_doc *doc, builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; + memset(&local_orig, 0, sizeof(local_orig)); if (!yyjson_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; @@ -2557,6 +2722,7 @@ yyjson_mut_val *yyjson_mut_merge_patch(yyjson_mut_doc *doc, builder = yyjson_mut_obj(doc); if (unlikely(!builder)) return NULL; + memset(&local_orig, 0, sizeof(local_orig)); if (!yyjson_mut_is_obj(orig)) { orig = &local_orig; orig->tag = builder->tag; diff --git a/src/3rdparty/yyjson/yyjson.h b/src/3rdparty/yyjson/yyjson.h index a9740045ad..d3d1074cd3 100644 --- a/src/3rdparty/yyjson/yyjson.h +++ b/src/3rdparty/yyjson/yyjson.h @@ -635,11 +635,11 @@ typedef struct yyjson_alc { function, but the amount of memory required to write a JSON cannot be directly calculated. - This is not a general-purpose allocator. If used to read multiple JSON - documents and only some of them are released, it may cause memory - fragmentation, leading to performance degradation and memory waste. Therefore, - it is recommended to use this allocator only for reading or writing a single - JSON document. + This is not a general-purpose allocator. It is designed to handle a single JSON + data at a time. If it is used for overly complex memory tasks, such as parsing + multiple JSON documents using the same allocator but releasing only a few of + them, it may cause memory fragmentation, resulting in performance degradation + and memory waste. @param alc The allocator to be initialized. If this parameter is NULL, the function will fail and return false. @@ -662,9 +662,31 @@ typedef struct yyjson_alc { yyjson_doc *doc = yyjson_read_opts(json, strlen(json), 0, &alc, NULL); // the memory of `doc` is on the stack @endcode + + @warning This Allocator is not thread-safe. */ yyjson_api bool yyjson_alc_pool_init(yyjson_alc *alc, void *buf, size_t size); +/** + A dynamic allocator. + + This allocator has a similar usage to the pool allocator above. However, when + there is not enough memory, this allocator will dynamically request more memory + using libc's `malloc` function, and frees it all at once when it is destroyed. + + @return A new dynamic allocator, or NULL if memory allocation failed. + @note The returned value should be freed with `yyjson_alc_dyn_free()`. + + @warning This Allocator is not thread-safe. + */ +yyjson_api yyjson_alc *yyjson_alc_dyn_new(void); + +/** + Free a dynamic allocator which is created by `yyjson_alc_dyn_new()`. + @param alc The dynamic allocator to be destroyed. + */ +yyjson_api void yyjson_alc_dyn_free(yyjson_alc *alc); + /*============================================================================== @@ -3556,7 +3578,7 @@ yyjson_api_inline bool yyjson_mut_obj_rotate(yyjson_mut_val *obj, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3566,7 +3588,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_null(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3576,7 +3598,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_true(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3586,7 +3608,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_false(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3596,7 +3618,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_bool(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3606,7 +3628,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_uint(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3616,7 +3638,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_sint(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3626,7 +3648,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_int(yyjson_mut_doc *doc, The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3636,7 +3658,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_real(yyjson_mut_doc *doc, The `key` and `val` should be null-terminated UTF-8 strings. This function allows duplicated key in one object. - @warning The key/value string are not copied, you should keep these strings + @warning The key/value strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3648,7 +3670,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_str(yyjson_mut_doc *doc, The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. - @warning The key/value string are not copied, you should keep these strings + @warning The key/value strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3660,7 +3682,7 @@ yyjson_api_inline bool yyjson_mut_obj_add_strn(yyjson_mut_doc *doc, The value string is copied. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -3673,18 +3695,44 @@ yyjson_api_inline bool yyjson_mut_obj_add_strcpy(yyjson_mut_doc *doc, The `len` should be the length of the `val`, in bytes. This function allows duplicated key in one object. - @warning The key/value string are not copied, you should keep these strings + @warning The key/value strings are not copied, you should keep these strings unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, const char *val, size_t len); +/** + Creates and adds a new array to the target object. + The `key` should be a null-terminated UTF-8 string. + This function allows duplicated key in one object. + + @warning The key string is not copied, you should keep these strings + unmodified for the lifetime of this JSON document. + @return The new array, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *key); + +/** + Creates and adds a new object to the target object. + The `key` should be a null-terminated UTF-8 string. + This function allows duplicated key in one object. + + @warning The key string is not copied, you should keep these strings + unmodified for the lifetime of this JSON document. + @return The new object, or NULL on error. + */ +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *key); + /** Adds a JSON value at the end of the object. The `key` should be a null-terminated UTF-8 string. This function allows duplicated key in one object. - @warning The key string are not copied, you should keep the string + @warning The key string is not copied, you should keep the string unmodified for the lifetime of this JSON document. */ yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, @@ -6920,6 +6968,22 @@ yyjson_api_inline bool yyjson_mut_obj_add_strncpy(yyjson_mut_doc *doc, }); } +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_arr(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *_key) { + yyjson_mut_val *key = yyjson_mut_str(doc, _key); + yyjson_mut_val *val = yyjson_mut_arr(doc); + return yyjson_mut_obj_add(obj, key, val) ? val : NULL; +} + +yyjson_api_inline yyjson_mut_val *yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, + yyjson_mut_val *obj, + const char *_key) { + yyjson_mut_val *key = yyjson_mut_str(doc, _key); + yyjson_mut_val *val = yyjson_mut_obj(doc); + return yyjson_mut_obj_add(obj, key, val) ? val : NULL; +} + yyjson_api_inline bool yyjson_mut_obj_add_val(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *_key, diff --git a/src/common/jsonconfig.h b/src/common/jsonconfig.h index ea8c589687..afb0fd8657 100644 --- a/src/common/jsonconfig.h +++ b/src/common/jsonconfig.h @@ -21,19 +21,3 @@ yyjson_api_inline bool yyjson_mut_arr_add_strbuf(yyjson_mut_doc *doc, const FFstrbuf* buf) { return yyjson_mut_arr_add_strncpy(doc, obj, buf->chars, buf->length); } - -yyjson_api_inline yyjson_mut_val* yyjson_mut_obj_add_obj(yyjson_mut_doc *doc, - yyjson_mut_val *obj, - const char *_key) { - yyjson_mut_val* newObj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, obj, _key, newObj); - return newObj; -} - -yyjson_api_inline yyjson_mut_val* yyjson_mut_obj_add_arr(yyjson_mut_doc *doc, - yyjson_mut_val *obj, - const char *_key) { - yyjson_mut_val* newArr = yyjson_mut_arr(doc); - yyjson_mut_obj_add_val(doc, obj, _key, newArr); - return newArr; -} From 16b01a06e01a3899e5f37e23de6ce4dcc7b4a0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 09:53:25 +0800 Subject: [PATCH 093/198] Vulkan: support JSON format --- src/modules/vulkan/vulkan.c | 36 +++++++++++++++++++++++++++++++++++- src/modules/vulkan/vulkan.h | 1 + 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index fe57fc9a07..7bd65e25cd 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -1,5 +1,6 @@ #include "common/printing.h" #include "common/jsonconfig.h" +#include "detection/gpu/gpu.h" #include "detection/vulkan/vulkan.h" #include "modules/vulkan/vulkan.h" #include "util/stringUtils.h" @@ -45,7 +46,7 @@ void ffPrintVulkan(FFVulkanOptions* options) void ffInitVulkanOptions(FFVulkanOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_VULKAN_MODULE_NAME, ffParseVulkanCommandOptions, ffParseVulkanJsonObject, ffPrintVulkan, ffGenerateVulkanJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -80,3 +81,36 @@ void ffParseVulkanJsonObject(FFVulkanOptions* options, yyjson_val* module) ffPrintError(FF_VULKAN_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateVulkanJson(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFVulkanResult* result = ffDetectVulkan(); + + if(result->error) + { + yyjson_mut_obj_add_str(doc, module, "error", result->error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "apiVersion", &result->apiVersion); + yyjson_mut_obj_add_strbuf(doc, obj, "conformanceVersion", &result->conformanceVersion); + yyjson_mut_obj_add_strbuf(doc, obj, "driver", &result->driver); + yyjson_mut_val* gpus = yyjson_mut_obj_add_arr(doc, obj, "gpus"); + FF_LIST_FOR_EACH(FFGPUResult, vulkanGpu, result->gpus) + { + yyjson_mut_val* gpuObj = yyjson_mut_arr_add_obj(doc, gpus); + yyjson_mut_obj_add_str(doc, gpuObj, "type", vulkanGpu->type == FF_GPU_TYPE_UNKNOWN ? "Unknown" : vulkanGpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete"); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "vendor", &vulkanGpu->vendor); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &vulkanGpu->name); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &vulkanGpu->driver); + yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); + yyjson_mut_val* dedicatedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "total", vulkanGpu->dedicated.total); + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "used", vulkanGpu->dedicated.used); + yyjson_mut_val* sharedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); + yyjson_mut_obj_add_uint(doc, sharedMemory, "total", vulkanGpu->shared.total); + yyjson_mut_obj_add_uint(doc, sharedMemory, "used", vulkanGpu->shared.used); + yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", vulkanGpu->vulkanDeviceId); + } +} diff --git a/src/modules/vulkan/vulkan.h b/src/modules/vulkan/vulkan.h index e9b7d3954e..a0b378394e 100644 --- a/src/modules/vulkan/vulkan.h +++ b/src/modules/vulkan/vulkan.h @@ -9,3 +9,4 @@ void ffInitVulkanOptions(FFVulkanOptions* options); bool ffParseVulkanCommandOptions(FFVulkanOptions* options, const char* key, const char* value); void ffDestroyVulkanOptions(FFVulkanOptions* options); void ffParseVulkanJsonObject(FFVulkanOptions* options, yyjson_val* module); +void ffGenerateVulkanJson(FFVulkanOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 9765885fe6373a11b4dabd029f60512add9a3d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 13:39:56 +0800 Subject: [PATCH 094/198] Wallpaper: support JSON format --- src/modules/wallpaper/wallpaper.c | 14 +++++++++++++- src/modules/wallpaper/wallpaper.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/modules/wallpaper/wallpaper.c b/src/modules/wallpaper/wallpaper.c index e6f49e18bc..947a1031e5 100644 --- a/src/modules/wallpaper/wallpaper.c +++ b/src/modules/wallpaper/wallpaper.c @@ -44,7 +44,7 @@ void ffPrintWallpaper(FFWallpaperOptions* options) void ffInitWallpaperOptions(FFWallpaperOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WALLPAPER_MODULE_NAME, ffParseWallpaperCommandOptions, ffParseWallpaperJsonObject, ffPrintWallpaper, ffGenerateWallpaperJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -79,3 +79,15 @@ void ffParseWallpaperJsonObject(FFWallpaperOptions* options, yyjson_val* module) ffPrintError(FF_WALLPAPER_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateWallpaperJson(FF_MAYBE_UNUSED FFWallpaperOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_STRBUF_AUTO_DESTROY fullpath = ffStrbufCreate(); + const char* error = ffDetectWallpaper(&fullpath); + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + yyjson_mut_obj_add_strbuf(doc, module, "result", &fullpath); +} diff --git a/src/modules/wallpaper/wallpaper.h b/src/modules/wallpaper/wallpaper.h index 244684fc4c..3925784b27 100644 --- a/src/modules/wallpaper/wallpaper.h +++ b/src/modules/wallpaper/wallpaper.h @@ -9,3 +9,4 @@ void ffInitWallpaperOptions(FFWallpaperOptions* options); bool ffParseWallpaperCommandOptions(FFWallpaperOptions* options, const char* key, const char* value); void ffDestroyWallpaperOptions(FFWallpaperOptions* options); void ffParseWallpaperJsonObject(FFWallpaperOptions* options, yyjson_val* module); +void ffGenerateWallpaperJson(FFWallpaperOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 3a8819d42b5223277fc2176d8f52746692fb3b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 14:01:15 +0800 Subject: [PATCH 095/198] Wifi: support JSON format --- src/modules/wifi/wifi.c | 48 ++++++++++++++++++++++++++++++++++++++++- src/modules/wifi/wifi.h | 1 + 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/modules/wifi/wifi.c b/src/modules/wifi/wifi.c index 0e030bd7e3..449b82e67a 100644 --- a/src/modules/wifi/wifi.c +++ b/src/modules/wifi/wifi.c @@ -72,7 +72,7 @@ void ffPrintWifi(FFWifiOptions* options) void ffInitWifiOptions(FFWifiOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WIFI_MODULE_NAME, ffParseWifiCommandOptions, ffParseWifiJsonObject, ffPrintWifi, ffGenerateWifiJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -107,3 +107,49 @@ void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module) ffPrintError(FF_WIFI_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateWifiJson(FF_MAYBE_UNUSED FFWifiOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFWifiResult)); + const char* error = ffDetectWifi(&result); + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + if(!result.length) + { + yyjson_mut_obj_add_str(doc, module, "error", "No Wifi interfaces found"); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFWifiResult, wifi, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + + yyjson_mut_val* inf = yyjson_mut_obj_add_obj(doc, obj, "inf"); + yyjson_mut_obj_add_strbuf(doc, inf, "description", &wifi->inf.description); + yyjson_mut_obj_add_strbuf(doc, inf, "status", &wifi->inf.status); + + yyjson_mut_val* conn = yyjson_mut_obj_add_obj(doc, obj, "conn"); + yyjson_mut_obj_add_strbuf(doc, conn, "status", &wifi->conn.status); + yyjson_mut_obj_add_strbuf(doc, conn, "ssid", &wifi->conn.ssid); + yyjson_mut_obj_add_strbuf(doc, conn, "macAddress", &wifi->conn.macAddress); + yyjson_mut_obj_add_strbuf(doc, conn, "protocol", &wifi->conn.protocol); + yyjson_mut_obj_add_real(doc, conn, "signalQuality", wifi->conn.signalQuality); + yyjson_mut_obj_add_real(doc, conn, "rxRate", wifi->conn.rxRate); + yyjson_mut_obj_add_real(doc, conn, "txRate", wifi->conn.txRate); + } + + FF_LIST_FOR_EACH(FFWifiResult, item, result) + { + ffStrbufDestroy(&item->inf.description); + ffStrbufDestroy(&item->inf.status); + ffStrbufDestroy(&item->conn.status); + ffStrbufDestroy(&item->conn.ssid); + ffStrbufDestroy(&item->conn.macAddress); + ffStrbufDestroy(&item->conn.protocol); + ffStrbufDestroy(&item->conn.security); + } +} diff --git a/src/modules/wifi/wifi.h b/src/modules/wifi/wifi.h index 0a7b78e2d0..2957f876d8 100644 --- a/src/modules/wifi/wifi.h +++ b/src/modules/wifi/wifi.h @@ -9,3 +9,4 @@ void ffInitWifiOptions(FFWifiOptions* options); bool ffParseWifiCommandOptions(FFWifiOptions* options, const char* key, const char* value); void ffDestroyWifiOptions(FFWifiOptions* options); void ffParseWifiJsonObject(FFWifiOptions* options, yyjson_val* module); +void ffGenerateWifiJson(FFWifiOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 77466ba6f55b6ba304f844084e9004a2e1d627e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 14:07:14 +0800 Subject: [PATCH 096/198] GPU: tidy --- src/modules/gpu/gpu.c | 6 ++++-- src/modules/vulkan/vulkan.c | 34 ++++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 18773e7f30..4bf6726ad4 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -230,7 +230,9 @@ void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va else yyjson_mut_obj_add_null(doc, obj, "coreCount"); - yyjson_mut_val* dedicatedObj = yyjson_mut_obj_add_obj(doc, obj, "dedicated"); + yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, obj, "memory"); + + yyjson_mut_val* dedicatedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) yyjson_mut_obj_add_uint(doc, dedicatedObj, "total", gpu->dedicated.total); else @@ -244,7 +246,7 @@ void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va yyjson_mut_obj_add_strbuf(doc, obj, "driver", &gpu->driver); yyjson_mut_obj_add_strbuf(doc, obj, "name", &gpu->name); - yyjson_mut_val* sharedObj = yyjson_mut_obj_add_obj(doc, obj, "shared"); + yyjson_mut_val* sharedObj = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) yyjson_mut_obj_add_uint(doc, sharedObj, "total", gpu->shared.total); else diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 7bd65e25cd..14c37153ac 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -104,13 +104,35 @@ void ffGenerateVulkanJson(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson_mut_d yyjson_mut_obj_add_strbuf(doc, gpuObj, "vendor", &vulkanGpu->vendor); yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &vulkanGpu->name); yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &vulkanGpu->driver); + yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); - yyjson_mut_val* dedicatedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); - yyjson_mut_obj_add_uint(doc, dedicatedMemory, "total", vulkanGpu->dedicated.total); - yyjson_mut_obj_add_uint(doc, dedicatedMemory, "used", vulkanGpu->dedicated.used); - yyjson_mut_val* sharedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); - yyjson_mut_obj_add_uint(doc, sharedMemory, "total", vulkanGpu->shared.total); - yyjson_mut_obj_add_uint(doc, sharedMemory, "used", vulkanGpu->shared.used); + + { + yyjson_mut_val* dedicatedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); + if (vulkanGpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "total", vulkanGpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "total"); + + if (vulkanGpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "used", vulkanGpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "used"); + } + + { + yyjson_mut_val* sharedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); + if (vulkanGpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "total", vulkanGpu->shared.total); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "total"); + + if (vulkanGpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "used", vulkanGpu->shared.used); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "used"); + } + yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", vulkanGpu->vulkanDeviceId); } } From 804463a4708efd00bbf21e930a8d97481fd3e581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 14:22:04 +0800 Subject: [PATCH 097/198] WM: support JSON format --- src/modules/wm/wm.c | 17 ++++++++++++++++- src/modules/wm/wm.h | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/modules/wm/wm.c b/src/modules/wm/wm.c index 3c7f532953..371b48deb8 100644 --- a/src/modules/wm/wm.c +++ b/src/modules/wm/wm.c @@ -43,7 +43,7 @@ void ffPrintWM(FFWMOptions* options) void ffInitWMOptions(FFWMOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WM_MODULE_NAME, ffParseWMCommandOptions, ffParseWMJsonObject, ffPrintWM, ffGenerateWMJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -78,3 +78,18 @@ void ffParseWMJsonObject(FFWMOptions* options, yyjson_val* module) ffPrintError(FF_WM_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateWMJson(FF_MAYBE_UNUSED FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + const FFDisplayServerResult* result = ffConnectDisplayServer(); + + if(result->wmPrettyName.length == 0) + { + yyjson_mut_obj_add_str(doc, module, "error", "No WM found"); + return; + } + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->wmProcessName); + yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->wmPrettyName); + yyjson_mut_obj_add_strbuf(doc, obj, "protocolName", &result->wmProtocolName); +} diff --git a/src/modules/wm/wm.h b/src/modules/wm/wm.h index 607732d720..fe960b6885 100644 --- a/src/modules/wm/wm.h +++ b/src/modules/wm/wm.h @@ -9,3 +9,4 @@ void ffInitWMOptions(FFWMOptions* options); bool ffParseWMCommandOptions(FFWMOptions* options, const char* key, const char* value); void ffDestroyWMOptions(FFWMOptions* options); void ffParseWMJsonObject(FFWMOptions* options, yyjson_val* module); +void ffGenerateWMJson(FFWMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 3dfa99c2326b8dbea4dd8559fca0823f787e3473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 14:25:00 +0800 Subject: [PATCH 098/198] WMTheme: support JSON format --- src/modules/wmtheme/wmtheme.c | 14 +++++++++++++- src/modules/wmtheme/wmtheme.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/modules/wmtheme/wmtheme.c b/src/modules/wmtheme/wmtheme.c index 9376b5475f..3560769223 100644 --- a/src/modules/wmtheme/wmtheme.c +++ b/src/modules/wmtheme/wmtheme.c @@ -32,7 +32,7 @@ void ffPrintWMTheme(FFWMThemeOptions* options) void ffInitWMThemeOptions(FFWMThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WMTHEME_MODULE_NAME, ffParseWMThemeCommandOptions, ffParseWMThemeJsonObject, ffPrintWMTheme, ffGenerateWMThemeJson); ffOptionInitModuleArg(&options->moduleArgs); } @@ -67,3 +67,15 @@ void ffParseWMThemeJsonObject(FFWMThemeOptions* options, yyjson_val* module) ffPrintError(FF_WMTHEME_DISPLAY_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateWMThemeJson(FF_MAYBE_UNUSED FFWMThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_STRBUF_AUTO_DESTROY themeOrError = ffStrbufCreate(); + if(!ffDetectWmTheme(&themeOrError)) + { + yyjson_mut_obj_add_strbuf(doc, module, "error", &themeOrError); + return; + } + + yyjson_mut_obj_add_strbuf(doc, module, "result", &themeOrError); +} diff --git a/src/modules/wmtheme/wmtheme.h b/src/modules/wmtheme/wmtheme.h index 216fdc7233..e90f9e2530 100644 --- a/src/modules/wmtheme/wmtheme.h +++ b/src/modules/wmtheme/wmtheme.h @@ -9,3 +9,4 @@ void ffInitWMThemeOptions(FFWMThemeOptions* options); bool ffParseWMThemeCommandOptions(FFWMThemeOptions* options, const char* key, const char* value); void ffDestroyWMThemeOptions(FFWMThemeOptions* options); void ffParseWMThemeJsonObject(FFWMThemeOptions* options, yyjson_val* module); +void ffGenerateWMThemeJson(FFWMThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 2963e3bd9377de0c4dfdcc4f3b0ff3d7814278e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 14:34:39 +0800 Subject: [PATCH 099/198] Terminal: don't print shell information in Terminal module --- src/fastfetch.c | 10 +++------- src/modules/terminal/terminal.c | 14 +++++--------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 5bf30bfa57..2d9cfb79d6 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -262,13 +262,9 @@ static inline void printCommandHelp(const char* command) "Terminal process name", "Terminal path with exe name", "Terminal exe name", - "Shell process name", - "Shell path with exe name", - "Shell exe name", - "Shell version", - "User shell path with exe name", - "User shell exe name", - "User shell version" + "Terminal pid", + "Terminal pretty name", + "Terminal version" ); } else if(ffStrEqualsIgnCase(command, "terminalfont-format")) diff --git a/src/modules/terminal/terminal.c b/src/modules/terminal/terminal.c index 6009b1dbca..ac68652f04 100644 --- a/src/modules/terminal/terminal.c +++ b/src/modules/terminal/terminal.c @@ -6,7 +6,7 @@ #include -#define FF_TERMINAL_NUM_FORMAT_ARGS 10 +#define FF_TERMINAL_NUM_FORMAT_ARGS 6 void ffPrintTerminal(FFTerminalOptions* options) { @@ -33,13 +33,9 @@ void ffPrintTerminal(FFTerminalOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalProcessName}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalExe}, {FF_FORMAT_ARG_TYPE_STRING, result->terminalExeName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &result->shellProcessName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &result->shellExe}, - {FF_FORMAT_ARG_TYPE_STRING, result->shellExeName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &result->shellVersion}, - {FF_FORMAT_ARG_TYPE_STRBUF, &result->userShellExe}, - {FF_FORMAT_ARG_TYPE_STRING, result->userShellExeName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &result->userShellVersion} + {FF_FORMAT_ARG_TYPE_UINT, &result->terminalPid}, + {FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalPrettyName}, + {FF_FORMAT_ARG_TYPE_STRBUF, &result->terminalVersion}, }); } } @@ -93,10 +89,10 @@ void ffGenerateTerminalJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_m } yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->terminalProcessName); yyjson_mut_obj_add_strbuf(doc, obj, "exe", &result->terminalExe); yyjson_mut_obj_add_strcpy(doc, obj, "exeName", result->terminalExeName); yyjson_mut_obj_add_uint(doc, obj, "pid", result->terminalPid); yyjson_mut_obj_add_strbuf(doc, obj, "prettyName", &result->terminalPrettyName); - yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->terminalProcessName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->terminalVersion); } From 7dfc0d8e6004a546e6fb997e21afbe040d929715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 14:47:13 +0800 Subject: [PATCH 100/198] Shell: don't detect user shell --- src/detection/terminalshell/terminalshell.h | 4 ---- .../terminalshell/terminalshell_linux.c | 21 +++---------------- .../terminalshell/terminalshell_windows.c | 4 ---- src/fastfetch.c | 7 +++---- src/modules/shell/shell.c | 10 +++------ src/modules/title/title.c | 1 + 6 files changed, 10 insertions(+), 37 deletions(-) diff --git a/src/detection/terminalshell/terminalshell.h b/src/detection/terminalshell/terminalshell.h index c727b5fdf4..41e31700f2 100644 --- a/src/detection/terminalshell/terminalshell.h +++ b/src/detection/terminalshell/terminalshell.h @@ -20,10 +20,6 @@ typedef struct FFTerminalShellResult const char* terminalExeName; //pointer to a char in terminalExe FFstrbuf terminalVersion; uint32_t terminalPid; - - FFstrbuf userShellExe; - const char* userShellExeName; //pointer to a char in userShellExe - FFstrbuf userShellVersion; } FFTerminalShellResult; const FFTerminalShellResult* ffDetectTerminalShell(); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 3eabaa6f66..1e1efa4166 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -269,18 +269,12 @@ static void getTerminalFromEnv(FFTerminalShellResult* result) static void getUserShellFromEnv(FFTerminalShellResult* result) { - ffStrbufSet(&result->userShellExe, &instance.state.platform.userShell); - if(result->userShellExe.length == 0) - return; - - setExeName(&result->userShellExe, &result->userShellExeName); - //If shell detection via processes failed - if(result->shellProcessName.length == 0 && result->userShellExe.length > 0) + if(result->shellProcessName.length == 0 && instance.state.platform.userShell.length > 0) { - ffStrbufAppendS(&result->shellProcessName, result->userShellExeName); - ffStrbufSet(&result->shellExe, &result->userShellExe); + ffStrbufSet(&result->shellExe, &instance.state.platform.userShell); setExeName(&result->shellExe, &result->shellExeName); + ffStrbufAppendS(&result->shellProcessName, result->shellExeName); } } @@ -348,10 +342,6 @@ const FFTerminalShellResult* ffDetectTerminalShell() result.terminalExeName = result.terminalExe.chars; result.terminalPid = 0; - ffStrbufInit(&result.userShellExe); - result.userShellExeName = result.userShellExe.chars; - ffStrbufInit(&result.userShellVersion); - getTerminalShell(&result, getppid()); getTerminalFromEnv(&result); @@ -360,11 +350,6 @@ const FFTerminalShellResult* ffDetectTerminalShell() ffStrbufClear(&result.shellVersion); getShellVersion(&result.shellExe, result.shellExeName, &result.shellVersion); - if(strcasecmp(result.shellExeName, result.userShellExeName) != 0) - getShellVersion(&result.userShellExe, result.userShellExeName, &result.userShellVersion); - else - ffStrbufSet(&result.userShellVersion, &result.shellVersion); - if(ffStrbufEqualS(&result.shellProcessName, "pwsh")) ffStrbufInitStatic(&result.shellPrettyName, "PowerShell"); else if(ffStrbufEqualS(&result.shellProcessName, "nu")) diff --git a/src/detection/terminalshell/terminalshell_windows.c b/src/detection/terminalshell/terminalshell_windows.c index 0bd65e5784..ebc062b337 100644 --- a/src/detection/terminalshell/terminalshell_windows.c +++ b/src/detection/terminalshell/terminalshell_windows.c @@ -379,10 +379,6 @@ const FFTerminalShellResult* ffDetectTerminalShell(void) ffStrbufInit(&result.terminalPrettyName); result.terminalPid = 0; - ffStrbufInit(&result.userShellExe); - result.userShellExeName = ""; - ffStrbufInit(&result.userShellVersion); - uint32_t ppid; if(!getProcessInfo(0, &ppid, NULL, NULL, NULL)) goto exit; diff --git a/src/fastfetch.c b/src/fastfetch.c index 2d9cfb79d6..3b78942d2d 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -158,14 +158,13 @@ static inline void printCommandHelp(const char* command) } else if(ffStrEqualsIgnCase(command, "shell-format")) { - constructAndPrintCommandHelpFormat("shell", "{3} {4}", 7, + constructAndPrintCommandHelpFormat("shell", "{3} {4}", 6, "Shell process name", "Shell path with exe name", "Shell exe name", "Shell version", - "User shell path with exe name", - "User shell exe name", - "User shell version" + "Shell pid", + "Shell pretty name" ); } else if(ffStrEqualsIgnCase(command, "display-format")) diff --git a/src/modules/shell/shell.c b/src/modules/shell/shell.c index a50607fff3..f7668c5882 100644 --- a/src/modules/shell/shell.c +++ b/src/modules/shell/shell.c @@ -4,7 +4,7 @@ #include "modules/shell/shell.h" #include "util/stringUtils.h" -#define FF_SHELL_NUM_FORMAT_ARGS 7 +#define FF_SHELL_NUM_FORMAT_ARGS 6 void ffPrintShell(FFShellOptions* options) { @@ -36,9 +36,8 @@ void ffPrintShell(FFShellOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &result->shellExe}, {FF_FORMAT_ARG_TYPE_STRING, result->shellExeName}, {FF_FORMAT_ARG_TYPE_STRBUF, &result->shellVersion}, - {FF_FORMAT_ARG_TYPE_STRBUF, &result->userShellExe}, - {FF_FORMAT_ARG_TYPE_STRING, result->userShellExeName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &result->userShellVersion} + {FF_FORMAT_ARG_TYPE_UINT, &result->shellPid}, + {FF_FORMAT_ARG_TYPE_STRBUF, &result->shellPrettyName}, }); } } @@ -97,7 +96,4 @@ void ffGenerateShellJson(FF_MAYBE_UNUSED FFShellOptions* options, yyjson_mut_doc yyjson_mut_obj_add_uint(doc, obj, "pid", result->shellPid); yyjson_mut_obj_add_strbuf(doc, obj, "processName", &result->shellProcessName); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result->shellVersion); - yyjson_mut_obj_add_strbuf(doc, obj, "userShellExe", &result->userShellExe); - yyjson_mut_obj_add_strcpy(doc, obj, "userShellExeName", result->userShellExeName); - yyjson_mut_obj_add_strbuf(doc, obj, "userShellVersion", &result->userShellVersion); } diff --git a/src/modules/title/title.c b/src/modules/title/title.c index dc67b6546b..7cfd087bef 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -149,4 +149,5 @@ void ffGenerateTitleJson(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &instance.state.platform.hostName); yyjson_mut_obj_add_strbuf(doc, obj, "domainName", &instance.state.platform.domainName); yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &instance.state.platform.exePath); + yyjson_mut_obj_add_strbuf(doc, obj, "userShell", &instance.state.platform.userShell); } From 58f234638b24724a80ff5e6db986c9ff39ebf6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 15:22:38 +0800 Subject: [PATCH 101/198] Users: make `--users-compact` false by default --- src/modules/users/users.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/users/users.c b/src/modules/users/users.c index dee5a9bee9..ab58440c2e 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -96,7 +96,7 @@ void ffInitUsersOptions(FFUsersOptions* options) ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_USERS_MODULE_NAME, ffParseUsersCommandOptions, ffParseUsersJsonObject, ffPrintUsers, ffGenerateUsersJson); ffOptionInitModuleArg(&options->moduleArgs); - options->compact = true; + options->compact = false; } bool ffParseUsersCommandOptions(FFUsersOptions* options, const char* key, const char* value) From 8d914ace33440602aa3baf964ce02f5c07eb2774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 15:23:02 +0800 Subject: [PATCH 102/198] Doc: update changelog --- CHANGELOG.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b9597dc75..84e75e4ad7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,32 @@ -# 2.0.6 +# 2.1.0 + +This release introduces a new output format: JSON result + +Changes: +* Users module detects and prints user login time by default. Specifying `--users-compact` to disable it +* Fastfetch now requires yyjson 0.7.1 or later, which is embeded in fastfetch source tree. If you build fastfetch with `-DENABLE_SYSTEM_YYJSON` cmake option, you must upgrade your yyjson package +* Reduced information supported by `--terminal-format`, `--shell-format` Features: +* Add `--format json`, which prints system information as JSON format * Add fast path for xfce4 version detection (DE, FreeBSD) -* Add contour terminal version and font detection (Terminal / TerminalFont) +* Support contour terminal version and font detection (Terminal / TerminalFont) +* Support `kitty-direct` / `iterm` without specifying logo width / height. Note: in this case, the entre screen will be cleared. +* Support new flag `--logo-separate`. If true, print modules at bottom of the logo +* Support Apple Silicon CPU frequency detection (CPU, macOS) +* Support user login time detection (Users) +* Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows) Bugfixes: * Fix `fastfetch --config verbose` doesn't work (#547) +* Fix short read when reading from stdin (Logo) +* Fix `poll() timeout or failed` error when image is very large (Logo) +* Fix Termux Monet terminal version detection (Terminal) Logo: -* support `kitty-direct` / `iterm` without specifying logo width / height. Note: in this case, the entre screen will be cleared. * Update EvolutionOS +* Update AOSC OS +* Add Afterglow # 2.0.5 From b3bdf494abf80679397fe04367a14efdd084a14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 16:20:50 +0800 Subject: [PATCH 103/198] PublicIP: code refactor --- CMakeLists.txt | 1 + src/detection/publicip/publicip.c | 73 ++++++++++++++++++++++++++ src/detection/publicip/publicip.h | 10 ++++ src/modules/publicip/publicip.c | 87 ++++++------------------------- 4 files changed, 100 insertions(+), 71 deletions(-) create mode 100644 src/detection/publicip/publicip.c create mode 100644 src/detection/publicip/publicip.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ed8a05f46a..8275f91df9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,6 +276,7 @@ set(LIBFASTFETCH_SRC src/detection/opencl/opencl.c src/detection/os/os.c src/detection/packages/packages.c + src/detection/publicip/publicip.c src/detection/terminalfont/terminalfont.c src/detection/terminalshell/terminalshell.c src/detection/version/version.c diff --git a/src/detection/publicip/publicip.c b/src/detection/publicip/publicip.c new file mode 100644 index 0000000000..4c1cdc42f7 --- /dev/null +++ b/src/detection/publicip/publicip.c @@ -0,0 +1,73 @@ +#include "publicip.h" +#include "common/networking.h" + +static FFNetworkingState state; +static int status = -1; + +void ffPreparePublicIp(FFPublicIpOptions* options) +{ + if (status != -1) + { + fputs("Error: this module can only be used once due to internal limitations\n", stderr); + exit(1); + } + + if (options->url.length == 0) + status = ffNetworkingSendHttpRequest(&state, "ipinfo.io", "/json", NULL); + else + { + FF_STRBUF_AUTO_DESTROY host = ffStrbufCreateCopy(&options->url); + ffStrbufSubstrAfterFirstS(&host, "://"); + uint32_t pathStartIndex = ffStrbufFirstIndexC(&host, '/'); + + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); + if(pathStartIndex != host.length) + { + ffStrbufAppendNS(&path, pathStartIndex, host.chars + (host.length - pathStartIndex)); + host.length = pathStartIndex; + host.chars[pathStartIndex] = '\0'; + } + + status = ffNetworkingSendHttpRequest(&state, host.chars, path.length == 0 ? "/" : path.chars, NULL); + } +} + +static inline void wrapYyjsonFree(yyjson_doc** doc) +{ + assert(doc); + if (*doc) + yyjson_doc_free(*doc); +} + +const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* result) +{ + if (status == -1) + ffPreparePublicIp(options); + + if (status == 0) + return "Failed to connect to an IP detection server"; + + FF_STRBUF_AUTO_DESTROY response = ffStrbufCreateA(4096); + bool success = ffNetworkingRecvHttpResponse(&state, &response, options->timeout); + if (success) ffStrbufSubstrAfterFirstS(&response, "\r\n\r\n"); + + if (!success || response.length == 0) + return "Failed to receive the server response"; + + if (options->url.length == 0) + { + yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(response.chars, response.length, 0, NULL, NULL); + if (doc) + { + yyjson_val* root = yyjson_doc_get_root(doc); + ffStrbufAppendS(&result->ip, yyjson_get_str(yyjson_obj_get(root, "ip"))); + ffStrbufDestroy(&result->location); + ffStrbufInitF(&result->location, "%s, %s", yyjson_get_str(yyjson_obj_get(root, "city")), yyjson_get_str(yyjson_obj_get(root, "country"))); + return NULL; + } + } + + ffStrbufDestroy(&result->ip); + ffStrbufInitMove(&result->ip, &response); + return NULL; +} diff --git a/src/detection/publicip/publicip.h b/src/detection/publicip/publicip.h new file mode 100644 index 0000000000..31ab394f47 --- /dev/null +++ b/src/detection/publicip/publicip.h @@ -0,0 +1,10 @@ +#include "fastfetch.h" + +typedef struct FFPublicIpResult +{ + FFstrbuf ip; + FFstrbuf location; +} FFPublicIpResult; + +void ffPreparePublicIp(FFPublicIpOptions* options); +const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* result); diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index fdaf7b9f6b..21ed3850b9 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -1,98 +1,43 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/networking.h" #include "modules/publicip/publicip.h" +#include "detection/publicip/publicip.h" #include "util/stringUtils.h" #define FF_PUBLICIP_DISPLAY_NAME "Public IP" #define FF_PUBLICIP_NUM_FORMAT_ARGS 1 -static FFNetworkingState state; -static int status = -1; - -static inline void wrapYyjsonFree(yyjson_doc** doc) -{ - assert(doc); - if (*doc) - yyjson_doc_free(*doc); -} - -void ffPreparePublicIp(FFPublicIpOptions* options) -{ - if (status != -1) - { - fputs("Error: " FF_PUBLICIP_DISPLAY_NAME " can only be used once due to internal limitations\n", stderr); - exit(1); - } - - if (options->url.length == 0) - status = ffNetworkingSendHttpRequest(&state, "ipinfo.io", "/json", NULL); - else - { - FF_STRBUF_AUTO_DESTROY host = ffStrbufCreateCopy(&options->url); - ffStrbufSubstrAfterFirstS(&host, "://"); - uint32_t pathStartIndex = ffStrbufFirstIndexC(&host, '/'); - - FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate(); - if(pathStartIndex != host.length) - { - ffStrbufAppendNS(&path, pathStartIndex, host.chars + (host.length - pathStartIndex)); - host.length = pathStartIndex; - host.chars[pathStartIndex] = '\0'; - } - - status = ffNetworkingSendHttpRequest(&state, host.chars, path.length == 0 ? "/" : path.chars, NULL); - } -} - void ffPrintPublicIp(FFPublicIpOptions* options) { - if (status == -1) - ffPreparePublicIp(options); + FFPublicIpResult result; + ffStrbufInit(&result.ip); + ffStrbufInit(&result.location); + const char* error = ffDetectPublicIp(options, &result); - if (status == 0) + if (error) { - ffPrintError(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, "Failed to connect to an IP detection server"); - return; - } - - FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(4096); - bool success = ffNetworkingRecvHttpResponse(&state, &result, options->timeout); - if (success) ffStrbufSubstrAfterFirstS(&result, "\r\n\r\n"); - - if (!success || result.length == 0) - { - ffPrintError(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, "Failed to receive the server response"); + ffPrintError(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, error); return; } if (options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - - if (options->url.length == 0) - { - yyjson_doc* __attribute__((__cleanup__(wrapYyjsonFree))) doc = yyjson_read_opts(result.chars, result.length, 0, NULL, NULL); - if (doc) - { - yyjson_val* root = yyjson_doc_get_root(doc); - printf("%s (%s, %s)\n", - yyjson_get_str(yyjson_obj_get(root, "ip")), - yyjson_get_str(yyjson_obj_get(root, "city")), - yyjson_get_str(yyjson_obj_get(root, "country")) - ); - return; - } - } - - ffStrbufPutTo(&result, stdout); + if (result.location.length) + printf("%s (%s)", result.ip.chars, result.location.chars); + else + ffStrbufPutTo(&result.ip, stdout); } else { ffPrintFormat(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PUBLICIP_NUM_FORMAT_ARGS, (FFformatarg[]) { - {FF_FORMAT_ARG_TYPE_STRBUF, &result} + {FF_FORMAT_ARG_TYPE_STRBUF, &result.ip}, + {FF_FORMAT_ARG_TYPE_STRBUF, &result.location}, }); } + + ffStrbufDestroy(&result.ip); + ffStrbufDestroy(&result.location); } void ffInitPublicIpOptions(FFPublicIpOptions* options) From 28d40d9037615b89f8c4e371447f54dfad0007a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 17:42:22 +0800 Subject: [PATCH 104/198] Global: fix some memleaks --- src/modules/datetime/datetime.c | 2 +- src/modules/sound/sound.c | 6 ++++++ src/modules/terminalfont/terminalfont.c | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 3c16442997..adc7c50cf9 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -120,7 +120,7 @@ void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) void ffPrintDateTime(FFDateTimeOptions* options) { uint64_t msNow = ffTimeGetNow(); - time_t sNow = msNow / 1000; + time_t sNow = (time_t) (msNow / 1000); struct tm* tm = localtime(&sNow); if(options->moduleArgs.outputFormat.length > 0) diff --git a/src/modules/sound/sound.c b/src/modules/sound/sound.c index f3efc6696d..3796a7365a 100644 --- a/src/modules/sound/sound.c +++ b/src/modules/sound/sound.c @@ -177,4 +177,10 @@ void ffGenerateSoundJson(FF_MAYBE_UNUSED FFSoundOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_obj_add_strbuf(doc, obj, "identifier", &item->identifier); } + + FF_LIST_FOR_EACH(FFSoundDevice, device, result) + { + ffStrbufDestroy(&device->identifier); + ffStrbufDestroy(&device->name); + } } diff --git a/src/modules/terminalfont/terminalfont.c b/src/modules/terminalfont/terminalfont.c index 2b992912c2..ca28576c92 100644 --- a/src/modules/terminalfont/terminalfont.c +++ b/src/modules/terminalfont/terminalfont.c @@ -119,4 +119,8 @@ void ffGenerateTerminalFontJson(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjs yyjson_mut_arr_add_strbuf(doc, fallbackStyles, style); } yyjson_mut_obj_add_strbuf(doc, fallback, "pretty", &result.fallback.pretty); + + ffStrbufDestroy(&result.error); + ffFontDestroy(&result.font); + ffFontDestroy(&result.fallback); } From f5ad07a87bdbd84f810f8514d8f8fd1027b9c2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 17:47:31 +0800 Subject: [PATCH 105/198] PublicIP: support JSON format --- src/detection/publicip/publicip.h | 7 +++++++ src/modules/publicip/publicip.c | 23 ++++++++++++++++++++++- src/modules/publicip/publicip.h | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/detection/publicip/publicip.h b/src/detection/publicip/publicip.h index 31ab394f47..1313cc46a0 100644 --- a/src/detection/publicip/publicip.h +++ b/src/detection/publicip/publicip.h @@ -1,3 +1,8 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_publicip_publicip +#define FF_INCLUDED_detection_publicip_publicip + #include "fastfetch.h" typedef struct FFPublicIpResult @@ -8,3 +13,5 @@ typedef struct FFPublicIpResult void ffPreparePublicIp(FFPublicIpOptions* options); const char* ffDetectPublicIp(FFPublicIpOptions* options, FFPublicIpResult* result); + +#endif diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index 21ed3850b9..fbd7f12dd9 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -42,7 +42,7 @@ void ffPrintPublicIp(FFPublicIpOptions* options) void ffInitPublicIpOptions(FFPublicIpOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_PUBLICIP_MODULE_NAME, ffParsePublicIpCommandOptions, ffParsePublicIpJsonObject, ffPrintPublicIp, ffGeneratePublicIpJson); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->url); @@ -106,3 +106,24 @@ void ffParsePublicIpJsonObject(FFPublicIpOptions* options, yyjson_val* module) ffPrintError(FF_PUBLICIP_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGeneratePublicIpJson(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFPublicIpResult result; + ffStrbufInit(&result.ip); + ffStrbufInit(&result.location); + const char* error = ffDetectPublicIp(options, &result); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "ip", &result.ip); + yyjson_mut_obj_add_strbuf(doc, obj, "location", &result.location); + + ffStrbufDestroy(&result.ip); + ffStrbufDestroy(&result.location); +} diff --git a/src/modules/publicip/publicip.h b/src/modules/publicip/publicip.h index 6a7c739d2e..870591eb74 100644 --- a/src/modules/publicip/publicip.h +++ b/src/modules/publicip/publicip.h @@ -11,3 +11,4 @@ void ffInitPublicIpOptions(FFPublicIpOptions* options); bool ffParsePublicIpCommandOptions(FFPublicIpOptions* options, const char* key, const char* value); void ffDestroyPublicIpOptions(FFPublicIpOptions* options); void ffParsePublicIpJsonObject(FFPublicIpOptions* options, yyjson_val* module); +void ffGeneratePublicIpJson(FFPublicIpOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 63c29b10fe5f8797135fa16c42fe09ce1ca9d5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 18:31:22 +0800 Subject: [PATCH 106/198] Weather: code refactor --- CMakeLists.txt | 1 + src/detection/weather/weather.c | 38 +++++++++++++++++++++++++++++++++ src/detection/weather/weather.h | 11 ++++++++++ src/modules/weather/weather.c | 38 +++++---------------------------- 4 files changed, 55 insertions(+), 33 deletions(-) create mode 100644 src/detection/weather/weather.c create mode 100644 src/detection/weather/weather.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8275f91df9..7bad8d4593 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -281,6 +281,7 @@ set(LIBFASTFETCH_SRC src/detection/terminalshell/terminalshell.c src/detection/version/version.c src/detection/vulkan/vulkan.c + src/detection/weather/weather.c src/logo/builtin.c src/logo/image/im6.c src/logo/image/im7.c diff --git a/src/detection/weather/weather.c b/src/detection/weather/weather.c new file mode 100644 index 0000000000..94bd6b5b68 --- /dev/null +++ b/src/detection/weather/weather.c @@ -0,0 +1,38 @@ +#include "weather.h" + +static FFNetworkingState state; +static int status = -1; + +void ffPrepareWeather(FFWeatherOptions* options) +{ + if (status != -1) + { + fputs("Error: this module can only be used once due to internal limitations\n", stderr); + exit(1); + } + + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/"); + if (options->location.length) + ffStrbufAppend(&path, &options->location); + ffStrbufAppendS(&path, "?format="); + ffStrbufAppend(&path, &options->outputFormat); + status = ffNetworkingSendHttpRequest(&state, "wttr.in", path.chars, "User-Agent: curl/0.0.0\r\n"); +} + +const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result) +{ + if(status == -1) + ffPrepareWeather(options); + + if(status == 0) + return "Failed to connect to 'wttr.in'"; + + ffStrbufEnsureFree(result, 4095); + bool success = ffNetworkingRecvHttpResponse(&state, result, options->timeout); + if (success) ffStrbufSubstrAfterFirstS(result, "\r\n\r\n"); + + if(!success || result->length == 0) + return "Failed to receive the server response"; + + return NULL; +} diff --git a/src/detection/weather/weather.h b/src/detection/weather/weather.h new file mode 100644 index 0000000000..c15f1ea3ac --- /dev/null +++ b/src/detection/weather/weather.h @@ -0,0 +1,11 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_weather_weather +#define FF_INCLUDED_detection_weather_weather + +#include "common/networking.h" + +void ffPrepareWeather(FFWeatherOptions* options); +const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result); + +#endif diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 1338f3286c..d71dbef743 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -1,50 +1,22 @@ #include "common/printing.h" #include "common/jsonconfig.h" -#include "common/networking.h" +#include "detection/weather/weather.h" #include "modules/weather/weather.h" #include "util/stringUtils.h" #define FF_WEATHER_NUM_FORMAT_ARGS 1 -static FFNetworkingState state; -static int status = -1; - -void ffPrepareWeather(FFWeatherOptions* options) -{ - if (status != -1) - { - fputs("Error: " FF_WEATHER_MODULE_NAME " can only be used once due to internal limitations\n", stderr); - exit(1); - } - - FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/"); - if (options->location.length) - ffStrbufAppend(&path, &options->location); - ffStrbufAppendS(&path, "?format="); - ffStrbufAppend(&path, &options->outputFormat); - status = ffNetworkingSendHttpRequest(&state, "wttr.in", path.chars, "User-Agent: curl/0.0.0\r\n"); -} - void ffPrintWeather(FFWeatherOptions* options) { - if(status == -1) - ffPrepareWeather(options); + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); + const char* error = ffDetectWeather(options, &result); - if(status == 0) + if(error) { - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, "Failed to connect to 'wttr.in'"); + ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, error); return; } - FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(4096); - bool success = ffNetworkingRecvHttpResponse(&state, &result, options->timeout); - if (success) ffStrbufSubstrAfterFirstS(&result, "\r\n\r\n"); - - if(!success || result.length == 0) - { - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, "Failed to receive the server response"); - return; - } if(options->moduleArgs.outputFormat.length == 0) { From 013abe2b3e18a9325824dfcce589162d68ac55eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 18:38:02 +0800 Subject: [PATCH 107/198] Weather: support JSON format --- src/modules/weather/weather.c | 16 +++++++++++++++- src/modules/weather/weather.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index d71dbef743..609f5f329d 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -33,7 +33,7 @@ void ffPrintWeather(FFWeatherOptions* options) void ffInitWeatherOptions(FFWeatherOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_WEATHER_MODULE_NAME, ffParseWeatherCommandOptions, ffParseWeatherJsonObject, ffPrintWeather, ffGenerateWeatherJson); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->location); @@ -110,3 +110,17 @@ void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module) ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } + +void ffGenerateWeatherJson(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreate(); + const char* error = ffDetectWeather(options, &result); + + if (error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_obj_add_strbuf(doc, module, "result", &result); +} diff --git a/src/modules/weather/weather.h b/src/modules/weather/weather.h index 8886069577..a769402448 100644 --- a/src/modules/weather/weather.h +++ b/src/modules/weather/weather.h @@ -11,3 +11,4 @@ void ffInitWeatherOptions(FFWeatherOptions* options); bool ffParseWeatherCommandOptions(FFWeatherOptions* options, const char* key, const char* value); void ffDestroyWeatherOptions(FFWeatherOptions* options); void ffParseWeatherJsonObject(FFWeatherOptions* options, yyjson_val* module); +void ffGenerateWeatherJson(FFWeatherOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 61131073f2a5b17c64081e7d8b45069f5c843183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 22:46:11 +0800 Subject: [PATCH 108/198] Global: silence compiler warnings --- src/modules/publicip/publicip.c | 2 +- src/modules/weather/weather.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index fbd7f12dd9..c2ff3f297e 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -16,7 +16,7 @@ void ffPrintPublicIp(FFPublicIpOptions* options) if (error) { - ffPrintError(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, error); + ffPrintError(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); return; } diff --git a/src/modules/weather/weather.c b/src/modules/weather/weather.c index 609f5f329d..ec25374b5d 100644 --- a/src/modules/weather/weather.c +++ b/src/modules/weather/weather.c @@ -13,7 +13,7 @@ void ffPrintWeather(FFWeatherOptions* options) if(error) { - ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, error); + ffPrintError(FF_WEATHER_MODULE_NAME, 0, &options->moduleArgs, "%s", error); return; } From 237c6f1c9ea31737b9b19cde9ecf5eb5063d8958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 13 Sep 2023 23:41:26 +0800 Subject: [PATCH 109/198] Processes / LocalIP: try increasing stability --- src/detection/localip/localip_windows.c | 16 ++++++----- src/detection/processes/processes_windows.c | 30 +++++++++++++-------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index c986120baf..841a608e33 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -70,14 +70,16 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) { IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL; - // Start with a 16 KB buffer and resize if needed - - // multiple attempts in case interfaces change while + // 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) + DWORD adapter_addresses_buffer_size = 0; + for (int attempts = 0;; ++attempts) { - adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size); - assert(adapter_addresses); + if (adapter_addresses_buffer_size) + { + adapter_addresses = (IP_ADAPTER_ADDRESSES*)realloc(adapter_addresses, adapter_addresses_buffer_size); + assert(adapter_addresses); + } DWORD error = GetAdaptersAddresses( options->showType & FF_LOCALIP_TYPE_IPV4_BIT @@ -90,7 +92,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (error == ERROR_SUCCESS) break; - else if (ERROR_BUFFER_OVERFLOW == error) + else if (ERROR_BUFFER_OVERFLOW == error && attempts < 4) continue; else return "GetAdaptersAddresses() failed"; diff --git a/src/detection/processes/processes_windows.c b/src/detection/processes/processes_windows.c index dc784c5db8..fb29cd2109 100644 --- a/src/detection/processes/processes_windows.c +++ b/src/detection/processes/processes_windows.c @@ -6,18 +6,26 @@ const char* ffDetectProcesses(uint32_t* result) { - ULONG size = 0; - if(NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &size) != STATUS_INFO_LENGTH_MISMATCH) - return "NtQuerySystemInformation(SystemProcessInformation, NULL) failed"; - - size += sizeof(SystemProcessInformation) * 5; //What if new processes are created during two syscalls? + SYSTEM_PROCESS_INFORMATION* FF_AUTO_FREE pstart = NULL; - SYSTEM_PROCESS_INFORMATION* FF_AUTO_FREE pstart = (SYSTEM_PROCESS_INFORMATION*)malloc(size); - if(!pstart) - return "malloc(size) failed"; - - if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, NULL))) - return "NtQuerySystemInformation(SystemProcessInformation, pstart) failed"; + // Multiple attempts in case processes change while + // we are in the middle of querying them. + ULONG size = 0; + for (int attempts = 0;; ++attempts) + { + if (size) + { + pstart = (SYSTEM_PROCESS_INFORMATION*)realloc(pstart, size); + assert(pstart); + } + NTSTATUS status = NtQuerySystemInformation(SystemProcessInformation, pstart, size, &size); + if(NT_SUCCESS(status)) + break; + else if(status == STATUS_INFO_LENGTH_MISMATCH && attempts < 4) + size += sizeof(SYSTEM_PROCESS_INFORMATION) * 5; + else + return "NtQuerySystemInformation(SystemProcessInformation) failed"; + } *result = 1; //Init with 1 because we test for ptr->NextEntryOffset for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*)((uint8_t*)ptr + ptr->NextEntryOffset)) From df945e824b3d8719356218ce7111b5d440e48b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 14 Sep 2023 08:36:16 +0800 Subject: [PATCH 110/198] Deps: upgrade yyjson --- CHANGELOG.md | 2 +- src/3rdparty/yyjson/repo.json | 2 +- src/3rdparty/yyjson/yyjson.c | 4 ++-- src/3rdparty/yyjson/yyjson.h | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84e75e4ad7..f280bce86b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This release introduces a new output format: JSON result Changes: * Users module detects and prints user login time by default. Specifying `--users-compact` to disable it -* Fastfetch now requires yyjson 0.7.1 or later, which is embeded in fastfetch source tree. If you build fastfetch with `-DENABLE_SYSTEM_YYJSON` cmake option, you must upgrade your yyjson package +* Fastfetch now requires yyjson 0.8.0 or later, which is embeded in fastfetch source tree. If you build fastfetch with `-DENABLE_SYSTEM_YYJSON` cmake option, you must upgrade your yyjson package * Reduced information supported by `--terminal-format`, `--shell-format` Features: diff --git a/src/3rdparty/yyjson/repo.json b/src/3rdparty/yyjson/repo.json index ac57551034..4e8e1106d0 100644 --- a/src/3rdparty/yyjson/repo.json +++ b/src/3rdparty/yyjson/repo.json @@ -1,6 +1,6 @@ { "home": "https://github.com/ibireme/yyjson", "license": "MIT ( embed in source )", - "version": "d50c9564b6cb22e0b24751941abcd36ad254cff8", + "version": "0.8.0", "author": "ibireme" } diff --git a/src/3rdparty/yyjson/yyjson.c b/src/3rdparty/yyjson/yyjson.c index 5934af7c1f..3e74166c19 100644 --- a/src/3rdparty/yyjson/yyjson.c +++ b/src/3rdparty/yyjson/yyjson.c @@ -3484,8 +3484,6 @@ static_inline void pow10_table_get_exp(i32 exp10, i32 *exp2) { -#if !YYJSON_DISABLE_READER - /*============================================================================== * JSON Character Matcher *============================================================================*/ @@ -3679,6 +3677,8 @@ static_inline bool digi_is_digit_or_fp(u8 d) { +#if !YYJSON_DISABLE_READER + /*============================================================================== * Hex Character Reader * This function is used by JSON reader to read escaped characters. diff --git a/src/3rdparty/yyjson/yyjson.h b/src/3rdparty/yyjson/yyjson.h index d3d1074cd3..97b86fb96b 100644 --- a/src/3rdparty/yyjson/yyjson.h +++ b/src/3rdparty/yyjson/yyjson.h @@ -527,16 +527,16 @@ extern "C" { #define YYJSON_VERSION_MAJOR 0 /** The minor version of yyjson. */ -#define YYJSON_VERSION_MINOR 7 +#define YYJSON_VERSION_MINOR 8 /** The patch version of yyjson. */ #define YYJSON_VERSION_PATCH 0 /** The version of yyjson in hex: `(major << 16) | (minor << 8) | (patch)`. */ -#define YYJSON_VERSION_HEX 0x000700 +#define YYJSON_VERSION_HEX 0x000800 /** The version string of yyjson. */ -#define YYJSON_VERSION_STRING "0.7.0" +#define YYJSON_VERSION_STRING "0.8.0" /** The version of yyjson in hex, same as `YYJSON_VERSION_HEX`. */ yyjson_api uint32_t yyjson_version(void); From 9535b6a8bf9c53019b90f4077584312f33439dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 14 Sep 2023 08:55:33 +0800 Subject: [PATCH 111/198] PublicIP: fix missing new line --- src/modules/publicip/publicip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/publicip/publicip.c b/src/modules/publicip/publicip.c index c2ff3f297e..e7c277e21e 100644 --- a/src/modules/publicip/publicip.c +++ b/src/modules/publicip/publicip.c @@ -24,7 +24,7 @@ void ffPrintPublicIp(FFPublicIpOptions* options) { ffPrintLogoAndKey(FF_PUBLICIP_DISPLAY_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if (result.location.length) - printf("%s (%s)", result.ip.chars, result.location.chars); + printf("%s (%s)\n", result.ip.chars, result.location.chars); else ffStrbufPutTo(&result.ip, stdout); } From 2039bed70dad24817c9f6642680f92ac924fe309 Mon Sep 17 00:00:00 2001 From: xbt573 <64583541+xbt573@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:08:57 +0300 Subject: [PATCH 112/198] Logo (Builtin): add Elbrus --- src/logo/ascii/elbrus.txt | 14 ++++++++++++++ src/logo/builtin.c | 10 ++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/logo/ascii/elbrus.txt diff --git a/src/logo/ascii/elbrus.txt b/src/logo/ascii/elbrus.txt new file mode 100644 index 0000000000..b70cac89c6 --- /dev/null +++ b/src/logo/ascii/elbrus.txt @@ -0,0 +1,14 @@ +▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ +██▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀██ +██ ██ +██ ███████ ███████ ██ +██ ██ ██ ██ ██ ██ +██ ██ ██ ██ ██ ██ +██ ██ ██ ██ ██ ██ +██ ██ ██ ██ ██ ██ +██ ██ ███████ ███████ +██ ██ ██ +██ ██▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄██ +██ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀██ +██ ██ +███████████████████████████ diff --git a/src/logo/builtin.c b/src/logo/builtin.c index b61b9589bd..dce999e908 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1192,6 +1192,16 @@ static const FFlogo D[] = { }; static const FFlogo E[] = { + // Elbrus + { + .names = {"elbrus"}, + .lines = FASTFETCH_DATATEXT_LOGO_ELBRUS, + .colors = { + FF_COLOR_FG_BLUE, + }, + .colorKeys = FF_COLOR_FG_BLUE, + .colorTitle = FF_COLOR_FG_BLUE, + }, // Elementary { .names = {"Elementary"}, From 0d7dc2d692bc28710897db68231731717bb33a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 14 Sep 2023 15:28:33 +0800 Subject: [PATCH 113/198] Logo (Ubuntu): changed the edges of the Ubuntu logo to make it rounder Ref: https://github.com/dylanaraps/neofetch/pull/2378 --- src/logo/ascii/ubuntu_old.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/logo/ascii/ubuntu_old.txt b/src/logo/ascii/ubuntu_old.txt index 5a816363b1..2b158dd4c0 100644 --- a/src/logo/ascii/ubuntu_old.txt +++ b/src/logo/ascii/ubuntu_old.txt @@ -1,5 +1,5 @@ - .-/+oossssoo+/-. - `:+ssssssssssssssssss+:` + --+oossssssoo+-- + .:+ssssssssssssssssss+:. -+ssssssssssssssssssyyssss+- .ossssssssssssssssssd$2MMMNy$1sssso. /sssssssssss$2hdmmNNmmyNMMMMh$1ssssss/ @@ -16,5 +16,5 @@ oss$2yNMMMNyMMh$1ssssssssssssss$2hmmmh$1ssssssso /sssssssssss$2hdmNNNNmyNMMMMh$1ssssss/ .ossssssssssssssssss$2dMMMNy$1sssso. -+sssssssssssssssss$2yyy$1ssss+- - `:+ssssssssssssssssss+:` - .-/+oossssoo+/-. \ No newline at end of file + `:+ssssssssssssssssss+:´ + --+oossssssoo+-- From 49f42cd003894408617760739048ce1f3007cf8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 14 Sep 2023 15:29:15 +0800 Subject: [PATCH 114/198] Doc: update changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f280bce86b..daa8255101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,9 +24,11 @@ Bugfixes: * Fix Termux Monet terminal version detection (Terminal) Logo: +* Add Afterglow +* Add Elbrus * Update EvolutionOS * Update AOSC OS -* Add Afterglow +* Update Ubuntu_old # 2.0.5 From f97cddf2da659ba1accf2412dd4c22693d27f133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 14 Sep 2023 15:53:44 +0800 Subject: [PATCH 115/198] JSON: support `--stat` for flag based configurations --- src/common/commandoption.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/common/commandoption.c b/src/common/commandoption.c index 934c52ef1d..5b6f8013b2 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -93,6 +93,8 @@ static void parseStructureCommand(const char* line, FFlist* customValues) void ffPrintCommandOption(FFdata* data) { + yyjson_mut_doc* resultDoc = instance.state.resultDoc; + //Parse the structure and call the modules uint32_t startIndex = 0; while (startIndex < data->structure.length) @@ -101,19 +103,29 @@ void ffPrintCommandOption(FFdata* data) data->structure.chars[colonIndex] = '\0'; uint64_t ms = 0; - if(__builtin_expect(instance.config.stat, false)) + if(instance.config.stat) ms = ffTimeGetTick(); parseStructureCommand(data->structure.chars + startIndex, &data->customValues); - if(__builtin_expect(instance.config.stat, false)) + if(instance.config.stat) { - char str[32]; - int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ffTimeGetTick() - ms); - if(instance.config.pipe) - puts(str); + ms = ffTimeGetTick() - ms; + + if (resultDoc) + { + yyjson_mut_val* moduleJson = yyjson_mut_arr_get_last(resultDoc->root); + yyjson_mut_obj_add_uint(resultDoc, moduleJson, "stat", ms); + } else - printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load + { + char str[32]; + int len = snprintf(str, sizeof str, "%" PRIu64 "ms", ms); + if(instance.config.pipe) + puts(str); + else + printf("\033[s\033[1A\033[9999999C\033[%dD%s\033[u", len, str); // Save; Up 1; Right 9999999; Left ; Print ; Load + } } #if defined(_WIN32) From 0d5cf52f0831547fab65afa2372d490651eb68a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 15 Sep 2023 10:35:12 +0800 Subject: [PATCH 116/198] FFstrbuf: add ffStrbufAppendNC --- src/util/FFstrbuf.c | 8 ++++++++ src/util/FFstrbuf.h | 1 + tests/strbuf.c | 10 ++++++++++ 3 files changed, 19 insertions(+) diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 70a2a029df..ef049b698d 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -73,6 +73,14 @@ void ffStrbufAppendC(FFstrbuf* strbuf, char c) strbuf->chars[strbuf->length] = '\0'; } +void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c) +{ + ffStrbufEnsureFree(strbuf, num); + memset(&strbuf->chars[strbuf->length], c, num); + strbuf->length += num; + strbuf->chars[strbuf->length] = '\0'; +} + void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) { if(value == NULL || length == 0) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 9e9bce198d..704abfd299 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -38,6 +38,7 @@ void ffStrbufClear(FFstrbuf* strbuf); static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* __restrict value); void ffStrbufAppendC(FFstrbuf* strbuf, char c); +void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c); void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value); void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude); void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transformFunc)(int)); diff --git a/tests/strbuf.c b/tests/strbuf.c index d35c93e2f6..defce5a87d 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -56,6 +56,16 @@ int main(void) VERIFY(strbuf.allocated == 0); VERIFY(strbuf.length == 0); + //append(N)C + + ffStrbufAppendC(&strbuf, '1'); + VERIFY(ffStrbufEqualS(&strbuf, "1")); + VERIFY(strbuf.allocated >= 1); + ffStrbufAppendNC(&strbuf, 5, '2'); + VERIFY(ffStrbufEqualS(&strbuf, "122222")); + VERIFY(strbuf.allocated >= 6); + ffStrbufClear(&strbuf); + //appendS ffStrbufAppendS(&strbuf, "12345"); From bd02e5c6328866dd1b345de3f49079edbb018172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 15 Sep 2023 10:53:09 +0800 Subject: [PATCH 117/198] Logo: code refactor --- src/common/printing.c | 4 +- src/logo/image/image.c | 96 +++++++++++++++++++++--------------------- src/logo/logo.c | 10 ++--- 3 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/common/printing.c b/src/common/printing.c index 063127081c..16b6de8efb 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -112,9 +112,7 @@ void ffPrintColor(const FFstrbuf* colorValue) if(colorValue->length == 0) return; - fputs("\033[", stdout); - ffStrbufWriteTo(colorValue, stdout); - fputc('m', stdout); + printf("\e[%sm", colorValue->chars); } void ffPrintCharTimes(char c, uint32_t times) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 6da5f4cfc3..953d12f8db 100644 --- a/src/logo/image/image.c +++ b/src/logo/image/image.c @@ -11,7 +11,7 @@ #include #endif -static FFstrbuf base64Encode(FFstrbuf* in) +static FFstrbuf base64Encode(const FFstrbuf* in) { const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -37,8 +37,9 @@ static FFstrbuf base64Encode(FFstrbuf* in) static bool printImageIterm(void) { + const FFLogoOptions* options = &instance.config.logo; FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate(); - if(!ffAppendFileBuffer(instance.config.logo.source.chars, &buf)) + if(!ffAppendFileBuffer(options->source.chars, &buf)) { fputs("Logo: Failed to load image file\n", stderr); return false; @@ -49,28 +50,26 @@ static bool printImageIterm(void) FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&buf); ffStrbufClear(&buf); - if (!instance.config.logo.width || !instance.config.logo.height) + if (!options->width || !options->height) { - if (!instance.config.logo.separate) + if (!options->separate) { ffStrbufAppendF(&buf, "\e[2J\e[3J\e[%u;%uH", - (unsigned) instance.config.logo.paddingTop, - (unsigned) instance.config.logo.paddingLeft + (unsigned) options->paddingTop, + (unsigned) options->paddingLeft ); } else { - for (uint32_t i = 0; i < instance.config.logo.paddingTop; ++i) - ffStrbufAppendC(&buf, '\n'); - for (uint32_t i = 0; i < instance.config.logo.paddingLeft; ++i) - ffStrbufAppendC(&buf, ' '); + ffStrbufAppendNC(&buf, options->paddingTop, '\n'); + ffStrbufAppendNC(&buf, options->paddingLeft, ' '); } ffStrbufAppendF(&buf, "\e]1337;File=inline=1:%s\a", base64.chars ); ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); - if (!instance.config.logo.separate) + if (!options->separate) { uint16_t X = 0, Y = 0; const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); @@ -79,40 +78,37 @@ static bool printImageIterm(void) fprintf(stderr, "\nLogo (iterm): fail to query cursor position: %s\n", error); return true; // We already printed image logo, don't print ascii logo then } - instance.state.logoWidth = X + instance.config.logo.paddingRight; + instance.state.logoWidth = X + options->paddingRight; instance.state.logoHeight = Y; fputs("\e[H", stdout); } else { instance.state.logoWidth = instance.state.logoHeight = 0; - ffPrintCharTimes('\n', instance.config.logo.paddingRight); + ffPrintCharTimes('\n', options->paddingRight); } } else { - for (uint32_t i = 0; i < instance.config.logo.paddingTop; ++i) - ffStrbufAppendC(&buf, '\n'); - for (uint32_t i = 0; i < instance.config.logo.paddingLeft; ++i) - ffStrbufAppendC(&buf, ' '); + ffStrbufAppendNC(&buf, options->paddingTop, '\n'); + ffStrbufAppendNC(&buf, options->paddingLeft, ' '); ffStrbufAppendF(&buf, "\e]1337;File=inline=1;width=%u;height=%u;preserveAspectRatio=%u:%s\a\n", - (unsigned) instance.config.logo.width, - (unsigned) instance.config.logo.height, - (unsigned) instance.config.logo.preserveAspectRadio, + (unsigned) options->width, + (unsigned) options->height, + (unsigned) options->preserveAspectRadio, base64.chars ); - if (!instance.config.logo.separate) + if (!options->separate) { - instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; + instance.state.logoWidth = options->width + options->paddingLeft + options->paddingRight; + instance.state.logoHeight = options->paddingTop + options->height; ffStrbufAppendF(&buf, "\e[%uA", (unsigned) instance.state.logoHeight); } else { instance.state.logoWidth = instance.state.logoHeight = 0; - for (uint32_t i = 0; i < instance.config.logo.paddingRight; ++i) - ffStrbufAppendC(&buf, '\n'); + ffStrbufAppendNC(&buf, options->paddingRight, '\n'); } ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &buf); } @@ -122,26 +118,27 @@ static bool printImageIterm(void) static bool printImageKittyDirect(void) { - FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&instance.config.logo.source); + const FFLogoOptions* options = &instance.config.logo; + FF_STRBUF_AUTO_DESTROY base64 = base64Encode(&options->source); - if (!instance.config.logo.width || !instance.config.logo.height) + if (!options->width || !options->height) { - if (!instance.config.logo.separate) + if (!options->separate) { // We must clear the entre screen to make sure that terminal buffer won't scroll up printf("\e[2J\e[3J\e[%u;%uH", - (unsigned) instance.config.logo.paddingTop, - (unsigned) instance.config.logo.paddingLeft + (unsigned) options->paddingTop, + (unsigned) options->paddingLeft ); } else { - ffPrintCharTimes('\n', instance.config.logo.paddingTop); - ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + ffPrintCharTimes('\n', options->paddingTop); + ffPrintCharTimes(' ', options->paddingLeft); } printf("\e_Ga=T,f=100,t=f;%s\e\\", base64.chars); fflush(stdout); - if (!instance.config.logo.separate) + if (!options->separate) { uint16_t X = 0, Y = 0; const char* error = ffGetTerminalResponse("\e[6n", "\e[%hu;%huR", &Y, &X); @@ -150,36 +147,36 @@ static bool printImageKittyDirect(void) fprintf(stderr, "\nLogo (kitty-direct): fail to query cursor position: %s\n", error); return true; // We already printed image logo, don't print ascii logo then } - instance.state.logoWidth = X + instance.config.logo.paddingRight; + instance.state.logoWidth = X + options->paddingRight; instance.state.logoHeight = Y; fputs("\e[H", stdout); } else { instance.state.logoWidth = instance.state.logoHeight = 0; - ffPrintCharTimes('\n', instance.config.logo.paddingRight); + ffPrintCharTimes('\n', options->paddingRight); } } else { - ffPrintCharTimes('\n', instance.config.logo.paddingTop); - ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + ffPrintCharTimes('\n', options->paddingTop); + ffPrintCharTimes(' ', options->paddingLeft); printf("\e_Ga=T,f=100,t=f,c=%u,r=%u;%s\e\\\n", - (unsigned) instance.config.logo.width, - (unsigned) instance.config.logo.height, + (unsigned) options->width, + (unsigned) options->height, base64.chars ); - if (!instance.config.logo.separate) + if (!options->separate) { - instance.state.logoWidth = instance.config.logo.width + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = instance.config.logo.paddingTop + instance.config.logo.height; + instance.state.logoWidth = options->width + options->paddingLeft + options->paddingRight; + instance.state.logoHeight = options->paddingTop + options->height; printf("\e[%uA", (unsigned) instance.state.logoHeight); } else { instance.state.logoWidth = instance.state.logoHeight = 0; - ffPrintCharTimes('\n', instance.config.logo.paddingRight); + ffPrintCharTimes('\n', options->paddingRight); } } @@ -299,22 +296,23 @@ static void writeCacheUint32(FFLogoRequestData* requestData, uint32_t value, con static void printImagePixels(FFLogoRequestData* requestData, const FFstrbuf* result, const char* cacheFileName) { + const FFLogoOptions* options = &instance.config.logo; //Calculate character dimensions - instance.state.logoWidth = requestData->logoCharacterWidth + instance.config.logo.paddingLeft + instance.config.logo.paddingRight; - instance.state.logoHeight = requestData->logoCharacterHeight + instance.config.logo.paddingTop - 1; + instance.state.logoWidth = requestData->logoCharacterWidth + options->paddingLeft + options->paddingRight; + instance.state.logoHeight = requestData->logoCharacterHeight + options->paddingTop - 1; //Write cache files writeCacheStrbuf(requestData, result, cacheFileName); - if(instance.config.logo.width == 0) + if(options->width == 0) writeCacheUint32(requestData, requestData->logoCharacterWidth, FF_CACHE_FILE_WIDTH); - if(instance.config.logo.height == 0) + if(options->height == 0) writeCacheUint32(requestData, requestData->logoCharacterHeight, FF_CACHE_FILE_HEIGHT); //Write result to stdout - ffPrintCharTimes('\n', instance.config.logo.paddingTop); - ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + ffPrintCharTimes('\n', options->paddingTop); + ffPrintCharTimes(' ', options->paddingLeft); fflush(stdout); ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), result); diff --git a/src/logo/logo.c b/src/logo/logo.c index 75a395ae91..8e52f318c9 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -43,10 +43,8 @@ static void ffLogoPrintCharsRaw(const char* data, size_t length) } else { - for (uint32_t i = 0; i < options->paddingTop; ++i) - ffStrbufAppendC(&buf, '\n'); - for (uint32_t i = 0; i < options->paddingLeft; ++i) - ffStrbufAppendC(&buf, ' '); + ffStrbufAppendNC(&buf, options->paddingTop, '\n'); + ffStrbufAppendNC(&buf, options->paddingLeft, ' '); ffStrbufAppendNS(&buf, (uint32_t) length, data); instance.state.logoHeight = options->paddingTop + options->height; instance.state.logoWidth = options->paddingLeft + options->width + options->paddingRight; @@ -106,11 +104,11 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) } //We have an escape sequence direclty as bytes. We print it, but don't increase the line length - if(*data == '\033' && *(data + 1) == '[') + if(*data == '\e' && *(data + 1) == '[') { const char* start = data; - fputs("\033[", stdout); + fputs("\e[", stdout); data += 2; while(isdigit(*data) || *data == ';') From b721f9020e91424bffec3f9fce342d6ef7162174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 15 Sep 2023 11:07:47 +0800 Subject: [PATCH 118/198] Logo (Builtin): improve performance on Windows --- src/logo/logo.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/logo/logo.c b/src/logo/logo.c index 8e52f318c9..e03ba72219 100644 --- a/src/logo/logo.c +++ b/src/logo/logo.c @@ -59,33 +59,35 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) uint32_t currentlineLength = 0; + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048); + if (instance.config.brightColor) - fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT); - ffPrintCharTimes('\n', options->paddingTop); - ffPrintCharTimes(' ', options->paddingLeft); + ffStrbufAppendNC(&result, options->paddingTop, '\n'); + ffStrbufAppendNC(&result, options->paddingLeft, ' '); instance.state.logoHeight = options->paddingTop; //Use logoColor[0] as the default color if(doColorReplacement) - ffPrintColor(&options->colors[0]); + ffStrbufAppendF(&result, "\e[%sm", options->colors[0].chars); while(*data != '\0') { //We are at the end of a line. Print paddings and update max line length if(*data == '\n' || (*data == '\r' && *(data + 1) == '\n')) { - ffPrintCharTimes(' ', options->paddingRight); + ffStrbufAppendNC(&result, options->paddingRight, ' '); //We have \r\n, skip the \r if(*data == '\r') ++data; - putchar('\n'); + ffStrbufAppendC(&result, '\n'); ++data; - ffPrintCharTimes(' ', options->paddingLeft); + ffStrbufAppendNC(&result, options->paddingLeft, ' '); if(currentlineLength > instance.state.logoWidth) instance.state.logoWidth = currentlineLength; @@ -98,7 +100,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) //Always print tabs as 4 spaces, to have consistent spacing if(*data == '\t') { - ffPrintCharTimes(' ', 4); + ffStrbufAppendNC(&result, 4, ' '); ++data; continue; } @@ -108,16 +110,16 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) { const char* start = data; - fputs("\e[", stdout); + ffStrbufAppendS(&result, "\e["); data += 2; while(isdigit(*data) || *data == ';') - putchar(*data++); // number + ffStrbufAppendC(&result, *data++); // number //We have a valid control sequence, print it and continue with next char if(isascii(*data)) { - putchar(*data++); // single letter, end of control sequence + ffStrbufAppendC(&result, *data++); // single letter, end of control sequence continue; } @@ -135,7 +137,7 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) //If we have $$, or $\0, print it as single $ if(*data == '$' || *data == '\0') { - putchar('$'); + ffStrbufAppendC(&result, '$'); ++currentlineLength; ++data; continue; @@ -147,13 +149,13 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) //If the index is valid, print the color. Otherwise continue as normal if(index < 0 || index >= FASTFETCH_LOGO_MAX_COLORS) { - putchar('$'); + ffStrbufAppendC(&result, '$'); ++currentlineLength; //Don't continue here, we want to print the current char as unicode } else { - ffPrintColor(&options->colors[index]); + ffStrbufAppendF(&result, "\e[%sm", options->colors[index].chars); ++data; continue; } @@ -182,11 +184,11 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) if(*data == '\0') break; - putchar(*data++); + ffStrbufAppendC(&result, *data++); } } - fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_RESET); if(!options->separate) { @@ -197,13 +199,15 @@ void ffLogoPrintChars(const char* data, bool doColorReplacement) instance.state.logoWidth += options->paddingLeft + options->paddingRight; //Go to the leftmost position and go up the height - printf("\e[1G\e[%uA", instance.state.logoHeight); + ffStrbufAppendF(&result, "\e[1G\e[%uA", instance.state.logoHeight); } else { instance.state.logoWidth = instance.state.logoHeight = 0; - ffPrintCharTimes('\n', options->paddingRight); + ffStrbufAppendNC(&result, options->paddingRight, '\n'); } + + ffWriteFDBuffer(FFUnixFD2NativeFD(STDOUT_FILENO), &result); } static void logoApplyColors(const FFlogo* logo) From 3c7903cc14f7841848477b1daecde4d27647b49c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 9 Sep 2023 12:01:13 +0800 Subject: [PATCH 119/198] JsonSchema: add `processingTimeout` --- doc/json_schema.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/json_schema.json b/doc/json_schema.json index b07bd08fb3..4151686dc1 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -274,6 +274,11 @@ "type": "integer", "title": "Set the timeout (ms) for WMI queries, `-1` for no timeout. Windows only", "default": 5000 + }, + "processingTimeout": { + "type": "integer", + "title": "Set the timeout (ms) when waiting for child processes, `-1` for no timeout", + "default": 1000 } }, "additionalProperties": false From 24a9231ad0bc1de76161a67f4ec199e04c324b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 15 Sep 2023 20:58:57 +0800 Subject: [PATCH 120/198] Kernel (Windows): remove trailing `\0` --- src/util/platform/FFPlatform_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 0009dd10e7..02389e63b6 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -184,7 +184,7 @@ static void getSystemReleaseAndVersion(FFPlatform* platform) ffStrbufEnsureFree(&platform->systemVersion, 256); bufSize = (DWORD) ffStrbufGetFree(&platform->systemVersion); if(RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, platform->systemVersion.chars, &bufSize) == ERROR_SUCCESS) - platform->systemVersion.length = (uint32_t) bufSize; + platform->systemVersion.length = (uint32_t) bufSize - 1; RegCloseKey(hKey); } From 2082e01555ffa7f290ec7d551066ac76c02492d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 16 Sep 2023 20:36:28 +0800 Subject: [PATCH 121/198] Theme: support JSON format (2) --- src/modules/theme/theme.c | 2 +- src/modules/theme/theme.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/theme/theme.c b/src/modules/theme/theme.c index 08b345fe7b..2fc89549bd 100644 --- a/src/modules/theme/theme.c +++ b/src/modules/theme/theme.c @@ -32,7 +32,7 @@ void ffPrintTheme(FFThemeOptions* options) void ffInitThemeOptions(FFThemeOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme, NULL); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_THEME_MODULE_NAME, ffParseThemeCommandOptions, ffParseThemeJsonObject, ffPrintTheme, ffGenerateThemeJson); ffOptionInitModuleArg(&options->moduleArgs); } diff --git a/src/modules/theme/theme.h b/src/modules/theme/theme.h index ef8f18a796..c0cee8584b 100644 --- a/src/modules/theme/theme.h +++ b/src/modules/theme/theme.h @@ -9,3 +9,4 @@ void ffInitThemeOptions(FFThemeOptions* options); bool ffParseThemeCommandOptions(FFThemeOptions* options, const char* key, const char* value); void ffDestroyThemeOptions(FFThemeOptions* options); void ffParseThemeJsonObject(FFThemeOptions* options, yyjson_val* module); +void ffGenerateThemeJson(FFThemeOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); From 6c1b39ae60778eac5e92b2b6068369ae0475eaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 16 Sep 2023 20:46:49 +0800 Subject: [PATCH 122/198] Shell (FreeBSD): remove trailing `\0` --- src/detection/terminalshell/terminalshell_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 1e1efa4166..957a0b304d 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -56,7 +56,7 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex exe->chars, &size, NULL, 0 )) - exe->length = (uint32_t)size; + exe->length = (uint32_t)size - 1; #endif From fb69d5629721105745c1ba58aceb09405556d053 Mon Sep 17 00:00:00 2001 From: xbt573 <64583541+xbt573@users.noreply.github.com> Date: Sun, 17 Sep 2023 08:09:31 +0300 Subject: [PATCH 123/198] Arguments: handle `--lib-pulse` properly --- src/fastfetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 3b78942d2d..94db3e6663 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1140,7 +1140,7 @@ static void parseOption(FFdata* data, const char* key, const char* value) ffOptionParseString(key, value, &instance.config.libOSMesa); else if(ffStrEqualsIgnCase(subkey, "-opencl")) ffOptionParseString(key, value, &instance.config.libOpenCL); - else if(ffStrEqualsIgnCase(key, "-pulse")) + else if(ffStrEqualsIgnCase(subkey, "-pulse")) ffOptionParseString(key, value, &instance.config.libPulse); else if(ffStrEqualsIgnCase(subkey, "-nm")) ffOptionParseString(key, value, &instance.config.libnm); From fe89e712008d97277478bc03168df9a14385297c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 17 Sep 2023 20:08:46 +0800 Subject: [PATCH 124/198] Disk (Linux): try fixing zpool detection Ref: #559 --- src/detection/disk/disk.h | 1 + src/detection/disk/disk_bsd.c | 1 + src/detection/disk/disk_linux.c | 150 +++++++++++++------------------- src/modules/disk/disk.c | 24 +++-- 4 files changed, 78 insertions(+), 98 deletions(-) diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index fced34a92f..3ccab52c4f 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -7,6 +7,7 @@ typedef struct FFDisk { + FFstrbuf mountFrom; FFstrbuf mountpoint; FFstrbuf filesystem; FFstrbuf name; diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index efe98db9b1..827ec32c28 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -78,6 +78,7 @@ const char* ffDetectDisksImpl(FFlist* disks) disk->filesTotal = (uint32_t) fs->f_files; disk->filesUsed = (uint32_t) (disk->filesTotal - (uint64_t)fs->f_ffree); + ffStrbufInitS(&disk->mountFrom, fs->f_mntfromname); ffStrbufInitS(&disk->mountpoint, fs->f_mntonname); ffStrbufInitS(&disk->filesystem, fs->f_fstypename); ffStrbufInit(&disk->name); diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index fb5597baa3..0460cdfd17 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #ifdef __USE_LARGEFILE64 #define stat stat64 @@ -15,74 +17,45 @@ #define readdir readdir64 #endif -static bool isPhysicalDevice(FFstrbuf* device) +static bool isPhysicalDevice(const struct mntent* device) { #ifndef __ANDROID__ //On Android, `/dev` is not accessable, so that the following checks always fail - //https://askubuntu.com/a/1289123 - if(ffStrbufEqualS(device, "/cow")) + //Always show the root path + if(ffStrEquals(device->mnt_dir, "/")) return true; //DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem. - if(ffStrbufEqualS(device, "drvfs")) + if(ffStrEquals(device->mnt_fsname, "drvfs")) return true; - //ZFS root pool. The format is rpool/// - if(ffStrbufStartsWithS(device, "rpool/")) + //ZFS pool + if(ffStrEquals(device->mnt_type, "zfs")) return true; + //Pseudo filesystems don't have a device in /dev + if(!ffStrStartsWith(device->mnt_fsname, "/dev/")) + return false; + + if( + ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices + ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices + ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices + ) return false; + struct stat deviceStat; - if(stat(device->chars, &deviceStat) != 0) + if(stat(device->mnt_fsname, &deviceStat) != 0) return false; //Ignore all devices that are not block devices if(!S_ISBLK(deviceStat.st_mode)) return false; - //Pseudo filesystems don't have a device in /dev - if(!ffStrbufStartsWithS(device, "/dev/")) - return false; - #endif // __ANDROID__ - if( - ffStrbufStartsWithS(device, "/dev/loop") || //Ignore loop devices - ffStrbufStartsWithS(device, "/dev/ram") || //Ignore ram devices - ffStrbufStartsWithS(device, "/dev/fd") //Ignore fd devices - ) return false; - return true; } -static void appendNextEntry(FFstrbuf* buffer, char** source) -{ - //Read the current entry into the buffer - while(**source != '\0' && !isspace(**source)) - { - //After a backslash the next 3 characters are octal ascii codes - if(**source == '\\' && strnlen(*source, 4) == 4) - { - char octal[4] = {0}; - strncpy(octal, *source + 1, 3); - - long value = strtol(octal, NULL, 8); //Returns 0 on error, so no need to check endptr - if(value > 0 && value < CHAR_MAX) - { - ffStrbufAppendC(buffer, (char) value); - *source += 4; - continue; - } - } - - ffStrbufAppendC(buffer, **source); - ++*source; - } - - //Skip whitespace - while(isspace(**source)) - ++*source; -} - static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFstrbuf* basePath) { DIR* dir = opendir(basePath->chars); @@ -114,10 +87,10 @@ static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFst closedir(dir); } -static void detectName(FFDisk* disk, const FFstrbuf* device) +static void detectName(FFDisk* disk, const struct mntent* device) { struct stat deviceStat; - if(stat(device->chars, &deviceStat) != 0) + if(stat(device->mnt_fsname, &deviceStat) != 0) return; FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreate(); @@ -133,6 +106,8 @@ static void detectName(FFDisk* disk, const FFstrbuf* device) detectNameFromPath(disk, &deviceStat, &basePath); } + if (disk->name.length == 0) return; + // Basic\x20data\x20partition for (uint32_t i = ffStrbufFirstIndexS(&disk->name, "\\x"); i != disk->name.length; @@ -164,35 +139,46 @@ static void detectType(FF_MAYBE_UNUSED const FFlist* devices, FFDisk* currentDis #else -static bool isSubvolume(const FFlist* devices) +static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) { - const FFstrbuf* current = ffListGet(devices, devices->length - 1); - - if(ffStrbufEqualS(current, "drvfs")) // WSL Windows drives + if(ffStrbufEqualS(¤tDisk->mountFrom, "drvfs")) // WSL Windows drives return false; //Filter all disks which device was already found. This catches BTRFS subvolumes. - for(uint32_t i = 0; i < devices->length - 1; i++) + for(uint32_t i = 0; i < disks->length - 1; i++) { - const FFstrbuf* otherDevice = ffListGet(devices, i); + const FFDisk* otherDevice = ffListGet(disks, i); - if(ffStrbufEqual(current, otherDevice)) + if(ffStrbufEqual(¤tDisk->mountFrom, &otherDevice->mountFrom)) return true; } - //ZFS subvolumes: rpool///. - //Test if the third slash is present. - if(ffStrbufStartsWithS(current, "rpool/") && ffStrHasNChars(current->chars, '/', 3)) - return true; + if(ffStrbufEqualS(¤tDisk->filesystem, "zfs")) + { + //ZFS subvolumes + uint32_t index = ffStrbufFirstIndexC(¤tDisk->filesystem, '/'); + if (index == currentDisk->filesystem.length) + return false; + + FF_STRBUF_AUTO_DESTROY zpoolName = ffStrbufCreateNS(index, currentDisk->filesystem.chars); + for(uint32_t i = 0; i < disks->length - 1; i++) + { + const FFDisk* otherDevice = ffListGet(disks, i); + if(ffStrbufEqualS(&otherDevice->filesystem, "zfs") && ffStrbufStartsWith(&otherDevice->mountFrom, &zpoolName)) + return true; + } + + return false; + } return false; } -static void detectType(const FFlist* devices, FFDisk* currentDisk, const char* options) +static void detectType(const FFlist* disks, FFDisk* currentDisk, const struct mntent* options) { - if(isSubvolume(devices)) + if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; - else if(strstr(options, "nosuid") != NULL || strstr(options, "nodev") != NULL) + else if(strstr(options->mnt_opts, MNTOPT_NOSUID) != NULL || strstr(options->mnt_opts, "nodev") != NULL) currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; @@ -222,61 +208,43 @@ static void detectStats(FFDisk* disk) const char* ffDetectDisksImpl(FFlist* disks) { - FILE* mountsFile = fopen("/proc/mounts", "r"); + FILE* mountsFile = setmntent("/proc/mounts", "r"); if(mountsFile == NULL) - return "fopen(\"/proc/mounts\", \"r\") == NULL"; + return "setmntent(\"/proc/mounts\", \"r\") == NULL"; FF_LIST_AUTO_DESTROY devices = ffListCreate(sizeof(FFstrbuf)); - char* line = NULL; - size_t len = 0; + struct mntent* device; - while(getline(&line, &len, mountsFile) != EOF) + while((device = getmntent(mountsFile))) { - //Format of the file: " ..." (Same as fstab) - char* currentPos = line; - - //detect device - FFstrbuf* device = ffListAdd(&devices); - ffStrbufInit(device); - appendNextEntry(device, ¤tPos); - if(!isPhysicalDevice(device)) - { - ffStrbufDestroy(device); - devices.length--; continue; - } //We have a valid device, add it to the list FFDisk* disk = ffListAdd(disks); + //detect mountFrom + ffStrbufInitS(&disk->mountFrom, device->mnt_fsname); + //detect mountpoint - ffStrbufInit(&disk->mountpoint); - appendNextEntry(&disk->mountpoint, ¤tPos); + ffStrbufInitS(&disk->mountpoint, device->mnt_dir); //detect filesystem - ffStrbufInit(&disk->filesystem); - appendNextEntry(&disk->filesystem, ¤tPos); + ffStrbufInitS(&disk->filesystem, device->mnt_type); //detect name ffStrbufInit(&disk->name); detectName(disk, device); //detect type - detectType(&devices, disk, currentPos); + detectType(disks, disk, device); //Detects stats detectStats(disk); } - if(line != NULL) - free(line); - - FF_LIST_FOR_EACH(FFstrbuf, device, devices) - ffStrbufDestroy(device); - - fclose(mountsFile); + endmntent(mountsFile); return NULL; } diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 4f74a380af..0dcd6d97ce 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -194,6 +194,7 @@ void ffPrintDisk(FFDiskOptions* options) FF_LIST_FOR_EACH(FFDisk, disk, disks) { + ffStrbufDestroy(&disk->mountFrom); ffStrbufDestroy(&disk->mountpoint); ffStrbufDestroy(&disk->filesystem); ffStrbufDestroy(&disk->name); @@ -387,16 +388,24 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ FF_LIST_FOR_EACH(FFDisk, item, disks) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - yyjson_mut_obj_add_uint(doc, obj, "bytesAvailable", item->bytesAvailable); - yyjson_mut_obj_add_uint(doc, obj, "bytesFree", item->bytesFree); - yyjson_mut_obj_add_uint(doc, obj, "bytesTotal", item->bytesTotal); - yyjson_mut_obj_add_uint(doc, obj, "bytesUsed", item->bytesUsed); - yyjson_mut_obj_add_uint(doc, obj, "filesTotal", item->filesTotal); - yyjson_mut_obj_add_uint(doc, obj, "filesUsed", item->filesUsed); - yyjson_mut_obj_add_strbuf(doc, obj, "filesystem", &item->filesystem); + + yyjson_mut_val* bytes = yyjson_mut_obj_add_obj(doc, obj, "bytes"); + yyjson_mut_obj_add_uint(doc, bytes, "available", item->bytesAvailable); + yyjson_mut_obj_add_uint(doc, bytes, "free", item->bytesFree); + yyjson_mut_obj_add_uint(doc, bytes, "total", item->bytesTotal); + yyjson_mut_obj_add_uint(doc, bytes, "used", item->bytesUsed); + + yyjson_mut_val* files = yyjson_mut_obj_add_obj(doc, obj, "files"); + yyjson_mut_obj_add_uint(doc, files, "total", item->filesTotal); + yyjson_mut_obj_add_uint(doc, files, "used", item->filesUsed); + + yyjson_mut_obj_add_strbuf(doc, files, "filesystem", &item->filesystem); yyjson_mut_obj_add_strbuf(doc, obj, "mountpoint", &item->mountpoint); + yyjson_mut_obj_add_strbuf(doc, obj, "mountFrom", &item->mountFrom); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); yyjson_mut_val* typeArr = yyjson_mut_obj_add_arr(doc, obj, "type"); + if(item->type & FF_DISK_VOLUME_TYPE_REGULAR_BIT) + yyjson_mut_arr_add_str(doc, typeArr, "Regular"); if(item->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT) yyjson_mut_arr_add_str(doc, typeArr, "External"); if(item->type & FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT) @@ -410,6 +419,7 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ FF_LIST_FOR_EACH(FFDisk, item, disks) { ffStrbufDestroy(&item->mountpoint); + ffStrbufDestroy(&item->mountFrom); ffStrbufDestroy(&item->filesystem); ffStrbufDestroy(&item->name); } From b54e182c0f4f181368dc83bafc59a708cbe1fffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 17 Sep 2023 20:41:07 +0800 Subject: [PATCH 125/198] Disk (Windows): detect volume name --- src/detection/disk/disk_windows.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index 5b3b39232e..dacf5ba94b 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -25,6 +25,12 @@ const char* ffDetectDisksImpl(FFlist* disks) FFDisk* disk = ffListAdd(disks); ffStrbufInitWS(&disk->mountpoint, mountpoint); + wchar_t volumeName[64]; + if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName))) + ffStrbufInitWS(&disk->mountFrom, volumeName); + else + ffStrbufInit(&disk->mountFrom); + if(!GetDiskFreeSpaceExW( mountpoint, (PULARGE_INTEGER)&disk->bytesAvailable, From d8e4575157734fc14127e9131be107afedccf6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 17 Sep 2023 22:28:03 +0800 Subject: [PATCH 126/198] Disk (Linux): fix ZFS subvolume detection --- src/detection/disk/disk_linux.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 0460cdfd17..91a7478dc3 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -144,23 +144,14 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) if(ffStrbufEqualS(¤tDisk->mountFrom, "drvfs")) // WSL Windows drives return false; - //Filter all disks which device was already found. This catches BTRFS subvolumes. - for(uint32_t i = 0; i < disks->length - 1; i++) - { - const FFDisk* otherDevice = ffListGet(disks, i); - - if(ffStrbufEqual(¤tDisk->mountFrom, &otherDevice->mountFrom)) - return true; - } - if(ffStrbufEqualS(¤tDisk->filesystem, "zfs")) { //ZFS subvolumes - uint32_t index = ffStrbufFirstIndexC(¤tDisk->filesystem, '/'); - if (index == currentDisk->filesystem.length) + uint32_t index = ffStrbufFirstIndexC(¤tDisk->mountFrom, '/'); + if (index == currentDisk->mountFrom.length) return false; - FF_STRBUF_AUTO_DESTROY zpoolName = ffStrbufCreateNS(index, currentDisk->filesystem.chars); + FF_STRBUF_AUTO_DESTROY zpoolName = ffStrbufCreateNS(index, currentDisk->mountFrom.chars); for(uint32_t i = 0; i < disks->length - 1; i++) { const FFDisk* otherDevice = ffListGet(disks, i); @@ -170,6 +161,17 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) return false; } + else + { + //Filter all disks which device was already found. This catches BTRFS subvolumes. + for(uint32_t i = 0; i < disks->length - 1; i++) + { + const FFDisk* otherDevice = ffListGet(disks, i); + + if(ffStrbufEqual(¤tDisk->mountFrom, &otherDevice->mountFrom)) + return true; + } + } return false; } From 2bb78af1a70c75d0b5d396d60e125f5bc1638172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 00:14:05 +0800 Subject: [PATCH 127/198] Disk (Linux): detect USB devices as external volumes only Fixes #559 --- src/detection/disk/disk_linux.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 91a7478dc3..ab328ac24f 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -87,13 +87,17 @@ static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFst closedir(dir); } -static void detectName(FFDisk* disk, const struct mntent* device) +static void detectName(FFDisk* disk) { struct stat deviceStat; - if(stat(device->mnt_fsname, &deviceStat) != 0) + if(stat(disk->mountFrom.chars, &deviceStat) != 0) return; - FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreate(); + //Detect external devices. Code is put here to reuse deviceStat + FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreateS("/dev/disk/by-id/"); + detectNameFromPath(disk, &deviceStat, &basePath); + disk->type = ffStrbufStartsWithS(&disk->name, "usb-") ? FF_DISK_VOLUME_TYPE_EXTERNAL_BIT : FF_DISK_VOLUME_TYPE_NONE; + ffStrbufClear(&disk->name); //Try label first ffStrbufSetS(&basePath, "/dev/disk/by-label/"); @@ -176,12 +180,10 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) return false; } -static void detectType(const FFlist* disks, FFDisk* currentDisk, const struct mntent* options) +static void detectType(const FFlist* disks, FFDisk* currentDisk) { if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; - else if(strstr(options->mnt_opts, MNTOPT_NOSUID) != NULL || strstr(options->mnt_opts, "nodev") != NULL) - currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; else @@ -237,10 +239,11 @@ const char* ffDetectDisksImpl(FFlist* disks) //detect name ffStrbufInit(&disk->name); - detectName(disk, device); + detectName(disk); // Also detects external devices //detect type - detectType(disks, disk, device); + if (disk->type == FF_DISK_VOLUME_TYPE_NONE) + detectType(disks, disk); //Detects stats detectStats(disk); From bdc79a29957851ab227b5ea2294fccef94ff4279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 00:15:15 +0800 Subject: [PATCH 128/198] Doc: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index daa8255101..8bfe24e1dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ Bugfixes: * Fix short read when reading from stdin (Logo) * Fix `poll() timeout or failed` error when image is very large (Logo) * Fix Termux Monet terminal version detection (Terminal) +* Fix zpool volumes detection (Disk, Linux) +* Fix external volumes detection (Disk, Linux) Logo: * Add Afterglow From b4f063e1daf0033071122566c03b2a0f30daea5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 09:45:21 +0800 Subject: [PATCH 129/198] Disk (Linux): detect external disk more accurately --- src/detection/disk/disk_linux.c | 50 +++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index ab328ac24f..7ab1180386 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -1,5 +1,6 @@ #include "disk.h" +#include "common/io/io.h" #include "util/stringUtils.h" #include @@ -58,7 +59,7 @@ static bool isPhysicalDevice(const struct mntent* device) static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFstrbuf* basePath) { - DIR* dir = opendir(basePath->chars); + FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath->chars); if(dir == NULL) return; @@ -83,8 +84,6 @@ static void detectNameFromPath(FFDisk* disk, const struct stat* deviceStat, FFst ffStrbufAppendS(&disk->name, entry->d_name); break; } - - closedir(dir); } static void detectName(FFDisk* disk) @@ -93,8 +92,11 @@ static void detectName(FFDisk* disk) if(stat(disk->mountFrom.chars, &deviceStat) != 0) return; - //Detect external devices. Code is put here to reuse deviceStat - FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreateS("/dev/disk/by-id/"); + FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreate(); + + //Detect USB devices. Code is put here to reuse deviceStat + //https://stackoverflow.com/a/73302717 + ffStrbufAppendS(&basePath, "/dev/disk/by-id/"); detectNameFromPath(disk, &deviceStat, &basePath); disk->type = ffStrbufStartsWithS(&disk->name, "usb-") ? FF_DISK_VOLUME_TYPE_EXTERNAL_BIT : FF_DISK_VOLUME_TYPE_NONE; ffStrbufClear(&disk->name); @@ -180,9 +182,45 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) return false; } +static bool isRemovable(FFDisk* currentDisk) +{ + // https://stackoverflow.com/a/73302025 + // Note my USB mobile hard disk isn't detected as removable, but my USB flash disk does. + // USB devices should be handled in detectName + FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreateS("/sys/block/"); + + FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath.chars); + if(dir == NULL) + return false; + + uint32_t index = ffStrbufLastIndexC(¤tDisk->mountFrom, '/'); + const char* partitionName = index == currentDisk->mountFrom.length ? NULL : currentDisk->mountFrom.chars + index + 1; + if (!partitionName || !*partitionName) return false; + + struct dirent* entry; + while((entry = readdir(dir)) != NULL) + { + if(entry->d_name[0] == '.') + continue; + + if (!ffStrStartsWith(partitionName, entry->d_name)) continue; + + // /sys/block/sdx/removable + ffStrbufAppendS(&basePath, entry->d_name); + ffStrbufAppendS(&basePath, "/removable"); + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1"); + } + + return false; +} + static void detectType(const FFlist* disks, FFDisk* currentDisk) { - if(isSubvolume(disks, currentDisk)) + if(isRemovable(currentDisk)) + currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; + else if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; else if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; From 939165d4cf71a282d200d274e8f837fd1a1a00ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 13:52:25 +0800 Subject: [PATCH 130/198] Platform: align logic of getting host name to neofetch Fixes: #561 --- src/modules/separator/separator.c | 2 +- src/modules/title/title.c | 12 ++++----- src/util/platform/FFPlatform.c | 5 ---- src/util/platform/FFPlatform.h | 1 - src/util/platform/FFPlatform_unix.c | 36 +------------------------- src/util/platform/FFPlatform_windows.c | 11 ++++---- 6 files changed, 13 insertions(+), 54 deletions(-) diff --git a/src/modules/separator/separator.c b/src/modules/separator/separator.c index fa2161228f..555bb2a04c 100644 --- a/src/modules/separator/separator.c +++ b/src/modules/separator/separator.c @@ -29,7 +29,7 @@ void ffPrintSeparator(FFSeparatorOptions* options) uint32_t titleLength = 1 // @ + getWcsWidth(&platform->userName, wstr, &state) // user name - + (fqdn ? platform->domainName.length : platform->hostName.length); // host name + + (fqdn ? platform->hostName.length : ffStrbufFirstIndexC(&platform->hostName, '.')); // host name ffLogoPrintLine(); if(options->string.length == 0) diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 7cfd087bef..3399f3c204 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -23,9 +23,10 @@ static inline void printTitlePart(const FFstrbuf* content, const FFstrbuf* color void ffPrintTitle(FFTitleOptions* options) { - FFstrbuf* host = options->fqdn ? - &instance.state.platform.domainName : - &instance.state.platform.hostName; + FF_STRBUF_AUTO_DESTROY hostName = ffStrbufCreateCopy(&instance.state.platform.hostName); + + if (!options->fqdn) + ffStrbufSubstrBeforeFirstC(&hostName, '.'); if (options->moduleArgs.outputFormat.length == 0) { @@ -37,14 +38,14 @@ void ffPrintTitle(FFTitleOptions* options) ffPrintColor(&options->colorAt); putchar('@'); - printTitlePart(host, &options->colorHost); + printTitlePart(&hostName, &options->colorHost); putchar('\n'); } else { ffPrintFormat(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_TITLE_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.userName}, - {FF_FORMAT_ARG_TYPE_STRBUF, host}, + {FF_FORMAT_ARG_TYPE_STRBUF, &hostName}, }); } } @@ -147,7 +148,6 @@ void ffGenerateTitleJson(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_mut_doc yyjson_mut_obj_add_strbuf(doc, obj, "userName", &instance.state.platform.userName); yyjson_mut_obj_add_strbuf(doc, obj, "homeDir", &instance.state.platform.homeDir); yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &instance.state.platform.hostName); - yyjson_mut_obj_add_strbuf(doc, obj, "domainName", &instance.state.platform.domainName); yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &instance.state.platform.exePath); yyjson_mut_obj_add_strbuf(doc, obj, "userShell", &instance.state.platform.userShell); } diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index ad0a179da8..baa69e1e1f 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -12,7 +12,6 @@ void ffPlatformInit(FFPlatform* platform) ffStrbufInit(&platform->userName); ffStrbufInit(&platform->hostName); - ffStrbufInit(&platform->domainName); ffStrbufInit(&platform->userShell); ffStrbufInit(&platform->systemName); @@ -22,9 +21,6 @@ void ffPlatformInit(FFPlatform* platform) ffPlatformInitImpl(platform); - if(platform->domainName.length == 0) - ffStrbufAppend(&platform->domainName, &platform->hostName); - if(platform->systemName.length == 0) { #if defined(__linux__) @@ -59,7 +55,6 @@ void ffPlatformDestroy(FFPlatform* platform) ffStrbufDestroy(&platform->userName); ffStrbufDestroy(&platform->hostName); - ffStrbufDestroy(&platform->domainName); ffStrbufDestroy(&platform->userShell); ffStrbufDestroy(&platform->systemArchitecture); diff --git a/src/util/platform/FFPlatform.h b/src/util/platform/FFPlatform.h index fa646f9deb..536b09aed0 100644 --- a/src/util/platform/FFPlatform.h +++ b/src/util/platform/FFPlatform.h @@ -15,7 +15,6 @@ typedef struct FFPlatform { FFstrbuf userName; FFstrbuf hostName; - FFstrbuf domainName; FFstrbuf userShell; FFstrbuf systemName; diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 3f7aada12d..2c9b0f4c6e 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -141,37 +141,8 @@ static void getUserName(FFPlatform* platform, const struct passwd* pwd) static void getHostName(FFPlatform* platform, const struct utsname* uts) { - char hostname[256]; - if(gethostname(hostname, sizeof(hostname)) == 0) - ffStrbufAppendS(&platform->hostName, hostname); - - if(platform->hostName.length == 0) - ffStrbufAppendS(&platform->hostName, uts->nodename); -} - -#ifdef __linux__ -#include -static void getDomainName(FFPlatform* platform) -{ - struct addrinfo hints = {0}; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_CANONNAME; - - struct addrinfo* info = NULL; - - if(getaddrinfo(platform->hostName.chars, "80", &hints, &info) != 0) - return; - - struct addrinfo* current = info; - while(platform->domainName.length == 0 && current != NULL) - { - ffStrbufAppendS(&platform->domainName, current->ai_canonname); - current = current->ai_next; - } - - freeaddrinfo(info); + ffStrbufAppendS(&platform->hostName, uts->nodename); } -#endif static void getUserShell(FFPlatform* platform, const struct passwd* pwd) { @@ -198,11 +169,6 @@ void ffPlatformInitImpl(FFPlatform* platform) getUserName(platform, pwd); getHostName(platform, &uts); - - #ifdef __linux__ - getDomainName(platform); - #endif - getUserShell(platform, pwd); ffStrbufAppendS(&platform->systemName, uts.sysname); diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 02389e63b6..fea0c26c62 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -130,12 +130,11 @@ static void getHostName(FFPlatform* platform) ffStrbufSetWS(&platform->hostName, buffer); } -static void getDomainName(FFPlatform* platform) +static void getUserShell(FFPlatform* platform) { - wchar_t buffer[128]; - DWORD len = sizeof(buffer) / sizeof(*buffer); - if(GetComputerNameExW(ComputerNameDnsDomain, buffer, &len)) - ffStrbufSetWS(&platform->domainName, buffer); + // Works in MSYS2 + ffStrbufAppendS(&platform->userShell, getenv("SHELL")); + ffStrbufReplaceAllC(&platform->userShell, '\\', '/'); } static void getSystemName(FFPlatform* platform) @@ -233,7 +232,7 @@ void ffPlatformInitImpl(FFPlatform* platform) getUserName(platform); getHostName(platform); - getDomainName(platform); + getUserShell(platform); getSystemName(platform); getSystemReleaseAndVersion(platform); From 7cd79d34bb8a32ab538c74e4b3c1ad813a083127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 14:19:19 +0800 Subject: [PATCH 131/198] Presets: remove `devinfo` and `verbose` --- CHANGELOG.md | 2 ++ presets/devinfo | 3 --- presets/devinfo-verbose | 3 --- presets/devinfo.jsonc | 49 ----------------------------------------- presets/verbose | 31 -------------------------- 5 files changed, 2 insertions(+), 86 deletions(-) delete mode 100644 presets/devinfo delete mode 100644 presets/devinfo-verbose delete mode 100644 presets/devinfo.jsonc delete mode 100644 presets/verbose diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfe24e1dd..b68905ceeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Changes: * Users module detects and prints user login time by default. Specifying `--users-compact` to disable it * Fastfetch now requires yyjson 0.8.0 or later, which is embeded in fastfetch source tree. If you build fastfetch with `-DENABLE_SYSTEM_YYJSON` cmake option, you must upgrade your yyjson package * Reduced information supported by `--terminal-format`, `--shell-format` +* Some config presets (`devinfo` and `verbose`) are obseleted and removed. They are barely maintained and can be replaced with `--format json` now. Features: * Add `--format json`, which prints system information as JSON format @@ -18,6 +19,7 @@ Features: * Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows) Bugfixes: +* Fix fastfetch hanging in specific environment (#561) * Fix `fastfetch --config verbose` doesn't work (#547) * Fix short read when reading from stdin (Logo) * Fix `poll() timeout or failed` error when image is very large (Logo) diff --git a/presets/devinfo b/presets/devinfo deleted file mode 100644 index 2ddf030b58..0000000000 --- a/presets/devinfo +++ /dev/null @@ -1,3 +0,0 @@ ---disable-linewrap false ---multithreading false ---show-errors diff --git a/presets/devinfo-verbose b/presets/devinfo-verbose deleted file mode 100644 index 6f79f97e78..0000000000 --- a/presets/devinfo-verbose +++ /dev/null @@ -1,3 +0,0 @@ ---load-config devinfo ---load-config all ---load-config verbose diff --git a/presets/devinfo.jsonc b/presets/devinfo.jsonc deleted file mode 100644 index 450adb9262..0000000000 --- a/presets/devinfo.jsonc +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", - "logo": { - "type": "builtin", - "source": "arch" - }, - "display": { - "disableLinewrap": false, - "showErrors": true - }, - "general": { - "multithreading": false - }, - "modules": [ - "title", - "separator", - { - "type": "os", - "format": "Arch Linux ({12})" - }, - "host", - "kernel", - "uptime", - { - "type": "packages", - "format": "{} (pacman)" - }, - "shell", - "display", - "de", - "wm", - "wmtheme", - "theme", - "icons", - "font", - "cursor", - "terminal", - "terminalfont", - "cpu", - "gpu", - "memory", - "disk", - "battery", - "poweradapter", - "locale", - "break", - "colors" - ] -} diff --git a/presets/verbose b/presets/verbose deleted file mode 100644 index 44c0c3ee95..0000000000 --- a/presets/verbose +++ /dev/null @@ -1,31 +0,0 @@ ---os-format System: {}; Name: {}; Pretty name: {}; ID: {}; ID like: {}; Variant: {}; Variant ID: {}; Version: {}; Version ID: {}; Version codename: {}; Build ID: {}; Architecture: {} ---host-format Family: product_family: {}; product_name: {}; product_version: {}; product_sku: {}; sys_vendor: {} ---kernel-format Sysname: {}; Release: {}; Version: {} ---uptime-format Days: {}; Hours: {}; Minutes: {}; Seconds: {} ---processes-format Count: {} ---packages-format All: {}; pacman: {}; pacman branch: {}; dpkg: {}; rpm: {}; emerge: {}; eopkg: {}; xbps: {}; apk: {}; flatpak-system: {}; flatpak-user: {}; snap: {}; brew: {}; brew-cask: {}; port: {}; scoop: {}; choco: {}; pkgtool: {}; paludis {} ---shell-format Process name: {}; Process path: {}; Process exe: {}; Process version: {}; User path: {}; User exe: {}; User version: {} ---display-format Width: {}; Height: {}; Refresh rate: {}; ScaledWith: {}; ScaledHeight: {} ---de-format Process name: {}; Pretty name: {}; Version: {} ---wm-format Process name: {}; Pretty name: {}; Protocol: {} ---wmtheme-format Name: {} ---theme-format Plasma: {}; Plasma colors: {}; Plasma colors pretty: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {} ---icons-format Plasma: {}; GTK2: {}; GTK3: {}; GTK4: {}; GTK: {} ---font-format Font1: {}; Font2: {}; Font3: {}; Font4: {} ---cursor-format Theme: {}; Size: {} ---terminal-format Process: {}; Path: {}; Exe: {} ---terminalfont-format Pretty: {}; Name: {}; Size: {}; Styles: {} ---cpu-format Name: {}, Vendor: {}, CoresPhysical: {}, CoresLogical: {}, CoresOnline: {}, FrequencyMin: {}, FrequencyMax: {}, Temperature: {} ---cpuusage-format Percentage: {} ---gpu-format Vendor: {}; Name: {}; Driver: {}; Temperature: {}; CoreCount: {}; Type: {} ---memory-format Used: {}; Total: {}; Percentage: {} ---disk-format SizeUsed: {}; SizeTotal: {}; SizePercentage: {}; FilesUsed: {}; FilesTotal: {}; FilesPercentage: {}; External: {}; Hidden: {}; Filesystem: {}; Name: {} ---battery-format Manufactor: {}; Model: {}; Technology: {}; Capacity: {}; Status: {} ---poweradapter-format Watts: {}; Name: {}; Manufactor: {}; Model: {}; Description: {} ---player-format Pretty: {}; Name: {}; Bus: {}; Url: {} ---media-format Pretty: {}; Name: {}; Artist: {}; Album: {} ---datetime-format year: {}; yearShort: {}; month: {}; monthPretty: {}; monthName: {}; monthNameShort: {}; weekNumber: {}; weekday: {}; weekdayShort: {}; dayInYear: {}; dayInMonth: {}; dayInWeek: {}; hour: {}; hourPretty: {}; hour12: {}; hour12Pretty: {}; minute: {}; minutePretty: {}; second: {}; secondPretty: {} ---vulkan-format driver: {}; Api Version: {}; Conformance Version: {} ---opengl-format version: {}; renderer: {}; vendor: {} ---opencl-format version: {}; device: {}; vendor: {} ---bluetooth-format Name: {}; Address: {}; Type: {}; Battery: {} From 7f727086af84669728563766fd45169db63bde53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 20:01:41 +0800 Subject: [PATCH 132/198] Disk: move filesystem outside of files (JSON format) --- src/modules/disk/disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 0dcd6d97ce..3698afa19a 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -399,7 +399,7 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ yyjson_mut_obj_add_uint(doc, files, "total", item->filesTotal); yyjson_mut_obj_add_uint(doc, files, "used", item->filesUsed); - yyjson_mut_obj_add_strbuf(doc, files, "filesystem", &item->filesystem); + yyjson_mut_obj_add_strbuf(doc, obj, "filesystem", &item->filesystem); yyjson_mut_obj_add_strbuf(doc, obj, "mountpoint", &item->mountpoint); yyjson_mut_obj_add_strbuf(doc, obj, "mountFrom", &item->mountFrom); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); From 8a14cbae0c3f9bc28ab795c9e0e9c140ba998740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 20:12:33 +0800 Subject: [PATCH 133/198] JSON: don't print the non-standand `NaN` --- src/fastfetch.c | 2 +- src/modules/cpu/cpu.c | 5 +---- src/modules/gpu/gpu.c | 5 +---- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 94db3e6663..6fcef48100 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -1274,7 +1274,7 @@ int main(int argc, const char** argv) if (instance.state.resultDoc) { - yyjson_mut_write_fp(stdout, instance.state.resultDoc, YYJSON_WRITE_ALLOW_INF_AND_NAN | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL); + yyjson_mut_write_fp(stdout, instance.state.resultDoc, YYJSON_WRITE_INF_AND_NAN_AS_NULL | YYJSON_WRITE_PRETTY_TWO_SPACES, NULL, NULL); } ffFinish(); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 1825747e40..644cda9f4c 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -157,10 +157,7 @@ void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va yyjson_mut_obj_add_uint(doc, obj, "coresOnline", cpu.coresOnline); yyjson_mut_obj_add_real(doc, obj, "frequencyMin", cpu.frequencyMin); yyjson_mut_obj_add_real(doc, obj, "frequencyMax", cpu.frequencyMax); - if (cpu.temperature == cpu.temperature) - yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); - else - yyjson_mut_obj_add_null(doc, obj, "temperature"); + yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); } ffStrbufDestroy(&cpu.name); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 4bf6726ad4..95a25df3b1 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -256,10 +256,7 @@ void ffGenerateGPUJson(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va else yyjson_mut_obj_add_null(doc, sharedObj, "used"); - if (gpu->temperature == gpu->temperature) - yyjson_mut_obj_add_real(doc, obj, "temperature", gpu->temperature); - else - yyjson_mut_obj_add_null(doc, obj, "temperature"); + yyjson_mut_obj_add_null(doc, obj, "temperature"); const char* type; switch (gpu->type) From 8edb7d3833a62f39d5709f7afbdf1ed57e1d9722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 20:45:23 +0800 Subject: [PATCH 134/198] Logo: fix Windows 11_small --- src/logo/ascii/windows_11_small.txt | 14 ++++++-------- src/logo/builtin.c | 3 +++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/logo/ascii/windows_11_small.txt b/src/logo/ascii/windows_11_small.txt index c04184f246..ee78eb35ab 100644 --- a/src/logo/ascii/windows_11_small.txt +++ b/src/logo/ascii/windows_11_small.txt @@ -1,9 +1,7 @@ -$1lllllllll $2lllllllll -$1lllllllll $2lllllllll -$1lllllllll $2lllllllll -$1lllllllll $2lllllllll +$1lllllll $2lllllll +$1lllllll $2lllllll +$1lllllll $2lllllll -$3lllllllll $4lllllllll -$3lllllllll $4lllllllll -$3lllllllll $4lllllllll -$3lllllllll $4lllllllll +$3lllllll $4lllllll +$3lllllll $4lllllll +$3lllllll $4lllllll diff --git a/src/logo/builtin.c b/src/logo/builtin.c index dce999e908..5bbb455f1f 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -4066,6 +4066,9 @@ static const FFlogo W[] = { .lines = FASTFETCH_DATATEXT_LOGO_WINDOWS_11_SMALL, .colors = { FF_COLOR_FG_BLUE, + FF_COLOR_FG_BLUE, + FF_COLOR_FG_BLUE, + FF_COLOR_FG_BLUE, }, .colorKeys = FF_COLOR_FG_YELLOW, .colorTitle = FF_COLOR_FG_CYAN, From 06b1051a7e620e86803037cb9f9191b6bef568cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 20:46:30 +0800 Subject: [PATCH 135/198] Global: don't trim custom strings It can be useful to align separators --- src/common/format.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/common/format.c b/src/common/format.c index 8ccf09fa3f..b5092c6c7f 100644 --- a/src/common/format.c +++ b/src/common/format.c @@ -256,7 +256,5 @@ void ffParseFormatString(FFstrbuf* buffer, const FFstrbuf* formatstr, uint32_t n ffFormatAppendFormatArg(buffer, &arguments[index - 1]); } - ffStrbufTrimRight(buffer, ' '); - ffStrbufAppendS(buffer, FASTFETCH_TEXT_MODIFIER_RESET); } From 3714dfdca75dd4cfdc3f81f162ec590f52b518ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 20:51:09 +0800 Subject: [PATCH 136/198] Presets: new example --- presets/examples/11.jsonc | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 presets/examples/11.jsonc diff --git a/presets/examples/11.jsonc b/presets/examples/11.jsonc new file mode 100644 index 0000000000..13215add19 --- /dev/null +++ b/presets/examples/11.jsonc @@ -0,0 +1,38 @@ +{ + "$schema": "file:///C:/msys64/home/zhang/fastfetch/doc/json_schema.json", + "logo": { + "type": "small" + }, + "display": { + "percentType": 9, + "separator": "\u001b[31m-> " + }, + "modules": [ + { + "key": "Distro ", + "type": "os" + }, + { + "key": "Shell ", + "type": "shell" + }, + { + "key": "Terminal ", + "type": "terminal" + }, + { + "key": "Display ", + "type": "display" + }, + { + "key": "Backlight ", + "type": "brightness" + }, + "break", + { + "type": "colors", + "paddingLeft": 6, + "symbol": "circle" + } + ] +} From dbd6e45abad229a956f594717d3ef5d3fb841fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 22:23:27 +0800 Subject: [PATCH 137/198] Disk (Android): fix build --- src/detection/disk/disk_linux.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 7ab1180386..ddb81c8bf1 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -133,7 +133,7 @@ static void detectName(FFDisk* disk) #ifdef __ANDROID__ -static void detectType(FF_MAYBE_UNUSED const FFlist* devices, FFDisk* currentDisk, FF_MAYBE_UNUSED const char* options) +static void detectType(FF_MAYBE_UNUSED const FFlist* disks, FFDisk* currentDisk) { if(ffStrbufEqualS(¤tDisk->mountpoint, "/") || ffStrbufEqualS(¤tDisk->mountpoint, "/storage/emulated")) currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; @@ -254,8 +254,6 @@ const char* ffDetectDisksImpl(FFlist* disks) if(mountsFile == NULL) return "setmntent(\"/proc/mounts\", \"r\") == NULL"; - FF_LIST_AUTO_DESTROY devices = ffListCreate(sizeof(FFstrbuf)); - struct mntent* device; while((device = getmntent(mountsFile))) From 69e57e52abb0f6a162f6bb27e51d453bb8e2b04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 18 Sep 2023 23:03:14 +0800 Subject: [PATCH 138/198] Disk (Android): fix detection on Android --- src/detection/disk/disk_linux.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index ddb81c8bf1..035cec8990 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -52,6 +52,18 @@ static bool isPhysicalDevice(const struct mntent* device) if(!S_ISBLK(deviceStat.st_mode)) return false; + #else + + //Pseudo filesystems don't have a device in /dev + if(!ffStrStartsWith(device->mnt_fsname, "/dev/")) + return false; + + if( + ffStrStartsWith(device->mnt_fsname + 5, "loop") || //Ignore loop devices + ffStrStartsWith(device->mnt_fsname + 5, "ram") || //Ignore ram devices + ffStrStartsWith(device->mnt_fsname + 5, "fd") //Ignore fd devices + ) return false; + #endif // __ANDROID__ return true; @@ -98,7 +110,8 @@ static void detectName(FFDisk* disk) //https://stackoverflow.com/a/73302717 ffStrbufAppendS(&basePath, "/dev/disk/by-id/"); detectNameFromPath(disk, &deviceStat, &basePath); - disk->type = ffStrbufStartsWithS(&disk->name, "usb-") ? FF_DISK_VOLUME_TYPE_EXTERNAL_BIT : FF_DISK_VOLUME_TYPE_NONE; + if (ffStrbufStartsWithS(&disk->name, "usb-")) + disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; ffStrbufClear(&disk->name); //Try label first @@ -263,6 +276,7 @@ const char* ffDetectDisksImpl(FFlist* disks) //We have a valid device, add it to the list FFDisk* disk = ffListAdd(disks); + disk->type = FF_DISK_VOLUME_TYPE_NONE; //detect mountFrom ffStrbufInitS(&disk->mountFrom, device->mnt_fsname); From 48cecd0ad155dd56118258010c7d5de3c8e27f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 19 Sep 2023 10:50:52 +0800 Subject: [PATCH 139/198] CPU: update JSON format structure --- src/modules/cpu/cpu.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 644cda9f4c..3cd5a6cf7a 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -152,11 +152,16 @@ void ffGenerateCPUJson(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_va yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "cpu", &cpu.name); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &cpu.vendor); - yyjson_mut_obj_add_uint(doc, obj, "coresPhysical", cpu.coresPhysical); - yyjson_mut_obj_add_uint(doc, obj, "coresLogical", cpu.coresLogical); - yyjson_mut_obj_add_uint(doc, obj, "coresOnline", cpu.coresOnline); - yyjson_mut_obj_add_real(doc, obj, "frequencyMin", cpu.frequencyMin); - yyjson_mut_obj_add_real(doc, obj, "frequencyMax", cpu.frequencyMax); + + yyjson_mut_val* cores = yyjson_mut_obj_add_obj(doc, obj, "cores"); + yyjson_mut_obj_add_uint(doc, cores, "physical", cpu.coresPhysical); + yyjson_mut_obj_add_uint(doc, cores, "logical", cpu.coresLogical); + yyjson_mut_obj_add_uint(doc, cores, "online", cpu.coresOnline); + + yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency"); + yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin); + yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax); + yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); } From 26e5790a78182a810eec31fd70c4d6dd478ee9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 19 Sep 2023 13:25:50 +0800 Subject: [PATCH 140/198] Brightness: report more detailed values --- src/detection/brightness/brightness.h | 2 +- src/detection/brightness/brightness_apple.c | 8 ++++++-- src/detection/brightness/brightness_bsd.c | 13 ++++++++----- src/detection/brightness/brightness_linux.c | 9 ++++++--- src/detection/brightness/brightness_windows.cpp | 8 ++++++-- src/modules/brightness/brightness.c | 17 ++++++++++++----- 6 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/detection/brightness/brightness.h b/src/detection/brightness/brightness.h index d65843947f..58aeed20a2 100644 --- a/src/detection/brightness/brightness.h +++ b/src/detection/brightness/brightness.h @@ -9,7 +9,7 @@ typedef struct FFBrightnessResult { FFstrbuf name; - float value; + double min, max, current; } FFBrightnessResult; const char* ffDetectBrightness(FFlist* result); // list of FFBrightnessResult diff --git a/src/detection/brightness/brightness_apple.c b/src/detection/brightness/brightness_apple.c index ecbe604787..a3b1d3c8f2 100644 --- a/src/detection/brightness/brightness_apple.c +++ b/src/detection/brightness/brightness_apple.c @@ -20,7 +20,9 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa if(DisplayServicesGetBrightness((CGDirectDisplayID) display->id, &value) == kCGErrorSuccess) { FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->value = value * 100; + brightness->current = value; + brightness->max = 1; + brightness->min = 0; ffStrbufInitCopy(&brightness->name, &display->name); } } @@ -90,7 +92,9 @@ FF_MAYBE_UNUSED static const char* detectWithDdcci(FFlist* result) uint32_t max = ((uint32_t) i2cOut[6] << 8u) + (uint32_t) i2cOut[7]; FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->value = (float) current * 100.f / max; + brightness->max = max; + brightness->min = 0; + brightness->current = current; ffStrbufInit(&brightness->name); uint8_t edid[128] = {}; diff --git a/src/detection/brightness/brightness_bsd.c b/src/detection/brightness/brightness_bsd.c index 8c6a89e2f8..72f1e54762 100644 --- a/src/detection/brightness/brightness_bsd.c +++ b/src/detection/brightness/brightness_bsd.c @@ -26,13 +26,16 @@ const char* ffDetectBrightness(FFlist* result) if(ioctl(blfd, BACKLIGHTGETSTATUS, &status) < 0) continue; - FFBrightnessResult* display = (FFBrightnessResult*) ffListAdd(result); - ffStrbufInit(&display->name); - display->value = (float) status.brightness / BACKLIGHTMAXLEVELS; + FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); + ffStrbufInit(&brightness->name); + + brightness->max = BACKLIGHTMAXLEVELS; + brightness->min = 0; + brightness->current = status.brightness; struct backlight_info info; if(ioctl(blfd, BACKLIGHTGETINFO, &info) < 0) - ffStrbufAppendS(&display->name, info.name); + ffStrbufAppendS(&brightness->name, info.name); } return NULL; } @@ -44,4 +47,4 @@ const char* ffDetectBrightness(FF_MAYBE_UNUSED FFlist* result) return "Backlight is supported only on FreeBSD 13 and newer"; } -#endif \ No newline at end of file +#endif diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index 8ab4e5f860..b3e75b2347 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -72,8 +72,9 @@ static const char* detectWithBacklight(FFlist* result) } else ffStrbufInitS(&brightness->name, entry->d_name); - double maxBrightness = ffStrbufToDouble(&buffer); - brightness->value = (float) (actualBrightness * 100 / maxBrightness); + brightness->max = ffStrbufToDouble(&buffer); + brightness->min = 0; + brightness->current = actualBrightness; } } ffStrbufSubstrBefore(&backlightDir, backlightDirLength); @@ -123,7 +124,9 @@ static const char* detectWithDdcci(FFlist* result) ffddca_free_any_vcp_value(vcpValue); FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->value = (float) current * 100.f / (float) max; + brightness->max = max; + brightness->min = 0; + brightness->current = current; ffStrbufInitS(&brightness->name, display->model_name); } ffddca_close_display(handle); diff --git a/src/detection/brightness/brightness_windows.cpp b/src/detection/brightness/brightness_windows.cpp index 28f489b966..06c1690178 100644 --- a/src/detection/brightness/brightness_windows.cpp +++ b/src/detection/brightness/brightness_windows.cpp @@ -20,7 +20,9 @@ static const char* detectWithWmi(FFlist* result) if(FFWmiVariant vtValue = record.get(L"CurrentBrightness")) { FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result); - brightness->value = vtValue.get(); + brightness->max = 100; + brightness->min = 0; + brightness->current = vtValue.get(); ffStrbufInit(&brightness->name); if (FFWmiVariant vtName = record.get(L"InstanceName")) @@ -51,7 +53,9 @@ static char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* else ffStrbufInitWS(&brightness->name, physicalMonitor.szPhysicalMonitorDescription); - brightness->value = (float) (curr - min) * 100.f / (float) (max - min); + brightness->max = max; + brightness->min = min; + brightness->current = curr; } } } diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index 120459245d..261122bb06 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -5,7 +5,7 @@ #include "modules/brightness/brightness.h" #include "util/stringUtils.h" -#define FF_BRIGHTNESS_NUM_FORMAT_ARGS 2 +#define FF_BRIGHTNESS_NUM_FORMAT_ARGS 5 void ffPrintBrightness(FFBrightnessOptions* options) { @@ -43,6 +43,8 @@ void ffPrintBrightness(FFBrightnessOptions* options) }); } + const double percent = (item->current - item->min) / (item->max - item->min) * 100; + if(options->moduleArgs.outputFormat.length == 0) { FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); @@ -50,7 +52,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) if (instance.config.percentType & FF_PERCENTAGE_TYPE_BAR_BIT) { - ffAppendPercentBar(&str, item->value, 0, 100, 100); + ffAppendPercentBar(&str, percent, 0, 100, 100); } if(instance.config.percentType & FF_PERCENTAGE_TYPE_NUM_BIT) @@ -58,7 +60,7 @@ void ffPrintBrightness(FFBrightnessOptions* options) if(str.length > 0) ffStrbufAppendC(&str, ' '); - ffAppendPercentNum(&str, item->value, 10, 10, str.length > 0); + ffAppendPercentNum(&str, percent, 10, 10, str.length > 0); } ffStrbufPutTo(&str, stdout); @@ -66,10 +68,13 @@ void ffPrintBrightness(FFBrightnessOptions* options) else { FF_STRBUF_AUTO_DESTROY valueStr = ffStrbufCreate(); - ffAppendPercentNum(&valueStr, item->value, 10, 10, false); + ffAppendPercentNum(&valueStr, percent, 10, 10, false); ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_BRIGHTNESS_NUM_FORMAT_ARGS, (FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &valueStr}, {FF_FORMAT_ARG_TYPE_STRBUF, &item->name}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &item->max}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &item->min}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &item->current}, }); } @@ -142,7 +147,9 @@ void ffGenerateBrightnessJson(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjs { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); - yyjson_mut_obj_add_real(doc, obj, "value", item->value); + yyjson_mut_obj_add_real(doc, obj, "max", item->max); + yyjson_mut_obj_add_real(doc, obj, "min", item->min); + yyjson_mut_obj_add_real(doc, obj, "current", item->current); } FF_LIST_FOR_EACH(FFBrightnessResult, item, result) From 064f624eabcfa5391784cc3e25b195dd46d9ac66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 19 Sep 2023 14:43:55 +0800 Subject: [PATCH 141/198] macOS: fix compiler warnings on latest xcode --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bad8d4593..e87dd9574d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -631,6 +631,8 @@ endif() target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1) if(WIN32) target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1) +elseif(APPLE) + target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE) endif() if(HAVE_WCWIDTH) From 38c22bf771c3ce09b24b8c5062fd734f0aea16c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Sep 2023 10:05:18 +0800 Subject: [PATCH 142/198] Disk (FreeBSD): hide `/boot` like what linux does --- src/detection/disk/disk_bsd.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 827ec32c28..bd7adf4e5f 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -1,20 +1,19 @@ #include "disk.h" #include "util/mallocHelper.h" +#include "util/stringUtils.h" #include #ifdef __FreeBSD__ -#include "util/stringUtils.h" - static void detectFsInfo(struct statfs* fs, FFDisk* disk) { if(ffStrbufEqualS(&disk->filesystem, "zfs")) { - disk->type = !ffStrStartsWith(fs->f_mntfromname, "zroot/") || ffStrStartsWith(fs->f_mntfromname, "zroot/ROOT/") + disk->type = !ffStrbufStartsWithS(&disk->mountFrom, "zroot/") || ffStrbufStartsWithS(&disk->mountFrom, "zroot/ROOT/") ? FF_DISK_VOLUME_TYPE_REGULAR_BIT : FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; } - else if(!ffStrStartsWith(fs->f_mntfromname, "/dev/")) + else if(ffStrbufStartsWithS(&disk->mountpoint, "/boot") || ffStrbufStartsWithS(&disk->mountpoint, "/efi")) disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; else if(!(fs->f_flags & MNT_LOCAL)) disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; @@ -35,13 +34,13 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk) { if(fs->f_flags & MNT_DONTBROWSE) disk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; - else if(fs->f_flags & MNT_REMOVABLE) + else if(fs->f_flags & MNT_REMOVABLE || !(fs->f_flags & MNT_LOCAL)) disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; struct VolAttrBuf attrBuf; - if (getattrlist(fs->f_mntonname, &(struct attrlist) { + if (getattrlist(disk->mountpoint.chars, &(struct attrlist) { .bitmapcount = ATTR_BIT_MAP_COUNT, .volattr = ATTR_VOL_INFO | ATTR_VOL_NAME, }, &attrBuf, sizeof(attrBuf), 0) == 0) @@ -62,6 +61,9 @@ const char* ffDetectDisksImpl(FFlist* disks) for(struct statfs* fs = buf; fs < buf + size; ++fs) { + if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs")) + continue; + FFDisk* disk = ffListAdd(disks); #ifdef __FreeBSD__ From 64615e635f1c6ffdb47e623dd26aafadde972210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Sep 2023 10:13:07 +0800 Subject: [PATCH 143/198] Doc: update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b68905ceeb..77dfce3cd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ Changes: * Fastfetch now requires yyjson 0.8.0 or later, which is embeded in fastfetch source tree. If you build fastfetch with `-DENABLE_SYSTEM_YYJSON` cmake option, you must upgrade your yyjson package * Reduced information supported by `--terminal-format`, `--shell-format` * Some config presets (`devinfo` and `verbose`) are obseleted and removed. They are barely maintained and can be replaced with `--format json` now. +* Custom strings in `--module-key` and `--module-format` are no longer trimmed. +* `/boot` is hidden by default (FreeBSD, Disk) Features: * Add `--format json`, which prints system information as JSON format @@ -33,6 +35,7 @@ Logo: * Update EvolutionOS * Update AOSC OS * Update Ubuntu_old +* Update Windows 11_small # 2.0.5 From 576fcd7d3dd1d1523e5ab31fec9774fe3f747719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Sep 2023 16:00:27 +0800 Subject: [PATCH 144/198] Display: print display type --- CHANGELOG.md | 1 + src/modules/display/display.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77dfce3cd2..34d0388a1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Features: * Support Apple Silicon CPU frequency detection (CPU, macOS) * Support user login time detection (Users) * Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows) +* Print monitor type (built-in or external) (Display) Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 14acbcca45..f623bc5f4f 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -85,6 +85,9 @@ void ffPrintDisplay(FFDisplayOptions* options) result->scaledHeight > 0 && result->scaledHeight != result->height) printf(" (as %ix%i)", result->scaledWidth, result->scaledHeight); + if(result->type != FF_DISPLAY_TYPE_UNKNOWN) + fputs(result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]", stdout); + if(moduleIndex > 0 && result->primary) printf(" *"); From 5337e5cead8d2c92f353c2ebaeb4aa2cdffba42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Sep 2023 16:00:09 +0800 Subject: [PATCH 145/198] Packages (Linux): fix snap package number detection on systems other than Ubuntu Fixes 562 --- CHANGELOG.md | 1 + src/detection/packages/packages_linux.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34d0388a1b..ab3a8bf776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Bugfixes: * Fix Termux Monet terminal version detection (Terminal) * Fix zpool volumes detection (Disk, Linux) * Fix external volumes detection (Disk, Linux) +* Fix snap package number detection on systems other than Ubuntu (Packages, Linux) Logo: * Add Afterglow diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 7dd4061b4a..deca9d86d5 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -197,6 +197,9 @@ static uint32_t getSnap(FFstrbuf* baseDir) { uint32_t result = getNumElements(baseDir, "/snap", DT_DIR); + if (result == 0) + result = getNumElements(baseDir, "/var/lib/snapd/snap", DT_DIR); + //Accounting for the /snap/bin folder return result > 0 ? result - 1 : 0; } From 30ae8a2f96e7446f3d31d2f5d92ab2e13ac2a304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Sep 2023 16:17:02 +0800 Subject: [PATCH 146/198] Packages (Linux): fix dpkg package number detection --- CHANGELOG.md | 1 + src/detection/packages/packages_linux.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab3a8bf776..0bf347ed08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Bugfixes: * Fix zpool volumes detection (Disk, Linux) * Fix external volumes detection (Disk, Linux) * Fix snap package number detection on systems other than Ubuntu (Packages, Linux) +* Fix dpkg / apt package number detection (Packages, Linux) Logo: * Add Afterglow diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index deca9d86d5..1aa2c2433a 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -265,7 +265,7 @@ static uint32_t getRpmFromLibrpm(void) static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts) { packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q"); - packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: "); + packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: install ok installed"); packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE"); packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR); packageCounts->flatpakSystem += getFlatpak(baseDir, "/var/lib/flatpak"); From ec8ee1a50934f5616ed4f3c0ebe0b3bc748456d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 21 Sep 2023 00:03:31 +0800 Subject: [PATCH 147/198] TerminalFont: fix compiler warnings --- src/detection/terminalfont/terminalfont.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 7f26d402af..1ebca55d9a 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -378,7 +378,7 @@ static bool detectContour(const FFstrbuf* exe, FFTerminalFontResult* result) uint32_t index = ffStrbufFirstIndexS(&buf, "Font description : (family="); if(index >= buf.length) return false; - index += strlen("Font description : (family="); + index += (uint32_t) strlen("Font description : (family="); ffStrbufSubstrBefore(&buf, ffStrbufNextIndexS(&buf, index, " weight=")); ffFontInitCopy(&result->font, buf.chars + index); return true; From 8cbe3f6453cbf81178f6c6cdc419dd583d808dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Sep 2023 23:55:36 +0800 Subject: [PATCH 148/198] GPU (Linux): add full GPU detection support in WSL With DX12 API ;) --- .github/workflows/ci.yml | 19 ++++--- CHANGELOG.md | 1 + CMakeLists.txt | 24 +++++++- README.md | 1 + src/detection/gpu/gpu_linux.c | 6 ++ src/detection/gpu/gpu_wsl.cpp | 102 ++++++++++++++++++++++++++++++++++ 6 files changed, 144 insertions(+), 9 deletions(-) create mode 100644 src/detection/gpu/gpu_wsl.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d09568c55c..3a0783c9f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,11 +13,15 @@ jobs: fail-fast: false matrix: os: [ubuntu-22.04, ubuntu-20.04] - compiler: [gcc, clang, "musl-gcc"] + compiler: [ + { cc: gcc, cxx: "g++" }, + { cc: clang, cxx: "clang++" }, + { cc: "musl-gcc", cxx: "musl-g++" } + ] enableFeatures: [ON, OFF] exclude: # The feature libraries are all build against glibc, so they can't be used with musl - - compiler: "musl-gcc" + - compiler: { cc: "musl-gcc", cxx: "musl-g++" } enableFeatures: ON runs-on: ${{ matrix.os }} steps: @@ -25,12 +29,13 @@ jobs: uses: actions/checkout@v4 - name: install required packages - run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev + run: sudo apt-get update && sudo apt-get install -y musl-dev musl-tools linux-headers-generic libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev - name: configure project env: - CC: ${{ matrix.compiler }} - run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} . + CC: ${{ matrix.compiler.cc }} + CXX: ${{ matrix.compiler.cxx }} + run: cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIBPCI=${{ matrix.enableFeatures }} -DENABLE_VULKAN=${{ matrix.enableFeatures }} -DENABLE_WAYLAND=${{ matrix.enableFeatures }} -DENABLE_XCB_RANDR=${{ matrix.enableFeatures }} -DENABLE_XCB=${{ matrix.enableFeatures }} -DENABLE_XRANDR=${{ matrix.enableFeatures }} -DENABLE_X11=${{ matrix.enableFeatures }} -DENABLE_GIO=${{ matrix.enableFeatures }} -DENABLE_DCONF=${{ matrix.enableFeatures }} -DENABLE_DBUS=${{ matrix.enableFeatures }} -DENABLE_XFCONF=${{ matrix.enableFeatures }} -DENABLE_SQLITE3=${{ matrix.enableFeatures }} -DENABLE_RPM=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK7=${{ matrix.enableFeatures }} -DENABLE_IMAGEMAGICK6=${{ matrix.enableFeatures }} -DENABLE_CHAFA=${{ matrix.enableFeatures }} -DENABLE_ZLIB=${{ matrix.enableFeatures }} -DENABLE_EGL=${{ matrix.enableFeatures }} -DENABLE_GLX=${{ matrix.enableFeatures }} -DENABLE_OSMESA=${{ matrix.enableFeatures }} -DENABLE_OPENCL=${{ matrix.enableFeatures }} -DENABLE_LIBNM=${{ matrix.enableFeatures }} -DENABLE_PULSE=${{ matrix.enableFeatures }} -DENABLE_JSONC=${{ matrix.enableFeatures }} -DENABLE_DIRECTX_HEADERS=${{ matrix.enableFeatures }} . - name: build project run: cmake --build . @@ -39,7 +44,7 @@ jobs: run: ctest - name: run fastfetch - run: ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all + run: ./fastfetch --stat --show-errors --no-buffer --load-config presets/all - name: run flashfetch run: ./flashfetch @@ -57,7 +62,7 @@ jobs: uses: actions/checkout@v4 - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev + run: sudo apt-get update && sudo apt-get install -y libpci-dev libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev rpm librpm-dev libzstd-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libnm-dev libpulse-dev directx-headers-dev - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bf347ed08..71d44430fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ Features: * Support user login time detection (Users) * Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows) * Print monitor type (built-in or external) (Display) +* Support full GPU detection in WSL (Linux, GPU) Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/CMakeLists.txt b/CMakeLists.txt index e87dd9574d..d570df8ebe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ cmake_dependent_option(ENABLE_LIBNM "Enable libnm" ON "LINUX" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) +cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF) cmake_dependent_option(ENABLE_PCI_MEMORY "Enable detecting GPU memory size with libpci" OFF "LINUX OR BSD" OFF) cmake_dependent_option(ENABLE_SYSTEM_YYJSON "Use system provided (instead of fastfetch embeded) yyjson library" OFF "LINUX OR APPLE OR BSD OR WIN32 OR ANDROID" OFF) @@ -98,10 +99,13 @@ set(WARNING_FLAGS "-Wall -Wextra -Wconversion -Werror=uninitialized -Werror=retu set(CMAKE_C_STANDARD 11) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointer-types -Werror=implicit-function-declaration") -if(WIN32) +if(WIN32 OR ENABLE_DIRECTX_HEADERS) enable_language(CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -fno-exceptions -fno-rtti") +endif() + +if(WIN32) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1") endif() @@ -121,8 +125,8 @@ if(NOT WIN32) set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -rdynamic") endif() - if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "Enabling LTO") include(CheckIPOSupported) check_ipo_supported(RESULT IPO_SUPPORTED) if(IPO_SUPPORTED) @@ -601,6 +605,11 @@ elseif(WIN32) ) endif() +if(ENABLE_DIRECTX_HEADERS) + message(STATUS "Enabling DirectX headers for WSL") + list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_wsl.cpp) +endif() + include(CheckFunctionExists) check_function_exists(wcwidth HAVE_WCWIDTH) if(NOT HAVE_WCWIDTH) @@ -623,6 +632,7 @@ endif() add_library(libfastfetch OBJECT ${LIBFASTFETCH_SRC} ) + if(yyjson_FOUND) target_compile_definitions(libfastfetch PRIVATE FF_USE_SYSTEM_YYJSON) target_link_libraries(libfastfetch PRIVATE yyjson) @@ -775,6 +785,10 @@ ff_lib_enable(DDCUTIL "ddcutil" "Ddcutil" ) +ff_lib_enable(DIRECTX_HEADERS + "DirectX-Headers" + "DirectX-Headers" +) if(ENABLE_THREADS) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS) @@ -879,6 +893,12 @@ target_link_libraries(flashfetch PRIVATE libfastfetch ) +# Prevent fastfetch from linking to libstdc++ +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") +set_target_properties(fastfetch PROPERTIES LINKER_LANGUAGE C) +set_target_properties(flashfetch PROPERTIES LINKER_LANGUAGE C) + if(WIN32) set(TARGET_NAME fastfetch) target_sources(fastfetch diff --git a/README.md b/README.md index ada5be426c..2233edf420 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ The following libraries are used if present at runtime: * [`libnm`](https://networkmanager.dev/docs/libnm/latest/): Used for Wifi detection. * [`libpulse`](https://freedesktop.org/software/pulseaudio/doxygen/): Used for Sound detection. * [`libddcutil`](https://github.com/rockowitz/ddcutil): Used for brightness detection of external displays +* [`DirectX-Headers`](https://github.com/microsoft/DirectX-Headers): Used for GPU detection in WSL ### macOS diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 749072f467..72a6530083 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -311,6 +311,12 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus) const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { + #ifdef FF_HAVE_DIRECTX_HEADERS + const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus); + if (!ffGPUDetectByDirectX(options, gpus)) + return NULL; + #endif + #ifdef FF_HAVE_LIBPCI return pciDetectGPUs(options, gpus); #else diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp new file mode 100644 index 0000000000..fa77a4be0d --- /dev/null +++ b/src/detection/gpu/gpu_wsl.cpp @@ -0,0 +1,102 @@ +#ifdef FF_HAVE_DIRECTX_HEADERS + +#define INITGUID +extern "C" { +#include "common/library.h" +#include "detection/gpu/gpu.h" +} + +#include +#include +#include +#include +#include +#include + +template +struct on_scope_exit { + on_scope_exit(Fn &&fn): _fn(std::move(fn)) {} + ~on_scope_exit() { this->_fn(); } + +private: + Fn _fn; +}; + +extern "C" +const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) +{ + FF_LIBRARY_LOAD(libdxcore, nullptr, "dlopen libdxcore.so failed. Make sure WSLg is enabled", "/usr/lib/wsl/lib/libdxcore" FF_LIBRARY_EXTENSION, 4) + // DXCoreCreateAdapterFactory is a reloaded function, so we can't use FF_LIBRARY_LOAD_SYMBOL_MESSAGE here + typedef HRESULT (*DXCoreCreateAdapterFactory_t)(REFIID riid, void** ppvFactory); + auto ffDXCoreCreateAdapterFactory = (DXCoreCreateAdapterFactory_t) dlsym(libdxcore, "DXCoreCreateAdapterFactory"); + if(ffDXCoreCreateAdapterFactory == nullptr) return "dlsym DXCoreCreateAdapterFactory failed"; + + IDXCoreAdapterFactory *factory = nullptr; + + if (FAILED(ffDXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory)))) + return "DXCoreCreateAdapterFactory(IID_PPV_ARGS(&factory)) failed"; + on_scope_exit destroyFactory([&] { factory->Release(); }); + + IDXCoreAdapterList *list = NULL; + if (FAILED(factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, &list))) + return "factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D11_GRAPHICS, &list) failed"; + on_scope_exit destroyList([&] { list->Release(); }); + + for (uint32_t i = 0, count = list->GetAdapterCount(); i < count; i++) + { + IDXCoreAdapter *adapter = nullptr; + if (FAILED(list->GetAdapter(i, &adapter))) + continue; + on_scope_exit destroyAdapter([&] { adapter->Release(); }); + + // https://learn.microsoft.com/en-us/windows/win32/api/dxcore_interface/ne-dxcore_interface-dxcoreadapterproperty + { + bool value = 0; + if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::IsHardware, sizeof(value), &value)) && !value) + continue; + } + + char desc[256]; + if (FAILED(adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, sizeof(desc), desc))) + continue; + + FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus); + ffStrbufInitS(&gpu->name, desc); + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->temperature = FF_GPU_TEMP_UNSET; + + ffStrbufInit(&gpu->driver); + uint64_t value = 0; + if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DriverVersion, sizeof(value), &value))) + { + ffStrbufSetF(&gpu->driver, "%" PRIu64 ".%" PRIu64 ".%" PRIu64 ".%" PRIu64, + (value >> 48) & 0xFFFF, + (value >> 32) & 0xFFFF, + (value >> 16) & 0xFFFF, + (value >> 0) & 0xFFFF); + } + + gpu->dedicated.used = gpu->shared.used = gpu->dedicated.total = gpu->shared.total = FF_GPU_VMEM_SIZE_UNSET; + if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::DedicatedAdapterMemory, sizeof(value), &value))) + gpu->dedicated.total = value; + if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::SharedSystemMemory, sizeof(value), &value))) + gpu->shared.total = value; + + gpu->type = FF_GPU_TYPE_UNKNOWN; + bool integrated; + if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::IsIntegrated, sizeof(integrated), &integrated))) + gpu->type = integrated ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + + ffStrbufInit(&gpu->vendor); + DXCoreHardwareID hardwareId; + if (SUCCEEDED(adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hardwareId), &hardwareId))) + { + const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID); + ffStrbufAppendS(&gpu->vendor, vendorStr); + } + } + + return NULL; +} + +#endif From 592de4c8f2ca78c17971169512c85cb473154287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 21 Sep 2023 16:04:27 +0800 Subject: [PATCH 149/198] CI: print dependencies --- .github/workflows/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a0783c9f6..42d6dbd962 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,6 +87,9 @@ jobs: - name: run flashfetch run: time ./flashfetch + - name: print dependencies + run: ldd fastfetch + - name: run tests run: ctest @@ -136,6 +139,9 @@ jobs: - name: run flashfetch run: time ./flashfetch + - name: print dependencies + run: otool -L fastfetch + - name: run tests run: ctest @@ -166,6 +172,7 @@ jobs: ./fastfetch --list-features time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all time ./flashfetch + ldd fastfetch ctest - name: upload artifacts @@ -223,6 +230,9 @@ jobs: - name: run flashfetch run: time ./flashfetch + - name: print dependencies + run: ldd fastfetch + - name: run tests run: ctest @@ -284,6 +294,9 @@ jobs: - name: run flashfetch run: time ./flashfetch + - name: print dependencies + run: ldd fastfetch + - name: run tests run: ctest From 560c2acb888ceb0e5ecbc39f3f382d5e5bfee605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 21 Sep 2023 16:17:23 +0800 Subject: [PATCH 150/198] Global: add `--module-key " "` as a magic case for hiding keys --- CHANGELOG.md | 1 + src/common/printing.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71d44430fd..c3a0896e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Features: * Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows) * Print monitor type (built-in or external) (Display) * Support full GPU detection in WSL (Linux, GPU) +* Add `--module-key " "` as a magic case for hiding keys Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/src/common/printing.c b/src/common/printing.c index 16b6de8efb..0d8635f2f0 100644 --- a/src/common/printing.c +++ b/src/common/printing.c @@ -10,6 +10,10 @@ void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModu if(moduleName == NULL) return; + //This is used as a magic value for hiding keys + if(moduleArgs && ffStrbufEqualS(&moduleArgs->key, " ")) + return; + if(!instance.config.pipe) { fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); From 4d86c53e81293f27d24790ce64b3d159efded9a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Sep 2023 13:39:40 +0800 Subject: [PATCH 151/198] Custom: code cleanup --- CHANGELOG.md | 2 +- src/modules/custom/custom.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3a0896e5c..60e4a3a1e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ Features: * Support winget package manager detection, guarded behind `--allow-slow-operations` (Packages, Windows) * Print monitor type (built-in or external) (Display) * Support full GPU detection in WSL (Linux, GPU) -* Add `--module-key " "` as a magic case for hiding keys +* Add `--module-key " "` as a special case for hiding keys Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/src/modules/custom/custom.c b/src/modules/custom/custom.c index 38dd4189a6..6576cd3c5e 100644 --- a/src/modules/custom/custom.c +++ b/src/modules/custom/custom.c @@ -12,7 +12,7 @@ void ffPrintCustom(FFCustomOptions* options) return; } - ffPrintLogoAndKey(options->moduleArgs.key.length == 0 ? NULL : FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_CUSTOM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffStrbufWriteTo(&options->moduleArgs.outputFormat, stdout); puts(FASTFETCH_TEXT_MODIFIER_RESET); } @@ -21,6 +21,7 @@ void ffInitCustomOptions(FFCustomOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_CUSTOM_MODULE_NAME, ffParseCustomCommandOptions, ffParseCustomJsonObject, ffPrintCustom, NULL); ffOptionInitModuleArg(&options->moduleArgs); + ffStrbufSetStatic(&options->moduleArgs.key, " "); } bool ffParseCustomCommandOptions(FFCustomOptions* options, const char* key, const char* value) From a0efbd20a101caa2552a06fcfce72d8cf3f6edaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Sep 2023 13:35:02 +0800 Subject: [PATCH 152/198] Title: make this module formattable --- CHANGELOG.md | 1 + src/data/config_user.txt | 2 ++ src/fastfetch.c | 13 +++++++++ src/modules/title/title.c | 57 ++++++++++++++++++++++++++------------- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e4a3a1e3..1d6743c723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Features: * Print monitor type (built-in or external) (Display) * Support full GPU detection in WSL (Linux, GPU) * Add `--module-key " "` as a special case for hiding keys +* Support `--title-format`. See `fastfetch --help title-format` for detail Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 3d6d0d0f1d..9d3be57960 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -391,6 +391,7 @@ # For information on format strings, see "fastfetch --help format". # To see the parameter they take and their default value, see "fastfetch --help *-format", e.g. "fastfetch --help os-format". # An empty format string (As they are currently below) will behave as if it was not set. +#--title-format #--os-format #--host-format #--chassis-format @@ -439,6 +440,7 @@ # Key color options: # Overrides the global `--color-keys` for one specified module +#--title-key-color #--os-key-color #--host-key-color #--chassis-key-color diff --git a/src/fastfetch.c b/src/fastfetch.c index 6fcef48100..2c6af9b475 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -49,6 +49,19 @@ static inline void printCommandHelp(const char* command) puts(FASTFETCH_DATATEXT_HELP_FORMAT); else if(ffStrEqualsIgnCase(command, "load-config") || ffStrEqualsIgnCase(command, "config")) puts(FASTFETCH_DATATEXT_HELP_CONFIG); + else if(ffStrEqualsIgnCase(command, "title-format")) + { + constructAndPrintCommandHelpFormat("title", "{6}{7}{8}", 8, + "User name", + "Host name", + "Home directory", + "Executable path of current process", + "User's default shell", + "User name (colored)", + "@ symbol (colored)", + "Host name (colored)" + ); + } else if(ffStrEqualsIgnCase(command, "os-format")) { constructAndPrintCommandHelpFormat("os", "{3} {12}", 12, diff --git a/src/modules/title/title.c b/src/modules/title/title.c index 3399f3c204..a0174322a5 100644 --- a/src/modules/title/title.c +++ b/src/modules/title/title.c @@ -4,48 +4,67 @@ #include "util/textModifier.h" #include "util/stringUtils.h" -#define FF_TITLE_NUM_FORMAT_ARGS 2 +#define FF_TITLE_NUM_FORMAT_ARGS 8 -static inline void printTitlePart(const FFstrbuf* content, const FFstrbuf* color) +static void appendText(FFstrbuf* output, const FFstrbuf* text, const FFstrbuf* color) { - if(!instance.config.pipe) + if (!instance.config.pipe) { if (instance.config.brightColor) - fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); - ffPrintColor(color->length > 0 ? color : &instance.config.colorTitle); + ffStrbufAppendS(output, FASTFETCH_TEXT_MODIFIER_BOLT); + if (color->length > 0) + ffStrbufAppendF(output, "\e[%sm", color->chars); + else if (instance.config.colorTitle.length > 0) + ffStrbufAppendF(output, "\e[%sm", instance.config.colorTitle.chars); } - ffStrbufWriteTo(content, stdout); + ffStrbufAppend(output, text); if(!instance.config.pipe) - fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout); + ffStrbufAppendS(output, FASTFETCH_TEXT_MODIFIER_RESET); } void ffPrintTitle(FFTitleOptions* options) { - FF_STRBUF_AUTO_DESTROY hostName = ffStrbufCreateCopy(&instance.state.platform.hostName); + FF_STRBUF_AUTO_DESTROY userNameColored = ffStrbufCreate(); + appendText(&userNameColored, &instance.state.platform.userName, &options->colorUser); + FF_STRBUF_AUTO_DESTROY hostName = ffStrbufCreateCopy(&instance.state.platform.hostName); if (!options->fqdn) ffStrbufSubstrBeforeFirstC(&hostName, '.'); - if (options->moduleArgs.outputFormat.length == 0) - { - ffPrintLogoAndKey(options->moduleArgs.key.length == 0 ? NULL : FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + FF_STRBUF_AUTO_DESTROY hostNameColored = ffStrbufCreate(); + appendText(&hostNameColored, &hostName, &options->colorHost); - printTitlePart(&instance.state.platform.userName, &options->colorUser); + FF_STRBUF_AUTO_DESTROY atColored = ffStrbufCreate(); + if (!instance.config.pipe && options->colorAt.length > 0) + { + ffStrbufAppendF(&atColored, "\e[%sm", options->colorAt.chars); + ffStrbufAppendC(&atColored, '@'); + ffStrbufAppendS(&atColored, FASTFETCH_TEXT_MODIFIER_RESET); + } + else + ffStrbufAppendC(&atColored, '@'); - if (!instance.config.pipe && options->colorAt.length > 0) - ffPrintColor(&options->colorAt); - putchar('@'); + if (options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - printTitlePart(&hostName, &options->colorHost); - putchar('\n'); + ffStrbufWriteTo(&userNameColored, stdout); + ffStrbufWriteTo(&atColored, stdout); + ffStrbufPutTo(&hostNameColored, stdout); } else { ffPrintFormat(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_TITLE_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.userName}, {FF_FORMAT_ARG_TYPE_STRBUF, &hostName}, + {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.homeDir}, + {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.exePath}, + {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.userShell}, + {FF_FORMAT_ARG_TYPE_STRBUF, &userNameColored}, + {FF_FORMAT_ARG_TYPE_STRBUF, &atColored}, + {FF_FORMAT_ARG_TYPE_STRBUF, &hostNameColored}, }); } } @@ -54,6 +73,8 @@ void ffInitTitleOptions(FFTitleOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_TITLE_MODULE_NAME, ffParseTitleCommandOptions, ffParseTitleJsonObject, ffPrintTitle, ffGenerateTitleJson); ffOptionInitModuleArg(&options->moduleArgs); + ffStrbufSetStatic(&options->moduleArgs.key, " "); + options->fqdn = false; ffStrbufInit(&options->colorUser); ffStrbufInit(&options->colorAt); @@ -146,8 +167,8 @@ void ffGenerateTitleJson(FF_MAYBE_UNUSED FFTitleOptions* options, yyjson_mut_doc { yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "userName", &instance.state.platform.userName); - yyjson_mut_obj_add_strbuf(doc, obj, "homeDir", &instance.state.platform.homeDir); yyjson_mut_obj_add_strbuf(doc, obj, "hostName", &instance.state.platform.hostName); + yyjson_mut_obj_add_strbuf(doc, obj, "homeDir", &instance.state.platform.homeDir); yyjson_mut_obj_add_strbuf(doc, obj, "exePath", &instance.state.platform.exePath); yyjson_mut_obj_add_strbuf(doc, obj, "userShell", &instance.state.platform.userShell); } From 34723bba897ed1898a9ada43958fbecb198dd197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Sep 2023 15:00:58 +0800 Subject: [PATCH 153/198] Colors: don't parse `--colors-*` as `--color *` --- src/fastfetch.c | 122 +++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 63 deletions(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index 2c6af9b475..a38f2ce0a8 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -830,25 +830,25 @@ static void parseOption(FFdata* data, const char* key, const char* value) puts(FASTFETCH_PROJECT_VERSION); exit(0); } - else if(ffStrStartsWithIgnCase(key, "--print")) + else if(ffStrStartsWithIgnCase(key, "--print-")) { - const char* subkey = key + strlen("--print"); - if(ffStrEqualsIgnCase(subkey, "-config-system")) + const char* subkey = key + strlen("--print-"); + if(ffStrEqualsIgnCase(subkey, "config-system")) { puts(FASTFETCH_DATATEXT_CONFIG_SYSTEM); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-config-user")) + else if(ffStrEqualsIgnCase(subkey, "config-user")) { puts(FASTFETCH_DATATEXT_CONFIG_USER); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-structure")) + else if(ffStrEqualsIgnCase(subkey, "structure")) { puts(FASTFETCH_DATATEXT_STRUCTURE); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-logos")) + else if(ffStrEqualsIgnCase(subkey, "logos")) { ffLogoBuiltinPrint(); exit(0); @@ -856,35 +856,35 @@ static void parseOption(FFdata* data, const char* key, const char* value) else goto error; } - else if(ffStrStartsWithIgnCase(key, "--list")) + else if(ffStrStartsWithIgnCase(key, "--list-")) { - const char* subkey = key + strlen("--list"); - if(ffStrEqualsIgnCase(subkey, "-modules")) + const char* subkey = key + strlen("--list-"); + if(ffStrEqualsIgnCase(subkey, "modules")) { listModules(); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-presets")) + else if(ffStrEqualsIgnCase(subkey, "presets")) { listAvailablePresets(); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-config-paths")) + else if(ffStrEqualsIgnCase(subkey, "config-paths")) { listConfigPaths(); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-data-paths")) + else if(ffStrEqualsIgnCase(subkey, "data-paths")) { listDataPaths(); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-features")) + else if(ffStrEqualsIgnCase(subkey, "features")) { ffListFeatures(); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-logos")) + else if(ffStrEqualsIgnCase(subkey, "logos")) { puts("Builtin logos:"); ffLogoBuiltinList(); @@ -892,7 +892,7 @@ static void parseOption(FFdata* data, const char* key, const char* value) listAvailableLogos(); exit(0); } - else if(ffStrEqualsIgnCase(subkey, "-logos-autocompletion")) + else if(ffStrEqualsIgnCase(subkey, "logos-autocompletion")) { ffLogoBuiltinListAutocompletion(); exit(0); @@ -900,12 +900,8 @@ static void parseOption(FFdata* data, const char* key, const char* value) else goto error; } - else if(ffStrStartsWithIgnCase(key, "--set")) + else if(ffStrEqualsIgnCase(key, "--set") || ffStrEqualsIgnCase(key, "--set-keyless")) { - const char* subkey = key + strlen("--set"); - if(*subkey != '\0' && !ffStrEqualsIgnCase(subkey, "-keyless")) - goto error; - FF_STRBUF_AUTO_DESTROY customValueStr = ffStrbufCreate(); ffOptionParseString(key, value, &customValueStr); uint32_t index = ffStrbufFirstIndexC(&customValueStr, '='); @@ -932,7 +928,7 @@ static void parseOption(FFdata* data, const char* key, const char* value) ffStrbufInitMove(&customValue->key, &customKey); ffStrbufSubstrAfter(&customValueStr, index); ffStrbufInitMove(&customValue->value, &customValueStr); - customValue->printKey = *subkey == '\0'; + customValue->printKey = key[5] == '\0'; } /////////////////// @@ -1019,21 +1015,21 @@ static void parseOption(FFdata* data, const char* key, const char* value) ffOptionParseString(key, value, &data->structure); else if(ffStrEqualsIgnCase(key, "--separator")) ffOptionParseString(key, value, &instance.config.keyValueSeparator); - else if(ffStrStartsWith(key, "--color")) + else if(ffStrEqualsIgnCase(key, "--color")) { - const char* subkey = key + strlen("--color"); - if(*subkey == '\0') - { - optionCheckString(key, value, &instance.config.colorKeys); - ffOptionParseColor(value, &instance.config.colorKeys); - ffStrbufSet(&instance.config.colorTitle, &instance.config.colorKeys); - } - else if(ffStrEqualsIgnCase(subkey, "-keys")) + optionCheckString(key, value, &instance.config.colorKeys); + ffOptionParseColor(value, &instance.config.colorKeys); + ffStrbufSet(&instance.config.colorTitle, &instance.config.colorKeys); + } + else if(ffStrStartsWithIgnCase(key, "--color-")) + { + const char* subkey = key + strlen("--color-"); + if(ffStrEqualsIgnCase(subkey, "keys")) { optionCheckString(key, value, &instance.config.colorKeys); ffOptionParseColor(value, &instance.config.colorKeys); } - else if(ffStrEqualsIgnCase(subkey, "-title")) + else if(ffStrEqualsIgnCase(subkey, "title")) { optionCheckString(key, value, &instance.config.colorTitle); ffOptionParseColor(value, &instance.config.colorTitle); @@ -1089,16 +1085,16 @@ static void parseOption(FFdata* data, const char* key, const char* value) instance.config.percentNdigits = (uint8_t) ffOptionParseUInt32(key, value); else if(ffStrEqualsIgnCase(key, "--no-buffer")) instance.config.noBuffer = ffOptionParseBoolean(value); - else if(ffStrStartsWithIgnCase(key, "--bar")) + else if(ffStrStartsWithIgnCase(key, "--bar-")) { - const char* subkey = key + strlen("--bar"); - if(ffStrEqualsIgnCase(subkey, "-char-elapsed")) + const char* subkey = key + strlen("--bar-"); + if(ffStrEqualsIgnCase(subkey, "char-elapsed")) ffOptionParseString(key, value, &instance.config.barCharElapsed); - else if(ffStrEqualsIgnCase(subkey, "-char-total")) + else if(ffStrEqualsIgnCase(subkey, "char-total")) ffOptionParseString(key, value, &instance.config.barCharTotal); - else if(ffStrEqualsIgnCase(subkey, "-width")) + else if(ffStrEqualsIgnCase(subkey, "width")) instance.config.barWidth = (uint8_t) ffOptionParseUInt32(key, value); - else if(ffStrEqualsIgnCase(subkey, "-border")) + else if(ffStrEqualsIgnCase(subkey, "border")) instance.config.barBorder = ffOptionParseBoolean(value); else goto error; @@ -1108,56 +1104,56 @@ static void parseOption(FFdata* data, const char* key, const char* value) //Library options// /////////////////// - else if(ffStrStartsWithIgnCase(key, "--lib")) + else if(ffStrStartsWithIgnCase(key, "--lib-")) { - const char* subkey = key + strlen("--lib"); - if(ffStrEqualsIgnCase(subkey, "-PCI")) + const char* subkey = key + strlen("--lib-"); + if(ffStrEqualsIgnCase(subkey, "PCI")) ffOptionParseString(key, value, &instance.config.libPCI); - else if(ffStrEqualsIgnCase(subkey, "-vulkan")) + else if(ffStrEqualsIgnCase(subkey, "vulkan")) ffOptionParseString(key, value, &instance.config.libVulkan); - else if(ffStrEqualsIgnCase(subkey, "-freetype")) + else if(ffStrEqualsIgnCase(subkey, "freetype")) ffOptionParseString(key, value, &instance.config.libfreetype); - else if(ffStrEqualsIgnCase(subkey, "-wayland")) + else if(ffStrEqualsIgnCase(subkey, "wayland")) ffOptionParseString(key, value, &instance.config.libWayland); - else if(ffStrEqualsIgnCase(subkey, "-xcb-randr")) + else if(ffStrEqualsIgnCase(subkey, "xcb-randr")) ffOptionParseString(key, value, &instance.config.libXcbRandr); - else if(ffStrEqualsIgnCase(subkey, "-xcb")) + else if(ffStrEqualsIgnCase(subkey, "xcb")) ffOptionParseString(key, value, &instance.config.libXcb); - else if(ffStrEqualsIgnCase(subkey, "-Xrandr")) + else if(ffStrEqualsIgnCase(subkey, "Xrandr")) ffOptionParseString(key, value, &instance.config.libXrandr); - else if(ffStrEqualsIgnCase(subkey, "-X11")) + else if(ffStrEqualsIgnCase(subkey, "X11")) ffOptionParseString(key, value, &instance.config.libX11); - else if(ffStrEqualsIgnCase(subkey, "-gio")) + else if(ffStrEqualsIgnCase(subkey, "gio")) ffOptionParseString(key, value, &instance.config.libGIO); - else if(ffStrEqualsIgnCase(subkey, "-DConf")) + else if(ffStrEqualsIgnCase(subkey, "DConf")) ffOptionParseString(key, value, &instance.config.libDConf); - else if(ffStrEqualsIgnCase(subkey, "-dbus")) + else if(ffStrEqualsIgnCase(subkey, "dbus")) ffOptionParseString(key, value, &instance.config.libDBus); - else if(ffStrEqualsIgnCase(subkey, "-XFConf")) + else if(ffStrEqualsIgnCase(subkey, "XFConf")) ffOptionParseString(key, value, &instance.config.libXFConf); - else if(ffStrEqualsIgnCase(subkey, "-sqlite") || ffStrEqualsIgnCase(subkey, "-sqlite3")) + else if(ffStrEqualsIgnCase(subkey, "sqlite") || ffStrEqualsIgnCase(subkey, "sqlite3")) ffOptionParseString(key, value, &instance.config.libSQLite3); - else if(ffStrEqualsIgnCase(subkey, "-rpm")) + else if(ffStrEqualsIgnCase(subkey, "rpm")) ffOptionParseString(key, value, &instance.config.librpm); - else if(ffStrEqualsIgnCase(subkey, "-imagemagick")) + else if(ffStrEqualsIgnCase(subkey, "imagemagick")) ffOptionParseString(key, value, &instance.config.libImageMagick); - else if(ffStrEqualsIgnCase(subkey, "-z")) + else if(ffStrEqualsIgnCase(subkey, "z")) ffOptionParseString(key, value, &instance.config.libZ); - else if(ffStrEqualsIgnCase(subkey, "-chafa")) + else if(ffStrEqualsIgnCase(subkey, "chafa")) ffOptionParseString(key, value, &instance.config.libChafa); - else if(ffStrEqualsIgnCase(subkey, "-egl")) + else if(ffStrEqualsIgnCase(subkey, "egl")) ffOptionParseString(key, value, &instance.config.libEGL); - else if(ffStrEqualsIgnCase(subkey, "-glx")) + else if(ffStrEqualsIgnCase(subkey, "glx")) ffOptionParseString(key, value, &instance.config.libGLX); - else if(ffStrEqualsIgnCase(subkey, "-osmesa")) + else if(ffStrEqualsIgnCase(subkey, "osmesa")) ffOptionParseString(key, value, &instance.config.libOSMesa); - else if(ffStrEqualsIgnCase(subkey, "-opencl")) + else if(ffStrEqualsIgnCase(subkey, "opencl")) ffOptionParseString(key, value, &instance.config.libOpenCL); - else if(ffStrEqualsIgnCase(subkey, "-pulse")) + else if(ffStrEqualsIgnCase(subkey, "pulse")) ffOptionParseString(key, value, &instance.config.libPulse); - else if(ffStrEqualsIgnCase(subkey, "-nm")) + else if(ffStrEqualsIgnCase(subkey, "nm")) ffOptionParseString(key, value, &instance.config.libnm); - else if(ffStrEqualsIgnCase(subkey, "-ddcutil")) + else if(ffStrEqualsIgnCase(subkey, "ddcutil")) ffOptionParseString(key, value, &instance.config.libDdcutil); else goto error; From d94fc32f458da6e4334ae3ca3db70306bf4a7012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Sep 2023 15:04:54 +0800 Subject: [PATCH 154/198] Colors: support `--colors-key` --- CHANGELOG.md | 1 + src/modules/colors/colors.c | 10 +++++++++- src/modules/colors/option.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d6743c723..13acef153b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Features: * Support full GPU detection in WSL (Linux, GPU) * Add `--module-key " "` as a special case for hiding keys * Support `--title-format`. See `fastfetch --help title-format` for detail +* Support `--colors-key` Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/src/modules/colors/colors.c b/src/modules/colors/colors.c index 2e20755823..4bcf9bafd2 100644 --- a/src/modules/colors/colors.c +++ b/src/modules/colors/colors.c @@ -9,7 +9,7 @@ void ffPrintColors(FFColorsOptions* options) if(instance.config.pipe) return; - ffLogoPrintLine(); + ffPrintLogoAndKey(FF_COLORS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); if(options->paddingLeft > 0) ffPrintCharTimes(' ', options->paddingLeft); @@ -58,6 +58,8 @@ void ffPrintColors(FFColorsOptions* options) void ffInitColorsOptions(FFColorsOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_COLORS_MODULE_NAME, ffParseColorsCommandOptions, ffParseColorsJsonObject, ffPrintColors, NULL); + ffOptionInitModuleArg(&options->moduleArgs); + ffStrbufSetStatic(&options->moduleArgs.key, " "); options->symbol = FF_COLORS_SYMBOL_BLOCK; options->paddingLeft = 0; } @@ -66,6 +68,8 @@ bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, cons { const char* subKey = ffOptionTestPrefix(key, FF_COLORS_MODULE_NAME); if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; if (ffStrEqualsIgnCase(subKey, "symbol")) { @@ -92,6 +96,7 @@ bool ffParseColorsCommandOptions(FFColorsOptions* options, const char* key, cons void ffDestroyColorsOptions(FF_MAYBE_UNUSED FFColorsOptions* options) { + ffOptionDestroyModuleArg(&options->moduleArgs); } void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) @@ -104,6 +109,9 @@ void ffParseColorsJsonObject(FFColorsOptions* options, yyjson_val* module) if(ffStrEqualsIgnCase(key, "type")) continue; + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + if (ffStrEqualsIgnCase(key, "symbol")) { int value; diff --git a/src/modules/colors/option.h b/src/modules/colors/option.h index a17029bd84..e51cea6f12 100644 --- a/src/modules/colors/option.h +++ b/src/modules/colors/option.h @@ -17,6 +17,8 @@ typedef enum FFColorsSymbol typedef struct FFColorsOptions { FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; + FFColorsSymbol symbol; uint32_t paddingLeft; } FFColorsOptions; From db5619541ab5e8183d49416a28349c0de12d7493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Sep 2023 15:06:02 +0800 Subject: [PATCH 155/198] Init (Windows): actually disable stdout buffer with `--no-buffer` --- src/common/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/init.c b/src/common/init.c index 8c5b60dcb1..a501ed3485 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -239,7 +239,7 @@ void ffStart(void) ffHideCursor = instance.config.hideCursor && !instance.config.pipe && !instance.state.resultDoc; #ifdef _WIN32 - if (!instance.config.noBuffer) setvbuf(stdout, NULL, _IOFBF, 4096); + setvbuf(stdout, NULL, _IOFBF, instance.config.noBuffer ? 0 : 4096); SetConsoleCtrlHandler(consoleHandler, TRUE); HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); DWORD mode = 0; From cc6cdb96fbb195f495e6e25eec8c6afa0674570c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Sep 2023 16:06:04 +0800 Subject: [PATCH 156/198] Networking: support timeout on Linux --- src/common/networking_linux.c | 7 +++--- src/common/thread.h | 40 +++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/common/networking_linux.c b/src/common/networking_linux.c index 7fb6fade55..37c796276f 100644 --- a/src/common/networking_linux.c +++ b/src/common/networking_linux.c @@ -77,7 +77,8 @@ bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, con bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, uint32_t timeout) { #ifdef FF_HAVE_THREADS - ffThreadJoin(state->thread); + if (!ffThreadJoin(state->thread, timeout)) + return false; #endif if(state->sockfd == -1) return false; @@ -85,8 +86,8 @@ bool ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer, ui if(timeout > 0) { struct timeval timev; - timev.tv_sec = 0; - timev.tv_usec = (__typeof__(timev.tv_usec)) (timeout * 1000); //milliseconds to microseconds + timev.tv_sec = timeout / 1000; + timev.tv_usec = (__typeof__(timev.tv_usec)) ((timeout % 1000) * 1000); //milliseconds to microseconds setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev)); } diff --git a/src/common/thread.h b/src/common/thread.h index 0b8989c4e3..55b4c5be70 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -10,6 +10,7 @@ #include #include #include + #include #define FF_THREAD_MUTEX_INITIALIZER SRWLOCK_INIT typedef SRWLOCK FFThreadMutex; typedef HANDLE FFThreadType; @@ -21,9 +22,23 @@ #define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static __stdcall unsigned fn ## ThreadMain (void* data) { fn((paramType)data); return 0; } #define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) static __stdcall unsigned fn ## ThreadMain () { fn(); return 0; } static inline void ffThreadDetach(FFThreadType thread) { CloseHandle(thread); } - static inline void ffThreadJoin(FFThreadType thread) { WaitForSingleObject(thread, 0xffffffff /*INFINITE*/); } + static inline bool ffThreadJoin(FFThreadType thread, uint32_t timeout) + { + if (WaitForSingleObject(thread, timeout == 0 ? (DWORD) -1 : timeout) != 0 /*WAIT_OBJECT_0*/) + { + TerminateThread(thread, (DWORD) -1); + CloseHandle(thread); + return false; + } + CloseHandle(thread); + return true; + } #else #include + #include + #if __has_include() + #include + #endif #define FF_THREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER typedef pthread_mutex_t FFThreadMutex; typedef pthread_t FFThreadType; @@ -37,7 +52,28 @@ #define FF_THREAD_ENTRY_DECL_WRAPPER(fn, paramType) static void* fn ## ThreadMain (void* data) { fn((paramType)data); return NULL; } #define FF_THREAD_ENTRY_DECL_WRAPPER_NOPARAM(fn) static void* fn ## ThreadMain () { fn(); return NULL; } static inline void ffThreadDetach(FFThreadType thread) { pthread_detach(thread); } - static inline void ffThreadJoin(FFThreadType thread) { pthread_join(thread, NULL); } + static inline bool ffThreadJoin(FFThreadType thread, FF_MAYBE_UNUSED uint32_t timeout) + { + #if (defined(__linux__) && !defined(__ANDROID__)) || __has_include() + if (timeout > 0) + { + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) + { + ts.tv_sec += ts.tv_sec / 1000; + ts.tv_nsec += (ts.tv_nsec % 1000) * 1000000; + if (pthread_timedjoin_np(thread, NULL, &ts) != 0) + { + pthread_kill(thread, SIGTERM); + return false; + } + return true; + } + } + #endif + pthread_join(thread, NULL); + return true; + } #endif #else //FF_HAVE_THREADS #define FF_THREAD_MUTEX_INITIALIZER 0 From ff1c3d98889e2d425470c1feebd96423ecf40c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Sep 2023 23:57:55 +0800 Subject: [PATCH 157/198] Doc: update changelog --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13acef153b..6b3cdcd3fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,11 +23,10 @@ Features: * Support full GPU detection in WSL (Linux, GPU) * Add `--module-key " "` as a special case for hiding keys * Support `--title-format`. See `fastfetch --help title-format` for detail -* Support `--colors-key` +* Support `--colors-key` (Colors) Bugfixes: * Fix fastfetch hanging in specific environment (#561) -* Fix `fastfetch --config verbose` doesn't work (#547) * Fix short read when reading from stdin (Logo) * Fix `poll() timeout or failed` error when image is very large (Logo) * Fix Termux Monet terminal version detection (Terminal) From 597daddf2a9d3edc4a0d43d752b2afc13be5b8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 23 Sep 2023 09:56:02 +0800 Subject: [PATCH 158/198] Fastfetch: add `-c` as a shortcut of `--load-config` --- .github/workflows/ci.yml | 10 +++++----- CHANGELOG.md | 1 + presets/ci | 7 +++++++ src/fastfetch.c | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 presets/ci diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42d6dbd962..c6832bdcfb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all + run: time ./fastfetch -c presets/ci - name: run flashfetch run: time ./flashfetch @@ -134,7 +134,7 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all + run: time ./fastfetch -c presets/ci - name: run flashfetch run: time ./flashfetch @@ -170,7 +170,7 @@ jobs: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . cmake --build . --target package ./fastfetch --list-features - time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all + time ./fastfetch -c presets/ci time ./flashfetch ldd fastfetch ctest @@ -225,7 +225,7 @@ jobs: run: ./fastfetch --list-features - name: run fastfetch - run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all + run: time ./fastfetch -c presets/ci - name: run flashfetch run: time ./flashfetch @@ -289,7 +289,7 @@ jobs: run: cp /clang32/bin/{OpenCL,vulkan-1}.dll . - name: run fastfetch - run: time ./fastfetch --disable-linewrap false --hide-cursor false --show-errors --no-buffer --load-config presets/all + run: time ./fastfetch -c presets/ci - name: run flashfetch run: time ./flashfetch diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b3cdcd3fd..f59238c450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Features: * Add `--module-key " "` as a special case for hiding keys * Support `--title-format`. See `fastfetch --help title-format` for detail * Support `--colors-key` (Colors) +* Add `-c` as a shortcut of `--load-config`. Note it was used as the shortcut of `--color` before 2.0.5 Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/presets/ci b/presets/ci new file mode 100644 index 0000000000..d8327be7ac --- /dev/null +++ b/presets/ci @@ -0,0 +1,7 @@ +-c all +--pipe +--show-errors +--no-buffer +--publicip-timeout 1000 +--weather-timeout 1000 +--stat diff --git a/src/fastfetch.c b/src/fastfetch.c index a38f2ce0a8..fd7dd82496 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -935,7 +935,7 @@ static void parseOption(FFdata* data, const char* key, const char* value) //General options// /////////////////// - else if(ffStrEqualsIgnCase(key, "--load-config") || ffStrEqualsIgnCase(key, "--config")) + else if(ffStrEqualsIgnCase(key, "-c") || ffStrEqualsIgnCase(key, "--load-config") || ffStrEqualsIgnCase(key, "--config")) optionParseConfigFile(data, key, value); else if(ffStrEqualsIgnCase(key, "--gen-config")) generateConfigFile(false, value); From 5aa2798e4267054a462cfeb803f226a62fee4f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 23 Sep 2023 11:51:37 +0800 Subject: [PATCH 159/198] Kernel (Windows): detect service pack version --- CHANGELOG.md | 1 + src/modules/kernel/kernel.c | 23 ++++---- src/util/platform/FFPlatform.h | 1 + src/util/platform/FFPlatform_unix.c | 1 + src/util/platform/FFPlatform_windows.c | 76 ++++++++++++-------------- 5 files changed, 50 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f59238c450..a56bb18781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Features: * Support `--title-format`. See `fastfetch --help title-format` for detail * Support `--colors-key` (Colors) * Add `-c` as a shortcut of `--load-config`. Note it was used as the shortcut of `--color` before 2.0.5 +* Support Windows Service Pack version detection (Kernel, Windows) Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/src/modules/kernel/kernel.c b/src/modules/kernel/kernel.c index b8c9e31cff..89aab0af12 100644 --- a/src/modules/kernel/kernel.c +++ b/src/modules/kernel/kernel.c @@ -7,25 +7,25 @@ void ffPrintKernel(FFKernelOptions* options) { + const FFPlatform* platform = &instance.state.platform; if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufWriteTo(&instance.state.platform.systemRelease, stdout); + ffStrbufWriteTo(&platform->systemRelease, stdout); - #ifdef _WIN32 - if(instance.state.platform.systemVersion.length > 0) - printf(" (%s)", instance.state.platform.systemVersion.chars); - #endif - - putchar('\n'); + if(platform->systemDisplayVersion.length > 0) + printf(" (%s)\n", platform->systemDisplayVersion.chars); + else + putchar('\n'); } else { ffPrintFormat(FF_KERNEL_MODULE_NAME, 0, &options->moduleArgs, FF_KERNEL_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.systemName}, - {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.systemRelease}, - {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.systemVersion}, - {FF_FORMAT_ARG_TYPE_STRBUF, &instance.state.platform.systemArchitecture} + {FF_FORMAT_ARG_TYPE_STRBUF, &platform->systemName}, + {FF_FORMAT_ARG_TYPE_STRBUF, &platform->systemRelease}, + {FF_FORMAT_ARG_TYPE_STRBUF, &platform->systemVersion}, + {FF_FORMAT_ARG_TYPE_STRBUF, &platform->systemArchitecture}, + {FF_FORMAT_ARG_TYPE_STRBUF, &platform->systemDisplayVersion} }); } } @@ -75,4 +75,5 @@ void ffGenerateKernelJson(FF_MAYBE_UNUSED FFKernelOptions* options, yyjson_mut_d yyjson_mut_obj_add_strbuf(doc, obj, "name", &instance.state.platform.systemName); yyjson_mut_obj_add_strbuf(doc, obj, "release", &instance.state.platform.systemRelease); yyjson_mut_obj_add_strbuf(doc, obj, "version", &instance.state.platform.systemVersion); + yyjson_mut_obj_add_strbuf(doc, obj, "displayVersion", &instance.state.platform.systemDisplayVersion); } diff --git a/src/util/platform/FFPlatform.h b/src/util/platform/FFPlatform.h index 536b09aed0..48c72513ef 100644 --- a/src/util/platform/FFPlatform.h +++ b/src/util/platform/FFPlatform.h @@ -21,6 +21,7 @@ typedef struct FFPlatform { FFstrbuf systemRelease; FFstrbuf systemVersion; FFstrbuf systemArchitecture; + FFstrbuf systemDisplayVersion; } FFPlatform; void ffPlatformInit(FFPlatform* platform); diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index 2c9b0f4c6e..cc6fa803ab 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -175,4 +175,5 @@ void ffPlatformInitImpl(FFPlatform* platform) ffStrbufAppendS(&platform->systemRelease, uts.release); ffStrbufAppendS(&platform->systemVersion, uts.version); ffStrbufAppendS(&platform->systemArchitecture, uts.machine); + ffStrbufInit(&platform->systemVersion); } diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index fea0c26c62..0774c81c39 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -2,10 +2,16 @@ #include "common/io/io.h" #include "util/stringUtils.h" #include "util/windows/unicode.h" +#include "util/windows/registry.h" +#include #include #include +NTSTATUS NTAPI RtlGetVersion( + _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation +); + static void getExePath(FFPlatform* platform) { wchar_t exePathW[MAX_PATH]; @@ -137,55 +143,44 @@ static void getUserShell(FFPlatform* platform) ffStrbufReplaceAllC(&platform->userShell, '\\', '/'); } -static void getSystemName(FFPlatform* platform) -{ - ffStrbufAppendS(&platform->systemName, getenv("OS")); -} - static void getSystemReleaseAndVersion(FFPlatform* platform) { - HKEY hKey; - if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + RTL_OSVERSIONINFOW osVersion = { .dwOSVersionInfoSize = sizeof(osVersion) }; + if (!NT_SUCCESS(RtlGetVersion(&osVersion))) return; - DWORD bufSize; - - char currentVersion[32]; - - { - DWORD currentMajorVersionNumber; - DWORD currentMinorVersionNumber; - bufSize = sizeof(currentMajorVersionNumber); - if(RegGetValueW(hKey, NULL, L"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMajorVersionNumber, &bufSize) == ERROR_SUCCESS && - RegGetValueW(hKey, NULL, L"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, ¤tMinorVersionNumber, &bufSize) == ERROR_SUCCESS - ) - snprintf(currentVersion, sizeof(currentVersion), "%u.%u", (unsigned)currentMajorVersionNumber, (unsigned)currentMinorVersionNumber); - else - { - bufSize = sizeof(currentVersion); - if(RegGetValueA(hKey, NULL, "CurrentVersion", RRF_RT_REG_SZ, NULL, currentVersion, &bufSize) != ERROR_SUCCESS) - strcpy(currentVersion, "0.0"); - } - } + FF_HKEY_AUTO_DESTROY hKey = NULL; + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL)) + return; - char currentBuildNumber[32]; - bufSize = sizeof(currentBuildNumber); - if(RegGetValueA(hKey, NULL, "CurrentBuildNumber", RRF_RT_REG_SZ, NULL, currentBuildNumber, &bufSize) != ERROR_SUCCESS) - strcpy(currentBuildNumber, "0"); + uint32_t ubr = 0; + ffRegReadUint(hKey, L"UBR", &ubr, NULL); - DWORD ubr; - bufSize = sizeof(ubr); - if(RegGetValueW(hKey, NULL, L"UBR", RRF_RT_REG_DWORD, NULL, &ubr, &bufSize) != ERROR_SUCCESS || bufSize != sizeof(ubr)) - ubr = 0; + ffStrbufAppendF(&platform->systemRelease, + "%u.%u.%u.%u", + (unsigned) osVersion.dwMajorVersion, + (unsigned) osVersion.dwMinorVersion, + (unsigned) osVersion.dwBuildNumber, + (unsigned) ubr); - ffStrbufAppendF(&platform->systemRelease, "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr); + ffStrbufInit(&platform->systemDisplayVersion); + if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &platform->systemDisplayVersion, NULL) && osVersion.szCSDVersion[0]) + ffStrbufSetWS(&platform->systemDisplayVersion, osVersion.szCSDVersion); - ffStrbufEnsureFree(&platform->systemVersion, 256); - bufSize = (DWORD) ffStrbufGetFree(&platform->systemVersion); - if(RegGetValueA(hKey, NULL, "DisplayVersion", RRF_RT_REG_SZ, NULL, platform->systemVersion.chars, &bufSize) == ERROR_SUCCESS) - platform->systemVersion.length = (uint32_t) bufSize - 1; + ffRegReadStrbuf(hKey, L"BuildLabEx", &platform->systemVersion, NULL); - RegCloseKey(hKey); + switch (osVersion.dwPlatformId) + { + case VER_PLATFORM_WIN32s: + ffStrbufAppendS(&platform->systemName, "WIN32s"); + break; + case VER_PLATFORM_WIN32_WINDOWS: + ffStrbufAppendS(&platform->systemName, "WIN32_WINDOWS"); + break; + case VER_PLATFORM_WIN32_NT: + ffStrbufAppendS(&platform->systemName, "WIN32_NT"); + break; + } } static void getSystemArchitecture(FFPlatform* platform) @@ -234,7 +229,6 @@ void ffPlatformInitImpl(FFPlatform* platform) getHostName(platform); getUserShell(platform); - getSystemName(platform); getSystemReleaseAndVersion(platform); getSystemArchitecture(platform); } From 1caaa69deb7d509b807b1862162720b7bf74c450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 23 Sep 2023 11:56:00 +0800 Subject: [PATCH 160/198] Platform: fix memleaks --- src/util/platform/FFPlatform.c | 1 + src/util/platform/FFPlatform_unix.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util/platform/FFPlatform.c b/src/util/platform/FFPlatform.c index baa69e1e1f..b81adc3c6a 100644 --- a/src/util/platform/FFPlatform.c +++ b/src/util/platform/FFPlatform.c @@ -61,6 +61,7 @@ void ffPlatformDestroy(FFPlatform* platform) ffStrbufDestroy(&platform->systemName); ffStrbufDestroy(&platform->systemRelease); ffStrbufDestroy(&platform->systemVersion); + ffStrbufDestroy(&platform->systemDisplayVersion); } void ffPlatformPathAddAbsolute(FFlist* dirs, const char* path) diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index cc6fa803ab..33c76bc694 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -175,5 +175,5 @@ void ffPlatformInitImpl(FFPlatform* platform) ffStrbufAppendS(&platform->systemRelease, uts.release); ffStrbufAppendS(&platform->systemVersion, uts.version); ffStrbufAppendS(&platform->systemArchitecture, uts.machine); - ffStrbufInit(&platform->systemVersion); + ffStrbufInit(&platform->systemDisplayVersion); } From 6ccf8856b90627ffa0d903e25e1ff6c949c05116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Sep 2023 21:16:54 +0800 Subject: [PATCH 161/198] Bluetooth (Windows): fix mac address detection --- src/detection/bluetooth/bluetooth_windows.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/detection/bluetooth/bluetooth_windows.c b/src/detection/bluetooth/bluetooth_windows.c index 9415ea5f43..bcd9da33eb 100644 --- a/src/detection/bluetooth/bluetooth_windows.c +++ b/src/detection/bluetooth/bluetooth_windows.c @@ -33,9 +33,14 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothResult */) device->connected = !!btdi.fConnected; ffStrbufSetWS(&device->name, btdi.szName); - for (uint32_t i = 0; i < sizeof(btdi.Address.rgBytes) / sizeof(btdi.Address.rgBytes); ++i) - ffStrbufAppendF(&device->address, "%X:", btdi.Address.rgBytes[i]); - ffStrbufTrimRight(&device->name, ':'); + + ffStrbufAppendF(&device->address, "%02x:%02x:%02x:%02x:%02x:%02x", + btdi.Address.rgBytes[0], + btdi.Address.rgBytes[1], + btdi.Address.rgBytes[2], + btdi.Address.rgBytes[3], + btdi.Address.rgBytes[4], + btdi.Address.rgBytes[5]); //https://btprodspecificationrefs.blob.core.windows.net/assigned-numbers/Assigned%20Number%20Types/Assigned%20Numbers.pdf if(BitTest(&btdi.ulClassofDevice, 13)) From 3e768ddfd44ddfafb23b5656c3fe9a8a539f116b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Sep 2023 21:49:39 +0800 Subject: [PATCH 162/198] OS (Linux): detect detailed debian version Ref: https://github.com/dylanaraps/neofetch/issues/2381 --- src/detection/os/os_linux.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 338a1fcfb1..e1371f0ac0 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -1,6 +1,7 @@ #include "os.h" #include "common/properties.h" #include "common/parsing.h" +#include "common/io/io.h" #include "util/stringUtils.h" #include @@ -121,6 +122,14 @@ static void getUbuntuFlavour(FFOSResult* result) } } +static void getDebianVersion(FFOSResult* result) +{ + FF_STRBUF_AUTO_DESTROY debianVersion = ffStrbufCreate(); + ffAppendFileBuffer("/etc/debian_version", &debianVersion); + if (debianVersion.length) + ffStrbufSet(&result->version, &debianVersion); +} + static void detectOS(FFOSResult* os) { if(instance.config.osFile.length > 0) @@ -169,6 +178,8 @@ void ffDetectOSImpl(FFOSResult* os) detectOS(os); - if(ffStrbufIgnCaseCompS(&os->id, "ubuntu") == 0) + if(ffStrbufIgnCaseEqualS(&os->id, "ubuntu")) getUbuntuFlavour(os); + else if(ffStrbufIgnCaseEqualS(&os->id, "debian")) + getDebianVersion(os); } From ddbd198864033cdab1e7b14a69ee3c4b0e90f9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Sep 2023 22:21:05 +0800 Subject: [PATCH 163/198] Doc: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a56bb18781..1167b9e1b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Features: * Support `--colors-key` (Colors) * Add `-c` as a shortcut of `--load-config`. Note it was used as the shortcut of `--color` before 2.0.5 * Support Windows Service Pack version detection (Kernel, Windows) +* Support Debian point releases detection (OS, Linux) Bugfixes: * Fix fastfetch hanging in specific environment (#561) @@ -36,6 +37,7 @@ Bugfixes: * Fix external volumes detection (Disk, Linux) * Fix snap package number detection on systems other than Ubuntu (Packages, Linux) * Fix dpkg / apt package number detection (Packages, Linux) +* Fix bluetooth mac address detection (Bluetooth, Windows) Logo: * Add Afterglow From ad0c2aa2e9e9a162510ede681d9f56e2b49d27fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Sep 2023 23:07:03 +0800 Subject: [PATCH 164/198] Version: detect compiler and compile time --- src/detection/version/version.c | 13 +++++++++++++ src/detection/version/version.h | 2 ++ src/fastfetch.c | 4 +++- src/modules/version/version.c | 6 +++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/detection/version/version.c b/src/detection/version/version.c index 4a8eb420c4..202c10ca20 100644 --- a/src/detection/version/version.c +++ b/src/detection/version/version.c @@ -20,6 +20,9 @@ #define FF_ARCHITECTURE "unknown" #endif +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + void ffDetectVersion(FFVersionResult* version) { version->projectName = FASTFETCH_PROJECT_NAME; @@ -27,6 +30,16 @@ void ffDetectVersion(FFVersionResult* version) version->version = FASTFETCH_PROJECT_VERSION; version->versionTweak = FASTFETCH_PROJECT_VERSION_TWEAK; version->cmakeBuiltType = FASTFETCH_PROJECT_CMAKE_BUILD_TYPE; + version->compileTime = __DATE__ ", " __TIME__; + #ifdef __clang__ + version->compiler = "clang " FF_STR(__clang_major__) "." FF_STR(__clang_minor__) "." FF_STR(__clang_patchlevel__); + #elif defined(__GNUC__) + version->compiler = "gcc " FF_STR(__GNUC__) "." FF_STR(__GNUC_MINOR__) "." FF_STR(__GNUC_PATCHLEVEL__); + #elif defined(_MSC_VER) + version->compiler = "msvc " FF_STR(_MSC_VER); + #else + version->compiler = "unknown"; + #endif #ifndef NDEBUG version->debugMode = true; #else diff --git a/src/detection/version/version.h b/src/detection/version/version.h index bdb11aa3a1..4cb7b9ac6c 100644 --- a/src/detection/version/version.h +++ b/src/detection/version/version.h @@ -12,6 +12,8 @@ typedef struct FFVersionResult const char* version; const char* versionTweak; const char* cmakeBuiltType; + const char* compileTime; + const char* compiler; bool debugMode; } FFVersionResult; diff --git a/src/fastfetch.c b/src/fastfetch.c index fd7dd82496..eafb1de61f 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -459,7 +459,9 @@ static inline void printCommandHelp(const char* command) "Version tweak", "Build type (debug or release)", "Architecture", - "CMake build type (Debug, Release, RelWithDebInfo, MinSizeRel)" + "CMake build type (Debug, Release, RelWithDebInfo, MinSizeRel)", + "Date time when compiling", + "Compiler used" ); } else if(ffStrEqualsIgnCase(command, "vulkan-format")) diff --git a/src/modules/version/version.c b/src/modules/version/version.c index 34b8e06423..54781eb622 100644 --- a/src/modules/version/version.c +++ b/src/modules/version/version.c @@ -4,7 +4,7 @@ #include "modules/version/version.h" #include "util/stringUtils.h" -#define FF_VERSION_NUM_FORMAT_ARGS 6 +#define FF_VERSION_NUM_FORMAT_ARGS 8 void ffPrintVersion(FFVersionOptions* options) { @@ -25,6 +25,8 @@ void ffPrintVersion(FFVersionOptions* options) {FF_FORMAT_ARG_TYPE_STRING, result.debugMode ? "debug" : "release"}, {FF_FORMAT_ARG_TYPE_STRING, result.architecture}, {FF_FORMAT_ARG_TYPE_STRING, result.cmakeBuiltType}, + {FF_FORMAT_ARG_TYPE_STRING, result.compileTime}, + {FF_FORMAT_ARG_TYPE_STRING, result.compiler}, }); } } @@ -78,5 +80,7 @@ void ffGenerateVersionJson(FF_MAYBE_UNUSED FFVersionOptions* options, yyjson_mut yyjson_mut_obj_add_str(doc, obj, "version", result.version); yyjson_mut_obj_add_str(doc, obj, "versionTweak", result.versionTweak); yyjson_mut_obj_add_str(doc, obj, "cmakeBuiltType", result.cmakeBuiltType); + yyjson_mut_obj_add_str(doc, obj, "compileTime", result.compileTime); + yyjson_mut_obj_add_str(doc, obj, "compiler", result.compiler); yyjson_mut_obj_add_bool(doc, obj, "debugMode", result.debugMode); } From 6d1bde17c8a9784de00ef994b0f0b4bc65ac3440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Sep 2023 16:11:00 +0800 Subject: [PATCH 165/198] Wifi (macOS): silence compiler warnings --- src/detection/wifi/wifi_apple.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index c6b572012f..775856eec8 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -63,7 +63,7 @@ ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode); break; } - item->conn.signalQuality = inf.rssiValue >= -50 ? 100 : inf.rssiValue <= -100 ? 0 : (inf.rssiValue + 100) * 2; + item->conn.signalQuality = (double) (inf.rssiValue >= -50 ? 100 : inf.rssiValue <= -100 ? 0 : (inf.rssiValue + 100) * 2); item->conn.txRate = inf.transmitRate; switch(inf.security) From bde2d67f25c73758dd909839f6b67fba28b05937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Sep 2023 16:40:26 +0800 Subject: [PATCH 166/198] CMake: disable UBSan --- CMakeLists.txt | 2 +- src/common/option.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d570df8ebe..889082cdd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,7 @@ endif() set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer") if(NOT WIN32) - set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined") + set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address") endif() set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}") diff --git a/src/common/option.h b/src/common/option.h index 9414e9a47d..3fef4995a0 100644 --- a/src/common/option.h +++ b/src/common/option.h @@ -10,6 +10,10 @@ struct yyjson_mut_val; typedef struct FFModuleBaseInfo { const char* name; + // A dirty polymorphic implementation in C. + // This is UB, because `void*` is not compatible with `FF*Options*`. + // However we can't do it better unless we move to C++, so that `option` becomes a `this` pointer + // https://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type bool (*parseCommandOptions)(void* options, const char* key, const char* value); void (*parseJsonObject)(void* options, struct yyjson_val *module); void (*printModule)(void* options); From 40e542852faa95f97f452211b602bf0933f3b959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 09:14:15 +0800 Subject: [PATCH 167/198] CMake: disable ASan on macOS Ref: https://stackoverflow.com/questions/64126942/malloc-nano-zone-abandoned-due-to-inability-to-preallocate-reserved-vm-space --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 889082cdd6..2215ef628a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ if(APPLE AND DEFINED ENV{HOMEBREW_PREFIX}) endif() set(FASTFETCH_FLAGS_DEBUG "-fno-omit-frame-pointer") -if(NOT WIN32) +if(NOT WIN32 AND NOT APPLE) set(FASTFETCH_FLAGS_DEBUG "${FASTFETCH_FLAGS_DEBUG} -fsanitize=address") endif() set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FASTFETCH_FLAGS_DEBUG}") From a4bc07cba574c7fa1903de152e1e487a7a54cd28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Sep 2023 23:31:32 +0800 Subject: [PATCH 168/198] LocalIp (Windows): add ioCounter detection --- src/detection/localip/localip.h | 14 ++++++++++++++ src/detection/localip/localip_windows.c | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index 6fea95a79d..994debec57 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -5,6 +5,18 @@ #include "fastfetch.h" +typedef struct FFLocalIpIoCounters +{ + uint64_t txBytes; + uint64_t rxBytes; + uint64_t txPackets; + uint64_t rxPackets; + uint64_t rxErrors; + uint64_t txErrors; + uint64_t rxDrops; + uint64_t txDrops; +} FFLocalIpIoCounters; + typedef struct FFLocalIpResult { FFstrbuf name; @@ -13,6 +25,8 @@ typedef struct FFLocalIpResult FFstrbuf mac; bool defaultRoute; + FFLocalIpIoCounters ioCounters; + #ifdef _WIN32 uint32_t ifIndex; #endif diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 841a608e33..09071d2751 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -46,6 +46,7 @@ static void addNewIp(FFlist* list, const char* name, const char* value, int type ffStrbufInit(&ip->mac); ip->defaultRoute = false; ip->ifIndex = ifIndex; + ip->ioCounters = (FFLocalIpIoCounters) {}; } else { @@ -141,6 +142,24 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) newIp = false; } } + + if (newIp) + { + MIB_IF_ROW2 ifRow = { .InterfaceIndex = adapter->IfIndex }; + if (GetIfEntry2(&ifRow) == NO_ERROR) + { + ((FFLocalIpResult*) ffListGet(results, results->length - 1))->ioCounters = (FFLocalIpIoCounters) { + .txBytes = ifRow.OutOctets, + .rxBytes = ifRow.InOctets, + .txPackets = (ifRow.OutUcastPkts + ifRow.OutNUcastPkts), + .rxPackets = (ifRow.InUcastPkts + ifRow.InNUcastPkts), + .rxErrors = ifRow.InErrors, + .txErrors = ifRow.OutErrors, + .rxDrops = ifRow.InDiscards, + .txDrops = ifRow.OutDiscards, + }; + } + } } setDefaultRoute(results); From e4c1ec916bcdcbbdd073c514b51a4b9208c0b887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 00:09:56 +0800 Subject: [PATCH 169/198] FFstrbuf: change `ffStrbufToUInt16` to more general function `ffStrbufToUInt` --- src/detection/chassis/chassis_linux.c | 2 +- src/detection/cpu/cpu_linux.c | 2 +- src/detection/displayserver/displayserver_android.c | 4 ++-- src/util/FFstrbuf.c | 6 +++--- src/util/FFstrbuf.h | 2 +- tests/strbuf.c | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/detection/chassis/chassis_linux.c b/src/detection/chassis/chassis_linux.c index deace35d91..074753eb64 100644 --- a/src/detection/chassis/chassis_linux.c +++ b/src/detection/chassis/chassis_linux.c @@ -25,7 +25,7 @@ const char* ffDetectChassis(FFChassisResult* result) if(result->type.length) { - const char* typeStr = ffChassisTypeToString(ffStrbufToUInt16(&result->type, 9999)); + const char* typeStr = ffChassisTypeToString((uint32_t) ffStrbufToUInt(&result->type, 9999)); if(typeStr) ffStrbufSetS(&result->type, typeStr); } diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index bdffc755ff..af340756bc 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -128,7 +128,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) const char* error = parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch); if (error) return error; - cpu->coresPhysical = ffStrbufToUInt16(&physicalCoresBuffer, 1); + cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 1); cpu->coresLogical = (uint16_t) get_nprocs_conf(); cpu->coresOnline = (uint16_t) get_nprocs(); diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index af57a06283..d1e342503f 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -80,9 +80,9 @@ static bool detectWithGetprop(FFDisplayServerResult* ds) ffStrbufContainC(&buffer, ',')) { // 1440,3200,560 => width,height,ppi - uint32_t width = ffStrbufToUInt16(&buffer, 0); + uint32_t width = (uint32_t) ffStrbufToUInt(&buffer, 0); ffStrbufSubstrAfterFirstC(&buffer, ','); - uint32_t height = ffStrbufToUInt16(&buffer, 0); + uint32_t height = (uint32_t) ffStrbufToUInt(&buffer, 0); return ffdsAppendDisplay(ds, width, height, diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index ef049b698d..221a98fc30 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -431,11 +431,11 @@ double ffStrbufToDouble(const FFstrbuf* strbuf) return str_end == strbuf->chars ? 0.0/0.0 : result; } -uint16_t ffStrbufToUInt16(const FFstrbuf* strbuf, uint16_t defaultValue) +uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue) { char* str_end; - unsigned long result = strtoul(strbuf->chars, &str_end, 10); - return str_end == strbuf->chars || result > UINT16_MAX ? defaultValue : (uint16_t)result; + unsigned long long result = strtoull(strbuf->chars, &str_end, 10); + return str_end == strbuf->chars ? defaultValue : (uint64_t)result; } void ffStrbufUpperCase(FFstrbuf* strbuf) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 704abfd299..77db4be967 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -82,7 +82,7 @@ void ffStrbufWriteTo(const FFstrbuf* strbuf, FILE* file); void ffStrbufPutTo(const FFstrbuf* strbuf, FILE* file); FF_C_NODISCARD double ffStrbufToDouble(const FFstrbuf* strbuf); -FF_C_NODISCARD uint16_t ffStrbufToUInt16(const FFstrbuf* strbuf, uint16_t defaultValue); +FF_C_NODISCARD uint64_t ffStrbufToUInt(const FFstrbuf* strbuf, uint64_t defaultValue); void ffStrbufUpperCase(FFstrbuf* strbuf); void ffStrbufLowerCase(FFstrbuf* strbuf); diff --git a/tests/strbuf.c b/tests/strbuf.c index defce5a87d..702f405392 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -123,7 +123,7 @@ int main(void) //toNumber VERIFY(ffStrbufToDouble(&strbuf) == 123456789.0); - VERIFY(ffStrbufToUInt16(&strbuf, 999) == 999); //overflow + VERIFY(ffStrbufToUInt(&strbuf, 999) == 123456789); //countC From 50c8809d51d39c51034d610b49f6eddc345fdb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 00:12:40 +0800 Subject: [PATCH 170/198] LocalIp (Linux): add ioCounter detection --- src/detection/localip/localip_linux.c | 55 +++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index e702347357..a94a83c95e 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -228,6 +228,61 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (ifAddrStruct) freeifaddrs(ifAddrStruct); + #ifdef __linux__ + { + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/net/"); + uint32_t baseLen = path.length; + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) + { + ffStrbufAppend(&path, &ip->name); + ffStrbufAppendS(&path, "/statistics/"); + uint32_t statLen = path.length; + + ffStrbufAppendS(&path, "rx_bytes"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.rxBytes = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_bytes"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.txBytes = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "rx_packets"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.rxPackets = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_packets"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.txPackets = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "rx_errors"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.rxErrors = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_errors"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.txErrors = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "rx_dropped"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.rxDrops = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_dropped"); + if (ffReadFileBuffer(path.chars, &buffer)) + ip->ioCounters.txDrops = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, baseLen); + } + } + #endif + char iface[16 /*IF_NAMESIZE*/ + 1]; if (getDefaultRoute(iface)) { From 57bd741d96e67c2891999e65f2fc1d952e67d838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 10:32:21 +0800 Subject: [PATCH 171/198] NetUsage (Linux): new module (WIP) --- CMakeLists.txt | 1 + src/detection/localip/localip.h | 14 ----- src/detection/localip/localip_linux.c | 55 ------------------- src/detection/netusage/netusage.h | 16 ++++++ src/detection/netusage/netusage_linux.c | 73 +++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 69 deletions(-) create mode 100644 src/detection/netusage/netusage.h create mode 100644 src/detection/netusage/netusage_linux.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2215ef628a..26208f7109 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -387,6 +387,7 @@ if(LINUX) src/detection/media/media_linux.c src/detection/memory/memory_linux.c src/detection/monitor/monitor_linux.c + src/detection/netusage/netusage_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c src/detection/packages/packages_linux.c diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index 994debec57..6fea95a79d 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -5,18 +5,6 @@ #include "fastfetch.h" -typedef struct FFLocalIpIoCounters -{ - uint64_t txBytes; - uint64_t rxBytes; - uint64_t txPackets; - uint64_t rxPackets; - uint64_t rxErrors; - uint64_t txErrors; - uint64_t rxDrops; - uint64_t txDrops; -} FFLocalIpIoCounters; - typedef struct FFLocalIpResult { FFstrbuf name; @@ -25,8 +13,6 @@ typedef struct FFLocalIpResult FFstrbuf mac; bool defaultRoute; - FFLocalIpIoCounters ioCounters; - #ifdef _WIN32 uint32_t ifIndex; #endif diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index a94a83c95e..e702347357 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -228,61 +228,6 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (ifAddrStruct) freeifaddrs(ifAddrStruct); - #ifdef __linux__ - { - FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/net/"); - uint32_t baseLen = path.length; - - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) - { - ffStrbufAppend(&path, &ip->name); - ffStrbufAppendS(&path, "/statistics/"); - uint32_t statLen = path.length; - - ffStrbufAppendS(&path, "rx_bytes"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.rxBytes = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_bytes"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.txBytes = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "rx_packets"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.rxPackets = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_packets"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.txPackets = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "rx_errors"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.rxErrors = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_errors"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.txErrors = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "rx_dropped"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.rxDrops = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_dropped"); - if (ffReadFileBuffer(path.chars, &buffer)) - ip->ioCounters.txDrops = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, baseLen); - } - } - #endif - char iface[16 /*IF_NAMESIZE*/ + 1]; if (getDefaultRoute(iface)) { diff --git a/src/detection/netusage/netusage.h b/src/detection/netusage/netusage.h new file mode 100644 index 0000000000..a754f3917d --- /dev/null +++ b/src/detection/netusage/netusage.h @@ -0,0 +1,16 @@ +#include "fastfetch.h" + +typedef struct FFNetUsageIoCounters +{ + FFstrbuf name; + uint64_t txBytes; + uint64_t rxBytes; + uint64_t txPackets; + uint64_t rxPackets; + uint64_t rxErrors; + uint64_t txErrors; + uint64_t rxDrops; + uint64_t txDrops; +} FFNetUsageIoCounters; + +const char* ffGetNetIoCounter(FFlist* result /* list of FFNetUsageIoCounters */); diff --git a/src/detection/netusage/netusage_linux.c b/src/detection/netusage/netusage_linux.c new file mode 100644 index 0000000000..c430a1f478 --- /dev/null +++ b/src/detection/netusage/netusage_linux.c @@ -0,0 +1,73 @@ +#include "netusage.h" + +#include "common/io/io.h" + +#include + +const char* ffGetNetIoCounter(FFlist* result) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net"); + if (!dirp) return "opendir(\"/sys/class/net\") == NULL"; + + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + if(entry->d_name[0] == '.') + continue; + + ffStrbufSetF(&path, "/sys/class/net/%s/operstate", entry->d_name); + if(!ffReadFileBuffer(path.chars, &buffer) || !ffStrbufEqualS(&buffer, "up")) + continue; + + FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); + ffStrbufInitS(&counters->name, entry->d_name); + + ffStrbufSetF(&path, "/sys/class/net/%s/statistics/"); + uint32_t statLen = path.length; + + ffStrbufAppendS(&path, "rx_bytes"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->rxBytes = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_bytes"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->txBytes = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "rx_packets"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->rxPackets = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_packets"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->txPackets = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "rx_errors"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->rxErrors = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_errors"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->txErrors = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "rx_dropped"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->rxDrops = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + + ffStrbufAppendS(&path, "tx_dropped"); + if (ffReadFileBuffer(path.chars, &buffer)) + counters->txDrops = ffStrbufToUInt(&buffer, 0); + ffStrbufSubstrBefore(&path, statLen); + } + + return NULL; +} From fa4fccd426532426e0496348ab60438a6348081e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 11:01:57 +0800 Subject: [PATCH 172/198] NetUsage (Windows): add detection support --- CMakeLists.txt | 1 + src/detection/localip/localip_windows.c | 19 ------- src/detection/netusage/netusage_windows.c | 62 +++++++++++++++++++++++ 3 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 src/detection/netusage/netusage_windows.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 26208f7109..ae7dd1e817 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -580,6 +580,7 @@ elseif(WIN32) src/detection/media/media_nosupport.c src/detection/memory/memory_windows.c src/detection/monitor/monitor_windows.c + src/detection/netusage/netusage_windows.c src/detection/opengl/opengl_windows.c src/detection/os/os_windows.cpp src/detection/packages/packages_windows.c diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 09071d2751..841a608e33 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -46,7 +46,6 @@ static void addNewIp(FFlist* list, const char* name, const char* value, int type ffStrbufInit(&ip->mac); ip->defaultRoute = false; ip->ifIndex = ifIndex; - ip->ioCounters = (FFLocalIpIoCounters) {}; } else { @@ -142,24 +141,6 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) newIp = false; } } - - if (newIp) - { - MIB_IF_ROW2 ifRow = { .InterfaceIndex = adapter->IfIndex }; - if (GetIfEntry2(&ifRow) == NO_ERROR) - { - ((FFLocalIpResult*) ffListGet(results, results->length - 1))->ioCounters = (FFLocalIpIoCounters) { - .txBytes = ifRow.OutOctets, - .rxBytes = ifRow.InOctets, - .txPackets = (ifRow.OutUcastPkts + ifRow.OutNUcastPkts), - .rxPackets = (ifRow.InUcastPkts + ifRow.InNUcastPkts), - .rxErrors = ifRow.InErrors, - .txErrors = ifRow.OutErrors, - .rxDrops = ifRow.InDiscards, - .txDrops = ifRow.OutDiscards, - }; - } - } } setDefaultRoute(results); diff --git a/src/detection/netusage/netusage_windows.c b/src/detection/netusage/netusage_windows.c new file mode 100644 index 0000000000..8facefcf58 --- /dev/null +++ b/src/detection/netusage/netusage_windows.c @@ -0,0 +1,62 @@ +#include "netusage.h" + +#include "common/io/io.h" +#include "util/mallocHelper.h" +#include "util/windows/unicode.h" + +#include +#include + +const char* ffGetNetIoCounter(FFlist* result) +{ + IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL; + + // Multiple attempts in case interfaces change while + // we are in the middle of querying them. + DWORD adapter_addresses_buffer_size = 0; + for (int attempts = 0;; ++attempts) + { + if (adapter_addresses_buffer_size) + { + 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, + NULL, + adapter_addresses, + &adapter_addresses_buffer_size); + + if (error == ERROR_SUCCESS) + break; + else if (ERROR_BUFFER_OVERFLOW == error && attempts < 4) + continue; + else + return "GetAdaptersAddresses() failed"; + } + + // Iterate through all of the adapters + for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) + { + MIB_IF_ROW2 ifRow = { .InterfaceIndex = adapter->IfIndex }; + if (GetIfEntry2(&ifRow) == NO_ERROR) + { + FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); + *counters = (FFNetUsageIoCounters) { + .txBytes = ifRow.OutOctets, + .rxBytes = ifRow.InOctets, + .txPackets = (ifRow.OutUcastPkts + ifRow.OutNUcastPkts), + .rxPackets = (ifRow.InUcastPkts + ifRow.InNUcastPkts), + .rxErrors = ifRow.InErrors, + .txErrors = ifRow.OutErrors, + .rxDrops = ifRow.InDiscards, + .txDrops = ifRow.OutDiscards, + }; + ffStrbufSetWS(&counters->name, adapter->FriendlyName); + } + } + + return NULL; +} From 9004d9e05cc743c9dc2a2b81066cbfafb9e656fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 12:04:19 +0800 Subject: [PATCH 173/198] NetUsage (BSD): add detection support --- CMakeLists.txt | 2 ++ src/detection/netusage/netusage_bsd.c | 46 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/detection/netusage/netusage_bsd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ae7dd1e817..4390f3bc06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -486,6 +486,7 @@ elseif(BSD) src/detection/media/media_linux.c src/detection/memory/memory_bsd.c src/detection/monitor/monitor_nosupport.c + src/detection/netusage/netusage_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c src/detection/packages/packages_linux.c @@ -533,6 +534,7 @@ elseif(APPLE) src/detection/media/media_apple.m src/detection/memory/memory_apple.c src/detection/monitor/monitor_apple.m + src/detection/netusage/netusage_bsd.c src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m src/detection/packages/packages_apple.c diff --git a/src/detection/netusage/netusage_bsd.c b/src/detection/netusage/netusage_bsd.c new file mode 100644 index 0000000000..1d85158639 --- /dev/null +++ b/src/detection/netusage/netusage_bsd.c @@ -0,0 +1,46 @@ +#include "netusage.h" + +#include "common/io/io.h" +#include "util/mallocHelper.h" + +#include +#include +#include +#include +#include + +const char* ffGetNetIoCounter(FFlist* result) +{ + size_t bufSize = 0; + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed"; + + FF_AUTO_FREE uint8_t *buf = NULL; + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) failed"; + + for (struct if_msghdr2* ifm = (struct if_msghdr2*)buf; + ifm < (struct if_msghdr2*) (buf + bufSize); + ifm = (struct if_msghdr2*) ((uint8_t *)ifm + ifm->ifm_msglen)) + { + if (ifm->ifm_type != RTM_IFINFO2) continue; + + struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1); + FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); + + *counters = (FFNetUsageIoCounters) { + .txBytes = ifm->ifm_data.ifi_obytes, + .rxBytes = ifm->ifm_data.ifi_ibytes, + .txPackets = ifm->ifm_data.ifi_opackets, + .rxPackets = ifm->ifm_data.ifi_ipackets, + .txErrors = ifm->ifm_data.ifi_oerrors, + .rxErrors = ifm->ifm_data.ifi_ierrors, + .txDrops = 0, // unsupported + .rxDrops = ifm->ifm_data.ifi_iqdrops, + }; + + ffStrbufInitNS(&counters->name, sdl->sdl_nlen, sdl->sdl_data); + } + + return NULL; +} From 24a6efa22793321dd9e10a557870039b7beaf6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 16:26:15 +0800 Subject: [PATCH 174/198] NetUsage: finish first working version --- CMakeLists.txt | 7 + src/common/commandoption.c | 3 + src/common/init.c | 2 + src/common/modules.c | 1 + src/common/netif/netif.h | 9 ++ src/common/netif/netif_bsd.c | 96 ++++++++++++++ src/common/netif/netif_linux.c | 25 ++++ src/common/netif/netif_windows.c | 27 ++++ src/detection/localip/localip_linux.c | 120 +---------------- src/detection/localip/localip_windows.c | 39 ++---- src/detection/netusage/netusage.c | 65 +++++++++ src/detection/netusage/netusage.h | 2 +- src/detection/netusage/netusage_bsd.c | 23 ++-- src/detection/netusage/netusage_linux.c | 2 +- src/detection/netusage/netusage_windows.c | 2 +- src/fastfetch.h | 1 + src/modules/localip/localip.c | 10 +- src/modules/modules.h | 1 + src/modules/netusage/netusage.c | 155 ++++++++++++++++++++++ src/modules/netusage/netusage.h | 14 ++ src/modules/netusage/option.h | 11 ++ src/modules/options.h | 1 + 22 files changed, 453 insertions(+), 163 deletions(-) create mode 100644 src/common/netif/netif.h create mode 100644 src/common/netif/netif_bsd.c create mode 100644 src/common/netif/netif_linux.c create mode 100644 src/common/netif/netif_windows.c create mode 100644 src/detection/netusage/netusage.c create mode 100644 src/modules/netusage/netusage.c create mode 100644 src/modules/netusage/netusage.h create mode 100644 src/modules/netusage/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4390f3bc06..c3b47e5cff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -277,6 +277,7 @@ set(LIBFASTFETCH_SRC src/detection/gpu/gpu.c src/detection/locale/locale.c src/detection/media/media.c + src/detection/netusage/netusage.c src/detection/opencl/opencl.c src/detection/os/os.c src/detection/packages/packages.c @@ -319,6 +320,7 @@ set(LIBFASTFETCH_SRC src/modules/localip/localip.c src/modules/memory/memory.c src/modules/monitor/monitor.c + src/modules/netusage/netusage.c src/modules/opencl/opencl.c src/modules/opengl/opengl.c src/modules/os/os.c @@ -359,6 +361,7 @@ if(LINUX) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c src/common/io/io_unix.c + src/common/netif/netif_linux.c src/common/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_linux.c @@ -411,6 +414,7 @@ if(LINUX) elseif(ANDROID) list(APPEND LIBFASTFETCH_SRC src/common/io/io_unix.c + src/common/netif/netif_linux.c src/common/networking_linux.c src/common/processing_linux.c src/detection/battery/battery_android.c @@ -457,6 +461,7 @@ elseif(BSD) list(APPEND LIBFASTFETCH_SRC src/common/dbus.c src/common/io/io_unix.c + src/common/netif/netif_bsd.c src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c @@ -510,6 +515,7 @@ elseif(BSD) elseif(APPLE) list(APPEND LIBFASTFETCH_SRC src/common/io/io_unix.c + src/common/netif/netif_bsd.c src/common/networking_linux.c src/common/processing_linux.c src/common/sysctl.c @@ -559,6 +565,7 @@ elseif(APPLE) elseif(WIN32) list(APPEND LIBFASTFETCH_SRC src/common/io/io_windows.c + src/common/netif/netif_windows.c src/common/networking_windows.c src/common/processing_windows.c src/detection/battery/battery_windows.c diff --git a/src/common/commandoption.c b/src/common/commandoption.c index 5b6f8013b2..6454f51e96 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -60,6 +60,9 @@ void ffPrepareCommandOption(FFdata* data) if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME)) ffPrepareCPUUsage(); + if(ffStrbufContainIgnCaseS(&data->structure, FF_NETUSAGE_MODULE_NAME)) + ffPrepareNetUsage(); + if(instance.config.multithreading) { if(ffStrbufContainIgnCaseS(&data->structure, FF_PUBLICIP_MODULE_NAME)) diff --git a/src/common/init.c b/src/common/init.c index a501ed3485..490e4d0b5e 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -106,6 +106,7 @@ static void defaultConfig(void) ffInitMediaOptions(&instance.config.media); ffInitMemoryOptions(&instance.config.memory); ffInitMonitorOptions(&instance.config.monitor); + ffInitNetUsageOptions(&instance.config.netUsage); ffInitOSOptions(&instance.config.os); ffInitOpenCLOptions(&instance.config.openCL); ffInitOpenGLOptions(&instance.config.openGL); @@ -319,6 +320,7 @@ static void destroyConfig(void) ffDestroyMediaOptions(&instance.config.media); ffDestroyMemoryOptions(&instance.config.memory); ffDestroyMonitorOptions(&instance.config.monitor); + ffDestroyNetUsageOptions(&instance.config.netUsage); ffDestroyOSOptions(&instance.config.os); ffDestroyOpenCLOptions(&instance.config.openCL); ffDestroyOpenGLOptions(&instance.config.openGL); diff --git a/src/common/modules.c b/src/common/modules.c index 1c4cd108aa..b83588992c 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -82,6 +82,7 @@ static FFModuleBaseInfo* M[] = { }; static FFModuleBaseInfo* N[] = { + (void*) &instance.config.netUsage, NULL, }; diff --git a/src/common/netif/netif.h b/src/common/netif/netif.h new file mode 100644 index 0000000000..c515df2793 --- /dev/null +++ b/src/common/netif/netif.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#ifndef _WIN32 +bool ffNetifGetDefaultRoute(FFstrbuf* iface); +#else +bool ffNetifGetDefaultRoute(uint32_t* ifIndex); +#endif diff --git a/src/common/netif/netif_bsd.c b/src/common/netif/netif_bsd.c new file mode 100644 index 0000000000..f001773928 --- /dev/null +++ b/src/common/netif/netif_bsd.c @@ -0,0 +1,96 @@ +#include "netif.h" + +#include "common/io/io.h" + +#include +#include +#include +#include + +#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n)) + +#if defined(__APPLE__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#elif defined(__NetBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t)) +#elif defined(__FreeBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#elif defined(__OpenBSD__) +# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) +#else +# error unknown platform +#endif + +static struct sockaddr * +get_rt_address(struct rt_msghdr *rtm, int desired) +{ + struct sockaddr *sa = (struct sockaddr *)(rtm + 1); + + for (int i = 0; i < RTAX_MAX; i++) + { + if (rtm->rtm_addrs & (1 << i)) + { + if ((1 <sa_len) + (char *)sa); + } + } + return NULL; +} + + + +bool ffNetifGetDefaultRoute(FFstrbuf* iface) +{ + //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 + + FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET); + if (pfRoute < 0) + return false; + + { + struct timeval timeout = {1, 0}; + setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); + setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); + } + + int pid = getpid(); + + struct { + struct rt_msghdr hdr; + struct sockaddr_in dst; + uint8_t data[512]; + } rtmsg = { + .hdr = { + .rtm_type = RTM_GET, + .rtm_flags = RTF_UP | RTF_GATEWAY, + .rtm_version = RTM_VERSION, + .rtm_addrs = RTA_DST | RTA_IFP, + .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), + .rtm_pid = pid, + .rtm_seq = 1, + }, + .dst = { + .sin_family = AF_INET, + .sin_len = sizeof(rtmsg.dst), + }, + }; + + if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen) + return false; + + while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0) + { + if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid) + { + struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); + if (sdl) + { + ffStrbufSetNS(iface, sdl->sdl_nlen, sdl->sdl_data); + return true; + } + return false; + } + } + return false; +} diff --git a/src/common/netif/netif_linux.c b/src/common/netif/netif_linux.c new file mode 100644 index 0000000000..299fd6034b --- /dev/null +++ b/src/common/netif/netif_linux.c @@ -0,0 +1,25 @@ +#include "netif.h" +#include "common/io/io.h" + +#include + +bool ffNetifGetDefaultRoute(FFstrbuf* iface) +{ + FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); + if (!netRoute) return false; + + // skip first line + flockfile(netRoute); + while (getc_unlocked(netRoute) != '\n'); + funlockfile(netRoute); + unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, + + char buf[16 /*IF_NAMESIZE*/ + 1]; + while (fscanf(netRoute, "%16s%llx%*[^\n]", buf, &destination) == 2) + { + if (destination != 0) continue; + ffStrbufSetS(iface, buf); + return true; + } + return false; +} diff --git a/src/common/netif/netif_windows.c b/src/common/netif/netif_windows.c new file mode 100644 index 0000000000..d48cdbac8e --- /dev/null +++ b/src/common/netif/netif_windows.c @@ -0,0 +1,27 @@ +#include "netif.h" +#include "util/mallocHelper.h" + +#include + +bool ffNetifGetDefaultRoute(uint32_t* ifIndex) +{ + ULONG size = 0; + if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER) + return false; + + FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size); + if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS) + return false; + + for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i) + { + MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i]; + if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0) + { + *ifIndex = ipForwardRow->dwForwardIfIndex; + break; + } + } + + return true; +} diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index e702347357..233d425002 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -1,5 +1,6 @@ #include "localip.h" #include "common/io/io.h" +#include "common/netif/netif.h" #include #include @@ -11,123 +12,10 @@ #if defined(__FreeBSD__) || defined(__APPLE__) #include -#include -#include #else #include #endif -#if defined(__linux__) -static bool getDefaultRoute(char iface[IF_NAMESIZE + 1]) -{ - FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); - if (!netRoute) return false; - - // skip first line - flockfile(netRoute); - while (getc_unlocked(netRoute) != '\n'); - funlockfile(netRoute); - unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, - - static_assert(IF_NAMESIZE >= 16, "IF_NAMESIZE is too small"); - while (fscanf(netRoute, "%16s%llx%*[^\n]", iface, &destination) == 2) - { - if (destination == 0) - return true; - } - return false; -} -#elif defined(__FreeBSD__) || defined(__APPLE__) - -#define ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1U) | ((n) - 1))) : (n)) - -#if defined(__APPLE__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#elif defined(__NetBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(uint64_t)) -#elif defined(__FreeBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#elif defined(__OpenBSD__) -# define ROUNDUP(a) ROUNDUP2((a), sizeof(int)) -#else -# error unknown platform -#endif - -static struct sockaddr * -get_rt_address(struct rt_msghdr *rtm, int desired) -{ - struct sockaddr *sa = (struct sockaddr *)(rtm + 1); - - for (int i = 0; i < RTAX_MAX; i++) - { - if (rtm->rtm_addrs & (1 << i)) - { - if ((1 <sa_len) + (char *)sa); - } - } - return NULL; -} - -static bool getDefaultRoute(char iface[IF_NAMESIZE + 1]) -{ - //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 - - FF_AUTO_CLOSE_FD int pfRoute = socket(PF_ROUTE, SOCK_RAW, AF_INET); - if (pfRoute < 0) - return false; - - { - struct timeval timeout = {1, 0}; - setsockopt(pfRoute, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); - setsockopt(pfRoute, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)); - } - - int pid = getpid(); - - struct { - struct rt_msghdr hdr; - struct sockaddr_in dst; - uint8_t data[512]; - } rtmsg = { - .hdr = { - .rtm_type = RTM_GET, - .rtm_flags = RTF_UP | RTF_GATEWAY, - .rtm_version = RTM_VERSION, - .rtm_addrs = RTA_DST | RTA_IFP, - .rtm_msglen = sizeof(rtmsg.hdr) + sizeof(rtmsg.dst), - .rtm_pid = pid, - .rtm_seq = 1, - }, - .dst = { - .sin_family = AF_INET, - .sin_len = sizeof(rtmsg.dst), - }, - }; - - if (write(pfRoute, &rtmsg, rtmsg.hdr.rtm_msglen) != rtmsg.hdr.rtm_msglen) - return false; - - while (read(pfRoute, &rtmsg, sizeof(rtmsg)) > 0) - { - if (rtmsg.hdr.rtm_seq == 1 && rtmsg.hdr.rtm_pid == pid) - { - struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); - if (sdl) - { - assert(sdl->sdl_nlen <= IF_NAMESIZE); - memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); - iface[sdl->sdl_nlen] = 0; - return true; - } - return false; - } - } - return false; -} -#endif - static void addNewIp(FFlist* list, const char* name, const char* addr, int type) { FFLocalIpResult* ip = NULL; @@ -228,11 +116,11 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (ifAddrStruct) freeifaddrs(ifAddrStruct); - char iface[16 /*IF_NAMESIZE*/ + 1]; - if (getDefaultRoute(iface)) + FF_STRBUF_AUTO_DESTROY iface = ffStrbufCreate(); + if (ffNetifGetDefaultRoute(&iface)) { FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) - ip->defaultRoute = ffStrbufEqualS(&ip->name, iface); + ip->defaultRoute = ffStrbufEqual(&ip->name, &iface); } return NULL; } diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 841a608e33..82323fd117 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -1,38 +1,11 @@ -#include #include #include +#include "common/netif/netif.h" #include "util/mallocHelper.h" #include "util/windows/unicode.h" #include "localip.h" -static void setDefaultRoute(FFlist* ips) -{ - ULONG size = 0; - if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER) - return; - - FF_AUTO_FREE MIB_IPFORWARDTABLE* pIpForwardTable = (MIB_IPFORWARDTABLE*) malloc(size); - if (GetIpForwardTable(pIpForwardTable, &size, TRUE) != ERROR_SUCCESS) - return; - - for (uint32_t i = 0; i < pIpForwardTable->dwNumEntries; ++i) - { - MIB_IPFORWARDROW* ipForwardRow = &pIpForwardTable->table[i]; - if (ipForwardRow->dwForwardDest == 0 && ipForwardRow->dwForwardMask == 0) - { - FF_LIST_FOR_EACH(FFLocalIpResult, ip, *ips) - { - if (ip->ifIndex == ipForwardRow->dwForwardIfIndex) - { - ip->defaultRoute = true; - break; - } - } - } - } -} - static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, uint32_t ifIndex) { FFLocalIpResult* ip = NULL; @@ -143,7 +116,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - setDefaultRoute(results); + uint32_t ifIndex; + if (ffNetifGetDefaultRoute(&ifIndex)) + { + FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) + { + if (ip->ifIndex != ifIndex) continue; + ip->defaultRoute = true; + } + } return NULL; } diff --git a/src/detection/netusage/netusage.c b/src/detection/netusage/netusage.c new file mode 100644 index 0000000000..af885edb26 --- /dev/null +++ b/src/detection/netusage/netusage.c @@ -0,0 +1,65 @@ +#include "netusage.h" + +#include "common/time.h" + +const char* ffNetUsageGetIoCounters(FFlist* result); + +static FFlist ioCounters1; +static uint64_t time1; + +void ffPrepareNetUsage(void) +{ + ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); + ffNetUsageGetIoCounters(&ioCounters1); + time1 = ffTimeGetNow(); +} + +const char* ffDetectNetUsage(FFlist* result) +{ + const char* error = NULL; + if (time1 == 0) + { + ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); + error = ffNetUsageGetIoCounters(&ioCounters1); + if (error) + return error; + time1 = ffTimeGetNow(); + ffTimeSleep(1000); + } + + uint64_t time2 = ffTimeGetNow(); + while (time2 - time1 < 1000) + { + ffTimeSleep((uint32_t) (1000 - (time2 - time1))); + time2 = ffTimeGetNow(); + } + + error = ffNetUsageGetIoCounters(result); + if (error) + return error; + + if (result->length != ioCounters1.length) + return "Different number of network interfaces. Network change?"; + + for (uint32_t i = 0; i < result->length; ++i) + { + FFNetUsageIoCounters* icPrev = (FFNetUsageIoCounters*)ffListGet(&ioCounters1, i); + FFNetUsageIoCounters* icCurr = (FFNetUsageIoCounters*)ffListGet(result, i); + if (!ffStrbufEqual(&icPrev->name, &icCurr->name)) + return "Network interface name changed"; + + static_assert(sizeof(FFNetUsageIoCounters) - offsetof(FFNetUsageIoCounters, txBytes) == sizeof(uint64_t) * 8, "Unexpected struct FFNetUsageIoCounters layout"); + for (size_t off = offsetof(FFNetUsageIoCounters, txBytes); off < sizeof(FFNetUsageIoCounters); off += sizeof(uint64_t)) + { + uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); + uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); + uint64_t temp = *currValue; + *currValue -= *prevValue; + *currValue /= (time2 - time1) / 1000 /* seconds */; + *prevValue = temp; + } + } + time1 = time2; + + return NULL; +} diff --git a/src/detection/netusage/netusage.h b/src/detection/netusage/netusage.h index a754f3917d..35a95367f4 100644 --- a/src/detection/netusage/netusage.h +++ b/src/detection/netusage/netusage.h @@ -13,4 +13,4 @@ typedef struct FFNetUsageIoCounters uint64_t txDrops; } FFNetUsageIoCounters; -const char* ffGetNetIoCounter(FFlist* result /* list of FFNetUsageIoCounters */); +const char* ffDetectNetUsage(FFlist* result); diff --git a/src/detection/netusage/netusage_bsd.c b/src/detection/netusage/netusage_bsd.c index 1d85158639..ffd430dfa7 100644 --- a/src/detection/netusage/netusage_bsd.c +++ b/src/detection/netusage/netusage_bsd.c @@ -5,27 +5,30 @@ #include #include +#include #include #include #include -const char* ffGetNetIoCounter(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result) { size_t bufSize = 0; - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed"; + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed"; - FF_AUTO_FREE uint8_t *buf = NULL; - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_IFLIST2, 0 }, 6, &buf, &bufSize, 0, 0) failed"; + FF_AUTO_FREE struct if_msghdr2* buf = (struct if_msghdr2*) malloc(bufSize); + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) failed"; - for (struct if_msghdr2* ifm = (struct if_msghdr2*)buf; - ifm < (struct if_msghdr2*) (buf + bufSize); - ifm = (struct if_msghdr2*) ((uint8_t *)ifm + ifm->ifm_msglen)) + for (struct if_msghdr2* ifm = buf; + ifm < (struct if_msghdr2*) ((uint8_t*) buf + bufSize); + ifm = (struct if_msghdr2*) ((uint8_t*) ifm + ifm->ifm_msglen)) { - if (ifm->ifm_type != RTM_IFINFO2) continue; + if (ifm->ifm_type != RTM_IFINFO2 || !(ifm->ifm_flags & IFF_RUNNING) || (ifm->ifm_flags & IFF_NOARP)) continue; struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1); + assert(sdl->sdl_family == AF_LINK); + if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue; FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); *counters = (FFNetUsageIoCounters) { diff --git a/src/detection/netusage/netusage_linux.c b/src/detection/netusage/netusage_linux.c index c430a1f478..aea66b4634 100644 --- a/src/detection/netusage/netusage_linux.c +++ b/src/detection/netusage/netusage_linux.c @@ -4,7 +4,7 @@ #include -const char* ffGetNetIoCounter(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result) { FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net"); if (!dirp) return "opendir(\"/sys/class/net\") == NULL"; diff --git a/src/detection/netusage/netusage_windows.c b/src/detection/netusage/netusage_windows.c index 8facefcf58..1604b61de7 100644 --- a/src/detection/netusage/netusage_windows.c +++ b/src/detection/netusage/netusage_windows.c @@ -7,7 +7,7 @@ #include #include -const char* ffGetNetIoCounter(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result) { IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL; diff --git a/src/fastfetch.h b/src/fastfetch.h index 8ba9158e9c..c9cbfbb627 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -108,6 +108,7 @@ typedef struct FFconfig FFMediaOptions media; FFMemoryOptions memory; FFMonitorOptions monitor; + FFNetUsageOptions netUsage; FFOSOptions os; FFOpenCLOptions openCL; FFOpenGLOptions openGL; diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 28139c1d6e..705a6c902f 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -13,14 +13,14 @@ static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) return ffStrbufComp(&left->name, &right->name); } -static void formatKey(const FFLocalIpOptions* options, const FFLocalIpResult* ip, uint32_t index, FFstrbuf* key) +static void formatKey(const FFLocalIpOptions* options, FFLocalIpResult* ip, uint32_t index, FFstrbuf* key) { if(options->moduleArgs.key.length == 0) { - if(ip->name.length) - ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars); - else - ffStrbufSetS(key, FF_LOCALIP_DISPLAY_NAME); + if(!ip->name.length) + ffStrbufSetF(&ip->name, "unknown %u", (unsigned) index); + + ffStrbufSetF(key, FF_LOCALIP_DISPLAY_NAME " (%s)", ip->name.chars); } else { diff --git a/src/modules/modules.h b/src/modules/modules.h index 1f7669c102..2ab14bc602 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -31,6 +31,7 @@ #include "modules/media/media.h" #include "modules/memory/memory.h" #include "modules/monitor/monitor.h" +#include "modules/netusage/netusage.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" #include "modules/os/os.h" diff --git a/src/modules/netusage/netusage.c b/src/modules/netusage/netusage.c new file mode 100644 index 0000000000..51a3c1f6b1 --- /dev/null +++ b/src/modules/netusage/netusage.c @@ -0,0 +1,155 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "common/parsing.h" +#include "detection/netusage/netusage.h" +#include "modules/netusage/netusage.h" +#include "util/stringUtils.h" + +#define FF_NETUSAGE_DISPLAY_NAME "Net Usage" +#define FF_NETUSAGE_NUM_FORMAT_ARGS 1 + +static int sortInfs(const FFNetUsageIoCounters* left, const FFNetUsageIoCounters* right) +{ + return ffStrbufComp(&left->name, &right->name); +} + +static void formatKey(const FFNetUsageOptions* options, FFNetUsageIoCounters* inf, uint32_t index, FFstrbuf* key) +{ + if(options->moduleArgs.key.length == 0) + { + if(!inf->name.length) + ffStrbufSetF(&inf->name, "unknown %u", (unsigned) index); + + ffStrbufSetF(key, FF_NETUSAGE_DISPLAY_NAME " (%s)", inf->name.chars); + } + else + { + ffStrbufClear(key); + ffParseFormatString(key, &options->moduleArgs.key, 2, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_UINT, &index}, + {FF_FORMAT_ARG_TYPE_STRBUF, &inf->name}, + }); + } +} + +void ffPrintNetUsage(FFNetUsageOptions* options) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); + const char* error = ffDetectNetUsage(&result); + + if(error) + { + ffPrintError(FF_NETUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); + return; + } + + ffListSort(&result, (const void*) sortInfs); + + uint32_t index = 0; + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); + + FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) + { + formatKey(options, inf, result.length == 1 ? 0 : index + 1, &key); + ffStrbufClear(&buffer); + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + + ffParseSize(inf->rxBytes, &buffer); + ffStrbufAppendS(&buffer, "/s (in) - "); + ffParseSize(inf->txBytes, &buffer); + ffStrbufAppendS(&buffer, "/s (out)"); + ffStrbufPutTo(&buffer, stdout); + } + else + { + ffStrbufClear(&buffer2); + ffParseSize(inf->rxBytes, &buffer); + ffParseSize(inf->txBytes, &buffer2); + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_NETUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){ + {FF_FORMAT_ARG_TYPE_STRBUF, &inf->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, + {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txBytes}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxBytes}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txPackets}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxPackets}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxErrors}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txErrors}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxDrops}, + {FF_FORMAT_ARG_TYPE_UINT64, &inf->txDrops}, + }); + } + ++index; + } +} + +void ffInitNetUsageOptions(FFNetUsageOptions* options) +{ + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETUSAGE_MODULE_NAME, ffParseNetUsageCommandOptions, ffParseNetUsageJsonObject, ffPrintNetUsage, ffGenerateNetUsageJson); + ffOptionInitModuleArg(&options->moduleArgs); +} + +bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_NETUSAGE_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffDestroyNetUsageOptions(FFNetUsageOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} + +void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_NETUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); + } +} + +void ffGenerateNetUsageJson(FF_MAYBE_UNUSED FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); + const char* error = ffDetectNetUsage(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); + FF_LIST_FOR_EACH(FFNetUsageIoCounters, counter, result) + { + yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name); + yyjson_mut_obj_add_uint(doc, obj, "txBytes", counter->txBytes); + yyjson_mut_obj_add_uint(doc, obj, "rxBytes", counter->rxBytes); + yyjson_mut_obj_add_uint(doc, obj, "txPackets", counter->txPackets); + yyjson_mut_obj_add_uint(doc, obj, "rxPackets", counter->rxPackets); + yyjson_mut_obj_add_uint(doc, obj, "rxErrors", counter->rxErrors); + yyjson_mut_obj_add_uint(doc, obj, "txErrors", counter->txErrors); + yyjson_mut_obj_add_uint(doc, obj, "rxDrops", counter->rxDrops); + yyjson_mut_obj_add_uint(doc, obj, "txDrops", counter->txDrops); + + } +} diff --git a/src/modules/netusage/netusage.h b/src/modules/netusage/netusage.h new file mode 100644 index 0000000000..4067d68993 --- /dev/null +++ b/src/modules/netusage/netusage.h @@ -0,0 +1,14 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_NETUSAGE_MODULE_NAME "NetUsage" + +void ffPrepareNetUsage(); + +void ffPrintNetUsage(FFNetUsageOptions* options); +void ffInitNetUsageOptions(FFNetUsageOptions* options); +bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value); +void ffDestroyNetUsageOptions(FFNetUsageOptions* options); +void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module); +void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); diff --git a/src/modules/netusage/option.h b/src/modules/netusage/option.h new file mode 100644 index 0000000000..59463249fb --- /dev/null +++ b/src/modules/netusage/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFNetUsageOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFNetUsageOptions; diff --git a/src/modules/options.h b/src/modules/options.h index 12041ce5b6..77c6cf8550 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -31,6 +31,7 @@ #include "modules/media/option.h" #include "modules/memory/option.h" #include "modules/monitor/option.h" +#include "modules/netusage/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" #include "modules/os/option.h" From 69373906cab547624abf3f9680a8a329a837945b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 20:09:41 +0800 Subject: [PATCH 175/198] Windows: pre-basic msvc support --- src/fastfetch.h | 4 ++++ src/util/FFcheckmacros.h | 6 ++++++ src/util/unused.h | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/fastfetch.h b/src/fastfetch.h index c9cbfbb627..ccf3a8f106 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -14,6 +14,10 @@ #include "3rdparty/yyjson/yyjson.h" #endif +#ifdef _MSC_VER + #define __attribute__(x) +#endif + #include "util/FFstrbuf.h" #include "util/FFlist.h" #include "util/platform/FFPlatform.h" diff --git a/src/util/FFcheckmacros.h b/src/util/FFcheckmacros.h index 1ed61cf82d..9eb45f78cf 100644 --- a/src/util/FFcheckmacros.h +++ b/src/util/FFcheckmacros.h @@ -3,8 +3,14 @@ #ifndef FASTFETCH_INCLUDED_FFCHECKMACROS #define FASTFETCH_INCLUDED_FFCHECKMACROS +#ifdef _MSC_VER + #include +#endif + #if defined(__GNUC__) || defined(__clang__) #define FF_C_NODISCARD __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) + #define FF_C_NODISCARD _Check_return_ #else #define FF_C_NODISCARD #endif diff --git a/src/util/unused.h b/src/util/unused.h index fbc0e93e37..faef70d09e 100644 --- a/src/util/unused.h +++ b/src/util/unused.h @@ -5,6 +5,10 @@ static inline void ffUnused(int dummy, ...) { (void) dummy; } #define FF_UNUSED(...) ffUnused(0, __VA_ARGS__); -#define FF_MAYBE_UNUSED __attribute__ ((__unused__)) +#if defined(__GNUC__) || defined(__clang__) + #define FF_MAYBE_UNUSED __attribute__ ((__unused__)) +#else + #define FF_MAYBE_UNUSED +#endif #endif From 4843dedb4ddab73830acb06c2adfa72dece70381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 20:27:33 +0800 Subject: [PATCH 176/198] LocalIp: filter `--localip-default-route-only` inside detection code --- src/detection/localip/localip.h | 4 ---- src/detection/localip/localip_linux.c | 24 +++++++++++----------- src/detection/localip/localip_windows.c | 27 ++++++++++--------------- src/modules/localip/localip.c | 6 ------ 4 files changed, 23 insertions(+), 38 deletions(-) diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index 6fea95a79d..8d0fe84bf4 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -12,10 +12,6 @@ typedef struct FFLocalIpResult FFstrbuf ipv6; FFstrbuf mac; bool defaultRoute; - - #ifdef _WIN32 - uint32_t ifIndex; - #endif } FFLocalIpResult; const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results); diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 233d425002..195ab2ae0e 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -16,7 +16,7 @@ #include #endif -static void addNewIp(FFlist* list, const char* name, const char* addr, int type) +static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute) { FFLocalIpResult* ip = NULL; @@ -33,7 +33,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type) ffStrbufInit(&ip->ipv4); ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); - ip->defaultRoute = false; + ip->defaultRoute = defaultRoute; } switch (type) @@ -56,11 +56,17 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if(getifaddrs(&ifAddrStruct) < 0) return "getifaddrs(&ifAddrStruct) failed"; + FF_STRBUF_AUTO_DESTROY defaultRouteIface = ffStrbufCreate(); + ffNetifGetDefaultRoute(&defaultRouteIface); + for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING)) continue; + if (options->defaultRouteOnly && !ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)) + continue; + if ((ifa->ifa_flags & IFF_LOOPBACK) && !(options->showType & FF_LOCALIP_TYPE_LOOP_BIT)) continue; @@ -75,7 +81,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) 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, AF_INET); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); } else if (ifa->ifa_addr->sa_family == AF_INET6) { @@ -85,7 +91,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) 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, AF_INET6); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); } #if defined(__FreeBSD__) || defined(__APPLE__) else if (ifa->ifa_addr->sa_family == AF_LINK) @@ -97,7 +103,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr); snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, ifa->ifa_name, addressBuffer, -1); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); } #else else if (ifa->ifa_addr->sa_family == AF_PACKET) @@ -109,18 +115,12 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr; snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, ifa->ifa_name, addressBuffer, -1); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); } #endif } if (ifAddrStruct) freeifaddrs(ifAddrStruct); - FF_STRBUF_AUTO_DESTROY iface = ffStrbufCreate(); - if (ffNetifGetDefaultRoute(&iface)) - { - FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) - ip->defaultRoute = ffStrbufEqual(&ip->name, &iface); - } return NULL; } diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 82323fd117..78552be5b4 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -6,7 +6,7 @@ #include "util/windows/unicode.h" #include "localip.h" -static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, uint32_t ifIndex) +static void addNewIp(FFlist* list, const char* name, const char* value, int type, bool newIp, bool defaultRoute) { FFLocalIpResult* ip = NULL; @@ -17,8 +17,7 @@ static void addNewIp(FFlist* list, const char* name, const char* value, int type ffStrbufInit(&ip->ipv4); ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); - ip->defaultRoute = false; - ip->ifIndex = ifIndex; + ip->defaultRoute = defaultRoute; } else { @@ -71,9 +70,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) return "GetAdaptersAddresses() failed"; } + uint32_t defaultRouteIfIndex = (uint32_t)-1; + ffNetifGetDefaultRoute(&defaultRouteIfIndex); + // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) { + if (options->defaultRouteOnly && adapter->IfIndex != defaultRouteIfIndex) + continue; + bool isLoop = adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK; if (isLoop && !(options->showType & FF_LOCALIP_TYPE_LOOP_BIT)) continue; @@ -91,7 +96,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = adapter->PhysicalAddress; snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, name, addressBuffer, -1, newIp, adapter->IfIndex); + addNewIp(results, name, addressBuffer, -1, newIp, adapter->IfIndex == defaultRouteIfIndex); newIp = false; } @@ -102,7 +107,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr; char addressBuffer[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN); - addNewIp(results, name, addressBuffer, AF_INET, newIp, adapter->IfIndex); + addNewIp(results, name, addressBuffer, AF_INET, newIp, adapter->IfIndex == defaultRouteIfIndex); newIp = false; } else if (ifa->Address.lpSockaddr->sa_family == AF_INET6) @@ -110,21 +115,11 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr; char addressBuffer[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN); - addNewIp(results, name, addressBuffer, AF_INET6, newIp, adapter->IfIndex); + addNewIp(results, name, addressBuffer, AF_INET6, newIp, adapter->IfIndex == defaultRouteIfIndex); newIp = false; } } } - uint32_t ifIndex; - if (ffNetifGetDefaultRoute(&ifIndex)) - { - FF_LIST_FOR_EACH(FFLocalIpResult, ip, *results) - { - if (ip->ifIndex != ifIndex) continue; - ip->defaultRoute = true; - } - } - return NULL; } diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 705a6c902f..c96b098063 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -86,9 +86,6 @@ void ffPrintLocalIp(FFLocalIpOptions* options) FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) { - if (options->defaultRouteOnly && !ip->defaultRoute) - continue; - if (flag) fputs(" - ", stdout); else @@ -104,9 +101,6 @@ void ffPrintLocalIp(FFLocalIpOptions* options) FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) { - if (options->defaultRouteOnly && !ip->defaultRoute) - continue; - formatKey(options, ip, results.length == 1 ? 0 : index + 1, &key); if(options->moduleArgs.outputFormat.length == 0) { From 917b049030dcd58b055115c8cf72b85b1503d1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 21:49:01 +0800 Subject: [PATCH 177/198] LocalIP: cache default route value --- CMakeLists.txt | 1 + src/common/netif/netif.c | 35 +++++++++++++++++++++++++ src/common/netif/netif.h | 4 +-- src/common/netif/netif_bsd.c | 9 ++++--- src/common/netif/netif_linux.c | 10 ++++--- src/common/netif/netif_windows.c | 2 +- src/detection/localip/localip_linux.c | 15 ++++++----- src/detection/localip/localip_windows.c | 12 ++++----- 8 files changed, 64 insertions(+), 24 deletions(-) create mode 100644 src/common/netif/netif.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c3b47e5cff..f780c91b9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -263,6 +263,7 @@ set(LIBFASTFETCH_SRC src/common/jsonconfig.c src/common/library.c src/common/modules.c + src/common/netif/netif.c src/common/option.c src/common/parsing.c src/common/printing.c diff --git a/src/common/netif/netif.c b/src/common/netif/netif.c new file mode 100644 index 0000000000..a6aed5730c --- /dev/null +++ b/src/common/netif/netif.c @@ -0,0 +1,35 @@ +#include "netif.h" + +#ifndef _WIN32 +#include + +bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]); + +const char* ffNetifGetDefaultRoute() +{ + static char iface[IF_NAMESIZE + 1]; + + if (*(uint16_t*) iface == 0) + { + if (!ffNetifGetDefaultRouteImpl(iface)) + iface[1] = 1; + } + + return iface; +} +#else +bool ffNetifGetDefaultRouteImpl(uint32_t* ifIndex); + +uint32_t ffNetifGetDefaultRoute() +{ + static uint32_t ifIndex = (uint32_t) -1; + + if (ifIndex == (uint32_t) -1) + { + if (!ffNetifGetDefaultRouteImpl(&ifIndex)) + ifIndex = (uint32_t) -2; + } + + return ifIndex; +} +#endif diff --git a/src/common/netif/netif.h b/src/common/netif/netif.h index c515df2793..5b20e16f82 100644 --- a/src/common/netif/netif.h +++ b/src/common/netif/netif.h @@ -3,7 +3,7 @@ #include "fastfetch.h" #ifndef _WIN32 -bool ffNetifGetDefaultRoute(FFstrbuf* iface); +const char* ffNetifGetDefaultRoute(); #else -bool ffNetifGetDefaultRoute(uint32_t* ifIndex); +uint32_t ffNetifGetDefaultRoute(); #endif diff --git a/src/common/netif/netif_bsd.c b/src/common/netif/netif_bsd.c index f001773928..fcd657a303 100644 --- a/src/common/netif/netif_bsd.c +++ b/src/common/netif/netif_bsd.c @@ -2,6 +2,7 @@ #include "common/io/io.h" +#include #include #include #include @@ -38,9 +39,7 @@ get_rt_address(struct rt_msghdr *rtm, int desired) return NULL; } - - -bool ffNetifGetDefaultRoute(FFstrbuf* iface) +bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]) { //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 @@ -86,7 +85,9 @@ bool ffNetifGetDefaultRoute(FFstrbuf* iface) struct sockaddr_dl* sdl = (struct sockaddr_dl *)get_rt_address(&rtmsg.hdr, RTA_IFP); if (sdl) { - ffStrbufSetNS(iface, sdl->sdl_nlen, sdl->sdl_data); + assert(sdl->sdl_nlen <= IF_NAMESIZE); + memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); + iface[sdl->sdl_nlen] = '\0'; return true; } return false; diff --git a/src/common/netif/netif_linux.c b/src/common/netif/netif_linux.c index 299fd6034b..f8b323b67d 100644 --- a/src/common/netif/netif_linux.c +++ b/src/common/netif/netif_linux.c @@ -1,9 +1,13 @@ #include "netif.h" #include "common/io/io.h" +#include #include -bool ffNetifGetDefaultRoute(FFstrbuf* iface) +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + +bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]) { FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); if (!netRoute) return false; @@ -14,11 +18,9 @@ bool ffNetifGetDefaultRoute(FFstrbuf* iface) funlockfile(netRoute); unsigned long long destination; //, gateway, flags, refCount, use, metric, mask, mtu, - char buf[16 /*IF_NAMESIZE*/ + 1]; - while (fscanf(netRoute, "%16s%llx%*[^\n]", buf, &destination) == 2) + while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2) { if (destination != 0) continue; - ffStrbufSetS(iface, buf); return true; } return false; diff --git a/src/common/netif/netif_windows.c b/src/common/netif/netif_windows.c index d48cdbac8e..3fc80ecba2 100644 --- a/src/common/netif/netif_windows.c +++ b/src/common/netif/netif_windows.c @@ -3,7 +3,7 @@ #include -bool ffNetifGetDefaultRoute(uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImpl(uint32_t* ifIndex) { ULONG size = 0; if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER) diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 195ab2ae0e..38cec42336 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -1,6 +1,7 @@ #include "localip.h" #include "common/io/io.h" #include "common/netif/netif.h" +#include "util/stringUtils.h" #include #include @@ -56,15 +57,15 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if(getifaddrs(&ifAddrStruct) < 0) return "getifaddrs(&ifAddrStruct) failed"; - FF_STRBUF_AUTO_DESTROY defaultRouteIface = ffStrbufCreate(); - ffNetifGetDefaultRoute(&defaultRouteIface); + const char* defaultRouteIface = ffNetifGetDefaultRoute(); for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING)) continue; - if (options->defaultRouteOnly && !ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)) + bool isDefaultRoute = ffStrEquals(defaultRouteIface, ifa->ifa_name); + if (options->defaultRouteOnly && !isDefaultRoute) continue; if ((ifa->ifa_flags & IFF_LOOPBACK) && !(options->showType & FF_LOCALIP_TYPE_LOOP_BIT)) @@ -81,7 +82,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) 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, AF_INET, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute); } else if (ifa->ifa_addr->sa_family == AF_INET6) { @@ -91,7 +92,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) 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, AF_INET6, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute); } #if defined(__FreeBSD__) || defined(__APPLE__) else if (ifa->ifa_addr->sa_family == AF_LINK) @@ -103,7 +104,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = (uint8_t*) LLADDR((struct sockaddr_dl *)ifa->ifa_addr); snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, ifa->ifa_name, addressBuffer, -1, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute); } #else else if (ifa->ifa_addr->sa_family == AF_PACKET) @@ -115,7 +116,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = ((struct sockaddr_ll *)ifa->ifa_addr)->sll_addr; snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, ifa->ifa_name, addressBuffer, -1, ffStrbufEqualS(&defaultRouteIface, ifa->ifa_name)); + addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute); } #endif } diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 78552be5b4..8863843fd3 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -70,13 +70,13 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) return "GetAdaptersAddresses() failed"; } - uint32_t defaultRouteIfIndex = (uint32_t)-1; - ffNetifGetDefaultRoute(&defaultRouteIfIndex); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRoute(); // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) { - if (options->defaultRouteOnly && adapter->IfIndex != defaultRouteIfIndex) + bool isDefaultRoute = adapter->IfIndex == defaultRouteIfIndex; + if (options->defaultRouteOnly && !isDefaultRoute) continue; bool isLoop = adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK; @@ -96,7 +96,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) uint8_t* ptr = adapter->PhysicalAddress; snprintf(addressBuffer, sizeof(addressBuffer), "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); - addNewIp(results, name, addressBuffer, -1, newIp, adapter->IfIndex == defaultRouteIfIndex); + addNewIp(results, name, addressBuffer, -1, newIp, isDefaultRoute); newIp = false; } @@ -107,7 +107,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr; char addressBuffer[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN); - addNewIp(results, name, addressBuffer, AF_INET, newIp, adapter->IfIndex == defaultRouteIfIndex); + addNewIp(results, name, addressBuffer, AF_INET, newIp, isDefaultRoute); newIp = false; } else if (ifa->Address.lpSockaddr->sa_family == AF_INET6) @@ -115,7 +115,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr; char addressBuffer[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN); - addNewIp(results, name, addressBuffer, AF_INET6, newIp, adapter->IfIndex == defaultRouteIfIndex); + addNewIp(results, name, addressBuffer, AF_INET6, newIp, isDefaultRoute); newIp = false; } } From b29b78b321e584ea716e5624cc4c968f1ccdbcac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 22:34:37 +0800 Subject: [PATCH 178/198] NetUsage: finish module --- doc/json_schema.json | 31 +++++++++++++++ src/common/commandoption.c | 2 +- src/common/jsonconfig.c | 8 ++++ src/detection/netusage/netusage.c | 16 ++++---- src/detection/netusage/netusage.h | 3 +- src/detection/netusage/netusage_bsd.c | 20 ++++++++-- src/detection/netusage/netusage_linux.c | 16 +++++++- src/detection/netusage/netusage_windows.c | 18 +++++++-- src/modules/netusage/netusage.c | 47 +++++++++++++++++++++-- src/modules/netusage/netusage.h | 2 +- src/modules/netusage/option.h | 3 ++ src/util/FFstrbuf.h | 2 +- 12 files changed, 145 insertions(+), 23 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 4151686dc1..7623f0a02c 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -558,6 +558,7 @@ "media", "memory", "monitor", + "netusage", "opencl", "opengl", "os", @@ -1019,6 +1020,36 @@ }, "additionalProperties": false }, + { + "title": "Network throughput (usage)", + "properties": { + "type": { + "const": "netusage" + }, + "namePrefix": { + "title": "Show IPs with given name prefix only", + "type": "string" + }, + "defaultRouteOnly": { + "title": "Show ips that are used for default routing only", + "type": "boolean", + "default": false + }, + "key": { + "$ref": "#/$defs/key" + }, + "keyColor": { + "$ref": "#/$defs/keyColor" + }, + "keyWidth": { + "$ref": "#/$defs/keyWidth" + }, + "format": { + "$ref": "#/$defs/format" + } + }, + "additionalProperties": false + }, { "title": "OpenGL", "properties": { diff --git a/src/common/commandoption.c b/src/common/commandoption.c index 6454f51e96..45369a1637 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -61,7 +61,7 @@ void ffPrepareCommandOption(FFdata* data) ffPrepareCPUUsage(); if(ffStrbufContainIgnCaseS(&data->structure, FF_NETUSAGE_MODULE_NAME)) - ffPrepareNetUsage(); + ffPrepareNetUsage(&instance.config.netUsage); if(instance.config.multithreading) { diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 0b257be53a..5d6027f4ab 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -112,6 +112,14 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) ffPrepareCPUUsage(); break; } + case 'n': case 'N': { + if (ffStrEqualsIgnCase(type, FF_NETUSAGE_MODULE_NAME)) + { + if (module) ffParseNetUsageJsonObject(&cfg->netUsage, module); + ffPrepareNetUsage(&cfg->netUsage); + } + break; + } case 'p': case 'P': { if (ffStrEqualsIgnCase(type, FF_PUBLICIP_MODULE_NAME)) { diff --git a/src/detection/netusage/netusage.c b/src/detection/netusage/netusage.c index af885edb26..88888c28a8 100644 --- a/src/detection/netusage/netusage.c +++ b/src/detection/netusage/netusage.c @@ -2,31 +2,33 @@ #include "common/time.h" -const char* ffNetUsageGetIoCounters(FFlist* result); +const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options); static FFlist ioCounters1; static uint64_t time1; -void ffPrepareNetUsage(void) +void ffPrepareNetUsage(FFNetUsageOptions* options) { ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); - ffNetUsageGetIoCounters(&ioCounters1); + ffNetUsageGetIoCounters(&ioCounters1, options); time1 = ffTimeGetNow(); } -const char* ffDetectNetUsage(FFlist* result) +const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options) { const char* error = NULL; if (time1 == 0) { ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); - error = ffNetUsageGetIoCounters(&ioCounters1); + error = ffNetUsageGetIoCounters(&ioCounters1, options); if (error) return error; time1 = ffTimeGetNow(); - ffTimeSleep(1000); } + if (ioCounters1.length == 0) + return "No network interfaces found"; + uint64_t time2 = ffTimeGetNow(); while (time2 - time1 < 1000) { @@ -34,7 +36,7 @@ const char* ffDetectNetUsage(FFlist* result) time2 = ffTimeGetNow(); } - error = ffNetUsageGetIoCounters(result); + error = ffNetUsageGetIoCounters(result, options); if (error) return error; diff --git a/src/detection/netusage/netusage.h b/src/detection/netusage/netusage.h index 35a95367f4..bb6234ee1a 100644 --- a/src/detection/netusage/netusage.h +++ b/src/detection/netusage/netusage.h @@ -3,6 +3,7 @@ typedef struct FFNetUsageIoCounters { FFstrbuf name; + bool defaultRoute; uint64_t txBytes; uint64_t rxBytes; uint64_t txPackets; @@ -13,4 +14,4 @@ typedef struct FFNetUsageIoCounters uint64_t txDrops; } FFNetUsageIoCounters; -const char* ffDetectNetUsage(FFlist* result); +const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options); diff --git a/src/detection/netusage/netusage_bsd.c b/src/detection/netusage/netusage_bsd.c index ffd430dfa7..c6ec58a3e5 100644 --- a/src/detection/netusage/netusage_bsd.c +++ b/src/detection/netusage/netusage_bsd.c @@ -1,6 +1,7 @@ #include "netusage.h" #include "common/io/io.h" +#include "common/netif/netif.h" #include "util/mallocHelper.h" #include @@ -10,7 +11,7 @@ #include #include -const char* ffNetUsageGetIoCounters(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) { size_t bufSize = 0; if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) @@ -20,6 +21,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result) if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) < 0) return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) failed"; + const char* defaultRouteIface = ffNetifGetDefaultRoute(); + for (struct if_msghdr2* ifm = buf; ifm < (struct if_msghdr2*) ((uint8_t*) buf + bufSize); ifm = (struct if_msghdr2*) ((uint8_t*) ifm + ifm->ifm_msglen)) @@ -29,9 +32,19 @@ const char* ffNetUsageGetIoCounters(FFlist* result) struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1); assert(sdl->sdl_family == AF_LINK); if (sdl->sdl_type != IFT_ETHER && !(ifm->ifm_flags & IFF_LOOPBACK)) continue; - FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); + sdl->sdl_data[sdl->sdl_nlen] = 0; + + bool isDefaultRoute = ffStrEquals(sdl->sdl_data, defaultRouteIface); + if(options->defaultRouteOnly && !isDefaultRoute) + continue; + + if (options->namePrefix.length && strncmp(sdl->sdl_data, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + + FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); *counters = (FFNetUsageIoCounters) { + .name = ffStrbufCreateNS(sdl->sdl_nlen, sdl->sdl_data), .txBytes = ifm->ifm_data.ifi_obytes, .rxBytes = ifm->ifm_data.ifi_ibytes, .txPackets = ifm->ifm_data.ifi_opackets, @@ -40,9 +53,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result) .rxErrors = ifm->ifm_data.ifi_ierrors, .txDrops = 0, // unsupported .rxDrops = ifm->ifm_data.ifi_iqdrops, + .defaultRoute = isDefaultRoute, }; - - ffStrbufInitNS(&counters->name, sdl->sdl_nlen, sdl->sdl_data); } return NULL; diff --git a/src/detection/netusage/netusage_linux.c b/src/detection/netusage/netusage_linux.c index aea66b4634..a5d64be5b0 100644 --- a/src/detection/netusage/netusage_linux.c +++ b/src/detection/netusage/netusage_linux.c @@ -1,10 +1,12 @@ #include "netusage.h" #include "common/io/io.h" +#include "common/netif/netif.h" +#include "util/stringUtils.h" #include -const char* ffNetUsageGetIoCounters(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) { FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net"); if (!dirp) return "opendir(\"/sys/class/net\") == NULL"; @@ -12,20 +14,30 @@ const char* ffNetUsageGetIoCounters(FFlist* result) FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + const char* defaultRouteIface = ffNetifGetDefaultRoute(); + struct dirent* entry; while((entry = readdir(dirp)) != NULL) { if(entry->d_name[0] == '.') continue; + bool isDefaultRoute = ffStrEquals(entry->d_name, defaultRouteIface); + if(options->defaultRouteOnly && !isDefaultRoute) + continue; + + if (options->namePrefix.length && strncmp(entry->d_name, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + ffStrbufSetF(&path, "/sys/class/net/%s/operstate", entry->d_name); if(!ffReadFileBuffer(path.chars, &buffer) || !ffStrbufEqualS(&buffer, "up")) continue; FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); ffStrbufInitS(&counters->name, entry->d_name); + counters->defaultRoute = isDefaultRoute; - ffStrbufSetF(&path, "/sys/class/net/%s/statistics/"); + ffStrbufSetF(&path, "/sys/class/net/%s/statistics/", entry->d_name); uint32_t statLen = path.length; ffStrbufAppendS(&path, "rx_bytes"); diff --git a/src/detection/netusage/netusage_windows.c b/src/detection/netusage/netusage_windows.c index 1604b61de7..b9d45f3e77 100644 --- a/src/detection/netusage/netusage_windows.c +++ b/src/detection/netusage/netusage_windows.c @@ -1,13 +1,13 @@ #include "netusage.h" -#include "common/io/io.h" +#include "common/netif/netif.h" #include "util/mallocHelper.h" #include "util/windows/unicode.h" #include #include -const char* ffNetUsageGetIoCounters(FFlist* result) +const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) { IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL; @@ -37,14 +37,26 @@ const char* ffNetUsageGetIoCounters(FFlist* result) return "GetAdaptersAddresses() failed"; } + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRoute(); + // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) { + bool isDefaultRoute = adapter->IfIndex == defaultRouteIfIndex; + if (options->defaultRouteOnly && !isDefaultRoute) + continue; + + char name[128]; + WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, name, sizeof(name), NULL, NULL); + if (options->namePrefix.length && strncmp(name, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + MIB_IF_ROW2 ifRow = { .InterfaceIndex = adapter->IfIndex }; if (GetIfEntry2(&ifRow) == NO_ERROR) { FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); *counters = (FFNetUsageIoCounters) { + .name = ffStrbufCreateS(name), .txBytes = ifRow.OutOctets, .rxBytes = ifRow.InOctets, .txPackets = (ifRow.OutUcastPkts + ifRow.OutNUcastPkts), @@ -53,8 +65,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result) .txErrors = ifRow.OutErrors, .rxDrops = ifRow.InDiscards, .txDrops = ifRow.OutDiscards, + .defaultRoute = isDefaultRoute, }; - ffStrbufSetWS(&counters->name, adapter->FriendlyName); } } diff --git a/src/modules/netusage/netusage.c b/src/modules/netusage/netusage.c index 51a3c1f6b1..75e0bfdf2f 100644 --- a/src/modules/netusage/netusage.c +++ b/src/modules/netusage/netusage.c @@ -35,7 +35,7 @@ static void formatKey(const FFNetUsageOptions* options, FFNetUsageIoCounters* in void ffPrintNetUsage(FFNetUsageOptions* options) { FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); - const char* error = ffDetectNetUsage(&result); + const char* error = ffDetectNetUsage(&result, options); if(error) { @@ -63,6 +63,8 @@ void ffPrintNetUsage(FFNetUsageOptions* options) ffStrbufAppendS(&buffer, "/s (in) - "); ffParseSize(inf->txBytes, &buffer); ffStrbufAppendS(&buffer, "/s (out)"); + if (!options->defaultRouteOnly && inf->defaultRoute) + ffStrbufAppendS(&buffer, " *"); ffStrbufPutTo(&buffer, stdout); } else @@ -82,16 +84,25 @@ void ffPrintNetUsage(FFNetUsageOptions* options) {FF_FORMAT_ARG_TYPE_UINT64, &inf->txErrors}, {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxDrops}, {FF_FORMAT_ARG_TYPE_UINT64, &inf->txDrops}, + {FF_FORMAT_ARG_TYPE_BOOL, &inf->defaultRoute}, }); } ++index; } + + FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) + { + ffStrbufDestroy(&inf->name); + } } void ffInitNetUsageOptions(FFNetUsageOptions* options) { ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETUSAGE_MODULE_NAME, ffParseNetUsageCommandOptions, ffParseNetUsageJsonObject, ffPrintNetUsage, ffGenerateNetUsageJson); ffOptionInitModuleArg(&options->moduleArgs); + + ffStrbufInit(&options->namePrefix); + options->defaultRouteOnly = false; } bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value) @@ -101,12 +112,25 @@ bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; + if (ffStrEqualsIgnCase(subKey, "name-prefix")) + { + ffOptionParseString(key, value, &options->namePrefix); + return true; + } + + if (ffStrEqualsIgnCase(subKey, "default-route-only")) + { + options->defaultRouteOnly = ffOptionParseBoolean(value); + return true; + } + return false; } void ffDestroyNetUsageOptions(FFNetUsageOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); + ffStrbufDestroy(&options->namePrefix); } void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module) @@ -122,14 +146,26 @@ void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module) if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) continue; + if (ffStrEqualsIgnCase(key, "namePrefix")) + { + ffStrbufSetS(&options->namePrefix, yyjson_get_str(val)); + continue; + } + + if (ffStrEqualsIgnCase(key, "defaultRouteOnly")) + { + options->defaultRouteOnly = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_NETUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } -void ffGenerateNetUsageJson(FF_MAYBE_UNUSED FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); - const char* error = ffDetectNetUsage(&result); + const char* error = ffDetectNetUsage(&result, options); if(error) { @@ -150,6 +186,11 @@ void ffGenerateNetUsageJson(FF_MAYBE_UNUSED FFNetUsageOptions* options, yyjson_m yyjson_mut_obj_add_uint(doc, obj, "txErrors", counter->txErrors); yyjson_mut_obj_add_uint(doc, obj, "rxDrops", counter->rxDrops); yyjson_mut_obj_add_uint(doc, obj, "txDrops", counter->txDrops); + yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", counter->defaultRoute); + } + FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) + { + ffStrbufDestroy(&inf->name); } } diff --git a/src/modules/netusage/netusage.h b/src/modules/netusage/netusage.h index 4067d68993..4feaee10a1 100644 --- a/src/modules/netusage/netusage.h +++ b/src/modules/netusage/netusage.h @@ -4,7 +4,7 @@ #define FF_NETUSAGE_MODULE_NAME "NetUsage" -void ffPrepareNetUsage(); +void ffPrepareNetUsage(FFNetUsageOptions* options); void ffPrintNetUsage(FFNetUsageOptions* options); void ffInitNetUsageOptions(FFNetUsageOptions* options); diff --git a/src/modules/netusage/option.h b/src/modules/netusage/option.h index 59463249fb..ff436aaf23 100644 --- a/src/modules/netusage/option.h +++ b/src/modules/netusage/option.h @@ -8,4 +8,7 @@ typedef struct FFNetUsageOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; + + FFstrbuf namePrefix; + bool defaultRouteOnly; } FFNetUsageOptions; diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 77db4be967..9a28bafb4e 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -50,7 +50,7 @@ void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value); void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value); void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value); -void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...); +FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufTrimLeft(FFstrbuf* strbuf, char c); void ffStrbufTrimRight(FFstrbuf* strbuf, char c); From b4f29918ede5d724de5de9fef7e94f8a7f408e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 23:18:19 +0800 Subject: [PATCH 179/198] NetUsage: finish docs --- CHANGELOG.md | 1 + README.md | 2 +- presets/all | 2 +- presets/all.jsonc | 1 + src/data/config_user.txt | 3 +++ src/data/help.txt | 6 ++++-- src/fastfetch.c | 25 +++++++++++++++++++------ src/modules/localip/localip.c | 2 +- src/modules/netusage/netusage.c | 11 +++++++---- 9 files changed, 38 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1167b9e1b1..f133d54494 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Features: * Add `-c` as a shortcut of `--load-config`. Note it was used as the shortcut of `--color` before 2.0.5 * Support Windows Service Pack version detection (Kernel, Windows) * Support Debian point releases detection (OS, Linux) +* Add new module `NetUsage` which prints network throughput (usage) of specified interface. Note this module costs about 1 second to finish. Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/README.md b/README.md index 2233edf420..5aefedd3ab 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetUsage, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme ``` ##### Builtin logos diff --git a/presets/all b/presets/all index 1841c47ca6..804589d811 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Version:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetUsage:Version:Break:Colors diff --git a/presets/all.jsonc b/presets/all.jsonc index b3e9c30d95..27c9f6d42c 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -51,6 +51,7 @@ "sound", "gamepad", "weather", + "netusage", "version", "break", "colors" diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 9d3be57960..aed51c7238 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -370,6 +370,7 @@ #--lm-key LM #--locale-key Locale #--localip-key Local IP ({1}) +#--netusage-key Net Usage ({1}) #--publicip-key Public IP #--wifi-key Wifi #--weather-key Weather @@ -422,6 +423,7 @@ #--lm-format #--locale-format #--localip-format +#--netusage-format #--publicip-format #--weather-format #--monitor-format @@ -471,6 +473,7 @@ #--lm-key-color #--locale-key-color #--localip-key-color +#--netusage-key-color #--publicip-key-color #--weather-key-color #--monitor-key-color diff --git a/src/data/help.txt b/src/data/help.txt index eb975f7865..36617c00a5 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -147,9 +147,11 @@ Module specific options: --localip-show-ipv6 : Show IPv6 addresses in local ip module. Default is false --localip-show-mac : Show mac addresses in local ip module. Default is false --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false - --localip-name-prefix : Show IPs with given name prefix only. Default is empty - --localip-default-route-only : Show ips that are used for default routing only. Default is false + --localip-name-prefix : Show interfaces with given interface name prefix only. Default is empty + --localip-default-route-only : Show the interface that is used for default routing only. Default is false --localip-compact : Show all IPs in one line. Default is false + --netusage-name-prefix : Show interfaces with given name prefix only. Default is empty + --netusage-default-route-only : Show the interfac that is used for default routing only. Default is false --publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) --publicip-url: The URL of public IP detection server to be used. --weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`). diff --git a/src/fastfetch.c b/src/fastfetch.c index eafb1de61f..bdd2fdf527 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -381,18 +381,31 @@ static inline void printCommandHelp(const char* command) "Locale code" ); } - else if(ffStrEqualsIgnCase(command, "local-ip-format")) - { - constructAndPrintCommandHelpFormat("local-ip", "{}", 1, - "Local IP address" + else if(ffStrEqualsIgnCase(command, "localip-format")) + { + constructAndPrintCommandHelpFormat("localip", "{}", 5, + "Local IPv4 address", + "Local IPv6 address", + "Physical (MAC) address", + "Interface name", + "Is default route" ); } - else if(ffStrEqualsIgnCase(command, "public-ip-format")) + else if(ffStrEqualsIgnCase(command, "publicip-format")) { - constructAndPrintCommandHelpFormat("public-ip", "{}", 1, + constructAndPrintCommandHelpFormat("publicip", "{}", 1, "Public IP address" ); } + else if(ffStrEqualsIgnCase(command, "netusage-format")) + { + constructAndPrintCommandHelpFormat("netusage", "{}", 3, + "Size of data received per second (formatted)", + "Size of data sent per second (formatted)", + "Interface name", + "Is default route" + ); + } else if(ffStrEqualsIgnCase(command, "wifi-format")) { constructAndPrintCommandHelpFormat("wifi", "{4} - {6}", 3, diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index c96b098063..36013d5058 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -5,7 +5,7 @@ #include "util/stringUtils.h" #define FF_LOCALIP_DISPLAY_NAME "Local IP" -#define FF_LOCALIP_NUM_FORMAT_ARGS 2 +#define FF_LOCALIP_NUM_FORMAT_ARGS 5 #pragma GCC diagnostic ignored "-Wsign-conversion" static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) diff --git a/src/modules/netusage/netusage.c b/src/modules/netusage/netusage.c index 75e0bfdf2f..2ae67a7040 100644 --- a/src/modules/netusage/netusage.c +++ b/src/modules/netusage/netusage.c @@ -6,7 +6,7 @@ #include "util/stringUtils.h" #define FF_NETUSAGE_DISPLAY_NAME "Net Usage" -#define FF_NETUSAGE_NUM_FORMAT_ARGS 1 +#define FF_NETUSAGE_NUM_FORMAT_ARGS 12 static int sortInfs(const FFNetUsageIoCounters* left, const FFNetUsageIoCounters* right) { @@ -71,11 +71,15 @@ void ffPrintNetUsage(FFNetUsageOptions* options) { ffStrbufClear(&buffer2); ffParseSize(inf->rxBytes, &buffer); + ffStrbufAppendS(&buffer, "/s"); ffParseSize(inf->txBytes, &buffer2); + ffStrbufAppendS(&buffer2, "/s"); + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_NETUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, &inf->name}, {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, + {FF_FORMAT_ARG_TYPE_STRBUF, &inf->name}, + {FF_FORMAT_ARG_TYPE_BOOL, &inf->defaultRoute}, {FF_FORMAT_ARG_TYPE_UINT64, &inf->txBytes}, {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxBytes}, {FF_FORMAT_ARG_TYPE_UINT64, &inf->txPackets}, @@ -84,7 +88,6 @@ void ffPrintNetUsage(FFNetUsageOptions* options) {FF_FORMAT_ARG_TYPE_UINT64, &inf->txErrors}, {FF_FORMAT_ARG_TYPE_UINT64, &inf->rxDrops}, {FF_FORMAT_ARG_TYPE_UINT64, &inf->txDrops}, - {FF_FORMAT_ARG_TYPE_BOOL, &inf->defaultRoute}, }); } ++index; @@ -178,6 +181,7 @@ void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyj { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name); + yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", counter->defaultRoute); yyjson_mut_obj_add_uint(doc, obj, "txBytes", counter->txBytes); yyjson_mut_obj_add_uint(doc, obj, "rxBytes", counter->rxBytes); yyjson_mut_obj_add_uint(doc, obj, "txPackets", counter->txPackets); @@ -186,7 +190,6 @@ void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyj yyjson_mut_obj_add_uint(doc, obj, "txErrors", counter->txErrors); yyjson_mut_obj_add_uint(doc, obj, "rxDrops", counter->rxDrops); yyjson_mut_obj_add_uint(doc, obj, "txDrops", counter->txDrops); - yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", counter->defaultRoute); } FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) From 3866f27448d61d670310cc1706abdd4a74dbce53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Sep 2023 23:58:05 +0800 Subject: [PATCH 180/198] NetUsage (BSD): fix compiling --- src/detection/netusage/netusage_bsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/netusage/netusage_bsd.c b/src/detection/netusage/netusage_bsd.c index c6ec58a3e5..b5fd61083a 100644 --- a/src/detection/netusage/netusage_bsd.c +++ b/src/detection/netusage/netusage_bsd.c @@ -2,6 +2,7 @@ #include "common/io/io.h" #include "common/netif/netif.h" +#include "util/stringUtils.h" #include "util/mallocHelper.h" #include From 154657b455a92f41faef6cc56aa3fb59446f2464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 00:05:37 +0800 Subject: [PATCH 181/198] NetUsage: rename to NetIO --- CHANGELOG.md | 2 +- CMakeLists.txt | 12 ++-- README.md | 2 +- doc/json_schema.json | 4 +- presets/all | 2 +- presets/all.jsonc | 2 +- src/common/commandoption.c | 4 +- src/common/init.c | 4 +- src/common/jsonconfig.c | 6 +- src/common/modules.c | 2 +- src/data/config_user.txt | 6 +- src/data/help.txt | 4 +- src/detection/gamepad/gamepad_windows.c | 2 +- .../{netusage/netusage.c => netio/netio.c} | 26 ++++----- .../{netusage/netusage.h => netio/netio.h} | 6 +- .../netusage_bsd.c => netio/netio_bsd.c} | 8 +-- .../netusage_linux.c => netio/netio_linux.c} | 6 +- .../netio_windows.c} | 8 +-- src/fastfetch.c | 4 +- src/fastfetch.h | 2 +- src/modules/modules.h | 2 +- .../{netusage/netusage.c => netio/netio.c} | 56 +++++++++---------- src/modules/netio/netio.h | 14 +++++ src/modules/{netusage => netio}/option.h | 4 +- src/modules/netusage/netusage.h | 14 ----- src/modules/options.h | 2 +- 26 files changed, 102 insertions(+), 102 deletions(-) rename src/detection/{netusage/netusage.c => netio/netio.c} (55%) rename src/detection/{netusage/netusage.h => netio/netio.h} (65%) rename src/detection/{netusage/netusage_bsd.c => netio/netio_bsd.c} (90%) rename src/detection/{netusage/netusage_linux.c => netio/netio_linux.c} (93%) rename src/detection/{netusage/netusage_windows.c => netio/netio_windows.c} (90%) rename src/modules/{netusage/netusage.c => netio/netio.c} (70%) create mode 100644 src/modules/netio/netio.h rename src/modules/{netusage => netio}/option.h (81%) delete mode 100644 src/modules/netusage/netusage.h diff --git a/CHANGELOG.md b/CHANGELOG.md index f133d54494..7c1cc3c754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ Features: * Add `-c` as a shortcut of `--load-config`. Note it was used as the shortcut of `--color` before 2.0.5 * Support Windows Service Pack version detection (Kernel, Windows) * Support Debian point releases detection (OS, Linux) -* Add new module `NetUsage` which prints network throughput (usage) of specified interface. Note this module costs about 1 second to finish. +* Add new module `NetIO` which prints network throughput (usage) of specified interface. Note this module costs about 1 second to finish. Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/CMakeLists.txt b/CMakeLists.txt index f780c91b9f..6b4292475d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -278,7 +278,7 @@ set(LIBFASTFETCH_SRC src/detection/gpu/gpu.c src/detection/locale/locale.c src/detection/media/media.c - src/detection/netusage/netusage.c + src/detection/netio/netio.c src/detection/opencl/opencl.c src/detection/os/os.c src/detection/packages/packages.c @@ -321,7 +321,7 @@ set(LIBFASTFETCH_SRC src/modules/localip/localip.c src/modules/memory/memory.c src/modules/monitor/monitor.c - src/modules/netusage/netusage.c + src/modules/netio/netio.c src/modules/opencl/opencl.c src/modules/opengl/opengl.c src/modules/os/os.c @@ -391,7 +391,7 @@ if(LINUX) src/detection/media/media_linux.c src/detection/memory/memory_linux.c src/detection/monitor/monitor_linux.c - src/detection/netusage/netusage_linux.c + src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c src/detection/packages/packages_linux.c @@ -492,7 +492,7 @@ elseif(BSD) src/detection/media/media_linux.c src/detection/memory/memory_bsd.c src/detection/monitor/monitor_nosupport.c - src/detection/netusage/netusage_bsd.c + src/detection/netio/netio_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c src/detection/packages/packages_linux.c @@ -541,7 +541,7 @@ elseif(APPLE) src/detection/media/media_apple.m src/detection/memory/memory_apple.c src/detection/monitor/monitor_apple.m - src/detection/netusage/netusage_bsd.c + src/detection/netio/netio_bsd.c src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m src/detection/packages/packages_apple.c @@ -590,7 +590,7 @@ elseif(WIN32) src/detection/media/media_nosupport.c src/detection/memory/memory_windows.c src/detection/monitor/monitor_windows.c - src/detection/netusage/netusage_windows.c + src/detection/netio/netio_windows.c src/detection/opengl/opengl_windows.c src/detection/os/os_windows.cpp src/detection/packages/packages_windows.c diff --git a/README.md b/README.md index 5aefedd3ab..b38e37b956 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ All categories not listed here should work without needing a specific implementa ##### Available Modules ``` -Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetUsage, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme +Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsage, Cursor, Custom, Date, DateTime, DE, Disk, Display, Font, Gamepad, GPU, Host, Icons, Kernel, LM, Locale, LocalIP, Media, Memory, Monitor, NetIO, OpenCL, OpenGL, OS, Packages, Player, Power Adapter, Processes, PublicIP, Separator, Shell, Sound, Swap, Terminal, Terminal Font, Terminal Size, Theme, Time, Title, Uptime, Version, Vulkan, Wallpaper, Weather, Wifi, WM, WMTheme ``` ##### Builtin logos diff --git a/doc/json_schema.json b/doc/json_schema.json index 7623f0a02c..d7e681566c 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -558,7 +558,7 @@ "media", "memory", "monitor", - "netusage", + "netio", "opencl", "opengl", "os", @@ -1024,7 +1024,7 @@ "title": "Network throughput (usage)", "properties": { "type": { - "const": "netusage" + "const": "netio" }, "namePrefix": { "title": "Show IPs with given name prefix only", diff --git a/presets/all b/presets/all index 804589d811..b0ed3cab52 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetUsage:Version:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:Monitor:LM:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Wallpaper:Terminal:TerminalFont:TerminalSize:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:NetIO:Version:Break:Colors diff --git a/presets/all.jsonc b/presets/all.jsonc index 27c9f6d42c..f8d4cc82ed 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -51,7 +51,7 @@ "sound", "gamepad", "weather", - "netusage", + "netio", "version", "break", "colors" diff --git a/src/common/commandoption.c b/src/common/commandoption.c index 45369a1637..e8a7e8001d 100644 --- a/src/common/commandoption.c +++ b/src/common/commandoption.c @@ -60,8 +60,8 @@ void ffPrepareCommandOption(FFdata* data) if(ffStrbufContainIgnCaseS(&data->structure, FF_CPUUSAGE_MODULE_NAME)) ffPrepareCPUUsage(); - if(ffStrbufContainIgnCaseS(&data->structure, FF_NETUSAGE_MODULE_NAME)) - ffPrepareNetUsage(&instance.config.netUsage); + if(ffStrbufContainIgnCaseS(&data->structure, FF_NETIO_MODULE_NAME)) + ffPrepareNetIO(&instance.config.netIo); if(instance.config.multithreading) { diff --git a/src/common/init.c b/src/common/init.c index 490e4d0b5e..35f1467fc4 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -106,7 +106,7 @@ static void defaultConfig(void) ffInitMediaOptions(&instance.config.media); ffInitMemoryOptions(&instance.config.memory); ffInitMonitorOptions(&instance.config.monitor); - ffInitNetUsageOptions(&instance.config.netUsage); + ffInitNetIOOptions(&instance.config.netIo); ffInitOSOptions(&instance.config.os); ffInitOpenCLOptions(&instance.config.openCL); ffInitOpenGLOptions(&instance.config.openGL); @@ -320,7 +320,7 @@ static void destroyConfig(void) ffDestroyMediaOptions(&instance.config.media); ffDestroyMemoryOptions(&instance.config.memory); ffDestroyMonitorOptions(&instance.config.monitor); - ffDestroyNetUsageOptions(&instance.config.netUsage); + ffDestroyNetIOOptions(&instance.config.netIo); ffDestroyOSOptions(&instance.config.os); ffDestroyOpenCLOptions(&instance.config.openCL); ffDestroyOpenGLOptions(&instance.config.openGL); diff --git a/src/common/jsonconfig.c b/src/common/jsonconfig.c index 5d6027f4ab..6d8fee3291 100644 --- a/src/common/jsonconfig.c +++ b/src/common/jsonconfig.c @@ -113,10 +113,10 @@ static void prepareModuleJsonObject(const char* type, yyjson_val* module) break; } case 'n': case 'N': { - if (ffStrEqualsIgnCase(type, FF_NETUSAGE_MODULE_NAME)) + if (ffStrEqualsIgnCase(type, FF_NETIO_MODULE_NAME)) { - if (module) ffParseNetUsageJsonObject(&cfg->netUsage, module); - ffPrepareNetUsage(&cfg->netUsage); + if (module) ffParseNetIOJsonObject(&cfg->netIo, module); + ffPrepareNetIO(&cfg->netIo); } break; } diff --git a/src/common/modules.c b/src/common/modules.c index b83588992c..420903c8ee 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -82,7 +82,7 @@ static FFModuleBaseInfo* M[] = { }; static FFModuleBaseInfo* N[] = { - (void*) &instance.config.netUsage, + (void*) &instance.config.netIo, NULL, }; diff --git a/src/data/config_user.txt b/src/data/config_user.txt index aed51c7238..c8a257ec53 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -370,7 +370,7 @@ #--lm-key LM #--locale-key Locale #--localip-key Local IP ({1}) -#--netusage-key Net Usage ({1}) +#--netio-key Network IO ({1}) #--publicip-key Public IP #--wifi-key Wifi #--weather-key Weather @@ -423,7 +423,7 @@ #--lm-format #--locale-format #--localip-format -#--netusage-format +#--netio-format #--publicip-format #--weather-format #--monitor-format @@ -473,7 +473,7 @@ #--lm-key-color #--locale-key-color #--localip-key-color -#--netusage-key-color +#--netio-key-color #--publicip-key-color #--weather-key-color #--monitor-key-color diff --git a/src/data/help.txt b/src/data/help.txt index 36617c00a5..94ba7f6175 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -150,8 +150,8 @@ Module specific options: --localip-name-prefix : Show interfaces with given interface name prefix only. Default is empty --localip-default-route-only : Show the interface that is used for default routing only. Default is false --localip-compact : Show all IPs in one line. Default is false - --netusage-name-prefix : Show interfaces with given name prefix only. Default is empty - --netusage-default-route-only : Show the interfac that is used for default routing only. Default is false + --netio-name-prefix : Show interfaces with given name prefix only. Default is empty + --netio-default-route-only : Show the interfac that is used for default routing only. Default is false --publicip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is disabled (0) --publicip-url: The URL of public IP detection server to be used. --weather-location: Set the location to be used. It must be URI encoded (eg a whitespace must be encoded as `+`). diff --git a/src/detection/gamepad/gamepad_windows.c b/src/detection/gamepad/gamepad_windows.c index e115782aa9..8a5799717d 100644 --- a/src/detection/gamepad/gamepad_windows.c +++ b/src/detection/gamepad/gamepad_windows.c @@ -130,7 +130,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) if (hHidFile && HidD_GetProductString(hHidFile, displayName, sizeof(wchar_t) * 126)) ffStrbufSetWS(&device->name, displayName); else - ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", rdi.hid.dwVendorId, rdi.hid.dwProductId); + ffStrbufSetF(&device->name, "Unknown gamepad %4X-%4X", (unsigned) rdi.hid.dwVendorId, (unsigned) rdi.hid.dwProductId); } } diff --git a/src/detection/netusage/netusage.c b/src/detection/netio/netio.c similarity index 55% rename from src/detection/netusage/netusage.c rename to src/detection/netio/netio.c index 88888c28a8..5a07af8e2a 100644 --- a/src/detection/netusage/netusage.c +++ b/src/detection/netio/netio.c @@ -1,26 +1,26 @@ -#include "netusage.h" +#include "netio.h" #include "common/time.h" -const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options); +const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options); static FFlist ioCounters1; static uint64_t time1; -void ffPrepareNetUsage(FFNetUsageOptions* options) +void ffPrepareNetIO(FFNetIOOptions* options) { - ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); - ffNetUsageGetIoCounters(&ioCounters1, options); + ffListInit(&ioCounters1, sizeof(FFNetIOResult)); + ffNetIOGetIoCounters(&ioCounters1, options); time1 = ffTimeGetNow(); } -const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options) +const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options) { const char* error = NULL; if (time1 == 0) { - ffListInit(&ioCounters1, sizeof(FFNetUsageIoCounters)); - error = ffNetUsageGetIoCounters(&ioCounters1, options); + ffListInit(&ioCounters1, sizeof(FFNetIOResult)); + error = ffNetIOGetIoCounters(&ioCounters1, options); if (error) return error; time1 = ffTimeGetNow(); @@ -36,7 +36,7 @@ const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options) time2 = ffTimeGetNow(); } - error = ffNetUsageGetIoCounters(result, options); + error = ffNetIOGetIoCounters(result, options); if (error) return error; @@ -45,13 +45,13 @@ const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options) for (uint32_t i = 0; i < result->length; ++i) { - FFNetUsageIoCounters* icPrev = (FFNetUsageIoCounters*)ffListGet(&ioCounters1, i); - FFNetUsageIoCounters* icCurr = (FFNetUsageIoCounters*)ffListGet(result, i); + FFNetIOResult* icPrev = (FFNetIOResult*)ffListGet(&ioCounters1, i); + FFNetIOResult* icCurr = (FFNetIOResult*)ffListGet(result, i); if (!ffStrbufEqual(&icPrev->name, &icCurr->name)) return "Network interface name changed"; - static_assert(sizeof(FFNetUsageIoCounters) - offsetof(FFNetUsageIoCounters, txBytes) == sizeof(uint64_t) * 8, "Unexpected struct FFNetUsageIoCounters layout"); - for (size_t off = offsetof(FFNetUsageIoCounters, txBytes); off < sizeof(FFNetUsageIoCounters); off += sizeof(uint64_t)) + static_assert(sizeof(FFNetIOResult) - offsetof(FFNetIOResult, txBytes) == sizeof(uint64_t) * 8, "Unexpected struct FFNetIOResult layout"); + for (size_t off = offsetof(FFNetIOResult, txBytes); off < sizeof(FFNetIOResult); off += sizeof(uint64_t)) { uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off); uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off); diff --git a/src/detection/netusage/netusage.h b/src/detection/netio/netio.h similarity index 65% rename from src/detection/netusage/netusage.h rename to src/detection/netio/netio.h index bb6234ee1a..295c4478ed 100644 --- a/src/detection/netusage/netusage.h +++ b/src/detection/netio/netio.h @@ -1,6 +1,6 @@ #include "fastfetch.h" -typedef struct FFNetUsageIoCounters +typedef struct FFNetIOResult { FFstrbuf name; bool defaultRoute; @@ -12,6 +12,6 @@ typedef struct FFNetUsageIoCounters uint64_t txErrors; uint64_t rxDrops; uint64_t txDrops; -} FFNetUsageIoCounters; +} FFNetIOResult; -const char* ffDetectNetUsage(FFlist* result, FFNetUsageOptions* options); +const char* ffDetectNetIO(FFlist* result, FFNetIOOptions* options); diff --git a/src/detection/netusage/netusage_bsd.c b/src/detection/netio/netio_bsd.c similarity index 90% rename from src/detection/netusage/netusage_bsd.c rename to src/detection/netio/netio_bsd.c index b5fd61083a..a0c764dbda 100644 --- a/src/detection/netusage/netusage_bsd.c +++ b/src/detection/netio/netio_bsd.c @@ -1,4 +1,4 @@ -#include "netusage.h" +#include "netio.h" #include "common/io/io.h" #include "common/netif/netif.h" @@ -12,7 +12,7 @@ #include #include -const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) +const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) { size_t bufSize = 0; if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) @@ -43,8 +43,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) if (options->namePrefix.length && strncmp(sdl->sdl_data, options->namePrefix.chars, options->namePrefix.length) != 0) continue; - FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); - *counters = (FFNetUsageIoCounters) { + FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); + *counters = (FFNetIOResult) { .name = ffStrbufCreateNS(sdl->sdl_nlen, sdl->sdl_data), .txBytes = ifm->ifm_data.ifi_obytes, .rxBytes = ifm->ifm_data.ifi_ibytes, diff --git a/src/detection/netusage/netusage_linux.c b/src/detection/netio/netio_linux.c similarity index 93% rename from src/detection/netusage/netusage_linux.c rename to src/detection/netio/netio_linux.c index a5d64be5b0..4b5565cbcf 100644 --- a/src/detection/netusage/netusage_linux.c +++ b/src/detection/netio/netio_linux.c @@ -1,4 +1,4 @@ -#include "netusage.h" +#include "netio.h" #include "common/io/io.h" #include "common/netif/netif.h" @@ -6,7 +6,7 @@ #include -const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) +const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) { FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net"); if (!dirp) return "opendir(\"/sys/class/net\") == NULL"; @@ -33,7 +33,7 @@ const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) if(!ffReadFileBuffer(path.chars, &buffer) || !ffStrbufEqualS(&buffer, "up")) continue; - FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); + FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); ffStrbufInitS(&counters->name, entry->d_name); counters->defaultRoute = isDefaultRoute; diff --git a/src/detection/netusage/netusage_windows.c b/src/detection/netio/netio_windows.c similarity index 90% rename from src/detection/netusage/netusage_windows.c rename to src/detection/netio/netio_windows.c index b9d45f3e77..526e017077 100644 --- a/src/detection/netusage/netusage_windows.c +++ b/src/detection/netio/netio_windows.c @@ -1,4 +1,4 @@ -#include "netusage.h" +#include "netio.h" #include "common/netif/netif.h" #include "util/mallocHelper.h" @@ -7,7 +7,7 @@ #include #include -const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) +const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) { IP_ADAPTER_ADDRESSES* FF_AUTO_FREE adapter_addresses = NULL; @@ -54,8 +54,8 @@ const char* ffNetUsageGetIoCounters(FFlist* result, FFNetUsageOptions* options) MIB_IF_ROW2 ifRow = { .InterfaceIndex = adapter->IfIndex }; if (GetIfEntry2(&ifRow) == NO_ERROR) { - FFNetUsageIoCounters* counters = (FFNetUsageIoCounters*) ffListAdd(result); - *counters = (FFNetUsageIoCounters) { + FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); + *counters = (FFNetIOResult) { .name = ffStrbufCreateS(name), .txBytes = ifRow.OutOctets, .rxBytes = ifRow.InOctets, diff --git a/src/fastfetch.c b/src/fastfetch.c index bdd2fdf527..c956357ebe 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -397,9 +397,9 @@ static inline void printCommandHelp(const char* command) "Public IP address" ); } - else if(ffStrEqualsIgnCase(command, "netusage-format")) + else if(ffStrEqualsIgnCase(command, "netio-format")) { - constructAndPrintCommandHelpFormat("netusage", "{}", 3, + constructAndPrintCommandHelpFormat("netio", "{}", 3, "Size of data received per second (formatted)", "Size of data sent per second (formatted)", "Interface name", diff --git a/src/fastfetch.h b/src/fastfetch.h index ccf3a8f106..0877c1088a 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -112,7 +112,7 @@ typedef struct FFconfig FFMediaOptions media; FFMemoryOptions memory; FFMonitorOptions monitor; - FFNetUsageOptions netUsage; + FFNetIOOptions netIo; FFOSOptions os; FFOpenCLOptions openCL; FFOpenGLOptions openGL; diff --git a/src/modules/modules.h b/src/modules/modules.h index 2ab14bc602..64ab6ea213 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -31,7 +31,7 @@ #include "modules/media/media.h" #include "modules/memory/memory.h" #include "modules/monitor/monitor.h" -#include "modules/netusage/netusage.h" +#include "modules/netio/netio.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" #include "modules/os/os.h" diff --git a/src/modules/netusage/netusage.c b/src/modules/netio/netio.c similarity index 70% rename from src/modules/netusage/netusage.c rename to src/modules/netio/netio.c index 2ae67a7040..3efef948fa 100644 --- a/src/modules/netusage/netusage.c +++ b/src/modules/netio/netio.c @@ -1,26 +1,26 @@ #include "common/printing.h" #include "common/jsonconfig.h" #include "common/parsing.h" -#include "detection/netusage/netusage.h" -#include "modules/netusage/netusage.h" +#include "detection/netio/netio.h" +#include "modules/netio/netio.h" #include "util/stringUtils.h" -#define FF_NETUSAGE_DISPLAY_NAME "Net Usage" -#define FF_NETUSAGE_NUM_FORMAT_ARGS 12 +#define FF_NETIO_DISPLAY_NAME "Network IO" +#define FF_NETIO_NUM_FORMAT_ARGS 12 -static int sortInfs(const FFNetUsageIoCounters* left, const FFNetUsageIoCounters* right) +static int sortInfs(const FFNetIOResult* left, const FFNetIOResult* right) { return ffStrbufComp(&left->name, &right->name); } -static void formatKey(const FFNetUsageOptions* options, FFNetUsageIoCounters* inf, uint32_t index, FFstrbuf* key) +static void formatKey(const FFNetIOOptions* options, FFNetIOResult* inf, uint32_t index, FFstrbuf* key) { if(options->moduleArgs.key.length == 0) { if(!inf->name.length) ffStrbufSetF(&inf->name, "unknown %u", (unsigned) index); - ffStrbufSetF(key, FF_NETUSAGE_DISPLAY_NAME " (%s)", inf->name.chars); + ffStrbufSetF(key, FF_NETIO_DISPLAY_NAME " (%s)", inf->name.chars); } else { @@ -32,14 +32,14 @@ static void formatKey(const FFNetUsageOptions* options, FFNetUsageIoCounters* in } } -void ffPrintNetUsage(FFNetUsageOptions* options) +void ffPrintNetIO(FFNetIOOptions* options) { - FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); - const char* error = ffDetectNetUsage(&result, options); + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetIOResult)); + const char* error = ffDetectNetIO(&result, options); if(error) { - ffPrintError(FF_NETUSAGE_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); + ffPrintError(FF_NETIO_DISPLAY_NAME, 0, &options->moduleArgs, "%s", error); return; } @@ -50,7 +50,7 @@ void ffPrintNetUsage(FFNetUsageOptions* options) FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY buffer2 = ffStrbufCreate(); - FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) + FF_LIST_FOR_EACH(FFNetIOResult, inf, result) { formatKey(options, inf, result.length == 1 ? 0 : index + 1, &key); ffStrbufClear(&buffer); @@ -60,9 +60,9 @@ void ffPrintNetUsage(FFNetUsageOptions* options) ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); ffParseSize(inf->rxBytes, &buffer); - ffStrbufAppendS(&buffer, "/s (in) - "); + ffStrbufAppendS(&buffer, "/s (IN) - "); ffParseSize(inf->txBytes, &buffer); - ffStrbufAppendS(&buffer, "/s (out)"); + ffStrbufAppendS(&buffer, "/s (OUT)"); if (!options->defaultRouteOnly && inf->defaultRoute) ffStrbufAppendS(&buffer, " *"); ffStrbufPutTo(&buffer, stdout); @@ -75,7 +75,7 @@ void ffPrintNetUsage(FFNetUsageOptions* options) ffParseSize(inf->txBytes, &buffer2); ffStrbufAppendS(&buffer2, "/s"); - ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_NETUSAGE_NUM_FORMAT_ARGS, (FFformatarg[]){ + ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_NETIO_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, {FF_FORMAT_ARG_TYPE_STRBUF, &buffer2}, {FF_FORMAT_ARG_TYPE_STRBUF, &inf->name}, @@ -93,24 +93,24 @@ void ffPrintNetUsage(FFNetUsageOptions* options) ++index; } - FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) + FF_LIST_FOR_EACH(FFNetIOResult, inf, result) { ffStrbufDestroy(&inf->name); } } -void ffInitNetUsageOptions(FFNetUsageOptions* options) +void ffInitNetIOOptions(FFNetIOOptions* options) { - ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETUSAGE_MODULE_NAME, ffParseNetUsageCommandOptions, ffParseNetUsageJsonObject, ffPrintNetUsage, ffGenerateNetUsageJson); + ffOptionInitModuleBaseInfo(&options->moduleInfo, FF_NETIO_MODULE_NAME, ffParseNetIOCommandOptions, ffParseNetIOJsonObject, ffPrintNetIO, ffGenerateNetIOJson); ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->namePrefix); options->defaultRouteOnly = false; } -bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value) +bool ffParseNetIOCommandOptions(FFNetIOOptions* options, const char* key, const char* value) { - const char* subKey = ffOptionTestPrefix(key, FF_NETUSAGE_MODULE_NAME); + const char* subKey = ffOptionTestPrefix(key, FF_NETIO_MODULE_NAME); if (!subKey) return false; if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; @@ -130,13 +130,13 @@ bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, return false; } -void ffDestroyNetUsageOptions(FFNetUsageOptions* options) +void ffDestroyNetIOOptions(FFNetIOOptions* options) { ffOptionDestroyModuleArg(&options->moduleArgs); ffStrbufDestroy(&options->namePrefix); } -void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module) +void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module) { yyjson_val *key_, *val; size_t idx, max; @@ -161,14 +161,14 @@ void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module) continue; } - ffPrintError(FF_NETUSAGE_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); + ffPrintError(FF_NETIO_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } -void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +void ffGenerateNetIOJson(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) { - FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetUsageIoCounters)); - const char* error = ffDetectNetUsage(&result, options); + FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFNetIOResult)); + const char* error = ffDetectNetIO(&result, options); if(error) { @@ -177,7 +177,7 @@ void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyj } yyjson_mut_val* arr = yyjson_mut_obj_add_arr(doc, module, "result"); - FF_LIST_FOR_EACH(FFNetUsageIoCounters, counter, result) + FF_LIST_FOR_EACH(FFNetIOResult, counter, result) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &counter->name); @@ -192,7 +192,7 @@ void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyj yyjson_mut_obj_add_uint(doc, obj, "txDrops", counter->txDrops); } - FF_LIST_FOR_EACH(FFNetUsageIoCounters, inf, result) + FF_LIST_FOR_EACH(FFNetIOResult, inf, result) { ffStrbufDestroy(&inf->name); } diff --git a/src/modules/netio/netio.h b/src/modules/netio/netio.h new file mode 100644 index 0000000000..3562d0ccd7 --- /dev/null +++ b/src/modules/netio/netio.h @@ -0,0 +1,14 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_NETIO_MODULE_NAME "NetIO" + +void ffPrepareNetIO(FFNetIOOptions* options); + +void ffPrintNetIO(FFNetIOOptions* options); +void ffInitNetIOOptions(FFNetIOOptions* options); +bool ffParseNetIOCommandOptions(FFNetIOOptions* options, const char* key, const char* value); +void ffDestroyNetIOOptions(FFNetIOOptions* options); +void ffParseNetIOJsonObject(FFNetIOOptions* options, yyjson_val* module); +void ffGenerateNetIOJson(FFNetIOOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); diff --git a/src/modules/netusage/option.h b/src/modules/netio/option.h similarity index 81% rename from src/modules/netusage/option.h rename to src/modules/netio/option.h index ff436aaf23..62b493d292 100644 --- a/src/modules/netusage/option.h +++ b/src/modules/netio/option.h @@ -4,11 +4,11 @@ #include "common/option.h" -typedef struct FFNetUsageOptions +typedef struct FFNetIOOptions { FFModuleBaseInfo moduleInfo; FFModuleArgs moduleArgs; FFstrbuf namePrefix; bool defaultRouteOnly; -} FFNetUsageOptions; +} FFNetIOOptions; diff --git a/src/modules/netusage/netusage.h b/src/modules/netusage/netusage.h deleted file mode 100644 index 4feaee10a1..0000000000 --- a/src/modules/netusage/netusage.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "fastfetch.h" - -#define FF_NETUSAGE_MODULE_NAME "NetUsage" - -void ffPrepareNetUsage(FFNetUsageOptions* options); - -void ffPrintNetUsage(FFNetUsageOptions* options); -void ffInitNetUsageOptions(FFNetUsageOptions* options); -bool ffParseNetUsageCommandOptions(FFNetUsageOptions* options, const char* key, const char* value); -void ffDestroyNetUsageOptions(FFNetUsageOptions* options); -void ffParseNetUsageJsonObject(FFNetUsageOptions* options, yyjson_val* module); -void ffGenerateNetUsageJson(FFNetUsageOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module); diff --git a/src/modules/options.h b/src/modules/options.h index 77c6cf8550..1be2e88e0c 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -31,7 +31,7 @@ #include "modules/media/option.h" #include "modules/memory/option.h" #include "modules/monitor/option.h" -#include "modules/netusage/option.h" +#include "modules/netio/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" #include "modules/os/option.h" From 5e5c0b4a58a70b4b9f1a183c04b94bea8ff8f254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 10:13:59 +0800 Subject: [PATCH 182/198] NetIO: improve performance --- src/common/netif/netif.c | 41 ++++--- src/common/netif/netif.h | 6 +- src/common/netif/netif_bsd.c | 3 +- src/common/netif/netif_linux.c | 3 +- src/common/netif/netif_windows.c | 2 +- src/detection/localip/localip_linux.c | 4 +- src/detection/localip/localip_windows.c | 2 +- src/detection/netio/netio_bsd.c | 18 ++-- src/detection/netio/netio_linux.c | 138 +++++++++++++----------- 9 files changed, 111 insertions(+), 106 deletions(-) diff --git a/src/common/netif/netif.c b/src/common/netif/netif.c index a6aed5730c..ec317454b8 100644 --- a/src/common/netif/netif.c +++ b/src/common/netif/netif.c @@ -1,35 +1,30 @@ #include "netif.h" #ifndef _WIN32 -#include + #include +#else + #define IF_NAMESIZE 16 +#endif -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]); +bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex); +enum { IF_INDEX_UNINITIALIZED = (uint32_t) -1, IF_INDEX_INVALID = (uint32_t) -2 }; +static uint32_t ifIndex = IF_INDEX_UNINITIALIZED; +static char ifName[IF_NAMESIZE + 1]; -const char* ffNetifGetDefaultRoute() +static inline void init() { - static char iface[IF_NAMESIZE + 1]; - - if (*(uint16_t*) iface == 0) - { - if (!ffNetifGetDefaultRouteImpl(iface)) - iface[1] = 1; - } - - return iface; + if (ifIndex == (uint32_t) IF_INDEX_UNINITIALIZED && !ffNetifGetDefaultRouteImpl(ifName, &ifIndex)) + ifIndex = (uint32_t) IF_INDEX_INVALID; } -#else -bool ffNetifGetDefaultRouteImpl(uint32_t* ifIndex); -uint32_t ffNetifGetDefaultRoute() +const char* ffNetifGetDefaultRouteIfName() { - static uint32_t ifIndex = (uint32_t) -1; - - if (ifIndex == (uint32_t) -1) - { - if (!ffNetifGetDefaultRouteImpl(&ifIndex)) - ifIndex = (uint32_t) -2; - } + init(); + return ifName; +} +uint32_t ffNetifGetDefaultRouteIfIndex() +{ + init(); return ifIndex; } -#endif diff --git a/src/common/netif/netif.h b/src/common/netif/netif.h index 5b20e16f82..23ca5ef607 100644 --- a/src/common/netif/netif.h +++ b/src/common/netif/netif.h @@ -3,7 +3,7 @@ #include "fastfetch.h" #ifndef _WIN32 -const char* ffNetifGetDefaultRoute(); -#else -uint32_t ffNetifGetDefaultRoute(); +const char* ffNetifGetDefaultRouteIfName(); #endif + +uint32_t ffNetifGetDefaultRouteIfIndex(); diff --git a/src/common/netif/netif_bsd.c b/src/common/netif/netif_bsd.c index fcd657a303..f288d7d356 100644 --- a/src/common/netif/netif_bsd.c +++ b/src/common/netif/netif_bsd.c @@ -39,7 +39,7 @@ get_rt_address(struct rt_msghdr *rtm, int desired) return NULL; } -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]) +bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) { //https://github.com/hashPirate/copenheimer-masscan-fork/blob/36f1ed9f7b751a7dccd5ed27874e2e703db7d481/src/rawsock-getif.c#L104 @@ -88,6 +88,7 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]) assert(sdl->sdl_nlen <= IF_NAMESIZE); memcpy(iface, sdl->sdl_data, sdl->sdl_nlen); iface[sdl->sdl_nlen] = '\0'; + *ifIndex = sdl->sdl_index; return true; } return false; diff --git a/src/common/netif/netif_linux.c b/src/common/netif/netif_linux.c index f8b323b67d..f645b0a0b7 100644 --- a/src/common/netif/netif_linux.c +++ b/src/common/netif/netif_linux.c @@ -7,7 +7,7 @@ #define FF_STR_INDIR(x) #x #define FF_STR(x) FF_STR_INDIR(x) -bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]) +bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1], uint32_t* ifIndex) { FILE* FF_AUTO_CLOSE_FILE netRoute = fopen("/proc/net/route", "r"); if (!netRoute) return false; @@ -21,6 +21,7 @@ bool ffNetifGetDefaultRouteImpl(char iface[IF_NAMESIZE + 1]) while (fscanf(netRoute, "%" FF_STR(IF_NAMESIZE) "s%llx%*[^\n]", iface, &destination) == 2) { if (destination != 0) continue; + *ifIndex = if_nametoindex(iface); return true; } return false; diff --git a/src/common/netif/netif_windows.c b/src/common/netif/netif_windows.c index 3fc80ecba2..df591d5e67 100644 --- a/src/common/netif/netif_windows.c +++ b/src/common/netif/netif_windows.c @@ -3,7 +3,7 @@ #include -bool ffNetifGetDefaultRouteImpl(uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImpl(char* iface/* unsupported */, uint32_t* ifIndex) { ULONG size = 0; if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER) diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 38cec42336..1f319ad34d 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -57,14 +57,14 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if(getifaddrs(&ifAddrStruct) < 0) return "getifaddrs(&ifAddrStruct) failed"; - const char* defaultRouteIface = ffNetifGetDefaultRoute(); + const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName(); for (struct ifaddrs* ifa = ifAddrStruct; ifa; ifa = ifa->ifa_next) { if (!ifa->ifa_addr || !(ifa->ifa_flags & IFF_RUNNING)) continue; - bool isDefaultRoute = ffStrEquals(defaultRouteIface, ifa->ifa_name); + bool isDefaultRoute = ffStrEquals(defaultRouteIfName, ifa->ifa_name); if (options->defaultRouteOnly && !isDefaultRoute) continue; diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index 8863843fd3..bb39b43254 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -70,7 +70,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) return "GetAdaptersAddresses() failed"; } - uint32_t defaultRouteIfIndex = ffNetifGetDefaultRoute(); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) diff --git a/src/detection/netio/netio_bsd.c b/src/detection/netio/netio_bsd.c index a0c764dbda..57e36d086b 100644 --- a/src/detection/netio/netio_bsd.c +++ b/src/detection/netio/netio_bsd.c @@ -14,15 +14,15 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) { + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); + size_t bufSize = 0; - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, NULL, &bufSize, 0, 0) failed"; + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, NULL, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, ifIndex }, 6, NULL, &bufSize, 0, 0) failed"; FF_AUTO_FREE struct if_msghdr2* buf = (struct if_msghdr2*) malloc(bufSize); - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 }, 6, buf, &bufSize, 0, 0) failed"; - - const char* defaultRouteIface = ffNetifGetDefaultRoute(); + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, buf, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, ifIndex }, 6, buf, &bufSize, 0, 0) failed"; for (struct if_msghdr2* ifm = buf; ifm < (struct if_msghdr2*) ((uint8_t*) buf + bufSize); @@ -36,10 +36,6 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) sdl->sdl_data[sdl->sdl_nlen] = 0; - bool isDefaultRoute = ffStrEquals(sdl->sdl_data, defaultRouteIface); - if(options->defaultRouteOnly && !isDefaultRoute) - continue; - if (options->namePrefix.length && strncmp(sdl->sdl_data, options->namePrefix.chars, options->namePrefix.length) != 0) continue; @@ -54,7 +50,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) .rxErrors = ifm->ifm_data.ifi_ierrors, .txDrops = 0, // unsupported .rxDrops = ifm->ifm_data.ifi_iqdrops, - .defaultRoute = isDefaultRoute, + .defaultRoute = sdl->sdl_index == defaultRouteIfIndex, }; } diff --git a/src/detection/netio/netio_linux.c b/src/detection/netio/netio_linux.c index 4b5565cbcf..2b1f244789 100644 --- a/src/detection/netio/netio_linux.c +++ b/src/detection/netio/netio_linux.c @@ -6,6 +6,60 @@ #include +static void getData(FFstrbuf* buffer, const char* ifName, bool isDefaultRoute, FFstrbuf* path, FFlist* result) +{ + ffStrbufSetF(path, "/sys/class/net/%s/operstate", ifName); + if(!ffReadFileBuffer(path->chars, buffer) || !ffStrbufEqualS(buffer, "up")) + return; + + FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); + ffStrbufInitS(&counters->name, ifName); + counters->defaultRoute = isDefaultRoute; + + ffStrbufSetF(path, "/sys/class/net/%s/statistics/", ifName); + uint32_t statLen = path->length; + + ffStrbufAppendS(path, "rx_bytes"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->rxBytes = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); + + ffStrbufAppendS(path, "tx_bytes"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->txBytes = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); + + ffStrbufAppendS(path, "rx_packets"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->rxPackets = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); + + ffStrbufAppendS(path, "tx_packets"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->txPackets = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); + + ffStrbufAppendS(path, "rx_errors"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->rxErrors = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); + + ffStrbufAppendS(path, "tx_errors"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->txErrors = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); + + ffStrbufAppendS(path, "rx_dropped"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->rxDrops = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); + + ffStrbufAppendS(path, "tx_dropped"); + if (ffReadFileBuffer(path->chars, buffer)) + counters->txDrops = ffStrbufToUInt(buffer, 0); + ffStrbufSubstrBefore(path, statLen); +} + const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) { FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net"); @@ -14,71 +68,29 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64); FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - const char* defaultRouteIface = ffNetifGetDefaultRoute(); + const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName(); - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) + if (options->defaultRouteOnly) + { + if (options->namePrefix.length && strncmp(defaultRouteIfName, options->namePrefix.chars, options->namePrefix.length) != 0) + return NULL; + + getData(&buffer, defaultRouteIfName, true, &path, result); + } + else { - if(entry->d_name[0] == '.') - continue; - - bool isDefaultRoute = ffStrEquals(entry->d_name, defaultRouteIface); - if(options->defaultRouteOnly && !isDefaultRoute) - continue; - - if (options->namePrefix.length && strncmp(entry->d_name, options->namePrefix.chars, options->namePrefix.length) != 0) - continue; - - ffStrbufSetF(&path, "/sys/class/net/%s/operstate", entry->d_name); - if(!ffReadFileBuffer(path.chars, &buffer) || !ffStrbufEqualS(&buffer, "up")) - continue; - - FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); - ffStrbufInitS(&counters->name, entry->d_name); - counters->defaultRoute = isDefaultRoute; - - ffStrbufSetF(&path, "/sys/class/net/%s/statistics/", entry->d_name); - uint32_t statLen = path.length; - - ffStrbufAppendS(&path, "rx_bytes"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->rxBytes = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_bytes"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->txBytes = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "rx_packets"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->rxPackets = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_packets"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->txPackets = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "rx_errors"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->rxErrors = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_errors"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->txErrors = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "rx_dropped"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->rxDrops = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); - - ffStrbufAppendS(&path, "tx_dropped"); - if (ffReadFileBuffer(path.chars, &buffer)) - counters->txDrops = ffStrbufToUInt(&buffer, 0); - ffStrbufSubstrBefore(&path, statLen); + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + const char* ifName = entry->d_name; + if(ifName[0] == '.') + continue; + + if (options->namePrefix.length && strncmp(ifName, options->namePrefix.chars, options->namePrefix.length) != 0) + continue; + + getData(&buffer, ifName, ffStrEquals(ifName, defaultRouteIfName), &path, result); + } } return NULL; From a7a8f2f461ee7652e1bc9db8521b557ee524aa09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 10:42:39 +0800 Subject: [PATCH 183/198] NetIO (BSD): fix compiling --- src/common/netif/netif_windows.c | 2 +- src/detection/netio/netio_bsd.c | 18 +++++++++--------- src/detection/netio/netio_windows.c | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/common/netif/netif_windows.c b/src/common/netif/netif_windows.c index df591d5e67..8607ed4866 100644 --- a/src/common/netif/netif_windows.c +++ b/src/common/netif/netif_windows.c @@ -3,7 +3,7 @@ #include -bool ffNetifGetDefaultRouteImpl(char* iface/* unsupported */, uint32_t* ifIndex) +bool ffNetifGetDefaultRouteImpl(FF_MAYBE_UNUSED char* iface/* unsupported */, uint32_t* ifIndex) { ULONG size = 0; if (GetIpForwardTable(NULL, &size, TRUE) != ERROR_INSUFFICIENT_BUFFER) diff --git a/src/detection/netio/netio_bsd.c b/src/detection/netio/netio_bsd.c index 57e36d086b..6bf9a8ce6e 100644 --- a/src/detection/netio/netio_bsd.c +++ b/src/detection/netio/netio_bsd.c @@ -17,18 +17,18 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); size_t bufSize = 0; - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, NULL, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, ifIndex }, 6, NULL, &bufSize, 0, 0) failed"; + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, NULL, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, ifIndex }, 6, NULL, &bufSize, 0, 0) failed"; - FF_AUTO_FREE struct if_msghdr2* buf = (struct if_msghdr2*) malloc(bufSize); - if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, buf, &bufSize, 0, 0) < 0) - return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, ifIndex }, 6, buf, &bufSize, 0, 0) failed"; + FF_AUTO_FREE struct if_msghdr* buf = (struct if_msghdr*) malloc(bufSize); + if (sysctl((int[]) { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, (options->defaultRouteOnly ? (int) defaultRouteIfIndex : 0) }, 6, buf, &bufSize, 0, 0) < 0) + return "sysctl({ CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, ifIndex }, 6, buf, &bufSize, 0, 0) failed"; - for (struct if_msghdr2* ifm = buf; - ifm < (struct if_msghdr2*) ((uint8_t*) buf + bufSize); - ifm = (struct if_msghdr2*) ((uint8_t*) ifm + ifm->ifm_msglen)) + for (struct if_msghdr* ifm = buf; + ifm < (struct if_msghdr*) ((uint8_t*) buf + bufSize); + ifm = (struct if_msghdr*) ((uint8_t*) ifm + ifm->ifm_msglen)) { - if (ifm->ifm_type != RTM_IFINFO2 || !(ifm->ifm_flags & IFF_RUNNING) || (ifm->ifm_flags & IFF_NOARP)) continue; + if (ifm->ifm_type != RTM_IFINFO || !(ifm->ifm_flags & IFF_RUNNING) || (ifm->ifm_flags & IFF_NOARP)) continue; struct sockaddr_dl* sdl = (struct sockaddr_dl*) (ifm + 1); assert(sdl->sdl_family == AF_LINK); diff --git a/src/detection/netio/netio_windows.c b/src/detection/netio/netio_windows.c index 526e017077..4291df3d46 100644 --- a/src/detection/netio/netio_windows.c +++ b/src/detection/netio/netio_windows.c @@ -37,7 +37,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options) return "GetAdaptersAddresses() failed"; } - uint32_t defaultRouteIfIndex = ffNetifGetDefaultRoute(); + uint32_t defaultRouteIfIndex = ffNetifGetDefaultRouteIfIndex(); // Iterate through all of the adapters for (IP_ADAPTER_ADDRESSES* adapter = adapter_addresses; adapter; adapter = adapter->Next) From 8b357c27b40352f0f70fe31aae3d89a9861c1175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 11:04:13 +0800 Subject: [PATCH 184/198] Logo (Builtin): add Amazon LInux Fix #566 --- CHANGELOG.md | 1 + README.md | 2 +- src/logo/ascii/amazon_linux.txt | 10 ++++++++++ src/logo/builtin.c | 13 ++++++++++--- 4 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 src/logo/ascii/amazon_linux.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c1cc3c754..e0fdfceb10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Logo: * Update AOSC OS * Update Ubuntu_old * Update Windows 11_small +* Add Amazon Linux # 2.0.5 diff --git a/README.md b/README.md index b38e37b956..3148465d55 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Battery, Bios, Bluetooth, Board, Break, Brightness, Colors, Command, CPU, CPUUsa ``` -AerOS, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin +AerOS, Afterglow, AIX, AlmaLinux, Alpine, Alpine2Small, AlpineSmall, Alter, Amazon, AmazonLinux, AmogOS, Anarchy, Android, AndroidSmall, Antergos, Antix, AoscOS, AoscOS_old, AoscOsRetro, AoscOsRetro_small, Aperture, Apple, AppleSmall, Apricity, Arch, Arch2, ArchBox, Archcraft, Archcraft2, Archlabs, ArchSmall, ArchStrike, ArcoLinux, ArcoLinuxSmall, ArseLinux, Artix, Artix2Small, ArtixSmall, Arya, Asahi, Aster, AsteroidOS, AstOS, Astra, Ataraxia, Athena, Bedrock, BigLinux, Bitrig, BlackArch, BlackPanther, BLAG, BlankOn, BlueLight, Bodhi, Bonsai, BSD, BunsenLabs, CachyOS, CachyOSSmall, Calculate, CalinixOS, CalinixOSSmall, Carbs, CBL-Mariner, CelOS, Center, CentOS, CentOSSmall, Chakra, ChaletOS, Chapeau, ChonkySealOS, Chrom, Cleanjaro, CleanjaroSmall, ClearLinux, ClearOS, Clover, Cobalt, Condres, ContainerLinux, CRUX, CRUXSmall, CrystalLinux, Cucumber, CutefishOS, CuteOS, CyberOS, Dahlia, DarkOS, Debian, DebianSmall, Deepin, DesaOS, Devuan, DevuanSmall, DietPi, DracOS, DragonFly, DragonFlyOld, DragonFlySmall, Drauger, Droidian, Elbrus, Elementary, ElementarySmall, Elive, EncryptOS, Endeavour, Endless, Enso, EuroLinux, EvolutionOS, EvolutionOS_old, EvolutionOSSmall, Exherbo, ExodiaPredator, Fedora, FedoraOld, FedoraSmall, FemboyOS, Feren, Finnix, Floflis, FreeBSD, FreeBSDSmall, FreeMiNT, Frugalware, Funtoo, GalliumOS, Garuda, GarudaDragon, GarudaSmall, Gentoo, GentooSmall, GhostBSD, Glaucus, GNewSense, Gnome, GNU, GoboLinux, GrapheneOS, Grombyang, Guix, GuixSmall, Haiku, HaikuSmall, HamoniKR, HarDClanZ, HardenedBSD, Hash, Huayra, Hybrid, HydroOS, Hyperbola, HyperbolaSmall, Iglunix, InstantOS, IRIX, Itc, Januslinux, Kaisen, Kali, KaliSmall, KaOS, KDENeon, Kibojoe, KISSLinux, Kogaion, Korora, KrassOS, KSLinux, Kubuntu, LangitKetujuh, Laxeros, LEDE, LibreELEC, Linspire, Linux, LinuxLight, LinuxLightSmall, LinuxMint, LinuxMintOld, LinuxMintSmall, LinuxSmall, Live_Raizo, LMDE, Lunar, MacOS, MacOS2, MacOS2Small, MacOSSmall, Mageia, MageiaSmall, MagpieOS, Mandriva, Manjaro, ManjaroSmall, MassOS, MatuusOS, MaUI, Meowix, Mer, Minix, Mint, MintOld, MintSmall, MiracleLinux, MOS, Msys2, MX, MXSmall, Namib, Nekos, Neptune, NetBSD, NetRunner, Nitrux, NixOS, NixOS_small, NixOsOld, NixOsSmall, Nobara, NomadBSD, Nurunner, NuTyX, Obarun, OBRevenge, OmniOS, OpenBSD, OpenBSDSmall, OpenEuler, OpenIndiana, OpenKylin, OpenMamba, OpenMandriva, OpenStage, OpenSuse, OpenSuseLeap, OpenSuseSmall, OpenSuseTumbleweed, OpenWrt, OPNsense, Oracle, Orchid, OrchidSmall, OS_Elbrus, OSMC, OSX, OSXSmall, PacBSD, Panwah, Parabola, ParabolaSmall, Parch, Pardus, Parrot, Parsix, PCBSD, PCLinuxOS, PearOS, Pengwin, Pentoo, Peppermint, PhyOS, Pisi, PNMLinux, Pop, PopSmall, Porteus, PostMarketOS, PostMarketOSSmall, Proxmox, PuffOS, Puppy, PureOS, PureOSSmall, Q4OS, Qubes, Qubyt, Quibian, Radix, Raspbian, RaspbianSmall, RavynOS, Reborn, RebornSmall, RedCore, RedHatEnterpriseLinux, RedHatEnterpriseLinux_old, RedstarOS, Refracted Devuan, Regata, Regolith, RhaymOS, RockyLinux, RockyLinuxSmall, RosaLinux, Sabayon, Sabotage, Sailfish, SalentOS, SalientOS, Salix, SambaBOX, Sasanqua, Scientific, Semc, Septor, Serene, SharkLinux, ShastraOS, Siduction, SkiffOS, Slackel, Slackware, SlackwareSmall, Slitaz, SmartOS, Soda, Solaris, SolarisSmall, Solus, SourceMage, Sparky, Star, SteamOS, StockLinux, Sulin, Suse, SuseSmall, Swagarch, T2, Tails, TeArch, TorizonCore, Trisquel, TuxedoOS, Twister, Ubuntu, Ubuntu2Old, Ubuntu2Small, UbuntuBudgie, UbuntuCinnamon, UbuntuGnome, UbuntuKde, UbuntuKylin, UbuntuMate, UbuntuOld, UbuntuSmall, UbuntuStudio, UbuntuSway, UbuntuTouch, UbuntuUnity, Ultramarine, Univalent, Univention, UOS, UrukOS, Uwuntu, Vanilla, Venom, VenomSmall, Vnux, Void, VoidSmall, Vzlinux, WiiLinuxNgx, Windows, Windows11, Windows11Small, Windows8, Windows95, Xferience, YiffOS, Zorin ``` Run `fastfetch --print-logos` to print them diff --git a/src/logo/ascii/amazon_linux.txt b/src/logo/ascii/amazon_linux.txt new file mode 100644 index 0000000000..9152678683 --- /dev/null +++ b/src/logo/ascii/amazon_linux.txt @@ -0,0 +1,10 @@ + , $2#_$1 + ~\_ $2####_$1 + ~~ \_$2#####\$1 + ~~ \$2###|$1 + ~~ \$2#/$1 ___ + ~~ V~' '-> + ~~~ / + ~~._. _/ + _/ _/ + _/m/' diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 5bbb455f1f..7c62bdb3d5 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -109,9 +109,16 @@ static const FFlogo A[] = { .colors = { FF_COLOR_FG_YELLOW, FF_COLOR_FG_WHITE, - }, - .colorKeys = FF_COLOR_FG_YELLOW, - .colorTitle = FF_COLOR_FG_WHITE, + } + }, + // AmazonLinux + { + .names = {"Amazon Linux", "amzn"}, + .lines = FASTFETCH_DATATEXT_LOGO_AMAZON_LINUX, + .colors = { + FF_COLOR_FG_WHITE, + FF_COLOR_FG_256 "178", + } }, // AmogOS { From 88c12486bfec2b4c57ae006372038989856a1329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 15:02:55 +0800 Subject: [PATCH 185/198] Processing (Linux): always set `LANG` to `C` before executing child process --- src/common/processing_linux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index 815ed1fc88..84bc79cece 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -38,6 +38,7 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use close(pipes[0]); close(pipes[1]); close(useStdErr ? STDOUT_FILENO : STDERR_FILENO); + setenv("LANG", "C", 1); execvp(argv[0], argv); exit(901); } From 7caa8d461801432e5e9463ee7f8ba82f4a2ccfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 15:03:28 +0800 Subject: [PATCH 186/198] CPU (Linux): try detecting CPU name using `lscpu` Fix #567 --- CHANGELOG.md | 1 + src/detection/cpu/cpu_linux.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0fdfceb10..796421cf4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Features: * Support Windows Service Pack version detection (Kernel, Windows) * Support Debian point releases detection (OS, Linux) * Add new module `NetIO` which prints network throughput (usage) of specified interface. Note this module costs about 1 second to finish. +* Use `lscpu` to detect CPU name for ARM CPUs (CPU, Linux) Bugfixes: * Fix fastfetch hanging in specific environment (#561) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index af340756bc..1243fbf785 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -1,5 +1,6 @@ #include "cpu.h" #include "common/io/io.h" +#include "common/processing.h" #include "common/properties.h" #include "detection/temps/temps_linux.h" #include "util/mallocHelper.h" @@ -50,6 +51,16 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, ); } + if (cpu->name.length == 0) + { + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (!ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL })) + { + ffParsePropLines(buffer.chars, "Model name:", &cpu->name); + if (ffStrbufEqualS(&cpu->name, "-")) ffStrbufClear(&cpu->name); + } + } + return NULL; } From 767f99cffa97184e1db47916d3e9479b831a84a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 15:11:05 +0800 Subject: [PATCH 187/198] CPU (Linux): only try `lscpu` on Linux Since `lscpu` is a program of `util-linux` --- src/detection/cpu/cpu_linux.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 1243fbf785..1241ef8891 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -51,16 +51,6 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer, ); } - if (cpu->name.length == 0) - { - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - if (!ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL })) - { - ffParsePropLines(buffer.chars, "Model name:", &cpu->name); - if (ffStrbufEqualS(&cpu->name, "-")) ffStrbufClear(&cpu->name); - } - } - return NULL; } @@ -174,5 +164,17 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) detectAndroid(cpu); #endif + #ifdef __linux__ + if (cpu->name.length == 0) + { + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (!ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL })) + { + ffParsePropLines(buffer.chars, "Model name:", &cpu->name); + if (ffStrbufEqualS(&cpu->name, "-")) ffStrbufClear(&cpu->name); + } + } + #endif + return NULL; } From eb0faec74a63fdc72ec7c054496853f4d14335b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 15:34:53 +0800 Subject: [PATCH 188/198] NetIO (Android): fix building Doesn't work because `/sys` is unaccessable on Android --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b4292475d..f75d27104b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -439,6 +439,7 @@ elseif(ANDROID) src/detection/media/media_nosupport.c src/detection/memory/memory_linux.c src/detection/monitor/monitor_nosupport.c + src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_android.c src/detection/packages/packages_linux.c From 72d2ce4b4393bfde50852b0c2f9069ec1af3979e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 15:52:52 +0800 Subject: [PATCH 189/198] Logo: add LainOS Ref: https://github.com/dylanaraps/neofetch/pull/2382 --- CHANGELOG.md | 1 + src/logo/ascii/LainOS.txt | 20 ++++++++++++++++++++ src/logo/builtin.c | 10 ++++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/logo/ascii/LainOS.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 796421cf4b..b815dad7de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Logo: * Update Ubuntu_old * Update Windows 11_small * Add Amazon Linux +* Add LainOS # 2.0.5 diff --git a/src/logo/ascii/LainOS.txt b/src/logo/ascii/LainOS.txt new file mode 100644 index 0000000000..9bd6c55305 --- /dev/null +++ b/src/logo/ascii/LainOS.txt @@ -0,0 +1,20 @@ +${c2} /==\\ + \\==/ +${c1} · · · · · · · + · · · · · · · · · · + · · · ${c2}.-======-.${c1}· · · · +${c2} .::.${c1} ·${c2}.-============-.${c1}· ${c2}.::. + .:==:${c1}· ${c2}.:===:'${c1}. ·· .${c2}':===:.${c1} ·${c2}:==:. + .:===:${c1} · ${c2}:===.${c1} · ${c3}.--.${c1} · ${c2}.===:${c1} · ${c2}:===:. + :===:${c1}· · ${c2}:===.${c1} · ${c3}.:====:.${c1} · ${c2}.===:${c1} · ·${c2}:===: +(===:${c1}· · ${c2}:===-${c1} · ${c3}:======:${c1} · ${c2}-===:${c1} · ·${c2}:===) + :===:${c1}· · ${c2}:===.${c1} · ${c3}':====:'${c1} · ${c2}.===:${c1} · ·${c2}:===: + ':===:${c1} · ${c2}:===.${c1} · ${c3}'--'${c1} · ${c2}.===:${c1} · ${c2}:===:' + ':==:${c1}· ${c2}':===:.${c1}' ·· '${c2}.:===:'${c1} ·${c2}:==:' + '::'${c1} · ${c2}'===-. .-==='${c1} · ${c2}'::' + ${c2}/==\\${c1} · · · ${c2}:=== ===:${c1} · · · ${c2}/==\\ + \\==/${c1} · · ·${c2}:===${c1} ·${c2}===:${c1}· · · ${c2}\\==/${c2} + .-. ${c1}· ${c2}:===${c1}· ${c2}===:${c1} ·${c2} ${c2}.-. + .===. .=== ===. .===. + .======== ========. + ''''' ''''' diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 7c62bdb3d5..d0a634b96d 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -2146,6 +2146,16 @@ static const FFlogo L[] = { .colorKeys = FF_COLOR_FG_GREEN, .colorTitle = FF_COLOR_FG_WHITE, }, + // LainOS + { + .names = {"LainOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_LAINOS, + .colors = { + FF_COLOR_FG_BLUE, + FF_COLOR_FG_256 "14", + FF_COLOR_FG_WHITE, + }, + }, // Lunar { .names = {"Lunar"}, From 289976372fc32730d23502701e4d5052fa3a96ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Sep 2023 20:05:55 +0800 Subject: [PATCH 190/198] Shell: improve nu version detection performance --- src/detection/terminalshell/terminalshell.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 110ae7512a..cad8c5cbcc 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -128,6 +128,13 @@ static bool getShellVersionOksh(FFstrbuf* exe, FFstrbuf* version) return true; } +static bool getShellVersionNushell(FFstrbuf* exe, FFstrbuf* version) +{ + ffStrbufSetS(version, getenv("NU_VERSION")); + if (version->length) return true; + return getExeVersionRaw(exe, version); //0.73.0 +} + #ifdef _WIN32 static bool getShellVersionWinPowerShell(FFstrbuf* exe, FFstrbuf* version) { @@ -158,7 +165,7 @@ bool fftsGetShellVersion(FFstrbuf* exe, const char* exeName, FFstrbuf* version) if(strcasecmp(exeName, "csh") == 0 || strcasecmp(exeName, "tcsh") == 0) return getExeVersionGeneral(exe, version); //tcsh 6.24.07 (Astron) 2022-12-21 (aarch64-apple-darwin) options wide,nls,dl,al,kan,sm,rh,color,filec if(strcasecmp(exeName, "nu") == 0) - return getExeVersionRaw(exe, version); //0.73.0 + return getShellVersionNushell(exe, version); if(strcasecmp(exeName, "ksh") == 0) return getShellVersionKsh(exe, version); if(strcasecmp(exeName, "oksh") == 0) From 9857f48bb919b6e698108b8715b9d50e22964708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 28 Sep 2023 23:40:03 +0800 Subject: [PATCH 191/198] OS (Linux): actually display debian .x version Also display code name on Linux --- src/detection/os/os_linux.c | 5 +++-- src/modules/os/os.c | 9 ++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index e1371f0ac0..1b99c174c8 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -126,8 +126,9 @@ static void getDebianVersion(FFOSResult* result) { FF_STRBUF_AUTO_DESTROY debianVersion = ffStrbufCreate(); ffAppendFileBuffer("/etc/debian_version", &debianVersion); - if (debianVersion.length) - ffStrbufSet(&result->version, &debianVersion); + if (!debianVersion.length) return; + ffStrbufSet(&result->version, &debianVersion); + ffStrbufSet(&result->versionID, &debianVersion); } static void detectOS(FFOSResult* os) diff --git a/src/modules/os/os.c b/src/modules/os/os.c index b905360e69..120f769fc1 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -21,21 +21,20 @@ static void buildOutputDefault(const FFOSResult* os, FFstrbuf* result) else ffStrbufAppend(result, &instance.state.platform.systemName); - #ifdef __APPLE__ - if(os->codename.length > 0) + //Append code name if it is missing + if(os->codename.length > 0 && !ffStrbufContain(result, &os->versionID)) { ffStrbufAppendC(result, ' '); ffStrbufAppend(result, &os->codename); } - #endif //Append version if it is missing - if(os->versionID.length > 0 && ffStrbufFirstIndex(result, &os->versionID) == result->length) + if(os->versionID.length > 0 && !ffStrbufContain(result, &os->versionID)) { ffStrbufAppendC(result, ' '); ffStrbufAppend(result, &os->versionID); } - else if(os->versionID.length == 0 && os->version.length > 0 && ffStrbufFirstIndex(result, &os->version) == result->length) + else if(os->versionID.length == 0 && os->version.length > 0 && !ffStrbufContain(result, &os->version)) { ffStrbufAppendC(result, ' '); ffStrbufAppend(result, &os->version); From 18233a27c541cd0a819cae79f435d295658dd1f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 30 Sep 2023 15:00:59 +0800 Subject: [PATCH 192/198] Disk (Windows): detect disk physical type --- src/detection/disk/disk.h | 8 ++++++++ src/detection/disk/disk_bsd.c | 5 +++-- src/detection/disk/disk_linux.c | 1 + src/detection/disk/disk_windows.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index 3ccab52c4f..08701b14f8 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -5,6 +5,13 @@ #include "fastfetch.h" +typedef enum FFDiskPhysicalType +{ + FF_DISK_TYPE_UNKNOWN, + FF_DISK_TYPE_HDD, + FF_DISK_TYPE_SSD, +} FFDiskPhysicalType; + typedef struct FFDisk { FFstrbuf mountFrom; @@ -12,6 +19,7 @@ typedef struct FFDisk FFstrbuf filesystem; FFstrbuf name; FFDiskVolumeType type; + FFDiskPhysicalType physicalType; uint64_t bytesUsed; uint64_t bytesFree; diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index bd7adf4e5f..f4345f4bf3 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -64,14 +64,15 @@ const char* ffDetectDisksImpl(FFlist* disks) if(!ffStrStartsWith(fs->f_mntfromname, "/dev/") && !ffStrEquals(fs->f_fstypename, "zfs")) continue; - FFDisk* disk = ffListAdd(disks); - #ifdef __FreeBSD__ // f_bavail and f_ffree are signed on FreeBSD... if(fs->f_bavail < 0) fs->f_bavail = 0; if(fs->f_ffree < 0) fs->f_ffree = 0; #endif + FFDisk* disk = ffListAdd(disks); + disk->physicalType = FF_DISK_TYPE_UNKNOWN; + disk->bytesTotal = fs->f_blocks * fs->f_bsize; disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize; disk->bytesAvailable = (uint64_t)fs->f_bavail * fs->f_bsize; diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 035cec8990..c58b0dee3e 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -277,6 +277,7 @@ const char* ffDetectDisksImpl(FFlist* disks) //We have a valid device, add it to the list FFDisk* disk = ffListAdd(disks); disk->type = FF_DISK_VOLUME_TYPE_NONE; + disk->physicalType = FF_DISK_TYPE_UNKNOWN; //detect mountFrom ffStrbufInitS(&disk->mountFrom, device->mnt_fsname); diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index dacf5ba94b..4f0213b53e 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -1,7 +1,9 @@ #include "disk.h" +#include "common/io/io.h" #include "util/windows/unicode.h" #include +#include #include const char* ffDetectDisksImpl(FFlist* disks) @@ -26,8 +28,37 @@ const char* ffDetectDisksImpl(FFlist* disks) ffStrbufInitWS(&disk->mountpoint, mountpoint); wchar_t volumeName[64]; + + disk->physicalType = FF_DISK_TYPE_UNKNOWN; + if(mountpoint[1] == ':') + { + memcpy(volumeName, L"\\\\.\\ :", sizeof(L"\\\\.\\ :")); + volumeName[4] = mountpoint[0]; + FF_AUTO_CLOSE_FD HANDLE handle = CreateFileW(volumeName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (handle != INVALID_HANDLE_VALUE) + { + DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; + if(DeviceIoControl( + handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceSeekPenaltyProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &dspd, + sizeof(dspd), + NULL, + NULL + )) + disk->physicalType = dspd.IncursSeekPenalty ? FF_DISK_TYPE_HDD : FF_DISK_TYPE_SSD; + } + } + if(GetVolumeNameForVolumeMountPointW(mountpoint, volumeName, sizeof(volumeName) / sizeof(*volumeName))) + { ffStrbufInitWS(&disk->mountFrom, volumeName); + } else ffStrbufInit(&disk->mountFrom); From e53acf42ec52139874a21b0b9c613f367c7c4b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 30 Sep 2023 20:32:14 +0800 Subject: [PATCH 193/198] Disk (Linux): detect physical type --- src/detection/disk/disk.h | 6 +++--- src/detection/disk/disk_bsd.c | 2 +- src/detection/disk/disk_linux.c | 25 ++++++++++++++++++------- src/detection/disk/disk_windows.c | 4 ++-- src/modules/disk/disk.c | 31 +++++++++++++++++++++++++++++-- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/detection/disk/disk.h b/src/detection/disk/disk.h index 08701b14f8..06611f85c2 100644 --- a/src/detection/disk/disk.h +++ b/src/detection/disk/disk.h @@ -7,9 +7,9 @@ typedef enum FFDiskPhysicalType { - FF_DISK_TYPE_UNKNOWN, - FF_DISK_TYPE_HDD, - FF_DISK_TYPE_SSD, + FF_DISK_PHYSICAL_TYPE_UNKNOWN, + FF_DISK_PHYSICAL_TYPE_HDD, + FF_DISK_PHYSICAL_TYPE_SSD, } FFDiskPhysicalType; typedef struct FFDisk diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index f4345f4bf3..55fc94a2e6 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -71,7 +71,7 @@ const char* ffDetectDisksImpl(FFlist* disks) #endif FFDisk* disk = ffListAdd(disks); - disk->physicalType = FF_DISK_TYPE_UNKNOWN; + disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; disk->bytesTotal = fs->f_blocks * fs->f_bsize; disk->bytesFree = (uint64_t)fs->f_bfree * fs->f_bsize; diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index c58b0dee3e..bc53eb7834 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -195,7 +195,7 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) return false; } -static bool isRemovable(FFDisk* currentDisk) +static bool detectPhysicalTypeAndReturnRemovable(FFDisk* currentDisk) { // https://stackoverflow.com/a/73302025 // Note my USB mobile hard disk isn't detected as removable, but my USB flash disk does. @@ -218,11 +218,20 @@ static bool isRemovable(FFDisk* currentDisk) if (!ffStrStartsWith(partitionName, entry->d_name)) continue; - // /sys/block/sdx/removable ffStrbufAppendS(&basePath, entry->d_name); + index = basePath.length; + // /sys/block/sdx/queue/rotational + ffStrbufAppendS(&basePath, "/queue/rotational"); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + if (ffReadFileBuffer(basePath.chars, &buffer)) + currentDisk->physicalType = ffStrbufEqualS(&buffer, "1") ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD; + else + currentDisk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; + ffStrbufSubstrBefore(&basePath, index); + + // /sys/block/sdx/removable ffStrbufAppendS(&basePath, "/removable"); - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); return ffReadFileBuffer(basePath.chars, &buffer) && ffStrbufEqualS(&buffer, "1"); } @@ -231,7 +240,10 @@ static bool isRemovable(FFDisk* currentDisk) static void detectType(const FFlist* disks, FFDisk* currentDisk) { - if(isRemovable(currentDisk)) + bool isRemovable = detectPhysicalTypeAndReturnRemovable(currentDisk); + + if(currentDisk->type != FF_DISK_VOLUME_TYPE_NONE) return; + if(isRemovable) currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; @@ -277,7 +289,7 @@ const char* ffDetectDisksImpl(FFlist* disks) //We have a valid device, add it to the list FFDisk* disk = ffListAdd(disks); disk->type = FF_DISK_VOLUME_TYPE_NONE; - disk->physicalType = FF_DISK_TYPE_UNKNOWN; + disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; //detect mountFrom ffStrbufInitS(&disk->mountFrom, device->mnt_fsname); @@ -293,8 +305,7 @@ const char* ffDetectDisksImpl(FFlist* disks) detectName(disk); // Also detects external devices //detect type - if (disk->type == FF_DISK_VOLUME_TYPE_NONE) - detectType(disks, disk); + detectType(disks, disk); //Detects stats detectStats(disk); diff --git a/src/detection/disk/disk_windows.c b/src/detection/disk/disk_windows.c index 4f0213b53e..dadb7d3aec 100644 --- a/src/detection/disk/disk_windows.c +++ b/src/detection/disk/disk_windows.c @@ -29,7 +29,7 @@ const char* ffDetectDisksImpl(FFlist* disks) wchar_t volumeName[64]; - disk->physicalType = FF_DISK_TYPE_UNKNOWN; + disk->physicalType = FF_DISK_PHYSICAL_TYPE_UNKNOWN; if(mountpoint[1] == ':') { memcpy(volumeName, L"\\\\.\\ :", sizeof(L"\\\\.\\ :")); @@ -51,7 +51,7 @@ const char* ffDetectDisksImpl(FFlist* disks) NULL, NULL )) - disk->physicalType = dspd.IncursSeekPenalty ? FF_DISK_TYPE_HDD : FF_DISK_TYPE_SSD; + disk->physicalType = dspd.IncursSeekPenalty ? FF_DISK_PHYSICAL_TYPE_HDD : FF_DISK_PHYSICAL_TYPE_SSD; } } diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index 3698afa19a..e6c976f0eb 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -6,7 +6,7 @@ #include "modules/disk/disk.h" #include "util/stringUtils.h" -#define FF_DISK_NUM_FORMAT_ARGS 10 +#define FF_DISK_NUM_FORMAT_ARGS 11 #pragma GCC diagnostic ignored "-Wsign-conversion" static void printDisk(FFDiskOptions* options, const FFDisk* disk) @@ -111,6 +111,19 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) bool isExternal = !!(disk->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT); bool isHidden = !!(disk->type & FF_DISK_VOLUME_TYPE_HIDDEN_BIT); bool isReadOnly = !!(disk->type & FF_DISK_VOLUME_TYPE_READONLY_BIT); + const char* physicalType; + switch(disk->physicalType) + { + case FF_DISK_PHYSICAL_TYPE_HDD: + physicalType = "HDD"; + break; + case FF_DISK_PHYSICAL_TYPE_SSD: + physicalType = "SSD"; + break; + default: + physicalType = "Unknown"; + break; + } ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISK_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &usedPretty}, {FF_FORMAT_ARG_TYPE_STRBUF, &totalPretty}, @@ -123,6 +136,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk) {FF_FORMAT_ARG_TYPE_STRBUF, &disk->filesystem}, {FF_FORMAT_ARG_TYPE_STRBUF, &disk->name}, {FF_FORMAT_ARG_TYPE_BOOL, &isReadOnly}, + {FF_FORMAT_ARG_TYPE_STRING, physicalType} }); } } @@ -403,7 +417,7 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ yyjson_mut_obj_add_strbuf(doc, obj, "mountpoint", &item->mountpoint); yyjson_mut_obj_add_strbuf(doc, obj, "mountFrom", &item->mountFrom); yyjson_mut_obj_add_strbuf(doc, obj, "name", &item->name); - yyjson_mut_val* typeArr = yyjson_mut_obj_add_arr(doc, obj, "type"); + yyjson_mut_val* typeArr = yyjson_mut_obj_add_arr(doc, obj, "volumeType"); if(item->type & FF_DISK_VOLUME_TYPE_REGULAR_BIT) yyjson_mut_arr_add_str(doc, typeArr, "Regular"); if(item->type & FF_DISK_VOLUME_TYPE_EXTERNAL_BIT) @@ -414,6 +428,19 @@ void ffGenerateDiskJson(FFDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_ yyjson_mut_arr_add_str(doc, typeArr, "Hidden"); if(item->type & FF_DISK_VOLUME_TYPE_READONLY_BIT) yyjson_mut_arr_add_str(doc, typeArr, "Read-only"); + + switch(item->physicalType) + { + case FF_DISK_PHYSICAL_TYPE_HDD: + yyjson_mut_obj_add_str(doc, obj, "physicalType", "HDD"); + break; + case FF_DISK_PHYSICAL_TYPE_SSD: + yyjson_mut_obj_add_str(doc, obj, "physicalType", "SSD"); + break; + default: + yyjson_mut_obj_add_null(doc, obj, "physicalType"); + break; + } } FF_LIST_FOR_EACH(FFDisk, item, disks) From 7f75d42ec845eef19e0966d116aae61fa732359a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 1 Oct 2023 20:50:10 +0800 Subject: [PATCH 194/198] Logo (Builtin): tidy --- src/logo/ascii/{LainOS.txt => lainos.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/logo/ascii/{LainOS.txt => lainos.txt} (100%) diff --git a/src/logo/ascii/LainOS.txt b/src/logo/ascii/lainos.txt similarity index 100% rename from src/logo/ascii/LainOS.txt rename to src/logo/ascii/lainos.txt From 74ac023cb0bd8e5f38c2818247be1f445ad8e1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 1 Oct 2023 20:51:58 +0800 Subject: [PATCH 195/198] Logo (Builtin): support Oracle Linux Server Fix #569 --- src/logo/builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index d0a634b96d..319a0dc025 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -2774,7 +2774,7 @@ static const FFlogo O[] = { }, // Oracle { - .names = {"oracle", "oracle linux"}, + .names = {"oracle", "oracle linux", "oracle linux server"}, .lines = FASTFETCH_DATATEXT_LOGO_ORACLE, .colors = { FF_COLOR_FG_RED, From ddec13be29685db077fca586f8be431b14f67f7f Mon Sep 17 00:00:00 2001 From: Alxhr0 Date: Sun, 1 Oct 2023 15:52:16 +0200 Subject: [PATCH 196/198] Fix Slackware --- src/logo/builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 319a0dc025..2063635713 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3522,7 +3522,7 @@ static const FFlogo S[] = { .lines = FASTFETCH_DATATEXT_LOGO_SLACKWARE, .colors = { FF_COLOR_FG_BLUE, - FF_COLOR_FG_BLUE, + FF_COLOR_FG_WHITE, }, .colorKeys = FF_COLOR_FG_BLUE, .colorTitle = FF_COLOR_FG_BLUE, From f7cc4fb4b1332a2bbdf6c102ac8925df6e33509a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Oct 2023 18:00:30 +0800 Subject: [PATCH 197/198] Doc: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b815dad7de..feeaeb4723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ Logo: * Update Windows 11_small * Add Amazon Linux * Add LainOS +* Fix colors of Slackware # 2.0.5 From 45f523adb8599aaa67f0fd24e5c88efb09bbeecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 2 Oct 2023 18:03:10 +0800 Subject: [PATCH 198/198] Release v2.1.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f75d27104b..04eebf6797 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.0.5 + VERSION 2.1.0 LANGUAGES C DESCRIPTION "Fast system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"