mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-03 03:41:04 +01:00
123 lines
3.4 KiB
C
123 lines
3.4 KiB
C
#include "packages.h"
|
|
#include "common/io/io.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];
|
|
|
|
if (result->all == 0)
|
|
return "No packages from known package managers found";
|
|
|
|
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;
|
|
if (!GetFileTime(handle, NULL, NULL, (FILETIME*) &mtime_current))
|
|
return false;
|
|
|
|
mtime_current = (mtime_current - 116444736000000000ull) / 10000ull;
|
|
|
|
if (__builtin_expect(mtime_current == 0, false))
|
|
return false;
|
|
#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 !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;
|
|
}
|
|
|
|
if(isdir && num_elements >= 2)
|
|
num_elements -= 2; // accounting for . and ..
|
|
|
|
return num_elements;
|
|
}
|
|
#endif
|