fix: report a file under a folder no one can enter

Path.exists() lets PermissionError through, so a BIOS subfolder without
search permission stopped --check and installs before any file. The file
is now reported unreadable and the run goes on with the others.
This commit is contained in:
Abdessamad Derraz committed 2026-10-23 22:03:38 +02:00
1 parent d1414263fa
commit 2f8416e5fe
2 files changed
+123 -20

No files matched your search

+59
View File
@@ -507,6 +507,65 @@ class ARefusedFolderReportsEachFile(unittest.TestCase):
list(range(1, len(downloaded) + 1)))
class AFolderThisUserCannotEnter(unittest.TestCase):
"""A subfolder of the BIOS folder without search permission (made 0700
by an emulator that ran as root, or denied by a Windows ACL) raised
PermissionError from Path.exists() before any file was handled, in
--check and in an install alike."""
def _locked(self, repo: FakeRepository) -> Path:
(repo.dest / "pcsx").mkdir(parents=True)
(repo.dest / "pcsx" / "extra.bin").write_bytes(b"old")
os.chmod(repo.dest / "pcsx", 0o000)
return repo.dest / "pcsx"
@unittest.skipIf(os.name == "nt" or os.geteuid() == 0,
"a folder without search permission is POSIX")
def test_check_names_the_file_and_reads_the_others(self):
with FakeRepository() as repo:
locked = self._locked(repo)
try:
proc = repo.run("--check")
finally:
os.chmod(locked, 0o755)
self.assertNotIn("Traceback", proc.stderr)
self.assertEqual(proc.returncode, 1, proc.stdout + proc.stderr)
self.assertIn("wrong hash: pcsx/extra.bin", proc.stdout)
self.assertIn("could not be read (Permission denied)", proc.stdout)
self.assertIn("missing: scph5501.bin", proc.stdout)
@unittest.skipIf(os.name == "nt" or os.geteuid() == 0,
"a folder without search permission is POSIX")
def test_install_fails_that_file_alone(self):
with FakeRepository() as repo:
locked = self._locked(repo)
try:
proc = repo.run("--events")
finally:
os.chmod(locked, 0o755)
installed = repo.installed()
self.assertNotIn("Traceback", proc.stderr)
events = [json.loads(line) for line in proc.stdout.splitlines()]
failed = {e["dest"]: e["reason"] for e in events
if e["event"] == "downloaded" and not e["ok"]}
self.assertEqual(list(failed), ["pcsx/extra.bin"], proc.stderr)
self.assertIn("this user may not have access", failed["pcsx/extra.bin"])
self.assertIn("scph5501.bin", installed)
self.assertIn("mgba/extra.bin", installed)
@unittest.skipIf(os.name == "nt" or os.geteuid() == 0,
"a folder without search permission is POSIX")
def test_declared_state_reads_it_as_wrong(self):
with FakeRepository() as repo:
locked = self._locked(repo)
entry = {"dest": "pcsx/extra.bin", "sha1": "0" * 40, "size": 3}
try:
state = install._declared_state(entry, entry, repo.dest)
finally:
os.chmod(locked, 0o755)
self.assertEqual(state, "wrong_hash")
class _Tty(io.StringIO):
def isatty(self) -> bool:
return True