| ... | ... | @@ -25,6 +25,14 @@ pub const page_size = 4 * 1024; |
| 25 | 25 | pub const UserInfo = @import("get_user_id.zig").UserInfo; |
| 26 | 26 | pub const getUserInfo = @import("get_user_id.zig").getUserInfo; |
| 27 | 27 | |
| 28 | const windows_util = @import("windows/util.zig"); |
| 29 | pub const windowsClose = windows_util.windowsClose; |
| 30 | pub const windowsWaitSingle = windows_util.windowsWaitSingle; |
| 31 | pub const windowsWrite = windows_util.windowsWrite; |
| 32 | pub const windowsIsTty = windows_util.windowsIsTty; |
| 33 | pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty; |
| 34 | pub const windowsOpen = windows_util.windowsOpen; |
| 35 | |
| 28 | 36 | const debug = @import("../debug.zig"); |
| 29 | 37 | const assert = debug.assert; |
| 30 | 38 | |
| ... | ... | @@ -162,10 +170,6 @@ pub fn posixClose(fd: i32) { |
| 162 | 170 | } |
| 163 | 171 | } |
| 164 | 172 | |
| 165 | | pub fn windowsClose(handle: windows.HANDLE) { |
| 166 | | assert(windows.CloseHandle(handle)); |
| 167 | | } |
| 168 | | |
| 169 | 173 | /// Calls POSIX read, and keeps trying if it gets interrupted. |
| 170 | 174 | pub fn posixRead(fd: i32, buf: []u8) -> %void { |
| 171 | 175 | var index: usize = 0; |
| ... | ... | @@ -223,50 +227,6 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void { |
| 223 | 227 | } |
| 224 | 228 | } |
| 225 | 229 | |
| 226 | | error SystemResources; |
| 227 | | error OperationAborted; |
| 228 | | error IoPending; |
| 229 | | error BrokenPipe; |
| 230 | | |
| 231 | | pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void { |
| 232 | | if (!windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null)) { |
| 233 | | return switch (windows.GetLastError()) { |
| 234 | | windows.ERROR.INVALID_USER_BUFFER => error.SystemResources, |
| 235 | | windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources, |
| 236 | | windows.ERROR.OPERATION_ABORTED => error.OperationAborted, |
| 237 | | windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources, |
| 238 | | windows.ERROR.IO_PENDING => error.IoPending, |
| 239 | | windows.ERROR.BROKEN_PIPE => error.BrokenPipe, |
| 240 | | else => error.Unexpected, |
| 241 | | }; |
| 242 | | } |
| 243 | | } |
| 244 | | |
| 245 | | pub fn windowsIsTty(handle: windows.HANDLE) -> bool { |
| 246 | | if (windowsIsCygwinPty(handle)) |
| 247 | | return true; |
| 248 | | |
| 249 | | var out: windows.DWORD = undefined; |
| 250 | | return windows.GetConsoleMode(handle, &out); |
| 251 | | } |
| 252 | | |
| 253 | | pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool { |
| 254 | | const size = @sizeOf(windows.FILE_NAME_INFO); |
| 255 | | var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH); |
| 256 | | |
| 257 | | if (!windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo, |
| 258 | | @ptrCast(&c_void, &name_info_bytes[0]), u32(name_info_bytes.len))) |
| 259 | | { |
| 260 | | return true; |
| 261 | | } |
| 262 | | |
| 263 | | const name_info = @ptrCast(&const windows.FILE_NAME_INFO, &name_info_bytes[0]); |
| 264 | | const name_bytes = name_info_bytes[size..size + usize(name_info.FileNameLength)]; |
| 265 | | const name_wide = ([]u16)(name_bytes); |
| 266 | | return mem.indexOf(u16, name_wide, []u16{'m','s','y','s','-'}) != null or |
| 267 | | mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null; |
| 268 | | } |
| 269 | | |
| 270 | 230 | /// ::file_path may need to be copied in memory to add a null terminating byte. In this case |
| 271 | 231 | /// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed |
| 272 | 232 | /// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned. |
| ... | ... | @@ -322,51 +282,6 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al |
| 322 | 282 | } |
| 323 | 283 | } |
| 324 | 284 | |
| 325 | | |
| 326 | | error SharingViolation; |
| 327 | | error PipeBusy; |
| 328 | | |
| 329 | | /// `file_path` may need to be copied in memory to add a null terminating byte. In this case |
| 330 | | /// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed |
| 331 | | /// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned. |
| 332 | | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. |
| 333 | | pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_mode: windows.DWORD, |
| 334 | | creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD, allocator: ?&Allocator) -> %windows.HANDLE |
| 335 | | { |
| 336 | | var stack_buf: [max_noalloc_path_len]u8 = undefined; |
| 337 | | var path0: []u8 = undefined; |
| 338 | | var need_free = false; |
| 339 | | defer if (need_free) (??allocator).free(path0); |
| 340 | | |
| 341 | | if (file_path.len < stack_buf.len) { |
| 342 | | path0 = stack_buf[0..file_path.len + 1]; |
| 343 | | } else if (allocator) |a| { |
| 344 | | path0 = %return a.alloc(u8, file_path.len + 1); |
| 345 | | need_free = true; |
| 346 | | } else { |
| 347 | | return error.NameTooLong; |
| 348 | | } |
| 349 | | mem.copy(u8, path0, file_path); |
| 350 | | path0[file_path.len] = 0; |
| 351 | | |
| 352 | | const result = windows.CreateFileA(path0.ptr, desired_access, share_mode, null, creation_disposition, |
| 353 | | flags_and_attrs, null); |
| 354 | | |
| 355 | | if (result == windows.INVALID_HANDLE_VALUE) { |
| 356 | | const err = windows.GetLastError(); |
| 357 | | return switch (err) { |
| 358 | | windows.ERROR.SHARING_VIOLATION => error.SharingViolation, |
| 359 | | windows.ERROR.ALREADY_EXISTS, windows.ERROR.FILE_EXISTS => error.PathAlreadyExists, |
| 360 | | windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, |
| 361 | | windows.ERROR.ACCESS_DENIED => error.AccessDenied, |
| 362 | | windows.ERROR.PIPE_BUSY => error.PipeBusy, |
| 363 | | else => error.Unexpected, |
| 364 | | }; |
| 365 | | } |
| 366 | | |
| 367 | | return result; |
| 368 | | } |
| 369 | | |
| 370 | 285 | pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { |
| 371 | 286 | while (true) { |
| 372 | 287 | const err = posix.getErrno(posix.dup2(old_fd, new_fd)); |
| ... | ... | @@ -1394,22 +1309,6 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const |
| 1394 | 1309 | assert(it.next(&debug.global_allocator) == null); |
| 1395 | 1310 | } |
| 1396 | 1311 | |
| 1397 | | error WaitAbandoned; |
| 1398 | | error WaitTimeOut; |
| 1399 | | |
| 1400 | | pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void { |
| 1401 | | const result = windows.WaitForSingleObject(handle, milliseconds); |
| 1402 | | return switch (result) { |
| 1403 | | windows.WAIT_ABANDONED => error.WaitAbandoned, |
| 1404 | | windows.WAIT_OBJECT_0 => {}, |
| 1405 | | windows.WAIT_TIMEOUT => error.WaitTimeOut, |
| 1406 | | windows.WAIT_FAILED => switch (windows.GetLastError()) { |
| 1407 | | else => error.Unexpected, |
| 1408 | | }, |
| 1409 | | else => error.Unexpected, |
| 1410 | | }; |
| 1411 | | } |
| 1412 | | |
| 1413 | 1312 | test "std.os" { |
| 1414 | 1313 | _ = @import("child_process.zig"); |
| 1415 | 1314 | _ = @import("darwin_errno.zig"); |