|
Packit |
0bf95d |
use strict;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# Shared defs for test programs
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# Paths. Must make case-insensitive.
|
|
Packit |
0bf95d |
use File::Temp qw(tempfile tempdir);
|
|
Packit |
0bf95d |
use File::Spec;
|
|
Packit |
0bf95d |
BEGIN { mkdir 'testdir' }
|
|
Packit |
0bf95d |
use constant TESTDIR => do {
|
|
Packit |
0bf95d |
my $tmpdir = File::Spec->abs2rel(tempdir(DIR => 'testdir', CLEANUP => 1));
|
|
Packit |
0bf95d |
$tmpdir =~ s!\\!/!g if $^O eq 'MSWin32';
|
|
Packit |
0bf95d |
$tmpdir
|
|
Packit |
0bf95d |
};
|
|
Packit |
0bf95d |
use constant INPUTZIP =>
|
|
Packit |
0bf95d |
(tempfile('testin-XXXXX', SUFFIX => '.zip', TMPDIR => 1, $^O eq 'MSWin32' ? () : (UNLINK => 1)))[1];
|
|
Packit |
0bf95d |
use constant OUTPUTZIP =>
|
|
Packit |
0bf95d |
(tempfile('testout-XXXXX', SUFFIX => '.zip', TMPDIR => 1, $^O eq 'MSWin32' ? () : (UNLINK => 1)))[1];
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# Do we have the 'zip' and 'unzip' programs?
|
|
Packit |
0bf95d |
# Embed a copy of the module, rather than adding a dependency
|
|
Packit |
0bf95d |
BEGIN {
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
package File::Which;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
use File::Spec;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
my $Is_VMS = ($^O eq 'VMS');
|
|
Packit |
0bf95d |
my $Is_MacOS = ($^O eq 'MacOS');
|
|
Packit |
0bf95d |
my $Is_DOSish =
|
|
Packit |
0bf95d |
(($^O eq 'MSWin32') or ($^O eq 'dos') or ($^O eq 'os2'));
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# For Win32 systems, stores the extensions used for
|
|
Packit |
0bf95d |
# executable files
|
|
Packit |
0bf95d |
# For others, the empty string is used
|
|
Packit |
0bf95d |
# because 'perl' . '' eq 'perl' => easier
|
|
Packit |
0bf95d |
my @path_ext = ('');
|
|
Packit |
0bf95d |
if ($Is_DOSish) {
|
|
Packit |
0bf95d |
if ($ENV{PATHEXT} and $Is_DOSish)
|
|
Packit |
0bf95d |
{ # WinNT. PATHEXT might be set on Cygwin, but not used.
|
|
Packit |
0bf95d |
push @path_ext, split ';', $ENV{PATHEXT};
|
|
Packit |
0bf95d |
} else {
|
|
Packit |
0bf95d |
push @path_ext, qw(.com .exe .bat)
|
|
Packit |
0bf95d |
; # Win9X or other: doesn't have PATHEXT, so needs hardcoded.
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
} elsif ($Is_VMS) {
|
|
Packit |
0bf95d |
push @path_ext, qw(.exe .com);
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
sub which {
|
|
Packit |
0bf95d |
my ($exec) = @_;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
return undef unless $exec;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
my $all = wantarray;
|
|
Packit |
0bf95d |
my @results = ();
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# check for aliases first
|
|
Packit |
0bf95d |
if ($Is_VMS) {
|
|
Packit |
0bf95d |
my $symbol = `SHOW SYMBOL $exec`;
|
|
Packit |
0bf95d |
chomp($symbol);
|
|
Packit |
0bf95d |
if (!$?) {
|
|
Packit |
0bf95d |
return $symbol unless $all;
|
|
Packit |
0bf95d |
push @results, $symbol;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
if ($Is_MacOS) {
|
|
Packit |
0bf95d |
my @aliases = split /\,/, $ENV{Aliases};
|
|
Packit |
0bf95d |
foreach my $alias (@aliases) {
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# This has not been tested!!
|
|
Packit |
0bf95d |
# PPT which says MPW-Perl cannot resolve `Alias $alias`,
|
|
Packit |
0bf95d |
# let's just hope it's fixed
|
|
Packit |
0bf95d |
if (lc($alias) eq lc($exec)) {
|
|
Packit |
0bf95d |
chomp(my $file = `Alias $alias`);
|
|
Packit |
0bf95d |
last unless $file; # if it failed, just go on the normal way
|
|
Packit |
0bf95d |
return $file unless $all;
|
|
Packit |
0bf95d |
push @results, $file;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# we can stop this loop as if it finds more aliases matching,
|
|
Packit |
0bf95d |
# it'll just be the same result anyway
|
|
Packit |
0bf95d |
last;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
my @path = File::Spec->path();
|
|
Packit |
0bf95d |
unshift @path, File::Spec->curdir if $Is_DOSish or $Is_VMS or $Is_MacOS;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
for my $base (map { File::Spec->catfile($_, $exec) } @path) {
|
|
Packit |
0bf95d |
for my $ext (@path_ext) {
|
|
Packit |
0bf95d |
my $file = $base . $ext;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# print STDERR "$file\n";
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
if (
|
|
Packit |
0bf95d |
(
|
|
Packit |
0bf95d |
-x $file or # executable, normal case
|
|
Packit |
0bf95d |
(
|
|
Packit |
0bf95d |
$Is_MacOS
|
|
Packit |
0bf95d |
|| # MacOS doesn't mark as executable so we check -e
|
|
Packit |
0bf95d |
(
|
|
Packit |
0bf95d |
$Is_DOSish
|
|
Packit |
0bf95d |
and grep { $file =~ /$_$/i }
|
|
Packit |
0bf95d |
@path_ext[1 .. $#path_ext])
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# DOSish systems don't pass -x on non-exe/bat/com files.
|
|
Packit |
0bf95d |
# so we check -e. However, we don't want to pass -e on files
|
|
Packit |
0bf95d |
# that aren't in PATHEXT, like README.
|
|
Packit |
0bf95d |
and -e _))
|
|
Packit |
0bf95d |
and !-d _)
|
|
Packit |
0bf95d |
{ # and finally, we don't want dirs to pass (as they are -x)
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# print STDERR "-x: ", -x $file, " -e: ", -e _, " -d: ", -d _, "\n";
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
return $file unless $all;
|
|
Packit |
0bf95d |
push @results, $file; # Make list to return later
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
if ($all) {
|
|
Packit |
0bf95d |
return @results;
|
|
Packit |
0bf95d |
} else {
|
|
Packit |
0bf95d |
return undef;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
use constant HAVEZIP => !!File::Which::which('zip');
|
|
Packit |
0bf95d |
use constant HAVEUNZIP => !!File::Which::which('unzip');
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
use constant ZIP => 'zip ';
|
|
Packit |
0bf95d |
use constant ZIPTEST => 'unzip -t ';
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# 300-character test string
|
|
Packit |
0bf95d |
use constant TESTSTRING => join("\n", 1 .. 102) . "\n";
|
|
Packit |
0bf95d |
use constant TESTSTRINGLENGTH => length(TESTSTRING);
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
use Archive::Zip ();
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# CRC-32 should be ac373f32
|
|
Packit |
0bf95d |
use constant TESTSTRINGCRC => Archive::Zip::computeCRC32(TESTSTRING);
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# This is so that it will work on other systems.
|
|
Packit |
0bf95d |
use constant CAT => $^X . ' -pe "BEGIN{binmode(STDIN);binmode(STDOUT)}"';
|
|
Packit |
0bf95d |
use constant CATPIPE => '| ' . CAT . ' >';
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
use vars qw($zipWorks $testZipDoesntWork $catWorks);
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# Run ZIPTEST to test a zip file.
|
|
Packit |
0bf95d |
sub testZip {
|
|
Packit |
0bf95d |
my $zipName = shift || OUTPUTZIP;
|
|
Packit |
0bf95d |
if ($testZipDoesntWork) {
|
|
Packit |
0bf95d |
return wantarray ? (0, '') : 0;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
my $cmd = ZIPTEST . $zipName . ($^O eq 'MSWin32' ? '' : ' 2>&1');
|
|
Packit |
0bf95d |
my $zipout = `$cmd`;
|
|
Packit |
0bf95d |
return wantarray ? ($?, $zipout) : $?;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# Return the crc-32 of the given file (0 if empty or error)
|
|
Packit |
0bf95d |
sub fileCRC {
|
|
Packit |
0bf95d |
my $fileName = shift;
|
|
Packit |
0bf95d |
local $/ = undef;
|
|
Packit |
0bf95d |
my $fh = IO::File->new($fileName, "r");
|
|
Packit |
0bf95d |
binmode($fh);
|
|
Packit |
0bf95d |
return 0 if not defined($fh);
|
|
Packit |
0bf95d |
my $contents = <$fh>;
|
|
Packit |
0bf95d |
return Archive::Zip::computeCRC32($contents);
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
#--------- check to see if cat works
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
sub testCat {
|
|
Packit |
0bf95d |
my $fh = IO::File->new(CATPIPE . OUTPUTZIP);
|
|
Packit |
0bf95d |
binmode($fh);
|
|
Packit |
0bf95d |
my $testString = pack('C256', 0 .. 255);
|
|
Packit |
0bf95d |
my $testCrc = Archive::Zip::computeCRC32($testString);
|
|
Packit |
0bf95d |
$fh->write($testString, length($testString)) or return 0;
|
|
Packit |
0bf95d |
$fh->close();
|
|
Packit |
0bf95d |
(-f OUTPUTZIP) or return 0;
|
|
Packit |
0bf95d |
my @stat = stat(OUTPUTZIP);
|
|
Packit |
0bf95d |
$stat[7] == length($testString) or return 0;
|
|
Packit |
0bf95d |
fileCRC(OUTPUTZIP) == $testCrc or return 0;
|
|
Packit |
0bf95d |
unlink(OUTPUTZIP);
|
|
Packit |
0bf95d |
return 1;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
BEGIN {
|
|
Packit |
0bf95d |
$catWorks = testCat();
|
|
Packit |
0bf95d |
unless ($catWorks) {
|
|
Packit |
0bf95d |
warn('warning: ', CAT, " doesn't seem to work, may skip some tests");
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
#--------- check to see if zip works (and make INPUTZIP)
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
BEGIN {
|
|
Packit |
0bf95d |
unlink(INPUTZIP);
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# Do we have zip installed?
|
|
Packit |
0bf95d |
if (HAVEZIP) {
|
|
Packit |
0bf95d |
my $cmd = ZIP . INPUTZIP . ' *' . ($^O eq 'MSWin32' ? '' : ' 2>&1');
|
|
Packit |
0bf95d |
my $zipout = `$cmd`;
|
|
Packit |
0bf95d |
$zipWorks = not $?;
|
|
Packit |
0bf95d |
unless ($zipWorks) {
|
|
Packit |
0bf95d |
warn('warning: ', ZIP,
|
|
Packit |
0bf95d |
" doesn't seem to work, may skip some tests");
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
#--------- check to see if unzip -t works
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
BEGIN {
|
|
Packit |
0bf95d |
$testZipDoesntWork = 1;
|
|
Packit |
0bf95d |
if (HAVEUNZIP) {
|
|
Packit |
0bf95d |
my ($status, $zipout) = do { local $testZipDoesntWork = 0; testZip(INPUTZIP) };
|
|
Packit |
0bf95d |
# 9 * 256 = 2304 - the specified zipfiles were not found
|
|
Packit |
0bf95d |
$testZipDoesntWork = (($status == 0 || $status == 2304) ? 0 : 1);
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
# Again, on Win32 no big surprise if this doesn't work
|
|
Packit |
0bf95d |
if ($testZipDoesntWork) {
|
|
Packit |
0bf95d |
warn('warning: ', ZIPTEST,
|
|
Packit |
0bf95d |
" doesn't seem to work, may skip some tests");
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
sub passthrough
|
|
Packit |
0bf95d |
{
|
|
Packit |
0bf95d |
my $fromFile = shift ;
|
|
Packit |
0bf95d |
my $toFile = shift ;
|
|
Packit |
0bf95d |
my $action = shift ;
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
my $z = Archive::Zip->new;
|
|
Packit |
0bf95d |
$z->read($fromFile);
|
|
Packit |
0bf95d |
if ($action)
|
|
Packit |
0bf95d |
{
|
|
Packit |
0bf95d |
for my $member($z->members())
|
|
Packit |
0bf95d |
{
|
|
Packit |
0bf95d |
&$action($member) ;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
$z->writeToFileNamed($toFile);
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
sub readFile
|
|
Packit |
0bf95d |
{
|
|
Packit |
0bf95d |
my $name = shift ;
|
|
Packit |
0bf95d |
local $/;
|
|
Packit |
0bf95d |
open F, "<$name"
|
|
Packit |
0bf95d |
or die "Cannot open $name: $!\n";
|
|
Packit |
0bf95d |
my $data = <F>;
|
|
Packit |
0bf95d |
close F ;
|
|
Packit |
0bf95d |
return $data;
|
|
Packit |
0bf95d |
}
|
|
Packit |
0bf95d |
|
|
Packit |
0bf95d |
1;
|