@@ -4486,11 +4486,12 @@ pub const AccessError = error{
4486
4486
} || UnexpectedError ;
4487
4487
4488
4488
/// check user's permissions for a file
4489
- /// TODO currently this assumes `mode` is `F.OK` on Windows.
4490
4489
pub fn access (path : []const u8 , mode : u32 ) AccessError ! void {
4491
4490
if (builtin .os .tag == .windows ) {
4492
4491
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 ;
4494
4495
return ;
4495
4496
} else if (builtin .os .tag == .wasi and ! builtin .link_libc ) {
4496
4497
return faccessat (wasi .AT .FDCWD , path , mode , 0 );
@@ -4503,7 +4504,9 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
4503
4504
pub fn accessZ (path : [* :0 ]const u8 , mode : u32 ) AccessError ! void {
4504
4505
if (builtin .os .tag == .windows ) {
4505
4506
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 ;
4507
4510
return ;
4508
4511
} else if (builtin .os .tag == .wasi and ! builtin .link_libc ) {
4509
4512
return access (mem .sliceTo (path , 0 ), mode );
@@ -4527,19 +4530,11 @@ pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
4527
4530
4528
4531
/// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string.
4529
4532
/// Otherwise use `access` or `accessC`.
4530
- /// TODO currently this ignores `mode`.
4531
4533
pub fn accessW (path : [* :0 ]const u16 , mode : u32 ) windows.GetFileAttributesError ! void {
4532
- _ = mode ;
4533
4534
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 ;
4543
4538
}
4544
4539
4545
4540
/// 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
4613
4608
4614
4609
/// Same as `faccessat` except asserts the target is Windows and the path parameter
4615
4610
/// is NtDll-prefixed, null-terminated, WTF-16 encoded.
4616
- /// TODO currently this ignores `mode` and ` flags`
4611
+ /// TODO currently this ignores `flags`
4617
4612
pub fn faccessatW (dirfd : fd_t , sub_path_w : [* :0 ]const u16 , mode : u32 , flags : u32 ) AccessError ! void {
4618
- _ = mode ;
4619
4613
_ = flags ;
4620
4614
if (sub_path_w [0 ] == '.' and sub_path_w [1 ] == 0 ) {
4621
4615
return ;
@@ -4640,7 +4634,11 @@ pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16, mode: u32, flags: u32
4640
4634
};
4641
4635
var basic_info : windows.FILE_BASIC_INFORMATION = undefined ;
4642
4636
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
+ },
4644
4642
.OBJECT_NAME_NOT_FOUND = > return error .FileNotFound ,
4645
4643
.OBJECT_PATH_NOT_FOUND = > return error .FileNotFound ,
4646
4644
.OBJECT_NAME_INVALID = > unreachable ,
0 commit comments