From 9d0207568514056c9ad07c33d3c9ee9bcbff01a7 Mon Sep 17 00:00:00 2001 From: R1kaB3rN <100738684+R1kaB3rN@users.noreply.github.com> Date: Wed, 21 Feb 2024 23:21:19 -0800 Subject: [PATCH] Support symlink of current unix username to steamuser --- ulwgl_run.py | 29 +++++++++++++++++++++++++++++ ulwgl_util.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 ulwgl_util.py diff --git a/ulwgl_run.py b/ulwgl_run.py index 6e29a14cc..a615a47a7 100755 --- a/ulwgl_run.py +++ b/ulwgl_run.py @@ -11,6 +11,7 @@ from re import match import subprocess from ulwgl_dl_util import get_ulwgl_proton +from ulwgl_util import UnixUser verbs: Set[str] = { "waitforexitandrun", @@ -62,6 +63,11 @@ def parse_args() -> Union[Namespace, Tuple[str, List[str]]]: # noqa: D103 def setup_pfx(path: str) -> None: """Create a symlink to the WINE prefix and tracked_files file.""" pfx: Path = Path(path).joinpath("pfx").expanduser() + steam: Path = Path(path).expanduser().joinpath("drive_c/users/steamuser") + user: UnixUser = UnixUser() + wineuser: Path = ( + Path(path).expanduser().joinpath(f"drive_c/users/{user.get_user()}") + ) if pfx.is_symlink(): pfx.unlink() @@ -71,6 +77,29 @@ def setup_pfx(path: str) -> None: Path(path).joinpath("tracked_files").expanduser().touch() + # Create a symlink of the current user to the steamuser dir or vice versa + # Always recreate the symlink in case they move the dir + # Default for new prefixes is: unixuser -> steamuser + if ( + not wineuser.is_dir() + and not steam.is_dir() + and not (wineuser.is_symlink() or steam.is_symlink()) + ): + # For new prefixes with our Proton: user -> steamuser + steam.mkdir(parents=True) + wineuser.unlink(missing_ok=True) + wineuser.symlink_to(steam) + elif wineuser.is_dir() and not steam.is_dir() and not steam.is_symlink(): + # When there's a user dir: steamuser -> user + steam.unlink(missing_ok=True) + steam.symlink_to(wineuser) + elif not wineuser.exists() and not wineuser.is_symlink() and steam.is_dir(): + wineuser.unlink(missing_ok=True) + wineuser.symlink_to(steam) + else: + # TODO Warn the user to consider merging the steamuser and user folder + pass + def check_env( env: Dict[str, str], toml: Dict[str, Any] = None diff --git a/ulwgl_util.py b/ulwgl_util.py new file mode 100644 index 000000000..430b406c9 --- /dev/null +++ b/ulwgl_util.py @@ -0,0 +1,33 @@ +from os import getuid +from pathlib import Path +from pwd import struct_passwd, getpwuid + + +class UnixUser: + """Represents the User of the system as determined by the password database rather than environment variables or file system paths.""" + + def __init__(self): + """Immutable properties of the user determined by the password database that's derived from the real user id.""" + uid: int = getuid() + entry: struct_passwd = getpwuid(uid) + # Immutable properties, hence no setters + self.name: str = entry.pw_name + self.puid: str = entry.pw_uid # Should be equivalent to the value from getuid + self.dir: str = entry.pw_dir + self.is_user: bool = self.puid == uid + + def get_home_dir(self) -> Path: + """User home directory as determined by the password database that's derived from the current process's real user id.""" + return Path(self.dir).as_posix() + + def get_user(self) -> str: + """User (login name) as determined by the password database that's derived from the current process's real user id.""" + return self.name + + def get_puid(self) -> int: + """Numerical user ID as determined by the password database that's derived from the current process's real user id.""" + return self.puid + + def is_user(self, uid: int) -> bool: + """Compare the UID passed in to this instance.""" + return uid == self.puid