Fallback if RENAME_EXCHANGE not supported by fs

Fixes #1213
This commit is contained in:
Unrud 2022-02-01 11:28:33 +01:00
parent 47f3a6d684
commit 45ff34f6c3

View File

@ -21,6 +21,7 @@ Helper functions for working with the file system.
""" """
import errno
import os import os
import posixpath import posixpath
import sys import sys
@ -178,14 +179,16 @@ def rename_exchange(src: str, dst: str) -> None:
try: try:
if renameat2(src_dir_fd, src_base_bytes, if renameat2(src_dir_fd, src_base_bytes,
dst_dir_fd, dst_base_bytes, dst_dir_fd, dst_base_bytes,
RENAME_EXCHANGE) != 0: RENAME_EXCHANGE) == 0:
errno = ctypes.get_errno() return
raise OSError(errno, os.strerror(errno)) errno_ = ctypes.get_errno()
# Fallback if RENAME_EXCHANGE not supported by filesystem
if errno_ != errno.EINVAL:
raise OSError(errno_, os.strerror(errno_))
finally: finally:
os.close(dst_dir_fd) os.close(dst_dir_fd)
finally: finally:
os.close(src_dir_fd) os.close(src_dir_fd)
else:
with TemporaryDirectory(prefix=".Radicale.tmp-", dir=src_dir with TemporaryDirectory(prefix=".Radicale.tmp-", dir=src_dir
) as tmp_dir: ) as tmp_dir:
os.rename(dst, os.path.join(tmp_dir, "interim")) os.rename(dst, os.path.join(tmp_dir, "interim"))