| author | |
| committer | |
| log | 93b35c69998398e962bff84f3e5006afa122fbde |
| tree | b88a6096e8aa0f8602523eadd8d0b2d092458287 |
| parent | 6d74c0d1b41b52bca3d66092a48660f2ee4ae4f8 |
- Fixes the first few code units of the name being omitted (it was using `@sizeOf(FILE_NAME_INFO)` as the start of the name bytes, but that includes the length of the dummy [1]u16 field and padding; instead the start should be the offset of the dummy [1]u16 field)
- Replaces kernel32.GetFileInformationByHandleEx call with ntdll.NtQueryInformationFile
+ Contributes towards #1840
- Checks that the handle is a named pipe first before querying and checking the name, which is a much faster call than NtQueryInformationFile (this was about a 10x speedup in my probably-not-so-good/take-it-with-a-grain-of-salt benchmarking)3 files changed, 69 insertions(+), 11 deletions(-)
lib/std/os.zig+37-11| ... | @@ -3217,22 +3217,48 @@ pub fn isatty(handle: fd_t) bool { | ... | @@ -3217,22 +3217,48 @@ pub fn isatty(handle: fd_t) bool { |
| 3217 | pub fn isCygwinPty(handle: fd_t) bool { | 3217 | pub fn isCygwinPty(handle: fd_t) bool { |
| 3218 | if (builtin.os.tag != .windows) return false; | 3218 | if (builtin.os.tag != .windows) return false; |
| 3219 | 3219 | ||
| 3220 | const size = @sizeOf(windows.FILE_NAME_INFO); | 3220 | // If this is a MSYS2/cygwin pty, then it will be a named pipe with a name in one of these formats: |
| 3221 | var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (size + windows.MAX_PATH); | 3221 | // msys-[...]-ptyN-[...] |
| 3222 | // cygwin-[...]-ptyN-[...] | ||
| 3223 | // | ||
| 3224 | // Example: msys-1888ae32e00d56aa-pty0-to-master | ||
| 3225 | |||
| 3226 | // First, just check that the handle is a named pipe. | ||
| 3227 | // This allows us to avoid the more costly NtQueryInformationFile call | ||
| 3228 | // for handles that aren't named pipes. | ||
| 3229 | { | ||
| 3230 | var io_status: windows.IO_STATUS_BLOCK = undefined; | ||
| 3231 | var device_info: windows.FILE_FS_DEVICE_INFORMATION = undefined; | ||
| 3232 | const rc = windows.ntdll.NtQueryVolumeInformationFile(handle, &io_status, &device_info, @sizeOf(windows.FILE_FS_DEVICE_INFORMATION), .FileFsDeviceInformation); | ||
| 3233 | switch (rc) { | ||
| 3234 | .SUCCESS => {}, | ||
| 3235 | else => return false, | ||
| 3236 | } | ||
| 3237 | if (device_info.DeviceType != windows.FILE_DEVICE_NAMED_PIPE) return false; | ||
| 3238 | } | ||
| 3222 | 3239 | ||
| 3223 | if (windows.kernel32.GetFileInformationByHandleEx( | 3240 | const name_bytes_offset = @offsetOf(windows.FILE_NAME_INFO, "FileName"); |
| 3224 | handle, | 3241 | // `NAME_MAX` UTF-16 code units (2 bytes each) |
| 3225 | windows.FileNameInfo, | 3242 | // Note: This buffer may not be long enough to handle *all* possible paths (PATH_MAX_WIDE would be necessary for that), |
| 3226 | @ptrCast(*anyopaque, &name_info_bytes), | 3243 | // but because we only care about certain paths and we know they must be within a reasonable length, |
| 3227 | name_info_bytes.len, | 3244 | // we can use this smaller buffer and just return false on any error from NtQueryInformationFile. |
| 3228 | ) == 0) { | 3245 | const num_name_bytes = windows.MAX_PATH * 2; |
| 3229 | return false; | 3246 | var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (name_bytes_offset + num_name_bytes); |
| 3247 | |||
| 3248 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; | ||
| 3249 | const rc = windows.ntdll.NtQueryInformationFile(handle, &io_status_block, &name_info_bytes, @intCast(u32, name_info_bytes.len), .FileNameInformation); | ||
| 3250 | switch (rc) { | ||
| 3251 | .SUCCESS => {}, | ||
| 3252 | .INVALID_PARAMETER => unreachable, | ||
| 3253 | else => return false, | ||
| 3230 | } | 3254 | } |
| 3231 | 3255 | ||
| 3232 | const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]); | 3256 | const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]); |
| 3233 | const name_bytes = name_info_bytes[size .. size + @as(usize, name_info.FileNameLength)]; | 3257 | const name_bytes = name_info_bytes[name_bytes_offset .. name_bytes_offset + @as(usize, name_info.FileNameLength)]; |
| 3234 | const name_wide = mem.bytesAsSlice(u16, name_bytes); | 3258 | const name_wide = mem.bytesAsSlice(u16, name_bytes); |
| 3235 | return mem.indexOf(u16, name_wide, &[_]u16{ 'm', 's', 'y', 's', '-' }) != null or | 3259 | // Note: The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master |
| 3260 | return (mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or | ||
| 3261 | mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'c', 'y', 'g', 'w', 'i', 'n', '-' })) and | ||
| 3236 | mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; | 3262 | mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; |
| 3237 | } | 3263 | } |
| 3238 | 3264 |
lib/std/os/windows.zig+23| ... | @@ -2472,6 +2472,29 @@ pub const FILE_INFORMATION_CLASS = enum(c_int) { | ... | @@ -2472,6 +2472,29 @@ pub const FILE_INFORMATION_CLASS = enum(c_int) { |
| 2472 | FileMaximumInformation, | 2472 | FileMaximumInformation, |
| 2473 | }; | 2473 | }; |
| 2474 | 2474 | ||
| 2475 | pub const FILE_FS_DEVICE_INFORMATION = extern struct { | ||
| 2476 | DeviceType: DEVICE_TYPE, | ||
| 2477 | Characteristics: ULONG, | ||
| 2478 | }; | ||
| 2479 | |||
| 2480 | pub const FS_INFORMATION_CLASS = enum(c_int) { | ||
| 2481 | FileFsVolumeInformation = 1, | ||
| 2482 | FileFsLabelInformation, | ||
| 2483 | FileFsSizeInformation, | ||
| 2484 | FileFsDeviceInformation, | ||
| 2485 | FileFsAttributeInformation, | ||
| 2486 | FileFsControlInformation, | ||
| 2487 | FileFsFullSizeInformation, | ||
| 2488 | FileFsObjectIdInformation, | ||
| 2489 | FileFsDriverPathInformation, | ||
| 2490 | FileFsVolumeFlagsInformation, | ||
| 2491 | FileFsSectorSizeInformation, | ||
| 2492 | FileFsDataCopyInformation, | ||
| 2493 | FileFsMetadataSizeInformation, | ||
| 2494 | FileFsFullSizeInformationEx, | ||
| 2495 | FileFsMaximumInformation, | ||
| 2496 | }; | ||
| 2497 | |||
| 2475 | pub const OVERLAPPED = extern struct { | 2498 | pub const OVERLAPPED = extern struct { |
| 2476 | Internal: ULONG_PTR, | 2499 | Internal: ULONG_PTR, |
| 2477 | InternalHigh: ULONG_PTR, | 2500 | 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; |