diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index 12e9879330..23ad68c6c4 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -1,10 +1,10 @@ #pragma once +#include "common/processing.h" #include "fastfetch.h" #include "modules/packages/option.h" -typedef struct FFPackagesResult -{ +typedef struct FFPackagesResult { uint32_t amSystem; uint32_t amUser; uint32_t apk; @@ -47,7 +47,7 @@ typedef struct FFPackagesResult uint32_t winget; uint32_t xbps; - uint32_t all; //Make sure this goes last + uint32_t all; // Make sure this goes last FFstrbuf pacmanBranch; } FFPackagesResult; @@ -57,7 +57,17 @@ bool ffPackagesReadCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, const char* bool ffPackagesWriteCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, uint32_t num_elements); #if defined(__linux__) || defined(__APPLE__) || defined(__GNU__) +void getNixPackagesMultiImpl(char* paths[], uint32_t counts[], FFProcessHandle handle[], uint8_t length); uint32_t ffPackagesGetNix(FFstrbuf* baseDir, const char* dirname); +#define ffPackagesGetNixMulti(dirs, counts, N) \ + do { \ + FFProcessHandle _handles[N]; \ + char* _paths[N]; \ + for (uint8_t i = 0; i < N; i++) { \ + _paths[i] = dirs[i]->chars; \ + } \ + getNixPackagesMultiImpl(_paths, counts, _handles, N); \ + } while (0) #endif #ifndef _WIN32 uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir); diff --git a/src/detection/packages/packages_apple.c b/src/detection/packages/packages_apple.c index 5a176c834d..423b676991 100644 --- a/src/detection/packages/packages_apple.c +++ b/src/detection/packages/packages_apple.c @@ -2,7 +2,9 @@ #include "common/io/io.h" #include "common/parsing.h" #include "common/processing.h" +#include "util/FFstrbuf.h" #include "util/stringUtils.h" +#include static void countBrewPackages(FFstrbuf* baseDir, FFPackagesResult* result) { @@ -61,9 +63,19 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT)) { ffStrbufSetS(&baseDir, FASTFETCH_TARGET_DIR_ROOT); - result->nixDefault += ffPackagesGetNix(&baseDir, "/nix/var/nix/profiles/default"); - result->nixSystem += ffPackagesGetNix(&baseDir, "/run/current-system"); - ffStrbufSet(&baseDir, &instance.state.platform.homeDir); - result->nixUser = ffPackagesGetNix(&baseDir, "/.nix-profile"); + ffStrbufAppendS(&baseDir, "/nix/var/nix/profiles/default"); + + FF_STRBUF_AUTO_DESTROY dir2 = ffStrbufCreateS(FASTFETCH_TARGET_DIR_ROOT); + ffStrbufAppendS(&dir2, "/run/current-system"); + + FF_STRBUF_AUTO_DESTROY dir3 = ffStrbufCreateCopy(&instance.state.platform.homeDir); + ffStrbufAppendS(&dir3, "/.nix-profile"); + + FFstrbuf* dirs[] = {&baseDir, &dir2, &dir3}; + uint32_t counts[3] = {0}; + ffPackagesGetNixMulti(dirs, counts, 3); + result->nixDefault = counts[0]; + result->nixSystem = counts[1]; + result->nixUser = counts[2]; } } diff --git a/src/detection/packages/packages_nix.c b/src/detection/packages/packages_nix.c index 08a5479a6b..910970cab5 100644 --- a/src/detection/packages/packages_nix.c +++ b/src/detection/packages/packages_nix.c @@ -2,6 +2,7 @@ #include "common/io/io.h" #include "common/processing.h" #include "util/stringUtils.h" +#include static bool isValidNixPkg(FFstrbuf* pkg) { @@ -51,6 +52,53 @@ static bool isValidNixPkg(FFstrbuf* pkg) return state == MATCH; } +void getNixPackagesMultiImpl(char* paths[], uint32_t counts[], FFProcessHandle handle[], uint8_t length) +{ + //Implementation based on bash script from here: + //https://github.com/fastfetch-cli/fastfetch/issues/195#issuecomment-1191748222 + // no need to use hash, it is not faster + for (uint8_t i = 0; i < length; i++){ + handle[i].pid = 0; + // Nix detection is kinda slow, so we only do it if the dir exists + if(ffPathExists(paths[i], FF_PATHTYPE_DIRECTORY)){ + ffProcessSpawn((char* const[]) { + "nix-store", + "--query", + "--requisites", + paths[i], + NULL + }, false, &handle[i]); + } + } + for (uint8_t i = 0; i < length; i++){ + FF_STRBUF_AUTO_DESTROY output = ffStrbufCreateA(1024); + if (!handle[i].pid){ + counts[i] = 0; + continue; + } + ffProcessReadOutput(&handle[i], &output); + uint32_t lineLength = 0; + for (uint32_t j = 0; j < output.length; j++) + { + if (output.chars[j] != '\n') + { + lineLength++; + continue; + } + + output.chars[j] = '\0'; + FFstrbuf line = { + .allocated = 0, + .length = lineLength, + .chars = output.chars + j - lineLength + }; + if (isValidNixPkg(&line)) + counts[i] += 1; + lineLength = 0; + } + } +} + static bool checkNixCache(FFstrbuf* cacheDir, FFstrbuf* hash, uint32_t* count) { if (!ffPathExists(cacheDir->chars, FF_PATHTYPE_FILE))