diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-07-19 10:18:39 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2016-07-20 07:31:18 +0000 |
commit | c14c149b51a1c7bf01e4e039f6e8cf1819e37ca6 (patch) | |
tree | eefa8c93d9d50d5a02dfa71d26bf05ae4066be68 /src/corelib | |
parent | b2029e9ca6c1645e85cbada1b09ba63fd1ee31ed (diff) |
Fix QTemporaryDir to handle Unicode characters on Windows
For platforms not providing mkdtemp(), QTemporaryDir relied on an implementation
of q_mkdtemp() operating on char *, converting back and forth using
QFile::encodeName()/decodeName() when passing the name to QFileSystemEngine.
This caused failures on Windows (which uses "System"/Latin1 encoding)
for names containing characters outside the Latin1 space.
Reimplement q_mkdtemp() to operate on QString, which avoids the conversions
altogether and also enables the use of larger character spaces for the
pattern.
Add tests.
Task-number: QTBUG-54810
Change-Id: Ie4323ad73b5beb8a1b8ab81425f73d03c626d58a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/io/qtemporarydir.cpp | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp index 71436c6497..d869318e35 100644 --- a/src/corelib/io/qtemporarydir.cpp +++ b/src/corelib/io/qtemporarydir.cpp @@ -44,8 +44,12 @@ #include "qcoreapplication.h" #endif +#if !defined(Q_OS_QNX) && !defined(Q_OS_WIN) &&!defined(Q_OS_ANDROID) +# define USE_SYSTEM_MKDTEMP +#endif + #include <stdlib.h> // mkdtemp -#if defined(Q_OS_QNX) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) +#ifndef USE_SYSTEM_MKDTEMP #include <private/qfilesystemengine_p.h> #endif @@ -91,8 +95,7 @@ static QString defaultTemplateName() return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX"); } -#if defined(Q_OS_QNX ) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) - +#ifndef USE_SYSTEM_MKDTEMP static int nextRand(int &v) { int r = v % 62; @@ -102,30 +105,28 @@ static int nextRand(int &v) return r; } -QPair<QString, bool> q_mkdtemp(char *templateName) +QPair<QString, bool> q_mkdtemp(QString templateName) { - static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Q_ASSERT(templateName.endsWith(QLatin1String("XXXXXX"))); - const size_t length = strlen(templateName); + static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - char *XXXXXX = templateName + length - 6; + const int length = templateName.size(); - Q_ASSERT((length >= 6u) && strncmp(XXXXXX, "XXXXXX", 6) == 0); + QChar *XXXXXX = templateName.data() + length - 6; for (int i = 0; i < 256; ++i) { int v = qrand(); /* Fill in the random bits. */ - XXXXXX[0] = letters[nextRand(v)]; - XXXXXX[1] = letters[nextRand(v)]; - XXXXXX[2] = letters[nextRand(v)]; - XXXXXX[3] = letters[nextRand(v)]; - XXXXXX[4] = letters[nextRand(v)]; - XXXXXX[5] = letters[v % 62]; - - QString templateNameStr = QFile::decodeName(templateName); - - QFileSystemEntry fileSystemEntry(templateNameStr); + XXXXXX[0] = QLatin1Char(letters[nextRand(v)]); + XXXXXX[1] = QLatin1Char(letters[nextRand(v)]); + XXXXXX[2] = QLatin1Char(letters[nextRand(v)]); + XXXXXX[3] = QLatin1Char(letters[nextRand(v)]); + XXXXXX[4] = QLatin1Char(letters[nextRand(v)]); + XXXXXX[5] = QLatin1Char(letters[v % 62]); + + QFileSystemEntry fileSystemEntry(templateName); if (QFileSystemEngine::createDirectory(fileSystemEntry, false)) { QSystemError error; QFileSystemEngine::setPermissions(fileSystemEntry, @@ -134,10 +135,10 @@ QPair<QString, bool> q_mkdtemp(char *templateName) QFile::ExeOwner, error); if (error.error() != 0) { if (!QFileSystemEngine::removeDirectory(fileSystemEntry, false)) - qWarning() << "Unable to remove unused directory" << templateNameStr; + qWarning() << "Unable to remove unused directory" << templateName; continue; } - return qMakePair(QFile::decodeName(templateName), true); + return qMakePair(templateName, true); } # ifdef Q_OS_WIN const int exists = ERROR_ALREADY_EXISTS; @@ -152,7 +153,7 @@ QPair<QString, bool> q_mkdtemp(char *templateName) return qMakePair(qt_error_string(), false); } -#else // defined(Q_OS_QNX ) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) +#else // !USE_SYSTEM_MKDTEMP QPair<QString, bool> q_mkdtemp(char *templateName) { @@ -160,14 +161,21 @@ QPair<QString, bool> q_mkdtemp(char *templateName) return qMakePair(ok ? QFile::decodeName(templateName) : qt_error_string(), ok); } -#endif +#endif // USE_SYSTEM_MKDTEMP void QTemporaryDirPrivate::create(const QString &templateName) { +#ifndef USE_SYSTEM_MKDTEMP + QString buffer = templateName; + if (!buffer.endsWith(QLatin1String("XXXXXX"))) + buffer += QLatin1String("XXXXXX"); + const QPair<QString, bool> result = q_mkdtemp(buffer); +#else // !USE_SYSTEM_MKDTEMP QByteArray buffer = QFile::encodeName(templateName); if (!buffer.endsWith("XXXXXX")) buffer += "XXXXXX"; QPair<QString, bool> result = q_mkdtemp(buffer.data()); // modifies buffer +#endif // USE_SYSTEM_MKDTEMP pathOrError = result.first; success = result.second; } |