diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 0ec059dc8795..db7a66689f4c 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1238,11 +1238,15 @@ pub fn access(path: [*:0]const u8, mode: u32) usize { if (@hasField(SYS, "access")) { return syscall2(.access, @intFromPtr(path), mode); } else { - return syscall4(.faccessat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(path), mode, 0); + return faccessat(AT.FDCWD, path, mode); } } -pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { +pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32) usize { + return syscall3(.faccessat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode); +} + +pub fn faccessat2(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { return syscall4(.faccessat2, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode, flags); } diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 90ab157f0c20..69cacf801084 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -5054,7 +5054,22 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces } else if (native_os == .wasi and !builtin.link_libc) { return faccessat(dirfd, mem.sliceTo(path, 0), mode, flags); } - switch (errno(system.faccessat(dirfd, path, mode, flags))) { + + const flags_unsupported = switch (system) { + linux => (builtin.abi.isAndroid() //standard android programs run in a seccomp sandbox that seems to trigger signal 31 (SIGSYS) for faccessat2 + or builtin.target.os.isAtLeast(.linux, .{ .major = 5, .minor = 8, .patch = 0 }) != true), //faccessat2 was introduced in Linux 5.8 + else => false, + }; + const need_flags = (flags != 0); + if (need_flags and flags_unsupported) return error.UnsupportedFlags; + const faccessat_result = switch (system) { + linux => if (need_flags) //the older, simpler syscall should stay supported, so we only need to use faccessat2 if we need flags + linux.faccessat2(dirfd, path, mode, flags) + else + linux.faccessat(dirfd, path, mode), + else => system.faccessat(dirfd, path, mode, flags), + }; + switch (errno(faccessat_result)) { .SUCCESS => return, .ACCES => return error.AccessDenied, .PERM => return error.PermissionDenied, @@ -5072,6 +5087,10 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces return error.InvalidUtf8 else return unexpectedErrno(err), + .NOSYS => |err| if (system == linux) + return error.UnsupportedFlags + else + return unexpectedErrno(err), else => |err| return unexpectedErrno(err), } }