authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-14 16:59:43-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-10-14 16:59:43-04:00
log0307dc0b774daa20c3258e3bd3330f5316c118cf
tree35d7fdaacf808631e8d7dc15455ca9710c59da8e
parenta68dc65327469b4b2cc8a034d5e28dac86fe2802

organize windows utility functions


3 files changed, 121 insertions(+), 109 deletions(-)

CMakeLists.txt+1
...@@ -581,6 +581,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_x86_64.zig" DESTINATION "${ZIG_S...@@ -581,6 +581,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/os/linux_x86_64.zig" DESTINATION "${ZIG_S
581install(FILES "${CMAKE_SOURCE_DIR}/std/os/path.zig" DESTINATION "${ZIG_STD_DEST}/os")581install(FILES "${CMAKE_SOURCE_DIR}/std/os/path.zig" DESTINATION "${ZIG_STD_DEST}/os")
582install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/error.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")582install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/error.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
583install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")583install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/index.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
584install(FILES "${CMAKE_SOURCE_DIR}/std/os/windows/util.zig" DESTINATION "${ZIG_STD_DEST}/os/windows")
584install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")585install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
585install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")586install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
586install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")587install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
std/os/index.zig+8-109
...@@ -25,6 +25,14 @@ pub const page_size = 4 * 1024;...@@ -25,6 +25,14 @@ pub const page_size = 4 * 1024;
25pub const UserInfo = @import("get_user_id.zig").UserInfo;25pub const UserInfo = @import("get_user_id.zig").UserInfo;
26pub const getUserInfo = @import("get_user_id.zig").getUserInfo;26pub const getUserInfo = @import("get_user_id.zig").getUserInfo;
2727
28const windows_util = @import("windows/util.zig");
29pub const windowsClose = windows_util.windowsClose;
30pub const windowsWaitSingle = windows_util.windowsWaitSingle;
31pub const windowsWrite = windows_util.windowsWrite;
32pub const windowsIsTty = windows_util.windowsIsTty;
33pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty;
34pub const windowsOpen = windows_util.windowsOpen;
35
28const debug = @import("../debug.zig");36const debug = @import("../debug.zig");
29const assert = debug.assert;37const assert = debug.assert;
3038
...@@ -162,10 +170,6 @@ pub fn posixClose(fd: i32) {...@@ -162,10 +170,6 @@ pub fn posixClose(fd: i32) {
162 }170 }
163}171}
164172
165pub fn windowsClose(handle: windows.HANDLE) {
166 assert(windows.CloseHandle(handle));
167}
168
169/// Calls POSIX read, and keeps trying if it gets interrupted.173/// Calls POSIX read, and keeps trying if it gets interrupted.
170pub fn posixRead(fd: i32, buf: []u8) -> %void {174pub fn posixRead(fd: i32, buf: []u8) -> %void {
171 var index: usize = 0;175 var index: usize = 0;
...@@ -223,50 +227,6 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {...@@ -223,50 +227,6 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void {
223 }227 }
224}228}
225229
226error SystemResources;
227error OperationAborted;
228error IoPending;
229error BrokenPipe;
230
231pub 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
245pub 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
253pub 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/// ::file_path may need to be copied in memory to add a null terminating byte. In this case230/// ::file_path may need to be copied in memory to add a null terminating byte. In this case
271/// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed231/// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed
272/// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned.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,51 +282,6 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al
322 }282 }
323}283}
324284
325
326error SharingViolation;
327error 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.
333pub 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
370pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void {285pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void {
371 while (true) {286 while (true) {
372 const err = posix.getErrno(posix.dup2(old_fd, new_fd));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,22 +1309,6 @@ fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const
1394 assert(it.next(&debug.global_allocator) == null);1309 assert(it.next(&debug.global_allocator) == null);
1395}1310}
13961311
1397error WaitAbandoned;
1398error WaitTimeOut;
1399
1400pub 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
1413test "std.os" {1312test "std.os" {
1414 _ = @import("child_process.zig");1313 _ = @import("child_process.zig");
1415 _ = @import("darwin_errno.zig");1314 _ = @import("darwin_errno.zig");
std/os/windows/util.zig created+112
...@@ -0,0 +1,112 @@
1const std = @import("../../index.zig");
2const windows = std.os.windows;
3const assert = std.debug.assert;
4const mem = std.mem;
5
6error WaitAbandoned;
7error WaitTimeOut;
8
9pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void {
10 const result = windows.WaitForSingleObject(handle, milliseconds);
11 return switch (result) {
12 windows.WAIT_ABANDONED => error.WaitAbandoned,
13 windows.WAIT_OBJECT_0 => {},
14 windows.WAIT_TIMEOUT => error.WaitTimeOut,
15 windows.WAIT_FAILED => switch (windows.GetLastError()) {
16 else => error.Unexpected,
17 },
18 else => error.Unexpected,
19 };
20}
21
22pub fn windowsClose(handle: windows.HANDLE) {
23 assert(windows.CloseHandle(handle));
24}
25
26error SystemResources;
27error OperationAborted;
28error IoPending;
29error BrokenPipe;
30
31pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void {
32 if (!windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null)) {
33 return switch (windows.GetLastError()) {
34 windows.ERROR.INVALID_USER_BUFFER => error.SystemResources,
35 windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources,
36 windows.ERROR.OPERATION_ABORTED => error.OperationAborted,
37 windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources,
38 windows.ERROR.IO_PENDING => error.IoPending,
39 windows.ERROR.BROKEN_PIPE => error.BrokenPipe,
40 else => error.Unexpected,
41 };
42 }
43}
44
45pub fn windowsIsTty(handle: windows.HANDLE) -> bool {
46 if (windowsIsCygwinPty(handle))
47 return true;
48
49 var out: windows.DWORD = undefined;
50 return windows.GetConsoleMode(handle, &out);
51}
52
53pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool {
54 const size = @sizeOf(windows.FILE_NAME_INFO);
55 var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH);
56
57 if (!windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo,
58 @ptrCast(&c_void, &name_info_bytes[0]), u32(name_info_bytes.len)))
59 {
60 return true;
61 }
62
63 const name_info = @ptrCast(&const windows.FILE_NAME_INFO, &name_info_bytes[0]);
64 const name_bytes = name_info_bytes[size..size + usize(name_info.FileNameLength)];
65 const name_wide = ([]u16)(name_bytes);
66 return mem.indexOf(u16, name_wide, []u16{'m','s','y','s','-'}) != null or
67 mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null;
68}
69
70error SharingViolation;
71error PipeBusy;
72
73/// `file_path` may need to be copied in memory to add a null terminating byte. In this case
74/// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed
75/// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned.
76/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory.
77pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_mode: windows.DWORD,
78 creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD, allocator: ?&Allocator) -> %windows.HANDLE
79{
80 var stack_buf: [max_noalloc_path_len]u8 = undefined;
81 var path0: []u8 = undefined;
82 var need_free = false;
83 defer if (need_free) (??allocator).free(path0);
84
85 if (file_path.len < stack_buf.len) {
86 path0 = stack_buf[0..file_path.len + 1];
87 } else if (allocator) |a| {
88 path0 = %return a.alloc(u8, file_path.len + 1);
89 need_free = true;
90 } else {
91 return error.NameTooLong;
92 }
93 mem.copy(u8, path0, file_path);
94 path0[file_path.len] = 0;
95
96 const result = windows.CreateFileA(path0.ptr, desired_access, share_mode, null, creation_disposition,
97 flags_and_attrs, null);
98
99 if (result == windows.INVALID_HANDLE_VALUE) {
100 const err = windows.GetLastError();
101 return switch (err) {
102 windows.ERROR.SHARING_VIOLATION => error.SharingViolation,
103 windows.ERROR.ALREADY_EXISTS, windows.ERROR.FILE_EXISTS => error.PathAlreadyExists,
104 windows.ERROR.FILE_NOT_FOUND => error.FileNotFound,
105 windows.ERROR.ACCESS_DENIED => error.AccessDenied,
106 windows.ERROR.PIPE_BUSY => error.PipeBusy,
107 else => error.Unexpected,
108 };
109 }
110
111 return result;
112}