summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qsettings.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-07-26 12:17:20 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-08-04 17:30:16 +0000
commit4934138be29868bdf848e2aeb6c6163819ab3a5c (patch)
tree3560d6e7e95c4e09df5faf396d8e6ce95f4d6327 /src/corelib/io/qsettings.cpp
parent66500b9d75cb895accfc385fd323f48c41b61a7a (diff)
Allow QSettings to synchronize non-atomically
This is required so that one can use QSettings in situations that temporary files or renaming may not work. [ChangeLog][QtCore][QSettings] Added setAtomicSyncRequired(), which allows one to use QSettings with config files in unwriteable directories or in Alternate Data Streams on NTFS on Windows. This used to work before Qt 5.4, but remains a non-default behavior due to the potential of data corruption. Task-number: QTBUG-47379 Change-Id: I81480fdb578d4d43b3fcfffd14d4f77112f0402f Reviewed-by: Jesus Fernandez <Jesus.Fernandez@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Kai Koehne <kai.koehne@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Diffstat (limited to 'src/corelib/io/qsettings.cpp')
-rw-r--r--src/corelib/io/qsettings.cpp78
1 files changed, 64 insertions, 14 deletions
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 850e729987..d0cbc82c56 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1405,6 +1405,11 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
return;
}
+ if (!readOnly && !confFile->isWritable()) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
#ifndef QT_BOOTSTRAPPED
/*
Use a lockfile in order to protect us against other QSettings instances
@@ -1414,17 +1419,11 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
Concurrent read and write are not a problem because the writing operation is atomic.
*/
QLockFile lockFile(confFile->name + QLatin1String(".lock"));
-#endif
- if (!readOnly) {
- if (!confFile->isWritable()
-#ifndef QT_BOOTSTRAPPED
- || !lockFile.lock()
-#endif
- ) {
- setStatus(QSettings::AccessError);
- return;
- }
+ if (!readOnly && !lockFile.lock() && atomicSyncOnly) {
+ setStatus(QSettings::AccessError);
+ return;
}
+#endif
/*
We hold the lock. Let's reread the file if it has changed
@@ -1496,6 +1495,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile)
QSaveFile sf(confFile->name);
+ sf.setDirectWriteFallback(!atomicSyncOnly);
#else
QFile sf(confFile->name);
#endif
@@ -2201,10 +2201,16 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
QSettings can safely be used from different processes (which can
be different instances of your application running at the same
time or different applications altogether) to read and write to
- the same system locations. It uses advisory file locking and a
- smart merging algorithm to ensure data integrity. Note that sync()
- imports changes made by other processes (in addition to writing
- the changes from this QSettings).
+ the same system locations, provided certain conditions are met. For
+ QSettings::IniFormat, it uses advisory file locking and a smart merging
+ algorithm to ensure data integrity. The condition for that to work is that
+ the writeable configuration file must be a regular file and must reside in
+ a directory that the current user can create new, temporary files in. If
+ that is not the case, then one must use setAtomicSyncRequired() to turn the
+ safety off.
+
+ Note that sync() imports changes made by other processes (in addition to
+ writing the changes from this QSettings).
\section1 Platform-Specific Notes
@@ -2885,6 +2891,50 @@ QSettings::Status QSettings::status() const
}
/*!
+ \since 5.10
+
+ Returns \c true if QSettings is only allowed to perform atomic saving and
+ reloading (synchronization) of the settings. Returns \c false if it is
+ allowed to save the settings contents directly to the configuration file.
+
+ The default is \c true.
+
+ \sa setAtomicSyncRequired(), QSaveFile
+*/
+bool QSettings::isAtomicSyncRequired() const
+{
+ Q_D(const QSettings);
+ return d->atomicSyncOnly;
+}
+
+/*!
+ \since 5.10
+
+ Configures whether QSettings is required to perform atomic saving and
+ reloading (synchronization) of the settings. If the \a enable argument is
+ \c true (the default), sync() will only perform synchronization operations
+ that are atomic. If this is not possible, sync() will fail and status()
+ will be an error condition.
+
+ Setting this property to \c false will allow QSettings to write directly to
+ the configuration file and ignore any errors trying to lock it against
+ other processes trying to write at the same time. Because of the potential
+ for corruption, this option should be used with care, but is required in
+ certain conditions, like a QSettings::IniFormat configuration file that
+ exists in an otherwise non-writeable directory or NTFS Alternate Data
+ Streams.
+
+ See \l QSaveFile for more information on the feature.
+
+ \sa isAtomicSyncRequired(), QSaveFile
+*/
+void QSettings::setAtomicSyncRequired(bool enable)
+{
+ Q_D(QSettings);
+ d->atomicSyncOnly = enable;
+}
+
+/*!
Appends \a prefix to the current group.
The current group is automatically prepended to all keys