summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qtemporaryfile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qtemporaryfile.cpp')
-rw-r--r--src/corelib/io/qtemporaryfile.cpp157
1 files changed, 90 insertions, 67 deletions
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 4b587857a8..4e48a18d91 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2017 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2017 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtemporaryfile.h"
@@ -59,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if defined(Q_OS_WIN)
typedef ushort Char;
@@ -79,19 +45,19 @@ QTemporaryFileName::QTemporaryFileName(const QString &templateName)
{
// Ensure there is a placeholder mask
QString qfilename = QDir::fromNativeSeparators(templateName);
- uint phPos = qfilename.length();
- uint phLength = 0;
+ qsizetype phPos = qfilename.size();
+ qsizetype phLength = 0;
while (phPos != 0) {
--phPos;
- if (qfilename[phPos] == QLatin1Char('X')) {
+ if (qfilename[phPos] == u'X') {
++phLength;
continue;
}
if (phLength >= 6
- || qfilename[phPos] == QLatin1Char('/')) {
+ || qfilename[phPos] == u'/') {
++phPos;
break;
}
@@ -101,15 +67,14 @@ QTemporaryFileName::QTemporaryFileName(const QString &templateName)
}
if (phLength < 6)
- qfilename.append(QLatin1String(".XXXXXX"));
+ qfilename.append(".XXXXXX"_L1);
// "Nativify" :-)
- QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName(
- QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()))
- .nativeFilePath();
+ QFileSystemEntry::NativePath filename =
+ QFileSystemEntry(QDir::cleanPath(qfilename)).nativeFilePath();
// Find mask in native path
- phPos = filename.length();
+ phPos = filename.size();
phLength = 0;
while (phPos != 0) {
--phPos;
@@ -143,8 +108,8 @@ QTemporaryFileName::QTemporaryFileName(const QString &templateName)
QFileSystemEntry::NativePath QTemporaryFileName::generateNext()
{
Q_ASSERT(length != 0);
- Q_ASSERT(pos < path.length());
- Q_ASSERT(length <= path.length() - pos);
+ Q_ASSERT(pos < path.size());
+ Q_ASSERT(length <= path.size() - pos);
Char *const placeholderStart = (Char *)path.data() + pos;
Char *const placeholderEnd = placeholderStart + length;
@@ -191,13 +156,13 @@ QFileSystemEntry::NativePath QTemporaryFileName::generateNext()
return path;
}
-#ifndef QT_NO_TEMPORARYFILE
+#if QT_CONFIG(temporaryfile)
/*!
\internal
Generates a unique file path from the template \a templ and creates a new
- file based based on those parameters: the \c templ.length characters in \c
+ file based on those parameters: the \c templ.length characters in \c
templ.path starting at \c templ.pos will be replaced by a random sequence of
characters. \a mode specifies the file mode bits (not used on Windows).
@@ -219,8 +184,9 @@ static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &t
const DWORD shareMode = (flags & QTemporaryFileEngine::Win32NonShared)
? 0u : (FILE_SHARE_READ | FILE_SHARE_WRITE);
+ const DWORD extraAccessFlags = (flags & QTemporaryFileEngine::Win32NonShared) ? DELETE : 0;
file = CreateFile((const wchar_t *)path.constData(),
- GENERIC_READ | GENERIC_WRITE,
+ GENERIC_READ | GENERIC_WRITE | extraAccessFlags,
shareMode, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
@@ -425,6 +391,18 @@ bool QTemporaryFileEngine::renameOverwrite(const QString &newName)
QFSFileEngine::close();
return ok;
}
+#ifdef Q_OS_WIN
+ if (flags & Win32NonShared) {
+ QFileSystemEntry newEntry(newName, QFileSystemEntry::FromInternalPath());
+ bool ok = d_func()->nativeRenameOverwrite(newEntry);
+ QFSFileEngine::close();
+ if (ok) {
+ // Match what QFSFileEngine::renameOverwrite() does
+ setFileEntry(std::move(newEntry));
+ }
+ return ok;
+ }
+#endif
QFSFileEngine::close();
return QFSFileEngine::renameOverwrite(newName);
}
@@ -440,7 +418,7 @@ bool QTemporaryFileEngine::close()
QString QTemporaryFileEngine::fileName(QAbstractFileEngine::FileName file) const
{
if (isUnnamedFile()) {
- if (file == AbsoluteLinkTarget) {
+ if (file == AbsoluteLinkTarget || file == RawLinkPath) {
// we know our file isn't (won't be) a symlink
return QString();
}
@@ -576,9 +554,9 @@ QString QTemporaryFilePrivate::defaultTemplateName()
baseName = QCoreApplication::applicationName();
if (baseName.isEmpty())
#endif
- baseName = QLatin1String("qt_temp");
+ baseName = "qt_temp"_L1;
- return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String(".XXXXXX");
+ return QDir::tempPath() + u'/' + baseName + ".XXXXXX"_L1;
}
//************* QTemporaryFile
@@ -620,6 +598,9 @@ QString QTemporaryFilePrivate::defaultTemplateName()
be placed into the temporary path as returned by QDir::tempPath().
If you specify your own filename, a relative file path will not be placed in the
temporary directory by default, but be relative to the current working directory.
+ It is important to specify the correct directory if the rename() function will be
+ called, as QTemporaryFile can only rename files within the same volume / filesystem
+ as the temporary file itself was created on.
Specified filenames can contain the following template \c XXXXXX
(six upper case "X" characters), which will be replaced by the
@@ -662,6 +643,12 @@ QTemporaryFile::QTemporaryFile()
}
/*!
+ \fn QTemporaryFile::QTemporaryFile(const std::filesystem::path &templateName, QObject *parent)
+ \overload
+ \since 6.7
+*/
+
+/*!
Constructs a QTemporaryFile with a template filename of \a
templateName. Upon opening the temporary file this will be used to create
a unique filename.
@@ -671,7 +658,11 @@ QTemporaryFile::QTemporaryFile()
If \a templateName is a relative path, the path will be relative to the
current working directory. You can use QDir::tempPath() to construct \a
- templateName if you want use the system's temporary directory.
+ templateName if you want use the system's temporary directory. It is
+ important to specify the correct directory if the rename() function will be
+ called, as QTemporaryFile can only rename files within the same volume /
+ filesystem as the temporary file itself was created on.
+
\sa open(), fileTemplate()
*/
@@ -704,7 +695,10 @@ QTemporaryFile::QTemporaryFile(QObject *parent)
If \a templateName is a relative path, the path will be relative to the
current working directory. You can use QDir::tempPath() to construct \a
- templateName if you want use the system's temporary directory.
+ templateName if you want use the system's temporary directory. It is
+ important to specify the correct directory if the rename() function will be
+ called, as QTemporaryFile can only rename files within the same volume /
+ filesystem as the temporary file itself was created on.
\sa open(), fileTemplate()
*/
@@ -737,7 +731,7 @@ QTemporaryFile::~QTemporaryFile()
return true upon success and will set the fileName() to the unique
filename used.
- \sa fileName()
+ \sa fileName(), QT_USE_NODISCARD_FILE_OPEN
*/
/*!
@@ -816,6 +810,12 @@ QString QTemporaryFile::fileTemplate() const
}
/*!
+ \fn void QTemporaryFile::setFileTemplate(const std::filesystem::path &name)
+ \overload
+ \since 6.7
+*/
+
+/*!
Sets the static portion of the file name to \a name. If the file
template contains XXXXXX that will automatically be replaced with
the unique part of the filename, otherwise a filename will be
@@ -823,7 +823,10 @@ QString QTemporaryFile::fileTemplate() const
If \a name contains a relative file path, the path will be relative to the
current working directory. You can use QDir::tempPath() to construct \a
- name if you want use the system's temporary directory.
+ name if you want use the system's temporary directory. It is important to
+ specify the correct directory if the rename() function will be called, as
+ QTemporaryFile can only rename files within the same volume / filesystem as
+ the temporary file itself was created on.
\sa fileTemplate()
*/
@@ -834,11 +837,28 @@ void QTemporaryFile::setFileTemplate(const QString &name)
}
/*!
- \internal
+ \fn bool QTemporaryFile::rename(const std::filesystem::path &newName)
+ \overload
+ \since 6.7
+*/
- This is just a simplified version of QFile::rename() because we know a few
- extra details about what kind of file we have. The documentation is hidden
- from the user because QFile::rename() should be enough.
+/*!
+ Renames the current temporary file to \a newName and returns true if it
+ succeeded.
+
+ This function has an important difference compared to QFile::rename(): it
+ will not perform a copy+delete if the low-level system call to rename the
+ file fails, something that could happen if \a newName specifies a file in a
+ different volume or filesystem than the temporary file was created on. In
+ other words, QTemporaryFile only supports atomic file renaming.
+
+ This functionality is intended to support materializing the destination
+ file with all contents already present, so another process cannot see an
+ incomplete file in the process of being written. The \l QSaveFile class can
+ be used for a similar purpose too, particularly if the destination file is
+ not temporary.
+
+ \sa QSaveFile, QSaveFile::commit(), QFile::rename()
*/
bool QTemporaryFile::rename(const QString &newName)
{
@@ -853,7 +873,6 @@ bool QTemporaryFile::rename(const QString &newName)
if (tef->rename(newName)) {
unsetError();
// engine was able to handle the new name so we just reset it
- tef->setFileName(newName);
d->fileName = newName;
return true;
}
@@ -870,7 +889,11 @@ bool QTemporaryFile::rename(const QString &newName)
Works on the given \a fileName rather than an existing QFile
object.
*/
-
+/*!
+ \fn QTemporaryFile *QTemporaryFile::createNativeFile(const std::filesystem::path &fileName)
+ \overload
+ \since 6.7
+*/
/*!
If \a file is not already a native file, then a QTemporaryFile is created
@@ -958,7 +981,7 @@ bool QTemporaryFile::open(OpenMode flags)
return false;
}
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
QT_END_NAMESPACE