diff --git a/src/borg/archive.py b/src/borg/archive.py index ab9de1d18..0ea945146 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -379,7 +379,8 @@ class IncompatibleFilesystemEncodingError(Error): """Failed to encode filename "{}" into file system encoding "{}". Consider configuring the LANG environment variable.""" def __init__(self, repository, key, manifest, name, cache=None, create=False, - checkpoint_interval=1800, numeric_owner=False, noatime=False, noctime=False, noflags=False, + checkpoint_interval=1800, numeric_owner=False, noatime=False, noctime=False, + noflags=False, noacls=False, noxattrs=False, progress=False, chunker_params=CHUNKER_PARAMS, start=None, start_monotonic=None, end=None, consider_part_files=False, log_json=False): self.cwd = os.getcwd() @@ -398,6 +399,8 @@ def __init__(self, repository, key, manifest, name, cache=None, create=False, self.noatime = noatime self.noctime = noctime self.noflags = noflags + self.noacls = noacls + self.noxattrs = noxattrs assert (start is None) == (start_monotonic is None), 'Logic error: if start is given, start_monotonic must be given as well and vice versa.' if start is None: start = datetime.utcnow() @@ -853,12 +856,14 @@ def restore_attrs(self, path, item, symlink=False, fd=None): except OSError: # some systems don't support calling utime on a symlink pass - acl_set(path, item, self.numeric_owner, fd=fd) - # chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include - # the Linux capabilities in the "security.capability" attribute. - warning = xattr.set_all(fd or path, item.get('xattrs', {}), follow_symlinks=False) - if warning: - set_ec(EXIT_WARNING) + if not self.noacls: + acl_set(path, item, self.numeric_owner, fd=fd) + if not self.noxattrs: + # chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include + # the Linux capabilities in the "security.capability" attribute. + warning = xattr.set_all(fd or path, item.get('xattrs', {}), follow_symlinks=False) + if warning: + set_ec(EXIT_WARNING) # bsdflags include the immutable flag and need to be set last: if not self.noflags and 'bsdflags' in item: try: @@ -1039,11 +1044,13 @@ def defer_if_necessary(item1, item2): class MetadataCollector: - def __init__(self, *, noatime, noctime, numeric_owner, noflags, nobirthtime): + def __init__(self, *, noatime, noctime, nobirthtime, numeric_owner, noflags, noacls, noxattrs): self.noatime = noatime self.noctime = noctime self.numeric_owner = numeric_owner self.noflags = noflags + self.noacls = noacls + self.noxattrs = noxattrs self.nobirthtime = nobirthtime def stat_simple_attrs(self, st): @@ -1072,12 +1079,11 @@ def stat_simple_attrs(self, st): def stat_ext_attrs(self, st, path, fd=None): attrs = {} - flags = 0 with backup_io('extended stat'): - if not self.noflags: - flags = get_flags(path, st, fd=fd) - xattrs = xattr.get_all(fd or path, follow_symlinks=False) - acl_get(path, attrs, st, self.numeric_owner, fd=fd) + flags = 0 if self.noflags else get_flags(path, st, fd=fd) + xattrs = {} if self.noxattrs else xattr.get_all(fd or path, follow_symlinks=False) + if not self.noacls: + acl_get(path, attrs, st, self.numeric_owner, fd=fd) if xattrs: attrs['xattrs'] = StableDict(xattrs) if flags: diff --git a/src/borg/archiver.py b/src/borg/archiver.py index 3cefb36f4..b720d4745 100644 --- a/src/borg/archiver.py +++ b/src/borg/archiver.py @@ -189,6 +189,8 @@ def wrapper(self, args, repository, key, manifest, **kwargs): archive = Archive(repository, key, manifest, args.location.archive, numeric_owner=getattr(args, 'numeric_owner', False), noflags=getattr(args, 'nobsdflags', False) or getattr(args, 'noflags', False), + noacls=getattr(args, 'noacls', False), + noxattrs=getattr(args, 'noxattrs', False), cache=kwargs.get('cache'), consider_part_files=args.consider_part_files, log_json=args.log_json) return method(self, args, repository=repository, manifest=manifest, key=key, archive=archive, **kwargs) @@ -635,6 +637,8 @@ def create_inner(archive, cache, fso): self.output_filter = args.output_filter self.output_list = args.output_list self.noflags = args.nobsdflags or args.noflags + self.noacls = args.noacls + self.noxattrs = args.noxattrs self.exclude_nodump = args.exclude_nodump dry_run = args.dry_run t0 = datetime.utcnow() @@ -651,7 +655,8 @@ def create_inner(archive, cache, fso): chunker_params=args.chunker_params, start=t0, start_monotonic=t0_monotonic, log_json=args.log_json) metadata_collector = MetadataCollector(noatime=not args.atime, noctime=args.noctime, - noflags=args.nobsdflags or args.noflags, numeric_owner=args.numeric_owner, nobirthtime=args.nobirthtime) + noflags=args.nobsdflags or args.noflags, noacls=args.noacls, noxattrs=args.noxattrs, + numeric_owner=args.numeric_owner, nobirthtime=args.nobirthtime) cp = ChunksProcessor(cache=cache, key=key, add_item=archive.add_item, write_checkpoint=archive.write_checkpoint, checkpoint_interval=args.checkpoint_interval, rechunkify=False) @@ -3379,6 +3384,10 @@ def define_borg_mount(parser): help='deprecated, use ``--noflags`` instead') fs_group.add_argument('--noflags', dest='noflags', action='store_true', help='do not read and store flags (e.g. NODUMP, IMMUTABLE) into archive') + fs_group.add_argument('--noacls', dest='noacls', action='store_true', + help='do not read and store ACLs into archive') + fs_group.add_argument('--noxattrs', dest='noxattrs', action='store_true', + help='do not read and store xattrs into archive') fs_group.add_argument('--sparse', dest='sparse', action='store_true', help='detect sparse holes in input (supported only by fixed chunker)') fs_group.add_argument('--files-cache', metavar='MODE', dest='files_cache_mode', @@ -3797,6 +3806,10 @@ def define_borg_mount(parser): help='deprecated, use ``--noflags`` instead') subparser.add_argument('--noflags', dest='noflags', action='store_true', help='do not extract/set flags (e.g. NODUMP, IMMUTABLE)') + subparser.add_argument('--noacls', dest='noacls', action='store_true', + help='do not extract/set ACLs') + subparser.add_argument('--noxattrs', dest='noxattrs', action='store_true', + help='do not extract/set xattrs') subparser.add_argument('--stdout', dest='stdout', action='store_true', help='write all extracted data to stdout') subparser.add_argument('--sparse', dest='sparse', action='store_true',