Skip to content

Commit

Permalink
Merge pull request #7749 from ThomasWaldmann/fix-unreadable-parent-of…
Browse files Browse the repository at this point in the history
…-root-1.2

do not try to read parent dir of recursion root (1.2-maint)
  • Loading branch information
ThomasWaldmann authored Jul 29, 2023
2 parents a3f4adf + ed7a410 commit ef52d13
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 23 deletions.
35 changes: 12 additions & 23 deletions src/borg/archiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,31 +590,20 @@ def create_inner(archive, cache, fso):
self.print_file_status(status, path)
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 <path>,
# 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 <path>,
# 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:
Expand Down
10 changes: 10 additions & 0 deletions src/borg/testsuite/archiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,16 @@ def test_init_parent_dirs(self):
self.cmd('init', '--encryption=none', '--make-parent-dirs', repository_location)
assert os.path.exists(parent_path)

def test_create_unreadable_parent(self):
parent_dir = os.path.join(self.input_path, 'parent')
root_dir = os.path.join(self.input_path, 'parent', 'root')
os.mkdir(parent_dir)
os.mkdir(root_dir)
os.chmod(parent_dir, 0o111) # --x--x--x == parent dir traversable, but not readable
self.cmd('init', '--encryption=none', self.repository_location)
# issue #7746: we *can* read root_dir and we *can* traverse parent_dir, so this should work:
self.cmd('create', self.repository_location + '::test', root_dir)

def test_unix_socket(self):
self.cmd('init', '--encryption=repokey', self.repository_location)
try:
Expand Down

0 comments on commit ef52d13

Please sign in to comment.