diff options
author | Renaud Paquay <rpaquay@google.com> | 2018-10-01 14:59:48 -0700 |
---|---|---|
committer | Renaud Paquay <rpaquay@google.com> | 2018-10-03 09:41:09 -0700 |
commit | 2b42d288c08bdfd0fc3402fa118d91a1aebdb655 (patch) | |
tree | 47e8605380a0ea76c5da92cf461b798a8c59ab25 | |
parent | e469a0c741832f6584513f4a382d6b93f417b8d2 (diff) | |
download | git-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
-rw-r--r-- | platform_utils_win32.py | 22 |
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 |
42 | SYMBOLIC_LINK_FLAG_FILE = 0x00 | 42 | SYMBOLIC_LINK_FLAG_FILE = 0x00 |
43 | SYMBOLIC_LINK_FLAG_DIRECTORY = 0x01 | 43 | SYMBOLIC_LINK_FLAG_DIRECTORY = 0x01 |
44 | # symlink support for CreateSymbolicLink() starting with Windows 10 (1703, v10.0.14972) | ||
45 | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x02 | ||
44 | 46 | ||
45 | GetFileAttributesW = kernel32.GetFileAttributesW | 47 | GetFileAttributesW = kernel32.GetFileAttributesW |
46 | GetFileAttributesW.restype = DWORD | 48 | GetFileAttributesW.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 | ||
161 | def islink(path): | 169 | def islink(path): |