diff options
| author | Gavin Mak <gavinmak@google.com> | 2023-03-11 06:46:20 +0000 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-22 17:46:28 +0000 |
| commit | ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1 (patch) | |
| tree | dc33ba0e56825b3e007d0589891756724725a465 /platform_utils_win32.py | |
| parent | 1604cf255f8c1786a23388db6d5277ac7949a24a (diff) | |
| download | git-repo-ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1.tar.gz | |
Format codebase with black and check formatting in CQ
Apply rules set by https://gerrit-review.googlesource.com/c/git-repo/+/362954/ across the codebase and fix any lingering errors caught
by flake8. Also check black formatting in run_tests (and CQ).
Bug: b/267675342
Change-Id: I972d77649dac351150dcfeb1cd1ad0ea2efc1956
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/363474
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Diffstat (limited to 'platform_utils_win32.py')
| -rw-r--r-- | platform_utils_win32.py | 245 |
1 files changed, 133 insertions, 112 deletions
diff --git a/platform_utils_win32.py b/platform_utils_win32.py index bf916d47..e9b15f46 100644 --- a/platform_utils_win32.py +++ b/platform_utils_win32.py | |||
| @@ -19,7 +19,7 @@ from ctypes import c_buffer, c_ubyte, Structure, Union, byref | |||
| 19 | from ctypes.wintypes import BOOL, BOOLEAN, LPCWSTR, DWORD, HANDLE | 19 | from ctypes.wintypes import BOOL, BOOLEAN, LPCWSTR, DWORD, HANDLE |
| 20 | from ctypes.wintypes import WCHAR, USHORT, LPVOID, ULONG, LPDWORD | 20 | from ctypes.wintypes import WCHAR, USHORT, LPVOID, ULONG, LPDWORD |
| 21 | 21 | ||
| 22 | kernel32 = WinDLL('kernel32', use_last_error=True) | 22 | kernel32 = WinDLL("kernel32", use_last_error=True) |
| 23 | 23 | ||
| 24 | UCHAR = c_ubyte | 24 | UCHAR = c_ubyte |
| 25 | 25 | ||
| @@ -31,14 +31,17 @@ ERROR_PRIVILEGE_NOT_HELD = 1314 | |||
| 31 | # Win32 API entry points | 31 | # Win32 API entry points |
| 32 | CreateSymbolicLinkW = kernel32.CreateSymbolicLinkW | 32 | CreateSymbolicLinkW = kernel32.CreateSymbolicLinkW |
| 33 | CreateSymbolicLinkW.restype = BOOLEAN | 33 | CreateSymbolicLinkW.restype = BOOLEAN |
| 34 | CreateSymbolicLinkW.argtypes = (LPCWSTR, # lpSymlinkFileName In | 34 | CreateSymbolicLinkW.argtypes = ( |
| 35 | LPCWSTR, # lpTargetFileName In | 35 | LPCWSTR, # lpSymlinkFileName In |
| 36 | DWORD) # dwFlags In | 36 | LPCWSTR, # lpTargetFileName In |
| 37 | DWORD, # dwFlags In | ||
| 38 | ) | ||
| 37 | 39 | ||
| 38 | # Symbolic link creation flags | 40 | # Symbolic link creation flags |
| 39 | SYMBOLIC_LINK_FLAG_FILE = 0x00 | 41 | SYMBOLIC_LINK_FLAG_FILE = 0x00 |
| 40 | SYMBOLIC_LINK_FLAG_DIRECTORY = 0x01 | 42 | SYMBOLIC_LINK_FLAG_DIRECTORY = 0x01 |
| 41 | # symlink support for CreateSymbolicLink() starting with Windows 10 (1703, v10.0.14972) | 43 | # symlink support for CreateSymbolicLink() starting with Windows 10 (1703, |
| 44 | # v10.0.14972) | ||
| 42 | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x02 | 45 | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x02 |
| 43 | 46 | ||
| 44 | GetFileAttributesW = kernel32.GetFileAttributesW | 47 | GetFileAttributesW = kernel32.GetFileAttributesW |
| @@ -50,13 +53,15 @@ FILE_ATTRIBUTE_REPARSE_POINT = 0x00400 | |||
| 50 | 53 | ||
| 51 | CreateFileW = kernel32.CreateFileW | 54 | CreateFileW = kernel32.CreateFileW |
| 52 | CreateFileW.restype = HANDLE | 55 | CreateFileW.restype = HANDLE |
| 53 | CreateFileW.argtypes = (LPCWSTR, # lpFileName In | 56 | CreateFileW.argtypes = ( |
| 54 | DWORD, # dwDesiredAccess In | 57 | LPCWSTR, # lpFileName In |
| 55 | DWORD, # dwShareMode In | 58 | DWORD, # dwDesiredAccess In |
| 56 | LPVOID, # lpSecurityAttributes In_opt | 59 | DWORD, # dwShareMode In |
| 57 | DWORD, # dwCreationDisposition In | 60 | LPVOID, # lpSecurityAttributes In_opt |
| 58 | DWORD, # dwFlagsAndAttributes In | 61 | DWORD, # dwCreationDisposition In |
| 59 | HANDLE) # hTemplateFile In_opt | 62 | DWORD, # dwFlagsAndAttributes In |
| 63 | HANDLE, # hTemplateFile In_opt | ||
| 64 | ) | ||
| 60 | 65 | ||
| 61 | CloseHandle = kernel32.CloseHandle | 66 | CloseHandle = kernel32.CloseHandle |
| 62 | CloseHandle.restype = BOOL | 67 | CloseHandle.restype = BOOL |
| @@ -69,14 +74,16 @@ FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 | |||
| 69 | 74 | ||
| 70 | DeviceIoControl = kernel32.DeviceIoControl | 75 | DeviceIoControl = kernel32.DeviceIoControl |
| 71 | DeviceIoControl.restype = BOOL | 76 | DeviceIoControl.restype = BOOL |
| 72 | DeviceIoControl.argtypes = (HANDLE, # hDevice In | 77 | DeviceIoControl.argtypes = ( |
| 73 | DWORD, # dwIoControlCode In | 78 | HANDLE, # hDevice In |
| 74 | LPVOID, # lpInBuffer In_opt | 79 | DWORD, # dwIoControlCode In |
| 75 | DWORD, # nInBufferSize In | 80 | LPVOID, # lpInBuffer In_opt |
| 76 | LPVOID, # lpOutBuffer Out_opt | 81 | DWORD, # nInBufferSize In |
| 77 | DWORD, # nOutBufferSize In | 82 | LPVOID, # lpOutBuffer Out_opt |
| 78 | LPDWORD, # lpBytesReturned Out_opt | 83 | DWORD, # nOutBufferSize In |
| 79 | LPVOID) # lpOverlapped Inout_opt | 84 | LPDWORD, # lpBytesReturned Out_opt |
| 85 | LPVOID, # lpOverlapped Inout_opt | ||
| 86 | ) | ||
| 80 | 87 | ||
| 81 | # Device I/O control flags and options | 88 | # Device I/O control flags and options |
| 82 | FSCTL_GET_REPARSE_POINT = 0x000900A8 | 89 | FSCTL_GET_REPARSE_POINT = 0x000900A8 |
| @@ -86,124 +93,138 @@ MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 0x4000 | |||
| 86 | 93 | ||
| 87 | 94 | ||
| 88 | class GENERIC_REPARSE_BUFFER(Structure): | 95 | class GENERIC_REPARSE_BUFFER(Structure): |
| 89 | _fields_ = (('DataBuffer', UCHAR * 1),) | 96 | _fields_ = (("DataBuffer", UCHAR * 1),) |
| 90 | 97 | ||
| 91 | 98 | ||
| 92 | class SYMBOLIC_LINK_REPARSE_BUFFER(Structure): | 99 | class SYMBOLIC_LINK_REPARSE_BUFFER(Structure): |
| 93 | _fields_ = (('SubstituteNameOffset', USHORT), | 100 | _fields_ = ( |
| 94 | ('SubstituteNameLength', USHORT), | 101 | ("SubstituteNameOffset", USHORT), |
| 95 | ('PrintNameOffset', USHORT), | 102 | ("SubstituteNameLength", USHORT), |
| 96 | ('PrintNameLength', USHORT), | 103 | ("PrintNameOffset", USHORT), |
| 97 | ('Flags', ULONG), | 104 | ("PrintNameLength", USHORT), |
| 98 | ('PathBuffer', WCHAR * 1)) | 105 | ("Flags", ULONG), |
| 99 | 106 | ("PathBuffer", WCHAR * 1), | |
| 100 | @property | 107 | ) |
| 101 | def PrintName(self): | 108 | |
| 102 | arrayt = WCHAR * (self.PrintNameLength // 2) | 109 | @property |
| 103 | offset = type(self).PathBuffer.offset + self.PrintNameOffset | 110 | def PrintName(self): |
| 104 | return arrayt.from_address(addressof(self) + offset).value | 111 | arrayt = WCHAR * (self.PrintNameLength // 2) |
| 112 | offset = type(self).PathBuffer.offset + self.PrintNameOffset | ||
| 113 | return arrayt.from_address(addressof(self) + offset).value | ||
| 105 | 114 | ||
| 106 | 115 | ||
| 107 | class MOUNT_POINT_REPARSE_BUFFER(Structure): | 116 | class MOUNT_POINT_REPARSE_BUFFER(Structure): |
| 108 | _fields_ = (('SubstituteNameOffset', USHORT), | 117 | _fields_ = ( |
| 109 | ('SubstituteNameLength', USHORT), | 118 | ("SubstituteNameOffset", USHORT), |
| 110 | ('PrintNameOffset', USHORT), | 119 | ("SubstituteNameLength", USHORT), |
| 111 | ('PrintNameLength', USHORT), | 120 | ("PrintNameOffset", USHORT), |
| 112 | ('PathBuffer', WCHAR * 1)) | 121 | ("PrintNameLength", USHORT), |
| 122 | ("PathBuffer", WCHAR * 1), | ||
| 123 | ) | ||
| 113 | 124 | ||
| 114 | @property | 125 | @property |
| 115 | def PrintName(self): | 126 | def PrintName(self): |
| 116 | arrayt = WCHAR * (self.PrintNameLength // 2) | 127 | arrayt = WCHAR * (self.PrintNameLength // 2) |
| 117 | offset = type(self).PathBuffer.offset + self.PrintNameOffset | 128 | offset = type(self).PathBuffer.offset + self.PrintNameOffset |
| 118 | return arrayt.from_address(addressof(self) + offset).value | 129 | return arrayt.from_address(addressof(self) + offset).value |
| 119 | 130 | ||
| 120 | 131 | ||
| 121 | class REPARSE_DATA_BUFFER(Structure): | 132 | class REPARSE_DATA_BUFFER(Structure): |
| 122 | class REPARSE_BUFFER(Union): | 133 | class REPARSE_BUFFER(Union): |
| 123 | _fields_ = (('SymbolicLinkReparseBuffer', SYMBOLIC_LINK_REPARSE_BUFFER), | 134 | _fields_ = ( |
| 124 | ('MountPointReparseBuffer', MOUNT_POINT_REPARSE_BUFFER), | 135 | ("SymbolicLinkReparseBuffer", SYMBOLIC_LINK_REPARSE_BUFFER), |
| 125 | ('GenericReparseBuffer', GENERIC_REPARSE_BUFFER)) | 136 | ("MountPointReparseBuffer", MOUNT_POINT_REPARSE_BUFFER), |
| 126 | _fields_ = (('ReparseTag', ULONG), | 137 | ("GenericReparseBuffer", GENERIC_REPARSE_BUFFER), |
| 127 | ('ReparseDataLength', USHORT), | 138 | ) |
| 128 | ('Reserved', USHORT), | 139 | |
| 129 | ('ReparseBuffer', REPARSE_BUFFER)) | 140 | _fields_ = ( |
| 130 | _anonymous_ = ('ReparseBuffer',) | 141 | ("ReparseTag", ULONG), |
| 142 | ("ReparseDataLength", USHORT), | ||
| 143 | ("Reserved", USHORT), | ||
| 144 | ("ReparseBuffer", REPARSE_BUFFER), | ||
| 145 | ) | ||
| 146 | _anonymous_ = ("ReparseBuffer",) | ||
| 131 | 147 | ||
| 132 | 148 | ||
| 133 | def create_filesymlink(source, link_name): | 149 | def create_filesymlink(source, link_name): |
| 134 | """Creates a Windows file symbolic link source pointing to link_name.""" | 150 | """Creates a Windows file symbolic link source pointing to link_name.""" |
| 135 | _create_symlink(source, link_name, SYMBOLIC_LINK_FLAG_FILE) | 151 | _create_symlink(source, link_name, SYMBOLIC_LINK_FLAG_FILE) |
| 136 | 152 | ||
| 137 | 153 | ||
| 138 | def create_dirsymlink(source, link_name): | 154 | def create_dirsymlink(source, link_name): |
| 139 | """Creates a Windows directory symbolic link source pointing to link_name. | 155 | """Creates a Windows directory symbolic link source pointing to link_name.""" # noqa: E501 |
| 140 | """ | 156 | _create_symlink(source, link_name, SYMBOLIC_LINK_FLAG_DIRECTORY) |
| 141 | _create_symlink(source, link_name, SYMBOLIC_LINK_FLAG_DIRECTORY) | ||
| 142 | 157 | ||
| 143 | 158 | ||
| 144 | def _create_symlink(source, link_name, dwFlags): | 159 | def _create_symlink(source, link_name, dwFlags): |
| 145 | if not CreateSymbolicLinkW(link_name, source, | 160 | if not CreateSymbolicLinkW( |
| 146 | dwFlags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE): | 161 | link_name, |
| 147 | # See https://github.com/golang/go/pull/24307/files#diff-b87bc12e4da2497308f9ef746086e4f0 | 162 | source, |
| 148 | # "the unprivileged create flag is unsupported below Windows 10 (1703, v10.0.14972). | 163 | dwFlags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE, |
| 149 | # retry without it." | 164 | ): |
| 150 | if not CreateSymbolicLinkW(link_name, source, dwFlags): | 165 | # See https://github.com/golang/go/pull/24307/files#diff-b87bc12e4da2497308f9ef746086e4f0 # noqa: E501 |
| 151 | code = get_last_error() | 166 | # "the unprivileged create flag is unsupported below Windows 10 (1703, |
| 152 | error_desc = FormatError(code).strip() | 167 | # v10.0.14972). retry without it." |
| 153 | if code == ERROR_PRIVILEGE_NOT_HELD: | 168 | if not CreateSymbolicLinkW(link_name, source, dwFlags): |
| 154 | raise OSError(errno.EPERM, error_desc, link_name) | 169 | code = get_last_error() |
| 155 | _raise_winerror( | 170 | error_desc = FormatError(code).strip() |
| 156 | code, | 171 | if code == ERROR_PRIVILEGE_NOT_HELD: |
| 157 | 'Error creating symbolic link \"%s\"'.format(link_name)) | 172 | raise OSError(errno.EPERM, error_desc, link_name) |
| 173 | _raise_winerror( | ||
| 174 | code, 'Error creating symbolic link "{}"'.format(link_name) | ||
| 175 | ) | ||
| 158 | 176 | ||
| 159 | 177 | ||
| 160 | def islink(path): | 178 | def islink(path): |
| 161 | result = GetFileAttributesW(path) | 179 | result = GetFileAttributesW(path) |
| 162 | if result == INVALID_FILE_ATTRIBUTES: | 180 | if result == INVALID_FILE_ATTRIBUTES: |
| 163 | return False | 181 | return False |
| 164 | return bool(result & FILE_ATTRIBUTE_REPARSE_POINT) | 182 | return bool(result & FILE_ATTRIBUTE_REPARSE_POINT) |
| 165 | 183 | ||
| 166 | 184 | ||
| 167 | def readlink(path): | 185 | def readlink(path): |
| 168 | reparse_point_handle = CreateFileW(path, | 186 | reparse_point_handle = CreateFileW( |
| 169 | 0, | 187 | path, |
| 170 | 0, | 188 | 0, |
| 171 | None, | 189 | 0, |
| 172 | OPEN_EXISTING, | 190 | None, |
| 173 | FILE_FLAG_OPEN_REPARSE_POINT | | 191 | OPEN_EXISTING, |
| 174 | FILE_FLAG_BACKUP_SEMANTICS, | 192 | FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, |
| 175 | None) | 193 | None, |
| 176 | if reparse_point_handle == INVALID_HANDLE_VALUE: | 194 | ) |
| 177 | _raise_winerror( | 195 | if reparse_point_handle == INVALID_HANDLE_VALUE: |
| 178 | get_last_error(), | 196 | _raise_winerror( |
| 179 | 'Error opening symbolic link \"%s\"'.format(path)) | 197 | get_last_error(), 'Error opening symbolic link "{}"'.format(path) |
| 180 | target_buffer = c_buffer(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) | 198 | ) |
| 181 | n_bytes_returned = DWORD() | 199 | target_buffer = c_buffer(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) |
| 182 | io_result = DeviceIoControl(reparse_point_handle, | 200 | n_bytes_returned = DWORD() |
| 183 | FSCTL_GET_REPARSE_POINT, | 201 | io_result = DeviceIoControl( |
| 184 | None, | 202 | reparse_point_handle, |
| 185 | 0, | 203 | FSCTL_GET_REPARSE_POINT, |
| 186 | target_buffer, | 204 | None, |
| 187 | len(target_buffer), | 205 | 0, |
| 188 | byref(n_bytes_returned), | 206 | target_buffer, |
| 189 | None) | 207 | len(target_buffer), |
| 190 | CloseHandle(reparse_point_handle) | 208 | byref(n_bytes_returned), |
| 191 | if not io_result: | 209 | None, |
| 210 | ) | ||
| 211 | CloseHandle(reparse_point_handle) | ||
| 212 | if not io_result: | ||
| 213 | _raise_winerror( | ||
| 214 | get_last_error(), 'Error reading symbolic link "{}"'.format(path) | ||
| 215 | ) | ||
| 216 | rdb = REPARSE_DATA_BUFFER.from_buffer(target_buffer) | ||
| 217 | if rdb.ReparseTag == IO_REPARSE_TAG_SYMLINK: | ||
| 218 | return rdb.SymbolicLinkReparseBuffer.PrintName | ||
| 219 | elif rdb.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT: | ||
| 220 | return rdb.MountPointReparseBuffer.PrintName | ||
| 221 | # Unsupported reparse point type. | ||
| 192 | _raise_winerror( | 222 | _raise_winerror( |
| 193 | get_last_error(), | 223 | ERROR_NOT_SUPPORTED, 'Error reading symbolic link "{}"'.format(path) |
| 194 | 'Error reading symbolic link \"%s\"'.format(path)) | 224 | ) |
| 195 | rdb = REPARSE_DATA_BUFFER.from_buffer(target_buffer) | ||
| 196 | if rdb.ReparseTag == IO_REPARSE_TAG_SYMLINK: | ||
| 197 | return rdb.SymbolicLinkReparseBuffer.PrintName | ||
| 198 | elif rdb.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT: | ||
| 199 | return rdb.MountPointReparseBuffer.PrintName | ||
| 200 | # Unsupported reparse point type | ||
| 201 | _raise_winerror( | ||
| 202 | ERROR_NOT_SUPPORTED, | ||
| 203 | 'Error reading symbolic link \"%s\"'.format(path)) | ||
| 204 | 225 | ||
| 205 | 226 | ||
| 206 | def _raise_winerror(code, error_desc): | 227 | def _raise_winerror(code, error_desc): |
| 207 | win_error_desc = FormatError(code).strip() | 228 | win_error_desc = FormatError(code).strip() |
| 208 | error_desc = "%s: %s".format(error_desc, win_error_desc) | 229 | error_desc = "{0}: {1}".format(error_desc, win_error_desc) |
| 209 | raise WinError(code, error_desc) | 230 | raise WinError(code, error_desc) |
