authorgravatar for igor.anic@gmail.comIgor Anić <igor.anic@gmail.com> 2023-11-27 22:23:16+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-13 19:37:33-07:00
logbe5d04ab7922d84b59dad06de3df378b94827d4a
tree814b071b6cc5cdd30d4398f557039e4a1b06606b
parent18170633754afb68c5831bfe4534c64af93ba55b

tar: add pax linkpath attribute parsing

Name of symbolic link can be also found in pax attribute.

1 files changed, 25 insertions(+), 16 deletions(-)

lib/std/tar.zig+25-16
...@@ -226,6 +226,9 @@ fn Iterator(comptime ReaderType: type) type {...@@ -226,6 +226,9 @@ fn Iterator(comptime ReaderType: type) type {
226 return struct {226 return struct {
227 file_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined,227 file_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined,
228 file_name_len: usize = 0,228 file_name_len: usize = 0,
229 link_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined,
230 link_name_len: usize = 0,
231
229 reader: BufferedReader(ReaderType),232 reader: BufferedReader(ReaderType),
230 diagnostics: ?*Options.Diagnostics,233 diagnostics: ?*Options.Diagnostics,
231234
...@@ -275,6 +278,8 @@ fn Iterator(comptime ReaderType: type) type {...@@ -275,6 +278,8 @@ fn Iterator(comptime ReaderType: type) type {
275278
276 pub fn next(self: *Self) !?File {279 pub fn next(self: *Self) !?File {
277 self.file_name_len = 0;280 self.file_name_len = 0;
281 self.link_name_len = 0;
282
278 while (true) {283 while (true) {
279 const chunk = try self.reader.readChunk(1024);284 const chunk = try self.reader.readChunk(1024);
280 switch (chunk.len) {285 switch (chunk.len) {
...@@ -287,10 +292,12 @@ fn Iterator(comptime ReaderType: type) type {...@@ -287,10 +292,12 @@ fn Iterator(comptime ReaderType: type) type {
287 const header: Header = .{ .bytes = chunk[0..512] };292 const header: Header = .{ .bytes = chunk[0..512] };
288 if (header.isZeroBlock()) return null;293 if (header.isZeroBlock()) return null;
289 const file_size = try header.fileSize();294 const file_size = try header.fileSize();
290 const file_type = header.fileType();
291 const link_name = header.linkName();
292 const rounded_file_size: usize = std.mem.alignForward(usize, file_size, 512);295 const rounded_file_size: usize = std.mem.alignForward(usize, file_size, 512);
293296 const file_type = header.fileType();
297 const link_name = if (self.link_name_len == 0)
298 header.linkName()
299 else
300 self.link_name_buffer[0..self.link_name_len];
294 const file_name = if (self.file_name_len == 0)301 const file_name = if (self.file_name_len == 0)
295 try header.fullFileName(&self.file_name_buffer)302 try header.fullFileName(&self.file_name_buffer)
296 else303 else
...@@ -314,7 +321,7 @@ fn Iterator(comptime ReaderType: type) type {...@@ -314,7 +321,7 @@ fn Iterator(comptime ReaderType: type) type {
314321
315 const chunk_size: usize = rounded_file_size + 512;322 const chunk_size: usize = rounded_file_size + 512;
316 var data_off: usize = 0;323 var data_off: usize = 0;
317 const file_name_override_len = while (data_off < file_size) {324 while (data_off < file_size) {
318 const slice = try self.reader.readChunk(chunk_size - data_off);325 const slice = try self.reader.readChunk(chunk_size - data_off);
319 if (slice.len == 0) return error.UnexpectedEndOfStream;326 if (slice.len == 0) return error.UnexpectedEndOfStream;
320 const remaining_size: usize = file_size - data_off;327 const remaining_size: usize = file_size - data_off;
...@@ -323,18 +330,22 @@ fn Iterator(comptime ReaderType: type) type {...@@ -323,18 +330,22 @@ fn Iterator(comptime ReaderType: type) type {
323 if (std.mem.eql(u8, attr_info.key, "path")) {330 if (std.mem.eql(u8, attr_info.key, "path")) {
324 if (attr_info.value_len > self.file_name_buffer.len) return error.NameTooLong;331 if (attr_info.value_len > self.file_name_buffer.len) return error.NameTooLong;
325 self.reader.advance(attr_info.value_off);332 self.reader.advance(attr_info.value_off);
326 data_off += attr_info.value_off;333 try self.reader.copy(&self.file_name_buffer, attr_info.value_len);
327 break attr_info.value_len;334 self.file_name_len = attr_info.value_len;
335 self.reader.advance(1);
336 } else if (std.mem.eql(u8, attr_info.key, "linkpath")) {
337 if (attr_info.value_len > self.link_name_buffer.len) return error.NameTooLong;
338 self.reader.advance(attr_info.value_off);
339 try self.reader.copy(&self.link_name_buffer, attr_info.value_len);
340 self.link_name_len = attr_info.value_len;
341 self.reader.advance(1);
342 } else {
343 try self.reader.skip(attr_info.size);
328 }344 }
329
330 try self.reader.skip(attr_info.size);
331 data_off += attr_info.size;345 data_off += attr_info.size;
332 } else 0;346 }
333347 try self.reader.skip(rounded_file_size - data_off);
334 try self.reader.copy(&self.file_name_buffer, file_name_override_len);
335348
336 try self.reader.skip(rounded_file_size - data_off - file_name_override_len);
337 self.file_name_len = file_name_override_len;
338 continue;349 continue;
339 },350 },
340 .hard_link => return error.TarUnsupportedFileType,351 .hard_link => return error.TarUnsupportedFileType,
...@@ -599,9 +610,7 @@ test "Go test cases" {...@@ -599,9 +610,7 @@ test "Go test cases" {
599 .name = "a/b",610 .name = "a/b",
600 .size = 0,611 .size = 0,
601 .file_type = .symbolic_link,612 .file_type = .symbolic_link,
602 .link_name = "1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545",613 .link_name = "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
603 // TODO fix reading link name from pax header
604 // .link_name = "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
605 },614 },
606 },615 },
607 .chksums = &[_][]const u8{616 .chksums = &[_][]const u8{