From 9221a476c520c80a56cd25f39823287c10d2aac0 Mon Sep 17 00:00:00 2001 From: Levente Polyak Date: Fri, 27 Oct 2023 11:18:05 +0200 Subject: [PATCH] feat(core): resolve symlinks on file write (#233) * feat(core): resolve symlinks on file write Instead of using the passed filename as the rename target, use Path.resolve for resolving any symlinks. This allows to use symlinks for the nvchecker database files that point somewhere else. Before this commit nvchecker simply replaced the symlink with an actual file, now we resolve the targets first and only replace the actual file that is pointed to. --------- Signed-off-by: Levente Polyak Co-authored-by: Andreas 'Segaja' Schleifer Co-authored-by: lilydjwg --- nvchecker/core.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/nvchecker/core.py b/nvchecker/core.py index 89c62f4..973e5f7 100644 --- a/nvchecker/core.py +++ b/nvchecker/core.py @@ -111,11 +111,12 @@ def process_common_arguments(args: argparse.Namespace) -> bool: return True return False -def safe_overwrite(fname: str, data: Union[bytes, str], *, +def safe_overwrite(file: Path, data: Union[bytes, str], *, method: str = 'write', mode: str = 'w', encoding: Optional[str] = None) -> None: # FIXME: directory has no read perm - # FIXME: symlinks and hard links - tmpname = fname + '.tmp' + # FIXME: hard links + resolved_path = file.resolve() + tmpname = str(resolved_path) + '.tmp' # if not using "with", write can fail without exception with open(tmpname, mode, encoding=encoding) as f: getattr(f, method)(data) @@ -123,7 +124,7 @@ def safe_overwrite(fname: str, data: Union[bytes, str], *, f.flush() os.fsync(f.fileno()) # if the above write failed (because disk is full etc), the old data should be kept - os.rename(tmpname, fname) + os.rename(tmpname, resolved_path) def read_verfile(file: Path) -> VersData: try: @@ -150,7 +151,7 @@ def write_verfile(file: Path, versions: VersData) -> None: indent=2, ensure_ascii=False, ) + '\n' - safe_overwrite(str(file), data) + safe_overwrite(file, data) class Options(NamedTuple): ver_files: Optional[Tuple[Path, Path]]