From b72d55ea5fa1de0c55e2cfb9aa65f4ec80986bc9 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 18 Jun 2021 10:27:37 +0200 Subject: [PATCH] std: Make copy_file_range checks run at compile-time * Avoid emitting the copy_file_range symbol at all to prevent link-time errors. * Fix a bug in the check logic, the has_copy_file_range_syscall was set to the wrong value in case of ENOSYS * If link_libc is true don't fall-back to the raw syscall approach, there's no policy about what to do in this case but let's follow what the other impls do. Fixes #9146 --- lib/std/os.zig | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 072771b000..321c44a919 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -5532,10 +5532,7 @@ pub const CopyFileRangeError = error{ FileBusy, } || PReadError || PWriteError || UnexpectedError; -var has_copy_file_range_syscall = init: { - const kernel_has_syscall = std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true; - break :init std.atomic.Atomic(bool).init(kernel_has_syscall); -}; +var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true); /// Transfer data between file descriptors at specified offsets. /// Returns the number of bytes written, which can less than requested. @@ -5563,18 +5560,17 @@ var has_copy_file_range_syscall = init: { /// /// Maximum offsets on Linux are `math.maxInt(i64)`. pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize { - const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok; - - if (std.Target.current.os.tag == .linux and - (use_c or has_copy_file_range_syscall.load(.Monotonic))) - { - const sys = if (use_c) std.c else linux; + const call_cfr = comptime if (builtin.link_libc) + std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok + else + std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true; + if (call_cfr and has_copy_file_range_syscall.load(.Monotonic)) { var off_in_copy = @bitCast(i64, off_in); var off_out_copy = @bitCast(i64, off_out); - const rc = sys.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags); - switch (sys.getErrno(rc)) { + const rc = system.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags); + switch (system.getErrno(rc)) { 0 => return @intCast(usize, rc), EBADF => return error.FilesOpenedWithWrongFlags, EFBIG => return error.FileTooBig, @@ -5591,7 +5587,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len EXDEV => {}, // syscall added in Linux 4.5, use fallback ENOSYS => { - has_copy_file_range_syscall.store(true, .Monotonic); + has_copy_file_range_syscall.store(false, .Monotonic); }, else => |err| return unexpectedErrno(err), }