Skip Menu |

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

Report information
The Basics
Id: 119905
Status: resolved
Worked: 3.7 hours (220 min)
Priority: 0/
Queue: Archive-Extract

People
Owner: BINGOS [...] cpan.org
Requestors: jkeenan [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 0.80



Subject: Archive-Extract can not locate '/usr/bin/unzip' on Linux
I have a CPAN distro, CPAN-Mini-Visit-Simple, which relies on Archive::Extract to extract archives found within a minicpan. ##### my $tdir = tempdir( CLEANUP => 1 ); chdir $tdir or croak "Unable to change to temporary directory"; my $ae = Archive::Extract->new( archive => $distro ); my $extract_ok; eval { $extract_ok = $ae->extract( to => $tdir ); }; # <- line 236 ##### When I traverse my minicpan and come to an archive which is in .bz2 format, I get a warning like this: ##### No '/bin/unzip' program found at /home/jkeenan/perl5/perlbrew/perls/perl-5.24.1/lib/site_perl/5.24.1/CPAN/Mini/Visit/Simple.pm line 236. ##### ... and the archive is not extracted. This may essentially be the same problem (though perhaps not the same cause) as https://rt.cpan.org/Ticket/Display.html?id=78201, which concerned 'unzip' on FreeBSD. I copied the diagnostic program provided by the OP in that ticket (see attached). When I run it, I get: ##### $ perl archive-extract-unzip-problem.pl Use of uninitialized value in concatenation (.) or string at archive-extract-unzip-problem.pl line 15. $ae->bin_unzip = IPC::Cmd::can_run = /usr/bin/unzip ##### If I create a '/bin/unzip' symlink to '/usr/bin/unzip', I still get the warning. Diagnostics: ##### $Archive::Extract::VERSION: 0.78 $ uname -a Linux zareason 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:47:47 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux $ which unzip /usr/bin/unzip tail of 'man unzip' v6.0 20 Apr 09 Info-ZIP (Zip-Bugs subgroup, SPC) Info-ZIP 20 April 2009 (v6.0) UNZIP(1) ###### So with respect to .bz2, it seems that Archive::Extract is not useful on Linux, either. :-( Suggestions? Thank you very much. Jim Keenan
Subject: archive-extract-unzip-problem.pl
# perl use strict; use warnings; use 5.10.1; use Data::Dumper;$Data::Dumper::Indent=1; use Data::Dump qw( pp ); use Carp; use Archive::Extract; use IPC::Cmd qw( can_run ); my $minicpan = '/home/jkeenan/minicpan'; my $bz2archive = "$minicpan/authors/id/A/AN/ANDK/CPAN-Testers-ParseReport-0.3.0.tar.bz2"; croak "Could not locate $bz2archive" unless -f $bz2archive; my $ae = Archive::Extract->new( archive => $bz2archive); say '$ae->bin_unzip = '.$ae->bin_unzip; say 'IPC::Cmd::can_run = ' . can_run('unzip');
Hi, Having checked the A::E code, it should not require unzip to extract a bz2'd tarball. But first I'll deal with why it doesn't find unzip binary (or rather why it does find it, but rejects it as suitable). A::E requires INFO-ZIP's unzip. Specifically the -Z and -1 switches which enable examination of the given zip archive. Both Linux and FreeBSD had to have heuristic tests at one point or another in the history of the module. Linux because there were installs with busybox masquerading as unzip (and lacking the -Z and -1 switches) and FreeBSD which started shipping with an unzip binary that at first didn't support zipinfo mode and then did. The Linux heuristic test for unzip is not the same as the FreeBSD heuristic test. I think this is where the rejection is happening. On Linux A::E runs the unzip binary with the -Z and -1 switches to determine if it is indeed INFO-ZIP's unzip. And you have indicated that it is INFO-ZIP's unzip. On my MINT system (based on trusty): $ unzip -Z -1 <lots of output> $ echo $? 0 Great. On a xenial system: $ unzip -Z -1 <lots of output and this> error: zipfile probably corrupt (segmentation violation) $ echo $? 3 Ouch. So our heuristic is going to fail every time and even when it is an INFO-ZIP unzip. The '/bin/unzip' is a slight red-herring as that is just the text in the error string and not the actual path to what is missing (before my time). I got the segmentation violation with unzip on yakkety as well. ( Seems it has been reported upstream https://bugs.launchpad.net/ubuntu/+source/unzip/+bug/1429939 ) I will switch the Linux test to using the same heuristic that I use for detecting a viable unzip on FreeBSD, because that seems to work fine: $ perl -MArchive::Extract -E 'say Archive::Extract::_is_infozip_esque(shift)' /usr/bin/unzip /usr/bin/unzip $ perl -MArchive::Extract -E 'say Archive::Extract::_is_infozip_esque(shift)' /bin/busybox $ Okay, now that is dealt with, back to the bz2 tarball. I adapted your script slightly after pulling the bz2'd tarball down locally and added an extraction too. $ ls ae-test.pl CPAN-Testers-ParseReport-0.3.0.tar.bz2 $ cat ae-test.pl use strict; use warnings; use 5.10.1; use Data::Dumper;$Data::Dumper::Indent=1; use Data::Dump qw( pp ); use Carp; use Archive::Extract; use IPC::Cmd qw( can_run ); my $bz2archive = "CPAN-Testers-ParseReport-0.3.0.tar.bz2"; croak "Could not locate $bz2archive" unless -f $bz2archive; my $ae = Archive::Extract->new( archive => $bz2archive); say '$ae->bin_unzip = '.$ae->bin_unzip; say 'IPC::Cmd::can_run = ' . can_run('unzip'); my $ok = $ae->extract; say $ok; $ perl ae-test.pl $ae->bin_unzip = /usr/bin/unzip IPC::Cmd::can_run = /usr/bin/unzip 1 $ ls ae-test.pl CPAN-Testers-ParseReport-0.3.0 CPAN-Testers-ParseReport-0.3.0.tar.bz2 $ $ sudo su - [sudo] password: azkaban ~ # mv /usr/bin/unzip /usr/bin/nunzip azkaban ~ # logout $ perl ae-test.pl Use of uninitialized value in concatenation (.) or string at ae-test.pl line 13. $ae->bin_unzip = Use of uninitialized value in concatenation (.) or string at ae-test.pl line 14. IPC::Cmd::can_run = 1 $ ls ae-test.pl CPAN-Testers-ParseReport-0.3.0 CPAN-Testers-ParseReport-0.3.0.tar.bz2 $ So it successfully extracted a bz2'd tarball without unzip existing. I also tried it out on the xenial system: bingos@uffer:~/build/minicpan$ ls ae-test.pl CPAN-Testers-ParseReport-0.3.0.tar.bz2 bingos@uffer:~/build/minicpan$ perl ae-test.pl Use of uninitialized value in concatenation (.) or string at ae-test.pl line 13. $ae->bin_unzip = IPC::Cmd::can_run = /usr/bin/unzip 1 bingos@uffer:~/build/minicpan$ ls ae-test.pl CPAN-Testers-ParseReport-0.3.0 CPAN-Testers-ParseReport-0.3.0.tar.bz2 bingos@uffer:~/build/minicpan$ unzip -Z -1 ZipInfo 3.00 of 20 April 2009, by Greg Roelofs and the Info-ZIP group. List name, date/time, attribute, size, compression method, etc., about files in list (excluding those in xlist) contained in the specified .zip archive(s). "file[.zip]" may be a wildcard name containing *, ?, [] (e.g., "[a-j]*.zip"). usage: zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...] or: unzip -Z [-12smlvChMtTz] file[.zip] [list...] [-x xlist...] main listing-format options: -s short Unix "ls -l" format (def.) -1 filenames ONLY, one per line -m medium Unix "ls -l" format -2 just filenames but allow -h/-t/-z -l long Unix "ls -l" format -v verbose, multi-page format error: zipfile probably corrupt (segmentation violation) bingos@uffer:~/build/minicpan$ echo $? 3
On Wed Jan 18 18:06:59 2017, BINGOS wrote: Show quoted text
> Hi, > > Having checked the A::E code, it should not require unzip to extract a > bz2'd tarball. But first I'll deal with > why it doesn't find unzip binary (or rather why it does find it, but > rejects it as suitable). >
I've been out of the house -- at an ny.pm social meeting! -- since my first post. I'll review this post tomorrow. In my module, I created a branch in which I made this change: ##### - local $Archive::Extract::PREFER_BIN = 1; + local $Archive::Extract::PREFER_BIN = 0; ##### My sense is that this was much slower than "true" PREFER_BIN -- but I didn't get the problem described in this story. Will explore more in coming days. Thank you very much. Jim Keenan
On Wed Jan 18 18:06:59 2017, BINGOS wrote: Show quoted text
> Hi, > > Having checked the A::E code, it should not require unzip to extract a > bz2'd tarball. But first I'll deal with > why it doesn't find unzip binary (or rather why it does find it, but > rejects it as suitable). > > A::E requires INFO-ZIP's unzip. Specifically the -Z and -1 switches > which enable examination of the given zip archive. > > Both Linux and FreeBSD had to have heuristic tests at one point or > another in the history of the module. > Linux because there were installs with busybox masquerading as unzip > (and lacking the -Z and -1 switches) and > FreeBSD which started shipping with an unzip binary that at first > didn't support zipinfo mode and then did. > > The Linux heuristic test for unzip is not the same as the FreeBSD > heuristic test. I think this is where the rejection > is happening. On Linux A::E runs the unzip binary with the -Z and -1 > switches to determine if it is indeed INFO-ZIP's > unzip. And you have indicated that it is INFO-ZIP's unzip. > [snip]
I have to admit that a lot of this goes over my head, but ... ... in version 0.012 (http://search.cpan.org/~jkeenan/CPAN-Mini-Visit-Simple-0.012/) I upgraded to v0.80 of Archive-Extract. That eliminated the "No '/bin/unzip' program found ..." warnings on Linux. They still appear on FreeBSD (11.0), but do not appear to affect results and so can be redirected to /dev/null. I think this ticket can be closed. Thank you for taking the time to write such a detailed response. Jim Keenan
Finally got around to closing the ticket. Many thanks.
On Wed Dec 04 16:29:47 2019, BINGOS wrote: Show quoted text
> Finally got around to closing the ticket. > > Many thanks.
What follows is a long and indirect confirmation that the work which BINGOS put in three years ago on Archive-Extract was successful. The text between 'BELOW NOT SENT' and 'ABOVE NOT SENT' is a bug report I spent several hours *preparing to file*. However -- as the comments at the end of this post indicate -- after reviewing Chris's work in this ticket I was able to figure out what I needed to do to work around a test failure in GitHub::Extract on a system where neither Archive::Zip nor the 'info-esque" version of unzip was installed. ##### BELOW NOT SENT ##### This week, while researching https://github.com/Perl/perl5/issues/16300, I had occasion to run a list of CPAN modules through `cpanm` in order to see whether they installed against a patched version of perl-5.31.10. This procedure is similar to that which I conduct on a monthly basis for the "CPAN River 3000," but on a smaller scale. The test was conducted on FreeBSD-11.2. In the course of this run, CPAN distro GitHub-Extract version 0.02 experienced a unit test failure. Here is an abridged extract from the build.log. ### $ cat github-extract-freebsd-failure-during-cpanm.abridged.txt Searching GitHub::Extract (0.02) on cpanmetadb ... --> Working on GitHub::Extract Fetching http://www.cpan.org/authors/id/A/AD/ADAMK/GitHub-Extract-0.02.tar.gz -> OK Unpacking GitHub-Extract-0.02.tar.gz Entering GitHub-Extract-0.02 Checking configure dependencies from META.yml Checking if you have ExtUtils::MakeMaker 6.59 ... Yes (7.44) Configuring GitHub-Extract-0.02 Running Makefile.PL Warning: prerequisite Archive::Extract 0.56 not found. Warning: prerequisite File::pushd 1.00 not found. Warning: prerequisite HTTP::Online 0.02 not found. Checking if your kit is complete... Looks good Generating a Unix-style Makefile Writing Makefile for GitHub::Extract Writing MYMETA.yml and MYMETA.json -> OK Checking dependencies from MYMETA.json ... Checking if you have HTTP::Online 0.02 ... No Checking if you have Object::Tiny 1.01 ... Yes (1.09) Checking if you have File::Remove 1.51 ... Yes (1.58) Checking if you have File::Spec 3.30 ... Yes (3.78) Checking if you have Archive::Extract 0.56 ... No Checking if you have Test::More 0.42 ... Yes (1.302173) Checking if you have Params::Util 1.00 ... Yes (1.07) Checking if you have IO::Socket::SSL 1.56 ... Yes (2.068) Checking if you have File::pushd 1.00 ... No Checking if you have File::Temp 0.21 ... Yes (0.2309) Checking if you have HTTP::Tiny 0.019 ... Yes (0.076) Checking if you have ExtUtils::MakeMaker 0 ... Yes (7.44) ==> Found dependencies: HTTP::Online, Archive::Extract, File::pushd [# snip successful installation of HTTP::Online] Searching Archive::Extract (0.56) on cpanmetadb ... --> Working on Archive::Extract Fetching http://www.cpan.org/authors/id/B/BI/BINGOS/Archive-Extract-0.86.tar.gz -> OK Unpacking Archive-Extract-0.86.tar.gz Entering Archive-Extract-0.86 Checking configure dependencies from META.json Checking if you have ExtUtils::MakeMaker 6.58 ... Yes (7.44) Configuring Archive-Extract-0.86 Running Makefile.PL Checking if your kit is complete... Looks good Generating a Unix-style Makefile Writing Makefile for Archive::Extract Writing MYMETA.yml and MYMETA.json -> OK Checking dependencies from MYMETA.json ... Checking if you have ExtUtils::MakeMaker 0 ... Yes (7.44) Checking if you have Test::More 0 ... Yes (1.302173) Checking if you have if 0 ... Yes (0.0608) Checking if you have IPC::Cmd 0.64 ... Yes (1.04) Checking if you have File::Basename 0 ... Yes (2.85) Checking if you have File::Path 0 ... Yes (2.16) Checking if you have File::Spec 0.82 ... Yes (3.78) Checking if you have Params::Check 0.07 ... Yes (0.38) Checking if you have Module::Load::Conditional 0.66 ... Yes (0.70) Checking if you have Locale::Maketext::Simple 0 ... Yes (0.21_01) Building and testing Archive-Extract-0.86 cp lib/Archive/Extract.pm blib/lib/Archive/Extract.pm PERL_DL_NONLAZY=1 "/homedir/testing/smoke-me/jkeenan/gh-16300-module-install/bin/perl" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/01_Archive-Extract.t .. ok All tests successful. Files=1, Tests=1572, 1 wallclock secs ( 0.12 usr 0.01 sys + 0.91 cusr 0.70 csys = 1.73 CPU) Result: PASS Installing /homedir/testing/smoke-me/jkeenan/gh-16300-module-install/lib/perl5/site_perl/5.32.0/Archive/Extract.pm Appending installation info to /homedir/testing/smoke-me/jkeenan/gh-16300-module-install/lib/perl5/5.32.0/amd64-freebsd-thread-multi/perllocal.pod -> OK Successfully installed Archive-Extract-0.86 Installing /homedir/testing/smoke-me/jkeenan/gh-16300-module-install/lib/perl5/site_perl/5.32.0/amd64-freebsd-thread-multi/.meta/Archive-Extract-0.86/MYMETA.json Installing /homedir/testing/smoke-me/jkeenan/gh-16300-module-install/lib/perl5/site_perl/5.32.0/amd64-freebsd-thread-multi/.meta/Archive-Extract-0.86/install.json [# So Archive-Extract gets installed, but ... ] [# Skip successful installation of File::pushd ] Building and testing GitHub-Extract-0.02 cp lib/GitHub/Extract.pm blib/lib/GitHub/Extract.pm PERL_DL_NONLAZY=1 "/homedir/testing/smoke-me/jkeenan/gh-16300-module-install/bin/perl" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'inc', 'blib/lib', 'blib/arch')" t/*.t t/01_compile.t .. ok You do not have 'Archive::Zip' installed - Please install it as soon as possible. at /homedir/.cpanm/work/1585792610.34356/GitHub-Extract-0.02/blib/lib/GitHub/Extract.pm line 228. No '/bin/unzip' program found at /homedir/.cpanm/work/1585792610.34356/GitHub-Extract-0.02/blib/lib/GitHub/Extract.pm line 228. Extract failed; no extractors available at /homedir/.cpanm/work/1585792610.34356/GitHub-Extract-0.02/blib/lib/GitHub/Extract.pm line 228. # Failed test 'https://github.com/adamkennedy/PPI/zipball/master' # at t/02_main.t line 51. # Failed test '->extract_path defined' # at t/02_main.t line 56. Use of uninitialized value in -d at t/02_main.t line 57. # Failed test '->extract_path exists' # at t/02_main.t line 57. # Failed test 'Got at least one file' # at t/02_main.t line 61. # Looks like you failed 4 tests of 19. t/02_main.t ..... Dubious, test returned 4 (wstat 1024, 0x400) Failed 4/19 subtests Test Summary Report ------------------- t/02_main.t (Wstat: 1024 Tests: 19 Failed: 4) Failed tests: 11, 15-16, 18 Non-zero exit status: 4 Files=2, Tests=20, 1 wallclock secs ( 0.03 usr 0.00 sys + 0.52 cusr 0.11 csys = 0.66 CPU) Result: FAIL Failed 1/2 test programs. 4/20 subtests failed. *** Error code 4 Stop. make: stopped in /homedir/.cpanm/work/1585792610.34356/GitHub-Extract-0.02 -> FAIL Installing GitHub::Extract failed. See /homedir/.cpanm/work/1585792610.34356/build.log for details. Retry with --force to force install it. ### At line 92 in the excerpt above we are warned that Archive::Zip has not yet been installed, even though Archive::Extract has been! This message appears to come from lib/Archive/Extract.pm: ### 1144 sub _unzip_az { 1145 my $self = shift; 1146 1147 my $use_list = { 'Archive::Zip' => '0.0' }; 1148 unless( can_load( modules => $use_list ) ) { 1149 $self->_error(loc("You do not have '%1' installed - Please " . 1150 "install it as soon as possible.", 'Archive::Zip')); 1151 return METHOD_NA; 1152 } ... ### Here is the context in `lib/GitHub/Extract.pm`: ### 206 sub extract { 207 my $self = shift; 208 my @to = @_; 209 210 # Clear any previous errors 211 delete $self->{_error_msg}; 212 delete $self->{_error_msg_long}; 213 214 # Download the code as a GitHub "zipball" 215 my $url = $self->url; 216 my $tempdir = File::Temp::tempdir( CLEANUP => 1 ); 217 my $archive = File::Spec->catfile( $tempdir, "github-extract.zip" ); 218 my $response = $self->http->mirror( $url, $archive ); 219 unless ( $response->{success} ) { 220 return $self->_error("Failed to download $url"); 221 } 222 $self->{archive} = $archive; 223 224 # Hand off extraction to Archive::Extract 225 local $Archive::Extract::WARN = $WARN; 226 local $Archive::Extract::DEBUG = $DEBUG; 227 $self->{archive_extract} = Archive::Extract->new( archive => $archive ); 228 return $self->{archive_extract}->extract(@to); 229 } ### At line 228 above we're calling Archive::Extract->extract() and getting this warning from that method: ### 449 ### warn something went wrong if we didn't get an extractor 450 unless( $self->_extractor ) { 451 my $diag = $fail ? loc("Extract failed due to errors") : 452 $na ? loc("Extract failed; no extractors available") : 453 ''; ### So, in the absence of an installed Archive::Zip, Archive::Extract is reporting that it cannot locate an extractor. On FreeBSD, however: ### $ which unzip /usr/bin/unzip ### So an extractor is there -- it's just not being found by Archive::Extract. (ISTR encountering this problem some years back.) And why is Archive::Zip not there? Because it's not explicitly require-d by Archive::Extract. It's not Perl 5-core. And in the sequence of CPAN modules I was feeding to `cpanm`, Archive::Zip was not explicitly require-d till farther down in the list. (At that point Archive::Zip was successfully installed. Hence, when I went back to the GitHub-Extract work subdirectory underneath `.cpanm/` and ran `make test`, GitHub-Extract now passed all its tests. I can understand that there may be a reason why Archive::Extract does not mandate Archive::Zip as a prerequisite -- but in that case shouldn't it search harder for extractors? ##### ABOVE NOT SENT ##### It turned out that this problem was extensively researched and discussed by BingOS in https://rt.cpan.org/Ticket/Display.html?id=119905 (which I should have remembered because I filed that ticket!). The problem is that there are various versions of 'unzip'. Archive::Extract needs "INFO-zip" -- a version for which there is a 'Z' command-line switch available. This is available as a *package* on FreeBSD, but it's not the "system" unzip. When you install this package, it gets installed as /usr/local/bin/unzip. Now, notwithstanding the fact that in $PATH /usr/bin/ precedes /usr/local/bin, Archive::Extract as of 0.86 does some fancy heuristics to say that if an 'infozip-esque' 'unzip' is installed, use *that* unzip within the domain of Archive::Extract. Earlier today, I *neither* had Archive::Zip installed on the host in question, *nor* had I installed the infozip-esque 'unzip' package. I installed that package: ##### $ pkg search unzip $ sudo pkg install unzip ##### .... which meant that I now had 2 'unzip's: ##### $ ls -l /usr/bin/unzip /usr/local/bin/unzip -r-xr-xr-x 1 root wheel 22176 Oct 20 2018 /usr/bin/unzip -r-xr-xr-x 1 root wheel 155792 Mar 21 01:15 /usr/local/bin/unzip ##### ... of which /usr/bin/unzip appeared first in $PATH and so was the "system" unzip -- the one lacking the -Z option needed by Archive::Extract. However, once I reviewed RTC 119905, I used 'cpan' to install GitHub::Extract. While I still got the "install Archive::Zip soon" advisory, I no longer got the '/bin/unzip' warning and GitHub::Extract now PASS and installed. I then used 'cpan' to install Archive::Zip, and then to 'test GitHub::Extract'. I no longer got the '/bun/unzip' warning. Thank you very much. Jim Keenan