@@ -6314,6 +6314,7 @@ pub const CopyFileRangeError = error{
6314
6314
Unseekable ,
6315
6315
PermissionDenied ,
6316
6316
SwapFile ,
6317
+ CorruptedData ,
6317
6318
} || PReadError || PWriteError || UnexpectedError ;
6318
6319
6319
6320
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);
6339
6340
///
6340
6341
/// These systems support in-kernel data copying:
6341
6342
/// * Linux 4.5 (cross-filesystem 5.3)
6343
+ /// * FreeBSD 13.0
6342
6344
///
6343
6345
/// Other systems fall back to calling `pread` / `pwrite`.
6344
6346
///
6345
- /// Maximum offsets on Linux are `math.maxInt(i64)`.
6347
+ /// Maximum offsets on Linux and FreeBSD are `math.maxInt(i64)`.
6346
6348
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 {
6347
- const call_cfr = comptime if (builtin .os .tag == .wasi )
6348
- // WASI-libc doesn't have copy_file_range.
6349
- false
6350
- else if (builtin .link_libc )
6351
- std .c .versionCheck (.{ .major = 2 , .minor = 27 , .patch = 0 }).ok
6352
- else
6353
- builtin .os .isAtLeast (.linux , .{ .major = 4 , .minor = 5 }) orelse true ;
6354
-
6355
- if (call_cfr and has_copy_file_range_syscall .load (.Monotonic )) {
6349
+ if ((comptime builtin .os .isAtLeast (.freebsd , .{ .major = 13 , .minor = 0 }) orelse false ) or
6350
+ ((comptime builtin .os .isAtLeast (.linux , .{ .major = 4 , .minor = 5 }) orelse false and
6351
+ std .c .versionCheck (.{ .major = 2 , .minor = 27 , .patch = 0 }).ok ) and
6352
+ has_copy_file_range_syscall .load (.Monotonic )))
6353
+ {
6356
6354
var off_in_copy = @bitCast (i64 , off_in );
6357
6355
var off_out_copy = @bitCast (i64 , off_out );
6358
6356
6359
- const rc = system .copy_file_range (fd_in , & off_in_copy , fd_out , & off_out_copy , len , flags );
6360
- switch (system .getErrno (rc )) {
6361
- .SUCCESS = > return @intCast (usize , rc ),
6362
- .BADF = > return error .FilesOpenedWithWrongFlags ,
6363
- .FBIG = > return error .FileTooBig ,
6364
- .IO = > return error .InputOutput ,
6365
- .ISDIR = > return error .IsDir ,
6366
- .NOMEM = > return error .OutOfMemory ,
6367
- .NOSPC = > return error .NoSpaceLeft ,
6368
- .OVERFLOW = > return error .Unseekable ,
6369
- .PERM = > return error .PermissionDenied ,
6370
- .TXTBSY = > return error .SwapFile ,
6371
- // these may not be regular files, try fallback
6372
- .INVAL = > {},
6373
- // support for cross-filesystem copy added in Linux 5.3, use fallback
6374
- .XDEV = > {},
6375
- // syscall added in Linux 4.5, use fallback
6376
- .NOSYS = > {
6377
- has_copy_file_range_syscall .store (false , .Monotonic );
6378
- },
6379
- else = > | err | return unexpectedErrno (err ),
6357
+ while (true ) {
6358
+ const rc = system .copy_file_range (fd_in , & off_in_copy , fd_out , & off_out_copy , len , flags );
6359
+ if (builtin .os .tag == .freebsd ) {
6360
+ switch (system .getErrno (rc )) {
6361
+ .SUCCESS = > return @intCast (usize , rc ),
6362
+ .BADF = > return error .FilesOpenedWithWrongFlags ,
6363
+ .FBIG = > return error .FileTooBig ,
6364
+ .IO = > return error .InputOutput ,
6365
+ .ISDIR = > return error .IsDir ,
6366
+ .NOSPC = > return error .NoSpaceLeft ,
6367
+ .INVAL = > break , // these may not be regular files, try fallback
6368
+ .INTEGRITY = > return error .CorruptedData ,
6369
+ .INTR = > continue ,
6370
+ else = > | err | return unexpectedErrno (err ),
6371
+ }
6372
+ } else { // assume linux
6373
+ switch (system .getErrno (rc )) {
6374
+ .SUCCESS = > return @intCast (usize , rc ),
6375
+ .BADF = > return error .FilesOpenedWithWrongFlags ,
6376
+ .FBIG = > return error .FileTooBig ,
6377
+ .IO = > return error .InputOutput ,
6378
+ .ISDIR = > return error .IsDir ,
6379
+ .NOSPC = > return error .NoSpaceLeft ,
6380
+ .INVAL = > break , // these may not be regular files, try fallback
6381
+ .NOMEM = > return error .OutOfMemory ,
6382
+ .OVERFLOW = > return error .Unseekable ,
6383
+ .PERM = > return error .PermissionDenied ,
6384
+ .TXTBSY = > return error .SwapFile ,
6385
+ .XDEV = > break , // support for cross-filesystem copy added in Linux 5.3, use fallback
6386
+ .NOSYS = > { // syscall added in Linux 4.5, use fallback
6387
+ has_copy_file_range_syscall .store (false , .Monotonic );
6388
+ break ;
6389
+ },
6390
+ else = > | err | return unexpectedErrno (err ),
6391
+ }
6392
+ }
6380
6393
}
6381
6394
}
6382
6395
0 commit comments