From 7a94c3ccc89683f831c22574743f76591e6f79c3 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Aug 2018 08:33:58 +0300 Subject: [PATCH 01/12] bpo-34384: Fix os.readlink() on Windows os.readlink() now accepts path-like objects on Windows. --- Lib/test/test_os.py | 7 +++++++ Modules/posixmodule.c | 32 ++++++++++++++++++-------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index a140ae0d29eae1..7048816142d54c 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2077,6 +2077,13 @@ def test_file_link(self): self.assertTrue(os.path.islink(self.filelink)) self.check_stat(self.filelink, self.filelink_target) + @unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()') + def test_readlink_pathlike(self): + os.symlink(self.filelink_target, self.filelink) + import pathlib + filelink = pathlib.Path(self.filelink) + self.assertEqual(os.readlink(filelink), self.filelink_target) + def _create_missing_dir_link(self): 'Create a "directory" link to a non-existent target' linkname = self.missing_link diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 3e03039f15b1c7..9c8d8e74960af8 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7467,10 +7467,10 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) static PyObject * win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) { - const wchar_t *path; + path_t path; DWORD n_bytes_returned; DWORD io_result; - PyObject *po, *result; + PyObject *result = NULL; int dir_fd; HANDLE reparse_point_handle; @@ -7480,15 +7480,13 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) static char *keywords[] = {"path", "dir_fd", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords, - &po, + memset(&path, 0, sizeof(path)); + path.function_name = "readlink"; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, + path_converter, &path, dir_fd_unavailable, &dir_fd )) - return NULL; - - path = _PyUnicode_AsUnicode(po); - if (path == NULL) - return NULL; + goto exit; /* First get a handle to the reparse point */ Py_BEGIN_ALLOW_THREADS @@ -7502,8 +7500,10 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) 0); Py_END_ALLOW_THREADS - if (reparse_point_handle==INVALID_HANDLE_VALUE) - return win32_error_object("readlink", po); + if (reparse_point_handle == INVALID_HANDLE_VALUE) { + result = path_error(&path); + goto exit; + } Py_BEGIN_ALLOW_THREADS /* New call DeviceIoControl to read the reparse point */ @@ -7518,20 +7518,24 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) CloseHandle(reparse_point_handle); Py_END_ALLOW_THREADS - if (io_result==0) - return win32_error_object("readlink", po); + if (io_result == 0) { + result = path_error(&path); + goto exit; + } if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) { PyErr_SetString(PyExc_ValueError, "not a symbolic link"); - return NULL; + goto exit; } print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.PrintNameOffset); result = PyUnicode_FromWideChar(print_name, rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); +exit: + path_cleanup(&path); return result; } From 618243b895d83e91d15c470953daa72355b0e913 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Aug 2018 08:45:00 +0300 Subject: [PATCH 02/12] add news blurb --- Lib/test/test_os.py | 2 +- .../next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 7048816142d54c..b58a264320b191 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2079,8 +2079,8 @@ def test_file_link(self): @unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()') def test_readlink_pathlike(self): - os.symlink(self.filelink_target, self.filelink) import pathlib + os.symlink(self.filelink_target, self.filelink) filelink = pathlib.Path(self.filelink) self.assertEqual(os.readlink(filelink), self.filelink_target) diff --git a/Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst b/Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst new file mode 100644 index 00000000000000..5a2a07e1990a12 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst @@ -0,0 +1,2 @@ +:func:`os.readlink` now accepts :term:`path-like objects ` +on Windows. From 35bb6b6c4e87d29045801cd8bd83c1909b3de132 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Aug 2018 08:45:08 +0300 Subject: [PATCH 03/12] fix build --- Modules/posixmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 9c8d8e74960af8..7340c29a1805ec 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7491,7 +7491,7 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) /* First get a handle to the reparse point */ Py_BEGIN_ALLOW_THREADS reparse_point_handle = CreateFileW( - path, + path.wide, 0, 0, 0, From b834795619e3567b65f2b98b30279e0cf3f63d3f Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Aug 2018 09:50:27 +0300 Subject: [PATCH 04/12] add some debug prints --- Lib/test/test_os.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index b58a264320b191..0e4da07ae09d51 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2082,6 +2082,12 @@ def test_readlink_pathlike(self): import pathlib os.symlink(self.filelink_target, self.filelink) filelink = pathlib.Path(self.filelink) + print() + print('Debug prints:') + print('filelink:', filelink) + print('readlink:', os.readlink(filelink)) + print('target:', self.filelink_target) + print() self.assertEqual(os.readlink(filelink), self.filelink_target) def _create_missing_dir_link(self): From 980b9c4b8da65d91d4bbd5f5fb79a54040db2b61 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Aug 2018 10:34:48 +0300 Subject: [PATCH 05/12] use FakePath --- Lib/test/test_os.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 0e4da07ae09d51..6695eb4e320736 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2079,15 +2079,8 @@ def test_file_link(self): @unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()') def test_readlink_pathlike(self): - import pathlib os.symlink(self.filelink_target, self.filelink) - filelink = pathlib.Path(self.filelink) - print() - print('Debug prints:') - print('filelink:', filelink) - print('readlink:', os.readlink(filelink)) - print('target:', self.filelink_target) - print() + filelink = FakePath(self.filelink) self.assertEqual(os.readlink(filelink), self.filelink_target) def _create_missing_dir_link(self): From 4c8b97e165cc193795d7879a198c07c7ff7bbacd Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sun, 12 Aug 2018 12:43:07 +0300 Subject: [PATCH 06/12] increase test coverage --- Lib/test/test_os.py | 53 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 6695eb4e320736..6658a61ea2a74a 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2039,6 +2039,53 @@ def test_listdir_extended_path(self): [os.fsencode(path) for path in self.created_paths]) +@unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()') +class ReadlinkTests(unittest.TestCase): + filelink = 'readlinktest' + filelink_target = os.path.abspath(__file__) + filelinkb = os.fsencode(filelink) + filelinkb_target = os.fsencode(filelink_target) + + def setUp(self): + self.assertTrue(os.path.exists(self.filelink_target)) + self.assertTrue(os.path.exists(self.filelinkb_target)) + self.assertFalse(os.path.exists(self.filelink)) + self.assertFalse(os.path.exists(self.filelinkb)) + + def test_not_symlink(self): + filelink_target = FakePath(self.filelink_target) + self.assertRaises(OSError, os.readlink, self.filelink_target) + self.assertRaises(OSError, os.readlink, filelink_target) + + def test_missing_link(self): + self.assertRaises(FileNotFoundError, os.readlink, 'missing-link') + self.assertRaises(FileNotFoundError, os.readlink, + FakePath('missing-link')) + + @support.skip_unless_symlink + def test_pathlike(self): + os.symlink(self.filelink_target, self.filelink) + self.addCleanup(support.unlink, self.filelink) + filelink = FakePath(self.filelink) + self.assertEqual(os.readlink(filelink), self.filelink_target) + + @support.skip_unless_symlink + def test_pathlike_bytes(self): + os.symlink(self.filelinkb_target, self.filelinkb) + self.addCleanup(support.unlink, self.filelinkb) + path = os.readlink(FakePath(self.filelinkb)) + self.assertEqual(path, self.filelinkb_target) + self.assertIsInstance(path, bytes) + + @support.skip_unless_symlink + def test_bytes(self): + os.symlink(self.filelinkb_target, self.filelinkb) + self.addCleanup(support.unlink, self.filelinkb) + path = os.readlink(self.filelinkb) + self.assertEqual(path, self.filelinkb_target) + self.assertIsInstance(path, bytes) + + @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") @support.skip_unless_symlink class Win32SymlinkTests(unittest.TestCase): @@ -2077,12 +2124,6 @@ def test_file_link(self): self.assertTrue(os.path.islink(self.filelink)) self.check_stat(self.filelink, self.filelink_target) - @unittest.skipUnless(hasattr(os, 'readlink'), 'needs os.readlink()') - def test_readlink_pathlike(self): - os.symlink(self.filelink_target, self.filelink) - filelink = FakePath(self.filelink) - self.assertEqual(os.readlink(filelink), self.filelink_target) - def _create_missing_dir_link(self): 'Create a "directory" link to a non-existent target' linkname = self.missing_link From 09c4335a27db47d44f7b3cff8a4bcbb3b44be181 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Mon, 13 Aug 2018 07:57:44 +0300 Subject: [PATCH 07/12] skip bytes tests on Windows --- Lib/test/test_os.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 6658a61ea2a74a..80654addec88a8 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2070,6 +2070,8 @@ def test_pathlike(self): self.assertEqual(os.readlink(filelink), self.filelink_target) @support.skip_unless_symlink + @unittest.skipIf(sys.platform == 'win32', + 'os.readlink() always returns str on Windows') def test_pathlike_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) @@ -2078,6 +2080,8 @@ def test_pathlike_bytes(self): self.assertIsInstance(path, bytes) @support.skip_unless_symlink + @unittest.skipIf(sys.platform == 'win32', + 'os.readlink() always returns str on Windows') def test_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) From 3b51dda6f9c5847a35b4c10d983499fbe2d3d062 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Mon, 13 Aug 2018 20:12:08 +0300 Subject: [PATCH 08/12] try to implement bytes support on Windows --- Lib/test/test_os.py | 4 ---- Modules/posixmodule.c | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 80654addec88a8..6658a61ea2a74a 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2070,8 +2070,6 @@ def test_pathlike(self): self.assertEqual(os.readlink(filelink), self.filelink_target) @support.skip_unless_symlink - @unittest.skipIf(sys.platform == 'win32', - 'os.readlink() always returns str on Windows') def test_pathlike_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) @@ -2080,8 +2078,6 @@ def test_pathlike_bytes(self): self.assertIsInstance(path, bytes) @support.skip_unless_symlink - @unittest.skipIf(sys.platform == 'win32', - 'os.readlink() always returns str on Windows') def test_bytes(self): os.symlink(self.filelinkb_target, self.filelinkb) self.addCleanup(support.unlink, self.filelinkb) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 7340c29a1805ec..d132a078fbf3bd 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7534,6 +7534,12 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) result = PyUnicode_FromWideChar(print_name, rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); + if (path.narrow) { + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); + if (!result) { + goto exit; + } + } exit: path_cleanup(&path); return result; From eb3063602bdde20c3aace00e9b075c12595d3ee9 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Mon, 13 Aug 2018 21:17:37 +0300 Subject: [PATCH 09/12] document new feature --- Doc/library/os.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst index c64f9321143731..df136da02cb1fa 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2014,8 +2014,10 @@ features: The *dir_fd* argument. .. versionchanged:: 3.6 - Accepts a :term:`path-like object`. + Accepts a :term:`path-like object` on Unix. + .. versionchanged:: 3.8 + Accepts a :term:`path-like object` and a bytes object on Windows. .. function:: remove(path, *, dir_fd=None) From d42c9b5371122d63c7e7d34230f038e4514cc44c Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Aug 2018 09:39:31 +0300 Subject: [PATCH 10/12] merge posix and windows implementations --- Modules/posixmodule.c | 86 +++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 56 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index d132a078fbf3bd..d086619cc9c010 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7414,18 +7414,25 @@ If dir_fd is not None, it should be a file descriptor open to a directory,\n\ and path should be relative; path will then be relative to that directory.\n\ dir_fd may not be implemented on your platform.\n\ If it is unavailable, using it will raise a NotImplementedError."); -#endif - -#ifdef HAVE_READLINK -/* AC 3.5: merge win32 and not together */ static PyObject * posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) { path_t path; +#if defined(HAVE_READLINK) int dir_fd = DEFAULT_DIR_FD; char buffer[MAXPATHLEN+1]; ssize_t length; +#elif defined(MS_WINDOWS) + int dir_fd; + DWORD n_bytes_returned; + DWORD io_result; + HANDLE reparse_point_handle; + + char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; + const wchar_t *print_name; +#endif PyObject *return_value = NULL; static char *keywords[] = {"path", "dir_fd", NULL}; @@ -7433,9 +7440,15 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) path.function_name = "readlink"; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, path_converter, &path, - READLINKAT_DIR_FD_CONVERTER, &dir_fd)) +#if defined(HAVE_READLINK) + READLINKAT_DIR_FD_CONVERTER, +#elif defined(MS_WINDOWS) + dir_fd_unavailable, +#endif + &dir_fd)) return NULL; +#if defined(HAVE_READLINK) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_READLINKAT if (dir_fd != DEFAULT_DIR_FD) @@ -7455,39 +7468,7 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length); else return_value = PyBytes_FromStringAndSize(buffer, length); -exit: - path_cleanup(&path); - return return_value; -} - -#endif /* HAVE_READLINK */ - -#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) - -static PyObject * -win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - DWORD n_bytes_returned; - DWORD io_result; - PyObject *result = NULL; - int dir_fd; - HANDLE reparse_point_handle; - - char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer; - const wchar_t *print_name; - - static char *keywords[] = {"path", "dir_fd", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "readlink"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, - path_converter, &path, - dir_fd_unavailable, &dir_fd - )) - goto exit; - +#elif defined(MS_WINDOWS) /* First get a handle to the reparse point */ Py_BEGIN_ALLOW_THREADS reparse_point_handle = CreateFileW( @@ -7501,7 +7482,7 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (reparse_point_handle == INVALID_HANDLE_VALUE) { - result = path_error(&path); + return_value = path_error(&path); goto exit; } @@ -7519,7 +7500,7 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (io_result == 0) { - result = path_error(&path); + return_value = path_error(&path); goto exit; } @@ -7532,22 +7513,20 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.PrintNameOffset); - result = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); + return_value = PyUnicode_FromWideChar(print_name, + rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); if (path.narrow) { - Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); - if (!result) { + Py_SETREF(return_value, PyUnicode_EncodeFSDefault(return_value)); + if (!return_value) { goto exit; } } +#endif exit: path_cleanup(&path); - return result; + return return_value; } - -#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ - - +#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ #ifdef HAVE_SYMLINK @@ -12960,16 +12939,11 @@ static PyMethodDef posix_methods[] = { OS_GETPRIORITY_METHODDEF OS_SETPRIORITY_METHODDEF OS_POSIX_SPAWN_METHODDEF -#ifdef HAVE_READLINK +#if defined(HAVE_READLINK) || defined(MS_WINDOWS) {"readlink", (PyCFunction)posix_readlink, METH_VARARGS | METH_KEYWORDS, readlink__doc__}, -#endif /* HAVE_READLINK */ -#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) - {"readlink", (PyCFunction)win_readlink, - METH_VARARGS | METH_KEYWORDS, - readlink__doc__}, -#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ +#endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */ OS_RENAME_METHODDEF OS_REPLACE_METHODDEF OS_RMDIR_METHODDEF From 7ccd0cea4b95d32f6f47858773646af8fbab35f5 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Aug 2018 10:38:57 +0300 Subject: [PATCH 11/12] adjust news entry --- .../next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst b/Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst index 5a2a07e1990a12..117236b21b04f2 100644 --- a/Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst +++ b/Misc/NEWS.d/next/Library/2018-08-12-08-43-21.bpo-34384.yjofCv.rst @@ -1,2 +1,2 @@ -:func:`os.readlink` now accepts :term:`path-like objects ` -on Windows. +:func:`os.readlink` now accepts :term:`path-like ` and +:class:`bytes` objects on Windows. From f3e6e2ffe28a4187bf2eca5faf4740b632088c15 Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Tue, 14 Aug 2018 13:06:52 +0300 Subject: [PATCH 12/12] address review comments --- Modules/posixmodule.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index d086619cc9c010..7f13735eadc8bd 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7419,12 +7419,11 @@ static PyObject * posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) { path_t path; -#if defined(HAVE_READLINK) int dir_fd = DEFAULT_DIR_FD; +#if defined(HAVE_READLINK) char buffer[MAXPATHLEN+1]; ssize_t length; #elif defined(MS_WINDOWS) - int dir_fd; DWORD n_bytes_returned; DWORD io_result; HANDLE reparse_point_handle; @@ -7440,12 +7439,7 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) path.function_name = "readlink"; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, path_converter, &path, -#if defined(HAVE_READLINK) - READLINKAT_DIR_FD_CONVERTER, -#elif defined(MS_WINDOWS) - dir_fd_unavailable, -#endif - &dir_fd)) + READLINKAT_DIR_FD_CONVERTER, &dir_fd)) return NULL; #if defined(HAVE_READLINK) @@ -7517,9 +7511,6 @@ posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); if (path.narrow) { Py_SETREF(return_value, PyUnicode_EncodeFSDefault(return_value)); - if (!return_value) { - goto exit; - } } #endif exit: