diff options
author | David Pursehouse <dpursehouse@collab.net> | 2017-08-30 10:24:03 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-08-30 10:24:03 +0000 |
commit | d1ebc89a083f2966f8c65246bb63e2deaadfab62 (patch) | |
tree | cd6bd047ba2c7b83a25ba045a48efa95393f7fbe /platform_utils_win32.py | |
parent | 9ead97bb51f5b1ad1d0a45e0c5442f15e1e38fd7 (diff) | |
parent | ad1abcb556bfff2744928a8f29d216aee43fdbe3 (diff) | |
download | git-repo-d1ebc89a083f2966f8c65246bb63e2deaadfab62.tar.gz |
Merge changes from topic "windows-support"
* changes:
Port os.rename calls to work on Windows
Workaround shutil.rmtree limitation on Windows
Add support for creating symbolic links on Windows
Make "git command" and "forall" work on Windows
Diffstat (limited to 'platform_utils_win32.py')
-rw-r--r-- | platform_utils_win32.py | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/platform_utils_win32.py b/platform_utils_win32.py new file mode 100644 index 00000000..02fb013a --- /dev/null +++ b/platform_utils_win32.py | |||
@@ -0,0 +1,63 @@ | |||
1 | # | ||
2 | # Copyright (C) 2016 The Android Open Source Project | ||
3 | # | ||
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | # you may not use this file except in compliance with the License. | ||
6 | # You may obtain a copy of the License at | ||
7 | # | ||
8 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | # | ||
10 | # Unless required by applicable law or agreed to in writing, software | ||
11 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | # See the License for the specific language governing permissions and | ||
14 | # limitations under the License. | ||
15 | |||
16 | import errno | ||
17 | |||
18 | from ctypes import WinDLL, get_last_error, FormatError, WinError | ||
19 | from ctypes.wintypes import BOOL, LPCWSTR, DWORD | ||
20 | |||
21 | kernel32 = WinDLL('kernel32', use_last_error=True) | ||
22 | |||
23 | # Win32 error codes | ||
24 | ERROR_SUCCESS = 0 | ||
25 | ERROR_PRIVILEGE_NOT_HELD = 1314 | ||
26 | |||
27 | # Win32 API entry points | ||
28 | CreateSymbolicLinkW = kernel32.CreateSymbolicLinkW | ||
29 | CreateSymbolicLinkW.restype = BOOL | ||
30 | CreateSymbolicLinkW.argtypes = (LPCWSTR, # lpSymlinkFileName In | ||
31 | LPCWSTR, # lpTargetFileName In | ||
32 | DWORD) # dwFlags In | ||
33 | |||
34 | # Symbolic link creation flags | ||
35 | SYMBOLIC_LINK_FLAG_FILE = 0x00 | ||
36 | SYMBOLIC_LINK_FLAG_DIRECTORY = 0x01 | ||
37 | |||
38 | |||
39 | def create_filesymlink(source, link_name): | ||
40 | """Creates a Windows file symbolic link source pointing to link_name.""" | ||
41 | _create_symlink(source, link_name, SYMBOLIC_LINK_FLAG_FILE) | ||
42 | |||
43 | |||
44 | def create_dirsymlink(source, link_name): | ||
45 | """Creates a Windows directory symbolic link source pointing to link_name. | ||
46 | """ | ||
47 | _create_symlink(source, link_name, SYMBOLIC_LINK_FLAG_DIRECTORY) | ||
48 | |||
49 | |||
50 | def _create_symlink(source, link_name, dwFlags): | ||
51 | # Note: Win32 documentation for CreateSymbolicLink is incorrect. | ||
52 | # On success, the function returns "1". | ||
53 | # On error, the function returns some random value (e.g. 1280). | ||
54 | # The best bet seems to use "GetLastError" and check for error/success. | ||
55 | CreateSymbolicLinkW(link_name, source, dwFlags) | ||
56 | code = get_last_error() | ||
57 | if code != ERROR_SUCCESS: | ||
58 | error_desc = FormatError(code).strip() | ||
59 | if code == ERROR_PRIVILEGE_NOT_HELD: | ||
60 | raise OSError(errno.EPERM, error_desc, link_name) | ||
61 | error_desc = 'Error creating symbolic link %s: %s'.format( | ||
62 | link_name, error_desc) | ||
63 | raise WinError(code, error_desc) | ||