summaryrefslogtreecommitdiffstats
path: root/src/detection/packages/packages.c
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/packages/packages.c
Add the files
Diffstat (limited to 'src/detection/packages/packages.c')
-rw-r--r--src/detection/packages/packages.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/detection/packages/packages.c b/src/detection/packages/packages.c
new file mode 100644
index 0000000..25f59b3
--- /dev/null
+++ b/src/detection/packages/packages.c
@@ -0,0 +1,119 @@
+#include "packages.h"
+#include "common/io.h"
+#include "common/time.h"
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#ifdef __APPLE__
+ #define st_mtim st_mtimespec
+#endif
+
+void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options);
+
+const char* ffDetectPackages(FFPackagesResult* result, FFPackagesOptions* options) {
+ ffDetectPackagesImpl(result, options);
+
+ for (uint32_t i = 0; i < offsetof(FFPackagesResult, all) / sizeof(uint32_t); ++i) {
+ result->all += ((uint32_t*) result)[i];
+ }
+
+ return NULL;
+}
+
+bool ffPackagesReadCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, const char* filePath, const char* packageId, uint32_t* result) {
+#ifndef _WIN32
+ struct stat st;
+ if (stat(filePath, &st) < 0) // file doesn't exist or isn't accessible
+ {
+ *result = 0;
+ return true;
+ }
+
+ if (__builtin_expect(st.st_mtim.tv_sec <= 0, false)) {
+ return false;
+ }
+
+ uint64_t mtime_current = (uint64_t) st.st_mtim.tv_sec * 1000ull + (uint64_t) st.st_mtim.tv_nsec / 1000000ull;
+#else
+ FF_AUTO_CLOSE_FD HANDLE handle = CreateFileA(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) // file doesn't exist or isn't accessible
+ {
+ *result = 0;
+ return true;
+ }
+
+ uint64_t mtime_current;
+ FILE_BASIC_INFORMATION fileInfo;
+ IO_STATUS_BLOCK iosb;
+ if (!NT_SUCCESS(NtQueryInformationFile(handle, &iosb, &fileInfo, sizeof(fileInfo), FileBasicInformation))) {
+ return false;
+ }
+
+ mtime_current = ffFileTimeToUnixMs((uint64_t) fileInfo.LastWriteTime.QuadPart);
+#endif
+
+ ffStrbufSet(cacheDir, &instance.state.platform.cacheDir);
+ ffStrbufEnsureEndsWithC(cacheDir, '/');
+ ffStrbufAppendF(cacheDir, "fastfetch/packages/%s.txt", packageId);
+
+ if (ffReadFileBuffer(cacheDir->chars, cacheContent)) {
+ uint64_t mtime_cached;
+ uint32_t num_cached;
+ if (sscanf(cacheContent->chars, "%" SCNu64 " %" SCNu32, &mtime_cached, &num_cached) == 2 &&
+ mtime_cached == mtime_current && num_cached > 0) {
+ *result = num_cached;
+ return true;
+ }
+ }
+
+ ffStrbufSetF(cacheContent, "%" PRIu64 " ", mtime_current);
+
+ return false;
+}
+
+bool ffPackagesWriteCache(FFstrbuf* cacheDir, FFstrbuf* cacheContent, uint32_t num_elements) {
+ if (__builtin_expect(cacheContent->length == 0, false)) {
+ return false;
+ }
+
+ ffStrbufAppendF(cacheContent, "%" PRIu32, num_elements);
+ return ffWriteFileBuffer(cacheDir->chars, cacheContent);
+}
+
+#ifndef _WIN32
+uint32_t ffPackagesGetNumElements(const char* dirname, bool isdir) {
+ 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) {
+ bool ok = false;
+
+ if (entry->d_name[0] != '.') {
+ #if !defined(__sun) && !defined(__HAIKU__)
+ if (entry->d_type != DT_UNKNOWN && entry->d_type != DT_LNK) {
+ ok = entry->d_type == (isdir ? DT_DIR : DT_REG);
+ } else
+ #endif
+ {
+ struct stat stbuf;
+ if (fstatat(dirfd(dirp), entry->d_name, &stbuf, 0) == 0) {
+ ok = isdir ? S_ISDIR(stbuf.st_mode) : S_ISREG(stbuf.st_mode);
+ }
+ }
+ }
+
+ if (ok) {
+ ++num_elements;
+ }
+ }
+
+ return num_elements;
+}
+#endif