2 from bup.helpers import *
3 import bup.xstat as xstat
6 O_LARGEFILE = os.O_LARGEFILE
10 O_NOFOLLOW = os.O_NOFOLLOW
11 except AttributeError:
15 # the use of fchdir() and lstat() is for two reasons:
16 # - help out the kernel by not making it repeatedly look up the absolute path
17 # - avoid race conditions caused by doing listdir() on a changing symlink
19 def __init__(self, path):
21 self.fd = os.open(path, os.O_RDONLY|O_LARGEFILE|O_NOFOLLOW|os.O_NDELAY)
33 return xstat.fstat(self.fd)
36 _IFMT = stat.S_IFMT(0xffffffff) # avoid function call in inner loop
39 for n in os.listdir('.'):
43 add_error(Exception('%s: %s' % (realpath(n), str(e))))
45 if (st.st_mode & _IFMT) == stat.S_IFDIR:
52 def _recursive_dirlist(prepend, xdev, bup_dir=None,
55 for (name,pst) in _dirlist():
58 if os.path.normpath(path) in excluded_paths:
59 debug1('Skipping %r: excluded.\n' % path)
61 if exclude_rxs and should_rx_exclude_path(path, exclude_rxs):
63 if name.endswith('/'):
65 if os.path.normpath(path) == bup_dir:
66 debug1('Skipping BUP_DIR.\n')
68 if xdev != None and pst.st_dev != xdev:
69 debug1('Skipping contents of %r: different filesystem.\n' % path)
74 add_error('%s: %s' % (prepend, e))
76 for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev,
78 excluded_paths=excluded_paths,
79 exclude_rxs=exclude_rxs):
85 def recursive_dirlist(paths, xdev, bup_dir=None, excluded_paths=None,
87 startdir = OsFile('.')
89 assert(type(paths) != type(''))
92 pst = xstat.lstat(path)
93 if stat.S_ISLNK(pst.st_mode):
97 add_error('recursive_dirlist: %s' % e)
109 if stat.S_ISDIR(pst.st_mode):
111 prepend = os.path.join(path, '')
112 for i in _recursive_dirlist(prepend=prepend, xdev=xdev,
114 excluded_paths=excluded_paths,
115 exclude_rxs=exclude_rxs):