summaryrefslogtreecommitdiffstats
path: root/Python/fileutils.c
diff options
context:
space:
mode:
authorSteve Dower <steve.dower@python.org>2019-08-21 22:27:33 (GMT)
committerGitHub <noreply@github.com>2019-08-21 22:27:33 (GMT)
commitdf2d4a6f3d5da2839c4fc11d31511c8e028daf2c (patch)
treee60154de9e835976aed87ab51ac3d5d9fda7f45f /Python/fileutils.c
parentbcc446f525421156fe693139140e7051d000592e (diff)
downloadcpython-df2d4a6f3d5da2839c4fc11d31511c8e028daf2c.zip
cpython-df2d4a6f3d5da2839c4fc11d31511c8e028daf2c.tar.gz
cpython-df2d4a6f3d5da2839c4fc11d31511c8e028daf2c.tar.bz2
bpo-37834: Normalise handling of reparse points on Windows (GH-15231)
bpo-37834: Normalise handling of reparse points on Windows * ntpath.realpath() and nt.stat() will traverse all supported reparse points (previously was mixed) * nt.lstat() will let the OS traverse reparse points that are not name surrogates (previously would not traverse any reparse point) * nt.[l]stat() will only set S_IFLNK for symlinks (previous behaviour) * nt.readlink() will read destinations for symlinks and junction points only bpo-1311: os.path.exists('nul') now returns True on Windows * nt.stat('nul').st_mode is now S_IFCHR (previously was an error)
Diffstat (limited to 'Python/fileutils.c')
-rw-r--r--Python/fileutils.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 55bc194..36a3c99 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -878,7 +878,12 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
result->st_nlink = info->nNumberOfLinks;
result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;
- if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
+ /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will
+ open other name surrogate reparse points without traversing them. To
+ detect/handle these, check st_file_attributes and st_reparse_tag. */
+ result->st_reparse_tag = reparse_tag;
+ if (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
+ reparse_tag == IO_REPARSE_TAG_SYMLINK) {
/* first clear the S_IFMT bits */
result->st_mode ^= (result->st_mode & S_IFMT);
/* now set the bits that make this a symlink */