diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2017-07-25 18:08:30 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2017-08-04 17:30:13 +0000 |
commit | 66500b9d75cb895accfc385fd323f48c41b61a7a (patch) | |
tree | c1e077c2bad0defb11a9623bb01d9da8fe071388 /src/corelib/io/qsavefile.cpp | |
parent | 9a3ce25f983b7ef842bbc055081474f044efb738 (diff) |
Support Alternate Data Streams in QSaveFile
We can't use MoveFile to do atomic commits on an ADS, so QSaveFile needs
to detect when the target name is ADS and then use the direct fallback
mode.
[ChangeLog][QtCore][QSaveFile] Saving to Alternate Data Streams on NTFS
on Windows is now possible, but requires setDirectWriteFallback(true).
Task-number: QTBUG-47379
Change-Id: I81480fdb578d4d43b3fcfffd14d4bc062ae1750d
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/io/qsavefile.cpp')
-rw-r--r-- | src/corelib/io/qsavefile.cpp | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp index 3f7ce8d9e9..63f2284ef5 100644 --- a/src/corelib/io/qsavefile.cpp +++ b/src/corelib/io/qsavefile.cpp @@ -231,6 +231,37 @@ bool QSaveFile::open(OpenMode mode) d->finalFileName = existingFile.filePath(); } + 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 @@ -243,12 +274,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 |