authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-16 17:10:43-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-16 17:10:43-05:00
log8173fbfb66132f0fca42a3c8415381ad9f5d632d
treea33289790cdc09c1a71ff14f6a35e82a54d082b8
parent4b02a39aa93b0043f05de0d90443051c019643ab
signaturelock-open Commit is signed but in an unrecognized format.

implement os.faccessat for Windows


4 files changed, 65 insertions(+), 14 deletions(-)

lib/std/event/batch.zig+2-2
......@@ -109,13 +109,13 @@ pub fn Batch(
109109
110110test "std.event.Batch" {
111111 var count: usize = 0;
112 var batch = Batch(void, 2).init();
112 var batch = Batch(void, 2, .auto_async).init();
113113 batch.add(&async sleepALittle(&count));
114114 batch.add(&async increaseByTen(&count));
115115 batch.wait();
116116 testing.expect(count == 11);
117117
118 var another = Batch(anyerror!void, 2).init();
118 var another = Batch(anyerror!void, 2, .auto_async).init();
119119 another.add(&async somethingElse());
120120 another.add(&async doSomethingThatFails());
121121 testing.expectError(error.ItBroke, another.wait());
lib/std/fs.zig+22-9
......@@ -818,6 +818,13 @@ pub const Dir = struct {
818818 ) File.OpenError!File {
819819 const w = os.windows;
820820
821 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
822 return error.IsDir;
823 }
824 if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
825 return error.IsDir;
826 }
827
821828 var result = File{
822829 .handle = undefined,
823830 .io_mode = .blocking,
......@@ -839,12 +846,6 @@ pub const Dir = struct {
839846 .SecurityDescriptor = null,
840847 .SecurityQualityOfService = null,
841848 };
842 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
843 return error.IsDir;
844 }
845 if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
846 return error.IsDir;
847 }
848849 var io: w.IO_STATUS_BLOCK = undefined;
849850 const rc = w.ntdll.NtCreateFile(
850851 &result.handle,
......@@ -1332,12 +1333,20 @@ pub const Dir = struct {
13321333 /// For example, instead of testing if a file exists and then opening it, just
13331334 /// open it and handle the error for file not found.
13341335 pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void {
1336 if (builtin.os == .windows) {
1337 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
1338 return self.accessW(&sub_path_w, flags);
1339 }
13351340 const path_c = try os.toPosixPath(sub_path);
13361341 return self.accessZ(&path_c, flags);
13371342 }
13381343
13391344 /// Same as `access` except the path parameter is null-terminated.
13401345 pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void {
1346 if (builtin.os == .windows) {
1347 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path);
1348 return self.accessW(&sub_path_w, flags);
1349 }
13411350 const os_mode = if (flags.write and flags.read)
13421351 @as(u32, os.R_OK | os.W_OK)
13431352 else if (flags.write)
......@@ -1351,9 +1360,13 @@ pub const Dir = struct {
13511360 return result;
13521361 }
13531362
1354 /// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
1355 pub fn accessW(self: Dir, sub_path: [*:0]const u16, flags: File.OpenFlags) AccessError!void {
1356 return os.faccessatW(self.fd, sub_path, 0, 0);
1363 /// Same as `access` except asserts the target OS is Windows and the path parameter is
1364 /// * WTF-16 encoded
1365 /// * null-terminated
1366 /// * NtDll prefixed
1367 /// TODO currently this ignores `flags`.
1368 pub fn accessW(self: Dir, sub_path_w: [*:0]const u16, flags: File.OpenFlags) AccessError!void {
1369 return os.faccessatW(self.fd, sub_path_w, 0, 0);
13571370 }
13581371};
13591372
lib/std/os.zig+35-3
......@@ -2553,10 +2553,42 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces
25532553}
25542554
25552555/// Same as `faccessat` except asserts the target is Windows and the path parameter
2556/// is null-terminated WTF-16 encoded.
2556/// is NtDll-prefixed, null-terminated, WTF-16 encoded.
25572557/// TODO currently this ignores `mode` and `flags`
2558pub fn faccessatW(dirfd: fd_t, path: [*:0]const u16, mode: u32, flags: u32) AccessError!void {
2559 @compileError("TODO implement faccessatW on Windows");
2558pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32) AccessError!void {
2559 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
2560 return;
2561 }
2562 if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
2563 return;
2564 }
2565
2566 const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) {
2567 error.Overflow => return error.NameTooLong,
2568 };
2569 var nt_name = windows.UNICODE_STRING{
2570 .Length = path_len_bytes,
2571 .MaximumLength = path_len_bytes,
2572 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
2573 };
2574 var attr = windows.OBJECT_ATTRIBUTES{
2575 .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
2576 .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dirfd,
2577 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
2578 .ObjectName = &nt_name,
2579 .SecurityDescriptor = null,
2580 .SecurityQualityOfService = null,
2581 };
2582 var basic_info: windows.FILE_BASIC_INFORMATION = undefined;
2583 switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) {
2584 .SUCCESS => return,
2585 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
2586 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
2587 .INVALID_PARAMETER => unreachable,
2588 .ACCESS_DENIED => return error.PermissionDenied,
2589 .OBJECT_PATH_SYNTAX_BAD => unreachable,
2590 else => |rc| return windows.unexpectedStatus(rc),
2591 }
25602592}
25612593
25622594pub const PipeError = error{
lib/std/os/windows/ntdll.zig+6
......@@ -8,6 +8,12 @@ pub extern "NtDll" fn NtQueryInformationFile(
88 Length: ULONG,
99 FileInformationClass: FILE_INFORMATION_CLASS,
1010) callconv(.Stdcall) NTSTATUS;
11
12pub extern "NtDll" fn NtQueryAttributesFile(
13 ObjectAttributes: *OBJECT_ATTRIBUTES,
14 FileAttributes: *FILE_BASIC_INFORMATION,
15) callconv(.Stdcall) NTSTATUS;
16
1117pub extern "NtDll" fn NtCreateFile(
1218 FileHandle: *HANDLE,
1319 DesiredAccess: ACCESS_MASK,