authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-28 20:32:09-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-28 20:33:29-07:00
logbeca85e644b2bce45143d20df6cf0f1388d37568
tree79600d798e0debdd45bdcac1eed6796ee247f286
parentb3ad45f267f4402855613f100c82b12f950b8143

std.tar.iterator: make the buffers configurable

Provides more API flexibility and correctness, while still preserving the handy high level `pipeToFileSystem` API.

2 files changed, 41 insertions(+), 14 deletions(-)

lib/std/tar.zig+34-13
......@@ -231,12 +231,27 @@ fn nullStr(str: []const u8) []const u8 {
231231 return str;
232232}
233233
234pub const IteratorOptions = struct {
235 /// Use a buffer with length `std.fs.MAX_PATH_BYTES` to match file system capabilities.
236 file_name_buffer: []u8,
237 /// Use a buffer with length `std.fs.MAX_PATH_BYTES` to match file system capabilities.
238 link_name_buffer: []u8,
239 diagnostics: ?*Diagnostics = null,
240
241 pub const Diagnostics = Options.Diagnostics;
242};
243
234244/// Iterates over files in tar archive.
235245/// `next` returns each file in `reader` tar archive.
236pub fn iterator(reader: anytype, diagnostics: ?*Options.Diagnostics) Iterator(@TypeOf(reader)) {
246pub fn iterator(reader: anytype, options: IteratorOptions) Iterator(@TypeOf(reader)) {
237247 return .{
238248 .reader = reader,
239 .diagnostics = diagnostics,
249 .diagnostics = options.diagnostics,
250 .header_buffer = undefined,
251 .file_name_buffer = options.file_name_buffer,
252 .link_name_buffer = options.link_name_buffer,
253 .padding = 0,
254 .file = undefined,
240255 };
241256}
242257
......@@ -246,14 +261,14 @@ fn Iterator(comptime ReaderType: type) type {
246261 diagnostics: ?*Options.Diagnostics,
247262
248263 // buffers for heeader and file attributes
249 header_buffer: [Header.SIZE]u8 = undefined,
250 file_name_buffer: [1024]u8 = undefined,
251 link_name_buffer: [1024]u8 = undefined,
264 header_buffer: [Header.SIZE]u8,
265 file_name_buffer: []u8,
266 link_name_buffer: []u8,
252267
253268 // bytes of padding to the end of the block
254 padding: usize = 0,
269 padding: usize,
255270 // current tar file
256 file: File = undefined,
271 file: File,
257272
258273 pub const File = struct {
259274 name: []const u8, // name of file, symlink or directory
......@@ -305,7 +320,7 @@ fn Iterator(comptime ReaderType: type) type {
305320 }
306321
307322 fn initFile(self: *Self) void {
308 self.file = File{
323 self.file = .{
309324 .name = self.file_name_buffer[0..0],
310325 .link_name = self.link_name_buffer[0..0],
311326 .size = 0,
......@@ -357,10 +372,10 @@ fn Iterator(comptime ReaderType: type) type {
357372 },
358373 // Prefix header types
359374 .gnu_long_name => {
360 self.file.name = try self.readString(@intCast(size), &self.file_name_buffer);
375 self.file.name = try self.readString(@intCast(size), self.file_name_buffer);
361376 },
362377 .gnu_long_link => {
363 self.file.link_name = try self.readString(@intCast(size), &self.link_name_buffer);
378 self.file.link_name = try self.readString(@intCast(size), self.link_name_buffer);
364379 },
365380 .extended_header => {
366381 // Use just attributes from last extended header.
......@@ -370,10 +385,10 @@ fn Iterator(comptime ReaderType: type) type {
370385 while (try rdr.next()) |attr| {
371386 switch (attr.kind) {
372387 .path => {
373 self.file.name = try attr.value(&self.file_name_buffer);
388 self.file.name = try attr.value(self.file_name_buffer);
374389 },
375390 .linkpath => {
376 self.file.link_name = try attr.value(&self.link_name_buffer);
391 self.file.link_name = try attr.value(self.link_name_buffer);
377392 },
378393 .size => {
379394 var buf: [pax_max_size_attr_len]u8 = undefined;
......@@ -536,7 +551,13 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi
536551 },
537552 }
538553
539 var iter = iterator(reader, options.diagnostics);
554 var file_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
555 var link_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
556 var iter = iterator(reader, .{
557 .file_name_buffer = &file_name_buffer,
558 .link_name_buffer = &link_name_buffer,
559 .diagnostics = options.diagnostics,
560 });
540561 while (try iter.next()) |file| {
541562 switch (file.kind) {
542563 .directory => {
lib/std/tar/test.zig+7-1
......@@ -323,9 +323,15 @@ test "tar run Go test cases" {
323323 },
324324 };
325325
326 var file_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
327 var link_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
328
326329 for (cases) |case| {
327330 var fsb = std.io.fixedBufferStream(case.data);
328 var iter = tar.iterator(fsb.reader(), null);
331 var iter = tar.iterator(fsb.reader(), .{
332 .file_name_buffer = &file_name_buffer,
333 .link_name_buffer = &link_name_buffer,
334 });
329335 var i: usize = 0;
330336 while (iter.next() catch |err| {
331337 if (case.err) |e| {