xattr: refactor/fix exception handling in get_all

if there is EPERM just for a single attr, it now still collects the
other attrs (previous behaviour: just return empty xattrs dict).
This commit is contained in:
Thomas Waldmann 2018-07-05 18:50:44 +02:00
parent 394d59e6d8
commit 389e806b68
1 changed files with 21 additions and 6 deletions

View File

@ -37,8 +37,8 @@ def get_all(path, follow_symlinks=False):
""" """
if isinstance(path, str): if isinstance(path, str):
path = os.fsencode(path) path = os.fsencode(path)
try:
result = {} result = {}
try:
names = listxattr(path, follow_symlinks=follow_symlinks) names = listxattr(path, follow_symlinks=follow_symlinks)
for name in names: for name in names:
try: try:
@ -47,14 +47,29 @@ def get_all(path, follow_symlinks=False):
# borg always did it like that... # borg always did it like that...
result[name] = getxattr(path, name, follow_symlinks=follow_symlinks) or None result[name] = getxattr(path, name, follow_symlinks=follow_symlinks) or None
except OSError as e: except OSError as e:
name_str = name.decode()
if isinstance(path, int):
path_str = '<FD %d>' % path
else:
path_str = os.fsdecode(path)
if e.errno == ENOATTR:
# if we get ENOATTR, a race has happened: xattr names were deleted after list. # if we get ENOATTR, a race has happened: xattr names were deleted after list.
# we just ignore the now missing ones. if you want consistency, do snapshots. # we just ignore the now missing ones. if you want consistency, do snapshots.
if e.errno != ENOATTR: pass
elif e.errno == errno.EPERM:
# we were not permitted to read this attribute, still can continue trying to read others
logger.warning('%s: Operation not permitted when reading extended attribute %s' % (
path_str, name_str))
else:
raise raise
return result
except OSError as e: except OSError as e:
if e.errno in (errno.ENOTSUP, errno.EPERM): if e.errno in (errno.ENOTSUP, errno.EPERM):
return {} # if xattrs are not supported on the filesystem, we give up.
# EPERM might be raised by listxattr.
pass
else:
raise
return result
def set_all(path, xattrs, follow_symlinks=False): def set_all(path, xattrs, follow_symlinks=False):