diff -r bae0912dd160 Lib/posixpath.py --- a/Lib/posixpath.py Thu Oct 01 08:56:54 2015 +0200 +++ b/Lib/posixpath.py Sat Nov 14 15:18:07 2015 +0100 @@ -182,7 +182,8 @@ try: s1 = os.lstat(path) except OSError: - # It doesn't exist -- so not a mount point. :-) + # the OSError should be handled with more care + # it could be a "permission denied" but path is still a mount return False else: # A symlink can never be a mount point @@ -193,19 +194,19 @@ parent = join(path, b'..') else: parent = join(path, '..') + parent = realpath(parent) + try: s2 = os.lstat(parent) except OSError: + # one should handle the returned OSError with more care to figure + # out whether this is still a mount return False - dev1 = s1.st_dev - dev2 = s2.st_dev - if dev1 != dev2: + if s1.st_dev != s2.st_dev: return True # path/.. on a different device as path - ino1 = s1.st_ino - ino2 = s2.st_ino - if ino1 == ino2: - return True # path/.. is the same i-node as path + if s1.st_ino == s2.st_ino: + return True # path/.. is the same i-node as path, i.e. path=='/' return False diff -r bae0912dd160 Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py Thu Oct 01 08:56:54 2015 +0200 +++ b/Lib/test/test_posixpath.py Sat Nov 14 15:18:07 2015 +0100 @@ -1,7 +1,5 @@ -import itertools import os import posixpath -import sys import unittest import warnings from posixpath import realpath, abspath, dirname, basename @@ -213,6 +211,29 @@ finally: os.lstat = save_lstat + @unittest.skipIf(posix is None, "Test requires posix module") + def test_ismount_directory_not_readable(self): + """Simulate ismount run on a directory that is not readable + this lead to a wrong result as stated in http://bugs.python.org/issue2466 + """ + 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") self.assertEqual(posixpath.expanduser(b"foo"), b"foo")