| ... | ... | @@ -536,14 +536,15 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi |
| 536 | 536 | while (try iter.next()) |file| { |
| 537 | 537 | switch (file.kind) { |
| 538 | 538 | .directory => { |
| 539 | | const file_name = try stripComponents(file.name, options.strip_components); |
| 539 | const file_name = stripComponents(file.name, options.strip_components); |
| 540 | 540 | if (file_name.len != 0 and !options.exclude_empty_directories) { |
| 541 | 541 | try dir.makePath(file_name); |
| 542 | 542 | } |
| 543 | 543 | }, |
| 544 | 544 | .normal => { |
| 545 | 545 | if (file.size == 0 and file.name.len == 0) return; |
| 546 | | const file_name = try stripComponents(file.name, options.strip_components); |
| 546 | const file_name = stripComponents(file.name, options.strip_components); |
| 547 | if (file_name.len == 0) return error.BadFileName; |
| 547 | 548 | |
| 548 | 549 | const fs_file = dir.createFile(file_name, .{}) catch |err| switch (err) { |
| 549 | 550 | error.FileNotFound => again: { |
| ... | ... | @@ -575,7 +576,8 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi |
| 575 | 576 | }, |
| 576 | 577 | .symbolic_link => { |
| 577 | 578 | // The file system path of the symbolic link. |
| 578 | | const file_name = try stripComponents(file.name, options.strip_components); |
| 579 | const file_name = stripComponents(file.name, options.strip_components); |
| 580 | if (file_name.len == 0) return error.BadFileName; |
| 579 | 581 | // The data inside the symbolic link. |
| 580 | 582 | const link_name = file.link_name; |
| 581 | 583 | |
| ... | ... | @@ -604,14 +606,15 @@ pub fn pipeToFileSystem(dir: std.fs.Dir, reader: anytype, options: Options) !voi |
| 604 | 606 | } |
| 605 | 607 | } |
| 606 | 608 | |
| 607 | | fn stripComponents(path: []const u8, count: u32) ![]const u8 { |
| 609 | fn stripComponents(path: []const u8, count: u32) []const u8 { |
| 608 | 610 | var i: usize = 0; |
| 609 | 611 | var c = count; |
| 610 | 612 | while (c > 0) : (c -= 1) { |
| 611 | 613 | if (std.mem.indexOfScalarPos(u8, path, i, '/')) |pos| { |
| 612 | 614 | i = pos + 1; |
| 613 | 615 | } else { |
| 614 | | return error.TarComponentsOutsideStrippedPrefix; |
| 616 | i = path.len; |
| 617 | break; |
| 615 | 618 | } |
| 616 | 619 | } |
| 617 | 620 | return path[i..]; |
| ... | ... | @@ -619,9 +622,11 @@ fn stripComponents(path: []const u8, count: u32) ![]const u8 { |
| 619 | 622 | |
| 620 | 623 | test "tar stripComponents" { |
| 621 | 624 | const expectEqualStrings = std.testing.expectEqualStrings; |
| 622 | | try expectEqualStrings("a/b/c", try stripComponents("a/b/c", 0)); |
| 623 | | try expectEqualStrings("b/c", try stripComponents("a/b/c", 1)); |
| 624 | | try expectEqualStrings("c", try stripComponents("a/b/c", 2)); |
| 625 | try expectEqualStrings("a/b/c", stripComponents("a/b/c", 0)); |
| 626 | try expectEqualStrings("b/c", stripComponents("a/b/c", 1)); |
| 627 | try expectEqualStrings("c", stripComponents("a/b/c", 2)); |
| 628 | try expectEqualStrings("", stripComponents("a/b/c", 3)); |
| 629 | try expectEqualStrings("", stripComponents("a/b/c", 4)); |
| 625 | 630 | } |
| 626 | 631 | |
| 627 | 632 | test "tar PaxIterator" { |