mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-25 05:09:03 -05:00
fix: no sudo advice for a read-only mount
EROFS was advised like a permission refusal, and sudo fails the same way on a read-only mount. The advice now reads the mount flag and says to check and remount the card or drive.
This commit is contained in:
1 parent
443a4e56c9
commit
10c94369df
5 files changed
+46
-3
No files matched your search
+1
-1
@@ -11,7 +11,7 @@
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
|
||||
$defaultInstallSha256 = "1eb1aed96cab57bf3bc4ef2918bf1ef40cafcb1de157af2e5fcd5a23ae69a443"
|
||||
$defaultInstallSha256 = "86c4e8b2a67b5721020dd3629212c741a67a3b3180e8f62fb61bba333303a5b6"
|
||||
$maximumInstallerBytes = 2MB
|
||||
$installerExit = 0
|
||||
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
||||
|
||||
+23
-1
@@ -3186,6 +3186,20 @@ class Invocation:
|
||||
_INVOCATION = Invocation()
|
||||
|
||||
|
||||
def _on_read_only_mount(path: Path) -> bool:
|
||||
"""Whether the file system holding path, or the folder it would go in,
|
||||
is mounted read-only (a card Linux remounts read-only after an error)."""
|
||||
if not hasattr(os, "statvfs"):
|
||||
return False
|
||||
probe = path
|
||||
while not probe.exists() and probe.parent != probe:
|
||||
probe = probe.parent
|
||||
try:
|
||||
return bool(os.statvfs(probe).f_flag & os.ST_RDONLY)
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def _write_advice(path: Path, assumed: bool, plat: str = "") -> str:
|
||||
"""What to do about a folder this run could not write.
|
||||
|
||||
@@ -3193,8 +3207,16 @@ def _write_advice(path: Path, assumed: bool, plat: str = "") -> str:
|
||||
machine it would create that folder on the wrong disk: a platform named
|
||||
but not found here is a card or share mounted elsewhere, named by --dest.
|
||||
Windows has no sudo, and Termux reaches shared storage once
|
||||
termux-setup-storage has run.
|
||||
termux-setup-storage has run. A read-only mount refuses root as well,
|
||||
so sudo is never offered for it.
|
||||
"""
|
||||
if _on_read_only_mount(path):
|
||||
again = f"\n {_INVOCATION.command(plat, path)}" if plat else ""
|
||||
return (f" {path} is on a file system mounted read-only, which no user can "
|
||||
"write, sudo included. Mount it read-write again (a card or drive "
|
||||
"the system switched to read-only after an error needs a check "
|
||||
"first: fsck, or chkdsk on Windows), then run the same command "
|
||||
f"again.{again}")
|
||||
if assumed:
|
||||
return (f" {path} is where the platform keeps its BIOS on its own system, "
|
||||
"and it was not found here. If this machine prepares its card or "
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ esac
|
||||
TEMP_INSTALLER=""
|
||||
TEMP_DIRECTORY=""
|
||||
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
|
||||
DEFAULT_INSTALL_SHA256="1eb1aed96cab57bf3bc4ef2918bf1ef40cafcb1de157af2e5fcd5a23ae69a443"
|
||||
DEFAULT_INSTALL_SHA256="86c4e8b2a67b5721020dd3629212c741a67a3b3180e8f62fb61bba333303a5b6"
|
||||
MAX_INSTALLER_BYTES=2097152
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -2425,6 +2425,23 @@ class SudoAdviceNamesTheFolder(unittest.TestCase):
|
||||
source = (REPO_ROOT / "install.py").read_text(encoding="utf-8")
|
||||
self.assertIn("platform_of={path: plat for plat, path in platforms}", source)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, "statvfs"), "statvfs reads mount flags")
|
||||
def test_a_read_only_mount_is_not_sent_to_sudo(self):
|
||||
"""A card Linux mounted read-only after a dirty unplug was answered
|
||||
with 'run it again with sudo', which fails the same way."""
|
||||
real = os.statvfs(".")
|
||||
flags = SimpleNamespace(f_flag=real.f_flag | os.ST_RDONLY)
|
||||
for plat in ("retroarch", ""):
|
||||
with self.subTest(platform=plat), \
|
||||
unittest.mock.patch.object(install.os, "statvfs", return_value=flags):
|
||||
advice = install._write_advice(Path("/media/card/bios"), False, plat)
|
||||
self.assertIn("mounted read-only", advice)
|
||||
self.assertNotIn("Run it again with sudo", advice)
|
||||
self.assertNotIn("sudo python3", advice)
|
||||
writable = SimpleNamespace(f_flag=real.f_flag & ~os.ST_RDONLY)
|
||||
with unittest.mock.patch.object(install.os, "statvfs", return_value=writable):
|
||||
self.assertIn("sudo", install._write_advice(Path("/media/card/bios"), False, "retroarch"))
|
||||
|
||||
|
||||
|
||||
class CaseVariants(unittest.TestCase):
|
||||
|
||||
@@ -272,6 +272,10 @@ The installer needs write access to the target directory.
|
||||
- On Linux/macOS: check directory ownership (`ls -la`) and run with appropriate
|
||||
permissions. Avoid running as root unless the target directory requires it.
|
||||
- On Windows: run PowerShell as Administrator if installing to a protected directory.
|
||||
- A file system mounted read-only refuses root too, so the installer does not
|
||||
suggest sudo for it. Linux remounts a card or drive read-only after an error
|
||||
(an unclean removal, for one): check it (`fsck`, or `chkdsk` on Windows) and
|
||||
mount it read-write again.
|
||||
|
||||
A file already in the BIOS folder with the read-only attribute is replaced
|
||||
like any other: on Windows the installer clears the attribute before putting
|
||||
|
||||
Reference in new issue
Block a user