fix: name the closed folder behind a link

This commit is contained in:
Abdessamad Derraz committed 2026-10-24 03:51:02 +02:00
1 parent 38190f009b
commit 78de625294
2 files changed
+52 -1

No files matched your search

+11 -1
View File
@@ -4305,7 +4305,17 @@ def closed_folder(path: Path) -> tuple[Path, str] | None:
except OSError as exc:
if exc.errno in (errno.ENOENT, errno.ENOTDIR):
return None
return folder.parent, exc.strerror or str(exc)
why = exc.strerror or str(exc)
if exc.errno == errno.ELOOP:
# The link that loops, not the open folder holding it.
return folder, why
real = Path(os.path.realpath(folder))
if real != folder:
# ~/Emulation linked into a closed card: the closed folder
# is under the link's target, and naming the link's
# parent told the user they cannot open their own HOME.
return closed_folder(real) or (real.parent, why)
return folder.parent, why
return probe, failure.strerror or str(failure)
+41
View File
@@ -8,6 +8,7 @@ honours Retry-After, and large files that resume where they stopped.
from __future__ import annotations
import contextlib
import errno
import hashlib
import http.server
import io
@@ -978,5 +979,45 @@ class WindowsMandatoryLock(unittest.TestCase):
self.assertEqual((ok, reason), (False, install.NOT_WRITABLE))
@unittest.skipIf(os.name == "nt" or os.geteuid() == 0,
"a folder without search permission is POSIX")
class AClosedFolderBehindALink(unittest.TestCase):
"""~/Emulation linked into a card at 000: the line named the link's
parent, telling the user they cannot open their own HOME. A link
that loops was named by its open parent."""
def setUp(self):
self.base = Path(tempfile.mkdtemp(dir=REPO_ROOT / "tmp"))
self.addCleanup(shutil.rmtree, self.base, True)
self.home = self.base / "home"
self.home.mkdir()
self.card = self.base / "card"
(self.card / "Emulation" / "bios").mkdir(parents=True)
def closed(self, path: Path):
os.chmod(self.card, 0o000)
try:
return install.closed_folder(path)
finally:
os.chmod(self.card, 0o755)
def test_a_link_into_the_closed_folder_names_that_folder(self):
(self.home / "Emulation").symlink_to(self.card / "Emulation")
self.assertEqual(self.closed(self.home / "Emulation" / "bios"),
(self.card, "Permission denied"))
def test_a_link_to_the_closed_folder_itself_names_it(self):
(self.home / "Emulation").symlink_to(self.card)
self.assertEqual(self.closed(self.home / "Emulation" / "Emulation" / "bios"),
(self.card, "Permission denied"))
def test_a_loop_names_the_link(self):
loop = self.base / "loop"
loop.symlink_to("loop")
folder, why = install.closed_folder(loop / "system")
self.assertEqual(folder, loop)
self.assertEqual(why, os.strerror(errno.ELOOP))
if __name__ == "__main__":
unittest.main()