summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl/lib/Archive
diff options
context:
space:
mode:
authorSiep Kroonenberg <siepo@cybercomm.nl>2011-02-17 12:20:49 +0000
committerSiep Kroonenberg <siepo@cybercomm.nl>2011-02-17 12:20:49 +0000
commit316ee97c621496b0fe3267f57cce81bee44ca1e6 (patch)
treecb2cab1192b4f58a7971af19b213e980bceda4b4 /Master/tlpkg/tlperl/lib/Archive
parentcd0f87b5d39480d85ad9bd4ee37f520f75bed560 (diff)
Moving old tlperl prior to committing new one
git-svn-id: svn://tug.org/texlive/trunk@21422 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlperl/lib/Archive')
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Extract.pm1511
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Tar.pm2146
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Tar/Constant.pm86
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Tar/File.pm660
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip.pm2059
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/Archive.pm978
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/BufferedFileHandle.pm131
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/DirectoryMember.pm80
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/FAQ.pod467
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/FileMember.pm64
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/Member.pm1083
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/MemberRead.pm333
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/MockFileHandle.pm69
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/NewFileMember.pm79
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/StringMember.pm64
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/Tree.pm49
-rwxr-xr-xMaster/tlpkg/tlperl/lib/Archive/Zip/ZipFileMember.pm416
17 files changed, 0 insertions, 10275 deletions
diff --git a/Master/tlpkg/tlperl/lib/Archive/Extract.pm b/Master/tlpkg/tlperl/lib/Archive/Extract.pm
deleted file mode 100755
index 08676fb1e08..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Extract.pm
+++ /dev/null
@@ -1,1511 +0,0 @@
-package Archive::Extract;
-
-use strict;
-
-use Cwd qw[cwd chdir];
-use Carp qw[carp];
-use IPC::Cmd qw[run can_run];
-use FileHandle;
-use File::Path qw[mkpath];
-use File::Spec;
-use File::Basename qw[dirname basename];
-use Params::Check qw[check];
-use Module::Load::Conditional qw[can_load check_install];
-use Locale::Maketext::Simple Style => 'gettext';
-
-### solaris has silly /bin/tar output ###
-use constant ON_SOLARIS => $^O eq 'solaris' ? 1 : 0;
-use constant FILE_EXISTS => sub { -e $_[0] ? 1 : 0 };
-
-### VMS may require quoting upper case command options
-use constant ON_VMS => $^O eq 'VMS' ? 1 : 0;
-
-### Windows needs special treatment of Tar options
-use constant ON_WIN32 => $^O eq 'MSWin32' ? 1 : 0;
-
-### we can't use this extraction method, because of missing
-### modules/binaries:
-use constant METHOD_NA => [];
-
-### If these are changed, update @TYPES and the new() POD
-use constant TGZ => 'tgz';
-use constant TAR => 'tar';
-use constant GZ => 'gz';
-use constant ZIP => 'zip';
-use constant BZ2 => 'bz2';
-use constant TBZ => 'tbz';
-use constant Z => 'Z';
-use constant LZMA => 'lzma';
-
-use vars qw[$VERSION $PREFER_BIN $PROGRAMS $WARN $DEBUG
- $_ALLOW_BIN $_ALLOW_PURE_PERL $_ALLOW_TAR_ITER
- ];
-
-$VERSION = '0.38';
-$PREFER_BIN = 0;
-$WARN = 1;
-$DEBUG = 0;
-$_ALLOW_PURE_PERL = 1; # allow pure perl extractors
-$_ALLOW_BIN = 1; # allow binary extractors
-$_ALLOW_TAR_ITER = 1; # try to use Archive::Tar->iter if available
-
-# same as all constants
-my @Types = ( TGZ, TAR, GZ, ZIP, BZ2, TBZ, Z, LZMA );
-
-local $Params::Check::VERBOSE = $Params::Check::VERBOSE = 1;
-
-=pod
-
-=head1 NAME
-
-Archive::Extract - A generic archive extracting mechanism
-
-=head1 SYNOPSIS
-
- use Archive::Extract;
-
- ### build an Archive::Extract object ###
- my $ae = Archive::Extract->new( archive => 'foo.tgz' );
-
- ### extract to cwd() ###
- my $ok = $ae->extract;
-
- ### extract to /tmp ###
- my $ok = $ae->extract( to => '/tmp' );
-
- ### what if something went wrong?
- my $ok = $ae->extract or die $ae->error;
-
- ### files from the archive ###
- my $files = $ae->files;
-
- ### dir that was extracted to ###
- my $outdir = $ae->extract_path;
-
-
- ### quick check methods ###
- $ae->is_tar # is it a .tar file?
- $ae->is_tgz # is it a .tar.gz or .tgz file?
- $ae->is_gz; # is it a .gz file?
- $ae->is_zip; # is it a .zip file?
- $ae->is_bz2; # is it a .bz2 file?
- $ae->is_tbz; # is it a .tar.bz2 or .tbz file?
- $ae->is_lzma; # is it a .lzma file?
-
- ### absolute path to the archive you provided ###
- $ae->archive;
-
- ### commandline tools, if found ###
- $ae->bin_tar # path to /bin/tar, if found
- $ae->bin_gzip # path to /bin/gzip, if found
- $ae->bin_unzip # path to /bin/unzip, if found
- $ae->bin_bunzip2 # path to /bin/bunzip2 if found
- $ae->bin_unlzma # path to /bin/unlzma if found
-
-=head1 DESCRIPTION
-
-Archive::Extract is a generic archive extraction mechanism.
-
-It allows you to extract any archive file of the type .tar, .tar.gz,
-.gz, .Z, tar.bz2, .tbz, .bz2, .zip or .lzma without having to worry how it
-does so, or use different interfaces for each type by using either
-perl modules, or commandline tools on your system.
-
-See the C<HOW IT WORKS> section further down for details.
-
-=cut
-
-
-### see what /bin/programs are available ###
-$PROGRAMS = {};
-for my $pgm (qw[tar unzip gzip bunzip2 uncompress unlzma]) {
- $PROGRAMS->{$pgm} = can_run($pgm);
-}
-
-### mapping from types to extractor methods ###
-my $Mapping = { # binary program # pure perl module
- is_tgz => { bin => '_untar_bin', pp => '_untar_at' },
- is_tar => { bin => '_untar_bin', pp => '_untar_at' },
- is_gz => { bin => '_gunzip_bin', pp => '_gunzip_cz' },
- is_zip => { bin => '_unzip_bin', pp => '_unzip_az' },
- is_tbz => { bin => '_untar_bin', pp => '_untar_at' },
- is_bz2 => { bin => '_bunzip2_bin', pp => '_bunzip2_bz2'},
- is_Z => { bin => '_uncompress_bin', pp => '_gunzip_cz' },
- is_lzma => { bin => '_unlzma_bin', pp => '_unlzma_cz' },
-};
-
-{ ### use subs so we re-generate array refs etc for the no-overide flags
- ### if we don't, then we reuse the same arrayref, meaning objects store
- ### previous errors
- my $tmpl = {
- archive => sub { { required => 1, allow => FILE_EXISTS } },
- type => sub { { default => '', allow => [ @Types ] } },
- _error_msg => sub { { no_override => 1, default => [] } },
- _error_msg_long => sub { { no_override => 1, default => [] } },
- };
-
- ### build accesssors ###
- for my $method( keys %$tmpl,
- qw[_extractor _gunzip_to files extract_path],
- ) {
- no strict 'refs';
- *$method = sub {
- my $self = shift;
- $self->{$method} = $_[0] if @_;
- return $self->{$method};
- }
- }
-
-=head1 METHODS
-
-=head2 $ae = Archive::Extract->new(archive => '/path/to/archive',[type => TYPE])
-
-Creates a new C<Archive::Extract> object based on the archive file you
-passed it. Automatically determines the type of archive based on the
-extension, but you can override that by explicitly providing the
-C<type> argument.
-
-Valid values for C<type> are:
-
-=over 4
-
-=item tar
-
-Standard tar files, as produced by, for example, C</bin/tar>.
-Corresponds to a C<.tar> suffix.
-
-=item tgz
-
-Gzip compressed tar files, as produced by, for example C</bin/tar -z>.
-Corresponds to a C<.tgz> or C<.tar.gz> suffix.
-
-=item gz
-
-Gzip compressed file, as produced by, for example C</bin/gzip>.
-Corresponds to a C<.gz> suffix.
-
-=item Z
-
-Lempel-Ziv compressed file, as produced by, for example C</bin/compress>.
-Corresponds to a C<.Z> suffix.
-
-=item zip
-
-Zip compressed file, as produced by, for example C</bin/zip>.
-Corresponds to a C<.zip>, C<.jar> or C<.par> suffix.
-
-=item bz2
-
-Bzip2 compressed file, as produced by, for example, C</bin/bzip2>.
-Corresponds to a C<.bz2> suffix.
-
-=item tbz
-
-Bzip2 compressed tar file, as produced by, for exmample C</bin/tar -j>.
-Corresponds to a C<.tbz> or C<.tar.bz2> suffix.
-
-=item lzma
-
-Lzma compressed file, as produced by C</bin/lzma>.
-Corresponds to a C<.lzma> suffix.
-
-=back
-
-Returns a C<Archive::Extract> object on success, or false on failure.
-
-=cut
-
- ### constructor ###
- sub new {
- my $class = shift;
- my %hash = @_;
-
- ### see above why we use subs here and generate the template;
- ### it's basically to not re-use arrayrefs
- my %utmpl = map { $_ => $tmpl->{$_}->() } keys %$tmpl;
-
- my $parsed = check( \%utmpl, \%hash ) or return;
-
- ### make sure we have an absolute path ###
- my $ar = $parsed->{archive} = File::Spec->rel2abs( $parsed->{archive} );
-
- ### figure out the type, if it wasn't already specified ###
- unless ( $parsed->{type} ) {
- $parsed->{type} =
- $ar =~ /.+?\.(?:tar\.gz|tgz)$/i ? TGZ :
- $ar =~ /.+?\.gz$/i ? GZ :
- $ar =~ /.+?\.tar$/i ? TAR :
- $ar =~ /.+?\.(zip|jar|par)$/i ? ZIP :
- $ar =~ /.+?\.(?:tbz2?|tar\.bz2?)$/i ? TBZ :
- $ar =~ /.+?\.bz2$/i ? BZ2 :
- $ar =~ /.+?\.Z$/ ? Z :
- $ar =~ /.+?\.lzma$/ ? LZMA :
- '';
-
- }
-
- bless $parsed, $class;
-
- ### don't know what type of file it is
- ### XXX this *has* to be an object call, not a package call
- return $parsed->_error(loc("Cannot determine file type for '%1'",
- $parsed->{archive} )) unless $parsed->{type};
- return $parsed;
- }
-}
-
-=head2 $ae->extract( [to => '/output/path'] )
-
-Extracts the archive represented by the C<Archive::Extract> object to
-the path of your choice as specified by the C<to> argument. Defaults to
-C<cwd()>.
-
-Since C<.gz> files never hold a directory, but only a single file; if
-the C<to> argument is an existing directory, the file is extracted
-there, with its C<.gz> suffix stripped.
-If the C<to> argument is not an existing directory, the C<to> argument
-is understood to be a filename, if the archive type is C<gz>.
-In the case that you did not specify a C<to> argument, the output
-file will be the name of the archive file, stripped from its C<.gz>
-suffix, in the current working directory.
-
-C<extract> will try a pure perl solution first, and then fall back to
-commandline tools if they are available. See the C<GLOBAL VARIABLES>
-section below on how to alter this behaviour.
-
-It will return true on success, and false on failure.
-
-On success, it will also set the follow attributes in the object:
-
-=over 4
-
-=item $ae->extract_path
-
-This is the directory that the files where extracted to.
-
-=item $ae->files
-
-This is an array ref with the paths of all the files in the archive,
-relative to the C<to> argument you specified.
-To get the full path to an extracted file, you would use:
-
- File::Spec->catfile( $to, $ae->files->[0] );
-
-Note that all files from a tar archive will be in unix format, as per
-the tar specification.
-
-=back
-
-=cut
-
-sub extract {
- my $self = shift;
- my %hash = @_;
-
- ### reset error messages
- $self->_error_msg( [] );
- $self->_error_msg_long( [] );
-
- my $to;
- my $tmpl = {
- to => { default => '.', store => \$to }
- };
-
- check( $tmpl, \%hash ) or return;
-
- ### so 'to' could be a file or a dir, depending on whether it's a .gz
- ### file, or basically anything else.
- ### so, check that, then act accordingly.
- ### set an accessor specifically so _gunzip can know what file to extract
- ### to.
- my $dir;
- { ### a foo.gz file
- if( $self->is_gz or $self->is_bz2 or $self->is_Z or $self->is_lzma ) {
-
- my $cp = $self->archive; $cp =~ s/\.(?:gz|bz2?|Z|lzma)$//i;
-
- ### to is a dir?
- if ( -d $to ) {
- $dir = $to;
- $self->_gunzip_to( basename($cp) );
-
- ### then it's a filename
- } else {
- $dir = dirname($to);
- $self->_gunzip_to( basename($to) );
- }
-
- ### not a foo.gz file
- } else {
- $dir = $to;
- }
- }
-
- ### make the dir if it doesn't exist ###
- unless( -d $dir ) {
- eval { mkpath( $dir ) };
-
- return $self->_error(loc("Could not create path '%1': %2", $dir, $@))
- if $@;
- }
-
- ### get the current dir, to restore later ###
- my $cwd = cwd();
-
- my $ok = 1;
- EXTRACT: {
-
- ### chdir to the target dir ###
- unless( chdir $dir ) {
- $self->_error(loc("Could not chdir to '%1': %2", $dir, $!));
- $ok = 0; last EXTRACT;
- }
-
- ### set files to an empty array ref, so there's always an array
- ### ref IN the accessor, to avoid errors like:
- ### Can't use an undefined value as an ARRAY reference at
- ### ../lib/Archive/Extract.pm line 742. (rt #19815)
- $self->files( [] );
-
- ### find out the dispatch methods needed for this type of
- ### archive. Do a $self->is_XXX to figure out the type, then
- ### get the hashref with bin + pure perl dispatchers.
- my ($map) = map { $Mapping->{$_} } grep { $self->$_ } keys %$Mapping;
-
- ### add pure perl extractor if allowed & add bin extractor if allowed
- my @methods;
- push @methods, $map->{'pp'} if $_ALLOW_PURE_PERL;
- push @methods, $map->{'bin'} if $_ALLOW_BIN;
-
- ### reverse it if we prefer bin extractors
- @methods = reverse @methods if $PREFER_BIN;
-
- my($na, $fail);
- for my $method (@methods) {
- print "# Extracting with ->$method\n" if $DEBUG;
-
- my $rv = $self->$method;
-
- ### a positive extraction
- if( $rv and $rv ne METHOD_NA ) {
- print "# Extraction succeeded\n" if $DEBUG;
- $self->_extractor($method);
- last;
-
- ### method is not available
- } elsif ( $rv and $rv eq METHOD_NA ) {
- print "# Extraction method not available\n" if $DEBUG;
- $na++;
- } else {
- print "# Extraction method failed\n" if $DEBUG;
- $fail++;
- }
- }
-
- ### warn something went wrong if we didn't get an extractor
- unless( $self->_extractor ) {
- my $diag = $fail ? loc("Extract failed due to errors") :
- $na ? loc("Extract failed; no extractors available") :
- '';
-
- $self->_error($diag);
- $ok = 0;
- }
- }
-
- ### and chdir back ###
- unless( chdir $cwd ) {
- $self->_error(loc("Could not chdir back to start dir '%1': %2'",
- $cwd, $!));
- }
-
- return $ok;
-}
-
-=pod
-
-=head1 ACCESSORS
-
-=head2 $ae->error([BOOL])
-
-Returns the last encountered error as string.
-Pass it a true value to get the C<Carp::longmess()> output instead.
-
-=head2 $ae->extract_path
-
-This is the directory the archive got extracted to.
-See C<extract()> for details.
-
-=head2 $ae->files
-
-This is an array ref holding all the paths from the archive.
-See C<extract()> for details.
-
-=head2 $ae->archive
-
-This is the full path to the archive file represented by this
-C<Archive::Extract> object.
-
-=head2 $ae->type
-
-This is the type of archive represented by this C<Archive::Extract>
-object. See accessors below for an easier way to use this.
-See the C<new()> method for details.
-
-=head2 $ae->types
-
-Returns a list of all known C<types> for C<Archive::Extract>'s
-C<new> method.
-
-=cut
-
-sub types { return @Types }
-
-=head2 $ae->is_tgz
-
-Returns true if the file is of type C<.tar.gz>.
-See the C<new()> method for details.
-
-=head2 $ae->is_tar
-
-Returns true if the file is of type C<.tar>.
-See the C<new()> method for details.
-
-=head2 $ae->is_gz
-
-Returns true if the file is of type C<.gz>.
-See the C<new()> method for details.
-
-=head2 $ae->is_Z
-
-Returns true if the file is of type C<.Z>.
-See the C<new()> method for details.
-
-=head2 $ae->is_zip
-
-Returns true if the file is of type C<.zip>.
-See the C<new()> method for details.
-
-=head2 $ae->is_lzma
-
-Returns true if the file is of type C<.lzma>.
-See the C<new()> method for details.
-
-=cut
-
-### quick check methods ###
-sub is_tgz { return $_[0]->type eq TGZ }
-sub is_tar { return $_[0]->type eq TAR }
-sub is_gz { return $_[0]->type eq GZ }
-sub is_zip { return $_[0]->type eq ZIP }
-sub is_tbz { return $_[0]->type eq TBZ }
-sub is_bz2 { return $_[0]->type eq BZ2 }
-sub is_Z { return $_[0]->type eq Z }
-sub is_lzma { return $_[0]->type eq LZMA }
-
-=pod
-
-=head2 $ae->bin_tar
-
-Returns the full path to your tar binary, if found.
-
-=head2 $ae->bin_gzip
-
-Returns the full path to your gzip binary, if found
-
-=head2 $ae->bin_unzip
-
-Returns the full path to your unzip binary, if found
-
-=head2 $ae->bin_unlzma
-
-Returns the full path to your unlzma binary, if found
-
-=cut
-
-### paths to commandline tools ###
-sub bin_gzip { return $PROGRAMS->{'gzip'} if $PROGRAMS->{'gzip'} }
-sub bin_unzip { return $PROGRAMS->{'unzip'} if $PROGRAMS->{'unzip'} }
-sub bin_tar { return $PROGRAMS->{'tar'} if $PROGRAMS->{'tar'} }
-sub bin_bunzip2 { return $PROGRAMS->{'bunzip2'} if $PROGRAMS->{'bunzip2'} }
-sub bin_uncompress { return $PROGRAMS->{'uncompress'}
- if $PROGRAMS->{'uncompress'} }
-sub bin_unlzma { return $PROGRAMS->{'unlzma'} if $PROGRAMS->{'unlzma'} }
-
-=head2 $bool = $ae->have_old_bunzip2
-
-Older versions of C</bin/bunzip2>, from before the C<bunzip2 1.0> release,
-require all archive names to end in C<.bz2> or it will not extract
-them. This method checks if you have a recent version of C<bunzip2>
-that allows any extension, or an older one that doesn't.
-
-=cut
-
-sub have_old_bunzip2 {
- my $self = shift;
-
- ### no bunzip2? no old bunzip2 either :)
- return unless $self->bin_bunzip2;
-
- ### if we can't run this, we can't be sure if it's too old or not
- ### XXX stupid stupid stupid bunzip2 doesn't understand --version
- ### is not a request to extract data:
- ### $ bunzip2 --version
- ### bzip2, a block-sorting file compressor. Version 1.0.2, 30-Dec-2001.
- ### [...]
- ### bunzip2: I won't read compressed data from a terminal.
- ### bunzip2: For help, type: `bunzip2 --help'.
- ### $ echo $?
- ### 1
- ### HATEFUL!
-
- ### double hateful: bunzip2 --version also hangs if input is a pipe
- ### See #32370: Archive::Extract will hang if stdin is a pipe [+PATCH]
- ### So, we have to provide *another* argument which is a fake filename,
- ### just so it wont try to read from stdin to print its version..
- ### *sigh*
- ### Even if the file exists, it won't clobber or change it.
- my $buffer;
- scalar run(
- command => [$self->bin_bunzip2, '--version', 'NoSuchFile'],
- verbose => 0,
- buffer => \$buffer
- );
-
- ### no output
- return unless $buffer;
-
- my ($version) = $buffer =~ /version \s+ (\d+)/ix;
-
- return 1 if $version < 1;
- return;
-}
-
-#################################
-#
-# Untar code
-#
-#################################
-
-### annoying issue with (gnu) tar on win32, as illustrated by this
-### bug: https://rt.cpan.org/Ticket/Display.html?id=40138
-### which shows that (gnu) tar will interpret a file name with a :
-### in it as a remote file name, so C:\tmp\foo.txt is interpreted
-### as a remote shell, and the extract fails.
-{ my @ExtraTarFlags;
- if( ON_WIN32 and my $cmd = __PACKAGE__->bin_tar ) {
-
- ### if this is gnu tar we are running, we need to use --force-local
- push @ExtraTarFlags, '--force-local' if `$cmd --version` =~ /gnu tar/i;
- }
-
-
- ### use /bin/tar to extract ###
- sub _untar_bin {
- my $self = shift;
-
- ### check for /bin/tar ###
- ### check for /bin/gzip if we need it ###
- ### if any of the binaries are not available, return NA
- { my $diag = not $self->bin_tar ?
- loc("No '%1' program found", '/bin/tar') :
- $self->is_tgz && !$self->bin_gzip ?
- loc("No '%1' program found", '/bin/gzip') :
- $self->is_tbz && !$self->bin_bunzip2 ?
- loc("No '%1' program found", '/bin/bunzip2') :
- '';
-
- if( $diag ) {
- $self->_error( $diag );
- return METHOD_NA;
- }
- }
-
- ### XXX figure out how to make IPC::Run do this in one call --
- ### currently i don't know how to get output of a command after a pipe
- ### trapped in a scalar. Mailed barries about this 5th of june 2004.
-
- ### see what command we should run, based on whether
- ### it's a .tgz or .tar
-
- ### XXX solaris tar and bsdtar are having different outputs
- ### depending whether you run with -x or -t
- ### compensate for this insanity by running -t first, then -x
- { my $cmd =
- $self->is_tgz ? [$self->bin_gzip, '-cdf', $self->archive, '|',
- $self->bin_tar, '-tf', '-'] :
- $self->is_tbz ? [$self->bin_bunzip2, '-cd', $self->archive, '|',
- $self->bin_tar, '-tf', '-'] :
- [$self->bin_tar, @ExtraTarFlags, '-tf', $self->archive];
-
- ### run the command
- ### newer versions of 'tar' (1.21 and up) now print record size
- ### to STDERR as well if v OR t is given (used to be both). This
- ### is a 'feature' according to the changelog, so we must now only
- ### inspect STDOUT, otherwise, failures like these occur:
- ### nntp.perl.org/group/perl.cpan.testers/2009/02/msg3230366.html
- my $buffer = '';
- my @out = run( command => $cmd,
- buffer => \$buffer,
- verbose => $DEBUG );
-
- ### command was unsuccessful
- unless( $out[0] ) {
- return $self->_error(loc(
- "Error listing contents of archive '%1': %2",
- $self->archive, $buffer ));
- }
-
- ### no buffers available?
- if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
- $self->_error( $self->_no_buffer_files( $self->archive ) );
-
- } else {
- ### if we're on solaris we /might/ be using /bin/tar, which has
- ### a weird output format... we might also be using
- ### /usr/local/bin/tar, which is gnu tar, which is perfectly
- ### fine... so we have to do some guessing here =/
- my @files = map { chomp;
- !ON_SOLARIS ? $_
- : (m|^ x \s+ # 'xtract' -- sigh
- (.+?), # the actual file name
- \s+ [\d,.]+ \s bytes,
- \s+ [\d,.]+ \s tape \s blocks
- |x ? $1 : $_);
-
- ### only STDOUT, see above. Sometims, extra whitespace
- ### is present, so make sure we only pick lines with
- ### a length
- } grep { length } map { split $/, $_ } @{$out[3]};
-
- ### store the files that are in the archive ###
- $self->files(\@files);
- }
- }
-
- ### now actually extract it ###
- { my $cmd =
- $self->is_tgz ? [$self->bin_gzip, '-cdf', $self->archive, '|',
- $self->bin_tar, '-xf', '-'] :
- $self->is_tbz ? [$self->bin_bunzip2, '-cd', $self->archive, '|',
- $self->bin_tar, '-xf', '-'] :
- [$self->bin_tar, @ExtraTarFlags, '-xf', $self->archive];
-
- my $buffer = '';
- unless( scalar run( command => $cmd,
- buffer => \$buffer,
- verbose => $DEBUG )
- ) {
- return $self->_error(loc("Error extracting archive '%1': %2",
- $self->archive, $buffer ));
- }
-
- ### we might not have them, due to lack of buffers
- if( $self->files ) {
- ### now that we've extracted, figure out where we extracted to
- my $dir = $self->__get_extract_dir( $self->files );
-
- ### store the extraction dir ###
- $self->extract_path( $dir );
- }
- }
-
- ### we got here, no error happened
- return 1;
- }
-}
-
-
-### use archive::tar to extract ###
-sub _untar_at {
- my $self = shift;
-
- ### Loading Archive::Tar is going to set it to 1, so make it local
- ### within this block, starting with its initial value. Whatever
- ### Achive::Tar does will be undone when we return.
- ###
- ### Also, later, set $Archive::Tar::WARN to $Archive::Extract::WARN
- ### so users don't have to even think about this variable. If they
- ### do, they still get their set value outside of this call.
- local $Archive::Tar::WARN = $Archive::Tar::WARN;
-
- ### we definitely need Archive::Tar, so load that first
- { my $use_list = { 'Archive::Tar' => '0.0' };
-
- unless( can_load( modules => $use_list ) ) {
-
- $self->_error(loc("You do not have '%1' installed - " .
- "Please install it as soon as possible.",
- 'Archive::Tar'));
-
- return METHOD_NA;
- }
- }
-
- ### we might pass it a filehandle if it's a .tbz file..
- my $fh_to_read = $self->archive;
-
- ### we will need Compress::Zlib too, if it's a tgz... and IO::Zlib
- ### if A::T's version is 0.99 or higher
- if( $self->is_tgz ) {
- my $use_list = { 'Compress::Zlib' => '0.0' };
- $use_list->{ 'IO::Zlib' } = '0.0'
- if $Archive::Tar::VERSION >= '0.99';
-
- unless( can_load( modules => $use_list ) ) {
- my $which = join '/', sort keys %$use_list;
-
- $self->_error(loc(
- "You do not have '%1' installed - Please ".
- "install it as soon as possible.", $which)
- );
-
- return METHOD_NA;
- }
-
- } elsif ( $self->is_tbz ) {
- my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
- unless( can_load( modules => $use_list ) ) {
- $self->_error(loc(
- "You do not have '%1' installed - Please " .
- "install it as soon as possible.",
- 'IO::Uncompress::Bunzip2')
- );
-
- return METHOD_NA;
- }
-
- my $bz = IO::Uncompress::Bunzip2->new( $self->archive ) or
- return $self->_error(loc("Unable to open '%1': %2",
- $self->archive,
- $IO::Uncompress::Bunzip2::Bunzip2Error));
-
- $fh_to_read = $bz;
- }
-
- my @files;
- {
- ### $Archive::Tar::WARN is 1 by default in Archive::Tar, but we've
- ### localized $Archive::Tar::WARN already.
- $Archive::Tar::WARN = $Archive::Extract::WARN;
-
- ### only tell it it's compressed if it's a .tgz, as we give it a file
- ### handle if it's a .tbz
- my @read = ( $fh_to_read, ( $self->is_tgz ? 1 : 0 ) );
-
- ### for version of Archive::Tar > 1.04
- local $Archive::Tar::CHOWN = 0;
-
- ### use the iterator if we can. it's a feature of A::T 1.40 and up
- if ( $_ALLOW_TAR_ITER && Archive::Tar->can( 'iter' ) ) {
-
- my $next;
- unless ( $next = Archive::Tar->iter( @read ) ) {
- return $self->_error(loc(
- "Unable to read '%1': %2", $self->archive,
- $Archive::Tar::error));
- }
-
- while ( my $file = $next->() ) {
- push @files, $file->full_path;
-
- $file->extract or return $self->_error(loc(
- "Unable to read '%1': %2",
- $self->archive,
- $Archive::Tar::error));
- }
-
- ### older version, read the archive into memory
- } else {
-
- my $tar = Archive::Tar->new();
-
- unless( $tar->read( @read ) ) {
- return $self->_error(loc("Unable to read '%1': %2",
- $self->archive, $Archive::Tar::error));
- }
-
- ### workaround to prevent Archive::Tar from setting uid, which
- ### is a potential security hole. -autrijus
- ### have to do it here, since A::T needs to be /loaded/ first ###
- { no strict 'refs'; local $^W;
-
- ### older versions of archive::tar <= 0.23
- *Archive::Tar::chown = sub {};
- }
-
- { local $^W; # quell 'splice() offset past end of array' warnings
- # on older versions of A::T
-
- ### older archive::tar always returns $self, return value
- ### slightly fux0r3d because of it.
- $tar->extract or return $self->_error(loc(
- "Unable to extract '%1': %2",
- $self->archive, $Archive::Tar::error ));
- }
-
- @files = $tar->list_files;
- }
- }
-
- my $dir = $self->__get_extract_dir( \@files );
-
- ### store the files that are in the archive ###
- $self->files(\@files);
-
- ### store the extraction dir ###
- $self->extract_path( $dir );
-
- ### check if the dir actually appeared ###
- return 1 if -d $self->extract_path;
-
- ### no dir, we failed ###
- return $self->_error(loc("Unable to extract '%1': %2",
- $self->archive, $Archive::Tar::error ));
-}
-
-#################################
-#
-# Gunzip code
-#
-#################################
-
-sub _gunzip_bin {
- my $self = shift;
-
- ### check for /bin/gzip -- we need it ###
- unless( $self->bin_gzip ) {
- $self->_error(loc("No '%1' program found", '/bin/gzip'));
- return METHOD_NA;
- }
-
- my $fh = FileHandle->new('>'. $self->_gunzip_to) or
- return $self->_error(loc("Could not open '%1' for writing: %2",
- $self->_gunzip_to, $! ));
-
- my $cmd = [ $self->bin_gzip, '-cdf', $self->archive ];
-
- my $buffer;
- unless( scalar run( command => $cmd,
- verbose => $DEBUG,
- buffer => \$buffer )
- ) {
- return $self->_error(loc("Unable to gunzip '%1': %2",
- $self->archive, $buffer));
- }
-
- ### no buffers available?
- if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
- $self->_error( $self->_no_buffer_content( $self->archive ) );
- }
-
- $self->_print($fh, $buffer) if defined $buffer;
-
- close $fh;
-
- ### set what files where extract, and where they went ###
- $self->files( [$self->_gunzip_to] );
- $self->extract_path( File::Spec->rel2abs(cwd()) );
-
- return 1;
-}
-
-sub _gunzip_cz {
- my $self = shift;
-
- my $use_list = { 'Compress::Zlib' => '0.0' };
- unless( can_load( modules => $use_list ) ) {
- $self->_error(loc("You do not have '%1' installed - Please " .
- "install it as soon as possible.", 'Compress::Zlib'));
- return METHOD_NA;
- }
-
- my $gz = Compress::Zlib::gzopen( $self->archive, "rb" ) or
- return $self->_error(loc("Unable to open '%1': %2",
- $self->archive, $Compress::Zlib::gzerrno));
-
- my $fh = FileHandle->new('>'. $self->_gunzip_to) or
- return $self->_error(loc("Could not open '%1' for writing: %2",
- $self->_gunzip_to, $! ));
-
- my $buffer;
- $self->_print($fh, $buffer) while $gz->gzread($buffer) > 0;
- $fh->close;
-
- ### set what files where extract, and where they went ###
- $self->files( [$self->_gunzip_to] );
- $self->extract_path( File::Spec->rel2abs(cwd()) );
-
- return 1;
-}
-
-#################################
-#
-# Uncompress code
-#
-#################################
-
-sub _uncompress_bin {
- my $self = shift;
-
- ### check for /bin/gzip -- we need it ###
- unless( $self->bin_uncompress ) {
- $self->_error(loc("No '%1' program found", '/bin/uncompress'));
- return METHOD_NA;
- }
-
- my $fh = FileHandle->new('>'. $self->_gunzip_to) or
- return $self->_error(loc("Could not open '%1' for writing: %2",
- $self->_gunzip_to, $! ));
-
- my $cmd = [ $self->bin_uncompress, '-c', $self->archive ];
-
- my $buffer;
- unless( scalar run( command => $cmd,
- verbose => $DEBUG,
- buffer => \$buffer )
- ) {
- return $self->_error(loc("Unable to uncompress '%1': %2",
- $self->archive, $buffer));
- }
-
- ### no buffers available?
- if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
- $self->_error( $self->_no_buffer_content( $self->archive ) );
- }
-
- $self->_print($fh, $buffer) if defined $buffer;
-
- close $fh;
-
- ### set what files where extract, and where they went ###
- $self->files( [$self->_gunzip_to] );
- $self->extract_path( File::Spec->rel2abs(cwd()) );
-
- return 1;
-}
-
-
-#################################
-#
-# Unzip code
-#
-#################################
-
-
-sub _unzip_bin {
- my $self = shift;
-
- ### check for /bin/gzip if we need it ###
- unless( $self->bin_unzip ) {
- $self->_error(loc("No '%1' program found", '/bin/unzip'));
- return METHOD_NA;
- }
-
- ### first, get the files.. it must be 2 different commands with 'unzip' :(
- { ### on VMS, capital letter options have to be quoted. This is
- ### peported by John Malmberg on P5P Tue 21 Aug 2007 05:05:11
- ### Subject: [patch@31735]Archive Extract fix on VMS.
- my $opt = ON_VMS ? '"-Z"' : '-Z';
- my $cmd = [ $self->bin_unzip, $opt, '-1', $self->archive ];
-
- my $buffer = '';
- unless( scalar run( command => $cmd,
- verbose => $DEBUG,
- buffer => \$buffer )
- ) {
- return $self->_error(loc("Unable to unzip '%1': %2",
- $self->archive, $buffer));
- }
-
- ### no buffers available?
- if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
- $self->_error( $self->_no_buffer_files( $self->archive ) );
-
- } else {
- $self->files( [split $/, $buffer] );
- }
- }
-
- ### now, extract the archive ###
- { my $cmd = [ $self->bin_unzip, '-qq', '-o', $self->archive ];
-
- my $buffer;
- unless( scalar run( command => $cmd,
- verbose => $DEBUG,
- buffer => \$buffer )
- ) {
- return $self->_error(loc("Unable to unzip '%1': %2",
- $self->archive, $buffer));
- }
-
- if( scalar @{$self->files} ) {
- my $files = $self->files;
- my $dir = $self->__get_extract_dir( $files );
-
- $self->extract_path( $dir );
- }
- }
-
- return 1;
-}
-
-sub _unzip_az {
- my $self = shift;
-
- my $use_list = { 'Archive::Zip' => '0.0' };
- unless( can_load( modules => $use_list ) ) {
- $self->_error(loc("You do not have '%1' installed - Please " .
- "install it as soon as possible.", 'Archive::Zip'));
- return METHOD_NA;
- }
-
- my $zip = Archive::Zip->new();
-
- unless( $zip->read( $self->archive ) == &Archive::Zip::AZ_OK ) {
- return $self->_error(loc("Unable to read '%1'", $self->archive));
- }
-
- my @files;
-
-
- ### Address: #43278: Explicitly tell Archive::Zip where to put the files:
- ### "In my BackPAN indexing, Archive::Zip was extracting things
- ### in my script's directory instead of the current working directory.
- ### I traced this back through Archive::Zip::_asLocalName which
- ### eventually calls File::Spec::Win32::rel2abs which on Windows might
- ### call Cwd::getdcwd. getdcwd returns the wrong directory in my
- ### case, even though I think I'm on the same drive.
- ###
- ### To fix this, I pass the optional second argument to
- ### extractMember using the cwd from Archive::Extract." --bdfoy
-
- ## store cwd() before looping; calls to cwd() can be expensive, and
- ### it won't change during the loop
- my $extract_dir = cwd();
-
- ### have to extract every member individually ###
- for my $member ($zip->members) {
- push @files, $member->{fileName};
-
- ### file to extact to, to avoid the above problem
- my $to = File::Spec->catfile( $extract_dir, $member->{fileName} );
-
- unless( $zip->extractMember($member, $to) == &Archive::Zip::AZ_OK ) {
- return $self->_error(loc("Extraction of '%1' from '%2' failed",
- $member->{fileName}, $self->archive ));
- }
- }
-
- my $dir = $self->__get_extract_dir( \@files );
-
- ### set what files where extract, and where they went ###
- $self->files( \@files );
- $self->extract_path( File::Spec->rel2abs($dir) );
-
- return 1;
-}
-
-sub __get_extract_dir {
- my $self = shift;
- my $files = shift || [];
-
- return unless scalar @$files;
-
- my($dir1, $dir2);
- for my $aref ( [ \$dir1, 0 ], [ \$dir2, -1 ] ) {
- my($dir,$pos) = @$aref;
-
- ### add a catdir(), so that any trailing slashes get
- ### take care of (removed)
- ### also, a catdir() normalises './dir/foo' to 'dir/foo';
- ### which was the problem in bug #23999
- my $res = -d $files->[$pos]
- ? File::Spec->catdir( $files->[$pos], '' )
- : File::Spec->catdir( dirname( $files->[$pos] ) );
-
- $$dir = $res;
- }
-
- ### if the first and last dir don't match, make sure the
- ### dirname is not set wrongly
- my $dir;
-
- ### dirs are the same, so we know for sure what the extract dir is
- if( $dir1 eq $dir2 ) {
- $dir = $dir1;
-
- ### dirs are different.. do they share the base dir?
- ### if so, use that, if not, fall back to '.'
- } else {
- my $base1 = [ File::Spec->splitdir( $dir1 ) ]->[0];
- my $base2 = [ File::Spec->splitdir( $dir2 ) ]->[0];
-
- $dir = File::Spec->rel2abs( $base1 eq $base2 ? $base1 : '.' );
- }
-
- return File::Spec->rel2abs( $dir );
-}
-
-#################################
-#
-# Bunzip2 code
-#
-#################################
-
-sub _bunzip2_bin {
- my $self = shift;
-
- ### check for /bin/gzip -- we need it ###
- unless( $self->bin_bunzip2 ) {
- $self->_error(loc("No '%1' program found", '/bin/bunzip2'));
- return METHOD_NA;
- }
-
- my $fh = FileHandle->new('>'. $self->_gunzip_to) or
- return $self->_error(loc("Could not open '%1' for writing: %2",
- $self->_gunzip_to, $! ));
-
- ### guard against broken bunzip2. See ->have_old_bunzip2()
- ### for details
- if( $self->have_old_bunzip2 and $self->archive !~ /\.bz2$/i ) {
- return $self->_error(loc("Your bunzip2 version is too old and ".
- "can only extract files ending in '%1'",
- '.bz2'));
- }
-
- my $cmd = [ $self->bin_bunzip2, '-cd', $self->archive ];
-
- my $buffer;
- unless( scalar run( command => $cmd,
- verbose => $DEBUG,
- buffer => \$buffer )
- ) {
- return $self->_error(loc("Unable to bunzip2 '%1': %2",
- $self->archive, $buffer));
- }
-
- ### no buffers available?
- if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
- $self->_error( $self->_no_buffer_content( $self->archive ) );
- }
-
- $self->_print($fh, $buffer) if defined $buffer;
-
- close $fh;
-
- ### set what files where extract, and where they went ###
- $self->files( [$self->_gunzip_to] );
- $self->extract_path( File::Spec->rel2abs(cwd()) );
-
- return 1;
-}
-
-### using cz2, the compact versions... this we use mainly in archive::tar
-### extractor..
-# sub _bunzip2_cz1 {
-# my $self = shift;
-#
-# my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
-# unless( can_load( modules => $use_list ) ) {
-# return $self->_error(loc("You do not have '%1' installed - Please " .
-# "install it as soon as possible.",
-# 'IO::Uncompress::Bunzip2'));
-# }
-#
-# my $bz = IO::Uncompress::Bunzip2->new( $self->archive ) or
-# return $self->_error(loc("Unable to open '%1': %2",
-# $self->archive,
-# $IO::Uncompress::Bunzip2::Bunzip2Error));
-#
-# my $fh = FileHandle->new('>'. $self->_gunzip_to) or
-# return $self->_error(loc("Could not open '%1' for writing: %2",
-# $self->_gunzip_to, $! ));
-#
-# my $buffer;
-# $fh->print($buffer) while $bz->read($buffer) > 0;
-# $fh->close;
-#
-# ### set what files where extract, and where they went ###
-# $self->files( [$self->_gunzip_to] );
-# $self->extract_path( File::Spec->rel2abs(cwd()) );
-#
-# return 1;
-# }
-
-sub _bunzip2_bz2 {
- my $self = shift;
-
- my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
- unless( can_load( modules => $use_list ) ) {
- $self->_error(loc("You do not have '%1' installed - Please " .
- "install it as soon as possible.",
- 'IO::Uncompress::Bunzip2'));
- return METHOD_NA;
- }
-
- IO::Uncompress::Bunzip2::bunzip2($self->archive => $self->_gunzip_to)
- or return $self->_error(loc("Unable to uncompress '%1': %2",
- $self->archive,
- $IO::Uncompress::Bunzip2::Bunzip2Error));
-
- ### set what files where extract, and where they went ###
- $self->files( [$self->_gunzip_to] );
- $self->extract_path( File::Spec->rel2abs(cwd()) );
-
- return 1;
-}
-
-
-#################################
-#
-# unlzma code
-#
-#################################
-
-sub _unlzma_bin {
- my $self = shift;
-
- ### check for /bin/unlzma -- we need it ###
- unless( $self->bin_unlzma ) {
- $self->_error(loc("No '%1' program found", '/bin/unlzma'));
- return METHOD_NA;
- }
-
- my $fh = FileHandle->new('>'. $self->_gunzip_to) or
- return $self->_error(loc("Could not open '%1' for writing: %2",
- $self->_gunzip_to, $! ));
-
- my $cmd = [ $self->bin_unlzma, '-c', $self->archive ];
-
- my $buffer;
- unless( scalar run( command => $cmd,
- verbose => $DEBUG,
- buffer => \$buffer )
- ) {
- return $self->_error(loc("Unable to unlzma '%1': %2",
- $self->archive, $buffer));
- }
-
- ### no buffers available?
- if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
- $self->_error( $self->_no_buffer_content( $self->archive ) );
- }
-
- $self->_print($fh, $buffer) if defined $buffer;
-
- close $fh;
-
- ### set what files where extract, and where they went ###
- $self->files( [$self->_gunzip_to] );
- $self->extract_path( File::Spec->rel2abs(cwd()) );
-
- return 1;
-}
-
-sub _unlzma_cz {
- my $self = shift;
-
- my $use_list = { 'Compress::unLZMA' => '0.0' };
- unless( can_load( modules => $use_list ) ) {
- $self->_error(loc("You do not have '%1' installed - Please " .
- "install it as soon as possible.", 'Compress::unLZMA'));
- return METHOD_NA;
- }
-
- my $fh = FileHandle->new('>'. $self->_gunzip_to) or
- return $self->_error(loc("Could not open '%1' for writing: %2",
- $self->_gunzip_to, $! ));
-
- my $buffer;
- $buffer = Compress::unLZMA::uncompressfile( $self->archive );
- unless ( defined $buffer ) {
- return $self->_error(loc("Could not unlzma '%1': %2",
- $self->archive, $@));
- }
-
- $self->_print($fh, $buffer) if defined $buffer;
-
- close $fh;
-
- ### set what files where extract, and where they went ###
- $self->files( [$self->_gunzip_to] );
- $self->extract_path( File::Spec->rel2abs(cwd()) );
-
- return 1;
-}
-
-#################################
-#
-# Error code
-#
-#################################
-
-# For printing binaries that avoids interfering globals
-sub _print {
- my $self = shift;
- my $fh = shift;
-
- local( $\, $", $, ) = ( undef, ' ', '' );
- return print $fh @_;
-}
-
-sub _error {
- my $self = shift;
- my $error = shift;
- my $lerror = Carp::longmess($error);
-
- push @{$self->_error_msg}, $error;
- push @{$self->_error_msg_long}, $lerror;
-
- ### set $Archive::Extract::WARN to 0 to disable printing
- ### of errors
- if( $WARN ) {
- carp $DEBUG ? $lerror : $error;
- }
-
- return;
-}
-
-sub error {
- my $self = shift;
-
- ### make sure we have a fallback aref
- my $aref = do {
- shift()
- ? $self->_error_msg_long
- : $self->_error_msg
- } || [];
-
- return join $/, @$aref;
-}
-
-sub _no_buffer_files {
- my $self = shift;
- my $file = shift or return;
- return loc("No buffer captured, unable to tell ".
- "extracted files or extraction dir for '%1'", $file);
-}
-
-sub _no_buffer_content {
- my $self = shift;
- my $file = shift or return;
- return loc("No buffer captured, unable to get content for '%1'", $file);
-}
-1;
-
-=pod
-
-=head1 HOW IT WORKS
-
-C<Archive::Extract> tries first to determine what type of archive you
-are passing it, by inspecting its suffix. It does not do this by using
-Mime magic, or something related. See C<CAVEATS> below.
-
-Once it has determined the file type, it knows which extraction methods
-it can use on the archive. It will try a perl solution first, then fall
-back to a commandline tool if that fails. If that also fails, it will
-return false, indicating it was unable to extract the archive.
-See the section on C<GLOBAL VARIABLES> to see how to alter this order.
-
-=head1 CAVEATS
-
-=head2 File Extensions
-
-C<Archive::Extract> trusts on the extension of the archive to determine
-what type it is, and what extractor methods therefore can be used. If
-your archives do not have any of the extensions as described in the
-C<new()> method, you will have to specify the type explicitly, or
-C<Archive::Extract> will not be able to extract the archive for you.
-
-=head2 Supporting Very Large Files
-
-C<Archive::Extract> can use either pure perl modules or command line
-programs under the hood. Some of the pure perl modules (like
-C<Archive::Tar> and Compress::unLZMA) take the entire contents of the archive into memory,
-which may not be feasible on your system. Consider setting the global
-variable C<$Archive::Extract::PREFER_BIN> to C<1>, which will prefer
-the use of command line programs and won't consume so much memory.
-
-See the C<GLOBAL VARIABLES> section below for details.
-
-=head2 Bunzip2 support of arbitrary extensions.
-
-Older versions of C</bin/bunzip2> do not support arbitrary file
-extensions and insist on a C<.bz2> suffix. Although we do our best
-to guard against this, if you experience a bunzip2 error, it may
-be related to this. For details, please see the C<have_old_bunzip2>
-method.
-
-=head1 GLOBAL VARIABLES
-
-=head2 $Archive::Extract::DEBUG
-
-Set this variable to C<true> to have all calls to command line tools
-be printed out, including all their output.
-This also enables C<Carp::longmess> errors, instead of the regular
-C<carp> errors.
-
-Good for tracking down why things don't work with your particular
-setup.
-
-Defaults to C<false>.
-
-=head2 $Archive::Extract::WARN
-
-This variable controls whether errors encountered internally by
-C<Archive::Extract> should be C<carp>'d or not.
-
-Set to false to silence warnings. Inspect the output of the C<error()>
-method manually to see what went wrong.
-
-Defaults to C<true>.
-
-=head2 $Archive::Extract::PREFER_BIN
-
-This variables controls whether C<Archive::Extract> should prefer the
-use of perl modules, or commandline tools to extract archives.
-
-Set to C<true> to have C<Archive::Extract> prefer commandline tools.
-
-Defaults to C<false>.
-
-=head1 TODO / CAVEATS
-
-=over 4
-
-=item Mime magic support
-
-Maybe this module should use something like C<File::Type> to determine
-the type, rather than blindly trust the suffix.
-
-=item Thread safety
-
-Currently, C<Archive::Extract> does a C<chdir> to the extraction dir before
-extraction, and a C<chdir> back again after. This is not necessarily
-thread safe. See C<rt.cpan.org> bug C<#45671> for details.
-
-=back
-
-=head1 BUG REPORTS
-
-Please report bugs or other issues to E<lt>bug-archive-extract@rt.cpan.org<gt>.
-
-=head1 AUTHOR
-
-This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
-
-=head1 COPYRIGHT
-
-This library is free software; you may redistribute and/or modify it
-under the same terms as Perl itself.
-
-=cut
-
-# Local variables:
-# c-indentation-style: bsd
-# c-basic-offset: 4
-# indent-tabs-mode: nil
-# End:
-# vim: expandtab shiftwidth=4:
-
diff --git a/Master/tlpkg/tlperl/lib/Archive/Tar.pm b/Master/tlpkg/tlperl/lib/Archive/Tar.pm
deleted file mode 100755
index 006edbd5c3e..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Tar.pm
+++ /dev/null
@@ -1,2146 +0,0 @@
-### the gnu tar specification:
-### http://www.gnu.org/software/tar/manual/tar.html
-###
-### and the pax format spec, which tar derives from:
-### http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html
-
-package Archive::Tar;
-require 5.005_03;
-
-use Cwd;
-use IO::Zlib;
-use IO::File;
-use Carp qw(carp croak);
-use File::Spec ();
-use File::Spec::Unix ();
-use File::Path ();
-
-use Archive::Tar::File;
-use Archive::Tar::Constant;
-
-require Exporter;
-
-use strict;
-use vars qw[$DEBUG $error $VERSION $WARN $FOLLOW_SYMLINK $CHOWN $CHMOD
- $DO_NOT_USE_PREFIX $HAS_PERLIO $HAS_IO_STRING $SAME_PERMISSIONS
- $INSECURE_EXTRACT_MODE @ISA @EXPORT
- ];
-
-@ISA = qw[Exporter];
-@EXPORT = qw[ COMPRESS_GZIP COMPRESS_BZIP ];
-$DEBUG = 0;
-$WARN = 1;
-$FOLLOW_SYMLINK = 0;
-$VERSION = "1.54";
-$CHOWN = 1;
-$CHMOD = 1;
-$SAME_PERMISSIONS = $> == 0 ? 1 : 0;
-$DO_NOT_USE_PREFIX = 0;
-$INSECURE_EXTRACT_MODE = 0;
-
-BEGIN {
- use Config;
- $HAS_PERLIO = $Config::Config{useperlio};
-
- ### try and load IO::String anyway, so you can dynamically
- ### switch between perlio and IO::String
- $HAS_IO_STRING = eval {
- require IO::String;
- import IO::String;
- 1;
- } || 0;
-}
-
-=head1 NAME
-
-Archive::Tar - module for manipulations of tar archives
-
-=head1 SYNOPSIS
-
- use Archive::Tar;
- my $tar = Archive::Tar->new;
-
- $tar->read('origin.tgz');
- $tar->extract();
-
- $tar->add_files('file/foo.pl', 'docs/README');
- $tar->add_data('file/baz.txt', 'This is the contents now');
-
- $tar->rename('oldname', 'new/file/name');
-
- $tar->write('files.tar'); # plain tar
- $tar->write('files.tgz', COMPRESS_GZIP); # gzip compressed
- $tar->write('files.tbz', COMPRESS_BZIP); # bzip2 compressed
-
-=head1 DESCRIPTION
-
-Archive::Tar provides an object oriented mechanism for handling tar
-files. It provides class methods for quick and easy files handling
-while also allowing for the creation of tar file objects for custom
-manipulation. If you have the IO::Zlib module installed,
-Archive::Tar will also support compressed or gzipped tar files.
-
-An object of class Archive::Tar represents a .tar(.gz) archive full
-of files and things.
-
-=head1 Object Methods
-
-=head2 Archive::Tar->new( [$file, $compressed] )
-
-Returns a new Tar object. If given any arguments, C<new()> calls the
-C<read()> method automatically, passing on the arguments provided to
-the C<read()> method.
-
-If C<new()> is invoked with arguments and the C<read()> method fails
-for any reason, C<new()> returns undef.
-
-=cut
-
-my $tmpl = {
- _data => [ ],
- _file => 'Unknown',
-};
-
-### install get/set accessors for this object.
-for my $key ( keys %$tmpl ) {
- no strict 'refs';
- *{__PACKAGE__."::$key"} = sub {
- my $self = shift;
- $self->{$key} = $_[0] if @_;
- return $self->{$key};
- }
-}
-
-sub new {
- my $class = shift;
- $class = ref $class if ref $class;
-
- ### copying $tmpl here since a shallow copy makes it use the
- ### same aref, causing for files to remain in memory always.
- my $obj = bless { _data => [ ], _file => 'Unknown', _error => '' }, $class;
-
- if (@_) {
- unless ( $obj->read( @_ ) ) {
- $obj->_error(qq[No data could be read from file]);
- return;
- }
- }
-
- return $obj;
-}
-
-=head2 $tar->read ( $filename|$handle, [$compressed, {opt => 'val'}] )
-
-Read the given tar file into memory.
-The first argument can either be the name of a file or a reference to
-an already open filehandle (or an IO::Zlib object if it's compressed)
-
-The C<read> will I<replace> any previous content in C<$tar>!
-
-The second argument may be considered optional, but remains for
-backwards compatibility. Archive::Tar now looks at the file
-magic to determine what class should be used to open the file
-and will transparently Do The Right Thing.
-
-Archive::Tar will warn if you try to pass a bzip2 compressed file and the
-IO::Zlib / IO::Uncompress::Bunzip2 modules are not available and simply return.
-
-Note that you can currently B<not> pass a C<gzip> compressed
-filehandle, which is not opened with C<IO::Zlib>, a C<bzip2> compressed
-filehandle, which is not opened with C<IO::Uncompress::Bunzip2>, nor a string
-containing the full archive information (either compressed or
-uncompressed). These are worth while features, but not currently
-implemented. See the C<TODO> section.
-
-The third argument can be a hash reference with options. Note that
-all options are case-sensitive.
-
-=over 4
-
-=item limit
-
-Do not read more than C<limit> files. This is useful if you have
-very big archives, and are only interested in the first few files.
-
-=item filter
-
-Can be set to a regular expression. Only files with names that match
-the expression will be read.
-
-=item extract
-
-If set to true, immediately extract entries when reading them. This
-gives you the same memory break as the C<extract_archive> function.
-Note however that entries will not be read into memory, but written
-straight to disk. This means no C<Archive::Tar::File> objects are
-created for you to inspect.
-
-=back
-
-All files are stored internally as C<Archive::Tar::File> objects.
-Please consult the L<Archive::Tar::File> documentation for details.
-
-Returns the number of files read in scalar context, and a list of
-C<Archive::Tar::File> objects in list context.
-
-=cut
-
-sub read {
- my $self = shift;
- my $file = shift;
- my $gzip = shift || 0;
- my $opts = shift || {};
-
- unless( defined $file ) {
- $self->_error( qq[No file to read from!] );
- return;
- } else {
- $self->_file( $file );
- }
-
- my $handle = $self->_get_handle($file, $gzip, READ_ONLY->( ZLIB ) )
- or return;
-
- my $data = $self->_read_tar( $handle, $opts ) or return;
-
- $self->_data( $data );
-
- return wantarray ? @$data : scalar @$data;
-}
-
-sub _get_handle {
- my $self = shift;
- my $file = shift; return unless defined $file;
- return $file if ref $file;
- my $compress = shift || 0;
- my $mode = shift || READ_ONLY->( ZLIB ); # default to read only
-
-
- ### get a FH opened to the right class, so we can use it transparently
- ### throughout the program
- my $fh;
- { ### reading magic only makes sense if we're opening a file for
- ### reading. otherwise, just use what the user requested.
- my $magic = '';
- if( MODE_READ->($mode) ) {
- open my $tmp, $file or do {
- $self->_error( qq[Could not open '$file' for reading: $!] );
- return;
- };
-
- ### read the first 4 bites of the file to figure out which class to
- ### use to open the file.
- sysread( $tmp, $magic, 4 );
- close $tmp;
- }
-
- ### is it bzip?
- ### if you asked specifically for bzip compression, or if we're in
- ### read mode and the magic numbers add up, use bzip
- if( BZIP and (
- ($compress eq COMPRESS_BZIP) or
- ( MODE_READ->($mode) and $magic =~ BZIP_MAGIC_NUM )
- )
- ) {
-
- ### different reader/writer modules, different error vars... sigh
- if( MODE_READ->($mode) ) {
- $fh = IO::Uncompress::Bunzip2->new( $file ) or do {
- $self->_error( qq[Could not read '$file': ] .
- $IO::Uncompress::Bunzip2::Bunzip2Error
- );
- return;
- };
-
- } else {
- $fh = IO::Compress::Bzip2->new( $file ) or do {
- $self->_error( qq[Could not write to '$file': ] .
- $IO::Compress::Bzip2::Bzip2Error
- );
- return;
- };
- }
-
- ### is it gzip?
- ### if you asked for compression, if you wanted to read or the gzip
- ### magic number is present (redundant with read)
- } elsif( ZLIB and (
- $compress or MODE_READ->($mode) or $magic =~ GZIP_MAGIC_NUM
- )
- ) {
- $fh = IO::Zlib->new;
-
- unless( $fh->open( $file, $mode ) ) {
- $self->_error(qq[Could not create filehandle for '$file': $!]);
- return;
- }
-
- ### is it plain tar?
- } else {
- $fh = IO::File->new;
-
- unless( $fh->open( $file, $mode ) ) {
- $self->_error(qq[Could not create filehandle for '$file': $!]);
- return;
- }
-
- ### enable bin mode on tar archives
- binmode $fh;
- }
- }
-
- return $fh;
-}
-
-
-sub _read_tar {
- my $self = shift;
- my $handle = shift or return;
- my $opts = shift || {};
-
- my $count = $opts->{limit} || 0;
- my $filter = $opts->{filter};
- my $extract = $opts->{extract} || 0;
-
- ### set a cap on the amount of files to extract ###
- my $limit = 0;
- $limit = 1 if $count > 0;
-
- my $tarfile = [ ];
- my $chunk;
- my $read = 0;
- my $real_name; # to set the name of a file when
- # we're encountering @longlink
- my $data;
-
- LOOP:
- while( $handle->read( $chunk, HEAD ) ) {
- ### IO::Zlib doesn't support this yet
- my $offset = eval { tell $handle } || 'unknown';
-
- unless( $read++ ) {
- my $gzip = GZIP_MAGIC_NUM;
- if( $chunk =~ /$gzip/ ) {
- $self->_error( qq[Cannot read compressed format in tar-mode] );
- return;
- }
-
- ### size is < HEAD, which means a corrupted file, as the minimum
- ### length is _at least_ HEAD
- if (length $chunk != HEAD) {
- $self->_error( qq[Cannot read enough bytes from the tarfile] );
- return;
- }
- }
-
- ### if we can't read in all bytes... ###
- last if length $chunk != HEAD;
-
- ### Apparently this should really be two blocks of 512 zeroes,
- ### but GNU tar sometimes gets it wrong. See comment in the
- ### source code (tar.c) to GNU cpio.
- next if $chunk eq TAR_END;
-
- ### according to the posix spec, the last 12 bytes of the header are
- ### null bytes, to pad it to a 512 byte block. That means if these
- ### bytes are NOT null bytes, it's a corrrupt header. See:
- ### www.koders.com/c/fidCE473AD3D9F835D690259D60AD5654591D91D5BA.aspx
- ### line 111
- { my $nulls = join '', "\0" x 12;
- unless( $nulls eq substr( $chunk, 500, 12 ) ) {
- $self->_error( qq[Invalid header block at offset $offset] );
- next LOOP;
- }
- }
-
- ### pass the realname, so we can set it 'proper' right away
- ### some of the heuristics are done on the name, so important
- ### to set it ASAP
- my $entry;
- { my %extra_args = ();
- $extra_args{'name'} = $$real_name if defined $real_name;
-
- unless( $entry = Archive::Tar::File->new( chunk => $chunk,
- %extra_args )
- ) {
- $self->_error( qq[Couldn't read chunk at offset $offset] );
- next LOOP;
- }
- }
-
- ### ignore labels:
- ### http://www.gnu.org/manual/tar/html_node/tar_139.html
- next if $entry->is_label;
-
- if( length $entry->type and ($entry->is_file || $entry->is_longlink) ) {
-
- if ( $entry->is_file && !$entry->validate ) {
- ### sometimes the chunk is rather fux0r3d and a whole 512
- ### bytes ends up in the ->name area.
- ### clean it up, if need be
- my $name = $entry->name;
- $name = substr($name, 0, 100) if length $name > 100;
- $name =~ s/\n/ /g;
-
- $self->_error( $name . qq[: checksum error] );
- next LOOP;
- }
-
- my $block = BLOCK_SIZE->( $entry->size );
-
- $data = $entry->get_content_by_ref;
-
- ### just read everything into memory
- ### can't do lazy loading since IO::Zlib doesn't support 'seek'
- ### this is because Compress::Zlib doesn't support it =/
- ### this reads in the whole data in one read() call.
- if( $handle->read( $$data, $block ) < $block ) {
- $self->_error( qq[Read error on tarfile (missing data) '].
- $entry->full_path ."' at offset $offset" );
- next LOOP;
- }
-
- ### throw away trailing garbage ###
- substr ($$data, $entry->size) = "" if defined $$data;
-
- ### part II of the @LongLink munging -- need to do /after/
- ### the checksum check.
- if( $entry->is_longlink ) {
- ### weird thing in tarfiles -- if the file is actually a
- ### @LongLink, the data part seems to have a trailing ^@
- ### (unprintable) char. to display, pipe output through less.
- ### but that doesn't *always* happen.. so check if the last
- ### character is a control character, and if so remove it
- ### at any rate, we better remove that character here, or tests
- ### like 'eq' and hashlook ups based on names will SO not work
- ### remove it by calculating the proper size, and then
- ### tossing out everything that's longer than that size.
-
- ### count number of nulls
- my $nulls = $$data =~ tr/\0/\0/;
-
- ### cut data + size by that many bytes
- $entry->size( $entry->size - $nulls );
- substr ($$data, $entry->size) = "";
- }
- }
-
- ### clean up of the entries.. posix tar /apparently/ has some
- ### weird 'feature' that allows for filenames > 255 characters
- ### they'll put a header in with as name '././@LongLink' and the
- ### contents will be the name of the /next/ file in the archive
- ### pretty crappy and kludgy if you ask me
-
- ### set the name for the next entry if this is a @LongLink;
- ### this is one ugly hack =/ but needed for direct extraction
- if( $entry->is_longlink ) {
- $real_name = $data;
- next LOOP;
- } elsif ( defined $real_name ) {
- $entry->name( $$real_name );
- $entry->prefix('');
- undef $real_name;
- }
-
- ### skip this entry if we're filtering
- if ($filter && $entry->name !~ $filter) {
- next LOOP;
-
- ### skip this entry if it's a pax header. This is a special file added
- ### by, among others, git-generated tarballs. It holds comments and is
- ### not meant for extracting. See #38932: pax_global_header extracted
- } elsif ( $entry->name eq PAX_HEADER ) {
- next LOOP;
- }
-
- $self->_extract_file( $entry ) if $extract
- && !$entry->is_longlink
- && !$entry->is_unknown
- && !$entry->is_label;
-
- ### Guard against tarfiles with garbage at the end
- last LOOP if $entry->name eq '';
-
- ### push only the name on the rv if we're extracting
- ### -- for extract_archive
- push @$tarfile, ($extract ? $entry->name : $entry);
-
- if( $limit ) {
- $count-- unless $entry->is_longlink || $entry->is_dir;
- last LOOP unless $count;
- }
- } continue {
- undef $data;
- }
-
- return $tarfile;
-}
-
-=head2 $tar->contains_file( $filename )
-
-Check if the archive contains a certain file.
-It will return true if the file is in the archive, false otherwise.
-
-Note however, that this function does an exact match using C<eq>
-on the full path. So it cannot compensate for case-insensitive file-
-systems or compare 2 paths to see if they would point to the same
-underlying file.
-
-=cut
-
-sub contains_file {
- my $self = shift;
- my $full = shift;
-
- return unless defined $full;
-
- ### don't warn if the entry isn't there.. that's what this function
- ### is for after all.
- local $WARN = 0;
- return 1 if $self->_find_entry($full);
- return;
-}
-
-=head2 $tar->extract( [@filenames] )
-
-Write files whose names are equivalent to any of the names in
-C<@filenames> to disk, creating subdirectories as necessary. This
-might not work too well under VMS.
-Under MacPerl, the file's modification time will be converted to the
-MacOS zero of time, and appropriate conversions will be done to the
-path. However, the length of each element of the path is not
-inspected to see whether it's longer than MacOS currently allows (32
-characters).
-
-If C<extract> is called without a list of file names, the entire
-contents of the archive are extracted.
-
-Returns a list of filenames extracted.
-
-=cut
-
-sub extract {
- my $self = shift;
- my @args = @_;
- my @files;
-
- # use the speed optimization for all extracted files
- local($self->{cwd}) = cwd() unless $self->{cwd};
-
- ### you requested the extraction of only certian files
- if( @args ) {
- for my $file ( @args ) {
-
- ### it's already an object?
- if( UNIVERSAL::isa( $file, 'Archive::Tar::File' ) ) {
- push @files, $file;
- next;
-
- ### go find it then
- } else {
-
- my $found;
- for my $entry ( @{$self->_data} ) {
- next unless $file eq $entry->full_path;
-
- ### we found the file you're looking for
- push @files, $entry;
- $found++;
- }
-
- unless( $found ) {
- return $self->_error(
- qq[Could not find '$file' in archive] );
- }
- }
- }
-
- ### just grab all the file items
- } else {
- @files = $self->get_files;
- }
-
- ### nothing found? that's an error
- unless( scalar @files ) {
- $self->_error( qq[No files found for ] . $self->_file );
- return;
- }
-
- ### now extract them
- for my $entry ( @files ) {
- unless( $self->_extract_file( $entry ) ) {
- $self->_error(q[Could not extract ']. $entry->full_path .q['] );
- return;
- }
- }
-
- return @files;
-}
-
-=head2 $tar->extract_file( $file, [$extract_path] )
-
-Write an entry, whose name is equivalent to the file name provided to
-disk. Optionally takes a second parameter, which is the full native
-path (including filename) the entry will be written to.
-
-For example:
-
- $tar->extract_file( 'name/in/archive', 'name/i/want/to/give/it' );
-
- $tar->extract_file( $at_file_object, 'name/i/want/to/give/it' );
-
-Returns true on success, false on failure.
-
-=cut
-
-sub extract_file {
- my $self = shift;
- my $file = shift; return unless defined $file;
- my $alt = shift;
-
- my $entry = $self->_find_entry( $file )
- or $self->_error( qq[Could not find an entry for '$file'] ), return;
-
- return $self->_extract_file( $entry, $alt );
-}
-
-sub _extract_file {
- my $self = shift;
- my $entry = shift or return;
- my $alt = shift;
-
- ### you wanted an alternate extraction location ###
- my $name = defined $alt ? $alt : $entry->full_path;
-
- ### splitpath takes a bool at the end to indicate
- ### that it's splitting a dir
- my ($vol,$dirs,$file);
- if ( defined $alt ) { # It's a local-OS path
- ($vol,$dirs,$file) = File::Spec->splitpath( $alt,
- $entry->is_dir );
- } else {
- ($vol,$dirs,$file) = File::Spec::Unix->splitpath( $name,
- $entry->is_dir );
- }
-
- my $dir;
- ### is $name an absolute path? ###
- if( $vol || File::Spec->file_name_is_absolute( $dirs ) ) {
-
- ### absolute names are not allowed to be in tarballs under
- ### strict mode, so only allow it if a user tells us to do it
- if( not defined $alt and not $INSECURE_EXTRACT_MODE ) {
- $self->_error(
- q[Entry ']. $entry->full_path .q[' is an absolute path. ].
- q[Not extracting absolute paths under SECURE EXTRACT MODE]
- );
- return;
- }
-
- ### user asked us to, it's fine.
- $dir = File::Spec->catpath( $vol, $dirs, "" );
-
- ### it's a relative path ###
- } else {
- my $cwd = (ref $self and defined $self->{cwd})
- ? $self->{cwd}
- : cwd();
-
- my @dirs = defined $alt
- ? File::Spec->splitdir( $dirs ) # It's a local-OS path
- : File::Spec::Unix->splitdir( $dirs ); # it's UNIX-style, likely
- # straight from the tarball
-
- if( not defined $alt and
- not $INSECURE_EXTRACT_MODE
- ) {
-
- ### paths that leave the current directory are not allowed under
- ### strict mode, so only allow it if a user tells us to do this.
- if( grep { $_ eq '..' } @dirs ) {
-
- $self->_error(
- q[Entry ']. $entry->full_path .q[' is attempting to leave ].
- q[the current working directory. Not extracting under ].
- q[SECURE EXTRACT MODE]
- );
- return;
- }
-
- ### the archive may be asking us to extract into a symlink. This
- ### is not sane and a possible security issue, as outlined here:
- ### https://rt.cpan.org/Ticket/Display.html?id=30380
- ### https://bugzilla.redhat.com/show_bug.cgi?id=295021
- ### https://issues.rpath.com/browse/RPL-1716
- my $full_path = $cwd;
- for my $d ( @dirs ) {
- $full_path = File::Spec->catdir( $full_path, $d );
-
- ### we've already checked this one, and it's safe. Move on.
- next if ref $self and $self->{_link_cache}->{$full_path};
-
- if( -l $full_path ) {
- my $to = readlink $full_path;
- my $diag = "symlinked directory ($full_path => $to)";
-
- $self->_error(
- q[Entry ']. $entry->full_path .q[' is attempting to ].
- qq[extract to a $diag. This is considered a security ].
- q[vulnerability and not allowed under SECURE EXTRACT ].
- q[MODE]
- );
- return;
- }
-
- ### XXX keep a cache if possible, so the stats become cheaper:
- $self->{_link_cache}->{$full_path} = 1 if ref $self;
- }
- }
-
- ### '.' is the directory delimiter on VMS, which has to be escaped
- ### or changed to '_' on vms. vmsify is used, because older versions
- ### of vmspath do not handle this properly.
- ### Must not add a '/' to an empty directory though.
- map { length() ? VMS::Filespec::vmsify($_.'/') : $_ } @dirs if ON_VMS;
-
- my ($cwd_vol,$cwd_dir,$cwd_file)
- = File::Spec->splitpath( $cwd );
- my @cwd = File::Spec->splitdir( $cwd_dir );
- push @cwd, $cwd_file if length $cwd_file;
-
- ### We need to pass '' as the last elemant to catpath. Craig Berry
- ### explains why (msgid <p0624083dc311ae541393@[172.16.52.1]>):
- ### The root problem is that splitpath on UNIX always returns the
- ### final path element as a file even if it is a directory, and of
- ### course there is no way it can know the difference without checking
- ### against the filesystem, which it is documented as not doing. When
- ### you turn around and call catpath, on VMS you have to know which bits
- ### are directory bits and which bits are file bits. In this case we
- ### know the result should be a directory. I had thought you could omit
- ### the file argument to catpath in such a case, but apparently on UNIX
- ### you can't.
- $dir = File::Spec->catpath(
- $cwd_vol, File::Spec->catdir( @cwd, @dirs ), ''
- );
-
- ### catdir() returns undef if the path is longer than 255 chars on
- ### older VMS systems.
- unless ( defined $dir ) {
- $^W && $self->_error( qq[Could not compose a path for '$dirs'\n] );
- return;
- }
-
- }
-
- if( -e $dir && !-d _ ) {
- $^W && $self->_error( qq['$dir' exists, but it's not a directory!\n] );
- return;
- }
-
- unless ( -d _ ) {
- eval { File::Path::mkpath( $dir, 0, 0777 ) };
- if( $@ ) {
- my $fp = $entry->full_path;
- $self->_error(qq[Could not create directory '$dir' for '$fp': $@]);
- return;
- }
-
- ### XXX chown here? that might not be the same as in the archive
- ### as we're only chown'ing to the owner of the file we're extracting
- ### not to the owner of the directory itself, which may or may not
- ### be another entry in the archive
- ### Answer: no, gnu tar doesn't do it either, it'd be the wrong
- ### way to go.
- #if( $CHOWN && CAN_CHOWN ) {
- # chown $entry->uid, $entry->gid, $dir or
- # $self->_error( qq[Could not set uid/gid on '$dir'] );
- #}
- }
-
- ### we're done if we just needed to create a dir ###
- return 1 if $entry->is_dir;
-
- my $full = File::Spec->catfile( $dir, $file );
-
- if( $entry->is_unknown ) {
- $self->_error( qq[Unknown file type for file '$full'] );
- return;
- }
-
- if( length $entry->type && $entry->is_file ) {
- my $fh = IO::File->new;
- $fh->open( '>' . $full ) or (
- $self->_error( qq[Could not open file '$full': $!] ),
- return
- );
-
- if( $entry->size ) {
- binmode $fh;
- syswrite $fh, $entry->data or (
- $self->_error( qq[Could not write data to '$full'] ),
- return
- );
- }
-
- close $fh or (
- $self->_error( qq[Could not close file '$full'] ),
- return
- );
-
- } else {
- $self->_make_special_file( $entry, $full ) or return;
- }
-
- ### only update the timestamp if it's not a symlink; that will change the
- ### timestamp of the original. This addresses bug #33669: Could not update
- ### timestamp warning on symlinks
- if( not -l $full ) {
- utime time, $entry->mtime - TIME_OFFSET, $full or
- $self->_error( qq[Could not update timestamp] );
- }
-
- if( $CHOWN && CAN_CHOWN->() ) {
- chown $entry->uid, $entry->gid, $full or
- $self->_error( qq[Could not set uid/gid on '$full'] );
- }
-
- ### only chmod if we're allowed to, but never chmod symlinks, since they'll
- ### change the perms on the file they're linking too...
- if( $CHMOD and not -l $full ) {
- my $mode = $entry->mode;
- unless ($SAME_PERMISSIONS) {
- $mode &= ~(oct(7000) | umask);
- }
- chmod $mode, $full or
- $self->_error( qq[Could not chown '$full' to ] . $entry->mode );
- }
-
- return 1;
-}
-
-sub _make_special_file {
- my $self = shift;
- my $entry = shift or return;
- my $file = shift; return unless defined $file;
-
- my $err;
-
- if( $entry->is_symlink ) {
- my $fail;
- if( ON_UNIX ) {
- symlink( $entry->linkname, $file ) or $fail++;
-
- } else {
- $self->_extract_special_file_as_plain_file( $entry, $file )
- or $fail++;
- }
-
- $err = qq[Making symbolic link '$file' to '] .
- $entry->linkname .q[' failed] if $fail;
-
- } elsif ( $entry->is_hardlink ) {
- my $fail;
- if( ON_UNIX ) {
- link( $entry->linkname, $file ) or $fail++;
-
- } else {
- $self->_extract_special_file_as_plain_file( $entry, $file )
- or $fail++;
- }
-
- $err = qq[Making hard link from '] . $entry->linkname .
- qq[' to '$file' failed] if $fail;
-
- } elsif ( $entry->is_fifo ) {
- ON_UNIX && !system('mknod', $file, 'p') or
- $err = qq[Making fifo ']. $entry->name .qq[' failed];
-
- } elsif ( $entry->is_blockdev or $entry->is_chardev ) {
- my $mode = $entry->is_blockdev ? 'b' : 'c';
-
- ON_UNIX && !system('mknod', $file, $mode,
- $entry->devmajor, $entry->devminor) or
- $err = qq[Making block device ']. $entry->name .qq[' (maj=] .
- $entry->devmajor . qq[ min=] . $entry->devminor .
- qq[) failed.];
-
- } elsif ( $entry->is_socket ) {
- ### the original doesn't do anything special for sockets.... ###
- 1;
- }
-
- return $err ? $self->_error( $err ) : 1;
-}
-
-### don't know how to make symlinks, let's just extract the file as
-### a plain file
-sub _extract_special_file_as_plain_file {
- my $self = shift;
- my $entry = shift or return;
- my $file = shift; return unless defined $file;
-
- my $err;
- TRY: {
- my $orig = $self->_find_entry( $entry->linkname );
-
- unless( $orig ) {
- $err = qq[Could not find file '] . $entry->linkname .
- qq[' in memory.];
- last TRY;
- }
-
- ### clone the entry, make it appear as a normal file ###
- my $clone = $entry->clone;
- $clone->_downgrade_to_plainfile;
- $self->_extract_file( $clone, $file ) or last TRY;
-
- return 1;
- }
-
- return $self->_error($err);
-}
-
-=head2 $tar->list_files( [\@properties] )
-
-Returns a list of the names of all the files in the archive.
-
-If C<list_files()> is passed an array reference as its first argument
-it returns a list of hash references containing the requested
-properties of each file. The following list of properties is
-supported: name, size, mtime (last modified date), mode, uid, gid,
-linkname, uname, gname, devmajor, devminor, prefix.
-
-Passing an array reference containing only one element, 'name', is
-special cased to return a list of names rather than a list of hash
-references, making it equivalent to calling C<list_files> without
-arguments.
-
-=cut
-
-sub list_files {
- my $self = shift;
- my $aref = shift || [ ];
-
- unless( $self->_data ) {
- $self->read() or return;
- }
-
- if( @$aref == 0 or ( @$aref == 1 and $aref->[0] eq 'name' ) ) {
- return map { $_->full_path } @{$self->_data};
- } else {
-
- #my @rv;
- #for my $obj ( @{$self->_data} ) {
- # push @rv, { map { $_ => $obj->$_() } @$aref };
- #}
- #return @rv;
-
- ### this does the same as the above.. just needs a +{ }
- ### to make sure perl doesn't confuse it for a block
- return map { my $o=$_;
- +{ map { $_ => $o->$_() } @$aref }
- } @{$self->_data};
- }
-}
-
-sub _find_entry {
- my $self = shift;
- my $file = shift;
-
- unless( defined $file ) {
- $self->_error( qq[No file specified] );
- return;
- }
-
- ### it's an object already
- return $file if UNIVERSAL::isa( $file, 'Archive::Tar::File' );
-
- for my $entry ( @{$self->_data} ) {
- my $path = $entry->full_path;
- return $entry if $path eq $file;
- }
-
- $self->_error( qq[No such file in archive: '$file'] );
- return;
-}
-
-=head2 $tar->get_files( [@filenames] )
-
-Returns the C<Archive::Tar::File> objects matching the filenames
-provided. If no filename list was passed, all C<Archive::Tar::File>
-objects in the current Tar object are returned.
-
-Please refer to the C<Archive::Tar::File> documentation on how to
-handle these objects.
-
-=cut
-
-sub get_files {
- my $self = shift;
-
- return @{ $self->_data } unless @_;
-
- my @list;
- for my $file ( @_ ) {
- push @list, grep { defined } $self->_find_entry( $file );
- }
-
- return @list;
-}
-
-=head2 $tar->get_content( $file )
-
-Return the content of the named file.
-
-=cut
-
-sub get_content {
- my $self = shift;
- my $entry = $self->_find_entry( shift ) or return;
-
- return $entry->data;
-}
-
-=head2 $tar->replace_content( $file, $content )
-
-Make the string $content be the content for the file named $file.
-
-=cut
-
-sub replace_content {
- my $self = shift;
- my $entry = $self->_find_entry( shift ) or return;
-
- return $entry->replace_content( shift );
-}
-
-=head2 $tar->rename( $file, $new_name )
-
-Rename the file of the in-memory archive to $new_name.
-
-Note that you must specify a Unix path for $new_name, since per tar
-standard, all files in the archive must be Unix paths.
-
-Returns true on success and false on failure.
-
-=cut
-
-sub rename {
- my $self = shift;
- my $file = shift; return unless defined $file;
- my $new = shift; return unless defined $new;
-
- my $entry = $self->_find_entry( $file ) or return;
-
- return $entry->rename( $new );
-}
-
-=head2 $tar->remove (@filenamelist)
-
-Removes any entries with names matching any of the given filenames
-from the in-memory archive. Returns a list of C<Archive::Tar::File>
-objects that remain.
-
-=cut
-
-sub remove {
- my $self = shift;
- my @list = @_;
-
- my %seen = map { $_->full_path => $_ } @{$self->_data};
- delete $seen{ $_ } for @list;
-
- $self->_data( [values %seen] );
-
- return values %seen;
-}
-
-=head2 $tar->clear
-
-C<clear> clears the current in-memory archive. This effectively gives
-you a 'blank' object, ready to be filled again. Note that C<clear>
-only has effect on the object, not the underlying tarfile.
-
-=cut
-
-sub clear {
- my $self = shift or return;
-
- $self->_data( [] );
- $self->_file( '' );
-
- return 1;
-}
-
-
-=head2 $tar->write ( [$file, $compressed, $prefix] )
-
-Write the in-memory archive to disk. The first argument can either
-be the name of a file or a reference to an already open filehandle (a
-GLOB reference).
-
-The second argument is used to indicate compression. You can either
-compress using C<gzip> or C<bzip2>. If you pass a digit, it's assumed
-to be the C<gzip> compression level (between 1 and 9), but the use of
-constants is prefered:
-
- # write a gzip compressed file
- $tar->write( 'out.tgz', COMPRESS_GZIP );
-
- # write a bzip compressed file
- $tar->write( 'out.tbz', COMPRESS_BZIP );
-
-Note that when you pass in a filehandle, the compression argument
-is ignored, as all files are printed verbatim to your filehandle.
-If you wish to enable compression with filehandles, use an
-C<IO::Zlib> or C<IO::Compress::Bzip2> filehandle instead.
-
-The third argument is an optional prefix. All files will be tucked
-away in the directory you specify as prefix. So if you have files
-'a' and 'b' in your archive, and you specify 'foo' as prefix, they
-will be written to the archive as 'foo/a' and 'foo/b'.
-
-If no arguments are given, C<write> returns the entire formatted
-archive as a string, which could be useful if you'd like to stuff the
-archive into a socket or a pipe to gzip or something.
-
-
-=cut
-
-sub write {
- my $self = shift;
- my $file = shift; $file = '' unless defined $file;
- my $gzip = shift || 0;
- my $ext_prefix = shift; $ext_prefix = '' unless defined $ext_prefix;
- my $dummy = '';
-
- ### only need a handle if we have a file to print to ###
- my $handle = length($file)
- ? ( $self->_get_handle($file, $gzip, WRITE_ONLY->($gzip) )
- or return )
- : $HAS_PERLIO ? do { open my $h, '>', \$dummy; $h }
- : $HAS_IO_STRING ? IO::String->new
- : __PACKAGE__->no_string_support();
-
- ### Addresses: #41798: Nonempty $\ when writing a TAR file produces a
- ### corrupt TAR file. Must clear out $\ to make sure no garbage is
- ### printed to the archive
- local $\;
-
- for my $entry ( @{$self->_data} ) {
- ### entries to be written to the tarfile ###
- my @write_me;
-
- ### only now will we change the object to reflect the current state
- ### of the name and prefix fields -- this needs to be limited to
- ### write() only!
- my $clone = $entry->clone;
-
-
- ### so, if you don't want use to use the prefix, we'll stuff
- ### everything in the name field instead
- if( $DO_NOT_USE_PREFIX ) {
-
- ### you might have an extended prefix, if so, set it in the clone
- ### XXX is ::Unix right?
- $clone->name( length $ext_prefix
- ? File::Spec::Unix->catdir( $ext_prefix,
- $clone->full_path)
- : $clone->full_path );
- $clone->prefix( '' );
-
- ### otherwise, we'll have to set it properly -- prefix part in the
- ### prefix and name part in the name field.
- } else {
-
- ### split them here, not before!
- my ($prefix,$name) = $clone->_prefix_and_file( $clone->full_path );
-
- ### you might have an extended prefix, if so, set it in the clone
- ### XXX is ::Unix right?
- $prefix = File::Spec::Unix->catdir( $ext_prefix, $prefix )
- if length $ext_prefix;
-
- $clone->prefix( $prefix );
- $clone->name( $name );
- }
-
- ### names are too long, and will get truncated if we don't add a
- ### '@LongLink' file...
- my $make_longlink = ( length($clone->name) > NAME_LENGTH or
- length($clone->prefix) > PREFIX_LENGTH
- ) || 0;
-
- ### perhaps we need to make a longlink file?
- if( $make_longlink ) {
- my $longlink = Archive::Tar::File->new(
- data => LONGLINK_NAME,
- $clone->full_path,
- { type => LONGLINK }
- );
-
- unless( $longlink ) {
- $self->_error( qq[Could not create 'LongLink' entry for ] .
- qq[oversize file '] . $clone->full_path ."'" );
- return;
- };
-
- push @write_me, $longlink;
- }
-
- push @write_me, $clone;
-
- ### write the one, optionally 2 a::t::file objects to the handle
- for my $clone (@write_me) {
-
- ### if the file is a symlink, there are 2 options:
- ### either we leave the symlink intact, but then we don't write any
- ### data OR we follow the symlink, which means we actually make a
- ### copy. if we do the latter, we have to change the TYPE of the
- ### clone to 'FILE'
- my $link_ok = $clone->is_symlink && $Archive::Tar::FOLLOW_SYMLINK;
- my $data_ok = !$clone->is_symlink && $clone->has_content;
-
- ### downgrade to a 'normal' file if it's a symlink we're going to
- ### treat as a regular file
- $clone->_downgrade_to_plainfile if $link_ok;
-
- ### get the header for this block
- my $header = $self->_format_tar_entry( $clone );
- unless( $header ) {
- $self->_error(q[Could not format header for: ] .
- $clone->full_path );
- return;
- }
-
- unless( print $handle $header ) {
- $self->_error(q[Could not write header for: ] .
- $clone->full_path);
- return;
- }
-
- if( $link_ok or $data_ok ) {
- unless( print $handle $clone->data ) {
- $self->_error(q[Could not write data for: ] .
- $clone->full_path);
- return;
- }
-
- ### pad the end of the clone if required ###
- print $handle TAR_PAD->( $clone->size ) if $clone->size % BLOCK
- }
-
- } ### done writing these entries
- }
-
- ### write the end markers ###
- print $handle TAR_END x 2 or
- return $self->_error( qq[Could not write tar end markers] );
-
- ### did you want it written to a file, or returned as a string? ###
- my $rv = length($file) ? 1
- : $HAS_PERLIO ? $dummy
- : do { seek $handle, 0, 0; local $/; <$handle> };
-
- ### make sure to close the handle;
- close $handle;
-
- return $rv;
-}
-
-sub _format_tar_entry {
- my $self = shift;
- my $entry = shift or return;
- my $ext_prefix = shift; $ext_prefix = '' unless defined $ext_prefix;
- my $no_prefix = shift || 0;
-
- my $file = $entry->name;
- my $prefix = $entry->prefix; $prefix = '' unless defined $prefix;
-
- ### remove the prefix from the file name
- ### not sure if this is still neeeded --kane
- ### no it's not -- Archive::Tar::File->_new_from_file will take care of
- ### this for us. Even worse, this would break if we tried to add a file
- ### like x/x.
- #if( length $prefix ) {
- # $file =~ s/^$match//;
- #}
-
- $prefix = File::Spec::Unix->catdir($ext_prefix, $prefix)
- if length $ext_prefix;
-
- ### not sure why this is... ###
- my $l = PREFIX_LENGTH; # is ambiguous otherwise...
- substr ($prefix, 0, -$l) = "" if length $prefix >= PREFIX_LENGTH;
-
- my $f1 = "%06o"; my $f2 = "%11o";
-
- ### this might be optimizable with a 'changed' flag in the file objects ###
- my $tar = pack (
- PACK,
- $file,
-
- (map { sprintf( $f1, $entry->$_() ) } qw[mode uid gid]),
- (map { sprintf( $f2, $entry->$_() ) } qw[size mtime]),
-
- "", # checksum field - space padded a bit down
-
- (map { $entry->$_() } qw[type linkname magic]),
-
- $entry->version || TAR_VERSION,
-
- (map { $entry->$_() } qw[uname gname]),
- (map { sprintf( $f1, $entry->$_() ) } qw[devmajor devminor]),
-
- ($no_prefix ? '' : $prefix)
- );
-
- ### add the checksum ###
- substr($tar,148,7) = sprintf("%6o\0", unpack("%16C*",$tar));
-
- return $tar;
-}
-
-=head2 $tar->add_files( @filenamelist )
-
-Takes a list of filenames and adds them to the in-memory archive.
-
-The path to the file is automatically converted to a Unix like
-equivalent for use in the archive, and, if on MacOS, the file's
-modification time is converted from the MacOS epoch to the Unix epoch.
-So tar archives created on MacOS with B<Archive::Tar> can be read
-both with I<tar> on Unix and applications like I<suntar> or
-I<Stuffit Expander> on MacOS.
-
-Be aware that the file's type/creator and resource fork will be lost,
-which is usually what you want in cross-platform archives.
-
-Instead of a filename, you can also pass it an existing C<Archive::Tar::File>
-object from, for example, another archive. The object will be clone, and
-effectively be a copy of the original, not an alias.
-
-Returns a list of C<Archive::Tar::File> objects that were just added.
-
-=cut
-
-sub add_files {
- my $self = shift;
- my @files = @_ or return;
-
- my @rv;
- for my $file ( @files ) {
-
- ### you passed an Archive::Tar::File object
- ### clone it so we don't accidentally have a reference to
- ### an object from another archive
- if( UNIVERSAL::isa( $file,'Archive::Tar::File' ) ) {
- push @rv, $file->clone;
- next;
- }
-
- unless( -e $file || -l $file ) {
- $self->_error( qq[No such file: '$file'] );
- next;
- }
-
- my $obj = Archive::Tar::File->new( file => $file );
- unless( $obj ) {
- $self->_error( qq[Unable to add file: '$file'] );
- next;
- }
-
- push @rv, $obj;
- }
-
- push @{$self->{_data}}, @rv;
-
- return @rv;
-}
-
-=head2 $tar->add_data ( $filename, $data, [$opthashref] )
-
-Takes a filename, a scalar full of data and optionally a reference to
-a hash with specific options.
-
-Will add a file to the in-memory archive, with name C<$filename> and
-content C<$data>. Specific properties can be set using C<$opthashref>.
-The following list of properties is supported: name, size, mtime
-(last modified date), mode, uid, gid, linkname, uname, gname,
-devmajor, devminor, prefix, type. (On MacOS, the file's path and
-modification times are converted to Unix equivalents.)
-
-Valid values for the file type are the following constants defined in
-Archive::Tar::Constants:
-
-=over 4
-
-=item FILE
-
-Regular file.
-
-=item HARDLINK
-
-=item SYMLINK
-
-Hard and symbolic ("soft") links; linkname should specify target.
-
-=item CHARDEV
-
-=item BLOCKDEV
-
-Character and block devices. devmajor and devminor should specify the major
-and minor device numbers.
-
-=item DIR
-
-Directory.
-
-=item FIFO
-
-FIFO (named pipe).
-
-=item SOCKET
-
-Socket.
-
-=back
-
-Returns the C<Archive::Tar::File> object that was just added, or
-C<undef> on failure.
-
-=cut
-
-sub add_data {
- my $self = shift;
- my ($file, $data, $opt) = @_;
-
- my $obj = Archive::Tar::File->new( data => $file, $data, $opt );
- unless( $obj ) {
- $self->_error( qq[Unable to add file: '$file'] );
- return;
- }
-
- push @{$self->{_data}}, $obj;
-
- return $obj;
-}
-
-=head2 $tar->error( [$BOOL] )
-
-Returns the current errorstring (usually, the last error reported).
-If a true value was specified, it will give the C<Carp::longmess>
-equivalent of the error, in effect giving you a stacktrace.
-
-For backwards compatibility, this error is also available as
-C<$Archive::Tar::error> although it is much recommended you use the
-method call instead.
-
-=cut
-
-{
- $error = '';
- my $longmess;
-
- sub _error {
- my $self = shift;
- my $msg = $error = shift;
- $longmess = Carp::longmess($error);
- if (ref $self) {
- $self->{_error} = $error;
- $self->{_longmess} = $longmess;
- }
-
- ### set Archive::Tar::WARN to 0 to disable printing
- ### of errors
- if( $WARN ) {
- carp $DEBUG ? $longmess : $msg;
- }
-
- return;
- }
-
- sub error {
- my $self = shift;
- if (ref $self) {
- return shift() ? $self->{_longmess} : $self->{_error};
- } else {
- return shift() ? $longmess : $error;
- }
- }
-}
-
-=head2 $tar->setcwd( $cwd );
-
-C<Archive::Tar> needs to know the current directory, and it will run
-C<Cwd::cwd()> I<every> time it extracts a I<relative> entry from the
-tarfile and saves it in the file system. (As of version 1.30, however,
-C<Archive::Tar> will use the speed optimization described below
-automatically, so it's only relevant if you're using C<extract_file()>).
-
-Since C<Archive::Tar> doesn't change the current directory internally
-while it is extracting the items in a tarball, all calls to C<Cwd::cwd()>
-can be avoided if we can guarantee that the current directory doesn't
-get changed externally.
-
-To use this performance boost, set the current directory via
-
- use Cwd;
- $tar->setcwd( cwd() );
-
-once before calling a function like C<extract_file> and
-C<Archive::Tar> will use the current directory setting from then on
-and won't call C<Cwd::cwd()> internally.
-
-To switch back to the default behaviour, use
-
- $tar->setcwd( undef );
-
-and C<Archive::Tar> will call C<Cwd::cwd()> internally again.
-
-If you're using C<Archive::Tar>'s C<exract()> method, C<setcwd()> will
-be called for you.
-
-=cut
-
-sub setcwd {
- my $self = shift;
- my $cwd = shift;
-
- $self->{cwd} = $cwd;
-}
-
-=head1 Class Methods
-
-=head2 Archive::Tar->create_archive($file, $compressed, @filelist)
-
-Creates a tar file from the list of files provided. The first
-argument can either be the name of the tar file to create or a
-reference to an open file handle (e.g. a GLOB reference).
-
-The second argument is used to indicate compression. You can either
-compress using C<gzip> or C<bzip2>. If you pass a digit, it's assumed
-to be the C<gzip> compression level (between 1 and 9), but the use of
-constants is prefered:
-
- # write a gzip compressed file
- Archive::Tar->create_archive( 'out.tgz', COMPRESS_GZIP, @filelist );
-
- # write a bzip compressed file
- Archive::Tar->create_archive( 'out.tbz', COMPRESS_BZIP, @filelist );
-
-Note that when you pass in a filehandle, the compression argument
-is ignored, as all files are printed verbatim to your filehandle.
-If you wish to enable compression with filehandles, use an
-C<IO::Zlib> or C<IO::Compress::Bzip2> filehandle instead.
-
-The remaining arguments list the files to be included in the tar file.
-These files must all exist. Any files which don't exist or can't be
-read are silently ignored.
-
-If the archive creation fails for any reason, C<create_archive> will
-return false. Please use the C<error> method to find the cause of the
-failure.
-
-Note that this method does not write C<on the fly> as it were; it
-still reads all the files into memory before writing out the archive.
-Consult the FAQ below if this is a problem.
-
-=cut
-
-sub create_archive {
- my $class = shift;
-
- my $file = shift; return unless defined $file;
- my $gzip = shift || 0;
- my @files = @_;
-
- unless( @files ) {
- return $class->_error( qq[Cowardly refusing to create empty archive!] );
- }
-
- my $tar = $class->new;
- $tar->add_files( @files );
- return $tar->write( $file, $gzip );
-}
-
-=head2 Archive::Tar->iter( $filename, [ $compressed, {opt => $val} ] )
-
-Returns an iterator function that reads the tar file without loading
-it all in memory. Each time the function is called it will return the
-next file in the tarball. The files are returned as
-C<Archive::Tar::File> objects. The iterator function returns the
-empty list once it has exhausted the files contained.
-
-The second argument can be a hash reference with options, which are
-identical to the arguments passed to C<read()>.
-
-Example usage:
-
- my $next = Archive::Tar->iter( "example.tar.gz", 1, {filter => qr/\.pm$/} );
-
- while( my $f = $next->() ) {
- print $f->name, "\n";
-
- $f->extract or warn "Extraction failed";
-
- # ....
- }
-
-=cut
-
-
-sub iter {
- my $class = shift;
- my $filename = shift or return;
- my $compressed = shift or 0;
- my $opts = shift || {};
-
- ### get a handle to read from.
- my $handle = $class->_get_handle(
- $filename,
- $compressed,
- READ_ONLY->( ZLIB )
- ) or return;
-
- my @data;
- return sub {
- return shift(@data) if @data; # more than one file returned?
- return unless $handle; # handle exhausted?
-
- ### read data, should only return file
- my $tarfile = $class->_read_tar($handle, { %$opts, limit => 1 });
- @data = @$tarfile if ref $tarfile && ref $tarfile eq 'ARRAY';
-
- ### return one piece of data
- return shift(@data) if @data;
-
- ### data is exhausted, free the filehandle
- undef $handle;
- return;
- };
-}
-
-=head2 Archive::Tar->list_archive($file, $compressed, [\@properties])
-
-Returns a list of the names of all the files in the archive. The
-first argument can either be the name of the tar file to list or a
-reference to an open file handle (e.g. a GLOB reference).
-
-If C<list_archive()> is passed an array reference as its third
-argument it returns a list of hash references containing the requested
-properties of each file. The following list of properties is
-supported: full_path, name, size, mtime (last modified date), mode,
-uid, gid, linkname, uname, gname, devmajor, devminor, prefix.
-
-See C<Archive::Tar::File> for details about supported properties.
-
-Passing an array reference containing only one element, 'name', is
-special cased to return a list of names rather than a list of hash
-references.
-
-=cut
-
-sub list_archive {
- my $class = shift;
- my $file = shift; return unless defined $file;
- my $gzip = shift || 0;
-
- my $tar = $class->new($file, $gzip);
- return unless $tar;
-
- return $tar->list_files( @_ );
-}
-
-=head2 Archive::Tar->extract_archive($file, $compressed)
-
-Extracts the contents of the tar file. The first argument can either
-be the name of the tar file to create or a reference to an open file
-handle (e.g. a GLOB reference). All relative paths in the tar file will
-be created underneath the current working directory.
-
-C<extract_archive> will return a list of files it extracted.
-If the archive extraction fails for any reason, C<extract_archive>
-will return false. Please use the C<error> method to find the cause
-of the failure.
-
-=cut
-
-sub extract_archive {
- my $class = shift;
- my $file = shift; return unless defined $file;
- my $gzip = shift || 0;
-
- my $tar = $class->new( ) or return;
-
- return $tar->read( $file, $gzip, { extract => 1 } );
-}
-
-=head2 $bool = Archive::Tar->has_io_string
-
-Returns true if we currently have C<IO::String> support loaded.
-
-Either C<IO::String> or C<perlio> support is needed to support writing
-stringified archives. Currently, C<perlio> is the preferred method, if
-available.
-
-See the C<GLOBAL VARIABLES> section to see how to change this preference.
-
-=cut
-
-sub has_io_string { return $HAS_IO_STRING; }
-
-=head2 $bool = Archive::Tar->has_perlio
-
-Returns true if we currently have C<perlio> support loaded.
-
-This requires C<perl-5.8> or higher, compiled with C<perlio>
-
-Either C<IO::String> or C<perlio> support is needed to support writing
-stringified archives. Currently, C<perlio> is the preferred method, if
-available.
-
-See the C<GLOBAL VARIABLES> section to see how to change this preference.
-
-=cut
-
-sub has_perlio { return $HAS_PERLIO; }
-
-=head2 $bool = Archive::Tar->has_zlib_support
-
-Returns true if C<Archive::Tar> can extract C<zlib> compressed archives
-
-=cut
-
-sub has_zlib_support { return ZLIB }
-
-=head2 $bool = Archive::Tar->has_bzip2_support
-
-Returns true if C<Archive::Tar> can extract C<bzip2> compressed archives
-
-=cut
-
-sub has_bzip2_support { return BZIP }
-
-=head2 Archive::Tar->can_handle_compressed_files
-
-A simple checking routine, which will return true if C<Archive::Tar>
-is able to uncompress compressed archives on the fly with C<IO::Zlib>
-and C<IO::Compress::Bzip2> or false if not both are installed.
-
-You can use this as a shortcut to determine whether C<Archive::Tar>
-will do what you think before passing compressed archives to its
-C<read> method.
-
-=cut
-
-sub can_handle_compressed_files { return ZLIB && BZIP ? 1 : 0 }
-
-sub no_string_support {
- croak("You have to install IO::String to support writing archives to strings");
-}
-
-1;
-
-__END__
-
-=head1 GLOBAL VARIABLES
-
-=head2 $Archive::Tar::FOLLOW_SYMLINK
-
-Set this variable to C<1> to make C<Archive::Tar> effectively make a
-copy of the file when extracting. Default is C<0>, which
-means the symlink stays intact. Of course, you will have to pack the
-file linked to as well.
-
-This option is checked when you write out the tarfile using C<write>
-or C<create_archive>.
-
-This works just like C</bin/tar>'s C<-h> option.
-
-=head2 $Archive::Tar::CHOWN
-
-By default, C<Archive::Tar> will try to C<chown> your files if it is
-able to. In some cases, this may not be desired. In that case, set
-this variable to C<0> to disable C<chown>-ing, even if it were
-possible.
-
-The default is C<1>.
-
-=head2 $Archive::Tar::CHMOD
-
-By default, C<Archive::Tar> will try to C<chmod> your files to
-whatever mode was specified for the particular file in the archive.
-In some cases, this may not be desired. In that case, set this
-variable to C<0> to disable C<chmod>-ing.
-
-The default is C<1>.
-
-=head2 $Archive::Tar::SAME_PERMISSIONS
-
-When, C<$Archive::Tar::CHMOD> is enabled, this setting controls whether
-the permissions on files from the archive are used without modification
-of if they are filtered by removing any setid bits and applying the
-current umask.
-
-The default is C<1> for the root user and C<0> for normal users.
-
-=head2 $Archive::Tar::DO_NOT_USE_PREFIX
-
-By default, C<Archive::Tar> will try to put paths that are over
-100 characters in the C<prefix> field of your tar header, as
-defined per POSIX-standard. However, some (older) tar programs
-do not implement this spec. To retain compatibility with these older
-or non-POSIX compliant versions, you can set the C<$DO_NOT_USE_PREFIX>
-variable to a true value, and C<Archive::Tar> will use an alternate
-way of dealing with paths over 100 characters by using the
-C<GNU Extended Header> feature.
-
-Note that clients who do not support the C<GNU Extended Header>
-feature will not be able to read these archives. Such clients include
-tars on C<Solaris>, C<Irix> and C<AIX>.
-
-The default is C<0>.
-
-=head2 $Archive::Tar::DEBUG
-
-Set this variable to C<1> to always get the C<Carp::longmess> output
-of the warnings, instead of the regular C<carp>. This is the same
-message you would get by doing:
-
- $tar->error(1);
-
-Defaults to C<0>.
-
-=head2 $Archive::Tar::WARN
-
-Set this variable to C<0> if you do not want any warnings printed.
-Personally I recommend against doing this, but people asked for the
-option. Also, be advised that this is of course not threadsafe.
-
-Defaults to C<1>.
-
-=head2 $Archive::Tar::error
-
-Holds the last reported error. Kept for historical reasons, but its
-use is very much discouraged. Use the C<error()> method instead:
-
- warn $tar->error unless $tar->extract;
-
-Note that in older versions of this module, the C<error()> method
-would return an effectively global value even when called an instance
-method as above. This has since been fixed, and multiple instances of
-C<Archive::Tar> now have separate error strings.
-
-=head2 $Archive::Tar::INSECURE_EXTRACT_MODE
-
-This variable indicates whether C<Archive::Tar> should allow
-files to be extracted outside their current working directory.
-
-Allowing this could have security implications, as a malicious
-tar archive could alter or replace any file the extracting user
-has permissions to. Therefor, the default is to not allow
-insecure extractions.
-
-If you trust the archive, or have other reasons to allow the
-archive to write files outside your current working directory,
-set this variable to C<true>.
-
-Note that this is a backwards incompatible change from version
-C<1.36> and before.
-
-=head2 $Archive::Tar::HAS_PERLIO
-
-This variable holds a boolean indicating if we currently have
-C<perlio> support loaded. This will be enabled for any perl
-greater than C<5.8> compiled with C<perlio>.
-
-If you feel strongly about disabling it, set this variable to
-C<false>. Note that you will then need C<IO::String> installed
-to support writing stringified archives.
-
-Don't change this variable unless you B<really> know what you're
-doing.
-
-=head2 $Archive::Tar::HAS_IO_STRING
-
-This variable holds a boolean indicating if we currently have
-C<IO::String> support loaded. This will be enabled for any perl
-that has a loadable C<IO::String> module.
-
-If you feel strongly about disabling it, set this variable to
-C<false>. Note that you will then need C<perlio> support from
-your perl to be able to write stringified archives.
-
-Don't change this variable unless you B<really> know what you're
-doing.
-
-=head1 FAQ
-
-=over 4
-
-=item What's the minimum perl version required to run Archive::Tar?
-
-You will need perl version 5.005_03 or newer.
-
-=item Isn't Archive::Tar slow?
-
-Yes it is. It's pure perl, so it's a lot slower then your C</bin/tar>
-However, it's very portable. If speed is an issue, consider using
-C</bin/tar> instead.
-
-=item Isn't Archive::Tar heavier on memory than /bin/tar?
-
-Yes it is, see previous answer. Since C<Compress::Zlib> and therefore
-C<IO::Zlib> doesn't support C<seek> on their filehandles, there is little
-choice but to read the archive into memory.
-This is ok if you want to do in-memory manipulation of the archive.
-
-If you just want to extract, use the C<extract_archive> class method
-instead. It will optimize and write to disk immediately.
-
-Another option is to use the C<iter> class method to iterate over
-the files in the tarball without reading them all in memory at once.
-
-=item Can you lazy-load data instead?
-
-In some cases, yes. You can use the C<iter> class method to iterate
-over the files in the tarball without reading them all in memory at once.
-
-=item How much memory will an X kb tar file need?
-
-Probably more than X kb, since it will all be read into memory. If
-this is a problem, and you don't need to do in memory manipulation
-of the archive, consider using the C<iter> class method, or C</bin/tar>
-instead.
-
-=item What do you do with unsupported filetypes in an archive?
-
-C<Unix> has a few filetypes that aren't supported on other platforms,
-like C<Win32>. If we encounter a C<hardlink> or C<symlink> we'll just
-try to make a copy of the original file, rather than throwing an error.
-
-This does require you to read the entire archive in to memory first,
-since otherwise we wouldn't know what data to fill the copy with.
-(This means that you cannot use the class methods, including C<iter>
-on archives that have incompatible filetypes and still expect things
-to work).
-
-For other filetypes, like C<chardevs> and C<blockdevs> we'll warn that
-the extraction of this particular item didn't work.
-
-=item I'm using WinZip, or some other non-POSIX client, and files are not being extracted properly!
-
-By default, C<Archive::Tar> is in a completely POSIX-compatible
-mode, which uses the POSIX-specification of C<tar> to store files.
-For paths greather than 100 characters, this is done using the
-C<POSIX header prefix>. Non-POSIX-compatible clients may not support
-this part of the specification, and may only support the C<GNU Extended
-Header> functionality. To facilitate those clients, you can set the
-C<$Archive::Tar::DO_NOT_USE_PREFIX> variable to C<true>. See the
-C<GLOBAL VARIABLES> section for details on this variable.
-
-Note that GNU tar earlier than version 1.14 does not cope well with
-the C<POSIX header prefix>. If you use such a version, consider setting
-the C<$Archive::Tar::DO_NOT_USE_PREFIX> variable to C<true>.
-
-=item How do I extract only files that have property X from an archive?
-
-Sometimes, you might not wish to extract a complete archive, just
-the files that are relevant to you, based on some criteria.
-
-You can do this by filtering a list of C<Archive::Tar::File> objects
-based on your criteria. For example, to extract only files that have
-the string C<foo> in their title, you would use:
-
- $tar->extract(
- grep { $_->full_path =~ /foo/ } $tar->get_files
- );
-
-This way, you can filter on any attribute of the files in the archive.
-Consult the C<Archive::Tar::File> documentation on how to use these
-objects.
-
-=item How do I access .tar.Z files?
-
-The C<Archive::Tar> module can optionally use C<Compress::Zlib> (via
-the C<IO::Zlib> module) to access tar files that have been compressed
-with C<gzip>. Unfortunately tar files compressed with the Unix C<compress>
-utility cannot be read by C<Compress::Zlib> and so cannot be directly
-accesses by C<Archive::Tar>.
-
-If the C<uncompress> or C<gunzip> programs are available, you can use
-one of these workarounds to read C<.tar.Z> files from C<Archive::Tar>
-
-Firstly with C<uncompress>
-
- use Archive::Tar;
-
- open F, "uncompress -c $filename |";
- my $tar = Archive::Tar->new(*F);
- ...
-
-and this with C<gunzip>
-
- use Archive::Tar;
-
- open F, "gunzip -c $filename |";
- my $tar = Archive::Tar->new(*F);
- ...
-
-Similarly, if the C<compress> program is available, you can use this to
-write a C<.tar.Z> file
-
- use Archive::Tar;
- use IO::File;
-
- my $fh = new IO::File "| compress -c >$filename";
- my $tar = Archive::Tar->new();
- ...
- $tar->write($fh);
- $fh->close ;
-
-=item How do I handle Unicode strings?
-
-C<Archive::Tar> uses byte semantics for any files it reads from or writes
-to disk. This is not a problem if you only deal with files and never
-look at their content or work solely with byte strings. But if you use
-Unicode strings with character semantics, some additional steps need
-to be taken.
-
-For example, if you add a Unicode string like
-
- # Problem
- $tar->add_data('file.txt', "Euro: \x{20AC}");
-
-then there will be a problem later when the tarfile gets written out
-to disk via C<$tar->write()>:
-
- Wide character in print at .../Archive/Tar.pm line 1014.
-
-The data was added as a Unicode string and when writing it out to disk,
-the C<:utf8> line discipline wasn't set by C<Archive::Tar>, so Perl
-tried to convert the string to ISO-8859 and failed. The written file
-now contains garbage.
-
-For this reason, Unicode strings need to be converted to UTF-8-encoded
-bytestrings before they are handed off to C<add_data()>:
-
- use Encode;
- my $data = "Accented character: \x{20AC}";
- $data = encode('utf8', $data);
-
- $tar->add_data('file.txt', $data);
-
-A opposite problem occurs if you extract a UTF8-encoded file from a
-tarball. Using C<get_content()> on the C<Archive::Tar::File> object
-will return its content as a bytestring, not as a Unicode string.
-
-If you want it to be a Unicode string (because you want character
-semantics with operations like regular expression matching), you need
-to decode the UTF8-encoded content and have Perl convert it into
-a Unicode string:
-
- use Encode;
- my $data = $tar->get_content();
-
- # Make it a Unicode string
- $data = decode('utf8', $data);
-
-There is no easy way to provide this functionality in C<Archive::Tar>,
-because a tarball can contain many files, and each of which could be
-encoded in a different way.
-
-=back
-
-=head1 CAVEATS
-
-The AIX tar does not fill all unused space in the tar archive with 0x00.
-This sometimes leads to warning messages from C<Archive::Tar>.
-
- Invalid header block at offset nnn
-
-A fix for that problem is scheduled to be released in the following levels
-of AIX, all of which should be coming out in the 4th quarter of 2009:
-
- AIX 5.3 TL7 SP10
- AIX 5.3 TL8 SP8
- AIX 5.3 TL9 SP5
- AIX 5.3 TL10 SP2
-
- AIX 6.1 TL0 SP11
- AIX 6.1 TL1 SP7
- AIX 6.1 TL2 SP6
- AIX 6.1 TL3 SP3
-
-The IBM APAR number for this problem is IZ50240 (Reported component ID:
-5765G0300 / AIX 5.3). It is possible to get an ifix for that problem.
-If you need an ifix please contact your local IBM AIX support.
-
-=head1 TODO
-
-=over 4
-
-=item Check if passed in handles are open for read/write
-
-Currently I don't know of any portable pure perl way to do this.
-Suggestions welcome.
-
-=item Allow archives to be passed in as string
-
-Currently, we only allow opened filehandles or filenames, but
-not strings. The internals would need some reworking to facilitate
-stringified archives.
-
-=item Facilitate processing an opened filehandle of a compressed archive
-
-Currently, we only support this if the filehandle is an IO::Zlib object.
-Environments, like apache, will present you with an opened filehandle
-to an uploaded file, which might be a compressed archive.
-
-=back
-
-=head1 SEE ALSO
-
-=over 4
-
-=item The GNU tar specification
-
-C<http://www.gnu.org/software/tar/manual/tar.html>
-
-=item The PAX format specication
-
-The specifcation which tar derives from; C< http://www.opengroup.org/onlinepubs/007904975/utilities/pax.html>
-
-=item A comparison of GNU and POSIX tar standards; C<http://www.delorie.com/gnu/docs/tar/tar_114.html>
-
-=item GNU tar intends to switch to POSIX compatibility
-
-GNU Tar authors have expressed their intention to become completely
-POSIX-compatible; C<http://www.gnu.org/software/tar/manual/html_node/Formats.html>
-
-=item A Comparison between various tar implementations
-
-Lists known issues and incompatibilities; C<http://gd.tuwien.ac.at/utils/archivers/star/README.otherbugs>
-
-=back
-
-=head1 AUTHOR
-
-This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
-
-Please reports bugs to E<lt>bug-archive-tar@rt.cpan.orgE<gt>.
-
-=head1 ACKNOWLEDGEMENTS
-
-Thanks to Sean Burke, Chris Nandor, Chip Salzenberg, Tim Heaney, Gisle Aas,
-Rainer Tammer and especially Andrew Savige for their help and suggestions.
-
-=head1 COPYRIGHT
-
-This module is copyright (c) 2002 - 2009 Jos Boumans
-E<lt>kane@cpan.orgE<gt>. All rights reserved.
-
-This library is free software; you may redistribute and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/Master/tlpkg/tlperl/lib/Archive/Tar/Constant.pm b/Master/tlpkg/tlperl/lib/Archive/Tar/Constant.pm
deleted file mode 100755
index aef1d623fa8..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Tar/Constant.pm
+++ /dev/null
@@ -1,86 +0,0 @@
-package Archive::Tar::Constant;
-
-BEGIN {
- require Exporter;
-
- $VERSION = '0.02';
- @ISA = qw[Exporter];
-
- require Time::Local if $^O eq "MacOS";
-}
-
-use Package::Constants;
-@EXPORT = Package::Constants->list( __PACKAGE__ );
-
-use constant FILE => 0;
-use constant HARDLINK => 1;
-use constant SYMLINK => 2;
-use constant CHARDEV => 3;
-use constant BLOCKDEV => 4;
-use constant DIR => 5;
-use constant FIFO => 6;
-use constant SOCKET => 8;
-use constant UNKNOWN => 9;
-use constant LONGLINK => 'L';
-use constant LABEL => 'V';
-
-use constant BUFFER => 4096;
-use constant HEAD => 512;
-use constant BLOCK => 512;
-
-use constant COMPRESS_GZIP => 9;
-use constant COMPRESS_BZIP => 'bzip2';
-
-use constant BLOCK_SIZE => sub { my $n = int($_[0]/BLOCK); $n++ if $_[0] % BLOCK; $n * BLOCK };
-use constant TAR_PAD => sub { my $x = shift || return; return "\0" x (BLOCK - ($x % BLOCK) ) };
-use constant TAR_END => "\0" x BLOCK;
-
-use constant READ_ONLY => sub { shift() ? 'rb' : 'r' };
-use constant WRITE_ONLY => sub { $_[0] ? 'wb' . shift : 'w' };
-use constant MODE_READ => sub { $_[0] =~ /^r/ ? 1 : 0 };
-
-# Pointless assignment to make -w shut up
-my $getpwuid; $getpwuid = 'unknown' unless eval { my $f = getpwuid (0); };
-my $getgrgid; $getgrgid = 'unknown' unless eval { my $f = getgrgid (0); };
-use constant UNAME => sub { $getpwuid || scalar getpwuid( shift() ) || '' };
-use constant GNAME => sub { $getgrgid || scalar getgrgid( shift() ) || '' };
-use constant UID => $>;
-use constant GID => (split ' ', $) )[0];
-
-use constant MODE => do { 0666 & (0777 & ~umask) };
-use constant STRIP_MODE => sub { shift() & 0777 };
-use constant CHECK_SUM => " ";
-
-use constant UNPACK => 'A100 A8 A8 A8 A12 A12 A8 A1 A100 A6 A2 A32 A32 A8 A8 A155 x12';
-use constant PACK => 'a100 a8 a8 a8 a12 a12 A8 a1 a100 a6 a2 a32 a32 a8 a8 a155 x12';
-use constant NAME_LENGTH => 100;
-use constant PREFIX_LENGTH => 155;
-
-use constant TIME_OFFSET => ($^O eq "MacOS") ? Time::Local::timelocal(0,0,0,1,0,70) : 0;
-use constant MAGIC => "ustar";
-use constant TAR_VERSION => "00";
-use constant LONGLINK_NAME => '././@LongLink';
-use constant PAX_HEADER => 'pax_global_header';
-
- ### allow ZLIB to be turned off using ENV: DEBUG only
-use constant ZLIB => do { !$ENV{'PERL5_AT_NO_ZLIB'} and
- eval { require IO::Zlib };
- $ENV{'PERL5_AT_NO_ZLIB'} || $@ ? 0 : 1
- };
-
- ### allow BZIP to be turned off using ENV: DEBUG only
-use constant BZIP => do { !$ENV{'PERL5_AT_NO_BZIP'} and
- eval { require IO::Uncompress::Bunzip2;
- require IO::Compress::Bzip2; };
- $ENV{'PERL5_AT_NO_BZIP'} || $@ ? 0 : 1
- };
-
-use constant GZIP_MAGIC_NUM => qr/^(?:\037\213|\037\235)/;
-use constant BZIP_MAGIC_NUM => qr/^BZh\d/;
-
-use constant CAN_CHOWN => sub { ($> == 0 and $^O ne "MacOS" and $^O ne "MSWin32") };
-use constant CAN_READLINK => ($^O ne 'MSWin32' and $^O !~ /RISC(?:[ _])?OS/i and $^O ne 'VMS');
-use constant ON_UNIX => ($^O ne 'MSWin32' and $^O ne 'MacOS' and $^O ne 'VMS');
-use constant ON_VMS => $^O eq 'VMS';
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Tar/File.pm b/Master/tlpkg/tlperl/lib/Archive/Tar/File.pm
deleted file mode 100755
index 0815bb67620..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Tar/File.pm
+++ /dev/null
@@ -1,660 +0,0 @@
-package Archive::Tar::File;
-use strict;
-
-use Carp ();
-use IO::File;
-use File::Spec::Unix ();
-use File::Spec ();
-use File::Basename ();
-
-### avoid circular use, so only require;
-require Archive::Tar;
-use Archive::Tar::Constant;
-
-use vars qw[@ISA $VERSION];
-#@ISA = qw[Archive::Tar];
-$VERSION = '0.02';
-
-### set value to 1 to oct() it during the unpack ###
-my $tmpl = [
- name => 0, # string
- mode => 1, # octal
- uid => 1, # octal
- gid => 1, # octal
- size => 1, # octal
- mtime => 1, # octal
- chksum => 1, # octal
- type => 0, # character
- linkname => 0, # string
- magic => 0, # string
- version => 0, # 2 bytes
- uname => 0, # string
- gname => 0, # string
- devmajor => 1, # octal
- devminor => 1, # octal
- prefix => 0,
-
-### end UNPACK items ###
- raw => 0, # the raw data chunk
- data => 0, # the data associated with the file --
- # This might be very memory intensive
-];
-
-### install get/set accessors for this object.
-for ( my $i=0; $i<scalar @$tmpl ; $i+=2 ) {
- my $key = $tmpl->[$i];
- no strict 'refs';
- *{__PACKAGE__."::$key"} = sub {
- my $self = shift;
- $self->{$key} = $_[0] if @_;
-
- ### just in case the key is not there or undef or something ###
- { local $^W = 0;
- return $self->{$key};
- }
- }
-}
-
-=head1 NAME
-
-Archive::Tar::File - a subclass for in-memory extracted file from Archive::Tar
-
-=head1 SYNOPSIS
-
- my @items = $tar->get_files;
-
- print $_->name, ' ', $_->size, "\n" for @items;
-
- print $object->get_content;
- $object->replace_content('new content');
-
- $object->rename( 'new/full/path/to/file.c' );
-
-=head1 DESCRIPTION
-
-Archive::Tar::Files provides a neat little object layer for in-memory
-extracted files. It's mostly used internally in Archive::Tar to tidy
-up the code, but there's no reason users shouldn't use this API as
-well.
-
-=head2 Accessors
-
-A lot of the methods in this package are accessors to the various
-fields in the tar header:
-
-=over 4
-
-=item name
-
-The file's name
-
-=item mode
-
-The file's mode
-
-=item uid
-
-The user id owning the file
-
-=item gid
-
-The group id owning the file
-
-=item size
-
-File size in bytes
-
-=item mtime
-
-Modification time. Adjusted to mac-time on MacOS if required
-
-=item chksum
-
-Checksum field for the tar header
-
-=item type
-
-File type -- numeric, but comparable to exported constants -- see
-Archive::Tar's documentation
-
-=item linkname
-
-If the file is a symlink, the file it's pointing to
-
-=item magic
-
-Tar magic string -- not useful for most users
-
-=item version
-
-Tar version string -- not useful for most users
-
-=item uname
-
-The user name that owns the file
-
-=item gname
-
-The group name that owns the file
-
-=item devmajor
-
-Device major number in case of a special file
-
-=item devminor
-
-Device minor number in case of a special file
-
-=item prefix
-
-Any directory to prefix to the extraction path, if any
-
-=item raw
-
-Raw tar header -- not useful for most users
-
-=back
-
-=head1 Methods
-
-=head2 Archive::Tar::File->new( file => $path )
-
-Returns a new Archive::Tar::File object from an existing file.
-
-Returns undef on failure.
-
-=head2 Archive::Tar::File->new( data => $path, $data, $opt )
-
-Returns a new Archive::Tar::File object from data.
-
-C<$path> defines the file name (which need not exist), C<$data> the
-file contents, and C<$opt> is a reference to a hash of attributes
-which may be used to override the default attributes (fields in the
-tar header), which are described above in the Accessors section.
-
-Returns undef on failure.
-
-=head2 Archive::Tar::File->new( chunk => $chunk )
-
-Returns a new Archive::Tar::File object from a raw 512-byte tar
-archive chunk.
-
-Returns undef on failure.
-
-=cut
-
-sub new {
- my $class = shift;
- my $what = shift;
-
- my $obj = ($what eq 'chunk') ? __PACKAGE__->_new_from_chunk( @_ ) :
- ($what eq 'file' ) ? __PACKAGE__->_new_from_file( @_ ) :
- ($what eq 'data' ) ? __PACKAGE__->_new_from_data( @_ ) :
- undef;
-
- return $obj;
-}
-
-### copies the data, creates a clone ###
-sub clone {
- my $self = shift;
- return bless { %$self }, ref $self;
-}
-
-sub _new_from_chunk {
- my $class = shift;
- my $chunk = shift or return; # 512 bytes of tar header
- my %hash = @_;
-
- ### filter any arguments on defined-ness of values.
- ### this allows overriding from what the tar-header is saying
- ### about this tar-entry. Particularly useful for @LongLink files
- my %args = map { $_ => $hash{$_} } grep { defined $hash{$_} } keys %hash;
-
- ### makes it start at 0 actually... :) ###
- my $i = -1;
- my %entry = map {
- $tmpl->[++$i] => $tmpl->[++$i] ? oct $_ : $_
- } map { /^([^\0]*)/ } unpack( UNPACK, $chunk );
-
- my $obj = bless { %entry, %args }, $class;
-
- ### magic is a filetype string.. it should have something like 'ustar' or
- ### something similar... if the chunk is garbage, skip it
- return unless $obj->magic !~ /\W/;
-
- ### store the original chunk ###
- $obj->raw( $chunk );
-
- $obj->type(FILE) if ( (!length $obj->type) or ($obj->type =~ /\W/) );
- $obj->type(DIR) if ( ($obj->is_file) && ($obj->name =~ m|/$|) );
-
-
- return $obj;
-
-}
-
-sub _new_from_file {
- my $class = shift;
- my $path = shift;
-
- ### path has to at least exist
- return unless defined $path;
-
- my $type = __PACKAGE__->_filetype($path);
- my $data = '';
-
- READ: {
- unless ($type == DIR ) {
- my $fh = IO::File->new;
-
- unless( $fh->open($path) ) {
- ### dangling symlinks are fine, stop reading but continue
- ### creating the object
- last READ if $type == SYMLINK;
-
- ### otherwise, return from this function --
- ### anything that's *not* a symlink should be
- ### resolvable
- return;
- }
-
- ### binmode needed to read files properly on win32 ###
- binmode $fh;
- $data = do { local $/; <$fh> };
- close $fh;
- }
- }
-
- my @items = qw[mode uid gid size mtime];
- my %hash = map { shift(@items), $_ } (lstat $path)[2,4,5,7,9];
-
- if (ON_VMS) {
- ### VMS has two UID modes, traditional and POSIX. Normally POSIX is
- ### not used. We currently do not have an easy way to see if we are in
- ### POSIX mode. In traditional mode, the UID is actually the VMS UIC.
- ### The VMS UIC has the upper 16 bits is the GID, which in many cases
- ### the VMS UIC will be larger than 209715, the largest that TAR can
- ### handle. So for now, assume it is traditional if the UID is larger
- ### than 0x10000.
-
- if ($hash{uid} > 0x10000) {
- $hash{uid} = $hash{uid} & 0xFFFF;
- }
-
- ### The file length from stat() is the physical length of the file
- ### However the amount of data read in may be more for some file types.
- ### Fixed length files are read past the logical EOF to end of the block
- ### containing. Other file types get expanded on read because record
- ### delimiters are added.
-
- my $data_len = length $data;
- $hash{size} = $data_len if $hash{size} < $data_len;
-
- }
- ### you *must* set size == 0 on symlinks, or the next entry will be
- ### though of as the contents of the symlink, which is wrong.
- ### this fixes bug #7937
- $hash{size} = 0 if ($type == DIR or $type == SYMLINK);
- $hash{mtime} -= TIME_OFFSET;
-
- ### strip the high bits off the mode, which we don't need to store
- $hash{mode} = STRIP_MODE->( $hash{mode} );
-
-
- ### probably requires some file path munging here ... ###
- ### name and prefix are set later
- my $obj = {
- %hash,
- name => '',
- chksum => CHECK_SUM,
- type => $type,
- linkname => ($type == SYMLINK and CAN_READLINK)
- ? readlink $path
- : '',
- magic => MAGIC,
- version => TAR_VERSION,
- uname => UNAME->( $hash{uid} ),
- gname => GNAME->( $hash{gid} ),
- devmajor => 0, # not handled
- devminor => 0, # not handled
- prefix => '',
- data => $data,
- };
-
- bless $obj, $class;
-
- ### fix up the prefix and file from the path
- my($prefix,$file) = $obj->_prefix_and_file( $path );
- $obj->prefix( $prefix );
- $obj->name( $file );
-
- return $obj;
-}
-
-sub _new_from_data {
- my $class = shift;
- my $path = shift; return unless defined $path;
- my $data = shift; return unless defined $data;
- my $opt = shift;
-
- my $obj = {
- data => $data,
- name => '',
- mode => MODE,
- uid => UID,
- gid => GID,
- size => length $data,
- mtime => time - TIME_OFFSET,
- chksum => CHECK_SUM,
- type => FILE,
- linkname => '',
- magic => MAGIC,
- version => TAR_VERSION,
- uname => UNAME->( UID ),
- gname => GNAME->( GID ),
- devminor => 0,
- devmajor => 0,
- prefix => '',
- };
-
- ### overwrite with user options, if provided ###
- if( $opt and ref $opt eq 'HASH' ) {
- for my $key ( keys %$opt ) {
-
- ### don't write bogus options ###
- next unless exists $obj->{$key};
- $obj->{$key} = $opt->{$key};
- }
- }
-
- bless $obj, $class;
-
- ### fix up the prefix and file from the path
- my($prefix,$file) = $obj->_prefix_and_file( $path );
- $obj->prefix( $prefix );
- $obj->name( $file );
-
- return $obj;
-}
-
-sub _prefix_and_file {
- my $self = shift;
- my $path = shift;
-
- my ($vol, $dirs, $file) = File::Spec->splitpath( $path, $self->is_dir );
- my @dirs = File::Spec->splitdir( $dirs );
-
- ### so sometimes the last element is '' -- probably when trailing
- ### dir slashes are encountered... this is of course pointless,
- ### so remove it
- pop @dirs while @dirs and not length $dirs[-1];
-
- ### if it's a directory, then $file might be empty
- $file = pop @dirs if $self->is_dir and not length $file;
-
- ### splitting ../ gives you the relative path in native syntax
- map { $_ = '..' if $_ eq '-' } @dirs if ON_VMS;
-
- my $prefix = File::Spec::Unix->catdir(
- grep { length } $vol, @dirs
- );
- return( $prefix, $file );
-}
-
-sub _filetype {
- my $self = shift;
- my $file = shift;
-
- return unless defined $file;
-
- return SYMLINK if (-l $file); # Symlink
-
- return FILE if (-f _); # Plain file
-
- return DIR if (-d _); # Directory
-
- return FIFO if (-p _); # Named pipe
-
- return SOCKET if (-S _); # Socket
-
- return BLOCKDEV if (-b _); # Block special
-
- return CHARDEV if (-c _); # Character special
-
- ### shouldn't happen, this is when making archives, not reading ###
- return LONGLINK if ( $file eq LONGLINK_NAME );
-
- return UNKNOWN; # Something else (like what?)
-
-}
-
-### this method 'downgrades' a file to plain file -- this is used for
-### symlinks when FOLLOW_SYMLINKS is true.
-sub _downgrade_to_plainfile {
- my $entry = shift;
- $entry->type( FILE );
- $entry->mode( MODE );
- $entry->linkname('');
-
- return 1;
-}
-
-=head2 $bool = $file->extract( [ $alternative_name ] )
-
-Extract this object, optionally to an alternative name.
-
-See C<< Archive::Tar->extract_file >> for details.
-
-Returns true on success and false on failure.
-
-=cut
-
-sub extract {
- my $self = shift;
-
- local $Carp::CarpLevel += 1;
-
- return Archive::Tar->_extract_file( $self, @_ );
-}
-
-=head2 $path = $file->full_path
-
-Returns the full path from the tar header; this is basically a
-concatenation of the C<prefix> and C<name> fields.
-
-=cut
-
-sub full_path {
- my $self = shift;
-
- ### if prefix field is emtpy
- return $self->name unless defined $self->prefix and length $self->prefix;
-
- ### or otherwise, catfile'd
- return File::Spec::Unix->catfile( $self->prefix, $self->name );
-}
-
-
-=head2 $bool = $file->validate
-
-Done by Archive::Tar internally when reading the tar file:
-validate the header against the checksum to ensure integer tar file.
-
-Returns true on success, false on failure
-
-=cut
-
-sub validate {
- my $self = shift;
-
- my $raw = $self->raw;
-
- ### don't know why this one is different from the one we /write/ ###
- substr ($raw, 148, 8) = " ";
-
- ### bug #43513: [PATCH] Accept wrong checksums from SunOS and HP-UX tar
- ### like GNU tar does. See here for details:
- ### http://www.gnu.org/software/tar/manual/tar.html#SEC139
- ### so we do both a signed AND unsigned validate. if one succeeds, that's
- ### good enough
- return ( (unpack ("%16C*", $raw) == $self->chksum)
- or (unpack ("%16c*", $raw) == $self->chksum)) ? 1 : 0;
-}
-
-=head2 $bool = $file->has_content
-
-Returns a boolean to indicate whether the current object has content.
-Some special files like directories and so on never will have any
-content. This method is mainly to make sure you don't get warnings
-for using uninitialized values when looking at an object's content.
-
-=cut
-
-sub has_content {
- my $self = shift;
- return defined $self->data() && length $self->data() ? 1 : 0;
-}
-
-=head2 $content = $file->get_content
-
-Returns the current content for the in-memory file
-
-=cut
-
-sub get_content {
- my $self = shift;
- $self->data( );
-}
-
-=head2 $cref = $file->get_content_by_ref
-
-Returns the current content for the in-memory file as a scalar
-reference. Normal users won't need this, but it will save memory if
-you are dealing with very large data files in your tar archive, since
-it will pass the contents by reference, rather than make a copy of it
-first.
-
-=cut
-
-sub get_content_by_ref {
- my $self = shift;
-
- return \$self->{data};
-}
-
-=head2 $bool = $file->replace_content( $content )
-
-Replace the current content of the file with the new content. This
-only affects the in-memory archive, not the on-disk version until
-you write it.
-
-Returns true on success, false on failure.
-
-=cut
-
-sub replace_content {
- my $self = shift;
- my $data = shift || '';
-
- $self->data( $data );
- $self->size( length $data );
- return 1;
-}
-
-=head2 $bool = $file->rename( $new_name )
-
-Rename the current file to $new_name.
-
-Note that you must specify a Unix path for $new_name, since per tar
-standard, all files in the archive must be Unix paths.
-
-Returns true on success and false on failure.
-
-=cut
-
-sub rename {
- my $self = shift;
- my $path = shift;
-
- return unless defined $path;
-
- my ($prefix,$file) = $self->_prefix_and_file( $path );
-
- $self->name( $file );
- $self->prefix( $prefix );
-
- return 1;
-}
-
-=head1 Convenience methods
-
-To quickly check the type of a C<Archive::Tar::File> object, you can
-use the following methods:
-
-=over 4
-
-=item $file->is_file
-
-Returns true if the file is of type C<file>
-
-=item $file->is_dir
-
-Returns true if the file is of type C<dir>
-
-=item $file->is_hardlink
-
-Returns true if the file is of type C<hardlink>
-
-=item $file->is_symlink
-
-Returns true if the file is of type C<symlink>
-
-=item $file->is_chardev
-
-Returns true if the file is of type C<chardev>
-
-=item $file->is_blockdev
-
-Returns true if the file is of type C<blockdev>
-
-=item $file->is_fifo
-
-Returns true if the file is of type C<fifo>
-
-=item $file->is_socket
-
-Returns true if the file is of type C<socket>
-
-=item $file->is_longlink
-
-Returns true if the file is of type C<LongLink>.
-Should not happen after a successful C<read>.
-
-=item $file->is_label
-
-Returns true if the file is of type C<Label>.
-Should not happen after a successful C<read>.
-
-=item $file->is_unknown
-
-Returns true if the file type is C<unknown>
-
-=back
-
-=cut
-
-#stupid perl5.5.3 needs to warn if it's not numeric
-sub is_file { local $^W; FILE == $_[0]->type }
-sub is_dir { local $^W; DIR == $_[0]->type }
-sub is_hardlink { local $^W; HARDLINK == $_[0]->type }
-sub is_symlink { local $^W; SYMLINK == $_[0]->type }
-sub is_chardev { local $^W; CHARDEV == $_[0]->type }
-sub is_blockdev { local $^W; BLOCKDEV == $_[0]->type }
-sub is_fifo { local $^W; FIFO == $_[0]->type }
-sub is_socket { local $^W; SOCKET == $_[0]->type }
-sub is_unknown { local $^W; UNKNOWN == $_[0]->type }
-sub is_longlink { local $^W; LONGLINK eq $_[0]->type }
-sub is_label { local $^W; LABEL eq $_[0]->type }
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip.pm b/Master/tlpkg/tlperl/lib/Archive/Zip.pm
deleted file mode 100755
index 8fd86c93b72..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip.pm
+++ /dev/null
@@ -1,2059 +0,0 @@
-package Archive::Zip;
-
-use strict;
-BEGIN {
- require 5.003_96;
-}
-use UNIVERSAL ();
-use Carp ();
-use Cwd ();
-use IO::File ();
-use IO::Seekable ();
-use Compress::Raw::Zlib ();
-use File::Spec ();
-use File::Temp ();
-use FileHandle ();
-
-use vars qw( $VERSION @ISA );
-BEGIN {
- $VERSION = '1.30';
-
- require Exporter;
- @ISA = qw( Exporter );
-}
-
-use vars qw( $ChunkSize $ErrorHandler );
-BEGIN {
- # This is the size we'll try to read, write, and (de)compress.
- # You could set it to something different if you had lots of memory
- # and needed more speed.
- $ChunkSize ||= 32768;
-
- $ErrorHandler = \&Carp::carp;
-}
-
-# BEGIN block is necessary here so that other modules can use the constants.
-use vars qw( @EXPORT_OK %EXPORT_TAGS );
-BEGIN {
- @EXPORT_OK = ('computeCRC32');
- %EXPORT_TAGS = (
- CONSTANTS => [ qw(
- FA_MSDOS
- FA_UNIX
- GPBF_ENCRYPTED_MASK
- GPBF_DEFLATING_COMPRESSION_MASK
- GPBF_HAS_DATA_DESCRIPTOR_MASK
- COMPRESSION_STORED
- COMPRESSION_DEFLATED
- COMPRESSION_LEVEL_NONE
- COMPRESSION_LEVEL_DEFAULT
- COMPRESSION_LEVEL_FASTEST
- COMPRESSION_LEVEL_BEST_COMPRESSION
- IFA_TEXT_FILE_MASK
- IFA_TEXT_FILE
- IFA_BINARY_FILE
- ) ],
-
- MISC_CONSTANTS => [ qw(
- FA_AMIGA
- FA_VAX_VMS
- FA_VM_CMS
- FA_ATARI_ST
- FA_OS2_HPFS
- FA_MACINTOSH
- FA_Z_SYSTEM
- FA_CPM
- FA_TOPS20
- FA_WINDOWS_NTFS
- FA_QDOS
- FA_ACORN
- FA_VFAT
- FA_MVS
- FA_BEOS
- FA_TANDEM
- FA_THEOS
- GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK
- GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK
- GPBF_IS_COMPRESSED_PATCHED_DATA_MASK
- COMPRESSION_SHRUNK
- DEFLATING_COMPRESSION_NORMAL
- DEFLATING_COMPRESSION_MAXIMUM
- DEFLATING_COMPRESSION_FAST
- DEFLATING_COMPRESSION_SUPER_FAST
- COMPRESSION_REDUCED_1
- COMPRESSION_REDUCED_2
- COMPRESSION_REDUCED_3
- COMPRESSION_REDUCED_4
- COMPRESSION_IMPLODED
- COMPRESSION_TOKENIZED
- COMPRESSION_DEFLATED_ENHANCED
- COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED
- ) ],
-
- ERROR_CODES => [ qw(
- AZ_OK
- AZ_STREAM_END
- AZ_ERROR
- AZ_FORMAT_ERROR
- AZ_IO_ERROR
- ) ],
-
- # For Internal Use Only
- PKZIP_CONSTANTS => [ qw(
- SIGNATURE_FORMAT
- SIGNATURE_LENGTH
- LOCAL_FILE_HEADER_SIGNATURE
- LOCAL_FILE_HEADER_FORMAT
- LOCAL_FILE_HEADER_LENGTH
- CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE
- DATA_DESCRIPTOR_FORMAT
- DATA_DESCRIPTOR_LENGTH
- DATA_DESCRIPTOR_SIGNATURE
- DATA_DESCRIPTOR_FORMAT_NO_SIG
- DATA_DESCRIPTOR_LENGTH_NO_SIG
- CENTRAL_DIRECTORY_FILE_HEADER_FORMAT
- CENTRAL_DIRECTORY_FILE_HEADER_LENGTH
- END_OF_CENTRAL_DIRECTORY_SIGNATURE
- END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING
- END_OF_CENTRAL_DIRECTORY_FORMAT
- END_OF_CENTRAL_DIRECTORY_LENGTH
- ) ],
-
- # For Internal Use Only
- UTILITY_METHODS => [ qw(
- _error
- _printError
- _ioError
- _formatError
- _subclassResponsibility
- _binmode
- _isSeekable
- _newFileHandle
- _readSignature
- _asZipDirName
- ) ],
- );
-
- # Add all the constant names and error code names to @EXPORT_OK
- Exporter::export_ok_tags( qw(
- CONSTANTS
- ERROR_CODES
- PKZIP_CONSTANTS
- UTILITY_METHODS
- MISC_CONSTANTS
- ) );
-
-}
-
-# Error codes
-use constant AZ_OK => 0;
-use constant AZ_STREAM_END => 1;
-use constant AZ_ERROR => 2;
-use constant AZ_FORMAT_ERROR => 3;
-use constant AZ_IO_ERROR => 4;
-
-# File types
-# Values of Archive::Zip::Member->fileAttributeFormat()
-
-use constant FA_MSDOS => 0;
-use constant FA_AMIGA => 1;
-use constant FA_VAX_VMS => 2;
-use constant FA_UNIX => 3;
-use constant FA_VM_CMS => 4;
-use constant FA_ATARI_ST => 5;
-use constant FA_OS2_HPFS => 6;
-use constant FA_MACINTOSH => 7;
-use constant FA_Z_SYSTEM => 8;
-use constant FA_CPM => 9;
-use constant FA_TOPS20 => 10;
-use constant FA_WINDOWS_NTFS => 11;
-use constant FA_QDOS => 12;
-use constant FA_ACORN => 13;
-use constant FA_VFAT => 14;
-use constant FA_MVS => 15;
-use constant FA_BEOS => 16;
-use constant FA_TANDEM => 17;
-use constant FA_THEOS => 18;
-
-# general-purpose bit flag masks
-# Found in Archive::Zip::Member->bitFlag()
-
-use constant GPBF_ENCRYPTED_MASK => 1 << 0;
-use constant GPBF_DEFLATING_COMPRESSION_MASK => 3 << 1;
-use constant GPBF_HAS_DATA_DESCRIPTOR_MASK => 1 << 3;
-
-# deflating compression types, if compressionMethod == COMPRESSION_DEFLATED
-# ( Archive::Zip::Member->bitFlag() & GPBF_DEFLATING_COMPRESSION_MASK )
-
-use constant DEFLATING_COMPRESSION_NORMAL => 0 << 1;
-use constant DEFLATING_COMPRESSION_MAXIMUM => 1 << 1;
-use constant DEFLATING_COMPRESSION_FAST => 2 << 1;
-use constant DEFLATING_COMPRESSION_SUPER_FAST => 3 << 1;
-
-# compression method
-
-# these two are the only ones supported in this module
-use constant COMPRESSION_STORED => 0; # file is stored (no compression)
-use constant COMPRESSION_DEFLATED => 8; # file is Deflated
-use constant COMPRESSION_LEVEL_NONE => 0;
-use constant COMPRESSION_LEVEL_DEFAULT => -1;
-use constant COMPRESSION_LEVEL_FASTEST => 1;
-use constant COMPRESSION_LEVEL_BEST_COMPRESSION => 9;
-
-# internal file attribute bits
-# Found in Archive::Zip::Member::internalFileAttributes()
-
-use constant IFA_TEXT_FILE_MASK => 1;
-use constant IFA_TEXT_FILE => 1;
-use constant IFA_BINARY_FILE => 0;
-
-# PKZIP file format miscellaneous constants (for internal use only)
-use constant SIGNATURE_FORMAT => "V";
-use constant SIGNATURE_LENGTH => 4;
-
-# these lengths are without the signature.
-use constant LOCAL_FILE_HEADER_SIGNATURE => 0x04034b50;
-use constant LOCAL_FILE_HEADER_FORMAT => "v3 V4 v2";
-use constant LOCAL_FILE_HEADER_LENGTH => 26;
-
-# PKZIP docs don't mention the signature, but Info-Zip writes it.
-use constant DATA_DESCRIPTOR_SIGNATURE => 0x08074b50;
-use constant DATA_DESCRIPTOR_FORMAT => "V3";
-use constant DATA_DESCRIPTOR_LENGTH => 12;
-
-# but the signature is apparently optional.
-use constant DATA_DESCRIPTOR_FORMAT_NO_SIG => "V2";
-use constant DATA_DESCRIPTOR_LENGTH_NO_SIG => 8;
-
-use constant CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE => 0x02014b50;
-use constant CENTRAL_DIRECTORY_FILE_HEADER_FORMAT => "C2 v3 V4 v5 V2";
-use constant CENTRAL_DIRECTORY_FILE_HEADER_LENGTH => 42;
-
-use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE => 0x06054b50;
-use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING =>
- pack( "V", END_OF_CENTRAL_DIRECTORY_SIGNATURE );
-use constant END_OF_CENTRAL_DIRECTORY_FORMAT => "v4 V2 v";
-use constant END_OF_CENTRAL_DIRECTORY_LENGTH => 18;
-
-use constant GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK => 1 << 1;
-use constant GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK => 1 << 2;
-use constant GPBF_IS_COMPRESSED_PATCHED_DATA_MASK => 1 << 5;
-
-# the rest of these are not supported in this module
-use constant COMPRESSION_SHRUNK => 1; # file is Shrunk
-use constant COMPRESSION_REDUCED_1 => 2; # file is Reduced CF=1
-use constant COMPRESSION_REDUCED_2 => 3; # file is Reduced CF=2
-use constant COMPRESSION_REDUCED_3 => 4; # file is Reduced CF=3
-use constant COMPRESSION_REDUCED_4 => 5; # file is Reduced CF=4
-use constant COMPRESSION_IMPLODED => 6; # file is Imploded
-use constant COMPRESSION_TOKENIZED => 7; # reserved for Tokenizing compr.
-use constant COMPRESSION_DEFLATED_ENHANCED => 9; # reserved for enh. Deflating
-use constant COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED => 10;
-
-# Load the various required classes
-require Archive::Zip::Archive;
-require Archive::Zip::Member;
-require Archive::Zip::FileMember;
-require Archive::Zip::DirectoryMember;
-require Archive::Zip::ZipFileMember;
-require Archive::Zip::NewFileMember;
-require Archive::Zip::StringMember;
-
-use constant ZIPARCHIVECLASS => 'Archive::Zip::Archive';
-use constant ZIPMEMBERCLASS => 'Archive::Zip::Member';
-
-# Convenience functions
-
-sub _ISA ($$) {
- # Can't rely on Scalar::Util, so use the next best way
- local $@;
- !! eval { ref $_[0] and $_[0]->isa($_[1]) };
-}
-
-sub _CAN ($$) {
- local $@;
- !! eval { ref $_[0] and $_[0]->can($_[1]) };
-}
-
-
-
-
-
-#####################################################################
-# Methods
-
-sub new {
- my $class = shift;
- return $class->ZIPARCHIVECLASS->new(@_);
-}
-
-sub computeCRC32 {
- my ( $data, $crc );
-
- if ( ref( $_[0] ) eq 'HASH' ) {
- $data = $_[0]->{string};
- $crc = $_[0]->{checksum};
- }
- else {
- $data = shift;
- $data = shift if ref($data);
- $crc = shift;
- }
-
- return Compress::Raw::Zlib::crc32( $data, $crc );
-}
-
-# Report or change chunk size used for reading and writing.
-# Also sets Zlib's default buffer size (eventually).
-sub setChunkSize {
- shift if ref( $_[0] ) eq 'Archive::Zip::Archive';
- my $chunkSize = ( ref( $_[0] ) eq 'HASH' ) ? shift->{chunkSize} : shift;
- my $oldChunkSize = $Archive::Zip::ChunkSize;
- $Archive::Zip::ChunkSize = $chunkSize if ($chunkSize);
- return $oldChunkSize;
-}
-
-sub chunkSize {
- return $Archive::Zip::ChunkSize;
-}
-
-sub setErrorHandler {
- my $errorHandler = ( ref( $_[0] ) eq 'HASH' ) ? shift->{subroutine} : shift;
- $errorHandler = \&Carp::carp unless defined($errorHandler);
- my $oldErrorHandler = $Archive::Zip::ErrorHandler;
- $Archive::Zip::ErrorHandler = $errorHandler;
- return $oldErrorHandler;
-}
-
-
-
-
-
-######################################################################
-# Private utility functions (not methods).
-
-sub _printError {
- my $string = join ( ' ', @_, "\n" );
- my $oldCarpLevel = $Carp::CarpLevel;
- $Carp::CarpLevel += 2;
- &{$ErrorHandler} ($string);
- $Carp::CarpLevel = $oldCarpLevel;
-}
-
-# This is called on format errors.
-sub _formatError {
- shift if ref( $_[0] );
- _printError( 'format error:', @_ );
- return AZ_FORMAT_ERROR;
-}
-
-# This is called on IO errors.
-sub _ioError {
- shift if ref( $_[0] );
- _printError( 'IO error:', @_, ':', $! );
- return AZ_IO_ERROR;
-}
-
-# This is called on generic errors.
-sub _error {
- shift if ref( $_[0] );
- _printError( 'error:', @_ );
- return AZ_ERROR;
-}
-
-# Called when a subclass should have implemented
-# something but didn't
-sub _subclassResponsibility {
- Carp::croak("subclass Responsibility\n");
-}
-
-# Try to set the given file handle or object into binary mode.
-sub _binmode {
- my $fh = shift;
- return _CAN( $fh, 'binmode' ) ? $fh->binmode() : binmode($fh);
-}
-
-# Attempt to guess whether file handle is seekable.
-# Because of problems with Windows, this only returns true when
-# the file handle is a real file.
-sub _isSeekable {
- my $fh = shift;
- return 0 unless ref $fh;
- if ( _ISA($fh, 'IO::Scalar') ) {
- # IO::Scalar objects are brokenly-seekable
- return 0;
- }
- if ( _ISA($fh, 'IO::String') ) {
- return 1;
- }
- if ( _ISA($fh, 'IO::Seekable') ) {
- # Unfortunately, some things like FileHandle objects
- # return true for Seekable, but AREN'T!!!!!
- if ( _ISA($fh, 'FileHandle') ) {
- return 0;
- } else {
- return 1;
- }
- }
- if ( _CAN($fh, 'stat') ) {
- return -f $fh;
- }
- return (
- _CAN($fh, 'seek') and _CAN($fh, 'tell')
- ) ? 1 : 0;
-}
-
-# Print to the filehandle, while making sure the pesky Perl special global
-# variables don't interfere.
-sub _print
-{
- my ($self, $fh, @data) = @_;
-
- local $\;
-
- return $fh->print(@data);
-}
-
-# Return an opened IO::Handle
-# my ( $status, fh ) = _newFileHandle( 'fileName', 'w' );
-# Can take a filename, file handle, or ref to GLOB
-# Or, if given something that is a ref but not an IO::Handle,
-# passes back the same thing.
-sub _newFileHandle {
- my $fd = shift;
- my $status = 1;
- my $handle;
-
- if ( ref($fd) ) {
- if ( _ISA($fd, 'IO::Scalar') or _ISA($fd, 'IO::String') ) {
- $handle = $fd;
- } elsif ( _ISA($fd, 'IO::Handle') or ref($fd) eq 'GLOB' ) {
- $handle = IO::File->new;
- $status = $handle->fdopen( $fd, @_ );
- } else {
- $handle = $fd;
- }
- } else {
- $handle = IO::File->new;
- $status = $handle->open( $fd, @_ );
- }
-
- return ( $status, $handle );
-}
-
-# Returns next signature from given file handle, leaves
-# file handle positioned afterwards.
-# In list context, returns ($status, $signature)
-# ( $status, $signature) = _readSignature( $fh, $fileName );
-
-sub _readSignature {
- my $fh = shift;
- my $fileName = shift;
- my $expectedSignature = shift; # optional
-
- my $signatureData;
- my $bytesRead = $fh->read( $signatureData, SIGNATURE_LENGTH );
- if ( $bytesRead != SIGNATURE_LENGTH ) {
- return _ioError("reading header signature");
- }
- my $signature = unpack( SIGNATURE_FORMAT, $signatureData );
- my $status = AZ_OK;
-
- # compare with expected signature, if any, or any known signature.
- if ( ( defined($expectedSignature) && $signature != $expectedSignature )
- || ( !defined($expectedSignature)
- && $signature != CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE
- && $signature != LOCAL_FILE_HEADER_SIGNATURE
- && $signature != END_OF_CENTRAL_DIRECTORY_SIGNATURE
- && $signature != DATA_DESCRIPTOR_SIGNATURE ) )
- {
- my $errmsg = sprintf( "bad signature: 0x%08x", $signature );
- if ( _isSeekable($fh) )
- {
- $errmsg .=
- sprintf( " at offset %d", $fh->tell() - SIGNATURE_LENGTH );
- }
-
- $status = _formatError("$errmsg in file $fileName");
- }
-
- return ( $status, $signature );
-}
-
-# Utility method to make and open a temp file.
-# Will create $temp_dir if it doesn't exist.
-# Returns file handle and name:
-#
-# my ($fh, $name) = Archive::Zip::tempFile();
-# my ($fh, $name) = Archive::Zip::tempFile('mytempdir');
-#
-
-sub tempFile {
- my $dir = ( ref( $_[0] ) eq 'HASH' ) ? shift->{tempDir} : shift;
- my ( $fh, $filename ) = File::Temp::tempfile(
- SUFFIX => '.zip',
- UNLINK => 0, # we will delete it!
- $dir ? ( DIR => $dir ) : ()
- );
- return ( undef, undef ) unless $fh;
- my ( $status, $newfh ) = _newFileHandle( $fh, 'w+' );
- return ( $newfh, $filename );
-}
-
-# Return the normalized directory name as used in a zip file (path
-# separators become slashes, etc.).
-# Will translate internal slashes in path components (i.e. on Macs) to
-# underscores. Discards volume names.
-# When $forceDir is set, returns paths with trailing slashes (or arrays
-# with trailing blank members).
-#
-# If third argument is a reference, returns volume information there.
-#
-# input output
-# . ('.') '.'
-# ./a ('a') a
-# ./a/b ('a','b') a/b
-# ./a/b/ ('a','b') a/b
-# a/b/ ('a','b') a/b
-# /a/b/ ('','a','b') /a/b
-# c:\a\b\c.doc ('','a','b','c.doc') /a/b/c.doc # on Windoze
-# "i/o maps:whatever" ('i_o maps', 'whatever') "i_o maps/whatever" # on Macs
-sub _asZipDirName
-{
- my $name = shift;
- my $forceDir = shift;
- my $volReturn = shift;
- my ( $volume, $directories, $file ) =
- File::Spec->splitpath( File::Spec->canonpath($name), $forceDir );
- $$volReturn = $volume if ( ref($volReturn) );
- my @dirs = map { $_ =~ s{/}{_}g; $_ } File::Spec->splitdir($directories);
- if ( @dirs > 0 ) { pop (@dirs) unless $dirs[-1] } # remove empty component
- push ( @dirs, defined($file) ? $file : '' );
- #return wantarray ? @dirs : join ( '/', @dirs );
- return join ( '/', @dirs );
-}
-
-# Return an absolute local name for a zip name.
-# Assume a directory if zip name has trailing slash.
-# Takes an optional volume name in FS format (like 'a:').
-#
-sub _asLocalName
-{
- my $name = shift; # zip format
- my $volume = shift;
- $volume = '' unless defined($volume); # local FS format
-
- my @paths = split ( /\//, $name );
- my $filename = pop (@paths);
- $filename = '' unless defined($filename);
- my $localDirs = @paths ? File::Spec->catdir(@paths) : '';
- my $localName = File::Spec->catpath( $volume, $localDirs, $filename );
- unless ( $volume ) {
- $localName = File::Spec->rel2abs( $localName, Cwd::getcwd() );
- }
- return $localName;
-}
-
-1;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-Archive::Zip - Provide an interface to ZIP archive files.
-
-=head1 SYNOPSIS
-
- # Create a Zip file
- use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
- my $zip = Archive::Zip->new();
-
- # Add a directory
- my $dir_member = $zip->addDirectory( 'dirname/' );
-
- # Add a file from a string with compression
- my $string_member = $zip->addString( 'This is a test', 'stringMember.txt' );
- $string_member->desiredCompressionMethod( COMPRESSION_DEFLATED );
-
- # Add a file from disk
- my $file_member = $zip->addFile( 'xyz.pl', 'AnotherName.pl' );
-
- # Save the Zip file
- unless ( $zip->writeToFileNamed('someZip.zip') == AZ_OK ) {
- die 'write error';
- }
-
- # Read a Zip file
- my $somezip = Archive::Zip->new();
- unless ( $somezip->read( 'someZip.zip' ) == AZ_OK ) {
- die 'read error';
- }
-
- # Change the compression type for a file in the Zip
- my $member = $somezip->memberNamed( 'stringMember.txt' );
- $member->desiredCompressionMethod( COMPRESSION_STORED );
- unless ( $zip->writeToFileNamed( 'someOtherZip.zip' ) == AZ_OK ) {
- die 'write error';
- }
-
-=head1 DESCRIPTION
-
-The Archive::Zip module allows a Perl program to create, manipulate, read,
-and write Zip archive files.
-
-Zip archives can be created, or you can read from existing zip files.
-
-Once created, they can be written to files, streams, or strings. Members
-can be added, removed, extracted, replaced, rearranged, and enumerated.
-They can also be renamed or have their dates, comments, or other attributes
-queried or modified. Their data can be compressed or uncompressed as needed.
-
-Members can be created from members in existing Zip files, or from existing
-directories, files, or strings.
-
-This module uses the L<Compress::Raw::Zlib> library to read and write the
-compressed streams inside the files.
-
-One can use L<Archive::Zip::MemberRead> to read the zip file archive members
-as if they were files.
-
-=head2 File Naming
-
-Regardless of what your local file system uses for file naming, names in a
-Zip file are in Unix format (I<forward> slashes (/) separating directory
-names, etc.).
-
-C<Archive::Zip> tries to be consistent with file naming conventions, and will
-translate back and forth between native and Zip file names.
-
-However, it can't guess which format names are in. So two rules control what
-kind of file name you must pass various routines:
-
-=over 4
-
-=item Names of files are in local format.
-
-C<File::Spec> and C<File::Basename> are used for various file
-operations. When you're referring to a file on your system, use its
-file naming conventions.
-
-=item Names of archive members are in Unix format.
-
-This applies to every method that refers to an archive member, or
-provides a name for new archive members. The C<extract()> methods
-that can take one or two names will convert from local to zip names
-if you call them with a single name.
-
-=back
-
-=head2 Archive::Zip Object Model
-
-=head2 Overview
-
-Archive::Zip::Archive objects are what you ordinarily deal with.
-These maintain the structure of a zip file, without necessarily
-holding data. When a zip is read from a disk file, the (possibly
-compressed) data still lives in the file, not in memory. Archive
-members hold information about the individual members, but not
-(usually) the actual member data. When the zip is written to a
-(different) file, the member data is compressed or copied as needed.
-It is possible to make archive members whose data is held in a string
-in memory, but this is not done when a zip file is read. Directory
-members don't have any data.
-
-=head2 Inheritance
-
- Exporter
- Archive::Zip Common base class, has defs.
- Archive::Zip::Archive A Zip archive.
- Archive::Zip::Member Abstract superclass for all members.
- Archive::Zip::StringMember Member made from a string
- Archive::Zip::FileMember Member made from an external file
- Archive::Zip::ZipFileMember Member that lives in a zip file
- Archive::Zip::NewFileMember Member whose data is in a file
- Archive::Zip::DirectoryMember Member that is a directory
-
-=head1 EXPORTS
-
-=over 4
-
-=item :CONSTANTS
-
-Exports the following constants:
-
-FA_MSDOS FA_UNIX GPBF_ENCRYPTED_MASK
-GPBF_DEFLATING_COMPRESSION_MASK GPBF_HAS_DATA_DESCRIPTOR_MASK
-COMPRESSION_STORED COMPRESSION_DEFLATED IFA_TEXT_FILE_MASK
-IFA_TEXT_FILE IFA_BINARY_FILE COMPRESSION_LEVEL_NONE
-COMPRESSION_LEVEL_DEFAULT COMPRESSION_LEVEL_FASTEST
-COMPRESSION_LEVEL_BEST_COMPRESSION
-
-=item :MISC_CONSTANTS
-
-Exports the following constants (only necessary for extending the
-module):
-
-FA_AMIGA FA_VAX_VMS FA_VM_CMS FA_ATARI_ST FA_OS2_HPFS
-FA_MACINTOSH FA_Z_SYSTEM FA_CPM FA_WINDOWS_NTFS
-GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK
-GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK
-GPBF_IS_COMPRESSED_PATCHED_DATA_MASK COMPRESSION_SHRUNK
-DEFLATING_COMPRESSION_NORMAL DEFLATING_COMPRESSION_MAXIMUM
-DEFLATING_COMPRESSION_FAST DEFLATING_COMPRESSION_SUPER_FAST
-COMPRESSION_REDUCED_1 COMPRESSION_REDUCED_2 COMPRESSION_REDUCED_3
-COMPRESSION_REDUCED_4 COMPRESSION_IMPLODED COMPRESSION_TOKENIZED
-COMPRESSION_DEFLATED_ENHANCED
-COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED
-
-=item :ERROR_CODES
-
-Explained below. Returned from most methods.
-
-AZ_OK AZ_STREAM_END AZ_ERROR AZ_FORMAT_ERROR AZ_IO_ERROR
-
-=back
-
-=head1 ERROR CODES
-
-Many of the methods in Archive::Zip return error codes. These are implemented
-as inline subroutines, using the C<use constant> pragma. They can be imported
-into your namespace using the C<:ERROR_CODES> tag:
-
- use Archive::Zip qw( :ERROR_CODES );
-
- ...
-
- unless ( $zip->read( 'myfile.zip' ) == AZ_OK ) {
- die "whoops!";
- }
-
-=over 4
-
-=item AZ_OK (0)
-
-Everything is fine.
-
-=item AZ_STREAM_END (1)
-
-The read stream (or central directory) ended normally.
-
-=item AZ_ERROR (2)
-
-There was some generic kind of error.
-
-=item AZ_FORMAT_ERROR (3)
-
-There is a format error in a ZIP file being read.
-
-=item AZ_IO_ERROR (4)
-
-There was an IO error.
-
-=back
-
-=head2 Compression
-
-Archive::Zip allows each member of a ZIP file to be compressed (using the
-Deflate algorithm) or uncompressed.
-
-Other compression algorithms that some versions of ZIP have been able to
-produce are not supported. Each member has two compression methods: the
-one it's stored as (this is always COMPRESSION_STORED for string and external
-file members), and the one you desire for the member in the zip file.
-
-These can be different, of course, so you can make a zip member that is not
-compressed out of one that is, and vice versa.
-
-You can inquire about the current compression and set the desired
-compression method:
-
- my $member = $zip->memberNamed( 'xyz.txt' );
- $member->compressionMethod(); # return current compression
-
- # set to read uncompressed
- $member->desiredCompressionMethod( COMPRESSION_STORED );
-
- # set to read compressed
- $member->desiredCompressionMethod( COMPRESSION_DEFLATED );
-
-There are two different compression methods:
-
-=over 4
-
-=item COMPRESSION_STORED
-
-File is stored (no compression)
-
-=item COMPRESSION_DEFLATED
-
-File is Deflated
-
-=back
-
-=head2 Compression Levels
-
-If a member's desiredCompressionMethod is COMPRESSION_DEFLATED, you
-can choose different compression levels. This choice may affect the
-speed of compression and decompression, as well as the size of the
-compressed member data.
-
- $member->desiredCompressionLevel( 9 );
-
-The levels given can be:
-
-=over 4
-
-=item 0 or COMPRESSION_LEVEL_NONE
-
-This is the same as saying
-
- $member->desiredCompressionMethod( COMPRESSION_STORED );
-
-=item 1 .. 9
-
-1 gives the best speed and worst compression, and 9 gives the
-best compression and worst speed.
-
-=item COMPRESSION_LEVEL_FASTEST
-
-This is a synonym for level 1.
-
-=item COMPRESSION_LEVEL_BEST_COMPRESSION
-
-This is a synonym for level 9.
-
-=item COMPRESSION_LEVEL_DEFAULT
-
-This gives a good compromise between speed and compression,
-and is currently equivalent to 6 (this is in the zlib code).
-This is the level that will be used if not specified.
-
-=back
-
-=head1 Archive::Zip Methods
-
-The Archive::Zip class (and its invisible subclass Archive::Zip::Archive)
-implement generic zip file functionality. Creating a new Archive::Zip object
-actually makes an Archive::Zip::Archive object, but you don't have to worry
-about this unless you're subclassing.
-
-=head2 Constructor
-
-=over 4
-
-=item new( [$fileName] )
-
-Make a new, empty zip archive.
-
- my $zip = Archive::Zip->new();
-
-If an additional argument is passed, new() will call read()
-to read the contents of an archive:
-
- my $zip = Archive::Zip->new( 'xyz.zip' );
-
-If a filename argument is passed and the read fails for any
-reason, new will return undef. For this reason, it may be
-better to call read separately.
-
-=back
-
-=head2 Zip Archive Utility Methods
-
-These Archive::Zip methods may be called as functions or as object
-methods. Do not call them as class methods:
-
- $zip = Archive::Zip->new();
- $crc = Archive::Zip::computeCRC32( 'ghijkl' ); # OK
- $crc = $zip->computeCRC32( 'ghijkl' ); # also OK
- $crc = Archive::Zip->computeCRC32( 'ghijkl' ); # NOT OK
-
-=over 4
-
-=item Archive::Zip::computeCRC32( $string [, $crc] )
-
-This is a utility function that uses the Compress::Raw::Zlib CRC
-routine to compute a CRC-32. You can get the CRC of a string:
-
- $crc = Archive::Zip::computeCRC32( $string );
-
-Or you can compute the running CRC:
-
- $crc = 0;
- $crc = Archive::Zip::computeCRC32( 'abcdef', $crc );
- $crc = Archive::Zip::computeCRC32( 'ghijkl', $crc );
-
-=item Archive::Zip::setChunkSize( $number )
-
-Report or change chunk size used for reading and writing.
-This can make big differences in dealing with large files.
-Currently, this defaults to 32K. This also changes the chunk
-size used for Compress::Raw::Zlib. You must call setChunkSize()
-before reading or writing. This is not exportable, so you
-must call it like:
-
- Archive::Zip::setChunkSize( 4096 );
-
-or as a method on a zip (though this is a global setting).
-Returns old chunk size.
-
-=item Archive::Zip::chunkSize()
-
-Returns the current chunk size:
-
- my $chunkSize = Archive::Zip::chunkSize();
-
-=item Archive::Zip::setErrorHandler( \&subroutine )
-
-Change the subroutine called with error strings. This
-defaults to \&Carp::carp, but you may want to change it to
-get the error strings. This is not exportable, so you must
-call it like:
-
- Archive::Zip::setErrorHandler( \&myErrorHandler );
-
-If myErrorHandler is undef, resets handler to default.
-Returns old error handler. Note that if you call Carp::carp
-or a similar routine or if you're chaining to the default
-error handler from your error handler, you may want to
-increment the number of caller levels that are skipped (do
-not just set it to a number):
-
- $Carp::CarpLevel++;
-
-=item Archive::Zip::tempFile( [$tmpdir] )
-
-Create a uniquely named temp file. It will be returned open
-for read/write. If C<$tmpdir> is given, it is used as the
-name of a directory to create the file in. If not given,
-creates the file using C<File::Spec::tmpdir()>. Generally, you can
-override this choice using the
-
- $ENV{TMPDIR}
-
-environment variable. But see the L<File::Spec|File::Spec>
-documentation for your system. Note that on many systems, if you're
-running in taint mode, then you must make sure that C<$ENV{TMPDIR}> is
-untainted for it to be used.
-Will I<NOT> create C<$tmpdir> if it doesn't exist (this is a change
-from prior versions!). Returns file handle and name:
-
- my ($fh, $name) = Archive::Zip::tempFile();
- my ($fh, $name) = Archive::Zip::tempFile('myTempDir');
- my $fh = Archive::Zip::tempFile(); # if you don't need the name
-
-=back
-
-=head2 Zip Archive Accessors
-
-=over 4
-
-=item members()
-
-Return a copy of the members array
-
- my @members = $zip->members();
-
-=item numberOfMembers()
-
-Return the number of members I have
-
-=item memberNames()
-
-Return a list of the (internal) file names of the zip members
-
-=item memberNamed( $string )
-
-Return ref to member whose filename equals given filename or
-undef. C<$string> must be in Zip (Unix) filename format.
-
-=item membersMatching( $regex )
-
-Return array of members whose filenames match given regular
-expression in list context. Returns number of matching
-members in scalar context.
-
- my @textFileMembers = $zip->membersMatching( '.*\.txt' );
- # or
- my $numberOfTextFiles = $zip->membersMatching( '.*\.txt' );
-
-=item diskNumber()
-
-Return the disk that I start on. Not used for writing zips,
-but might be interesting if you read a zip in. This should be
-0, as Archive::Zip does not handle multi-volume archives.
-
-=item diskNumberWithStartOfCentralDirectory()
-
-Return the disk number that holds the beginning of the
-central directory. Not used for writing zips, but might be
-interesting if you read a zip in. This should be 0, as
-Archive::Zip does not handle multi-volume archives.
-
-=item numberOfCentralDirectoriesOnThisDisk()
-
-Return the number of CD structures in the zipfile last read in.
-Not used for writing zips, but might be interesting if you read a zip
-in.
-
-=item numberOfCentralDirectories()
-
-Return the number of CD structures in the zipfile last read in.
-Not used for writing zips, but might be interesting if you read a zip
-in.
-
-=item centralDirectorySize()
-
-Returns central directory size, as read from an external zip
-file. Not used for writing zips, but might be interesting if
-you read a zip in.
-
-=item centralDirectoryOffsetWRTStartingDiskNumber()
-
-Returns the offset into the zip file where the CD begins. Not
-used for writing zips, but might be interesting if you read a
-zip in.
-
-=item zipfileComment( [$string] )
-
-Get or set the zipfile comment. Returns the old comment.
-
- print $zip->zipfileComment();
- $zip->zipfileComment( 'New Comment' );
-
-=item eocdOffset()
-
-Returns the (unexpected) number of bytes between where the
-EOCD was found and where it expected to be. This is normally
-0, but would be positive if something (a virus, perhaps) had
-added bytes somewhere before the EOCD. Not used for writing
-zips, but might be interesting if you read a zip in. Here is
-an example of how you can diagnose this:
-
- my $zip = Archive::Zip->new('somefile.zip');
- if ($zip->eocdOffset())
- {
- warn "A virus has added ", $zip->eocdOffset, " bytes of garbage\n";
- }
-
-The C<eocdOffset()> is used to adjust the starting position of member
-headers, if necessary.
-
-=item fileName()
-
-Returns the name of the file last read from. If nothing has
-been read yet, returns an empty string; if read from a file
-handle, returns the handle in string form.
-
-=back
-
-=head2 Zip Archive Member Operations
-
-Various operations on a zip file modify members. When a member is
-passed as an argument, you can either use a reference to the member
-itself, or the name of a member. Of course, using the name requires
-that names be unique within a zip (this is not enforced).
-
-=over 4
-
-=item removeMember( $memberOrName )
-
-Remove and return the given member, or match its name and
-remove it. Returns undef if member or name doesn't exist in this
-Zip. No-op if member does not belong to this zip.
-
-=item replaceMember( $memberOrName, $newMember )
-
-Remove and return the given member, or match its name and
-remove it. Replace with new member. Returns undef if member or
-name doesn't exist in this Zip, or if C<$newMember> is undefined.
-
-It is an (undiagnosed) error to provide a C<$newMember> that is a
-member of the zip being modified.
-
- my $member1 = $zip->removeMember( 'xyz' );
- my $member2 = $zip->replaceMember( 'abc', $member1 );
- # now, $member2 (named 'abc') is not in $zip,
- # and $member1 (named 'xyz') is, having taken $member2's place.
-
-=item extractMember( $memberOrName [, $extractedName ] )
-
-Extract the given member, or match its name and extract it.
-Returns undef if member doesn't exist in this Zip. If
-optional second arg is given, use it as the name of the
-extracted member. Otherwise, the internal filename of the
-member is used as the name of the extracted file or
-directory.
-If you pass C<$extractedName>, it should be in the local file
-system's format.
-All necessary directories will be created. Returns C<AZ_OK>
-on success.
-
-=item extractMemberWithoutPaths( $memberOrName [, $extractedName ] )
-
-Extract the given member, or match its name and extract it.
-Does not use path information (extracts into the current
-directory). Returns undef if member doesn't exist in this
-Zip.
-If optional second arg is given, use it as the name of the
-extracted member (its paths will be deleted too). Otherwise,
-the internal filename of the member (minus paths) is used as
-the name of the extracted file or directory. Returns C<AZ_OK>
-on success.
-
-=item addMember( $member )
-
-Append a member (possibly from another zip file) to the zip
-file. Returns the new member. Generally, you will use
-addFile(), addDirectory(), addFileOrDirectory(), addString(),
-or read() to add members.
-
- # Move member named 'abc' to end of zip:
- my $member = $zip->removeMember( 'abc' );
- $zip->addMember( $member );
-
-=item updateMember( $memberOrName, $fileName )
-
-Update a single member from the file or directory named C<$fileName>.
-Returns the (possibly added or updated) member, if any; C<undef> on
-errors.
-The comparison is based on C<lastModTime()> and (in the case of a
-non-directory) the size of the file.
-
-=item addFile( $fileName [, $newName ] )
-
-Append a member whose data comes from an external file,
-returning the member or undef. The member will have its file
-name set to the name of the external file, and its
-desiredCompressionMethod set to COMPRESSION_DEFLATED. The
-file attributes and last modification time will be set from
-the file.
-If the name given does not represent a readable plain file or
-symbolic link, undef will be returned. C<$fileName> must be
-in the format required for the local file system.
-The optional C<$newName> argument sets the internal file name
-to something different than the given $fileName. C<$newName>,
-if given, must be in Zip name format (i.e. Unix).
-The text mode bit will be set if the contents appears to be
-text (as returned by the C<-T> perl operator).
-
-
-I<NOTE> that you shouldn't (generally) use absolute path names
-in zip member names, as this will cause problems with some zip
-tools as well as introduce a security hole and make the zip
-harder to use.
-
-=item addDirectory( $directoryName [, $fileName ] )
-
-
-
-Append a member created from the given directory name. The
-directory name does not have to name an existing directory.
-If the named directory exists, the file modification time and
-permissions are set from the existing directory, otherwise
-they are set to now and permissive default permissions.
-C<$directoryName> must be in local file system format.
-The optional second argument sets the name of the archive
-member (which defaults to C<$directoryName>). If given, it
-must be in Zip (Unix) format.
-Returns the new member.
-
-=item addFileOrDirectory( $name [, $newName ] )
-
-
-
-Append a member from the file or directory named $name. If
-$newName is given, use it for the name of the new member.
-Will add or remove trailing slashes from $newName as needed.
-C<$name> must be in local file system format.
-The optional second argument sets the name of the archive
-member (which defaults to C<$name>). If given, it must be in
-Zip (Unix) format.
-
-=item addString( $stringOrStringRef, $name )
-
-
-
-Append a member created from the given string or string
-reference. The name is given by the second argument.
-Returns the new member. The last modification time will be
-set to now, and the file attributes will be set to permissive
-defaults.
-
- my $member = $zip->addString( 'This is a test', 'test.txt' );
-
-=item contents( $memberOrMemberName [, $newContents ] )
-
-
-
-Returns the uncompressed data for a particular member, or
-undef.
-
- print "xyz.txt contains " . $zip->contents( 'xyz.txt' );
-
-Also can change the contents of a member:
-
- $zip->contents( 'xyz.txt', 'This is the new contents' );
-
-If called expecting an array as the return value, it will include
-the status as the second value in the array.
-
- ($content, $status) = $zip->contents( 'xyz.txt');
-
-=back
-
-=head2 Zip Archive I/O operations
-
-
-A Zip archive can be written to a file or file handle, or read from
-one.
-
-=over 4
-
-=item writeToFileNamed( $fileName )
-
-
-
-Write a zip archive to named file. Returns C<AZ_OK> on
-success.
-
- my $status = $zip->writeToFileNamed( 'xx.zip' );
- die "error somewhere" if $status != AZ_OK;
-
-Note that if you use the same name as an existing zip file
-that you read in, you will clobber ZipFileMembers. So
-instead, write to a different file name, then delete the
-original.
-If you use the C<overwrite()> or C<overwriteAs()> methods, you can
-re-write the original zip in this way.
-C<$fileName> should be a valid file name on your system.
-
-=item writeToFileHandle( $fileHandle [, $seekable] )
-
-Write a zip archive to a file handle. Return AZ_OK on
-success. The optional second arg tells whether or not to try
-to seek backwards to re-write headers. If not provided, it is
-set if the Perl C<-f> test returns true. This could fail on
-some operating systems, though.
-
- my $fh = IO::File->new( 'someFile.zip', 'w' );
- unless ( $zip->writeToFileHandle( $fh ) == AZ_OK ) {
- # error handling
- }
-
-If you pass a file handle that is not seekable (like if
-you're writing to a pipe or a socket), pass a false second
-argument:
-
- my $fh = IO::File->new( '| cat > somefile.zip', 'w' );
- $zip->writeToFileHandle( $fh, 0 ); # fh is not seekable
-
-If this method fails during the write of a member, that
-member and all following it will return false from
-C<wasWritten()>. See writeCentralDirectory() for a way to
-deal with this.
-If you want, you can write data to the file handle before
-passing it to writeToFileHandle(); this could be used (for
-instance) for making self-extracting archives. However, this
-only works reliably when writing to a real file (as opposed
-to STDOUT or some other possible non-file).
-
-See examples/selfex.pl for how to write a self-extracting
-archive.
-
-=item writeCentralDirectory( $fileHandle [, $offset ] )
-
-Writes the central directory structure to the given file
-handle.
-
-Returns AZ_OK on success. If given an $offset, will
-seek to that point before writing. This can be used for
-recovery in cases where writeToFileHandle or writeToFileNamed
-returns an IO error because of running out of space on the
-destination file.
-
-You can truncate the zip by seeking backwards and then writing the
-directory:
-
- my $fh = IO::File->new( 'someFile.zip', 'w' );
- my $retval = $zip->writeToFileHandle( $fh );
- if ( $retval == AZ_IO_ERROR ) {
- my @unwritten = grep { not $_->wasWritten() } $zip->members();
- if (@unwritten) {
- $zip->removeMember( $member ) foreach my $member ( @unwritten );
- $zip->writeCentralDirectory( $fh,
- $unwritten[0]->writeLocalHeaderRelativeOffset());
- }
- }
-
-=item overwriteAs( $newName )
-
-Write the zip to the specified file, as safely as possible.
-This is done by first writing to a temp file, then renaming
-the original if it exists, then renaming the temp file, then
-deleting the renamed original if it exists. Returns AZ_OK if
-successful.
-
-=item overwrite()
-
-Write back to the original zip file. See overwriteAs() above.
-If the zip was not ever read from a file, this generates an
-error.
-
-=item read( $fileName )
-
-Read zipfile headers from a zip file, appending new members.
-Returns C<AZ_OK> or error code.
-
- my $zipFile = Archive::Zip->new();
- my $status = $zipFile->read( '/some/FileName.zip' );
-
-=item readFromFileHandle( $fileHandle, $filename )
-
-Read zipfile headers from an already-opened file handle,
-appending new members. Does not close the file handle.
-Returns C<AZ_OK> or error code. Note that this requires a
-seekable file handle; reading from a stream is not yet
-supported.
-
- my $fh = IO::File->new( '/some/FileName.zip', 'r' );
- my $zip1 = Archive::Zip->new();
- my $status = $zip1->readFromFileHandle( $fh );
- my $zip2 = Archive::Zip->new();
- $status = $zip2->readFromFileHandle( $fh );
-
-=back
-
-=head2 Zip Archive Tree operations
-
-These used to be in Archive::Zip::Tree but got moved into
-Archive::Zip. They enable operation on an entire tree of members or
-files.
-A usage example:
-
- use Archive::Zip;
- my $zip = Archive::Zip->new();
-
- # add all readable files and directories below . as xyz/*
- $zip->addTree( '.', 'xyz' );
-
- # add all readable plain files below /abc as def/*
- $zip->addTree( '/abc', 'def', sub { -f && -r } );
-
- # add all .c files below /tmp as stuff/*
- $zip->addTreeMatching( '/tmp', 'stuff', '\.c$' );
-
- # add all .o files below /tmp as stuff/* if they aren't writable
- $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } );
-
- # add all .so files below /tmp that are smaller than 200 bytes as stuff/*
- $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { -s < 200 } );
-
- # and write them into a file
- $zip->writeToFileNamed('xxx.zip');
-
- # now extract the same files into /tmpx
- $zip->extractTree( 'stuff', '/tmpx' );
-
-=over 4
-
-=item $zip->addTree( $root, $dest [,$pred] ) -- Add tree of files to a zip
-
-C<$root> is the root of the tree of files and directories to be
-added. It is a valid directory name on your system. C<$dest> is
-the name for the root in the zip file (undef or blank means
-to use relative pathnames). It is a valid ZIP directory name
-(that is, it uses forward slashes (/) for separating
-directory components). C<$pred> is an optional subroutine
-reference to select files: it is passed the name of the
-prospective file or directory using C<$_>, and if it returns
-true, the file or directory will be included. The default is
-to add all readable files and directories. For instance,
-using
-
- my $pred = sub { /\.txt/ };
- $zip->addTree( '.', '', $pred );
-
-will add all the .txt files in and below the current
-directory, using relative names, and making the names
-identical in the zipfile:
-
- original name zip member name
- ./xyz xyz
- ./a/ a/
- ./a/b a/b
-
-To translate absolute to relative pathnames, just pass them
-in: $zip->addTree( '/c/d', 'a' );
-
- original name zip member name
- /c/d/xyz a/xyz
- /c/d/a/ a/a/
- /c/d/a/b a/a/b
-
-Returns AZ_OK on success. Note that this will not follow
-symbolic links to directories. Note also that this does not
-check for the validity of filenames.
-
-Note that you generally I<don't> want to make zip archive member names
-absolute.
-
-=item $zip->addTreeMatching( $root, $dest, $pattern [,$pred] )
-
-$root is the root of the tree of files and directories to be
-added $dest is the name for the root in the zip file (undef
-means to use relative pathnames) $pattern is a (non-anchored)
-regular expression for filenames to match $pred is an
-optional subroutine reference to select files: it is passed
-the name of the prospective file or directory in C<$_>, and
-if it returns true, the file or directory will be included.
-The default is to add all readable files and directories. To
-add all files in and below the current dirctory whose names
-end in C<.pl>, and make them extract into a subdirectory
-named C<xyz>, do this:
-
- $zip->addTreeMatching( '.', 'xyz', '\.pl$' )
-
-To add all I<writable> files in and below the dirctory named
-C</abc> whose names end in C<.pl>, and make them extract into
-a subdirectory named C<xyz>, do this:
-
- $zip->addTreeMatching( '/abc', 'xyz', '\.pl$', sub { -w } )
-
-Returns AZ_OK on success. Note that this will not follow
-symbolic links to directories.
-
-=item $zip->updateTree( $root, [ $dest, [ $pred [, $mirror]]] );
-
-
-
-Update a zip file from a directory tree.
-
-C<updateTree()> takes the same arguments as C<addTree()>, but first
-checks to see whether the file or directory already exists in the zip
-file, and whether it has been changed.
-
-If the fourth argument C<$mirror> is true, then delete all my members
-if corresponding files weren't found.
-
-
-Returns an error code or AZ_OK if all is well.
-
-=item $zip->extractTree()
-
-
-
-=item $zip->extractTree( $root )
-
-
-
-=item $zip->extractTree( $root, $dest )
-
-
-
-=item $zip->extractTree( $root, $dest, $volume )
-
-
-
-If you don't give any arguments at all, will extract all the
-files in the zip with their original names.
-
-
-If you supply one argument for C<$root>, C<extractTree> will extract
-all the members whose names start with C<$root> into the current
-directory, stripping off C<$root> first.
-C<$root> is in Zip (Unix) format.
-For instance,
-
- $zip->extractTree( 'a' );
-
-when applied to a zip containing the files:
-a/x a/b/c ax/d/e d/e will extract:
-
-
-a/x as ./x
-
-
-a/b/c as ./b/c
-
-
-If you give two arguments, C<extractTree> extracts all the members
-whose names start with C<$root>. It will translate C<$root> into
-C<$dest> to construct the destination file name.
-C<$root> and C<$dest> are in Zip (Unix) format.
-For instance,
-
- $zip->extractTree( 'a', 'd/e' );
-
-when applied to a zip containing the files:
-a/x a/b/c ax/d/e d/e will extract:
-
-
-a/x to d/e/x
-
-
-a/b/c to d/e/b/c and ignore ax/d/e and d/e
-
-
-If you give three arguments, C<extractTree> extracts all the members
-whose names start with C<$root>. It will translate C<$root> into
-C<$dest> to construct the destination file name, and then it will
-convert to local file system format, using C<$volume> as the name of
-the destination volume.
-
-
-C<$root> and C<$dest> are in Zip (Unix) format.
-
-
-C<$volume> is in local file system format.
-
-
-For instance, under Windows,
-
- $zip->extractTree( 'a', 'd/e', 'f:' );
-
-when applied to a zip containing the files:
-a/x a/b/c ax/d/e d/e will extract:
-
-
-a/x to f:d/e/x
-
-
-a/b/c to f:d/e/b/c and ignore ax/d/e and d/e
-
-
-If you want absolute paths (the prior example used paths relative to
-the current directory on the destination volume, you can specify these
-in C<$dest>:
-
- $zip->extractTree( 'a', '/d/e', 'f:' );
-
-when applied to a zip containing the files:
-a/x a/b/c ax/d/e d/e will extract:
-
-
-a/x to f:\d\e\x
-
-
-a/b/c to f:\d\e\b\c and ignore ax/d/e and d/e
-
-Returns an error code or AZ_OK if everything worked OK.
-
-=back
-
-=head1 MEMBER OPERATIONS
-
-
-=head2 Member Class Methods
-
-
-Several constructors allow you to construct members without adding
-them to a zip archive. These work the same as the addFile(),
-addDirectory(), and addString() zip instance methods described above,
-but they don't add the new members to a zip.
-
-=over 4
-
-=item Archive::Zip::Member->newFromString( $stringOrStringRef [, $fileName] )
-
-
-
-Construct a new member from the given string. Returns undef
-on error.
-
- my $member = Archive::Zip::Member->newFromString( 'This is a test',
- 'xyz.txt' );
-
-=item newFromFile( $fileName )
-
-
-
-Construct a new member from the given file. Returns undef on
-error.
-
- my $member = Archive::Zip::Member->newFromFile( 'xyz.txt' );
-
-=item newDirectoryNamed( $directoryName [, $zipname ] )
-
-
-
-Construct a new member from the given directory.
-C<$directoryName> must be a valid name on your file system; it doesn't
-have to exist.
-
-
-If given, C<$zipname> will be the name of the zip member; it must be a
-valid Zip (Unix) name. If not given, it will be converted from
-C<$directoryName>.
-
-
-Returns undef on error.
-
- my $member = Archive::Zip::Member->newDirectoryNamed( 'CVS/' );
-
-=back
-
-=head2 Member Simple accessors
-
-
-These methods get (and/or set) member attribute values.
-
-=over 4
-
-=item versionMadeBy()
-
-
-
-Gets the field from the member header.
-
-=item fileAttributeFormat( [$format] )
-
-
-
-Gets or sets the field from the member header. These are
-C<FA_*> values.
-
-=item versionNeededToExtract()
-
-
-
-Gets the field from the member header.
-
-=item bitFlag()
-
-
-
-Gets the general purpose bit field from the member header.
-This is where the C<GPBF_*> bits live.
-
-=item compressionMethod()
-
-
-
-Returns the member compression method. This is the method
-that is currently being used to compress the member data.
-This will be COMPRESSION_STORED for added string or file
-members, or any of the C<COMPRESSION_*> values for members
-from a zip file. However, this module can only handle members
-whose data is in COMPRESSION_STORED or COMPRESSION_DEFLATED
-format.
-
-=item desiredCompressionMethod( [$method] )
-
-
-
-Get or set the member's C<desiredCompressionMethod>. This is
-the compression method that will be used when the member is
-written. Returns prior desiredCompressionMethod. Only
-COMPRESSION_DEFLATED or COMPRESSION_STORED are valid
-arguments. Changing to COMPRESSION_STORED will change the
-member desiredCompressionLevel to 0; changing to
-COMPRESSION_DEFLATED will change the member
-desiredCompressionLevel to COMPRESSION_LEVEL_DEFAULT.
-
-=item desiredCompressionLevel( [$method] )
-
-
-
-Get or set the member's desiredCompressionLevel This is the
-method that will be used to write. Returns prior
-desiredCompressionLevel. Valid arguments are 0 through 9,
-COMPRESSION_LEVEL_NONE, COMPRESSION_LEVEL_DEFAULT,
-COMPRESSION_LEVEL_BEST_COMPRESSION, and
-COMPRESSION_LEVEL_FASTEST. 0 or COMPRESSION_LEVEL_NONE will
-change the desiredCompressionMethod to COMPRESSION_STORED.
-All other arguments will change the desiredCompressionMethod
-to COMPRESSION_DEFLATED.
-
-=item externalFileName()
-
-
-
-Return the member's external file name, if any, or undef.
-
-=item fileName()
-
-
-
-Get or set the member's internal filename. Returns the
-(possibly new) filename. Names will have backslashes
-converted to forward slashes, and will have multiple
-consecutive slashes converted to single ones.
-
-=item lastModFileDateTime()
-
-
-
-Return the member's last modification date/time stamp in
-MS-DOS format.
-
-=item lastModTime()
-
-
-
-Return the member's last modification date/time stamp,
-converted to unix localtime format.
-
- print "Mod Time: " . scalar( localtime( $member->lastModTime() ) );
-
-=item setLastModFileDateTimeFromUnix()
-
-Set the member's lastModFileDateTime from the given unix
-time.
-
- $member->setLastModFileDateTimeFromUnix( time() );
-
-=item internalFileAttributes()
-
-Return the internal file attributes field from the zip
-header. This is only set for members read from a zip file.
-
-=item externalFileAttributes()
-
-Return member attributes as read from the ZIP file. Note that
-these are NOT UNIX!
-
-=item unixFileAttributes( [$newAttributes] )
-
-Get or set the member's file attributes using UNIX file
-attributes. Returns old attributes.
-
- my $oldAttribs = $member->unixFileAttributes( 0666 );
-
-Note that the return value has more than just the file
-permissions, so you will have to mask off the lowest bits for
-comparisions.
-
-=item localExtraField( [$newField] )
-
-Gets or sets the extra field that was read from the local
-header. This is not set for a member from a zip file until
-after the member has been written out. The extra field must
-be in the proper format.
-
-=item cdExtraField( [$newField] )
-
-Gets or sets the extra field that was read from the central
-directory header. The extra field must be in the proper
-format.
-
-=item extraFields()
-
-Return both local and CD extra fields, concatenated.
-
-=item fileComment( [$newComment] )
-
-Get or set the member's file comment.
-
-=item hasDataDescriptor()
-
-Get or set the data descriptor flag. If this is set, the
-local header will not necessarily have the correct data
-sizes. Instead, a small structure will be stored at the end
-of the member data with these values. This should be
-transparent in normal operation.
-
-=item crc32()
-
-Return the CRC-32 value for this member. This will not be set
-for members that were constructed from strings or external
-files until after the member has been written.
-
-=item crc32String()
-
-Return the CRC-32 value for this member as an 8 character
-printable hex string. This will not be set for members that
-were constructed from strings or external files until after
-the member has been written.
-
-=item compressedSize()
-
-Return the compressed size for this member. This will not be
-set for members that were constructed from strings or
-external files until after the member has been written.
-
-=item uncompressedSize()
-
-Return the uncompressed size for this member.
-
-=item isEncrypted()
-
-Return true if this member is encrypted. The Archive::Zip
-module does not currently create or extract encrypted
-members.
-
-=item isTextFile( [$flag] )
-
-Returns true if I am a text file. Also can set the status if
-given an argument (then returns old state). Note that this
-module does not currently do anything with this flag upon
-extraction or storage. That is, bytes are stored in native
-format whether or not they came from a text file.
-
-=item isBinaryFile()
-
-Returns true if I am a binary file. Also can set the status
-if given an argument (then returns old state). Note that this
-module does not currently do anything with this flag upon
-extraction or storage. That is, bytes are stored in native
-format whether or not they came from a text file.
-
-=item extractToFileNamed( $fileName )
-
-Extract me to a file with the given name. The file will be
-created with default modes. Directories will be created as
-needed.
-The C<$fileName> argument should be a valid file name on your
-file system.
-Returns AZ_OK on success.
-
-=item isDirectory()
-
-Returns true if I am a directory.
-
-=item writeLocalHeaderRelativeOffset()
-
-Returns the file offset in bytes the last time I was written.
-
-=item wasWritten()
-
-Returns true if I was successfully written. Reset at the
-beginning of a write attempt.
-
-=back
-
-=head2 Low-level member data reading
-
-It is possible to use lower-level routines to access member data
-streams, rather than the extract* methods and contents(). For
-instance, here is how to print the uncompressed contents of a member
-in chunks using these methods:
-
- my ( $member, $status, $bufferRef );
- $member = $zip->memberNamed( 'xyz.txt' );
- $member->desiredCompressionMethod( COMPRESSION_STORED );
- $status = $member->rewindData();
- die "error $status" unless $status == AZ_OK;
- while ( ! $member->readIsDone() )
- {
- ( $bufferRef, $status ) = $member->readChunk();
- die "error $status"
- if $status != AZ_OK && $status != AZ_STREAM_END;
- # do something with $bufferRef:
- print $$bufferRef;
- }
- $member->endRead();
-
-=over 4
-
-=item readChunk( [$chunkSize] )
-
-This reads the next chunk of given size from the member's
-data stream and compresses or uncompresses it as necessary,
-returning a reference to the bytes read and a status. If size
-argument is not given, defaults to global set by
-Archive::Zip::setChunkSize. Status is AZ_OK on success until
-the last chunk, where it returns AZ_STREAM_END. Returns C<(
-\$bytes, $status)>.
-
- my ( $outRef, $status ) = $self->readChunk();
- print $$outRef if $status != AZ_OK && $status != AZ_STREAM_END;
-
-=item rewindData()
-
-Rewind data and set up for reading data streams or writing
-zip files. Can take options for C<inflateInit()> or
-C<deflateInit()>, but this isn't likely to be necessary.
-Subclass overrides should call this method. Returns C<AZ_OK>
-on success.
-
-=item endRead()
-
-Reset the read variables and free the inflater or deflater.
-Must be called to close files, etc. Returns AZ_OK on success.
-
-=item readIsDone()
-
-Return true if the read has run out of data or errored out.
-
-=item contents()
-
-Return the entire uncompressed member data or undef in scalar
-context. When called in array context, returns C<( $string,
-$status )>; status will be AZ_OK on success:
-
- my $string = $member->contents();
- # or
- my ( $string, $status ) = $member->contents();
- die "error $status" unless $status == AZ_OK;
-
-Can also be used to set the contents of a member (this may
-change the class of the member):
-
- $member->contents( "this is my new contents" );
-
-=item extractToFileHandle( $fh )
-
-Extract (and uncompress, if necessary) the member's contents
-to the given file handle. Return AZ_OK on success.
-
-=back
-
-=head1 Archive::Zip::FileMember methods
-
-The Archive::Zip::FileMember class extends Archive::Zip::Member. It is the
-base class for both ZipFileMember and NewFileMember classes. This class adds
-an C<externalFileName> and an C<fh> member to keep track of the external
-file.
-
-=over 4
-
-=item externalFileName()
-
-Return the member's external filename.
-
-=item fh()
-
-Return the member's read file handle. Automatically opens file if
-necessary.
-
-=back
-
-=head1 Archive::Zip::ZipFileMember methods
-
-The Archive::Zip::ZipFileMember class represents members that have been read
-from external zip files.
-
-=over 4
-
-=item diskNumberStart()
-
-Returns the disk number that the member's local header resides in.
-Should be 0.
-
-=item localHeaderRelativeOffset()
-
-Returns the offset into the zip file where the member's local header
-is.
-
-=item dataOffset()
-
-Returns the offset from the beginning of the zip file to the member's
-data.
-
-=back
-
-=head1 REQUIRED MODULES
-
-L<Archive::Zip> requires several other modules:
-
-L<Carp>
-
-L<Compress::Raw::Zlib>
-
-L<Cwd>
-
-L<File::Basename>
-
-L<File::Copy>
-
-L<File::Find>
-
-L<File::Path>
-
-L<File::Spec>
-
-L<IO::File>
-
-L<IO::Seekable>
-
-L<Time::Local>
-
-=head1 BUGS AND CAVEATS
-
-=head2 When not to use Archive::Zip
-
-If you are just going to be extracting zips (and/or other archives) you
-are recommended to look at using L<Archive::Extract> instead, as it is much
-easier to use and factors out archive-specific functionality.
-
-=head2 Try to avoid IO::Scalar
-
-One of the most common ways to use Archive::Zip is to generate Zip files
-in-memory. Most people have use L<IO::Scalar> for this purpose.
-
-Unfortunately, as of 1.11 this module no longer works with L<IO::Scalar>
-as it incorrectly implements seeking.
-
-Anybody using L<IO::Scalar> should consider porting to L<IO::String>,
-which is smaller, lighter, and is implemented to be perfectly compatible
-with regular seekable filehandles.
-
-Support for L<IO::Scalar> most likely will B<not> be restored in the
-future, as L<IO::Scalar> itself cannot change the way it is implemented
-due to back-compatibility issues.
-
-=head1 TO DO
-
-* auto-choosing storing vs compression
-
-* extra field hooks (see notes.txt)
-
-* check for dups on addition/renaming?
-
-* Text file extraction (line end translation)
-
-* Reading zip files from non-seekable inputs
- (Perhaps by proxying through IO::String?)
-
-* separate unused constants into separate module
-
-* cookbook style docs
-
-* Handle tainted paths correctly
-
-* Work on better compatability with other IO:: modules
-
-=head1 SUPPORT
-
-Bugs should be reported via the CPAN bug tracker
-
-L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Archive-Zip>
-
-For other issues contact the maintainer
-
-=head1 AUTHOR
-
-Adam Kennedy E<lt>adamk@cpan.orgE<gt>
-
-Previously maintained by Steve Peters E<lt>steve@fisharerojo.orgE<gt>.
-
-File attributes code by Maurice Aubrey E<lt>maurice@lovelyfilth.comE<gt>.
-
-Originally by Ned Konz E<lt>nedkonz@cpan.orgE<gt>.
-
-=head1 COPYRIGHT
-
-Some parts copyright 2006 - 2009 Adam Kennedy.
-
-Some parts copyright 2005 Steve Peters.
-
-Original work copyright 2000 - 2004 Ned Konz.
-
-This program is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-Look at L<Archive::Zip::MemberRead> which is a wrapper that allows one to
-read Zip archive members as if they were files.
-
-L<Compress::Raw::Zlib>, L<Archive::Tar>, L<Archive::Extract>
-
-There is a Japanese translation of this
-document at L<http://www.memb.jp/~deq/perl/doc-ja/Archive-Zip.html>
-that was done by DEQ E<lt>deq@oct.zaq.ne.jpE<gt> . Thanks!
-
-=cut
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/Archive.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/Archive.pm
deleted file mode 100755
index d9fd02e5e02..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/Archive.pm
+++ /dev/null
@@ -1,978 +0,0 @@
-package Archive::Zip::Archive;
-
-# Represents a generic ZIP archive
-
-use strict;
-use File::Path;
-use File::Find ();
-use File::Spec ();
-use File::Copy ();
-use File::Basename;
-use Cwd;
-
-use vars qw( $VERSION @ISA );
-
-BEGIN {
- $VERSION = '1.30';
- @ISA = qw( Archive::Zip );
-}
-
-use Archive::Zip qw(
- :CONSTANTS
- :ERROR_CODES
- :PKZIP_CONSTANTS
- :UTILITY_METHODS
-);
-
-# Note that this returns undef on read errors, else new zip object.
-
-sub new {
- my $class = shift;
- my $self = bless(
- {
- 'diskNumber' => 0,
- 'diskNumberWithStartOfCentralDirectory' => 0,
- 'numberOfCentralDirectoriesOnThisDisk' => 0, # shld be # of members
- 'numberOfCentralDirectories' => 0, # shld be # of members
- 'centralDirectorySize' => 0, # must re-compute on write
- 'centralDirectoryOffsetWRTStartingDiskNumber' =>
- 0, # must re-compute
- 'writeEOCDOffset' => 0,
- 'writeCentralDirectoryOffset' => 0,
- 'zipfileComment' => '',
- 'eocdOffset' => 0,
- 'fileName' => ''
- },
- $class
- );
- $self->{'members'} = [];
- my $fileName = ( ref( $_[0] ) eq 'HASH' ) ? shift->{filename} : shift;
- if ($fileName) {
- my $status = $self->read($fileName);
- return $status == AZ_OK ? $self : undef;
- }
- return $self;
-}
-
-sub storeSymbolicLink {
- my $self = shift;
- $self->{'storeSymbolicLink'} = shift;
-}
-
-sub members {
- @{ shift->{'members'} };
-}
-
-sub numberOfMembers {
- scalar( shift->members() );
-}
-
-sub memberNames {
- my $self = shift;
- return map { $_->fileName() } $self->members();
-}
-
-# return ref to member with given name or undef
-sub memberNamed {
- my $self = shift;
- my $fileName = ( ref( $_[0] ) eq 'HASH' ) ? shift->{zipName} : shift;
- foreach my $member ( $self->members() ) {
- return $member if $member->fileName() eq $fileName;
- }
- return undef;
-}
-
-sub membersMatching {
- my $self = shift;
- my $pattern = ( ref( $_[0] ) eq 'HASH' ) ? shift->{regex} : shift;
- return grep { $_->fileName() =~ /$pattern/ } $self->members();
-}
-
-sub diskNumber {
- shift->{'diskNumber'};
-}
-
-sub diskNumberWithStartOfCentralDirectory {
- shift->{'diskNumberWithStartOfCentralDirectory'};
-}
-
-sub numberOfCentralDirectoriesOnThisDisk {
- shift->{'numberOfCentralDirectoriesOnThisDisk'};
-}
-
-sub numberOfCentralDirectories {
- shift->{'numberOfCentralDirectories'};
-}
-
-sub centralDirectorySize {
- shift->{'centralDirectorySize'};
-}
-
-sub centralDirectoryOffsetWRTStartingDiskNumber {
- shift->{'centralDirectoryOffsetWRTStartingDiskNumber'};
-}
-
-sub zipfileComment {
- my $self = shift;
- my $comment = $self->{'zipfileComment'};
- if (@_) {
- my $new_comment = ( ref( $_[0] ) eq 'HASH' ) ? shift->{comment} : shift;
- $self->{'zipfileComment'} = pack( 'C0a*', $new_comment ); # avoid unicode
- }
- return $comment;
-}
-
-sub eocdOffset {
- shift->{'eocdOffset'};
-}
-
-# Return the name of the file last read.
-sub fileName {
- shift->{'fileName'};
-}
-
-sub removeMember {
- my $self = shift;
- my $member = ( ref( $_[0] ) eq 'HASH' ) ? shift->{memberOrZipName} : shift;
- $member = $self->memberNamed($member) unless ref($member);
- return undef unless $member;
- my @newMembers = grep { $_ != $member } $self->members();
- $self->{'members'} = \@newMembers;
- return $member;
-}
-
-sub replaceMember {
- my $self = shift;
-
- my ( $oldMember, $newMember );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $oldMember = $_[0]->{memberOrZipName};
- $newMember = $_[0]->{newMember};
- }
- else {
- ( $oldMember, $newMember ) = @_;
- }
-
- $oldMember = $self->memberNamed($oldMember) unless ref($oldMember);
- return undef unless $oldMember;
- return undef unless $newMember;
- my @newMembers =
- map { ( $_ == $oldMember ) ? $newMember : $_ } $self->members();
- $self->{'members'} = \@newMembers;
- return $oldMember;
-}
-
-sub extractMember {
- my $self = shift;
-
- my ( $member, $name );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $member = $_[0]->{memberOrZipName};
- $name = $_[0]->{name};
- }
- else {
- ( $member, $name ) = @_;
- }
-
- $member = $self->memberNamed($member) unless ref($member);
- return _error('member not found') unless $member;
- my $originalSize = $member->compressedSize();
- my ( $volumeName, $dirName, $fileName );
- if ( defined($name) ) {
- ( $volumeName, $dirName, $fileName ) = File::Spec->splitpath($name);
- $dirName = File::Spec->catpath( $volumeName, $dirName, '' );
- }
- else {
- $name = $member->fileName();
- ( $dirName = $name ) =~ s{[^/]*$}{};
- $dirName = Archive::Zip::_asLocalName($dirName);
- $name = Archive::Zip::_asLocalName($name);
- }
- if ( $dirName && !-d $dirName ) {
- mkpath($dirName);
- return _ioError("can't create dir $dirName") if ( !-d $dirName );
- }
- my $rc = $member->extractToFileNamed( $name, @_ );
-
- # TODO refactor this fix into extractToFileNamed()
- $member->{'compressedSize'} = $originalSize;
- return $rc;
-}
-
-sub extractMemberWithoutPaths {
- my $self = shift;
-
- my ( $member, $name );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $member = $_[0]->{memberOrZipName};
- $name = $_[0]->{name};
- }
- else {
- ( $member, $name ) = @_;
- }
-
- $member = $self->memberNamed($member) unless ref($member);
- return _error('member not found') unless $member;
- my $originalSize = $member->compressedSize();
- return AZ_OK if $member->isDirectory();
- unless ($name) {
- $name = $member->fileName();
- $name =~ s{.*/}{}; # strip off directories, if any
- $name = Archive::Zip::_asLocalName($name);
- }
- my $rc = $member->extractToFileNamed( $name, @_ );
- $member->{'compressedSize'} = $originalSize;
- return $rc;
-}
-
-sub addMember {
- my $self = shift;
- my $newMember = ( ref( $_[0] ) eq 'HASH' ) ? shift->{member} : shift;
- push( @{ $self->{'members'} }, $newMember ) if $newMember;
- return $newMember;
-}
-
-sub addFile {
- my $self = shift;
-
- my ( $fileName, $newName, $compressionLevel );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $fileName = $_[0]->{filename};
- $newName = $_[0]->{zipName};
- $compressionLevel = $_[0]->{compressionLevel};
- }
- else {
- ( $fileName, $newName, $compressionLevel ) = @_;
- }
-
- my $newMember = $self->ZIPMEMBERCLASS->newFromFile( $fileName, $newName );
- $newMember->desiredCompressionLevel($compressionLevel);
- if ( $self->{'storeSymbolicLink'} && -l $fileName ) {
- my $newMember = $self->ZIPMEMBERCLASS->newFromString(readlink $fileName, $newName);
- # For symbolic links, External File Attribute is set to 0xA1FF0000 by Info-ZIP
- $newMember->{'externalFileAttributes'} = 0xA1FF0000;
- $self->addMember($newMember);
- } else {
- $self->addMember($newMember);
- }
- return $newMember;
-}
-
-sub addString {
- my $self = shift;
-
- my ( $stringOrStringRef, $name, $compressionLevel );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $stringOrStringRef = $_[0]->{string};
- $name = $_[0]->{zipName};
- $compressionLevel = $_[0]->{compressionLevel};
- }
- else {
- ( $stringOrStringRef, $name, $compressionLevel ) = @_;;
- }
-
- my $newMember = $self->ZIPMEMBERCLASS->newFromString(
- $stringOrStringRef, $name
- );
- $newMember->desiredCompressionLevel($compressionLevel);
- return $self->addMember($newMember);
-}
-
-sub addDirectory {
- my $self = shift;
-
- my ( $name, $newName );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $name = $_[0]->{directoryName};
- $newName = $_[0]->{zipName};
- }
- else {
- ( $name, $newName ) = @_;
- }
-
- my $newMember = $self->ZIPMEMBERCLASS->newDirectoryNamed( $name, $newName );
- if ( $self->{'storeSymbolicLink'} && -l $name ) {
- my $link = readlink $name;
- ( $newName =~ s{/$}{} ) if $newName; # Strip trailing /
- my $newMember = $self->ZIPMEMBERCLASS->newFromString($link, $newName);
- # For symbolic links, External File Attribute is set to 0xA1FF0000 by Info-ZIP
- $newMember->{'externalFileAttributes'} = 0xA1FF0000;
- $self->addMember($newMember);
- } else {
- $self->addMember($newMember);
- }
- return $newMember;
-}
-
-# add either a file or a directory.
-
-sub addFileOrDirectory {
- my $self = shift;
-
- my ( $name, $newName, $compressionLevel );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $name = $_[0]->{name};
- $newName = $_[0]->{zipName};
- $compressionLevel = $_[0]->{compressionLevel};
- }
- else {
- ( $name, $newName, $compressionLevel ) = @_;
- }
-
- $name =~ s{/$}{};
- if ( $newName ) {
- $newName =~ s{/$}{};
- } else {
- $newName = $name;
- }
- if ( -f $name ) {
- return $self->addFile( $name, $newName, $compressionLevel );
- }
- elsif ( -d $name ) {
- return $self->addDirectory( $name, $newName );
- }
- else {
- return _error("$name is neither a file nor a directory");
- }
-}
-
-sub contents {
- my $self = shift;
-
- my ( $member, $newContents );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $member = $_[0]->{memberOrZipName};
- $newContents = $_[0]->{contents};
- }
- else {
- ( $member, $newContents ) = @_;
- }
-
- return _error('No member name given') unless $member;
- $member = $self->memberNamed($member) unless ref($member);
- return undef unless $member;
- return $member->contents($newContents);
-}
-
-sub writeToFileNamed {
- my $self = shift;
- my $fileName =
- ( ref( $_[0] ) eq 'HASH' ) ? shift->{filename} : shift; # local FS format
- foreach my $member ( $self->members() ) {
- if ( $member->_usesFileNamed($fileName) ) {
- return _error( "$fileName is needed by member "
- . $member->fileName()
- . "; consider using overwrite() or overwriteAs() instead." );
- }
- }
- my ( $status, $fh ) = _newFileHandle( $fileName, 'w' );
- return _ioError("Can't open $fileName for write") unless $status;
- my $retval = $self->writeToFileHandle( $fh, 1 );
- $fh->close();
- $fh = undef;
-
- return $retval;
-}
-
-# It is possible to write data to the FH before calling this,
-# perhaps to make a self-extracting archive.
-sub writeToFileHandle {
- my $self = shift;
-
- my ( $fh, $fhIsSeekable );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $fh = $_[0]->{fileHandle};
- $fhIsSeekable =
- exists( $_[0]->{seek} ) ? $_[0]->{seek} : _isSeekable($fh);
- }
- else {
- $fh = shift;
- $fhIsSeekable = @_ ? shift : _isSeekable($fh);
- }
-
- return _error('No filehandle given') unless $fh;
- return _ioError('filehandle not open') unless $fh->opened();
- _binmode($fh);
-
- # Find out where the current position is.
- my $offset = $fhIsSeekable ? $fh->tell() : 0;
- $offset = 0 if $offset < 0;
-
- foreach my $member ( $self->members() ) {
- my $retval = $member->_writeToFileHandle( $fh, $fhIsSeekable, $offset );
- $member->endRead();
- return $retval if $retval != AZ_OK;
- $offset += $member->_localHeaderSize() + $member->_writeOffset();
- $offset +=
- $member->hasDataDescriptor()
- ? DATA_DESCRIPTOR_LENGTH + SIGNATURE_LENGTH
- : 0;
-
- # changed this so it reflects the last successful position
- $self->{'writeCentralDirectoryOffset'} = $offset;
- }
- return $self->writeCentralDirectory($fh);
-}
-
-# Write zip back to the original file,
-# as safely as possible.
-# Returns AZ_OK if successful.
-sub overwrite {
- my $self = shift;
- return $self->overwriteAs( $self->{'fileName'} );
-}
-
-# Write zip to the specified file,
-# as safely as possible.
-# Returns AZ_OK if successful.
-sub overwriteAs {
- my $self = shift;
- my $zipName = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{filename} : shift;
- return _error("no filename in overwriteAs()") unless defined($zipName);
-
- my ( $fh, $tempName ) = Archive::Zip::tempFile();
- return _error( "Can't open temp file", $! ) unless $fh;
-
- ( my $backupName = $zipName ) =~ s{(\.[^.]*)?$}{.zbk};
-
- my $status = $self->writeToFileHandle($fh);
- $fh->close();
- $fh = undef;
-
- if ( $status != AZ_OK ) {
- unlink($tempName);
- _printError("Can't write to $tempName");
- return $status;
- }
-
- my $err;
-
- # rename the zip
- if ( -f $zipName && !rename( $zipName, $backupName ) ) {
- $err = $!;
- unlink($tempName);
- return _error( "Can't rename $zipName as $backupName", $err );
- }
-
- # move the temp to the original name (possibly copying)
- unless ( File::Copy::move( $tempName, $zipName ) ) {
- $err = $!;
- rename( $backupName, $zipName );
- unlink($tempName);
- return _error( "Can't move $tempName to $zipName", $err );
- }
-
- # unlink the backup
- if ( -f $backupName && !unlink($backupName) ) {
- $err = $!;
- return _error( "Can't unlink $backupName", $err );
- }
-
- return AZ_OK;
-}
-
-# Used only during writing
-sub _writeCentralDirectoryOffset {
- shift->{'writeCentralDirectoryOffset'};
-}
-
-sub _writeEOCDOffset {
- shift->{'writeEOCDOffset'};
-}
-
-# Expects to have _writeEOCDOffset() set
-sub _writeEndOfCentralDirectory {
- my ( $self, $fh ) = @_;
-
- $self->_print($fh, END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING)
- or return _ioError('writing EOCD Signature');
- my $zipfileCommentLength = length( $self->zipfileComment() );
-
- my $header = pack(
- END_OF_CENTRAL_DIRECTORY_FORMAT,
- 0, # {'diskNumber'},
- 0, # {'diskNumberWithStartOfCentralDirectory'},
- $self->numberOfMembers(), # {'numberOfCentralDirectoriesOnThisDisk'},
- $self->numberOfMembers(), # {'numberOfCentralDirectories'},
- $self->_writeEOCDOffset() - $self->_writeCentralDirectoryOffset(),
- $self->_writeCentralDirectoryOffset(),
- $zipfileCommentLength
- );
- $self->_print($fh, $header)
- or return _ioError('writing EOCD header');
- if ($zipfileCommentLength) {
- $self->_print($fh, $self->zipfileComment() )
- or return _ioError('writing zipfile comment');
- }
- return AZ_OK;
-}
-
-# $offset can be specified to truncate a zip file.
-sub writeCentralDirectory {
- my $self = shift;
-
- my ( $fh, $offset );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $fh = $_[0]->{fileHandle};
- $offset = $_[0]->{offset};
- }
- else {
- ( $fh, $offset ) = @_;
- }
-
- if ( defined($offset) ) {
- $self->{'writeCentralDirectoryOffset'} = $offset;
- $fh->seek( $offset, IO::Seekable::SEEK_SET )
- or return _ioError('seeking to write central directory');
- }
- else {
- $offset = $self->_writeCentralDirectoryOffset();
- }
-
- foreach my $member ( $self->members() ) {
- my $status = $member->_writeCentralDirectoryFileHeader($fh);
- return $status if $status != AZ_OK;
- $offset += $member->_centralDirectoryHeaderSize();
- $self->{'writeEOCDOffset'} = $offset;
- }
- return $self->_writeEndOfCentralDirectory($fh);
-}
-
-sub read {
- my $self = shift;
- my $fileName = ( ref( $_[0] ) eq 'HASH' ) ? shift->{filename} : shift;
- return _error('No filename given') unless $fileName;
- my ( $status, $fh ) = _newFileHandle( $fileName, 'r' );
- return _ioError("opening $fileName for read") unless $status;
-
- $status = $self->readFromFileHandle( $fh, $fileName );
- return $status if $status != AZ_OK;
-
- $fh->close();
- $self->{'fileName'} = $fileName;
- return AZ_OK;
-}
-
-sub readFromFileHandle {
- my $self = shift;
-
- my ( $fh, $fileName );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $fh = $_[0]->{fileHandle};
- $fileName = $_[0]->{filename};
- }
- else {
- ( $fh, $fileName ) = @_;
- }
-
- $fileName = $fh unless defined($fileName);
- return _error('No filehandle given') unless $fh;
- return _ioError('filehandle not open') unless $fh->opened();
-
- _binmode($fh);
- $self->{'fileName'} = "$fh";
-
- # TODO: how to support non-seekable zips?
- return _error('file not seekable')
- unless _isSeekable($fh);
-
- $fh->seek( 0, 0 ); # rewind the file
-
- my $status = $self->_findEndOfCentralDirectory($fh);
- return $status if $status != AZ_OK;
-
- my $eocdPosition = $fh->tell();
-
- $status = $self->_readEndOfCentralDirectory($fh);
- return $status if $status != AZ_OK;
-
- $fh->seek( $eocdPosition - $self->centralDirectorySize(),
- IO::Seekable::SEEK_SET )
- or return _ioError("Can't seek $fileName");
-
- # Try to detect garbage at beginning of archives
- # This should be 0
- $self->{'eocdOffset'} = $eocdPosition - $self->centralDirectorySize() # here
- - $self->centralDirectoryOffsetWRTStartingDiskNumber();
-
- for ( ; ; ) {
- my $newMember =
- $self->ZIPMEMBERCLASS->_newFromZipFile( $fh, $fileName,
- $self->eocdOffset() );
- my $signature;
- ( $status, $signature ) = _readSignature( $fh, $fileName );
- return $status if $status != AZ_OK;
- last if $signature == END_OF_CENTRAL_DIRECTORY_SIGNATURE;
- $status = $newMember->_readCentralDirectoryFileHeader();
- return $status if $status != AZ_OK;
- $status = $newMember->endRead();
- return $status if $status != AZ_OK;
- $newMember->_becomeDirectoryIfNecessary();
- push( @{ $self->{'members'} }, $newMember );
- }
-
- return AZ_OK;
-}
-
-# Read EOCD, starting from position before signature.
-# Return AZ_OK on success.
-sub _readEndOfCentralDirectory {
- my $self = shift;
- my $fh = shift;
-
- # Skip past signature
- $fh->seek( SIGNATURE_LENGTH, IO::Seekable::SEEK_CUR )
- or return _ioError("Can't seek past EOCD signature");
-
- my $header = '';
- my $bytesRead = $fh->read( $header, END_OF_CENTRAL_DIRECTORY_LENGTH );
- if ( $bytesRead != END_OF_CENTRAL_DIRECTORY_LENGTH ) {
- return _ioError("reading end of central directory");
- }
-
- my $zipfileCommentLength;
- (
- $self->{'diskNumber'},
- $self->{'diskNumberWithStartOfCentralDirectory'},
- $self->{'numberOfCentralDirectoriesOnThisDisk'},
- $self->{'numberOfCentralDirectories'},
- $self->{'centralDirectorySize'},
- $self->{'centralDirectoryOffsetWRTStartingDiskNumber'},
- $zipfileCommentLength
- ) = unpack( END_OF_CENTRAL_DIRECTORY_FORMAT, $header );
-
- if ($zipfileCommentLength) {
- my $zipfileComment = '';
- $bytesRead = $fh->read( $zipfileComment, $zipfileCommentLength );
- if ( $bytesRead != $zipfileCommentLength ) {
- return _ioError("reading zipfile comment");
- }
- $self->{'zipfileComment'} = $zipfileComment;
- }
-
- return AZ_OK;
-}
-
-# Seek in my file to the end, then read backwards until we find the
-# signature of the central directory record. Leave the file positioned right
-# before the signature. Returns AZ_OK if success.
-sub _findEndOfCentralDirectory {
- my $self = shift;
- my $fh = shift;
- my $data = '';
- $fh->seek( 0, IO::Seekable::SEEK_END )
- or return _ioError("seeking to end");
-
- my $fileLength = $fh->tell();
- if ( $fileLength < END_OF_CENTRAL_DIRECTORY_LENGTH + 4 ) {
- return _formatError("file is too short");
- }
-
- my $seekOffset = 0;
- my $pos = -1;
- for ( ; ; ) {
- $seekOffset += 512;
- $seekOffset = $fileLength if ( $seekOffset > $fileLength );
- $fh->seek( -$seekOffset, IO::Seekable::SEEK_END )
- or return _ioError("seek failed");
- my $bytesRead = $fh->read( $data, $seekOffset );
- if ( $bytesRead != $seekOffset ) {
- return _ioError("read failed");
- }
- $pos = rindex( $data, END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING );
- last
- if ( $pos >= 0
- or $seekOffset == $fileLength
- or $seekOffset >= $Archive::Zip::ChunkSize );
- }
-
- if ( $pos >= 0 ) {
- $fh->seek( $pos - $seekOffset, IO::Seekable::SEEK_CUR )
- or return _ioError("seeking to EOCD");
- return AZ_OK;
- }
- else {
- return _formatError("can't find EOCD signature");
- }
-}
-
-# Used to avoid taint problems when chdir'ing.
-# Not intended to increase security in any way; just intended to shut up the -T
-# complaints. If your Cwd module is giving you unreliable returns from cwd()
-# you have bigger problems than this.
-sub _untaintDir {
- my $dir = shift;
- $dir =~ m/\A(.+)\z/s;
- return $1;
-}
-
-sub addTree {
- my $self = shift;
-
- my ( $root, $dest, $pred, $compressionLevel );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $root = $_[0]->{root};
- $dest = $_[0]->{zipName};
- $pred = $_[0]->{select};
- $compressionLevel = $_[0]->{compressionLevel};
- }
- else {
- ( $root, $dest, $pred, $compressionLevel ) = @_;
- }
-
- return _error("root arg missing in call to addTree()")
- unless defined($root);
- $dest = '' unless defined($dest);
- $pred = sub { -r } unless defined($pred);
-
- my @files;
- my $startDir = _untaintDir( cwd() );
-
- return _error( 'undef returned by _untaintDir on cwd ', cwd() )
- unless $startDir;
-
- # This avoids chdir'ing in Find, in a way compatible with older
- # versions of File::Find.
- my $wanted = sub {
- local $main::_ = $File::Find::name;
- my $dir = _untaintDir($File::Find::dir);
- chdir($startDir);
- push( @files, $File::Find::name ) if (&$pred);
- chdir($dir);
- };
-
- File::Find::find( $wanted, $root );
-
- my $rootZipName = _asZipDirName( $root, 1 ); # with trailing slash
- my $pattern = $rootZipName eq './' ? '^' : "^\Q$rootZipName\E";
-
- $dest = _asZipDirName( $dest, 1 ); # with trailing slash
-
- foreach my $fileName (@files) {
- my $isDir = -d $fileName;
-
- # normalize, remove leading ./
- my $archiveName = _asZipDirName( $fileName, $isDir );
- if ( $archiveName eq $rootZipName ) { $archiveName = $dest }
- else { $archiveName =~ s{$pattern}{$dest} }
- next if $archiveName =~ m{^\.?/?$}; # skip current dir
- my $member = $isDir
- ? $self->addDirectory( $fileName, $archiveName )
- : $self->addFile( $fileName, $archiveName );
- $member->desiredCompressionLevel($compressionLevel);
-
- return _error("add $fileName failed in addTree()") if !$member;
- }
- return AZ_OK;
-}
-
-sub addTreeMatching {
- my $self = shift;
-
- my ( $root, $dest, $pattern, $pred, $compressionLevel );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $root = $_[0]->{root};
- $dest = $_[0]->{zipName};
- $pattern = $_[0]->{pattern};
- $pred = $_[0]->{select};
- $compressionLevel = $_[0]->{compressionLevel};
- }
- else {
- ( $root, $dest, $pattern, $pred, $compressionLevel ) = @_;
- }
-
- return _error("root arg missing in call to addTreeMatching()")
- unless defined($root);
- $dest = '' unless defined($dest);
- return _error("pattern missing in call to addTreeMatching()")
- unless defined($pattern);
- my $matcher =
- $pred ? sub { m{$pattern} && &$pred } : sub { m{$pattern} && -r };
- return $self->addTree( $root, $dest, $matcher, $compressionLevel );
-}
-
-# $zip->extractTree( $root, $dest [, $volume] );
-#
-# $root and $dest are Unix-style.
-# $volume is in local FS format.
-#
-sub extractTree {
- my $self = shift;
-
- my ( $root, $dest, $volume );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $root = $_[0]->{root};
- $dest = $_[0]->{zipName};
- $volume = $_[0]->{volume};
- }
- else {
- ( $root, $dest, $volume ) = @_;
- }
-
- $root = '' unless defined($root);
- $dest = './' unless defined($dest);
- my $pattern = "^\Q$root";
- my @members = $self->membersMatching($pattern);
-
- foreach my $member (@members) {
- my $fileName = $member->fileName(); # in Unix format
- $fileName =~ s{$pattern}{$dest}; # in Unix format
- # convert to platform format:
- $fileName = Archive::Zip::_asLocalName( $fileName, $volume );
- my $status = $member->extractToFileNamed($fileName);
- return $status if $status != AZ_OK;
- }
- return AZ_OK;
-}
-
-# $zip->updateMember( $memberOrName, $fileName );
-# Returns (possibly updated) member, if any; undef on errors.
-
-sub updateMember {
- my $self = shift;
-
- my ( $oldMember, $fileName );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $oldMember = $_[0]->{memberOrZipName};
- $fileName = $_[0]->{name};
- }
- else {
- ( $oldMember, $fileName ) = @_;
- }
-
- if ( !defined($fileName) ) {
- _error("updateMember(): missing fileName argument");
- return undef;
- }
-
- my @newStat = stat($fileName);
- if ( !@newStat ) {
- _ioError("Can't stat $fileName");
- return undef;
- }
-
- my $isDir = -d _;
-
- my $memberName;
-
- if ( ref($oldMember) ) {
- $memberName = $oldMember->fileName();
- }
- else {
- $oldMember = $self->memberNamed( $memberName = $oldMember )
- || $self->memberNamed( $memberName =
- _asZipDirName( $oldMember, $isDir ) );
- }
-
- unless ( defined($oldMember)
- && $oldMember->lastModTime() == $newStat[9]
- && $oldMember->isDirectory() == $isDir
- && ( $isDir || ( $oldMember->uncompressedSize() == $newStat[7] ) ) )
- {
-
- # create the new member
- my $newMember = $isDir
- ? $self->ZIPMEMBERCLASS->newDirectoryNamed( $fileName, $memberName )
- : $self->ZIPMEMBERCLASS->newFromFile( $fileName, $memberName );
-
- unless ( defined($newMember) ) {
- _error("creation of member $fileName failed in updateMember()");
- return undef;
- }
-
- # replace old member or append new one
- if ( defined($oldMember) ) {
- $self->replaceMember( $oldMember, $newMember );
- }
- else { $self->addMember($newMember); }
-
- return $newMember;
- }
-
- return $oldMember;
-}
-
-# $zip->updateTree( $root, [ $dest, [ $pred [, $mirror]]] );
-#
-# This takes the same arguments as addTree, but first checks to see
-# whether the file or directory already exists in the zip file.
-#
-# If the fourth argument $mirror is true, then delete all my members
-# if corresponding files weren't found.
-
-sub updateTree {
- my $self = shift;
-
- my ( $root, $dest, $pred, $mirror, $compressionLevel );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $root = $_[0]->{root};
- $dest = $_[0]->{zipName};
- $pred = $_[0]->{select};
- $mirror = $_[0]->{mirror};
- $compressionLevel = $_[0]->{compressionLevel};
- }
- else {
- ( $root, $dest, $pred, $mirror, $compressionLevel ) = @_;
- }
-
- return _error("root arg missing in call to updateTree()")
- unless defined($root);
- $dest = '' unless defined($dest);
- $pred = sub { -r } unless defined($pred);
-
- $dest = _asZipDirName( $dest, 1 );
- my $rootZipName = _asZipDirName( $root, 1 ); # with trailing slash
- my $pattern = $rootZipName eq './' ? '^' : "^\Q$rootZipName\E";
-
- my @files;
- my $startDir = _untaintDir( cwd() );
-
- return _error( 'undef returned by _untaintDir on cwd ', cwd() )
- unless $startDir;
-
- # This avoids chdir'ing in Find, in a way compatible with older
- # versions of File::Find.
- my $wanted = sub {
- local $main::_ = $File::Find::name;
- my $dir = _untaintDir($File::Find::dir);
- chdir($startDir);
- push( @files, $File::Find::name ) if (&$pred);
- chdir($dir);
- };
-
- File::Find::find( $wanted, $root );
-
- # Now @files has all the files that I could potentially be adding to
- # the zip. Only add the ones that are necessary.
- # For each file (updated or not), add its member name to @done.
- my %done;
- foreach my $fileName (@files) {
- my @newStat = stat($fileName);
- my $isDir = -d _;
-
- # normalize, remove leading ./
- my $memberName = _asZipDirName( $fileName, $isDir );
- if ( $memberName eq $rootZipName ) { $memberName = $dest }
- else { $memberName =~ s{$pattern}{$dest} }
- next if $memberName =~ m{^\.?/?$}; # skip current dir
-
- $done{$memberName} = 1;
- my $changedMember = $self->updateMember( $memberName, $fileName );
- $changedMember->desiredCompressionLevel($compressionLevel);
- return _error("updateTree failed to update $fileName")
- unless ref($changedMember);
- }
-
- # @done now has the archive names corresponding to all the found files.
- # If we're mirroring, delete all those members that aren't in @done.
- if ($mirror) {
- foreach my $member ( $self->members() ) {
- $self->removeMember($member)
- unless $done{ $member->fileName() };
- }
- }
-
- return AZ_OK;
-}
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/BufferedFileHandle.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/BufferedFileHandle.pm
deleted file mode 100755
index 4e56f9f007c..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/BufferedFileHandle.pm
+++ /dev/null
@@ -1,131 +0,0 @@
-package Archive::Zip::BufferedFileHandle;
-
-# File handle that uses a string internally and can seek
-# This is given as a demo for getting a zip file written
-# to a string.
-# I probably should just use IO::Scalar instead.
-# Ned Konz, March 2000
-
-use strict;
-use IO::File;
-use Carp;
-
-use vars qw{$VERSION};
-
-BEGIN {
- $VERSION = '1.30';
- $VERSION = eval $VERSION;
-}
-
-sub new {
- my $class = shift || __PACKAGE__;
- $class = ref($class) || $class;
- my $self = bless(
- {
- content => '',
- position => 0,
- size => 0
- },
- $class
- );
- return $self;
-}
-
-# Utility method to read entire file
-sub readFromFile {
- my $self = shift;
- my $fileName = shift;
- my $fh = IO::File->new( $fileName, "r" );
- CORE::binmode($fh);
- if ( !$fh ) {
- Carp::carp("Can't open $fileName: $!\n");
- return undef;
- }
- local $/ = undef;
- $self->{content} = <$fh>;
- $self->{size} = length( $self->{content} );
- return $self;
-}
-
-sub contents {
- my $self = shift;
- if (@_) {
- $self->{content} = shift;
- $self->{size} = length( $self->{content} );
- }
- return $self->{content};
-}
-
-sub binmode { 1 }
-
-sub close { 1 }
-
-sub opened { 1 }
-
-sub eof {
- my $self = shift;
- return $self->{position} >= $self->{size};
-}
-
-sub seek {
- my $self = shift;
- my $pos = shift;
- my $whence = shift;
-
- # SEEK_SET
- if ( $whence == 0 ) { $self->{position} = $pos; }
-
- # SEEK_CUR
- elsif ( $whence == 1 ) { $self->{position} += $pos; }
-
- # SEEK_END
- elsif ( $whence == 2 ) { $self->{position} = $self->{size} + $pos; }
- else { return 0; }
-
- return 1;
-}
-
-sub tell { return shift->{position}; }
-
-# Copy my data to given buffer
-sub read {
- my $self = shift;
- my $buf = \( $_[0] );
- shift;
- my $len = shift;
- my $offset = shift || 0;
-
- $$buf = '' if not defined($$buf);
- my $bytesRead =
- ( $self->{position} + $len > $self->{size} )
- ? ( $self->{size} - $self->{position} )
- : $len;
- substr( $$buf, $offset, $bytesRead ) =
- substr( $self->{content}, $self->{position}, $bytesRead );
- $self->{position} += $bytesRead;
- return $bytesRead;
-}
-
-# Copy given buffer to me
-sub write {
- my $self = shift;
- my $buf = \( $_[0] );
- shift;
- my $len = shift;
- my $offset = shift || 0;
-
- $$buf = '' if not defined($$buf);
- my $bufLen = length($$buf);
- my $bytesWritten =
- ( $offset + $len > $bufLen )
- ? $bufLen - $offset
- : $len;
- substr( $self->{content}, $self->{position}, $bytesWritten ) =
- substr( $$buf, $offset, $bytesWritten );
- $self->{size} = length( $self->{content} );
- return $bytesWritten;
-}
-
-sub clearerr() { 1 }
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/DirectoryMember.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/DirectoryMember.pm
deleted file mode 100755
index c9d3705f08f..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/DirectoryMember.pm
+++ /dev/null
@@ -1,80 +0,0 @@
-package Archive::Zip::DirectoryMember;
-
-use strict;
-use File::Path;
-
-use vars qw( $VERSION @ISA );
-
-BEGIN {
- $VERSION = '1.30';
- @ISA = qw( Archive::Zip::Member );
-}
-
-use Archive::Zip qw(
- :ERROR_CODES
- :UTILITY_METHODS
-);
-
-sub _newNamed {
- my $class = shift;
- my $fileName = shift; # FS name
- my $newName = shift; # Zip name
- $newName = _asZipDirName($fileName) unless $newName;
- my $self = $class->new(@_);
- $self->{'externalFileName'} = $fileName;
- $self->fileName($newName);
-
- if ( -e $fileName ) {
-
- # -e does NOT do a full stat, so we need to do one now
- if ( -d _ ) {
- my @stat = stat(_);
- $self->unixFileAttributes( $stat[2] );
- my $mod_t = $stat[9];
- if ( $^O eq 'MSWin32' and !$mod_t ) {
- $mod_t = time();
- }
- $self->setLastModFileDateTimeFromUnix($mod_t);
-
- } else { # hmm.. trying to add a non-directory?
- _error( $fileName, ' exists but is not a directory' );
- return undef;
- }
- } else {
- $self->unixFileAttributes( $self->DEFAULT_DIRECTORY_PERMISSIONS );
- $self->setLastModFileDateTimeFromUnix( time() );
- }
- return $self;
-}
-
-sub externalFileName {
- shift->{'externalFileName'};
-}
-
-sub isDirectory {
- return 1;
-}
-
-sub extractToFileNamed {
- my $self = shift;
- my $name = shift; # local FS name
- my $attribs = $self->unixFileAttributes() & 07777;
- mkpath( $name, 0, $attribs ); # croaks on error
- utime( $self->lastModTime(), $self->lastModTime(), $name );
- return AZ_OK;
-}
-
-sub fileName {
- my $self = shift;
- my $newName = shift;
- $newName =~ s{/?$}{/} if defined($newName);
- return $self->SUPER::fileName($newName);
-}
-
-# So people don't get too confused. This way it looks like the problem
-# is in their code...
-sub contents {
- return wantarray ? ( undef, AZ_OK ) : undef;
-}
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/FAQ.pod b/Master/tlpkg/tlperl/lib/Archive/Zip/FAQ.pod
deleted file mode 100755
index 2b2d8ed9e88..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/FAQ.pod
+++ /dev/null
@@ -1,467 +0,0 @@
-
-=head1 NAME
-
-
-Archive::Zip::FAQ - Answers to a few frequently asked questions about Archive::Zip
-
-=head1 DESCRIPTION
-
-
-It seems that I keep answering the same questions over and over again. I
-assume that this is because my documentation is deficient, rather than that
-people don't read the documentation.
-
-
-So this FAQ is an attempt to cut down on the number of personal answers I have
-to give. At least I can now say "You I<did> read the FAQ, right?".
-
-
-The questions are not in any particular order. The answers assume the current
-version of Archive::Zip; some of the answers depend on newly added/fixed
-functionality.
-
-=head1 Install problems on RedHat 8 or 9 with Perl 5.8.0
-
-
-B<Q:> Archive::Zip won't install on my RedHat 9 system! It's broke!
-
-
-B<A:> This has become something of a FAQ.
-Basically, RedHat broke some versions of Perl by setting LANG to UTF8.
-They apparently have a fixed version out as an update.
-
-You might try running CPAN or creating your Makefile after exporting the LANG
-environment variable as
-
-C<LANG=C>
-
-L<https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=87682>
-
-
-=head1 Why is my zip file so big?
-
-
-B<Q:> My zip file is actually bigger than what I stored in it! Why?
-
-
-B<A:> Some things to make sure of:
-
-=over 4
-
-=item Make sure that you are requesting COMPRESSION_DEFLATED if you are storing strings.
-
-
-
-
-$member->desiredCompressionMethod( COMPRESSION_DEFLATED );
-
-
-=item Don't make lots of little files if you can help it.
-
-
-
-Since zip computes the compression tables for each member, small
-members without much entropy won't compress well. Instead, if you've
-got lots of repeated strings in your data, try to combine them into
-one big member.
-
-
-=item Make sure that you are requesting COMPRESSION_STORED if you are storing things that are already compressed.
-
-
-
-If you're storing a .zip, .jpg, .mp3, or other compressed file in a zip,
-then don't compress them again. They'll get bigger.
-
-=back
-
-=head1 Sample code?
-
-
-B<Q:> Can you send me code to do (whatever)?
-
-
-B<A:> Have you looked in the C<examples/> directory yet? It contains:
-
-=over 4
-
-=item examples/calcSizes.pl -- How to find out how big a Zip file will be before writing it
-
-
-
-=item examples/copy.pl -- Copies one Zip file to another
-
-
-
-=item examples/extract.pl -- extract file(s) from a Zip
-
-
-
-=item examples/mailZip.pl -- make and mail a zip file
-
-
-
-=item examples/mfh.pl -- demo for use of MockFileHandle
-
-
-
-=item examples/readScalar.pl -- shows how to use IO::Scalar as the source of a Zip read
-
-
-
-=item examples/selfex.pl -- a brief example of a self-extracting Zip
-
-
-
-=item examples/unzipAll.pl -- uses Archive::Zip::Tree to unzip an entire Zip
-
-
-
-=item examples/updateZip.pl -- shows how to read/modify/write a Zip
-
-
-
-=item examples/updateTree.pl -- shows how to update a Zip in place
-
-
-
-=item examples/writeScalar.pl -- shows how to use IO::Scalar as the destination of a Zip write
-
-
-
-=item examples/writeScalar2.pl -- shows how to use IO::String as the destination of a Zip write
-
-
-
-=item examples/zip.pl -- Constructs a Zip file
-
-
-
-=item examples/zipcheck.pl -- One way to check a Zip file for validity
-
-
-
-=item examples/zipinfo.pl -- Prints out information about a Zip archive file
-
-
-
-=item examples/zipGrep.pl -- Searches for text in Zip files
-
-
-
-=item examples/ziptest.pl -- Lists a Zip file and checks member CRCs
-
-
-
-=item examples/ziprecent.pl -- Puts recent files into a zipfile
-
-
-
-=item examples/ziptest.pl -- Another way to check a Zip file for validity
-
-
-
-=back
-
-=head1 Can't Read/modify/write same Zip file
-
-
-B<Q:> Why can't I open a Zip file, add a member, and write it back? I get an
-error message when I try.
-
-
-B<A:> Because Archive::Zip doesn't (and can't, generally) read file contents into memory,
-the original Zip file is required to stay around until the writing of the new
-file is completed.
-
-
-The best way to do this is to write the Zip to a temporary file and then
-rename the temporary file to have the old name (possibly after deleting the
-old one).
-
-
-Archive::Zip v1.02 added the archive methods C<overwrite()> and
-C<overwriteAs()> to do this simply and carefully.
-
-
-See C<examples/updateZip.pl> for an example of this technique.
-
-=head1 File creation time not set
-
-
-B<Q:> Upon extracting files, I see that their modification (and access) times are
-set to the time in the Zip archive. However, their creation time is not set to
-the same time. Why?
-
-
-B<A:> Mostly because Perl doesn't give cross-platform access to I<creation time>.
-Indeed, many systems (like Unix) don't support such a concept.
-However, if yours does, you can easily set it. Get the modification time from
-the member using C<lastModTime()>.
-
-=head1 Can't use Archive::Zip on gzip files
-
-
-B<Q:> Can I use Archive::Zip to extract Unix gzip files?
-
-
-B<A:> No.
-
-
-There is a distinction between Unix gzip files, and Zip archives that
-also can use the gzip compression.
-
-
-Depending on the format of the gzip file, you can use L<Compress::Raw::Zlib>, or
-L<Archive::Tar> to decompress it (and de-archive it in the case of Tar files).
-
-
-You can unzip PKZIP/WinZip/etc/ archives using Archive::Zip (that's what
-it's for) as long as any compressed members are compressed using
-Deflate compression.
-
-=head1 Add a directory/tree to a Zip
-
-
-B<Q:> How can I add a directory (or tree) full of files to a Zip?
-
-
-B<A:> You can use the Archive::Zip::addTree*() methods:
-
- use Archive::Zip;
- my $zip = Archive::Zip->new();
- # add all readable files and directories below . as xyz/*
- $zip->addTree( '.', 'xyz' );
- # add all readable plain files below /abc as def/*
- $zip->addTree( '/abc', 'def', sub { -f && -r } );
- # add all .c files below /tmp as stuff/*
- $zip->addTreeMatching( '/tmp', 'stuff', '\.c$' );
- # add all .o files below /tmp as stuff/* if they aren't writable
- $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } );
- # add all .so files below /tmp that are smaller than 200 bytes as stuff/*
- $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { -s < 200 } );
- # and write them into a file
- $zip->writeToFileNamed('xxx.zip');
-
-=head1 Extract a directory/tree
-
-
-B<Q:> How can I extract some (or all) files from a Zip into a different
-directory?
-
-
-B<A:> You can use the Archive::Zip::extractTree() method:
-??? ||
-
-
- # now extract the same files into /tmpx
- $zip->extractTree( 'stuff', '/tmpx' );
-
-=head1 Update a directory/tree
-
-
-B<Q:> How can I update a Zip from a directory tree, adding or replacing only
-the newer files?
-
-
-B<A:> You can use the Archive::Zip::updateTree() method that was added in version 1.09.
-
-=head1 Zip times might be off by 1 second
-
-
-B<Q:> It bothers me greatly that my file times are wrong by one second about half
-the time. Why don't you do something about it?
-
-
-B<A:> Get over it. This is a result of the Zip format storing times in DOS
-format, which has a resolution of only two seconds.
-
-=head1 Zip times don't include time zone information
-
-
-B<Q:> My file times don't respect time zones. What gives?
-
-
-B<A:> If this is important to you, please submit patches to read the various
-Extra Fields that encode times with time zones. I'm just using the DOS
-Date/Time, which doesn't have a time zone.
-
-=head1 How do I make a self-extracting Zip
-
-
-B<Q:> I want to make a self-extracting Zip file. Can I do this?
-
-
-B<A:> Yes. You can write a self-extracting archive stub (that is, a version of
-unzip) to the output filehandle that you pass to writeToFileHandle(). See
-examples/selfex.pl for how to write a self-extracting archive.
-
-
-However, you should understand that this will only work on one kind of
-platform (the one for which the stub was compiled).
-
-=head1 How can I deal with Zips with prepended garbage (i.e. from Sircam)
-
-
-B<Q:> How can I tell if a Zip has been damaged by adding garbage to the
-beginning or inside the file?
-
-
-B<A:> I added code for this for the Amavis virus scanner. You can query archives
-for their 'eocdOffset' property, which should be 0:
-
-
- if ($zip->eocdOffset > 0)
- { warn($zip->eocdOffset . " bytes of garbage at beginning or within Zip") }
-
-
-When members are extracted, this offset will be used to adjust the start of
-the member if necessary.
-
-=head1 Can't extract Shrunk files
-
-
-B<Q:> I'm trying to extract a file out of a Zip produced by PKZIP, and keep
-getting this error message:
-
-
- error: Unsupported compression combination: read 6, write 0
-
-
-B<A:> You can't uncompress this archive member. Archive::Zip only supports uncompressed
-members, and compressed members that are compressed using the compression
-supported by Compress::Raw::Zlib. That means only Deflated and Stored members.
-
-
-Your file is compressed using the Shrink format, which isn't supported by
-Compress::Raw::Zlib.
-
-
-You could, perhaps, use a command-line UnZip program (like the Info-Zip
-one) to extract this.
-
-=head1 Can't do decryption
-
-
-B<Q:> How do I decrypt encrypted Zip members?
-
-
-B<A:> With some other program or library. Archive::Zip doesn't support decryption,
-and probably never will (unless I<you> write it).
-
-=head1 How to test file integrity?
-
-
-B<Q:> How can Archive::Zip can test the validity of a Zip file?
-
-
-B<A:> If you try to decompress the file, the gzip streams will report errors
-if you have garbage. Most of the time.
-
-If you try to open the file and a central directory structure can't be
-found, an error will be reported.
-
-When a file is being read, if we can't find a proper PK.. signature in
-the right places we report a format error.
-
-If there is added garbage at the beginning of a Zip file (as inserted
-by some viruses), you can find out about it, but Archive::Zip will ignore it,
-and you can still use the archive. When it gets written back out the
-added stuff will be gone.
-
-
-There are two ready-to-use utilities in the examples directory that can
-be used to test file integrity, or that you can use as examples
-for your own code:
-
-=over 4
-
-=item examples/zipcheck.pl shows how to use an attempted extraction to test a file.
-
-
-
-=item examples/ziptest.pl shows how to test CRCs in a file.
-
-
-
-=back
-
-=head1 Duplicate files in Zip?
-
-
-B<Q:> Archive::Zip let me put the same file in my Zip twice! Why don't you prevent this?
-
-
-B<A:> As far as I can tell, this is not disallowed by the Zip spec. If you
-think it's a bad idea, check for it yourself:
-
-
- $zip->addFile($someFile, $someName) unless $zip->memberNamed($someName);
-
-
-I can even imagine cases where this might be useful (for instance, multiple
-versions of files).
-
-=head1 File ownership/permissions/ACLS/etc
-
-
-B<Q:> Why doesn't Archive::Zip deal with file ownership, ACLs, etc.?
-
-
-B<A:> There is no standard way to represent these in the Zip file format. If
-you want to send me code to properly handle the various extra fields that
-have been used to represent these through the years, I'll look at it.
-
-=head1 I can't compile but ActiveState only has an old version of Archive::Zip
-
-
-B<Q:> I've only installed modules using ActiveState's PPM program and
-repository. But they have a much older version of Archive::Zip than is in CPAN. Will
-you send me a newer PPM?
-
-
-B<A:> Probably not, unless I get lots of extra time. But there's no reason you
-can't install the version from CPAN. Archive::Zip is pure Perl, so all you need is
-NMAKE, which you can get for free from Microsoft (see the FAQ in the
-ActiveState documentation for details on how to install CPAN modules).
-
-=head1 My JPEGs (or MP3's) don't compress when I put them into Zips!
-
-
-B<Q:> How come my JPEGs and MP3's don't compress much when I put them into Zips?
-
-
-B<A:> Because they're already compressed.
-
-=head1 Under Windows, things lock up/get damaged
-
-
-B<Q:> I'm using Windows. When I try to use Archive::Zip, my machine locks up/makes
-funny sounds/displays a BSOD/corrupts data. How can I fix this?
-
-
-B<A:> First, try the newest version of Compress::Raw::Zlib. I know of
-Windows-related problems prior to v1.14 of that library.
-
-
-If that doesn't get rid of the problem, fix your computer or get rid of
-Windows.
-
-=head1 Zip contents in a scalar
-
-
-B<Q:> I want to read a Zip file from (or write one to) a scalar variable instead
-of a file. How can I do this?
-
-
-B<A:> Use C<IO::String> and the C<readFromFileHandle()> and
-C<writeToFileHandle()> methods.
-See C<examples/readScalar.pl> and C<examples/writeScalar.pl>.
-
-=head1 Reading from streams
-
-
-B<Q:> How do I read from a stream (like for the Info-Zip C<funzip> program)?
-
-
-B<A:> This isn't currently supported, though writing to a stream is.
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/FileMember.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/FileMember.pm
deleted file mode 100755
index a9b8cf5d7be..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/FileMember.pm
+++ /dev/null
@@ -1,64 +0,0 @@
-package Archive::Zip::FileMember;
-
-use strict;
-use vars qw( $VERSION @ISA );
-
-BEGIN {
- $VERSION = '1.30';
- @ISA = qw ( Archive::Zip::Member );
-}
-
-use Archive::Zip qw(
- :UTILITY_METHODS
-);
-
-sub externalFileName {
- shift->{'externalFileName'};
-}
-
-# Return true if I depend on the named file
-sub _usesFileNamed {
- my $self = shift;
- my $fileName = shift;
- my $xfn = $self->externalFileName();
- return undef if ref($xfn);
- return $xfn eq $fileName;
-}
-
-sub fh {
- my $self = shift;
- $self->_openFile()
- if !defined( $self->{'fh'} ) || !$self->{'fh'}->opened();
- return $self->{'fh'};
-}
-
-# opens my file handle from my file name
-sub _openFile {
- my $self = shift;
- my ( $status, $fh ) = _newFileHandle( $self->externalFileName(), 'r' );
- if ( !$status ) {
- _ioError( "Can't open", $self->externalFileName() );
- return undef;
- }
- $self->{'fh'} = $fh;
- _binmode($fh);
- return $fh;
-}
-
-# Make sure I close my file handle
-sub endRead {
- my $self = shift;
- undef $self->{'fh'}; # _closeFile();
- return $self->SUPER::endRead(@_);
-}
-
-sub _become {
- my $self = shift;
- my $newClass = shift;
- return $self if ref($self) eq $newClass;
- delete( $self->{'externalFileName'} );
- delete( $self->{'fh'} );
- return $self->SUPER::_become($newClass);
-}
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/Member.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/Member.pm
deleted file mode 100755
index f86ef75d55d..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/Member.pm
+++ /dev/null
@@ -1,1083 +0,0 @@
-package Archive::Zip::Member;
-
-# A generic membet of an archive
-
-use strict;
-use vars qw( $VERSION @ISA );
-
-BEGIN {
- $VERSION = '1.30';
- @ISA = qw( Archive::Zip );
-}
-
-use Archive::Zip qw(
- :CONSTANTS
- :MISC_CONSTANTS
- :ERROR_CODES
- :PKZIP_CONSTANTS
- :UTILITY_METHODS
-);
-
-use Time::Local ();
-use Compress::Raw::Zlib qw( Z_OK Z_STREAM_END MAX_WBITS );
-use File::Path;
-use File::Basename;
-
-use constant ZIPFILEMEMBERCLASS => 'Archive::Zip::ZipFileMember';
-use constant NEWFILEMEMBERCLASS => 'Archive::Zip::NewFileMember';
-use constant STRINGMEMBERCLASS => 'Archive::Zip::StringMember';
-use constant DIRECTORYMEMBERCLASS => 'Archive::Zip::DirectoryMember';
-
-# Unix perms for default creation of files/dirs.
-use constant DEFAULT_DIRECTORY_PERMISSIONS => 040755;
-use constant DEFAULT_FILE_PERMISSIONS => 0100666;
-use constant DIRECTORY_ATTRIB => 040000;
-use constant FILE_ATTRIB => 0100000;
-
-# Returns self if successful, else undef
-# Assumes that fh is positioned at beginning of central directory file header.
-# Leaves fh positioned immediately after file header or EOCD signature.
-sub _newFromZipFile {
- my $class = shift;
- my $self = $class->ZIPFILEMEMBERCLASS->_newFromZipFile(@_);
- return $self;
-}
-
-sub newFromString {
- my $class = shift;
-
- my ( $stringOrStringRef, $fileName );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $stringOrStringRef = $_[0]->{string};
- $fileName = $_[0]->{zipName};
- }
- else {
- ( $stringOrStringRef, $fileName ) = @_;
- }
-
- my $self = $class->STRINGMEMBERCLASS->_newFromString( $stringOrStringRef,
- $fileName );
- return $self;
-}
-
-sub newFromFile {
- my $class = shift;
-
- my ( $fileName, $zipName );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $fileName = $_[0]->{fileName};
- $zipName = $_[0]->{zipName};
- }
- else {
- ( $fileName, $zipName ) = @_;
- }
-
- my $self = $class->NEWFILEMEMBERCLASS->_newFromFileNamed( $fileName,
- $zipName );
- return $self;
-}
-
-sub newDirectoryNamed {
- my $class = shift;
-
- my ( $directoryName, $newName );
- if ( ref( $_[0] ) eq 'HASH' ) {
- $directoryName = $_[0]->{directoryName};
- $newName = $_[0]->{zipName};
- }
- else {
- ( $directoryName, $newName ) = @_;
- }
-
- my $self = $class->DIRECTORYMEMBERCLASS->_newNamed( $directoryName,
- $newName );
- return $self;
-}
-
-sub new {
- my $class = shift;
- my $self = {
- 'lastModFileDateTime' => 0,
- 'fileAttributeFormat' => FA_UNIX,
- 'versionMadeBy' => 20,
- 'versionNeededToExtract' => 20,
- 'bitFlag' => 0,
- 'compressionMethod' => COMPRESSION_STORED,
- 'desiredCompressionMethod' => COMPRESSION_STORED,
- 'desiredCompressionLevel' => COMPRESSION_LEVEL_NONE,
- 'internalFileAttributes' => 0,
- 'externalFileAttributes' => 0, # set later
- 'fileName' => '',
- 'cdExtraField' => '',
- 'localExtraField' => '',
- 'fileComment' => '',
- 'crc32' => 0,
- 'compressedSize' => 0,
- 'uncompressedSize' => 0,
- 'isSymbolicLink' => 0,
- @_
- };
- bless( $self, $class );
- $self->unixFileAttributes( $self->DEFAULT_FILE_PERMISSIONS );
- return $self;
-}
-
-sub _becomeDirectoryIfNecessary {
- my $self = shift;
- $self->_become(DIRECTORYMEMBERCLASS)
- if $self->isDirectory();
- return $self;
-}
-
-# Morph into given class (do whatever cleanup I need to do)
-sub _become {
- return bless( $_[0], $_[1] );
-}
-
-sub versionMadeBy {
- shift->{'versionMadeBy'};
-}
-
-sub fileAttributeFormat {
- my $self = shift;
-
- if (@_) {
- $self->{fileAttributeFormat} = ( ref( $_[0] ) eq 'HASH' )
- ? $_[0]->{format} : $_[0];
- }
- else {
- return $self->{fileAttributeFormat};
- }
-}
-
-sub versionNeededToExtract {
- shift->{'versionNeededToExtract'};
-}
-
-sub bitFlag {
- my $self = shift;
-
- # Set General Purpose Bit Flags according to the desiredCompressionLevel setting
- if ( $self->desiredCompressionLevel == 1 || $self->desiredCompressionLevel == 2 ) {
- $self->{'bitFlag'} = DEFLATING_COMPRESSION_FAST;
- } elsif ( $self->desiredCompressionLevel == 3 || $self->desiredCompressionLevel == 4
- || $self->desiredCompressionLevel == 5 || $self->desiredCompressionLevel == 6
- || $self->desiredCompressionLevel == 7 ) {
- $self->{'bitFlag'} = DEFLATING_COMPRESSION_NORMAL;
- } elsif ( $self->desiredCompressionLevel == 8 || $self->desiredCompressionLevel == 9 ) {
- $self->{'bitFlag'} = DEFLATING_COMPRESSION_MAXIMUM;
- }
- $self->{'bitFlag'};
-}
-
-sub compressionMethod {
- shift->{'compressionMethod'};
-}
-
-sub desiredCompressionMethod {
- my $self = shift;
- my $newDesiredCompressionMethod =
- ( ref( $_[0] ) eq 'HASH' ) ? shift->{compressionMethod} : shift;
- my $oldDesiredCompressionMethod = $self->{'desiredCompressionMethod'};
- if ( defined($newDesiredCompressionMethod) ) {
- $self->{'desiredCompressionMethod'} = $newDesiredCompressionMethod;
- if ( $newDesiredCompressionMethod == COMPRESSION_STORED ) {
- $self->{'desiredCompressionLevel'} = 0;
- $self->{'bitFlag'} &= ~GPBF_HAS_DATA_DESCRIPTOR_MASK;
-
- } elsif ( $oldDesiredCompressionMethod == COMPRESSION_STORED ) {
- $self->{'desiredCompressionLevel'} = COMPRESSION_LEVEL_DEFAULT;
- }
- }
- return $oldDesiredCompressionMethod;
-}
-
-sub desiredCompressionLevel {
- my $self = shift;
- my $newDesiredCompressionLevel =
- ( ref( $_[0] ) eq 'HASH' ) ? shift->{compressionLevel} : shift;
- my $oldDesiredCompressionLevel = $self->{'desiredCompressionLevel'};
- if ( defined($newDesiredCompressionLevel) ) {
- $self->{'desiredCompressionLevel'} = $newDesiredCompressionLevel;
- $self->{'desiredCompressionMethod'} = (
- $newDesiredCompressionLevel
- ? COMPRESSION_DEFLATED
- : COMPRESSION_STORED
- );
- }
- return $oldDesiredCompressionLevel;
-}
-
-sub fileName {
- my $self = shift;
- my $newName = shift;
- if ($newName) {
- $newName =~ s{[\\/]+}{/}g; # deal with dos/windoze problems
- $self->{'fileName'} = $newName;
- }
- return $self->{'fileName'};
-}
-
-sub lastModFileDateTime {
- my $modTime = shift->{'lastModFileDateTime'};
- $modTime =~ m/^(\d+)$/; # untaint
- return $1;
-}
-
-sub lastModTime {
- my $self = shift;
- return _dosToUnixTime( $self->lastModFileDateTime() );
-}
-
-sub setLastModFileDateTimeFromUnix {
- my $self = shift;
- my $time_t = shift;
- $self->{'lastModFileDateTime'} = _unixToDosTime($time_t);
-}
-
-sub internalFileAttributes {
- shift->{'internalFileAttributes'};
-}
-
-sub externalFileAttributes {
- shift->{'externalFileAttributes'};
-}
-
-# Convert UNIX permissions into proper value for zip file
-# Usable as a function or a method
-sub _mapPermissionsFromUnix {
- my $self = shift;
- my $mode = shift;
- my $attribs = $mode << 16;
-
- # Microsoft Windows Explorer needs this bit set for directories
- if ( $mode & DIRECTORY_ATTRIB ) {
- $attribs |= 16;
- }
-
- return $attribs;
-
- # TODO: map more MS-DOS perms
-}
-
-# Convert ZIP permissions into Unix ones
-#
-# This was taken from Info-ZIP group's portable UnZip
-# zipfile-extraction program, version 5.50.
-# http://www.info-zip.org/pub/infozip/
-#
-# See the mapattr() function in unix/unix.c
-# See the attribute format constants in unzpriv.h
-#
-# XXX Note that there's one situation that isn't implemented
-# yet that depends on the "extra field."
-sub _mapPermissionsToUnix {
- my $self = shift;
-
- my $format = $self->{'fileAttributeFormat'};
- my $attribs = $self->{'externalFileAttributes'};
-
- my $mode = 0;
-
- if ( $format == FA_AMIGA ) {
- $attribs = $attribs >> 17 & 7; # Amiga RWE bits
- $mode = $attribs << 6 | $attribs << 3 | $attribs;
- return $mode;
- }
-
- if ( $format == FA_THEOS ) {
- $attribs &= 0xF1FFFFFF;
- if ( ( $attribs & 0xF0000000 ) != 0x40000000 ) {
- $attribs &= 0x01FFFFFF; # not a dir, mask all ftype bits
- }
- else {
- $attribs &= 0x41FFFFFF; # leave directory bit as set
- }
- }
-
- if ( $format == FA_UNIX
- || $format == FA_VAX_VMS
- || $format == FA_ACORN
- || $format == FA_ATARI_ST
- || $format == FA_BEOS
- || $format == FA_QDOS
- || $format == FA_TANDEM )
- {
- $mode = $attribs >> 16;
- return $mode if $mode != 0 or not $self->localExtraField;
-
- # warn("local extra field is: ", $self->localExtraField, "\n");
-
- # XXX This condition is not implemented
- # I'm just including the comments from the info-zip section for now.
-
- # Some (non-Info-ZIP) implementations of Zip for Unix and
- # VMS (and probably others ??) leave 0 in the upper 16-bit
- # part of the external_file_attributes field. Instead, they
- # store file permission attributes in some extra field.
- # As a work-around, we search for the presence of one of
- # these extra fields and fall back to the MSDOS compatible
- # part of external_file_attributes if one of the known
- # e.f. types has been detected.
- # Later, we might implement extraction of the permission
- # bits from the VMS extra field. But for now, the work-around
- # should be sufficient to provide "readable" extracted files.
- # (For ASI Unix e.f., an experimental remap from the e.f.
- # mode value IS already provided!)
- }
-
- # PKWARE's PKZip for Unix marks entries as FA_MSDOS, but stores the
- # Unix attributes in the upper 16 bits of the external attributes
- # field, just like Info-ZIP's Zip for Unix. We try to use that
- # value, after a check for consistency with the MSDOS attribute
- # bits (see below).
- if ( $format == FA_MSDOS ) {
- $mode = $attribs >> 16;
- }
-
- # FA_MSDOS, FA_OS2_HPFS, FA_WINDOWS_NTFS, FA_MACINTOSH, FA_TOPS20
- $attribs = !( $attribs & 1 ) << 1 | ( $attribs & 0x10 ) >> 4;
-
- # keep previous $mode setting when its "owner"
- # part appears to be consistent with DOS attribute flags!
- return $mode if ( $mode & 0700 ) == ( 0400 | $attribs << 6 );
- $mode = 0444 | $attribs << 6 | $attribs << 3 | $attribs;
- return $mode;
-}
-
-sub unixFileAttributes {
- my $self = shift;
- my $oldPerms = $self->_mapPermissionsToUnix;
-
- my $perms;
- if ( @_ ) {
- $perms = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{attributes} : $_[0];
-
- if ( $self->isDirectory ) {
- $perms &= ~FILE_ATTRIB;
- $perms |= DIRECTORY_ATTRIB;
- } else {
- $perms &= ~DIRECTORY_ATTRIB;
- $perms |= FILE_ATTRIB;
- }
- $self->{externalFileAttributes} = $self->_mapPermissionsFromUnix($perms);
- }
-
- return $oldPerms;
-}
-
-sub localExtraField {
- my $self = shift;
-
- if (@_) {
- $self->{localExtraField} = ( ref( $_[0] ) eq 'HASH' )
- ? $_[0]->{field} : $_[0];
- }
- else {
- return $self->{localExtraField};
- }
-}
-
-sub cdExtraField {
- my $self = shift;
-
- if (@_) {
- $self->{cdExtraField} = ( ref( $_[0] ) eq 'HASH' )
- ? $_[0]->{field} : $_[0];
- }
- else {
- return $self->{cdExtraField};
- }
-}
-
-sub extraFields {
- my $self = shift;
- return $self->localExtraField() . $self->cdExtraField();
-}
-
-sub fileComment {
- my $self = shift;
-
- if (@_) {
- $self->{fileComment} = ( ref( $_[0] ) eq 'HASH' )
- ? pack( 'C0a*', $_[0]->{comment} ) : pack( 'C0a*', $_[0] );
- }
- else {
- return $self->{fileComment};
- }
-}
-
-sub hasDataDescriptor {
- my $self = shift;
- if (@_) {
- my $shouldHave = shift;
- if ($shouldHave) {
- $self->{'bitFlag'} |= GPBF_HAS_DATA_DESCRIPTOR_MASK;
- }
- else {
- $self->{'bitFlag'} &= ~GPBF_HAS_DATA_DESCRIPTOR_MASK;
- }
- }
- return $self->{'bitFlag'} & GPBF_HAS_DATA_DESCRIPTOR_MASK;
-}
-
-sub crc32 {
- shift->{'crc32'};
-}
-
-sub crc32String {
- sprintf( "%08x", shift->{'crc32'} );
-}
-
-sub compressedSize {
- shift->{'compressedSize'};
-}
-
-sub uncompressedSize {
- shift->{'uncompressedSize'};
-}
-
-sub isEncrypted {
- shift->bitFlag() & GPBF_ENCRYPTED_MASK;
-}
-
-sub isTextFile {
- my $self = shift;
- my $bit = $self->internalFileAttributes() & IFA_TEXT_FILE_MASK;
- if (@_) {
- my $flag = ( ref( $_[0] ) eq 'HASH' ) ? shift->{flag} : shift;
- $self->{'internalFileAttributes'} &= ~IFA_TEXT_FILE_MASK;
- $self->{'internalFileAttributes'} |=
- ( $flag ? IFA_TEXT_FILE: IFA_BINARY_FILE );
- }
- return $bit == IFA_TEXT_FILE;
-}
-
-sub isBinaryFile {
- my $self = shift;
- my $bit = $self->internalFileAttributes() & IFA_TEXT_FILE_MASK;
- if (@_) {
- my $flag = shift;
- $self->{'internalFileAttributes'} &= ~IFA_TEXT_FILE_MASK;
- $self->{'internalFileAttributes'} |=
- ( $flag ? IFA_BINARY_FILE: IFA_TEXT_FILE );
- }
- return $bit == IFA_BINARY_FILE;
-}
-
-sub extractToFileNamed {
- my $self = shift;
-
- # local FS name
- my $name = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{name} : $_[0];
- $self->{'isSymbolicLink'} = 0;
-
- # Check if the file / directory is a symbolic link or not
- if ( $self->{'externalFileAttributes'} == 0xA1FF0000 ) {
- $self->{'isSymbolicLink'} = 1;
- $self->{'newName'} = $name;
- my ( $status, $fh ) = _newFileHandle( $name, 'r' );
- my $retval = $self->extractToFileHandle($fh);
- $fh->close();
- } else {
- #return _writeSymbolicLink($self, $name) if $self->isSymbolicLink();
- return _error("encryption unsupported") if $self->isEncrypted();
- mkpath( dirname($name) ); # croaks on error
- my ( $status, $fh ) = _newFileHandle( $name, 'w' );
- return _ioError("Can't open file $name for write") unless $status;
- my $retval = $self->extractToFileHandle($fh);
- $fh->close();
- chmod ($self->unixFileAttributes(), $name)
- or return _error("Can't chmod() ${name}: $!");
- utime( $self->lastModTime(), $self->lastModTime(), $name );
- return $retval;
- }
-}
-
-sub _writeSymbolicLink {
- my $self = shift;
- my $name = shift;
- my $chunkSize = $Archive::Zip::ChunkSize;
- #my ( $outRef, undef ) = $self->readChunk($chunkSize);
- my $fh;
- my $retval = $self->extractToFileHandle($fh);
- my ( $outRef, undef ) = $self->readChunk(100);
-}
-
-sub isSymbolicLink {
- my $self = shift;
- if ( $self->{'externalFileAttributes'} == 0xA1FF0000 ) {
- $self->{'isSymbolicLink'} = 1;
- } else {
- return 0;
- }
- 1;
-}
-
-sub isDirectory {
- return 0;
-}
-
-sub externalFileName {
- return undef;
-}
-
-# The following are used when copying data
-sub _writeOffset {
- shift->{'writeOffset'};
-}
-
-sub _readOffset {
- shift->{'readOffset'};
-}
-
-sub writeLocalHeaderRelativeOffset {
- shift->{'writeLocalHeaderRelativeOffset'};
-}
-
-sub wasWritten { shift->{'wasWritten'} }
-
-sub _dataEnded {
- shift->{'dataEnded'};
-}
-
-sub _readDataRemaining {
- shift->{'readDataRemaining'};
-}
-
-sub _inflater {
- shift->{'inflater'};
-}
-
-sub _deflater {
- shift->{'deflater'};
-}
-
-# Return the total size of my local header
-sub _localHeaderSize {
- my $self = shift;
- return SIGNATURE_LENGTH + LOCAL_FILE_HEADER_LENGTH +
- length( $self->fileName() ) + length( $self->localExtraField() );
-}
-
-# Return the total size of my CD header
-sub _centralDirectoryHeaderSize {
- my $self = shift;
- return SIGNATURE_LENGTH + CENTRAL_DIRECTORY_FILE_HEADER_LENGTH +
- length( $self->fileName() ) + length( $self->cdExtraField() ) +
- length( $self->fileComment() );
-}
-
-# DOS date/time format
-# 0-4 (5) Second divided by 2
-# 5-10 (6) Minute (0-59)
-# 11-15 (5) Hour (0-23 on a 24-hour clock)
-# 16-20 (5) Day of the month (1-31)
-# 21-24 (4) Month (1 = January, 2 = February, etc.)
-# 25-31 (7) Year offset from 1980 (add 1980 to get actual year)
-
-# Convert DOS date/time format to unix time_t format
-# NOT AN OBJECT METHOD!
-sub _dosToUnixTime {
- my $dt = shift;
- return time() unless defined($dt);
-
- my $year = ( ( $dt >> 25 ) & 0x7f ) + 80;
- my $mon = ( ( $dt >> 21 ) & 0x0f ) - 1;
- my $mday = ( ( $dt >> 16 ) & 0x1f );
-
- my $hour = ( ( $dt >> 11 ) & 0x1f );
- my $min = ( ( $dt >> 5 ) & 0x3f );
- my $sec = ( ( $dt << 1 ) & 0x3e );
-
- # catch errors
- my $time_t =
- eval { Time::Local::timelocal( $sec, $min, $hour, $mday, $mon, $year ); };
- return time() if ($@);
- return $time_t;
-}
-
-# Note, this isn't exactly UTC 1980, it's 1980 + 12 hours and 1
-# minute so that nothing timezoney can muck us up.
-my $safe_epoch = 315576060;
-
-# convert a unix time to DOS date/time
-# NOT AN OBJECT METHOD!
-sub _unixToDosTime {
- my $time_t = shift;
- unless ($time_t) {
- _error("Tried to add member with zero or undef value for time");
- $time_t = $safe_epoch;
- }
- if ( $time_t < $safe_epoch ) {
- _ioError("Unsupported date before 1980 encountered, moving to 1980");
- $time_t = $safe_epoch;
- }
- my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime($time_t);
- my $dt = 0;
- $dt += ( $sec >> 1 );
- $dt += ( $min << 5 );
- $dt += ( $hour << 11 );
- $dt += ( $mday << 16 );
- $dt += ( ( $mon + 1 ) << 21 );
- $dt += ( ( $year - 80 ) << 25 );
- return $dt;
-}
-
-# Write my local header to a file handle.
-# Stores the offset to the start of the header in my
-# writeLocalHeaderRelativeOffset member.
-# Returns AZ_OK on success.
-sub _writeLocalFileHeader {
- my $self = shift;
- my $fh = shift;
-
- my $signatureData = pack( SIGNATURE_FORMAT, LOCAL_FILE_HEADER_SIGNATURE );
- $self->_print($fh, $signatureData)
- or return _ioError("writing local header signature");
-
- my $header = pack(
- LOCAL_FILE_HEADER_FORMAT,
- $self->versionNeededToExtract(),
- $self->bitFlag(),
- $self->desiredCompressionMethod(),
- $self->lastModFileDateTime(),
- $self->crc32(),
- $self->compressedSize(), # may need to be re-written later
- $self->uncompressedSize(),
- length( $self->fileName() ),
- length( $self->localExtraField() )
- );
-
- $self->_print($fh, $header) or return _ioError("writing local header");
-
- # Check for a valid filename or a filename equal to a literal `0'
- if ( $self->fileName() || $self->fileName eq '0' ) {
- $self->_print($fh, $self->fileName() )
- or return _ioError("writing local header filename");
- }
- if ( $self->localExtraField() ) {
- $self->_print($fh, $self->localExtraField() )
- or return _ioError("writing local extra field");
- }
-
- return AZ_OK;
-}
-
-sub _writeCentralDirectoryFileHeader {
- my $self = shift;
- my $fh = shift;
-
- my $sigData =
- pack( SIGNATURE_FORMAT, CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE );
- $self->_print($fh, $sigData)
- or return _ioError("writing central directory header signature");
-
- my $fileNameLength = length( $self->fileName() );
- my $extraFieldLength = length( $self->cdExtraField() );
- my $fileCommentLength = length( $self->fileComment() );
-
- my $header = pack(
- CENTRAL_DIRECTORY_FILE_HEADER_FORMAT,
- $self->versionMadeBy(),
- $self->fileAttributeFormat(),
- $self->versionNeededToExtract(),
- $self->bitFlag(),
- $self->desiredCompressionMethod(),
- $self->lastModFileDateTime(),
- $self->crc32(), # these three fields should have been updated
- $self->_writeOffset(), # by writing the data stream out
- $self->uncompressedSize(), #
- $fileNameLength,
- $extraFieldLength,
- $fileCommentLength,
- 0, # {'diskNumberStart'},
- $self->internalFileAttributes(),
- $self->externalFileAttributes(),
- $self->writeLocalHeaderRelativeOffset()
- );
-
- $self->_print($fh, $header)
- or return _ioError("writing central directory header");
- if ($fileNameLength) {
- $self->_print($fh, $self->fileName() )
- or return _ioError("writing central directory header signature");
- }
- if ($extraFieldLength) {
- $self->_print($fh, $self->cdExtraField() )
- or return _ioError("writing central directory extra field");
- }
- if ($fileCommentLength) {
- $self->_print($fh, $self->fileComment() )
- or return _ioError("writing central directory file comment");
- }
-
- return AZ_OK;
-}
-
-# This writes a data descriptor to the given file handle.
-# Assumes that crc32, writeOffset, and uncompressedSize are
-# set correctly (they should be after a write).
-# Further, the local file header should have the
-# GPBF_HAS_DATA_DESCRIPTOR_MASK bit set.
-sub _writeDataDescriptor {
- my $self = shift;
- my $fh = shift;
- my $header = pack(
- SIGNATURE_FORMAT . DATA_DESCRIPTOR_FORMAT,
- DATA_DESCRIPTOR_SIGNATURE,
- $self->crc32(),
- $self->_writeOffset(), # compressed size
- $self->uncompressedSize()
- );
-
- $self->_print($fh, $header)
- or return _ioError("writing data descriptor");
- return AZ_OK;
-}
-
-# Re-writes the local file header with new crc32 and compressedSize fields.
-# To be called after writing the data stream.
-# Assumes that filename and extraField sizes didn't change since last written.
-sub _refreshLocalFileHeader {
- my $self = shift;
- my $fh = shift;
-
- my $here = $fh->tell();
- $fh->seek( $self->writeLocalHeaderRelativeOffset() + SIGNATURE_LENGTH,
- IO::Seekable::SEEK_SET )
- or return _ioError("seeking to rewrite local header");
-
- my $header = pack(
- LOCAL_FILE_HEADER_FORMAT,
- $self->versionNeededToExtract(),
- $self->bitFlag(),
- $self->desiredCompressionMethod(),
- $self->lastModFileDateTime(),
- $self->crc32(),
- $self->_writeOffset(), # compressed size
- $self->uncompressedSize(),
- length( $self->fileName() ),
- length( $self->localExtraField() )
- );
-
- $self->_print($fh, $header)
- or return _ioError("re-writing local header");
- $fh->seek( $here, IO::Seekable::SEEK_SET )
- or return _ioError("seeking after rewrite of local header");
-
- return AZ_OK;
-}
-
-sub readChunk {
- my $self = shift;
- my $chunkSize = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{chunkSize} : $_[0];
-
- if ( $self->readIsDone() ) {
- $self->endRead();
- my $dummy = '';
- return ( \$dummy, AZ_STREAM_END );
- }
-
- $chunkSize = $Archive::Zip::ChunkSize if not defined($chunkSize);
- $chunkSize = $self->_readDataRemaining()
- if $chunkSize > $self->_readDataRemaining();
-
- my $buffer = '';
- my $outputRef;
- my ( $bytesRead, $status ) = $self->_readRawChunk( \$buffer, $chunkSize );
- return ( \$buffer, $status ) unless $status == AZ_OK;
-
- $self->{'readDataRemaining'} -= $bytesRead;
- $self->{'readOffset'} += $bytesRead;
-
- if ( $self->compressionMethod() == COMPRESSION_STORED ) {
- $self->{'crc32'} = $self->computeCRC32( $buffer, $self->{'crc32'} );
- }
-
- ( $outputRef, $status ) = &{ $self->{'chunkHandler'} }( $self, \$buffer );
- $self->{'writeOffset'} += length($$outputRef);
-
- $self->endRead()
- if $self->readIsDone();
-
- return ( $outputRef, $status );
-}
-
-# Read the next raw chunk of my data. Subclasses MUST implement.
-# my ( $bytesRead, $status) = $self->_readRawChunk( \$buffer, $chunkSize );
-sub _readRawChunk {
- my $self = shift;
- return $self->_subclassResponsibility();
-}
-
-# A place holder to catch rewindData errors if someone ignores
-# the error code.
-sub _noChunk {
- my $self = shift;
- return ( \undef, _error("trying to copy chunk when init failed") );
-}
-
-# Basically a no-op so that I can have a consistent interface.
-# ( $outputRef, $status) = $self->_copyChunk( \$buffer );
-sub _copyChunk {
- my ( $self, $dataRef ) = @_;
- return ( $dataRef, AZ_OK );
-}
-
-# ( $outputRef, $status) = $self->_deflateChunk( \$buffer );
-sub _deflateChunk {
- my ( $self, $buffer ) = @_;
- my ( $status ) = $self->_deflater()->deflate( $buffer, my $out );
-
- if ( $self->_readDataRemaining() == 0 ) {
- my $extraOutput;
- ( $status ) = $self->_deflater()->flush($extraOutput);
- $out .= $extraOutput;
- $self->endRead();
- return ( \$out, AZ_STREAM_END );
- }
- elsif ( $status == Z_OK ) {
- return ( \$out, AZ_OK );
- }
- else {
- $self->endRead();
- my $retval = _error( 'deflate error', $status );
- my $dummy = '';
- return ( \$dummy, $retval );
- }
-}
-
-# ( $outputRef, $status) = $self->_inflateChunk( \$buffer );
-sub _inflateChunk {
- my ( $self, $buffer ) = @_;
- my ( $status ) = $self->_inflater()->inflate( $buffer, my $out );
- my $retval;
- $self->endRead() unless $status == Z_OK;
- if ( $status == Z_OK || $status == Z_STREAM_END ) {
- $retval = ( $status == Z_STREAM_END ) ? AZ_STREAM_END: AZ_OK;
- return ( \$out, $retval );
- }
- else {
- $retval = _error( 'inflate error', $status );
- my $dummy = '';
- return ( \$dummy, $retval );
- }
-}
-
-sub rewindData {
- my $self = shift;
- my $status;
-
- # set to trap init errors
- $self->{'chunkHandler'} = $self->can('_noChunk');
-
- # Work around WinZip bug with 0-length DEFLATED files
- $self->desiredCompressionMethod(COMPRESSION_STORED)
- if $self->uncompressedSize() == 0;
-
- # assume that we're going to read the whole file, and compute the CRC anew.
- $self->{'crc32'} = 0
- if ( $self->compressionMethod() == COMPRESSION_STORED );
-
- # These are the only combinations of methods we deal with right now.
- if ( $self->compressionMethod() == COMPRESSION_STORED
- and $self->desiredCompressionMethod() == COMPRESSION_DEFLATED )
- {
- ( $self->{'deflater'}, $status ) = Compress::Raw::Zlib::Deflate->new(
- '-Level' => $self->desiredCompressionLevel(),
- '-WindowBits' => -MAX_WBITS(), # necessary magic
- '-Bufsize' => $Archive::Zip::ChunkSize,
- @_
- ); # pass additional options
- return _error( 'deflateInit error:', $status )
- unless $status == Z_OK;
- $self->{'chunkHandler'} = $self->can('_deflateChunk');
- }
- elsif ( $self->compressionMethod() == COMPRESSION_DEFLATED
- and $self->desiredCompressionMethod() == COMPRESSION_STORED )
- {
- ( $self->{'inflater'}, $status ) = Compress::Raw::Zlib::Inflate->new(
- '-WindowBits' => -MAX_WBITS(), # necessary magic
- '-Bufsize' => $Archive::Zip::ChunkSize,
- @_
- ); # pass additional options
- return _error( 'inflateInit error:', $status )
- unless $status == Z_OK;
- $self->{'chunkHandler'} = $self->can('_inflateChunk');
- }
- elsif ( $self->compressionMethod() == $self->desiredCompressionMethod() ) {
- $self->{'chunkHandler'} = $self->can('_copyChunk');
- }
- else {
- return _error(
- sprintf(
- "Unsupported compression combination: read %d, write %d",
- $self->compressionMethod(),
- $self->desiredCompressionMethod()
- )
- );
- }
-
- $self->{'readDataRemaining'} =
- ( $self->compressionMethod() == COMPRESSION_STORED )
- ? $self->uncompressedSize()
- : $self->compressedSize();
- $self->{'dataEnded'} = 0;
- $self->{'readOffset'} = 0;
-
- return AZ_OK;
-}
-
-sub endRead {
- my $self = shift;
- delete $self->{'inflater'};
- delete $self->{'deflater'};
- $self->{'dataEnded'} = 1;
- $self->{'readDataRemaining'} = 0;
- return AZ_OK;
-}
-
-sub readIsDone {
- my $self = shift;
- return ( $self->_dataEnded() or !$self->_readDataRemaining() );
-}
-
-sub contents {
- my $self = shift;
- my $newContents = shift;
-
- if ( defined($newContents) ) {
-
- # change our type and call the subclass contents method.
- $self->_become(STRINGMEMBERCLASS);
- return $self->contents( pack( 'C0a*', $newContents ) )
- ; # in case of Unicode
- }
- else {
- my $oldCompression =
- $self->desiredCompressionMethod(COMPRESSION_STORED);
- my $status = $self->rewindData(@_);
- if ( $status != AZ_OK ) {
- $self->endRead();
- return $status;
- }
- my $retval = '';
- while ( $status == AZ_OK ) {
- my $ref;
- ( $ref, $status ) = $self->readChunk( $self->_readDataRemaining() );
-
- # did we get it in one chunk?
- if ( length($$ref) == $self->uncompressedSize() ) {
- $retval = $$ref;
- }
- else { $retval .= $$ref }
- }
- $self->desiredCompressionMethod($oldCompression);
- $self->endRead();
- $status = AZ_OK if $status == AZ_STREAM_END;
- $retval = undef unless $status == AZ_OK;
- return wantarray ? ( $retval, $status ) : $retval;
- }
-}
-
-sub extractToFileHandle {
- my $self = shift;
- return _error("encryption unsupported") if $self->isEncrypted();
- my $fh = ( ref( $_[0] ) eq 'HASH' ) ? shift->{fileHandle} : shift;
- _binmode($fh);
- my $oldCompression = $self->desiredCompressionMethod(COMPRESSION_STORED);
- my $status = $self->rewindData(@_);
- $status = $self->_writeData($fh) if $status == AZ_OK;
- $self->desiredCompressionMethod($oldCompression);
- $self->endRead();
- return $status;
-}
-
-# write local header and data stream to file handle
-sub _writeToFileHandle {
- my $self = shift;
- my $fh = shift;
- my $fhIsSeekable = shift;
- my $offset = shift;
-
- return _error("no member name given for $self")
- if $self->fileName() eq '';
-
- $self->{'writeLocalHeaderRelativeOffset'} = $offset;
- $self->{'wasWritten'} = 0;
-
- # Determine if I need to write a data descriptor
- # I need to do this if I can't refresh the header
- # and I don't know compressed size or crc32 fields.
- my $headerFieldsUnknown = (
- ( $self->uncompressedSize() > 0 )
- and ($self->compressionMethod() == COMPRESSION_STORED
- or $self->desiredCompressionMethod() == COMPRESSION_DEFLATED )
- );
-
- my $shouldWriteDataDescriptor =
- ( $headerFieldsUnknown and not $fhIsSeekable );
-
- $self->hasDataDescriptor(1)
- if ($shouldWriteDataDescriptor);
-
- $self->{'writeOffset'} = 0;
-
- my $status = $self->rewindData();
- ( $status = $self->_writeLocalFileHeader($fh) )
- if $status == AZ_OK;
- ( $status = $self->_writeData($fh) )
- if $status == AZ_OK;
- if ( $status == AZ_OK ) {
- $self->{'wasWritten'} = 1;
- if ( $self->hasDataDescriptor() ) {
- $status = $self->_writeDataDescriptor($fh);
- }
- elsif ($headerFieldsUnknown) {
- $status = $self->_refreshLocalFileHeader($fh);
- }
- }
-
- return $status;
-}
-
-# Copy my (possibly compressed) data to given file handle.
-# Returns C<AZ_OK> on success
-sub _writeData {
- my $self = shift;
- my $writeFh = shift;
-
- # If symbolic link, just create one if the operating system is Linux, Unix, BSD or VMS
- # TODO: Add checks for other operating systems
- if ( $self->{'isSymbolicLink'} == 1 && $^O eq 'linux' ) {
- my $chunkSize = $Archive::Zip::ChunkSize;
- my ( $outRef, $status ) = $self->readChunk($chunkSize);
- symlink $$outRef, $self->{'newName'};
- } else {
- return AZ_OK if ( $self->uncompressedSize() == 0 );
- my $status;
- my $chunkSize = $Archive::Zip::ChunkSize;
- while ( $self->_readDataRemaining() > 0 ) {
- my $outRef;
- ( $outRef, $status ) = $self->readChunk($chunkSize);
- return $status if ( $status != AZ_OK and $status != AZ_STREAM_END );
-
- if ( length($$outRef) > 0 ) {
- $self->_print($writeFh, $$outRef)
- or return _ioError("write error during copy");
- }
-
- last if $status == AZ_STREAM_END;
- }
- $self->{'compressedSize'} = $self->_writeOffset();
- }
- return AZ_OK;
-}
-
-# Return true if I depend on the named file
-sub _usesFileNamed {
- return 0;
-}
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/MemberRead.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/MemberRead.pm
deleted file mode 100755
index a27bfdc45f0..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/MemberRead.pm
+++ /dev/null
@@ -1,333 +0,0 @@
-package Archive::Zip::MemberRead;
-
-=head1 NAME
-
-Archive::Zip::MemberRead - A wrapper that lets you read Zip archive members as if they were files.
-
-=cut
-
-=head1 SYNOPSIS
-
- use Archive::Zip;
- use Archive::Zip::MemberRead;
- $zip = Archive::Zip->new("file.zip");
- $fh = Archive::Zip::MemberRead->new($zip, "subdir/abc.txt");
- while (defined($line = $fh->getline()))
- {
- print $fh->input_line_number . "#: $line\n";
- }
-
- $read = $fh->read($buffer, 32*1024);
- print "Read $read bytes as :$buffer:\n";
-
-=head1 DESCRIPTION
-
-The Archive::Zip::MemberRead module lets you read Zip archive member data
-just like you read data from files.
-
-=head1 METHODS
-
-=over 4
-
-=cut
-
-use strict;
-
-use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
-
-use vars qw{$VERSION};
-
-my $nl;
-
-BEGIN {
- $VERSION = '1.30';
- $VERSION = eval $VERSION;
- # Requirement for newline conversion. Should check for e.g., DOS and OS/2 as well, but am too lazy.
- $nl = $^O eq 'MSWin32' ? "\r\n" : "\n";
-}
-
-=item Archive::Zip::Member::readFileHandle()
-
-You can get a C<Archive::Zip::MemberRead> from an archive member by
-calling C<readFileHandle()>:
-
- my $member = $zip->memberNamed('abc/def.c');
- my $fh = $member->readFileHandle();
- while (defined($line = $fh->getline()))
- {
- # ...
- }
- $fh->close();
-
-=cut
-
-sub Archive::Zip::Member::readFileHandle {
- return Archive::Zip::MemberRead->new( shift() );
-}
-
-=item Archive::Zip::MemberRead->new($zip, $fileName)
-
-=item Archive::Zip::MemberRead->new($zip, $member)
-
-=item Archive::Zip::MemberRead->new($member)
-
-Construct a new Archive::Zip::MemberRead on the specified member.
-
- my $fh = Archive::Zip::MemberRead->new($zip, 'fred.c')
-
-=cut
-
-sub new {
- my ( $class, $zip, $file ) = @_;
- my ( $self, $member );
-
- if ( $zip && $file ) # zip and filename, or zip and member
- {
- $member = ref($file) ? $file : $zip->memberNamed($file);
- }
- elsif ( $zip && !$file && ref($zip) ) # just member
- {
- $member = $zip;
- }
- else {
- die(
-'Archive::Zip::MemberRead::new needs a zip and filename, zip and member, or member'
- );
- }
-
- $self = {};
- bless( $self, $class );
- $self->set_member($member);
- return $self;
-}
-
-sub set_member {
- my ( $self, $member ) = @_;
-
- $self->{member} = $member;
- $self->set_compression(COMPRESSION_STORED);
- $self->rewind();
-}
-
-sub set_compression {
- my ( $self, $compression ) = @_;
- $self->{member}->desiredCompressionMethod($compression) if $self->{member};
-}
-
-=item setLineEnd(expr)
-
-Set the line end character to use. This is set to \n by default
-except on Windows systems where it is set to \r\n. You will
-only need to set this on systems which are not Windows or Unix
-based and require a line end diffrent from \n.
-This is a class method so call as C<Archive::Zip::MemberRead>->C<setLineEnd($nl)>
-
-=cut
-
-sub setLineEnd {
- shift;
- $nl = shift;
-}
-
-=item rewind()
-
-Rewinds an C<Archive::Zip::MemberRead> so that you can read from it again
-starting at the beginning.
-
-=cut
-
-sub rewind {
- my $self = shift;
-
- $self->_reset_vars();
- $self->{member}->rewindData() if $self->{member};
-}
-
-sub _reset_vars {
- my $self = shift;
-
- $self->{line_no} = 0;
- $self->{at_end} = 0;
-
- delete $self->{buffer};
-}
-
-=item input_record_separator(expr)
-
-If the argumnet is given, input_record_separator for this
-instance is set to it. The current setting (which may be
-the global $/) is always returned.
-
-=cut
-
-sub input_record_separator {
- my $self = shift;
- if (@_) {
- $self->{sep} = shift;
- $self->{sep_re} = _sep_as_re($self->{sep}); # Cache the RE as an optimization
- }
- return exists $self->{sep} ? $self->{sep} : $/;
-}
-
-# Return the input_record_separator in use as an RE fragment
-# Note that if we have a per-instance input_record_separator
-# we can just return the already converted value. Otherwise,
-# the conversion must be done on $/ every time since we cannot
-# know whether it has changed or not.
-sub _sep_re {
- my $self = shift;
- # Important to phrase this way: sep's value may be undef.
- return exists $self->{sep} ? $self->{sep_re} : _sep_as_re($/);
-}
-
-# Convert the input record separator into an RE and return it.
-sub _sep_as_re {
- my $sep = shift;
- if (defined $sep) {
- if ($sep eq '') {
- return "(?:$nl){2,}";
- } else {
- $sep =~ s/\n/$nl/og;
- return quotemeta $sep;
- }
- } else {
- return undef;
- }
-}
-
-=item input_line_number()
-
-Returns the current line number, but only if you're using C<getline()>.
-Using C<read()> will not update the line number.
-
-=cut
-
-sub input_line_number {
- my $self = shift;
- return $self->{line_no};
-}
-
-=item close()
-
-Closes the given file handle.
-
-=cut
-
-sub close {
- my $self = shift;
-
- $self->_reset_vars();
- $self->{member}->endRead();
-}
-
-=item buffer_size([ $size ])
-
-Gets or sets the buffer size used for reads.
-Default is the chunk size used by Archive::Zip.
-
-=cut
-
-sub buffer_size {
- my ( $self, $size ) = @_;
-
- if ( !$size ) {
- return $self->{chunkSize} || Archive::Zip::chunkSize();
- }
- else {
- $self->{chunkSize} = $size;
- }
-}
-
-=item getline()
-
-Returns the next line from the currently open member.
-Makes sense only for text files.
-A read error is considered fatal enough to die.
-Returns undef on eof. All subsequent calls would return undef,
-unless a rewind() is called.
-Note: The line returned has the input_record_separator (default: newline) removed.
-
-=cut
-
-sub getline {
- my $self = shift;
- my $size = $self->buffer_size();
- my $sep = $self->_sep_re();
-
- for (;;) {
- if ( $sep
- && defined($self->{buffer})
- && $self->{buffer} =~ s/^(.*?)$sep//s
- ) {
- $self->{line_no}++;
- return $1;
- } elsif ($self->{at_end}) {
- $self->{line_no}++ if $self->{buffer};
- return delete $self->{buffer};
- }
- my ($temp,$status) = $self->{member}->readChunk($size);
- if ($status != AZ_OK && $status != AZ_STREAM_END) {
- die "ERROR: Error reading chunk from archive - $status";
- }
- $self->{at_end} = $status == AZ_STREAM_END;
- $self->{buffer} .= $$temp;
- }
-}
-
-=item read($buffer, $num_bytes_to_read)
-
-Simulates a normal C<read()> system call.
-Returns the no. of bytes read. C<undef> on error, 0 on eof, I<e.g.>:
-
- $fh = Archive::Zip::MemberRead->new($zip, "sreeji/secrets.bin");
- while (1)
- {
- $read = $fh->read($buffer, 1024);
- die "FATAL ERROR reading my secrets !\n" if (!defined($read));
- last if (!$read);
- # Do processing.
- ....
- }
-
-=cut
-
-#
-# All these $_ are required to emulate read().
-#
-sub read {
- my $self = $_[0];
- my $size = $_[2];
- my ( $temp, $status, $ret );
-
- ( $temp, $status ) = $self->{member}->readChunk($size);
- if ( $status != AZ_OK && $status != AZ_STREAM_END ) {
- $_[1] = undef;
- $ret = undef;
- }
- else {
- $_[1] = $$temp;
- $ret = length($$temp);
- }
- return $ret;
-}
-
-1;
-
-=back
-
-=head1 AUTHOR
-
-Sreeji K. Das, <sreeji_k@yahoo.com>
-See L<Archive::Zip> by Ned Konz without which this module does not make
-any sense!
-
-Minor mods by Ned Konz.
-
-=head1 COPYRIGHT
-
-Copyright 2002 Sreeji K. Das.
-
-This program is free software; you can redistribute it and/or modify it under
-the same terms as Perl itself.
-
-=cut
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/MockFileHandle.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/MockFileHandle.pm
deleted file mode 100755
index bceb181ae13..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/MockFileHandle.pm
+++ /dev/null
@@ -1,69 +0,0 @@
-package Archive::Zip::MockFileHandle;
-
-# Output file handle that calls a custom write routine
-# Ned Konz, March 2000
-# This is provided to help with writing zip files
-# when you have to process them a chunk at a time.
-
-use strict;
-
-use vars qw{$VERSION};
-
-BEGIN {
- $VERSION = '1.30';
- $VERSION = eval $VERSION;
-}
-
-sub new {
- my $class = shift || __PACKAGE__;
- $class = ref($class) || $class;
- my $self = bless(
- {
- 'position' => 0,
- 'size' => 0
- },
- $class
- );
- return $self;
-}
-
-sub eof {
- my $self = shift;
- return $self->{'position'} >= $self->{'size'};
-}
-
-# Copy given buffer to me
-sub print {
- my $self = shift;
- my $bytes = join( '', @_ );
- my $bytesWritten = $self->writeHook($bytes);
- if ( $self->{'position'} + $bytesWritten > $self->{'size'} ) {
- $self->{'size'} = $self->{'position'} + $bytesWritten;
- }
- $self->{'position'} += $bytesWritten;
- return $bytesWritten;
-}
-
-# Called on each write.
-# Override in subclasses.
-# Return number of bytes written (0 on error).
-sub writeHook {
- my $self = shift;
- my $bytes = shift;
- return length($bytes);
-}
-
-sub binmode { 1 }
-
-sub close { 1 }
-
-sub clearerr { 1 }
-
-# I'm write-only!
-sub read { 0 }
-
-sub tell { return shift->{'position'} }
-
-sub opened { 1 }
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/NewFileMember.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/NewFileMember.pm
deleted file mode 100755
index 79178082151..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/NewFileMember.pm
+++ /dev/null
@@ -1,79 +0,0 @@
-package Archive::Zip::NewFileMember;
-
-use strict;
-use vars qw( $VERSION @ISA );
-
-BEGIN {
- $VERSION = '1.30';
- @ISA = qw ( Archive::Zip::FileMember );
-}
-
-use Archive::Zip qw(
- :CONSTANTS
- :ERROR_CODES
- :UTILITY_METHODS
-);
-
-# Given a file name, set up for eventual writing.
-sub _newFromFileNamed {
- my $class = shift;
- my $fileName = shift; # local FS format
- my $newName = shift;
- $newName = _asZipDirName($fileName) unless defined($newName);
- return undef unless ( stat($fileName) && -r _ && !-d _ );
- my $self = $class->new(@_);
- $self->{'fileName'} = $newName;
- $self->{'externalFileName'} = $fileName;
- $self->{'compressionMethod'} = COMPRESSION_STORED;
- my @stat = stat(_);
- $self->{'compressedSize'} = $self->{'uncompressedSize'} = $stat[7];
- $self->desiredCompressionMethod(
- ( $self->compressedSize() > 0 )
- ? COMPRESSION_DEFLATED
- : COMPRESSION_STORED
- );
- $self->unixFileAttributes( $stat[2] );
- $self->setLastModFileDateTimeFromUnix( $stat[9] );
- $self->isTextFile( -T _ );
- return $self;
-}
-
-sub rewindData {
- my $self = shift;
-
- my $status = $self->SUPER::rewindData(@_);
- return $status unless $status == AZ_OK;
-
- return AZ_IO_ERROR unless $self->fh();
- $self->fh()->clearerr();
- $self->fh()->seek( 0, IO::Seekable::SEEK_SET )
- or return _ioError( "rewinding", $self->externalFileName() );
- return AZ_OK;
-}
-
-# Return bytes read. Note that first parameter is a ref to a buffer.
-# my $data;
-# my ( $bytesRead, $status) = $self->readRawChunk( \$data, $chunkSize );
-sub _readRawChunk {
- my ( $self, $dataRef, $chunkSize ) = @_;
- return ( 0, AZ_OK ) unless $chunkSize;
- my $bytesRead = $self->fh()->read( $$dataRef, $chunkSize )
- or return ( 0, _ioError("reading data") );
- return ( $bytesRead, AZ_OK );
-}
-
-# If I already exist, extraction is a no-op.
-sub extractToFileNamed {
- my $self = shift;
- my $name = shift; # local FS name
- if ( File::Spec->rel2abs($name) eq
- File::Spec->rel2abs( $self->externalFileName() ) and -r $name )
- {
- return AZ_OK;
- }
- else {
- return $self->SUPER::extractToFileNamed( $name, @_ );
- }
-}
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/StringMember.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/StringMember.pm
deleted file mode 100755
index fe6760849ac..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/StringMember.pm
+++ /dev/null
@@ -1,64 +0,0 @@
-package Archive::Zip::StringMember;
-
-use strict;
-use vars qw( $VERSION @ISA );
-
-BEGIN {
- $VERSION = '1.30';
- @ISA = qw( Archive::Zip::Member );
-}
-
-use Archive::Zip qw(
- :CONSTANTS
- :ERROR_CODES
-);
-
-# Create a new string member. Default is COMPRESSION_STORED.
-# Can take a ref to a string as well.
-sub _newFromString {
- my $class = shift;
- my $string = shift;
- my $name = shift;
- my $self = $class->new(@_);
- $self->contents($string);
- $self->fileName($name) if defined($name);
-
- # Set the file date to now
- $self->setLastModFileDateTimeFromUnix( time() );
- $self->unixFileAttributes( $self->DEFAULT_FILE_PERMISSIONS );
- return $self;
-}
-
-sub _become {
- my $self = shift;
- my $newClass = shift;
- return $self if ref($self) eq $newClass;
- delete( $self->{'contents'} );
- return $self->SUPER::_become($newClass);
-}
-
-# Get or set my contents. Note that we do not call the superclass
-# version of this, because it calls us.
-sub contents {
- my $self = shift;
- my $string = shift;
- if ( defined($string) ) {
- $self->{'contents'} =
- pack( 'C0a*', ( ref($string) eq 'SCALAR' ) ? $$string : $string );
- $self->{'uncompressedSize'} = $self->{'compressedSize'} =
- length( $self->{'contents'} );
- $self->{'compressionMethod'} = COMPRESSION_STORED;
- }
- return $self->{'contents'};
-}
-
-# Return bytes read. Note that first parameter is a ref to a buffer.
-# my $data;
-# my ( $bytesRead, $status) = $self->readRawChunk( \$data, $chunkSize );
-sub _readRawChunk {
- my ( $self, $dataRef, $chunkSize ) = @_;
- $$dataRef = substr( $self->contents(), $self->_readOffset(), $chunkSize );
- return ( length($$dataRef), AZ_OK );
-}
-
-1;
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/Tree.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/Tree.pm
deleted file mode 100755
index fb8bc0b3c7e..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/Tree.pm
+++ /dev/null
@@ -1,49 +0,0 @@
-package Archive::Zip::Tree;
-
-use strict;
-use vars qw{$VERSION};
-BEGIN {
- $VERSION = '1.30';
-}
-
-use Archive::Zip;
-
-warn(
-"Archive::Zip::Tree is deprecated; its methods have been moved into Archive::Zip."
-) if $^W;
-
-1;
-
-__END__
-
-=head1 NAME
-
-Archive::Zip::Tree - (DEPRECATED) methods for adding/extracting trees using Archive::Zip
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-This module is deprecated, because all its methods were moved into the main
-Archive::Zip module.
-
-It is included in the distribution merely to avoid breaking old code.
-
-See L<Archive::Zip>.
-
-=head1 AUTHOR
-
-Ned Konz, perl@bike-nomad.com
-
-=head1 COPYRIGHT
-
-Copyright (c) 2000-2002 Ned Konz. All rights reserved. This program is free
-software; you can redistribute it and/or modify it under the same terms
-as Perl itself.
-
-=head1 SEE ALSO
-
-L<Archive::Zip>
-
-=cut
-
diff --git a/Master/tlpkg/tlperl/lib/Archive/Zip/ZipFileMember.pm b/Master/tlpkg/tlperl/lib/Archive/Zip/ZipFileMember.pm
deleted file mode 100755
index cc606697b15..00000000000
--- a/Master/tlpkg/tlperl/lib/Archive/Zip/ZipFileMember.pm
+++ /dev/null
@@ -1,416 +0,0 @@
-package Archive::Zip::ZipFileMember;
-
-use strict;
-use vars qw( $VERSION @ISA );
-
-BEGIN {
- $VERSION = '1.30';
- @ISA = qw ( Archive::Zip::FileMember );
-}
-
-use Archive::Zip qw(
- :CONSTANTS
- :ERROR_CODES
- :PKZIP_CONSTANTS
- :UTILITY_METHODS
-);
-
-# Create a new Archive::Zip::ZipFileMember
-# given a filename and optional open file handle
-#
-sub _newFromZipFile {
- my $class = shift;
- my $fh = shift;
- my $externalFileName = shift;
- my $possibleEocdOffset = shift; # normally 0
-
- my $self = $class->new(
- 'crc32' => 0,
- 'diskNumberStart' => 0,
- 'localHeaderRelativeOffset' => 0,
- 'dataOffset' => 0, # localHeaderRelativeOffset + header length
- @_
- );
- $self->{'externalFileName'} = $externalFileName;
- $self->{'fh'} = $fh;
- $self->{'possibleEocdOffset'} = $possibleEocdOffset;
- return $self;
-}
-
-sub isDirectory {
- my $self = shift;
- return (
- substr( $self->fileName, -1, 1 ) eq '/'
- and
- $self->uncompressedSize == 0
- );
-}
-
-# Seek to the beginning of the local header, just past the signature.
-# Verify that the local header signature is in fact correct.
-# Update the localHeaderRelativeOffset if necessary by adding the possibleEocdOffset.
-# Returns status.
-
-sub _seekToLocalHeader {
- my $self = shift;
- my $where = shift; # optional
- my $previousWhere = shift; # optional
-
- $where = $self->localHeaderRelativeOffset() unless defined($where);
-
- # avoid loop on certain corrupt files (from Julian Field)
- return _formatError("corrupt zip file")
- if defined($previousWhere) && $where == $previousWhere;
-
- my $status;
- my $signature;
-
- $status = $self->fh()->seek( $where, IO::Seekable::SEEK_SET );
- return _ioError("seeking to local header") unless $status;
-
- ( $status, $signature ) =
- _readSignature( $self->fh(), $self->externalFileName(),
- LOCAL_FILE_HEADER_SIGNATURE );
- return $status if $status == AZ_IO_ERROR;
-
- # retry with EOCD offset if any was given.
- if ( $status == AZ_FORMAT_ERROR && $self->{'possibleEocdOffset'} ) {
- $status = $self->_seekToLocalHeader(
- $self->localHeaderRelativeOffset() + $self->{'possibleEocdOffset'},
- $where
- );
- if ( $status == AZ_OK ) {
- $self->{'localHeaderRelativeOffset'} +=
- $self->{'possibleEocdOffset'};
- $self->{'possibleEocdOffset'} = 0;
- }
- }
-
- return $status;
-}
-
-# Because I'm going to delete the file handle, read the local file
-# header if the file handle is seekable. If it isn't, I assume that
-# I've already read the local header.
-# Return ( $status, $self )
-
-sub _become {
- my $self = shift;
- my $newClass = shift;
- return $self if ref($self) eq $newClass;
-
- my $status = AZ_OK;
-
- if ( _isSeekable( $self->fh() ) ) {
- my $here = $self->fh()->tell();
- $status = $self->_seekToLocalHeader();
- $status = $self->_readLocalFileHeader() if $status == AZ_OK;
- $self->fh()->seek( $here, IO::Seekable::SEEK_SET );
- return $status unless $status == AZ_OK;
- }
-
- delete( $self->{'eocdCrc32'} );
- delete( $self->{'diskNumberStart'} );
- delete( $self->{'localHeaderRelativeOffset'} );
- delete( $self->{'dataOffset'} );
-
- return $self->SUPER::_become($newClass);
-}
-
-sub diskNumberStart {
- shift->{'diskNumberStart'};
-}
-
-sub localHeaderRelativeOffset {
- shift->{'localHeaderRelativeOffset'};
-}
-
-sub dataOffset {
- shift->{'dataOffset'};
-}
-
-# Skip local file header, updating only extra field stuff.
-# Assumes that fh is positioned before signature.
-sub _skipLocalFileHeader {
- my $self = shift;
- my $header;
- my $bytesRead = $self->fh()->read( $header, LOCAL_FILE_HEADER_LENGTH );
- if ( $bytesRead != LOCAL_FILE_HEADER_LENGTH ) {
- return _ioError("reading local file header");
- }
- my $fileNameLength;
- my $extraFieldLength;
- my $bitFlag;
- (
- undef, # $self->{'versionNeededToExtract'},
- $bitFlag,
- undef, # $self->{'compressionMethod'},
- undef, # $self->{'lastModFileDateTime'},
- undef, # $crc32,
- undef, # $compressedSize,
- undef, # $uncompressedSize,
- $fileNameLength,
- $extraFieldLength
- ) = unpack( LOCAL_FILE_HEADER_FORMAT, $header );
-
- if ($fileNameLength) {
- $self->fh()->seek( $fileNameLength, IO::Seekable::SEEK_CUR )
- or return _ioError("skipping local file name");
- }
-
- if ($extraFieldLength) {
- $bytesRead =
- $self->fh()->read( $self->{'localExtraField'}, $extraFieldLength );
- if ( $bytesRead != $extraFieldLength ) {
- return _ioError("reading local extra field");
- }
- }
-
- $self->{'dataOffset'} = $self->fh()->tell();
-
- if ( $bitFlag & GPBF_HAS_DATA_DESCRIPTOR_MASK ) {
-
- # Read the crc32, compressedSize, and uncompressedSize from the
- # extended data descriptor, which directly follows the compressed data.
- #
- # Skip over the compressed file data (assumes that EOCD compressedSize
- # was correct)
- $self->fh()->seek( $self->{'compressedSize'}, IO::Seekable::SEEK_CUR )
- or return _ioError("seeking to extended local header");
-
- # these values should be set correctly from before.
- my $oldCrc32 = $self->{'eocdCrc32'};
- my $oldCompressedSize = $self->{'compressedSize'};
- my $oldUncompressedSize = $self->{'uncompressedSize'};
-
- my $status = $self->_readDataDescriptor();
- return $status unless $status == AZ_OK;
-
- return _formatError(
- "CRC or size mismatch while skipping data descriptor")
- if ( $oldCrc32 != $self->{'crc32'}
- || $oldUncompressedSize != $self->{'uncompressedSize'} );
- }
-
- return AZ_OK;
-}
-
-# Read from a local file header into myself. Returns AZ_OK if successful.
-# Assumes that fh is positioned after signature.
-# Note that crc32, compressedSize, and uncompressedSize will be 0 if
-# GPBF_HAS_DATA_DESCRIPTOR_MASK is set in the bitFlag.
-
-sub _readLocalFileHeader {
- my $self = shift;
- my $header;
- my $bytesRead = $self->fh()->read( $header, LOCAL_FILE_HEADER_LENGTH );
- if ( $bytesRead != LOCAL_FILE_HEADER_LENGTH ) {
- return _ioError("reading local file header");
- }
- my $fileNameLength;
- my $crc32;
- my $compressedSize;
- my $uncompressedSize;
- my $extraFieldLength;
- (
- $self->{'versionNeededToExtract'}, $self->{'bitFlag'},
- $self->{'compressionMethod'}, $self->{'lastModFileDateTime'},
- $crc32, $compressedSize,
- $uncompressedSize, $fileNameLength,
- $extraFieldLength
- ) = unpack( LOCAL_FILE_HEADER_FORMAT, $header );
-
- if ($fileNameLength) {
- my $fileName;
- $bytesRead = $self->fh()->read( $fileName, $fileNameLength );
- if ( $bytesRead != $fileNameLength ) {
- return _ioError("reading local file name");
- }
- $self->fileName($fileName);
- }
-
- if ($extraFieldLength) {
- $bytesRead =
- $self->fh()->read( $self->{'localExtraField'}, $extraFieldLength );
- if ( $bytesRead != $extraFieldLength ) {
- return _ioError("reading local extra field");
- }
- }
-
- $self->{'dataOffset'} = $self->fh()->tell();
-
- if ( $self->hasDataDescriptor() ) {
-
- # Read the crc32, compressedSize, and uncompressedSize from the
- # extended data descriptor.
- # Skip over the compressed file data (assumes that EOCD compressedSize
- # was correct)
- $self->fh()->seek( $self->{'compressedSize'}, IO::Seekable::SEEK_CUR )
- or return _ioError("seeking to extended local header");
-
- my $status = $self->_readDataDescriptor();
- return $status unless $status == AZ_OK;
- }
- else {
- return _formatError(
- "CRC or size mismatch after reading data descriptor")
- if ( $self->{'crc32'} != $crc32
- || $self->{'uncompressedSize'} != $uncompressedSize );
- }
-
- return AZ_OK;
-}
-
-# This will read the data descriptor, which is after the end of compressed file
-# data in members that that have GPBF_HAS_DATA_DESCRIPTOR_MASK set in their
-# bitFlag.
-# The only reliable way to find these is to rely on the EOCD compressedSize.
-# Assumes that file is positioned immediately after the compressed data.
-# Returns status; sets crc32, compressedSize, and uncompressedSize.
-sub _readDataDescriptor {
- my $self = shift;
- my $signatureData;
- my $header;
- my $crc32;
- my $compressedSize;
- my $uncompressedSize;
-
- my $bytesRead = $self->fh()->read( $signatureData, SIGNATURE_LENGTH );
- return _ioError("reading header signature")
- if $bytesRead != SIGNATURE_LENGTH;
- my $signature = unpack( SIGNATURE_FORMAT, $signatureData );
-
- # unfortunately, the signature appears to be optional.
- if ( $signature == DATA_DESCRIPTOR_SIGNATURE
- && ( $signature != $self->{'crc32'} ) )
- {
- $bytesRead = $self->fh()->read( $header, DATA_DESCRIPTOR_LENGTH );
- return _ioError("reading data descriptor")
- if $bytesRead != DATA_DESCRIPTOR_LENGTH;
-
- ( $crc32, $compressedSize, $uncompressedSize ) =
- unpack( DATA_DESCRIPTOR_FORMAT, $header );
- }
- else {
- $bytesRead =
- $self->fh()->read( $header, DATA_DESCRIPTOR_LENGTH_NO_SIG );
- return _ioError("reading data descriptor")
- if $bytesRead != DATA_DESCRIPTOR_LENGTH_NO_SIG;
-
- $crc32 = $signature;
- ( $compressedSize, $uncompressedSize ) =
- unpack( DATA_DESCRIPTOR_FORMAT_NO_SIG, $header );
- }
-
- $self->{'eocdCrc32'} = $self->{'crc32'}
- unless defined( $self->{'eocdCrc32'} );
- $self->{'crc32'} = $crc32;
- $self->{'compressedSize'} = $compressedSize;
- $self->{'uncompressedSize'} = $uncompressedSize;
-
- return AZ_OK;
-}
-
-# Read a Central Directory header. Return AZ_OK on success.
-# Assumes that fh is positioned right after the signature.
-
-sub _readCentralDirectoryFileHeader {
- my $self = shift;
- my $fh = $self->fh();
- my $header = '';
- my $bytesRead = $fh->read( $header, CENTRAL_DIRECTORY_FILE_HEADER_LENGTH );
- if ( $bytesRead != CENTRAL_DIRECTORY_FILE_HEADER_LENGTH ) {
- return _ioError("reading central dir header");
- }
- my ( $fileNameLength, $extraFieldLength, $fileCommentLength );
- (
- $self->{'versionMadeBy'},
- $self->{'fileAttributeFormat'},
- $self->{'versionNeededToExtract'},
- $self->{'bitFlag'},
- $self->{'compressionMethod'},
- $self->{'lastModFileDateTime'},
- $self->{'crc32'},
- $self->{'compressedSize'},
- $self->{'uncompressedSize'},
- $fileNameLength,
- $extraFieldLength,
- $fileCommentLength,
- $self->{'diskNumberStart'},
- $self->{'internalFileAttributes'},
- $self->{'externalFileAttributes'},
- $self->{'localHeaderRelativeOffset'}
- ) = unpack( CENTRAL_DIRECTORY_FILE_HEADER_FORMAT, $header );
-
- $self->{'eocdCrc32'} = $self->{'crc32'};
-
- if ($fileNameLength) {
- $bytesRead = $fh->read( $self->{'fileName'}, $fileNameLength );
- if ( $bytesRead != $fileNameLength ) {
- _ioError("reading central dir filename");
- }
- }
- if ($extraFieldLength) {
- $bytesRead = $fh->read( $self->{'cdExtraField'}, $extraFieldLength );
- if ( $bytesRead != $extraFieldLength ) {
- return _ioError("reading central dir extra field");
- }
- }
- if ($fileCommentLength) {
- $bytesRead = $fh->read( $self->{'fileComment'}, $fileCommentLength );
- if ( $bytesRead != $fileCommentLength ) {
- return _ioError("reading central dir file comment");
- }
- }
-
- # NK 10/21/04: added to avoid problems with manipulated headers
- if ( $self->{'uncompressedSize'} != $self->{'compressedSize'}
- and $self->{'compressionMethod'} == COMPRESSION_STORED )
- {
- $self->{'uncompressedSize'} = $self->{'compressedSize'};
- }
-
- $self->desiredCompressionMethod( $self->compressionMethod() );
-
- return AZ_OK;
-}
-
-sub rewindData {
- my $self = shift;
-
- my $status = $self->SUPER::rewindData(@_);
- return $status unless $status == AZ_OK;
-
- return AZ_IO_ERROR unless $self->fh();
-
- $self->fh()->clearerr();
-
- # Seek to local file header.
- # The only reason that I'm doing this this way is that the extraField
- # length seems to be different between the CD header and the LF header.
- $status = $self->_seekToLocalHeader();
- return $status unless $status == AZ_OK;
-
- # skip local file header
- $status = $self->_skipLocalFileHeader();
- return $status unless $status == AZ_OK;
-
- # Seek to beginning of file data
- $self->fh()->seek( $self->dataOffset(), IO::Seekable::SEEK_SET )
- or return _ioError("seeking to beginning of file data");
-
- return AZ_OK;
-}
-
-# Return bytes read. Note that first parameter is a ref to a buffer.
-# my $data;
-# my ( $bytesRead, $status) = $self->readRawChunk( \$data, $chunkSize );
-sub _readRawChunk {
- my ( $self, $dataRef, $chunkSize ) = @_;
- return ( 0, AZ_OK ) unless $chunkSize;
- my $bytesRead = $self->fh()->read( $$dataRef, $chunkSize )
- or return ( 0, _ioError("reading data") );
- return ( $bytesRead, AZ_OK );
-}
-
-1;