mirror of https://github.com/borgbackup/borg.git
fix openat/statat issues for root directory, fixes #4405
basename('/') == '' and we can't use that for openat/statat. also, there is no parent FD for the root directory...
This commit is contained in:
parent
009bac2e9f
commit
db2b385a8b
|
@ -50,7 +50,7 @@ from .helpers import format_timedelta, format_file_size, parse_file_size, format
|
|||
from .helpers import safe_encode, remove_surrogates, bin_to_hex, prepare_dump_dict
|
||||
from .helpers import interval, prune_within, prune_split, PRUNING_PATTERNS
|
||||
from .helpers import timestamp
|
||||
from .helpers import get_cache_dir
|
||||
from .helpers import get_cache_dir, os_stat
|
||||
from .helpers import Manifest, AI_HUMAN_SORT_KEYS
|
||||
from .helpers import hardlinkable
|
||||
from .helpers import StableDict
|
||||
|
@ -486,9 +486,11 @@ class Archiver:
|
|||
path = os.path.normpath(path)
|
||||
parent_dir = os.path.dirname(path) or '.'
|
||||
name = os.path.basename(path)
|
||||
# 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(name, dir_fd=parent_fd, follow_symlinks=False)
|
||||
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
|
||||
|
@ -565,7 +567,7 @@ class Archiver:
|
|||
recurse_excluded_dir = False
|
||||
if matcher.match(path):
|
||||
with backup_io('stat'):
|
||||
st = os.stat(name, dir_fd=parent_fd, follow_symlinks=False)
|
||||
st = os_stat(path=path, parent_fd=parent_fd, name=name, follow_symlinks=False)
|
||||
else:
|
||||
self.print_file_status('x', path)
|
||||
# get out here as quickly as possible:
|
||||
|
@ -575,7 +577,7 @@ class Archiver:
|
|||
if not matcher.recurse_dir:
|
||||
return
|
||||
with backup_io('stat'):
|
||||
st = os.stat(name, dir_fd=parent_fd, follow_symlinks=False)
|
||||
st = os_stat(path=path, parent_fd=parent_fd, name=name, follow_symlinks=False)
|
||||
recurse_excluded_dir = stat.S_ISDIR(st.st_mode)
|
||||
if not recurse_excluded_dir:
|
||||
return
|
||||
|
|
|
@ -224,7 +224,11 @@ def os_open(*, flags, path=None, parent_fd=None, name=None, noatime=False):
|
|||
:param noatime: True if access time shall be preserved
|
||||
:return: file descriptor
|
||||
"""
|
||||
fname = name if name is not None and parent_fd is not None else path
|
||||
if name and parent_fd is not None:
|
||||
# name is neither None nor empty, parent_fd given.
|
||||
fname = name # use name relative to parent_fd
|
||||
else:
|
||||
fname, parent_fd = path, None # just use the path
|
||||
_flags_normal = flags
|
||||
if noatime:
|
||||
_flags_noatime = _flags_normal | O_('NOATIME')
|
||||
|
@ -242,6 +246,26 @@ def os_open(*, flags, path=None, parent_fd=None, name=None, noatime=False):
|
|||
return fd
|
||||
|
||||
|
||||
def os_stat(*, path=None, parent_fd=None, name=None, follow_symlinks=False):
|
||||
"""
|
||||
Use os.stat to open a fs item.
|
||||
|
||||
If parent_fd and name are given, they are preferred and statat will be used,
|
||||
path is not used in this case.
|
||||
|
||||
:param path: full (but not necessarily absolute) path
|
||||
:param parent_fd: open directory file descriptor
|
||||
:param name: name relative to parent_fd
|
||||
:return: stat info
|
||||
"""
|
||||
if name and parent_fd is not None:
|
||||
# name is neither None nor empty, parent_fd given.
|
||||
fname = name # use name relative to parent_fd
|
||||
else:
|
||||
fname, parent_fd = path, None # just use the path
|
||||
return os.stat(fname, dir_fd=parent_fd, follow_symlinks=follow_symlinks)
|
||||
|
||||
|
||||
def umount(mountpoint):
|
||||
env = prepare_subprocess_env(system=True)
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue