| author | |
| committer | |
| log | 5e161c102d4a99be4903d0074ea2513ebcdb985b |
| tree | 667f03b3e98400194cfaaceeaa1064658cd14dfc |
| parent | 1e087d3a64e6b504524c32f72b22faffef78b41e |
| parent | 93b35c69998398e962bff84f3e5006afa122fbde |
| signature |
`os.isCygwinPty`: Fix a bug, replace kernel32 call, and optimize4 files changed, 75 insertions(+), 11 deletions(-)
lib/std/fs/file.zig+6| ... | @@ -379,6 +379,9 @@ pub const File = struct { | ... | @@ -379,6 +379,9 @@ pub const File = struct { |
| 379 | const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation); | 379 | const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation); |
| 380 | switch (rc) { | 380 | switch (rc) { |
| 381 | .SUCCESS => {}, | 381 | .SUCCESS => {}, |
| 382 | // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer | ||
| 383 | // size provided. This is treated as success because the type of variable-length information that this would be relevant for | ||
| 384 | // (name, volume name, etc) we don't care about. | ||
| 382 | .BUFFER_OVERFLOW => {}, | 385 | .BUFFER_OVERFLOW => {}, |
| 383 | .INVALID_PARAMETER => unreachable, | 386 | .INVALID_PARAMETER => unreachable, |
| 384 | .ACCESS_DENIED => return error.AccessDenied, | 387 | .ACCESS_DENIED => return error.AccessDenied, |
| ... | @@ -830,6 +833,9 @@ pub const File = struct { | ... | @@ -830,6 +833,9 @@ pub const File = struct { |
| 830 | const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation); | 833 | const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation); |
| 831 | switch (rc) { | 834 | switch (rc) { |
| 832 | .SUCCESS => {}, | 835 | .SUCCESS => {}, |
| 836 | // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer | ||
| 837 | // size provided. This is treated as success because the type of variable-length information that this would be relevant for | ||
| 838 | // (name, volume name, etc) we don't care about. | ||
| 833 | .BUFFER_OVERFLOW => {}, | 839 | .BUFFER_OVERFLOW => {}, |
| 834 | .INVALID_PARAMETER => unreachable, | 840 | .INVALID_PARAMETER => unreachable, |
| 835 | .ACCESS_DENIED => return error.AccessDenied, | 841 | .ACCESS_DENIED => return error.AccessDenied, |
lib/std/os.zig+37-11| ... | @@ -3239,22 +3239,48 @@ pub fn isatty(handle: fd_t) bool { | ... | @@ -3239,22 +3239,48 @@ pub fn isatty(handle: fd_t) bool { |
| 3239 | pub fn isCygwinPty(handle: fd_t) bool { | 3239 | pub fn isCygwinPty(handle: fd_t) bool { |
| 3240 | if (builtin.os.tag != .windows) return false; | 3240 | if (builtin.os.tag != .windows) return false; |
| 3241 | 3241 | ||
| 3242 | const size = @sizeOf(windows.FILE_NAME_INFO); | 3242 | // If this is a MSYS2/cygwin pty, then it will be a named pipe with a name in one of these formats: |
| 3243 | var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (size + windows.MAX_PATH); | 3243 | // msys-[...]-ptyN-[...] |
| 3244 | // cygwin-[...]-ptyN-[...] | ||
| 3245 | // | ||
| 3246 | // Example: msys-1888ae32e00d56aa-pty0-to-master | ||
| 3247 | |||
| 3248 | // First, just check that the handle is a named pipe. | ||
| 3249 | // This allows us to avoid the more costly NtQueryInformationFile call | ||
| 3250 | // for handles that aren't named pipes. | ||
| 3251 | { | ||
| 3252 | var io_status: windows.IO_STATUS_BLOCK = undefined; | ||
| 3253 | var device_info: windows.FILE_FS_DEVICE_INFORMATION = undefined; | ||
| 3254 | const rc = windows.ntdll.NtQueryVolumeInformationFile(handle, &io_status, &device_info, @sizeOf(windows.FILE_FS_DEVICE_INFORMATION), .FileFsDeviceInformation); | ||
| 3255 | switch (rc) { | ||
| 3256 | .SUCCESS => {}, | ||
| 3257 | else => return false, | ||
| 3258 | } | ||
| 3259 | if (device_info.DeviceType != windows.FILE_DEVICE_NAMED_PIPE) return false; | ||
| 3260 | } | ||
| 3244 | 3261 | ||
| 3245 | if (windows.kernel32.GetFileInformationByHandleEx( | 3262 | const name_bytes_offset = @offsetOf(windows.FILE_NAME_INFO, "FileName"); |
| 3246 | handle, | 3263 | // `NAME_MAX` UTF-16 code units (2 bytes each) |
| 3247 | windows.FileNameInfo, | 3264 | // Note: This buffer may not be long enough to handle *all* possible paths (PATH_MAX_WIDE would be necessary for that), |
| 3248 | @ptrCast(*anyopaque, &name_info_bytes), | 3265 | // but because we only care about certain paths and we know they must be within a reasonable length, |
| 3249 | name_info_bytes.len, | 3266 | // we can use this smaller buffer and just return false on any error from NtQueryInformationFile. |
| 3250 | ) == 0) { | 3267 | const num_name_bytes = windows.MAX_PATH * 2; |
| 3251 | return false; | 3268 | var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (name_bytes_offset + num_name_bytes); |
| 3269 | |||
| 3270 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; | ||
| 3271 | const rc = windows.ntdll.NtQueryInformationFile(handle, &io_status_block, &name_info_bytes, @intCast(u32, name_info_bytes.len), .FileNameInformation); | ||
| 3272 | switch (rc) { | ||
| 3273 | .SUCCESS => {}, | ||
| 3274 | .INVALID_PARAMETER => unreachable, | ||
| 3275 | else => return false, | ||
| 3252 | } | 3276 | } |
| 3253 | 3277 | ||
| 3254 | const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]); | 3278 | const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]); |
| 3255 | const name_bytes = name_info_bytes[size .. size + @as(usize, name_info.FileNameLength)]; | 3279 | const name_bytes = name_info_bytes[name_bytes_offset .. name_bytes_offset + @as(usize, name_info.FileNameLength)]; |
| 3256 | const name_wide = mem.bytesAsSlice(u16, name_bytes); | 3280 | const name_wide = mem.bytesAsSlice(u16, name_bytes); |
| 3257 | return mem.indexOf(u16, name_wide, &[_]u16{ 'm', 's', 'y', 's', '-' }) != null or | 3281 | // Note: The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master |
| 3282 | return (mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or | ||
| 3283 | mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'c', 'y', 'g', 'w', 'i', 'n', '-' })) and | ||
| 3258 | mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; | 3284 | mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; |
| 3259 | } | 3285 | } |
| 3260 | 3286 |
lib/std/os/windows.zig+23| ... | @@ -2452,6 +2452,29 @@ pub const FILE_INFORMATION_CLASS = enum(c_int) { | ... | @@ -2452,6 +2452,29 @@ pub const FILE_INFORMATION_CLASS = enum(c_int) { |
| 2452 | FileMaximumInformation, | 2452 | FileMaximumInformation, |
| 2453 | }; | 2453 | }; |
| 2454 | 2454 | ||
| 2455 | pub const FILE_FS_DEVICE_INFORMATION = extern struct { | ||
| 2456 | DeviceType: DEVICE_TYPE, | ||
| 2457 | Characteristics: ULONG, | ||
| 2458 | }; | ||
| 2459 | |||
| 2460 | pub const FS_INFORMATION_CLASS = enum(c_int) { | ||
| 2461 | FileFsVolumeInformation = 1, | ||
| 2462 | FileFsLabelInformation, | ||
| 2463 | FileFsSizeInformation, | ||
| 2464 | FileFsDeviceInformation, | ||
| 2465 | FileFsAttributeInformation, | ||
| 2466 | FileFsControlInformation, | ||
| 2467 | FileFsFullSizeInformation, | ||
| 2468 | FileFsObjectIdInformation, | ||
| 2469 | FileFsDriverPathInformation, | ||
| 2470 | FileFsVolumeFlagsInformation, | ||
| 2471 | FileFsSectorSizeInformation, | ||
| 2472 | FileFsDataCopyInformation, | ||
| 2473 | FileFsMetadataSizeInformation, | ||
| 2474 | FileFsFullSizeInformationEx, | ||
| 2475 | FileFsMaximumInformation, | ||
| 2476 | }; | ||
| 2477 | |||
| 2455 | pub const OVERLAPPED = extern struct { | 2478 | pub const OVERLAPPED = extern struct { |
| 2456 | Internal: ULONG_PTR, | 2479 | Internal: ULONG_PTR, |
| 2457 | InternalHigh: ULONG_PTR, | 2480 | InternalHigh: ULONG_PTR, |
lib/std/os/windows/ntdll.zig+9| ... | @@ -18,6 +18,7 @@ const IO_STATUS_BLOCK = windows.IO_STATUS_BLOCK; | ... | @@ -18,6 +18,7 @@ const IO_STATUS_BLOCK = windows.IO_STATUS_BLOCK; |
| 18 | const LARGE_INTEGER = windows.LARGE_INTEGER; | 18 | const LARGE_INTEGER = windows.LARGE_INTEGER; |
| 19 | const OBJECT_INFORMATION_CLASS = windows.OBJECT_INFORMATION_CLASS; | 19 | const OBJECT_INFORMATION_CLASS = windows.OBJECT_INFORMATION_CLASS; |
| 20 | const FILE_INFORMATION_CLASS = windows.FILE_INFORMATION_CLASS; | 20 | const FILE_INFORMATION_CLASS = windows.FILE_INFORMATION_CLASS; |
| 21 | const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS; | ||
| 21 | const UNICODE_STRING = windows.UNICODE_STRING; | 22 | const UNICODE_STRING = windows.UNICODE_STRING; |
| 22 | const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; | 23 | const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; |
| 23 | const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION; | 24 | const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION; |
| ... | @@ -232,6 +233,14 @@ pub extern "ntdll" fn NtQueryObject( | ... | @@ -232,6 +233,14 @@ pub extern "ntdll" fn NtQueryObject( |
| 232 | ReturnLength: ?*ULONG, | 233 | ReturnLength: ?*ULONG, |
| 233 | ) callconv(WINAPI) NTSTATUS; | 234 | ) callconv(WINAPI) NTSTATUS; |
| 234 | 235 | ||
| 236 | pub extern "ntdll" fn NtQueryVolumeInformationFile( | ||
| 237 | FileHandle: HANDLE, | ||
| 238 | IoStatusBlock: *IO_STATUS_BLOCK, | ||
| 239 | FsInformation: *anyopaque, | ||
| 240 | Length: ULONG, | ||
| 241 | FsInformationClass: FS_INFORMATION_CLASS, | ||
| 242 | ) callconv(WINAPI) NTSTATUS; | ||
| 243 | |||
| 235 | pub extern "ntdll" fn RtlWakeAddressAll( | 244 | pub extern "ntdll" fn RtlWakeAddressAll( |
| 236 | Address: ?*const anyopaque, | 245 | Address: ?*const anyopaque, |
| 237 | ) callconv(WINAPI) void; | 246 | ) callconv(WINAPI) void; |