Skip to content

Commit cf081fa

Browse files
committed
std.tar: support pax headers and gnulong_{name,link}
tar.zig: * add HeaderIterator() type and convert pipeToFileSystem() to use it. * add initial support for options.executable_bit_only. * initial windows support: * skip symlinks which require admin rights * workaround file.updateTimes() panic by truncating file times * add tests parseNumeric and parsePaxTime ported from https://go.dev/src/archive/tar/strconv_test.go. lib/std/compress/tar/testdata/ * copy a subset of tar files from https://go.dev/src/archive/tar/testdata * gzip them all with -9. results in around 95% file size reduction reader_test.zig: * validate headers against files from testdata/. a port of https://go.dev/src/archive/tar/reader_test.go. test_decompress.zig: * runs tar.pipeToFileSystem() on valid testdata/ files.
1 parent a867599 commit cf081fa

32 files changed

+1944
-135
lines changed

Diff for: lib/std/compress.zig

+1
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,5 @@ test {
4646
_ = xz;
4747
_ = zlib;
4848
_ = zstd;
49+
_ = @import("compress/tar.zig");
4950
}

Diff for: lib/std/compress/tar.zig

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
test "std.tar" {
2+
_ = @import("tar/reader_test.zig");
3+
_ = @import("tar/test_decompress.zig");
4+
}

Diff for: lib/std/compress/tar/reader_test.zig

+762
Large diffs are not rendered by default.

Diff for: lib/std/compress/tar/test_common.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const std = @import("std");
2+
/// testing helper for decompressing a .gz file. returns an io.fixedBufferStream
3+
/// with the decompressed data. caller owns the returned FixedBufferStream.buffer
4+
pub fn decompressGz(
5+
comptime file_name: []const u8,
6+
alloc: std.mem.Allocator,
7+
) !std.io.FixedBufferStream([]u8) {
8+
var fbs = std.io.fixedBufferStream(@embedFile(file_name));
9+
var decompressor = try std.compress.gzip.decompress(alloc, fbs.reader());
10+
defer decompressor.deinit();
11+
const decompressed = try decompressor.reader().readAllAlloc(alloc, 1024 * 32);
12+
return std.io.fixedBufferStream(decompressed);
13+
}

Diff for: lib/std/compress/tar/test_decompress.zig

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const std = @import("std");
2+
const mem = std.mem;
3+
const tar = std.tar;
4+
const testing = std.testing;
5+
const talloc = testing.allocator;
6+
const builtin = @import("builtin");
7+
const test_common = @import("test_common.zig");
8+
9+
test "tar decompress testdata" {
10+
// skip if wine and debug mode due to 'incorrect alignment'
11+
// TODO re-enable after https://github.com/ziglang/zig/issues/14036 is solved
12+
if (builtin.os.tag == .windows and builtin.mode == .Debug)
13+
return error.SkipZigTest;
14+
15+
const test_files = [_][]const u8{
16+
"xattrs.tar",
17+
"gnu-long-nul.tar",
18+
"v7.tar",
19+
"pax-bad-hdr-file.tar",
20+
"pax-global-records.tar",
21+
"star.tar",
22+
"pax-multi-hdrs.tar",
23+
"gnu.tar",
24+
"gnu-utf8.tar",
25+
"trailing-slash.tar",
26+
"pax.tar",
27+
"nil-uid.tar",
28+
"ustar-file-devs.tar",
29+
"pax-pos-size-file.tar",
30+
"hardlink.tar",
31+
"pax-records.tar",
32+
"gnu-multi-hdrs.tar",
33+
};
34+
35+
var cache_dir = testing.tmpDir(.{});
36+
defer cache_dir.cleanup();
37+
38+
inline for (test_files) |test_file| {
39+
var fbs = try test_common.decompressGz("testdata/" ++ test_file ++ ".gz", talloc);
40+
defer talloc.free(fbs.buffer);
41+
{
42+
var output_dir = try cache_dir.dir.makeOpenPath(test_file, .{});
43+
defer output_dir.close();
44+
try tar.pipeToFileSystem(output_dir, fbs.reader(), .{ .mode_mode = .ignore });
45+
}
46+
try cache_dir.dir.deleteTree(test_file);
47+
fbs.reset();
48+
{
49+
var output_dir = try cache_dir.dir.makeOpenPath(test_file, .{});
50+
defer output_dir.close();
51+
try tar.pipeToFileSystem(output_dir, fbs.reader(), .{ .mode_mode = .executable_bit_only });
52+
}
53+
}
54+
}

Diff for: lib/std/compress/tar/testdata/gnu-long-nul.tar.gz

175 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/gnu-multi-hdrs.tar.gz

208 Bytes
Binary file not shown.
125 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/gnu-not-utf8.tar.gz

109 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/gnu-utf8.tar.gz

148 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/gnu.tar.gz

163 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/hardlink.tar.gz

164 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/issue10968.tar.gz

220 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/issue11169.tar.gz

119 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/issue12435.tar.gz

61 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/neg-size.tar.gz

219 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/nil-uid.tar.gz

134 Bytes
Binary file not shown.
746 Bytes
Binary file not shown.
750 Bytes
Binary file not shown.
290 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/pax-multi-hdrs.tar.gz

218 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/pax-nul-path.tar.gz

148 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/pax-nul-xattrs.tar.gz

163 Bytes
Binary file not shown.
736 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/pax-records.tar.gz

186 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/pax.tar.gz

412 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/star.tar.gz

179 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/trailing-slash.tar.gz

134 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/ustar-file-devs.tar.gz

93 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/v7.tar.gz

551 Bytes
Binary file not shown.

Diff for: lib/std/compress/tar/testdata/xattrs.tar.gz

376 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)