Commit 8173fbfb66
lib/std/event/batch.zig
@@ -109,13 +109,13 @@ pub fn Batch(
test "std.event.Batch" {
var count: usize = 0;
- var batch = Batch(void, 2).init();
+ var batch = Batch(void, 2, .auto_async).init();
batch.add(&async sleepALittle(&count));
batch.add(&async increaseByTen(&count));
batch.wait();
testing.expect(count == 11);
- var another = Batch(anyerror!void, 2).init();
+ var another = Batch(anyerror!void, 2, .auto_async).init();
another.add(&async somethingElse());
another.add(&async doSomethingThatFails());
testing.expectError(error.ItBroke, another.wait());
lib/std/os/windows/ntdll.zig
@@ -8,6 +8,12 @@ pub extern "NtDll" fn NtQueryInformationFile(
Length: ULONG,
FileInformationClass: FILE_INFORMATION_CLASS,
) callconv(.Stdcall) NTSTATUS;
+
+pub extern "NtDll" fn NtQueryAttributesFile(
+ ObjectAttributes: *OBJECT_ATTRIBUTES,
+ FileAttributes: *FILE_BASIC_INFORMATION,
+) callconv(.Stdcall) NTSTATUS;
+
pub extern "NtDll" fn NtCreateFile(
FileHandle: *HANDLE,
DesiredAccess: ACCESS_MASK,
lib/std/fs.zig
@@ -818,6 +818,13 @@ pub const Dir = struct {
) File.OpenError!File {
const w = os.windows;
+ if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
+ return error.IsDir;
+ }
+ if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
+ return error.IsDir;
+ }
+
var result = File{
.handle = undefined,
.io_mode = .blocking,
@@ -839,12 +846,6 @@ pub const Dir = struct {
.SecurityDescriptor = null,
.SecurityQualityOfService = null,
};
- if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
- return error.IsDir;
- }
- if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
- return error.IsDir;
- }
var io: w.IO_STATUS_BLOCK = undefined;
const rc = w.ntdll.NtCreateFile(
&result.handle,
@@ -1332,12 +1333,20 @@ pub const Dir = struct {
/// For example, instead of testing if a file exists and then opening it, just
/// open it and handle the error for file not found.
pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void {
+ if (builtin.os == .windows) {
+ const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
+ return self.accessW(&sub_path_w, flags);
+ }
const path_c = try os.toPosixPath(sub_path);
return self.accessZ(&path_c, flags);
}
/// Same as `access` except the path parameter is null-terminated.
pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void {
+ if (builtin.os == .windows) {
+ const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path);
+ return self.accessW(&sub_path_w, flags);
+ }
const os_mode = if (flags.write and flags.read)
@as(u32, os.R_OK | os.W_OK)
else if (flags.write)
@@ -1351,9 +1360,13 @@ pub const Dir = struct {
return result;
}
- /// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
- pub fn accessW(self: Dir, sub_path: [*:0]const u16, flags: File.OpenFlags) AccessError!void {
- return os.faccessatW(self.fd, sub_path, 0, 0);
+ /// Same as `access` except asserts the target OS is Windows and the path parameter is
+ /// * WTF-16 encoded
+ /// * null-terminated
+ /// * NtDll prefixed
+ /// TODO currently this ignores `flags`.
+ pub fn accessW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) AccessError!void {
+ return os.faccessatW(self.fd, sub_path_w, 0, 0);
}
};
lib/std/os.zig
@@ -2553,10 +2553,42 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces
}
/// Same as `faccessat` except asserts the target is Windows and the path parameter
-/// is null-terminated WTF-16 encoded.
+/// is NtDll-prefixed, null-terminated, WTF-16 encoded.
/// TODO currently this ignores `mode` and `flags`
-pub fn faccessatW(dirfd: fd_t, path: [*:0]const u16, mode: u32, flags: u32) AccessError!void {
- @compileError("TODO implement faccessatW on Windows");
+pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32) AccessError!void {
+ if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
+ return;
+ }
+ if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
+ return;
+ }
+
+ const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
+ error.Overflow => return error.NameTooLong,
+ };
+ var nt_name = windows.UNICODE_STRING{
+ .Length = path_len_bytes,
+ .MaximumLength = path_len_bytes,
+ .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
+ };
+ var attr = windows.OBJECT_ATTRIBUTES{
+ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
+ .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dirfd,
+ .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
+ .ObjectName = &nt_name,
+ .SecurityDescriptor = null,
+ .SecurityQualityOfService = null,
+ };
+ var basic_info: windows.FILE_BASIC_INFORMATION = undefined;
+ switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) {
+ .SUCCESS => return,
+ .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
+ .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .INVALID_PARAMETER => unreachable,
+ .ACCESS_DENIED => return error.PermissionDenied,
+ .OBJECT_PATH_SYNTAX_BAD => unreachable,
+ else => |rc| return windows.unexpectedStatus(rc),
+ }
}
pub const PipeError = error{