@@ -6262,6 +6262,7 @@ pub const CopyFileRangeError = error{
6262
6262
Unseekable ,
6263
6263
PermissionDenied ,
6264
6264
SwapFile ,
6265
+ CorruptedData ,
6265
6266
} || PReadError || PWriteError || UnexpectedError ;
6266
6267
6267
6268
var has_copy_file_range_syscall = std .atomic .Atomic (bool ).init (true );
@@ -6287,44 +6288,56 @@ var has_copy_file_range_syscall = std.atomic.Atomic(bool).init(true);
6287
6288
///
6288
6289
/// These systems support in-kernel data copying:
6289
6290
/// * Linux 4.5 (cross-filesystem 5.3)
6291
+ /// * FreeBSD 13.0
6290
6292
///
6291
6293
/// Other systems fall back to calling `pread` / `pwrite`.
6292
6294
///
6293
- /// Maximum offsets on Linux are `math.maxInt(i64)`.
6295
+ /// Maximum offsets on Linux and FreeBSD are `math.maxInt(i64)`.
6294
6296
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 {
6295
- const call_cfr = comptime if (builtin .os .tag == .wasi )
6296
- // WASI-libc doesn't have copy_file_range.
6297
- false
6298
- else if (builtin .link_libc )
6299
- std .c .versionCheck (.{ .major = 2 , .minor = 27 , .patch = 0 }).ok
6300
- else
6301
- builtin .os .isAtLeast (.linux , .{ .major = 4 , .minor = 5 }) orelse true ;
6302
-
6303
- if (call_cfr and has_copy_file_range_syscall .load (.Monotonic )) {
6297
+ if ((comptime builtin .os .isAtLeast (.freebsd , .{ .major = 13 , .minor = 0 }) orelse false ) or
6298
+ ((comptime builtin .os .isAtLeast (.linux , .{ .major = 4 , .minor = 5 }) orelse false and
6299
+ std .c .versionCheck (.{ .major = 2 , .minor = 27 , .patch = 0 }).ok ) and
6300
+ has_copy_file_range_syscall .load (.Monotonic )))
6301
+ {
6304
6302
var off_in_copy = @bitCast (i64 , off_in );
6305
6303
var off_out_copy = @bitCast (i64 , off_out );
6306
6304
6307
- const rc = system .copy_file_range (fd_in , & off_in_copy , fd_out , & off_out_copy , len , flags );
6308
- switch (system .getErrno (rc )) {
6309
- .SUCCESS = > return @intCast (usize , rc ),
6310
- .BADF = > return error .FilesOpenedWithWrongFlags ,
6311
- .FBIG = > return error .FileTooBig ,
6312
- .IO = > return error .InputOutput ,
6313
- .ISDIR = > return error .IsDir ,
6314
- .NOMEM = > return error .OutOfMemory ,
6315
- .NOSPC = > return error .NoSpaceLeft ,
6316
- .OVERFLOW = > return error .Unseekable ,
6317
- .PERM = > return error .PermissionDenied ,
6318
- .TXTBSY = > return error .SwapFile ,
6319
- // these may not be regular files, try fallback
6320
- .INVAL = > {},
6321
- // support for cross-filesystem copy added in Linux 5.3, use fallback
6322
- .XDEV = > {},
6323
- // syscall added in Linux 4.5, use fallback
6324
- .NOSYS = > {
6325
- has_copy_file_range_syscall .store (false , .Monotonic );
6326
- },
6327
- else = > | err | return unexpectedErrno (err ),
6305
+ while (true ) {
6306
+ const rc = system .copy_file_range (fd_in , & off_in_copy , fd_out , & off_out_copy , len , flags );
6307
+ if (builtin .os .tag == .freebsd ) {
6308
+ switch (system .getErrno (rc )) {
6309
+ .SUCCESS = > return @intCast (usize , rc ),
6310
+ .BADF = > return error .FilesOpenedWithWrongFlags ,
6311
+ .FBIG = > return error .FileTooBig ,
6312
+ .IO = > return error .InputOutput ,
6313
+ .ISDIR = > return error .IsDir ,
6314
+ .NOSPC = > return error .NoSpaceLeft ,
6315
+ .INVAL = > break , // these may not be regular files, try fallback
6316
+ .INTEGRITY = > return error .CorruptedData ,
6317
+ .INTR = > continue ,
6318
+ else = > | err | return unexpectedErrno (err ),
6319
+ }
6320
+ } else { // assume linux
6321
+ switch (system .getErrno (rc )) {
6322
+ .SUCCESS = > return @intCast (usize , rc ),
6323
+ .BADF = > return error .FilesOpenedWithWrongFlags ,
6324
+ .FBIG = > return error .FileTooBig ,
6325
+ .IO = > return error .InputOutput ,
6326
+ .ISDIR = > return error .IsDir ,
6327
+ .NOSPC = > return error .NoSpaceLeft ,
6328
+ .INVAL = > break , // these may not be regular files, try fallback
6329
+ .NOMEM = > return error .OutOfMemory ,
6330
+ .OVERFLOW = > return error .Unseekable ,
6331
+ .PERM = > return error .PermissionDenied ,
6332
+ .TXTBSY = > return error .SwapFile ,
6333
+ .XDEV = > break , // support for cross-filesystem copy added in Linux 5.3, use fallback
6334
+ .NOSYS = > { // syscall added in Linux 4.5, use fallback
6335
+ has_copy_file_range_syscall .store (false , .Monotonic );
6336
+ break ;
6337
+ },
6338
+ else = > | err | return unexpectedErrno (err ),
6339
+ }
6340
+ }
6328
6341
}
6329
6342
}
6330
6343
0 commit comments