Skip to content

Commit c7d5d11

Browse files
committed
std.tar: use writeFile in tar.writer
Fixing performance problem: #19603 (comment)
1 parent d5ec672 commit c7d5d11

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

lib/std/tar/writer.zig

+27-11
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,7 @@ pub fn Writer(comptime WriterType: type) type {
5252
/// reader must be equal to `size`. If options are omitted
5353
/// `default_mode.file` is used for mode and current time for mtime.
5454
pub fn addFile(self: *Self, sub_path: []const u8, size: u64, reader: anytype, opt: Options) !void {
55-
var header = Header.init(.regular);
56-
try self.setPath(&header, sub_path);
57-
try self.setMtime(&header, opt.mtime);
58-
try header.setSize(size);
59-
try header.setMode(opt.mode);
60-
try header.write(self.underlying_writer);
55+
try self.addFileHeader(sub_path, size, opt);
6156

6257
var written: usize = 0;
6358
while (written < size) {
@@ -70,6 +65,24 @@ pub fn Writer(comptime WriterType: type) type {
7065
}
7166
}
7267

68+
/// Writes file system file.
69+
pub fn addFsFile(self: *Self, sub_path: []const u8, file: std.fs.File) !void {
70+
const stat = try file.stat();
71+
const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
72+
try self.addFileHeader(sub_path, stat.size, .{ .mtime = mtime });
73+
try self.underlying_writer.any().writeFile(file);
74+
try self.writePadding(stat.size);
75+
}
76+
77+
fn addFileHeader(self: *Self, sub_path: []const u8, size: u64, opt: Options) !void {
78+
var header = Header.init(.regular);
79+
try self.setPath(&header, sub_path);
80+
try self.setMtime(&header, opt.mtime);
81+
try header.setSize(size);
82+
try header.setMode(opt.mode);
83+
try header.write(self.underlying_writer);
84+
}
85+
7386
fn setMtime(self: *Self, header: *Header, mtime: u64) !void {
7487
const mt = blk: {
7588
if (mtime == 0) {
@@ -100,28 +113,31 @@ pub fn Writer(comptime WriterType: type) type {
100113
/// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and
101114
/// default from `default_mode` for entry mode.
102115
pub fn addEntry(self: *Self, entry: std.fs.Dir.Walker.WalkerEntry) !void {
103-
const stat = try entry.dir.statFile(entry.basename);
104-
const mtime: u64 = @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
105116
switch (entry.kind) {
106117
.directory => {
107-
try self.addDir(entry.path, .{ .mtime = mtime });
118+
try self.addDir(entry.path, .{ .mtime = try entryMtime(entry) });
108119
},
109120
.file => {
110121
var file = try entry.dir.openFile(entry.basename, .{});
111122
defer file.close();
112-
try self.addFile(entry.path, stat.size, file.reader(), .{ .mtime = mtime });
123+
try self.addFsFile(entry.path, file);
113124
},
114125
.sym_link => {
115126
var link_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
116127
const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer);
117-
try self.addLink(entry.path, link_name, .{ .mtime = mtime });
128+
try self.addLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) });
118129
},
119130
else => {
120131
return error.UnsupportedWalkerEntryKind;
121132
},
122133
}
123134
}
124135

136+
fn entryMtime(entry: std.fs.Dir.Walker.WalkerEntry) !u64 {
137+
const stat = try entry.dir.statFile(entry.basename);
138+
return @intCast(@divFloor(stat.mtime, std.time.ns_per_s));
139+
}
140+
125141
/// Writes path in posix header, if don't fit (in name+prefix; 100+155
126142
/// bytes) writes it in gnu extended header.
127143
fn setPath(self: *Self, header: *Header, sub_path: []const u8) !void {

0 commit comments

Comments
 (0)