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.cpp103
1 files changed, 80 insertions, 23 deletions
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index a0238eeeb8..4e48a18d91 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -45,8 +45,8 @@ 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;
@@ -70,12 +70,11 @@ QTemporaryFileName::QTemporaryFileName(const QString &templateName)
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;
@@ -109,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;
@@ -157,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).
@@ -185,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);
@@ -391,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);
}
@@ -406,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();
}
@@ -586,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
@@ -628,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.
@@ -637,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()
*/
@@ -670,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()
*/
@@ -703,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
*/
/*!
@@ -782,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
@@ -789,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()
*/
@@ -800,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)
{
@@ -819,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;
}
@@ -836,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
@@ -924,7 +981,7 @@ bool QTemporaryFile::open(OpenMode flags)
return false;
}
-#endif // QT_NO_TEMPORARYFILE
+#endif // QT_CONFIG(temporaryfile)
QT_END_NAMESPACE