Skip to content

Commit 7ac8d0a

Browse files
committed
use tar.writer instead of tar.output.Header
1 parent 4788714 commit 7ac8d0a

File tree

3 files changed

+41
-96
lines changed

3 files changed

+41
-96
lines changed

lib/compiler/std-docs.zig

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,16 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
180180
},
181181
},
182182
});
183-
const w = response.writer();
184183

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

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

190+
var archiver = std.tar.writer(response.writer());
191+
archiver.prefix = "std";
192+
191193
while (try walker.next()) |entry| {
192194
switch (entry.kind) {
193195
.file => {
@@ -198,47 +200,20 @@ fn serveSourcesTar(request: *std.http.Server.Request, context: *Context) !void {
198200
},
199201
else => continue,
200202
}
201-
202-
var file = try std_dir.openFile(entry.path, .{});
203-
defer file.close();
204-
205-
const stat = try file.stat();
206-
const padding = p: {
207-
const remainder = stat.size % 512;
208-
break :p if (remainder > 0) 512 - remainder else 0;
209-
};
210-
211-
var file_header = std.tar.output.Header.init();
212-
file_header.typeflag = .regular;
213-
try file_header.setPath("std", entry.path);
214-
try file_header.setSize(stat.size);
215-
try file_header.updateChecksum();
216-
try w.writeAll(std.mem.asBytes(&file_header));
217-
try w.writeFile(file);
218-
try w.writeByteNTimes(0, padding);
203+
try archiver.addEntry(entry);
219204
}
220205

221206
{
222207
// Since this command is JIT compiled, the builtin module available in
223208
// this source file corresponds to the user's host system.
224209
const builtin_zig = @embedFile("builtin");
225-
226-
var file_header = std.tar.output.Header.init();
227-
file_header.typeflag = .regular;
228-
try file_header.setPath("builtin", "builtin.zig");
229-
try file_header.setSize(builtin_zig.len);
230-
try file_header.updateChecksum();
231-
try w.writeAll(std.mem.asBytes(&file_header));
232-
try w.writeAll(builtin_zig);
233-
const padding = p: {
234-
const remainder = builtin_zig.len % 512;
235-
break :p if (remainder > 0) 512 - remainder else 0;
236-
};
237-
try w.writeByteNTimes(0, padding);
210+
archiver.prefix = "builtin";
211+
var stream = std.io.fixedBufferStream(builtin_zig);
212+
try archiver.addFile("builtin.zig", builtin_zig.len, stream.reader(), .{});
238213
}
239214

240215
// intentionally omitting the pointless trailer
241-
//try w.writeByteNTimes(0, 512 * 2);
216+
//try archiver.finish();
242217
try response.end();
243218
}
244219

lib/std/tar/writer.zig

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@ const assert = std.debug.assert;
33
const testing = std.testing;
44

55
/// Creates tar Writer which will write tar content to the `underlying_writer`.
6-
/// All paths will be prefixed with `perfix` if it is not empty string.
7-
pub fn writer(underlying_writer: anytype, prefix: []const u8) !Writer(@TypeOf(underlying_writer)) {
8-
return Writer(@TypeOf(underlying_writer)).init(
9-
underlying_writer,
10-
prefix,
11-
);
6+
/// Use setRoot to nest all following entries under single root. If file don't
7+
/// fit into posix header (name+prefix: 100+155 bytes) gnu extented header will
8+
/// be used for long names. Options enables setting file premission mode and
9+
/// mtime. Default is to use current time for mtime and
10+
/// `default_mode`.file/dir/sym_link for mode.
11+
pub fn writer(underlying_writer: anytype) Writer(@TypeOf(underlying_writer)) {
12+
return .{ .underlying_writer = underlying_writer };
1213
}
1314

1415
pub fn Writer(comptime WriterType: type) type {
1516
return struct {
1617
const block_size = @sizeOf(Header);
1718
const zero: [@sizeOf(Header)]u8 = .{0} ** @sizeOf(Header);
1819
pub const Options = struct {
20+
/// File system permission mode.
1921
mode: u32 = 0,
22+
/// File system modification time.
2023
mtime: u64 = 0,
2124
};
2225
const Self = @This();
@@ -27,21 +30,16 @@ pub fn Writer(comptime WriterType: type) type {
2730
block_buffer: [block_size]u8 = undefined,
2831
mtime_now: u64 = 0,
2932

30-
/// Tar will be written to the `underlying_writer`. All paths will be
31-
/// prefixed with `perfix` if it is not empty string.
32-
pub fn init(underlying_writer: WriterType, prefix: []const u8) !Self {
33-
var self = Self{
34-
.underlying_writer = underlying_writer,
35-
};
36-
if (prefix.len > 0) {
37-
try self.addDir(prefix, .{});
38-
self.prefix = prefix;
33+
/// Sets prefix for all other add* method paths.
34+
pub fn setRoot(self: *Self, root: []const u8) !void {
35+
if (root.len > 0) {
36+
try self.addDir(root, .{});
3937
}
40-
return self;
38+
self.prefix = root;
4139
}
4240

4341
/// Writes directory. If options are omitted `default_mode.dir` is used
44-
/// for mode and current time for mtime.
42+
/// for mode and current time for `mtime`.
4543
pub fn addDir(self: *Self, sub_path: []const u8, opt: Options) !void {
4644
var header = Header.init(.directory);
4745
try self.setPath(&header, sub_path);
@@ -86,7 +84,7 @@ pub fn Writer(comptime WriterType: type) type {
8684
}
8785

8886
/// Writes symlink. If options are omitted `default_mode.sym_link` is
89-
/// used for mode and current time for mtime.
87+
/// used for mode and current time for `mtime`.
9088
pub fn addLink(self: *Self, sub_path: []const u8, link_name: []const u8, opt: Options) !void {
9189
var header = Header.init(.symbolic_link);
9290
try self.setPath(&header, sub_path);
@@ -99,8 +97,8 @@ pub fn Writer(comptime WriterType: type) type {
9997
try header.write(self.underlying_writer);
10098
}
10199

102-
/// Writes fs.Dir.WalkerEntry. Uses mtime from file system entry and
103-
/// defaults from `default_mode` for mode.
100+
/// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and
101+
/// default from `default_mode` for entry mode.
104102
pub fn addEntry(self: *Self, entry: std.fs.Dir.Walker.WalkerEntry) !void {
105103
const stat = try entry.dir.statFile(entry.basename);
106104
const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
@@ -140,6 +138,7 @@ pub fn Writer(comptime WriterType: type) type {
140138
};
141139
}
142140

141+
/// Writes gnu extended header: gnu_long_name or gnu_long_link.
143142
fn writeExtendedHeader(self: *Self, typeflag: Header.FileType, buffers: []const []const u8) !void {
144143
var len: usize = 0;
145144
for (buffers) |buf|
@@ -413,11 +412,12 @@ test "write files" {
413412

414413
// with root
415414
{
416-
const prefix = "root";
415+
const root = "root";
417416

418417
var output = std.ArrayList(u8).init(testing.allocator);
419418
defer output.deinit();
420-
var wrt = try writer(output.writer(), prefix);
419+
var wrt = writer(output.writer());
420+
try wrt.setRoot(root);
421421
for (files) |file| {
422422
var content = std.io.fixedBufferStream(file.content);
423423
try wrt.addFile(file.path, file.content.len, content.reader(), .{});
@@ -432,17 +432,17 @@ test "write files" {
432432
// first entry is directory with prefix
433433
{
434434
const actual = (try iter.next()).?;
435-
try testing.expectEqualStrings(prefix, actual.name);
435+
try testing.expectEqualStrings(root, actual.name);
436436
try testing.expectEqual(std.tar.FileKind.directory, actual.kind);
437437
}
438438

439439
var i: usize = 0;
440440
while (try iter.next()) |actual| {
441441
defer i += 1;
442442
const expected = files[i];
443-
try testing.expectEqualStrings(prefix, actual.name[0..prefix.len]);
444-
try testing.expectEqual('/', actual.name[prefix.len..][0]);
445-
try testing.expectEqualStrings(expected.path, actual.name[prefix.len + 1 ..]);
443+
try testing.expectEqualStrings(root, actual.name[0..root.len]);
444+
try testing.expectEqual('/', actual.name[root.len..][0]);
445+
try testing.expectEqualStrings(expected.path, actual.name[root.len + 1 ..]);
446446

447447
var content = std.ArrayList(u8).init(testing.allocator);
448448
defer content.deinit();
@@ -454,7 +454,7 @@ test "write files" {
454454
{
455455
var output = std.ArrayList(u8).init(testing.allocator);
456456
defer output.deinit();
457-
var wrt = try writer(output.writer(), "");
457+
var wrt = writer(output.writer());
458458
for (files) |file| {
459459
var content = std.io.fixedBufferStream(file.content);
460460
try wrt.addFile(file.path, file.content.len, content.reader(), .{});
@@ -592,7 +592,8 @@ test "sourcesTar" {
592592
{
593593
var out_file = try out_dir.createFile("sources_new.tar", .{});
594594
defer out_file.close();
595-
var w = try writer(out_file.writer(), "std");
595+
var w = writer(out_file.writer());
596+
try w.setRoot("std");
596597

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

src/Compilation.zig

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3761,7 +3761,7 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, tar_file: std.fs.
37613761
var walker = try mod_dir.walk(comp.gpa);
37623762
defer walker.deinit();
37633763

3764-
const padding_buffer = [1]u8{0} ** 512;
3764+
var archiver = std.tar.writer(tar_file.writer());
37653765

37663766
while (try walker.next()) |entry| {
37673767
switch (entry.kind) {
@@ -3772,43 +3772,12 @@ fn docsCopyModule(comp: *Compilation, module: *Package.Module, tar_file: std.fs.
37723772
},
37733773
else => continue,
37743774
}
3775-
3776-
var file = mod_dir.openFile(entry.path, .{}) catch |err| {
3777-
return comp.lockAndSetMiscFailure(.docs_copy, "unable to open '{}{s}': {s}", .{
3778-
root, entry.path, @errorName(err),
3779-
});
3780-
};
3781-
defer file.close();
3782-
3783-
const stat = file.stat() catch |err| {
3784-
return comp.lockAndSetMiscFailure(.docs_copy, "unable to stat '{}{s}': {s}", .{
3775+
archiver.prefix = module.fully_qualified_name;
3776+
archiver.addEntry(entry) catch |err| {
3777+
return comp.lockAndSetMiscFailure(.docs_copy, "unable to archive '{}{s}': {s}", .{
37853778
root, entry.path, @errorName(err),
37863779
});
37873780
};
3788-
3789-
var file_header = std.tar.output.Header.init();
3790-
file_header.typeflag = .regular;
3791-
try file_header.setPath(module.fully_qualified_name, entry.path);
3792-
try file_header.setSize(stat.size);
3793-
try file_header.updateChecksum();
3794-
3795-
const header_bytes = std.mem.asBytes(&file_header);
3796-
const padding = p: {
3797-
const remainder: u16 = @intCast(stat.size % 512);
3798-
const n = if (remainder > 0) 512 - remainder else 0;
3799-
break :p padding_buffer[0..n];
3800-
};
3801-
3802-
var header_and_trailer: [2]std.posix.iovec_const = .{
3803-
.{ .iov_base = header_bytes.ptr, .iov_len = header_bytes.len },
3804-
.{ .iov_base = padding.ptr, .iov_len = padding.len },
3805-
};
3806-
3807-
try tar_file.writeFileAll(file, .{
3808-
.in_len = stat.size,
3809-
.headers_and_trailers = &header_and_trailer,
3810-
.header_count = 1,
3811-
});
38123781
}
38133782
}
38143783

0 commit comments

Comments
 (0)