summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@qt.io>2021-05-11 14:09:11 +0200
committerKarsten Heimrich <karsten.heimrich@qt.io>2021-06-05 01:16:06 +0200
commit0564ebdb3641d7325f73dbbf2cbb04e6dca92d83 (patch)
treea766802e3bd675e8d84d655c3b93a0ea62d98d92 /src
parenta1d967357f2715899d0236ea4910e615d178024f (diff)
Unify behavior for long path or UNC prefix removal
Split the code out of QDir::fromNativeSeparator into a separate reusable function to remove the above-mentioned prefixes. Fixes and unifies behavior if the prefix was given with slashes instead of backslashes. Add a couple more test cases. Fixes: QTBUG-93868 Pick-to: 5.15 6.0 6.1 Change-Id: Ibd94ae283e2fb113f9c2db97475fbc7d89522bbf Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qdir.cpp31
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp14
-rw-r--r--src/corelib/io/qfilesystementry.cpp28
-rw-r--r--src/corelib/io/qfilesystementry_p.h1
4 files changed, 34 insertions, 40 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index c4dbd27aa1..e92d2f9ca7 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -953,35 +953,10 @@ QString QDir::toNativeSeparators(const QString &pathName)
QString QDir::fromNativeSeparators(const QString &pathName)
{
#if defined(Q_OS_WIN)
- const QChar nativeSeparator = u'\\';
- int i = pathName.indexOf(nativeSeparator);
- if (i != -1) {
- QString n(pathName);
- const QStringView uncPrefix(uR"(\\?\UNC\)");
- const QStringView extendedLengthPathPrefix(uR"(\\?\)");
- if (n.startsWith(uncPrefix)) {
- // Keep the initial double-slash, chop out the rest of the prefix.
- n = n.remove(2, uncPrefix.size() - 2);
- if ((i = n.indexOf(nativeSeparator)) == -1)
- return n;
- } else if (n.startsWith(extendedLengthPathPrefix)) {
- n = n.sliced(extendedLengthPathPrefix.size());
- if ((i = n.indexOf(nativeSeparator)) == -1)
- return n;
- }
-
- QChar * const data = n.data();
- data[i++] = u'/';
-
- for (; i < n.length(); ++i) {
- if (data[i] == nativeSeparator)
- data[i] = u'/';
- }
-
- return n;
- }
-#endif
+ return QFileSystemEntry::removeUncOrLongPathPrefix(pathName).replace(u'\\', u'/');
+#else
return pathName;
+#endif
}
static QString qt_cleanPath(const QString &path, bool *ok = nullptr);
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 6c4418a83b..d587e2bfd0 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -297,18 +297,8 @@ static QString readSymLink(const QFileSystemEntry &link)
const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
result = QString::fromWCharArray(PathBuffer, length);
}
- // cut-off "\\?\" and "\??\"
- if (result.size() > 4
- && result.at(0) == QLatin1Char('\\')
- && result.at(2) == QLatin1Char('?')
- && result.at(3) == QLatin1Char('\\')) {
- result = result.mid(4);
- // cut off UNC in addition when the link points at a UNC share
- // in which case we need to prepend another backslash to get \\server\share
- if (QStringView{result}.left(3) == QLatin1String("UNC")) {
- result.replace(0, 3, QLatin1Char('\\'));
- }
- }
+ // remove "\\?\", "\??\" or "\\?\UNC\"
+ result = QFileSystemEntry::removeUncOrLongPathPrefix(result);
}
free(rdb);
CloseHandle(handle);
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
index c061f58e87..bb39a46642 100644
--- a/src/corelib/io/qfilesystementry.cpp
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -288,6 +288,34 @@ bool QFileSystemEntry::isDriveRootPath(const QString &path)
&& path.at(0).isLetter() && path.at(1) == QLatin1Char(':')
&& path.at(2) == QLatin1Char('/'));
}
+
+QString QFileSystemEntry::removeUncOrLongPathPrefix(QString path)
+{
+ constexpr qsizetype minPrefixSize = 4;
+ if (path.size() < minPrefixSize)
+ return path;
+
+ auto data = path.data();
+ const auto slash = path[0];
+ if (slash != u'\\' && slash != u'/')
+ return path;
+
+ // check for "//?/" or "/??/"
+ if (data[2] == u'?' && data[3] == slash && (data[1] == slash || data[1] == u'?')) {
+ path = path.sliced(minPrefixSize);
+
+ // check for a possible "UNC/" prefix left-over
+ if (path.size() >= 4) {
+ data = path.data();
+ if (data[0] == u'U' && data[1] == u'N' && data[2] == u'C' && data[3] == slash) {
+ data[2] = slash;
+ return path.sliced(2);
+ }
+ }
+ }
+
+ return path;
+}
#endif // Q_OS_WIN
bool QFileSystemEntry::isRootPath(const QString &path)
diff --git a/src/corelib/io/qfilesystementry_p.h b/src/corelib/io/qfilesystementry_p.h
index d6b1abf498..ba0c7812e9 100644
--- a/src/corelib/io/qfilesystementry_p.h
+++ b/src/corelib/io/qfilesystementry_p.h
@@ -91,6 +91,7 @@ public:
#if defined(Q_OS_WIN)
bool isDriveRoot() const;
static bool isDriveRootPath(const QString &path);
+ static QString removeUncOrLongPathPrefix(QString path);
#endif
bool isRoot() const;