]> granicus.if.org Git - python/commitdiff
# 2466: ismount now recognizes mount points user can't access.
authorR David Murray <rdmurray@bitdance.com>
Tue, 23 Aug 2016 16:30:28 +0000 (12:30 -0400)
committerR David Murray <rdmurray@bitdance.com>
Tue, 23 Aug 2016 16:30:28 +0000 (12:30 -0400)
Patch by Robin Roth, backport by Xiang Zhang.

Lib/posixpath.py
Lib/test/test_posixpath.py
Misc/ACKS
Misc/NEWS

index 8f928225e0191effb56d51d79793560f4e695fac..f5c2260f1e5f08a07ee74da9e303ce14dfd8038c 100644 (file)
@@ -186,7 +186,7 @@ def ismount(path):
         return False
     try:
         s1 = os.lstat(path)
-        s2 = os.lstat(join(path, '..'))
+        s2 = os.lstat(realpath(join(path, '..')))
     except os.error:
         return False # It doesn't exist -- so not a mount point :-)
     dev1 = s1.st_dev
index fbb18fd22bd02bf35d02822b20730321784c17ef..98bf0e041dd70135472db68970b4199b91190b87 100644 (file)
@@ -1,4 +1,5 @@
 import unittest
+from test import symlink_support
 from test import test_support, test_genericpath
 from test import test_support as support
 
@@ -7,6 +8,11 @@ import os
 import sys
 from posixpath import realpath, abspath, dirname, basename
 
+try:
+    import posix
+except ImportError:
+    posix = None
+
 # An absolute path to a temporary filename for testing. We can't rely on TESTFN
 # being an absolute path, so we need this.
 
@@ -100,7 +106,7 @@ class PosixPathTest(unittest.TestCase):
             f.write("foo")
             f.close()
             self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False)
-            if hasattr(os, "symlink"):
+            if symlink_support.can_symlink():
                 os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2")
                 self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True)
                 os.remove(test_support.TESTFN + "1")
@@ -196,6 +202,64 @@ class PosixPathTest(unittest.TestCase):
     def test_ismount(self):
         self.assertIs(posixpath.ismount("/"), True)
 
+    def test_ismount_non_existent(self):
+        # Non-existent mountpoint.
+        self.assertIs(posixpath.ismount(ABSTFN), False)
+        try:
+            os.mkdir(ABSTFN)
+            self.assertIs(posixpath.ismount(ABSTFN), False)
+        finally:
+            safe_rmdir(ABSTFN)
+
+    @symlink_support.skip_unless_symlink
+    def test_ismount_symlinks(self):
+        # Symlinks are never mountpoints.
+        try:
+            os.symlink("/", ABSTFN)
+            self.assertIs(posixpath.ismount(ABSTFN), False)
+        finally:
+            os.unlink(ABSTFN)
+
+    @unittest.skipIf(posix is None, "Test requires posix module")
+    def test_ismount_different_device(self):
+        # Simulate the path being on a different device from its parent by
+        # mocking out st_dev.
+        save_lstat = os.lstat
+        def fake_lstat(path):
+            st_ino = 0
+            st_dev = 0
+            if path == ABSTFN:
+                st_dev = 1
+                st_ino = 1
+            return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
+        try:
+            os.lstat = fake_lstat
+            self.assertIs(posixpath.ismount(ABSTFN), True)
+        finally:
+            os.lstat = save_lstat
+
+    @unittest.skipIf(posix is None, "Test requires posix module")
+    def test_ismount_directory_not_readable(self):
+        # issue #2466: Simulate ismount run on a directory that is not
+        # readable, which used to return False.
+        save_lstat = os.lstat
+        def fake_lstat(path):
+            st_ino = 0
+            st_dev = 0
+            if path.startswith(ABSTFN) and path != ABSTFN:
+                # ismount tries to read something inside the ABSTFN directory;
+                # simulate this being forbidden (no read permission).
+                raise OSError("Fake [Errno 13] Permission denied")
+            if path == ABSTFN:
+                st_dev = 1
+                st_ino = 1
+            return posix.stat_result((0, st_ino, st_dev, 0, 0, 0, 0, 0, 0, 0))
+        try:
+            os.lstat = fake_lstat
+            self.assertIs(posixpath.ismount(ABSTFN), True)
+        finally:
+            os.lstat = save_lstat
+
     def test_expanduser(self):
         self.assertEqual(posixpath.expanduser("foo"), "foo")
         with test_support.EnvironmentVarGuard() as env:
index 0210a4cd3650e9a4cc6b783d9e0e151084a155cb..07e5724fe4115f7cf51135e5cc84077276bfa936 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1186,6 +1186,7 @@ Guido van Rossum
 Just van Rossum
 Hugo van Rossum
 Saskia van Rossum
+Robin Roth
 Clement Rouault
 Donald Wallace Rouse II
 Liam Routt
index 392e9e7f88a5222a14eeccc8dfa236ec2443f829..d7ba5893c85937f9c8758e702eca7f34890193ec 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -33,6 +33,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #2466: posixpath.ismount now correctly recognizes mount points which
+  the user does not have permission to access.
+
 - Issue #27783: Fix possible usage of uninitialized memory in operator.methodcaller.
 
 - Issue #27774: Fix possible Py_DECREF on unowned object in _sre.