Ingests tar file from reader, populating file contents within dir. If
any file would be extracted outside of dir, an error is return instead.
pub fn extract(io: Io, dir: Io.Dir, reader: *Io.Reader, options: ExtractOptions) !void
pub fn extract(io: Io, dir: Io.Dir, reader: *Io.Reader, options: ExtractOptions) !void {
var file_name_buffer: [Io.Dir.max_path_bytes]u8 = undefined;
var link_name_buffer: [Io.Dir.max_path_bytes]u8 = undefined;
var sanitize_buffer: [Io.Dir.max_path_bytes]u8 = undefined;
var file_contents_buffer: [1024]u8 = undefined;
var it: Iterator = .init(reader, .{
.file_name_buffer = &file_name_buffer,
.link_name_buffer = &link_name_buffer,
.diagnostics = options.diagnostics,
});
while (try it.next()) |file| {
const n = sanitizePath(&sanitize_buffer, file.name, options.strip_components) catch 0;
if (n == 0 and file.kind != .directory) {
const d = options.diagnostics orelse return error.TarComponentsOutsideStrippedPrefix;
try d.errors.append(d.allocator, .{ .components_outside_stripped_prefix = .{
.file_name = try d.allocator.dupe(u8, file.name),
} });
continue;
}
const file_name = sanitize_buffer[0..n];
if (options.diagnostics) |d| {
try d.findRoot(file.kind, file_name);
}
switch (file.kind) {
.directory => {
if (file_name.len > 0 and !options.exclude_empty_directories) {
try dir.createDirPath(io, file_name);
}
},
.file => {
if (createDirAndFile(io, dir, file_name, filePermissions(file.mode, options))) |fs_file| {
defer fs_file.close(io);
var file_writer = fs_file.writer(io, &file_contents_buffer);
try it.streamRemaining(file, &file_writer.interface);
try file_writer.interface.flush();
} else |err| {
const d = options.diagnostics orelse return err;
try d.errors.append(d.allocator, .{ .unable_to_create_file = .{
.code = err,
.file_name = try d.allocator.dupe(u8, file_name),
} });
}
},
.sym_link => {
const link_name = file.link_name;
createDirAndSymlink(io, dir, link_name, file_name) catch |err| {
const d = options.diagnostics orelse return error.UnableToCreateSymLink;
try d.errors.append(d.allocator, .{ .unable_to_create_sym_link = .{
.code = err,
.file_name = try d.allocator.dupe(u8, file_name),
.link_name = try d.allocator.dupe(u8, link_name),
} });
};
},
}
}
}