X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=lib%2Fbup%2Fdrecurse.py;h=14bb7212a9ecb3e5466f8236ed9674a9420d2332;hb=715706923d39c3f409017ce35cea799b97e5dabb;hp=879ba5a522fc64464bf43ec4d5545558c7ef362b;hpb=ea5af6638e0a26d6e515081a70d6d75e2630a151;p=bup.git diff --git a/lib/bup/drecurse.py b/lib/bup/drecurse.py index 879ba5a..14bb721 100644 --- a/lib/bup/drecurse.py +++ b/lib/bup/drecurse.py @@ -1,10 +1,18 @@ + import stat, os -from bup.helpers import * + +from bup.helpers import add_error, should_rx_exclude_path, debug1, resolve_parent +import bup.xstat as xstat + try: O_LARGEFILE = os.O_LARGEFILE except AttributeError: O_LARGEFILE = 0 +try: + O_NOFOLLOW = os.O_NOFOLLOW +except AttributeError: + O_NOFOLLOW = 0 # the use of fchdir() and lstat() is for two reasons: @@ -13,8 +21,7 @@ except AttributeError: class OsFile: def __init__(self, path): self.fd = None - self.fd = os.open(path, - os.O_RDONLY|O_LARGEFILE|os.O_NOFOLLOW|os.O_NDELAY) + self.fd = os.open(path, os.O_RDONLY|O_LARGEFILE|O_NOFOLLOW|os.O_NDELAY) def __del__(self): if self.fd: @@ -26,7 +33,7 @@ class OsFile: os.fchdir(self.fd) def stat(self): - return os.fstat(self.fd) + return xstat.fstat(self.fd) _IFMT = stat.S_IFMT(0xffffffff) # avoid function call in inner loop @@ -34,9 +41,9 @@ def _dirlist(): l = [] for n in os.listdir('.'): try: - st = os.lstat(n) - except OSError, e: - add_error(Exception('%s: %s' % (realpath(n), str(e)))) + st = xstat.lstat(n) + except OSError as e: + add_error(Exception('%s: %s' % (resolve_parent(n), str(e)))) continue if (st.st_mode & _IFMT) == stat.S_IFDIR: n += '/' @@ -45,49 +52,61 @@ def _dirlist(): return l -def _recursive_dirlist(prepend, xdev, bup_dir=None, excluded_paths=None): +def _recursive_dirlist(prepend, xdev, bup_dir=None, + excluded_paths=None, + exclude_rxs=None, + xdev_exceptions=frozenset()): for (name,pst) in _dirlist(): - if name.endswith('/'): - if xdev != None and pst.st_dev != xdev: - log('Skipping %r: different filesystem.\n' % (prepend+name)) + path = prepend + name + if excluded_paths: + if os.path.normpath(path) in excluded_paths: + debug1('Skipping %r: excluded.\n' % path) continue + if exclude_rxs and should_rx_exclude_path(path, exclude_rxs): + continue + if name.endswith('/'): if bup_dir != None: - if os.path.normpath(prepend+name) == bup_dir: - log('Skipping BUP_DIR.\n') - continue - if excluded_paths: - if os.path.normpath(prepend+name) in excluded_paths: - log('Skipping %r: excluded.\n' % (prepend+name)) + if os.path.normpath(path) == bup_dir: + debug1('Skipping BUP_DIR.\n') continue - try: - OsFile(name).fchdir() - except OSError, e: - add_error('%s: %s' % (prepend, e)) + if xdev != None and pst.st_dev != xdev \ + and path not in xdev_exceptions: + debug1('Skipping contents of %r: different filesystem.\n' % path) else: - for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev, - bup_dir=bup_dir, - excluded_paths=excluded_paths): - yield i - os.chdir('..') - yield (prepend + name, pst) + try: + OsFile(name).fchdir() + except OSError as e: + add_error('%s: %s' % (prepend, e)) + else: + for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev, + bup_dir=bup_dir, + excluded_paths=excluded_paths, + exclude_rxs=exclude_rxs, + xdev_exceptions=xdev_exceptions): + yield i + os.chdir('..') + yield (path, pst) -def recursive_dirlist(paths, xdev, bup_dir=None, excluded_paths=None): +def recursive_dirlist(paths, xdev, bup_dir=None, + excluded_paths=None, + exclude_rxs=None, + xdev_exceptions=frozenset()): startdir = OsFile('.') try: assert(type(paths) != type('')) for path in paths: try: - pst = os.lstat(path) + pst = xstat.lstat(path) if stat.S_ISLNK(pst.st_mode): yield (path, pst) continue - except OSError, e: + except OSError as e: add_error('recursive_dirlist: %s' % e) continue try: pfile = OsFile(path) - except OSError, e: + except OSError as e: add_error(e) continue pst = pfile.stat() @@ -100,7 +119,9 @@ def recursive_dirlist(paths, xdev, bup_dir=None, excluded_paths=None): prepend = os.path.join(path, '') for i in _recursive_dirlist(prepend=prepend, xdev=xdev, bup_dir=bup_dir, - excluded_paths=excluded_paths): + excluded_paths=excluded_paths, + exclude_rxs=exclude_rxs, + xdev_exceptions=xdev_exceptions): yield i startdir.fchdir() else: