Browse code

Compartmentalized symlink-safe directory walk, with all tests passing on python2.5 and python2.6

git-svn-id: https://s3tools.svn.sourceforge.net/svnroot/s3tools/s3cmd/branches/amax-follow-symlinks@432 830e0280-6d2a-0410-9c65-932aecc39d9d

Aaron Maxwell authored on 2010/07/26 03:48:37
Showing 1 changed files
... ...
@@ -36,6 +36,31 @@ def check_args_type(args, type, verbose_type):
36 36
 		if S3Uri(arg).type != type:
37 37
 			raise ParameterError("Expecting %s instead of '%s'" % (verbose_type, arg))
38 38
 
39
+def fswalk_follow_symlinks(path):
40
+        '''
41
+        Walk filesystem, following symbolic links (but without recursion), on python2.4 and later
42
+        '''
43
+        assert os.path.isdir(path) # only designed for directory argument
44
+        walkdirs = set([path])
45
+        symlink_targets = set()
46
+        for dirpath, dirnames, filenames in os.walk(path):
47
+                for dirname in dirnames:
48
+                        if os.path.islink(dirname):
49
+                                target = os.path.realpath(dirname)
50
+                                if target in symlink_targets:
51
+                                        warning(u"Skipping recursively symlinked directory %s" % dirname)
52
+                                else:
53
+                                        walkdirs.add(dirname)
54
+                                        symlink_targets.add(target)
55
+        for walkdir in walkdirs:
56
+                for value in os.walk(walkdir):
57
+                        yield value
58
+
59
+def fswalk(path, follow_symlinks):
60
+        if follow_symlinks:
61
+                return fswalk_follow_symlinks(path)
62
+        return os.walk(path)
63
+
39 64
 def cmd_du(args):
40 65
 	s3 = S3(Config())
41 66
 	if len(args) > 0:
... ...
@@ -620,7 +645,7 @@ def _get_filelist_local(local_uri):
620 620
 	if local_uri.isdir():
621 621
 		local_base = deunicodise(local_uri.basename())
622 622
 		local_path = deunicodise(local_uri.path())
623
-		filelist = os.walk(local_path)
623
+		filelist = fswalk(local_path, cfg.follow_symlinks)
624 624
 		single_file = False
625 625
 	else:
626 626
 		local_base = ""