authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-06-18 10:27:37+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-20 16:54:39-07:00
logb72d55ea5fa1de0c55e2cfb9aa65f4ec80986bc9
tree2e4c355f3e4f9e0c6a2ea6b9b0cd5cb1de02049c
parentc7dd3cc5350b56a5afbaec89916f0799b4e017e1

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
...@@ -5532,10 +5532,7 @@ pub const CopyFileRangeError = error{...@@ -5532,10 +5532,7 @@ pub const CopyFileRangeError = error{
5532 FileBusy,5532 FileBusy,
5533} || PReadError || PWriteError || UnexpectedError;5533} || PReadError || PWriteError || UnexpectedError;
55345534
5535var has_copy_file_range_syscall = init: {5535var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
5536 const kernel_has_syscall = std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true;
5537 break :init std.atomic.Atomic(bool).init(kernel_has_syscall);
5538};
55395536
5540/// Transfer data between file descriptors at specified offsets.5537/// Transfer data between file descriptors at specified offsets.
5541/// Returns the number of bytes written, which can less than requested.5538/// Returns the number of bytes written, which can less than requested.
...@@ -5563,18 +5560,17 @@ var has_copy_file_range_syscall = init: {...@@ -5563,18 +5560,17 @@ var has_copy_file_range_syscall = init: {
5563///5560///
5564/// Maximum offsets on Linux are `math.maxInt(i64)`.5561/// Maximum offsets on Linux are `math.maxInt(i64)`.
5565pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {5562pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {
5566 const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok;5563 const call_cfr = comptime if (builtin.link_libc)
55675564 std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok
5568 if (std.Target.current.os.tag == .linux and5565 else
5569 (use_c or has_copy_file_range_syscall.load(.Monotonic)))5566 std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true;
5570 {
5571 const sys = if (use_c) std.c else linux;
55725567
5568 if (call_cfr and has_copy_file_range_syscall.load(.Monotonic)) {
5573 var off_in_copy = @bitCast(i64, off_in);5569 var off_in_copy = @bitCast(i64, off_in);
5574 var off_out_copy = @bitCast(i64, off_out);5570 var off_out_copy = @bitCast(i64, off_out);
55755571
5576 const rc = sys.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);5572 const rc = system.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);
5577 switch (sys.getErrno(rc)) {5573 switch (system.getErrno(rc)) {
5578 0 => return @intCast(usize, rc),5574 0 => return @intCast(usize, rc),
5579 EBADF => return error.FilesOpenedWithWrongFlags,5575 EBADF => return error.FilesOpenedWithWrongFlags,
5580 EFBIG => return error.FileTooBig,5576 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...@@ -5591,7 +5587,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len
5591 EXDEV => {},5587 EXDEV => {},
5592 // syscall added in Linux 4.5, use fallback5588 // syscall added in Linux 4.5, use fallback
5593 ENOSYS => {5589 ENOSYS => {
5594 has_copy_file_range_syscall.store(true, .Monotonic);5590 has_copy_file_range_syscall.store(false, .Monotonic);
5595 },5591 },
5596 else => |err| return unexpectedErrno(err),5592 else => |err| return unexpectedErrno(err),
5597 }5593 }