organize windows utility functions
parent
a68dc65327
commit
0307dc0b77
|
@ -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")
|
||||
|
|
117
std/os/index.zig
117
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");
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue