From 63b5cbfc99a2d7f2e064c539ddc08170862a3ed3 Mon Sep 17 00:00:00 2001 From: Abdel-Rahman Date: Wed, 8 Mar 2017 18:13:42 +0200 Subject: [PATCH] extract: warning RC for unextracted big extended attributes, followup (#2258) * Set warning exit code when xattr is too big * Warnings for more extended attributes errors (ENOTSUP, EACCES) * Add tests for all xattr warnings --- src/borg/archive.py | 18 ++++++++++++------ src/borg/testsuite/archiver.py | 27 ++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index 9cab897de..0756730bf 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -26,7 +26,7 @@ from .constants import * # NOQA from .hashindex import ChunkIndex, ChunkIndexEntry from .helpers import Manifest from .helpers import Chunk, ChunkIteratorFileWrapper, open_item -from .helpers import Error, IntegrityError +from .helpers import Error, IntegrityError, set_ec from .helpers import uid2user, user2uid, gid2group, group2gid from .helpers import parse_timestamp, to_localtime from .helpers import format_time, format_timedelta, format_file_size, file_status, FileSize @@ -689,13 +689,19 @@ Utilization of max. archive size: {csize_max:.0%} xattr.setxattr(fd or path, k, v, follow_symlinks=False) except OSError as e: if e.errno == errno.E2BIG: + # xattr is too big logger.warning('%s: Value or key of extended attribute %s is too big for this filesystem' % (path, k.decode())) - elif e.errno not in (errno.ENOTSUP, errno.EACCES): - # only raise if the errno is not on our ignore list: - # ENOTSUP == xattrs not supported here - # EACCES == permission denied to set this specific xattr - # (this may happen related to security.* keys) + set_ec(EXIT_WARNING) + elif e.errno == errno.ENOTSUP: + # xattrs not supported here + logger.warning('%s: Extended attributes are not supported on this filesystem' % path) + set_ec(EXIT_WARNING) + elif e.errno == errno.EACCES: + # permission denied to set this specific xattr (this may happen related to security.* keys) + logger.warning('%s: Permission denied when setting extended attribute %s' % (path, k.decode())) + set_ec(EXIT_WARNING) + else: raise def set_meta(self, key, value): diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index e2184a67c..52cb05a6a 100644 --- a/src/borg/testsuite/archiver.py +++ b/src/borg/testsuite/archiver.py @@ -1049,18 +1049,35 @@ class ArchiverTestCase(ArchiverTestCaseBase): @pytest.mark.skipif(not xattr.XATTR_FAKEROOT, reason='xattr not supported on this system or on this version of' 'fakeroot') - def test_extract_big_xattrs(self): - def patched_setxattr(*args, **kwargs): + def test_extract_xattrs_errors(self): + def patched_setxattr_E2BIG(*args, **kwargs): raise OSError(errno.E2BIG, 'E2BIG') + + def patched_setxattr_ENOTSUP(*args, **kwargs): + raise OSError(errno.ENOTSUP, 'ENOTSUP') + + def patched_setxattr_EACCES(*args, **kwargs): + raise OSError(errno.EACCES, 'EACCES') + self.create_regular_file('file') xattr.setxattr('input/file', 'attribute', 'value') self.cmd('init', self.repository_location, '-e' 'none') self.cmd('create', self.repository_location + '::test', 'input') with changedir('output'): - with patch.object(xattr, 'setxattr', patched_setxattr): + input_abspath = os.path.abspath('input/file') + with patch.object(xattr, 'setxattr', patched_setxattr_E2BIG): out = self.cmd('extract', self.repository_location + '::test', exit_code=EXIT_WARNING) - assert out == (os.path.abspath('input/file') + ': Value or key of extended attribute attribute is too big' - 'for this filesystem\n') + assert out == (input_abspath + ': Value or key of extended attribute attribute is too big for this ' + 'filesystem\n') + os.remove(input_abspath) + with patch.object(xattr, 'setxattr', patched_setxattr_ENOTSUP): + out = self.cmd('extract', self.repository_location + '::test', exit_code=EXIT_WARNING) + assert out == (input_abspath + ': Extended attributes are not supported on this filesystem\n') + os.remove(input_abspath) + with patch.object(xattr, 'setxattr', patched_setxattr_EACCES): + out = self.cmd('extract', self.repository_location + '::test', exit_code=EXIT_WARNING) + assert out == (input_abspath + ': Permission denied when setting extended attribute attribute\n') + assert os.path.isfile(input_abspath) def test_path_normalization(self): self.cmd('init', '--encryption=repokey', self.repository_location)