| ... | @@ -4088,6 +4088,30 @@ fn fileStatLinux(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { | ... | @@ -4088,6 +4088,30 @@ fn fileStatLinux(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { |
| 4088 | } | 4088 | } |
| 4089 | } | 4089 | } |
| 4090 | | 4090 | |
| | 4091 | fn windowsGetFileDevice(file: File) error{ Canceled, AccessDenied, Unexpected }!windows.CTL_CODE.FILE_DEVICE { |
| | 4092 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| | 4093 | var device_info: windows.FILE.FS_DEVICE_INFORMATION = undefined; |
| | 4094 | { |
| | 4095 | const syscall: Syscall = try .start(); |
| | 4096 | while (true) switch (windows.ntdll.NtQueryVolumeInformationFile( |
| | 4097 | file.handle, |
| | 4098 | &io_status_block, |
| | 4099 | &device_info, |
| | 4100 | @sizeOf(windows.FILE.FS_DEVICE_INFORMATION), |
| | 4101 | .Device, |
| | 4102 | )) { |
| | 4103 | .SUCCESS => break syscall.finish(), |
| | 4104 | .CANCELLED => { |
| | 4105 | try syscall.checkCancel(); |
| | 4106 | continue; |
| | 4107 | }, |
| | 4108 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| | 4109 | else => |s| return syscall.unexpectedNtstatus(s), |
| | 4110 | }; |
| | 4111 | } |
| | 4112 | return device_info.DeviceType.FileDevice; |
| | 4113 | } |
| | 4114 | |
| 4091 | fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { | 4115 | fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { |
| 4092 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 4116 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 4093 | | 4117 | |
| ... | @@ -4112,7 +4136,31 @@ fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { | ... | @@ -4112,7 +4136,31 @@ fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { |
| 4112 | // size provided. This is treated as success because the type of variable-length information that this would be relevant for | 4136 | // size provided. This is treated as success because the type of variable-length information that this would be relevant for |
| 4113 | // (name, volume name, etc) we don't care about. | 4137 | // (name, volume name, etc) we don't care about. |
| 4114 | .BUFFER_OVERFLOW => break syscall.finish(), | 4138 | .BUFFER_OVERFLOW => break syscall.finish(), |
| 4115 | .INVALID_PARAMETER => |err| return syscall.ntstatusBug(err), | 4139 | .INVALID_PARAMETER, // SERIAL_PORT devices like AUX, COM1, etc |
| | 4140 | .INVALID_DEVICE_REQUEST, // CONSOLE, etc devices |
| | 4141 | .INVALID_INFO_CLASS, // NULL, etc devices |
| | 4142 | => { |
| | 4143 | syscall.finish(); |
| | 4144 | const device = try windowsGetFileDevice(file); |
| | 4145 | return .{ |
| | 4146 | .inode = @intCast(@intFromPtr(file.handle)), |
| | 4147 | .size = 0, |
| | 4148 | .permissions = .default_file, |
| | 4149 | .kind = switch (device) { |
| | 4150 | // These are classified as FILE_TYPE_CHAR by GetFileType |
| | 4151 | // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfiletype |
| | 4152 | // (GetFileType calls NtQueryVolumeInformationFile with FS_DEVICE_INFORMATION) |
| | 4153 | .CONSOLE, .NULL, .SERIAL_PORT => .character_device, |
| | 4154 | else => .unknown, |
| | 4155 | }, |
| | 4156 | // Match the times that NtQueryInformationFile returns for named pipes. |
| | 4157 | .atime = windows.fromSysTime(0), |
| | 4158 | .mtime = windows.fromSysTime(0), |
| | 4159 | .ctime = windows.fromSysTime(0), |
| | 4160 | .nlink = 1, |
| | 4161 | .block_size = block_size, |
| | 4162 | }; |
| | 4163 | }, |
| 4116 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), | 4164 | .ACCESS_DENIED => return syscall.fail(error.AccessDenied), |
| 4117 | .CANCELLED => { | 4165 | .CANCELLED => { |
| 4118 | try syscall.checkCancel(); | 4166 | try syscall.checkCancel(); |
| ... | @@ -4151,8 +4199,10 @@ fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { | ... | @@ -4151,8 +4199,10 @@ fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat { |
| 4151 | break :reparse_point .unknown; | 4199 | break :reparse_point .unknown; |
| 4152 | } else if (info.BasicInformation.FileAttributes.DIRECTORY) | 4200 | } else if (info.BasicInformation.FileAttributes.DIRECTORY) |
| 4153 | .directory | 4201 | .directory |
| 4154 | else | 4202 | else switch (try windowsGetFileDevice(file)) { |
| 4155 | .file, | 4203 | .NAMED_PIPE => .named_pipe, |
| | 4204 | else => .file, |
| | 4205 | }, |
| 4156 | .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime), | 4206 | .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime), |
| 4157 | .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime), | 4207 | .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime), |
| 4158 | .ctime = windows.fromSysTime(info.BasicInformation.ChangeTime), | 4208 | .ctime = windows.fromSysTime(info.BasicInformation.ChangeTime), |
| ... | @@ -17794,6 +17844,7 @@ pub fn windowsCreatePipe(t: *Threaded, options: CreatePipeOptions) ![2]windows.H | ... | @@ -17794,6 +17844,7 @@ pub fn windowsCreatePipe(t: *Threaded, options: CreatePipeOptions) ![2]windows.H |
| 17794 | .READ_DATA = options.inbound, | 17844 | .READ_DATA = options.inbound, |
| 17795 | .WRITE_DATA = options.outbound, | 17845 | .WRITE_DATA = options.outbound, |
| 17796 | .WRITE_ATTRIBUTES = true, | 17846 | .WRITE_ATTRIBUTES = true, |
| | 17847 | .READ_ATTRIBUTES = true, |
| 17797 | } }, | 17848 | } }, |
| 17798 | .STANDARD = .{ .SYNCHRONIZE = true }, | 17849 | .STANDARD = .{ .SYNCHRONIZE = true }, |
| 17799 | }, | 17850 | }, |
| ... | @@ -17836,6 +17887,7 @@ pub fn windowsCreatePipe(t: *Threaded, options: CreatePipeOptions) ![2]windows.H | ... | @@ -17836,6 +17887,7 @@ pub fn windowsCreatePipe(t: *Threaded, options: CreatePipeOptions) ![2]windows.H |
| 17836 | .READ_DATA = options.outbound, | 17887 | .READ_DATA = options.outbound, |
| 17837 | .WRITE_DATA = options.inbound, | 17888 | .WRITE_DATA = options.inbound, |
| 17838 | .WRITE_ATTRIBUTES = true, | 17889 | .WRITE_ATTRIBUTES = true, |
| | 17890 | .READ_ATTRIBUTES = true, |
| 17839 | } }, | 17891 | } }, |
| 17840 | .STANDARD = .{ .SYNCHRONIZE = true }, | 17892 | .STANDARD = .{ .SYNCHRONIZE = true }, |
| 17841 | }, | 17893 | }, |