authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-06-18 10:27:37+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-20 20:58:10+03:00
loge4225ca5f76760568c632d1f1c455e9d8759dce1
treeb40a3d748704ab3b2cbdec34abd6a8ef38fd3f45
parent6de45c826c39ecd2d39deed20fd426240c496402

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

1 files changed, 9 insertions(+), 13 deletions(-)

lib/std/os.zig+9-13
......@@ -5542,10 +5542,7 @@ pub const CopyFileRangeError = error{
55425542 FileBusy,
55435543} || PReadError || PWriteError || UnexpectedError;
55445544
5545var has_copy_file_range_syscall = init: {
5546 const kernel_has_syscall = std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true;
5547 break :init std.atomic.Atomic(bool).init(kernel_has_syscall);
5548};
5545var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
55495546
55505547/// Transfer data between file descriptors at specified offsets.
55515548/// Returns the number of bytes written, which can less than requested.
......@@ -5573,18 +5570,17 @@ var has_copy_file_range_syscall = init: {
55735570///
55745571/// Maximum offsets on Linux are `math.maxInt(i64)`.
55755572pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {
5576 const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok;
5577
5578 if (std.Target.current.os.tag == .linux and
5579 (use_c or has_copy_file_range_syscall.load(.Monotonic)))
5580 {
5581 const sys = if (use_c) std.c else linux;
5573 const call_cfr = comptime if (builtin.link_libc)
5574 std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok
5575 else
5576 std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true;
55825577
5578 if (call_cfr and has_copy_file_range_syscall.load(.Monotonic)) {
55835579 var off_in_copy = @bitCast(i64, off_in);
55845580 var off_out_copy = @bitCast(i64, off_out);
55855581
5586 const rc = sys.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);
5587 switch (sys.getErrno(rc)) {
5582 const rc = system.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);
5583 switch (system.getErrno(rc)) {
55885584 0 => return @intCast(usize, rc),
55895585 EBADF => return error.FilesOpenedWithWrongFlags,
55905586 EFBIG => return error.FileTooBig,
......@@ -5601,7 +5597,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len
56015597 EXDEV => {},
56025598 // syscall added in Linux 4.5, use fallback
56035599 ENOSYS => {
5604 has_copy_file_range_syscall.store(true, .Monotonic);
5600 has_copy_file_range_syscall.store(false, .Monotonic);
56055601 },
56065602 else => |err| return unexpectedErrno(err),
56075603 }