diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index f3ca054f2..3aa0e2b12 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -467,6 +467,78 @@ static uint32_t getGuixPackages(FFstrbuf* baseDir, const char* dirname) return num_elements; } +static inline uint32_t getFlatpakRuntimePackagesArch(FFstrbuf* baseDir) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars); + if (dirp == NULL) + return 0; + + uint32_t num_elements = 0; + + struct dirent *entry; + while ((entry = readdir(dirp)) != NULL) + { + if(entry->d_type == DT_DIR && entry->d_name[0] != '.') + { + num_elements += getNumElements(baseDir, entry->d_name, DT_DIR); + } + } + + return num_elements; +} + +static inline uint32_t getFlatpakRuntimePackages(FFstrbuf* baseDir) +{ + ffStrbufAppendS(baseDir, "runtime/"); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars); + if (dirp == NULL) + return 0; + + uint32_t runtimeDirLength = baseDir->length; + uint32_t num_elements = 0; + + struct dirent *entry; + while ((entry = readdir(dirp)) != NULL) + { + if(entry->d_type == DT_DIR && entry->d_name[0] != '.') + { + // `flatpak list` ignores `.Locale` and `.Debug` packages, and maybe others + const char* dot = strrchr(entry->d_name, '.'); + if (__builtin_expect(!dot, false)) continue; + dot++; + + if (ffStrEquals(dot, "Locale") || ffStrEquals(dot, "Debug")) + continue; + + ffStrbufAppendS(baseDir, entry->d_name); + ffStrbufAppendC(baseDir, '/'); + num_elements += getFlatpakRuntimePackagesArch(baseDir); + ffStrbufSubstrBefore(baseDir, runtimeDirLength); + } + } + + return num_elements; +} + +static uint32_t getFlatpakPackages(FFstrbuf* baseDir, const char* dirname) +{ + uint32_t num_elements = 0; + uint32_t baseDirLength = baseDir->length; + ffStrbufAppendS(baseDir, dirname); + ffStrbufAppendS(baseDir, "/flatpak/"); + uint32_t flatpakDirLength = baseDir->length; + + ffStrbufAppendS(baseDir, "app"); + num_elements += getNumElementsImpl(baseDir->chars, DT_DIR); + ffStrbufSubstrBefore(baseDir, flatpakDirLength); + + num_elements += getFlatpakRuntimePackages(baseDir); + + ffStrbufSubstrBefore(baseDir, baseDirLength); + + return num_elements; +} + static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options) { if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q", "apk"); @@ -474,7 +546,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, if (!(options->disabled & FF_PACKAGES_FLAG_LPKG_BIT)) packageCounts->lpkg += getNumStrings(baseDir, "/opt/Loc-OS-LPKG/installed-lpkg/Listinstalled-lpkg.list", "\n", "lpkg"); if (!(options->disabled & FF_PACKAGES_FLAG_EMERGE_BIT)) packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE"); if (!(options->disabled & FF_PACKAGES_FLAG_EOPKG_BIT)) packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR); - if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getNumElements(baseDir, "/var/lib/flatpak/app", DT_DIR); + if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpakPackages(baseDir, "/var/lib"); if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT)) { packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default"); @@ -603,5 +675,5 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) } if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) - result->flatpakUser = getNumElements(&baseDir, "/.local/share/flatpak/app", DT_DIR); + result->flatpakUser = getFlatpakPackages(&baseDir, "/.local/share"); }