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 {...@@ -1624,7 +1624,6 @@ pub const Writer = struct {
1624 const pattern = data[data.len - 1];1624 const pattern = data[data.len - 1];
1625 if (pattern.len == 0 or splat == 0) return 0;1625 if (pattern.len == 0 or splat == 0) return 0;
1626 const n = windows.WriteFile(handle, pattern, null) catch |err| {1626 const n = windows.WriteFile(handle, pattern, null) catch |err| {
1627 std.debug.print("windows write file failed3: {t}\n", .{err});
1628 w.err = err;1627 w.err = err;
1629 return error.WriteFailed;1628 return error.WriteFailed;
1630 };1629 };
...@@ -1735,6 +1734,16 @@ pub const Writer = struct {...@@ -1735,6 +1734,16 @@ pub const Writer = struct {
1735 const out_fd = w.file.handle;1734 const out_fd = w.file.handle;
1736 const in_fd = file_reader.file.handle;1735 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
1738 if (native_os == .freebsd and w.mode == .streaming) sf: {1747 if (native_os == .freebsd and w.mode == .streaming) sf: {
1739 // Try using sendfile on FreeBSD.1748 // Try using sendfile on FreeBSD.
1740 if (w.sendfile_err != null) break :sf;1749 if (w.sendfile_err != null) break :sf;
...@@ -1780,6 +1789,10 @@ pub const Writer = struct {...@@ -1780,6 +1789,10 @@ pub const Writer = struct {
1780 .NOBUFS => w.sendfile_err = error.SystemResources,1789 .NOBUFS => w.sendfile_err = error.SystemResources,
1781 else => |err| w.sendfile_err = posix.unexpectedErrno(err),1790 else => |err| w.sendfile_err = posix.unexpectedErrno(err),
1782 }1791 }
1792 if (sbytes == 0) {
1793 file_reader.size = file_reader.pos;
1794 return error.EndOfStream;
1795 }
1783 const consumed = io_w.consume(@bitCast(sbytes));1796 const consumed = io_w.consume(@bitCast(sbytes));
1784 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;1797 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
1785 return consumed;1798 return consumed;
...@@ -1810,9 +1823,9 @@ pub const Writer = struct {...@@ -1810,9 +1823,9 @@ pub const Writer = struct {
1810 break :b &hdtr_data;1823 break :b &hdtr_data;
1811 };1824 };
1812 const max_count = maxInt(i32); // Avoid EINVAL.1825 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);
1814 const flags = 0;1827 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))) {
1816 .SUCCESS, .INTR => {},1829 .SUCCESS, .INTR => {},
1817 .OPNOTSUPP, .NOTSOCK, .NOSYS => w.sendfile_err = error.UnsupportedOperation,1830 .OPNOTSUPP, .NOTSOCK, .NOSYS => w.sendfile_err = error.UnsupportedOperation,
1818 .BADF => if (builtin.mode == .Debug) @panic("race condition") else {1831 .BADF => if (builtin.mode == .Debug) @panic("race condition") else {
...@@ -1825,14 +1838,18 @@ pub const Writer = struct {...@@ -1825,14 +1838,18 @@ pub const Writer = struct {
1825 w.sendfile_err = error.Unexpected;1838 w.sendfile_err = error.Unexpected;
1826 },1839 },
1827 .NOTCONN => w.sendfile_err = error.BrokenPipe,1840 .NOTCONN => w.sendfile_err = error.BrokenPipe,
1828 .AGAIN => if (sbytes == 0) {1841 .AGAIN => if (len == 0) {
1829 w.sendfile_err = error.WouldBlock;1842 w.sendfile_err = error.WouldBlock;
1830 },1843 },
1831 .IO => w.sendfile_err = error.InputOutput,1844 .IO => w.sendfile_err = error.InputOutput,
1832 .PIPE => w.sendfile_err = error.BrokenPipe,1845 .PIPE => w.sendfile_err = error.BrokenPipe,
1833 else => |err| w.sendfile_err = posix.unexpectedErrno(err),1846 else => |err| w.sendfile_err = posix.unexpectedErrno(err),
1834 }1847 }
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));
1836 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;1853 file_reader.seekTo(file_reader.pos + consumed) catch return error.ReadFailed;
1837 return consumed;1854 return consumed;
1838 }1855 }