mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 06:15:21 +00:00
std.os: take advantage of the freebsd's copy_file_range
This commit is contained in:
parent
28288dcbbf
commit
aea617c60b
@ -1440,6 +1440,7 @@ pub const E = enum(u16) {
|
||||
CAPMODE = 94, // Not permitted in capability mode
|
||||
NOTRECOVERABLE = 95, // State not recoverable
|
||||
OWNERDEAD = 96, // Previous owner died
|
||||
INTEGRITY = 97, // Integrity check failed
|
||||
_,
|
||||
};
|
||||
|
||||
@ -1875,3 +1876,4 @@ pub const MFD = struct {
|
||||
};
|
||||
|
||||
pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int;
|
||||
pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*off_t, fd_out: fd_t, off_out: ?*off_t, len: usize, flags: u32) usize;
|
||||
|
||||
@ -6314,6 +6314,7 @@ pub const CopyFileRangeError = error{
|
||||
Unseekable,
|
||||
PermissionDenied,
|
||||
SwapFile,
|
||||
CorruptedData,
|
||||
} || PReadError || PWriteError || UnexpectedError;
|
||||
|
||||
var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
|
||||
@ -6339,44 +6340,56 @@ var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
|
||||
///
|
||||
/// These systems support in-kernel data copying:
|
||||
/// * Linux 4.5 (cross-filesystem 5.3)
|
||||
/// * FreeBSD 13.0
|
||||
///
|
||||
/// Other systems fall back to calling `pread` / `pwrite`.
|
||||
///
|
||||
/// Maximum offsets on Linux are `math.maxInt(i64)`.
|
||||
/// Maximum offsets on Linux and FreeBSD 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 call_cfr = comptime if (builtin.os.tag == .wasi)
|
||||
// WASI-libc doesn't have copy_file_range.
|
||||
false
|
||||
else if (builtin.link_libc)
|
||||
std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok
|
||||
else
|
||||
builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true;
|
||||
|
||||
if (call_cfr and has_copy_file_range_syscall.load(.Monotonic)) {
|
||||
if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0 }) orelse false) or
|
||||
((comptime builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse false and
|
||||
std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok) 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 = system.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);
|
||||
switch (system.getErrno(rc)) {
|
||||
.SUCCESS => return @intCast(usize, rc),
|
||||
.BADF => return error.FilesOpenedWithWrongFlags,
|
||||
.FBIG => return error.FileTooBig,
|
||||
.IO => return error.InputOutput,
|
||||
.ISDIR => return error.IsDir,
|
||||
.NOMEM => return error.OutOfMemory,
|
||||
.NOSPC => return error.NoSpaceLeft,
|
||||
.OVERFLOW => return error.Unseekable,
|
||||
.PERM => return error.PermissionDenied,
|
||||
.TXTBSY => return error.SwapFile,
|
||||
// these may not be regular files, try fallback
|
||||
.INVAL => {},
|
||||
// support for cross-filesystem copy added in Linux 5.3, use fallback
|
||||
.XDEV => {},
|
||||
// syscall added in Linux 4.5, use fallback
|
||||
.NOSYS => {
|
||||
has_copy_file_range_syscall.store(false, .Monotonic);
|
||||
},
|
||||
else => |err| return unexpectedErrno(err),
|
||||
while (true) {
|
||||
const rc = system.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags);
|
||||
if (builtin.os.tag == .freebsd) {
|
||||
switch (system.getErrno(rc)) {
|
||||
.SUCCESS => return @intCast(usize, rc),
|
||||
.BADF => return error.FilesOpenedWithWrongFlags,
|
||||
.FBIG => return error.FileTooBig,
|
||||
.IO => return error.InputOutput,
|
||||
.ISDIR => return error.IsDir,
|
||||
.NOSPC => return error.NoSpaceLeft,
|
||||
.INVAL => break, // these may not be regular files, try fallback
|
||||
.INTEGRITY => return error.CorruptedData,
|
||||
.INTR => continue,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
} else { // assume linux
|
||||
switch (system.getErrno(rc)) {
|
||||
.SUCCESS => return @intCast(usize, rc),
|
||||
.BADF => return error.FilesOpenedWithWrongFlags,
|
||||
.FBIG => return error.FileTooBig,
|
||||
.IO => return error.InputOutput,
|
||||
.ISDIR => return error.IsDir,
|
||||
.NOSPC => return error.NoSpaceLeft,
|
||||
.INVAL => break, // these may not be regular files, try fallback
|
||||
.NOMEM => return error.OutOfMemory,
|
||||
.OVERFLOW => return error.Unseekable,
|
||||
.PERM => return error.PermissionDenied,
|
||||
.TXTBSY => return error.SwapFile,
|
||||
.XDEV => break, // support for cross-filesystem copy added in Linux 5.3, use fallback
|
||||
.NOSYS => { // syscall added in Linux 4.5, use fallback
|
||||
has_copy_file_range_syscall.store(false, .Monotonic);
|
||||
break;
|
||||
},
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -457,6 +457,7 @@ pub const File = struct {
|
||||
Unseekable,
|
||||
PermissionDenied,
|
||||
SwapFile,
|
||||
CorruptedData,
|
||||
SystemResources,
|
||||
OperationAborted,
|
||||
BrokenPipe,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user