-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Closed
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behavioros-linuxLinuxLinuxstandard libraryThis issue involves writing Zig code for the standard library.This issue involves writing Zig code for the standard library.
Milestone
Description
Zig Version
0.11.0-dev.4296+7e25fb4a4
Steps to Reproduce and Observed Behavior
faccessatZ on linux ignores flags because it is using the wrong syscall, faccessat instead of faccessat2 (see here). In the man page
Because the Linux kernel's faccessat() system call does not support a flags argument, the glibc faccessat() wrapper function provided in glibc 2.32 and earlier emulates the required functionality using a com‐ bination of the faccessat() system call and fstatat(2). However, this emulation does not take ACLs into account. Starting with glibc 2.33, the wrapper function avoids this bug by making use of the faccessat2() system call where it is provided by the underlying kernel.
This can be seen in the code below. Created a simple ln --symbolic main.zing src/main2.zig
const std = @import("std");
pub fn main() !void {
// stdout is for the actual output of your application, for example if you
// are implementing gzip, then only the compressed bytes should be sent to
// stdout, not any debugging messages.
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout = bw.writer();
const x = faccessat2Z(std.os.AT.FDCWD, "./src/main2.zig", std.os.X_OK, 0);
try stdout.print("faccessat2 (follow symlink): {!}\n", .{x});
const y = faccessat2Z(std.os.AT.FDCWD, "./src/main2.zig", std.os.X_OK, std.os.AT.SYMLINK_NOFOLLOW);
try stdout.print("faccessat2 (SYMLINK_NOFOLLOW): {!}\n", .{y});
const a = std.os.faccessatZ(std.os.AT.FDCWD, "./src/main2.zig", std.os.X_OK, 0);
try stdout.print("std.os.faccessat (follow symlink): {!}\n", .{a});
const b = std.os.faccessatZ(std.os.AT.FDCWD, "./src/main2.zig", std.os.X_OK, std.os.AT.SYMLINK_NOFOLLOW);
try stdout.print("std.os.faccessat (SYMLINK_NOFOLLOW): {!}\n", .{b});
try bw.flush(); // don't forget to flush!
}
pub fn faccessat2(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize {
return std.os.linux.syscall4(.faccessat2, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode, flags);
}
pub fn faccessat2Z(dirfd: std.os.fd_t, path: [*:0]const u8, mode: u32, flags: u32) std.os.AccessError!void {
switch (std.os.errno(faccessat2(dirfd, path, mode, flags))) {
.SUCCESS => return,
.ACCES => return error.PermissionDenied,
.ROFS => return error.ReadOnlyFileSystem,
.LOOP => return error.SymLinkLoop,
.TXTBSY => return error.FileBusy,
.NOTDIR => return error.FileNotFound,
.NOENT => return error.FileNotFound,
.NAMETOOLONG => return error.NameTooLong,
.INVAL => unreachable,
.FAULT => unreachable,
.IO => return error.InputOutput,
.NOMEM => return error.SystemResources,
else => |err| return std.os.unexpectedErrno(err),
}
}Output: (notice only faccessat2 did not follow the symlink and returned success)
faccessat2 (follow symlink): error.PermissionDenied
faccessat2 (SYMLINK_NOFOLLOW): void
std.os.faccessat (follow symlink): error.PermissionDenied
std.os.faccessat (SYMLINK_NOFOLLOW): error.PermissionDeniedExpected Behavior
The std library should use the faccessat2. If it does not exist can choose to either fallback to faccessat and ignore flags, or also use the emulated fstatat behavior found in glibc.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behavioros-linuxLinuxLinuxstandard libraryThis issue involves writing Zig code for the standard library.This issue involves writing Zig code for the standard library.