소스 검색

create/extract: add --noxattrs option, #3955

when given with borg create, borg will not get xattrs from input files (and thus, it will not archive xattrs).

when given with borg extract, borg will not read xattrs from archive and it will not set xattrs on extracted files.
Thomas Waldmann 4 년 전
부모
커밋
1b65db990d
2개의 변경된 파일21개의 추가작업 그리고 9개의 파일을 삭제
  1. 14 8
      src/borg/archive.py
  2. 7 1
      src/borg/archiver.py

+ 14 - 8
src/borg/archive.py

@@ -380,7 +380,7 @@ class Archive:
 
 
     def __init__(self, repository, key, manifest, name, cache=None, create=False,
     def __init__(self, repository, key, manifest, name, cache=None, create=False,
                  checkpoint_interval=1800, numeric_owner=False, noatime=False, noctime=False,
                  checkpoint_interval=1800, numeric_owner=False, noatime=False, noctime=False,
-                 noflags=False, noacls=False,
+                 noflags=False, noacls=False, noxattrs=False,
                  progress=False, chunker_params=CHUNKER_PARAMS, start=None, start_monotonic=None, end=None,
                  progress=False, chunker_params=CHUNKER_PARAMS, start=None, start_monotonic=None, end=None,
                  consider_part_files=False, log_json=False):
                  consider_part_files=False, log_json=False):
         self.cwd = os.getcwd()
         self.cwd = os.getcwd()
@@ -400,6 +400,7 @@ class Archive:
         self.noctime = noctime
         self.noctime = noctime
         self.noflags = noflags
         self.noflags = noflags
         self.noacls = noacls
         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.'
         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:
         if start is None:
             start = datetime.utcnow()
             start = datetime.utcnow()
@@ -857,11 +858,12 @@ Utilization of max. archive size: {csize_max:.0%}
                 pass
                 pass
             if not self.noacls:
             if not self.noacls:
                 acl_set(path, item, self.numeric_owner, fd=fd)
                 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.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:
             # bsdflags include the immutable flag and need to be set last:
             if not self.noflags and 'bsdflags' in item:
             if not self.noflags and 'bsdflags' in item:
                 try:
                 try:
@@ -1042,11 +1044,13 @@ Utilization of max. archive size: {csize_max:.0%}
 
 
 
 
 class MetadataCollector:
 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.noatime = noatime
         self.noctime = noctime
         self.noctime = noctime
         self.numeric_owner = numeric_owner
         self.numeric_owner = numeric_owner
         self.noflags = noflags
         self.noflags = noflags
+        self.noacls = noacls
+        self.noxattrs = noxattrs
         self.nobirthtime = nobirthtime
         self.nobirthtime = nobirthtime
 
 
     def stat_simple_attrs(self, st):
     def stat_simple_attrs(self, st):
@@ -1076,10 +1080,12 @@ class MetadataCollector:
     def stat_ext_attrs(self, st, path, fd=None):
     def stat_ext_attrs(self, st, path, fd=None):
         attrs = {}
         attrs = {}
         flags = 0
         flags = 0
+        xattrs = {}
         with backup_io('extended stat'):
         with backup_io('extended stat'):
             if not self.noflags:
             if not self.noflags:
                 flags = get_flags(path, st, fd=fd)
                 flags = get_flags(path, st, fd=fd)
-            xattrs = xattr.get_all(fd or path, follow_symlinks=False)
+            if not self.noxattrs:
+                xattrs = xattr.get_all(fd or path, follow_symlinks=False)
             if not self.noacls:
             if not self.noacls:
                 acl_get(path, attrs, st, self.numeric_owner, fd=fd)
                 acl_get(path, attrs, st, self.numeric_owner, fd=fd)
         if xattrs:
         if xattrs:

+ 7 - 1
src/borg/archiver.py

@@ -190,6 +190,7 @@ def with_archive(method):
                           numeric_owner=getattr(args, 'numeric_owner', False),
                           numeric_owner=getattr(args, 'numeric_owner', False),
                           noflags=getattr(args, 'nobsdflags', False) or getattr(args, 'noflags', False),
                           noflags=getattr(args, 'nobsdflags', False) or getattr(args, 'noflags', False),
                           noacls=getattr(args, 'noacls', False),
                           noacls=getattr(args, 'noacls', False),
+                          noxattrs=getattr(args, 'noxattrs', False),
                           cache=kwargs.get('cache'),
                           cache=kwargs.get('cache'),
                           consider_part_files=args.consider_part_files, log_json=args.log_json)
                           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)
         return method(self, args, repository=repository, manifest=manifest, key=key, archive=archive, **kwargs)
@@ -637,6 +638,7 @@ class Archiver:
         self.output_list = args.output_list
         self.output_list = args.output_list
         self.noflags = args.nobsdflags or args.noflags
         self.noflags = args.nobsdflags or args.noflags
         self.noacls = args.noacls
         self.noacls = args.noacls
+        self.noxattrs = args.noxattrs
         self.exclude_nodump = args.exclude_nodump
         self.exclude_nodump = args.exclude_nodump
         dry_run = args.dry_run
         dry_run = args.dry_run
         t0 = datetime.utcnow()
         t0 = datetime.utcnow()
@@ -653,7 +655,7 @@ class Archiver:
                                   chunker_params=args.chunker_params, start=t0, start_monotonic=t0_monotonic,
                                   chunker_params=args.chunker_params, start=t0, start_monotonic=t0_monotonic,
                                   log_json=args.log_json)
                                   log_json=args.log_json)
                 metadata_collector = MetadataCollector(noatime=not args.atime, noctime=args.noctime,
                 metadata_collector = MetadataCollector(noatime=not args.atime, noctime=args.noctime,
-                    noflags=args.nobsdflags or args.noflags, noacls=args.noacls,
+                    noflags=args.nobsdflags or args.noflags, noacls=args.noacls, noxattrs=args.noxattrs,
                     numeric_owner=args.numeric_owner, nobirthtime=args.nobirthtime)
                     numeric_owner=args.numeric_owner, nobirthtime=args.nobirthtime)
                 cp = ChunksProcessor(cache=cache, key=key,
                 cp = ChunksProcessor(cache=cache, key=key,
                     add_item=archive.add_item, write_checkpoint=archive.write_checkpoint,
                     add_item=archive.add_item, write_checkpoint=archive.write_checkpoint,
@@ -3384,6 +3386,8 @@ class Archiver:
                               help='do not read and store flags (e.g. NODUMP, IMMUTABLE) into archive')
                               help='do not read and store flags (e.g. NODUMP, IMMUTABLE) into archive')
         fs_group.add_argument('--noacls', dest='noacls', action='store_true',
         fs_group.add_argument('--noacls', dest='noacls', action='store_true',
                               help='do not read and store ACLs into archive')
                               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',
         fs_group.add_argument('--sparse', dest='sparse', action='store_true',
                                help='detect sparse holes in input (supported only by fixed chunker)')
                                help='detect sparse holes in input (supported only by fixed chunker)')
         fs_group.add_argument('--files-cache', metavar='MODE', dest='files_cache_mode',
         fs_group.add_argument('--files-cache', metavar='MODE', dest='files_cache_mode',
@@ -3804,6 +3808,8 @@ class Archiver:
                                help='do not extract/set flags (e.g. NODUMP, IMMUTABLE)')
                                help='do not extract/set flags (e.g. NODUMP, IMMUTABLE)')
         subparser.add_argument('--noacls', dest='noacls', action='store_true',
         subparser.add_argument('--noacls', dest='noacls', action='store_true',
                                help='do not extract/set ACLs')
                                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',
         subparser.add_argument('--stdout', dest='stdout', action='store_true',
                                help='write all extracted data to stdout')
                                help='write all extracted data to stdout')
         subparser.add_argument('--sparse', dest='sparse', action='store_true',
         subparser.add_argument('--sparse', dest='sparse', action='store_true',