diff options
Diffstat (limited to 'src/corelib/io/qsavefile.cpp')
-rw-r--r-- | src/corelib/io/qsavefile.cpp | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index 3f45ca5f91..56934a9a0f 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -184,7 +184,8 @@ void QSaveFile::setFileName(const QString &name) Important: the \a mode must include QIODevice::WriteOnly. It may also have additional flags, such as QIODevice::Text and QIODevice::Unbuffered. - QIODevice::ReadWrite and QIODevice::Append are not supported at the moment. + QIODevice::ReadWrite, QIODevice::Append, QIODevice::NewOnly and + QIODevice::ExistingOnly are not supported at the moment. \sa QIODevice::OpenMode, setFileName() */ @@ -201,7 +202,8 @@ bool QSaveFile::open(OpenMode mode) return false; } // In the future we could implement ReadWrite by copying from the existing file to the temp file... - if ((mode & ReadOnly) || (mode & Append)) { + // The implications of NewOnly and ExistingOnly when used with QSaveFile need to be considered carefully... + if (mode & (ReadOnly | Append | NewOnly | ExistingOnly)) { qWarning("QSaveFile::open: Unsupported open mode 0x%x", int(mode)); return false; } @@ -231,7 +233,38 @@ bool QSaveFile::open(OpenMode mode) d->finalFileName = existingFile.filePath(); } - d->fileEngine = new QTemporaryFileEngine; + auto openDirectly = [&]() { + d->fileEngine = QAbstractFileEngine::create(d->finalFileName); + if (d->fileEngine->open(mode | QIODevice::Unbuffered)) { + d->useTemporaryFile = false; + QFileDevice::open(mode); + return true; + } + return false; + }; + +#ifdef Q_OS_WIN + // check if it is an Alternate Data Stream + if (d->finalFileName == d->fileName && d->fileName.indexOf(QLatin1Char(':'), 2) > 1) { + // yes, we can't rename onto it... + if (d->directWriteFallback) { + if (openDirectly()) + return true; + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); + delete d->fileEngine; + d->fileEngine = 0; + } else { + QString msg = + QSaveFile::tr("QSaveFile cannot open '%1' without direct write fallback " + "enabled: path contains an Alternate Data Stream specifier") + .arg(QDir::toNativeSeparators(d->fileName)); + d->setError(QFileDevice::OpenError, msg); + } + return false; + } +#endif + + d->fileEngine = new QTemporaryFileEngine(&d->finalFileName); // if the target file exists, we'll copy its permissions below, // but until then, let's ensure the temporary file is not accessible // to a third party @@ -243,12 +276,8 @@ bool QSaveFile::open(OpenMode mode) #ifdef Q_OS_UNIX if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) { delete d->fileEngine; - d->fileEngine = QAbstractFileEngine::create(d->finalFileName); - if (d->fileEngine->open(mode | QIODevice::Unbuffered)) { - d->useTemporaryFile = false; - QFileDevice::open(mode); + if (openDirectly()) return true; - } err = d->fileEngine->error(); } #endif |