From 70e8398f05590ec56d23b46891b56d8a2b133dbd Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 29 Sep 2024 16:18:43 +0800 Subject: [PATCH 01/48] Packaging: update debian stuff [ci skip] --- debian/changelog | 12 ++++++++++++ debian/files | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 3a6b98854b..3eff4467a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +fastfetch (2.26.1ubuntu1) jammy; urgency=medium + + * Update correct code + + -- Carter Li Mon, 30 Sep 2024 00:21:20 +0800 + +fastfetch (2.26.1) jammy; urgency=medium + + * Update to 2.26.1 + + -- Carter Li Sun, 29 Sep 2024 16:15:31 +0800 + fastfetch (2.26.0) jammy; urgency=medium * Update to 2.26.0 diff --git a/debian/files b/debian/files index 1d7ec558e0..8a4ba4133c 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.26.0_source.buildinfo universe/utils optional +fastfetch_2.26.1ubuntu1_source.buildinfo universe/utils optional From d97999ddc9a774e034541b371162ff6d4b5f0939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 29 Sep 2024 23:08:41 +0800 Subject: [PATCH 02/48] GPU (Linux): trim trailing new line Fix #1303 --- src/detection/gpu/gpu_linux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 2862f73c0a..2392a09ba7 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -657,7 +657,10 @@ static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, co #endif if (!gpu->name.length) + { ffStrbufSetS(&gpu->name, name ? name : compatible); + ffStrbufTrimRightSpace(&gpu->name); + } if (!gpu->vendor.length && name) { compatible[0] = (char) toupper(compatible[0]); From eeb2d1c746027feec58dbf85d70c68f260a0dce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 10:24:08 +0800 Subject: [PATCH 03/48] Doc: update README.md [ci skip] --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d6e8e3d05..6487d0e70e 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,10 @@ pyfiglet -s -f small_slant $(fastfetch -s os --format json | jq -r '.[0].result. ![image](https://github.com/fastfetch-cli/fastfetch/assets/6134068/6466524e-ab8c-484f-848d-eec7ddeb7df2) +### Q: My image logo behaves weird. How can I fix it? + +See troubleshooting section: + ### Q: Fastfetch runs in white and black on shell startup. Why? This issue usually happens when using fastfetch with `p10k`. There are known incompatibility between fastfetch and p10k instant prompt. @@ -186,9 +190,19 @@ You can always use `fastfetch --pipe false` to force fastfetch running in colorf See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096). +### Q: Fastfetch shows less dpkg packages than neofetch, is it a bug? + +Neofetch incorrectly counts `rc` packages ( the package has been removed, but that the configuration files remain ). Bug https://github.com/dylanaraps/neofetch/issues/2278 + ### Q: I use Debian / Ubuntu / Debian deserved distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug? -See [#1282](https://github.com/fastfetch-cli/fastfetch/issues/1282) +Try upgrading `pci.ids`: Download and overwrite file `/usr/share/hwdata/pci.ids`. For AMD GPUs, you should also upgrade `amdgpu.ids`: Download and overwrite file `/usr/share/libdrm/amdgpu.ids` + +Alternatively, you may try to use `fastfetch --gpu-driver-specific`, so that `fastfetch` will try to ask the driver for GPU name if supported. + +### Q: Fastfetch cannot detect my awesome 3rd-party macOS window manager! + +Try `fastfetch --wm-detect-plugin`. See also [#984](https://github.com/fastfetch-cli/fastfetch/issues/984) ### Q: I want feature A / B / C. Will fastfetch support it? From 2cd6cb3ca14a34d597577baa46380e61bf02817b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 30 Sep 2024 15:00:55 +0800 Subject: [PATCH 04/48] Board (Linux): use `/proc/device-tree/board` if available --- src/detection/board/board_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/board/board_linux.c b/src/detection/board/board_linux.c index 0165df2e1f..2820bbc847 100644 --- a/src/detection/board/board_linux.c +++ b/src/detection/board/board_linux.c @@ -12,9 +12,9 @@ const char* ffDetectBoard(FFBoardResult* board) ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor); ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version); } - else if (ffReadFileBuffer("/proc/device-tree/compatible", &board->vendor)) + else if (ffReadFileBuffer("/proc/device-tree/board", &board->vendor) || + ffReadFileBuffer("/proc/device-tree/compatible", &board->vendor)) { - // use model name as board name uint32_t comma = ffStrbufFirstIndexC(&board->vendor, ','); if (comma < board->vendor.length) { From 1df129083b2cd8b8336752afe95209348cae22f5 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 30 Sep 2024 15:02:49 +0800 Subject: [PATCH 05/48] GPU (Linux): add a special case for brcm --- src/detection/gpu/gpu_linux.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 2392a09ba7..45fbdfef0a 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -663,8 +663,13 @@ static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, co } if (!gpu->vendor.length && name) { - compatible[0] = (char) toupper(compatible[0]); - ffStrbufSetS(&gpu->vendor, compatible); + if (ffStrEquals(compatible, "brcm")) + ffStrbufSetStatic(&gpu->vendor, "Broadcom"); // Raspberry Pi + else + { + ffStrbufSetS(&gpu->vendor, compatible); + gpu->vendor.chars[0] = (char) toupper(compatible[0]); + } } return NULL; From d77f0fe3d9acfd7e77c9876de2471d645a470e1c Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 30 Sep 2024 15:03:25 +0800 Subject: [PATCH 06/48] CPU (Linux): detect SOC name if available --- src/detection/cpu/cpu_linux.c | 70 +++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index ffc6d835dc..704e506fba 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -388,38 +388,53 @@ FF_MAYBE_UNUSED static void detectArmSoc(FFCPUResult* cpu) return; // device-vendor,device-model\0soc-vendor,soc-model\0 - char content[64]; + char content[256]; ssize_t length = ffReadFileData("/proc/device-tree/compatible", sizeof(content), content); if (length <= 2) return; - // get the second NUL terminated string - char* modelName = memchr(content, '\0', (size_t) length) + 1; - if (!modelName || modelName - content >= length) return; + // get the second NUL terminated string if it exists + char* vendor = memchr(content, '\0', (size_t) length) + 1; + if (!vendor || vendor - content >= length) vendor = content; - if (ffStrStartsWith(modelName, "apple,t")) + char* model = strchr(vendor, ','); + if (!model) return; + *model = '\0'; + ++model; + + if (false) {} + #if __aarch64__ + else if (ffStrEquals(vendor, "apple")) { - // https://elixir.bootlin.com/linux/v6.11-rc7/source/arch/arm64/boot/dts/apple - const char* code = modelName + strlen("apple,t"); - uint32_t deviceId = (uint32_t) strtoul(code, NULL, 10); - ffStrbufSetStatic(&cpu->name, ffCPUAppleCodeToName(deviceId)); - if (!cpu->name.length) + // https://elixir.bootlin.com/linux/v6.11/source/arch/arm64/boot/dts/apple + if (model[0] == 't') { - ffStrbufAppendS(&cpu->name, "Apple Silicon T"); - ffStrbufAppendS(&cpu->name, code); + uint32_t deviceId = (uint32_t) strtoul(model + 1, NULL, 10); + ffStrbufSetStatic(&cpu->name, ffCPUAppleCodeToName(deviceId)); + + if (!cpu->name.length) + { + ffStrbufSetS(&cpu->name, "Apple Silicon "); + ffStrbufAppendS(&cpu->name, model); + } } + else + ffStrbufSetS(&cpu->name, model); + + ffStrbufSetStatic(&cpu->vendor, "Apple"); } - else if (ffStrStartsWith(modelName, "qcom,")) + #endif + else if (ffStrEquals(vendor, "qcom")) { - // https://elixir.bootlin.com/linux/v6.11-rc7/source/arch/arm64/boot/dts/qcom - if (ffStrStartsWith(modelName + strlen("qcom,"), "x")) + // https://elixir.bootlin.com/linux/v6.11/source/arch/arm64/boot/dts/qcom + if (ffStrStartsWith(model, "x")) { ffStrbufSetS(&cpu->name, "Qualcomm Snapdragon X Elite "); - for (const char* p = modelName + strlen("qcom,"); *p; ++p) + for (const char* p = model + 1; *p; ++p) ffStrbufAppendC(&cpu->name, (char) toupper(*p)); } - else if (ffStrStartsWith(modelName + strlen("qcom,"), "sc")) + else if (ffStrStartsWith(model, "sc")) { - const char* code = modelName + strlen("qcom,sc"); + const char* code = model + 2; uint32_t deviceId = (uint32_t) strtoul(code, NULL, 10); ffStrbufSetStatic(&cpu->name, ffCPUQualcommCodeToName(deviceId)); if (!cpu->name.length) @@ -428,6 +443,23 @@ FF_MAYBE_UNUSED static void detectArmSoc(FFCPUResult* cpu) ffStrbufAppendS(&cpu->name, code); } } + else + ffStrbufSetS(&cpu->name, model); + + ffStrbufSetStatic(&cpu->vendor, "Qualcomm"); + } + else if (ffStrEquals(vendor, "brcm")) + { + // Raspberry Pi + ffStrbufSetStatic(&cpu->vendor, "Broadcom"); + for (const char* p = model; *p; ++p) + ffStrbufAppendC(&cpu->name, (char) toupper(*p)); + } + else + { + ffStrbufSetS(&cpu->name, model); + ffStrbufSetS(&cpu->vendor, vendor); + cpu->vendor.chars[0] = (char) toupper(vendor[0]); } } @@ -480,7 +512,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) #if __ANDROID__ detectAndroid(cpu); - #elif __aarch64__ + #else detectArmSoc(cpu); #endif From a32361fdc5bcb2b2f9c9dafe8d42f416bb2d59a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 15:45:06 +0800 Subject: [PATCH 07/48] Brightness: add new option `--brightness-compact` --- doc/json_schema.json | 5 +++++ src/data/help.json | 8 +++++++ src/modules/brightness/brightness.c | 34 +++++++++++++++++++++++++++++ src/modules/brightness/option.h | 1 + 4 files changed, 48 insertions(+) diff --git a/doc/json_schema.json b/doc/json_schema.json index 04266e3833..231b9db3f0 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1041,6 +1041,11 @@ "maximum": 400, "default": 10 }, + "compact": { + "description": "Set if multiple results should be printed in one line", + "type": "boolean", + "default": false + }, "key": { "$ref": "#/$defs/key" }, diff --git a/src/data/help.json b/src/data/help.json index 0d3424adbe..2d99a0b3aa 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1000,6 +1000,14 @@ "default": 10 } }, + { + "long": "brightness-compact", + "desc": "Set if multiple results should be printed in one line", + "arg": { + "type": "bool", + "default": false + } + }, { "long": "sound-type", "desc": "Set what type of sound devices should be printed", diff --git a/src/modules/brightness/brightness.c b/src/modules/brightness/brightness.c index ca989d35b5..c5740bc57a 100644 --- a/src/modules/brightness/brightness.c +++ b/src/modules/brightness/brightness.c @@ -25,6 +25,24 @@ void ffPrintBrightness(FFBrightnessOptions* options) return; } + if (options->compact) + { + FF_STRBUF_AUTO_DESTROY str = ffStrbufCreate(); + + FF_LIST_FOR_EACH(FFBrightnessResult, item, result) + { + if(str.length > 0) + ffStrbufAppendC(&str, ' '); + + const double percent = (item->current - item->min) / (item->max - item->min) * 100; + ffPercentAppendNum(&str, percent, options->percent, false, &options->moduleArgs); + } + + ffPrintLogoAndKey(FF_BRIGHTNESS_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&str, stdout); + return; + } + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); uint32_t index = 0; @@ -101,6 +119,12 @@ bool ffParseBrightnessCommandOptions(FFBrightnessOptions* options, const char* k return true; } + if (ffStrEqualsIgnCase(subKey, "compact")) + { + options->compact = ffOptionParseBoolean(value); + return true; + } + if (ffPercentParseCommandOptions(key, subKey, value, &options->percent)) return true; @@ -126,6 +150,12 @@ void ffParseBrightnessJsonObject(FFBrightnessOptions* options, yyjson_val* modul continue; } + if (ffStrEqualsIgnCase(key, "compact")) + { + options->compact = (uint32_t) yyjson_get_bool(val); + continue; + } + if (ffPercentParseJsonObject(key, val, &options->percent)) continue; @@ -144,6 +174,9 @@ void ffGenerateBrightnessJsonConfig(FFBrightnessOptions* options, yyjson_mut_doc yyjson_mut_obj_add_uint(doc, module, "ddcciSleep", options->ddcciSleep); ffPercentGenerateJsonConfig(doc, module, defaultOptions.percent, options->percent); + + if (defaultOptions.compact != options->compact) + yyjson_mut_obj_add_bool(doc, module, "compact", options->compact); } void ffGenerateBrightnessJsonResult(FF_MAYBE_UNUSED FFBrightnessOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -205,6 +238,7 @@ void ffInitBrightnessOptions(FFBrightnessOptions* options) options->ddcciSleep = 10; options->percent = (FFColorRangeConfig) { 100, 100 }; + options->compact = false; } void ffDestroyBrightnessOptions(FFBrightnessOptions* options) diff --git a/src/modules/brightness/option.h b/src/modules/brightness/option.h index 2623d0aead..e359cdc3e8 100644 --- a/src/modules/brightness/option.h +++ b/src/modules/brightness/option.h @@ -12,4 +12,5 @@ typedef struct FFBrightnessOptions uint32_t ddcciSleep; // ms FFColorRangeConfig percent; + bool compact; } FFBrightnessOptions; From ca442b3da49728b29cf4fba14eaffcb746e79f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 19:53:10 +0800 Subject: [PATCH 08/48] Monitor (macOS): improve performance --- src/detection/monitor/monitor_apple.m | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 04163bc7cb..8a9487443c 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -9,6 +9,7 @@ #ifdef MAC_OS_X_VERSION_10_15 extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); +extern Boolean CoreDisplay_Display_SupportsHDRMode(CGDirectDisplayID display) __attribute__((weak_import)); #else #include #endif @@ -43,6 +44,19 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) return false; } +static bool detectHdrSupport(CFDictionaryRef displayInfo, FFDisplayResult* display) +{ + #ifdef MAC_OS_X_VERSION_10_15 + if (CoreDisplay_Display_SupportsHDRMode) + { + if (CoreDisplay_Display_SupportsHDRMode(display->id)) + return true; + } + #endif + return CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || + detectHdrSupportWithNSScreen(display); +} + const char* ffDetectMonitor(FFlist* results) { #ifdef MAC_OS_X_VERSION_10_15 @@ -77,8 +91,7 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) monitor->width = width; monitor->height = height; ffEdidGetPhysicalSize(edidData, &monitor->physicalWidth, &monitor->physicalHeight); - monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || - detectHdrSupportWithNSScreen(display); + monitor->hdrCompatible = detectHdrSupport(displayInfo, display); continue; } } @@ -97,8 +110,7 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) CGSize size = CGDisplayScreenSize((CGDirectDisplayID) display->id); monitor->physicalWidth = (uint32_t) (size.width + 0.5); monitor->physicalHeight = (uint32_t) (size.height + 0.5); - monitor->hdrCompatible = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || - detectHdrSupportWithNSScreen(display); + monitor->hdrCompatible = detectHdrSupport(displayInfo, display); monitor->serial = CGDisplaySerialNumber((CGDirectDisplayID) display->id); FF_CFTYPE_AUTO_RELEASE CFArrayRef modes = CGDisplayCopyAllDisplayModes((CGDirectDisplayID) display->id, NULL); From fb0a18dc8200f2359a16ef46a220565fe7da88b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 20:16:24 +0800 Subject: [PATCH 09/48] Display (macOS): merge `monitor` module features --- src/detection/displayserver/displayserver.c | 5 +- src/detection/displayserver/displayserver.h | 13 ++++- .../displayserver/displayserver_apple.c | 22 +++++-- src/modules/display/display.c | 58 +++++++++++++++++-- 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index ddc973962f..74898721bc 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -33,7 +33,10 @@ FFDisplayResult* ffdsAppendDisplay( display->primary = primary; display->bitDepth = 0; - display->hdrEnabled = false; + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + display->manufactureYear = 0; + display->manufactureWeek = 0; + display->serial = 0; return display; } diff --git a/src/detection/displayserver/displayserver.h b/src/detection/displayserver/displayserver.h index 127dbc5fe9..5a030b12ab 100644 --- a/src/detection/displayserver/displayserver.h +++ b/src/detection/displayserver/displayserver.h @@ -48,6 +48,14 @@ typedef enum FFDisplayType { FF_DISPLAY_TYPE_EXTERNAL, } FFDisplayType; +typedef enum FFDisplayHdrStatus +{ + FF_DISPLAY_HDR_STATUS_UNKNOWN, + FF_DISPLAY_HDR_STATUS_UNSUPPORTED, + FF_DISPLAY_HDR_STATUS_SUPPORTED, + FF_DISPLAY_HDR_STATUS_ENABLED, +} FFDisplayHdrStatus; + typedef struct FFDisplayResult { uint32_t width; @@ -63,7 +71,10 @@ typedef struct FFDisplayResult uint32_t physicalHeight; bool primary; uint8_t bitDepth; - bool hdrEnabled; + FFDisplayHdrStatus hdrStatus; + uint16_t manufactureYear; + uint16_t manufactureWeek; + uint32_t serial; } FFDisplayResult; typedef struct FFDisplayServerResult diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index ab2abe5e29..b419d52c7b 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -8,9 +8,10 @@ #include #include +extern Boolean CoreDisplay_Display_SupportsHDRMode(CGDirectDisplayID display) __attribute__((weak_import)); +extern Boolean CoreDisplay_Display_IsHDRModeEnabled(CGDirectDisplayID display) __attribute__((weak_import)); #ifdef MAC_OS_X_VERSION_10_15 extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); -extern Boolean CoreDisplay_Display_IsHDRModeEnabled(CGDirectDisplayID display) __attribute__((weak_import)); #else #include #endif @@ -89,12 +90,23 @@ static void detectDisplays(FFDisplayServerResult* ds) display->bitDepth = (uint8_t) bitDepth; } - #ifdef MAC_OS_X_VERSION_10_15 - if (CoreDisplay_Display_IsHDRModeEnabled) + if (display->type == FF_DISPLAY_TYPE_BUILTIN) + display->hdrStatus = CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) + ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else if (CoreDisplay_Display_SupportsHDRMode) { - display->hdrEnabled = CoreDisplay_Display_IsHDRModeEnabled(screen); + if (CoreDisplay_Display_SupportsHDRMode(screen)) + { + if (CoreDisplay_Display_IsHDRModeEnabled) + { + display->hdrStatus = CoreDisplay_Display_IsHDRModeEnabled(screen) + ? FF_DISPLAY_HDR_STATUS_ENABLED + : FF_DISPLAY_HDR_STATUS_SUPPORTED; + } + else + display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + } } - #endif } CGDisplayModeRelease(mode); } diff --git a/src/modules/display/display.c b/src/modules/display/display.c index ff1c93528b..91e5719d1a 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -6,7 +6,7 @@ #include -#define FF_DISPLAY_NUM_FORMAT_ARGS 15 +#define FF_DISPLAY_NUM_FORMAT_ARGS 18 static int sortByNameAsc(FFDisplayResult* a, FFDisplayResult* b) { @@ -127,7 +127,7 @@ void ffPrintDisplay(FFDisplayOptions* options) if(result->type != FF_DISPLAY_TYPE_UNKNOWN) ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); - if (result->hdrEnabled) + if (result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED) ffStrbufAppendS(&buffer, " [HDR]"); if(moduleIndex > 0 && result->primary) @@ -151,6 +151,16 @@ void ffPrintDisplay(FFDisplayOptions* options) else refreshRate[0] = 0; + char buf[32]; + if (result->serial) + { + const uint8_t* nums = (uint8_t*) &result->serial; + snprintf(buf, sizeof(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); + } + else + buf[0] = '\0'; + + bool hdrEnabled = result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISPLAY_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(result->width, "width"), FF_FORMAT_ARG(result->height, "height"), @@ -166,7 +176,10 @@ void ffPrintDisplay(FFDisplayOptions* options) FF_FORMAT_ARG(inch, "inch"), FF_FORMAT_ARG(ppi, "ppi"), FF_FORMAT_ARG(result->bitDepth, "bit-depth"), - FF_FORMAT_ARG(result->hdrEnabled, "hdr-enabled"), + FF_FORMAT_ARG(hdrEnabled, "hdr-enabled"), + FF_FORMAT_ARG(result->manufactureYear, "manufacture-year"), + FF_FORMAT_ARG(result->manufactureWeek, "manufacture-week"), + FF_FORMAT_ARG(buf, "serial"), })); } } @@ -335,7 +348,23 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs 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, "bitDepth", item->bitDepth); - yyjson_mut_obj_add_bool(doc, obj, "hdrEnabled", item->hdrEnabled); + if (item->hdrStatus == FF_DISPLAY_HDR_STATUS_UNKNOWN) + yyjson_mut_obj_add_null(doc, obj, "hdrStatus"); + else switch (item->hdrStatus) + { + case FF_DISPLAY_HDR_STATUS_UNSUPPORTED: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Unsupported"); + break; + case FF_DISPLAY_HDR_STATUS_SUPPORTED: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Supported"); + break; + case FF_DISPLAY_HDR_STATUS_ENABLED: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Enabled"); + break; + default: + yyjson_mut_obj_add_str(doc, obj, "hdrStatus", "Unknown"); + break; + } switch (item->type) { @@ -349,6 +378,22 @@ void ffGenerateDisplayJsonResult(FF_MAYBE_UNUSED FFDisplayOptions* options, yyjs yyjson_mut_obj_add_str(doc, obj, "type", "Unknown"); break; } + + if (item->manufactureYear) + { + yyjson_mut_val* manufactureDate = yyjson_mut_obj_add_obj(doc, obj, "manufactureDate"); + yyjson_mut_obj_add_uint(doc, manufactureDate, "year", item->manufactureYear); + yyjson_mut_obj_add_uint(doc, manufactureDate, "week", item->manufactureWeek); + } + else + { + yyjson_mut_obj_add_null(doc, obj, "manufactureDate"); + } + + if (item->serial) + yyjson_mut_obj_add_uint(doc, obj, "serial", item->serial); + else + yyjson_mut_obj_add_null(doc, obj, "serial"); } } @@ -369,7 +414,10 @@ void ffPrintDisplayHelpFormat(void) "Physical diagonal length in inches - inch", "Pixels per inch (PPI) - ppi", "Bits per color channel - bit-depth", - "True if high dynamic range (HDR) is enabled - hdr-enabled", + "True if high dynamic range (HDR) mode is enabled - hdr-enabled", + "Year of manufacturing - manufacture-year", + "Nth week of manufacturing in the year - manufacture-week", + "Serial number - serial", })); } From 46eb0e4b1c0229e18986053301f3cd162afa768c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 22:43:29 +0800 Subject: [PATCH 10/48] Display (Linux): merge features of `Monitor` module --- .../displayserver/linux/displayserver_linux.c | 39 ---------- .../displayserver/linux/displayserver_linux.h | 2 - src/detection/displayserver/linux/drm.c | 77 +++++++++++++------ .../linux/wayland/global-output.c | 15 +++- .../displayserver/linux/wayland/kde-output.c | 16 +++- .../displayserver/linux/wayland/wayland.c | 43 ++++++++++- .../displayserver/linux/wayland/wayland.h | 5 ++ .../displayserver/linux/wayland/zwlr-output.c | 15 +++- src/detection/displayserver/linux/xcb.c | 61 +++++++-------- src/detection/displayserver/linux/xlib.c | 32 +++++--- 10 files changed, 191 insertions(+), 114 deletions(-) diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index de006c56b4..a841776503 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -1,6 +1,5 @@ #include "displayserver_linux.h" #include "common/io/io.h" -#include "util/edidHelper.h" #include "util/stringUtils.h" #ifdef __FreeBSD__ @@ -104,44 +103,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) } } -bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName) -{ - // https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name - // The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc." - // However I can't find a better method to get the edid data - const char* drmDirPath = "/sys/class/drm/"; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); - if(dirp == NULL) - return false; - - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - const char* plainName = entry->d_name; - if (ffStrStartsWith(plainName, "card")) - { - const char* tmp = strchr(plainName + strlen("card"), '-'); - if (tmp) plainName = tmp + 1; - } - if (ffStrEquals(plainName, connName)) - { - ffStrbufAppendF(edidName, "%s%s/edid", drmDirPath, entry->d_name); - - uint8_t edidData[128]; - if(ffReadFileData(edidName->chars, sizeof(edidData), edidData) == sizeof(edidData)) - { - ffStrbufClear(edidName); - ffEdidGetName(edidData, edidName); - return true; - } - break; - } - } - ffStrbufClear(edidName); - return false; -} - FFDisplayType ffdsGetDisplayType(const char* name) { if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-")) diff --git a/src/detection/displayserver/linux/displayserver_linux.h b/src/detection/displayserver/linux/displayserver_linux.h index 99cad927fb..b52b35b453 100644 --- a/src/detection/displayserver/linux/displayserver_linux.h +++ b/src/detection/displayserver/linux/displayserver_linux.h @@ -5,8 +5,6 @@ #include "detection/displayserver/displayserver.h" -bool ffdsMatchDrmConnector(const char* connName, FFstrbuf* edidName); - const char* ffdsConnectWayland(FFDisplayServerResult* result); const char* ffdsConnectXcbRandr(FFDisplayServerResult* result); diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 48949266d6..9ccaa3f7ee 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -50,15 +50,18 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); ffStrbufAppendS(&drmDir, "/edid"); - uint8_t edidData[128]; - if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData)) + const char* plainName = entry->d_name; + if (ffStrStartsWith(plainName, "card")) { - ffEdidGetName(edidData, &name); - ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate); - ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); + const char* tmp = strchr(plainName + strlen("card"), '-'); + if (tmp) plainName = tmp + 1; } - else + + uint8_t edidData[512]; + ssize_t edidLength = ffReadFileData(drmDir.chars, sizeof(edidData), edidData); + if(edidLength <= 0 || edidLength % 128 != 0) { + edidLength = 0; ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); ffStrbufAppendS(&drmDir, "/modes"); @@ -66,29 +69,34 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) if (ffReadFileData(drmDir.chars, sizeof(modes), modes) >= 3) { sscanf(modes, "%ux%u", &width, &height); - const char* plainName = entry->d_name; - if (ffStrStartsWith(plainName, "card")) - { - const char* tmp = strchr(plainName + strlen("card"), '-'); - if (tmp) plainName = tmp + 1; - } ffStrbufAppendS(&name, plainName); } } + else + { + ffEdidGetName(edidData, &name); + ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate); + ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); + } - ffdsAppendDisplay( + FFDisplayResult* item = ffdsAppendDisplay( result, width, height, refreshRate, 0, 0, 0, &name, - FF_DISPLAY_TYPE_UNKNOWN, + ffdsGetDisplayType(plainName), false, 0, physicalWidth, physicalHeight ); + if (item && edidLength) + { + item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + } ffStrbufSubstrBefore(&drmDir, drmDirLength); } @@ -160,7 +168,7 @@ static inline const char* drmType2Name(uint32_t connector_type) } } -static const char* drmGetNameByConnId(uint32_t connId, FFstrbuf* name) +static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edidData, ssize_t* edidLength) { const char* drmDirPath = "/sys/class/drm/"; @@ -182,24 +190,22 @@ static const char* drmGetNameByConnId(uint32_t connId, FFstrbuf* name) ffStrbufAppendS(&drmDir, entry->d_name); uint32_t drmDirWithDnameLength = drmDir.length; + char connectorId[16] = {}; + ffStrbufAppendS(&drmDir, "/connector_id"); - ffReadFileBuffer(drmDir.chars, name); - if (ffStrbufToUInt(name, 0) != connId) + ffReadFileData(drmDir.chars, sizeof(connectorId), connectorId); + if (strtoul(connectorId, NULL, 10) != connId) { ffStrbufSubstrBefore(&drmDir, drmDirLength); continue; } ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); - ffStrbufClear(name); ffStrbufAppendS(&drmDir, "/edid"); - uint8_t edidData[128]; - if(ffReadFileData(drmDir.chars, sizeof(edidData), edidData) == sizeof(edidData)) - ffEdidGetName(edidData, name); + *edidLength = ffReadFileData(drmDir.chars, (uint32_t) *edidLength, edidData); return NULL; } - ffStrbufClear(name); return "Failed to match connector ID"; } @@ -309,6 +315,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffStrbufClear(&name); + uint16_t myear = 0, mweak = 0; + uint32_t serial = 0; + FFDisplayHdrStatus hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; for (int iProp = 0; iProp < conn->count_props; ++iProp) { @@ -329,7 +338,11 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) if (blob) { if (blob->length >= 128) + { ffEdidGetName(blob->data, &name); + hdrStatus = ffEdidGetHdrCompatible(blob->data, blob->length) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(blob->data, &serial, &myear, &mweak); + } ffdrmModeFreePropertyBlob(blob); } break; @@ -339,7 +352,15 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) if (name.length == 0) { - drmGetNameByConnId(conn->connector_id, &name); + uint8_t edidData[512]; + ssize_t edidLength = 0; + drmGetEdidByConnId(conn->connector_id, edidData, &edidLength); + if (edidLength > 0 && edidLength % 128 == 0) + { + ffEdidGetName(edidData, &name); + hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &serial, &myear, &mweak); + } } if (name.length == 0) @@ -350,7 +371,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn + 1); } - ffdsAppendDisplay(result, + FFDisplayResult* item = ffdsAppendDisplay(result, width, height, refreshRate, @@ -367,6 +388,14 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) conn->mmWidth, conn->mmHeight ); + + if (item) + { + item->hdrStatus = hdrStatus; + item->serial = serial; + item->manufactureYear = myear; + item->manufactureWeek = mweak; + } } ffdrmModeFreeConnector(conn); diff --git a/src/detection/displayserver/linux/wayland/global-output.c b/src/detection/displayserver/linux/wayland/global-output.c index a8299d16d7..20227be364 100644 --- a/src/detection/displayserver/linux/wayland/global-output.c +++ b/src/detection/displayserver/linux/wayland/global-output.c @@ -112,7 +112,7 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist uint32_t rotation = ffWaylandHandleRotation(&display); - ffdsAppendDisplay(wldata->result, + FFDisplayResult* item = ffdsAppendDisplay(wldata->result, (uint32_t) display.width, (uint32_t) display.height, display.refreshRate / 1000.0, @@ -131,6 +131,19 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist (uint32_t) display.physicalWidth, (uint32_t) display.physicalHeight ); + if (item) + { + if (display.hdrSupported) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else if (display.hdrInfoAvailable) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + + item->manufactureYear = display.myear; + item->manufactureWeek = display.mweek; + item->serial = display.serial; + } ffStrbufDestroy(&display.description); ffStrbufDestroy(&display.name); diff --git a/src/detection/displayserver/linux/wayland/kde-output.c b/src/detection/displayserver/linux/wayland/kde-output.c index fd0d4809ba..0993f72a5f 100644 --- a/src/detection/displayserver/linux/wayland/kde-output.c +++ b/src/detection/displayserver/linux/wayland/kde-output.c @@ -80,6 +80,9 @@ static void waylandKdeEdidListener(void* data, FF_MAYBE_UNUSED struct kde_output FF_STRBUF_AUTO_DESTROY edid = ffBase64DecodeStrbuf(&b64); if (edid.length < 128) return; ffEdidGetName((const uint8_t*) edid.chars, &wldata->edidName); + wldata->hdrSupported = ffEdidGetHdrCompatible((const uint8_t*) edid.chars, edid.length); + ffEdidGetSerialAndManufactureDate((const uint8_t*) edid.chars, &wldata->serial, &wldata->myear, &wldata->mweek); + wldata->hdrInfoAvailable = true; } static void waylandKdeEnabledListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, int32_t enabled) @@ -195,7 +198,18 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, ); if (item) { - item->hdrEnabled = display.hdrEnabled; + if (display.hdrEnabled) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED; + else if (display.hdrSupported) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else if (display.hdrInfoAvailable) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + + item->manufactureYear = display.myear; + item->manufactureWeek = display.mweek; + item->serial = display.serial; } ffStrbufDestroy(&display.description); diff --git a/src/detection/displayserver/linux/wayland/wayland.c b/src/detection/displayserver/linux/wayland/wayland.c index a0472ae742..5a67f7887f 100644 --- a/src/detection/displayserver/linux/wayland/wayland.c +++ b/src/detection/displayserver/linux/wayland/wayland.c @@ -1,5 +1,6 @@ #include "../displayserver_linux.h" #include "common/io/io.h" +#include "util/edidHelper.h" #include "util/stringUtils.h" #include @@ -82,6 +83,46 @@ static void waylandGlobalAddListener(void* data, struct wl_registry* registry, u } } +static bool matchDrmConnector(const char* connName, WaylandDisplay* wldata) +{ + // https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name + // The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc." + // However I can't find a better method to get the edid data + const char* drmDirPath = "/sys/class/drm/"; + + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); + if(dirp == NULL) + return false; + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + const char* plainName = entry->d_name; + if (ffStrStartsWith(plainName, "card")) + { + const char* tmp = strchr(plainName + strlen("card"), '-'); + if (tmp) plainName = tmp + 1; + } + if (ffStrEquals(plainName, connName)) + { + FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s%s/edid", drmDirPath, entry->d_name); + + uint8_t edidData[512]; + ssize_t edidLength = ffReadFileData(path.chars, sizeof(edidData), edidData); + if (edidLength <= 0 || edidLength % 128 != 0) + { + ffEdidGetName(edidData, &wldata->edidName); + ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); + ffEdidGetSerialAndManufactureDate(edidData, &wldata->serial, &wldata->myear, &wldata->mweek); + wldata->hdrInfoAvailable = true; + return true; + } + break; + } + } + return false; +} + void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name) { WaylandDisplay* display = data; @@ -89,7 +130,7 @@ void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const display->type = ffdsGetDisplayType(name); if (!display->edidName.length) - ffdsMatchDrmConnector(name, &display->edidName); + matchDrmConnector(name, display); display->id = ffWaylandGenerateIdFromName(name); ffStrbufAppendS(&display->name, name); } diff --git a/src/detection/displayserver/linux/wayland/wayland.h b/src/detection/displayserver/linux/wayland/wayland.h index df7056a7b1..3c3b64a94b 100644 --- a/src/detection/displayserver/linux/wayland/wayland.h +++ b/src/detection/displayserver/linux/wayland/wayland.h @@ -46,7 +46,12 @@ typedef struct WaylandDisplay FFstrbuf description; FFstrbuf edidName; uint64_t id; + bool hdrInfoAvailable; + bool hdrSupported; bool hdrEnabled; + uint16_t myear; + uint16_t mweek; + uint32_t serial; void* internal; } WaylandDisplay; diff --git a/src/detection/displayserver/linux/wayland/zwlr-output.c b/src/detection/displayserver/linux/wayland/zwlr-output.c index dd31b91b0a..7e23d593e8 100644 --- a/src/detection/displayserver/linux/wayland/zwlr-output.c +++ b/src/detection/displayserver/linux/wayland/zwlr-output.c @@ -122,7 +122,7 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output uint32_t rotation = ffWaylandHandleRotation(&display); - ffdsAppendDisplay(wldata->result, + FFDisplayResult* item = ffdsAppendDisplay(wldata->result, (uint32_t) display.width, (uint32_t) display.height, display.refreshRate / 1000.0, @@ -140,6 +140,19 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output (uint32_t) display.physicalWidth, (uint32_t) display.physicalHeight ); + if (item) + { + if (display.hdrSupported) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else if (display.hdrInfoAvailable) + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + else + item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + + item->manufactureYear = display.myear; + item->manufactureWeek = display.mweek; + item->serial = display.serial; + } ffStrbufDestroy(&display.description); ffStrbufDestroy(&display.name); diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 6bf82e14bc..d40386eb0b 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -180,47 +180,29 @@ typedef struct XcbRandrData xcb_randr_get_screen_resources_current_reply_t* screenResources; } XcbRandrData; -static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) -{ - double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); - - return ffdsAppendDisplay( - data->result, - (uint32_t) modeInfo->width, - (uint32_t) modeInfo->height, - refreshRate, - (uint32_t) modeInfo->width, - (uint32_t) modeInfo->height, - rotation, - name, - displayType, - primary, - 0, - (uint32_t) output->mm_width, - (uint32_t) output->mm_height - ); -} - -static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrbuf* name, uint32_t rotation, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) +static double xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) - return false; + return 0; xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(data->screenResources); while(modesIterator.rem > 0) { if(modesIterator.data->id == mode) - return xcbRandrHandleModeInfo(data, modesIterator.data, name, rotation, primary, output, displayType); + { + xcb_randr_mode_info_t* modeInfo = modesIterator.data; + return (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); + } data->ffxcb_randr_mode_info_next(&modesIterator); } - return false; + return 0; } -static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType) +static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name, bool primary, xcb_randr_get_output_info_reply_t* output, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength) { xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME); FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL); @@ -243,12 +225,12 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb rotation = 0; break; } - bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation, primary, output, displayType); - res = res ? true : !!ffdsAppendDisplay( + + FFDisplayResult* item = ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, - 0, + xcbRandrHandleMode(data, crtcInfoReply->mode), (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, rotation, @@ -259,8 +241,13 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb (uint32_t) output->mm_width, (uint32_t) output->mm_height ); + if (item && edidLength) + { + item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + } - return res; + return !!item; } static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType) @@ -272,21 +259,27 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen("EDID"), "EDID"); FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL); + FF_AUTO_FREE xcb_randr_get_output_property_reply_t* outputPropertyReply = NULL; + uint8_t* edidData = NULL; + uint32_t edidLength = 0; if(requestAtomReply) { xcb_randr_get_output_property_cookie_t outputPropertyCookie = data->ffxcb_randr_get_output_property(data->connection, output, requestAtomReply->atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 100, false, false); - FF_AUTO_FREE xcb_randr_get_output_property_reply_t* outputPropertyReply = data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL); + outputPropertyReply = data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL); if(outputPropertyReply) { - if(data->ffxcb_randr_get_output_property_data_length(outputPropertyReply) >= 128) + int len = data->ffxcb_randr_get_output_property_data_length(outputPropertyReply); + if(len >= 128) { ffStrbufClear(name); - ffEdidGetName(data->ffxcb_randr_get_output_property_data(outputPropertyReply), name); + edidData = data->ffxcb_randr_get_output_property_data(outputPropertyReply); + ffEdidGetName(edidData, name); + edidLength = (uint32_t) len; } } } - bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType); + bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name, primary, outputInfoReply, displayType, edidData, edidLength); return res; } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 4a6a370802..e83b0e1ede 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -153,13 +153,13 @@ static double xrandrHandleMode(XrandrData* data, RRMode mode) return 0; } -static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool primary, XRROutputInfo* output, FFDisplayType displayType) +static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) return false; - XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, crtc); + XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, output->crtc); if(crtcInfo == NULL) return false; @@ -180,7 +180,7 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool break; } - bool res = ffdsAppendDisplay( + FFDisplayResult* item = ffdsAppendDisplay( data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, @@ -196,8 +196,14 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc, FFstrbuf* name, bool (uint32_t) output->mm_height ); + if (edidLength) + { + item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; + ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + } + data->ffXRRFreeCrtcInfo(crtcInfo); - return res; + return !!item; } static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType) @@ -206,26 +212,30 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name if(outputInfo == NULL) return false; + uint8_t* edidData = NULL; + unsigned long edidLength = 0; Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true); if (atomEdid != None) { int actual_format = 0; - unsigned long nitems = 0, bytes_after = 0; + unsigned long bytes_after = 0; Atom actual_type = None; - uint8_t* edidData = NULL; - if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success) + if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &edidLength, &bytes_after, &edidData) == Success) { - if (nitems >= 128) + if (edidLength >= 128) { ffStrbufClear(name); ffEdidGetName(edidData, name); } + else + edidLength = 0; } - if (edidData) - data->ffXFree(edidData); } - bool res = xrandrHandleCrtc(data, outputInfo->crtc, name, primary, outputInfo, displayType); + bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength); + + if (edidData) + data->ffXFree(edidData); data->ffXRRFreeOutputInfo(outputInfo); return res; From d5c395fb85991a4180590f3a7a4c111f5f536813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 23:25:08 +0800 Subject: [PATCH 11/48] Display (Windows): merge features of `Monitor` module --- .../displayserver/displayserver_windows.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 3c685e2878..11d9a5de76 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -86,6 +86,9 @@ static void detectDisplays(FFDisplayServerResult* ds) .id = path->targetInfo.id, }, }; + uint8_t edidData[1024]; + DWORD edidLength = 0; + if(DisplayConfigGetDeviceInfo(&targetName.header) == ERROR_SUCCESS) { wchar_t regPath[256] = L"SYSTEM\\CurrentControlSet\\Enum"; @@ -103,8 +106,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } wcscpy(pRegPath, L"Device Parameters"); - uint8_t edidData[1024]; - DWORD edidLength = sizeof(edidData); + edidLength = sizeof(edidData); if (RegGetValueW(HKEY_LOCAL_MACHINE, regPath, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidLength) == ERROR_SUCCESS && edidLength > 0 && edidLength % 128 == 0) { @@ -113,6 +115,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } else { + edidLength = 0; if (targetName.flags.friendlyNameFromEdid) ffStrbufSetWS(&name, targetName.monitorFriendlyDeviceName); else @@ -177,9 +180,18 @@ static void detectDisplays(FFDisplayServerResult* ds) }; if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS) { - display->hdrEnabled = !!advColorInfo.advancedColorEnabled; + if (advColorInfo.advancedColorEnabled) + display->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED; + else if (advColorInfo.advancedColorSupported) + display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + else + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; display->bitDepth = (uint8_t) advColorInfo.bitsPerColorChannel; } + else + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN; + if (edidLength > 0) + ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); } } } From 316849e5df458aa412a521e9540d9f5b5d5de8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 23:35:34 +0800 Subject: [PATCH 12/48] Monitor: remove module --- CMakeLists.txt | 7 - doc/json_schema.json | 5 - presets/all.jsonc | 1 - presets/ci.jsonc | 1 - presets/examples/19.jsonc | 5 +- src/common/modules.c | 1 - src/detection/monitor/monitor.h | 17 -- src/detection/monitor/monitor_apple.m | 137 ------------ src/detection/monitor/monitor_linux.c | 254 ---------------------- src/detection/monitor/monitor_nosupport.c | 6 - src/detection/monitor/monitor_windows.c | 116 ---------- src/modules/modules.h | 1 - src/modules/monitor/monitor.c | 222 ------------------- src/modules/monitor/monitor.h | 9 - src/modules/monitor/option.h | 11 - src/modules/options.h | 1 - src/options/modules.c | 2 - src/options/modules.h | 1 - 18 files changed, 3 insertions(+), 794 deletions(-) delete mode 100644 src/detection/monitor/monitor.h delete mode 100644 src/detection/monitor/monitor_apple.m delete mode 100644 src/detection/monitor/monitor_linux.c delete mode 100644 src/detection/monitor/monitor_nosupport.c delete mode 100644 src/detection/monitor/monitor_windows.c delete mode 100644 src/modules/monitor/monitor.c delete mode 100644 src/modules/monitor/monitor.h delete mode 100644 src/modules/monitor/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index bbd9964dc7..662e4c663c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -382,7 +382,6 @@ set(LIBFASTFETCH_SRC src/modules/locale/locale.c src/modules/localip/localip.c src/modules/memory/memory.c - src/modules/monitor/monitor.c src/modules/netio/netio.c src/modules/opencl/opencl.c src/modules/opengl/opengl.c @@ -484,7 +483,6 @@ if(LINUX) src/detection/gamepad/gamepad_linux.c src/detection/media/media_linux.c src/detection/memory/memory_linux.c - src/detection/monitor/monitor_linux.c src/detection/netio/netio_linux.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -549,7 +547,6 @@ elseif(ANDROID) src/detection/gamepad/gamepad_nosupport.c 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 @@ -629,7 +626,6 @@ elseif(FreeBSD) src/detection/gamepad/gamepad_bsd.c src/detection/media/media_linux.c src/detection/memory/memory_bsd.c - src/detection/monitor/monitor_linux.c src/detection/netio/netio_bsd.c src/detection/opengl/opengl_linux.c src/detection/os/os_linux.c @@ -696,7 +692,6 @@ elseif(APPLE) src/detection/gamepad/gamepad_apple.c src/detection/media/media_apple.m src/detection/memory/memory_apple.c - src/detection/monitor/monitor_apple.m src/detection/netio/netio_bsd.c src/detection/opengl/opengl_apple.c src/detection/os/os_apple.m @@ -764,7 +759,6 @@ elseif(WIN32) src/detection/media/media_windows.c src/detection/memory/memory_windows.c src/detection/physicalmemory/physicalmemory_linux.c - src/detection/monitor/monitor_windows.c src/detection/netio/netio_windows.c src/detection/opengl/opengl_windows.c src/detection/os/os_windows.cpp @@ -848,7 +842,6 @@ elseif(SunOS) src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_sunos.c - src/detection/monitor/monitor_linux.c src/detection/netio/netio_sunos.c src/detection/opengl/opengl_linux.c src/detection/os/os_sunos.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 231b9db3f0..7eebf00998 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -684,7 +684,6 @@ "localip", "media", "memory", - "monitor", "netio", "opencl", "opengl", @@ -814,10 +813,6 @@ "const": "media", "description": "Print playing song name" }, - { - "const": "monitor", - "description": "Print connected physical monitor information" - }, { "const": "opencl", "description": "Print highest OpenCL version supported by the GPU" diff --git a/presets/all.jsonc b/presets/all.jsonc index 9b27615e04..e50c450cb8 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -24,7 +24,6 @@ "editor", "display", "brightness", - "monitor", "lm", "de", "wm", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 3027010d8f..fe506e3544 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -26,7 +26,6 @@ "editor", "display", "brightness", - "monitor", "lm", "de", "wm", diff --git a/presets/examples/19.jsonc b/presets/examples/19.jsonc index 17db60c262..d6ef2a904a 100644 --- a/presets/examples/19.jsonc +++ b/presets/examples/19.jsonc @@ -119,9 +119,10 @@ "keyColor": "blue" }, { - "type": "monitor", + "type": "display", "key": "MONITOR ({name})", - "keyColor": "blue" + "keyColor": "blue", + "format": "{width}x{height} @ {refresh-rate} Hz - {physical-width}x{physical-height} mm ({inch} inches, {ppi} ppi)" }, { "type": "custom", // DesignInfo diff --git a/src/common/modules.c b/src/common/modules.c index 4e8ae69e4c..87ae82829a 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -87,7 +87,6 @@ static FFModuleBaseInfo* L[] = { static FFModuleBaseInfo* M[] = { (void*) &instance.config.modules.media, (void*) &instance.config.modules.memory, - (void*) &instance.config.modules.monitor, NULL, }; diff --git a/src/detection/monitor/monitor.h b/src/detection/monitor/monitor.h deleted file mode 100644 index 4066f1178d..0000000000 --- a/src/detection/monitor/monitor.h +++ /dev/null @@ -1,17 +0,0 @@ -#include "fastfetch.h" - -typedef struct FFMonitorResult -{ - FFstrbuf name; - uint32_t width; // native / maximum resolution, in pixels - uint32_t height; // native / maximum resolution, in pixels - double refreshRate;// maximum refresh rate in native resolution, in Hz - uint32_t physicalWidth; // in mm - uint32_t physicalHeight; // in mm - bool hdrCompatible; - uint16_t manufactureYear; - uint16_t manufactureWeek; - uint32_t serial; -} FFMonitorResult; - -const char* ffDetectMonitor(FFlist* results); diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m deleted file mode 100644 index 8a9487443c..0000000000 --- a/src/detection/monitor/monitor_apple.m +++ /dev/null @@ -1,137 +0,0 @@ -#include "monitor.h" -#include "detection/displayserver/displayserver.h" -#include "util/apple/cf_helpers.h" -#include "util/edidHelper.h" - -#import -#import -#import - -#ifdef MAC_OS_X_VERSION_10_15 -extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); -extern Boolean CoreDisplay_Display_SupportsHDRMode(CGDirectDisplayID display) __attribute__((weak_import)); -#else -#include -#endif - -static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) -{ - NSScreen* mainScreen = NSScreen.mainScreen; - if (display->primary) - { - #ifdef MAC_OS_X_VERSION_10_15 - return mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; - #else - return mainScreen.maximumExtendedDynamicRangeColorComponentValue > 1; - #endif - } - else - { - for (NSScreen* screen in NSScreen.screens) - { - if (screen == mainScreen) continue; - NSNumber* screenNumber = screen.deviceDescription[@"NSScreenNumber"]; - if (screenNumber && screenNumber.longValue == (long) display->id) - { - #ifdef MAC_OS_X_VERSION_10_15 - return screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1; - #else - return screen.maximumExtendedDynamicRangeColorComponentValue > 1; - #endif - } - } - } - return false; -} - -static bool detectHdrSupport(CFDictionaryRef displayInfo, FFDisplayResult* display) -{ - #ifdef MAC_OS_X_VERSION_10_15 - if (CoreDisplay_Display_SupportsHDRMode) - { - if (CoreDisplay_Display_SupportsHDRMode(display->id)) - return true; - } - #endif - return CFDictionaryContainsKey(displayInfo, CFSTR("ReferencePeakHDRLuminance")) || - detectHdrSupportWithNSScreen(display); -} - -const char* ffDetectMonitor(FFlist* results) -{ - #ifdef MAC_OS_X_VERSION_10_15 - if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available"; - #endif - const FFDisplayServerResult* displayServer = ffConnectDisplayServer(); - - FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays) - { - #ifdef MAC_OS_X_VERSION_10_15 - CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id); - #else - io_service_t servicePort = CGDisplayIOServicePort((CGDirectDisplayID) display->id); - CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName); - #endif - if(!displayInfo) continue; - - bool isVirtual = false; - if (ffCfDictGetBool(displayInfo, CFSTR("kCGDisplayIsVirtualDevice"), &isVirtual) == NULL && isVirtual) - continue; - - uint8_t edidData[128] = {}; - uint32_t edidLength = 0; - if (ffCfDictGetData(displayInfo, CFSTR(kIODisplayEDIDKey), 0, sizeof(edidData), edidData, &edidLength) == NULL) - { - uint32_t width, height; - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width > 0 && height > 0) - { - FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); - ffStrbufInitCopy(&monitor->name, &display->name); - monitor->width = width; - monitor->height = height; - ffEdidGetPhysicalSize(edidData, &monitor->physicalWidth, &monitor->physicalHeight); - monitor->hdrCompatible = detectHdrSupport(displayInfo, display); - continue; - } - } - - int width, height; - if (ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), &width) || // Default resolution (limited by connectors, GPUs, etc.) - ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), &height) || - width <= 0 || height <= 0) - continue; - - FFMonitorResult* monitor = (FFMonitorResult*) ffListAdd(results); - monitor->width = (uint32_t) width; - monitor->height = (uint32_t) height; - ffStrbufInitCopy(&monitor->name, &display->name); - - CGSize size = CGDisplayScreenSize((CGDirectDisplayID) display->id); - monitor->physicalWidth = (uint32_t) (size.width + 0.5); - monitor->physicalHeight = (uint32_t) (size.height + 0.5); - monitor->hdrCompatible = detectHdrSupport(displayInfo, display); - monitor->serial = CGDisplaySerialNumber((CGDirectDisplayID) display->id); - - FF_CFTYPE_AUTO_RELEASE CFArrayRef modes = CGDisplayCopyAllDisplayModes((CGDirectDisplayID) display->id, NULL); - double maxRefreshRate = 0; - for (uint32_t j = 0; j < CFArrayGetCount(modes); ++j) - { - CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, j); - if (CGDisplayModeGetWidth(mode) == (uint32_t) width && CGDisplayModeGetHeight(mode) == (uint32_t) height) - { - double refreshRate = CGDisplayModeGetRefreshRate(mode); - if (refreshRate > maxRefreshRate) maxRefreshRate = refreshRate; - } - } - monitor->refreshRate = maxRefreshRate; - - int64_t year, week; - if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayYearManufacture"), &year) == NULL) - monitor->manufactureYear = (uint16_t) year; - if (ffCfDictGetInt64(displayInfo, CFSTR("DisplayWeekManufacture"), &week) == NULL) - monitor->manufactureWeek = (uint16_t) week; - } - - return NULL; -} diff --git a/src/detection/monitor/monitor_linux.c b/src/detection/monitor/monitor_linux.c deleted file mode 100644 index 48d52d0b0b..0000000000 --- a/src/detection/monitor/monitor_linux.c +++ /dev/null @@ -1,254 +0,0 @@ -#include "monitor.h" - -#include "common/io/io.h" -#include "common/library.h" -#include "util/edidHelper.h" -#include "util/stringUtils.h" - -#ifdef FF_HAVE_XRANDR - -#include -#include - -typedef struct XrandrData -{ - FF_LIBRARY_SYMBOL(XInternAtom) - FF_LIBRARY_SYMBOL(XGetAtomName); - FF_LIBRARY_SYMBOL(XFree); - FF_LIBRARY_SYMBOL(XRRGetMonitors) - FF_LIBRARY_SYMBOL(XRRGetOutputInfo) - FF_LIBRARY_SYMBOL(XRRGetOutputProperty) - FF_LIBRARY_SYMBOL(XRRFreeOutputInfo) - FF_LIBRARY_SYMBOL(XRRFreeMonitors) - - //Init once - Display* display; - - //Init per screen - XRRScreenResources* screenResources; -} XrandrData; - -static const char* xrandrHandleMonitors(XrandrData* data, Screen* screen, FFlist* results) -{ - int numberOfMonitors; - XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, RootWindowOfScreen(screen), True, &numberOfMonitors); - if(monitorInfos == NULL) - return "XRRGetMonitors() failed"; - - for(int i = 0; i < numberOfMonitors; i++) - { - XRRMonitorInfo* monitorInfo = &monitorInfos[i]; - for(int i = 0; i < monitorInfo->noutput; i++) - { - RROutput output = monitorInfo->outputs[i]; - XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output); - if(outputInfo == NULL) - continue; - - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - ffStrbufInit(&display->name); - display->width = 0; - display->height = 0; - display->manufactureYear = 0; - display->manufactureWeek = 0; - display->serial = 0; - display->hdrCompatible = false; - display->refreshRate = 0; - - bool edidOk = false; - Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true); - if (atomEdid != None) - { - int actual_format = 0; - unsigned long nitems = 0, bytes_after = 0; - Atom actual_type = None; - uint8_t* edidData = NULL; - if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &edidData) == Success) - { - if (nitems > 0 && nitems % 128 == 0) - { - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalResolution(edidData, &display->width, &display->height); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) nitems); - edidOk = true; - } - } - if (edidData) - data->ffXFree(edidData); - } - - if (!edidOk) - { - ffStrbufSetS(&display->name, data->ffXGetAtomName(data->display, monitorInfo->name)); - display->physicalWidth = (uint32_t) monitorInfo->mwidth; - display->physicalHeight = (uint32_t) monitorInfo->mheight; - display->width = (uint32_t) monitorInfo->width; - display->height = (uint32_t) monitorInfo->height; - } - - for(int i = 0; i < data->screenResources->nmode; i++) - { - bool found = false; - for (int j = 0; j < outputInfo->nmode; ++j) - { - if (data->screenResources->modes[i].id == outputInfo->modes[j]) - { - found = true; - break; - } - } - - if(found) - { - XRRModeInfo* modeInfo = &data->screenResources->modes[i]; - double refreshRate = (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); - if (edidOk) - { - if (display->width != modeInfo->width || display->height != modeInfo->height) - continue; - } - else - { - if (display->width < modeInfo->width || display->height < modeInfo->height) - { - display->width = (uint32_t) modeInfo->width; - display->height = (uint32_t) modeInfo->height; - display->refreshRate = refreshRate; - continue; - } - else if (display->width != modeInfo->width || display->height != modeInfo->height) - continue; - } - if (display->refreshRate < refreshRate) - display->refreshRate = refreshRate; - } - } - data->ffXRRFreeOutputInfo(outputInfo); - } - } - - data->ffXRRFreeMonitors(monitorInfos); - return NULL; -} - -static const char* detectByXrandr(FFlist* results) -{ - FF_LIBRARY_LOAD(xrandr, "dlopen libXrandr" FF_LIBRARY_EXTENSION " failed", "libXrandr" FF_LIBRARY_EXTENSION, 3) - - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XOpenDisplay) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XCloseDisplay) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XRRGetScreenResourcesCurrent); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XRRFreeScreenResources); - - XrandrData data; - - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XInternAtom); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XGetAtomName); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XFree); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetMonitors); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetOutputInfo); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetOutputProperty); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeOutputInfo); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeMonitors); - - data.display = ffXOpenDisplay(NULL); - if(data.display == NULL) - return "XOpenDisplay() failed"; - - for(int i = 0; i < ScreenCount(data.display); i++) - { - Screen* screen = ScreenOfDisplay(data.display, i); - data.screenResources = ffXRRGetScreenResourcesCurrent(data.display, RootWindowOfScreen(screen)); - xrandrHandleMonitors(&data, screen, results); - ffXRRFreeScreenResources(data.screenResources); - } - - ffXCloseDisplay(data.display); - - return NULL; -} -#endif // FF_HAVE_XRANDR - -#ifdef __linux__ -FF_MAYBE_UNUSED static const char* detectByDrm(FFlist* results) -{ - const char* drmDirPath = "/sys/class/drm/"; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); - if(dirp == NULL) - return "opendir(drmDirPath) == NULL"; - - FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64); - ffStrbufAppendS(&drmDir, drmDirPath); - - uint32_t drmDirLength = drmDir.length; - - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - if(ffStrEquals(entry->d_name, ".") || ffStrEquals(entry->d_name, "..")) - continue; - - ffStrbufAppendS(&drmDir, entry->d_name); - uint32_t drmDirWithDnameLength = drmDir.length; - - ffStrbufAppendS(&drmDir, "/status"); - char status = 'd'; // disconnected - ffReadFileData(drmDir.chars, sizeof(status), &status); - if (status != 'c') // connected - { - ffStrbufSubstrBefore(&drmDir, drmDirLength); - continue; - } - - ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); - ffStrbufAppendS(&drmDir, "/edid"); - - uint8_t edidData[512]; - ssize_t edidLength = ffReadFileData(drmDir.chars, sizeof(edidData), edidData); - if(edidLength <= 0 || edidLength % 128 != 0) - { - ffStrbufSubstrBefore(&drmDir, drmDirLength); - continue; - } - - uint32_t width, height; - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width != 0 && height != 0) - { - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - display->width = width; - display->height = height; - ffStrbufInit(&display->name); - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); - display->refreshRate = 0; - } - - ffStrbufSubstrBefore(&drmDir, drmDirLength); - } - - return NULL; -} -#endif // __linux__ - -const char* ffDetectMonitor(FFlist* results) -{ - const char* error = NULL; - - #if defined(__linux__) - error = detectByDrm(results); - if (!error && results->length > 0) return NULL; - #endif - - #ifdef FF_HAVE_XRANDR - error = detectByXrandr(results); - if (!error) return NULL; - #endif - - return "Fastfetch was compiled without xrandr support"; -} diff --git a/src/detection/monitor/monitor_nosupport.c b/src/detection/monitor/monitor_nosupport.c deleted file mode 100644 index c5bd0547a9..0000000000 --- a/src/detection/monitor/monitor_nosupport.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "monitor.h" - -const char* ffDetectMonitor(FF_MAYBE_UNUSED FFlist* results) -{ - return "Not supported on this platform"; -} diff --git a/src/detection/monitor/monitor_windows.c b/src/detection/monitor/monitor_windows.c deleted file mode 100644 index 4d9ebed2b6..0000000000 --- a/src/detection/monitor/monitor_windows.c +++ /dev/null @@ -1,116 +0,0 @@ -#include "monitor.h" - -#include "util/edidHelper.h" -#include "util/windows/registry.h" - -#include - -const char* ffDetectMonitor(FFlist* results) -{ - DISPLAYCONFIG_PATH_INFO paths[128]; - uint32_t pathCount = sizeof(paths) / sizeof(paths[0]); - DISPLAYCONFIG_MODE_INFO modes[256]; - uint32_t modeCount = sizeof(modes) / sizeof(modes[0]); - - if (QueryDisplayConfig( - QDC_ONLY_ACTIVE_PATHS, - &pathCount, - paths, - &modeCount, - modes, - NULL) != ERROR_SUCCESS) - return "QueryDisplayConfig() failed"; - - if (pathCount == 0) - return "QueryDisplayConfig() returns 0 paths"; - - for (uint32_t i = 0; i < pathCount; ++i) - { - DISPLAYCONFIG_PATH_INFO* path = &paths[i]; - - DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = { - .header = { - .type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME, - .size = sizeof(targetName), - .adapterId = path->targetInfo.adapterId, - .id = path->targetInfo.id, - }, - }; - if (DisplayConfigGetDeviceInfo(&targetName.header) != ERROR_SUCCESS) - continue; - - wchar_t regPath[256] = L"SYSTEM\\CurrentControlSet\\Enum"; - wchar_t* pRegPath = regPath + strlen("SYSTEM\\CurrentControlSet\\Enum"); - wchar_t* pDevPath = targetName.monitorDevicePath + strlen("\\\\?"); - while (*pDevPath && *pDevPath != L'{') - { - if (*pDevPath == L'#') - *pRegPath = L'\\'; - else - *pRegPath = *pDevPath; - ++pRegPath; - ++pDevPath; - assert(pRegPath < regPath + sizeof(regPath) / sizeof(wchar_t) + strlen("Device Parameters")); - } - wcscpy(pRegPath, L"Device Parameters"); - - uint8_t edidData[1024]; - DWORD edidLength = sizeof(edidData); - - if (RegGetValueW(HKEY_LOCAL_MACHINE, regPath, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidLength) == ERROR_SUCCESS && - edidLength > 0 && edidLength % 128 == 0) - { - uint32_t width, height; - ffEdidGetPhysicalResolution(edidData, &width, &height); - if (width == 0 || height == 0) continue; - - FFMonitorResult* display = (FFMonitorResult*) ffListAdd(results); - display->width = width; - display->height = height; - ffEdidGetSerialAndManufactureDate(edidData, &display->serial, &display->manufactureYear, &display->manufactureWeek); - ffStrbufInit(&display->name); - ffEdidGetName(edidData, &display->name); - ffEdidGetPhysicalSize(edidData, &display->physicalWidth, &display->physicalHeight); - display->refreshRate = 0; - display->hdrCompatible = false; - - DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO advColorInfo = { - .header = { - .type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO, - .size = sizeof(advColorInfo), - .adapterId = path->targetInfo.adapterId, - .id = path->targetInfo.id, - } - }; - if (DisplayConfigGetDeviceInfo(&advColorInfo.header) == ERROR_SUCCESS) - display->hdrCompatible = !!advColorInfo.advancedColorSupported; - else - display->hdrCompatible = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength); - - DISPLAYCONFIG_TARGET_PREFERRED_MODE preferredMode = { - .header = { - .type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE, - .size = sizeof(preferredMode), - .adapterId = path->targetInfo.adapterId, - .id = path->targetInfo.id, - } - }; - if (DisplayConfigGetDeviceInfo(&preferredMode.header) == ERROR_SUCCESS) - { - if (preferredMode.width == width && preferredMode.height == height) - { - DISPLAYCONFIG_RATIONAL freq = preferredMode.targetMode.targetVideoSignalInfo.vSyncFreq; - display->refreshRate = freq.Numerator / (double) freq.Denominator; - } - } - - DISPLAYCONFIG_VIDEO_SIGNAL_INFO current = modes[path->targetInfo.modeInfoIdx].targetMode.targetVideoSignalInfo; - if (current.activeSize.cx == width && current.activeSize.cy == height) - { - double refreshRate = current.vSyncFreq.Numerator / (double) current.vSyncFreq.Denominator; - if (refreshRate > display->refreshRate) display->refreshRate = refreshRate; - } - } - } - return NULL; -} diff --git a/src/modules/modules.h b/src/modules/modules.h index 4f9fa7a407..76d76d6225 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -40,7 +40,6 @@ #include "modules/localip/localip.h" #include "modules/media/media.h" #include "modules/memory/memory.h" -#include "modules/monitor/monitor.h" #include "modules/netio/netio.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c deleted file mode 100644 index a2d43cff7d..0000000000 --- a/src/modules/monitor/monitor.c +++ /dev/null @@ -1,222 +0,0 @@ -#include "common/printing.h" -#include "common/jsonconfig.h" -#include "detection/monitor/monitor.h" -#include "modules/monitor/monitor.h" -#include "util/stringUtils.h" - -#include - -#define FF_MONITOR_NUM_FORMAT_ARGS 11 - -void ffPrintMonitor(FFMonitorOptions* options) -{ - FF_LIST_AUTO_DESTROY result = ffListCreate(sizeof(FFMonitorResult)); - - const char* error = ffDetectMonitor(&result); - - if(error) - { - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); - return; - } - - if(!result.length) - { - ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No physical display detected"); - return; - } - - FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); - uint32_t index = 0; - FF_LIST_FOR_EACH(FFMonitorResult, display, result) - { - double inch = sqrt(display->physicalWidth * display->physicalWidth + display->physicalHeight * display->physicalHeight) / 25.4; - double ppi = sqrt(display->width * display->width + display->height * display->height) / inch; - - ffStrbufClear(&key); - if(options->moduleArgs.key.length == 0) - { - ffStrbufAppendF(&key, "%s (%s)", FF_MONITOR_MODULE_NAME, display->name.chars); - } - else - { - uint32_t moduleIndex = result.length == 1 ? 0 : index + 1; - FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 3, ((FFformatarg[]){ - FF_FORMAT_ARG(moduleIndex, "index"), - FF_FORMAT_ARG(display->name, "name"), - FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"), - })); - } - - if(options->moduleArgs.outputFormat.length == 0) - { - ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); - - printf("%ux%u px", display->width, display->height); - if (display->refreshRate > 0) - printf(" @ %g Hz", ((int) (display->refreshRate * 1000 + 0.5)) / 1000.0); - if (inch > 0) - printf(" - %ux%u mm (%.2f inches, %.2f ppi)\n", display->physicalWidth, display->physicalHeight, inch, ppi); - else - putchar('\n'); - } - else - { - char buf[32]; - if (display->serial) - { - const uint8_t* nums = (uint8_t*) &display->serial; - snprintf(buf, sizeof(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); - } - else - buf[0] = '\0'; - - FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_MONITOR_NUM_FORMAT_ARGS, ((FFformatarg[]) { - FF_FORMAT_ARG(display->name, "name"), - FF_FORMAT_ARG(display->width, "width"), - FF_FORMAT_ARG(display->height, "height"), - FF_FORMAT_ARG(display->physicalWidth, "physical-width"), - FF_FORMAT_ARG(display->physicalHeight, "physical-height"), - FF_FORMAT_ARG(inch, "inch"), - FF_FORMAT_ARG(ppi, "ppi"), - FF_FORMAT_ARG(display->manufactureYear, "manufacture-year"), - FF_FORMAT_ARG(display->manufactureWeek, "manufacture-week"), - FF_FORMAT_ARG(buf, "serial"), - FF_FORMAT_ARG(display->refreshRate, "refresh-rate"), - })); - } - - ffStrbufDestroy(&display->name); - ++index; - } -} - -bool ffParseMonitorCommandOptions(FFMonitorOptions* options, const char* key, const char* value) -{ - const char* subKey = ffOptionTestPrefix(key, FF_MONITOR_MODULE_NAME); - if (!subKey) return false; - if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) - return true; - - return false; -} - -void ffParseMonitorJsonObject(FFMonitorOptions* 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_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); - } -} - -void ffGenerateMonitorJsonConfig(FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) -{ - __attribute__((__cleanup__(ffDestroyMonitorOptions))) FFMonitorOptions defaultOptions; - ffInitMonitorOptions(&defaultOptions); - - ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); -} - -void ffGenerateMonitorJsonResult(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_strbuf(doc, obj, "name", &item->name); - - yyjson_mut_val* resolution = yyjson_mut_obj_add_obj(doc, obj, "resolution"); - yyjson_mut_obj_add_uint(doc, resolution, "width", item->width); - yyjson_mut_obj_add_uint(doc, resolution, "height", item->height); - - yyjson_mut_val* physical = yyjson_mut_obj_add_obj(doc, obj, "physical"); - yyjson_mut_obj_add_uint(doc, physical, "height", item->physicalHeight); - yyjson_mut_obj_add_uint(doc, physical, "width", item->physicalWidth); - - yyjson_mut_obj_add_real(doc, obj, "refreshRate", item->refreshRate); - - if (item->manufactureYear) - { - yyjson_mut_val* manufactureDate = yyjson_mut_obj_add_obj(doc, obj, "manufactureDate"); - yyjson_mut_obj_add_uint(doc, manufactureDate, "year", item->manufactureYear); - yyjson_mut_obj_add_uint(doc, manufactureDate, "week", item->manufactureWeek); - } - else - { - yyjson_mut_obj_add_null(doc, obj, "manufactureDate"); - } - - if (item->serial) - yyjson_mut_obj_add_uint(doc, obj, "serial", item->serial); - else - yyjson_mut_obj_add_null(doc, obj, "serial"); - } - } - - FF_LIST_FOR_EACH(FFMonitorResult, item, results) - { - ffStrbufDestroy(&item->name); - } -} - -void ffPrintMonitorHelpFormat(void) -{ - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_MONITOR_MODULE_NAME, "{2}x{3} px - {4}x{5} mm ({6} inches, {7} ppi)", FF_MONITOR_NUM_FORMAT_ARGS, ((const char* []) { - "Display name - name", - "Native resolution width in pixels - width", - "Native resolution height in pixels - height", - "Physical width in millimeters - physical-width", - "Physical height in millimeters - physical-height", - "Physical diagonal length in inches - inch", - "Pixels per inch (PPI) - ppi", - "Year of manufacturing - manufacture-year", - "Nth week of manufacturing in the year - manufacture-week", - "Serial number - serial", - "Maximum refresh rate in Hz - refresh-rate", - })); -} - -void ffInitMonitorOptions(FFMonitorOptions* options) -{ - ffOptionInitModuleBaseInfo( - &options->moduleInfo, - FF_MONITOR_MODULE_NAME, - "Print connected physical monitor information", - ffParseMonitorCommandOptions, - ffParseMonitorJsonObject, - ffPrintMonitor, - ffGenerateMonitorJsonResult, - ffPrintMonitorHelpFormat, - ffGenerateMonitorJsonConfig - ); - ffOptionInitModuleArg(&options->moduleArgs, "󰹑"); -} - -void ffDestroyMonitorOptions(FFMonitorOptions* options) -{ - ffOptionDestroyModuleArg(&options->moduleArgs); -} diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h deleted file mode 100644 index d928c2ffef..0000000000 --- a/src/modules/monitor/monitor.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "fastfetch.h" - -#define FF_MONITOR_MODULE_NAME "Monitor" - -void ffPrintMonitor(FFMonitorOptions* options); -void ffInitMonitorOptions(FFMonitorOptions* options); -void ffDestroyMonitorOptions(FFMonitorOptions* options); diff --git a/src/modules/monitor/option.h b/src/modules/monitor/option.h deleted file mode 100644 index b474ae7b25..0000000000 --- a/src/modules/monitor/option.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -// This file will be included in "fastfetch.h", do NOT put unnecessary things here - -#include "common/option.h" - -typedef struct FFMonitorOptions -{ - FFModuleBaseInfo moduleInfo; - FFModuleArgs moduleArgs; -} FFMonitorOptions; diff --git a/src/modules/options.h b/src/modules/options.h index 783757d3a1..b3a9dc74a6 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -40,7 +40,6 @@ #include "modules/localip/option.h" #include "modules/media/option.h" #include "modules/memory/option.h" -#include "modules/monitor/option.h" #include "modules/netio/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index cea3c7af0d..4006391d33 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -41,7 +41,6 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitLocaleOptions(&options->locale); ffInitMediaOptions(&options->media); ffInitMemoryOptions(&options->memory); - ffInitMonitorOptions(&options->monitor); ffInitNetIOOptions(&options->netIo); ffInitOSOptions(&options->os); ffInitOpenCLOptions(&options->openCL); @@ -116,7 +115,6 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyLocaleOptions(&options->locale); ffDestroyMediaOptions(&options->media); ffDestroyMemoryOptions(&options->memory); - ffDestroyMonitorOptions(&options->monitor); ffDestroyNetIOOptions(&options->netIo); ffDestroyOSOptions(&options->os); ffDestroyOpenCLOptions(&options->openCL); diff --git a/src/options/modules.h b/src/options/modules.h index 919d924089..c57ac5c6bb 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -42,7 +42,6 @@ typedef struct FFOptionsModules FFLocaleOptions locale; FFMediaOptions media; FFMemoryOptions memory; - FFMonitorOptions monitor; FFNetIOOptions netIo; FFOSOptions os; FFOpenCLOptions openCL; From 5bdae7afc36e4eb1ed28391a11c35ce26711854e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 23:40:47 +0800 Subject: [PATCH 13/48] Display: display `ppi` in integer --- src/modules/display/display.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 91e5719d1a..6d6637ade7 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -100,7 +100,7 @@ void ffPrintDisplay(FFDisplayOptions* options) } FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - uint32_t inch = (uint32_t) (sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4 + 0.5); + double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4; if(options->moduleArgs.outputFormat.length == 0) { @@ -122,7 +122,7 @@ void ffPrintDisplay(FFDisplayOptions* options) ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight); if (inch > 1) - ffStrbufAppendF(&buffer, " in %i″", inch); + ffStrbufAppendF(&buffer, " in %i″", (uint32_t) (inch + 0.5)); if(result->type != FF_DISPLAY_TYPE_UNKNOWN) ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); @@ -139,6 +139,8 @@ void ffPrintDisplay(FFDisplayOptions* options) else { double ppi = sqrt(result->width * result->width + result->height * result->height) / inch; + bool hdrEnabled = result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; + uint32_t iInch = (uint32_t) (inch + 0.5), iPpi = (uint32_t) (ppi + 0.5); char refreshRate[16]; if(result->refreshRate > 0) @@ -160,7 +162,6 @@ void ffPrintDisplay(FFDisplayOptions* options) else buf[0] = '\0'; - bool hdrEnabled = result->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_DISPLAY_NUM_FORMAT_ARGS, ((FFformatarg[]) { FF_FORMAT_ARG(result->width, "width"), FF_FORMAT_ARG(result->height, "height"), @@ -173,8 +174,8 @@ void ffPrintDisplay(FFDisplayOptions* options) FF_FORMAT_ARG(result->primary, "is-primary"), FF_FORMAT_ARG(result->physicalWidth, "physical-width"), FF_FORMAT_ARG(result->physicalHeight, "physical-height"), - FF_FORMAT_ARG(inch, "inch"), - FF_FORMAT_ARG(ppi, "ppi"), + FF_FORMAT_ARG(iInch, "inch"), + FF_FORMAT_ARG(iPpi, "ppi"), FF_FORMAT_ARG(result->bitDepth, "bit-depth"), FF_FORMAT_ARG(hdrEnabled, "hdr-enabled"), FF_FORMAT_ARG(result->manufactureYear, "manufacture-year"), From 18be6c8fd17e3bcfd7320b1a0ef7d286ec54f11d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 30 Sep 2024 23:42:08 +0800 Subject: [PATCH 14/48] Display: don't use non-ascii charactors Which cannot be displayed in Linux console --- src/modules/display/display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 6d6637ade7..53f39a467b 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -122,7 +122,7 @@ void ffPrintDisplay(FFDisplayOptions* options) ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight); if (inch > 1) - ffStrbufAppendF(&buffer, " in %i″", (uint32_t) (inch + 0.5)); + ffStrbufAppendF(&buffer, " in %i\"", (uint32_t) (inch + 0.5)); if(result->type != FF_DISPLAY_TYPE_UNKNOWN) ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); From 6dd6266a2a66815ddd57861d72e12431eed67a18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 1 Oct 2024 09:30:39 +0800 Subject: [PATCH 15/48] GPU (Linux): fix possible buffer overflow --- src/detection/gpu/gpu_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 45fbdfef0a..c3678d6e60 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -625,7 +625,7 @@ FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, cons static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) { char compatible[256]; // vendor,model-name - if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%256[^C]", compatible) != 1) + if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%255[^C]", compatible) != 1) return "Failed to parse of modalias or not a GPU device"; char* name = strchr(compatible, ','); From 3381262930ae838fbb0639f706ef7832b725143f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 1 Oct 2024 12:10:15 +0800 Subject: [PATCH 16/48] Monitor: make it an alias of Display module --- CMakeLists.txt | 1 + doc/json_schema.json | 5 + presets/all.jsonc | 1 + presets/ci.jsonc | 1 + src/common/modules.c | 1 + src/modules/modules.h | 1 + src/modules/monitor/monitor.c | 166 ++++++++++++++++++++++++++++++++++ src/modules/monitor/monitor.h | 9 ++ src/modules/monitor/option.h | 11 +++ src/modules/options.h | 1 + src/options/modules.c | 2 + src/options/modules.h | 1 + 12 files changed, 200 insertions(+) create mode 100644 src/modules/monitor/monitor.c create mode 100644 src/modules/monitor/monitor.h create mode 100644 src/modules/monitor/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 662e4c663c..dd95d42917 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -382,6 +382,7 @@ set(LIBFASTFETCH_SRC src/modules/locale/locale.c src/modules/localip/localip.c src/modules/memory/memory.c + src/modules/monitor/monitor.c src/modules/netio/netio.c src/modules/opencl/opencl.c src/modules/opengl/opengl.c diff --git a/doc/json_schema.json b/doc/json_schema.json index 7eebf00998..009e35484a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -684,6 +684,7 @@ "localip", "media", "memory", + "monitor", "netio", "opencl", "opengl", @@ -813,6 +814,10 @@ "const": "media", "description": "Print playing song name" }, + { + "const": "monitor", + "description": "Alias of Display module; deprecated" + }, { "const": "opencl", "description": "Print highest OpenCL version supported by the GPU" diff --git a/presets/all.jsonc b/presets/all.jsonc index e50c450cb8..9b27615e04 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -24,6 +24,7 @@ "editor", "display", "brightness", + "monitor", "lm", "de", "wm", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index fe506e3544..3027010d8f 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -26,6 +26,7 @@ "editor", "display", "brightness", + "monitor", "lm", "de", "wm", diff --git a/src/common/modules.c b/src/common/modules.c index 87ae82829a..4e8ae69e4c 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -87,6 +87,7 @@ static FFModuleBaseInfo* L[] = { static FFModuleBaseInfo* M[] = { (void*) &instance.config.modules.media, (void*) &instance.config.modules.memory, + (void*) &instance.config.modules.monitor, NULL, }; diff --git a/src/modules/modules.h b/src/modules/modules.h index 76d76d6225..4f9fa7a407 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -40,6 +40,7 @@ #include "modules/localip/localip.h" #include "modules/media/media.h" #include "modules/memory/memory.h" +#include "modules/monitor/monitor.h" #include "modules/netio/netio.h" #include "modules/opengl/opengl.h" #include "modules/opencl/opencl.h" diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c new file mode 100644 index 0000000000..6fe9b91adf --- /dev/null +++ b/src/modules/monitor/monitor.c @@ -0,0 +1,166 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/displayserver/displayserver.h" +#include "modules/monitor/monitor.h" +#include "util/stringUtils.h" + +#include + +#define FF_MONITOR_NUM_FORMAT_ARGS 12 + +void ffPrintMonitor(FFMonitorOptions* options) +{ + const FFDisplayServerResult* result = ffConnectDisplayServer(); + + if(!result->displays.length) + { + ffPrintError(FF_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "No display detected"); + return; + } + + FF_STRBUF_AUTO_DESTROY key = ffStrbufCreate(); + uint32_t index = 0; + FF_LIST_FOR_EACH(FFDisplayResult, display, result->displays) + { + double inch = sqrt(display->physicalWidth * display->physicalWidth + display->physicalHeight * display->physicalHeight) / 25.4; + double ppi = sqrt(display->width * display->width + display->height * display->height) / inch; + bool hdrCompatible = display->hdrStatus == FF_DISPLAY_HDR_STATUS_SUPPORTED || display->hdrStatus == FF_DISPLAY_HDR_STATUS_ENABLED; + + ffStrbufClear(&key); + if(options->moduleArgs.key.length == 0) + { + ffStrbufAppendF(&key, "%s (%s)", FF_MONITOR_MODULE_NAME, display->name.chars); + } + else + { + uint32_t moduleIndex = result->displays.length == 1 ? 0 : index + 1; + FF_PARSE_FORMAT_STRING_CHECKED(&key, &options->moduleArgs.key, 3, ((FFformatarg[]){ + FF_FORMAT_ARG(moduleIndex, "index"), + FF_FORMAT_ARG(display->name, "name"), + FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"), + })); + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY); + + printf("%ux%u px", display->width, display->height); + if (display->refreshRate > 0) + printf(" @ %g Hz", ((int) (display->refreshRate * 1000 + 0.5)) / 1000.0); + if (inch > 0) + printf(" - %ux%u mm (%.2f inches, %.2f ppi)", display->physicalWidth, display->physicalHeight, inch, ppi); + if (hdrCompatible) + fputs(" [HDR Compatible]", stdout); + putchar('\n'); + } + else + { + char buf[32]; + if (display->serial) + { + const uint8_t* nums = (uint8_t*) &display->serial; + snprintf(buf, sizeof(buf), "%2X-%2X-%2X-%2X", nums[0], nums[1], nums[2], nums[3]); + } + else + buf[0] = '\0'; + + FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_MONITOR_NUM_FORMAT_ARGS, ((FFformatarg[]) { + FF_FORMAT_ARG(display->name, "name"), + FF_FORMAT_ARG(display->width, "width"), + FF_FORMAT_ARG(display->height, "height"), + FF_FORMAT_ARG(display->physicalWidth, "physical-width"), + FF_FORMAT_ARG(display->physicalHeight, "physical-height"), + FF_FORMAT_ARG(inch, "inch"), + FF_FORMAT_ARG(ppi, "ppi"), + FF_FORMAT_ARG(display->manufactureYear, "manufacture-year"), + FF_FORMAT_ARG(display->manufactureWeek, "manufacture-week"), + FF_FORMAT_ARG(buf, "serial"), + FF_FORMAT_ARG(display->refreshRate, "refresh-rate"), + FF_FORMAT_ARG(hdrCompatible, "hdr-compatible"), + })); + } + + ffStrbufDestroy(&display->name); + ++index; + } +} + +bool ffParseMonitorCommandOptions(FFMonitorOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_MONITOR_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseMonitorJsonObject(FFMonitorOptions* 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_MONITOR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateMonitorJsonConfig(FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyMonitorOptions))) FFMonitorOptions defaultOptions; + ffInitMonitorOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateMonitorJsonResult(FF_MAYBE_UNUSED FFMonitorOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + yyjson_mut_obj_add_str(doc, module, "error", "Monitor module is an alias of Display module"); +} + +void ffPrintMonitorHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_MONITOR_MODULE_NAME, "{2}x{3} px - {4}x{5} mm ({6} inches, {7} ppi)", FF_MONITOR_NUM_FORMAT_ARGS, ((const char* []) { + "Display name - name", + "Native resolution width in pixels - width", + "Native resolution height in pixels - height", + "Physical width in millimeters - physical-width", + "Physical height in millimeters - physical-height", + "Physical diagonal length in inches - inch", + "Pixels per inch (PPI) - ppi", + "Year of manufacturing - manufacture-year", + "Nth week of manufacturing in the year - manufacture-week", + "Serial number - serial", + "Maximum refresh rate in Hz - refresh-rate", + "True if the display is HDR compatible - hdr-compatible", + })); +} + +void ffInitMonitorOptions(FFMonitorOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_MONITOR_MODULE_NAME, + "Alias of Display module; deprecated", + ffParseMonitorCommandOptions, + ffParseMonitorJsonObject, + ffPrintMonitor, + ffGenerateMonitorJsonResult, + ffPrintMonitorHelpFormat, + ffGenerateMonitorJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰹑"); +} + +void ffDestroyMonitorOptions(FFMonitorOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/monitor/monitor.h b/src/modules/monitor/monitor.h new file mode 100644 index 0000000000..d928c2ffef --- /dev/null +++ b/src/modules/monitor/monitor.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_MONITOR_MODULE_NAME "Monitor" + +void ffPrintMonitor(FFMonitorOptions* options); +void ffInitMonitorOptions(FFMonitorOptions* options); +void ffDestroyMonitorOptions(FFMonitorOptions* options); diff --git a/src/modules/monitor/option.h b/src/modules/monitor/option.h new file mode 100644 index 0000000000..b474ae7b25 --- /dev/null +++ b/src/modules/monitor/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 FFMonitorOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFMonitorOptions; diff --git a/src/modules/options.h b/src/modules/options.h index b3a9dc74a6..783757d3a1 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -40,6 +40,7 @@ #include "modules/localip/option.h" #include "modules/media/option.h" #include "modules/memory/option.h" +#include "modules/monitor/option.h" #include "modules/netio/option.h" #include "modules/opengl/option.h" #include "modules/opencl/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index 4006391d33..cea3c7af0d 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -41,6 +41,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitLocaleOptions(&options->locale); ffInitMediaOptions(&options->media); ffInitMemoryOptions(&options->memory); + ffInitMonitorOptions(&options->monitor); ffInitNetIOOptions(&options->netIo); ffInitOSOptions(&options->os); ffInitOpenCLOptions(&options->openCL); @@ -115,6 +116,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyLocaleOptions(&options->locale); ffDestroyMediaOptions(&options->media); ffDestroyMemoryOptions(&options->memory); + ffDestroyMonitorOptions(&options->monitor); ffDestroyNetIOOptions(&options->netIo); ffDestroyOSOptions(&options->os); ffDestroyOpenCLOptions(&options->openCL); diff --git a/src/options/modules.h b/src/options/modules.h index c57ac5c6bb..919d924089 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -42,6 +42,7 @@ typedef struct FFOptionsModules FFLocaleOptions locale; FFMediaOptions media; FFMemoryOptions memory; + FFMonitorOptions monitor; FFNetIOOptions netIo; FFOSOptions os; FFOpenCLOptions openCL; From 99626149f649b9e3fcb1c4fe6c640e94726c78d8 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 1 Oct 2024 17:26:29 +0800 Subject: [PATCH 17/48] Display (FreeBSD): add guards between linux specific code --- src/detection/displayserver/linux/drm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 9ccaa3f7ee..56a16d3f75 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -168,7 +168,7 @@ static inline const char* drmType2Name(uint32_t connector_type) } } -static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edidData, ssize_t* edidLength) +FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edidData, ssize_t* edidLength) { const char* drmDirPath = "/sys/class/drm/"; @@ -229,7 +229,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) drmDevice* devices[64]; int nDevices = ffdrmGetDevices(devices, sizeof(devices) / sizeof(devices[0])); - if (nDevices < 0) + if (nDevices <= 0) return "drmGetDevices() failed"; FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); @@ -243,11 +243,13 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) const char* path = dev->nodes[DRM_NODE_PRIMARY]; + #if __linux__ ffStrbufSetF(&name, "/sys/class/drm/%s/device/power/runtime_status", strrchr(path, '/') + 1); char buffer[8] = ""; if (ffReadFileData(name.chars, strlen("suspend"), buffer) > 0 && ffStrStartsWith(buffer, "suspend")) continue; + #endif FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) @@ -350,6 +352,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffdrmModeFreeProperty(prop); } + #if __linux__ if (name.length == 0) { uint8_t edidData[512]; @@ -362,6 +365,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) ffEdidGetSerialAndManufactureDate(edidData, &serial, &myear, &mweak); } } + #endif if (name.length == 0) { From b49c509a6caa1b4b829f3692258a4637fa68efab Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 1 Oct 2024 17:44:23 +0800 Subject: [PATCH 18/48] DateTime: add `day-pretty` Fix #1305 --- src/modules/datetime/datetime.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/datetime/datetime.c b/src/modules/datetime/datetime.c index 67bded503f..a79a31c49c 100644 --- a/src/modules/datetime/datetime.c +++ b/src/modules/datetime/datetime.c @@ -9,7 +9,7 @@ #pragma GCC diagnostic ignored "-Wformat" // warning: unknown conversion type character 'F' in format #define FF_DATETIME_DISPLAY_NAME "Date & Time" -#define FF_DATETIME_NUM_FORMAT_ARGS 22 +#define FF_DATETIME_NUM_FORMAT_ARGS 23 typedef struct FFDateTimeResult { @@ -26,6 +26,7 @@ typedef struct FFDateTimeResult uint16_t dayInYear; //52 uint8_t dayInMonth; //21 uint8_t dayInWeek; //1 + char dayPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //01 uint8_t hour; //15 char hourPretty[FASTFETCH_STRBUF_DEFAULT_ALLOC]; //15 uint8_t hour12; //3 @@ -54,6 +55,7 @@ void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) 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; + strftime(result.dayPretty, sizeof(result.dayPretty), "%0d", tm); result.hour = (uint8_t) tm->tm_hour; strftime(result.hourPretty, sizeof(result.hourPretty), "%H", tm); result.hour12 = (uint8_t) (result.hour % 12); @@ -88,6 +90,7 @@ void ffPrintDateTimeFormat(struct tm* tm, const FFModuleArgs* moduleArgs) FF_FORMAT_ARG(result.secondPretty, "second-pretty"), // 20 FF_FORMAT_ARG(result.offsetFromUtc, "offset-from-utc"), // 21 FF_FORMAT_ARG(result.timezoneName, "timezone-name"), // 22 + FF_FORMAT_ARG(result.dayPretty, "day-pretty"), // 23 })); } @@ -157,7 +160,7 @@ void ffGenerateDateTimeJsonResult(FF_MAYBE_UNUSED FFDateTimeOptions* options, yy void ffPrintDateTimeHelpFormat(void) { - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_DATETIME_MODULE_NAME, "{1}-{4}-{11} {14}:{18}:{20}", FF_DATETIME_NUM_FORMAT_ARGS, ((const char* []) { + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_DATETIME_MODULE_NAME, "{1}-{4}-{23} {14}:{18}:{20}", FF_DATETIME_NUM_FORMAT_ARGS, ((const char* []) { "year - year", "last two digits of year - year-short", "month - month", @@ -180,6 +183,7 @@ void ffPrintDateTimeHelpFormat(void) "second with leading zero - second-pretty", "offset from UTC in the ISO 8601 format - offset-from-utc", "locale-dependent timezone name or abbreviation - timezone-name", + "day in month with leading zero - day-pretty", })); } From 89d3924659210609e0d3a1845e13f615f60da660 Mon Sep 17 00:00:00 2001 From: kralverde <80051564+kralverde@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:43:58 -0400 Subject: [PATCH 19/48] CPU (Linux): fix temperature detection (#1308) Return proper NaN instead of false -> 0.0 coercion --- src/detection/cpu/cpu_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 704e506fba..fe08272f2a 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -47,7 +47,7 @@ static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) ffStrbufEqualS(buffer, "coretemp") // Intel ) return value / 1000.; - return false; + return 0.0/0.0; } static double detectCPUTemp(void) From 8a11aa0f8f8e4f74bdde0af74b012aa7406432bf Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Wed, 2 Oct 2024 23:30:19 +1000 Subject: [PATCH 20/48] Completions (zsh, fish): check for python3 (#1310) Both the zsh and fish completions depend on python3. When the completitions kick in with those shells where no python3 is found it throws errors. Check python3 is installed, otherwise return no completitions to avoid throwing errors Co-authored-by: Andrew Davis --- completions/fastfetch.fish | 5 +++++ completions/fastfetch.zsh | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/completions/fastfetch.fish b/completions/fastfetch.fish index 494de27308..7badab3881 100755 --- a/completions/fastfetch.fish +++ b/completions/fastfetch.fish @@ -2,6 +2,11 @@ if not type -q fastfetch exit end +command -q python3 +if test $status -ne 0 + exit +end + complete -c fastfetch -f function __fastfetch_complete_bool diff --git a/completions/fastfetch.zsh b/completions/fastfetch.zsh index a6ce692798..5688c17458 100644 --- a/completions/fastfetch.zsh +++ b/completions/fastfetch.zsh @@ -1,6 +1,13 @@ #compdef fastfetch function _fastfetch() { + + whence python3 &> /dev/null + if [ $? -ne 0 ] + then + return + fi + local state local -a opts=("${(f)$( From 46c8bc1f99966880b42eed88bfd24bcbde849af2 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 3 Oct 2024 20:44:49 +0800 Subject: [PATCH 21/48] Board (Linux): trim strings --- src/detection/board/board_linux.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/detection/board/board_linux.c b/src/detection/board/board_linux.c index 2820bbc847..70cd54034a 100644 --- a/src/detection/board/board_linux.c +++ b/src/detection/board/board_linux.c @@ -12,13 +12,17 @@ const char* ffDetectBoard(FFBoardResult* board) ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor); ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version); } - else if (ffReadFileBuffer("/proc/device-tree/board", &board->vendor) || - ffReadFileBuffer("/proc/device-tree/compatible", &board->vendor)) + else if (ffReadFileBuffer("/proc/device-tree/board", &board->name)) + { + ffStrbufTrimRightSpace(&board->name); + } + else if (ffReadFileBuffer("/proc/device-tree/compatible", &board->vendor)) { uint32_t comma = ffStrbufFirstIndexC(&board->vendor, ','); if (comma < board->vendor.length) { ffStrbufSetS(&board->name, board->vendor.chars + comma + 1); + ffStrbufTrimRightSpace(&board->name); ffStrbufSubstrBefore(&board->vendor, comma); } } From 53a373c9cf43d89488fe1d0cab6e3be5877e0b3d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 3 Oct 2024 20:58:14 +0800 Subject: [PATCH 22/48] Monitor: don't deprecate this module --- doc/json_schema.json | 2 +- src/modules/monitor/monitor.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 009e35484a..0847a4aa2a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -816,7 +816,7 @@ }, { "const": "monitor", - "description": "Alias of Display module; deprecated" + "description": "Alias of Display module" }, { "const": "opencl", diff --git a/src/modules/monitor/monitor.c b/src/modules/monitor/monitor.c index 6fe9b91adf..701444c294 100644 --- a/src/modules/monitor/monitor.c +++ b/src/modules/monitor/monitor.c @@ -149,7 +149,7 @@ void ffInitMonitorOptions(FFMonitorOptions* options) ffOptionInitModuleBaseInfo( &options->moduleInfo, FF_MONITOR_MODULE_NAME, - "Alias of Display module; deprecated", + "Alias of Display module", ffParseMonitorCommandOptions, ffParseMonitorJsonObject, ffPrintMonitor, From a4fe933625491eb31a7d8c2c7e098cf6778f7b19 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 3 Oct 2024 21:02:20 +0800 Subject: [PATCH 23/48] Doc: update changelog for 2.27.0 --- CHANGELOG.md | 19 +++++++++++++++++++ CMakeLists.txt | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57eda8efec..a66095c62f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +# 2.27.0 + +Changes: +* We now print `"` instead of `″` when displaying diagonal length in inches, so that the character can be correctly displayed in Linux console (Display) +* All detection code of `monitor` module is merged into `display` module. Now `monitor` just prints the same information as `display` with different format. Notably: + * The resolution reported by `monitor` module is now current resolution instead of native / maximum resolution. PPI is calcuated based on current resolution too. + * The refresh rate reported by `monitor` module is the current refresh rate. + +Features: +* Improve support for Raspberry pi (CPU / GPU, Linux) +* Detect SOC name, instead of displaying components used in the SOC, if available (CPU, Linux) +* Add option `--brightness-compact` to display multiple brightness values in one line (Brightness) +* Add `day-pretty` (#1305, DateTime) + +Bugfixes: +* Remove trailing newline in GPU name for Raspberry pi (#1303, GPU, Linux) +* Fix a possible buffer overflow (GPU, Linux) +* Fix CPU temp incorrectly reported as 0 celsius (#1308, CPU, Linux) + # 2.26.1 Features: diff --git a/CMakeLists.txt b/CMakeLists.txt index dd95d42917..365ea40a1a 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.26.1 + VERSION 2.27.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From aa734e222021cf921847b233652a340540af00bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 2 Oct 2024 00:43:31 +0800 Subject: [PATCH 24/48] Doc: fix Json schema [ci skip] --- 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 0847a4aa2a..6a38e48ce7 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -344,7 +344,7 @@ "description": "Set the command to be executed before printing logos", "default": "" }, - "showVersion": { + "detectVersion": { "type": "boolean", "description": "Whether to detect and display component versions. Mainly for benchmarking", "default": true From 937b2e41edd0f96baaaee3c1cba88040f148a610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 2 Oct 2024 20:13:12 +0800 Subject: [PATCH 25/48] Terminal (Linux): remove invalid info when fail to detect terminal by process tracing --- .../terminalshell/terminalshell_linux.c | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 0355e25636..c29d97742d 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -161,23 +161,30 @@ static bool getTerminalInfoByPidEnv(FFTerminalResult* result, const char* pidEnv static void getTerminalFromEnv(FFTerminalResult* result) { - if( - result->processName.length > 0 && - !ffStrbufStartsWithS(&result->processName, "login") && - !ffStrbufEqualS(&result->processName, "(login)") && + if (result->processName.length > 0) + { + if (!ffStrbufStartsWithS(&result->processName, "login") && + !ffStrbufEqualS(&result->processName, "(login)") && + + #ifdef __APPLE__ + !ffStrbufEqualS(&result->processName, "launchd") && + !ffStrbufEqualS(&result->processName, "stable") && //for WarpTerminal + #else + !ffStrbufEqualS(&result->processName, "systemd") && + !ffStrbufEqualS(&result->processName, "init") && + !ffStrbufEqualS(&result->processName, "(init)") && + !ffStrbufEqualS(&result->processName, "SessionLeader") && // #750 + #endif - #ifdef __APPLE__ - !ffStrbufEqualS(&result->processName, "launchd") && - !ffStrbufEqualS(&result->processName, "stable") && //for WarpTerminal - #else - !ffStrbufEqualS(&result->processName, "systemd") && - !ffStrbufEqualS(&result->processName, "init") && - !ffStrbufEqualS(&result->processName, "(init)") && - !ffStrbufEqualS(&result->processName, "SessionLeader") && // #750 - #endif + !ffStrbufEqualS(&result->processName, "0") + ) return; - !ffStrbufEqualS(&result->processName, "0") - ) return; + ffStrbufClear(&result->processName); + ffStrbufClear(&result->exe); + result->exeName = result->exe.chars; + ffStrbufClear(&result->exePath); + result->pid = result->ppid = 0; + } const char* term = NULL; From c2b60a2ebf1ddfa8fa308d0a18b16fbd38e80063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 3 Oct 2024 21:58:15 +0800 Subject: [PATCH 26/48] Logo (Builtin): remove some paddings --- src/logo/ascii/center.txt | 26 +++++++++++++------------- src/logo/ascii/cyberos.txt | 30 +++++++++++++++--------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/logo/ascii/center.txt b/src/logo/ascii/center.txt index a4c365d0bb..58d64f79a7 100644 --- a/src/logo/ascii/center.txt +++ b/src/logo/ascii/center.txt @@ -1,13 +1,13 @@ - . - o, - . d, . - ';' ..d;.. .cl' - .:; 'oldO,.oo. - ..,:,xKXxoo;'. - ,;;;;;ldxkONMMMXxkxc;;;;;. - .....':oddXWMNOxlcl:...... - .:dlxk0c;:. . - :d:.,xcld,.,:. - ;l, .l; ';' - .o; - l, \ No newline at end of file + . + o, + . d, . + ';' ..d;.. .cl' + .:; 'oldO,.oo. + ..,:,xKXxoo;'. +,;;;;;ldxkONMMMXxkxc;;;;;. +.....':oddXWMNOxlcl:...... + .:dlxk0c;:. . + :d:.,xcld,.,:. + ;l, .l; ';' + .o; + l, \ No newline at end of file diff --git a/src/logo/ascii/cyberos.txt b/src/logo/ascii/cyberos.txt index c47301fd3a..0dea1b5331 100644 --- a/src/logo/ascii/cyberos.txt +++ b/src/logo/ascii/cyberos.txt @@ -1,15 +1,15 @@ -${c3} !M$EEEEEEEEEEEP - .MMMMM000000Nr. - ${c3}&MMMMMM${c2}MMMMMMMMMMMMM9 - ${c3}~MMM${c1}MMMM${c2}MMMMMMMMMMMMC - ${c1}" ${c3}M${c1}MMMMMMM${c2}MMMMMMMMMMs - ${c1}iM${c2}MMM&&${c1}MMMMMMMM${c2}MMMMMMMM\\ - ${c1}BMMM${c2}MMMMM${c1}MMMMMMM${c2}MMMMMM${c3}" - ${c1}9MMMMM${c2}MMMMMMM${c1}MMMM${c2}MMMM${c3}MMMf- - ${c2}sMMMMMMMM${c1}MM${c2}M${c3}MMMMMMMMM3_ - ${c2}+ffffffff${c1}P${c3}MMMMMMMMMMMM0 - ${c2}CMMMMMMMMMMM - }MMMMMMMMM - ~MMMMMMM - "RMMMM - .PMB \ No newline at end of file +${c3} !M$EEEEEEEEEEEP + .MMMMM000000Nr. + ${c3}&MMMMMM${c2}MMMMMMMMMMMMM9 + ${c3}~MMM${c1}MMMM${c2}MMMMMMMMMMMMC + ${c1}" ${c3}M${c1}MMMMMMM${c2}MMMMMMMMMMs + ${c1}iM${c2}MMM&&${c1}MMMMMMMM${c2}MMMMMMMM\\ + ${c1}BMMM${c2}MMMMM${c1}MMMMMMM${c2}MMMMMM${c3}" +${c1}9MMMMM${c2}MMMMMMM${c1}MMMM${c2}MMMM${c3}MMMf- + ${c2}sMMMMMMMM${c1}MM${c2}M${c3}MMMMMMMMM3_ + ${c2}+ffffffff${c1}P${c3}MMMMMMMMMMMM0 + ${c2}CMMMMMMMMMMM + }MMMMMMMMM + ~MMMMMMM + "RMMMM + .PMB \ No newline at end of file From d06f9a1509314434d99d146b8fead00c5283373c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 4 Oct 2024 16:57:12 +0800 Subject: [PATCH 27/48] Chore (Windows): silence some warnings --- src/common/io/io_windows.c | 6 ++++++ src/detection/localip/localip_windows.c | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 6f2465da64..742d564ff3 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -266,14 +266,20 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char* { DWORD bytes = 0; if (!ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL) || bytes == 0) + { + va_end(args); return "ReadFile() failed"; + } bytesRead += bytes; buffer[bytesRead] = '\0'; int ret = vsscanf(buffer, format, args); if (ret <= 0) + { + va_end(args); return "vsscanf(buffer, format, args) failed"; + } if (ret >= nParams) break; } diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index a24d38591b..f26bb35b84 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -113,13 +113,13 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (!(typesToAdd & (FF_LOCALIP_TYPE_IPV4_BIT | FF_LOCALIP_TYPE_ALL_IPS_BIT))) continue; SOCKADDR_IN* ipv4 = (SOCKADDR_IN*) ifa->Address.lpSockaddr; - char addressBuffer[INET_ADDRSTRLEN + 4]; + char addressBuffer[INET_ADDRSTRLEN + 6]; inet_ntop(AF_INET, &ipv4->sin_addr, addressBuffer, INET_ADDRSTRLEN); if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength) { size_t len = strlen(addressBuffer); - snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength); + snprintf(addressBuffer + len, 6, "/%u", (unsigned) ifa->OnLinkPrefixLength); } addNewIp(results, name, addressBuffer, AF_INET, newIp, isDefaultRoute); @@ -133,13 +133,13 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (!(typesToAdd & (FF_LOCALIP_TYPE_IPV6_BIT | FF_LOCALIP_TYPE_ALL_IPS_BIT))) continue; SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*) ifa->Address.lpSockaddr; - char addressBuffer[INET6_ADDRSTRLEN + 4]; + char addressBuffer[INET6_ADDRSTRLEN + 6]; inet_ntop(AF_INET6, &ipv6->sin6_addr, addressBuffer, INET6_ADDRSTRLEN); if ((options->showType & FF_LOCALIP_TYPE_PREFIX_LEN_BIT) && ifa->OnLinkPrefixLength) { size_t len = strlen(addressBuffer); - snprintf(addressBuffer + len, 4, "/%u", (unsigned) ifa->OnLinkPrefixLength); + snprintf(addressBuffer + len, 6, "/%u", (unsigned) ifa->OnLinkPrefixLength); } addNewIp(results, name, addressBuffer, AF_INET6, newIp, isDefaultRoute); From a32d9d788c111eb1b490662d9e7bdbf782fe3ed5 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 4 Oct 2024 15:58:17 +0800 Subject: [PATCH 28/48] OpenBSD: init platform support --- CMakeLists.txt | 153 ++++++++++++++++---- src/common/init.c | 2 +- src/common/io/io_unix.c | 6 + src/common/processing_linux.c | 33 +++++ src/common/sysctl.c | 36 +++++ src/common/sysctl.h | 6 + src/detection/cpu/cpu_obsd.c | 19 +++ src/detection/cpuusage/cpuusage_bsd.c | 16 ++ src/detection/disk/disk_bsd.c | 9 ++ src/detection/displayserver/linux/wmde.c | 29 +++- src/detection/dns/dns_linux.c | 5 +- src/detection/host/host_obsd.c | 19 +++ src/detection/loadavg/loadavg_bsd.c | 6 +- src/detection/localip/localip_linux.c | 6 +- src/detection/memory/memory_obsd.c | 20 +++ src/detection/opengl/opengl_linux.c | 11 +- src/detection/os/os_obsd.c | 7 + src/detection/packages/packages_bsd.c | 2 +- src/detection/packages/packages_obsd.c | 31 ++++ src/detection/processes/processes_obsd.c | 14 ++ src/detection/swap/swap_obsd.c | 30 ++++ src/detection/terminalshell/terminalshell.c | 20 ++- src/detection/users/users_nosupport.c | 7 + src/detection/version/version.c | 2 + src/logo/builtin.c | 1 + src/modules/localip/localip.c | 2 +- src/modules/memory/memory.c | 2 +- src/modules/os/os.c | 2 + src/modules/swap/swap.c | 2 +- src/options/general.c | 4 +- src/options/general.h | 2 +- src/util/binary_linux.c | 2 +- src/util/platform/FFPlatform_unix.c | 8 +- 33 files changed, 459 insertions(+), 55 deletions(-) create mode 100644 src/detection/cpu/cpu_obsd.c create mode 100644 src/detection/host/host_obsd.c create mode 100644 src/detection/memory/memory_obsd.c create mode 100644 src/detection/os/os_obsd.c create mode 100644 src/detection/packages/packages_obsd.c create mode 100644 src/detection/processes/processes_obsd.c create mode 100644 src/detection/swap/swap_obsd.c create mode 100644 src/detection/users/users_nosupport.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 365ea40a1a..f8ab5015c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,8 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") set(LINUX TRUE CACHE BOOL "..." FORCE) # LINUX means GNU/Linux, not just the kernel elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD") set(FreeBSD TRUE CACHE BOOL "..." FORCE) +elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD") + set(OpenBSD TRUE CACHE BOOL "..." FORCE) elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") set(SunOS TRUE CACHE BOOL "..." FORCE) elseif(NOT APPLE AND NOT WIN32) @@ -44,30 +46,30 @@ include(CheckIncludeFile) include(CMakeDependentOption) -cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF) -cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD" OFF) -cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_VULKAN "Enable vulkan" ON "LINUX OR APPLE OR FreeBSD OR OpenBSD OR WIN32 OR ANDROID OR SunOS" OFF) +cmake_dependent_option(ENABLE_WAYLAND "Enable wayland-client" ON "LINUX OR FreeBSD OR OpenBSD" OFF) +cmake_dependent_option(ENABLE_XCB_RANDR "Enable xcb-randr" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF) -cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF) +cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_XFCONF "Enable libxfconf-0" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_SQLITE3 "Enable sqlite3" ON "LINUX OR FreeBSD OR APPLE OR OpenBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_RPM "Enable rpm" ON "LINUX" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR APPLE OR WIN32 OR SunOS" OFF) -cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR APPLE OR SunOS" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK7 "Enable imagemagick 7" ON "LINUX OR FreeBSD OR OpenBSD OR APPLE OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_IMAGEMAGICK6 "Enable imagemagick 6" ON "LINUX OR FreeBSD OR OpenBSD OR APPLE OR SunOS" OFF) cmake_dependent_option(ENABLE_CHAFA "Enable chafa" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) cmake_dependent_option(ENABLE_ZLIB "Enable zlib" ON "ENABLE_IMAGEMAGICK6 OR ENABLE_IMAGEMAGICK7" OFF) -cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR WIN32 OR SunOS" OFF) -cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR SunOS" OFF) -cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR WIN32 OR ANDROID OR SunOS" OFF) +cmake_dependent_option(ENABLE_EGL "Enable egl" ON "LINUX OR FreeBSD OR OpenBSD OR WIN32 OR SunOS" OFF) +cmake_dependent_option(ENABLE_GLX "Enable glx" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OSMESA "Enable osmesa" ON "LINUX OR FreeBSD OR OpenBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_OPENCL "Enable opencl" ON "LINUX OR FreeBSD OR OpenBSD OR WIN32 OR ANDROID OR SunOS" OFF) cmake_dependent_option(ENABLE_FREETYPE "Enable freetype" ON "ANDROID" OFF) -cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR SunOS" OFF) +cmake_dependent_option(ENABLE_PULSE "Enable pulse" ON "LINUX OR OpenBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF) cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID" OFF) @@ -653,6 +655,85 @@ elseif(FreeBSD) src/util/platform/FFPlatform_unix.c src/util/binary_linux.c ) +elseif(OpenBSD) + 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 + src/detection/battery/battery_nosupport.c + src/detection/bios/bios_nosupport.c + src/detection/bluetooth/bluetooth_nosupport.c + src/detection/bluetoothradio/bluetoothradio_nosupport.c + src/detection/board/board_nosupport.c + src/detection/bootmgr/bootmgr_nosupport.c + src/detection/brightness/brightness_nosupport.c + src/detection/btrfs/btrfs_nosupport.c + src/detection/chassis/chassis_nosupport.c + src/detection/cpu/cpu_obsd.c + src/detection/cpucache/cpucache_nosupport.c + src/detection/cpuusage/cpuusage_bsd.c + src/detection/cursor/cursor_linux.c + src/detection/disk/disk_bsd.c + src/detection/dns/dns_linux.c + src/detection/physicaldisk/physicaldisk_nosupport.c + src/detection/physicalmemory/physicalmemory_nosupport.c + src/detection/diskio/diskio_nosupport.c + src/detection/displayserver/linux/displayserver_linux.c + src/detection/displayserver/linux/drm.c + src/detection/displayserver/linux/wayland/wayland.c + src/detection/displayserver/linux/wayland/global-output.c + src/detection/displayserver/linux/wayland/zwlr-output.c + src/detection/displayserver/linux/wayland/kde-output.c + src/detection/displayserver/linux/wayland/wlr-output-management-unstable-v1-protocol.c + src/detection/displayserver/linux/wayland/kde-output-device-v2-protocol.c + src/detection/displayserver/linux/wayland/kde-output-order-v1-protocol.c + src/detection/displayserver/linux/wayland/xdg-output-unstable-v1-protocol.c + src/detection/displayserver/linux/wmde.c + src/detection/displayserver/linux/xcb.c + src/detection/displayserver/linux/xlib.c + src/detection/font/font_linux.c + src/detection/gpu/gpu_nosupport.c + src/detection/gtk_qt/gtk.c + src/detection/host/host_obsd.c + src/detection/lm/lm_nosupport.c + src/detection/icons/icons_linux.c + src/detection/initsystem/initsystem_linux.c + src/detection/libc/libc_nosupport.c + src/detection/loadavg/loadavg_bsd.c + src/detection/locale/locale_linux.c + src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c + src/detection/media/media_linux.c + src/detection/memory/memory_obsd.c + src/detection/netio/netio_nosupport.c + src/detection/opengl/opengl_linux.c + src/detection/os/os_obsd.c + src/detection/packages/packages_obsd.c + src/detection/poweradapter/poweradapter_nosupport.c + src/detection/processes/processes_obsd.c + src/detection/gtk_qt/qt.c + src/detection/sound/sound_linux.c + src/detection/swap/swap_obsd.c + src/detection/terminalfont/terminalfont_linux.c + src/detection/terminalshell/terminalshell_linux.c + src/detection/terminalsize/terminalsize_linux.c + src/detection/theme/theme_linux.c + src/detection/tpm/tpm_nosupport.c + src/detection/uptime/uptime_bsd.c + src/detection/users/users_nosupport.c + src/detection/wallpaper/wallpaper_linux.c + src/detection/wifi/wifi_nosupport.c + src/detection/wm/wm_nosupport.c + src/detection/de/de_linux.c + src/detection/wmtheme/wmtheme_linux.c + src/detection/camera/camera_nosupport.c + src/detection/zpool/zpool_nosupport.c + src/util/platform/FFPlatform_unix.c + src/util/binary_linux.c + ) elseif(APPLE) list(APPEND LIBFASTFETCH_SRC src/common/io/io_unix.c @@ -945,13 +1026,16 @@ if(FreeBSD AND EXISTS "/usr/local/bin/objdump") endif() endif() -target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1 _FILE_OFFSET_BITS=64) -if(WIN32) - target_compile_definitions(libfastfetch PUBLIC WIN32_LEAN_AND_MEAN=1) +if(LINUX) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1 _FILE_OFFSET_BITS=64) +elseif(WIN32) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00) elseif(APPLE) - target_compile_definitions(libfastfetch PUBLIC _DARWIN_C_SOURCE) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _DARWIN_C_SOURCE) +elseif(OpenBSD) + target_compile_definitions(libfastfetch PUBLIC _XOPEN_SOURCE=700 _FILE_OFFSET_BITS=64 _BSD_SOURCE) elseif(SunOS) - target_compile_definitions(libfastfetch PUBLIC __EXTENSIONS__ _POSIX_C_SOURCE=1) + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 __EXTENSIONS__ _POSIX_C_SOURCE) endif() if(HAVE_STATX) @@ -1097,10 +1181,17 @@ ff_lib_enable(EGL "egl" "EGL" ) -ff_lib_enable(GLX - "glx" - "GLX" -) +if(NOT OpenBSD) + ff_lib_enable(GLX + "glx" + "GLX" + ) +else() + ff_lib_enable(GLX + "gl" + "GL" + ) +endif() ff_lib_enable(OSMESA "osmesa" "OSMesa" @@ -1194,7 +1285,6 @@ elseif(APPLE) PRIVATE "-weak_framework Apple80211" ) elseif(WIN32) - target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0A00) target_link_libraries(libfastfetch PRIVATE "dwmapi" PRIVATE "gdi32" @@ -1215,6 +1305,11 @@ elseif(FreeBSD) PRIVATE "usbhid" PRIVATE "geom" ) +elseif(OpenBSD) + target_link_libraries(libfastfetch + PRIVATE "m" + PRIVATE "kvm" + ) elseif(SunOS) target_link_libraries(libfastfetch PRIVATE "m" diff --git a/src/common/init.c b/src/common/init.c index 514b9fb6af..643f94a944 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -245,7 +245,7 @@ void ffListFeatures(void) #if FF_HAVE_DDCUTIL "libddcutil\n" #endif - #if FF_HAVE_ELF || __sun || __FreeBSD__ + #if FF_HAVE_ELF || __sun || __FreeBSD__ || __OpenBSD__ "libelf\n" #endif #if FF_HAVE_LIBZFS diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index facc03a56f..957789c693 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -191,14 +191,20 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char* ssize_t nRead = read(ftty, buffer + bytesRead, sizeof(buffer) - bytesRead - 1); if (nRead <= 0) + { + va_end(args); return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed"; + } bytesRead += (size_t) nRead; buffer[bytesRead] = '\0'; int ret = vsscanf(buffer, format, args); if (ret <= 0) + { + va_end(args); return "vsscanf(buffer, format, args) failed"; + } if (ret >= nParams) break; } diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index af3f4ebf50..ca7059417d 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -22,6 +22,10 @@ #include #elif defined(__sun) #include +#elif defined(__OpenBSD__) +#include +#include +#include #endif enum { FF_PIPE_BUFSIZ = 8192 }; @@ -259,6 +263,18 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons } } + #elif defined(__OpenBSD__) + + kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + int count = 0; + const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count); + if (proc) + { + char** argv = kvm_getargv(kd, proc, 0); + if (argv) ffStrbufSetS(exe, argv[0]); + } + kvm_close(kd); + #endif if(exe->length == 0) @@ -373,6 +389,23 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i if (tty) *tty = (int) proc.pr_ttydev; + #elif defined(__OpenBSD__) + + kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + int count = 0; + const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count); + if (proc) + { + ffStrbufSetS(name, proc->p_comm); + if (ppid) + *ppid = proc->p_ppid; + if (tty) + *tty = (int) proc->p_tdev; + } + kvm_close(kd); + if (!proc) + return "kvm_getprocs() failed"; + #else return "Unsupported platform"; diff --git a/src/common/sysctl.c b/src/common/sysctl.c index 4f0f3b65ce..42a5875a6a 100644 --- a/src/common/sysctl.c +++ b/src/common/sysctl.c @@ -2,6 +2,41 @@ #include +#ifdef __OpenBSD__ +const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result) +{ + size_t neededLength; + if (sysctl((int[]) {mib1, mib2}, 2, NULL, &neededLength, NULL, 0) != 0 || neededLength == 1) //neededLength is 1 for empty strings, because of the null terminator + return "sysctlbyname() failed"; + + ffStrbufEnsureFree(result, (uint32_t) neededLength - 1); + + if (sysctl((int[]) {mib1, mib2}, 2, result->chars + result->length, &neededLength, NULL, 0) == 0) + result->length += (uint32_t) neededLength - 1; + + result->chars[result->length] = '\0'; + + return NULL; +} + +int ffSysctlGetInt(int mib1, int mib2, int defaultValue) +{ + int result; + size_t neededLength = sizeof(result); + if (sysctl((int[]) {mib1, mib2}, 2, &result, &neededLength, NULL, 0) != 0) + return defaultValue; + return result; +} + +int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue) +{ + int64_t result; + size_t neededLength = sizeof(result); + if(sysctl((int[]) {mib1, mib2}, 2, &result, &neededLength, NULL, 0) != 0) + return defaultValue; + return result; +} +#else const char* ffSysctlGetString(const char* propName, FFstrbuf* result) { size_t neededLength; @@ -35,6 +70,7 @@ int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue) return defaultValue; return result; } +#endif // OpenBSD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength) { diff --git a/src/common/sysctl.h b/src/common/sysctl.h index 2a210de862..1d5cc503a6 100644 --- a/src/common/sysctl.h +++ b/src/common/sysctl.h @@ -6,7 +6,13 @@ #include #include +#ifdef __OpenBSD__ +const char* ffSysctlGetString(int mib1, int mib2, FFstrbuf* result); +FF_C_NODISCARD int ffSysctlGetInt(int mib1, int mib2, int defaultValue); +FF_C_NODISCARD int64_t ffSysctlGetInt64(int mib1, int mib2, int64_t defaultValue); +#else const char* ffSysctlGetString(const char* propName, FFstrbuf* result); FF_C_NODISCARD int ffSysctlGetInt(const char* propName, int defaultValue); FF_C_NODISCARD int64_t ffSysctlGetInt64(const char* propName, int64_t defaultValue); +#endif FF_C_NODISCARD void* ffSysctlGetData(int* request, u_int requestLength, size_t* resultLength); diff --git a/src/detection/cpu/cpu_obsd.c b/src/detection/cpu/cpu_obsd.c new file mode 100644 index 0000000000..04d5501989 --- /dev/null +++ b/src/detection/cpu/cpu_obsd.c @@ -0,0 +1,19 @@ +#include "cpu.h" +#include "common/sysctl.h" + +const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) +{ + if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name)) + return "sysctl(hw.model) failed"; + + cpu->coresPhysical = (uint16_t) ffSysctlGetInt(CTL_HW, HW_NCPU, 1); + cpu->coresLogical = cpu->coresPhysical; + cpu->coresOnline = (uint16_t) ffSysctlGetInt(CTL_HW, HW_NCPUONLINE, cpu->coresLogical); + + ffCPUDetectSpeedByCpuid(cpu); + + cpu->frequencyBase = (uint32_t) ffSysctlGetInt(CTL_HW, HW_CPUSPEED, 0); + cpu->temperature = FF_CPU_TEMP_UNSET; // HW_SENSORS? + + return NULL; +} diff --git a/src/detection/cpuusage/cpuusage_bsd.c b/src/detection/cpuusage/cpuusage_bsd.c index af513878ff..a04c05b75d 100644 --- a/src/detection/cpuusage/cpuusage_bsd.c +++ b/src/detection/cpuusage/cpuusage_bsd.c @@ -6,18 +6,34 @@ #include #include +#ifdef __OpenBSD__ + #include +#endif + const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { size_t neededLength = 0; +#ifdef __OpenBSD__ + int ctls[] = {CTL_KERN, KERN_CPTIME}; + if (sysctl(ctls, 2, NULL, &neededLength, NULL, 0) != 0) + return "sysctl({CTL_KERN, KERN_CPTIME}, 2, NULL) failed"; +#else if(sysctlbyname("kern.cp_times", NULL, &neededLength, NULL, 0) != 0) return "sysctlbyname(kern.cp_times, NULL) failed"; +#endif uint32_t coreCount = (uint32_t) (neededLength / (CPUSTATES * sizeof(uint64_t))); assert(coreCount > 0); FF_AUTO_FREE uint64_t (*cpTimes)[CPUSTATES] = malloc(neededLength); + +#ifdef __OpenBSD__ + if (sysctl(ctls, 2, cpTimes, &neededLength, NULL, 0) != 0) + return "sysctl({CTL_KERN, KERN_CPTIME}, 2, NULL) failed"; +#else if(sysctlbyname("kern.cp_times", cpTimes, &neededLength, NULL, 0) != 0) return "sysctlbyname(kern.cp_times, cpTime) failed"; +#endif for (uint32_t i = 0; i < coreCount; ++i) { diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 81be9c83fc..4060669c33 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -92,6 +92,11 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk) }, &attrBuf, sizeof(attrBuf), 0) == 0) ffStrbufInitNS(&disk->name, attrBuf.nameRef.attr_length - 1 /* excluding '\0' */, attrBuf.nameSpace); } +#else +static void detectFsInfo(struct statfs* fs, FFDisk* disk) +{ + FF_UNUSED(fs, disk); +} #endif const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) @@ -143,6 +148,10 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) if(fs->f_flags & MNT_RDONLY) disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT; + #ifdef __OpenBSD__ + #define st_birthtimespec __st_birthtim + #endif + struct stat st; if(stat(fs->f_mntonname, &st) == 0 && st.st_birthtimespec.tv_sec > 0) disk->createTime = (uint64_t)((st.st_birthtimespec.tv_sec * 1000) + (st.st_birthtimespec.tv_nsec / 1000000)); diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 9d174b5ea7..b9d6c32485 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -12,6 +12,10 @@ #include #include #include +#elif defined(__OpenBSD__) + #include + #include + #include #elif defined(__sun) #include #endif @@ -252,7 +256,7 @@ static const char* getFromProcesses(FFDisplayServerResult* result) { uint32_t userId = getuid(); -#ifdef __FreeBSD__ +#if __FreeBSD__ int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_UID, (int) userId}; size_t length = 0; @@ -276,7 +280,26 @@ static const char* getFromProcesses(FFDisplayServerResult* result) if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) break; } -#elif defined(__sun) +#elif __OpenBSD__ + kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + int count = 0; + const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, userId, sizeof(struct kinfo_proc), &count); + if (proc) + { + for (int i = 0; i < count; ++i) + { + if(result->dePrettyName.length == 0) + applyPrettyNameIfDE(result, proc->p_comm); + + if(result->wmPrettyName.length == 0) + applyNameIfWM(result, proc->p_comm); + + if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) + break; + } + } + kvm_close(kd); +#elif __sun FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); if(procdir == NULL) return "opendir(\"/proc\") failed"; @@ -312,7 +335,7 @@ static const char* getFromProcesses(FFDisplayServerResult* result) break; } } -#else +#elif __linux__ FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); if(procdir == NULL) return "opendir(\"/proc\") failed"; diff --git a/src/detection/dns/dns_linux.c b/src/detection/dns/dns_linux.c index 84b2f91790..1179ea4a96 100644 --- a/src/detection/dns/dns_linux.c +++ b/src/detection/dns/dns_linux.c @@ -17,11 +17,14 @@ const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) { if (ffStrStartsWith(line, "nameserver")) { - const char* nameserver = line + strlen("nameserver"); + char* nameserver = line + strlen("nameserver"); while (*nameserver == ' ' || *nameserver == '\t') nameserver++; if (*nameserver == '\0') continue; + char* comment = strchr(nameserver, '#'); + if (comment) *comment = '\0'; + if ((ffStrContainsC(nameserver, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) || (ffStrContainsC(nameserver, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT))) continue; diff --git a/src/detection/host/host_obsd.c b/src/detection/host/host_obsd.c new file mode 100644 index 0000000000..960248ab3a --- /dev/null +++ b/src/detection/host/host_obsd.c @@ -0,0 +1,19 @@ +#include "host.h" +#include "common/sysctl.h" +#include "util/smbiosHelper.h" + +const char* ffDetectHost(FFHostResult* host) +{ + const char* error = NULL; + if ((error = ffSysctlGetString(CTL_HW, HW_PRODUCT, &host->name))) + return error; + ffCleanUpSmbiosValue(&host->name); + if (ffSysctlGetString(CTL_HW, HW_VENDOR, &host->vendor) == NULL) + ffCleanUpSmbiosValue(&host->vendor); + if (ffSysctlGetString(CTL_HW, HW_VERSION, &host->version) == NULL) + ffCleanUpSmbiosValue(&host->version); + if (ffSysctlGetString(CTL_HW, HW_SERIALNO, &host->serial) == NULL) + ffCleanUpSmbiosValue(&host->serial); + + return NULL; +} diff --git a/src/detection/loadavg/loadavg_bsd.c b/src/detection/loadavg/loadavg_bsd.c index 71c4304c13..3a0b6bca57 100644 --- a/src/detection/loadavg/loadavg_bsd.c +++ b/src/detection/loadavg/loadavg_bsd.c @@ -2,10 +2,12 @@ #include -#ifdef __FreeBSD__ +#if __FreeBSD__ || __OpenBSD__ #include #include - #include + #if __FreeBSD__ + #include + #endif #endif const char* ffDetectLoadavg(double result[3]) diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index 9dd8aaeacd..61f64c36b5 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -17,7 +17,7 @@ #include #endif -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #include #include #else @@ -143,7 +143,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } - #if defined(__FreeBSD__) || defined(__APPLE__) + #if __FreeBSD__ || __OpenBSD__ || __APPLE__ else if (ifa->ifa_addr->sa_family == AF_LINK) { if (!(options->showType & FF_LOCALIP_TYPE_MAC_BIT)) @@ -199,7 +199,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) ifr.ifr_data = (void*) &edata; if (ioctl(sockfd, SIOCETHTOOL, &ifr) == 0) iface->speed = (edata.speed_hi << 16) | edata.speed; // ethtool_cmd_speed is not available on Android - #elif __FreeBSD__ || __APPLE__ + #elif __FreeBSD__ || __APPLE__ || __OpenBSD__ struct ifmediareq ifmr = {}; strncpy(ifmr.ifm_name, iface->name.chars, IFNAMSIZ - 1); if (ioctl(sockfd, SIOCGIFMEDIA, &ifmr) == 0 && (IFM_TYPE(ifmr.ifm_active) & IFM_ETHER)) diff --git a/src/detection/memory/memory_obsd.c b/src/detection/memory/memory_obsd.c new file mode 100644 index 0000000000..c4119efb3f --- /dev/null +++ b/src/detection/memory/memory_obsd.c @@ -0,0 +1,20 @@ +#include "memory.h" +#include "common/sysctl.h" + +#include + +const char* ffDetectMemory(FFMemoryResult* ram) +{ + size_t length = sizeof(ram->bytesTotal); + if (sysctl((int[]){ CTL_HW, HW_PHYSMEM }, 2, &ram->bytesTotal, &length, NULL, 0) < 0) + return "Failed to read hw.physmem"; + + struct vmtotal vmtotal; + length = sizeof(vmtotal); + if (sysctl((int[]) {CTL_VM, VM_METER}, 2, &vmtotal, &length, NULL, 0) < 0) + return "sysctl(VM_METER) failed"; + + ram->bytesUsed = ram->bytesTotal - vmtotal.t_free * instance.state.platform.sysinfo.pageSize; + + return NULL; +} diff --git a/src/detection/opengl/opengl_linux.c b/src/detection/opengl/opengl_linux.c index 051107bece..05a72bf25c 100644 --- a/src/detection/opengl/opengl_linux.c +++ b/src/detection/opengl/opengl_linux.c @@ -14,7 +14,6 @@ void ffOpenGLHandleResult(FFOpenGLResult* result, __typeof__(&glGetString) ffglG #endif // FF_HAVE_GL - #ifdef FF_HAVE_GLX #include @@ -25,7 +24,7 @@ typedef struct GLXData FF_LIBRARY_SYMBOL(glXQueryVersion) FF_LIBRARY_SYMBOL(XOpenDisplay) FF_LIBRARY_SYMBOL(glXChooseVisual) - FF_LIBRARY_SYMBOL(XCreatePixmap); + FF_LIBRARY_SYMBOL(XCreatePixmap) FF_LIBRARY_SYMBOL(glXCreateGLXPixmap) FF_LIBRARY_SYMBOL(glXCreateContext) FF_LIBRARY_SYMBOL(glXMakeCurrent) @@ -120,7 +119,13 @@ static const char* detectByGlx(FFOpenGLResult* result) { GLXData data; - FF_LIBRARY_LOAD(glx, "dlopen glx failed", "libGLX" FF_LIBRARY_EXTENSION, 1); + FF_LIBRARY_LOAD(glx, "dlopen glx failed", + #if !__OpenBSD__ + "libGLX" + #else + "libGL" + #endif + FF_LIBRARY_EXTENSION, 1); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXGetProcAddress); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, glXQueryVersion); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(glx, data, XOpenDisplay); diff --git a/src/detection/os/os_obsd.c b/src/detection/os/os_obsd.c new file mode 100644 index 0000000000..10a0bfd812 --- /dev/null +++ b/src/detection/os/os_obsd.c @@ -0,0 +1,7 @@ +#include "os.h" + +void ffDetectOSImpl(FFOSResult* os) +{ + ffStrbufSetStatic(&os->name, "OpenBSD"); + ffStrbufSet(&os->version, &instance.state.platform.sysinfo.release); +} diff --git a/src/detection/packages/packages_bsd.c b/src/detection/packages/packages_bsd.c index 8212229270..511af569b1 100644 --- a/src/detection/packages/packages_bsd.c +++ b/src/detection/packages/packages_bsd.c @@ -18,7 +18,7 @@ static uint32_t getSQLite3Int(const char* dbPath, const char* query, const char* return num_elements; } -void ffDetectPackagesImpl(FFPackagesResult* result, FF_MAYBE_UNUSED FFPackagesOptions* options) +void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) { if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT)) { diff --git a/src/detection/packages/packages_obsd.c b/src/detection/packages/packages_obsd.c new file mode 100644 index 0000000000..c7fadcbdff --- /dev/null +++ b/src/detection/packages/packages_obsd.c @@ -0,0 +1,31 @@ +#include "packages.h" + +#include "common/io/io.h" + +static uint32_t getNumElementsImpl(const char* dirname, unsigned char type) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(dirname); + if(dirp == NULL) + return 0; + + uint32_t num_elements = 0; + + struct dirent *entry; + while((entry = readdir(dirp)) != NULL) { + if(entry->d_type == type) + ++num_elements; + } + + if(type == DT_DIR && num_elements >= 2) + num_elements -= 2; // accounting for . and .. + + return num_elements; +} + +void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) +{ + if (!(options->disabled & FF_PACKAGES_FLAG_PKG_BIT)) + { + result->pkg = getNumElementsImpl(FASTFETCH_TARGET_DIR_ROOT "/var/db/pkg", DT_DIR); + } +} diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c new file mode 100644 index 0000000000..75db1c4d09 --- /dev/null +++ b/src/detection/processes/processes_obsd.c @@ -0,0 +1,14 @@ +#include "processes.h" + +#include +#include +#include + +const char* ffDetectProcesses(uint32_t* result) +{ + kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL); + const void* ret = kvm_getprocs(kd, KERN_PROC_ALL, 0, 1, result); + kvm_close(kd); + if (!ret) return "kvm_getprocs() failed"; + return NULL; +} diff --git a/src/detection/swap/swap_obsd.c b/src/detection/swap/swap_obsd.c new file mode 100644 index 0000000000..b64900c9fa --- /dev/null +++ b/src/detection/swap/swap_obsd.c @@ -0,0 +1,30 @@ +#include "swap.h" +#include "util/mallocHelper.h" + +#include +#include +#include +#include + +const char* ffDetectSwap(FFSwapResult* swap) +{ + int nswap = swapctl(SWAP_NSWAP, 0, 0); + if (nswap < 0) return "swapctl(SWAP_NSWAP) failed"; + if (nswap == 0) NULL; + + struct swapent* swdev = malloc((uint32_t) nswap * sizeof(*swdev)); + + if (swapctl(SWAP_STATS, swdev, nswap) < 0) + return "swapctl(SWAP_STATS) failed"; + + for (int i = 0; i < nswap; i++) + { + if (swdev[i].se_flags & SWF_ENABLE) + { + swap->bytesUsed += (uint64_t) swdev[i].se_inuse * DEV_BSIZE; + swap->bytesTotal += (uint64_t) swdev[i].se_nblks * DEV_BSIZE; + } + } + + return NULL; +} diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 4280f20df2..45e4bb75f9 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -8,6 +8,8 @@ #include #ifdef __FreeBSD__ #include +#elif __OpenBSD__ + #define _PATH_LOCALBASE "/usr/local" #endif #ifdef _WIN32 @@ -119,6 +121,19 @@ static bool getShellVersionPwsh(FFstrbuf* exe, FFstrbuf* version) static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version) { +#if __OpenBSD__ + if(ffProcessAppendStdOut(version, (char* const[]) { + exe->chars, + "-c", + "echo $KSH_VERSION", + NULL + }) != NULL) + return false; + + // @(#)PD KSH v5.2.14 99/07/13.2 + ffStrbufSubstrAfterFirstC(version, 'v'); + ffStrbufSubstrBeforeFirstC(version, ' '); +#else if(ffProcessAppendStdErr(version, (char* const[]) { exe->chars, "--version", @@ -129,6 +144,7 @@ static bool getShellVersionKsh(FFstrbuf* exe, FFstrbuf* version) // version sh (AT&T Research) 93u+ 2012-08-01 ffStrbufSubstrAfterLastC(version, ')'); ffStrbufTrim(version, ' '); +#endif return true; } @@ -559,7 +575,7 @@ static bool getTerminalVersionZed(FFstrbuf* exe, FFstrbuf* version) #ifndef _WIN32 static bool getTerminalVersionKitty(FFstrbuf* exe, FFstrbuf* version) { - #if defined(__linux__) || defined(__FreeBSD__) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) char buffer[1024] = {}; if ( #ifdef __linux__ @@ -662,7 +678,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe #endif - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun) if(ffStrbufStartsWithIgnCaseS(processName, "gnome-terminal")) return getTerminalVersionGnome(exe, version); diff --git a/src/detection/users/users_nosupport.c b/src/detection/users/users_nosupport.c new file mode 100644 index 0000000000..d7893ba463 --- /dev/null +++ b/src/detection/users/users_nosupport.c @@ -0,0 +1,7 @@ +#include "fastfetch.h" +#include "users.h" + +const char* ffDetectUsers(FFUsersOptions* options, FFlist* users) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/version/version.c b/src/detection/version/version.c index fe87e2e778..ef0138d6ef 100644 --- a/src/detection/version/version.c +++ b/src/detection/version/version.c @@ -33,6 +33,8 @@ #define FF_SYSNAME "WIN32" #elif defined(__sun) #define FF_SYSNAME "SunOS" +#elif defined(__OpenBSD__) + #define FF_SYSNAME "OpenBSD" #else #define FF_SYSNAME "unknown" #endif diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 62f8291cad..dfdc3adf19 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3088,6 +3088,7 @@ static const FFlogo O[] = { FF_COLOR_FG_WHITE, FF_COLOR_FG_CYAN, FF_COLOR_FG_RED, + FF_COLOR_FG_LIGHT_BLACK, }, .colorKeys = FF_COLOR_FG_YELLOW, .colorTitle = FF_COLOR_FG_WHITE, diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 0ca38374f7..38e1b67fbf 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -492,7 +492,7 @@ void ffInitLocalIpOptions(FFLocalIpOptions* options) ffOptionInitModuleArg(&options->moduleArgs, "󰩟"); options->showType = FF_LOCALIP_TYPE_IPV4_BIT | FF_LOCALIP_TYPE_PREFIX_LEN_BIT - #ifndef __ANDROID__ + #if !__ANDROID__ /*Permission denied*/ && !__OpenBSD__ /*Report invalid argument for some reason*/ | FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT #endif ; diff --git a/src/modules/memory/memory.c b/src/modules/memory/memory.c index 1ce5ab8fd9..05f58a0e75 100644 --- a/src/modules/memory/memory.c +++ b/src/modules/memory/memory.c @@ -10,7 +10,7 @@ void ffPrintMemory(FFMemoryOptions* options) { - FFMemoryResult storage; + FFMemoryResult storage = {}; const char* error = ffDetectMemory(&storage); if(error) diff --git a/src/modules/os/os.c b/src/modules/os/os.c index c00676fced..8224b65c51 100644 --- a/src/modules/os/os.c +++ b/src/modules/os/os.c @@ -230,6 +230,8 @@ void ffInitOSOptions(FFOSOptions* options) "" #elif __sun "" + #elif __OpenBSD__ + "" #else "?" #endif diff --git a/src/modules/swap/swap.c b/src/modules/swap/swap.c index 6666a9c6ee..210351631c 100644 --- a/src/modules/swap/swap.c +++ b/src/modules/swap/swap.c @@ -10,7 +10,7 @@ void ffPrintSwap(FFSwapOptions* options) { - FFSwapResult storage; + FFSwapResult storage = {}; const char* error = ffDetectSwap(&storage); if(error) diff --git a/src/options/general.c b/src/options/general.c index abb8d10546..a29c21960a 100644 --- a/src/options/general.c +++ b/src/options/general.c @@ -39,7 +39,7 @@ const char* ffOptionsParseGeneralJsonConfig(FFOptionsGeneral* options, yyjson_va else if (ffStrEqualsIgnCase(key, "detectVersion")) options->detectVersion = yyjson_get_bool(val); - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) else if (ffStrEqualsIgnCase(key, "escapeBedrock")) options->escapeBedrock = yyjson_get_bool(val); else if (ffStrEqualsIgnCase(key, "playerName")) @@ -84,7 +84,7 @@ bool ffOptionsParseGeneralCommandLine(FFOptionsGeneral* options, const char* key else if(ffStrEqualsIgnCase(key, "--detect-version")) options->detectVersion = ffOptionParseBoolean(value); - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) else if(ffStrEqualsIgnCase(key, "--escape-bedrock")) options->escapeBedrock = ffOptionParseBoolean(value); else if(ffStrEqualsIgnCase(key, "--player-name")) diff --git a/src/options/general.h b/src/options/general.h index 8b14283d81..0a85df7672 100644 --- a/src/options/general.h +++ b/src/options/general.h @@ -16,7 +16,7 @@ typedef struct FFOptionsGeneral bool detectVersion; // Module options that cannot be put in module option structure - #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) + #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) || defined(__OpenBSD__) FFstrbuf playerName; bool escapeBedrock; FFDsForceDrmType dsForceDrm; diff --git a/src/util/binary_linux.c b/src/util/binary_linux.c index e5c7f5c982..b9c521ca9c 100644 --- a/src/util/binary_linux.c +++ b/src/util/binary_linux.c @@ -1,6 +1,6 @@ #include "binary.h" -#if defined(FF_HAVE_ELF) || defined(__sun) || defined(__FreeBSD__) +#if defined(FF_HAVE_ELF) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) #include "common/io/io.h" #include "common/library.h" diff --git a/src/util/platform/FFPlatform_unix.c b/src/util/platform/FFPlatform_unix.c index b442eed54f..9eaeae38a5 100644 --- a/src/util/platform/FFPlatform_unix.c +++ b/src/util/platform/FFPlatform_unix.c @@ -12,7 +12,7 @@ #ifdef __APPLE__ #include #include -#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__) || defined(__OpenBSD__) #include #endif @@ -34,7 +34,9 @@ static void getExePath(FFPlatform* platform) exePathLen = 0; else exePathLen--; // remove terminating NUL - #else + #elif defined(__OpenBSD__) + size_t exePathLen = 0; + #elif defined(__sun) ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1); exePath[exePathLen] = '\0'; #endif @@ -177,7 +179,7 @@ static void getSysinfo(FFPlatformSysinfo* info, const struct utsname* uts) ffStrbufAppendS(&info->architecture, uts->machine); ffStrbufInit(&info->displayVersion); - #if defined(__FreeBSD__) || defined(__APPLE__) + #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) size_t length = sizeof(info->pageSize); sysctl((int[]){ CTL_HW, HW_PAGESIZE }, 2, &info->pageSize, &length, NULL, 0); #else From 729085e05443ac7f9a1733a2f76b2f7d0f3c2745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 4 Oct 2024 18:01:02 +0800 Subject: [PATCH 29/48] CI: add OpenBSD --- .github/workflows/ci.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1745a789d3..73d7a20c77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -438,6 +438,42 @@ jobs: name: fastfetch-freebsd-amd64 path: ./fastfetch-*.* + openbsd-amd64: + name: OpenBSD-amd64 + runs-on: ubuntu-latest + permissions: + security-events: write + contents: read + steps: + - name: checkout repository + uses: actions/checkout@v4 + + - name: run VM + uses: cross-platform-actions/action@master + with: + operating_system: openbsd + architecture: x86-64 + cpu_count: 4 + shell: bash + version: '7.5' + run: | + uname -a + sudo pkg_add -r cmake git pkgconf wayland vulkan-headers vulkan-loader glib2 dconf dbus sqlite3 xfconf imagemagick chafa pulseaudio + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + cmake --build . --target package --verbose -j4 + ./fastfetch --list-features + time ./fastfetch -c presets/ci.jsonc --stat false + time ./fastfetch -c presets/ci.jsonc --format json + time ./flashfetch + ldd fastfetch + ctest + + - name: upload artifacts + uses: actions/upload-artifact@v4 + with: + name: fastfetch-openbsd-amd64 + path: ./fastfetch-*.* + windows-amd64: name: Windows-amd64 runs-on: windows-latest @@ -586,6 +622,7 @@ jobs: - musl-aarch64 - macos-universal - freebsd-amd64 + - openbsd-amd64 - sunos-amd64 - windows-amd64 - windows-i686 From 84fc5b4503972909e6b053a827773c1aa1fe35b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 4 Oct 2024 19:58:55 +0800 Subject: [PATCH 30/48] TPM (Windows): corrently report `TPM device is not found` Fix #1314 --- src/detection/tpm/tpm_windows.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c index a63a93f5f2..7a77eb3a78 100644 --- a/src/detection/tpm/tpm_windows.c +++ b/src/detection/tpm/tpm_windows.c @@ -3,10 +3,9 @@ // #include -#define TBS_SUCCESS 0u -#define TBS_E_INTERNAL_ERROR 0x80284001u -#define TBS_E_INVALID_CONTEXT 0x80284004u typedef UINT32 TBS_RESULT; +#define TBS_SUCCESS 0u +#define TBS_E_TPM_NOT_FOUND ((TBS_RESULT) 0x8028400Fu) #define TPM_VERSION_UNKNOWN 0 #define TPM_VERSION_12 1 @@ -42,7 +41,7 @@ const char* ffDetectTPM(FFTPMResult* result) TPM_DEVICE_INFO deviceInfo = {}; TBS_RESULT code = ffTbsi_GetDeviceInfo(sizeof(deviceInfo), &deviceInfo); if (code != TBS_SUCCESS) - return code == (TBS_RESULT) TBS_E_INVALID_CONTEXT ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; + return code == TBS_E_TPM_NOT_FOUND ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; switch (deviceInfo.tpmVersion) { From 716bfe7cc1a3e409a98e68a0337581ff8cab0447 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 4 Oct 2024 19:15:04 +0800 Subject: [PATCH 31/48] Global: use glob(3) if wordexp(3) is not available --- CMakeLists.txt | 4 ++++ src/common/io/io_unix.c | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f8ab5015c3..4ee1a67a72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1385,6 +1385,10 @@ if(NOT WIN32) if(HAVE_WORDEXP) target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WORDEXP=1) endif() + CHECK_INCLUDE_FILE("glob.h" HAVE_GLOB) + if(HAVE_GLOB) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_GLOB=1) + endif() if(ENABLE_THREADS AND CMAKE_USE_PTHREADS_INIT) CHECK_INCLUDE_FILE("pthread_np.h" HAVE_PTHREAD_NP) if(HAVE_PTHREAD_NP) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 957789c693..f08e9140af 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -14,8 +14,11 @@ #if FF_HAVE_WORDEXP #include +#elif FF_HAVE_GLOB + #warning " is not available, use instead + #include #else - #warning " not available" + #warning "Neither nor is available" #endif static void createSubfolders(const char* fileName) @@ -121,7 +124,7 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o #if FF_HAVE_WORDEXP // https://github.com/termux/termux-packages/pull/7056 wordexp_t exp; - if(wordexp(in, &exp, 0) != 0) + if (wordexp(in, &exp, 0) != 0) return false; if (exp.we_wordc == 1) @@ -132,6 +135,20 @@ bool ffPathExpandEnv(FF_MAYBE_UNUSED const char* in, FF_MAYBE_UNUSED FFstrbuf* o wordfree(&exp); + #elif FF_HAVE_GLOB + + glob_t gb; + if (glob(in, GLOB_NOSORT | GLOB_TILDE, NULL, &gb) != 0) + return false; + + if (gb.gl_matchc == 1) + { + result = true; + ffStrbufSetS(out, gb.gl_pathv[0]); + } + + globfree(&gb); + #endif return result; From 40ab735e6be76cc89e64f74c4f1197c71e8c5981 Mon Sep 17 00:00:00 2001 From: apocelipes Date: Sat, 5 Oct 2024 09:49:27 +0800 Subject: [PATCH 32/48] LocalIp: support get interface flags (#1315) --- .codespellrc | 2 +- completions/fastfetch.bash | 1 + doc/json_schema.json | 5 +++ src/data/help.json | 9 ++++ src/detection/localip/localip.h | 20 +++++++++ src/detection/localip/localip_linux.c | 55 +++++++++++++++++++++++++ src/detection/localip/localip_windows.c | 18 ++++++++ src/modules/localip/localip.c | 34 ++++++++++++++- src/modules/localip/option.h | 1 + 9 files changed, 143 insertions(+), 2 deletions(-) diff --git a/.codespellrc b/.codespellrc index 087150a6d5..9e972389e7 100644 --- a/.codespellrc +++ b/.codespellrc @@ -2,4 +2,4 @@ check-filenames = builtin = clear,rare,usage,informal skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii -ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,sur,doas,conexant +ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant diff --git a/completions/fastfetch.bash b/completions/fastfetch.bash index 76e43859a7..abd7fffb77 100644 --- a/completions/fastfetch.bash +++ b/completions/fastfetch.bash @@ -183,6 +183,7 @@ __fastfetch_completion() "--display-precise-refresh-rate" "--localip-show-ipv4" "--localip-show-ipv6" + "--localip-show-flags" "--localip-show-loop" "--localip-name-prefix" "--localip-compact-type" diff --git a/doc/json_schema.json b/doc/json_schema.json index 6a38e48ce7..c9bf608317 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1703,6 +1703,11 @@ "type": "boolean", "default": false }, + "showFlags": { + "description": "Show the interface's flags", + "type": "boolean", + "default": false + }, "compact": { "description": "Show all IPs in one line", "type": "boolean", diff --git a/src/data/help.json b/src/data/help.json index 2d99a0b3aa..3a326f350a 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1231,6 +1231,15 @@ "default": false } }, + { + "long": "localip-show-flags", + "desc": "Show net interface flags in local ip module", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "localip-compact", "desc": "Show all IPs in one line", diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index 859d5340fa..7f2304bdf1 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -8,9 +8,29 @@ typedef struct FFLocalIpResult FFstrbuf ipv4; FFstrbuf ipv6; FFstrbuf mac; + FFstrbuf flags; int32_t mtu; int32_t speed; bool defaultRoute; } FFLocalIpResult; +typedef struct NIFlag +{ + int flag; + const char *name; +} NIFlag; + +static inline void writeNIFlagsToStrBuf(FFstrbuf *buf, int flag, const NIFlag names[]) +{ + for (const NIFlag *nf = names; nf->name != NULL && flag != 0; ++nf) + { + if (flag & nf->flag) { + if (nf - names != 0) + ffStrbufAppendC(buf, ','); + ffStrbufAppendS(buf, nf->name); + flag &= ~nf->flag; + } + } +} + 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 61f64c36b5..b41d4eed9c 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -15,6 +15,7 @@ #ifdef __linux__ #include #include +#include #endif #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__) @@ -27,6 +28,47 @@ #include #endif +static const NIFlag niFlags[] = { + { IFF_UP, "UP" }, + { IFF_BROADCAST, "BROADCAST" }, + { IFF_DEBUG, "DEBUG" }, + { IFF_LOOPBACK, "LOOPBACK" }, + { IFF_POINTOPOINT, "POINTOPOINT" }, + { IFF_RUNNING, "RUNNING" }, + { IFF_NOARP, "NOARP" }, + { IFF_PROMISC, "PROMISC" }, + { IFF_ALLMULTI, "ALLMULTI" }, + { IFF_MULTICAST, "MULTICAST" }, +#if defined(__linux__) || defined(__APPLE__) || defined(__sun) + { IFF_NOTRAILERS, "NOTRAILERS" }, +#endif +#ifdef __linux__ + { IFF_MASTER, "MASTER" }, + { IFF_SLAVE, "SLAVE" }, + { IFF_PORTSEL, "PORTSEL" }, + { IFF_AUTOMEDIA, "AUTOMEDIA" }, + { IFF_DYNAMIC, "DYNAMIC" }, + { IFF_LOWER_UP, "LOWER_UP" }, + { IFF_DORMANT, "DORMANT" }, + { IFF_ECHO, "ECHO" }, +#endif +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) + { IFF_OACTIVE, "OACTIVE" }, + { IFF_SIMPLEX, "SIMPLEX" }, + { IFF_LINK0, "LINK0" }, + { IFF_LINK1, "LINK1" }, + { IFF_LINK2, "LINK2" }, +#endif +#if defined(__FreeBSD__) || defined(__APPLE__) + { IFF_ALTPHYS, "ALTPHYS" }, +#endif +#ifdef __FreeBSD__ + { IFF_CANTCONFIG, "CANTCONFIG" }, +#endif + // sentinel + { 0, NULL } +}; + static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, bool firstOnly) { FFLocalIpResult* ip = NULL; @@ -44,6 +86,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, ffStrbufInit(&ip->ipv4); ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); + ffStrbufInit(&ip->flags); ip->defaultRoute = defaultRoute; ip->mtu = -1; ip->speed = -1; @@ -96,6 +139,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (options->namePrefix.length && strncmp(ifa->ifa_name, options->namePrefix.chars, options->namePrefix.length) != 0) continue; + bool newIP = false; if (ifa->ifa_addr->sa_family == AF_INET) { if (!(options->showType & FF_LOCALIP_TYPE_IPV4_BIT)) @@ -117,6 +161,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); + newIP = true; } else if (ifa->ifa_addr->sa_family == AF_INET6) { @@ -142,6 +187,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); + newIP = true; } #if __FreeBSD__ || __OpenBSD__ || __APPLE__ else if (ifa->ifa_addr->sa_family == AF_LINK) @@ -154,6 +200,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) 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, isDefaultRoute, false); + newIP = true; } #else else if (ifa->ifa_addr->sa_family == AF_PACKET) @@ -166,8 +213,16 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) 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, isDefaultRoute, false); + newIP = true; } #endif + + if (newIP) + { + FFLocalIpResult* result = FF_LIST_GET(FFLocalIpResult, *results, results->length - 1); + if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) + writeNIFlagsToStrBuf(&result->flags, (int)ifa->ifa_flags, niFlags); + } } if (ifAddrStruct) freeifaddrs(ifAddrStruct); diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index f26bb35b84..e6750bac94 100644 --- a/src/detection/localip/localip_windows.c +++ b/src/detection/localip/localip_windows.c @@ -6,6 +6,21 @@ #include "util/windows/unicode.h" #include "localip.h" +static const NIFlag niFlags[] = { + { IP_ADAPTER_DDNS_ENABLED, "DDNS_ENABLED" }, + { IP_ADAPTER_REGISTER_ADAPTER_SUFFIX, "REGISTER_ADAPTER_SUFFIX" }, + { IP_ADAPTER_DHCP_ENABLED, "DHCP_ENABLED" }, + { IP_ADAPTER_RECEIVE_ONLY, "RECEIVE_ONLY" }, + { IP_ADAPTER_NO_MULTICAST, "NO_MULTICAST" }, + { IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG, "IPV6_OTHER_STATEFUL_CONFIG" }, + { IP_ADAPTER_NETBIOS_OVER_TCPIP_ENABLED, "NETBIOS_OVER_TCPIP_ENABLED" }, + { IP_ADAPTER_IPV4_ENABLED, "IPV4_ENABLED" }, + { IP_ADAPTER_IPV6_ENABLED, "IPV6_ENABLED" }, + { IP_ADAPTER_IPV6_MANAGE_ADDRESS_CONFIG, "IPV6_MANAGE_ADDRESS_CONFIG" }, + // sentinel + { 0, NULL } +}; + static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool newIp, bool defaultRoute) { FFLocalIpResult* ip = NULL; @@ -17,6 +32,7 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, ffStrbufInit(&ip->ipv4); ffStrbufInit(&ip->ipv6); ffStrbufInit(&ip->mac); + ffStrbufInit(&ip->flags); ip->defaultRoute = defaultRoute; ip->speed = -1; ip->mtu = -1; @@ -157,6 +173,8 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) result->speed = (int32_t) (adapter->ReceiveLinkSpeed / 1000); if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) result->mtu = (int32_t) adapter->Mtu; + if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) + writeNIFlagsToStrBuf(&result->flags, (int)adapter->Flags, niFlags); } } diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 38e1b67fbf..7343f716dc 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 7 +#define FF_LOCALIP_NUM_FORMAT_ARGS 8 #pragma GCC diagnostic ignored "-Wsign-conversion" static int sortIps(const FFLocalIpResult* left, const FFLocalIpResult* right) @@ -77,6 +77,12 @@ static void printIp(FFLocalIpResult* ip, bool markDefaultRoute) putchar(']'); flag = true; } + if (ip->flags.length) { + if (flag) fputs(" <", stdout); + ffStrbufWriteTo(&ip->flags, stdout); + putchar('>'); + flag = true; + } if (markDefaultRoute && flag && ip->defaultRoute) fputs(" *", stdout); } @@ -151,6 +157,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) FF_FORMAT_ARG(ip->defaultRoute, "is-default-route"), FF_FORMAT_ARG(ip->mtu, "mtu"), FF_FORMAT_ARG(speedStr, "speed"), + FF_FORMAT_ARG(ip->flags, "flags"), })); } ++index; @@ -163,6 +170,7 @@ void ffPrintLocalIp(FFLocalIpOptions* options) ffStrbufDestroy(&ip->ipv4); ffStrbufDestroy(&ip->ipv6); ffStrbufDestroy(&ip->mac); + ffStrbufDestroy(&ip->flags); } } @@ -236,6 +244,15 @@ bool ffParseLocalIpCommandOptions(FFLocalIpOptions* options, const char* key, co return true; } + if (ffStrEqualsIgnCase(subKey, "show-flags")) + { + if (ffOptionParseBoolean(value)) + options->showType |= FF_LOCALIP_TYPE_FLAGS_BIT; + else + options->showType &= ~FF_LOCALIP_TYPE_FLAGS_BIT; + return true; + } + if(ffStrEqualsIgnCase(subKey, "compact")) { if (ffOptionParseBoolean(value)) @@ -348,6 +365,15 @@ void ffParseLocalIpJsonObject(FFLocalIpOptions* options, yyjson_val* module) continue; } + if (ffStrEqualsIgnCase(key, "showFlags")) + { + if (yyjson_get_bool(val)) + options->showType |= FF_LOCALIP_TYPE_FLAGS_BIT; + else + options->showType &= ~FF_LOCALIP_TYPE_FLAGS_BIT; + continue; + } + if (ffStrEqualsIgnCase(key, "compact")) { if (yyjson_get_bool(val)) @@ -415,6 +441,9 @@ void ffGenerateLocalIpJsonConfig(FFLocalIpOptions* options, yyjson_mut_doc* doc, if (options->showType & FF_LOCALIP_TYPE_SPEED_BIT) yyjson_mut_obj_add_bool(doc, module, "showSpeed", true); + if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) + yyjson_mut_obj_add_bool(doc, module, "showFlags", true); + if (options->showType & FF_LOCALIP_TYPE_COMPACT_BIT) yyjson_mut_obj_add_bool(doc, module, "compact", true); @@ -452,6 +481,7 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs yyjson_mut_obj_add_strbuf(doc, obj, "name", &ip->name); yyjson_mut_obj_add_int(doc, obj, "mtu", ip->mtu); yyjson_mut_obj_add_int(doc, obj, "speed", ip->speed); + yyjson_mut_obj_add_strbuf(doc, obj, "flags", &ip->flags); } FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) @@ -460,6 +490,7 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs ffStrbufDestroy(&ip->ipv4); ffStrbufDestroy(&ip->ipv6); ffStrbufDestroy(&ip->mac); + ffStrbufDestroy(&ip->flags); } } @@ -473,6 +504,7 @@ void ffPrintLocalIpHelpFormat(void) "Is default route - is-default-route", "MTU size in bytes - mtu", "Link speed (formatted) - speed", + "Interface flags - flags", })); } diff --git a/src/modules/localip/option.h b/src/modules/localip/option.h index 1a01611528..511ec729db 100644 --- a/src/modules/localip/option.h +++ b/src/modules/localip/option.h @@ -14,6 +14,7 @@ typedef enum FFLocalIpType FF_LOCALIP_TYPE_PREFIX_LEN_BIT = 1 << 4, FF_LOCALIP_TYPE_MTU_BIT = 1 << 5, FF_LOCALIP_TYPE_SPEED_BIT = 1 << 6, + FF_LOCALIP_TYPE_FLAGS_BIT = 1 << 7, FF_LOCALIP_TYPE_COMPACT_BIT = 1 << 10, FF_LOCALIP_TYPE_DEFAULT_ROUTE_ONLY_BIT = 1 << 11, From 320283a538a04a9e445357ad74e3235fcf61e58b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 5 Oct 2024 10:15:53 +0800 Subject: [PATCH 33/48] LocalIP: fix bug that flags are appended multiple times --- src/detection/localip/localip.h | 15 +++++++------ src/detection/localip/localip_linux.c | 30 +++++++++---------------- src/detection/localip/localip_windows.c | 6 ++--- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/detection/localip/localip.h b/src/detection/localip/localip.h index 7f2304bdf1..11ac50e558 100644 --- a/src/detection/localip/localip.h +++ b/src/detection/localip/localip.h @@ -14,18 +14,19 @@ typedef struct FFLocalIpResult bool defaultRoute; } FFLocalIpResult; -typedef struct NIFlag +typedef struct FFLocalIpNIFlag { - int flag; + uint32_t flag; const char *name; -} NIFlag; +} FFLocalIpNIFlag; -static inline void writeNIFlagsToStrBuf(FFstrbuf *buf, int flag, const NIFlag names[]) +static inline void ffLocalIpFillNIFlags(FFstrbuf *buf, uint32_t flag, const FFLocalIpNIFlag names[]) { - for (const NIFlag *nf = names; nf->name != NULL && flag != 0; ++nf) + for (const FFLocalIpNIFlag *nf = names; flag && nf->name; ++nf) { - if (flag & nf->flag) { - if (nf - names != 0) + if (flag & nf->flag) + { + if (buf->length > 0) ffStrbufAppendC(buf, ','); ffStrbufAppendS(buf, nf->name); flag &= ~nf->flag; diff --git a/src/detection/localip/localip_linux.c b/src/detection/localip/localip_linux.c index b41d4eed9c..243091ddfb 100644 --- a/src/detection/localip/localip_linux.c +++ b/src/detection/localip/localip_linux.c @@ -28,7 +28,7 @@ #include #endif -static const NIFlag niFlags[] = { +static const FFLocalIpNIFlag niFlagOptions[] = { { IFF_UP, "UP" }, { IFF_BROADCAST, "BROADCAST" }, { IFF_DEBUG, "DEBUG" }, @@ -66,10 +66,10 @@ static const NIFlag niFlags[] = { { IFF_CANTCONFIG, "CANTCONFIG" }, #endif // sentinel - { 0, NULL } + {}, }; -static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, bool firstOnly) +static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool defaultRoute, uint32_t flags, bool firstOnly) { FFLocalIpResult* ip = NULL; @@ -90,6 +90,8 @@ static void addNewIp(FFlist* list, const char* name, const char* addr, int type, ip->defaultRoute = defaultRoute; ip->mtu = -1; ip->speed = -1; + + ffLocalIpFillNIFlags(&ip->flags, flags, niFlagOptions); } switch (type) @@ -139,7 +141,8 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (options->namePrefix.length && strncmp(ifa->ifa_name, options->namePrefix.chars, options->namePrefix.length) != 0) continue; - bool newIP = false; + uint32_t flags = options->showType & FF_LOCALIP_TYPE_FLAGS_BIT ? ifa->ifa_flags : 0; + if (ifa->ifa_addr->sa_family == AF_INET) { if (!(options->showType & FF_LOCALIP_TYPE_IPV4_BIT)) @@ -160,8 +163,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); - newIP = true; + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } else if (ifa->ifa_addr->sa_family == AF_INET6) { @@ -186,8 +188,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) } } - addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); - newIP = true; + addNewIp(results, ifa->ifa_name, addressBuffer, AF_INET6, isDefaultRoute, flags, !(options->showType & FF_LOCALIP_TYPE_ALL_IPS_BIT)); } #if __FreeBSD__ || __OpenBSD__ || __APPLE__ else if (ifa->ifa_addr->sa_family == AF_LINK) @@ -199,8 +200,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, isDefaultRoute, false); - newIP = true; + addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); } #else else if (ifa->ifa_addr->sa_family == AF_PACKET) @@ -212,17 +212,9 @@ 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, isDefaultRoute, false); - newIP = true; + addNewIp(results, ifa->ifa_name, addressBuffer, -1, isDefaultRoute, flags, false); } #endif - - if (newIP) - { - FFLocalIpResult* result = FF_LIST_GET(FFLocalIpResult, *results, results->length - 1); - if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) - writeNIFlagsToStrBuf(&result->flags, (int)ifa->ifa_flags, niFlags); - } } if (ifAddrStruct) freeifaddrs(ifAddrStruct); diff --git a/src/detection/localip/localip_windows.c b/src/detection/localip/localip_windows.c index e6750bac94..00fee43ed0 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 const NIFlag niFlags[] = { +static const FFLocalIpNIFlag niFlagOptions[] = { { IP_ADAPTER_DDNS_ENABLED, "DDNS_ENABLED" }, { IP_ADAPTER_REGISTER_ADAPTER_SUFFIX, "REGISTER_ADAPTER_SUFFIX" }, { IP_ADAPTER_DHCP_ENABLED, "DHCP_ENABLED" }, @@ -18,7 +18,7 @@ static const NIFlag niFlags[] = { { IP_ADAPTER_IPV6_ENABLED, "IPV6_ENABLED" }, { IP_ADAPTER_IPV6_MANAGE_ADDRESS_CONFIG, "IPV6_MANAGE_ADDRESS_CONFIG" }, // sentinel - { 0, NULL } + {}, }; static void addNewIp(FFlist* list, const char* name, const char* addr, int type, bool newIp, bool defaultRoute) @@ -174,7 +174,7 @@ const char* ffDetectLocalIps(const FFLocalIpOptions* options, FFlist* results) if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) result->mtu = (int32_t) adapter->Mtu; if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) - writeNIFlagsToStrBuf(&result->flags, (int)adapter->Flags, niFlags); + ffLocalIpFillNIFlags(&result->flags, adapter->Flags, niFlagOptions); } } From 41a1b3a9d5cc266cdeac4058bfb5a621ee478d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 10:33:14 +0800 Subject: [PATCH 34/48] CI: test `showFlags` --- presets/all.jsonc | 4 +++- presets/ci.jsonc | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/presets/all.jsonc b/presets/all.jsonc index 9b27615e04..8e4da85d62 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -72,7 +72,9 @@ "showIpv6": true, "showMac": true, "showSpeed": true, - "showMtu": true + "showMtu": true, + "showLoop": true, + "showFlags": true }, "dns", "wifi", diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 3027010d8f..6431509c28 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -74,7 +74,9 @@ "showIpv6": true, "showMac": true, "showSpeed": true, - "showMtu": true + "showMtu": true, + "showLoop": true, + "showFlags": true }, "dns", "wifi", From 67964363e827608670b7a4bc09a4e7e2f86a9c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 10:41:36 +0800 Subject: [PATCH 35/48] Doc: update changelog [ci skip] --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a66095c62f..f3d4f6ca1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,11 +11,14 @@ Features: * Detect SOC name, instead of displaying components used in the SOC, if available (CPU, Linux) * Add option `--brightness-compact` to display multiple brightness values in one line (Brightness) * Add `day-pretty` (#1305, DateTime) +* Add basic, highly experimental support of OpenBSD (OpenBSD) +* Support network interface adatper flag detection (LocalIP) Bugfixes: * Remove trailing newline in GPU name for Raspberry pi (#1303, GPU, Linux) * Fix a possible buffer overflow (GPU, Linux) * Fix CPU temp incorrectly reported as 0 celsius (#1308, CPU, Linux) +* Corrently report `TPM device is not found` error (#1314, TPM, Windows) # 2.26.1 From b34283eaf0eebdf072591c6e67fa1572a89a904a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 11:33:57 +0800 Subject: [PATCH 36/48] Chore: fix a warning of warning --- src/common/io/io_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index f08e9140af..c29b43a9f8 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -15,7 +15,7 @@ #if FF_HAVE_WORDEXP #include #elif FF_HAVE_GLOB - #warning " is not available, use instead + #warning " is not available, use instead" #include #else #warning "Neither nor is available" From d4c8a4c9fd7a1f36662b5839a308b05c2ab7b32d Mon Sep 17 00:00:00 2001 From: XeroArch Date: Fri, 4 Oct 2024 23:42:27 -0400 Subject: [PATCH 37/48] Logo (Builtin): add XeroArch Ascii logo (#1312) * putting xeroarch logo in askii * updating logo * updating * updating * uploading xeroarch ascii logo * upgrading fetch ascii logo * fixing a very small issue * removing unecessary line * removing trailing lines --- src/logo/ascii/xeroarch.txt | 19 +++++++++++++++++++ src/logo/builtin.c | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/logo/ascii/xeroarch.txt diff --git a/src/logo/ascii/xeroarch.txt b/src/logo/ascii/xeroarch.txt new file mode 100644 index 0000000000..1f094ea061 --- /dev/null +++ b/src/logo/ascii/xeroarch.txt @@ -0,0 +1,19 @@ +${c1} ████ +${c1} ███${c2}▓▓${c1}███ +${c1} ███${c2}▓▓▓▓${c1}███ +${c1} ███${c2}▓▓▓▓▓▓${c1}███ +${c1} ███${c2}▓▓▓▓▓▓▓▓${c1}███ +${c1} ███${c2}▓▓▓▓▓▓▓▓▓▓${c1}███ +${c1} ███${c2}▓▓▓▓▓▓▓▓▓▓▓▓${c1}███ +${c1} ███${c2}▓▓▓▓▓▓${c1}██${c2}▓▓▓▓▓▓${c1}▓██ +${c1} ███${c2}▓▓▓▓▓▓${c1}████${c2}▓▓▓▓▓▓${c1}▓██ +${c1} ██▓${c2}▓▓▓▓▓▓${c1}█▓${c3}▓▓${c1}▓█${c2}▓▓▓▓▓▓${c1}▓██ +${c1} █████▓▒▒▒██${c3}▓${c4}▒▒${c3}▓${c1}██▒▒▒▓█████ +${c1} ███${c6}▓▓▓▓▓${c1}████${c3}▓${c4}▒▒▒▒${c3}▓${c1}▓███${c6}▓▓▓▓▓${c1}███ +${c1} ███${c6}▓▓▓▓▓▓▓▓▓${c1}███▓▓███${c6}▓▓▓▓▓▓▓▓▓${c1}███ +${c1} ███${c6}▓▓▓▓▓▓▓${c2}▓▓${c6}▓▓▓▓▓${c1}█${c6}▓▓▓▓▓▓▓▓▓▓▓▓▓${c1}███ +${c1} ███${c6}▓▓▓▓▓▓${c2}▓▓${c5}▒▒${c6}${c2}▓▓${c6}▓▓▓${c1}▓${c6}▓▓▓▓${c4}()${c6}▓▓▓▓▓▓▓▓${c1}███ +${c1} ███${c6}▓▓▓▓▓${c2}▓▓${c5}▒▒▒▒▒▒${c6}${c2}▓▓${c6}▓${c1}▓${c6}▓▓${c3}()${c6}▓▓${c3}()${c6}▓▓▓▓▓▓▓${c1}███ +${c1}███${c6}▓▓▓▓▓▓▓▓${c2}▓▓${c5}▒▒${c6}${c2}▓▓${c6}▓▓▓${c1}▓${c6}▓▓▓▓${c4}()${c6}▓▓▓▓▓▓▓▓▓▓${c1}███ +${c1}██${c6}▓▓▓▓▓▓▓▓▓▓▓${c2}▓▓${c6}▓▓▓▓▓${c1}▓${c6}▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓${c1}██ +${c1}████████████████████████████████████████ \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index dfdc3adf19..2597a8993c 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -4786,12 +4786,25 @@ static const FFlogo X[] = { FF_COLOR_FG_CYAN, }, }, + //XeroArch + { + .names = {"XeroArch"}, + .lines = FASTFETCH_DATATEXT_LOGO_XEROARCH, + .colors = { + FF_COLOR_FG_256 "16", + FF_COLOR_FG_256 "14", + FF_COLOR_FG_256 "50", + FF_COLOR_FG_256 "93", + FF_COLOR_FG_256 "46", + FF_COLOR_FG_256 "15", + } + }, //Xray_OS { .names = {"Xray_OS"}, .lines = FASTFETCH_DATATEXT_LOGO_XRAY_OS, .colors = { - FF_COLOR_FG_256 "15", + FF_COLOR_FG_256 "16", FF_COLOR_FG_256 "14", FF_COLOR_FG_256 "16", } From 7fac54e7b8e00c490495b752bae0263983528cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 11:52:59 +0800 Subject: [PATCH 38/48] Doc: update changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3d4f6ca1f..3f2ab5f23a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,13 +12,18 @@ Features: * Add option `--brightness-compact` to display multiple brightness values in one line (Brightness) * Add `day-pretty` (#1305, DateTime) * Add basic, highly experimental support of OpenBSD (OpenBSD) -* Support network interface adatper flag detection (LocalIP) +* Support network interface adapter flag detection (#1315, LocalIP) Bugfixes: * Remove trailing newline in GPU name for Raspberry pi (#1303, GPU, Linux) * Fix a possible buffer overflow (GPU, Linux) * Fix CPU temp incorrectly reported as 0 celsius (#1308, CPU, Linux) * Corrently report `TPM device is not found` error (#1314, TPM, Windows) +* Fix errors when triggering shell completion with python3 uninstalled (#1310) + * To package managers: as shell completion scripts of fastfetch use python3, it should be added as an optional dependency of fastfetch + +Logos: +* Add XeroArch # 2.26.1 From bde6c3b829c118f8b09c9f2df82297d68a490be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 15:44:53 +0800 Subject: [PATCH 39/48] Logo (Builtin): add ValhallaOS Fix #1316 --- CHANGELOG.md | 1 + src/logo/ascii/valhalla.txt | 10 ++++++++++ src/logo/builtin.c | 10 ++++++++++ 3 files changed, 21 insertions(+) create mode 100644 src/logo/ascii/valhalla.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f2ab5f23a..127ec173a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Bugfixes: Logos: * Add XeroArch +* Add ValhallaOS # 2.26.1 diff --git a/src/logo/ascii/valhalla.txt b/src/logo/ascii/valhalla.txt new file mode 100644 index 0000000000..e9611793b0 --- /dev/null +++ b/src/logo/ascii/valhalla.txt @@ -0,0 +1,10 @@ + .:~: + !55P&#: + ^@G?G!&Y + !GYYGP55P: Y5J777!^:. +.GY?J#G!Y?5. ....P#7Y!##Y??57 +.5JY5PPY5GBBBPYYPBBGBYYP5PJP5: +^#J?Y@5?J5@@&!GG!&@@YJ?5@PJ7B? +5PY55G5YY5P!55YY5P7P5JJY5YYJ5Y +#G?J5@PJJP@~&55Y5@7@5JJG@5J?GB + .:.^:^^:!.!:!!:!:!:^^:^.:. \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 2597a8993c..014f93fa99 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -4575,6 +4575,16 @@ static const FFlogo U[] = { }; static const FFlogo V[] = { + // Valhalla + { + .names = {"Valhalla", "valhallaos", "valhalla-linux"}, + .lines = FASTFETCH_DATATEXT_LOGO_VALHALLA, + .colors = { + FF_COLOR_FG_WHITE, + }, + .colorKeys = FF_COLOR_FG_WHITE, + .colorTitle = FF_COLOR_FG_WHITE, + }, // Vanilla { .names = {"vanilla", "vanilla-os", "vanilla-linux"}, From f30501f36500147074b9d2d0692c858fea5aa902 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 5 Oct 2024 17:22:32 +0800 Subject: [PATCH 40/48] Display (macOS): fix invalid physical size on old Intel Mac --- .../displayserver/displayserver_apple.c | 50 +++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index b419d52c7b..8522ea4772 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -1,6 +1,7 @@ #include "displayserver.h" #include "util/apple/cf_helpers.h" #include "util/stringUtils.h" +#include "util/edidHelper.h" #include #include @@ -23,6 +24,7 @@ static void detectDisplays(FFDisplayServerResult* ds) if(CGGetOnlineDisplayList(sizeof(screens) / sizeof(screens[0]), screens, &screenCount) != kCGErrorSuccess) return; + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); for(uint32_t i = 0; i < screenCount; i++) { CGDirectDisplayID screen = screens[i]; @@ -44,7 +46,7 @@ static void detectDisplays(FFDisplayServerResult* ds) } } - FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate(); + ffStrbufClear(&buffer); CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = NULL; #ifdef MAC_OS_X_VERSION_10_15 if(CoreDisplay_DisplayCreateInfoDictionary) @@ -55,14 +57,30 @@ static void detectDisplays(FFDisplayServerResult* ds) displayInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName); } #endif + uint32_t physicalWidth = 0, physicalHeight = 0; if(displayInfo) { CFDictionaryRef productNames; if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames)) - ffCfDictGetString(productNames, CFSTR("en_US"), &name); + ffCfDictGetString(productNames, CFSTR("en_US"), &buffer); + + // CGDisplayScreenSize reports invalid result for external displays on old Intel MacBook Pro + CFDataRef edidRef = (CFDataRef) CFDictionaryGetValue(displayInfo, CFSTR(kIODisplayEDIDKey)); + if (edidRef && CFGetTypeID(edidRef) == CFDataGetTypeID()) + { + const uint8_t* edidData = CFDataGetBytePtr(edidRef); + uint32_t edidLength = (uint32_t) CFDataGetLength(edidRef); + if (edidLength >= 128) + ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight); + } } - CGSize size = CGDisplayScreenSize(screen); + if (!physicalWidth || !physicalHeight) + { + CGSize size = CGDisplayScreenSize(screen); + physicalWidth = (uint32_t) (size.width + 0.5); + physicalHeight = (uint32_t) (size.height + 0.5); + } FFDisplayResult* display = ffdsAppendDisplay(ds, (uint32_t)CGDisplayModeGetPixelWidth(mode), @@ -71,12 +89,12 @@ static void detectDisplays(FFDisplayServerResult* ds) (uint32_t)CGDisplayModeGetWidth(mode), (uint32_t)CGDisplayModeGetHeight(mode), (uint32_t)CGDisplayRotation(screen), - &name, + &buffer, CGDisplayIsBuiltin(screen) ? FF_DISPLAY_TYPE_BUILTIN : FF_DISPLAY_TYPE_EXTERNAL, CGDisplayIsMain(screen), (uint64_t)screen, - (uint32_t) (size.width + 0.5), - (uint32_t) (size.height + 0.5) + physicalWidth, + physicalHeight ); if (display) { @@ -97,16 +115,20 @@ static void detectDisplays(FFDisplayServerResult* ds) { if (CoreDisplay_Display_SupportsHDRMode(screen)) { - if (CoreDisplay_Display_IsHDRModeEnabled) - { - display->hdrStatus = CoreDisplay_Display_IsHDRModeEnabled(screen) - ? FF_DISPLAY_HDR_STATUS_ENABLED - : FF_DISPLAY_HDR_STATUS_SUPPORTED; - } - else - display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + display->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED; + if (CoreDisplay_Display_IsHDRModeEnabled && CoreDisplay_Display_IsHDRModeEnabled(screen)) + display->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED; } + else + display->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED; } + + display->serial = CGDisplaySerialNumber(screen); + int value; + if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayYearOfManufacture), &value) == NULL) + display->manufactureYear = (uint16_t) value; + if (ffCfDictGetInt(displayInfo, CFSTR(kDisplayWeekOfManufacture), &value) == NULL) + display->manufactureWeek = (uint16_t) value; } CGDisplayModeRelease(mode); } From 951a15b61b8516b4b519dc6d577ee5576d5f3204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 17:41:56 +0800 Subject: [PATCH 41/48] LocalIP: only print properties if detected in JSON results --- src/modules/localip/localip.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/modules/localip/localip.c b/src/modules/localip/localip.c index 7343f716dc..a6bcd261ad 100644 --- a/src/modules/localip/localip.c +++ b/src/modules/localip/localip.c @@ -474,14 +474,20 @@ void ffGenerateLocalIpJsonResult(FF_MAYBE_UNUSED FFLocalIpOptions* options, yyjs 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); - yyjson_mut_obj_add_int(doc, obj, "mtu", ip->mtu); - yyjson_mut_obj_add_int(doc, obj, "speed", ip->speed); - yyjson_mut_obj_add_strbuf(doc, obj, "flags", &ip->flags); + yyjson_mut_obj_add_bool(doc, obj, "defaultRoute", ip->defaultRoute); + if (options->showType & FF_LOCALIP_TYPE_IPV4_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "ipv4", &ip->ipv4); + if (options->showType & FF_LOCALIP_TYPE_IPV6_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "ipv6", &ip->ipv6); + if (options->showType & FF_LOCALIP_TYPE_MAC_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "mac", &ip->mac); + if (options->showType & FF_LOCALIP_TYPE_MTU_BIT) + yyjson_mut_obj_add_int(doc, obj, "mtu", ip->mtu); + if (options->showType & FF_LOCALIP_TYPE_SPEED_BIT) + yyjson_mut_obj_add_int(doc, obj, "speed", ip->speed); + if (options->showType & FF_LOCALIP_TYPE_FLAGS_BIT) + yyjson_mut_obj_add_strbuf(doc, obj, "flags", &ip->flags); } FF_LIST_FOR_EACH(FFLocalIpResult, ip, results) From c2ec1e96068d94e5083961d53aa3bc5e8dddd6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 18:42:47 +0800 Subject: [PATCH 42/48] CMake: fix building on Android --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ee1a67a72..065c241599 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1026,7 +1026,7 @@ if(FreeBSD AND EXISTS "/usr/local/bin/objdump") endif() endif() -if(LINUX) +if(LINUX OR ANDROID) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__=1 _FILE_OFFSET_BITS=64) elseif(WIN32) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN=1 _WIN32_WINNT=0x0A00) @@ -1614,4 +1614,4 @@ fastfetch is a neofetch-like tool for fetching system information and displaying It is written mostly in C to achieve much better performance.\ ") -include(CPack) +include(CPack) \ No newline at end of file From 24c3f0d6b988b6e0b1d4112cfd4d32db2779cd59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 5 Oct 2024 18:47:00 +0800 Subject: [PATCH 43/48] Version (Android): correctly report sysName --- src/detection/version/version.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/detection/version/version.c b/src/detection/version/version.c index ef0138d6ef..6e89c3b660 100644 --- a/src/detection/version/version.c +++ b/src/detection/version/version.c @@ -22,8 +22,9 @@ #define FF_ARCHITECTURE "unknown" #endif - -#if defined(__linux__) +#if defined(__ANDROID__) + #define FF_SYSNAME "Android" +#elif defined(__linux__) #define FF_SYSNAME "Linux" #elif defined(__FreeBSD__) #define FF_SYSNAME "FreeBSD" From acfab74d4b00b6a95930a95c6489ab7822527fce Mon Sep 17 00:00:00 2001 From: apocelipes Date: Sat, 5 Oct 2024 21:49:29 +0800 Subject: [PATCH 44/48] LocalIP: document show-mtu and show-speed command line options (#1318) Also add these options to shell completions. --- completions/fastfetch.bash | 2 ++ src/data/help.json | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/completions/fastfetch.bash b/completions/fastfetch.bash index abd7fffb77..0e7464d6b7 100644 --- a/completions/fastfetch.bash +++ b/completions/fastfetch.bash @@ -185,6 +185,8 @@ __fastfetch_completion() "--localip-show-ipv6" "--localip-show-flags" "--localip-show-loop" + "--localip-show-mtu" + "--localip-show-speed" "--localip-name-prefix" "--localip-compact-type" "--escape-bedrock" diff --git a/src/data/help.json b/src/data/help.json index 3a326f350a..bdce5411fe 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1196,6 +1196,24 @@ "default": false } }, + { + "long": "localip-show-mtu", + "desc": "Show net interface's MTU (Maximum Transmission Unit) size in bytes", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, + { + "long": "localip-show-speed", + "desc": "Show net interface's link speed with human-readable format (or an 1Mb units integer in JSON format)", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "localip-show-prefix-len", "desc": "Show network prefix length (/N) in local ip module", From 5f3ce500229a58468bb32e6541952fd1af309c45 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 5 Oct 2024 23:56:16 +0800 Subject: [PATCH 45/48] Display (Linux): prefer detecting physical size from EDID --- src/detection/displayserver/linux/xcb.c | 1 + src/detection/displayserver/linux/xlib.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index d40386eb0b..18592a4c2e 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -245,6 +245,7 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrb { item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetPhysicalSize(edidData, &item->physicalWidth, &item->physicalHeight); } return !!item; diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index e83b0e1ede..4719611959 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -200,6 +200,7 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* { item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED; ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek); + ffEdidGetPhysicalSize(edidData, &item->physicalWidth, &item->physicalHeight); } data->ffXRRFreeCrtcInfo(crtcInfo); From 9ea887e841c4f02633d26cb986ed9de83f0e63e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 6 Oct 2024 09:27:55 +0800 Subject: [PATCH 46/48] TerminalFont: fix possible buffer overflow --- 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 e992f78929..c933937bf9 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -82,7 +82,7 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul if (ffGetTerminalResponse( "\eP+q6b697474792d71756572792d666f6e745f66616d696c79;6b697474792d71756572792d666f6e745f73697a65\e\\", // kitty-query-font_family;kitty-query-font_size 2, - "\eP1+r%*[^=]=%512[^\e]\e\\\eP1+r%*[^=]=%512[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) + "\eP1+r%*[^=]=%511[^\e]\e\\\eP1+r%*[^=]=%511[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) { // decode hex string for (const char* p = fontHex; p[0] && p[1]; p += 2) From 2d356aa64444355382d06f0cd106a10cac8b3c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 6 Oct 2024 09:29:54 +0800 Subject: [PATCH 47/48] IO: don't reuse va_list Fix #1321 --- src/common/io/io_unix.c | 6 +++++- src/common/io/io_windows.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index c29b43a9f8..54689ffaec 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -216,7 +216,11 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char* bytesRead += (size_t) nRead; buffer[bytesRead] = '\0'; - int ret = vsscanf(buffer, format, args); + va_list cargs; + va_copy(cargs, args); + int ret = vsscanf(buffer, format, cargs); + va_end(cargs); + if (ret <= 0) { va_end(args); diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index 742d564ff3..632530ccc8 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -274,7 +274,11 @@ const char* ffGetTerminalResponse(const char* request, int nParams, const char* bytesRead += bytes; buffer[bytesRead] = '\0'; + va_list cargs; + va_copy(cargs, args); int ret = vsscanf(buffer, format, args); + va_end(cargs); + if (ret <= 0) { va_end(args); From 6bcfc3a61e835229d863d878e0f47be0511fcd7f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 6 Oct 2024 10:25:50 +0800 Subject: [PATCH 48/48] Doc: update README.md [ci skip] --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 127ec173a3..3614d0370c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,13 @@ Changes: * The refresh rate reported by `monitor` module is the current refresh rate. Features: +* Add basic, highly experimental support of OpenBSD (OpenBSD) * Improve support for Raspberry pi (CPU / GPU, Linux) * Detect SOC name, instead of displaying components used in the SOC, if available (CPU, Linux) * Add option `--brightness-compact` to display multiple brightness values in one line (Brightness) * Add `day-pretty` (#1305, DateTime) -* Add basic, highly experimental support of OpenBSD (OpenBSD) * Support network interface adapter flag detection (#1315, LocalIP) + * Enable it with `--localip-show-flags` Bugfixes: * Remove trailing newline in GPU name for Raspberry pi (#1303, GPU, Linux) @@ -21,6 +22,7 @@ Bugfixes: * Corrently report `TPM device is not found` error (#1314, TPM, Windows) * Fix errors when triggering shell completion with python3 uninstalled (#1310) * To package managers: as shell completion scripts of fastfetch use python3, it should be added as an optional dependency of fastfetch +* Fix possible crashes when detecting term font of kitty (#1321, TerminalFont, Linux) Logos: * Add XeroArch