mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
std.fs.File.writeFileAll: support unseekable files
With this commit, the function tries to use more efficient syscalls, and
then falls back to non-positional reads.
The motivating use case for this change is to support something like the
following:
try io.getStdOut().writeFileAll(dest_file, .{});
This commit is contained in:
parent
37bc6ee54a
commit
ede41759be
@ -690,10 +690,54 @@ pub const File = struct {
|
||||
header_count: usize = 0,
|
||||
};
|
||||
|
||||
pub const WriteFileError = os.SendFileError;
|
||||
pub const WriteFileError = ReadError || WriteError;
|
||||
|
||||
/// TODO integrate with async I/O
|
||||
pub fn writeFileAll(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
|
||||
return self.writeFileAllSendfile(in_file, args) catch |err| switch (err) {
|
||||
error.Unseekable,
|
||||
error.FastOpenAlreadyInProgress,
|
||||
error.MessageTooBig,
|
||||
error.FileDescriptorNotASocket,
|
||||
=> return self.writeFileAllUnseekable(in_file, args),
|
||||
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
/// Does not try seeking in either of the File parameters.
|
||||
/// See `writeFileAll` as an alternative to calling this.
|
||||
pub fn writeFileAllUnseekable(self: File, in_file: File, args: WriteFileOptions) WriteFileError!void {
|
||||
const headers = args.headers_and_trailers[0..args.header_count];
|
||||
const trailers = args.headers_and_trailers[args.header_count..];
|
||||
|
||||
try self.writevAll(headers);
|
||||
|
||||
var buffer: [4096]u8 = undefined;
|
||||
{
|
||||
var index: usize = 0;
|
||||
// Skip in_offset bytes.
|
||||
while (index < args.in_offset) {
|
||||
const ask = math.min(buffer.len, args.in_offset - index);
|
||||
const amt = try in_file.read(buffer[0..ask]);
|
||||
index += amt;
|
||||
}
|
||||
}
|
||||
const in_len = args.in_len orelse math.maxInt(u64);
|
||||
var index: usize = 0;
|
||||
while (index < in_len) {
|
||||
const ask = math.min(buffer.len, in_len - index);
|
||||
const amt = try in_file.read(buffer[0..ask]);
|
||||
if (amt == 0) break;
|
||||
index += try self.write(buffer[0..amt]);
|
||||
}
|
||||
|
||||
try self.writevAll(trailers);
|
||||
}
|
||||
|
||||
/// Low level function which can fail for OS-specific reasons.
|
||||
/// See `writeFileAll` as an alternative to calling this.
|
||||
/// TODO integrate with async I/O
|
||||
fn writeFileAllSendfile(self: File, in_file: File, args: WriteFileOptions) os.SendFileError!void {
|
||||
const count = blk: {
|
||||
if (args.in_len) |l| {
|
||||
if (l == 0) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user