path: root/contrib
diff options
authorJohannes Schindelin <>2007-05-01 21:42:44 (GMT)
committerShawn O. Pearce <>2007-05-02 17:22:34 (GMT)
commit775477aa1da94cb9fb9b9afdc217231a0cd42ac1 (patch)
treeb503ff64c120c824e60a30abcdb891b3396d3be3 /contrib
parentb5cc62f701abf8b903387a5d7c77a59f347d66fd (diff)
Teach import-tars about GNU tar's @LongLink extension.
This extension allows GNU tar to process file names in excess of the 100 characters defined by the original tar standard. It does this by faking a file, named '././@LongLink' containing the true file name, and then adding the file with a truncated name. The idea is that tar without this extension will write out a file with the long file name, and write the contents into a file with truncated name. Unfortunately, GNU tar does a lousy job at times. When truncating results in a _directory_ name, it will happily use _that_ as a truncated name for the file. An example where this actually happens is gcc-4.1.2, where the full path of the file truncates _exactly_ before the basename. So, we have to support that ad-hoc extension. This bug was noticed by Chris Riddoch on IRC. Signed-off-by: Johannes Schindelin <> Signed-off-by: Shawn O. Pearce <>
Diffstat (limited to 'contrib')
1 files changed, 19 insertions, 0 deletions
diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl
index 82a9042..e464920 100755
--- a/contrib/fast-import/import-tars.perl
+++ b/contrib/fast-import/import-tars.perl
@@ -52,6 +52,25 @@ foreach my $tar_file (@ARGV)
Z8 Z1 Z100 Z6
Z2 Z32 Z32 Z8 Z8 Z*', $_;
last unless $name;
+ if ($name eq '././@LongLink') {
+ # GNU tar extension
+ if (read(I, $_, 512) != 512) {
+ die ('Short archive');
+ }
+ $name = unpack 'Z257', $_;
+ next unless $name;
+ my $dummy;
+ if (read(I, $_, 512) != 512) {
+ die ('Short archive');
+ }
+ ($dummy, $mode, $uid, $gid, $size, $mtime,
+ $chksum, $typeflag, $linkname, $magic,
+ $version, $uname, $gname, $devmajor, $devminor,
+ $prefix) = unpack 'Z100 Z8 Z8 Z8 Z12 Z12
+ Z8 Z1 Z100 Z6
+ Z2 Z32 Z32 Z8 Z8 Z*', $_;
+ }
next if $name =~ m{/\z};
$mode = oct $mode;
$size = oct $size;