2 from __future__ import absolute_import
5 from bup.helpers import add_error, should_rx_exclude_path, debug1, resolve_parent
6 from bup.io import path_msg
7 import bup.xstat as xstat
11 O_LARGEFILE = os.O_LARGEFILE
12 except AttributeError:
15 O_NOFOLLOW = os.O_NOFOLLOW
16 except AttributeError:
20 # the use of fchdir() and lstat() is for two reasons:
21 # - help out the kernel by not making it repeatedly look up the absolute path
22 # - avoid race conditions caused by doing listdir() on a changing symlink
24 def __init__(self, path):
26 self.fd = os.open(path, os.O_RDONLY|O_LARGEFILE|O_NOFOLLOW|os.O_NDELAY)
38 return xstat.fstat(self.fd)
41 _IFMT = stat.S_IFMT(0xffffffff) # avoid function call in inner loop
44 for n in os.listdir(b'.'):
48 add_error(Exception('%s: %s' % (resolve_parent(n), str(e))))
50 if (st.st_mode & _IFMT) == stat.S_IFDIR:
57 def _recursive_dirlist(prepend, xdev, bup_dir=None,
60 xdev_exceptions=frozenset()):
61 for (name,pst) in _dirlist():
64 if os.path.normpath(path) in excluded_paths:
65 debug1('Skipping %r: excluded.\n' % path_msg(path))
67 if exclude_rxs and should_rx_exclude_path(path, exclude_rxs):
69 if name.endswith(b'/'):
71 if os.path.normpath(path) == bup_dir:
72 debug1('Skipping BUP_DIR.\n')
74 if xdev != None and pst.st_dev != xdev \
75 and path not in xdev_exceptions:
76 debug1('Skipping contents of %r: different filesystem.\n'
82 add_error('%s: %s' % (prepend, e))
84 for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev,
86 excluded_paths=excluded_paths,
87 exclude_rxs=exclude_rxs,
88 xdev_exceptions=xdev_exceptions):
94 def recursive_dirlist(paths, xdev, bup_dir=None,
97 xdev_exceptions=frozenset()):
98 startdir = OsFile(b'.')
100 assert(type(paths) != type(''))
103 pst = xstat.lstat(path)
104 if stat.S_ISLNK(pst.st_mode):
108 add_error('recursive_dirlist: %s' % e)
120 if stat.S_ISDIR(pst.st_mode):
122 prepend = os.path.join(path, b'')
123 for i in _recursive_dirlist(prepend=prepend, xdev=xdev,
125 excluded_paths=excluded_paths,
126 exclude_rxs=exclude_rxs,
127 xdev_exceptions=xdev_exceptions):