From c99b849abe645d824cc2524cdee065df07f0d041 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 29 Jul 2023 23:04:44 +0200 Subject: [PATCH] create: do not try to read parent dir of recursion root, fixes #7746 --- src/borg/archiver/create_cmd.py | 57 +++++++++++++-------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/src/borg/archiver/create_cmd.py b/src/borg/archiver/create_cmd.py index 284a7a0c6..676152c60 100644 --- a/src/borg/archiver/create_cmd.py +++ b/src/borg/archiver/create_cmd.py @@ -24,7 +24,7 @@ from ..helpers import get_cache_dir, os_stat from ..helpers import dir_is_tagged from ..helpers import log_multi from ..helpers import basic_json_data, json_print -from ..helpers import flags_root, flags_dir, flags_special_follow, flags_special +from ..helpers import flags_dir, flags_special_follow, flags_special from ..helpers import sig_int, ignore_sigint from ..helpers import iter_separated from ..helpers import MakePathSafeAction @@ -156,41 +156,30 @@ class CreateMixIn: fso.stats.files_stats[status] += 1 continue path = os.path.normpath(path) - parent_dir = os.path.dirname(path) or "." - name = os.path.basename(path) try: - # note: for path == '/': name == '' and parent_dir == '/'. - # the empty name will trigger a fall-back to path-based processing in os_stat and os_open. - with OsOpen(path=parent_dir, flags=flags_root, noatime=True, op="open_root") as parent_fd: - try: - st = os_stat(path=path, parent_fd=parent_fd, name=name, follow_symlinks=False) - except OSError as e: - self.print_warning("%s: %s", path, e) - continue - if args.one_file_system: - restrict_dev = st.st_dev - else: - restrict_dev = None - self._rec_walk( - path=path, - parent_fd=parent_fd, - name=name, - fso=fso, - cache=cache, - matcher=matcher, - exclude_caches=args.exclude_caches, - exclude_if_present=args.exclude_if_present, - keep_exclude_tags=args.keep_exclude_tags, - skip_inodes=skip_inodes, - restrict_dev=restrict_dev, - read_special=args.read_special, - dry_run=dry_run, - ) - # if we get back here, we've finished recursing into , - # we do not ever want to get back in there (even if path is given twice as recursion root) - skip_inodes.add((st.st_ino, st.st_dev)) + with backup_io("stat"): + st = os_stat(path=path, parent_fd=None, name=None, follow_symlinks=False) + restrict_dev = st.st_dev if args.one_file_system else None + self._rec_walk( + path=path, + parent_fd=None, + name=None, + fso=fso, + cache=cache, + matcher=matcher, + exclude_caches=args.exclude_caches, + exclude_if_present=args.exclude_if_present, + keep_exclude_tags=args.keep_exclude_tags, + skip_inodes=skip_inodes, + restrict_dev=restrict_dev, + read_special=args.read_special, + dry_run=dry_run, + ) + # if we get back here, we've finished recursing into , + # we do not ever want to get back in there (even if path is given twice as recursion root) + skip_inodes.add((st.st_ino, st.st_dev)) except (BackupOSError, BackupError) as e: - # this comes from OsOpen, self._rec_walk has own exception handler + # this comes from os.stat, self._rec_walk has own exception handler self.print_warning("%s: %s", path, e) continue if not dry_run: