Handle unsupported ownership transfer in atomic writes
This commit is contained in:
parent
d5904283ab
commit
c7ce0db4fa
2 changed files with 21 additions and 3 deletions
13
api/paths.py
13
api/paths.py
|
|
@ -144,7 +144,18 @@ def _atomic_write_text(path: Path, text: str, *, encoding: str = "utf-8") -> Non
|
|||
if existing_stat is not None and hasattr(os, "fchown"):
|
||||
try:
|
||||
os.fchown(fd, existing_stat.st_uid, existing_stat.st_gid)
|
||||
except (PermissionError, NotImplementedError):
|
||||
except (OSError, NotImplementedError) as exc:
|
||||
unsupported_ownership_errnos = {
|
||||
errno.EINVAL,
|
||||
errno.ENOSYS,
|
||||
errno.ENOTSUP,
|
||||
}
|
||||
if (
|
||||
isinstance(exc, OSError)
|
||||
and not isinstance(exc, PermissionError)
|
||||
and exc.errno not in unsupported_ownership_errnos
|
||||
):
|
||||
raise
|
||||
os.close(fd)
|
||||
owns_fd = False
|
||||
os.unlink(tmp)
|
||||
|
|
|
|||
|
|
@ -99,15 +99,22 @@ def test_atomic_write_preserves_existing_group(tmp_path: Path) -> None:
|
|||
|
||||
|
||||
@pytest.mark.skipif(not hasattr(os, "fchown"), reason="POSIX ownership semantics")
|
||||
@pytest.mark.parametrize(
|
||||
"failure",
|
||||
[
|
||||
PermissionError("simulated ownership denial"),
|
||||
OSError(errno.EINVAL, "simulated unsupported ownership transfer"),
|
||||
],
|
||||
)
|
||||
def test_fchown_denial_falls_back_without_temp_debris(
|
||||
tmp_path: Path, monkeypatch
|
||||
tmp_path: Path, monkeypatch, failure: OSError
|
||||
) -> None:
|
||||
"""A writer unable to transfer ownership must keep the old inode contract."""
|
||||
target = tmp_path / "config.yaml"
|
||||
target.write_text("old: true\n", encoding="utf-8")
|
||||
|
||||
def _deny_fchown(*_args) -> None:
|
||||
raise PermissionError("simulated ownership denial")
|
||||
raise failure
|
||||
|
||||
monkeypatch.setattr(os, "fchown", _deny_fchown)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue