authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-21 23:26:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-21 23:33:19-07:00
log76fe518d498116763dc1e3a7669619a3a9413715
tree106068d0306ffd659f2893c006682d570f111d4f
parent96cbdd145d6ec5bf2e3ed80743c99ab4b2cdff68

std.fs.File.Reader.sendFile: fix EndOfStream detection


1 files changed, 22 insertions(+), 5 deletions(-)

lib/std/fs/File.zig+22-5
......@@ -1624,7 +1624,6 @@ pub const Writer = struct {
16241624 const pattern = data[data.len - 1];
16251625 if (pattern.len == 0 or splat == 0) return 0;
16261626 const n = windows.WriteFile(handle, pattern, null) catch |err| {
1627 std.debug.print("windows write file failed3: {t}\n", .{err});
16281627 w.err = err;
16291628 return error.WriteFailed;
16301629 };
......@@ -1735,6 +1734,16 @@ pub const Writer = struct {
17351734 const out_fd = w.file.handle;
17361735 const in_fd = file_reader.file.handle;
17371736
1737 if (file_reader.size) |size| {
1738 if (size - file_reader.pos == 0) {
1739 if (reader_buffered.len != 0) {
1740 return sendFileBuffered(io_w, file_reader, reader_buffered);
1741 } else {
1742 return error.EndOfStream;
1743 }
1744 }
1745 }
1746
17381747 if (native_os == .freebsd and w.mode == .streaming) sf: {
17391748 // Try using sendfile on FreeBSD.
17401749 if (w.sendfile_err != null) break :sf;
......@@ -1780,6 +1789,10 @@ pub const Writer = struct {
17801789 .NOBUFS => w.sendfile_err = error.SystemResources,
17811790 else => |err| w.sendfile_err = posix.unexpectedErrno(err),
17821791 }
1792 if (sbytes == 0) {
1793 file_reader.size = file_reader.pos;
1794 return error.EndOfStream;
1795 }
17831796 const consumed = io_w.consume(@bitCast(sbytes));
17841797 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
17851798 return consumed;
......@@ -1810,9 +1823,9 @@ pub const Writer = struct {
18101823 break :b &hdtr_data;
18111824 };
18121825 const max_count = maxInt(i32); // Avoid EINVAL.
1813 var sbytes: std.c.off_t = @min(file_limit, max_count);
1826 var len: std.c.off_t = @min(file_limit, max_count);
18141827 const flags = 0;
1815 switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, &sbytes, hdtr, flags))) {
1828 switch (posix.errno(std.c.sendfile(in_fd, out_fd, offset, &len, hdtr, flags))) {
18161829 .SUCCESS, .INTR => {},
18171830 .OPNOTSUPP, .NOTSOCK, .NOSYS => w.sendfile_err = error.UnsupportedOperation,
18181831 .BADF => if (builtin.mode == .Debug) @panic("race condition") else {
......@@ -1825,14 +1838,18 @@ pub const Writer = struct {
18251838 w.sendfile_err = error.Unexpected;
18261839 },
18271840 .NOTCONN => w.sendfile_err = error.BrokenPipe,
1828 .AGAIN => if (sbytes == 0) {
1841 .AGAIN => if (len == 0) {
18291842 w.sendfile_err = error.WouldBlock;
18301843 },
18311844 .IO => w.sendfile_err = error.InputOutput,
18321845 .PIPE => w.sendfile_err = error.BrokenPipe,
18331846 else => |err| w.sendfile_err = posix.unexpectedErrno(err),
18341847 }
1835 const consumed = io_w.consume(@bitCast(sbytes));
1848 if (len == 0) {
1849 file_reader.size = file_reader.pos;
1850 return error.EndOfStream;
1851 }
1852 const consumed = io_w.consume(@bitCast(len));
18361853 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
18371854 return consumed;
18381855 }