]> granicus.if.org Git - python/commitdiff
#14773: Fix os.fwalk() failing on dangling symlinks
authorHynek Schlawack <hs@ox.cx>
Tue, 15 May 2012 14:32:21 +0000 (16:32 +0200)
committerHynek Schlawack <hs@ox.cx>
Tue, 15 May 2012 14:32:21 +0000 (16:32 +0200)
Lib/os.py
Lib/test/test_os.py
Misc/NEWS

index ed2a31e88134d2a270c272cbac7dc40e627c4ba9..af4990fb8bfae18de1117a4489fb16de2f380f85 100644 (file)
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -353,13 +353,23 @@ if _exists("openat"):
         names = flistdir(topfd)
         dirs, nondirs = [], []
         for name in names:
-            # Here, we don't use AT_SYMLINK_NOFOLLOW to be consistent with
-            # walk() which reports symlinks to directories as directories. We do
-            # however check for symlinks before recursing into a subdirectory.
-            if st.S_ISDIR(fstatat(topfd, name).st_mode):
-                dirs.append(name)
-            else:
-                nondirs.append(name)
+            try:
+                # Here, we don't use AT_SYMLINK_NOFOLLOW to be consistent with
+                # walk() which reports symlinks to directories as directories.
+                # We do however check for symlinks before recursing into
+                # a subdirectory.
+                if st.S_ISDIR(fstatat(topfd, name).st_mode):
+                    dirs.append(name)
+                else:
+                    nondirs.append(name)
+            except FileNotFoundError:
+                try:
+                    # Add dangling symlinks, ignore disappeared files
+                    if st.S_ISLNK(fstatat(topfd, name, AT_SYMLINK_NOFOLLOW)
+                                .st_mode):
+                        nondirs.append(name)
+                except FileNotFoundError:
+                    continue
 
         if topdown:
             yield toppath, dirs, nondirs, topfd
index 066bf7231e3ff7167ea723b54af18aeb038faf08..1e0daf08556a16a8f78f699ac3e4cada49e7373a 100644 (file)
@@ -651,6 +651,7 @@ class WalkTests(unittest.TestCase):
         #         SUB2/             a file kid and a dirsymlink kid
         #           tmp3
         #           link/           a symlink to TESTFN.2
+        #           broken_link
         #       TEST2/
         #         tmp4              a lone file
         walk_path = join(support.TESTFN, "TEST1")
@@ -663,6 +664,8 @@ class WalkTests(unittest.TestCase):
         link_path = join(sub2_path, "link")
         t2_path = join(support.TESTFN, "TEST2")
         tmp4_path = join(support.TESTFN, "TEST2", "tmp4")
+        link_path = join(sub2_path, "link")
+        broken_link_path = join(sub2_path, "broken_link")
 
         # Create stuff.
         os.makedirs(sub11_path)
@@ -679,7 +682,8 @@ class WalkTests(unittest.TestCase):
             else:
                 symlink_to_dir = os.symlink
             symlink_to_dir(os.path.abspath(t2_path), link_path)
-            sub2_tree = (sub2_path, ["link"], ["tmp3"])
+            symlink_to_dir('broken', broken_link_path)
+            sub2_tree = (sub2_path, ["link"], ["broken_link", "tmp3"])
         else:
             sub2_tree = (sub2_path, [], ["tmp3"])
 
index 95a2c4f2f1ebcc33a7cd98715690ca2f47ce6c20..0e369030fdeb7a52e5c4de36cc5004bde2c7c856 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -31,6 +31,8 @@ Core and Builtins
 Library
 -------
 
+- Issue 14773: Fix os.fwalk() failing on dangling symlinks.
+
 - Issue 14807: move undocumented tarfile.filemode() to stat.filemode() and add
   doc entry. Add tarfile.filemode alias with deprecation warning.