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 9defef35e..e158640bc 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 8cca6e147..b91ef7a01 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 f1bcea4ee..b34c429f2 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 4f239650a..ee4bd5af7 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 7fcd772af..efee4a7f3 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 e158640bc..1d2b3e3f1 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 a8db1c600..9a59d7116 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 3ed020f19..44c0c3ee9 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 7bd07a49e..3d6d0d0f1 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 4c947d562..e2ef0a7b5 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 9277ee3a5..3248aa756 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 4f1a1ebc3..832e0d981 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 7a6622d4a..654f08cb8 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 000000000..7a6622d4a --- /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 879328062..4e838ad69 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 | 105 ++++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 33 deletions(-) diff --git a/src/logo/image/image.c b/src/logo/image/image.c index 3248aa756..82be5667e 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); } - ffPrintCharTimes('\n', instance.config.logo.paddingTop); - ffPrintCharTimes(' ', instance.config.logo.paddingLeft); + else + { + 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 - ); + 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 + ); + } 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 1d2b3e3f1..d2b089d0b 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 18a9b79c8..72508c954 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 d2b089d0b..7b9597dc7 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 8fcb7db6c..01931b861 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 1941e6637..fbfa55b56 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 2cd916bd8..c00706082 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 58e29f1f8..9d30b2be0 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 | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/logo/logo.c b/src/logo/logo.c index 9206a5ab1..fe068bad1 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); + 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); - 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); + 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 82be5667e..ee0fa3574 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 b91ef7a01..78c94ad9f 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 fbfa55b56..db5f3c65b 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 c00706082..c4c26145b 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 60c3c5259..dc6e28486 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 ee0fa3574..dc0d7e052 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 fe068bad1..c0aa519f5 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 ae79a4517..bced44147 100644 --- a/src/detection/terminalfont/terminalfont_android.c +++ b/src/detection/terminalfont/terminalfont_android.c @@ -55,7 +55,7 @@ exit: 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 72508c954..110ae7512 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 9d30b2be0..3eabaa6f6 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 | 113 ++++++++++++++++++++++++++++------------- src/logo/logo.c | 21 +++++--- src/logo/option.c | 8 +++ src/logo/option.h | 1 + 5 files changed, 105 insertions(+), 43 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index dc6e28486..b07bd08fb 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 dc0d7e052..3cd7c6294 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 - ); - 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) { - 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 + // 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); + 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 + { + 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 c0aa519f5..af240c549 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 59474a2d3..32114de22 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 @@ logoType: 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 1eb41c1e9..9273e2a3f 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 8da49361b..8ea44355d 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 3cd7c6294..16792842f 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 832e0d981..ada5be426 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 01931b861..7f26d402a 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 510ac61a9..934c52ef1 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 3ae2a8311..c938fe2a8 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 dfe8b4d19..8c5b60dcb 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 71bc3cf8f..0b257be53 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 e701cae86..1e932cf98 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 342b48083..9414e9a47 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 e2ef0a7b5..ef041ae3b 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 + ffPrintCommandOption(&data); + + if (instance.state.resultDoc) { - //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; - } + 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 a5f990912..8ba9158e9 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 af240c549..613e9a99b 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 ee4bd5af7..b0d95986e 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 26312bca7..adefbdedd 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 ee4201795..e1e7c6f96 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -55,7 +55,7 @@ exit: 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 aaaf15d65..a3bb81d8d 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 fa8b65d51..569d61e40 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 29a676ca8..7ec518c26 100644 --- a/src/modules/board/board.c +++ b/src/modules/board/board.c @@ -51,7 +51,7 @@ exit: 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 87821ee00..59c39c1d7 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 560353749..d13c4370c 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 02cd3e97d..d685ceb0b 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -52,7 +52,7 @@ exit: 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 488413f21..2e2075582 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 f19f1f27d..ad429d201 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 00aec6ba8..d89a9a17e 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 23b29e791..c0f8cd68c 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 c33e13d26..5a0143df7 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 b9406dcd3..38dd4189a 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 9d6307a13..1c11f5ac3 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 a44f437d7..80e69b854 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 202d8e1a8..f5d2bae98 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 31371de42..fa758911d 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 97c77359b..2d49fe3ee 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 3691b5ac8..5ba347ba2 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 5f71779a7..4edca36b5 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 d281ece1b..4fa03cb64 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -67,7 +67,7 @@ exit: 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 aa1827a5f..7d59c6bbf 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 bc1bd21a8..7e9fcf558 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 afef101a0..0cd896a53 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 4fa037b15..3d783f79f 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 74b61c580..9f3a1ca84 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 87b9b7f12..ef227cb9f 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 410fb97f2..3d7cb7139 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 688c62413..15b801fa1 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 6194b7a0b..4218dbfd2 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 d94849cf5..56f03a0cb 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 e5e5d58ee..b40dde038 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 21599e07a..1c1b67140 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 4dca65916..5e4bf6889 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 efee4a7f3..d847cb0cc 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 fa2fc89bd..02cf45b38 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 6097b54a3..fdaf7b9f6 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 0eaceff6a..fa2161228 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 d7e2cfa6d..1328c7acf 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 707556360..f8ddb13de 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 d4b08031d..1361009f9 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 5afa31c19..3d0367a22 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 755fc302d..4d92ccc61 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 f1ad620bc..a6083f8ed 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 025e2c78f..268d7bf50 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 8374cd10b..32d4b5ad9 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 1574209e0..89c93fd17 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 0c1263620..6c6387082 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 9cef899d2..0805c1ee4 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 bb66ae604..fe57fc9a0 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 e51ba590a..e6f49e18b 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 68d18d550..1338f3286 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 afa026917..0e030bd7e 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 f02efbf4e..3c7f53295 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 438e7f832..9376b5475 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 5667af76c..7df622ea2 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 b05cce111..16dce83d0 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 dc1281dda..52f179780 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 287f004a1..8675ab099 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 41d49db62..a0bbf85f6 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 66df36cf3..056bfd06a 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 b0d95986e..8d622885d 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 569d61e40..9b793e404 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 411bb3965..b4d1f0a89 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 4aecdfc6f..a9c07b161 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 d6f3e9878..abd31a0c2 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 @@ const char* ffDetectBluetooth(FFlist* devices /* FFBluetoothDevice */) 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 79f61d5fb..1ed712c90 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 4ae74ac3e..8db5a465c 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 0066cebb3..9415ea5f4 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 9b793e404..99b330fdb 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 7ec518c26..4c94ac3bd 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 f5531368e..0e1dabbab 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 d13c4370c..120459245 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 1272e5d0f..6933c6500 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 d685ceb0b..93c91c942 100644 --- a/src/modules/chassis/chassis.c +++ b/src/modules/chassis/chassis.c @@ -52,7 +52,7 @@ exit: 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 5fe4bb62f..c5553f772 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 ad429d201..393aab97b 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 8ee5cc82c..ec8e2bab3 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 9dcb07edd..da55404ee 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 d89a9a17e..dc46d835b 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 acff0a13c..0a3e7c4c6 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 c0f8cd68c..ca0909377 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 5a221f554..e31bc14c7 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 5a0143df7..945f44b72 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 ff849b547..02ed47e8f 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 1e932cf98..5dbfcc68f 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 1c11f5ac3..84188eb92 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 6ccb30b27..8f4ceb690 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 5dbfcc68f..d66636d2a 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 80e69b854..a6d896d7c 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 0a4e14541..b8d122184 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 d66636d2a..012caf0c1 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 8d622885d..85103b5c8 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 e1e7c6f96..b3f3e598c 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 99b330fdb..ade503bc1 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 4c94ac3bd..17e187ade 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 93c91c942..28a0f557d 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 dc46d835b..bab69f8f2 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 945f44b72..58f0ff981 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 84188eb92..a6e5e2245 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 f5d2bae98..4f74a380a 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 1f71f766b..eb4520b35 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 fa758911d..2f99b132b 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 b2f757056..6c46dfb18 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 012caf0c1..ea8c58968 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 2d49fe3ee..a737c615e 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 a51f9d447..dedb1dfb9 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 5ba347ba2..43818aa2f 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 eae8a8a17..eff98e992 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 4edca36b5..18773e7f3 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 b5334730a..73bd7fad5 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 bab69f8f2..7ff3ddf8f 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 4fa03cb64..30df24f12 100644 --- a/src/modules/host/host.c +++ b/src/modules/host/host.c @@ -67,7 +67,7 @@ exit: 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 5a689288a..4ed4575a1 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 7d59c6bbf..720432b70 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 97533b096..dab251e25 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 7e9fcf558..b8c9e31cf 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 943641d60..419f2544a 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 0cd896a53..f84a422a3 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 079f90e5f..72509adcb 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 3d783f79f..10c53ba3d 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 405f697c9..8570a3c8d 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 9f3a1ca84..28139c1d6 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 114459c6f..799860a42 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 ef227cb9f..7a0e01e77 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 f5267e579..853814d7e 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 5e4bf6889..5ca58ba27 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 f63e12250..829b7857a 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 3d7cb7139..1d2bba391 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 aec76b21f..b4fefff5d 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 1361009f9..331cbf26d 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 5921ad9c5..fbb125a44 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 d847cb0cc..a35ecfad4 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 e9490c832..a99d6acab 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 9abdd48ec..0c60d4d9f 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 de3025a40..06d8a8df6 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 a35ecfad4..a5ce64002 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 15b801fa1..c7f76a039 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 ff03d26e9..851144204 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 d8cb4a66b..0526de2e2 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 4218dbfd2..afe3efa24 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 f5e2a32c2..592f453bf 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 56f03a0cb..78bbf1842 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 5d0b1937b..6c35ede54 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 b40dde038..b905360e6 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 07320194d..b7ed39d0d 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 b6c656e8b..69431950f 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 | 32 ++++++++++++++++++++++++++++---- 3 files changed, 28 insertions(+), 22 deletions(-) delete mode 100644 src/detection/disk/disk_apple.m diff --git a/CMakeLists.txt b/CMakeLists.txt index a799086ba..fc0562fa0 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 81bcdeb48..000000000 --- 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 69431950f..efe98db9b 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; - - ffStrbufInit(&disk->name); } -#else -void detectFsInfo(struct statfs* fs, FFDisk* disk); +#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; + + 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); +} #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 da55404ee..792a9aaac 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 792a9aaac..ded5e0d89 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 797b51b59..2ce563d5e 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 52755bb8b..a8d9804a3 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 231ea342e..59f07ab7a 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 | 42 ++++++++++--- src/modules/users/option.h | 2 + src/modules/users/users.c | 98 +++++++++++++++++++++++------ src/util/windows/unicode.h | 3 + 8 files changed, 146 insertions(+), 35 deletions(-) diff --git a/src/common/format.c b/src/common/format.c index 4ed096dc1..8ccf09fa3 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 57c8c680f..3e7c751f2 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 8842e16a2..7248d8322 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 c17bf139c..dbad1255d 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 @@ next: 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 01fab40a7..6ef912670 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); + FFUserResult* user = (FFUserResult*) ffListAdd(users); + ffStrbufInitWS(&user->name, session->pUserName); + ffStrbufInitWS(&user->hostname, session->pHostName); - ffStrbufInitF((FFstrbuf*)ffListAdd(users), "%s\\%s", domainName.chars, userName.chars); + 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 80bf87698..6883e8dd0 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 6c6387082..764e73811 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_LIST_AUTO_DESTROY users = ffListCreate(sizeof(FFUserResult)); - FF_STRBUF_AUTO_DESTROY error = ffStrbufCreate(); + const char* error = ffDetectUsers(&users); - ffDetectUsers(&users, &error); - - 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 6892134dc..a25d4a7b4 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 447b13d5b..105e1bfa5 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 4e3a707c6..0b1bf00c7 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 0339bc7e6..039d550da 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 55053ab24..10f7157bb 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 6ef912670..0c222ef91 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 89c93fd17..74bce2798 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 77f8e6812..ae36b5078 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 5b5343f79..bfd6a4c79 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 ef041ae3b..5bf30bfa5 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 1c1b67140..2129050fe 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 16792842f..6da5f4cfc 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 74bce2798..c8334fef0 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 c8334fef0..96be15456 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 3bc1fd55f..2fa12e963 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 7248d8322..8ddc2a0cf 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 dbad1255d..904cde08a 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -30,7 +30,7 @@ next: 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 0c222ef91..a891520b1 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 764e73811..dee5a9bee 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 86d5f66f4..3ef57a1cf 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 2129050fe..1d6ba534a 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 14fd7301d..97b4ce239 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 02cf45b38..02a8bb53f 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 724faf7fb..8f14e00e4 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 1328c7acf..e7f03e730 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 4e4f976bf..354b51229 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 904cde08a..294c69b3e 100644 --- a/src/detection/users/users_linux.c +++ b/src/detection/users/users_linux.c @@ -36,9 +36,8 @@ next: 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 7ff3ddf8f..1825747e4 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 58f0ff981..555ec0374 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 2f99b132b..14acbcca4 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 654f08cb8..18ca20e23 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 000000000..8692019a9 --- /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 4e838ad69..87885bbd5 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 2886c092d..8681218b4 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 000000000..2886c092d --- /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 87885bbd5..e910c0130 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 613e9a99b..75a395ae9 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 000000000..3b86a44d4 --- /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 e910c0130..b61b9589b 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 c7f76a039..be0e22830 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 000000000..96ec3bb06 --- /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 715ebbcdc..d09568c55 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 f8ddb13de..f3efc6696 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 c35c16801..03ec8fe68 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 e7f03e730..a50607fff 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 3d0367a22..6009b1dbc 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 09949b00d..709b02e56 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 4d92ccc61..2b992912c 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 ac5953a36..434eb1a1f 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 797461cbd..8da249448 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 0b1bf00c7..90b986da7 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 039d550da..bfa67215b 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 10f7157bb..6978a1163 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 fc0562fa0..ed8a05f46 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 60cc1f658..000000000 --- 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 fd47ba03b..000000000 --- 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 a6e5e2245..3c1644299 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 { - 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 + //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) +{ + 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 a6083f8ed..22ef849ef 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 1703c5944..33699057d 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 268d7bf50..08b345fe7 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 32d4b5ad9..dc67b6546 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 fd7ae5e68..76bec364d 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 0805c1ee4..34b8e0642 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 ef423b36e..bb1e4c15f 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 90b986da7..47202544a 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 d9edbde01..ac5755103 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 c669bab9b..5934af7c1 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 a9740045a..d3d1074cd 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 ea8c58968..afb0fd865 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 fe57fc9a0..7bd65e25c 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 e9b7d3954..a0b378394 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 e6f49e18b..947a1031e 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 244684fc4..3925784b2 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 0e030bd7e..449b82e67 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 0a7b78e2d..2957f876d 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 18773e7f3..4bf6726ad 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 7bd65e25c..14c37153a 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 3c7f53295..371b48deb 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 607732d72..fe960b688 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 9376b5475..356076922 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 216fdc723..e90f9e253 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 5bf30bfa5..2d9cfb79d 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 6009b1dbc..ac68652f0 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 c727b5fdf..41e31700f 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 3eabaa6f6..1e1efa416 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 0bd65e578..ebc062b33 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 2d9cfb79d..3b78942d2 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 a50607fff..f7668c588 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 dc67b6546..7cfd087be 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 dee5a9bee..ab58440c2 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 7b9597dc7..84e75e4ad 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 ed8a05f46..8275f91df 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 000000000..4c1cdc42f --- /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 000000000..31ab394f4 --- /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 fdaf7b9f6..21ed3850b 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 3c1644299..adc7c50cf 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 f3efc6696..3796a7365 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 2b992912c..ca28576c9 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 31ab394f4..1313cc46a 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 21ed3850b..fbd7f12dd 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 6a7c739d2..870591eb7 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 8275f91df..7bad8d459 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 000000000..94bd6b5b6 --- /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 000000000..c15f1ea3a --- /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 1338f3286..d71dbef74 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 d71dbef74..609f5f329 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 888606957..a76940244 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 fbd7f12dd..c2ff3f297 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 609f5f329..ec25374b5 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 c986120ba..841a608e3 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 dc784c5db..fb29cd210 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) { + SYSTEM_PROCESS_INFORMATION* FF_AUTO_FREE pstart = NULL; + + // Multiple attempts in case processes change while + // we are in the middle of querying them. 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 = (SYSTEM_PROCESS_INFORMATION*)malloc(size); - if(!pstart) - return "malloc(size) failed"; - - if(!NT_SUCCESS(NtQuerySystemInformation(SystemProcessInformation, pstart, size, NULL))) - return "NtQuerySystemInformation(SystemProcessInformation, pstart) failed"; + 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 84e75e4ad..f280bce86 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 ac5755103..4e8e1106d 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 5934af7c1..3e74166c1 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 d3d1074cd..97b86fb96 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 c2ff3f297..e7c277e21 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 000000000..b70cac89c --- /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 b61b9589b..dce999e90 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 5a816363b..2b158dd4c 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 f280bce86..daa825510 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 934c52ef1..5b6f8013b 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 70a2a029d..ef049b698 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 9e9bce198..704abfd29 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 d35c93e2f..defce5a87 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 063127081..16b6de8ef 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 6da5f4cfc..953d12f8d 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 75a395ae9..8e52f318c 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 | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/logo/logo.c b/src/logo/logo.c index 8e52f318c..e03ba7221 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; - if (instance.config.brightColor) - fputs(FASTFETCH_TEXT_MODIFIER_BOLT, stdout); + FF_STRBUF_AUTO_DESTROY result = ffStrbufCreateA(2048); - ffPrintCharTimes('\n', options->paddingTop); - ffPrintCharTimes(' ', options->paddingLeft); + if (instance.config.brightColor) + ffStrbufAppendS(&result, FASTFETCH_TEXT_MODIFIER_BOLT); + + 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 b07bd08fb..4151686dc 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 0009dd10e..02389e63b 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 08b345fe7..2fc89549b 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 ef8f18a79..c0cee8584 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 1e1efa416..957a0b304 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 3b78942d2..94db3e666 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 fced34a92..3ccab52c4 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 efe98db9b..827ec32c2 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 fb5597baa..0460cdfd1 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 4f74a380a..0dcd6d97c 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 5b3b39232..dacf5ba94 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 0460cdfd1..91a7478dc 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 91a7478dc..ab328ac24 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 daa825510..8bfe24e1d 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 ab328ac24..7ab118038 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 fa2161228..555bb2a04 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 7cfd087be..3399f3c20 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 ad0a179da..baa69e1e1 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 fa646f9de..536b09aed 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 3f7aada12..2c9b0f4c6 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -141,38 +141,9 @@ 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); + 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); -} -#endif - static void getUserShell(FFPlatform* platform, const struct passwd* pwd) { const char* shell = getenv("SHELL"); @@ -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 02389e63b..fea0c26c6 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 8bfe24e1d..b68905cee 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 2ddf030b5..000000000 --- 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 6f79f97e7..000000000 --- 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 450adb926..000000000 --- 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 44c0c3ee9..000000000 --- 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 0dcd6d97c..3698afa19 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 94db3e666..6fcef4810 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 1825747e4..644cda9f4 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 4bf6726ad..95a25df3b 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 c04184f24..ee78eb35a 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 dce999e90..5bbb455f1 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 8ccf09fa3..b5092c6c7 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 000000000..13215add1 --- /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 7ab118038..ddb81c8bf 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 ddb81c8bf..035cec899 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 644cda9f4..3cd5a6cf7 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 d65843947..58aeed20a 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 ecbe60478..a3b1d3c8f 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 8c6a89e2f..72f1e5476 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 8ab4e5f86..b3e75b234 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 28f489b96..06c169017 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 120459245..261122bb0 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 7bad8d459..e87dd9574 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 827ec32c2..bd7adf4e5 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 b68905cee..77dfce3cd 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 77dfce3cd..34d0388a1 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 14acbcca4..f623bc5f4 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 34d0388a1..ab3a8bf77 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 7dd4061b4..deca9d86d 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 ab3a8bf77..0bf347ed0 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 deca9d86d..1aa2c2433 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 7f26d402a..1ebca55d9 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 d09568c55..3a0783c9f 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 0bf347ed0..71d44430f 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 e87dd9574..d570df8eb 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 ada5be426..2233edf42 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 749072f46..72a653008 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 000000000..fa77a4be0 --- /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 3a0783c9f..42d6dbd96 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 71d44430f..c3a0896e5 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 16b6de8ef..0d8635f2f 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 c3a0896e5..60e4a3a1e 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 38dd4189a..6576cd3c5 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 60e4a3a1e..1d6743c72 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 3d6d0d0f1..9d3be5796 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 6fcef4810..2c6af9b47 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 3399f3c20..a0174322a 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, '.'); + FF_STRBUF_AUTO_DESTROY hostNameColored = ffStrbufCreate(); + appendText(&hostNameColored, &hostName, &options->colorHost); + + 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 (options->moduleArgs.outputFormat.length == 0) { - ffPrintLogoAndKey(options->moduleArgs.key.length == 0 ? NULL : FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffPrintLogoAndKey(FF_TITLE_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - printTitlePart(&instance.state.platform.userName, &options->colorUser); - - if (!instance.config.pipe && options->colorAt.length > 0) - ffPrintColor(&options->colorAt); - putchar('@'); - - 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 2c6af9b47..a38f2ce0a 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 1d6743c72..13acef153 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 2e2075582..4bcf9bafd 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 a17029bd8..e51cea6f1 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 8c5b60dcb..a501ed348 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 7fb6fade5..37c796276 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 0b8989c4e..55b4c5be7 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 13acef153..6b3cdcd3f 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 42d6dbd96..c6832bdcf 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 6b3cdcd3f..f59238c45 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 000000000..d8327be7a --- /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 a38f2ce0a..fd7dd8249 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 | 78 ++++++++++++-------------- 5 files changed, 51 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f59238c45..a56bb1878 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 b8c9e31cf..89aab0af1 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 536b09aed..48c72513e 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 2c9b0f4c6..cc6fa803a 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 fea0c26c6..0774c81c3 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; + FF_HKEY_AUTO_DESTROY hKey = NULL; + if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", &hKey, NULL)) + return; - char currentVersion[32]; + uint32_t ubr = 0; + ffRegReadUint(hKey, L"UBR", &ubr, NULL); + ffStrbufAppendF(&platform->systemRelease, + "%u.%u.%u.%u", + (unsigned) osVersion.dwMajorVersion, + (unsigned) osVersion.dwMinorVersion, + (unsigned) osVersion.dwBuildNumber, + (unsigned) ubr); + + ffStrbufInit(&platform->systemDisplayVersion); + if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &platform->systemDisplayVersion, NULL) && osVersion.szCSDVersion[0]) + ffStrbufSetWS(&platform->systemDisplayVersion, osVersion.szCSDVersion); + + ffRegReadStrbuf(hKey, L"BuildLabEx", &platform->systemVersion, NULL); + + switch (osVersion.dwPlatformId) { - 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"); - } + 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; } - - char currentBuildNumber[32]; - bufSize = sizeof(currentBuildNumber); - if(RegGetValueA(hKey, NULL, "CurrentBuildNumber", RRF_RT_REG_SZ, NULL, currentBuildNumber, &bufSize) != ERROR_SUCCESS) - strcpy(currentBuildNumber, "0"); - - 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, "%s.%s.%u", currentVersion, currentBuildNumber, (unsigned)ubr); - - 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; - - RegCloseKey(hKey); } 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 baa69e1e1..b81adc3c6 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 cc6fa803a..33c76bc69 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 9415ea5f4..bcd9da33e 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 338a1fcfb..e1371f0ac 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 a56bb1878..1167b9e1b 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 4a8eb420c..202c10ca2 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 bdb11aa3a..4cb7b9ac6 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 fd7dd8249..eafb1de61 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 34b8e0642..54781eb62 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 c6b572012..775856eec 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -63,7 +63,7 @@ const char* ffDetectWifi(FFlist* result) 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 d570df8eb..889082cdd 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 9414e9a47..3fef4995a 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 889082cdd..2215ef628 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 6fea95a79..994debec5 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 841a608e3..09071d275 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 deace35d9..074753eb6 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 bdffc755f..af340756b 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 af57a0628..d1e342503 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 ef049b698..221a98fc3 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 704abfd29..77db4be96 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 defce5a87..702f40539 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 e70234735..a94a83c95 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 2215ef628..26208f710 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 994debec5..6fea95a79 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 a94a83c95..e70234735 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 000000000..a754f3917 --- /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 000000000..c430a1f47 --- /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 26208f710..ae7dd1e81 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 09071d275..841a608e3 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 000000000..8facefcf5 --- /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 ae7dd1e81..4390f3bc0 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 000000000..1d8515863 --- /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 4390f3bc0..c3b47e5cf 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 5b6f8013b..6454f51e9 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 a501ed348..490e4d0b5 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 1c4cd108a..b83588992 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 000000000..c515df279 --- /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 000000000..f00177392 --- /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 000000000..299fd6034 --- /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 000000000..d48cdbac8 --- /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 e70234735..233d42500 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 841a608e3..82323fd11 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 000000000..af885edb2 --- /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 a754f3917..35a95367f 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 1d8515863..ffd430dfa 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 c430a1f47..aea66b463 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 8facefcf5..1604b61de 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 8ba9158e9..c9cbfbb62 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 28139c1d6..705a6c902 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 1f7669c10..2ab14bc60 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 000000000..51a3c1f6b --- /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 000000000..4067d6899 --- /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 000000000..59463249f --- /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 12041ce5b..77c6cf855 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 c9cbfbb62..ccf3a8f10 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 1ed61cf82..9eb45f78c 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 fbc0e93e3..faef70d09 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 6fea95a79..8d0fe84bf 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 233d42500..195ab2ae0 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 82323fd11..78552be5b 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 705a6c902..c96b09806 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 c3b47e5cf..f780c91b9 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 000000000..a6aed5730 --- /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 c515df279..5b20e16f8 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 f00177392..fcd657a30 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 299fd6034..f8b323b67 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 d48cdbac8..3fc80ecba 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 195ab2ae0..38cec4233 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 78552be5b..8863843fd 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 4151686dc..7623f0a02 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 6454f51e9..45369a163 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 0b257be53..5d6027f4a 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 af885edb2..88888c28a 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 35a95367f..bb6234ee1 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 ffd430dfa..c6ec58a3e 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 aea66b463..a5d64be5b 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 1604b61de..b9d45f3e7 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 51a3c1f6b..75e0bfdf2 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 4067d6899..4feaee10a 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 59463249f..ff436aaf2 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 77db4be96..9a28bafb4 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 | 23 ++++++++++++++++++----- src/modules/localip/localip.c | 2 +- src/modules/netusage/netusage.c | 11 +++++++---- 9 files changed, 37 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1167b9e1b..f133d5449 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 2233edf42..5aefedd3a 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 1841c47ca..804589d81 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 b3e9c30d9..27c9f6d42 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 9d3be5796..aed51c723 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 eb975f786..36617c00a 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 eafb1de61..bdd2fdf52 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")) + else if(ffStrEqualsIgnCase(command, "localip-format")) { - constructAndPrintCommandHelpFormat("local-ip", "{}", 1, - "Local IP address" + 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 c96b09806..36013d505 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 75e0bfdf2..2ae67a704 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 c6ec58a3e..b5fd61083 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 f133d5449..7c1cc3c75 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 f780c91b9..6b4292475 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 5aefedd3a..b38e37b95 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 7623f0a02..d7e681566 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 804589d81..b0ed3cab5 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 27c9f6d42..f8d4cc82e 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 45369a163..e8a7e8001 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 490e4d0b5..35f1467fc 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 5d6027f4a..6d8fee329 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 b83588992..420903c8e 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 aed51c723..c8a257ec5 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 36617c00a..94ba7f617 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 e115782aa..8a5799717 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 88888c28a..5a07af8e2 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 bb6234ee1..295c4478e 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 b5fd61083..a0c764dbd 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 a5d64be5b..4b5565cbc 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 b9d45f3e7..526e01707 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 bdd2fdf52..c956357eb 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 ccf3a8f10..0877c1088 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 2ab14bc60..64ab6ea21 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 2ae67a704..3efef948f 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 000000000..3562d0ccd --- /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 ff436aaf2..62b493d29 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 4feaee10a..000000000 --- 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 77c6cf855..1be2e88e0 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 | 45 ++++---- 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 | 132 +++++++++++++----------- 9 files changed, 110 insertions(+), 105 deletions(-) diff --git a/src/common/netif/netif.c b/src/common/netif/netif.c index a6aed5730..ec317454b 100644 --- a/src/common/netif/netif.c +++ b/src/common/netif/netif.c @@ -1,35 +1,30 @@ #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; -} + #include #else -bool ffNetifGetDefaultRouteImpl(uint32_t* ifIndex); + #define IF_NAMESIZE 16 +#endif -uint32_t ffNetifGetDefaultRoute() +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]; + +static inline void init() { - static uint32_t ifIndex = (uint32_t) -1; + if (ifIndex == (uint32_t) IF_INDEX_UNINITIALIZED && !ffNetifGetDefaultRouteImpl(ifName, &ifIndex)) + ifIndex = (uint32_t) IF_INDEX_INVALID; +} - if (ifIndex == (uint32_t) -1) - { - if (!ffNetifGetDefaultRouteImpl(&ifIndex)) - ifIndex = (uint32_t) -2; - } +const char* ffNetifGetDefaultRouteIfName() +{ + 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 5b20e16f8..23ca5ef60 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 fcd657a30..f288d7d35 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 f8b323b67..f645b0a0b 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 3fc80ecba..df591d5e6 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 38cec4233..1f319ad34 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 8863843fd..bb39b4325 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 a0c764dbd..57e36d086 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 4b5565cbc..2b1f24478 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(entry->d_name[0] == '.') - continue; + if (options->namePrefix.length && strncmp(defaultRouteIfName, options->namePrefix.chars, options->namePrefix.length) != 0) + return NULL; - bool isDefaultRoute = ffStrEquals(entry->d_name, defaultRouteIface); - if(options->defaultRouteOnly && !isDefaultRoute) - continue; + getData(&buffer, defaultRouteIfName, true, &path, result); + } + else + { + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + const char* ifName = entry->d_name; + if(ifName[0] == '.') + continue; - if (options->namePrefix.length && strncmp(entry->d_name, options->namePrefix.chars, options->namePrefix.length) != 0) - continue; + if (options->namePrefix.length && strncmp(ifName, 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); + 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 df591d5e6..8607ed486 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 57e36d086..6bf9a8ce6 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 526e01707..4291df3d4 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 7c1cc3c75..e0fdfceb1 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 b38e37b95..3148465d5 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 000000000..915267868 --- /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 5bbb455f1..7c62bdb3d 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 815ed1fc8..84bc79cec 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 e0fdfceb1..796421cf4 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 af340756b..1243fbf78 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 1243fbf78..1241ef889 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 6b4292475..f75d27104 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 796421cf4..b815dad7d 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 000000000..9bd6c5530 --- /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 7c62bdb3d..d0a634b96 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 110ae7512..cad8c5cbc 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 e1371f0ac..1b99c174c 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 b905360e6..120f769fc 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 3ccab52c4..08701b14f 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 bd7adf4e5..f4345f4bf 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 035cec899..c58b0dee3 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 dacf5ba94..4f0213b53 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 08701b14f..06611f85c 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 f4345f4bf..55fc94a2e 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 c58b0dee3..bc53eb783 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 4f0213b53..dadb7d3ae 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 3698afa19..e6c976f0e 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 d0a634b96..319a0dc02 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 319a0dc02..206363571 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 b815dad7d..feeaeb472 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 f75d27104..04eebf679 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"