diff options
Diffstat (limited to 'src/corelib/io/qtemporaryfile.cpp')
-rw-r--r-- | src/corelib/io/qtemporaryfile.cpp | 103 |
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 |