Function next [src]

Iterates through the tar archive as if it is a series of files. Internally, the tar format often uses entries (header with optional content) to add meta data that describes the next file. These entries should not normally be visible to the outside. As such, this loop iterates through one or more entries until it collects a all file attributes.

Prototype

pub fn next(self: *Iterator) !?File

Parameters

self: *Iterator

Source

pub fn next(self: *Iterator) !?File { if (self.unread_file_bytes > 0) { // If file content was not consumed by caller try self.reader.discardAll64(self.unread_file_bytes); self.unread_file_bytes = 0; } var file: File = self.newFile(); while (try self.readHeader()) |header| { const kind = header.kind(); const size: u64 = try header.size(); self.padding = blockPadding(size); switch (kind) { // File types to return upstream .directory, .normal, .symbolic_link => { file.kind = switch (kind) { .directory => .directory, .normal => .file, .symbolic_link => .sym_link, else => unreachable, }; file.mode = try header.mode(); // set file attributes if not already set by prefix/extended headers if (file.size == 0) { file.size = size; } if (file.link_name.len == 0) { file.link_name = try header.linkName(self.link_name_buffer); } if (file.name.len == 0) { file.name = try header.fullName(self.file_name_buffer); } self.padding = blockPadding(file.size); self.unread_file_bytes = file.size; return file; }, // Prefix header types .gnu_long_name => { file.name = try self.readString(@intCast(size), self.file_name_buffer); }, .gnu_long_link => { file.link_name = try self.readString(@intCast(size), self.link_name_buffer); }, .extended_header => { // Use just attributes from last extended header. file = self.newFile(); var rdr: PaxIterator = .{ .reader = self.reader, .size = @intCast(size), }; while (try rdr.next()) |attr| { switch (attr.kind) { .path => { file.name = try attr.value(self.file_name_buffer); }, .linkpath => { file.link_name = try attr.value(self.link_name_buffer); }, .size => { var buf: [pax_max_size_attr_len]u8 = undefined; file.size = try std.fmt.parseInt(u64, try attr.value(&buf), 10); }, } } }, // Ignored header type .global_extended_header => { self.reader.discardAll64(size) catch return error.TarHeadersTooBig; }, // All other are unsupported header types else => { const d = self.diagnostics orelse return error.TarUnsupportedHeader; try d.errors.append(d.allocator, .{ .unsupported_file_type = .{ .file_name = try d.allocator.dupe(u8, header.name()), .file_type = kind, } }); if (kind == .gnu_sparse) { try self.skipGnuSparseExtendedHeaders(header); } self.reader.discardAll64(size) catch return error.TarHeadersTooBig; }, } } return null; }