Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5311c1d

Browse files
committed
Issue #13772: In os.symlink() under Windows, do not try to guess the link
target's type (file or directory). The detection was buggy and made the call non-atomic (therefore prone to race conditions).
1 parent 3b65fd7 commit 5311c1d

4 files changed

Lines changed: 14 additions & 19 deletions

File tree

Doc/library/os.rst

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,11 +1429,9 @@ Files and Directories
14291429
*target_is_directory*, which defaults to ``False``.
14301430

14311431
On Windows, a symlink represents a file or a directory, and does not morph to
1432-
the target dynamically. For this reason, when creating a symlink on Windows,
1433-
if the target is not already present, the symlink will default to being a
1434-
file symlink. If *target_is_directory* is set to ``True``, the symlink will
1435-
be created as a directory symlink. This parameter is ignored if the target
1436-
exists (and the symlink is created with the same type as the target).
1432+
the target dynamically. If *target_is_directory* is set to ``True``, the
1433+
symlink will be created as a directory symlink, otherwise as a file symlink
1434+
(the default).
14371435

14381436
Symbolic link support was introduced in Windows 6.0 (Vista). :func:`symlink`
14391437
will raise a :exc:`NotImplementedError` on Windows versions earlier than 6.0.
@@ -1446,7 +1444,6 @@ Files and Directories
14461444
administrator level. Either obtaining the privilege or running your
14471445
application as an administrator are ways to successfully create symlinks.
14481446

1449-
14501447
:exc:`OSError` is raised when the function is called by an unprivileged
14511448
user.
14521449

Lib/test/test_os.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,12 @@ def test_traversal(self):
476476
f.write("I'm " + path + " and proud of it. Blame test_os.\n")
477477
f.close()
478478
if support.can_symlink():
479-
os.symlink(os.path.abspath(t2_path), link_path)
479+
if os.name == 'nt':
480+
def symlink_to_dir(src, dest):
481+
os.symlink(src, dest, True)
482+
else:
483+
symlink_to_dir = os.symlink
484+
symlink_to_dir(os.path.abspath(t2_path), link_path)
480485
sub2_tree = (sub2_path, ["link"], ["tmp3"])
481486
else:
482487
sub2_tree = (sub2_path, [], ["tmp3"])
@@ -1106,7 +1111,7 @@ def tearDown(self):
11061111
os.remove(self.missing_link)
11071112

11081113
def test_directory_link(self):
1109-
os.symlink(self.dirlink_target, self.dirlink)
1114+
os.symlink(self.dirlink_target, self.dirlink, True)
11101115
self.assertTrue(os.path.exists(self.dirlink))
11111116
self.assertTrue(os.path.isdir(self.dirlink))
11121117
self.assertTrue(os.path.islink(self.dirlink))

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ Core and Builtins
108108
Library
109109
-------
110110

111+
- Issue #13772: In os.symlink() under Windows, do not try to guess the link
112+
target's type (file or directory). The detection was buggy and made the
113+
call non-atomic (therefore prone to race conditions).
114+
111115
- Issue #6631: Disallow relative file paths in urllib urlopen methods.
112116

113117
- Issue #13722: Avoid silencing ImportErrors when initializing the codecs

Modules/posixmodule.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5330,7 +5330,6 @@ win_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
53305330
PyObject *src, *dest;
53315331
int target_is_directory = 0;
53325332
DWORD res;
5333-
WIN32_FILE_ATTRIBUTE_DATA src_info;
53345333

53355334
if (!check_CreateSymbolicLinkW())
53365335
{
@@ -5351,16 +5350,6 @@ win_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
53515350
return NULL;
53525351
}
53535352

5354-
/* if src is a directory, ensure target_is_directory==1 */
5355-
if(
5356-
GetFileAttributesExW(
5357-
PyUnicode_AsUnicode(src), GetFileExInfoStandard, &src_info
5358-
))
5359-
{
5360-
target_is_directory = target_is_directory ||
5361-
(src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5362-
}
5363-
53645353
Py_BEGIN_ALLOW_THREADS
53655354
res = Py_CreateSymbolicLinkW(
53665355
PyUnicode_AsUnicode(dest),

0 commit comments

Comments
 (0)