Skip to content

Commit

Permalink
std.tar: add writer (ziglang#19603)
Browse files Browse the repository at this point in the history
Simplifies code in docs creation where we used `std.tar.output.Header`.
Writer uses that Header internally and provides higher level interface.
Updates checksum on write, handles long file names, allows setting mtime and file permission mode. Provides handy interface for passing `Dir.WalkerEntry`.
  • Loading branch information
ianic authored and richerfu committed Oct 28, 2024
1 parent 7009677 commit 169649a
Show file tree
Hide file tree
Showing 6 changed files with 517 additions and 174 deletions.
40 changes: 8 additions & 32 deletions lib/compiler/std-docs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,16 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
},
},
});
const w = response.writer();

var std_dir = try context.lib_dir.openDir("std", .{ .iterate = true });
defer std_dir.close();

var walker = try std_dir.walk(gpa);
defer walker.deinit();

var archiver = std.tar.writer(response.writer());
archiver.prefix = "std";

while (try walker.next()) |entry| {
switch (entry.kind) {
.file => {
Expand All @@ -199,47 +201,21 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
},
else => continue,
}

var file = try std_dir.openFile(entry.path, .{});
var file = try entry.dir.openFile(entry.basename, .{});
defer file.close();

const stat = try file.stat();
const padding = p: {
const remainder = stat.size % 512;
break :p if (remainder > 0) 512 - remainder else 0;
};

var file_header = std.tar.output.Header.init();
file_header.typeflag = .regular;
try file_header.setPath("std", entry.path);
try file_header.setSize(stat.size);
try file_header.updateChecksum();
try w.writeAll(std.mem.asBytes(&file_header));
try w.writeFile(file);
try w.writeByteNTimes(0, padding);
try archiver.writeFile(entry.path, file);
}

{
// Since this command is JIT compiled, the builtin module available in
// this source file corresponds to the user's host system.
const builtin_zig = @embedFile("builtin");

var file_header = std.tar.output.Header.init();
file_header.typeflag = .regular;
try file_header.setPath("builtin", "builtin.zig");
try file_header.setSize(builtin_zig.len);
try file_header.updateChecksum();
try w.writeAll(std.mem.asBytes(&file_header));
try w.writeAll(builtin_zig);
const padding = p: {
const remainder = builtin_zig.len % 512;
break :p if (remainder > 0) 512 - remainder else 0;
};
try w.writeByteNTimes(0, padding);
archiver.prefix = "builtin";
try archiver.writeFileBytes("builtin.zig", builtin_zig, .{});
}

// intentionally omitting the pointless trailer
//try w.writeByteNTimes(0, 512 * 2);
//try archiver.finish();
try response.end();
}

Expand Down
30 changes: 5 additions & 25 deletions lib/std/Build/Fuzz/WebServer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,6 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {
},
},
});
const w = response.writer();

const DedupeTable = std.ArrayHashMapUnmanaged(Build.Cache.Path, void, Build.Cache.Path.TableAdapter, false);
var dedupe_table: DedupeTable = .{};
Expand Down Expand Up @@ -490,40 +489,21 @@ fn serveSourcesTar(ws: *WebServer, request: *std.http.Server.Request) !void {

var cwd_cache: ?[]const u8 = null;

var archiver = std.tar.writer(response.writer());

for (deduped_paths) |joined_path| {
var file = joined_path.root_dir.handle.openFile(joined_path.sub_path, .{}) catch |err| {
log.err("failed to open {}: {s}", .{ joined_path, @errorName(err) });
continue;
};
defer file.close();

const stat = file.stat() catch |err| {
log.err("failed to stat {}: {s}", .{ joined_path, @errorName(err) });
continue;
};
if (stat.kind != .file)
continue;

const padding = p: {
const remainder = stat.size % 512;
break :p if (remainder > 0) 512 - remainder else 0;
};

var file_header = std.tar.output.Header.init();
file_header.typeflag = .regular;
try file_header.setPath(
joined_path.root_dir.path orelse try memoizedCwd(arena, &cwd_cache),
joined_path.sub_path,
);
try file_header.setSize(stat.size);
try file_header.updateChecksum();
try w.writeAll(std.mem.asBytes(&file_header));
try w.writeFile(file);
try w.writeByteNTimes(0, padding);
archiver.prefix = joined_path.root_dir.path orelse try memoizedCwd(arena, &cwd_cache);
try archiver.writeFile(joined_path.sub_path, file);
}

// intentionally omitting the pointless trailer
//try w.writeByteNTimes(0, 512 * 2);
//try archiver.finish();
try response.end();
}

Expand Down
6 changes: 3 additions & 3 deletions lib/std/tar.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const std = @import("std");
const assert = std.debug.assert;
const testing = std.testing;

pub const output = @import("tar/output.zig");
pub const writer = @import("tar/writer.zig").writer;

/// Provide this to receive detailed error messages.
/// When this is provided, some errors which would otherwise be returned
Expand Down Expand Up @@ -355,13 +355,13 @@ pub fn Iterator(comptime ReaderType: type) type {
}

// Writes file content to writer.
pub fn writeAll(self: File, writer: anytype) !void {
pub fn writeAll(self: File, out_writer: anytype) !void {
var buffer: [4096]u8 = undefined;

while (self.unread_bytes.* > 0) {
const buf = buffer[0..@min(buffer.len, self.unread_bytes.*)];
try self.parent_reader.readNoEof(buf);
try writer.writeAll(buf);
try out_writer.writeAll(buf);
self.unread_bytes.* -= buf.len;
}
}
Expand Down
85 changes: 0 additions & 85 deletions lib/std/tar/output.zig

This file was deleted.

Loading

0 comments on commit 169649a

Please sign in to comment.