summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorRyan Chu <ryan.chu@qt.io>2019-08-21 16:18:07 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2019-11-09 00:47:45 +0100
commit004e3e0dc2cab4a4534d2ed3ace41aad6bfbe45d (patch)
tree89648f07e55a607a7d38e0f7b6eecb81b5607a66 /src/corelib
parentb81863cfad1ca1e5825eaffb50a9b2fe2da51c7f (diff)
Make Qt aware of NTFS Junctions on Windows
On NTFS, a junction point can be created and deleted by the mklink and rmdir commands, respectively. If a directory is not identified correctly as a junction, then applications will likely try to remove it using recursive methods, leading to fatal data loss. With this change, Qt can identify file system entries as junctions, allowing applications to use the correct file system operation to remove it. The test needs to delay the cleaning up of junctions and files it creates until the checks are complete; since they might fail and make the test function return prematurely, use a scope guard. [ChangeLog][QtCore][QFileInfo] Add QFileInfo::isJunction so that applications can recognize NTFS file system entries as junctions Task-number: QTBUG-75869 Change-Id: I3c208245afbd9fb7555515fb776ff63b133ca858 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/io/qfileinfo.cpp19
-rw-r--r--src/corelib/io/qfileinfo.h1
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h16
3 files changed, 33 insertions, 3 deletions
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 89834de29f..93696c1320 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -1145,6 +1145,25 @@ bool QFileInfo::isShortcut() const
[d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); });
}
+
+/*!
+ Returns \c true if the object points to a junction;
+ otherwise returns \c false.
+
+ Junctions only exist on Windows' NTFS file system, and are typically
+ created by the \c{mklink} command. They can be thought of as symlinks for
+ directories, and can only be created for absolute paths on the local
+ volume.
+*/
+bool QFileInfo::isJunction() const
+{
+ Q_D(const QFileInfo);
+ return d->checkAttribute<bool>(
+ QFileSystemMetaData::LegacyLinkType,
+ [d]() { return d->metaData.isJunction(); },
+ [d]() { return d->getFileFlags(QAbstractFileEngine::LinkType); });
+}
+
/*!
Returns \c true if the object points to a directory or to a symbolic
link to a directory, and that directory is the root directory; otherwise
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index 3ac028085a..7c7ff56ae4 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -113,6 +113,7 @@ public:
bool isSymLink() const;
bool isSymbolicLink() const;
bool isShortcut() const;
+ bool isJunction() const;
bool isRoot() const;
bool isBundle() const;
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index 81f4b3ba13..275a4bf8d0 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -111,8 +111,10 @@ public:
AliasType = 0x0,
#endif
#if defined(Q_OS_WIN)
+ JunctionType = 0x04000000,
WinLnkType = 0x08000000, // Note: Uses the same position for AliasType on Mac
#else
+ JunctionType = 0x0,
WinLnkType = 0x0,
#endif
SequentialType = 0x00800000, // Note: overlaps with QAbstractFileEngine::RootFlag
@@ -205,8 +207,10 @@ public:
bool wasDeleted() const { return (entryFlags & WasDeletedAttribute); }
#if defined(Q_OS_WIN)
bool isLnkFile() const { return (entryFlags & WinLnkType); }
+ bool isJunction() const { return (entryFlags & JunctionType); }
#else
bool isLnkFile() const { return false; }
+ bool isJunction() const { return false; }
#endif
qint64 size() const { return size_; }
@@ -356,9 +360,15 @@ inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, boo
if (setLinkType) {
knownFlagsMask |= LinkType;
entryFlags &= ~LinkType;
- 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;
+#if defined(IO_REPARSE_TAG_MOUNT_POINT)
+ } else if ((fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY)
+ && (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT)) {
+ entryFlags |= JunctionType;
+#endif
+ }
}
}
}