mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-29 16:26:39 +01:00
Packages (Windows): improves performance for directory enumeration
This commit is contained in:
@@ -2,35 +2,63 @@
|
||||
#include "common/processing.h"
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/path.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <handleapi.h>
|
||||
#include <fileapi.h>
|
||||
#include <Windows.h>
|
||||
#include "util/windows/nt.h"
|
||||
#include <ntstatus.h>
|
||||
|
||||
static uint32_t getNumElements(const char* searchPath /* including `\*` suffix */, DWORD type, const char* ignore)
|
||||
static uint32_t getNumElements(const char* searchPath, DWORD type, const wchar_t* ignore)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
bool flag = ignore == NULL;
|
||||
WIN32_FIND_DATAA wfd;
|
||||
HANDLE hFind = FindFirstFileA(searchPath, &wfd);
|
||||
FF_AUTO_CLOSE_FD HANDLE dfd = CreateFileA(searchPath, FILE_LIST_DIRECTORY | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (dfd == INVALID_HANDLE_VALUE) return 0;
|
||||
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do // Managed to locate and create an handle to that folder.
|
||||
bool flag = ignore == NULL;
|
||||
uint32_t counter = 0;
|
||||
uint8_t buffer[64 * 1024] __attribute__((aligned(8))); // Required for WoA
|
||||
BOOLEAN firstScan = TRUE;
|
||||
|
||||
while (true) {
|
||||
IO_STATUS_BLOCK ioStatus = {};
|
||||
NTSTATUS status = NtQueryDirectoryFile(
|
||||
dfd,
|
||||
NULL, NULL, NULL,
|
||||
&ioStatus,
|
||||
buffer, ARRAY_SIZE(buffer),
|
||||
FileDirectoryInformation,
|
||||
FALSE,
|
||||
NULL,
|
||||
firstScan
|
||||
);
|
||||
firstScan = FALSE;
|
||||
|
||||
if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) break;
|
||||
|
||||
for (FILE_DIRECTORY_INFORMATION* entry = (FILE_DIRECTORY_INFORMATION*) buffer;
|
||||
;
|
||||
entry = (FILE_DIRECTORY_INFORMATION*) ((uint8_t*) entry + entry->NextEntryOffset))
|
||||
{
|
||||
if(!(wfd.dwFileAttributes & type)) continue;
|
||||
if(!flag && ffStrEqualsIgnCase(ignore, wfd.cFileName))
|
||||
if (!(entry->FileAttributes & type)) continue;
|
||||
|
||||
if (!flag && _wcsicmp(entry->FileName, ignore) == 0)
|
||||
{
|
||||
flag = true;
|
||||
continue;
|
||||
}
|
||||
counter++;
|
||||
} while (FindNextFileA(hFind, &wfd));
|
||||
FindClose(hFind);
|
||||
|
||||
if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2)
|
||||
counter -= 2; // accounting for . and ..
|
||||
counter++;
|
||||
|
||||
if (entry->NextEntryOffset == 0) break;
|
||||
}
|
||||
|
||||
if (status == STATUS_SUCCESS) break; // No next page
|
||||
}
|
||||
|
||||
if(type == FILE_ATTRIBUTE_DIRECTORY && counter >= 2)
|
||||
counter -= 2; // accounting for . and ..
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
@@ -65,8 +93,8 @@ static void detectScoop(FFPackagesResult* result)
|
||||
ffStrbufSet(&scoopPath, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(&scoopPath, "/scoop");
|
||||
}
|
||||
ffStrbufAppendS(&scoopPath, "/apps/*");
|
||||
result->scoopUser = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
|
||||
ffStrbufAppendS(&scoopPath, "/apps/");
|
||||
result->scoopUser = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, L"scoop");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -78,8 +106,8 @@ static void detectScoop(FFPackagesResult* result)
|
||||
ffStrbufSetS(&scoopPath, getenv("ProgramData"));
|
||||
ffStrbufAppendS(&scoopPath, "/scoop");
|
||||
}
|
||||
ffStrbufAppendS(&scoopPath, "/apps/*");
|
||||
result->scoopGlobal = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, "scoop");
|
||||
ffStrbufAppendS(&scoopPath, "/apps/");
|
||||
result->scoopGlobal = getNumElements(scoopPath.chars, FILE_ATTRIBUTE_DIRECTORY, L"scoop");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +119,8 @@ static void detectChoco(FF_MAYBE_UNUSED FFPackagesResult* result)
|
||||
|
||||
char chocoPath[MAX_PATH + 3];
|
||||
char* pend = ffStrCopy(chocoPath, chocoInstall, ARRAY_SIZE(chocoPath));
|
||||
ffStrCopy(pend, "/lib/*", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath));
|
||||
result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, "choco");
|
||||
ffStrCopy(pend, "/lib/", ARRAY_SIZE(chocoPath) - (size_t) (pend - chocoPath));
|
||||
result->choco = getNumElements(chocoPath, FILE_ATTRIBUTE_DIRECTORY, L"choco");
|
||||
}
|
||||
|
||||
static void detectPacman(FFPackagesResult* result)
|
||||
@@ -104,7 +132,7 @@ static void detectPacman(FFPackagesResult* result)
|
||||
// MSYS2
|
||||
char pacmanPath[MAX_PATH + 3];
|
||||
char* pend = ffStrCopy(pacmanPath, msystemPrefix, ARRAY_SIZE(pacmanPath));
|
||||
ffStrCopy(pend, "/../var/lib/pacman/local/*", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath));
|
||||
ffStrCopy(pend, "/../var/lib/pacman/local/", ARRAY_SIZE(pacmanPath) - (size_t) (pend - pacmanPath));
|
||||
result->pacman = getNumElements(pacmanPath, FILE_ATTRIBUTE_DIRECTORY, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -232,3 +232,19 @@ typedef struct _D3DKMT_NODEMETADATA
|
||||
static_assert(sizeof(D3DKMT_NODEMETADATA) == 0x4E, "D3DKMT_NODEMETADATA structure size mismatch");
|
||||
|
||||
#endif
|
||||
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtQueryDirectoryFile(
|
||||
IN HANDLE FileHandle,
|
||||
IN HANDLE Event OPTIONAL,
|
||||
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
||||
IN PVOID ApcContext OPTIONAL,
|
||||
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
||||
OUT PVOID FileInformation,
|
||||
IN ULONG Length,
|
||||
IN FILE_INFORMATION_CLASS FileInformationClass,
|
||||
IN BOOLEAN ReturnSingleEntry,
|
||||
IN PUNICODE_STRING FileName OPTIONAL,
|
||||
IN BOOLEAN RestartScan);
|
||||
|
||||
Reference in New Issue
Block a user