QTemporaryFile: add private API for an overwriting rename()
In many situations, it is desireable that QTemporaryFile::rename() overwrites an existing file, such as when emulating QSaveFile because one would like more control over the temp file (such as passing it to a different process). The public API of QTemporaryFile did not allow it, making the typical Unix mktemp + mv algorithm to avoid symlink attacks unimplementable with public Qt API. QSaveFile is not a 100% replacement, because it always follows symlinks and places the temporary file beside the physical target file, keeping the symlink intact, instead of placing the tmp file beside the symlink and clobbering it, if the target happens to be one. Extract Method QTemporaryFilePrivate::rename() and add a bool overwrite parameter that causes the existing QTemporaryFileEngine::renameOverwrite() to be called in lieu of QTemporaryFileEngine::rename(). The non-atomic path via QFile::rename() is not affected. This makes the functionality available as private API, in case we need it in older branches. Task-number: QTBUG-132646 Pick-to: 6.9 6.8 6.5 5.15 Change-Id: I0d5ca96c0a1a557854582e1a565a3db0d8af2a95 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
2dfbfd5f9a
commit
a01b14f1de
@ -886,21 +886,27 @@ void QTemporaryFile::setFileTemplate(const QString &name)
|
||||
bool QTemporaryFile::rename(const QString &newName)
|
||||
{
|
||||
Q_D(QTemporaryFile);
|
||||
auto tef = static_cast<QTemporaryFileEngine *>(d->fileEngine.get());
|
||||
if (!tef || !tef->isReallyOpen() || !tef->filePathWasTemplate)
|
||||
return QFile::rename(newName);
|
||||
return d->rename(newName, false);
|
||||
}
|
||||
|
||||
unsetError();
|
||||
close();
|
||||
if (error() == QFile::NoError) {
|
||||
if (tef->rename(newName)) {
|
||||
unsetError();
|
||||
bool QTemporaryFilePrivate::rename(const QString &newName, bool overwrite)
|
||||
{
|
||||
Q_Q(QTemporaryFile);
|
||||
auto tef = static_cast<QTemporaryFileEngine *>(fileEngine.get());
|
||||
if (!tef || !tef->isReallyOpen() || !tef->filePathWasTemplate)
|
||||
return q->QFile::rename(newName);
|
||||
|
||||
q->unsetError();
|
||||
q->close();
|
||||
if (q->error() == QFile::NoError) {
|
||||
if (overwrite ? tef->renameOverwrite(newName) : tef->rename(newName)) {
|
||||
q->unsetError();
|
||||
// engine was able to handle the new name so we just reset it
|
||||
d->fileName = newName;
|
||||
fileName = newName;
|
||||
return true;
|
||||
}
|
||||
|
||||
d->setError(QFile::RenameError, tef->errorString());
|
||||
setError(QFile::RenameError, tef->errorString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
explicit QTemporaryFilePrivate(const QString &templateNameIn);
|
||||
~QTemporaryFilePrivate();
|
||||
|
||||
bool rename(const QString &newName, bool overwrite);
|
||||
|
||||
QAbstractFileEngine *engine() const override;
|
||||
void resetFileEngine() const;
|
||||
void materializeUnnamedFile();
|
||||
|
Loading…
x
Reference in New Issue
Block a user