OS X QSettings auto test/writing check update

This patch aims to provide an updated test that follows changes started
in 10.7: new rule is that only root can access SystemScope settings. It
also disables the sync() workaround code path which is at least not
executed during the tst_QSettings execution and returns wrong value to
the test.

From Apple's documentation:
"Note that modification of some preferences domains (those not
belonging to the “Current User”) requires root privileges (or Admin
privileges prior to OS X v10.6)—see Authorization Services Programming
Guide for information on how to gain suitable privileges"

https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFPreferencesUtils/Reference/reference.html

[ChangeLog][QtCore][QSettings] QSettings now returns the correct value
for isWritable() when using SystemScope settings.

Task-number: QTBUG-9824
Task-number: QTBUG-21062
Task-number: QTBUG-22745

Change-Id: Ib6a1490ec596b99d189ec4de9a0f28ecfd684172
Reviewed-by: Liang Qi <liang.qi@digia.com>
This commit is contained in:
Samuel Gaist 2014-03-28 22:52:04 +01:00 committed by The Qt Project
parent 0c7241ccf2
commit 35a11d6fce
3 changed files with 50 additions and 21 deletions

View File

@ -2496,6 +2496,12 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\snippet code/src_corelib_io_qsettings.cpp 7
\li On Mac OS X, permissions to access settings not belonging to the
current user (i.e. SystemScope) have changed with 10.7 (Lion). Prior to
that version, users having admin rights could access these. For 10.7 and
10.8 (Mountain Lion), only root can. However, 10.9 (Mavericks) changes
that rule again but only for the native format (plist files).
\li On Unix and Mac OS X systems, the advisory file locking is disabled
if NFS (or AutoFS or CacheFS) is detected to work around a bug in the
NFS fcntl() implementation, which hangs forever if statd or lockd aren't

View File

@ -405,7 +405,6 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString &
}
// if no bundle identifier yet. use a hard coded string.
if (domainName.isEmpty()) {
setStatus(QSettings::AccessError);
domainName = QLatin1String("unknown-organization.trolltech.com");
}
@ -540,27 +539,30 @@ void QMacSettingsPrivate::sync()
// only report failures for the primary file (the one we write to)
if (!ok && i == 0 && hostNames[j] == hostName && status == QSettings::NoError) {
#if 1
// work around what seems to be a bug in CFPreferences:
// don't report an error if there are no preferences for the application
QCFType<CFArrayRef> appIds = CFPreferencesCopyApplicationList(domains[i].userName,
hostNames[j]);
if (QSysInfo::macVersion() < QSysInfo::MV_10_7) {
// work around what seems to be a bug in CFPreferences:
// don't report an error if there are no preferences for the application
QCFType<CFArrayRef> appIds = CFPreferencesCopyApplicationList(domains[i].userName,
hostNames[j]);
// iterate through all the applications and see if we're there
CFIndex size = CFArrayGetCount(appIds);
for (CFIndex k = 0; k < size; ++k) {
const void *cfvalue = CFArrayGetValueAtIndex(appIds, k);
if (CFGetTypeID(cfvalue) == CFStringGetTypeID()) {
if (CFStringCompare(static_cast<CFStringRef>(cfvalue),
domains[i].applicationOrSuiteId,
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
setStatus(QSettings::AccessError);
break;
// iterate through all the applications and see if we're there
CFIndex size = CFArrayGetCount(appIds);
for (CFIndex k = 0; k < size; ++k) {
const void *cfvalue = CFArrayGetValueAtIndex(appIds, k);
if (CFGetTypeID(cfvalue) == CFStringGetTypeID()) {
if (CFStringCompare(static_cast<CFStringRef>(cfvalue),
domains[i].applicationOrSuiteId,
kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
setStatus(QSettings::AccessError);
break;
}
}
}
}
#else
setStatus(QSettings::AccessError);
} else
#endif
{
setStatus(QSettings::AccessError);
}
}
}
}

View File

@ -50,6 +50,7 @@
#include <QtCore/QString>
#include <QtCore/QDir>
#include <QtCore/QThread>
#include <QtCore/QSysInfo>
#include <QtGui/QKeySequence>
#include <cctype>
@ -2797,10 +2798,30 @@ void tst_QSettings::isWritable()
QSettings s1(format, QSettings::SystemScope, "software.org", "KillerAPP");
QSettings s2(format, QSettings::SystemScope, "software.org", "Something Different");
QSettings s3(format, QSettings::SystemScope, "foo.org", "Something Different");
if (s1.contains("foo")) {
QVERIFY(s1.isWritable());
QVERIFY(s2.isWritable());
QVERIFY(s3.isWritable());
#if defined(Q_OS_MACX)
if (QSysInfo::macVersion() >= QSysInfo::MV_10_9) {
QVERIFY(s1.isWritable());
if (format == QSettings::NativeFormat) {
QVERIFY(!s2.isWritable());
QVERIFY(!s3.isWritable());
} else {
QVERIFY(s2.isWritable());
QVERIFY(s3.isWritable());
}
} else if (QSysInfo::macVersion() >= QSysInfo::MV_10_7 &&
format == QSettings::NativeFormat) {
QVERIFY(!s1.isWritable());
QVERIFY(!s2.isWritable());
QVERIFY(!s3.isWritable());
} else
#endif
{
QVERIFY(s1.isWritable());
QVERIFY(s2.isWritable());
QVERIFY(s3.isWritable());
}
} else {
QVERIFY(!s1.isWritable());
QVERIFY(!s2.isWritable());