From f304d8e50afac12ac209f850ced4f9ddf3bcff3b Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Tue, 18 Feb 2025 17:12:51 -0800 Subject: [PATCH 1/3] windows: Use AccessDenied for ACCESS_DENIED on Windows Windows defines an `ACCESS_DENIED` error code. There is no PERMISSION_DENIED (or its equivalent) which seems to only exist on POSIX systems. Fix a couple Windows calls code to return `error.AccessDenied` for `ACCESS_DENIED` and to stop mapping AccessDenied into PermissionDenied. --- lib/std/fs/Dir.zig | 10 ++-------- lib/std/os/windows.zig | 8 ++++---- lib/std/posix.zig | 10 ++-------- lib/std/process/Child.zig | 2 +- 4 files changed, 9 insertions(+), 21 deletions(-) diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig index 4ebec1ce14..a863eda3f9 100644 --- a/lib/std/fs/Dir.zig +++ b/lib/std/fs/Dir.zig @@ -2447,10 +2447,7 @@ pub const AccessError = posix.AccessError; /// 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 (native_os == .windows) { - const sub_path_w = windows.sliceToPrefixedFileW(self.fd, sub_path) catch |err| switch (err) { - error.AccessDenied => return error.PermissionDenied, - else => |e| return e, - }; + const sub_path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path); return self.accessW(sub_path_w.span().ptr, flags); } const path_c = try posix.toPosixPath(sub_path); @@ -2460,10 +2457,7 @@ pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessErro /// 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 (native_os == .windows) { - const sub_path_w = windows.cStrToPrefixedFileW(self.fd, sub_path) catch |err| switch (err) { - error.AccessDenied => return error.PermissionDenied, - else => |e| return e, - }; + const sub_path_w = try windows.cStrToPrefixedFileW(self.fd, sub_path); return self.accessW(sub_path_w.span().ptr, flags); } const os_mode = switch (flags.mode) { diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index c29eb0f05a..776173f7e0 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1517,7 +1517,7 @@ pub fn GetFileSizeEx(hFile: HANDLE) GetFileSizeError!u64 { pub const GetFileAttributesError = error{ FileNotFound, - PermissionDenied, + AccessDenied, Unexpected, }; @@ -1532,7 +1532,7 @@ pub fn GetFileAttributesW(lpFileName: [*:0]const u16) GetFileAttributesError!DWO switch (GetLastError()) { .FILE_NOT_FOUND => return error.FileNotFound, .PATH_NOT_FOUND => return error.FileNotFound, - .ACCESS_DENIED => return error.PermissionDenied, + .ACCESS_DENIED => return error.AccessDenied, else => |err| return unexpectedError(err), } } @@ -1747,12 +1747,12 @@ pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) Ge return buf_ptr[0..rc :0]; } -pub const TerminateProcessError = error{ PermissionDenied, Unexpected }; +pub const TerminateProcessError = error{ AccessDenied, Unexpected }; pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) TerminateProcessError!void { if (kernel32.TerminateProcess(hProcess, uExitCode) == 0) { switch (GetLastError()) { - Win32Error.ACCESS_DENIED => return error.PermissionDenied, + Win32Error.ACCESS_DENIED => return error.AccessDenied, else => |err| return unexpectedError(err), } } diff --git a/lib/std/posix.zig b/lib/std/posix.zig index f920784ca5..b3e0d37fca 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -4896,10 +4896,7 @@ pub const AccessError = error{ /// Windows. See `fs` for the cross-platform file system API. pub fn access(path: []const u8, mode: u32) AccessError!void { if (native_os == .windows) { - const path_w = windows.sliceToPrefixedFileW(null, path) catch |err| switch (err) { - error.AccessDenied => return error.PermissionDenied, - else => |e| return e, - }; + const path_w = try windows.sliceToPrefixedFileW(null, path); _ = try windows.GetFileAttributesW(path_w.span().ptr); return; } else if (native_os == .wasi and !builtin.link_libc) { @@ -4912,10 +4909,7 @@ pub fn access(path: []const u8, mode: u32) AccessError!void { /// Same as `access` except `path` is null-terminated. pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { if (native_os == .windows) { - const path_w = windows.cStrToPrefixedFileW(null, path) catch |err| switch (err) { - error.AccessDenied => return error.PermissionDenied, - else => |e| return e, - }; + const path_w = try windows.cStrToPrefixedFileW(null, path); _ = try windows.GetFileAttributesW(path_w.span().ptr); return; } else if (native_os == .wasi and !builtin.link_libc) { diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index 8a4cab5e83..39fc74ece8 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -269,7 +269,7 @@ pub fn killWindows(self: *ChildProcess, exit_code: windows.UINT) !Term { } windows.TerminateProcess(self.id, exit_code) catch |err| switch (err) { - error.PermissionDenied => { + error.AccessDenied => { // Usually when TerminateProcess triggers a ACCESS_DENIED error, it // indicates that the process has already exited, but there may be // some rare edge cases where our process handle no longer has the From 02373eb2a59f4a16a06460c244958e236b1c5291 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Tue, 18 Feb 2025 17:16:13 -0800 Subject: [PATCH 2/3] lib/std/: WASI code should follow POSIX semantics for AccessDenied/PermissionDenied Use error.AccessDenied for permissions (rights) failures on Wasi (`EACCES`) and error.PermissionDenied (`EPERM`) for systemic failures. And pass-through underlying Wasi errors (PermissionDenied or AccessDenied) without mapping. --- lib/std/fs/test.zig | 2 +- lib/std/posix.zig | 25 ++++++++++--------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 546435f4ab..093c05fe33 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -383,7 +383,7 @@ test "openDirAbsolute" { test "openDir cwd parent '..'" { var dir = fs.cwd().openDir("..", .{}) catch |err| { - if (native_os == .wasi and err == error.AccessDenied) { + if (native_os == .wasi and err == error.PermissionDenied) { return; // This is okay. WASI disallows escaping from the fs sandbox } return err; diff --git a/lib/std/posix.zig b/lib/std/posix.zig index b3e0d37fca..cab0ce0ef0 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -1740,7 +1740,7 @@ pub fn openatWasi( .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .EXIST => return error.PathAlreadyExists, .BUSY => return error.DeviceBusy, .NOTCAPABLE => return error.AccessDenied, @@ -2178,7 +2178,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c .INVAL => unreachable, .BADF => unreachable, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .DQUOT => return error.DiskQuota, .EXIST => return error.PathAlreadyExists, .IO => return error.FileSystem, @@ -2502,7 +2502,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro switch (res) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .FAULT => unreachable, .IO => return error.FileSystem, @@ -2698,7 +2698,7 @@ fn renameatWasi(old: RelativePathWasi, new: RelativePathWasi) RenameError!void { switch (wasi.path_rename(old.dir_fd, old.relative_path.ptr, old.relative_path.len, new.dir_fd, new.relative_path.ptr, new.relative_path.len)) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .DQUOT => return error.DiskQuota, .FAULT => unreachable, @@ -2903,7 +2903,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDir .SUCCESS => return, .ACCES => return error.AccessDenied, .BADF => unreachable, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .DQUOT => return error.DiskQuota, .EXIST => return error.PathAlreadyExists, .FAULT => unreachable, @@ -4952,19 +4952,14 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr } else if (native_os == .wasi and !builtin.link_libc) { const resolved: RelativePathWasi = .{ .dir_fd = dirfd, .relative_path = path }; - const st = blk: { - break :blk std.os.fstatat_wasi(dirfd, path, .{ - .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0, - }); - } catch |err| switch (err) { - error.AccessDenied => return error.PermissionDenied, - else => |e| return e, - }; + const st = try std.os.fstatat_wasi(dirfd, path, .{ + .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0, + }); if (mode != F_OK) { var directory: wasi.fdstat_t = undefined; if (wasi.fd_fdstat_get(resolved.dir_fd, &directory) != .SUCCESS) { - return error.PermissionDenied; + return error.AccessDenied; } var rights: wasi.rights_t = .{}; @@ -4984,7 +4979,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr const rights_int: u64 = @bitCast(rights); const inheriting_int: u64 = @bitCast(directory.fs_rights_inheriting); if ((rights_int & inheriting_int) != rights_int) { - return error.PermissionDenied; + return error.AccessDenied; } } return; From 14c046fc0728070c575c0e849b7be649cbb2b9a0 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Tue, 18 Feb 2025 17:18:03 -0800 Subject: [PATCH 3/3] lib/std: PermissionDenied/AccessDenied cleanup and fallout This PR consistently maps .ACCES into AccessDenied and .PERM into PermissionDenied. AccessDenied is returned if the file mode bit (user/group/other rwx bits) disallow access (errno was `EACCES`). PermissionDenied is returned if something else denies access (errno was `EPERM`) (immutable bit, SELinux, capabilities, etc). This somewhat subtle distinction is a POSIX thing. Most of the change is updating std.posix Error Sets to contain both errors, and then propagating the pair up through caller Error Sets. Fixes #16782 --- lib/std/fs/Dir.zig | 25 ++++++--- lib/std/io/c_writer.zig | 2 +- lib/std/os.zig | 2 +- lib/std/os/linux/bpf.zig | 12 ++--- lib/std/posix.zig | 106 ++++++++++++++++++++++----------------- lib/std/zig/system.zig | 4 ++ src/DarwinPosixSpawn.zig | 3 +- 7 files changed, 93 insertions(+), 61 deletions(-) diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig index a863eda3f9..3d869d9b59 100644 --- a/lib/std/fs/Dir.zig +++ b/lib/std/fs/Dir.zig @@ -247,7 +247,7 @@ pub const Iterator = switch (native_os) { .NOTDIR => unreachable, .INVAL => unreachable, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return posix.unexpectedErrno(err), } self.first_iter = false; @@ -267,7 +267,7 @@ pub const Iterator = switch (native_os) { .INVAL => unreachable, .OVERFLOW => unreachable, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return posix.unexpectedErrno(err), } } @@ -294,7 +294,7 @@ pub const Iterator = switch (native_os) { .BADF => unreachable, // Dir is invalid .NOMEM => return error.SystemResources, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .FAULT => unreachable, .NAMETOOLONG => unreachable, .LOOP => unreachable, @@ -768,6 +768,7 @@ pub const OpenError = error{ FileNotFound, NotDir, AccessDenied, + PermissionDenied, SymLinkLoop, ProcessFdQuotaExceeded, NameTooLong, @@ -1503,7 +1504,7 @@ pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenOptions) OpenErr .NOENT => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOTDIR => return error.NotDir, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.DeviceBusy, else => |err| return posix.unexpectedErrno(err), } @@ -1652,9 +1653,9 @@ pub fn deleteFile(self: Dir, sub_path: []const u8) DeleteFileError!void { pub fn deleteFileZ(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void { posix.unlinkatZ(self.fd, sub_path_c, 0) catch |err| switch (err) { error.DirNotEmpty => unreachable, // not passing AT.REMOVEDIR - error.AccessDenied => |e| switch (native_os) { - // non-Linux POSIX systems return EPERM when trying to delete a directory, so - // we need to handle that case specifically and translate the error + error.AccessDenied, error.PermissionDenied => |e| switch (native_os) { + // non-Linux POSIX systems return permission errors when trying to delete a + // directory, so we need to handle that case specifically and translate the error .macos, .ios, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris, .illumos => { // Don't follow symlinks to match unlinkat (which acts on symlinks rather than follows them) const fstat = posix.fstatatZ(self.fd, sub_path_c, posix.AT.SYMLINK_NOFOLLOW) catch return e; @@ -1679,6 +1680,7 @@ pub const DeleteDirError = error{ DirNotEmpty, FileNotFound, AccessDenied, + PermissionDenied, FileBusy, FileSystem, SymLinkLoop, @@ -1991,6 +1993,7 @@ pub fn readFileAllocOptions( pub const DeleteTreeError = error{ AccessDenied, + PermissionDenied, FileTooBig, SymLinkLoop, ProcessFdQuotaExceeded, @@ -2073,6 +2076,7 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void { }, error.AccessDenied, + error.PermissionDenied, error.SymLinkLoop, error.ProcessFdQuotaExceeded, error.NameTooLong, @@ -2112,6 +2116,7 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void { }, error.AccessDenied, + error.PermissionDenied, error.InvalidUtf8, error.InvalidWtf8, error.SymLinkLoop, @@ -2168,6 +2173,7 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void { }, error.AccessDenied, + error.PermissionDenied, error.SymLinkLoop, error.ProcessFdQuotaExceeded, error.NameTooLong, @@ -2197,6 +2203,7 @@ pub fn deleteTree(self: Dir, sub_path: []const u8) DeleteTreeError!void { }, error.AccessDenied, + error.PermissionDenied, error.InvalidUtf8, error.InvalidWtf8, error.SymLinkLoop, @@ -2273,6 +2280,7 @@ fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint }, error.AccessDenied, + error.PermissionDenied, error.SymLinkLoop, error.ProcessFdQuotaExceeded, error.NameTooLong, @@ -2309,6 +2317,7 @@ fn deleteTreeMinStackSizeWithKindHint(self: Dir, sub_path: []const u8, kind_hint }, error.AccessDenied, + error.PermissionDenied, error.InvalidUtf8, error.InvalidWtf8, error.SymLinkLoop, @@ -2371,6 +2380,7 @@ fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File }, error.AccessDenied, + error.PermissionDenied, error.SymLinkLoop, error.ProcessFdQuotaExceeded, error.NameTooLong, @@ -2397,6 +2407,7 @@ fn deleteTreeOpenInitialSubpath(self: Dir, sub_path: []const u8, kind_hint: File }, error.AccessDenied, + error.PermissionDenied, error.InvalidUtf8, error.InvalidWtf8, error.SymLinkLoop, diff --git a/lib/std/io/c_writer.zig b/lib/std/io/c_writer.zig index cbe4e7834d..8c25e51029 100644 --- a/lib/std/io/c_writer.zig +++ b/lib/std/io/c_writer.zig @@ -23,7 +23,7 @@ fn cWriterWrite(c_file: *std.c.FILE, bytes: []const u8) std.fs.File.WriteError!u .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, else => |err| return std.posix.unexpectedErrno(err), } diff --git a/lib/std/os.zig b/lib/std/os.zig index 45568caf3c..3e9ec49e6e 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -65,7 +65,7 @@ pub fn accessW(path: [*:0]const u16) windows.GetFileAttributesError!void { switch (windows.GetLastError()) { .FILE_NOT_FOUND => return error.FileNotFound, .PATH_NOT_FOUND => return error.FileNotFound, - .ACCESS_DENIED => return error.PermissionDenied, + .ACCESS_DENIED => return error.AccessDenied, else => |err| return windows.unexpectedError(err), } } diff --git a/lib/std/os/linux/bpf.zig b/lib/std/os/linux/bpf.zig index f35ccf4f1a..86bc071030 100644 --- a/lib/std/os/linux/bpf.zig +++ b/lib/std/os/linux/bpf.zig @@ -1548,7 +1548,7 @@ pub fn map_create(map_type: MapType, key_size: u32, value_size: u32, max_entries .SUCCESS => return @as(fd_t, @intCast(rc)), .INVAL => return error.MapTypeOrAttrInvalid, .NOMEM => return error.SystemResources, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return unexpectedErrno(err), } } @@ -1574,7 +1574,7 @@ pub fn map_lookup_elem(fd: fd_t, key: []const u8, value: []u8) !void { .FAULT => unreachable, .INVAL => return error.FieldInAttrNeedsZeroing, .NOENT => return error.NotFound, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return unexpectedErrno(err), } } @@ -1597,7 +1597,7 @@ pub fn map_update_elem(fd: fd_t, key: []const u8, value: []const u8, flags: u64) .FAULT => unreachable, .INVAL => return error.FieldInAttrNeedsZeroing, .NOMEM => return error.SystemResources, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return unexpectedErrno(err), } } @@ -1617,7 +1617,7 @@ pub fn map_delete_elem(fd: fd_t, key: []const u8) !void { .FAULT => unreachable, .INVAL => return error.FieldInAttrNeedsZeroing, .NOENT => return error.NotFound, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return unexpectedErrno(err), } } @@ -1638,7 +1638,7 @@ pub fn map_get_next_key(fd: fd_t, key: []const u8, next_key: []u8) !bool { .FAULT => unreachable, .INVAL => return error.FieldInAttrNeedsZeroing, .NOENT => return false, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return unexpectedErrno(err), } } @@ -1712,7 +1712,7 @@ pub fn prog_load( .ACCES => error.UnsafeProgram, .FAULT => unreachable, .INVAL => error.InvalidProgram, - .PERM => error.AccessDenied, + .PERM => error.PermissionDenied, else => |err| unexpectedErrno(err), }; } diff --git a/lib/std/posix.zig b/lib/std/posix.zig index cab0ce0ef0..7c243f7b01 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -281,6 +281,7 @@ pub fn close(fd: fd_t) void { pub const FChmodError = error{ AccessDenied, + PermissionDenied, InputOutput, SymLinkLoop, FileNotFound, @@ -310,7 +311,7 @@ pub fn fchmod(fd: fd_t, mode: mode_t) FChmodError!void { .NOENT => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOTDIR => return error.FileNotFound, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, else => |err| return unexpectedErrno(err), } @@ -387,7 +388,7 @@ fn fchmodat1(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr .NOTDIR => return error.FileNotFound, .NOMEM => return error.SystemResources, .OPNOTSUPP => return error.OperationNotSupported, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, else => |err| return unexpectedErrno(err), } @@ -418,7 +419,7 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr .NOMEM => return error.SystemResources, .NOTDIR => return error.FileNotFound, .OPNOTSUPP => return error.OperationNotSupported, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, .NOSYS => { @@ -447,7 +448,7 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr .FAULT => unreachable, .INVAL => unreachable, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .LOOP => return error.SymLinkLoop, .MFILE => return error.ProcessFdQuotaExceeded, .NAMETOOLONG => return error.NameTooLong, @@ -486,7 +487,7 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr .LOOP => return error.SymLinkLoop, .NOMEM => return error.SystemResources, .NOTDIR => return error.FileNotFound, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, else => |err| return unexpectedErrno(err), } @@ -495,6 +496,7 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr pub const FChownError = error{ AccessDenied, + PermissionDenied, InputOutput, SymLinkLoop, FileNotFound, @@ -529,7 +531,7 @@ pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void { .NOENT => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOTDIR => return error.FileNotFound, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, else => |err| return unexpectedErrno(err), } @@ -1031,10 +1033,8 @@ pub const TruncateError = error{ FileTooBig, InputOutput, FileBusy, - - /// In WASI, this error occurs when the file descriptor does - /// not hold the required rights to call `ftruncate` on it. AccessDenied, + PermissionDenied, } || UnexpectedError; pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { @@ -1066,7 +1066,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { .INTR => unreachable, .FBIG => return error.FileTooBig, .IO => return error.InputOutput, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .TXTBSY => return error.FileBusy, .BADF => unreachable, // Handle not open for writing .INVAL => unreachable, // Handle not open for writing @@ -1082,7 +1082,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { .INTR => continue, .FBIG => return error.FileTooBig, .IO => return error.InputOutput, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .TXTBSY => return error.FileBusy, .BADF => unreachable, // Handle not open for writing .INVAL => unreachable, // Handle not open for writing @@ -1176,6 +1176,7 @@ pub const WriteError = error{ /// File descriptor does not hold the required rights to write to it. AccessDenied, + PermissionDenied, BrokenPipe, SystemResources, OperationAborted, @@ -1250,7 +1251,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .NOTCAPABLE => return error.AccessDenied, else => |err| return unexpectedErrno(err), @@ -1278,7 +1279,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .CONNRESET => return error.ConnectionResetByPeer, .BUSY => return error.DeviceBusy, @@ -1331,7 +1332,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .NOTCAPABLE => return error.AccessDenied, else => |err| return unexpectedErrno(err), @@ -1353,7 +1354,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .CONNRESET => return error.ConnectionResetByPeer, .BUSY => return error.DeviceBusy, @@ -1410,7 +1411,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .NXIO => return error.Unseekable, .SPIPE => return error.Unseekable, @@ -1443,7 +1444,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .NXIO => return error.Unseekable, .SPIPE => return error.Unseekable, @@ -1502,7 +1503,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .NXIO => return error.Unseekable, .SPIPE => return error.Unseekable, @@ -1528,7 +1529,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz .FBIG => return error.FileTooBig, .IO => return error.InputOutput, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .PIPE => return error.BrokenPipe, .NXIO => return error.Unseekable, .SPIPE => return error.Unseekable, @@ -1543,6 +1544,7 @@ pub const OpenError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to open a new resource relative to it. AccessDenied, + PermissionDenied, SymLinkLoop, ProcessFdQuotaExceeded, SystemFdQuotaExceeded, @@ -1660,7 +1662,7 @@ pub fn openZ(file_path: [*:0]const u8, flags: O, perm: mode_t) OpenError!fd_t { .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .EXIST => return error.PathAlreadyExists, .BUSY => return error.DeviceBusy, .ILSEQ => |err| if (native_os == .wasi) @@ -1831,7 +1833,7 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: O, mode: mode_t) O .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .EXIST => return error.PathAlreadyExists, .BUSY => return error.DeviceBusy, .OPNOTSUPP => return error.FileLocksNotSupported, @@ -1873,6 +1875,7 @@ pub fn dup2(old_fd: fd_t, new_fd: fd_t) !void { pub const ExecveError = error{ SystemResources, AccessDenied, + PermissionDenied, InvalidExe, FileSystem, IsDir, @@ -1899,7 +1902,7 @@ pub fn execveZ( .NFILE => return error.SystemFdQuotaExceeded, .NOMEM => return error.SystemResources, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .INVAL => return error.InvalidExe, .NOEXEC => return error.InvalidExe, .IO => return error.FileSystem, @@ -2077,6 +2080,7 @@ pub const SymLinkError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to create a new symbolic link relative to it. AccessDenied, + PermissionDenied, DiskQuota, PathAlreadyExists, FileSystem, @@ -2130,7 +2134,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin .FAULT => unreachable, .INVAL => unreachable, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .DQUOT => return error.DiskQuota, .EXIST => return error.PathAlreadyExists, .IO => return error.FileSystem, @@ -2208,7 +2212,7 @@ pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*: .FAULT => unreachable, .INVAL => unreachable, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .DQUOT => return error.DiskQuota, .EXIST => return error.PathAlreadyExists, .IO => return error.FileSystem, @@ -2229,6 +2233,7 @@ pub fn symlinkatZ(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*: pub const LinkError = UnexpectedError || error{ AccessDenied, + PermissionDenied, DiskQuota, PathAlreadyExists, FileSystem, @@ -2264,7 +2269,7 @@ pub fn linkZ(oldpath: [*:0]const u8, newpath: [*:0]const u8) LinkError!void { .NOENT => return error.FileNotFound, .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.NotSameFileSystem, .INVAL => unreachable, @@ -2318,7 +2323,7 @@ pub fn linkatZ( .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.NotSameFileSystem, .INVAL => unreachable, @@ -2367,7 +2372,7 @@ pub fn linkat( .NOMEM => return error.SystemResources, .NOSPC => return error.NoSpaceLeft, .NOTDIR => return error.NotDir, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, .XDEV => return error.NotSameFileSystem, .INVAL => unreachable, @@ -2386,6 +2391,7 @@ pub const UnlinkError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to unlink a resource by path relative to it. AccessDenied, + PermissionDenied, FileBusy, FileSystem, IsDir, @@ -2441,7 +2447,7 @@ pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void { switch (errno(system.unlink(file_path))) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .FAULT => unreachable, .INVAL => unreachable, @@ -2535,7 +2541,7 @@ pub fn unlinkatZ(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatEr switch (errno(system.unlinkat(dirfd, file_path_c, flags))) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .FAULT => unreachable, .IO => return error.FileSystem, @@ -2573,6 +2579,7 @@ pub const RenameError = error{ /// On Windows, this error may be returned instead of PathAlreadyExists when /// renaming a directory over an existing directory. AccessDenied, + PermissionDenied, FileBusy, DiskQuota, IsDir, @@ -2635,7 +2642,7 @@ pub fn renameZ(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!voi switch (errno(system.rename(old_path, new_path))) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .DQUOT => return error.DiskQuota, .FAULT => unreachable, @@ -2750,7 +2757,7 @@ pub fn renameatZ( switch (errno(system.renameat(old_dir_fd, old_path, new_dir_fd, new_path))) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .DQUOT => return error.DiskQuota, .FAULT => unreachable, @@ -2933,7 +2940,7 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: mode_t) MakeDir .SUCCESS => return, .ACCES => return error.AccessDenied, .BADF => unreachable, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .DQUOT => return error.DiskQuota, .EXIST => return error.PathAlreadyExists, .FAULT => unreachable, @@ -2978,6 +2985,7 @@ pub const MakeDirError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to create a new directory relative to it. AccessDenied, + PermissionDenied, DiskQuota, PathAlreadyExists, SymLinkLoop, @@ -3030,7 +3038,7 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: mode_t) MakeDirError!void { switch (errno(system.mkdir(dir_path, mode))) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .DQUOT => return error.DiskQuota, .EXIST => return error.PathAlreadyExists, .FAULT => unreachable, @@ -3071,6 +3079,7 @@ pub fn mkdirW(dir_path_w: []const u16, mode: mode_t) MakeDirError!void { pub const DeleteDirError = error{ AccessDenied, + PermissionDenied, FileBusy, SymLinkLoop, NameTooLong, @@ -3123,7 +3132,7 @@ pub fn rmdirZ(dir_path: [*:0]const u8) DeleteDirError!void { switch (errno(system.rmdir(dir_path))) { .SUCCESS => return, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .BUSY => return error.FileBusy, .FAULT => unreachable, .INVAL => return error.BadPathName, @@ -3254,6 +3263,7 @@ pub const ReadLinkError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to read value of a symbolic link relative to it. AccessDenied, + PermissionDenied, FileSystem, SymLinkLoop, NameTooLong, @@ -3534,7 +3544,7 @@ pub fn isatty(handle: fd_t) bool { pub const SocketError = error{ /// Permission to create a socket of the specified type and/or /// pro‐tocol is denied. - PermissionDenied, + AccessDenied, /// The implementation does not support the specified address family. AddressFamilyNotSupported, @@ -3604,7 +3614,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t } return fd; }, - .ACCES => return error.PermissionDenied, + .ACCES => return error.AccessDenied, .AFNOSUPPORT => return error.AddressFamilyNotSupported, .INVAL => return error.ProtocolFamilyNotAvailable, .MFILE => return error.ProcessFdQuotaExceeded, @@ -4188,6 +4198,9 @@ pub const ConnectError = error{ /// or /// The user tried to connect to a broadcast address without having the socket broadcast flag enabled or /// the connection request failed because of a local firewall rule. + AccessDenied, + + /// See AccessDenied PermissionDenied, /// Local address is already in use. @@ -4261,7 +4274,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne while (true) { switch (errno(system.connect(sock, sock_addr, len))) { .SUCCESS => return, - .ACCES => return error.PermissionDenied, + .ACCES => return error.AccessDenied, .PERM => return error.PermissionDenied, .ADDRINUSE => return error.AddressInUse, .ADDRNOTAVAIL => return error.AddressNotAvailable, @@ -4323,7 +4336,7 @@ pub fn getsockoptError(sockfd: fd_t) ConnectError!void { switch (errno(rc)) { .SUCCESS => switch (@as(E, @enumFromInt(err_code))) { .SUCCESS => return, - .ACCES => return error.PermissionDenied, + .ACCES => return error.AccessDenied, .PERM => return error.PermissionDenied, .ADDRINUSE => return error.AddressInUse, .ADDRNOTAVAIL => return error.AddressNotAvailable, @@ -4398,6 +4411,7 @@ pub const FStatError = error{ /// In WASI, this error may occur when the file descriptor does /// not hold the required rights to get its filestat information. AccessDenied, + PermissionDenied, } || UnexpectedError; /// Return information about a file descriptor. @@ -4466,7 +4480,7 @@ pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!S .BADF => unreachable, // Always a race condition. .NOMEM => return error.SystemResources, .ACCES => return error.AccessDenied, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, .FAULT => unreachable, .NAMETOOLONG => return error.NameTooLong, .LOOP => return error.SymLinkLoop, @@ -4870,6 +4884,7 @@ pub fn msync(memory: []align(page_size_min) u8, flags: i32) MSyncError!void { } pub const AccessError = error{ + AccessDenied, PermissionDenied, FileNotFound, NameTooLong, @@ -4917,7 +4932,7 @@ pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { } switch (errno(system.access(path, mode))) { .SUCCESS => return, - .ACCES => return error.PermissionDenied, + .ACCES => return error.AccessDenied, .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, .LOOP => return error.SymLinkLoop, @@ -4998,7 +5013,7 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces } switch (errno(system.faccessat(dirfd, path, mode, flags))) { .SUCCESS => return, - .ACCES => return error.PermissionDenied, + .ACCES => return error.AccessDenied, .PERM => return error.PermissionDenied, .ROFS => return error.ReadOnlyFileSystem, .LOOP => return error.SymLinkLoop, @@ -5049,7 +5064,7 @@ pub fn faccessatW(dirfd: fd_t, sub_path_w: [*:0]const u16) AccessError!void { .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, .OBJECT_NAME_INVALID => unreachable, .INVALID_PARAMETER => unreachable, - .ACCESS_DENIED => return error.PermissionDenied, + .ACCESS_DENIED => return error.AccessDenied, .OBJECT_PATH_SYNTAX_BAD => unreachable, else => |rc| return windows.unexpectedStatus(rc), } @@ -5431,6 +5446,7 @@ pub fn flock(fd: fd_t, operation: i32) FlockError!void { pub const RealPathError = error{ FileNotFound, AccessDenied, + PermissionDenied, NameTooLong, NotSupported, NotDir, @@ -6812,7 +6828,7 @@ pub const SetSockOptError = error{ /// Insufficient resources are available in the system to complete the call. SystemResources, - // Setting the socket option requires more elevated permissions. + /// Setting the socket option requires more elevated permissions. PermissionDenied, OperationNotSupported, @@ -7307,7 +7323,7 @@ pub fn perf_event_open( } pub const TimerFdCreateError = error{ - AccessDenied, + PermissionDenied, ProcessFdQuotaExceeded, SystemFdQuotaExceeded, NoDevice, @@ -7326,7 +7342,7 @@ pub fn timerfd_create(clock_id: system.timerfd_clockid_t, flags: system.TFD) Tim .NFILE => return error.SystemFdQuotaExceeded, .NODEV => return error.NoDevice, .NOMEM => return error.SystemResources, - .PERM => return error.AccessDenied, + .PERM => return error.PermissionDenied, else => |err| return unexpectedErrno(err), }; } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index a4b16d6c46..3bc815eb87 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -731,6 +731,7 @@ pub fn abiAndDynamicLinkerFromFile( error.NetworkNotFound => unreachable, // Windows only error.AccessDenied, + error.PermissionDenied, error.FileNotFound, error.NotLink, error.NotDir, @@ -825,6 +826,7 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion { error.FileNotFound, error.NotDir, error.AccessDenied, + error.PermissionDenied, error.NoDevice, => return error.GLibCNotFound, @@ -863,6 +865,7 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion { error.NoDevice => unreachable, // not asking for a special device error.AccessDenied, + error.PermissionDenied, error.FileNotFound, error.NotDir, error.IsDir, @@ -1122,6 +1125,7 @@ fn detectAbiAndDynamicLinker( error.IsDir, error.NotDir, error.AccessDenied, + error.PermissionDenied, error.NoDevice, error.FileNotFound, error.NetworkNotFound, diff --git a/src/DarwinPosixSpawn.zig b/src/DarwinPosixSpawn.zig index aaf2df6ec3..0743eb0c66 100644 --- a/src/DarwinPosixSpawn.zig +++ b/src/DarwinPosixSpawn.zig @@ -6,6 +6,7 @@ pub const Error = error{ InvalidFileDescriptor, NameTooLong, TooBig, + AccessDenied, PermissionDenied, InputOutput, FileSystem, @@ -188,7 +189,7 @@ pub fn spawnZ( .@"2BIG" => return error.TooBig, .NOMEM => return error.SystemResources, .BADF => return error.InvalidFileDescriptor, - .ACCES => return error.PermissionDenied, + .ACCES => return error.AccessDenied, .IO => return error.InputOutput, .LOOP => return error.FileSystem, .NAMETOOLONG => return error.NameTooLong,