From 23d97f7566ed505bc554dc7f1202ce491522aac0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 15 Mar 2025 08:50:18 -0700 Subject: [PATCH] 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 (cherry picked from commit 606ba105074cff21384e5da66f56f05d6ce49992) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/io/qfilesystemiterator_win.cpp | 2 +- src/corelib/io/qfilesystemmetadata_p.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp index fb4f0a5433a..b5a5a71d1b7 100644 --- a/src/corelib/io/qfilesystemiterator_win.cpp +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -106,7 +106,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa QString fileName = QString::fromWCharArray(findData.cFileName); fileEntry = QFileSystemEntry(dirPath + fileName); metaData = QFileSystemMetaData(); - if (!fileName.endsWith(".lnk"_L1)) { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY || !fileName.endsWith(".lnk"_L1)) { metaData.fillFromFindData(findData, true); } return true; diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index 1a6e451ac4d..0e910804e14 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -337,6 +337,9 @@ inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool entryFlags |= ((fileAttribute & FILE_ATTRIBUTE_DIRECTORY) ? DirectoryType: FileType); entryFlags |= 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)