diff options
| author | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-26 12:55:00 -0500 |
|---|---|---|
| committer | SulfurNitride <SulfurNitride@users.noreply.github.com> | 2026-04-26 12:55:00 -0500 |
| commit | 1d1765af605fb927021ad8f7e27bacb520bcfa85 (patch) | |
| tree | b870c856e990f0b851ff67c11a21bc6eeef3e34a /src | |
| parent | d06dd9bf82040ad67a6f12fb92fb411770d63f28 (diff) | |
Spawn: prune non-{C:,Z:} drive letters from prefix at launch
Wine canonicalises paths against the dosdevices map and prefers the most
specific (longest-prefix) drive letter. An external symlink such as
dosdevices/x: -> /home/<user> turns every Z:\home\<user>\... binary path
into X:\..., which confuses tools and obscures launch logs.
PrefixSetupRunner::stepDriveCleanup already enforces the {C:, Z:} policy
but only runs as part of the explicit prefix-setup pipeline; drives
added later (Faugus, manual edits, modlist installers) survive forever.
Mirror that cleanup at launch in spawn.cpp's pruneExtraDrives() so every
Proton launch sees a known-good dosdevices layout.
Diffstat (limited to 'src')
| -rw-r--r-- | src/src/spawn.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/src/spawn.cpp b/src/src/spawn.cpp index 8e97ed0..9d4d8f2 100644 --- a/src/src/spawn.cpp +++ b/src/src/spawn.cpp @@ -27,7 +27,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "settingsdialogworkarounds.h"
#include "shared/appconfig.h"
#include <QApplication>
+#include <QDir>
+#include <QFile>
#include <QMessageBox>
+#include <QSet>
#include <QSettings>
#include <QtDebug>
#include <uibase/errorcodes.h>
@@ -517,6 +520,44 @@ QString firstExistingSetting(const QSettings &settings, return {};
}
+// Remove dosdevices/<letter>: symlinks for any drive other than C: and Z:.
+// External tooling (Faugus, manual edits, modlist installers) can re-add
+// drives like X: that map subtrees of the host filesystem; Wine then prefers
+// the more specific drive when canonicalising paths, which mangles binary
+// paths we passed in as Z:\... into X:\... Keeping this list minimal means
+// MO2 can rely on Z: being the only host-mapped drive.
+void pruneExtraDrives(const QString &prefixPath) {
+ static const QSet<QString> kept = {QStringLiteral("c:"), QStringLiteral("z:")};
+
+ const QString dosdevices = QDir(prefixPath).filePath("dosdevices");
+ QDir dir(dosdevices);
+ if (!dir.exists()) {
+ return;
+ }
+
+ QStringList removed;
+ for (const QString &entry :
+ dir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries)) {
+ const QString lower = entry.toLower();
+ if (lower.length() != 2 || !lower.endsWith(':') ||
+ !lower.at(0).isLetter()) {
+ continue;
+ }
+ if (kept.contains(lower)) {
+ continue;
+ }
+ if (QFile::remove(dir.filePath(entry))) {
+ removed << entry.toUpper();
+ }
+ }
+
+ if (!removed.isEmpty()) {
+ MOBase::log::info(
+ "Pruned stale drive letters from prefix '{}': {}", prefixPath,
+ removed.join(QStringLiteral(", ")).toStdString());
+ }
+}
+
QString resolvePrefixPath() {
// The Fluorine config is authoritative: it's the prefix the user
// explicitly created through Settings > Proton and that Fluorine itself
@@ -702,6 +743,7 @@ int spawn(const SpawnParameters &sp, pid_t &processId) { return ENOENT;
} else {
MOBase::log::info("Using Wine prefix: {}", prefixPath);
+ pruneExtraDrives(prefixPath);
launcher.setPrefix(prefixPath);
}
|
