* Initialize per-session temporary directory and ensure its cleanup. * * When KDevelop crashes, it leaves many files, some of which are huge, in the temporary directory. * These files are not automatically removed until system restart. No space may be left in the * temporary directory after multiple crashes. This function removes the temporary directory for the * active session on KDevelop st
| 95 | * or the system temporary directory path in case of error. |
| 96 | */ |
| 97 | QString setupSessionTemporaryDirectory(const KDevelop::ISession& session) |
| 98 | { |
| 99 | QString systemTempDirPath = QDir::tempPath(); |
| 100 | |
| 101 | // Session IDs are generated via QUuid::createUuid(), so they should be unique across all users in a system. |
| 102 | // However, users could copy/share session directories and thus get equal session IDs. If two users are logged |
| 103 | // in a system and have equal-ID KDevelop sessions open, the per-session temporary directory paths would coincide. |
| 104 | // Prevent such conflicts by including the real user ID in the temporary directory path. |
| 105 | const QString userId = KUserId::currentUserId().toString(); |
| 106 | |
| 107 | // The temporary directory path does not contain the session ID in test mode, because most KDevelop |
| 108 | // tests create a temporary session with a unique id on each run. Such temporary sessions are never |
| 109 | // loaded again, and so their temporary files cannot possibly be removed on next start. Including |
| 110 | // session IDs in temporary directory names for test sessions are only harmful then: empty directories |
| 111 | // accumulate (and even nonempty directories as some tests don't remove their files during cleanup). |
| 112 | // The session name is used in place of the session ID in test mode. TestCore::initializeNonStatic() sets most |
| 113 | // test session names to "test-" + <test executable name>. The few custom test session names are also sufficiently |
| 114 | // verbose and unique. Separate temporary directories for different tests allow running tests concurrently. |
| 115 | // QStandardPaths::isTestModeEnabled() is undocumented internal API. But KSharedConfig::openConfig() relies on it. |
| 116 | // So we venture to use this API here despite the risk of removal without notice in a future Qt version. |
| 117 | const QString subdirName = QStandardPaths::isTestModeEnabled() ? session.name() : session.id().toString(); |
| 118 | |
| 119 | QString tempDirPath = QLatin1String("%1/kdevelop-%2/%3").arg(systemTempDirPath, userId, subdirName); |
| 120 | QDir tempDir(tempDirPath); |
| 121 | |
| 122 | // Remove files left after a possible previous crash of this session. |
| 123 | if (!tempDir.removeRecursively()) { |
| 124 | qCWarning(SHELL) << "couldn't delete the session temporary directory" << tempDirPath; |
| 125 | return systemTempDirPath; |
| 126 | } |
| 127 | |
| 128 | // Create the session temporary directory. |
| 129 | if (!tempDir.mkpath(tempDirPath)) { |
| 130 | qCWarning(SHELL) << "couldn't create the session temporary directory" << tempDirPath; |
| 131 | return systemTempDirPath; |
| 132 | } |
| 133 | |
| 134 | // Allow only the owner to access the temporary directory, just like QTemporaryDir() does. |
| 135 | if (!QFile::setPermissions(tempDirPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)) { |
| 136 | qCWarning(SHELL) << "couldn't set permissions for the session temporary directory" << tempDirPath; |
| 137 | return systemTempDirPath; |
| 138 | } |
| 139 | |
| 140 | qCDebug(SHELL) << "set up the session temporary directory" << tempDirPath; |
| 141 | return tempDirPath; |
| 142 | } |
| 143 | } // unnamed namespace |
| 144 | |
| 145 | namespace KDevelop { |
no test coverage detected