summaryrefslogtreecommitdiffstats
path: root/platform_utils_win32.py
diff options
context:
space:
mode:
authorRenaud Paquay <rpaquay@google.com>2018-10-01 14:59:48 -0700
committerRenaud Paquay <rpaquay@google.com>2018-10-03 09:41:09 -0700
commit2b42d288c08bdfd0fc3402fa118d91a1aebdb655 (patch)
tree47e8605380a0ea76c5da92cf461b798a8c59ab25 /platform_utils_win32.py
parente469a0c741832f6584513f4a382d6b93f417b8d2 (diff)
downloadgit-repo-2b42d288c08bdfd0fc3402fa118d91a1aebdb655.tar.gz
Windows: Add support for creating symlinks as an unprivileged user
See https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/ for announcement of new flag. This change follow the same pattern as what was done in "go": https://github.com/golang/go/pull/24307/files#diff-b87bc12e4da2497308f9ef746086e4f0 Change-Id: If1e99fefdd3f787598e695731019c34b9bfcd1c2
Diffstat (limited to 'platform_utils_win32.py')
-rw-r--r--platform_utils_win32.py22
1 files changed, 15 insertions, 7 deletions
diff --git a/platform_utils_win32.py b/platform_utils_win32.py
index fe76b3d6..a6431216 100644
--- a/platform_utils_win32.py
+++ b/platform_utils_win32.py
@@ -41,6 +41,8 @@ CreateSymbolicLinkW.argtypes = (LPCWSTR, # lpSymlinkFileName In
41# Symbolic link creation flags 41# Symbolic link creation flags
42SYMBOLIC_LINK_FLAG_FILE = 0x00 42SYMBOLIC_LINK_FLAG_FILE = 0x00
43SYMBOLIC_LINK_FLAG_DIRECTORY = 0x01 43SYMBOLIC_LINK_FLAG_DIRECTORY = 0x01
44# symlink support for CreateSymbolicLink() starting with Windows 10 (1703, v10.0.14972)
45SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x02
44 46
45GetFileAttributesW = kernel32.GetFileAttributesW 47GetFileAttributesW = kernel32.GetFileAttributesW
46GetFileAttributesW.restype = DWORD 48GetFileAttributesW.restype = DWORD
@@ -147,15 +149,21 @@ def _create_symlink(source, link_name, dwFlags):
147 # On success, the function returns "1". 149 # On success, the function returns "1".
148 # On error, the function returns some random value (e.g. 1280). 150 # On error, the function returns some random value (e.g. 1280).
149 # The best bet seems to use "GetLastError" and check for error/success. 151 # The best bet seems to use "GetLastError" and check for error/success.
150 CreateSymbolicLinkW(link_name, source, dwFlags) 152 CreateSymbolicLinkW(link_name, source, dwFlags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
151 code = get_last_error() 153 code = get_last_error()
152 if code != ERROR_SUCCESS: 154 if code != ERROR_SUCCESS:
153 error_desc = FormatError(code).strip() 155 # See https://github.com/golang/go/pull/24307/files#diff-b87bc12e4da2497308f9ef746086e4f0
154 if code == ERROR_PRIVILEGE_NOT_HELD: 156 # "the unprivileged create flag is unsupported below Windows 10 (1703, v10.0.14972).
155 raise OSError(errno.EPERM, error_desc, link_name) 157 # retry without it."
156 _raise_winerror( 158 CreateSymbolicLinkW(link_name, source, dwFlags)
157 code, 159 code = get_last_error()
158 'Error creating symbolic link \"%s\"'.format(link_name)) 160 if code != ERROR_SUCCESS:
161 error_desc = FormatError(code).strip()
162 if code == ERROR_PRIVILEGE_NOT_HELD:
163 raise OSError(errno.EPERM, error_desc, link_name)
164 _raise_winerror(
165 code,
166 'Error creating symbolic link \"%s\"'.format(link_name))
159 167
160 168
161def islink(path): 169def islink(path):