Revert 22c60c18c and introduce a better detection
for symlink-loops. For example this is ok:
dir1/
dir2/
symdir -> dir2/
While this is a loop:
dir1/
symdir -> ../dir1/
... | ... |
@@ -21,15 +21,25 @@ def _fswalk_follow_symlinks(path): |
21 | 21 |
''' |
22 | 22 |
Walk filesystem, following symbolic links (but without recursion), on python2.4 and later |
23 | 23 |
|
24 |
- If a recursive directory link is detected, emit a warning and skip. |
|
24 |
+ If a symlink directory loop is detected, emit a warning and skip. |
|
25 |
+ E.g. |
|
26 |
+ dir1/ |
|
27 |
+ dir2/ |
|
28 |
+ sym-dir -> ../dir2 |
|
25 | 29 |
''' |
26 | 30 |
assert os.path.isdir(path) # only designed for directory argument |
27 |
- walkdirs = [path] |
|
31 |
+ walkdirs = set([path]) |
|
28 | 32 |
for dirpath, dirnames, filenames in os.walk(path): |
33 |
+ real_dirpath = os.path.realpath(dirpath) |
|
29 | 34 |
for dirname in dirnames: |
30 | 35 |
current = os.path.join(dirpath, dirname) |
36 |
+ real_current = os.path.realpath(current) |
|
31 | 37 |
if os.path.islink(current): |
32 |
- walkdirs.append(current) |
|
38 |
+ if (real_dirpath == real_current or |
|
39 |
+ real_dirpath.startswith(real_current + os.path.sep)): |
|
40 |
+ warning("Skipping recursively symlinked directory %s" % dirname) |
|
41 |
+ else: |
|
42 |
+ walkdirs.add(current) |
|
33 | 43 |
for walkdir in walkdirs: |
34 | 44 |
for value in os.walk(walkdir): |
35 | 45 |
yield value |