summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuli Piippo <samuli.piippo@qt.io>2019-03-20 15:39:59 +0200
committerSamuli Piippo <samuli.piippo@qt.io>2019-10-12 08:57:35 +0300
commit55427858e3f9d98dc7a75638c54a4fffde6be73a (patch)
tree5c59cbc5a33909e940584b5a3487c6b096ffd7af
parent2e12825b0b4457d709d6d467c84f30ce35336ff3 (diff)
QStandardPaths: Correct handling for XDG_RUNTIME_DIR
Always try to create the runtime directory and never change the permissions of an existing directory. Conform to the XDG Base Directory Specification: "If, when attempting to write a file, the destination directory is non-existent an attempt should be made to create it with permission 0700. If the destination directory exists already the permissions should not be changed." Fixes: QTBUG-68338 Change-Id: Iaf854d69225fc46e43abae86232d749e5c247df0 Reviewed-by: David Faure <david.faure@kdab.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp51
-rw-r--r--tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp34
2 files changed, 48 insertions, 37 deletions
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index 3d4a349c8c..cc656954d9 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -120,54 +120,59 @@ QString QStandardPaths::writableLocation(StandardLocation type)
}
case RuntimeLocation:
{
- const uint myUid = uint(geteuid());
// http://standards.freedesktop.org/basedir-spec/latest/
+ const uint myUid = uint(geteuid());
+ // since the current user is the owner, set both xxxUser and xxxOwner
+ const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
+ | QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
QFileInfo fileInfo;
QString xdgRuntimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR"));
if (xdgRuntimeDir.isEmpty()) {
const QString userName = QFileSystemEngine::resolveUserName(myUid);
xdgRuntimeDir = QDir::tempPath() + QLatin1String("/runtime-") + userName;
fileInfo.setFile(xdgRuntimeDir);
- if (!fileInfo.isDir()) {
- if (!QDir().mkdir(xdgRuntimeDir)) {
- qWarning("QStandardPaths: error creating runtime directory %s: %s", qPrintable(xdgRuntimeDir), qPrintable(qt_error_string(errno)));
- return QString();
- }
- }
#ifndef Q_OS_WASM
qWarning("QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '%s'", qPrintable(xdgRuntimeDir));
#endif
} else {
fileInfo.setFile(xdgRuntimeDir);
- if (!fileInfo.exists()) {
- qWarning("QStandardPaths: XDG_RUNTIME_DIR points to non-existing path '%s', "
- "please create it with 0700 permissions.", qPrintable(xdgRuntimeDir));
- return QString();
- }
+ }
+ if (fileInfo.exists()) {
if (!fileInfo.isDir()) {
qWarning("QStandardPaths: XDG_RUNTIME_DIR points to '%s' which is not a directory",
qPrintable(xdgRuntimeDir));
return QString();
}
+ } else {
+ QFileSystemEntry entry(xdgRuntimeDir);
+ if (!QFileSystemEngine::createDirectory(entry, false)) {
+ if (errno != EEXIST) {
+ qWarning("QStandardPaths: error creating runtime directory %s: %s",
+ qPrintable(xdgRuntimeDir), qPrintable(qt_error_string(errno)));
+ return QString();
+ }
+ } else {
+ QSystemError error;
+ if (!QFileSystemEngine::setPermissions(entry, wantedPerms, error)) {
+ qWarning("QStandardPaths: could not set correct permissions on runtime directory %s: %s",
+ qPrintable(xdgRuntimeDir), qPrintable(error.toString()));
+ return QString();
+ }
+ }
}
// "The directory MUST be owned by the user"
if (fileInfo.ownerId() != myUid) {
- qWarning("QStandardPaths: wrong ownership on runtime directory %s, %d instead of %d", qPrintable(xdgRuntimeDir),
- fileInfo.ownerId(), myUid);
+ qWarning("QStandardPaths: wrong ownership on runtime directory %s, %d instead of %d",
+ qPrintable(xdgRuntimeDir), fileInfo.ownerId(), myUid);
return QString();
}
// "and he MUST be the only one having read and write access to it. Its Unix access mode MUST be 0700."
- // since the current user is the owner, set both xxxUser and xxxOwner
- const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
- | QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
if (fileInfo.permissions() != wantedPerms) {
- QFile file(xdgRuntimeDir);
- if (!file.setPermissions(wantedPerms)) {
- qWarning("QStandardPaths: could not set correct permissions on runtime directory %s: %s",
- qPrintable(xdgRuntimeDir), qPrintable(file.errorString()));
- return QString();
- }
+ qWarning("QStandardPaths: wrong permissions on runtime directory %s, %x instead of %x",
+ qPrintable(xdgRuntimeDir), uint(fileInfo.permissions()), uint(wantedPerms));
+ return QString();
}
+
return xdgRuntimeDir;
}
default:
diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
index 1379c788d1..40023d7fea 100644
--- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
+++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
@@ -465,16 +465,6 @@ void tst_qstandardpaths::testRuntimeDirectory()
#ifdef Q_XDG_PLATFORM
const QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
QVERIFY(!runtimeDir.isEmpty());
-
- // Check that it can automatically fix permissions
- QFile file(runtimeDir);
- const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser;
- const QFile::Permissions additionalPerms = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
- QCOMPARE(file.permissions(), wantedPerms | additionalPerms);
- QVERIFY(file.setPermissions(wantedPerms | QFile::ExeGroup));
- const QString runtimeDirAgain = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
- QCOMPARE(runtimeDirAgain, runtimeDir);
- QCOMPARE(QFile(runtimeDirAgain).permissions(), wantedPerms | additionalPerms);
#endif
}
@@ -516,11 +506,27 @@ void tst_qstandardpaths::testCustomRuntimeDirectory()
const QString runtimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
QVERIFY2(runtimeDir.isEmpty(), qPrintable(runtimeDir));
- // When $XDG_RUNTIME_DIR points to a non-existing directory, QStandardPaths should warn (QTBUG-48771)
- qputenv("XDG_RUNTIME_DIR", "does_not_exist");
- QTest::ignoreMessage(QtWarningMsg, "QStandardPaths: XDG_RUNTIME_DIR points to non-existing path 'does_not_exist', please create it with 0700 permissions.");
+ // When $XDG_RUNTIME_DIR points to a directory with wrong permissions, QStandardPaths should warn
+ const QByteArray wrongPermissionFileName = "wrong_permissions";
+ QDir::current().mkdir(wrongPermissionFileName);
+ QFile wrongPermissionFile(wrongPermissionFileName);
+ const QFile::Permissions wantedPerms = QFile::ReadUser | QFile::WriteUser | QFile::ExeUser;
+ QVERIFY(wrongPermissionFile.setPermissions(wantedPerms | QFile::ExeGroup));
+
+ qputenv("XDG_RUNTIME_DIR", wrongPermissionFileName);
+ QTest::ignoreMessage(QtWarningMsg,
+ qPrintable(QString::fromLatin1("QStandardPaths: wrong permissions on runtime directory " + wrongPermissionFileName + ", 7710 instead of 7700")));
+ const QString wrongPermissionRuntimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
+ QVERIFY(wrongPermissionRuntimeDir.isEmpty());
+ QDir::current().rmdir(wrongPermissionFileName);
+
+ // When $XDG_RUNTIME_DIR points to a non-existing directory, QStandardPaths should create it first
+ const QByteArray nonExistingDir = "does_not_exist";
+ qputenv("XDG_RUNTIME_DIR", nonExistingDir);
const QString nonExistingRuntimeDir = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
- QVERIFY2(nonExistingRuntimeDir.isEmpty(), qPrintable(nonExistingRuntimeDir));
+ QVERIFY2(!nonExistingRuntimeDir.compare(nonExistingDir), qPrintable(nonExistingRuntimeDir));
+ QVERIFY(QDir::current().exists(nonExistingRuntimeDir));
+ QDir::current().rmdir(nonExistingRuntimeDir);
// When $XDG_RUNTIME_DIR points to a file, QStandardPaths should warn
const QString file = QFINDTESTDATA("tst_qstandardpaths.cpp");