Skip Menu |

This queue is for tickets about the Archive-Tar-Builder CPAN distribution.

Report information
The Basics
Id: 115370
Status: new
Priority: 0/
Queue: Archive-Tar-Builder

People
Owner: Nobody in particular
Requestors: mjgardner [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 2.0000
Fixed in: (no value)



Subject: Truncates symlink destinations even with GNU extensions on
When building an archive with symbolic links containing long (>100 character) destinations, those destinations are truncated in the resulting tar archive. I've attached a test script that demonstrates the issue; it uses Archive::Tar::Wrapper and the first binary named "gnutar", "gtar" or "tar" in one's path to extract the archive built by Archive::Tar::Builder.
Subject: Archive-Tar-Builder_longsymlink.t
#!/usr/bin/env perl use strict; use warnings; use English '-no_match_vars'; use Test::More tests => 4; use Test::TempDir::Tiny; use Archive::Tar::Builder; use Archive::Tar::Wrapper; use Const::Fast; use File::Temp; use IO::All; use List::Util 'first'; # find a GNU tar executable in path with which to validate Archive::Tar::Builder my @executable = grep { $_->is_executable } map { $_->all_files } map { io->dir($_) } io->path; my $TAR_EXECUTABLE; for my $executable (@executable) { $TAR_EXECUTABLE = first {$executable->filename eq $_} qw(gnutar gtar tar) and last; } const my $PATH_SEPARATOR => '/'; const my $NAME_LENGTH => 10; const my $DIR_COUNT => 20; # make some long paths out of x's and y's my @paths = map { join $PATH_SEPARATOR => ( $_ x $NAME_LENGTH ) x $DIR_COUNT } qw(x y); # make and enter the source directory my $temp_dir = tempdir($PROGRAM_NAME); my $temp_io = io->dir($temp_dir); $temp_io->chdir; # create file and symlink from @paths, including all intervening dirs my @file = ( sub { shift->assert->touch }, sub { shift->link->assert } ); $file[$_] = $file[$_]->( io->catfile( $temp_dir, $paths[$_] ) )->relative($temp_io) for 0 .. $#file; # set the link target my $link_target = $file[0]->pathname; $link_target =~ s/^$temp_dir\///; $file[1]->symlink('../' x ($DIR_COUNT - 1) . $link_target); # get a list of all dirs and files to archive my @file_io = map { $_->relative($temp_io) } $temp_io->deep->all; # build tar file my $tar_file = File::Temp->new; my $tar_build = Archive::Tar::Builder->new(gnu_extensions => 1); $tar_build->set_handle($tar_file); ok( $tar_build->archive(map {"$_"} @file_io), 'built tar'); $tar_build->finish; # test overall archive file my $tar_wrap = Archive::Tar::Wrapper->new(tar => $TAR_EXECUTABLE, dirs => 1); ok($tar_wrap->read($tar_file), 'read tar'); ok($tar_wrap->is_gnu(), 'is GNU tar'); # test symlink and destination my $unarchived_symlink = (io->dir($tar_wrap->tardir)->deep->filter( sub {$_->type eq 'link'} )->all)[0]; is( $unarchived_symlink->readlink->pathname, $file[1]->readlink->pathname, 'symlink targets match', );