summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@qt.io>2021-05-03 14:40:53 +0200
committerKarsten Heimrich <karsten.heimrich@qt.io>2021-05-11 13:22:44 +0200
commitec9e85656339dbc9e6918a1369c981cece7bc97d (patch)
tree8129c385cfb4cacd6f86b3cbdb2c1ef504fa5ab0
parenta120d11cb5506ef0a5535e790f23d49595fb8857 (diff)
Fix QSaveFile and QTemporaryFile issues with windows network shares
The commit amends commit 3966b571 to take UNC prefix into account as well. Fixes the weird file name output as reported in QTBUG-74291 and QTBUG-83365. Replace manual separator normalizing in qt_cleanPath(), this is another spot where UNC prefix handling needs to be applied. Also make QTemporaryFile operate on '/' as file separators to fix creating both file types with native path separators on network shares. Fixes: QTBUG-74291 Fixes: QTBUG-76228 Fixes: QTBUG-83365 Pick-to: 5.15 6.0 6.1 Change-Id: Iff8d26b994bf4194c074cd5c996cda3934297fa5 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qdir.cpp33
-rw-r--r--src/corelib/io/qfilesystementry.cpp6
-rw-r--r--src/corelib/io/qtemporaryfile.cpp2
-rw-r--r--tests/auto/corelib/io/qdir/tst_qdir.cpp4
-rw-r--r--tests/auto/corelib/io/qfilesystementry/tst_qfilesystementry.cpp13
-rw-r--r--tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp6
-rw-r--r--tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp6
7 files changed, 45 insertions, 25 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 4016c12f13..7f58569a28 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -953,22 +953,29 @@ QString QDir::toNativeSeparators(const QString &pathName)
QString QDir::fromNativeSeparators(const QString &pathName)
{
#if defined(Q_OS_WIN)
- int i = pathName.indexOf(QLatin1Char('\\'));
+ const QChar nativeSeparator = u'\\';
+ int i = pathName.indexOf(nativeSeparator);
if (i != -1) {
QString n(pathName);
- if (n.startsWith(QLatin1String("\\\\?\\"))) {
- n.remove(0, 4);
- i = n.indexOf(QLatin1Char('\\'));
- if (i == -1)
+ 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++] = QLatin1Char('/');
+ data[i++] = u'/';
for (; i < n.length(); ++i) {
- if (data[i] == QLatin1Char('\\'))
- data[i] = QLatin1Char('/');
+ if (data[i] == nativeSeparator)
+ data[i] = u'/';
}
return n;
@@ -2310,16 +2317,8 @@ static QString qt_cleanPath(const QString &path, bool *ok)
{
if (path.isEmpty())
return path;
- QString name = path;
-#if defined (Q_OS_WIN)
- if (name.startsWith(QLatin1String("\\\\?\\")))
- name.remove(0, 4);
-#endif
-
- QChar dir_separator = QDir::separator();
- if (dir_separator != QLatin1Char('/'))
- name.replace(dir_separator, QLatin1Char('/'));
+ QString name = QDir::fromNativeSeparators(path);
QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths ? QDirPrivate::AllowUncPaths : QDirPrivate::DefaultNormalization, ok);
// Strip away last slash except for root directories
diff --git a/src/corelib/io/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp
index 9b474b25b1..83f8a86439 100644
--- a/src/corelib/io/qfilesystementry.cpp
+++ b/src/corelib/io/qfilesystementry.cpp
@@ -142,12 +142,6 @@ void QFileSystemEntry::resolveFilePath() const
if (m_filePath.isEmpty() && !m_nativeFilePath.isEmpty()) {
#if defined(QFILESYSTEMENTRY_NATIVE_PATH_IS_UTF16)
m_filePath = QDir::fromNativeSeparators(m_nativeFilePath);
-#ifdef Q_OS_WIN
- if (m_filePath.startsWith(QLatin1String("//?/UNC/")))
- m_filePath = m_filePath.remove(2,6);
- if (m_filePath.startsWith(QLatin1String("//?/")))
- m_filePath = m_filePath.remove(0,4);
-#endif
#else
m_filePath = QDir::fromNativeSeparators(QFile::decodeName(m_nativeFilePath));
#endif
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index bdd128a88c..1e7e67b625 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -78,7 +78,7 @@ typedef int NativeFileHandle;
QTemporaryFileName::QTemporaryFileName(const QString &templateName)
{
// Ensure there is a placeholder mask
- QString qfilename = templateName;
+ QString qfilename = QDir::fromNativeSeparators(templateName);
uint phPos = qfilename.length();
uint phLength = 0;
diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp
index f71bc7e7eb..cfb25d7acb 100644
--- a/tests/auto/corelib/io/qdir/tst_qdir.cpp
+++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp
@@ -1269,6 +1269,8 @@ tst_QDir::cleanPath_data()
QTest::newRow("unc-server-up") << "//server/path/.." << "//server";
QTest::newRow("unc-server-above-root") << "//server/.." << "//server/..";
QTest::newRow("longpath") << "\\\\?\\d:\\" << "d:/";
+ QTest::newRow("unc-network-share") << uR"(\\?\UNC\localhost\c$\tmp.txt)"_qs
+ << u"//localhost/c$/tmp.txt"_qs;
#else
QTest::newRow("data15") << "//c:/foo" << "/c:/foo";
#endif // non-windows
@@ -1744,6 +1746,8 @@ void tst_QDir::nativeSeparators()
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("/")), QString("/"));
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\")), QString("/"));
QCOMPARE(QDir::fromNativeSeparators(QLatin1String("\\\\?\\C:\\")), QString("C:/"));
+ QCOMPARE(QDir::fromNativeSeparators(uR"(\\?\UNC\localhost\c$\tmp.txt)"_qs),
+ u"//localhost/c$/tmp.txt"_qs);
#else
QCOMPARE(QDir::toNativeSeparators(QLatin1String("/")), QString("/"));
QCOMPARE(QDir::toNativeSeparators(QLatin1String("\\")), QString("\\"));
diff --git a/tests/auto/corelib/io/qfilesystementry/tst_qfilesystementry.cpp b/tests/auto/corelib/io/qfilesystementry/tst_qfilesystementry.cpp
index 30c38b20f9..a9ae848251 100644
--- a/tests/auto/corelib/io/qfilesystementry/tst_qfilesystementry.cpp
+++ b/tests/auto/corelib/io/qfilesystementry/tst_qfilesystementry.cpp
@@ -104,6 +104,17 @@ void tst_QFileSystemEntry::getSetCheck_data()
<< QString("A:dir\\without\\leading\\backslash.bat")
<< absPrefix + QString("A:\\dir\\without\\leading\\backslash.bat")
<< "A:dir/without/leading/backslash.bat" << "backslash.bat" << "backslash" << "backslash" << "bat" << "bat" << false << false;
+
+ QTest::newRow("longpath")
+ << uR"(\\?\D:\)"_qs
+ << absPrefix + QLatin1String(R"(D:\)")
+ << "D:/" << "" << "" << "" << "" << "" << true << false;
+
+ QTest::newRow("uncprefix")
+ << uR"(\\?\UNC\localhost\C$\tmp.txt)"_qs
+ << absPrefix + QLatin1String(R"(UNC\localhost\C$\tmp.txt)")
+ << "//localhost/C$/tmp.txt" << "tmp.txt" << "tmp" << "tmp" << "txt" << "txt" << true
+ << false;
}
void tst_QFileSystemEntry::getSetCheck()
@@ -137,7 +148,7 @@ void tst_QFileSystemEntry::getSetCheck()
QCOMPARE(entry2.isRelative(), relative);
QCOMPARE(entry2.filePath(), filepath);
// Since this entry was created using the native path,
- // the object shouldnot change nativeFilePath.
+ // the object shouldn't change nativeFilePath.
QCOMPARE(entry2.nativeFilePath(), nativeFilePath);
QCOMPARE(entry2.fileName(), filename);
QCOMPARE(entry2.baseName(), baseName);
diff --git a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
index 4969c0e6e3..db07f80495 100644
--- a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
+++ b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
@@ -157,6 +157,12 @@ void tst_QTemporaryDir::fileTemplate_data()
prefix = "qt_" + hanTestText();
QTest::newRow("Chinese") << (prefix + "XXXXXX" + umlautTestText()) << prefix << umlautTestText();
}
+
+#ifdef Q_OS_WIN
+ const auto tmp = QDir::toNativeSeparators(QDir::tempPath()).sliced(QDir::rootPath().size());
+ QTest::newRow("UNC") << uR"(\\localhost\C$\)"_qs + tmp + uR"(\UNC.XXXXXX.tmpDir)"_qs
+ << "UNC." << ".tmpDir";
+#endif
}
void tst_QTemporaryDir::fileTemplate()
diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
index 331558255f..bb938e9695 100644
--- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
+++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
@@ -206,6 +206,12 @@ void tst_QTemporaryFile::fileTemplate_data()
prefix = "qt_" + hanTestText();
QTest::newRow("Chinese characters") << (prefix + "XXXXXX") << prefix << QString() << QString();
}
+
+#ifdef Q_OS_WIN
+ const auto tmp = QDir::toNativeSeparators(QDir::tempPath()).sliced(QDir::rootPath().size());
+ QTest::newRow("UNC") << uR"(\\localhost\C$\)"_qs + tmp + uR"(\QTBUG-74291.XXXXXX.tmpFile)"_qs
+ << "QTBUG-74291." << ".tmpFile" << "";
+#endif
}
void tst_QTemporaryFile::fileTemplate()