[channels,drive] Small performance improvements in drive channel

This commit fixes following performance issues in the drive channel:
- `GetFileAttributes` functions where using `FindFirstFile` to query
  attributes. The same can be achieved with `stat` and reusing the
existing stat <-> file info conversion code.
- `drive_file_query_information` was calling `CreateFile` on directories
  which will always fail with the given parameters.
This commit is contained in:
Martin Fleisz
2025-11-20 14:26:19 +01:00
parent 129565951f
commit 236959c440
2 changed files with 47 additions and 36 deletions

View File

@@ -587,7 +587,6 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
{
BY_HANDLE_FILE_INFORMATION fileInformation = { 0 };
BOOL status = 0;
HANDLE hFile = NULL;
if (!file || !output)
return FALSE;
@@ -597,20 +596,23 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
return drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
output);
hFile = CreateFileW(file->fullpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
if (!file->is_dir)
{
status = GetFileInformationByHandle(hFile, &fileInformation);
(void)CloseHandle(hFile);
if (!status)
goto out_fail;
HANDLE hFile = CreateFileW(file->fullpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
status = GetFileInformationByHandle(hFile, &fileInformation);
(void)CloseHandle(hFile);
if (!status)
goto out_fail;
if (!drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
output))
goto out_fail;
if (!drive_file_query_from_handle_information(file, &fileInformation,
FsInformationClass, output))
goto out_fail;
return TRUE;
return TRUE;
}
}
/* If we failed before (i.e. if information for a drive is queried) fall back to

View File

@@ -182,6 +182,10 @@ static pthread_once_t HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
#include "../comm/comm.h"
#include "namedPipeClient.h"
static DWORD FileAttributesFromStat(const char* path, const struct stat* fileStat);
static BOOL FindDataFromStat(const char* path, const struct stat* fileStat,
LPWIN32_FIND_DATAA lpFindFileData);
static void HandleCreatorsInit(void)
{
WINPR_ASSERT(HandleCreators == NULL);
@@ -476,16 +480,17 @@ BOOL WINAPI GetFileAttributesExA(LPCSTR lpFileName,
LPVOID lpFileInformation)
{
LPWIN32_FILE_ATTRIBUTE_DATA fd = lpFileInformation;
WIN32_FIND_DATAA findFileData = { 0 };
if (!fd)
return FALSE;
HANDLE hFind = FindFirstFileA(lpFileName, &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
struct stat fileStat = { 0 };
if (stat(lpFileName, &fileStat) != 0)
return FALSE;
WIN32_FIND_DATAA findFileData = { 0 };
if (!FindDataFromStat(lpFileName, &fileStat, &findFileData))
return FALSE;
FindClose(hFind);
fd->dwFileAttributes = findFileData.dwFileAttributes;
fd->ftCreationTime = findFileData.ftCreationTime;
fd->ftLastAccessTime = findFileData.ftLastAccessTime;
@@ -516,14 +521,11 @@ BOOL WINAPI GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInf
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
{
WIN32_FIND_DATAA findFileData = { 0 };
HANDLE hFind = FindFirstFileA(lpFileName, &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
struct stat fileStat = { 0 };
if (stat(lpFileName, &fileStat) != 0)
return INVALID_FILE_ATTRIBUTES;
FindClose(hFind);
return findFileData.dwFileAttributes;
return FileAttributesFromStat(lpFileName, &fileStat);
}
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
@@ -935,32 +937,39 @@ static BOOL is_valid_file_search_handle(HANDLE handle)
return FALSE;
return TRUE;
}
static BOOL FindDataFromStat(const char* path, const struct stat* fileStat,
LPWIN32_FIND_DATAA lpFindFileData)
static DWORD FileAttributesFromStat(const char* path, const struct stat* fileStat)
{
UINT64 ft = 0;
char* lastSep = NULL;
lpFindFileData->dwFileAttributes = 0;
DWORD dwFileAttributes = 0;
if (S_ISDIR(fileStat->st_mode))
lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
if (lpFindFileData->dwFileAttributes == 0)
lpFindFileData->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
if (dwFileAttributes == 0)
dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
lastSep = strrchr(path, '/');
if (lastSep)
{
const char* name = lastSep + 1;
const size_t namelen = strlen(name);
if ((namelen > 1) && (name[0] == '.') && (name[1] != '.'))
lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
}
if (!(fileStat->st_mode & S_IWUSR))
lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
return dwFileAttributes;
}
static BOOL FindDataFromStat(const char* path, const struct stat* fileStat,
LPWIN32_FIND_DATAA lpFindFileData)
{
UINT64 ft = 0;
lpFindFileData->dwFileAttributes = FileAttributesFromStat(path, fileStat);
#ifdef _DARWIN_FEATURE_64_BIT_INODE
ft = STAT_TIME_TO_FILETIME(fileStat->st_birthtime);
@@ -1205,9 +1214,9 @@ BOOL FindClose(HANDLE hFindFile)
if (!pFileSearch)
return FALSE;
/* Since INVALID_HANDLE_VALUE != NULL the analyzer guesses that there
* is a initialized HANDLE that is not freed properly.
* Disable this return to stop confusing the analyzer. */
/* Since INVALID_HANDLE_VALUE != NULL the analyzer guesses that there
* is a initialized HANDLE that is not freed properly.
* Disable this return to stop confusing the analyzer. */
#ifndef __clang_analyzer__
if (!is_valid_file_search_handle(hFindFile))
return FALSE;