From 0307dc0b774daa20c3258e3bd3330f5316c118cf Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 14 Oct 2017 16:59:43 -0400 Subject: [PATCH] organize windows utility functions --- CMakeLists.txt | 1 + std/os/index.zig | 117 +++------------------------------------- std/os/windows/util.zig | 112 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 109 deletions(-) create mode 100644 std/os/windows/util.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index a10e6504a..26489b52c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -581,6 +581,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_x86_64.zig" DESTINATION "${ZIG_S install(FILES "${CMAKE_SOURCE_DIR}/std/os/path.zig" DESTINATION "${ZIG_STD_DEST}/os") install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/error.zig" DESTINATION "${ZIG_STD_DEST}/os/windows") install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_STD_DEST}/os/windows") +install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/util.zig" DESTINATION "${ZIG_STD_DEST}/os/windows") install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special") diff --git a/std/os/index.zig b/std/os/index.zig index 6f5631c12..a9d91972b 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -25,6 +25,14 @@ pub const page_size = 4 * 1024; pub const UserInfo = @import("get_user_id.zig").UserInfo; pub const getUserInfo = @import("get_user_id.zig").getUserInfo; +const windows_util = @import("windows/util.zig"); +pub const windowsClose = windows_util.windowsClose; +pub const windowsWaitSingle = windows_util.windowsWaitSingle; +pub const windowsWrite = windows_util.windowsWrite; +pub const windowsIsTty = windows_util.windowsIsTty; +pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty; +pub const windowsOpen = windows_util.windowsOpen; + const debug = @import("../debug.zig"); const assert = debug.assert; @@ -162,10 +170,6 @@ pub fn posixClose(fd: i32) { } } -pub fn windowsClose(handle: windows.HANDLE) { - assert(windows.CloseHandle(handle)); -} - /// Calls POSIX read, and keeps trying if it gets interrupted. pub fn posixRead(fd: i32, buf: []u8) -> %void { var index: usize = 0; @@ -223,50 +227,6 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void { } } -error SystemResources; -error OperationAborted; -error IoPending; -error BrokenPipe; - -pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void { - if (!windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null)) { - return switch (windows.GetLastError()) { - windows.ERROR.INVALID_USER_BUFFER => error.SystemResources, - windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources, - windows.ERROR.OPERATION_ABORTED => error.OperationAborted, - windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources, - windows.ERROR.IO_PENDING => error.IoPending, - windows.ERROR.BROKEN_PIPE => error.BrokenPipe, - else => error.Unexpected, - }; - } -} - -pub fn windowsIsTty(handle: windows.HANDLE) -> bool { - if (windowsIsCygwinPty(handle)) - return true; - - var out: windows.DWORD = undefined; - return windows.GetConsoleMode(handle, &out); -} - -pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool { - const size = @sizeOf(windows.FILE_NAME_INFO); - var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH); - - if (!windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo, - @ptrCast(&c_void, &name_info_bytes[0]), u32(name_info_bytes.len))) - { - return true; - } - - const name_info = @ptrCast(&const windows.FILE_NAME_INFO, &name_info_bytes[0]); - const name_bytes = name_info_bytes[size..size + usize(name_info.FileNameLength)]; - const name_wide = ([]u16)(name_bytes); - return mem.indexOf(u16, name_wide, []u16{'m','s','y','s','-'}) != null or - mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null; -} - /// ::file_path may need to be copied in memory to add a null terminating byte. In this case /// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed /// 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 } } - -error SharingViolation; -error PipeBusy; - -/// `file_path` may need to be copied in memory to add a null terminating byte. In this case -/// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed -/// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned. -/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. -pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_mode: windows.DWORD, - creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD, allocator: ?&Allocator) -> %windows.HANDLE -{ - var stack_buf: [max_noalloc_path_len]u8 = undefined; - var path0: []u8 = undefined; - var need_free = false; - defer if (need_free) (??allocator).free(path0); - - if (file_path.len < stack_buf.len) { - path0 = stack_buf[0..file_path.len + 1]; - } else if (allocator) |a| { - path0 = %return a.alloc(u8, file_path.len + 1); - need_free = true; - } else { - return error.NameTooLong; - } - mem.copy(u8, path0, file_path); - path0[file_path.len] = 0; - - const result = windows.CreateFileA(path0.ptr, desired_access, share_mode, null, creation_disposition, - flags_and_attrs, null); - - if (result == windows.INVALID_HANDLE_VALUE) { - const err = windows.GetLastError(); - return switch (err) { - windows.ERROR.SHARING_VIOLATION => error.SharingViolation, - windows.ERROR.ALREADY_EXISTS, windows.ERROR.FILE_EXISTS => error.PathAlreadyExists, - windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, - windows.ERROR.ACCESS_DENIED => error.AccessDenied, - windows.ERROR.PIPE_BUSY => error.PipeBusy, - else => error.Unexpected, - }; - } - - return result; -} - pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { while (true) { 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 assert(it.next(&debug.global_allocator) == null); } -error WaitAbandoned; -error WaitTimeOut; - -pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void { - const result = windows.WaitForSingleObject(handle, milliseconds); - return switch (result) { - windows.WAIT_ABANDONED => error.WaitAbandoned, - windows.WAIT_OBJECT_0 => {}, - windows.WAIT_TIMEOUT => error.WaitTimeOut, - windows.WAIT_FAILED => switch (windows.GetLastError()) { - else => error.Unexpected, - }, - else => error.Unexpected, - }; -} - test "std.os" { _ = @import("child_process.zig"); _ = @import("darwin_errno.zig"); diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig new file mode 100644 index 000000000..2d33810b3 --- /dev/null +++ b/std/os/windows/util.zig @@ -0,0 +1,112 @@ +const std = @import("../../index.zig"); +const windows = std.os.windows; +const assert = std.debug.assert; +const mem = std.mem; + +error WaitAbandoned; +error WaitTimeOut; + +pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void { + const result = windows.WaitForSingleObject(handle, milliseconds); + return switch (result) { + windows.WAIT_ABANDONED => error.WaitAbandoned, + windows.WAIT_OBJECT_0 => {}, + windows.WAIT_TIMEOUT => error.WaitTimeOut, + windows.WAIT_FAILED => switch (windows.GetLastError()) { + else => error.Unexpected, + }, + else => error.Unexpected, + }; +} + +pub fn windowsClose(handle: windows.HANDLE) { + assert(windows.CloseHandle(handle)); +} + +error SystemResources; +error OperationAborted; +error IoPending; +error BrokenPipe; + +pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void { + if (!windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null)) { + return switch (windows.GetLastError()) { + windows.ERROR.INVALID_USER_BUFFER => error.SystemResources, + windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources, + windows.ERROR.OPERATION_ABORTED => error.OperationAborted, + windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources, + windows.ERROR.IO_PENDING => error.IoPending, + windows.ERROR.BROKEN_PIPE => error.BrokenPipe, + else => error.Unexpected, + }; + } +} + +pub fn windowsIsTty(handle: windows.HANDLE) -> bool { + if (windowsIsCygwinPty(handle)) + return true; + + var out: windows.DWORD = undefined; + return windows.GetConsoleMode(handle, &out); +} + +pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool { + const size = @sizeOf(windows.FILE_NAME_INFO); + var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH); + + if (!windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo, + @ptrCast(&c_void, &name_info_bytes[0]), u32(name_info_bytes.len))) + { + return true; + } + + const name_info = @ptrCast(&const windows.FILE_NAME_INFO, &name_info_bytes[0]); + const name_bytes = name_info_bytes[size..size + usize(name_info.FileNameLength)]; + const name_wide = ([]u16)(name_bytes); + return mem.indexOf(u16, name_wide, []u16{'m','s','y','s','-'}) != null or + mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null; +} + +error SharingViolation; +error PipeBusy; + +/// `file_path` may need to be copied in memory to add a null terminating byte. In this case +/// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed +/// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned. +/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. +pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_mode: windows.DWORD, + creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD, allocator: ?&Allocator) -> %windows.HANDLE +{ + var stack_buf: [max_noalloc_path_len]u8 = undefined; + var path0: []u8 = undefined; + var need_free = false; + defer if (need_free) (??allocator).free(path0); + + if (file_path.len < stack_buf.len) { + path0 = stack_buf[0..file_path.len + 1]; + } else if (allocator) |a| { + path0 = %return a.alloc(u8, file_path.len + 1); + need_free = true; + } else { + return error.NameTooLong; + } + mem.copy(u8, path0, file_path); + path0[file_path.len] = 0; + + const result = windows.CreateFileA(path0.ptr, desired_access, share_mode, null, creation_disposition, + flags_and_attrs, null); + + if (result == windows.INVALID_HANDLE_VALUE) { + const err = windows.GetLastError(); + return switch (err) { + windows.ERROR.SHARING_VIOLATION => error.SharingViolation, + windows.ERROR.ALREADY_EXISTS, windows.ERROR.FILE_EXISTS => error.PathAlreadyExists, + windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, + windows.ERROR.ACCESS_DENIED => error.AccessDenied, + windows.ERROR.PIPE_BUSY => error.PipeBusy, + else => error.Unexpected, + }; + } + + return result; +}