diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2017-06-29 14:53:05 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2017-08-04 17:30:03 +0000 |
commit | 3d6cbe3409d52e5ca63b8d04261b8fd531d89c98 (patch) | |
tree | d4747085290bb913448152b2b68fb96bf96ad3e0 /src/corelib/io | |
parent | 3981a1f440914e8108af3d854a1b01dd596a8a0e (diff) |
Long live QTemporaryFileName!
So we can use it in QTemporaryFile, QTemporaryDir and QFile::rename()
[ChangeLog][QtCore][QTemporaryDir] The class now supports the "XXXXXX"
replacement token anywhere in the template, not just at the end. This
behavior is similar to what QTemporaryFile supports.
Change-Id: I1eba2b016de74620bfc8fffd14ccb645729de170
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qtemporarydir.cpp | 83 | ||||
-rw-r--r-- | src/corelib/io/qtemporaryfile.cpp | 144 | ||||
-rw-r--r-- | src/corelib/io/qtemporaryfile_p.h | 19 |
3 files changed, 95 insertions, 151 deletions
diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp index ffaee9c683..2779246c5b 100644 --- a/src/corelib/io/qtemporarydir.cpp +++ b/src/corelib/io/qtemporarydir.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -44,22 +44,15 @@ #include "qdiriterator.h" #include "qplatformdefs.h" +#include "private/qtemporaryfile_p.h" #include <QDebug> #include <QPair> +#include <QRandomGenerator> #if defined(QT_BUILD_CORE_LIB) #include "qcoreapplication.h" #endif -#if !defined(Q_OS_QNX) && !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) -# define USE_SYSTEM_MKDTEMP -#endif - -#include <stdlib.h> // mkdtemp -#ifndef USE_SYSTEM_MKDTEMP -#include <private/qfilesystemengine_p.h> -#endif - #if !defined(Q_OS_WIN) #include <errno.h> #endif @@ -102,38 +95,12 @@ static QString defaultTemplateName() return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX"); } -#ifndef USE_SYSTEM_MKDTEMP -static int nextRand(int &v) -{ - int r = v % 62; - v /= 62; - if (v < 62) - v = qrand(); - return r; -} - -QPair<QString, bool> q_mkdtemp(QString templateName) +void QTemporaryDirPrivate::create(const QString &templateName) { - Q_ASSERT(templateName.endsWith(QLatin1String("XXXXXX"))); - - static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - - const int length = templateName.size(); - - QChar *XXXXXX = templateName.data() + length - 6; - + QTemporaryFileName tfn(templateName); for (int i = 0; i < 256; ++i) { - int v = qrand(); - - /* Fill in the random bits. */ - 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); + tfn.generateNext(); + QFileSystemEntry fileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath()); if (QFileSystemEngine::createDirectory(fileSystemEntry, false)) { QSystemError error; QFileSystemEngine::setPermissions(fileSystemEntry, @@ -145,7 +112,9 @@ QPair<QString, bool> q_mkdtemp(QString templateName) qWarning() << "Unable to remove unused directory" << templateName; continue; } - return qMakePair(templateName, true); + success = true; + pathOrError = fileSystemEntry.filePath(); + return; } # ifdef Q_OS_WIN const int exists = ERROR_ALREADY_EXISTS; @@ -155,36 +124,10 @@ QPair<QString, bool> q_mkdtemp(QString templateName) int code = errno; # endif if (code != exists) - return qMakePair(qt_error_string(code), false); + break; } - return qMakePair(qt_error_string(), false); -} - -#else // !USE_SYSTEM_MKDTEMP - -QPair<QString, bool> q_mkdtemp(char *templateName) -{ - bool ok = (mkdtemp(templateName) != 0); - return qMakePair(ok ? QFile::decodeName(templateName) : qt_error_string(), ok); -} - -#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; + pathOrError = qt_error_string(); + success = false; } //************* QTemporaryDir diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 1ff7edb8e0..aa9ad66eaa 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -39,8 +39,6 @@ #include "qtemporaryfile.h" -#ifndef QT_NO_TEMPORARYFILE - #include "qplatformdefs.h" #include "qrandom.h" #include "private/qtemporaryfile_p.h" @@ -76,12 +74,63 @@ typedef char Latin1Char; typedef int NativeFileHandle; #endif -namespace { -struct NativeTemplate { - QFileSystemEntry::NativePath path; - qssize_t pos; - qssize_t length; -}; +QTemporaryFileName::QTemporaryFileName(const QString &templateName) +{ + // Ensure there is a placeholder mask + QString qfilename = templateName; + uint phPos = qfilename.length(); + uint phLength = 0; + + while (phPos != 0) { + --phPos; + + if (qfilename[phPos] == QLatin1Char('X')) { + ++phLength; + continue; + } + + if (phLength >= 6 + || qfilename[phPos] == QLatin1Char('/')) { + ++phPos; + break; + } + + // start over + phLength = 0; + } + + if (phLength < 6) + qfilename.append(QLatin1String(".XXXXXX")); + + // "Nativify" :-) + QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName( + QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath())) + .nativeFilePath(); + + // Find mask in native path + phPos = filename.length(); + phLength = 0; + while (phPos != 0) { + --phPos; + + if (filename[phPos] == Latin1Char('X')) { + ++phLength; + continue; + } + + if (phLength >= 6) { + ++phPos; + break; + } + + // start over + phLength = 0; + } + + Q_ASSERT(phLength >= 6); + path = filename; + pos = phPos; + length = phLength; } // The following code is a heavily modified version, originally copyright: @@ -120,12 +169,8 @@ struct NativeTemplate { Generates a unique file path from the template \a templ and returns it. The path in \c templ.path is modified. */ -static QFileSystemEntry::NativePath generateNameFromTemplate(NativeTemplate &templ) +QFileSystemEntry::NativePath QTemporaryFileName::generateNext() { - QFileSystemEntry::NativePath &path = templ.path; - qssize_t pos = templ.pos; - qssize_t length = templ.length; - Q_ASSERT(length != 0); Q_ASSERT(pos < path.length()); Q_ASSERT(length <= path.length() - pos); @@ -159,6 +204,8 @@ static QFileSystemEntry::NativePath generateNameFromTemplate(NativeTemplate &tem return path; } +#ifndef QT_NO_TEMPORARYFILE + /*! \internal @@ -172,13 +219,13 @@ static QFileSystemEntry::NativePath generateNameFromTemplate(NativeTemplate &tem condition in \a error. In both cases, the string in \a templ will be changed and contain the generated path name. */ -static bool createFileFromTemplate(NativeFileHandle &file, NativeTemplate &templ, +static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &templ, quint32 mode, QSystemError &error) { const int maxAttempts = 16; for (int attempt = 0; attempt < maxAttempts; ++attempt) { // Atomically create file and obtain handle - const QFileSystemEntry::NativePath &path = generateNameFromTemplate(templ); + const QFileSystemEntry::NativePath &path = templ.generateNext(); #if defined(Q_OS_WIN) Q_UNUSED(mode); @@ -261,62 +308,6 @@ void QTemporaryFileEngine::setFileName(const QString &file) QFSFileEngine::setFileName(file); } -static NativeTemplate makeNativeTemplate(QString qfilename) -{ - // Ensure there is a placeholder mask - uint phPos = qfilename.length(); - uint phLength = 0; - - while (phPos != 0) { - --phPos; - - if (qfilename[phPos] == QLatin1Char('X')) { - ++phLength; - continue; - } - - if (phLength >= 6 - || qfilename[phPos] == QLatin1Char('/')) { - ++phPos; - break; - } - - // start over - phLength = 0; - } - - if (phLength < 6) - qfilename.append(QLatin1String(".XXXXXX")); - - // "Nativify" :-) - QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName( - QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath())) - .nativeFilePath(); - - // Find mask in native path - phPos = filename.length(); - phLength = 0; - while (phPos != 0) { - --phPos; - - if (filename[phPos] == Latin1Char('X')) { - ++phLength; - continue; - } - - if (phLength >= 6) { - ++phPos; - break; - } - - // start over - phLength = 0; - } - - Q_ASSERT(phLength >= 6); - return {filename, phPos, phLength}; -} - bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) { Q_D(QFSFileEngine); @@ -327,8 +318,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) if (!filePathIsTemplate) return QFSFileEngine::open(openMode); - QString qfilename = templateName; - NativeTemplate templ = makeNativeTemplate(qfilename); + QTemporaryFileName tfn(templateName); QSystemError error; #if defined(Q_OS_WIN) @@ -337,12 +327,12 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) NativeFileHandle &file = d->fd; #endif - if (!createFileFromTemplate(file, templ, fileMode, error)) { + if (!createFileFromTemplate(file, tfn, fileMode, error)) { setError(QFile::OpenError, error.toString()); return false; } - d->fileEntry = QFileSystemEntry(templ.path, QFileSystemEntry::FromNativePath()); + d->fileEntry = QFileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath()); #if !defined(Q_OS_WIN) || defined(Q_OS_WINRT) d->closeFileHandle = true; @@ -815,10 +805,10 @@ bool QTemporaryFile::open(OpenMode flags) return false; } -QT_END_NAMESPACE - #endif // QT_NO_TEMPORARYFILE +QT_END_NAMESPACE + #ifndef QT_NO_QOBJECT #include "moc_qtemporaryfile.cpp" #endif diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h index 2db07c36bc..97ffc48507 100644 --- a/src/corelib/io/qtemporaryfile_p.h +++ b/src/corelib/io/qtemporaryfile_p.h @@ -53,14 +53,25 @@ #include <QtCore/qglobal.h> -#ifndef QT_NO_TEMPORARYFILE - #include "private/qfsfileengine_p.h" #include "private/qfilesystemengine_p.h" #include "private/qfile_p.h" +#include "qtemporaryfile.h" QT_BEGIN_NAMESPACE +struct QTemporaryFileName +{ + QFileSystemEntry::NativePath path; + qssize_t pos; + qssize_t length; + + QTemporaryFileName(const QString &templateName); + QFileSystemEntry::NativePath generateNext(); +}; + +#ifndef QT_NO_TEMPORARYFILE + class QTemporaryFilePrivate : public QFilePrivate { Q_DECLARE_PUBLIC(QTemporaryFile) @@ -120,9 +131,9 @@ public: bool filePathWasTemplate; }; -QT_END_NAMESPACE - #endif // QT_NO_TEMPORARYFILE +QT_END_NAMESPACE + #endif /* QTEMPORARYFILE_P_H */ |