Thatâs handled for you by the interface.
const std = @import("std");
pub fn main() !void {
var src = try std.fs.cwd().openFile("16KiB-file", .{});
defer src.close();
var dest = try std.fs.cwd().createFile("copied-file", .{});
defer dest.close();
// The reader's buffer can be zero-length since `sendFile`
// will read into the writer's buffer if necessary and we know
// we are using a writer with a non-zero-length buffer
var reader = src.reader(&.{});
var write_buf: [4096]u8 = undefined;
var writer = dest.writer(&write_buf);
const bytes_written = try writer.interface.sendFileAll(&reader, .unlimited);
_ = bytes_written;
try writer.interface.flush();
}
Running that with strace gives:
openat(AT_FDCWD, "16KiB-file", O_RDONLY|O_NOCTTY|O_CLOEXEC) = 3
openat(AT_FDCWD, "copied-file", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 4
pread64(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 0) = 4096
pwritev(4, [{iov_base="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=4096}], 1, 0) = 4096
pread64(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 4096) = 4096
pwritev(4, [{iov_base="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=4096}], 1, 4096) = 4096
pread64(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 8192) = 4096
pwritev(4, [{iov_base="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=4096}], 1, 8192) = 4096
pread64(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096, 12288) = 4096
pwritev(4, [{iov_base="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=4096}], 1, 12288) = 4096
pread64(3, "", 4096, 16384) = 0
close(4) = 0
close(3) = 0
However, in this case it should be possible to use fd-to-fd syscalls instead of falling back to pread/pwrite, but for me that seems to (probably unintentionally) require linking libc:
$ zig build-exe test.zig -lc
$ strace ./test
...
openat(AT_FDCWD, "16KiB-file", O_RDONLY|O_NOCTTY|O_CLOEXEC) = 3
openat(AT_FDCWD, "copied-file", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 4
copy_file_range(3, NULL, 4, [0], 18446744073709551615, 0) = 16384
copy_file_range(3, NULL, 4, [16384], 18446744073709535231, 0) = 0
close(4) = 0
close(3) = 0