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:
parent
0c7241ccf2
commit
35a11d6fce
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user