From 1656c4780cc6c1d96f47522046f3f53b1eebb95a Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 17 Jan 2012 14:21:05 +0100 Subject: fix NTFS mount points NTFS mount points are not treated as symlinks, because they might not have a link target. This is the case when a volume is mounted as a single mount point without a drive letter. This patch fixes building Qt in an NTFS mount point. Task-number: QTBUG-20431 Change-Id: Ie2e15212e1a7ca7fa0067b7ca8857e243e42c21a Reviewed-by: Thomas Hartmann --- src/corelib/io/qfilesystemengine_win.cpp | 10 ++++++---- src/corelib/io/qfilesystemiterator_win.cpp | 2 +- src/corelib/io/qfilesystemmetadata_p.h | 23 +++++++++++++++++------ tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp | 2 +- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index d724429f6b..4d56739483 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -792,9 +792,10 @@ static bool tryFindFallback(const QFileSystemEntry &fname, QFileSystemMetaData & int errorCode = GetLastError(); if (errorCode == ERROR_ACCESS_DENIED || errorCode == ERROR_SHARING_VIOLATION) { WIN32_FIND_DATA findData; - if (getFindData(fname.nativeFilePath(), findData) + const QString nativeFilePath = fname.nativeFilePath(); + if (getFindData(nativeFilePath, findData) && findData.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { - data.fillFromFindData(findData, true, fname.isDriveRoot()); + data.fillFromFindData(findData, true, fname.isDriveRoot(), nativeFilePath); filledData = true; } } @@ -875,8 +876,9 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM data.knownFlagsMask |= QFileSystemMetaData::LinkType; if (data.fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) { WIN32_FIND_DATA findData; - if (getFindData(fname.nativeFilePath(), findData)) - data.fillFromFindData(findData, true); + const QString nativeFilePath = fname.nativeFilePath(); + if (getFindData(nativeFilePath, findData)) + data.fillFromFindData(findData, true, false, nativeFilePath); } } data.knownFlagsMask |= what; diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp index 1f5cf356a0..030ef2120f 100644 --- a/src/corelib/io/qfilesystemiterator_win.cpp +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -138,7 +138,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa fileEntry = QFileSystemEntry(dirPath + fileName); metaData = QFileSystemMetaData(); if (!fileName.endsWith(QLatin1String(".lnk"))) { - metaData.fillFromFindData(findData, true); + metaData.fillFromFindData(findData, true, false, fileEntry.nativeFilePath()); } return true; } diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h index 6ed5cec954..9895c22440 100644 --- a/src/corelib/io/qfilesystemmetadata_p.h +++ b/src/corelib/io/qfilesystemmetadata_p.h @@ -234,7 +234,7 @@ public: #if defined(Q_OS_WIN) inline void fillFromFileAttribute(DWORD fileAttribute, bool isDriveRoot = false); - inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false); + inline void fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType = false, bool isDriveRoot = false, const QString &nativeFullFilePath = QString()); inline void fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo); #endif private: @@ -350,7 +350,7 @@ inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool knownFlagsMask |= FileType | DirectoryType | HiddenAttribute | ExistsAttribute; } -inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot) +inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot, const QString &nativeFullFilePath) { fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot); creationTime_ = findData.ftCreationTime; @@ -368,12 +368,23 @@ inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, boo knownFlagsMask |= LinkType; entryFlags &= ~LinkType; #if !defined(Q_OS_WINCE) - if ((fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) - && (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) { - entryFlags |= LinkType; + if (fileAttribute_ & FILE_ATTRIBUTE_REPARSE_POINT) { + if (findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + entryFlags |= LinkType; + } else if (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) { + // Junctions and mount points are implemented as NTFS reparse points. + // But mount points cannot be treated as symlinks because they might + // not have a link target. + wchar_t buf[50]; + QString path = nativeFullFilePath; + if (!path.endsWith(QLatin1Char('\\'))) + path.append(QLatin1Char('\\')); + BOOL isMountPoint = GetVolumeNameForVolumeMountPoint(reinterpret_cast(path.utf16()), buf, sizeof(buf) / sizeof(wchar_t)); + if (!isMountPoint) + entryFlags |= LinkType; + } } #endif - } } diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 5764cee66d..48bef1e873 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -1390,7 +1390,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() junction = "mountpoint"; rootVolume.replace("\\\\?\\","\\??\\"); FileSystem::createNtfsJunction(rootVolume, junction); - QTest::newRow("mountpoint") << junction << true << QDir::fromNativeSeparators(rootPath) << QDir::rootPath(); + QTest::newRow("mountpoint") << junction << false << QString() << QFileInfo(junction).canonicalFilePath(); } } -- cgit v1.2.3