-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
+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:
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:
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
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 += '/'
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)
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('/'):
+ 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)
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('..')
+ yield (path, pst)
-def recursive_dirlist(paths, xdev):
+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:
- 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()
if stat.S_ISDIR(pst.st_mode):
pfile.fchdir()
prepend = os.path.join(path, '')
- for i in _recursive_dirlist(prepend=prepend, xdev=xdev):
+ 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: