Skip to content

Commit 12ecea4

Browse files
palvarez89gitster
authored andcommitted
import-tars: read overlong names from pax extended header
Importing gcc tarballs[1] with import-tars script (in contrib) fails when hitting a pax extended header. Make sure we always read the extended attributes from the pax entries, and store the 'path' value if found to be used in the next ustar entry. The code to parse pax extended headers was written consulting the Pax Pax Interchange Format documentation [2]. [1] http://ftp.gnu.org/gnu/gcc/gcc-7.3.0/gcc-7.3.0.tar.xz [2] https://www.freebsd.org/cgi/man.cgi?manpath=FreeBSD+8-current&query=tar&sektion=5 Signed-off-by: Pedro Alvarez <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 468165c commit 12ecea4

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

contrib/fast-import/import-tars.perl

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,22 @@
6363
my $have_top_dir = 1;
6464
my ($top_dir, %files);
6565

66+
my $next_path = '';
67+
6668
while (read(I, $_, 512) == 512) {
6769
my ($name, $mode, $uid, $gid, $size, $mtime,
6870
$chksum, $typeflag, $linkname, $magic,
6971
$version, $uname, $gname, $devmajor, $devminor,
7072
$prefix) = unpack 'Z100 Z8 Z8 Z8 Z12 Z12
7173
Z8 Z1 Z100 Z6
7274
Z2 Z32 Z32 Z8 Z8 Z*', $_;
75+
76+
unless ($next_path eq '') {
77+
# Recover name from previous extended header
78+
$name = $next_path;
79+
$next_path = '';
80+
}
81+
7382
last unless length($name);
7483
if ($name eq '././@LongLink') {
7584
# GNU tar extension
@@ -90,13 +99,31 @@
9099
Z8 Z1 Z100 Z6
91100
Z2 Z32 Z32 Z8 Z8 Z*', $_;
92101
}
93-
next if $name =~ m{/\z};
94102
$mode = oct $mode;
95103
$size = oct $size;
96104
$mtime = oct $mtime;
97105
next if $typeflag == 5; # directory
98106

99-
if ($typeflag != 1) { # handle hard links later
107+
if ($typeflag eq 'x') { # extended header
108+
# If extended header, check for path
109+
my $pax_header = '';
110+
while ($size > 0 && read(I, $_, 512) == 512) {
111+
$pax_header = $pax_header . substr($_, 0, $size);
112+
$size -= 512;
113+
}
114+
115+
my @lines = split /\n/, $pax_header;
116+
foreach my $line (@lines) {
117+
my ($len, $entry) = split / /, $line;
118+
my ($key, $value) = split /=/, $entry;
119+
if ($key eq 'path') {
120+
$next_path = $value;
121+
}
122+
}
123+
next;
124+
} elsif ($name =~ m{/\z}) { # directory
125+
next;
126+
} elsif ($typeflag != 1) { # handle hard links later
100127
print FI "blob\n", "mark :$next_mark\n";
101128
if ($typeflag == 2) { # symbolic link
102129
print FI "data ", length($linkname), "\n",

0 commit comments

Comments
 (0)