authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-03-21 15:03:33+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-03-21 15:03:33+02:00
log5e161c102d4a99be4903d0074ea2513ebcdb985b
tree667f03b3e98400194cfaaceeaa1064658cd14dfc
parent1e087d3a64e6b504524c32f72b22faffef78b41e
parent93b35c69998398e962bff84f3e5006afa122fbde
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14841 from squeek502/is-cygwin-pty-stuff

`os.isCygwinPty`: Fix a bug, replace kernel32 call, and optimize

4 files changed, 75 insertions(+), 11 deletions(-)

lib/std/fs/file.zig+6
......@@ -379,6 +379,9 @@ pub const File = struct {
379379 const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation);
380380 switch (rc) {
381381 .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.
382385 .BUFFER_OVERFLOW => {},
383386 .INVALID_PARAMETER => unreachable,
384387 .ACCESS_DENIED => return error.AccessDenied,
......@@ -830,6 +833,9 @@ pub const File = struct {
830833 const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation);
831834 switch (rc) {
832835 .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.
833839 .BUFFER_OVERFLOW => {},
834840 .INVALID_PARAMETER => unreachable,
835841 .ACCESS_DENIED => return error.AccessDenied,
lib/std/os.zig+37-11
......@@ -3239,22 +3239,48 @@ pub fn isatty(handle: fd_t) bool {
32393239pub fn isCygwinPty(handle: fd_t) bool {
32403240 if (builtin.os.tag != .windows) return false;
32413241
3242 const size = @sizeOf(windows.FILE_NAME_INFO);
3243 var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (size + windows.MAX_PATH);
3242 // If this is a MSYS2/cygwin pty, then it will be a named pipe with a name in one of these formats:
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 }
32443261
3245 if (windows.kernel32.GetFileInformationByHandleEx(
3246 handle,
3247 windows.FileNameInfo,
3248 @ptrCast(*anyopaque, &name_info_bytes),
3249 name_info_bytes.len,
3250 ) == 0) {
3251 return false;
3262 const name_bytes_offset = @offsetOf(windows.FILE_NAME_INFO, "FileName");
3263 // `NAME_MAX` UTF-16 code units (2 bytes each)
3264 // Note: This buffer may not be long enough to handle *all* possible paths (PATH_MAX_WIDE would be necessary for that),
3265 // but because we only care about certain paths and we know they must be within a reasonable length,
3266 // we can use this smaller buffer and just return false on any error from NtQueryInformationFile.
3267 const num_name_bytes = windows.MAX_PATH * 2;
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,
32523276 }
32533277
32543278 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)];
32563280 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
32583284 mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null;
32593285}
32603286
lib/std/os/windows.zig+23
......@@ -2452,6 +2452,29 @@ pub const FILE_INFORMATION_CLASS = enum(c_int) {
24522452 FileMaximumInformation,
24532453};
24542454
2455pub const FILE_FS_DEVICE_INFORMATION = extern struct {
2456 DeviceType: DEVICE_TYPE,
2457 Characteristics: ULONG,
2458};
2459
2460pub 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
24552478pub const OVERLAPPED = extern struct {
24562479 Internal: ULONG_PTR,
24572480 InternalHigh: ULONG_PTR,
lib/std/os/windows/ntdll.zig+9
......@@ -18,6 +18,7 @@ const IO_STATUS_BLOCK = windows.IO_STATUS_BLOCK;
1818const LARGE_INTEGER = windows.LARGE_INTEGER;
1919const OBJECT_INFORMATION_CLASS = windows.OBJECT_INFORMATION_CLASS;
2020const FILE_INFORMATION_CLASS = windows.FILE_INFORMATION_CLASS;
21const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS;
2122const UNICODE_STRING = windows.UNICODE_STRING;
2223const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW;
2324const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION;
......@@ -232,6 +233,14 @@ pub extern "ntdll" fn NtQueryObject(
232233 ReturnLength: ?*ULONG,
233234) callconv(WINAPI) NTSTATUS;
234235
236pub 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
235244pub extern "ntdll" fn RtlWakeAddressAll(
236245 Address: ?*const anyopaque,
237246) callconv(WINAPI) void;