diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig index 18988ab7fb..a58cdb91a3 100644 --- a/lib/std/Build/Cache.zig +++ b/lib/std/Build/Cache.zig @@ -335,7 +335,6 @@ pub const Manifest = struct { manifest_create: fs.File.OpenError, manifest_read: fs.File.ReadError, manifest_lock: fs.File.LockError, - manifest_seek: fs.File.SeekError, file_open: FileOp, file_stat: FileOp, file_read: FileOp, @@ -609,12 +608,6 @@ pub const Manifest = struct { var file = self.files.pop().?; file.key.deinit(self.cache.gpa); } - // Also, seek the file back to the start. - self.manifest_file.?.seekTo(0) catch |err| { - self.diagnostic = .{ .manifest_seek = err }; - return error.CacheCheckFailed; - }; - switch (try self.hitWithCurrentLock()) { .hit => break :hit, .miss => |m| break :digests m.file_digests_populated, @@ -659,9 +652,8 @@ pub const Manifest = struct { return true; } - /// Assumes that `self.hash.hasher` has been updated only with the original digest, that - /// `self.files` contains only the original input files, and that `self.manifest_file.?` is - /// seeked to the start of the file. + /// Assumes that `self.hash.hasher` has been updated only with the original digest and that + /// `self.files` contains only the original input files. fn hitWithCurrentLock(self: *Manifest) HitError!union(enum) { hit, miss: struct { @@ -670,12 +662,13 @@ pub const Manifest = struct { } { const gpa = self.cache.gpa; const input_file_count = self.files.entries.len; - - const file_contents = self.manifest_file.?.reader().readAllAlloc(gpa, manifest_file_size_max) catch |err| switch (err) { + var manifest_reader = self.manifest_file.?.reader(); // Reads positionally from zero. + const limit: std.io.Reader.Limit = .limited(manifest_file_size_max); + const file_contents = manifest_reader.interface().readRemainingAlloc(gpa, limit) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.StreamTooLong => return error.OutOfMemory, - else => |e| { - self.diagnostic = .{ .manifest_read = e }; + error.ReadFailed => { + self.diagnostic = .{ .manifest_read = manifest_reader.err.? }; return error.CacheCheckFailed; }, }; diff --git a/lib/std/Build/Fuzz/WebServer.zig b/lib/std/Build/Fuzz/WebServer.zig index d84c3ccd9c..620ab1ad71 100644 --- a/lib/std/Build/Fuzz/WebServer.zig +++ b/lib/std/Build/Fuzz/WebServer.zig @@ -109,7 +109,7 @@ fn accept(ws: *WebServer, connection: std.net.Server.Connection) void { var server: std.http.Server = .init(&br, &bw); var web_socket: std.http.WebSocket = undefined; var ws_recv_buffer: [0x4000]u8 align(4) = undefined; - while (server.state == .ready) { + while (server.reader.state == .ready) { var request = server.receiveHead() catch |err| switch (err) { error.HttpConnectionClosing => return, else => { @@ -476,7 +476,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void { defer arena_instance.deinit(); const arena = arena_instance.allocator(); - var response = try request.respondStreaming(.{ + var body_writer = try request.respondStreaming(.{ .respond_options = .{ .extra_headers = &.{ .{ .name = "content-type", .value = "application/x-tar" }, @@ -517,7 +517,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void { var cwd_cache: ?[]const u8 = null; - var response_writer = response.writer().unbuffered(); + var response_writer = body_writer.interface().unbuffered(); var archiver: std.tar.Writer = .{ .underlying_writer = &response_writer }; for (deduped_paths) |joined_path| { @@ -531,9 +531,7 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void { try archiver.writeFile(joined_path.sub_path, file, try file.stat()); } - // intentionally omitting the pointless trailer - //try archiver.finish(); - try response.end(); + try body_writer.end(); } fn memoizedCwd(arena: Allocator, opt_ptr: *?[]const u8) ![]const u8 { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index a0066a6be2..01d01f626b 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -812,7 +812,7 @@ fn failWithCacheError(s: *Step, man: *const Build.Cache.Manifest, err: Build.Cac switch (err) { error.CacheCheckFailed => switch (man.diagnostic) { .none => unreachable, - .manifest_create, .manifest_read, .manifest_lock, .manifest_seek => |e| return s.fail("failed to check cache: {s} {s}", .{ + .manifest_create, .manifest_read, .manifest_lock => |e| return s.fail("failed to check cache: {s} {s}", .{ @tagName(man.diagnostic), @errorName(e), }), .file_open, .file_stat, .file_read, .file_hash => |op| { diff --git a/lib/std/http.zig b/lib/std/http.zig index e808cd201e..1b507b4ee9 100644 --- a/lib/std/http.zig +++ b/lib/std/http.zig @@ -772,6 +772,7 @@ pub const BodyWriter = struct { /// * `endChunked` pub fn endUnflushed(w: *BodyWriter) WriteError!void { switch (w.state) { + .end => unreachable, .content_length => |len| { assert(len == 0); // Trips when end() called before all bytes written. w.state = .end; @@ -1033,6 +1034,7 @@ pub const BodyWriter = struct { .writeSplat = chunkedWriteSplat, .writeFile = chunkedWriteFile, }, + .end => unreachable, }, }; } diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig index e0c224c560..8efac3d0ef 100644 --- a/lib/std/http/Server.zig +++ b/lib/std/http/Server.zig @@ -11,7 +11,6 @@ const Server = @This(); /// Data from the HTTP server to the HTTP client. out: *std.io.BufferedWriter, -/// Internal state managed by this abstraction. reader: http.Reader, /// Initialize an HTTP server that can respond to multiple requests on the same @@ -26,6 +25,7 @@ pub fn init(in: *std.io.BufferedReader, out: *std.io.BufferedWriter) Server { .reader = .{ .in = in, .state = .ready, + .body_state = undefined, }, .out = out, }; @@ -39,7 +39,7 @@ pub const ReceiveHeadError = http.Reader.HeadError || error{ HttpHeadersInvalid, }; -pub fn receiveHead(s: *Server) http.Reader.HeadError!Request { +pub fn receiveHead(s: *Server) ReceiveHeadError!Request { try s.reader.receiveHead(); return .{ .server = s, @@ -490,13 +490,13 @@ pub const Request = struct { return .{ .http_protocol_output = request.server.out, - .transfer_encoding = if (o.transfer_encoding) |te| switch (te) { + .state = if (o.transfer_encoding) |te| switch (te) { .chunked => .{ .chunked = .init }, .none => .none, } else if (options.content_length) |len| .{ .content_length = len, } else .{ .chunked = .init }, - .elide_body = elide_body, + .elide = elide_body, }; } diff --git a/lib/std/tar/Writer.zig b/lib/std/tar/Writer.zig index 064168d21c..3b48fc17b2 100644 --- a/lib/std/tar/Writer.zig +++ b/lib/std/tar/Writer.zig @@ -50,9 +50,14 @@ pub fn writeFile( try w.setPath(&header, sub_path); try header.setSize(stat.size); try header.setMtime(mtime); - try header.write(w.underlying_writer); + try header.updateChecksum(); - try w.underlying_writer.writeFileAll(file, .{ .limit = .limited(stat.size) }); + var vec: [1][]const u8 = .{@ptrCast((&header)[0..1])}; + try w.underlying_writer.writeFileAll(file, .{ + .limit = .limited(stat.size), + .headers_and_trailers = &vec, + .headers_len = 1, + }); try w.writePadding(stat.size); }