summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTW <tw@waldmann-edv.de>2017-10-28 13:31:47 +0200
committerGitHub <noreply@github.com>2017-10-28 13:31:47 +0200
commit926b1c6374ae51f1aec0060a616666068aab94f4 (patch)
treeae2584a4279f4ea8993d520ab7ab22121a1b9508
parentc0b905875953a3819cb8b1454d3985608dff1934 (diff)
parent36f2a4e1dcac69f58e5cfc8141a65b5006f32cf3 (diff)
Merge pull request #3212 from ThomasWaldmann/stat-after-match
don't do stat() when not recursing into excluded dir, fixes #3209
-rw-r--r--src/borg/archiver.py37
1 files changed, 23 insertions, 14 deletions
diff --git a/src/borg/archiver.py b/src/borg/archiver.py
index 32983ade8..b09490bf2 100644
--- a/src/borg/archiver.py
+++ b/src/borg/archiver.py
@@ -537,20 +537,27 @@ class Archiver:
This should only raise on critical errors. Per-item errors must be handled within this method.
"""
- if st is None:
- with backup_io('stat'):
- st = os.stat(path, follow_symlinks=False)
-
- recurse_excluded_dir = False
- if not matcher.match(path):
- self.print_file_status('x', path)
-
- if stat.S_ISDIR(st.st_mode) and matcher.recurse_dir:
- recurse_excluded_dir = True
+ try:
+ recurse_excluded_dir = False
+ if matcher.match(path):
+ if st is None:
+ with backup_io('stat'):
+ st = os.stat(path, follow_symlinks=False)
else:
- return
+ self.print_file_status('x', path)
+ # get out here as quickly as possible:
+ # we only need to continue if we shall recurse into an excluded directory.
+ # if we shall not recurse, then do not even touch (stat()) the item, it
+ # could trigger an error, e.g. if access is forbidden, see #3209.
+ if not matcher.recurse_dir:
+ return
+ if st is None:
+ with backup_io('stat'):
+ st = os.stat(path, follow_symlinks=False)
+ recurse_excluded_dir = stat.S_ISDIR(st.st_mode)
+ if not recurse_excluded_dir:
+ return
- try:
if (st.st_ino, st.st_dev) in skip_inodes:
return
# if restrict_dev is given, we do not want to recurse into a new filesystem,
@@ -1823,10 +1830,12 @@ class Archiver:
may specify the backup roots (starting points) and patterns for inclusion/exclusion.
A root path starts with the prefix `R`, followed by a path (a plain path, not a
file pattern). An include rule starts with the prefix +, an exclude rule starts
- with the prefix -, both followed by a pattern.
+ with the prefix -, an exclude-norecurse rule starts with !, all followed by a pattern.
Inclusion patterns are useful to include paths that are contained in an excluded
path. The first matching pattern is used so if an include pattern matches before
- an exclude pattern, the file is backed up.
+ an exclude pattern, the file is backed up. If an exclude-norecurse pattern matches
+ a directory, it won't recurse into it and won't discover any potential matches for
+ include rules below that directory.
Note that the default pattern style for ``--pattern`` and ``--patterns-from`` is
shell style (`sh:`), so those patterns behave similar to rsync include/exclude