| ... | @@ -120,8 +120,10 @@ pub const Diagnostics = struct { | ... | @@ -120,8 +120,10 @@ pub const Diagnostics = struct { |
| 120 | } | 120 | } |
| 121 | }; | 121 | }; |
| 122 | | 122 | |
| 123 | /// pipeToFileSystem options | 123 | /// Deprecated, renamed to `ExtractOptions`. |
| 124 | pub const PipeOptions = struct { | 124 | pub const PipeOptions = ExtractOptions; |
| | 125 | |
| | 126 | pub const ExtractOptions = struct { |
| 125 | /// Number of directory levels to skip when extracting files. | 127 | /// Number of directory levels to skip when extracting files. |
| 126 | strip_components: u32 = 0, | 128 | strip_components: u32 = 0, |
| 127 | /// How to handle the "mode" property of files from within the tar file. | 129 | /// How to handle the "mode" property of files from within the tar file. |
| ... | @@ -580,8 +582,12 @@ pub const PaxIterator = struct { | ... | @@ -580,8 +582,12 @@ pub const PaxIterator = struct { |
| 580 | } | 582 | } |
| 581 | }; | 583 | }; |
| 582 | | 584 | |
| 583 | /// Saves tar file content to the file systems. | 585 | /// Deprecated, renamed to `extract`. |
| 584 | pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOptions) !void { | 586 | pub const pipeToFileSystem = extract; |
| | 587 | |
| | 588 | /// Ingests tar file from `reader`, populating file contents within `dir`. If |
| | 589 | /// any file would be extracted outside of `dir`, an error is return instead. |
| | 590 | pub fn extract(io: Io, dir: Io.Dir, reader: *Io.Reader, options: ExtractOptions) !void { |
| 585 | var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; | 591 | var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; |
| 586 | var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; | 592 | var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; |
| 587 | var file_contents_buffer: [1024]u8 = undefined; | 593 | var file_contents_buffer: [1024]u8 = undefined; |
| ... | @@ -958,7 +964,7 @@ test Iterator { | ... | @@ -958,7 +964,7 @@ test Iterator { |
| 958 | } | 964 | } |
| 959 | } | 965 | } |
| 960 | | 966 | |
| 961 | test pipeToFileSystem { | 967 | test extract { |
| 962 | const io = testing.io; | 968 | const io = testing.io; |
| 963 | // Example tar file is created from this tree structure: | 969 | // Example tar file is created from this tree structure: |
| 964 | // $ tree example | 970 | // $ tree example |
| ... | @@ -987,7 +993,7 @@ test pipeToFileSystem { | ... | @@ -987,7 +993,7 @@ test pipeToFileSystem { |
| 987 | const dir = tmp.dir; | 993 | const dir = tmp.dir; |
| 988 | | 994 | |
| 989 | // Save tar from reader to the file system `dir` | 995 | // Save tar from reader to the file system `dir` |
| 990 | pipeToFileSystem(io, dir, &reader, .{ | 996 | extract(io, dir, &reader, .{ |
| 991 | .mode_mode = .ignore, | 997 | .mode_mode = .ignore, |
| 992 | .strip_components = 1, | 998 | .strip_components = 1, |
| 993 | .exclude_empty_directories = true, | 999 | .exclude_empty_directories = true, |
| ... | @@ -1009,7 +1015,7 @@ test pipeToFileSystem { | ... | @@ -1009,7 +1015,7 @@ test pipeToFileSystem { |
| 1009 | ); | 1015 | ); |
| 1010 | } | 1016 | } |
| 1011 | | 1017 | |
| 1012 | test "pipeToFileSystem root_dir" { | 1018 | test "extract root_dir" { |
| 1013 | const io = testing.io; | 1019 | const io = testing.io; |
| 1014 | const data = @embedFile("tar/testdata/example.tar"); | 1020 | const data = @embedFile("tar/testdata/example.tar"); |
| 1015 | var reader: Io.Reader = .fixed(data); | 1021 | var reader: Io.Reader = .fixed(data); |
| ... | @@ -1021,7 +1027,7 @@ test "pipeToFileSystem root_dir" { | ... | @@ -1021,7 +1027,7 @@ test "pipeToFileSystem root_dir" { |
| 1021 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; | 1027 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; |
| 1022 | defer diagnostics.deinit(); | 1028 | defer diagnostics.deinit(); |
| 1023 | | 1029 | |
| 1024 | pipeToFileSystem(io, tmp.dir, &reader, .{ | 1030 | extract(io, tmp.dir, &reader, .{ |
| 1025 | .strip_components = 1, | 1031 | .strip_components = 1, |
| 1026 | .diagnostics = &diagnostics, | 1032 | .diagnostics = &diagnostics, |
| 1027 | }) catch |err| { | 1033 | }) catch |err| { |
| ... | @@ -1043,7 +1049,7 @@ test "pipeToFileSystem root_dir" { | ... | @@ -1043,7 +1049,7 @@ test "pipeToFileSystem root_dir" { |
| 1043 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; | 1049 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; |
| 1044 | defer diagnostics.deinit(); | 1050 | defer diagnostics.deinit(); |
| 1045 | | 1051 | |
| 1046 | pipeToFileSystem(io, tmp.dir, &reader, .{ | 1052 | extract(io, tmp.dir, &reader, .{ |
| 1047 | .strip_components = 0, | 1053 | .strip_components = 0, |
| 1048 | .diagnostics = &diagnostics, | 1054 | .diagnostics = &diagnostics, |
| 1049 | }) catch |err| { | 1055 | }) catch |err| { |
| ... | @@ -1068,7 +1074,7 @@ test "findRoot with single file archive" { | ... | @@ -1068,7 +1074,7 @@ test "findRoot with single file archive" { |
| 1068 | | 1074 | |
| 1069 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; | 1075 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; |
| 1070 | defer diagnostics.deinit(); | 1076 | defer diagnostics.deinit(); |
| 1071 | try pipeToFileSystem(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); | 1077 | try extract(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); |
| 1072 | | 1078 | |
| 1073 | try testing.expectEqualStrings("", diagnostics.root_dir); | 1079 | try testing.expectEqualStrings("", diagnostics.root_dir); |
| 1074 | } | 1080 | } |
| ... | @@ -1083,12 +1089,12 @@ test "findRoot without explicit root dir" { | ... | @@ -1083,12 +1089,12 @@ test "findRoot without explicit root dir" { |
| 1083 | | 1089 | |
| 1084 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; | 1090 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; |
| 1085 | defer diagnostics.deinit(); | 1091 | defer diagnostics.deinit(); |
| 1086 | try pipeToFileSystem(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); | 1092 | try extract(io, tmp.dir, &reader, .{ .diagnostics = &diagnostics }); |
| 1087 | | 1093 | |
| 1088 | try testing.expectEqualStrings("root", diagnostics.root_dir); | 1094 | try testing.expectEqualStrings("root", diagnostics.root_dir); |
| 1089 | } | 1095 | } |
| 1090 | | 1096 | |
| 1091 | test "pipeToFileSystem strip_components" { | 1097 | test "extract strip_components" { |
| 1092 | const io = testing.io; | 1098 | const io = testing.io; |
| 1093 | const data = @embedFile("tar/testdata/example.tar"); | 1099 | const data = @embedFile("tar/testdata/example.tar"); |
| 1094 | var reader: Io.Reader = .fixed(data); | 1100 | var reader: Io.Reader = .fixed(data); |
| ... | @@ -1098,7 +1104,7 @@ test "pipeToFileSystem strip_components" { | ... | @@ -1098,7 +1104,7 @@ test "pipeToFileSystem strip_components" { |
| 1098 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; | 1104 | var diagnostics: Diagnostics = .{ .allocator = testing.allocator }; |
| 1099 | defer diagnostics.deinit(); | 1105 | defer diagnostics.deinit(); |
| 1100 | | 1106 | |
| 1101 | pipeToFileSystem(io, tmp.dir, &reader, .{ | 1107 | extract(io, tmp.dir, &reader, .{ |
| 1102 | .strip_components = 3, | 1108 | .strip_components = 3, |
| 1103 | .diagnostics = &diagnostics, | 1109 | .diagnostics = &diagnostics, |
| 1104 | }) catch |err| { | 1110 | }) catch |err| { |
| ... | @@ -1120,7 +1126,7 @@ fn normalizePath(bytes: []u8) []u8 { | ... | @@ -1120,7 +1126,7 @@ fn normalizePath(bytes: []u8) []u8 { |
| 1120 | } | 1126 | } |
| 1121 | | 1127 | |
| 1122 | // File system mode based on tar header mode and mode_mode options. | 1128 | // File system mode based on tar header mode and mode_mode options. |
| 1123 | fn filePermissions(mode: u32, options: PipeOptions) Io.File.Permissions { | 1129 | fn filePermissions(mode: u32, options: ExtractOptions) Io.File.Permissions { |
| 1124 | return if (!Io.File.Permissions.has_executable_bit or options.mode_mode == .ignore or (mode & 0o100) == 0) | 1130 | return if (!Io.File.Permissions.has_executable_bit or options.mode_mode == .ignore or (mode & 0o100) == 0) |
| 1125 | .default_file | 1131 | .default_file |
| 1126 | else | 1132 | else |
| ... | @@ -1142,13 +1148,13 @@ test "executable bit" { | ... | @@ -1142,13 +1148,13 @@ test "executable bit" { |
| 1142 | const S = std.posix.S; | 1148 | const S = std.posix.S; |
| 1143 | const data = @embedFile("tar/testdata/example.tar"); | 1149 | const data = @embedFile("tar/testdata/example.tar"); |
| 1144 | | 1150 | |
| 1145 | for ([_]PipeOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| { | 1151 | for ([_]ExtractOptions.ModeMode{ .ignore, .executable_bit_only }) |opt| { |
| 1146 | var reader: Io.Reader = .fixed(data); | 1152 | var reader: Io.Reader = .fixed(data); |
| 1147 | | 1153 | |
| 1148 | var tmp = testing.tmpDir(.{ .follow_symlinks = false }); | 1154 | var tmp = testing.tmpDir(.{ .follow_symlinks = false }); |
| 1149 | //defer tmp.cleanup(); | 1155 | //defer tmp.cleanup(); |
| 1150 | | 1156 | |
| 1151 | pipeToFileSystem(io, tmp.dir, &reader, .{ | 1157 | extract(io, tmp.dir, &reader, .{ |
| 1152 | .strip_components = 1, | 1158 | .strip_components = 1, |
| 1153 | .exclude_empty_directories = true, | 1159 | .exclude_empty_directories = true, |
| 1154 | .mode_mode = opt, | 1160 | .mode_mode = opt, |