QDirListing/Win: improve performance by setting WinLnkType earlier

This line in QDirListingPrivate::checkAndPushDirectory() was causing a
call to GetFileAttributesEx() for every single directory entry when
recursion was enabled:

    // Follow symlinks only when asked
    if (!iteratorFlags.testAnyFlags(F::FollowDirSymlinks) && entryInfo.isSymLink())
        return;

That happened because QFileSystemIterator::advance() never set
QFileSystemMetaData::WinLnkType in knownFlagsMask, because QFSMD is
supposed to contain the information about what that .lnk was pointing to
and we don't want to read it unnecessarily.

However, we *do* when the directory entry is *not* a .lnk file. For
those cases, we can set WinLnkType in knownFlagsMask, which will cause
QDirEntryInfo::isSymLink() to return false without having to make
further system calls.

This change is fragile and this code deserves a bit of refactoring
(starting with getting rid of The Boolean Trap). All calls to either
fillFromFindData() or fillFromFileAttribute() are currently protected by
a .lnk filename check (all of them are either in this function or inside
of QFileSystemEngine::fillMetaData()).

Fixes: QTBUG-134699
Pick-to: 6.8
Change-Id: I87b19f89035bcd7e1c1ffffd14eac5fb5ac3e693
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
(cherry picked from commit 606ba105074cff21384e5da66f56f05d6ce49992)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Thiago Macieira 2025-03-15 08:50:18 -07:00 committed by Qt Cherry-pick Bot
parent 8d0f762177
commit 23d97f7566
2 changed files with 4 additions and 1 deletions

View File

@ -106,7 +106,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa
QString fileName = QString::fromWCharArray(findData.cFileName); QString fileName = QString::fromWCharArray(findData.cFileName);
fileEntry = QFileSystemEntry(dirPath + fileName); fileEntry = QFileSystemEntry(dirPath + fileName);
metaData = QFileSystemMetaData(); metaData = QFileSystemMetaData();
if (!fileName.endsWith(".lnk"_L1)) { if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY || !fileName.endsWith(".lnk"_L1)) {
metaData.fillFromFindData(findData, true); metaData.fillFromFindData(findData, true);
} }
return true; return true;

View File

@ -337,6 +337,9 @@ inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool
entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType); entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType);
entryFlags |= ExistsAttribute; entryFlags |= ExistsAttribute;
knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute; knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute;
// this function is never called for a .lnk file
knownFlagsMask |= WinLnkType;
} }
inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot) inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)