Files
darling-lol/tools/ensure-league-runtime-layout.py

55 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""Recover League's stale lock and validate its existing game directory."""
import os
from pathlib import Path
prefix = Path(os.environ.get("DPREFIX", str(Path.home() / ".darling")))
app = prefix / "Applications/League of Legends.app"
game = app / "Contents/LoL/Game"
alias = app / "Game"
lockfile = app / "Contents/LoL/lockfile"
# An interrupted runtime can leave this ephemeral remoting lock behind. Riot
# waits for that old client at startup. Guest PIDs are namespaced, so identify
# a live owner by its executable mapping rather than checking the host PID.
if lockfile.is_file() and not lockfile.is_symlink():
observed = lockfile.stat()
owner = False
for proc in Path("/proc").iterdir():
if not proc.name.isdigit():
continue
try:
if proc.stat().st_uid != os.getuid():
continue
if proc.joinpath("comm").read_text().strip() != "mldr":
continue
if proc.joinpath("exe").readlink().name != "mldr":
continue
mappings = proc.joinpath("maps").read_text()
if str(app) + "/Contents/LoL/LeagueClient.app/Contents/MacOS/LeagueClient\n" in mappings:
owner = True
break
except FileNotFoundError:
continue
except PermissionError:
owner = True # Cannot establish that the owner is gone.
break
if not owner:
try:
current = lockfile.stat()
except FileNotFoundError:
current = None
if current and (current.st_ino, current.st_mtime_ns) == (observed.st_ino, observed.st_mtime_ns):
lockfile.unlink()
print("Cleared stale League remoting lock after its process exited")
if not (game / "LeagueofLegends.app/Contents/MacOS/LeagueofLegends").is_file():
raise SystemExit(0)
if os.path.lexists(alias):
if alias.resolve() != game.resolve():
if alias.is_dir() and not alias.is_symlink():
print("Riot created a separate Game directory; the update hook registers Contents/LoL/Game directly")
else:
raise SystemExit("League secondary install root conflicts with its macOS game directory")
# The startup API hook registers the native directory directly. Creating a new
# bundle-root alias here makes Riot's integrity pass see an extra directory
# and can turn the first Play action into another repair.