Skip to content

Commit e2d21cf

Browse files
committed
Implement access and faccessat with W_OK on Windows
`windows.GetFileAttributesW` seems to already handle the errors checked for in `accessW`.
1 parent 4652729 commit e2d21cf

File tree

2 files changed

+17
-17
lines changed

2 files changed

+17
-17
lines changed

lib/std/c/windows.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ pub const E = enum(u16) {
199199
pub const STRUNCATE = 80;
200200

201201
pub const F_OK = 0;
202+
// pub const R_OK = 1;
203+
pub const W_OK = 2;
202204

203205
/// Remove directory instead of unlinking file
204206
pub const AT = struct {

lib/std/os.zig

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4486,11 +4486,12 @@ pub const AccessError = error{
44864486
} || UnexpectedError;
44874487

44884488
/// check user's permissions for a file
4489-
/// TODO currently this assumes `mode` is `F.OK` on Windows.
44904489
pub fn access(path: []const u8, mode: u32) AccessError!void {
44914490
if (builtin.os.tag == .windows) {
44924491
const path_w = try windows.sliceToPrefixedFileW(path);
4493-
_ = try windows.GetFileAttributesW(path_w.span().ptr);
4492+
const attrs = try windows.GetFileAttributesW(path_w.span().ptr);
4493+
if (mode & W_OK != 0 and attrs & windows.FILE_ATTRIBUTE_READONLY != 0)
4494+
return error.PermissionDenied;
44944495
return;
44954496
} else if (builtin.os.tag == .wasi and !builtin.link_libc) {
44964497
return faccessat(wasi.AT.FDCWD, path, mode, 0);
@@ -4503,7 +4504,9 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
45034504
pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
45044505
if (builtin.os.tag == .windows) {
45054506
const path_w = try windows.cStrToPrefixedFileW(path);
4506-
_ = try windows.GetFileAttributesW(path_w.span().ptr);
4507+
const attrs = try windows.GetFileAttributesW(path_w.span().ptr);
4508+
if (mode & W_OK != 0 and attrs & windows.FILE_ATTRIBUTE_READONLY != 0)
4509+
return error.PermissionDenied;
45074510
return;
45084511
} else if (builtin.os.tag == .wasi and !builtin.link_libc) {
45094512
return access(mem.sliceTo(path, 0), mode);
@@ -4527,19 +4530,11 @@ pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
45274530

45284531
/// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string.
45294532
/// Otherwise use `access` or `accessC`.
4530-
/// TODO currently this ignores `mode`.
45314533
pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!void {
4532-
_ = mode;
45334534
const ret = try windows.GetFileAttributesW(path);
4534-
if (ret != windows.INVALID_FILE_ATTRIBUTES) {
4535-
return;
4536-
}
4537-
switch (windows.kernel32.GetLastError()) {
4538-
.FILE_NOT_FOUND => return error.FileNotFound,
4539-
.PATH_NOT_FOUND => return error.FileNotFound,
4540-
.ACCESS_DENIED => return error.PermissionDenied,
4541-
else => |err| return windows.unexpectedError(err),
4542-
}
4535+
if (mode & W_OK != 0 and ret & windows.FILE_ATTRIBUTE_READONLY != 0)
4536+
return error.PermissionDenied;
4537+
return;
45434538
}
45444539

45454540
/// Check user's permissions for a file, based on an open directory handle.
@@ -4613,9 +4608,8 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces
46134608

46144609
/// Same as `faccessat` except asserts the target is Windows and the path parameter
46154610
/// is NtDll-prefixed, null-terminated, WTF-16 encoded.
4616-
/// TODO currently this ignores `mode` and `flags`
4611+
/// TODO currently this ignores `flags`
46174612
pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32) AccessError!void {
4618-
_ = mode;
46194613
_ = flags;
46204614
if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
46214615
return;
@@ -4640,7 +4634,11 @@ pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32
46404634
};
46414635
var basic_info: windows.FILE_BASIC_INFORMATION = undefined;
46424636
switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) {
4643-
.SUCCESS => return,
4637+
.SUCCESS => {
4638+
if (mode & W_OK != 0 and basic_info.FileAttributes & windows.FILE_ATTRIBUTE_READONLY != 0)
4639+
return error.PermissionDenied;
4640+
return;
4641+
},
46444642
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
46454643
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
46464644
.OBJECT_NAME_INVALID => unreachable,

0 commit comments

Comments
 (0)