Archive-Tar-Stream
view release on metacpan or search on metacpan
lib/Archive/Tar/Stream.pm view on Meta::CPAN
my $header = $Self->BlankHeader(@_, name => $name, size => $size);
return $size ? $Self->WriteFromFh($fh, $header) : $Self->WriteHeader($header);
}
=head2 AddLink
my $header = $ts->AddLink($name, $linkname, %extra);
Adds a symlink to the output filehandle.
See TARHEADER for documentation of the header fields.
Returns the complete header that was written.
=cut
sub AddLink {
my $Self = shift;
my $name = shift;
my $linkname = shift;
my $header = $Self->BlankHeader(typeflag => 2, @_, name => $name, linkname => $linkname);
return $Self->WriteHeader($header);
}
=head2 StreamCopy
Streams all records from the input filehandle and provides
an easy way to write them to the output filehandle.
Requires: infh
Optional: outfh - required if you return 'KEEP'
$ts->StreamCopy(sub {
my ($header, $outpos, $fh) = @_;
# ...
return 'KEEP';
});
The chooser function can either return a single 'action' or
a tuple of action and a new header.
The action can be:
KEEP - copy this file as is (possibly changed header) to output tar
EDIT - re-call $Chooser with filehandle
SKIP - skip over the file and call $Chooser on the next one
EXIT - skip and also stop further processing
EDIT mode:
the file will be copied to a temporary file and the filehandle passed to
$Chooser. It can truncate, rewrite, edit - whatever. So long as it updates
$header->{size} and returns it as $newheader it's all good.
you don't have to change the file of course, it's also good just as a way to
view the contents of some files as you stream them.
A standard usage pattern looks like this:
$ts->StreamCopy(sub {
my ($header, $outpos, $fs) = @_;
# simple checks
return 'KEEP' if do_want($header);
return 'SKIP' if dont_want($header);
return 'EDIT' unless $fh;
# checks that require a filehandle
});
=cut
sub StreamCopy {
my $Self = shift;
my $Chooser = shift;
while (my $header = $Self->ReadHeader()) {
my $pos = $header->{_pos};
if ($Chooser) {
my ($rc, $newheader) = $Chooser->($header, $Self->{outpos}, undef);
my $TempFile;
my $Edited;
# positive code means read the file
if ($rc eq 'EDIT') {
$Edited = 1;
$TempFile = $Self->CopyToTempFile($header->{size});
# call chooser again with the contents
($rc, $newheader) = $Chooser->($newheader || $header, $Self->{outpos}, $TempFile);
seek($TempFile, 0, 0);
}
# short circuit exit code
return if $rc eq 'EXIT';
# NOTE: even the size could have been changed if it's an edit!
$header = $newheader if $newheader;
if ($rc eq 'KEEP') {
print "KEEP $header->{name} $pos/$Self->{outpos}\n" if $VERBOSE;
if ($TempFile) {
$Self->WriteFromFh($TempFile, $header);
}
# guarantee safety by getting everything into a temporary file first
elsif ($Self->{safe_copy} and $header->{size}) {
$TempFile = $Self->CopyToTempFile($header->{size});
$Self->WriteFromFh($TempFile, $header);
}
else {
$Self->WriteCopy($header);
}
}
# anything else means discard it
elsif ($rc eq 'SKIP') {
if ($TempFile) {
( run in 1.915 second using v1.01-cache-2.11-cpan-39bf76dae61 )