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 safe_encode, remove_surrogates, bin_to_hex, prepare_dump_dict
|
||||||
from .helpers import interval, prune_within, prune_split, PRUNING_PATTERNS
|
from .helpers import interval, prune_within, prune_split, PRUNING_PATTERNS
|
||||||
from .helpers import timestamp
|
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 Manifest, AI_HUMAN_SORT_KEYS
|
||||||
from .helpers import hardlinkable
|
from .helpers import hardlinkable
|
||||||
from .helpers import StableDict
|
from .helpers import StableDict
|
||||||
|
@ -486,9 +486,11 @@ class Archiver:
|
||||||
path = os.path.normpath(path)
|
path = os.path.normpath(path)
|
||||||
parent_dir = os.path.dirname(path) or '.'
|
parent_dir = os.path.dirname(path) or '.'
|
||||||
name = os.path.basename(path)
|
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:
|
with OsOpen(path=parent_dir, flags=flags_root, noatime=True, op='open_root') as parent_fd:
|
||||||
try:
|
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:
|
except OSError as e:
|
||||||
self.print_warning('%s: %s', path, e)
|
self.print_warning('%s: %s', path, e)
|
||||||
continue
|
continue
|
||||||
|
@ -565,7 +567,7 @@ class Archiver:
|
||||||
recurse_excluded_dir = False
|
recurse_excluded_dir = False
|
||||||
if matcher.match(path):
|
if matcher.match(path):
|
||||||
with backup_io('stat'):
|
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:
|
else:
|
||||||
self.print_file_status('x', path)
|
self.print_file_status('x', path)
|
||||||
# get out here as quickly as possible:
|
# get out here as quickly as possible:
|
||||||
|
@ -575,7 +577,7 @@ class Archiver:
|
||||||
if not matcher.recurse_dir:
|
if not matcher.recurse_dir:
|
||||||
return
|
return
|
||||||
with backup_io('stat'):
|
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)
|
recurse_excluded_dir = stat.S_ISDIR(st.st_mode)
|
||||||
if not recurse_excluded_dir:
|
if not recurse_excluded_dir:
|
||||||
return
|
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
|
:param noatime: True if access time shall be preserved
|
||||||
:return: file descriptor
|
: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
|
_flags_normal = flags
|
||||||
if noatime:
|
if noatime:
|
||||||
_flags_noatime = _flags_normal | O_('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
|
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):
|
def umount(mountpoint):
|
||||||
env = prepare_subprocess_env(system=True)
|
env = prepare_subprocess_env(system=True)
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue