2 from bup.helpers import *
3 import bup.xstat as xstat
6 O_LARGEFILE = os.O_LARGEFILE
11 # the use of fchdir() and lstat() is for two reasons:
12 # - help out the kernel by not making it repeatedly look up the absolute path
13 # - avoid race conditions caused by doing listdir() on a changing symlink
15 def __init__(self, path):
17 self.fd = os.open(path,
18 os.O_RDONLY|O_LARGEFILE|os.O_NOFOLLOW|os.O_NDELAY)
30 return xstat.fstat(self.fd)
33 _IFMT = stat.S_IFMT(0xffffffff) # avoid function call in inner loop
36 for n in os.listdir('.'):
40 add_error(Exception('%s: %s' % (realpath(n), str(e))))
42 if (st.st_mode & _IFMT) == stat.S_IFDIR:
49 def _recursive_dirlist(prepend, xdev):
50 for (name,pst) in _dirlist():
51 if name.endswith('/'):
52 if xdev != None and pst.st_dev != xdev:
53 log('Skipping %r: different filesystem.\n' % (prepend+name))
58 add_error('%s: %s' % (prepend, e))
60 for i in _recursive_dirlist(prepend=prepend+name, xdev=xdev):
63 yield (prepend + name, pst)
66 def recursive_dirlist(paths, xdev):
67 startdir = OsFile('.')
69 assert(type(paths) != type(''))
72 pst = xstat.lstat(path)
73 if stat.S_ISLNK(pst.st_mode):
77 add_error('recursive_dirlist: %s' % e)
89 if stat.S_ISDIR(pst.st_mode):
91 prepend = os.path.join(path, '')
92 for i in _recursive_dirlist(prepend=prepend, xdev=xdev):