X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fbup%2Fdrecurse.py;h=1d9a4e14b5e5d91c3951acd587c88be619955319;hb=f0a4b3b6ef7d00e64b04dee51b8e15db71b693d3;hp=169aa31c64f549e77799381ed044d5672910e184;hpb=2ff672c48f3dbde761b30775adcdc76a621df527;p=bup.git diff --git a/lib/bup/drecurse.py b/lib/bup/drecurse.py index 169aa31..1d9a4e1 100644 --- a/lib/bup/drecurse.py +++ b/lib/bup/drecurse.py @@ -1,10 +1,20 @@ -import stat -from bup.helpers import * + +from __future__ import absolute_import +import stat, os + +from bup.helpers import add_error, should_rx_exclude_path, debug1, resolve_parent +from bup.io import path_msg +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 +23,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,58 +35,81 @@ 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 def _dirlist(): l = [] - for n in os.listdir('.'): + for n in os.listdir(b'.'): 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 += '/' + n += b'/' l.append((n,st)) l.sort(reverse=True) return l -def _recursive_dirlist(prepend, xdev): +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_msg(path)) continue - try: - OsFile(name).fchdir() - except OSError, e: - add_error('%s: %s' % (prepend, e)) + if exclude_rxs and should_rx_exclude_path(path, exclude_rxs): + continue + if name.endswith(b'/'): + if bup_dir != None: + if os.path.normpath(path) == bup_dir: + debug1('Skipping BUP_DIR.\n') + continue + if xdev != None and pst.st_dev != xdev \ + and path not in xdev_exceptions: + debug1('Skipping contents of %r: different filesystem.\n' + % path_msg(path)) else: - for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev): - 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(b'..') + yield (path, pst) -def recursive_dirlist(paths, xdev): - startdir = OsFile('.') +def recursive_dirlist(paths, xdev, bup_dir=None, + excluded_paths=None, + exclude_rxs=None, + xdev_exceptions=frozenset()): + startdir = OsFile(b'.') 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: - add_error(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() @@ -87,8 +119,12 @@ def recursive_dirlist(paths, xdev): xdev = None if stat.S_ISDIR(pst.st_mode): pfile.fchdir() - prepend = os.path.join(path, '') - for i in _recursive_dirlist(prepend=prepend, xdev=xdev): + prepend = os.path.join(path, b'') + for i in _recursive_dirlist(prepend=prepend, xdev=xdev, + bup_dir=bup_dir, + excluded_paths=excluded_paths, + exclude_rxs=exclude_rxs, + xdev_exceptions=xdev_exceptions): yield i startdir.fchdir() else: