summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorBrian Curtin <brian@python.org>2011-06-13 20:16:04 (GMT)
committerBrian Curtin <brian@python.org>2011-06-13 20:16:04 (GMT)
commitd25aef55c8b0025dd2ee7de11b526f34ceed6b66 (patch)
tree567a6c5afb5d1fbb53aed9a8f99eff1b907190cb /Lib/test
parent5b52f957977f450613c6eafdc9216ae7993d4d49 (diff)
downloadcpython-d25aef55c8b0025dd2ee7de11b526f34ceed6b66.zip
cpython-d25aef55c8b0025dd2ee7de11b526f34ceed6b66.tar.gz
cpython-d25aef55c8b0025dd2ee7de11b526f34ceed6b66.tar.bz2
Fix #12084. os.stat on Windows wasn't working properly with relative symlinks.
Use of DeviceIoControl to obtain the symlink path via the reparse tag was removed. The code now uses GetFinalPathNameByHandle in the case of a symbolic link and works properly given the added test which creates a symbolic link and calls os.stat on it from multiple locations. Victor Stinner also noticed an issue with os.lstat following the os.stat code path when being passed bytes. The posix_lstat function was adjusted to properly hook up win32_lstat instead of the previous STAT macro (win32_stat).
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/support.py2
-rw-r--r--Lib/test/test_os.py45
2 files changed, 46 insertions, 1 deletions
diff --git a/Lib/test/support.py b/Lib/test/support.py
index 2aedf24..9c8f6d3 100644
--- a/Lib/test/support.py
+++ b/Lib/test/support.py
@@ -1490,7 +1490,7 @@ def can_symlink():
try:
os.symlink(TESTFN, TESTFN + "can_symlink")
can = True
- except (OSError, NotImplementedError):
+ except (OSError, NotImplementedError, AttributeError):
can = False
_can_symlink = can
return can
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 56be375..f58a5c1 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -1243,6 +1243,51 @@ class Win32SymlinkTests(unittest.TestCase):
self.assertEqual(os.stat(link), os.stat(target))
self.assertNotEqual(os.lstat(link), os.stat(link))
+ bytes_link = os.fsencode(link)
+ self.assertEqual(os.stat(bytes_link), os.stat(target))
+ self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link))
+
+ def test_12084(self):
+ level1 = os.path.abspath(support.TESTFN)
+ level2 = os.path.join(level1, "level2")
+ level3 = os.path.join(level2, "level3")
+ try:
+ os.mkdir(level1)
+ os.mkdir(level2)
+ os.mkdir(level3)
+
+ file1 = os.path.abspath(os.path.join(level1, "file1"))
+
+ with open(file1, "w") as f:
+ f.write("file1")
+
+ orig_dir = os.getcwd()
+ try:
+ os.chdir(level2)
+ link = os.path.join(level2, "link")
+ os.symlink(os.path.relpath(file1), "link")
+ self.assertIn("link", os.listdir(os.getcwd()))
+
+ # Check os.stat calls from the same dir as the link
+ self.assertEqual(os.stat(file1), os.stat("link"))
+
+ # Check os.stat calls from a dir below the link
+ os.chdir(level1)
+ self.assertEqual(os.stat(file1),
+ os.stat(os.path.relpath(link)))
+
+ # Check os.stat calls from a dir above the link
+ os.chdir(level3)
+ self.assertEqual(os.stat(file1),
+ os.stat(os.path.relpath(link)))
+ finally:
+ os.chdir(orig_dir)
+ except OSError as err:
+ self.fail(err)
+ finally:
+ os.remove(file1)
+ shutil.rmtree(level1)
+
class FSEncodingTests(unittest.TestCase):
def test_nop(self):