diff -r 5c48fbe12cb8 Lib/test/test_os.py --- a/Lib/test/test_os.py Sat Jan 14 21:04:40 2017 +0900 +++ b/Lib/test/test_os.py Sat Jan 14 09:49:43 2017 -0500 @@ -2139,9 +2139,13 @@ self.assertTrue(os.path.exists(self.junction)) self.assertTrue(os.path.isdir(self.junction)) - # Junctions are not recognized as links. - self.assertFalse(os.path.islink(self.junction)) - + # Junctions are recognized as links. + self.assertTrue(os.path.islink(self.junction)) + + # os.readlink supports junctions. + real_junction_target = os.readlink(self.junction) + self.assertTrue(os.path.samefile(real_junction_target, self.junction_target)) + def test_unlink_removes_junction(self): _winapi.CreateJunction(self.junction_target, self.junction) self.assertTrue(os.path.exists(self.junction)) diff -r 5c48fbe12cb8 Modules/posixmodule.c --- a/Modules/posixmodule.c Sat Jan 14 21:04:40 2017 +0900 +++ b/Modules/posixmodule.c Sat Jan 14 09:49:43 2017 -0500 @@ -4187,8 +4187,7 @@ if(find_data_handle != INVALID_HANDLE_VALUE) { /* IO_REPARSE_TAG_SYMLINK if it is a symlink and IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ - is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || - find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; + is_link = IsReparseTagNameSurrogate(find_data.dwReserved0); FindClose(find_data_handle); } } @@ -7055,6 +7054,7 @@ 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; + USHORT print_name_length; static char *keywords[] = {"path", "dir_fd", NULL}; @@ -7099,17 +7099,27 @@ if (io_result==0) return win32_error_object("readlink", po); - if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) - { - PyErr_SetString(PyExc_ValueError, - "not a symbolic link"); - return NULL; - } - print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.PrintNameOffset; + if(rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK) + { + print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + + (rdb->SymbolicLinkReparseBuffer.PrintNameOffset / 2); + print_name_length = rdb->SymbolicLinkReparseBuffer.PrintNameLength / 2; + } + else if(rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) + { + print_name = rdb->MountPointReparseBuffer.PathBuffer + + (rdb->MountPointReparseBuffer.PrintNameOffset / 2); + print_name_length = rdb->MountPointReparseBuffer.PrintNameLength / 2; + } + else + { + PyErr_SetString(PyExc_ValueError, + "unsupported reparse tag"); + return NULL; + } result = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength/2); + print_name_length); return result; } diff -r 5c48fbe12cb8 Python/fileutils.c --- a/Python/fileutils.c Sat Jan 14 21:04:40 2017 +0900 +++ b/Python/fileutils.c Sat Jan 14 09:49:43 2017 -0500 @@ -584,7 +584,7 @@ FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec); result->st_nlink = info->nNumberOfLinks; result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow; - if (reparse_tag == IO_REPARSE_TAG_SYMLINK) { + if (IsReparseTagNameSurrogate(reparse_tag)) { /* first clear the S_IFMT bits */ result->st_mode ^= (result->st_mode & S_IFMT); /* now set the bits that make this a symlink */