From 7e5e7eeaa1418d959906cdf9d717c984c9fc7a7e Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 28 May 2014 22:53:57 +0200 Subject: QSaveFile: follow symbolic links [ChangeLog][QtCore][QSaveFile] Now follows symbolic links while writing to a link instead of replacing the link with the contents. Change-Id: I5afd519cb9f96ae68fa4c23c33a18de75671a301 Reviewed-by: Oswald Buddenhagen Reviewed-by: David Faure --- src/corelib/io/qsavefile.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/corelib/io/qsavefile.cpp') diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index 2b901c7ccd..05d7687007 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -205,14 +205,26 @@ bool QSaveFile::open(OpenMode mode) d->writeError = QFileDevice::WriteError; return false; } - d->fileEngine = new QTemporaryFileEngine(d->fileName); + + // Resolve symlinks. Don't use QFileInfo::canonicalFilePath so it still give the expected + // target even if the file does not exist + d->finalFileName = d->fileName; + if (existingFile.isSymLink()) { + int maxDepth = 128; + while (--maxDepth && existingFile.isSymLink()) + existingFile.setFile(existingFile.symLinkTarget()); + if (maxDepth > 0) + d->finalFileName = existingFile.filePath(); + } + + d->fileEngine = new QTemporaryFileEngine(d->finalFileName); // Same as in QFile: QIODevice provides the buffering, so there's no need to request it from the file engine. if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) { QFileDevice::FileError err = d->fileEngine->error(); #ifdef Q_OS_UNIX if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) { delete d->fileEngine; - d->fileEngine = QAbstractFileEngine::create(d->fileName); + d->fileEngine = QAbstractFileEngine::create(d->finalFileName); if (d->fileEngine->open(mode | QIODevice::Unbuffered)) { d->useTemporaryFile = false; QFileDevice::open(mode); @@ -285,7 +297,7 @@ bool QSaveFile::commit() // atomically replace old file with new file // Can't use QFile::rename for that, must use the file engine directly Q_ASSERT(d->fileEngine); - if (!d->fileEngine->renameOverwrite(d->fileName)) { + if (!d->fileEngine->renameOverwrite(d->finalFileName)) { d->setError(d->fileEngine->error(), d->fileEngine->errorString()); d->fileEngine->remove(); delete d->fileEngine; -- cgit v1.2.3