1 package Archive::Extract;
7 use IPC::Cmd qw[run can_run];
9 use File::Path qw[mkpath];
11 use File::Basename qw[dirname basename];
12 use Params::Check qw[check];
13 use Module::Load::Conditional qw[can_load check_install];
14 use Locale::Maketext::Simple Style => 'gettext';
16 ### solaris has silly /bin/tar output ###
17 use constant ON_SOLARIS => $^O eq 'solaris' ? 1 : 0;
18 use constant FILE_EXISTS => sub { -e $_[0] ? 1 : 0 };
20 ### VMS may require quoting upper case command options
21 use constant ON_VMS => $^O eq 'VMS' ? 1 : 0;
23 ### If these are changed, update @TYPES and the new() POD
24 use constant TGZ => 'tgz';
25 use constant TAR => 'tar';
26 use constant GZ => 'gz';
27 use constant ZIP => 'zip';
28 use constant BZ2 => 'bz2';
29 use constant TBZ => 'tbz';
30 use constant Z => 'Z';
31 use constant LZMA => 'lzma';
33 use vars qw[$VERSION $PREFER_BIN $PROGRAMS $WARN $DEBUG];
39 my @Types = ( TGZ, TAR, GZ, ZIP, BZ2, TBZ, Z, LZMA ); # same as all constants
41 local $Params::Check::VERBOSE = $Params::Check::VERBOSE = 1;
47 Archive::Extract - A generic archive extracting mechanism
53 ### build an Archive::Extract object ###
54 my $ae = Archive::Extract->new( archive => 'foo.tgz' );
56 ### extract to cwd() ###
57 my $ok = $ae->extract;
59 ### extract to /tmp ###
60 my $ok = $ae->extract( to => '/tmp' );
62 ### what if something went wrong?
63 my $ok = $ae->extract or die $ae->error;
65 ### files from the archive ###
66 my $files = $ae->files;
68 ### dir that was extracted to ###
69 my $outdir = $ae->extract_path;
72 ### quick check methods ###
73 $ae->is_tar # is it a .tar file?
74 $ae->is_tgz # is it a .tar.gz or .tgz file?
75 $ae->is_gz; # is it a .gz file?
76 $ae->is_zip; # is it a .zip file?
77 $ae->is_bz2; # is it a .bz2 file?
78 $ae->is_tbz; # is it a .tar.bz2 or .tbz file?
79 $ae->is_lzma; # is it a .lzma file?
81 ### absolute path to the archive you provided ###
84 ### commandline tools, if found ###
85 $ae->bin_tar # path to /bin/tar, if found
86 $ae->bin_gzip # path to /bin/gzip, if found
87 $ae->bin_unzip # path to /bin/unzip, if found
88 $ae->bin_bunzip2 # path to /bin/bunzip2 if found
89 $ae->bin_unlzma # path to /bin/unlzma if found
93 Archive::Extract is a generic archive extraction mechanism.
95 It allows you to extract any archive file of the type .tar, .tar.gz,
96 .gz, .Z, tar.bz2, .tbz, .bz2, .zip or .lzma without having to worry how it
97 does so, or use different interfaces for each type by using either
98 perl modules, or commandline tools on your system.
100 See the C<HOW IT WORKS> section further down for details.
105 ### see what /bin/programs are available ###
107 for my $pgm (qw[tar unzip gzip bunzip2 uncompress unlzma]) {
108 $PROGRAMS->{$pgm} = can_run($pgm);
111 ### mapping from types to extractor methods ###
118 is_bz2 => '_bunzip2',
119 is_Z => '_uncompress',
120 is_lzma => '_unlzma',
125 archive => { required => 1, allow => FILE_EXISTS },
126 type => { default => '', allow => [ @Types ] },
129 ### build accesssors ###
130 for my $method( keys %$tmpl,
131 qw[_extractor _gunzip_to files extract_path],
132 qw[_error_msg _error_msg_long]
137 $self->{$method} = $_[0] if @_;
138 return $self->{$method};
144 =head2 $ae = Archive::Extract->new(archive => '/path/to/archive',[type => TYPE])
146 Creates a new C<Archive::Extract> object based on the archive file you
147 passed it. Automatically determines the type of archive based on the
148 extension, but you can override that by explicitly providing the
151 Valid values for C<type> are:
157 Standard tar files, as produced by, for example, C</bin/tar>.
158 Corresponds to a C<.tar> suffix.
162 Gzip compressed tar files, as produced by, for example C</bin/tar -z>.
163 Corresponds to a C<.tgz> or C<.tar.gz> suffix.
167 Gzip compressed file, as produced by, for example C</bin/gzip>.
168 Corresponds to a C<.gz> suffix.
172 Lempel-Ziv compressed file, as produced by, for example C</bin/compress>.
173 Corresponds to a C<.Z> suffix.
177 Zip compressed file, as produced by, for example C</bin/zip>.
178 Corresponds to a C<.zip>, C<.jar> or C<.par> suffix.
182 Bzip2 compressed file, as produced by, for example, C</bin/bzip2>.
183 Corresponds to a C<.bz2> suffix.
187 Bzip2 compressed tar file, as produced by, for exmample C</bin/tar -j>.
188 Corresponds to a C<.tbz> or C<.tar.bz2> suffix.
192 Lzma compressed file, as produced by C</bin/lzma>.
193 Corresponds to a C<.lzma> suffix.
197 Returns a C<Archive::Extract> object on success, or false on failure.
206 my $parsed = check( $tmpl, \%hash ) or return;
208 ### make sure we have an absolute path ###
209 my $ar = $parsed->{archive} = File::Spec->rel2abs( $parsed->{archive} );
211 ### figure out the type, if it wasn't already specified ###
212 unless ( $parsed->{type} ) {
214 $ar =~ /.+?\.(?:tar\.gz|tgz)$/i ? TGZ :
215 $ar =~ /.+?\.gz$/i ? GZ :
216 $ar =~ /.+?\.tar$/i ? TAR :
217 $ar =~ /.+?\.(zip|jar|par)$/i ? ZIP :
218 $ar =~ /.+?\.(?:tbz2?|tar\.bz2?)$/i ? TBZ :
219 $ar =~ /.+?\.bz2$/i ? BZ2 :
220 $ar =~ /.+?\.Z$/ ? Z :
221 $ar =~ /.+?\.lzma$/ ? LZMA :
226 ### don't know what type of file it is ###
227 return __PACKAGE__->_error(loc("Cannot determine file type for '%1'",
228 $parsed->{archive} )) unless $parsed->{type};
230 return bless $parsed, $class;
234 =head2 $ae->extract( [to => '/output/path'] )
236 Extracts the archive represented by the C<Archive::Extract> object to
237 the path of your choice as specified by the C<to> argument. Defaults to
240 Since C<.gz> files never hold a directory, but only a single file; if
241 the C<to> argument is an existing directory, the file is extracted
242 there, with it's C<.gz> suffix stripped.
243 If the C<to> argument is not an existing directory, the C<to> argument
244 is understood to be a filename, if the archive type is C<gz>.
245 In the case that you did not specify a C<to> argument, the output
246 file will be the name of the archive file, stripped from it's C<.gz>
247 suffix, in the current working directory.
249 C<extract> will try a pure perl solution first, and then fall back to
250 commandline tools if they are available. See the C<GLOBAL VARIABLES>
251 section below on how to alter this behaviour.
253 It will return true on success, and false on failure.
255 On success, it will also set the follow attributes in the object:
259 =item $ae->extract_path
261 This is the directory that the files where extracted to.
265 This is an array ref with the paths of all the files in the archive,
266 relative to the C<to> argument you specified.
267 To get the full path to an extracted file, you would use:
269 File::Spec->catfile( $to, $ae->files->[0] );
271 Note that all files from a tar archive will be in unix format, as per
272 the tar specification.
284 to => { default => '.', store => \$to }
287 check( $tmpl, \%hash ) or return;
289 ### so 'to' could be a file or a dir, depending on whether it's a .gz
290 ### file, or basically anything else.
291 ### so, check that, then act accordingly.
292 ### set an accessor specifically so _gunzip can know what file to extract
296 if( $self->is_gz or $self->is_bz2 or $self->is_Z or $self->is_lzma ) {
298 my $cp = $self->archive; $cp =~ s/\.(?:gz|bz2?|Z|lzma)$//i;
303 $self->_gunzip_to( basename($cp) );
305 ### then it's a filename
308 $self->_gunzip_to( basename($to) );
311 ### not a foo.gz file
317 ### make the dir if it doesn't exist ###
319 eval { mkpath( $dir ) };
321 return $self->_error(loc("Could not create path '%1': %2", $dir, $@))
325 ### get the current dir, to restore later ###
331 ### chdir to the target dir ###
332 unless( chdir $dir ) {
333 $self->_error(loc("Could not chdir to '%1': %2", $dir, $!));
334 $ok = 0; last EXTRACT;
337 ### set files to an empty array ref, so there's always an array
338 ### ref IN the accessor, to avoid errors like:
339 ### Can't use an undefined value as an ARRAY reference at
340 ### ../lib/Archive/Extract.pm line 742. (rt #19815)
343 ### find what extractor method to use ###
344 while( my($type,$method) = each %$Mapping ) {
346 ### call the corresponding method if the type is OK ###
348 $ok = $self->$method();
352 ### warn something went wrong if we didn't get an OK ###
353 $self->_error(loc("Extract failed, no extractor found"))
358 ### and chdir back ###
359 unless( chdir $cwd ) {
360 $self->_error(loc("Could not chdir back to start dir '%1': %2'",
371 =head2 $ae->error([BOOL])
373 Returns the last encountered error as string.
374 Pass it a true value to get the C<Carp::longmess()> output instead.
376 =head2 $ae->extract_path
378 This is the directory the archive got extracted to.
379 See C<extract()> for details.
383 This is an array ref holding all the paths from the archive.
384 See C<extract()> for details.
388 This is the full path to the archive file represented by this
389 C<Archive::Extract> object.
393 This is the type of archive represented by this C<Archive::Extract>
394 object. See accessors below for an easier way to use this.
395 See the C<new()> method for details.
399 Returns a list of all known C<types> for C<Archive::Extract>'s
404 sub types { return @Types }
408 Returns true if the file is of type C<.tar.gz>.
409 See the C<new()> method for details.
413 Returns true if the file is of type C<.tar>.
414 See the C<new()> method for details.
418 Returns true if the file is of type C<.gz>.
419 See the C<new()> method for details.
423 Returns true if the file is of type C<.Z>.
424 See the C<new()> method for details.
428 Returns true if the file is of type C<.zip>.
429 See the C<new()> method for details.
433 Returns true if the file is of type C<.lzma>.
434 See the C<new()> method for details.
438 ### quick check methods ###
439 sub is_tgz { return $_[0]->type eq TGZ }
440 sub is_tar { return $_[0]->type eq TAR }
441 sub is_gz { return $_[0]->type eq GZ }
442 sub is_zip { return $_[0]->type eq ZIP }
443 sub is_tbz { return $_[0]->type eq TBZ }
444 sub is_bz2 { return $_[0]->type eq BZ2 }
445 sub is_Z { return $_[0]->type eq Z }
446 sub is_lzma { return $_[0]->type eq LZMA }
452 Returns the full path to your tar binary, if found.
456 Returns the full path to your gzip binary, if found
458 =head2 $ae->bin_unzip
460 Returns the full path to your unzip binary, if found
462 =head2 $ae->bin_unlzma
464 Returns the full path to your unlzma binary, if found
468 ### paths to commandline tools ###
469 sub bin_gzip { return $PROGRAMS->{'gzip'} if $PROGRAMS->{'gzip'} }
470 sub bin_unzip { return $PROGRAMS->{'unzip'} if $PROGRAMS->{'unzip'} }
471 sub bin_tar { return $PROGRAMS->{'tar'} if $PROGRAMS->{'tar'} }
472 sub bin_bunzip2 { return $PROGRAMS->{'bunzip2'} if $PROGRAMS->{'bunzip2'} }
473 sub bin_uncompress { return $PROGRAMS->{'uncompress'}
474 if $PROGRAMS->{'uncompress'} }
475 sub bin_unlzma { return $PROGRAMS->{'unlzma'} if $PROGRAMS->{'unlzma'} }
477 =head2 $bool = $ae->have_old_bunzip2
479 Older versions of C</bin/bunzip2>, from before the C<bunzip2 1.0> release,
480 require all archive names to end in C<.bz2> or it will not extract
481 them. This method checks if you have a recent version of C<bunzip2>
482 that allows any extension, or an older one that doesn't.
486 sub have_old_bunzip2 {
489 ### no bunzip2? no old bunzip2 either :)
490 return unless $self->bin_bunzip2;
492 ### if we can't run this, we can't be sure if it's too old or not
493 ### XXX stupid stupid stupid bunzip2 doesn't understand --version
494 ### is not a request to extract data:
495 ### $ bunzip2 --version
496 ### bzip2, a block-sorting file compressor. Version 1.0.2, 30-Dec-2001.
498 ### bunzip2: I won't read compressed data from a terminal.
499 ### bunzip2: For help, type: `bunzip2 --help'.
504 ### double hateful: bunzip2 --version also hangs if input is a pipe
505 ### See #32370: Archive::Extract will hang if stdin is a pipe [+PATCH]
506 ### So, we have to provide *another* argument which is a fake filename,
507 ### just so it wont try to read from stdin to print it's version..
509 ### Even if the file exists, it won't clobber or change it.
512 command => [$self->bin_bunzip2, '--version', 'NoSuchFile'],
518 return unless $buffer;
520 my ($version) = $buffer =~ /version \s+ (\d+)/ix;
522 return 1 if $version < 1;
526 #################################
530 #################################
532 ### untar wrapper... goes to either Archive::Tar or /bin/tar
533 ### depending on $PREFER_BIN
537 ### bzip2 support in A::T via IO::Uncompress::Bzip2
538 my @methods = qw[_untar_at _untar_bin];
539 @methods = reverse @methods if $PREFER_BIN;
541 for my $method (@methods) {
542 $self->_extractor($method) && return 1 if $self->$method();
545 return $self->_error(loc("Unable to untar file '%1'", $self->archive));
548 ### use /bin/tar to extract ###
552 ### check for /bin/tar ###
553 return $self->_error(loc("No '%1' program found", '/bin/tar'))
554 unless $self->bin_tar;
556 ### check for /bin/gzip if we need it ###
557 return $self->_error(loc("No '%1' program found", '/bin/gzip'))
558 if $self->is_tgz && !$self->bin_gzip;
560 return $self->_error(loc("No '%1' program found", '/bin/bunzip2'))
561 if $self->is_tbz && !$self->bin_bunzip2;
563 ### XXX figure out how to make IPC::Run do this in one call --
564 ### currently i don't know how to get output of a command after a pipe
565 ### trapped in a scalar. Mailed barries about this 5th of june 2004.
569 ### see what command we should run, based on whether
570 ### it's a .tgz or .tar
572 ### XXX solaris tar and bsdtar are having different outputs
573 ### depending whether you run with -x or -t
574 ### compensate for this insanity by running -t first, then -x
576 $self->is_tgz ? [$self->bin_gzip, '-cdf', $self->archive, '|',
577 $self->bin_tar, '-tf', '-'] :
578 $self->is_tbz ? [$self->bin_bunzip2, '-cd', $self->archive, '|',
579 $self->bin_tar, '-tf', '-'] :
580 [$self->bin_tar, '-tf', $self->archive];
582 ### run the command ###
584 unless( scalar run( command => $cmd,
588 return $self->_error(loc(
589 "Error listing contents of archive '%1': %2",
590 $self->archive, $buffer ));
593 ### no buffers available?
594 if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
595 $self->_error( $self->_no_buffer_files( $self->archive ) );
598 ### if we're on solaris we /might/ be using /bin/tar, which has
599 ### a weird output format... we might also be using
600 ### /usr/local/bin/tar, which is gnu tar, which is perfectly
601 ### fine... so we have to do some guessing here =/
602 my @files = map { chomp;
604 : (m|^ x \s+ # 'xtract' -- sigh
605 (.+?), # the actual file name
606 \s+ [\d,.]+ \s bytes,
607 \s+ [\d,.]+ \s tape \s blocks
612 ### store the files that are in the archive ###
613 $self->files(\@files);
617 ### now actually extract it ###
619 $self->is_tgz ? [$self->bin_gzip, '-cdf', $self->archive, '|',
620 $self->bin_tar, '-xf', '-'] :
621 $self->is_tbz ? [$self->bin_bunzip2, '-cd', $self->archive, '|',
622 $self->bin_tar, '-xf', '-'] :
623 [$self->bin_tar, '-xf', $self->archive];
626 unless( scalar run( command => $cmd,
630 return $self->_error(loc("Error extracting archive '%1': %2",
631 $self->archive, $buffer ));
634 ### we might not have them, due to lack of buffers
636 ### now that we've extracted, figure out where we extracted to
637 my $dir = $self->__get_extract_dir( $self->files );
639 ### store the extraction dir ###
640 $self->extract_path( $dir );
644 ### we got here, no error happened
648 ### use archive::tar to extract ###
652 ### we definitely need A::T, so load that first
653 { my $use_list = { 'Archive::Tar' => '0.0' };
655 unless( can_load( modules => $use_list ) ) {
657 return $self->_error(loc("You do not have '%1' installed - " .
658 "Please install it as soon as possible.",
663 ### we might pass it a filehandle if it's a .tbz file..
664 my $fh_to_read = $self->archive;
666 ### we will need Compress::Zlib too, if it's a tgz... and IO::Zlib
667 ### if A::T's version is 0.99 or higher
668 if( $self->is_tgz ) {
669 my $use_list = { 'Compress::Zlib' => '0.0' };
670 $use_list->{ 'IO::Zlib' } = '0.0'
671 if $Archive::Tar::VERSION >= '0.99';
673 unless( can_load( modules => $use_list ) ) {
674 my $which = join '/', sort keys %$use_list;
676 return $self->_error(loc(
677 "You do not have '%1' installed - Please ".
678 "install it as soon as possible.", $which));
681 } elsif ( $self->is_tbz ) {
682 my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
683 unless( can_load( modules => $use_list ) ) {
684 return $self->_error(loc(
685 "You do not have '%1' installed - Please " .
686 "install it as soon as possible.",
687 'IO::Uncompress::Bunzip2'));
690 my $bz = IO::Uncompress::Bunzip2->new( $self->archive ) or
691 return $self->_error(loc("Unable to open '%1': %2",
693 $IO::Uncompress::Bunzip2::Bunzip2Error));
698 my $tar = Archive::Tar->new();
700 ### only tell it it's compressed if it's a .tgz, as we give it a file
701 ### handle if it's a .tbz
702 unless( $tar->read( $fh_to_read, ( $self->is_tgz ? 1 : 0 ) ) ) {
703 return $self->_error(loc("Unable to read '%1': %2", $self->archive,
704 $Archive::Tar::error));
707 ### workaround to prevent Archive::Tar from setting uid, which
708 ### is a potential security hole. -autrijus
709 ### have to do it here, since A::T needs to be /loaded/ first ###
710 { no strict 'refs'; local $^W;
712 ### older versions of archive::tar <= 0.23
713 *Archive::Tar::chown = sub {};
716 ### for version of archive::tar > 1.04
717 local $Archive::Tar::Constant::CHOWN = 0;
719 { local $^W; # quell 'splice() offset past end of array' warnings
720 # on older versions of A::T
722 ### older archive::tar always returns $self, return value slightly
723 ### fux0r3d because of it.
725 or return $self->_error(loc("Unable to extract '%1': %2",
726 $self->archive, $Archive::Tar::error ));
729 my @files = $tar->list_files;
730 my $dir = $self->__get_extract_dir( \@files );
732 ### store the files that are in the archive ###
733 $self->files(\@files);
735 ### store the extraction dir ###
736 $self->extract_path( $dir );
738 ### check if the dir actually appeared ###
739 return 1 if -d $self->extract_path;
741 ### no dir, we failed ###
742 return $self->_error(loc("Unable to extract '%1': %2",
743 $self->archive, $Archive::Tar::error ));
746 #################################
750 #################################
752 ### gunzip wrapper... goes to either Compress::Zlib or /bin/gzip
753 ### depending on $PREFER_BIN
757 my @methods = qw[_gunzip_cz _gunzip_bin];
758 @methods = reverse @methods if $PREFER_BIN;
760 for my $method (@methods) {
761 $self->_extractor($method) && return 1 if $self->$method();
764 return $self->_error(loc("Unable to gunzip file '%1'", $self->archive));
770 ### check for /bin/gzip -- we need it ###
771 return $self->_error(loc("No '%1' program found", '/bin/gzip'))
772 unless $self->bin_gzip;
775 my $fh = FileHandle->new('>'. $self->_gunzip_to) or
776 return $self->_error(loc("Could not open '%1' for writing: %2",
777 $self->_gunzip_to, $! ));
779 my $cmd = [ $self->bin_gzip, '-cdf', $self->archive ];
782 unless( scalar run( command => $cmd,
786 return $self->_error(loc("Unable to gunzip '%1': %2",
787 $self->archive, $buffer));
790 ### no buffers available?
791 if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
792 $self->_error( $self->_no_buffer_content( $self->archive ) );
795 print $fh $buffer if defined $buffer;
799 ### set what files where extract, and where they went ###
800 $self->files( [$self->_gunzip_to] );
801 $self->extract_path( File::Spec->rel2abs(cwd()) );
809 my $use_list = { 'Compress::Zlib' => '0.0' };
810 unless( can_load( modules => $use_list ) ) {
811 return $self->_error(loc("You do not have '%1' installed - Please " .
812 "install it as soon as possible.", 'Compress::Zlib'));
815 my $gz = Compress::Zlib::gzopen( $self->archive, "rb" ) or
816 return $self->_error(loc("Unable to open '%1': %2",
817 $self->archive, $Compress::Zlib::gzerrno));
819 my $fh = FileHandle->new('>'. $self->_gunzip_to) or
820 return $self->_error(loc("Could not open '%1' for writing: %2",
821 $self->_gunzip_to, $! ));
824 $fh->print($buffer) while $gz->gzread($buffer) > 0;
827 ### set what files where extract, and where they went ###
828 $self->files( [$self->_gunzip_to] );
829 $self->extract_path( File::Spec->rel2abs(cwd()) );
834 #################################
838 #################################
841 ### untar wrapper... goes to either Archive::Tar or /bin/tar
842 ### depending on $PREFER_BIN
846 my @methods = qw[_gunzip_cz _uncompress_bin];
847 @methods = reverse @methods if $PREFER_BIN;
849 for my $method (@methods) {
850 $self->_extractor($method) && return 1 if $self->$method();
853 return $self->_error(loc("Unable to untar file '%1'", $self->archive));
856 sub _uncompress_bin {
859 ### check for /bin/gzip -- we need it ###
860 return $self->_error(loc("No '%1' program found", '/bin/uncompress'))
861 unless $self->bin_uncompress;
864 my $fh = FileHandle->new('>'. $self->_gunzip_to) or
865 return $self->_error(loc("Could not open '%1' for writing: %2",
866 $self->_gunzip_to, $! ));
868 my $cmd = [ $self->bin_uncompress, '-c', $self->archive ];
871 unless( scalar run( command => $cmd,
875 return $self->_error(loc("Unable to uncompress '%1': %2",
876 $self->archive, $buffer));
879 ### no buffers available?
880 if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
881 $self->_error( $self->_no_buffer_content( $self->archive ) );
884 print $fh $buffer if defined $buffer;
888 ### set what files where extract, and where they went ###
889 $self->files( [$self->_gunzip_to] );
890 $self->extract_path( File::Spec->rel2abs(cwd()) );
896 #################################
900 #################################
902 ### unzip wrapper... goes to either Archive::Zip or /bin/unzip
903 ### depending on $PREFER_BIN
907 my @methods = qw[_unzip_az _unzip_bin];
908 @methods = reverse @methods if $PREFER_BIN;
910 for my $method (@methods) {
911 $self->_extractor($method) && return 1 if $self->$method();
914 return $self->_error(loc("Unable to gunzip file '%1'", $self->archive));
920 ### check for /bin/gzip if we need it ###
921 return $self->_error(loc("No '%1' program found", '/bin/unzip'))
922 unless $self->bin_unzip;
925 ### first, get the files.. it must be 2 different commands with 'unzip' :(
926 { ### on VMS, capital letter options have to be quoted. This is
927 ### peported by John Malmberg on P5P Tue 21 Aug 2007 05:05:11
928 ### Subject: [patch@31735]Archive Extract fix on VMS.
929 my $opt = ON_VMS ? '"-Z"' : '-Z';
930 my $cmd = [ $self->bin_unzip, $opt, '-1', $self->archive ];
933 unless( scalar run( command => $cmd,
937 return $self->_error(loc("Unable to unzip '%1': %2",
938 $self->archive, $buffer));
941 ### no buffers available?
942 if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
943 $self->_error( $self->_no_buffer_files( $self->archive ) );
946 $self->files( [split $/, $buffer] );
950 ### now, extract the archive ###
951 { my $cmd = [ $self->bin_unzip, '-qq', '-o', $self->archive ];
954 unless( scalar run( command => $cmd,
958 return $self->_error(loc("Unable to unzip '%1': %2",
959 $self->archive, $buffer));
962 if( scalar @{$self->files} ) {
963 my $files = $self->files;
964 my $dir = $self->__get_extract_dir( $files );
966 $self->extract_path( $dir );
976 my $use_list = { 'Archive::Zip' => '0.0' };
977 unless( can_load( modules => $use_list ) ) {
978 return $self->_error(loc("You do not have '%1' installed - Please " .
979 "install it as soon as possible.", 'Archive::Zip'));
982 my $zip = Archive::Zip->new();
984 unless( $zip->read( $self->archive ) == &Archive::Zip::AZ_OK ) {
985 return $self->_error(loc("Unable to read '%1'", $self->archive));
989 ### have to extract every memeber individually ###
990 for my $member ($zip->members) {
991 push @files, $member->{fileName};
993 unless( $zip->extractMember($member) == &Archive::Zip::AZ_OK ) {
994 return $self->_error(loc("Extraction of '%1' from '%2' failed",
995 $member->{fileName}, $self->archive ));
999 my $dir = $self->__get_extract_dir( \@files );
1001 ### set what files where extract, and where they went ###
1002 $self->files( \@files );
1003 $self->extract_path( File::Spec->rel2abs($dir) );
1008 sub __get_extract_dir {
1010 my $files = shift || [];
1012 return unless scalar @$files;
1015 for my $aref ( [ \$dir1, 0 ], [ \$dir2, -1 ] ) {
1016 my($dir,$pos) = @$aref;
1018 ### add a catdir(), so that any trailing slashes get
1019 ### take care of (removed)
1020 ### also, a catdir() normalises './dir/foo' to 'dir/foo';
1021 ### which was the problem in bug #23999
1022 my $res = -d $files->[$pos]
1023 ? File::Spec->catdir( $files->[$pos], '' )
1024 : File::Spec->catdir( dirname( $files->[$pos] ) );
1029 ### if the first and last dir don't match, make sure the
1030 ### dirname is not set wrongly
1033 ### dirs are the same, so we know for sure what the extract dir is
1034 if( $dir1 eq $dir2 ) {
1037 ### dirs are different.. do they share the base dir?
1038 ### if so, use that, if not, fall back to '.'
1040 my $base1 = [ File::Spec->splitdir( $dir1 ) ]->[0];
1041 my $base2 = [ File::Spec->splitdir( $dir2 ) ]->[0];
1043 $dir = File::Spec->rel2abs( $base1 eq $base2 ? $base1 : '.' );
1046 return File::Spec->rel2abs( $dir );
1049 #################################
1053 #################################
1055 ### bunzip2 wrapper...
1059 my @methods = qw[_bunzip2_cz2 _bunzip2_bin];
1060 @methods = reverse @methods if $PREFER_BIN;
1062 for my $method (@methods) {
1063 $self->_extractor($method) && return 1 if $self->$method();
1066 return $self->_error(loc("Unable to bunzip2 file '%1'", $self->archive));
1072 ### check for /bin/gzip -- we need it ###
1073 return $self->_error(loc("No '%1' program found", '/bin/bunzip2'))
1074 unless $self->bin_bunzip2;
1077 my $fh = FileHandle->new('>'. $self->_gunzip_to) or
1078 return $self->_error(loc("Could not open '%1' for writing: %2",
1079 $self->_gunzip_to, $! ));
1081 ### guard against broken bunzip2. See ->have_old_bunzip2()
1083 if( $self->have_old_bunzip2 and $self->archive !~ /\.bz2$/i ) {
1084 return $self->_error(loc("Your bunzip2 version is too old and ".
1085 "can only extract files ending in '%1'",
1089 my $cmd = [ $self->bin_bunzip2, '-cd', $self->archive ];
1092 unless( scalar run( command => $cmd,
1094 buffer => \$buffer )
1096 return $self->_error(loc("Unable to bunzip2 '%1': %2",
1097 $self->archive, $buffer));
1100 ### no buffers available?
1101 if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
1102 $self->_error( $self->_no_buffer_content( $self->archive ) );
1105 print $fh $buffer if defined $buffer;
1109 ### set what files where extract, and where they went ###
1110 $self->files( [$self->_gunzip_to] );
1111 $self->extract_path( File::Spec->rel2abs(cwd()) );
1116 ### using cz2, the compact versions... this we use mainly in archive::tar
1118 # sub _bunzip2_cz1 {
1121 # my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
1122 # unless( can_load( modules => $use_list ) ) {
1123 # return $self->_error(loc("You do not have '%1' installed - Please " .
1124 # "install it as soon as possible.",
1125 # 'IO::Uncompress::Bunzip2'));
1128 # my $bz = IO::Uncompress::Bunzip2->new( $self->archive ) or
1129 # return $self->_error(loc("Unable to open '%1': %2",
1131 # $IO::Uncompress::Bunzip2::Bunzip2Error));
1133 # my $fh = FileHandle->new('>'. $self->_gunzip_to) or
1134 # return $self->_error(loc("Could not open '%1' for writing: %2",
1135 # $self->_gunzip_to, $! ));
1138 # $fh->print($buffer) while $bz->read($buffer) > 0;
1141 # ### set what files where extract, and where they went ###
1142 # $self->files( [$self->_gunzip_to] );
1143 # $self->extract_path( File::Spec->rel2abs(cwd()) );
1151 my $use_list = { 'IO::Uncompress::Bunzip2' => '0.0' };
1152 unless( can_load( modules => $use_list ) ) {
1153 return $self->_error(loc("You do not have '%1' installed - Please " .
1154 "install it as soon as possible.",
1155 'IO::Uncompress::Bunzip2'));
1158 IO::Uncompress::Bunzip2::bunzip2($self->archive => $self->_gunzip_to)
1159 or return $self->_error(loc("Unable to uncompress '%1': %2",
1161 $IO::Uncompress::Bunzip2::Bunzip2Error));
1163 ### set what files where extract, and where they went ###
1164 $self->files( [$self->_gunzip_to] );
1165 $self->extract_path( File::Spec->rel2abs(cwd()) );
1171 #################################
1175 #################################
1177 ### unlzma wrapper... goes to either Compress::unLZMA or /bin/unlzma
1178 ### depending on $PREFER_BIN
1182 my @methods = qw[_unlzma_cz _unlzma_bin];
1183 @methods = reverse @methods if $PREFER_BIN;
1185 for my $method (@methods) {
1186 $self->_extractor($method) && return 1 if $self->$method();
1189 return $self->_error(loc("Unable to unlzma file '%1'", $self->archive));
1195 ### check for /bin/unlzma -- we need it ###
1196 return $self->_error(loc("No '%1' program found", '/bin/unlzma'))
1197 unless $self->bin_unlzma;
1199 my $fh = FileHandle->new('>'. $self->_gunzip_to) or
1200 return $self->_error(loc("Could not open '%1' for writing: %2",
1201 $self->_gunzip_to, $! ));
1203 my $cmd = [ $self->bin_unlzma, '-c', $self->archive ];
1206 unless( scalar run( command => $cmd,
1208 buffer => \$buffer )
1210 return $self->_error(loc("Unable to unlzma '%1': %2",
1211 $self->archive, $buffer));
1214 ### no buffers available?
1215 if( !IPC::Cmd->can_capture_buffer and !$buffer ) {
1216 $self->_error( $self->_no_buffer_content( $self->archive ) );
1219 print $fh $buffer if defined $buffer;
1223 ### set what files where extract, and where they went ###
1224 $self->files( [$self->_gunzip_to] );
1225 $self->extract_path( File::Spec->rel2abs(cwd()) );
1233 my $use_list = { 'Compress::unLZMA' => '0.0' };
1234 unless( can_load( modules => $use_list ) ) {
1235 return $self->_error(loc("You do not have '%1' installed - Please " .
1236 "install it as soon as possible.", 'Compress::unLZMA'));
1239 my $fh = FileHandle->new('>'. $self->_gunzip_to) or
1240 return $self->_error(loc("Could not open '%1' for writing: %2",
1241 $self->_gunzip_to, $! ));
1244 $buffer = Compress::unLZMA::uncompressfile( $self->archive );
1245 unless ( defined $buffer ) {
1246 return $self->_error(loc("Could not unlzma '%1': %2",
1247 $self->archive, $@));
1250 print $fh $buffer if defined $buffer;
1254 ### set what files where extract, and where they went ###
1255 $self->files( [$self->_gunzip_to] );
1256 $self->extract_path( File::Spec->rel2abs(cwd()) );
1261 #################################
1265 #################################
1271 $self->_error_msg( $error );
1272 $self->_error_msg_long( Carp::longmess($error) );
1274 ### set $Archive::Extract::WARN to 0 to disable printing
1277 carp $DEBUG ? $self->_error_msg_long : $self->_error_msg;
1285 return shift() ? $self->_error_msg_long : $self->_error_msg;
1288 sub _no_buffer_files {
1290 my $file = shift or return;
1291 return loc("No buffer captured, unable to tell ".
1292 "extracted files or extraction dir for '%1'", $file);
1295 sub _no_buffer_content {
1297 my $file = shift or return;
1298 return loc("No buffer captured, unable to get content for '%1'", $file);
1306 C<Archive::Extract> tries first to determine what type of archive you
1307 are passing it, by inspecting its suffix. It does not do this by using
1308 Mime magic, or something related. See C<CAVEATS> below.
1310 Once it has determined the file type, it knows which extraction methods
1311 it can use on the archive. It will try a perl solution first, then fall
1312 back to a commandline tool if that fails. If that also fails, it will
1313 return false, indicating it was unable to extract the archive.
1314 See the section on C<GLOBAL VARIABLES> to see how to alter this order.
1318 =head2 File Extensions
1320 C<Archive::Extract> trusts on the extension of the archive to determine
1321 what type it is, and what extractor methods therefore can be used. If
1322 your archives do not have any of the extensions as described in the
1323 C<new()> method, you will have to specify the type explicitly, or
1324 C<Archive::Extract> will not be able to extract the archive for you.
1326 =head2 Supporting Very Large Files
1328 C<Archive::Extract> can use either pure perl modules or command line
1329 programs under the hood. Some of the pure perl modules (like
1330 C<Archive::Tar> and Compress::unLZMA) take the entire contents of the archive into memory,
1331 which may not be feasible on your system. Consider setting the global
1332 variable C<$Archive::Extract::PREFER_BIN> to C<1>, which will prefer
1333 the use of command line programs and won't consume so much memory.
1335 See the C<GLOBAL VARIABLES> section below for details.
1337 =head2 Bunzip2 support of arbitrary extensions.
1339 Older versions of C</bin/bunzip2> do not support arbitrary file
1340 extensions and insist on a C<.bz2> suffix. Although we do our best
1341 to guard against this, if you experience a bunzip2 error, it may
1342 be related to this. For details, please see the C<have_old_bunzip2>
1345 =head1 GLOBAL VARIABLES
1347 =head2 $Archive::Extract::DEBUG
1349 Set this variable to C<true> to have all calls to command line tools
1350 be printed out, including all their output.
1351 This also enables C<Carp::longmess> errors, instead of the regular
1354 Good for tracking down why things don't work with your particular
1357 Defaults to C<false>.
1359 =head2 $Archive::Extract::WARN
1361 This variable controls whether errors encountered internally by
1362 C<Archive::Extract> should be C<carp>'d or not.
1364 Set to false to silence warnings. Inspect the output of the C<error()>
1365 method manually to see what went wrong.
1367 Defaults to C<true>.
1369 =head2 $Archive::Extract::PREFER_BIN
1371 This variables controls whether C<Archive::Extract> should prefer the
1372 use of perl modules, or commandline tools to extract archives.
1374 Set to C<true> to have C<Archive::Extract> prefer commandline tools.
1376 Defaults to C<false>.
1382 =item Mime magic support
1384 Maybe this module should use something like C<File::Type> to determine
1385 the type, rather than blindly trust the suffix.
1391 Please report bugs or other issues to E<lt>bug-archive-extract@rt.cpan.org<gt>.
1395 This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
1399 This library is free software; you may redistribute and/or modify it
1400 under the same terms as Perl itself.
1405 # c-indentation-style: bsd
1407 # indent-tabs-mode: nil
1409 # vim: expandtab shiftwidth=4: