Initial Commit
This commit is contained in:
153
database/perl/lib/IO/Compress/Adapter/Bzip2.pm
Normal file
153
database/perl/lib/IO/Compress/Adapter/Bzip2.pm
Normal file
@@ -0,0 +1,153 @@
|
||||
package IO::Compress::Adapter::Bzip2 ;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Status);
|
||||
|
||||
use Compress::Raw::Bzip2 2.100 ;
|
||||
|
||||
our ($VERSION);
|
||||
$VERSION = '2.100';
|
||||
|
||||
sub mkCompObject
|
||||
{
|
||||
my $BlockSize100K = shift ;
|
||||
my $WorkFactor = shift ;
|
||||
my $Verbosity = shift ;
|
||||
|
||||
$BlockSize100K = 1 if ! defined $BlockSize100K ;
|
||||
$WorkFactor = 0 if ! defined $WorkFactor ;
|
||||
$Verbosity = 0 if ! defined $Verbosity ;
|
||||
|
||||
my ($def, $status) = Compress::Raw::Bzip2->new(1, $BlockSize100K,
|
||||
$WorkFactor, $Verbosity);
|
||||
|
||||
return (undef, "Could not create Deflate object: $status", $status)
|
||||
if $status != BZ_OK ;
|
||||
|
||||
return bless {'Def' => $def,
|
||||
'Error' => '',
|
||||
'ErrorNo' => 0,
|
||||
} ;
|
||||
}
|
||||
|
||||
sub compr
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
my $status = $def->bzdeflate($_[0], $_[1]) ;
|
||||
$self->{ErrorNo} = $status;
|
||||
|
||||
if ($status != BZ_RUN_OK)
|
||||
{
|
||||
$self->{Error} = "Deflate Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub flush
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
my $status = $def->bzflush($_[0]);
|
||||
$self->{ErrorNo} = $status;
|
||||
|
||||
if ($status != BZ_RUN_OK)
|
||||
{
|
||||
$self->{Error} = "Deflate Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
sub close
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
my $status = $def->bzclose($_[0]);
|
||||
$self->{ErrorNo} = $status;
|
||||
|
||||
if ($status != BZ_STREAM_END)
|
||||
{
|
||||
$self->{Error} = "Deflate Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub reset
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $outer = $self->{Outer};
|
||||
|
||||
my ($def, $status) = Compress::Raw::Bzip2->new();
|
||||
$self->{ErrorNo} = ($status == BZ_OK) ? 0 : $status ;
|
||||
|
||||
if ($status != BZ_OK)
|
||||
{
|
||||
$self->{Error} = "Cannot create Deflate object: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
$self->{Def} = $def;
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub compressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Def}->compressedBytes();
|
||||
}
|
||||
|
||||
sub uncompressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Def}->uncompressedBytes();
|
||||
}
|
||||
|
||||
#sub total_out
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# 0;
|
||||
#}
|
||||
#
|
||||
|
||||
#sub total_in
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# $self->{Def}->total_in();
|
||||
#}
|
||||
#
|
||||
#sub crc32
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# $self->{Def}->crc32();
|
||||
#}
|
||||
#
|
||||
#sub adler32
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# $self->{Def}->adler32();
|
||||
#}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
169
database/perl/lib/IO/Compress/Adapter/Deflate.pm
Normal file
169
database/perl/lib/IO/Compress/Adapter/Deflate.pm
Normal file
@@ -0,0 +1,169 @@
|
||||
package IO::Compress::Adapter::Deflate ;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Status);
|
||||
use Compress::Raw::Zlib 2.100 qw( !crc32 !adler32 ) ;
|
||||
|
||||
require Exporter;
|
||||
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, @EXPORT, %DEFLATE_CONSTANTS);
|
||||
|
||||
$VERSION = '2.100';
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT_OK = @Compress::Raw::Zlib::DEFLATE_CONSTANTS;
|
||||
%EXPORT_TAGS = %Compress::Raw::Zlib::DEFLATE_CONSTANTS;
|
||||
@EXPORT = @EXPORT_OK;
|
||||
%DEFLATE_CONSTANTS = %EXPORT_TAGS ;
|
||||
|
||||
sub mkCompObject
|
||||
{
|
||||
my $crc32 = shift ;
|
||||
my $adler32 = shift ;
|
||||
my $level = shift ;
|
||||
my $strategy = shift ;
|
||||
|
||||
my ($def, $status) = Compress::Raw::Zlib::Deflate->new(
|
||||
-AppendOutput => 1,
|
||||
-CRC32 => $crc32,
|
||||
-ADLER32 => $adler32,
|
||||
-Level => $level,
|
||||
-Strategy => $strategy,
|
||||
-WindowBits => - MAX_WBITS);
|
||||
|
||||
return (undef, "Cannot create Deflate object: $status", $status)
|
||||
if $status != Z_OK;
|
||||
|
||||
return bless {'Def' => $def,
|
||||
'Error' => '',
|
||||
} ;
|
||||
}
|
||||
|
||||
sub compr
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
my $status = $def->deflate($_[0], $_[1]) ;
|
||||
$self->{ErrorNo} = $status;
|
||||
|
||||
if ($status != Z_OK)
|
||||
{
|
||||
$self->{Error} = "Deflate Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub flush
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
my $opt = $_[1] || Z_FINISH;
|
||||
my $status = $def->flush($_[0], $opt);
|
||||
$self->{ErrorNo} = $status;
|
||||
|
||||
if ($status != Z_OK)
|
||||
{
|
||||
$self->{Error} = "Deflate Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub close
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
$def->flush($_[0], Z_FINISH)
|
||||
if defined $def ;
|
||||
}
|
||||
|
||||
sub reset
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
my $status = $def->deflateReset() ;
|
||||
$self->{ErrorNo} = $status;
|
||||
if ($status != Z_OK)
|
||||
{
|
||||
$self->{Error} = "Deflate Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub deflateParams
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my $def = $self->{Def};
|
||||
|
||||
my $status = $def->deflateParams(@_);
|
||||
$self->{ErrorNo} = $status;
|
||||
if ($status != Z_OK)
|
||||
{
|
||||
$self->{Error} = "deflateParams Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#sub total_out
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# $self->{Def}->total_out();
|
||||
#}
|
||||
#
|
||||
#sub total_in
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# $self->{Def}->total_in();
|
||||
#}
|
||||
|
||||
sub compressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
$self->{Def}->compressedBytes();
|
||||
}
|
||||
|
||||
sub uncompressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Def}->uncompressedBytes();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
sub crc32
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Def}->crc32();
|
||||
}
|
||||
|
||||
sub adler32
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Def}->adler32();
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
100
database/perl/lib/IO/Compress/Adapter/Identity.pm
Normal file
100
database/perl/lib/IO/Compress/Adapter/Identity.pm
Normal file
@@ -0,0 +1,100 @@
|
||||
package IO::Compress::Adapter::Identity ;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Status);
|
||||
our ($VERSION);
|
||||
|
||||
$VERSION = '2.100';
|
||||
|
||||
sub mkCompObject
|
||||
{
|
||||
my $level = shift ;
|
||||
my $strategy = shift ;
|
||||
|
||||
return bless {
|
||||
'CompSize' => 0,
|
||||
'UnCompSize' => 0,
|
||||
'Error' => '',
|
||||
'ErrorNo' => 0,
|
||||
} ;
|
||||
}
|
||||
|
||||
sub compr
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
if (defined ${ $_[0] } && length ${ $_[0] }) {
|
||||
$self->{CompSize} += length ${ $_[0] } ;
|
||||
$self->{UnCompSize} = $self->{CompSize} ;
|
||||
|
||||
if ( ref $_[1] )
|
||||
{ ${ $_[1] } .= ${ $_[0] } }
|
||||
else
|
||||
{ $_[1] .= ${ $_[0] } }
|
||||
}
|
||||
|
||||
return STATUS_OK ;
|
||||
}
|
||||
|
||||
sub flush
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub close
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub reset
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
$self->{CompSize} = 0;
|
||||
$self->{UnCompSize} = 0;
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
sub deflateParams
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
#sub total_out
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# return $self->{UnCompSize} ;
|
||||
#}
|
||||
#
|
||||
#sub total_in
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# return $self->{UnCompSize} ;
|
||||
#}
|
||||
|
||||
sub compressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
return $self->{UnCompSize} ;
|
||||
}
|
||||
|
||||
sub uncompressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
return $self->{UnCompSize} ;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
__END__
|
||||
1057
database/perl/lib/IO/Compress/Base.pm
Normal file
1057
database/perl/lib/IO/Compress/Base.pm
Normal file
File diff suppressed because it is too large
Load Diff
1053
database/perl/lib/IO/Compress/Base/Common.pm
Normal file
1053
database/perl/lib/IO/Compress/Base/Common.pm
Normal file
File diff suppressed because it is too large
Load Diff
824
database/perl/lib/IO/Compress/Bzip2.pm
Normal file
824
database/perl/lib/IO/Compress/Bzip2.pm
Normal file
@@ -0,0 +1,824 @@
|
||||
package IO::Compress::Bzip2 ;
|
||||
|
||||
use strict ;
|
||||
use warnings;
|
||||
use bytes;
|
||||
require Exporter ;
|
||||
|
||||
use IO::Compress::Base 2.100 ;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw();
|
||||
use IO::Compress::Adapter::Bzip2 2.100 ;
|
||||
|
||||
|
||||
|
||||
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $Bzip2Error);
|
||||
|
||||
$VERSION = '2.100';
|
||||
$Bzip2Error = '';
|
||||
|
||||
@ISA = qw(IO::Compress::Base Exporter);
|
||||
@EXPORT_OK = qw( $Bzip2Error bzip2 ) ;
|
||||
%EXPORT_TAGS = %IO::Compress::Base::EXPORT_TAGS ;
|
||||
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
|
||||
Exporter::export_ok_tags('all');
|
||||
|
||||
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift ;
|
||||
|
||||
my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$Bzip2Error);
|
||||
return $obj->_create(undef, @_);
|
||||
}
|
||||
|
||||
sub bzip2
|
||||
{
|
||||
my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$Bzip2Error);
|
||||
$obj->_def(@_);
|
||||
}
|
||||
|
||||
|
||||
sub mkHeader
|
||||
{
|
||||
my $self = shift ;
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
sub getExtraParams
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Parse);
|
||||
|
||||
return (
|
||||
'blocksize100k' => [IO::Compress::Base::Common::Parse_unsigned, 1],
|
||||
'workfactor' => [IO::Compress::Base::Common::Parse_unsigned, 0],
|
||||
'verbosity' => [IO::Compress::Base::Common::Parse_boolean, 0],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub ckParams
|
||||
{
|
||||
my $self = shift ;
|
||||
my $got = shift;
|
||||
|
||||
# check that BlockSize100K is a number between 1 & 9
|
||||
if ($got->parsed('blocksize100k')) {
|
||||
my $value = $got->getValue('blocksize100k');
|
||||
return $self->saveErrorString(undef, "Parameter 'BlockSize100K' not between 1 and 9, got $value")
|
||||
unless defined $value && $value >= 1 && $value <= 9;
|
||||
|
||||
}
|
||||
|
||||
# check that WorkFactor between 0 & 250
|
||||
if ($got->parsed('workfactor')) {
|
||||
my $value = $got->getValue('workfactor');
|
||||
return $self->saveErrorString(undef, "Parameter 'WorkFactor' not between 0 and 250, got $value")
|
||||
unless $value >= 0 && $value <= 250;
|
||||
}
|
||||
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
|
||||
sub mkComp
|
||||
{
|
||||
my $self = shift ;
|
||||
my $got = shift ;
|
||||
|
||||
my $BlockSize100K = $got->getValue('blocksize100k');
|
||||
my $WorkFactor = $got->getValue('workfactor');
|
||||
my $Verbosity = $got->getValue('verbosity');
|
||||
|
||||
my ($obj, $errstr, $errno) = IO::Compress::Adapter::Bzip2::mkCompObject(
|
||||
$BlockSize100K, $WorkFactor,
|
||||
$Verbosity);
|
||||
|
||||
return $self->saveErrorString(undef, $errstr, $errno)
|
||||
if ! defined $obj;
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
|
||||
sub mkTrailer
|
||||
{
|
||||
my $self = shift ;
|
||||
return '';
|
||||
}
|
||||
|
||||
sub mkFinalTrailer
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
#sub newHeader
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# return '';
|
||||
#}
|
||||
|
||||
sub getInverseClass
|
||||
{
|
||||
return ('IO::Uncompress::Bunzip2');
|
||||
}
|
||||
|
||||
sub getFileInfo
|
||||
{
|
||||
my $self = shift ;
|
||||
my $params = shift;
|
||||
my $file = shift ;
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Compress::Bzip2 - Write bzip2 files/buffers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
|
||||
|
||||
my $status = bzip2 $input => $output [,OPTS]
|
||||
or die "bzip2 failed: $Bzip2Error\n";
|
||||
|
||||
my $z = IO::Compress::Bzip2->new( $output [,OPTS] )
|
||||
or die "bzip2 failed: $Bzip2Error\n";
|
||||
|
||||
$z->print($string);
|
||||
$z->printf($format, $string);
|
||||
$z->write($string);
|
||||
$z->syswrite($string [, $length, $offset]);
|
||||
$z->flush();
|
||||
$z->tell();
|
||||
$z->eof();
|
||||
$z->seek($position, $whence);
|
||||
$z->binmode();
|
||||
$z->fileno();
|
||||
$z->opened();
|
||||
$z->autoflush();
|
||||
$z->input_line_number();
|
||||
$z->newStream( [OPTS] );
|
||||
|
||||
$z->close() ;
|
||||
|
||||
$Bzip2Error ;
|
||||
|
||||
# IO::File mode
|
||||
|
||||
print $z $string;
|
||||
printf $z $format, $string;
|
||||
tell $z
|
||||
eof $z
|
||||
seek $z, $position, $whence
|
||||
binmode $z
|
||||
fileno $z
|
||||
close $z ;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module provides a Perl interface that allows writing bzip2
|
||||
compressed data to files or buffer.
|
||||
|
||||
For reading bzip2 files/buffers, see the companion module
|
||||
L<IO::Uncompress::Bunzip2|IO::Uncompress::Bunzip2>.
|
||||
|
||||
=head1 Functional Interface
|
||||
|
||||
A top-level function, C<bzip2>, is provided to carry out
|
||||
"one-shot" compression between buffers and/or files. For finer
|
||||
control over the compression process, see the L</"OO Interface">
|
||||
section.
|
||||
|
||||
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
|
||||
|
||||
bzip2 $input_filename_or_reference => $output_filename_or_reference [,OPTS]
|
||||
or die "bzip2 failed: $Bzip2Error\n";
|
||||
|
||||
The functional interface needs Perl5.005 or better.
|
||||
|
||||
=head2 bzip2 $input_filename_or_reference => $output_filename_or_reference [, OPTS]
|
||||
|
||||
C<bzip2> expects at least two parameters,
|
||||
C<$input_filename_or_reference> and C<$output_filename_or_reference>
|
||||
and zero or more optional parameters (see L</Optional Parameters>)
|
||||
|
||||
=head3 The C<$input_filename_or_reference> parameter
|
||||
|
||||
The parameter, C<$input_filename_or_reference>, is used to define the
|
||||
source of the uncompressed data.
|
||||
|
||||
It can take one of the following forms:
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is a simple scalar, it is
|
||||
assumed to be a filename. This file will be opened for reading and the
|
||||
input data will be read from it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is a filehandle, the input
|
||||
data will be read from it. The string '-' can be used as an alias for
|
||||
standard input.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$input_filename_or_reference> is a scalar reference, the input data
|
||||
will be read from C<$$input_filename_or_reference>.
|
||||
|
||||
=item An array reference
|
||||
|
||||
If C<$input_filename_or_reference> is an array reference, each element in
|
||||
the array must be a filename.
|
||||
|
||||
The input data will be read from each file in turn.
|
||||
|
||||
The complete array will be walked to ensure that it only
|
||||
contains valid filenames before any data is compressed.
|
||||
|
||||
=item An Input FileGlob string
|
||||
|
||||
If C<$input_filename_or_reference> is a string that is delimited by the
|
||||
characters "<" and ">" C<bzip2> will assume that it is an
|
||||
I<input fileglob string>. The input is the list of files that match the
|
||||
fileglob.
|
||||
|
||||
See L<File::GlobMapper|File::GlobMapper> for more details.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is any other type,
|
||||
C<undef> will be returned.
|
||||
|
||||
=head3 The C<$output_filename_or_reference> parameter
|
||||
|
||||
The parameter C<$output_filename_or_reference> is used to control the
|
||||
destination of the compressed data. This parameter can take one of
|
||||
these forms.
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is a simple scalar, it is
|
||||
assumed to be a filename. This file will be opened for writing and the
|
||||
compressed data will be written to it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is a filehandle, the
|
||||
compressed data will be written to it. The string '-' can be used as
|
||||
an alias for standard output.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$output_filename_or_reference> is a scalar reference, the
|
||||
compressed data will be stored in C<$$output_filename_or_reference>.
|
||||
|
||||
=item An Array Reference
|
||||
|
||||
If C<$output_filename_or_reference> is an array reference,
|
||||
the compressed data will be pushed onto the array.
|
||||
|
||||
=item An Output FileGlob
|
||||
|
||||
If C<$output_filename_or_reference> is a string that is delimited by the
|
||||
characters "<" and ">" C<bzip2> will assume that it is an
|
||||
I<output fileglob string>. The output is the list of files that match the
|
||||
fileglob.
|
||||
|
||||
When C<$output_filename_or_reference> is an fileglob string,
|
||||
C<$input_filename_or_reference> must also be a fileglob string. Anything
|
||||
else is an error.
|
||||
|
||||
See L<File::GlobMapper|File::GlobMapper> for more details.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is any other type,
|
||||
C<undef> will be returned.
|
||||
|
||||
=head2 Notes
|
||||
|
||||
When C<$input_filename_or_reference> maps to multiple files/buffers and
|
||||
C<$output_filename_or_reference> is a single
|
||||
file/buffer the input files/buffers will be stored
|
||||
in C<$output_filename_or_reference> as a concatenated series of compressed data streams.
|
||||
|
||||
=head2 Optional Parameters
|
||||
|
||||
The optional parameters for the one-shot function C<bzip2>
|
||||
are (for the most part) identical to those used with the OO interface defined in the
|
||||
L</"Constructor Options"> section. The exceptions are listed below
|
||||
|
||||
=over 5
|
||||
|
||||
=item C<< AutoClose => 0|1 >>
|
||||
|
||||
This option applies to any input or output data streams to
|
||||
C<bzip2> that are filehandles.
|
||||
|
||||
If C<AutoClose> is specified, and the value is true, it will result in all
|
||||
input and/or output filehandles being closed once C<bzip2> has
|
||||
completed.
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< BinModeIn => 0|1 >>
|
||||
|
||||
This option is now a no-op. All files will be read in binmode.
|
||||
|
||||
=item C<< Append => 0|1 >>
|
||||
|
||||
The behaviour of this option is dependent on the type of output data
|
||||
stream.
|
||||
|
||||
=over 5
|
||||
|
||||
=item * A Buffer
|
||||
|
||||
If C<Append> is enabled, all compressed data will be append to the end of
|
||||
the output buffer. Otherwise the output buffer will be cleared before any
|
||||
compressed data is written to it.
|
||||
|
||||
=item * A Filename
|
||||
|
||||
If C<Append> is enabled, the file will be opened in append mode. Otherwise
|
||||
the contents of the file, if any, will be truncated before any compressed
|
||||
data is written to it.
|
||||
|
||||
=item * A Filehandle
|
||||
|
||||
If C<Append> is enabled, the filehandle will be positioned to the end of
|
||||
the file via a call to C<seek> before any compressed data is
|
||||
written to it. Otherwise the file pointer will not be moved.
|
||||
|
||||
=back
|
||||
|
||||
When C<Append> is specified, and set to true, it will I<append> all compressed
|
||||
data to the output data stream.
|
||||
|
||||
So when the output is a filehandle it will carry out a seek to the eof
|
||||
before writing any compressed data. If the output is a filename, it will be opened for
|
||||
appending. If the output is a buffer, all compressed data will be
|
||||
appended to the existing buffer.
|
||||
|
||||
Conversely when C<Append> is not specified, or it is present and is set to
|
||||
false, it will operate as follows.
|
||||
|
||||
When the output is a filename, it will truncate the contents of the file
|
||||
before writing any compressed data. If the output is a filehandle
|
||||
its position will not be changed. If the output is a buffer, it will be
|
||||
wiped before any compressed data is output.
|
||||
|
||||
Defaults to 0.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Examples
|
||||
|
||||
Here are a few example that show the capabilities of the module.
|
||||
|
||||
=head3 Streaming
|
||||
|
||||
This very simple command line example demonstrates the streaming capabilities of the module.
|
||||
The code reads data from STDIN, compresses it, and writes the compressed data to STDOUT.
|
||||
|
||||
$ echo hello world | perl -MIO::Compress::Bzip2=bzip2 -e 'bzip2 \*STDIN => \*STDOUT' >output.bz2
|
||||
|
||||
The special filename "-" can be used as a standin for both C<\*STDIN> and C<\*STDOUT>,
|
||||
so the above can be rewritten as
|
||||
|
||||
$ echo hello world | perl -MIO::Compress::Bzip2=bzip2 -e 'bzip2 "-" => "-"' >output.bz2
|
||||
|
||||
=head3 Compressing a file from the filesystem
|
||||
|
||||
To read the contents of the file C<file1.txt> and write the compressed
|
||||
data to the file C<file1.txt.bz2>.
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
|
||||
|
||||
my $input = "file1.txt";
|
||||
bzip2 $input => "$input.bz2"
|
||||
or die "bzip2 failed: $Bzip2Error\n";
|
||||
|
||||
=head3 Reading from a Filehandle and writing to an in-memory buffer
|
||||
|
||||
To read from an existing Perl filehandle, C<$input>, and write the
|
||||
compressed data to a buffer, C<$buffer>.
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
|
||||
use IO::File ;
|
||||
|
||||
my $input = IO::File->new( "<file1.txt" )
|
||||
or die "Cannot open 'file1.txt': $!\n" ;
|
||||
my $buffer ;
|
||||
bzip2 $input => \$buffer
|
||||
or die "bzip2 failed: $Bzip2Error\n";
|
||||
|
||||
=head3 Compressing multiple files
|
||||
|
||||
To compress all files in the directory "/my/home" that match "*.txt"
|
||||
and store the compressed data in the same directory
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
|
||||
|
||||
bzip2 '</my/home/*.txt>' => '<*.bz2>'
|
||||
or die "bzip2 failed: $Bzip2Error\n";
|
||||
|
||||
and if you want to compress each file one at a time, this will do the trick
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
|
||||
|
||||
for my $input ( glob "/my/home/*.txt" )
|
||||
{
|
||||
my $output = "$input.bz2" ;
|
||||
bzip2 $input => $output
|
||||
or die "Error compressing '$input': $Bzip2Error\n";
|
||||
}
|
||||
|
||||
=head1 OO Interface
|
||||
|
||||
=head2 Constructor
|
||||
|
||||
The format of the constructor for C<IO::Compress::Bzip2> is shown below
|
||||
|
||||
my $z = IO::Compress::Bzip2->new( $output [,OPTS] )
|
||||
or die "IO::Compress::Bzip2 failed: $Bzip2Error\n";
|
||||
|
||||
It returns an C<IO::Compress::Bzip2> object on success and undef on failure.
|
||||
The variable C<$Bzip2Error> will contain an error message on failure.
|
||||
|
||||
If you are running Perl 5.005 or better the object, C<$z>, returned from
|
||||
IO::Compress::Bzip2 can be used exactly like an L<IO::File|IO::File> filehandle.
|
||||
This means that all normal output file operations can be carried out
|
||||
with C<$z>.
|
||||
For example, to write to a compressed file/buffer you can use either of
|
||||
these forms
|
||||
|
||||
$z->print("hello world\n");
|
||||
print $z "hello world\n";
|
||||
|
||||
The mandatory parameter C<$output> is used to control the destination
|
||||
of the compressed data. This parameter can take one of these forms.
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$output> parameter is a simple scalar, it is assumed to be a
|
||||
filename. This file will be opened for writing and the compressed data
|
||||
will be written to it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$output> parameter is a filehandle, the compressed data will be
|
||||
written to it.
|
||||
The string '-' can be used as an alias for standard output.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$output> is a scalar reference, the compressed data will be stored
|
||||
in C<$$output>.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$output> parameter is any other type, C<IO::Compress::Bzip2>::new will
|
||||
return undef.
|
||||
|
||||
=head2 Constructor Options
|
||||
|
||||
C<OPTS> is any combination of zero or more the following options:
|
||||
|
||||
=over 5
|
||||
|
||||
=item C<< AutoClose => 0|1 >>
|
||||
|
||||
This option is only valid when the C<$output> parameter is a filehandle. If
|
||||
specified, and the value is true, it will result in the C<$output> being
|
||||
closed once either the C<close> method is called or the C<IO::Compress::Bzip2>
|
||||
object is destroyed.
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< Append => 0|1 >>
|
||||
|
||||
Opens C<$output> in append mode.
|
||||
|
||||
The behaviour of this option is dependent on the type of C<$output>.
|
||||
|
||||
=over 5
|
||||
|
||||
=item * A Buffer
|
||||
|
||||
If C<$output> is a buffer and C<Append> is enabled, all compressed data
|
||||
will be append to the end of C<$output>. Otherwise C<$output> will be
|
||||
cleared before any data is written to it.
|
||||
|
||||
=item * A Filename
|
||||
|
||||
If C<$output> is a filename and C<Append> is enabled, the file will be
|
||||
opened in append mode. Otherwise the contents of the file, if any, will be
|
||||
truncated before any compressed data is written to it.
|
||||
|
||||
=item * A Filehandle
|
||||
|
||||
If C<$output> is a filehandle, the file pointer will be positioned to the
|
||||
end of the file via a call to C<seek> before any compressed data is written
|
||||
to it. Otherwise the file pointer will not be moved.
|
||||
|
||||
=back
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< BlockSize100K => number >>
|
||||
|
||||
Specify the number of 100K blocks bzip2 uses during compression.
|
||||
|
||||
Valid values are from 1 to 9, where 9 is best compression.
|
||||
|
||||
The default is 1.
|
||||
|
||||
=item C<< WorkFactor => number >>
|
||||
|
||||
Specifies how much effort bzip2 should take before resorting to a slower
|
||||
fallback compression algorithm.
|
||||
|
||||
Valid values range from 0 to 250, where 0 means use the default value 30.
|
||||
|
||||
The default is 0.
|
||||
|
||||
=item C<< Strict => 0|1 >>
|
||||
|
||||
This is a placeholder option.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Examples
|
||||
|
||||
TODO
|
||||
|
||||
=head1 Methods
|
||||
|
||||
=head2 print
|
||||
|
||||
Usage is
|
||||
|
||||
$z->print($data)
|
||||
print $z $data
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter. This
|
||||
has the same behaviour as the C<print> built-in.
|
||||
|
||||
Returns true if successful.
|
||||
|
||||
=head2 printf
|
||||
|
||||
Usage is
|
||||
|
||||
$z->printf($format, $data)
|
||||
printf $z $format, $data
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter.
|
||||
|
||||
Returns true if successful.
|
||||
|
||||
=head2 syswrite
|
||||
|
||||
Usage is
|
||||
|
||||
$z->syswrite $data
|
||||
$z->syswrite $data, $length
|
||||
$z->syswrite $data, $length, $offset
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter.
|
||||
|
||||
Returns the number of uncompressed bytes written, or C<undef> if
|
||||
unsuccessful.
|
||||
|
||||
=head2 write
|
||||
|
||||
Usage is
|
||||
|
||||
$z->write $data
|
||||
$z->write $data, $length
|
||||
$z->write $data, $length, $offset
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter.
|
||||
|
||||
Returns the number of uncompressed bytes written, or C<undef> if
|
||||
unsuccessful.
|
||||
|
||||
=head2 flush
|
||||
|
||||
Usage is
|
||||
|
||||
$z->flush;
|
||||
|
||||
Flushes any pending compressed data to the output file/buffer.
|
||||
|
||||
TODO
|
||||
|
||||
Returns true on success.
|
||||
|
||||
=head2 tell
|
||||
|
||||
Usage is
|
||||
|
||||
$z->tell()
|
||||
tell $z
|
||||
|
||||
Returns the uncompressed file offset.
|
||||
|
||||
=head2 eof
|
||||
|
||||
Usage is
|
||||
|
||||
$z->eof();
|
||||
eof($z);
|
||||
|
||||
Returns true if the C<close> method has been called.
|
||||
|
||||
=head2 seek
|
||||
|
||||
$z->seek($position, $whence);
|
||||
seek($z, $position, $whence);
|
||||
|
||||
Provides a sub-set of the C<seek> functionality, with the restriction
|
||||
that it is only legal to seek forward in the output file/buffer.
|
||||
It is a fatal error to attempt to seek backward.
|
||||
|
||||
Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
|
||||
|
||||
The C<$whence> parameter takes one the usual values, namely SEEK_SET,
|
||||
SEEK_CUR or SEEK_END.
|
||||
|
||||
Returns 1 on success, 0 on failure.
|
||||
|
||||
=head2 binmode
|
||||
|
||||
Usage is
|
||||
|
||||
$z->binmode
|
||||
binmode $z ;
|
||||
|
||||
This is a noop provided for completeness.
|
||||
|
||||
=head2 opened
|
||||
|
||||
$z->opened()
|
||||
|
||||
Returns true if the object currently refers to a opened file/buffer.
|
||||
|
||||
=head2 autoflush
|
||||
|
||||
my $prev = $z->autoflush()
|
||||
my $prev = $z->autoflush(EXPR)
|
||||
|
||||
If the C<$z> object is associated with a file or a filehandle, this method
|
||||
returns the current autoflush setting for the underlying filehandle. If
|
||||
C<EXPR> is present, and is non-zero, it will enable flushing after every
|
||||
write/print operation.
|
||||
|
||||
If C<$z> is associated with a buffer, this method has no effect and always
|
||||
returns C<undef>.
|
||||
|
||||
B<Note> that the special variable C<$|> B<cannot> be used to set or
|
||||
retrieve the autoflush setting.
|
||||
|
||||
=head2 input_line_number
|
||||
|
||||
$z->input_line_number()
|
||||
$z->input_line_number(EXPR)
|
||||
|
||||
This method always returns C<undef> when compressing.
|
||||
|
||||
=head2 fileno
|
||||
|
||||
$z->fileno()
|
||||
fileno($z)
|
||||
|
||||
If the C<$z> object is associated with a file or a filehandle, C<fileno>
|
||||
will return the underlying file descriptor. Once the C<close> method is
|
||||
called C<fileno> will return C<undef>.
|
||||
|
||||
If the C<$z> object is associated with a buffer, this method will return
|
||||
C<undef>.
|
||||
|
||||
=head2 close
|
||||
|
||||
$z->close() ;
|
||||
close $z ;
|
||||
|
||||
Flushes any pending compressed data and then closes the output file/buffer.
|
||||
|
||||
For most versions of Perl this method will be automatically invoked if
|
||||
the IO::Compress::Bzip2 object is destroyed (either explicitly or by the
|
||||
variable with the reference to the object going out of scope). The
|
||||
exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
|
||||
these cases, the C<close> method will be called automatically, but
|
||||
not until global destruction of all live objects when the program is
|
||||
terminating.
|
||||
|
||||
Therefore, if you want your scripts to be able to run on all versions
|
||||
of Perl, you should call C<close> explicitly and not rely on automatic
|
||||
closing.
|
||||
|
||||
Returns true on success, otherwise 0.
|
||||
|
||||
If the C<AutoClose> option has been enabled when the IO::Compress::Bzip2
|
||||
object was created, and the object is associated with a file, the
|
||||
underlying file will also be closed.
|
||||
|
||||
=head2 newStream([OPTS])
|
||||
|
||||
Usage is
|
||||
|
||||
$z->newStream( [OPTS] )
|
||||
|
||||
Closes the current compressed data stream and starts a new one.
|
||||
|
||||
OPTS consists of any of the options that are available when creating
|
||||
the C<$z> object.
|
||||
|
||||
See the L</"Constructor Options"> section for more details.
|
||||
|
||||
=head1 Importing
|
||||
|
||||
No symbolic constants are required by IO::Compress::Bzip2 at present.
|
||||
|
||||
=over 5
|
||||
|
||||
=item :all
|
||||
|
||||
Imports C<bzip2> and C<$Bzip2Error>.
|
||||
Same as doing this
|
||||
|
||||
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
=head2 Apache::GZip Revisited
|
||||
|
||||
See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
|
||||
|
||||
=head2 Working with Net::FTP
|
||||
|
||||
See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
General feedback/questions/bug reports should be sent to
|
||||
L<https://github.com/pmqs/IO-Compress/issues> (preferred) or
|
||||
L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzip>, L<IO::Uncompress::UnLzip>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Compress::Zstd>, L<IO::Uncompress::UnZstd>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
|
||||
|
||||
L<IO::Compress::FAQ|IO::Compress::FAQ>
|
||||
|
||||
L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
|
||||
L<Archive::Tar|Archive::Tar>,
|
||||
L<IO::Zlib|IO::Zlib>
|
||||
|
||||
The primary site for the bzip2 program is L<https://sourceware.org/bzip2/>.
|
||||
|
||||
See the module L<Compress::Bzip2|Compress::Bzip2>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
This module was written by Paul Marquess, C<pmqs@cpan.org>.
|
||||
|
||||
=head1 MODIFICATION HISTORY
|
||||
|
||||
See the Changes file.
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (c) 2005-2021 Paul Marquess. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
958
database/perl/lib/IO/Compress/Deflate.pm
Normal file
958
database/perl/lib/IO/Compress/Deflate.pm
Normal file
@@ -0,0 +1,958 @@
|
||||
package IO::Compress::Deflate ;
|
||||
|
||||
require 5.006 ;
|
||||
|
||||
use strict ;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
require Exporter ;
|
||||
|
||||
use IO::Compress::RawDeflate 2.100 ();
|
||||
use IO::Compress::Adapter::Deflate 2.100 ;
|
||||
|
||||
use IO::Compress::Zlib::Constants 2.100 ;
|
||||
use IO::Compress::Base::Common 2.100 qw();
|
||||
|
||||
|
||||
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $DeflateError);
|
||||
|
||||
$VERSION = '2.100';
|
||||
$DeflateError = '';
|
||||
|
||||
@ISA = qw(IO::Compress::RawDeflate Exporter);
|
||||
@EXPORT_OK = qw( $DeflateError deflate ) ;
|
||||
%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
|
||||
|
||||
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
|
||||
Exporter::export_ok_tags('all');
|
||||
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift ;
|
||||
|
||||
my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$DeflateError);
|
||||
return $obj->_create(undef, @_);
|
||||
}
|
||||
|
||||
sub deflate
|
||||
{
|
||||
my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$DeflateError);
|
||||
return $obj->_def(@_);
|
||||
}
|
||||
|
||||
|
||||
sub bitmask($$$$)
|
||||
{
|
||||
my $into = shift ;
|
||||
my $value = shift ;
|
||||
my $offset = shift ;
|
||||
my $mask = shift ;
|
||||
|
||||
return $into | (($value & $mask) << $offset ) ;
|
||||
}
|
||||
|
||||
sub mkDeflateHdr($$$;$)
|
||||
{
|
||||
my $method = shift ;
|
||||
my $cinfo = shift;
|
||||
my $level = shift;
|
||||
my $fdict_adler = shift ;
|
||||
|
||||
my $cmf = 0;
|
||||
my $flg = 0;
|
||||
my $fdict = 0;
|
||||
$fdict = 1 if defined $fdict_adler;
|
||||
|
||||
$cmf = bitmask($cmf, $method, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS);
|
||||
$cmf = bitmask($cmf, $cinfo, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS);
|
||||
|
||||
$flg = bitmask($flg, $fdict, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS);
|
||||
$flg = bitmask($flg, $level, ZLIB_FLG_LEVEL_OFFSET, ZLIB_FLG_LEVEL_BITS);
|
||||
|
||||
my $fcheck = 31 - ($cmf * 256 + $flg) % 31 ;
|
||||
$flg = bitmask($flg, $fcheck, ZLIB_FLG_FCHECK_OFFSET, ZLIB_FLG_FCHECK_BITS);
|
||||
|
||||
my $hdr = pack("CC", $cmf, $flg) ;
|
||||
$hdr .= pack("N", $fdict_adler) if $fdict ;
|
||||
|
||||
return $hdr;
|
||||
}
|
||||
|
||||
sub mkHeader
|
||||
{
|
||||
my $self = shift ;
|
||||
my $param = shift ;
|
||||
|
||||
my $level = $param->getValue('level');
|
||||
my $strategy = $param->getValue('strategy');
|
||||
|
||||
my $lflag ;
|
||||
$level = 6
|
||||
if $level == Z_DEFAULT_COMPRESSION ;
|
||||
|
||||
if (ZLIB_VERNUM >= 0x1210)
|
||||
{
|
||||
if ($strategy >= Z_HUFFMAN_ONLY || $level < 2)
|
||||
{ $lflag = ZLIB_FLG_LEVEL_FASTEST }
|
||||
elsif ($level < 6)
|
||||
{ $lflag = ZLIB_FLG_LEVEL_FAST }
|
||||
elsif ($level == 6)
|
||||
{ $lflag = ZLIB_FLG_LEVEL_DEFAULT }
|
||||
else
|
||||
{ $lflag = ZLIB_FLG_LEVEL_SLOWEST }
|
||||
}
|
||||
else
|
||||
{
|
||||
$lflag = ($level - 1) >> 1 ;
|
||||
$lflag = 3 if $lflag > 3 ;
|
||||
}
|
||||
|
||||
#my $wbits = (MAX_WBITS - 8) << 4 ;
|
||||
my $wbits = 7;
|
||||
mkDeflateHdr(ZLIB_CMF_CM_DEFLATED, $wbits, $lflag);
|
||||
}
|
||||
|
||||
sub ckParams
|
||||
{
|
||||
my $self = shift ;
|
||||
my $got = shift;
|
||||
|
||||
$got->setValue('adler32' => 1);
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
|
||||
sub mkTrailer
|
||||
{
|
||||
my $self = shift ;
|
||||
return pack("N", *$self->{Compress}->adler32()) ;
|
||||
}
|
||||
|
||||
sub mkFinalTrailer
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
#sub newHeader
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# return *$self->{Header};
|
||||
#}
|
||||
|
||||
sub getExtraParams
|
||||
{
|
||||
my $self = shift ;
|
||||
return $self->getZlibParams(),
|
||||
}
|
||||
|
||||
sub getInverseClass
|
||||
{
|
||||
no warnings 'once';
|
||||
return ('IO::Uncompress::Inflate',
|
||||
\$IO::Uncompress::Inflate::InflateError);
|
||||
}
|
||||
|
||||
sub getFileInfo
|
||||
{
|
||||
my $self = shift ;
|
||||
my $params = shift;
|
||||
my $file = shift ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Compress::Deflate - Write RFC 1950 files/buffers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Compress::Deflate qw(deflate $DeflateError) ;
|
||||
|
||||
my $status = deflate $input => $output [,OPTS]
|
||||
or die "deflate failed: $DeflateError\n";
|
||||
|
||||
my $z = IO::Compress::Deflate->new( $output [,OPTS] )
|
||||
or die "deflate failed: $DeflateError\n";
|
||||
|
||||
$z->print($string);
|
||||
$z->printf($format, $string);
|
||||
$z->write($string);
|
||||
$z->syswrite($string [, $length, $offset]);
|
||||
$z->flush();
|
||||
$z->tell();
|
||||
$z->eof();
|
||||
$z->seek($position, $whence);
|
||||
$z->binmode();
|
||||
$z->fileno();
|
||||
$z->opened();
|
||||
$z->autoflush();
|
||||
$z->input_line_number();
|
||||
$z->newStream( [OPTS] );
|
||||
|
||||
$z->deflateParams();
|
||||
|
||||
$z->close() ;
|
||||
|
||||
$DeflateError ;
|
||||
|
||||
# IO::File mode
|
||||
|
||||
print $z $string;
|
||||
printf $z $format, $string;
|
||||
tell $z
|
||||
eof $z
|
||||
seek $z, $position, $whence
|
||||
binmode $z
|
||||
fileno $z
|
||||
close $z ;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module provides a Perl interface that allows writing compressed
|
||||
data to files or buffer as defined in RFC 1950.
|
||||
|
||||
For reading RFC 1950 files/buffers, see the companion module
|
||||
L<IO::Uncompress::Inflate|IO::Uncompress::Inflate>.
|
||||
|
||||
=head1 Functional Interface
|
||||
|
||||
A top-level function, C<deflate>, is provided to carry out
|
||||
"one-shot" compression between buffers and/or files. For finer
|
||||
control over the compression process, see the L</"OO Interface">
|
||||
section.
|
||||
|
||||
use IO::Compress::Deflate qw(deflate $DeflateError) ;
|
||||
|
||||
deflate $input_filename_or_reference => $output_filename_or_reference [,OPTS]
|
||||
or die "deflate failed: $DeflateError\n";
|
||||
|
||||
The functional interface needs Perl5.005 or better.
|
||||
|
||||
=head2 deflate $input_filename_or_reference => $output_filename_or_reference [, OPTS]
|
||||
|
||||
C<deflate> expects at least two parameters,
|
||||
C<$input_filename_or_reference> and C<$output_filename_or_reference>
|
||||
and zero or more optional parameters (see L</Optional Parameters>)
|
||||
|
||||
=head3 The C<$input_filename_or_reference> parameter
|
||||
|
||||
The parameter, C<$input_filename_or_reference>, is used to define the
|
||||
source of the uncompressed data.
|
||||
|
||||
It can take one of the following forms:
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is a simple scalar, it is
|
||||
assumed to be a filename. This file will be opened for reading and the
|
||||
input data will be read from it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is a filehandle, the input
|
||||
data will be read from it. The string '-' can be used as an alias for
|
||||
standard input.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$input_filename_or_reference> is a scalar reference, the input data
|
||||
will be read from C<$$input_filename_or_reference>.
|
||||
|
||||
=item An array reference
|
||||
|
||||
If C<$input_filename_or_reference> is an array reference, each element in
|
||||
the array must be a filename.
|
||||
|
||||
The input data will be read from each file in turn.
|
||||
|
||||
The complete array will be walked to ensure that it only
|
||||
contains valid filenames before any data is compressed.
|
||||
|
||||
=item An Input FileGlob string
|
||||
|
||||
If C<$input_filename_or_reference> is a string that is delimited by the
|
||||
characters "<" and ">" C<deflate> will assume that it is an
|
||||
I<input fileglob string>. The input is the list of files that match the
|
||||
fileglob.
|
||||
|
||||
See L<File::GlobMapper|File::GlobMapper> for more details.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is any other type,
|
||||
C<undef> will be returned.
|
||||
|
||||
=head3 The C<$output_filename_or_reference> parameter
|
||||
|
||||
The parameter C<$output_filename_or_reference> is used to control the
|
||||
destination of the compressed data. This parameter can take one of
|
||||
these forms.
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is a simple scalar, it is
|
||||
assumed to be a filename. This file will be opened for writing and the
|
||||
compressed data will be written to it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is a filehandle, the
|
||||
compressed data will be written to it. The string '-' can be used as
|
||||
an alias for standard output.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$output_filename_or_reference> is a scalar reference, the
|
||||
compressed data will be stored in C<$$output_filename_or_reference>.
|
||||
|
||||
=item An Array Reference
|
||||
|
||||
If C<$output_filename_or_reference> is an array reference,
|
||||
the compressed data will be pushed onto the array.
|
||||
|
||||
=item An Output FileGlob
|
||||
|
||||
If C<$output_filename_or_reference> is a string that is delimited by the
|
||||
characters "<" and ">" C<deflate> will assume that it is an
|
||||
I<output fileglob string>. The output is the list of files that match the
|
||||
fileglob.
|
||||
|
||||
When C<$output_filename_or_reference> is an fileglob string,
|
||||
C<$input_filename_or_reference> must also be a fileglob string. Anything
|
||||
else is an error.
|
||||
|
||||
See L<File::GlobMapper|File::GlobMapper> for more details.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is any other type,
|
||||
C<undef> will be returned.
|
||||
|
||||
=head2 Notes
|
||||
|
||||
When C<$input_filename_or_reference> maps to multiple files/buffers and
|
||||
C<$output_filename_or_reference> is a single
|
||||
file/buffer the input files/buffers will be stored
|
||||
in C<$output_filename_or_reference> as a concatenated series of compressed data streams.
|
||||
|
||||
=head2 Optional Parameters
|
||||
|
||||
The optional parameters for the one-shot function C<deflate>
|
||||
are (for the most part) identical to those used with the OO interface defined in the
|
||||
L</"Constructor Options"> section. The exceptions are listed below
|
||||
|
||||
=over 5
|
||||
|
||||
=item C<< AutoClose => 0|1 >>
|
||||
|
||||
This option applies to any input or output data streams to
|
||||
C<deflate> that are filehandles.
|
||||
|
||||
If C<AutoClose> is specified, and the value is true, it will result in all
|
||||
input and/or output filehandles being closed once C<deflate> has
|
||||
completed.
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< BinModeIn => 0|1 >>
|
||||
|
||||
This option is now a no-op. All files will be read in binmode.
|
||||
|
||||
=item C<< Append => 0|1 >>
|
||||
|
||||
The behaviour of this option is dependent on the type of output data
|
||||
stream.
|
||||
|
||||
=over 5
|
||||
|
||||
=item * A Buffer
|
||||
|
||||
If C<Append> is enabled, all compressed data will be append to the end of
|
||||
the output buffer. Otherwise the output buffer will be cleared before any
|
||||
compressed data is written to it.
|
||||
|
||||
=item * A Filename
|
||||
|
||||
If C<Append> is enabled, the file will be opened in append mode. Otherwise
|
||||
the contents of the file, if any, will be truncated before any compressed
|
||||
data is written to it.
|
||||
|
||||
=item * A Filehandle
|
||||
|
||||
If C<Append> is enabled, the filehandle will be positioned to the end of
|
||||
the file via a call to C<seek> before any compressed data is
|
||||
written to it. Otherwise the file pointer will not be moved.
|
||||
|
||||
=back
|
||||
|
||||
When C<Append> is specified, and set to true, it will I<append> all compressed
|
||||
data to the output data stream.
|
||||
|
||||
So when the output is a filehandle it will carry out a seek to the eof
|
||||
before writing any compressed data. If the output is a filename, it will be opened for
|
||||
appending. If the output is a buffer, all compressed data will be
|
||||
appended to the existing buffer.
|
||||
|
||||
Conversely when C<Append> is not specified, or it is present and is set to
|
||||
false, it will operate as follows.
|
||||
|
||||
When the output is a filename, it will truncate the contents of the file
|
||||
before writing any compressed data. If the output is a filehandle
|
||||
its position will not be changed. If the output is a buffer, it will be
|
||||
wiped before any compressed data is output.
|
||||
|
||||
Defaults to 0.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Examples
|
||||
|
||||
Here are a few example that show the capabilities of the module.
|
||||
|
||||
=head3 Streaming
|
||||
|
||||
This very simple command line example demonstrates the streaming capabilities of the module.
|
||||
The code reads data from STDIN, compresses it, and writes the compressed data to STDOUT.
|
||||
|
||||
$ echo hello world | perl -MIO::Compress::Deflate=deflate -e 'deflate \*STDIN => \*STDOUT' >output.1950
|
||||
|
||||
The special filename "-" can be used as a standin for both C<\*STDIN> and C<\*STDOUT>,
|
||||
so the above can be rewritten as
|
||||
|
||||
$ echo hello world | perl -MIO::Compress::Deflate=deflate -e 'deflate "-" => "-"' >output.1950
|
||||
|
||||
=head3 Compressing a file from the filesystem
|
||||
|
||||
To read the contents of the file C<file1.txt> and write the compressed
|
||||
data to the file C<file1.txt.1950>.
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Deflate qw(deflate $DeflateError) ;
|
||||
|
||||
my $input = "file1.txt";
|
||||
deflate $input => "$input.1950"
|
||||
or die "deflate failed: $DeflateError\n";
|
||||
|
||||
=head3 Reading from a Filehandle and writing to an in-memory buffer
|
||||
|
||||
To read from an existing Perl filehandle, C<$input>, and write the
|
||||
compressed data to a buffer, C<$buffer>.
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Deflate qw(deflate $DeflateError) ;
|
||||
use IO::File ;
|
||||
|
||||
my $input = IO::File->new( "<file1.txt" )
|
||||
or die "Cannot open 'file1.txt': $!\n" ;
|
||||
my $buffer ;
|
||||
deflate $input => \$buffer
|
||||
or die "deflate failed: $DeflateError\n";
|
||||
|
||||
=head3 Compressing multiple files
|
||||
|
||||
To compress all files in the directory "/my/home" that match "*.txt"
|
||||
and store the compressed data in the same directory
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Deflate qw(deflate $DeflateError) ;
|
||||
|
||||
deflate '</my/home/*.txt>' => '<*.1950>'
|
||||
or die "deflate failed: $DeflateError\n";
|
||||
|
||||
and if you want to compress each file one at a time, this will do the trick
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Compress::Deflate qw(deflate $DeflateError) ;
|
||||
|
||||
for my $input ( glob "/my/home/*.txt" )
|
||||
{
|
||||
my $output = "$input.1950" ;
|
||||
deflate $input => $output
|
||||
or die "Error compressing '$input': $DeflateError\n";
|
||||
}
|
||||
|
||||
=head1 OO Interface
|
||||
|
||||
=head2 Constructor
|
||||
|
||||
The format of the constructor for C<IO::Compress::Deflate> is shown below
|
||||
|
||||
my $z = IO::Compress::Deflate->new( $output [,OPTS] )
|
||||
or die "IO::Compress::Deflate failed: $DeflateError\n";
|
||||
|
||||
It returns an C<IO::Compress::Deflate> object on success and undef on failure.
|
||||
The variable C<$DeflateError> will contain an error message on failure.
|
||||
|
||||
If you are running Perl 5.005 or better the object, C<$z>, returned from
|
||||
IO::Compress::Deflate can be used exactly like an L<IO::File|IO::File> filehandle.
|
||||
This means that all normal output file operations can be carried out
|
||||
with C<$z>.
|
||||
For example, to write to a compressed file/buffer you can use either of
|
||||
these forms
|
||||
|
||||
$z->print("hello world\n");
|
||||
print $z "hello world\n";
|
||||
|
||||
The mandatory parameter C<$output> is used to control the destination
|
||||
of the compressed data. This parameter can take one of these forms.
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$output> parameter is a simple scalar, it is assumed to be a
|
||||
filename. This file will be opened for writing and the compressed data
|
||||
will be written to it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$output> parameter is a filehandle, the compressed data will be
|
||||
written to it.
|
||||
The string '-' can be used as an alias for standard output.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$output> is a scalar reference, the compressed data will be stored
|
||||
in C<$$output>.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$output> parameter is any other type, C<IO::Compress::Deflate>::new will
|
||||
return undef.
|
||||
|
||||
=head2 Constructor Options
|
||||
|
||||
C<OPTS> is any combination of zero or more the following options:
|
||||
|
||||
=over 5
|
||||
|
||||
=item C<< AutoClose => 0|1 >>
|
||||
|
||||
This option is only valid when the C<$output> parameter is a filehandle. If
|
||||
specified, and the value is true, it will result in the C<$output> being
|
||||
closed once either the C<close> method is called or the C<IO::Compress::Deflate>
|
||||
object is destroyed.
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< Append => 0|1 >>
|
||||
|
||||
Opens C<$output> in append mode.
|
||||
|
||||
The behaviour of this option is dependent on the type of C<$output>.
|
||||
|
||||
=over 5
|
||||
|
||||
=item * A Buffer
|
||||
|
||||
If C<$output> is a buffer and C<Append> is enabled, all compressed data
|
||||
will be append to the end of C<$output>. Otherwise C<$output> will be
|
||||
cleared before any data is written to it.
|
||||
|
||||
=item * A Filename
|
||||
|
||||
If C<$output> is a filename and C<Append> is enabled, the file will be
|
||||
opened in append mode. Otherwise the contents of the file, if any, will be
|
||||
truncated before any compressed data is written to it.
|
||||
|
||||
=item * A Filehandle
|
||||
|
||||
If C<$output> is a filehandle, the file pointer will be positioned to the
|
||||
end of the file via a call to C<seek> before any compressed data is written
|
||||
to it. Otherwise the file pointer will not be moved.
|
||||
|
||||
=back
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< Merge => 0|1 >>
|
||||
|
||||
This option is used to compress input data and append it to an existing
|
||||
compressed data stream in C<$output>. The end result is a single compressed
|
||||
data stream stored in C<$output>.
|
||||
|
||||
It is a fatal error to attempt to use this option when C<$output> is not an
|
||||
RFC 1950 data stream.
|
||||
|
||||
There are a number of other limitations with the C<Merge> option:
|
||||
|
||||
=over 5
|
||||
|
||||
=item 1
|
||||
|
||||
This module needs to have been built with zlib 1.2.1 or better to work. A
|
||||
fatal error will be thrown if C<Merge> is used with an older version of
|
||||
zlib.
|
||||
|
||||
=item 2
|
||||
|
||||
If C<$output> is a file or a filehandle, it must be seekable.
|
||||
|
||||
=back
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item -Level
|
||||
|
||||
Defines the compression level used by zlib. The value should either be
|
||||
a number between 0 and 9 (0 means no compression and 9 is maximum
|
||||
compression), or one of the symbolic constants defined below.
|
||||
|
||||
Z_NO_COMPRESSION
|
||||
Z_BEST_SPEED
|
||||
Z_BEST_COMPRESSION
|
||||
Z_DEFAULT_COMPRESSION
|
||||
|
||||
The default is Z_DEFAULT_COMPRESSION.
|
||||
|
||||
Note, these constants are not imported by C<IO::Compress::Deflate> by default.
|
||||
|
||||
use IO::Compress::Deflate qw(:strategy);
|
||||
use IO::Compress::Deflate qw(:constants);
|
||||
use IO::Compress::Deflate qw(:all);
|
||||
|
||||
=item -Strategy
|
||||
|
||||
Defines the strategy used to tune the compression. Use one of the symbolic
|
||||
constants defined below.
|
||||
|
||||
Z_FILTERED
|
||||
Z_HUFFMAN_ONLY
|
||||
Z_RLE
|
||||
Z_FIXED
|
||||
Z_DEFAULT_STRATEGY
|
||||
|
||||
The default is Z_DEFAULT_STRATEGY.
|
||||
|
||||
=item C<< Strict => 0|1 >>
|
||||
|
||||
This is a placeholder option.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Examples
|
||||
|
||||
TODO
|
||||
|
||||
=head1 Methods
|
||||
|
||||
=head2 print
|
||||
|
||||
Usage is
|
||||
|
||||
$z->print($data)
|
||||
print $z $data
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter. This
|
||||
has the same behaviour as the C<print> built-in.
|
||||
|
||||
Returns true if successful.
|
||||
|
||||
=head2 printf
|
||||
|
||||
Usage is
|
||||
|
||||
$z->printf($format, $data)
|
||||
printf $z $format, $data
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter.
|
||||
|
||||
Returns true if successful.
|
||||
|
||||
=head2 syswrite
|
||||
|
||||
Usage is
|
||||
|
||||
$z->syswrite $data
|
||||
$z->syswrite $data, $length
|
||||
$z->syswrite $data, $length, $offset
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter.
|
||||
|
||||
Returns the number of uncompressed bytes written, or C<undef> if
|
||||
unsuccessful.
|
||||
|
||||
=head2 write
|
||||
|
||||
Usage is
|
||||
|
||||
$z->write $data
|
||||
$z->write $data, $length
|
||||
$z->write $data, $length, $offset
|
||||
|
||||
Compresses and outputs the contents of the C<$data> parameter.
|
||||
|
||||
Returns the number of uncompressed bytes written, or C<undef> if
|
||||
unsuccessful.
|
||||
|
||||
=head2 flush
|
||||
|
||||
Usage is
|
||||
|
||||
$z->flush;
|
||||
$z->flush($flush_type);
|
||||
|
||||
Flushes any pending compressed data to the output file/buffer.
|
||||
|
||||
This method takes an optional parameter, C<$flush_type>, that controls
|
||||
how the flushing will be carried out. By default the C<$flush_type>
|
||||
used is C<Z_FINISH>. Other valid values for C<$flush_type> are
|
||||
C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is
|
||||
strongly recommended that you only set the C<flush_type> parameter if
|
||||
you fully understand the implications of what it does - overuse of C<flush>
|
||||
can seriously degrade the level of compression achieved. See the C<zlib>
|
||||
documentation for details.
|
||||
|
||||
Returns true on success.
|
||||
|
||||
=head2 tell
|
||||
|
||||
Usage is
|
||||
|
||||
$z->tell()
|
||||
tell $z
|
||||
|
||||
Returns the uncompressed file offset.
|
||||
|
||||
=head2 eof
|
||||
|
||||
Usage is
|
||||
|
||||
$z->eof();
|
||||
eof($z);
|
||||
|
||||
Returns true if the C<close> method has been called.
|
||||
|
||||
=head2 seek
|
||||
|
||||
$z->seek($position, $whence);
|
||||
seek($z, $position, $whence);
|
||||
|
||||
Provides a sub-set of the C<seek> functionality, with the restriction
|
||||
that it is only legal to seek forward in the output file/buffer.
|
||||
It is a fatal error to attempt to seek backward.
|
||||
|
||||
Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
|
||||
|
||||
The C<$whence> parameter takes one the usual values, namely SEEK_SET,
|
||||
SEEK_CUR or SEEK_END.
|
||||
|
||||
Returns 1 on success, 0 on failure.
|
||||
|
||||
=head2 binmode
|
||||
|
||||
Usage is
|
||||
|
||||
$z->binmode
|
||||
binmode $z ;
|
||||
|
||||
This is a noop provided for completeness.
|
||||
|
||||
=head2 opened
|
||||
|
||||
$z->opened()
|
||||
|
||||
Returns true if the object currently refers to a opened file/buffer.
|
||||
|
||||
=head2 autoflush
|
||||
|
||||
my $prev = $z->autoflush()
|
||||
my $prev = $z->autoflush(EXPR)
|
||||
|
||||
If the C<$z> object is associated with a file or a filehandle, this method
|
||||
returns the current autoflush setting for the underlying filehandle. If
|
||||
C<EXPR> is present, and is non-zero, it will enable flushing after every
|
||||
write/print operation.
|
||||
|
||||
If C<$z> is associated with a buffer, this method has no effect and always
|
||||
returns C<undef>.
|
||||
|
||||
B<Note> that the special variable C<$|> B<cannot> be used to set or
|
||||
retrieve the autoflush setting.
|
||||
|
||||
=head2 input_line_number
|
||||
|
||||
$z->input_line_number()
|
||||
$z->input_line_number(EXPR)
|
||||
|
||||
This method always returns C<undef> when compressing.
|
||||
|
||||
=head2 fileno
|
||||
|
||||
$z->fileno()
|
||||
fileno($z)
|
||||
|
||||
If the C<$z> object is associated with a file or a filehandle, C<fileno>
|
||||
will return the underlying file descriptor. Once the C<close> method is
|
||||
called C<fileno> will return C<undef>.
|
||||
|
||||
If the C<$z> object is associated with a buffer, this method will return
|
||||
C<undef>.
|
||||
|
||||
=head2 close
|
||||
|
||||
$z->close() ;
|
||||
close $z ;
|
||||
|
||||
Flushes any pending compressed data and then closes the output file/buffer.
|
||||
|
||||
For most versions of Perl this method will be automatically invoked if
|
||||
the IO::Compress::Deflate object is destroyed (either explicitly or by the
|
||||
variable with the reference to the object going out of scope). The
|
||||
exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
|
||||
these cases, the C<close> method will be called automatically, but
|
||||
not until global destruction of all live objects when the program is
|
||||
terminating.
|
||||
|
||||
Therefore, if you want your scripts to be able to run on all versions
|
||||
of Perl, you should call C<close> explicitly and not rely on automatic
|
||||
closing.
|
||||
|
||||
Returns true on success, otherwise 0.
|
||||
|
||||
If the C<AutoClose> option has been enabled when the IO::Compress::Deflate
|
||||
object was created, and the object is associated with a file, the
|
||||
underlying file will also be closed.
|
||||
|
||||
=head2 newStream([OPTS])
|
||||
|
||||
Usage is
|
||||
|
||||
$z->newStream( [OPTS] )
|
||||
|
||||
Closes the current compressed data stream and starts a new one.
|
||||
|
||||
OPTS consists of any of the options that are available when creating
|
||||
the C<$z> object.
|
||||
|
||||
See the L</"Constructor Options"> section for more details.
|
||||
|
||||
=head2 deflateParams
|
||||
|
||||
Usage is
|
||||
|
||||
$z->deflateParams
|
||||
|
||||
TODO
|
||||
|
||||
=head1 Importing
|
||||
|
||||
A number of symbolic constants are required by some methods in
|
||||
C<IO::Compress::Deflate>. None are imported by default.
|
||||
|
||||
=over 5
|
||||
|
||||
=item :all
|
||||
|
||||
Imports C<deflate>, C<$DeflateError> and all symbolic
|
||||
constants that can be used by C<IO::Compress::Deflate>. Same as doing this
|
||||
|
||||
use IO::Compress::Deflate qw(deflate $DeflateError :constants) ;
|
||||
|
||||
=item :constants
|
||||
|
||||
Import all symbolic constants. Same as doing this
|
||||
|
||||
use IO::Compress::Deflate qw(:flush :level :strategy) ;
|
||||
|
||||
=item :flush
|
||||
|
||||
These symbolic constants are used by the C<flush> method.
|
||||
|
||||
Z_NO_FLUSH
|
||||
Z_PARTIAL_FLUSH
|
||||
Z_SYNC_FLUSH
|
||||
Z_FULL_FLUSH
|
||||
Z_FINISH
|
||||
Z_BLOCK
|
||||
|
||||
=item :level
|
||||
|
||||
These symbolic constants are used by the C<Level> option in the constructor.
|
||||
|
||||
Z_NO_COMPRESSION
|
||||
Z_BEST_SPEED
|
||||
Z_BEST_COMPRESSION
|
||||
Z_DEFAULT_COMPRESSION
|
||||
|
||||
=item :strategy
|
||||
|
||||
These symbolic constants are used by the C<Strategy> option in the constructor.
|
||||
|
||||
Z_FILTERED
|
||||
Z_HUFFMAN_ONLY
|
||||
Z_RLE
|
||||
Z_FIXED
|
||||
Z_DEFAULT_STRATEGY
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
=head2 Apache::GZip Revisited
|
||||
|
||||
See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
|
||||
|
||||
=head2 Working with Net::FTP
|
||||
|
||||
See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
General feedback/questions/bug reports should be sent to
|
||||
L<https://github.com/pmqs/IO-Compress/issues> (preferred) or
|
||||
L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzip>, L<IO::Uncompress::UnLzip>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Compress::Zstd>, L<IO::Uncompress::UnZstd>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
|
||||
|
||||
L<IO::Compress::FAQ|IO::Compress::FAQ>
|
||||
|
||||
L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
|
||||
L<Archive::Tar|Archive::Tar>,
|
||||
L<IO::Zlib|IO::Zlib>
|
||||
|
||||
For RFC 1950, 1951 and 1952 see
|
||||
L<http://www.faqs.org/rfcs/rfc1950.html>,
|
||||
L<http://www.faqs.org/rfcs/rfc1951.html> and
|
||||
L<http://www.faqs.org/rfcs/rfc1952.html>
|
||||
|
||||
The I<zlib> compression library was written by Jean-loup Gailly
|
||||
C<gzip@prep.ai.mit.edu> and Mark Adler C<madler@alumni.caltech.edu>.
|
||||
|
||||
The primary site for the I<zlib> compression library is
|
||||
L<http://www.zlib.org>.
|
||||
|
||||
The primary site for gzip is L<http://www.gzip.org>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
This module was written by Paul Marquess, C<pmqs@cpan.org>.
|
||||
|
||||
=head1 MODIFICATION HISTORY
|
||||
|
||||
See the Changes file.
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (c) 2005-2021 Paul Marquess. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
689
database/perl/lib/IO/Compress/FAQ.pod
Normal file
689
database/perl/lib/IO/Compress/FAQ.pod
Normal file
@@ -0,0 +1,689 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Compress::FAQ -- Frequently Asked Questions about IO::Compress
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Common questions answered.
|
||||
|
||||
=head1 GENERAL
|
||||
|
||||
=head2 Compatibility with Unix compress/uncompress.
|
||||
|
||||
Although C<Compress::Zlib> has a pair of functions called C<compress> and
|
||||
C<uncompress>, they are I<not> related to the Unix programs of the same
|
||||
name. The C<Compress::Zlib> module is not compatible with Unix
|
||||
C<compress>.
|
||||
|
||||
If you have the C<uncompress> program available, you can use this to read
|
||||
compressed files
|
||||
|
||||
open F, "uncompress -c $filename |";
|
||||
while (<F>)
|
||||
{
|
||||
...
|
||||
|
||||
Alternatively, if you have the C<gunzip> program available, you can use
|
||||
this to read compressed files
|
||||
|
||||
open F, "gunzip -c $filename |";
|
||||
while (<F>)
|
||||
{
|
||||
...
|
||||
|
||||
and this to write compress files, if you have the C<compress> program
|
||||
available
|
||||
|
||||
open F, "| compress -c $filename ";
|
||||
print F "data";
|
||||
...
|
||||
close F ;
|
||||
|
||||
=head2 Accessing .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
|
||||
accessed 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 strict;
|
||||
use warnings;
|
||||
use Archive::Tar;
|
||||
|
||||
open F, "uncompress -c $filename |";
|
||||
my $tar = Archive::Tar->new(*F);
|
||||
...
|
||||
|
||||
and this with C<gunzip>
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
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 strict;
|
||||
use warnings;
|
||||
use Archive::Tar;
|
||||
use IO::File;
|
||||
|
||||
my $fh = IO::File->new( "| compress -c >$filename" );
|
||||
my $tar = Archive::Tar->new();
|
||||
...
|
||||
$tar->write($fh);
|
||||
$fh->close ;
|
||||
|
||||
=head2 How do I recompress using a different compression?
|
||||
|
||||
This is easier that you might expect if you realise that all the
|
||||
C<IO::Compress::*> objects are derived from C<IO::File> and that all the
|
||||
C<IO::Uncompress::*> modules can read from an C<IO::File> filehandle.
|
||||
|
||||
So, for example, say you have a file compressed with gzip that you want to
|
||||
recompress with bzip2. Here is all that is needed to carry out the
|
||||
recompression.
|
||||
|
||||
use IO::Uncompress::Gunzip ':all';
|
||||
use IO::Compress::Bzip2 ':all';
|
||||
|
||||
my $gzipFile = "somefile.gz";
|
||||
my $bzipFile = "somefile.bz2";
|
||||
|
||||
my $gunzip = IO::Uncompress::Gunzip->new( $gzipFile )
|
||||
or die "Cannot gunzip $gzipFile: $GunzipError\n" ;
|
||||
|
||||
bzip2 $gunzip => $bzipFile
|
||||
or die "Cannot bzip2 to $bzipFile: $Bzip2Error\n" ;
|
||||
|
||||
Note, there is a limitation of this technique. Some compression file
|
||||
formats store extra information along with the compressed data payload. For
|
||||
example, gzip can optionally store the original filename and Zip stores a
|
||||
lot of information about the original file. If the original compressed file
|
||||
contains any of this extra information, it will not be transferred to the
|
||||
new compressed file using the technique above.
|
||||
|
||||
=head1 ZIP
|
||||
|
||||
=head2 What Compression Types do IO::Compress::Zip & IO::Uncompress::Unzip support?
|
||||
|
||||
The following compression formats are supported by C<IO::Compress::Zip> and
|
||||
C<IO::Uncompress::Unzip>
|
||||
|
||||
=over 5
|
||||
|
||||
=item * Store (method 0)
|
||||
|
||||
No compression at all.
|
||||
|
||||
=item * Deflate (method 8)
|
||||
|
||||
This is the default compression used when creating a zip file with
|
||||
C<IO::Compress::Zip>.
|
||||
|
||||
=item * Bzip2 (method 12)
|
||||
|
||||
Only supported if the C<IO-Compress-Bzip2> module is installed.
|
||||
|
||||
=item * Lzma (method 14)
|
||||
|
||||
Only supported if the C<IO-Compress-Lzma> module is installed.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Can I Read/Write Zip files larger the 4 Gig?
|
||||
|
||||
Yes, both the C<IO-Compress-Zip> and C<IO-Uncompress-Unzip> modules
|
||||
support the zip feature called I<Zip64>. That allows them to read/write
|
||||
files/buffers larger than 4Gig.
|
||||
|
||||
If you are creating a Zip file using the one-shot interface, and any of the
|
||||
input files is greater than 4Gig, a zip64 complaint zip file will be
|
||||
created.
|
||||
|
||||
zip "really-large-file" => "my.zip";
|
||||
|
||||
Similarly with the one-shot interface, if the input is a buffer larger than
|
||||
4 Gig, a zip64 complaint zip file will be created.
|
||||
|
||||
zip \$really_large_buffer => "my.zip";
|
||||
|
||||
The one-shot interface allows you to force the creation of a zip64 zip file
|
||||
by including the C<Zip64> option.
|
||||
|
||||
zip $filehandle => "my.zip", Zip64 => 1;
|
||||
|
||||
If you want to create a zip64 zip file with the OO interface you must
|
||||
specify the C<Zip64> option.
|
||||
|
||||
my $zip = IO::Compress::Zip->new( "whatever", Zip64 => 1 );
|
||||
|
||||
When uncompressing with C<IO-Uncompress-Unzip>, it will automatically
|
||||
detect if the zip file is zip64.
|
||||
|
||||
If you intend to manipulate the Zip64 zip files created with
|
||||
C<IO-Compress-Zip> using an external zip/unzip, make sure that it supports
|
||||
Zip64.
|
||||
|
||||
In particular, if you are using Info-Zip you need to have zip version 3.x
|
||||
or better to update a Zip64 archive and unzip version 6.x to read a zip64
|
||||
archive.
|
||||
|
||||
=head2 Can I write more that 64K entries is a Zip files?
|
||||
|
||||
Yes. Zip64 allows this. See previous question.
|
||||
|
||||
=head2 Zip Resources
|
||||
|
||||
The primary reference for zip files is the "appnote" document available at
|
||||
L<http://www.pkware.com/documents/casestudies/APPNOTE.TXT>
|
||||
|
||||
An alternatively is the Info-Zip appnote. This is available from
|
||||
L<ftp://ftp.info-zip.org/pub/infozip/doc/>
|
||||
|
||||
=head1 GZIP
|
||||
|
||||
=head2 Gzip Resources
|
||||
|
||||
The primary reference for gzip files is RFC 1952
|
||||
L<http://www.faqs.org/rfcs/rfc1952.html>
|
||||
|
||||
The primary site for gzip is L<http://www.gzip.org>.
|
||||
|
||||
=head2 Dealing with concatenated gzip files
|
||||
|
||||
If the gunzip program encounters a file containing multiple gzip files
|
||||
concatenated together it will automatically uncompress them all.
|
||||
The example below illustrates this behaviour
|
||||
|
||||
$ echo abc | gzip -c >x.gz
|
||||
$ echo def | gzip -c >>x.gz
|
||||
$ gunzip -c x.gz
|
||||
abc
|
||||
def
|
||||
|
||||
By default C<IO::Uncompress::Gunzip> will I<not> behave like the gunzip
|
||||
program. It will only uncompress the first gzip data stream in the file, as
|
||||
shown below
|
||||
|
||||
$ perl -MIO::Uncompress::Gunzip=:all -e 'gunzip "x.gz" => \*STDOUT'
|
||||
abc
|
||||
|
||||
To force C<IO::Uncompress::Gunzip> to uncompress all the gzip data streams,
|
||||
include the C<MultiStream> option, as shown below
|
||||
|
||||
$ perl -MIO::Uncompress::Gunzip=:all -e 'gunzip "x.gz" => \*STDOUT, MultiStream => 1'
|
||||
abc
|
||||
def
|
||||
|
||||
=head2 Reading bgzip files with IO::Uncompress::Gunzip
|
||||
|
||||
A C<bgzip> file consists of a series of valid gzip-compliant data streams
|
||||
concatenated together. To read a file created by C<bgzip> with
|
||||
C<IO::Uncompress::Gunzip> use the C<MultiStream> option as shown in the
|
||||
previous section.
|
||||
|
||||
See the section titled "The BGZF compression format" in
|
||||
L<http://samtools.github.io/hts-specs/SAMv1.pdf> for a definition of
|
||||
C<bgzip>.
|
||||
|
||||
=head1 ZLIB
|
||||
|
||||
=head2 Zlib Resources
|
||||
|
||||
The primary site for the I<zlib> compression library is
|
||||
L<http://www.zlib.org>.
|
||||
|
||||
=head1 Bzip2
|
||||
|
||||
=head2 Bzip2 Resources
|
||||
|
||||
The primary site for bzip2 is L<http://www.bzip.org>.
|
||||
|
||||
=head2 Dealing with Concatenated bzip2 files
|
||||
|
||||
If the bunzip2 program encounters a file containing multiple bzip2 files
|
||||
concatenated together it will automatically uncompress them all.
|
||||
The example below illustrates this behaviour
|
||||
|
||||
$ echo abc | bzip2 -c >x.bz2
|
||||
$ echo def | bzip2 -c >>x.bz2
|
||||
$ bunzip2 -c x.bz2
|
||||
abc
|
||||
def
|
||||
|
||||
By default C<IO::Uncompress::Bunzip2> will I<not> behave like the bunzip2
|
||||
program. It will only uncompress the first bunzip2 data stream in the file, as
|
||||
shown below
|
||||
|
||||
$ perl -MIO::Uncompress::Bunzip2=:all -e 'bunzip2 "x.bz2" => \*STDOUT'
|
||||
abc
|
||||
|
||||
To force C<IO::Uncompress::Bunzip2> to uncompress all the bzip2 data streams,
|
||||
include the C<MultiStream> option, as shown below
|
||||
|
||||
$ perl -MIO::Uncompress::Bunzip2=:all -e 'bunzip2 "x.bz2" => \*STDOUT, MultiStream => 1'
|
||||
abc
|
||||
def
|
||||
|
||||
=head2 Interoperating with Pbzip2
|
||||
|
||||
Pbzip2 (L<http://compression.ca/pbzip2/>) is a parallel implementation of
|
||||
bzip2. The output from pbzip2 consists of a series of concatenated bzip2
|
||||
data streams.
|
||||
|
||||
By default C<IO::Uncompress::Bzip2> will only uncompress the first bzip2
|
||||
data stream in a pbzip2 file. To uncompress the complete pbzip2 file you
|
||||
must include the C<MultiStream> option, like this.
|
||||
|
||||
bunzip2 $input => \$output, MultiStream => 1
|
||||
or die "bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
=head1 HTTP & NETWORK
|
||||
|
||||
=head2 Apache::GZip Revisited
|
||||
|
||||
Below is a mod_perl Apache compression module, called C<Apache::GZip>,
|
||||
taken from
|
||||
L<http://perl.apache.org/docs/tutorials/tips/mod_perl_tricks/mod_perl_tricks.html#On_the_Fly_Compression>
|
||||
|
||||
package Apache::GZip;
|
||||
#File: Apache::GZip.pm
|
||||
|
||||
use strict vars;
|
||||
use Apache::Constants ':common';
|
||||
use Compress::Zlib;
|
||||
use IO::File;
|
||||
use constant GZIP_MAGIC => 0x1f8b;
|
||||
use constant OS_MAGIC => 0x03;
|
||||
|
||||
sub handler {
|
||||
my $r = shift;
|
||||
my ($fh,$gz);
|
||||
my $file = $r->filename;
|
||||
return DECLINED unless $fh=IO::File->new($file);
|
||||
$r->header_out('Content-Encoding'=>'gzip');
|
||||
$r->send_http_header;
|
||||
return OK if $r->header_only;
|
||||
|
||||
tie *STDOUT,'Apache::GZip',$r;
|
||||
print($_) while <$fh>;
|
||||
untie *STDOUT;
|
||||
return OK;
|
||||
}
|
||||
|
||||
sub TIEHANDLE {
|
||||
my($class,$r) = @_;
|
||||
# initialize a deflation stream
|
||||
my $d = deflateInit(-WindowBits=>-MAX_WBITS()) || return undef;
|
||||
|
||||
# gzip header -- don't ask how I found out
|
||||
$r->print(pack("nccVcc",GZIP_MAGIC,Z_DEFLATED,0,time(),0,OS_MAGIC));
|
||||
|
||||
return bless { r => $r,
|
||||
crc => crc32(undef),
|
||||
d => $d,
|
||||
l => 0
|
||||
},$class;
|
||||
}
|
||||
|
||||
sub PRINT {
|
||||
my $self = shift;
|
||||
foreach (@_) {
|
||||
# deflate the data
|
||||
my $data = $self->{d}->deflate($_);
|
||||
$self->{r}->print($data);
|
||||
# keep track of its length and crc
|
||||
$self->{l} += length($_);
|
||||
$self->{crc} = crc32($_,$self->{crc});
|
||||
}
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
my $self = shift;
|
||||
|
||||
# flush the output buffers
|
||||
my $data = $self->{d}->flush;
|
||||
$self->{r}->print($data);
|
||||
|
||||
# print the CRC and the total length (uncompressed)
|
||||
$self->{r}->print(pack("LL",@{$self}{qw/crc l/}));
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
Here's the Apache configuration entry you'll need to make use of it. Once
|
||||
set it will result in everything in the /compressed directory will be
|
||||
compressed automagically.
|
||||
|
||||
<Location /compressed>
|
||||
SetHandler perl-script
|
||||
PerlHandler Apache::GZip
|
||||
</Location>
|
||||
|
||||
Although at first sight there seems to be quite a lot going on in
|
||||
C<Apache::GZip>, you could sum up what the code was doing as follows --
|
||||
read the contents of the file in C<< $r->filename >>, compress it and write
|
||||
the compressed data to standard output. That's all.
|
||||
|
||||
This code has to jump through a few hoops to achieve this because
|
||||
|
||||
=over
|
||||
|
||||
=item 1.
|
||||
|
||||
The gzip support in C<Compress::Zlib> version 1.x can only work with a real
|
||||
filesystem filehandle. The filehandles used by Apache modules are not
|
||||
associated with the filesystem.
|
||||
|
||||
=item 2.
|
||||
|
||||
That means all the gzip support has to be done by hand - in this case by
|
||||
creating a tied filehandle to deal with creating the gzip header and
|
||||
trailer.
|
||||
|
||||
=back
|
||||
|
||||
C<IO::Compress::Gzip> doesn't have that filehandle limitation (this was one
|
||||
of the reasons for writing it in the first place). So if
|
||||
C<IO::Compress::Gzip> is used instead of C<Compress::Zlib> the whole tied
|
||||
filehandle code can be removed. Here is the rewritten code.
|
||||
|
||||
package Apache::GZip;
|
||||
|
||||
use strict vars;
|
||||
use Apache::Constants ':common';
|
||||
use IO::Compress::Gzip;
|
||||
use IO::File;
|
||||
|
||||
sub handler {
|
||||
my $r = shift;
|
||||
my ($fh,$gz);
|
||||
my $file = $r->filename;
|
||||
return DECLINED unless $fh=IO::File->new($file);
|
||||
$r->header_out('Content-Encoding'=>'gzip');
|
||||
$r->send_http_header;
|
||||
return OK if $r->header_only;
|
||||
|
||||
my $gz = IO::Compress::Gzip->new( '-', Minimal => 1 )
|
||||
or return DECLINED ;
|
||||
|
||||
print $gz $_ while <$fh>;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
or even more succinctly, like this, using a one-shot gzip
|
||||
|
||||
package Apache::GZip;
|
||||
|
||||
use strict vars;
|
||||
use Apache::Constants ':common';
|
||||
use IO::Compress::Gzip qw(gzip);
|
||||
|
||||
sub handler {
|
||||
my $r = shift;
|
||||
$r->header_out('Content-Encoding'=>'gzip');
|
||||
$r->send_http_header;
|
||||
return OK if $r->header_only;
|
||||
|
||||
gzip $r->filename => '-', Minimal => 1
|
||||
or return DECLINED ;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
The use of one-shot C<gzip> above just reads from C<< $r->filename >> and
|
||||
writes the compressed data to standard output.
|
||||
|
||||
Note the use of the C<Minimal> option in the code above. When using gzip
|
||||
for Content-Encoding you should I<always> use this option. In the example
|
||||
above it will prevent the filename being included in the gzip header and
|
||||
make the size of the gzip data stream a slight bit smaller.
|
||||
|
||||
=head2 Compressed files and Net::FTP
|
||||
|
||||
The C<Net::FTP> module provides two low-level methods called C<stor> and
|
||||
C<retr> that both return filehandles. These filehandles can used with the
|
||||
C<IO::Compress/Uncompress> modules to compress or uncompress files read
|
||||
from or written to an FTP Server on the fly, without having to create a
|
||||
temporary file.
|
||||
|
||||
Firstly, here is code that uses C<retr> to uncompressed a file as it is
|
||||
read from the FTP Server.
|
||||
|
||||
use Net::FTP;
|
||||
use IO::Uncompress::Gunzip qw(:all);
|
||||
|
||||
my $ftp = Net::FTP->new( ... )
|
||||
|
||||
my $retr_fh = $ftp->retr($compressed_filename);
|
||||
gunzip $retr_fh => $outFilename, AutoClose => 1
|
||||
or die "Cannot uncompress '$compressed_file': $GunzipError\n";
|
||||
|
||||
and this to compress a file as it is written to the FTP Server
|
||||
|
||||
use Net::FTP;
|
||||
use IO::Compress::Gzip qw(:all);
|
||||
|
||||
my $stor_fh = $ftp->stor($filename);
|
||||
gzip "filename" => $stor_fh, AutoClose => 1
|
||||
or die "Cannot compress '$filename': $GzipError\n";
|
||||
|
||||
=head1 MISC
|
||||
|
||||
=head2 Using C<InputLength> to uncompress data embedded in a larger file/buffer.
|
||||
|
||||
A fairly common use-case is where compressed data is embedded in a larger
|
||||
file/buffer and you want to read both.
|
||||
|
||||
As an example consider the structure of a zip file. This is a well-defined
|
||||
file format that mixes both compressed and uncompressed sections of data in
|
||||
a single file.
|
||||
|
||||
For the purposes of this discussion you can think of a zip file as sequence
|
||||
of compressed data streams, each of which is prefixed by an uncompressed
|
||||
local header. The local header contains information about the compressed
|
||||
data stream, including the name of the compressed file and, in particular,
|
||||
the length of the compressed data stream.
|
||||
|
||||
To illustrate how to use C<InputLength> here is a script that walks a zip
|
||||
file and prints out how many lines are in each compressed file (if you
|
||||
intend write code to walking through a zip file for real see
|
||||
L<IO::Uncompress::Unzip/"Walking through a zip file"> ). Also, although
|
||||
this example uses the zlib-based compression, the technique can be used by
|
||||
the other C<IO::Uncompress::*> modules.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use IO::File;
|
||||
use IO::Uncompress::RawInflate qw(:all);
|
||||
|
||||
use constant ZIP_LOCAL_HDR_SIG => 0x04034b50;
|
||||
use constant ZIP_LOCAL_HDR_LENGTH => 30;
|
||||
|
||||
my $file = $ARGV[0] ;
|
||||
|
||||
my $fh = IO::File->new( "<$file" )
|
||||
or die "Cannot open '$file': $!\n";
|
||||
|
||||
while (1)
|
||||
{
|
||||
my $sig;
|
||||
my $buffer;
|
||||
|
||||
my $x ;
|
||||
($x = $fh->read($buffer, ZIP_LOCAL_HDR_LENGTH)) == ZIP_LOCAL_HDR_LENGTH
|
||||
or die "Truncated file: $!\n";
|
||||
|
||||
my $signature = unpack ("V", substr($buffer, 0, 4));
|
||||
|
||||
last unless $signature == ZIP_LOCAL_HDR_SIG;
|
||||
|
||||
# Read Local Header
|
||||
my $gpFlag = unpack ("v", substr($buffer, 6, 2));
|
||||
my $compressedMethod = unpack ("v", substr($buffer, 8, 2));
|
||||
my $compressedLength = unpack ("V", substr($buffer, 18, 4));
|
||||
my $uncompressedLength = unpack ("V", substr($buffer, 22, 4));
|
||||
my $filename_length = unpack ("v", substr($buffer, 26, 2));
|
||||
my $extra_length = unpack ("v", substr($buffer, 28, 2));
|
||||
|
||||
my $filename ;
|
||||
$fh->read($filename, $filename_length) == $filename_length
|
||||
or die "Truncated file\n";
|
||||
|
||||
$fh->read($buffer, $extra_length) == $extra_length
|
||||
or die "Truncated file\n";
|
||||
|
||||
if ($compressedMethod != 8 && $compressedMethod != 0)
|
||||
{
|
||||
warn "Skipping file '$filename' - not deflated $compressedMethod\n";
|
||||
$fh->read($buffer, $compressedLength) == $compressedLength
|
||||
or die "Truncated file\n";
|
||||
next;
|
||||
}
|
||||
|
||||
if ($compressedMethod == 0 && $gpFlag & 8 == 8)
|
||||
{
|
||||
die "Streamed Stored not supported for '$filename'\n";
|
||||
}
|
||||
|
||||
next if $compressedLength == 0;
|
||||
|
||||
# Done reading the Local Header
|
||||
|
||||
my $inf = IO::Uncompress::RawInflate->new( $fh,
|
||||
Transparent => 1,
|
||||
InputLength => $compressedLength )
|
||||
or die "Cannot uncompress $file [$filename]: $RawInflateError\n" ;
|
||||
|
||||
my $line_count = 0;
|
||||
|
||||
while (<$inf>)
|
||||
{
|
||||
++ $line_count;
|
||||
}
|
||||
|
||||
print "$filename: $line_count\n";
|
||||
}
|
||||
|
||||
The majority of the code above is concerned with reading the zip local
|
||||
header data. The code that I want to focus on is at the bottom.
|
||||
|
||||
while (1) {
|
||||
|
||||
# read local zip header data
|
||||
# get $filename
|
||||
# get $compressedLength
|
||||
|
||||
my $inf = IO::Uncompress::RawInflate->new( $fh,
|
||||
Transparent => 1,
|
||||
InputLength => $compressedLength )
|
||||
or die "Cannot uncompress $file [$filename]: $RawInflateError\n" ;
|
||||
|
||||
my $line_count = 0;
|
||||
|
||||
while (<$inf>)
|
||||
{
|
||||
++ $line_count;
|
||||
}
|
||||
|
||||
print "$filename: $line_count\n";
|
||||
}
|
||||
|
||||
The call to C<IO::Uncompress::RawInflate> creates a new filehandle C<$inf>
|
||||
that can be used to read from the parent filehandle C<$fh>, uncompressing
|
||||
it as it goes. The use of the C<InputLength> option will guarantee that
|
||||
I<at most> C<$compressedLength> bytes of compressed data will be read from
|
||||
the C<$fh> filehandle (The only exception is for an error case like a
|
||||
truncated file or a corrupt data stream).
|
||||
|
||||
This means that once RawInflate is finished C<$fh> will be left at the
|
||||
byte directly after the compressed data stream.
|
||||
|
||||
Now consider what the code looks like without C<InputLength>
|
||||
|
||||
while (1) {
|
||||
|
||||
# read local zip header data
|
||||
# get $filename
|
||||
# get $compressedLength
|
||||
|
||||
# read all the compressed data into $data
|
||||
read($fh, $data, $compressedLength);
|
||||
|
||||
my $inf = IO::Uncompress::RawInflate->new( \$data,
|
||||
Transparent => 1 )
|
||||
or die "Cannot uncompress $file [$filename]: $RawInflateError\n" ;
|
||||
|
||||
my $line_count = 0;
|
||||
|
||||
while (<$inf>)
|
||||
{
|
||||
++ $line_count;
|
||||
}
|
||||
|
||||
print "$filename: $line_count\n";
|
||||
}
|
||||
|
||||
The difference here is the addition of the temporary variable C<$data>.
|
||||
This is used to store a copy of the compressed data while it is being
|
||||
uncompressed.
|
||||
|
||||
If you know that C<$compressedLength> isn't that big then using temporary
|
||||
storage won't be a problem. But if C<$compressedLength> is very large or
|
||||
you are writing an application that other people will use, and so have no
|
||||
idea how big C<$compressedLength> will be, it could be an issue.
|
||||
|
||||
Using C<InputLength> avoids the use of temporary storage and means the
|
||||
application can cope with large compressed data streams.
|
||||
|
||||
One final point -- obviously C<InputLength> can only be used whenever you
|
||||
know the length of the compressed data beforehand, like here with a zip
|
||||
file.
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
General feedback/questions/bug reports should be sent to
|
||||
L<https://github.com/pmqs//issues> (preferred) or
|
||||
L<https://rt.cpan.org/Public/Dist/Display.html?Name=>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzip>, L<IO::Uncompress::UnLzip>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Compress::Zstd>, L<IO::Uncompress::UnZstd>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
|
||||
|
||||
L<IO::Compress::FAQ|IO::Compress::FAQ>
|
||||
|
||||
L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
|
||||
L<Archive::Tar|Archive::Tar>,
|
||||
L<IO::Zlib|IO::Zlib>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
This module was written by Paul Marquess, C<pmqs@cpan.org>.
|
||||
|
||||
=head1 MODIFICATION HISTORY
|
||||
|
||||
See the Changes file.
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (c) 2005-2021 Paul Marquess. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
1270
database/perl/lib/IO/Compress/Gzip.pm
Normal file
1270
database/perl/lib/IO/Compress/Gzip.pm
Normal file
File diff suppressed because it is too large
Load Diff
148
database/perl/lib/IO/Compress/Gzip/Constants.pm
Normal file
148
database/perl/lib/IO/Compress/Gzip/Constants.pm
Normal file
@@ -0,0 +1,148 @@
|
||||
package IO::Compress::Gzip::Constants;
|
||||
|
||||
use strict ;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our ($VERSION, @ISA, @EXPORT, %GZIP_OS_Names);
|
||||
our ($GZIP_FNAME_INVALID_CHAR_RE, $GZIP_FCOMMENT_INVALID_CHAR_RE);
|
||||
|
||||
$VERSION = '2.100';
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
|
||||
@EXPORT= qw(
|
||||
|
||||
GZIP_ID_SIZE
|
||||
GZIP_ID1
|
||||
GZIP_ID2
|
||||
|
||||
GZIP_FLG_DEFAULT
|
||||
GZIP_FLG_FTEXT
|
||||
GZIP_FLG_FHCRC
|
||||
GZIP_FLG_FEXTRA
|
||||
GZIP_FLG_FNAME
|
||||
GZIP_FLG_FCOMMENT
|
||||
GZIP_FLG_RESERVED
|
||||
|
||||
GZIP_CM_DEFLATED
|
||||
|
||||
GZIP_MIN_HEADER_SIZE
|
||||
GZIP_TRAILER_SIZE
|
||||
|
||||
GZIP_MTIME_DEFAULT
|
||||
GZIP_XFL_DEFAULT
|
||||
GZIP_FEXTRA_HEADER_SIZE
|
||||
GZIP_FEXTRA_MAX_SIZE
|
||||
GZIP_FEXTRA_SUBFIELD_HEADER_SIZE
|
||||
GZIP_FEXTRA_SUBFIELD_ID_SIZE
|
||||
GZIP_FEXTRA_SUBFIELD_LEN_SIZE
|
||||
GZIP_FEXTRA_SUBFIELD_MAX_SIZE
|
||||
|
||||
$GZIP_FNAME_INVALID_CHAR_RE
|
||||
$GZIP_FCOMMENT_INVALID_CHAR_RE
|
||||
|
||||
GZIP_FHCRC_SIZE
|
||||
|
||||
GZIP_ISIZE_MAX
|
||||
GZIP_ISIZE_MOD_VALUE
|
||||
|
||||
|
||||
GZIP_NULL_BYTE
|
||||
|
||||
GZIP_OS_DEFAULT
|
||||
|
||||
%GZIP_OS_Names
|
||||
|
||||
GZIP_MINIMUM_HEADER
|
||||
|
||||
);
|
||||
|
||||
# Constant names derived from RFC 1952
|
||||
|
||||
use constant GZIP_ID_SIZE => 2 ;
|
||||
use constant GZIP_ID1 => 0x1F;
|
||||
use constant GZIP_ID2 => 0x8B;
|
||||
|
||||
use constant GZIP_MIN_HEADER_SIZE => 10 ;# minimum gzip header size
|
||||
use constant GZIP_TRAILER_SIZE => 8 ;
|
||||
|
||||
|
||||
use constant GZIP_FLG_DEFAULT => 0x00 ;
|
||||
use constant GZIP_FLG_FTEXT => 0x01 ;
|
||||
use constant GZIP_FLG_FHCRC => 0x02 ; # called CONTINUATION in gzip
|
||||
use constant GZIP_FLG_FEXTRA => 0x04 ;
|
||||
use constant GZIP_FLG_FNAME => 0x08 ;
|
||||
use constant GZIP_FLG_FCOMMENT => 0x10 ;
|
||||
#use constant GZIP_FLG_ENCRYPTED => 0x20 ; # documented in gzip sources
|
||||
use constant GZIP_FLG_RESERVED => (0x20 | 0x40 | 0x80) ;
|
||||
|
||||
use constant GZIP_XFL_DEFAULT => 0x00 ;
|
||||
|
||||
use constant GZIP_MTIME_DEFAULT => 0x00 ;
|
||||
|
||||
use constant GZIP_FEXTRA_HEADER_SIZE => 2 ;
|
||||
use constant GZIP_FEXTRA_MAX_SIZE => 0xFFFF ;
|
||||
use constant GZIP_FEXTRA_SUBFIELD_ID_SIZE => 2 ;
|
||||
use constant GZIP_FEXTRA_SUBFIELD_LEN_SIZE => 2 ;
|
||||
use constant GZIP_FEXTRA_SUBFIELD_HEADER_SIZE => GZIP_FEXTRA_SUBFIELD_ID_SIZE +
|
||||
GZIP_FEXTRA_SUBFIELD_LEN_SIZE;
|
||||
use constant GZIP_FEXTRA_SUBFIELD_MAX_SIZE => GZIP_FEXTRA_MAX_SIZE -
|
||||
GZIP_FEXTRA_SUBFIELD_HEADER_SIZE ;
|
||||
|
||||
|
||||
if (ord('A') == 193)
|
||||
{
|
||||
# EBCDIC
|
||||
$GZIP_FNAME_INVALID_CHAR_RE = '[\x00-\x3f\xff]';
|
||||
$GZIP_FCOMMENT_INVALID_CHAR_RE = '[\x00-\x0a\x11-\x14\x16-\x3f\xff]';
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$GZIP_FNAME_INVALID_CHAR_RE = '[\x00-\x1F\x7F-\x9F]';
|
||||
$GZIP_FCOMMENT_INVALID_CHAR_RE = '[\x00-\x09\x11-\x1F\x7F-\x9F]';
|
||||
}
|
||||
|
||||
use constant GZIP_FHCRC_SIZE => 2 ; # aka CONTINUATION in gzip
|
||||
|
||||
use constant GZIP_CM_DEFLATED => 8 ;
|
||||
|
||||
use constant GZIP_NULL_BYTE => "\x00";
|
||||
use constant GZIP_ISIZE_MAX => 0xFFFFFFFF ;
|
||||
use constant GZIP_ISIZE_MOD_VALUE => GZIP_ISIZE_MAX + 1 ;
|
||||
|
||||
# OS Names sourced from http://www.gzip.org/format.txt
|
||||
|
||||
use constant GZIP_OS_DEFAULT=> 0xFF ;
|
||||
%GZIP_OS_Names = (
|
||||
0 => 'MS-DOS',
|
||||
1 => 'Amiga',
|
||||
2 => 'VMS',
|
||||
3 => 'Unix',
|
||||
4 => 'VM/CMS',
|
||||
5 => 'Atari TOS',
|
||||
6 => 'HPFS (OS/2, NT)',
|
||||
7 => 'Macintosh',
|
||||
8 => 'Z-System',
|
||||
9 => 'CP/M',
|
||||
10 => 'TOPS-20',
|
||||
11 => 'NTFS (NT)',
|
||||
12 => 'SMS QDOS',
|
||||
13 => 'Acorn RISCOS',
|
||||
14 => 'VFAT file system (Win95, NT)',
|
||||
15 => 'MVS',
|
||||
16 => 'BeOS',
|
||||
17 => 'Tandem/NSK',
|
||||
18 => 'THEOS',
|
||||
GZIP_OS_DEFAULT() => 'Unknown',
|
||||
) ;
|
||||
|
||||
use constant GZIP_MINIMUM_HEADER => pack("C4 V C C",
|
||||
GZIP_ID1, GZIP_ID2, GZIP_CM_DEFLATED, GZIP_FLG_DEFAULT,
|
||||
GZIP_MTIME_DEFAULT, GZIP_XFL_DEFAULT, GZIP_OS_DEFAULT) ;
|
||||
|
||||
|
||||
1;
|
||||
1013
database/perl/lib/IO/Compress/RawDeflate.pm
Normal file
1013
database/perl/lib/IO/Compress/RawDeflate.pm
Normal file
File diff suppressed because it is too large
Load Diff
2149
database/perl/lib/IO/Compress/Zip.pm
Normal file
2149
database/perl/lib/IO/Compress/Zip.pm
Normal file
File diff suppressed because it is too large
Load Diff
130
database/perl/lib/IO/Compress/Zip/Constants.pm
Normal file
130
database/perl/lib/IO/Compress/Zip/Constants.pm
Normal file
@@ -0,0 +1,130 @@
|
||||
package IO::Compress::Zip::Constants;
|
||||
|
||||
use strict ;
|
||||
use warnings;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our ($VERSION, @ISA, @EXPORT, %ZIP_CM_MIN_VERSIONS);
|
||||
|
||||
$VERSION = '2.100';
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
|
||||
@EXPORT= qw(
|
||||
|
||||
ZIP_CM_STORE
|
||||
ZIP_CM_DEFLATE
|
||||
ZIP_CM_BZIP2
|
||||
ZIP_CM_LZMA
|
||||
ZIP_CM_PPMD
|
||||
ZIP_CM_XZ
|
||||
ZIP_CM_ZSTD
|
||||
|
||||
ZIP_LOCAL_HDR_SIG
|
||||
ZIP_DATA_HDR_SIG
|
||||
ZIP_CENTRAL_HDR_SIG
|
||||
ZIP_END_CENTRAL_HDR_SIG
|
||||
ZIP64_END_CENTRAL_REC_HDR_SIG
|
||||
ZIP64_END_CENTRAL_LOC_HDR_SIG
|
||||
ZIP64_ARCHIVE_EXTRA_SIG
|
||||
ZIP64_DIGITAL_SIGNATURE_SIG
|
||||
|
||||
ZIP_GP_FLAG_ENCRYPTED_MASK
|
||||
ZIP_GP_FLAG_STREAMING_MASK
|
||||
ZIP_GP_FLAG_PATCHED_MASK
|
||||
ZIP_GP_FLAG_STRONG_ENCRYPTED_MASK
|
||||
ZIP_GP_FLAG_LZMA_EOS_PRESENT
|
||||
ZIP_GP_FLAG_LANGUAGE_ENCODING
|
||||
|
||||
ZIP_EXTRA_ID_ZIP64
|
||||
ZIP_EXTRA_ID_EXT_TIMESTAMP
|
||||
ZIP_EXTRA_ID_INFO_ZIP_UNIX2
|
||||
ZIP_EXTRA_ID_INFO_ZIP_UNIXN
|
||||
ZIP_EXTRA_ID_INFO_ZIP_Upath
|
||||
ZIP_EXTRA_ID_INFO_ZIP_Ucom
|
||||
ZIP_EXTRA_ID_JAVA_EXE
|
||||
|
||||
ZIP_OS_CODE_UNIX
|
||||
ZIP_OS_CODE_DEFAULT
|
||||
|
||||
ZIP_IFA_TEXT_MASK
|
||||
|
||||
%ZIP_CM_MIN_VERSIONS
|
||||
ZIP64_MIN_VERSION
|
||||
|
||||
ZIP_A_RONLY
|
||||
ZIP_A_HIDDEN
|
||||
ZIP_A_SYSTEM
|
||||
ZIP_A_LABEL
|
||||
ZIP_A_DIR
|
||||
ZIP_A_ARCHIVE
|
||||
);
|
||||
|
||||
# Compression types supported
|
||||
use constant ZIP_CM_STORE => 0 ;
|
||||
use constant ZIP_CM_DEFLATE => 8 ;
|
||||
use constant ZIP_CM_BZIP2 => 12 ;
|
||||
use constant ZIP_CM_LZMA => 14 ;
|
||||
use constant ZIP_CM_ZSTD => 93 ;
|
||||
use constant ZIP_CM_XZ => 95 ;
|
||||
use constant ZIP_CM_PPMD => 98 ; # Not Supported yet
|
||||
|
||||
# General Purpose Flag
|
||||
use constant ZIP_GP_FLAG_ENCRYPTED_MASK => (1 << 0) ;
|
||||
use constant ZIP_GP_FLAG_STREAMING_MASK => (1 << 3) ;
|
||||
use constant ZIP_GP_FLAG_PATCHED_MASK => (1 << 5) ;
|
||||
use constant ZIP_GP_FLAG_STRONG_ENCRYPTED_MASK => (1 << 6) ;
|
||||
use constant ZIP_GP_FLAG_LZMA_EOS_PRESENT => (1 << 1) ;
|
||||
use constant ZIP_GP_FLAG_LANGUAGE_ENCODING => (1 << 11) ;
|
||||
|
||||
# Internal File Attributes
|
||||
use constant ZIP_IFA_TEXT_MASK => 1;
|
||||
|
||||
# Signatures for each of the headers
|
||||
use constant ZIP_LOCAL_HDR_SIG => 0x04034b50;
|
||||
use constant ZIP_DATA_HDR_SIG => 0x08074b50;
|
||||
use constant packed_ZIP_DATA_HDR_SIG => pack "V", ZIP_DATA_HDR_SIG;
|
||||
use constant ZIP_CENTRAL_HDR_SIG => 0x02014b50;
|
||||
use constant ZIP_END_CENTRAL_HDR_SIG => 0x06054b50;
|
||||
use constant ZIP64_END_CENTRAL_REC_HDR_SIG => 0x06064b50;
|
||||
use constant ZIP64_END_CENTRAL_LOC_HDR_SIG => 0x07064b50;
|
||||
use constant ZIP64_ARCHIVE_EXTRA_SIG => 0x08064b50;
|
||||
use constant ZIP64_DIGITAL_SIGNATURE_SIG => 0x05054b50;
|
||||
|
||||
use constant ZIP_OS_CODE_UNIX => 3;
|
||||
use constant ZIP_OS_CODE_DEFAULT => 3;
|
||||
|
||||
# Extra Field ID's
|
||||
use constant ZIP_EXTRA_ID_ZIP64 => pack "v", 1;
|
||||
use constant ZIP_EXTRA_ID_EXT_TIMESTAMP => "UT";
|
||||
use constant ZIP_EXTRA_ID_INFO_ZIP_UNIX2 => "Ux";
|
||||
use constant ZIP_EXTRA_ID_INFO_ZIP_UNIXN => "ux";
|
||||
use constant ZIP_EXTRA_ID_INFO_ZIP_Upath => "up";
|
||||
use constant ZIP_EXTRA_ID_INFO_ZIP_Ucom => "uc";
|
||||
use constant ZIP_EXTRA_ID_JAVA_EXE => pack "v", 0xCAFE;
|
||||
|
||||
# DOS Attributes
|
||||
use constant ZIP_A_RONLY => 0x01;
|
||||
use constant ZIP_A_HIDDEN => 0x02;
|
||||
use constant ZIP_A_SYSTEM => 0x04;
|
||||
use constant ZIP_A_LABEL => 0x08;
|
||||
use constant ZIP_A_DIR => 0x10;
|
||||
use constant ZIP_A_ARCHIVE => 0x20;
|
||||
|
||||
use constant ZIP64_MIN_VERSION => 45;
|
||||
|
||||
%ZIP_CM_MIN_VERSIONS = (
|
||||
ZIP_CM_STORE() => 20,
|
||||
ZIP_CM_DEFLATE() => 20,
|
||||
ZIP_CM_BZIP2() => 46,
|
||||
ZIP_CM_LZMA() => 63,
|
||||
ZIP_CM_PPMD() => 63,
|
||||
ZIP_CM_ZSTD() => 20, # Winzip needs these to be 20
|
||||
ZIP_CM_XZ() => 20,
|
||||
);
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
77
database/perl/lib/IO/Compress/Zlib/Constants.pm
Normal file
77
database/perl/lib/IO/Compress/Zlib/Constants.pm
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
package IO::Compress::Zlib::Constants ;
|
||||
|
||||
use strict ;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our ($VERSION, @ISA, @EXPORT);
|
||||
|
||||
$VERSION = '2.100';
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
|
||||
@EXPORT= qw(
|
||||
|
||||
ZLIB_HEADER_SIZE
|
||||
ZLIB_TRAILER_SIZE
|
||||
|
||||
ZLIB_CMF_CM_OFFSET
|
||||
ZLIB_CMF_CM_BITS
|
||||
ZLIB_CMF_CM_DEFLATED
|
||||
|
||||
ZLIB_CMF_CINFO_OFFSET
|
||||
ZLIB_CMF_CINFO_BITS
|
||||
ZLIB_CMF_CINFO_MAX
|
||||
|
||||
ZLIB_FLG_FCHECK_OFFSET
|
||||
ZLIB_FLG_FCHECK_BITS
|
||||
|
||||
ZLIB_FLG_FDICT_OFFSET
|
||||
ZLIB_FLG_FDICT_BITS
|
||||
|
||||
ZLIB_FLG_LEVEL_OFFSET
|
||||
ZLIB_FLG_LEVEL_BITS
|
||||
|
||||
ZLIB_FLG_LEVEL_FASTEST
|
||||
ZLIB_FLG_LEVEL_FAST
|
||||
ZLIB_FLG_LEVEL_DEFAULT
|
||||
ZLIB_FLG_LEVEL_SLOWEST
|
||||
|
||||
ZLIB_FDICT_SIZE
|
||||
|
||||
);
|
||||
|
||||
# Constant names derived from RFC1950
|
||||
|
||||
use constant ZLIB_HEADER_SIZE => 2;
|
||||
use constant ZLIB_TRAILER_SIZE => 4;
|
||||
|
||||
use constant ZLIB_CMF_CM_OFFSET => 0;
|
||||
use constant ZLIB_CMF_CM_BITS => 0xF ; # 0b1111
|
||||
use constant ZLIB_CMF_CM_DEFLATED => 8;
|
||||
|
||||
use constant ZLIB_CMF_CINFO_OFFSET => 4;
|
||||
use constant ZLIB_CMF_CINFO_BITS => 0xF ; # 0b1111;
|
||||
use constant ZLIB_CMF_CINFO_MAX => 7;
|
||||
|
||||
use constant ZLIB_FLG_FCHECK_OFFSET => 0;
|
||||
use constant ZLIB_FLG_FCHECK_BITS => 0x1F ; # 0b11111;
|
||||
|
||||
use constant ZLIB_FLG_FDICT_OFFSET => 5;
|
||||
use constant ZLIB_FLG_FDICT_BITS => 0x1 ; # 0b1;
|
||||
|
||||
use constant ZLIB_FLG_LEVEL_OFFSET => 6;
|
||||
use constant ZLIB_FLG_LEVEL_BITS => 0x3 ; # 0b11;
|
||||
|
||||
use constant ZLIB_FLG_LEVEL_FASTEST => 0;
|
||||
use constant ZLIB_FLG_LEVEL_FAST => 1;
|
||||
use constant ZLIB_FLG_LEVEL_DEFAULT => 2;
|
||||
use constant ZLIB_FLG_LEVEL_SLOWEST => 3;
|
||||
|
||||
use constant ZLIB_FDICT_SIZE => 4;
|
||||
|
||||
|
||||
1;
|
||||
229
database/perl/lib/IO/Compress/Zlib/Extra.pm
Normal file
229
database/perl/lib/IO/Compress/Zlib/Extra.pm
Normal file
@@ -0,0 +1,229 @@
|
||||
package IO::Compress::Zlib::Extra;
|
||||
|
||||
require 5.006 ;
|
||||
|
||||
use strict ;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS);
|
||||
|
||||
$VERSION = '2.100';
|
||||
|
||||
use IO::Compress::Gzip::Constants 2.100 ;
|
||||
|
||||
sub ExtraFieldError
|
||||
{
|
||||
return $_[0];
|
||||
return "Error with ExtraField Parameter: $_[0]" ;
|
||||
}
|
||||
|
||||
sub validateExtraFieldPair
|
||||
{
|
||||
my $pair = shift ;
|
||||
my $strict = shift;
|
||||
my $gzipMode = shift ;
|
||||
|
||||
return ExtraFieldError("Not an array ref")
|
||||
unless ref $pair && ref $pair eq 'ARRAY';
|
||||
|
||||
return ExtraFieldError("SubField must have two parts")
|
||||
unless @$pair == 2 ;
|
||||
|
||||
return ExtraFieldError("SubField ID is a reference")
|
||||
if ref $pair->[0] ;
|
||||
|
||||
return ExtraFieldError("SubField Data is a reference")
|
||||
if ref $pair->[1] ;
|
||||
|
||||
# ID is exactly two chars
|
||||
return ExtraFieldError("SubField ID not two chars long")
|
||||
unless length $pair->[0] == GZIP_FEXTRA_SUBFIELD_ID_SIZE ;
|
||||
|
||||
# Check that the 2nd byte of the ID isn't 0
|
||||
return ExtraFieldError("SubField ID 2nd byte is 0x00")
|
||||
if $strict && $gzipMode && substr($pair->[0], 1, 1) eq "\x00" ;
|
||||
|
||||
return ExtraFieldError("SubField Data too long")
|
||||
if length $pair->[1] > GZIP_FEXTRA_SUBFIELD_MAX_SIZE ;
|
||||
|
||||
|
||||
return undef ;
|
||||
}
|
||||
|
||||
sub parseRawExtra
|
||||
{
|
||||
my $data = shift ;
|
||||
my $extraRef = shift;
|
||||
my $strict = shift;
|
||||
my $gzipMode = shift ;
|
||||
|
||||
#my $lax = shift ;
|
||||
|
||||
#return undef
|
||||
# if $lax ;
|
||||
|
||||
my $XLEN = length $data ;
|
||||
|
||||
return ExtraFieldError("Too Large")
|
||||
if $XLEN > GZIP_FEXTRA_MAX_SIZE;
|
||||
|
||||
my $offset = 0 ;
|
||||
while ($offset < $XLEN) {
|
||||
|
||||
return ExtraFieldError("Truncated in FEXTRA Body Section")
|
||||
if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ;
|
||||
|
||||
my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE);
|
||||
$offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE;
|
||||
|
||||
my $subLen = unpack("v", substr($data, $offset,
|
||||
GZIP_FEXTRA_SUBFIELD_LEN_SIZE));
|
||||
$offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ;
|
||||
|
||||
return ExtraFieldError("Truncated in FEXTRA Body Section")
|
||||
if $offset + $subLen > $XLEN ;
|
||||
|
||||
my $bad = validateExtraFieldPair( [$id,
|
||||
substr($data, $offset, $subLen)],
|
||||
$strict, $gzipMode );
|
||||
return $bad if $bad ;
|
||||
push @$extraRef, [$id => substr($data, $offset, $subLen)]
|
||||
if defined $extraRef;;
|
||||
|
||||
$offset += $subLen ;
|
||||
}
|
||||
|
||||
|
||||
return undef ;
|
||||
}
|
||||
|
||||
sub findID
|
||||
{
|
||||
my $id_want = shift ;
|
||||
my $data = shift;
|
||||
|
||||
my $XLEN = length $data ;
|
||||
|
||||
my $offset = 0 ;
|
||||
while ($offset < $XLEN) {
|
||||
|
||||
return undef
|
||||
if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ;
|
||||
|
||||
my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE);
|
||||
$offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE;
|
||||
|
||||
my $subLen = unpack("v", substr($data, $offset,
|
||||
GZIP_FEXTRA_SUBFIELD_LEN_SIZE));
|
||||
$offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ;
|
||||
|
||||
return undef
|
||||
if $offset + $subLen > $XLEN ;
|
||||
|
||||
return substr($data, $offset, $subLen)
|
||||
if $id eq $id_want ;
|
||||
|
||||
$offset += $subLen ;
|
||||
}
|
||||
|
||||
return undef ;
|
||||
}
|
||||
|
||||
|
||||
sub mkSubField
|
||||
{
|
||||
my $id = shift ;
|
||||
my $data = shift ;
|
||||
|
||||
return $id . pack("v", length $data) . $data ;
|
||||
}
|
||||
|
||||
sub parseExtraField
|
||||
{
|
||||
my $dataRef = $_[0];
|
||||
my $strict = $_[1];
|
||||
my $gzipMode = $_[2];
|
||||
#my $lax = @_ == 2 ? $_[1] : 1;
|
||||
|
||||
|
||||
# ExtraField can be any of
|
||||
#
|
||||
# -ExtraField => $data
|
||||
#
|
||||
# -ExtraField => [$id1, $data1,
|
||||
# $id2, $data2]
|
||||
# ...
|
||||
# ]
|
||||
#
|
||||
# -ExtraField => [ [$id1 => $data1],
|
||||
# [$id2 => $data2],
|
||||
# ...
|
||||
# ]
|
||||
#
|
||||
# -ExtraField => { $id1 => $data1,
|
||||
# $id2 => $data2,
|
||||
# ...
|
||||
# }
|
||||
|
||||
if ( ! ref $dataRef ) {
|
||||
|
||||
return undef
|
||||
if ! $strict;
|
||||
|
||||
return parseRawExtra($dataRef, undef, 1, $gzipMode);
|
||||
}
|
||||
|
||||
my $data = $dataRef;
|
||||
my $out = '' ;
|
||||
|
||||
if (ref $data eq 'ARRAY') {
|
||||
if (ref $data->[0]) {
|
||||
|
||||
foreach my $pair (@$data) {
|
||||
return ExtraFieldError("Not list of lists")
|
||||
unless ref $pair eq 'ARRAY' ;
|
||||
|
||||
my $bad = validateExtraFieldPair($pair, $strict, $gzipMode) ;
|
||||
return $bad if $bad ;
|
||||
|
||||
$out .= mkSubField(@$pair);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return ExtraFieldError("Not even number of elements")
|
||||
unless @$data % 2 == 0;
|
||||
|
||||
for (my $ix = 0; $ix <= @$data -1 ; $ix += 2) {
|
||||
my $bad = validateExtraFieldPair([$data->[$ix],
|
||||
$data->[$ix+1]],
|
||||
$strict, $gzipMode) ;
|
||||
return $bad if $bad ;
|
||||
|
||||
$out .= mkSubField($data->[$ix], $data->[$ix+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif (ref $data eq 'HASH') {
|
||||
while (my ($id, $info) = each %$data) {
|
||||
my $bad = validateExtraFieldPair([$id, $info], $strict, $gzipMode);
|
||||
return $bad if $bad ;
|
||||
|
||||
$out .= mkSubField($id, $info);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return ExtraFieldError("Not a scalar, array ref or hash ref") ;
|
||||
}
|
||||
|
||||
return ExtraFieldError("Too Large")
|
||||
if length $out > GZIP_FEXTRA_MAX_SIZE;
|
||||
|
||||
$_[0] = $out ;
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
247
database/perl/lib/IO/Dir.pm
Normal file
247
database/perl/lib/IO/Dir.pm
Normal file
@@ -0,0 +1,247 @@
|
||||
# IO::Dir.pm
|
||||
#
|
||||
# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Dir;
|
||||
|
||||
use 5.008_001;
|
||||
|
||||
use strict;
|
||||
use Carp;
|
||||
use Symbol;
|
||||
use Exporter;
|
||||
use IO::File;
|
||||
use Tie::Hash;
|
||||
use File::stat;
|
||||
use File::Spec;
|
||||
|
||||
our @ISA = qw(Tie::Hash Exporter);
|
||||
our $VERSION = "1.45";
|
||||
|
||||
our @EXPORT_OK = qw(DIR_UNLINK);
|
||||
|
||||
sub DIR_UNLINK () { 1 }
|
||||
|
||||
sub new {
|
||||
@_ >= 1 && @_ <= 2 or croak 'usage: IO::Dir->new([DIRNAME])';
|
||||
my $class = shift;
|
||||
my $dh = gensym;
|
||||
if (@_) {
|
||||
IO::Dir::open($dh, $_[0])
|
||||
or return undef;
|
||||
}
|
||||
bless $dh, $class;
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
my ($dh) = @_;
|
||||
local($., $@, $!, $^E, $?);
|
||||
no warnings 'io';
|
||||
closedir($dh);
|
||||
}
|
||||
|
||||
sub open {
|
||||
@_ == 2 or croak 'usage: $dh->open(DIRNAME)';
|
||||
my ($dh, $dirname) = @_;
|
||||
return undef
|
||||
unless opendir($dh, $dirname);
|
||||
# a dir name should always have a ":" in it; assume dirname is
|
||||
# in current directory
|
||||
$dirname = ':' . $dirname if ( ($^O eq 'MacOS') && ($dirname !~ /:/) );
|
||||
${*$dh}{io_dir_path} = $dirname;
|
||||
1;
|
||||
}
|
||||
|
||||
sub close {
|
||||
@_ == 1 or croak 'usage: $dh->close()';
|
||||
my ($dh) = @_;
|
||||
closedir($dh);
|
||||
}
|
||||
|
||||
sub read {
|
||||
@_ == 1 or croak 'usage: $dh->read()';
|
||||
my ($dh) = @_;
|
||||
readdir($dh);
|
||||
}
|
||||
|
||||
sub seek {
|
||||
@_ == 2 or croak 'usage: $dh->seek(POS)';
|
||||
my ($dh,$pos) = @_;
|
||||
seekdir($dh,$pos);
|
||||
}
|
||||
|
||||
sub tell {
|
||||
@_ == 1 or croak 'usage: $dh->tell()';
|
||||
my ($dh) = @_;
|
||||
telldir($dh);
|
||||
}
|
||||
|
||||
sub rewind {
|
||||
@_ == 1 or croak 'usage: $dh->rewind()';
|
||||
my ($dh) = @_;
|
||||
rewinddir($dh);
|
||||
}
|
||||
|
||||
sub TIEHASH {
|
||||
my($class,$dir,$options) = @_;
|
||||
|
||||
my $dh = $class->new($dir)
|
||||
or return undef;
|
||||
|
||||
$options ||= 0;
|
||||
|
||||
${*$dh}{io_dir_unlink} = $options & DIR_UNLINK;
|
||||
$dh;
|
||||
}
|
||||
|
||||
sub FIRSTKEY {
|
||||
my($dh) = @_;
|
||||
$dh->rewind;
|
||||
scalar $dh->read;
|
||||
}
|
||||
|
||||
sub NEXTKEY {
|
||||
my($dh) = @_;
|
||||
scalar $dh->read;
|
||||
}
|
||||
|
||||
sub EXISTS {
|
||||
my($dh,$key) = @_;
|
||||
-e File::Spec->catfile(${*$dh}{io_dir_path}, $key);
|
||||
}
|
||||
|
||||
sub FETCH {
|
||||
my($dh,$key) = @_;
|
||||
&lstat(File::Spec->catfile(${*$dh}{io_dir_path}, $key));
|
||||
}
|
||||
|
||||
sub STORE {
|
||||
my($dh,$key,$data) = @_;
|
||||
my($atime,$mtime) = ref($data) ? @$data : ($data,$data);
|
||||
my $file = File::Spec->catfile(${*$dh}{io_dir_path}, $key);
|
||||
unless(-e $file) {
|
||||
my $io = IO::File->new($file,O_CREAT | O_RDWR);
|
||||
$io->close if $io;
|
||||
}
|
||||
utime($atime,$mtime, $file);
|
||||
}
|
||||
|
||||
sub DELETE {
|
||||
my($dh,$key) = @_;
|
||||
|
||||
# Only unlink if unlink-ing is enabled
|
||||
return 0
|
||||
unless ${*$dh}{io_dir_unlink};
|
||||
|
||||
my $file = File::Spec->catfile(${*$dh}{io_dir_path}, $key);
|
||||
|
||||
-d $file
|
||||
? rmdir($file)
|
||||
: unlink($file);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Dir - supply object methods for directory handles
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Dir;
|
||||
$d = IO::Dir->new(".");
|
||||
if (defined $d) {
|
||||
while (defined($_ = $d->read)) { something($_); }
|
||||
$d->rewind;
|
||||
while (defined($_ = $d->read)) { something_else($_); }
|
||||
undef $d;
|
||||
}
|
||||
|
||||
tie %dir, 'IO::Dir', ".";
|
||||
foreach (keys %dir) {
|
||||
print $_, " " , $dir{$_}->size,"\n";
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<IO::Dir> package provides two interfaces to perl's directory reading
|
||||
routines.
|
||||
|
||||
The first interface is an object approach. C<IO::Dir> provides an object
|
||||
constructor and methods, which are just wrappers around perl's built in
|
||||
directory reading routines.
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ( [ DIRNAME ] )
|
||||
|
||||
C<new> is the constructor for C<IO::Dir> objects. It accepts one optional
|
||||
argument which, if given, C<new> will pass to C<open>
|
||||
|
||||
=back
|
||||
|
||||
The following methods are wrappers for the directory related functions built
|
||||
into perl (the trailing 'dir' has been removed from the names). See L<perlfunc>
|
||||
for details of these functions.
|
||||
|
||||
=over 4
|
||||
|
||||
=item open ( DIRNAME )
|
||||
|
||||
=item read ()
|
||||
|
||||
=item seek ( POS )
|
||||
|
||||
=item tell ()
|
||||
|
||||
=item rewind ()
|
||||
|
||||
=item close ()
|
||||
|
||||
=back
|
||||
|
||||
C<IO::Dir> also provides an interface to reading directories via a tied
|
||||
hash. The tied hash extends the interface beyond just the directory
|
||||
reading routines by the use of C<lstat>, from the C<File::stat> package,
|
||||
C<unlink>, C<rmdir> and C<utime>.
|
||||
|
||||
=over 4
|
||||
|
||||
=item tie %hash, 'IO::Dir', DIRNAME [, OPTIONS ]
|
||||
|
||||
=back
|
||||
|
||||
The keys of the hash will be the names of the entries in the directory.
|
||||
Reading a value from the hash will be the result of calling
|
||||
C<File::stat::lstat>. Deleting an element from the hash will
|
||||
delete the corresponding file or subdirectory,
|
||||
provided that C<DIR_UNLINK> is included in the C<OPTIONS>.
|
||||
|
||||
Assigning to an entry in the hash will cause the time stamps of the file
|
||||
to be modified. If the file does not exist then it will be created. Assigning
|
||||
a single integer to a hash element will cause both the access and
|
||||
modification times to be changed to that value. Alternatively a reference to
|
||||
an array of two values can be passed. The first array element will be used to
|
||||
set the access time and the second element will be used to set the modification
|
||||
time.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<File::stat>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Graham Barr. Currently maintained by the Perl Porters. Please report all
|
||||
bugs to <perlbug@perl.org>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1997-2003 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
202
database/perl/lib/IO/File.pm
Normal file
202
database/perl/lib/IO/File.pm
Normal file
@@ -0,0 +1,202 @@
|
||||
#
|
||||
|
||||
package IO::File;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::File - supply object methods for filehandles
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::File;
|
||||
|
||||
$fh = IO::File->new();
|
||||
if ($fh->open("< file")) {
|
||||
print <$fh>;
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
$fh = IO::File->new("> file");
|
||||
if (defined $fh) {
|
||||
print $fh "bar\n";
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
$fh = IO::File->new("file", "r");
|
||||
if (defined $fh) {
|
||||
print <$fh>;
|
||||
undef $fh; # automatically closes the file
|
||||
}
|
||||
|
||||
$fh = IO::File->new("file", O_WRONLY|O_APPEND);
|
||||
if (defined $fh) {
|
||||
print $fh "corge\n";
|
||||
|
||||
$pos = $fh->getpos;
|
||||
$fh->setpos($pos);
|
||||
|
||||
undef $fh; # automatically closes the file
|
||||
}
|
||||
|
||||
autoflush STDOUT 1;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::File> inherits from C<IO::Handle> and C<IO::Seekable>. It extends
|
||||
these classes with methods that are specific to file handles.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ( FILENAME [,MODE [,PERMS]] )
|
||||
|
||||
Creates an C<IO::File>. If it receives any parameters, they are passed to
|
||||
the method C<open>; if the open fails, the object is destroyed. Otherwise,
|
||||
it is returned to the caller.
|
||||
|
||||
=item new_tmpfile
|
||||
|
||||
Creates an C<IO::File> opened for read/write on a newly created temporary
|
||||
file. On systems where this is possible, the temporary file is anonymous
|
||||
(i.e. it is unlinked after creation, but held open). If the temporary
|
||||
file cannot be created or opened, the C<IO::File> object is destroyed.
|
||||
Otherwise, it is returned to the caller.
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item open( FILENAME [,MODE [,PERMS]] )
|
||||
|
||||
=item open( FILENAME, IOLAYERS )
|
||||
|
||||
C<open> accepts one, two or three parameters. With one parameter,
|
||||
it is just a front end for the built-in C<open> function. With two or three
|
||||
parameters, the first parameter is a filename that may include
|
||||
whitespace or other special characters, and the second parameter is
|
||||
the open mode, optionally followed by a file permission value.
|
||||
|
||||
If C<IO::File::open> receives a Perl mode string ("E<gt>", "+E<lt>", etc.)
|
||||
or an ANSI C fopen() mode string ("w", "r+", etc.), it uses the basic
|
||||
Perl C<open> operator (but protects any special characters).
|
||||
|
||||
If C<IO::File::open> is given a numeric mode, it passes that mode
|
||||
and the optional permissions value to the Perl C<sysopen> operator.
|
||||
The permissions default to 0666.
|
||||
|
||||
If C<IO::File::open> is given a mode that includes the C<:> character,
|
||||
it passes all the three arguments to the three-argument C<open> operator.
|
||||
|
||||
For convenience, C<IO::File> exports the O_XXX constants from the
|
||||
Fcntl module, if this module is available.
|
||||
|
||||
=item binmode( [LAYER] )
|
||||
|
||||
C<binmode> sets C<binmode> on the underlying C<IO> object, as documented
|
||||
in C<perldoc -f binmode>.
|
||||
|
||||
C<binmode> accepts one optional parameter, which is the layer to be
|
||||
passed on to the C<binmode> call.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTE
|
||||
|
||||
Some operating systems may perform C<IO::File::new()> or C<IO::File::open()>
|
||||
on a directory without errors. This behavior is not portable and not
|
||||
suggested for use. Using C<opendir()> and C<readdir()> or C<IO::Dir> are
|
||||
suggested instead.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<perlfunc>,
|
||||
L<perlop/"I/O Operators">,
|
||||
L<IO::Handle>,
|
||||
L<IO::Seekable>,
|
||||
L<IO::Dir>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
Derived from FileHandle.pm by Graham Barr E<lt>F<gbarr@pobox.com>E<gt>.
|
||||
|
||||
=cut
|
||||
|
||||
use 5.008_001;
|
||||
use strict;
|
||||
use Carp;
|
||||
use Symbol;
|
||||
use SelectSaver;
|
||||
use IO::Seekable;
|
||||
|
||||
require Exporter;
|
||||
|
||||
our @ISA = qw(IO::Handle IO::Seekable Exporter);
|
||||
|
||||
our $VERSION = "1.45";
|
||||
|
||||
our @EXPORT = @IO::Seekable::EXPORT;
|
||||
|
||||
eval {
|
||||
# Make all Fcntl O_XXX constants available for importing
|
||||
require Fcntl;
|
||||
my @O = grep /^O_/, @Fcntl::EXPORT;
|
||||
Fcntl->import(@O); # first we import what we want to export
|
||||
push(@EXPORT, @O);
|
||||
};
|
||||
|
||||
################################################
|
||||
## Constructor
|
||||
##
|
||||
|
||||
sub new {
|
||||
my $type = shift;
|
||||
my $class = ref($type) || $type || "IO::File";
|
||||
@_ >= 0 && @_ <= 3
|
||||
or croak "usage: $class->new([FILENAME [,MODE [,PERMS]]])";
|
||||
my $fh = $class->SUPER::new();
|
||||
if (@_) {
|
||||
$fh->open(@_)
|
||||
or return undef;
|
||||
}
|
||||
$fh;
|
||||
}
|
||||
|
||||
################################################
|
||||
## Open
|
||||
##
|
||||
|
||||
sub open {
|
||||
@_ >= 2 && @_ <= 4 or croak 'usage: $fh->open(FILENAME [,MODE [,PERMS]])';
|
||||
my ($fh, $file) = @_;
|
||||
if (@_ > 2) {
|
||||
my ($mode, $perms) = @_[2, 3];
|
||||
if ($mode =~ /^\d+$/) {
|
||||
defined $perms or $perms = 0666;
|
||||
return sysopen($fh, $file, $mode, $perms);
|
||||
} elsif ($mode =~ /:/) {
|
||||
return open($fh, $mode, $file) if @_ == 3;
|
||||
croak 'usage: $fh->open(FILENAME, IOLAYERS)';
|
||||
} else {
|
||||
return open($fh, IO::Handle::_open_mode_string($mode), $file);
|
||||
}
|
||||
}
|
||||
open($fh, $file);
|
||||
}
|
||||
|
||||
################################################
|
||||
## Binmode
|
||||
##
|
||||
|
||||
sub binmode {
|
||||
( @_ == 1 or @_ == 2 ) or croak 'usage $fh->binmode([LAYER])';
|
||||
|
||||
my($fh, $layer) = @_;
|
||||
|
||||
return binmode $$fh unless $layer;
|
||||
return binmode $$fh, $layer;
|
||||
}
|
||||
|
||||
1;
|
||||
631
database/perl/lib/IO/Handle.pm
Normal file
631
database/perl/lib/IO/Handle.pm
Normal file
@@ -0,0 +1,631 @@
|
||||
package IO::Handle;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Handle - supply object methods for I/O handles
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Handle;
|
||||
|
||||
$io = IO::Handle->new();
|
||||
if ($io->fdopen(fileno(STDIN),"r")) {
|
||||
print $io->getline;
|
||||
$io->close;
|
||||
}
|
||||
|
||||
$io = IO::Handle->new();
|
||||
if ($io->fdopen(fileno(STDOUT),"w")) {
|
||||
$io->print("Some text\n");
|
||||
}
|
||||
|
||||
# setvbuf is not available by default on Perls 5.8.0 and later.
|
||||
use IO::Handle '_IOLBF';
|
||||
$io->setvbuf($buffer_var, _IOLBF, 1024);
|
||||
|
||||
undef $io; # automatically closes the file if it's open
|
||||
|
||||
autoflush STDOUT 1;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Handle> is the base class for all other IO handle classes. It is
|
||||
not intended that objects of C<IO::Handle> would be created directly,
|
||||
but instead C<IO::Handle> is inherited from by several other classes
|
||||
in the IO hierarchy.
|
||||
|
||||
If you are reading this documentation, looking for a replacement for
|
||||
the C<FileHandle> package, then I suggest you read the documentation
|
||||
for C<IO::File> too.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ()
|
||||
|
||||
Creates a new C<IO::Handle> object.
|
||||
|
||||
=item new_from_fd ( FD, MODE )
|
||||
|
||||
Creates an C<IO::Handle> like C<new> does.
|
||||
It requires two parameters, which are passed to the method C<fdopen>;
|
||||
if the fdopen fails, the object is destroyed. Otherwise, it is returned
|
||||
to the caller.
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
See L<perlfunc> for complete descriptions of each of the following
|
||||
supported C<IO::Handle> methods, which are just front ends for the
|
||||
corresponding built-in functions:
|
||||
|
||||
$io->close
|
||||
$io->eof
|
||||
$io->fcntl( FUNCTION, SCALAR )
|
||||
$io->fileno
|
||||
$io->format_write( [FORMAT_NAME] )
|
||||
$io->getc
|
||||
$io->ioctl( FUNCTION, SCALAR )
|
||||
$io->read ( BUF, LEN, [OFFSET] )
|
||||
$io->print ( ARGS )
|
||||
$io->printf ( FMT, [ARGS] )
|
||||
$io->say ( ARGS )
|
||||
$io->stat
|
||||
$io->sysread ( BUF, LEN, [OFFSET] )
|
||||
$io->syswrite ( BUF, [LEN, [OFFSET]] )
|
||||
$io->truncate ( LEN )
|
||||
|
||||
See L<perlvar> for complete descriptions of each of the following
|
||||
supported C<IO::Handle> methods. All of them return the previous
|
||||
value of the attribute and takes an optional single argument that when
|
||||
given will set the value. If no argument is given the previous value
|
||||
is unchanged (except for $io->autoflush will actually turn ON
|
||||
autoflush by default).
|
||||
|
||||
$io->autoflush ( [BOOL] ) $|
|
||||
$io->format_page_number( [NUM] ) $%
|
||||
$io->format_lines_per_page( [NUM] ) $=
|
||||
$io->format_lines_left( [NUM] ) $-
|
||||
$io->format_name( [STR] ) $~
|
||||
$io->format_top_name( [STR] ) $^
|
||||
$io->input_line_number( [NUM]) $.
|
||||
|
||||
The following methods are not supported on a per-filehandle basis.
|
||||
|
||||
IO::Handle->format_line_break_characters( [STR] ) $:
|
||||
IO::Handle->format_formfeed( [STR]) $^L
|
||||
IO::Handle->output_field_separator( [STR] ) $,
|
||||
IO::Handle->output_record_separator( [STR] ) $\
|
||||
|
||||
IO::Handle->input_record_separator( [STR] ) $/
|
||||
|
||||
Furthermore, for doing normal I/O you might need these:
|
||||
|
||||
=over 4
|
||||
|
||||
=item $io->fdopen ( FD, MODE )
|
||||
|
||||
C<fdopen> is like an ordinary C<open> except that its first parameter
|
||||
is not a filename but rather a file handle name, an IO::Handle object,
|
||||
or a file descriptor number. (For the documentation of the C<open>
|
||||
method, see L<IO::File>.)
|
||||
|
||||
=item $io->opened
|
||||
|
||||
Returns true if the object is currently a valid file descriptor, false
|
||||
otherwise.
|
||||
|
||||
=item $io->getline
|
||||
|
||||
This works like <$io> described in L<perlop/"I/O Operators">
|
||||
except that it's more readable and can be safely called in a
|
||||
list context but still returns just one line. If used as the conditional
|
||||
within a C<while> or C-style C<for> loop, however, you will need to
|
||||
emulate the functionality of <$io> with C<< defined($_ = $io->getline) >>.
|
||||
|
||||
=item $io->getlines
|
||||
|
||||
This works like <$io> when called in a list context to read all
|
||||
the remaining lines in a file, except that it's more readable.
|
||||
It will also croak() if accidentally called in a scalar context.
|
||||
|
||||
=item $io->ungetc ( ORD )
|
||||
|
||||
Pushes a character with the given ordinal value back onto the given
|
||||
handle's input stream. Only one character of pushback per handle is
|
||||
guaranteed.
|
||||
|
||||
=item $io->write ( BUF, LEN [, OFFSET ] )
|
||||
|
||||
This C<write> is somewhat like C<write> found in C, in that it is the
|
||||
opposite of read. The wrapper for the perl C<write> function is
|
||||
called C<format_write>. However, whilst the C C<write> function returns
|
||||
the number of bytes written, this C<write> function simply returns true
|
||||
if successful (like C<print>). A more C-like C<write> is C<syswrite>
|
||||
(see above).
|
||||
|
||||
=item $io->error
|
||||
|
||||
Returns a true value if the given handle has experienced any errors
|
||||
since it was opened or since the last call to C<clearerr>, or if the
|
||||
handle is invalid. It only returns false for a valid handle with no
|
||||
outstanding errors.
|
||||
|
||||
=item $io->clearerr
|
||||
|
||||
Clear the given handle's error indicator. Returns -1 if the handle is
|
||||
invalid, 0 otherwise.
|
||||
|
||||
=item $io->sync
|
||||
|
||||
C<sync> synchronizes a file's in-memory state with that on the
|
||||
physical medium. C<sync> does not operate at the perlio api level, but
|
||||
operates on the file descriptor (similar to sysread, sysseek and
|
||||
systell). This means that any data held at the perlio api level will not
|
||||
be synchronized. To synchronize data that is buffered at the perlio api
|
||||
level you must use the flush method. C<sync> is not implemented on all
|
||||
platforms. Returns "0 but true" on success, C<undef> on error, C<undef>
|
||||
for an invalid handle. See L<fsync(3c)>.
|
||||
|
||||
=item $io->flush
|
||||
|
||||
C<flush> causes perl to flush any buffered data at the perlio api level.
|
||||
Any unread data in the buffer will be discarded, and any unwritten data
|
||||
will be written to the underlying file descriptor. Returns "0 but true"
|
||||
on success, C<undef> on error.
|
||||
|
||||
=item $io->printflush ( ARGS )
|
||||
|
||||
Turns on autoflush, print ARGS and then restores the autoflush status of the
|
||||
C<IO::Handle> object. Returns the return value from print.
|
||||
|
||||
=item $io->blocking ( [ BOOL ] )
|
||||
|
||||
If called with an argument C<blocking> will turn on non-blocking IO if
|
||||
C<BOOL> is false, and turn it off if C<BOOL> is true.
|
||||
|
||||
C<blocking> will return the value of the previous setting, or the
|
||||
current setting if C<BOOL> is not given.
|
||||
|
||||
If an error occurs C<blocking> will return undef and C<$!> will be set.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
If the C functions setbuf() and/or setvbuf() are available, then
|
||||
C<IO::Handle::setbuf> and C<IO::Handle::setvbuf> set the buffering
|
||||
policy for an IO::Handle. The calling sequences for the Perl functions
|
||||
are the same as their C counterparts--including the constants C<_IOFBF>,
|
||||
C<_IOLBF>, and C<_IONBF> for setvbuf()--except that the buffer parameter
|
||||
specifies a scalar variable to use as a buffer. You should only
|
||||
change the buffer before any I/O, or immediately after calling flush.
|
||||
|
||||
WARNING: The IO::Handle::setvbuf() is not available by default on
|
||||
Perls 5.8.0 and later because setvbuf() is rather specific to using
|
||||
the stdio library, while Perl prefers the new perlio subsystem instead.
|
||||
|
||||
WARNING: A variable used as a buffer by C<setbuf> or C<setvbuf> B<must not
|
||||
be modified> in any way until the IO::Handle is closed or C<setbuf> or
|
||||
C<setvbuf> is called again, or memory corruption may result! Remember that
|
||||
the order of global destruction is undefined, so even if your buffer
|
||||
variable remains in scope until program termination, it may be undefined
|
||||
before the file IO::Handle is closed. Note that you need to import the
|
||||
constants C<_IOFBF>, C<_IOLBF>, and C<_IONBF> explicitly. Like C, setbuf
|
||||
returns nothing. setvbuf returns "0 but true", on success, C<undef> on
|
||||
failure.
|
||||
|
||||
Lastly, there is a special method for working under B<-T> and setuid/gid
|
||||
scripts:
|
||||
|
||||
=over 4
|
||||
|
||||
=item $io->untaint
|
||||
|
||||
Marks the object as taint-clean, and as such data read from it will also
|
||||
be considered taint-clean. Note that this is a very trusting action to
|
||||
take, and appropriate consideration for the data source and potential
|
||||
vulnerability should be kept in mind. Returns 0 on success, -1 if setting
|
||||
the taint-clean flag failed. (eg invalid handle)
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTE
|
||||
|
||||
An C<IO::Handle> object is a reference to a symbol/GLOB reference (see
|
||||
the C<Symbol> package). Some modules that
|
||||
inherit from C<IO::Handle> may want to keep object related variables
|
||||
in the hash table part of the GLOB. In an attempt to prevent modules
|
||||
trampling on each other I propose the that any such module should prefix
|
||||
its variables with its own name separated by _'s. For example the IO::Socket
|
||||
module keeps a C<timeout> variable in 'io_socket_timeout'.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<perlfunc>,
|
||||
L<perlop/"I/O Operators">,
|
||||
L<IO::File>
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
Due to backwards compatibility, all filehandles resemble objects
|
||||
of class C<IO::Handle>, or actually classes derived from that class.
|
||||
They actually aren't. Which means you can't derive your own
|
||||
class from C<IO::Handle> and inherit those methods.
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
Derived from FileHandle.pm by Graham Barr E<lt>F<gbarr@pobox.com>E<gt>
|
||||
|
||||
=cut
|
||||
|
||||
use 5.008_001;
|
||||
use strict;
|
||||
use Carp;
|
||||
use Symbol;
|
||||
use SelectSaver;
|
||||
use IO (); # Load the XS module
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
our $VERSION = "1.45";
|
||||
|
||||
our @EXPORT_OK = qw(
|
||||
autoflush
|
||||
output_field_separator
|
||||
output_record_separator
|
||||
input_record_separator
|
||||
input_line_number
|
||||
format_page_number
|
||||
format_lines_per_page
|
||||
format_lines_left
|
||||
format_name
|
||||
format_top_name
|
||||
format_line_break_characters
|
||||
format_formfeed
|
||||
format_write
|
||||
|
||||
print
|
||||
printf
|
||||
say
|
||||
getline
|
||||
getlines
|
||||
|
||||
printflush
|
||||
flush
|
||||
|
||||
SEEK_SET
|
||||
SEEK_CUR
|
||||
SEEK_END
|
||||
_IOFBF
|
||||
_IOLBF
|
||||
_IONBF
|
||||
);
|
||||
|
||||
################################################
|
||||
## Constructors, destructors.
|
||||
##
|
||||
|
||||
sub new {
|
||||
my $class = ref($_[0]) || $_[0] || "IO::Handle";
|
||||
if (@_ != 1) {
|
||||
# Since perl will automatically require IO::File if needed, but
|
||||
# also initialises IO::File's @ISA as part of the core we must
|
||||
# ensure IO::File is loaded if IO::Handle is. This avoids effect-
|
||||
# ively "half-loading" IO::File.
|
||||
if ($] > 5.013 && $class eq 'IO::File' && !$INC{"IO/File.pm"}) {
|
||||
require IO::File;
|
||||
shift;
|
||||
return IO::File::->new(@_);
|
||||
}
|
||||
croak "usage: $class->new()";
|
||||
}
|
||||
my $io = gensym;
|
||||
bless $io, $class;
|
||||
}
|
||||
|
||||
sub new_from_fd {
|
||||
my $class = ref($_[0]) || $_[0] || "IO::Handle";
|
||||
@_ == 3 or croak "usage: $class->new_from_fd(FD, MODE)";
|
||||
my $io = gensym;
|
||||
shift;
|
||||
IO::Handle::fdopen($io, @_)
|
||||
or return undef;
|
||||
bless $io, $class;
|
||||
}
|
||||
|
||||
#
|
||||
# There is no need for DESTROY to do anything, because when the
|
||||
# last reference to an IO object is gone, Perl automatically
|
||||
# closes its associated files (if any). However, to avoid any
|
||||
# attempts to autoload DESTROY, we here define it to do nothing.
|
||||
#
|
||||
sub DESTROY {}
|
||||
|
||||
|
||||
################################################
|
||||
## Open and close.
|
||||
##
|
||||
|
||||
sub _open_mode_string {
|
||||
my ($mode) = @_;
|
||||
$mode =~ /^\+?(<|>>?)$/
|
||||
or $mode =~ s/^r(\+?)$/$1</
|
||||
or $mode =~ s/^w(\+?)$/$1>/
|
||||
or $mode =~ s/^a(\+?)$/$1>>/
|
||||
or croak "IO::Handle: bad open mode: $mode";
|
||||
$mode;
|
||||
}
|
||||
|
||||
sub fdopen {
|
||||
@_ == 3 or croak 'usage: $io->fdopen(FD, MODE)';
|
||||
my ($io, $fd, $mode) = @_;
|
||||
local(*GLOB);
|
||||
|
||||
if (ref($fd) && "$fd" =~ /GLOB\(/o) {
|
||||
# It's a glob reference; Alias it as we cannot get name of anon GLOBs
|
||||
my $n = qualify(*GLOB);
|
||||
*GLOB = *{*$fd};
|
||||
$fd = $n;
|
||||
} elsif ($fd =~ m#^\d+$#) {
|
||||
# It's an FD number; prefix with "=".
|
||||
$fd = "=$fd";
|
||||
}
|
||||
|
||||
open($io, _open_mode_string($mode) . '&' . $fd)
|
||||
? $io : undef;
|
||||
}
|
||||
|
||||
sub close {
|
||||
@_ == 1 or croak 'usage: $io->close()';
|
||||
my($io) = @_;
|
||||
|
||||
close($io);
|
||||
}
|
||||
|
||||
################################################
|
||||
## Normal I/O functions.
|
||||
##
|
||||
|
||||
# flock
|
||||
# select
|
||||
|
||||
sub opened {
|
||||
@_ == 1 or croak 'usage: $io->opened()';
|
||||
defined fileno($_[0]);
|
||||
}
|
||||
|
||||
sub fileno {
|
||||
@_ == 1 or croak 'usage: $io->fileno()';
|
||||
fileno($_[0]);
|
||||
}
|
||||
|
||||
sub getc {
|
||||
@_ == 1 or croak 'usage: $io->getc()';
|
||||
getc($_[0]);
|
||||
}
|
||||
|
||||
sub eof {
|
||||
@_ == 1 or croak 'usage: $io->eof()';
|
||||
eof($_[0]);
|
||||
}
|
||||
|
||||
sub print {
|
||||
@_ or croak 'usage: $io->print(ARGS)';
|
||||
my $this = shift;
|
||||
print $this @_;
|
||||
}
|
||||
|
||||
sub printf {
|
||||
@_ >= 2 or croak 'usage: $io->printf(FMT,[ARGS])';
|
||||
my $this = shift;
|
||||
printf $this @_;
|
||||
}
|
||||
|
||||
sub say {
|
||||
@_ or croak 'usage: $io->say(ARGS)';
|
||||
my $this = shift;
|
||||
local $\ = "\n";
|
||||
print $this @_;
|
||||
}
|
||||
|
||||
sub truncate {
|
||||
@_ == 2 or croak 'usage: $io->truncate(LEN)';
|
||||
truncate($_[0], $_[1]);
|
||||
}
|
||||
|
||||
sub read {
|
||||
@_ == 3 || @_ == 4 or croak 'usage: $io->read(BUF, LEN [, OFFSET])';
|
||||
read($_[0], $_[1], $_[2], $_[3] || 0);
|
||||
}
|
||||
|
||||
sub sysread {
|
||||
@_ == 3 || @_ == 4 or croak 'usage: $io->sysread(BUF, LEN [, OFFSET])';
|
||||
sysread($_[0], $_[1], $_[2], $_[3] || 0);
|
||||
}
|
||||
|
||||
sub write {
|
||||
@_ >= 2 && @_ <= 4 or croak 'usage: $io->write(BUF [, LEN [, OFFSET]])';
|
||||
local($\) = "";
|
||||
$_[2] = length($_[1]) unless defined $_[2];
|
||||
print { $_[0] } substr($_[1], $_[3] || 0, $_[2]);
|
||||
}
|
||||
|
||||
sub syswrite {
|
||||
@_ >= 2 && @_ <= 4 or croak 'usage: $io->syswrite(BUF [, LEN [, OFFSET]])';
|
||||
if (defined($_[2])) {
|
||||
syswrite($_[0], $_[1], $_[2], $_[3] || 0);
|
||||
} else {
|
||||
syswrite($_[0], $_[1]);
|
||||
}
|
||||
}
|
||||
|
||||
sub stat {
|
||||
@_ == 1 or croak 'usage: $io->stat()';
|
||||
stat($_[0]);
|
||||
}
|
||||
|
||||
################################################
|
||||
## State modification functions.
|
||||
##
|
||||
|
||||
sub autoflush {
|
||||
my $old = SelectSaver->new(qualify($_[0], caller));
|
||||
my $prev = $|;
|
||||
$| = @_ > 1 ? $_[1] : 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub output_field_separator {
|
||||
carp "output_field_separator is not supported on a per-handle basis"
|
||||
if ref($_[0]);
|
||||
my $prev = $,;
|
||||
$, = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub output_record_separator {
|
||||
carp "output_record_separator is not supported on a per-handle basis"
|
||||
if ref($_[0]);
|
||||
my $prev = $\;
|
||||
$\ = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub input_record_separator {
|
||||
carp "input_record_separator is not supported on a per-handle basis"
|
||||
if ref($_[0]);
|
||||
my $prev = $/;
|
||||
$/ = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub input_line_number {
|
||||
local $.;
|
||||
() = tell qualify($_[0], caller) if ref($_[0]);
|
||||
my $prev = $.;
|
||||
$. = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub format_page_number {
|
||||
my $old;
|
||||
$old = SelectSaver->new(qualify($_[0], caller)) if ref($_[0]);
|
||||
my $prev = $%;
|
||||
$% = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub format_lines_per_page {
|
||||
my $old;
|
||||
$old = SelectSaver->new(qualify($_[0], caller)) if ref($_[0]);
|
||||
my $prev = $=;
|
||||
$= = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub format_lines_left {
|
||||
my $old;
|
||||
$old = SelectSaver->new(qualify($_[0], caller)) if ref($_[0]);
|
||||
my $prev = $-;
|
||||
$- = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub format_name {
|
||||
my $old;
|
||||
$old = SelectSaver->new(qualify($_[0], caller)) if ref($_[0]);
|
||||
my $prev = $~;
|
||||
$~ = qualify($_[1], caller) if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub format_top_name {
|
||||
my $old;
|
||||
$old = SelectSaver->new(qualify($_[0], caller)) if ref($_[0]);
|
||||
my $prev = $^;
|
||||
$^ = qualify($_[1], caller) if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub format_line_break_characters {
|
||||
carp "format_line_break_characters is not supported on a per-handle basis"
|
||||
if ref($_[0]);
|
||||
my $prev = $:;
|
||||
$: = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub format_formfeed {
|
||||
carp "format_formfeed is not supported on a per-handle basis"
|
||||
if ref($_[0]);
|
||||
my $prev = $^L;
|
||||
$^L = $_[1] if @_ > 1;
|
||||
$prev;
|
||||
}
|
||||
|
||||
sub formline {
|
||||
my $io = shift;
|
||||
my $picture = shift;
|
||||
local($^A) = $^A;
|
||||
local($\) = "";
|
||||
formline($picture, @_);
|
||||
print $io $^A;
|
||||
}
|
||||
|
||||
sub format_write {
|
||||
@_ < 3 || croak 'usage: $io->write( [FORMAT_NAME] )';
|
||||
if (@_ == 2) {
|
||||
my ($io, $fmt) = @_;
|
||||
my $oldfmt = $io->format_name(qualify($fmt,caller));
|
||||
CORE::write($io);
|
||||
$io->format_name($oldfmt);
|
||||
} else {
|
||||
CORE::write($_[0]);
|
||||
}
|
||||
}
|
||||
|
||||
sub fcntl {
|
||||
@_ == 3 || croak 'usage: $io->fcntl( OP, VALUE );';
|
||||
my ($io, $op) = @_;
|
||||
return fcntl($io, $op, $_[2]);
|
||||
}
|
||||
|
||||
sub ioctl {
|
||||
@_ == 3 || croak 'usage: $io->ioctl( OP, VALUE );';
|
||||
my ($io, $op) = @_;
|
||||
return ioctl($io, $op, $_[2]);
|
||||
}
|
||||
|
||||
# this sub is for compatibility with older releases of IO that used
|
||||
# a sub called constant to determine if a constant existed -- GMB
|
||||
#
|
||||
# The SEEK_* and _IO?BF constants were the only constants at that time
|
||||
# any new code should just check defined(&CONSTANT_NAME)
|
||||
|
||||
sub constant {
|
||||
no strict 'refs';
|
||||
my $name = shift;
|
||||
(($name =~ /^(SEEK_(SET|CUR|END)|_IO[FLN]BF)$/) && defined &{$name})
|
||||
? &{$name}() : undef;
|
||||
}
|
||||
|
||||
|
||||
# so that flush.pl can be deprecated
|
||||
|
||||
sub printflush {
|
||||
my $io = shift;
|
||||
my $old;
|
||||
$old = SelectSaver->new(qualify($io, caller)) if ref($io);
|
||||
local $| = 1;
|
||||
if(ref($io)) {
|
||||
print $io @_;
|
||||
}
|
||||
else {
|
||||
print @_;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
256
database/perl/lib/IO/Pipe.pm
Normal file
256
database/perl/lib/IO/Pipe.pm
Normal file
@@ -0,0 +1,256 @@
|
||||
# IO::Pipe.pm
|
||||
#
|
||||
# Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Pipe;
|
||||
|
||||
use 5.008_001;
|
||||
|
||||
use IO::Handle;
|
||||
use strict;
|
||||
use Carp;
|
||||
use Symbol;
|
||||
|
||||
our $VERSION = "1.45";
|
||||
|
||||
sub new {
|
||||
my $type = shift;
|
||||
my $class = ref($type) || $type || "IO::Pipe";
|
||||
@_ == 0 || @_ == 2 or croak "usage: $class->([READFH, WRITEFH])";
|
||||
|
||||
my $me = bless gensym(), $class;
|
||||
|
||||
my($readfh,$writefh) = @_ ? @_ : $me->handles;
|
||||
|
||||
pipe($readfh, $writefh)
|
||||
or return undef;
|
||||
|
||||
@{*$me} = ($readfh, $writefh);
|
||||
|
||||
$me;
|
||||
}
|
||||
|
||||
sub handles {
|
||||
@_ == 1 or croak 'usage: $pipe->handles()';
|
||||
(IO::Pipe::End->new(), IO::Pipe::End->new());
|
||||
}
|
||||
|
||||
my $do_spawn = $^O eq 'os2' || $^O eq 'MSWin32';
|
||||
|
||||
sub _doit {
|
||||
my $me = shift;
|
||||
my $rw = shift;
|
||||
|
||||
my $pid = $do_spawn ? 0 : fork();
|
||||
|
||||
if($pid) { # Parent
|
||||
return $pid;
|
||||
}
|
||||
elsif(defined $pid) { # Child or spawn
|
||||
my $fh;
|
||||
my $io = $rw ? \*STDIN : \*STDOUT;
|
||||
my ($mode, $save) = $rw ? "r" : "w";
|
||||
if ($do_spawn) {
|
||||
require Fcntl;
|
||||
$save = IO::Handle->new_from_fd($io, $mode);
|
||||
my $handle = shift;
|
||||
# Close in child:
|
||||
unless ($^O eq 'MSWin32') {
|
||||
fcntl($handle, Fcntl::F_SETFD(), 1) or croak "fcntl: $!";
|
||||
}
|
||||
$fh = $rw ? ${*$me}[0] : ${*$me}[1];
|
||||
} else {
|
||||
shift;
|
||||
$fh = $rw ? $me->reader() : $me->writer(); # close the other end
|
||||
}
|
||||
bless $io, "IO::Handle";
|
||||
$io->fdopen($fh, $mode);
|
||||
$fh->close;
|
||||
|
||||
if ($do_spawn) {
|
||||
$pid = eval { system 1, @_ }; # 1 == P_NOWAIT
|
||||
my $err = $!;
|
||||
|
||||
$io->fdopen($save, $mode);
|
||||
$save->close or croak "Cannot close $!";
|
||||
croak "IO::Pipe: Cannot spawn-NOWAIT: $err" if not $pid or $pid < 0;
|
||||
return $pid;
|
||||
} else {
|
||||
exec @_ or
|
||||
croak "IO::Pipe: Cannot exec: $!";
|
||||
}
|
||||
}
|
||||
else {
|
||||
croak "IO::Pipe: Cannot fork: $!";
|
||||
}
|
||||
|
||||
# NOT Reached
|
||||
}
|
||||
|
||||
sub reader {
|
||||
@_ >= 1 or croak 'usage: $pipe->reader( [SUB_COMMAND_ARGS] )';
|
||||
my $me = shift;
|
||||
|
||||
return undef
|
||||
unless(ref($me) || ref($me = $me->new));
|
||||
|
||||
my $fh = ${*$me}[0];
|
||||
my $pid;
|
||||
$pid = $me->_doit(0, $fh, @_)
|
||||
if(@_);
|
||||
|
||||
close ${*$me}[1];
|
||||
bless $me, ref($fh);
|
||||
*$me = *$fh; # Alias self to handle
|
||||
$me->fdopen($fh->fileno,"r")
|
||||
unless defined($me->fileno);
|
||||
bless $fh; # Really wan't un-bless here
|
||||
${*$me}{'io_pipe_pid'} = $pid
|
||||
if defined $pid;
|
||||
|
||||
$me;
|
||||
}
|
||||
|
||||
sub writer {
|
||||
@_ >= 1 or croak 'usage: $pipe->writer( [SUB_COMMAND_ARGS] )';
|
||||
my $me = shift;
|
||||
|
||||
return undef
|
||||
unless(ref($me) || ref($me = $me->new));
|
||||
|
||||
my $fh = ${*$me}[1];
|
||||
my $pid;
|
||||
$pid = $me->_doit(1, $fh, @_)
|
||||
if(@_);
|
||||
|
||||
close ${*$me}[0];
|
||||
bless $me, ref($fh);
|
||||
*$me = *$fh; # Alias self to handle
|
||||
$me->fdopen($fh->fileno,"w")
|
||||
unless defined($me->fileno);
|
||||
bless $fh; # Really wan't un-bless here
|
||||
${*$me}{'io_pipe_pid'} = $pid
|
||||
if defined $pid;
|
||||
|
||||
$me;
|
||||
}
|
||||
|
||||
package IO::Pipe::End;
|
||||
|
||||
our(@ISA);
|
||||
|
||||
@ISA = qw(IO::Handle);
|
||||
|
||||
sub close {
|
||||
my $fh = shift;
|
||||
my $r = $fh->SUPER::close(@_);
|
||||
|
||||
waitpid(${*$fh}{'io_pipe_pid'},0)
|
||||
if(defined ${*$fh}{'io_pipe_pid'});
|
||||
|
||||
$r;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Pipe - supply object methods for pipes
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Pipe;
|
||||
|
||||
$pipe = IO::Pipe->new();
|
||||
|
||||
if($pid = fork()) { # Parent
|
||||
$pipe->reader();
|
||||
|
||||
while(<$pipe>) {
|
||||
...
|
||||
}
|
||||
|
||||
}
|
||||
elsif(defined $pid) { # Child
|
||||
$pipe->writer();
|
||||
|
||||
print $pipe ...
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
$pipe = IO::Pipe->new();
|
||||
|
||||
$pipe->reader(qw(ls -l));
|
||||
|
||||
while(<$pipe>) {
|
||||
...
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Pipe> provides an interface to creating pipes between
|
||||
processes.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ( [READER, WRITER] )
|
||||
|
||||
Creates an C<IO::Pipe>, which is a reference to a newly created symbol
|
||||
(see the C<Symbol> package). C<IO::Pipe::new> optionally takes two
|
||||
arguments, which should be objects blessed into C<IO::Handle>, or a
|
||||
subclass thereof. These two objects will be used for the system call
|
||||
to C<pipe>. If no arguments are given then method C<handles> is called
|
||||
on the new C<IO::Pipe> object.
|
||||
|
||||
These two handles are held in the array part of the GLOB until either
|
||||
C<reader> or C<writer> is called.
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item reader ([ARGS])
|
||||
|
||||
The object is re-blessed into a sub-class of C<IO::Handle>, and becomes a
|
||||
handle at the reading end of the pipe. If C<ARGS> are given then C<fork>
|
||||
is called and C<ARGS> are passed to exec.
|
||||
|
||||
=item writer ([ARGS])
|
||||
|
||||
The object is re-blessed into a sub-class of C<IO::Handle>, and becomes a
|
||||
handle at the writing end of the pipe. If C<ARGS> are given then C<fork>
|
||||
is called and C<ARGS> are passed to exec.
|
||||
|
||||
=item handles ()
|
||||
|
||||
This method is called during construction by C<IO::Pipe::new>
|
||||
on the newly created C<IO::Pipe> object. It returns an array of two objects
|
||||
blessed into C<IO::Pipe::End>, or a subclass thereof.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<IO::Handle>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Graham Barr. Currently maintained by the Perl Porters. Please report all
|
||||
bugs to <perlbug@perl.org>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
208
database/perl/lib/IO/Poll.pm
Normal file
208
database/perl/lib/IO/Poll.pm
Normal file
@@ -0,0 +1,208 @@
|
||||
|
||||
# IO::Poll.pm
|
||||
#
|
||||
# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Poll;
|
||||
|
||||
use strict;
|
||||
use IO::Handle;
|
||||
use Exporter ();
|
||||
|
||||
our @ISA = qw(Exporter);
|
||||
our $VERSION = "1.45";
|
||||
|
||||
our @EXPORT = qw( POLLIN
|
||||
POLLOUT
|
||||
POLLERR
|
||||
POLLHUP
|
||||
POLLNVAL
|
||||
);
|
||||
|
||||
our @EXPORT_OK = qw(
|
||||
POLLPRI
|
||||
POLLRDNORM
|
||||
POLLWRNORM
|
||||
POLLRDBAND
|
||||
POLLWRBAND
|
||||
POLLNORM
|
||||
);
|
||||
|
||||
# [0] maps fd's to requested masks
|
||||
# [1] maps fd's to returned masks
|
||||
# [2] maps fd's to handles
|
||||
sub new {
|
||||
my $class = shift;
|
||||
|
||||
my $self = bless [{},{},{}], $class;
|
||||
|
||||
$self;
|
||||
}
|
||||
|
||||
sub mask {
|
||||
my $self = shift;
|
||||
my $io = shift;
|
||||
my $fd = fileno($io);
|
||||
return unless defined $fd;
|
||||
if (@_) {
|
||||
my $mask = shift;
|
||||
if($mask) {
|
||||
$self->[0]{$fd}{$io} = $mask; # the error events are always returned
|
||||
$self->[1]{$fd} = 0; # output mask
|
||||
$self->[2]{$io} = $io; # remember handle
|
||||
} else {
|
||||
delete $self->[0]{$fd}{$io};
|
||||
unless(%{$self->[0]{$fd}}) {
|
||||
# We no longer have any handles for this FD
|
||||
delete $self->[1]{$fd};
|
||||
delete $self->[0]{$fd};
|
||||
}
|
||||
delete $self->[2]{$io};
|
||||
}
|
||||
}
|
||||
|
||||
return unless exists $self->[0]{$fd} and exists $self->[0]{$fd}{$io};
|
||||
return $self->[0]{$fd}{$io};
|
||||
}
|
||||
|
||||
|
||||
sub poll {
|
||||
my($self,$timeout) = @_;
|
||||
|
||||
$self->[1] = {};
|
||||
|
||||
my($fd,$mask,$iom);
|
||||
my @poll = ();
|
||||
|
||||
while(($fd,$iom) = each %{$self->[0]}) {
|
||||
$mask = 0;
|
||||
$mask |= $_ for values(%$iom);
|
||||
push(@poll,$fd => $mask);
|
||||
}
|
||||
|
||||
my $ret = _poll(defined($timeout) ? $timeout * 1000 : -1,@poll);
|
||||
|
||||
return $ret
|
||||
unless $ret > 0;
|
||||
|
||||
while(@poll) {
|
||||
my($fd,$got) = splice(@poll,0,2);
|
||||
$self->[1]{$fd} = $got if $got;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
sub events {
|
||||
my $self = shift;
|
||||
my $io = shift;
|
||||
my $fd = fileno($io);
|
||||
exists $self->[1]{$fd} and exists $self->[0]{$fd}{$io}
|
||||
? $self->[1]{$fd} & ($self->[0]{$fd}{$io}|POLLHUP|POLLERR|POLLNVAL)
|
||||
: 0;
|
||||
}
|
||||
|
||||
sub remove {
|
||||
my $self = shift;
|
||||
my $io = shift;
|
||||
$self->mask($io,0);
|
||||
}
|
||||
|
||||
sub handles {
|
||||
my $self = shift;
|
||||
return values %{$self->[2]} unless @_;
|
||||
|
||||
my $events = shift || 0;
|
||||
my($fd,$ev,$io,$mask);
|
||||
my @handles = ();
|
||||
|
||||
while(($fd,$ev) = each %{$self->[1]}) {
|
||||
while (($io,$mask) = each %{$self->[0]{$fd}}) {
|
||||
$mask |= POLLHUP|POLLERR|POLLNVAL; # must allow these
|
||||
push @handles,$self->[2]{$io} if ($ev & $mask) & $events;
|
||||
}
|
||||
}
|
||||
return @handles;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Poll - Object interface to system poll call
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Poll qw(POLLRDNORM POLLWRNORM POLLIN POLLHUP);
|
||||
|
||||
$poll = IO::Poll->new();
|
||||
|
||||
$poll->mask($input_handle => POLLIN);
|
||||
$poll->mask($output_handle => POLLOUT);
|
||||
|
||||
$poll->poll($timeout);
|
||||
|
||||
$ev = $poll->events($input);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Poll> is a simple interface to the system level poll routine.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item mask ( IO [, EVENT_MASK ] )
|
||||
|
||||
If EVENT_MASK is given, then, if EVENT_MASK is non-zero, IO is added to the
|
||||
list of file descriptors and the next call to poll will check for
|
||||
any event specified in EVENT_MASK. If EVENT_MASK is zero then IO will be
|
||||
removed from the list of file descriptors.
|
||||
|
||||
If EVENT_MASK is not given then the return value will be the current
|
||||
event mask value for IO.
|
||||
|
||||
=item poll ( [ TIMEOUT ] )
|
||||
|
||||
Call the system level poll routine. If TIMEOUT is not specified then the
|
||||
call will block. Returns the number of handles which had events
|
||||
happen, or -1 on error.
|
||||
|
||||
=item events ( IO )
|
||||
|
||||
Returns the event mask which represents the events that happened on IO
|
||||
during the last call to C<poll>.
|
||||
|
||||
=item remove ( IO )
|
||||
|
||||
Remove IO from the list of file descriptors for the next poll.
|
||||
|
||||
=item handles( [ EVENT_MASK ] )
|
||||
|
||||
Returns a list of handles. If EVENT_MASK is not given then a list of all
|
||||
handles known will be returned. If EVENT_MASK is given then a list
|
||||
of handles will be returned which had one of the events specified by
|
||||
EVENT_MASK happen during the last call ti C<poll>
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<poll(2)>, L<IO::Handle>, L<IO::Select>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Graham Barr. Currently maintained by the Perl Porters. Please report all
|
||||
bugs to <perlbug@perl.org>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
126
database/perl/lib/IO/Seekable.pm
Normal file
126
database/perl/lib/IO/Seekable.pm
Normal file
@@ -0,0 +1,126 @@
|
||||
#
|
||||
|
||||
package IO::Seekable;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Seekable - supply seek based methods for I/O objects
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Seekable;
|
||||
package IO::Something;
|
||||
@ISA = qw(IO::Seekable);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Seekable> does not have a constructor of its own as it is intended to
|
||||
be inherited by other C<IO::Handle> based objects. It provides methods
|
||||
which allow seeking of the file descriptors.
|
||||
|
||||
=over 4
|
||||
|
||||
=item $io->getpos
|
||||
|
||||
Returns an opaque value that represents the current position of the
|
||||
IO::File, or C<undef> if this is not possible (eg an unseekable stream such
|
||||
as a terminal, pipe or socket). If the fgetpos() function is available in
|
||||
your C library it is used to implements getpos, else perl emulates getpos
|
||||
using C's ftell() function.
|
||||
|
||||
=item $io->setpos
|
||||
|
||||
Uses the value of a previous getpos call to return to a previously visited
|
||||
position. Returns "0 but true" on success, C<undef> on failure.
|
||||
|
||||
=back
|
||||
|
||||
See L<perlfunc> for complete descriptions of each of the following
|
||||
supported C<IO::Seekable> methods, which are just front ends for the
|
||||
corresponding built-in functions:
|
||||
|
||||
=over 4
|
||||
|
||||
=item $io->seek ( POS, WHENCE )
|
||||
|
||||
Seek the IO::File to position POS, relative to WHENCE:
|
||||
|
||||
=over 8
|
||||
|
||||
=item WHENCE=0 (SEEK_SET)
|
||||
|
||||
POS is absolute position. (Seek relative to the start of the file)
|
||||
|
||||
=item WHENCE=1 (SEEK_CUR)
|
||||
|
||||
POS is an offset from the current position. (Seek relative to current)
|
||||
|
||||
=item WHENCE=2 (SEEK_END)
|
||||
|
||||
POS is an offset from the end of the file. (Seek relative to end)
|
||||
|
||||
=back
|
||||
|
||||
The SEEK_* constants can be imported from the C<Fcntl> module if you
|
||||
don't wish to use the numbers C<0> C<1> or C<2> in your code.
|
||||
|
||||
Returns C<1> upon success, C<0> otherwise.
|
||||
|
||||
=item $io->sysseek( POS, WHENCE )
|
||||
|
||||
Similar to $io->seek, but sets the IO::File's position using the system
|
||||
call lseek(2) directly, so will confuse most perl IO operators except
|
||||
sysread and syswrite (see L<perlfunc> for full details)
|
||||
|
||||
Returns the new position, or C<undef> on failure. A position
|
||||
of zero is returned as the string C<"0 but true">
|
||||
|
||||
=item $io->tell
|
||||
|
||||
Returns the IO::File's current position, or -1 on error.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<perlfunc>,
|
||||
L<perlop/"I/O Operators">,
|
||||
L<IO::Handle>
|
||||
L<IO::File>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
Derived from FileHandle.pm by Graham Barr E<lt>gbarr@pobox.comE<gt>
|
||||
|
||||
=cut
|
||||
|
||||
use 5.008_001;
|
||||
use Carp;
|
||||
use strict;
|
||||
use IO::Handle ();
|
||||
# XXX we can't get these from IO::Handle or we'll get prototype
|
||||
# mismatch warnings on C<use POSIX; use IO::File;> :-(
|
||||
use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END);
|
||||
require Exporter;
|
||||
|
||||
our @EXPORT = qw(SEEK_SET SEEK_CUR SEEK_END);
|
||||
our @ISA = qw(Exporter);
|
||||
|
||||
our $VERSION = "1.45";
|
||||
|
||||
sub seek {
|
||||
@_ == 3 or croak 'usage: $io->seek(POS, WHENCE)';
|
||||
seek($_[0], $_[1], $_[2]);
|
||||
}
|
||||
|
||||
sub sysseek {
|
||||
@_ == 3 or croak 'usage: $io->sysseek(POS, WHENCE)';
|
||||
sysseek($_[0], $_[1], $_[2]);
|
||||
}
|
||||
|
||||
sub tell {
|
||||
@_ == 1 or croak 'usage: $io->tell()';
|
||||
tell($_[0]);
|
||||
}
|
||||
|
||||
1;
|
||||
417
database/perl/lib/IO/Select.pm
Normal file
417
database/perl/lib/IO/Select.pm
Normal file
@@ -0,0 +1,417 @@
|
||||
# IO::Select.pm
|
||||
#
|
||||
# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Select;
|
||||
|
||||
use strict;
|
||||
use warnings::register;
|
||||
require Exporter;
|
||||
|
||||
our $VERSION = "1.45";
|
||||
|
||||
our @ISA = qw(Exporter); # This is only so we can do version checking
|
||||
|
||||
sub VEC_BITS () {0}
|
||||
sub FD_COUNT () {1}
|
||||
sub FIRST_FD () {2}
|
||||
|
||||
sub new
|
||||
{
|
||||
my $self = shift;
|
||||
my $type = ref($self) || $self;
|
||||
|
||||
my $vec = bless [undef,0], $type;
|
||||
|
||||
$vec->add(@_)
|
||||
if @_;
|
||||
|
||||
$vec;
|
||||
}
|
||||
|
||||
sub add
|
||||
{
|
||||
shift->_update('add', @_);
|
||||
}
|
||||
|
||||
|
||||
sub remove
|
||||
{
|
||||
shift->_update('remove', @_);
|
||||
}
|
||||
|
||||
|
||||
sub exists
|
||||
{
|
||||
my $vec = shift;
|
||||
my $fno = $vec->_fileno(shift);
|
||||
return undef unless defined $fno;
|
||||
$vec->[$fno + FIRST_FD];
|
||||
}
|
||||
|
||||
|
||||
sub _fileno
|
||||
{
|
||||
my($self, $f) = @_;
|
||||
return unless defined $f;
|
||||
$f = $f->[0] if ref($f) eq 'ARRAY';
|
||||
if($f =~ /^[0-9]+$/) { # plain file number
|
||||
return $f;
|
||||
}
|
||||
elsif(defined(my $fd = fileno($f))) {
|
||||
return $fd;
|
||||
}
|
||||
else {
|
||||
# Neither a plain file number nor an opened filehandle; but maybe it was
|
||||
# previously registered and has since been closed. ->remove still wants to
|
||||
# know what fileno it had
|
||||
foreach my $i ( FIRST_FD .. $#$self ) {
|
||||
return $i - FIRST_FD if $self->[$i] == $f;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
sub _update
|
||||
{
|
||||
my $vec = shift;
|
||||
my $add = shift eq 'add';
|
||||
|
||||
my $bits = $vec->[VEC_BITS];
|
||||
$bits = '' unless defined $bits;
|
||||
|
||||
my $count = 0;
|
||||
my $f;
|
||||
foreach $f (@_)
|
||||
{
|
||||
my $fn = $vec->_fileno($f);
|
||||
if ($add) {
|
||||
next unless defined $fn;
|
||||
my $i = $fn + FIRST_FD;
|
||||
if (defined $vec->[$i]) {
|
||||
$vec->[$i] = $f; # if array rest might be different, so we update
|
||||
next;
|
||||
}
|
||||
$vec->[FD_COUNT]++;
|
||||
vec($bits, $fn, 1) = 1;
|
||||
$vec->[$i] = $f;
|
||||
} else { # remove
|
||||
if ( ! defined $fn ) { # remove if fileno undef'd
|
||||
$fn = 0;
|
||||
for my $fe (@{$vec}[FIRST_FD .. $#$vec]) {
|
||||
if (defined($fe) && $fe == $f) {
|
||||
$vec->[FD_COUNT]--;
|
||||
$fe = undef;
|
||||
vec($bits, $fn, 1) = 0;
|
||||
last;
|
||||
}
|
||||
++$fn;
|
||||
}
|
||||
}
|
||||
else {
|
||||
my $i = $fn + FIRST_FD;
|
||||
next unless defined $vec->[$i];
|
||||
$vec->[FD_COUNT]--;
|
||||
vec($bits, $fn, 1) = 0;
|
||||
$vec->[$i] = undef;
|
||||
}
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
$vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef;
|
||||
$count;
|
||||
}
|
||||
|
||||
sub can_read
|
||||
{
|
||||
my $vec = shift;
|
||||
my $timeout = shift;
|
||||
my $r = $vec->[VEC_BITS];
|
||||
|
||||
defined($r) && (select($r,undef,undef,$timeout) > 0)
|
||||
? handles($vec, $r)
|
||||
: ();
|
||||
}
|
||||
|
||||
sub can_write
|
||||
{
|
||||
my $vec = shift;
|
||||
my $timeout = shift;
|
||||
my $w = $vec->[VEC_BITS];
|
||||
|
||||
defined($w) && (select(undef,$w,undef,$timeout) > 0)
|
||||
? handles($vec, $w)
|
||||
: ();
|
||||
}
|
||||
|
||||
sub has_exception
|
||||
{
|
||||
my $vec = shift;
|
||||
my $timeout = shift;
|
||||
my $e = $vec->[VEC_BITS];
|
||||
|
||||
defined($e) && (select(undef,undef,$e,$timeout) > 0)
|
||||
? handles($vec, $e)
|
||||
: ();
|
||||
}
|
||||
|
||||
sub has_error
|
||||
{
|
||||
warnings::warn("Call to deprecated method 'has_error', use 'has_exception'")
|
||||
if warnings::enabled();
|
||||
goto &has_exception;
|
||||
}
|
||||
|
||||
sub count
|
||||
{
|
||||
my $vec = shift;
|
||||
$vec->[FD_COUNT];
|
||||
}
|
||||
|
||||
sub bits
|
||||
{
|
||||
my $vec = shift;
|
||||
$vec->[VEC_BITS];
|
||||
}
|
||||
|
||||
sub as_string # for debugging
|
||||
{
|
||||
my $vec = shift;
|
||||
my $str = ref($vec) . ": ";
|
||||
my $bits = $vec->bits;
|
||||
my $count = $vec->count;
|
||||
$str .= defined($bits) ? unpack("b*", $bits) : "undef";
|
||||
$str .= " $count";
|
||||
my @handles = @$vec;
|
||||
splice(@handles, 0, FIRST_FD);
|
||||
for (@handles) {
|
||||
$str .= " " . (defined($_) ? "$_" : "-");
|
||||
}
|
||||
$str;
|
||||
}
|
||||
|
||||
sub _max
|
||||
{
|
||||
my($a,$b,$c) = @_;
|
||||
$a > $b
|
||||
? $a > $c
|
||||
? $a
|
||||
: $c
|
||||
: $b > $c
|
||||
? $b
|
||||
: $c;
|
||||
}
|
||||
|
||||
sub select
|
||||
{
|
||||
shift
|
||||
if defined $_[0] && !ref($_[0]);
|
||||
|
||||
my($r,$w,$e,$t) = @_;
|
||||
my @result = ();
|
||||
|
||||
my $rb = defined $r ? $r->[VEC_BITS] : undef;
|
||||
my $wb = defined $w ? $w->[VEC_BITS] : undef;
|
||||
my $eb = defined $e ? $e->[VEC_BITS] : undef;
|
||||
|
||||
if(select($rb,$wb,$eb,$t) > 0)
|
||||
{
|
||||
my @r = ();
|
||||
my @w = ();
|
||||
my @e = ();
|
||||
my $i = _max(defined $r ? scalar(@$r)-1 : 0,
|
||||
defined $w ? scalar(@$w)-1 : 0,
|
||||
defined $e ? scalar(@$e)-1 : 0);
|
||||
|
||||
for( ; $i >= FIRST_FD ; $i--)
|
||||
{
|
||||
my $j = $i - FIRST_FD;
|
||||
push(@r, $r->[$i])
|
||||
if defined $rb && defined $r->[$i] && vec($rb, $j, 1);
|
||||
push(@w, $w->[$i])
|
||||
if defined $wb && defined $w->[$i] && vec($wb, $j, 1);
|
||||
push(@e, $e->[$i])
|
||||
if defined $eb && defined $e->[$i] && vec($eb, $j, 1);
|
||||
}
|
||||
|
||||
@result = (\@r, \@w, \@e);
|
||||
}
|
||||
@result;
|
||||
}
|
||||
|
||||
|
||||
sub handles
|
||||
{
|
||||
my $vec = shift;
|
||||
my $bits = shift;
|
||||
my @h = ();
|
||||
my $i;
|
||||
my $max = scalar(@$vec) - 1;
|
||||
|
||||
for ($i = FIRST_FD; $i <= $max; $i++)
|
||||
{
|
||||
next unless defined $vec->[$i];
|
||||
push(@h, $vec->[$i])
|
||||
if !defined($bits) || vec($bits, $i - FIRST_FD, 1);
|
||||
}
|
||||
|
||||
@h;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Select - OO interface to the select system call
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Select;
|
||||
|
||||
$s = IO::Select->new();
|
||||
|
||||
$s->add(\*STDIN);
|
||||
$s->add($some_handle);
|
||||
|
||||
@ready = $s->can_read($timeout);
|
||||
|
||||
@ready = IO::Select->new(@handles)->can_read(0);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The C<IO::Select> package implements an object approach to the system C<select>
|
||||
function call. It allows the user to see what IO handles, see L<IO::Handle>,
|
||||
are ready for reading, writing or have an exception pending.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ( [ HANDLES ] )
|
||||
|
||||
The constructor creates a new object and optionally initialises it with a set
|
||||
of handles.
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item add ( HANDLES )
|
||||
|
||||
Add the list of handles to the C<IO::Select> object. It is these values that
|
||||
will be returned when an event occurs. C<IO::Select> keeps these values in a
|
||||
cache which is indexed by the C<fileno> of the handle, so if more than one
|
||||
handle with the same C<fileno> is specified then only the last one is cached.
|
||||
|
||||
Each handle can be an C<IO::Handle> object, an integer or an array
|
||||
reference where the first element is an C<IO::Handle> or an integer.
|
||||
|
||||
=item remove ( HANDLES )
|
||||
|
||||
Remove all the given handles from the object. This method also works
|
||||
by the C<fileno> of the handles. So the exact handles that were added
|
||||
need not be passed, just handles that have an equivalent C<fileno>
|
||||
|
||||
=item exists ( HANDLE )
|
||||
|
||||
Returns a true value (actually the handle itself) if it is present.
|
||||
Returns undef otherwise.
|
||||
|
||||
=item handles
|
||||
|
||||
Return an array of all registered handles.
|
||||
|
||||
=item can_read ( [ TIMEOUT ] )
|
||||
|
||||
Return an array of handles that are ready for reading. C<TIMEOUT> is the
|
||||
maximum amount of time to wait before returning an empty list (with C<$!>
|
||||
unchanged), in seconds, possibly fractional. If C<TIMEOUT> is not given
|
||||
and any handles are registered then the call will block indefinitely.
|
||||
Upon error, an empty list is returned, with C<$!> set to indicate the
|
||||
error. To distinguish between timeout and error, set C<$!> to zero
|
||||
before calling this method, and check it after an empty list is returned.
|
||||
|
||||
=item can_write ( [ TIMEOUT ] )
|
||||
|
||||
Same as C<can_read> except check for handles that can be written to.
|
||||
|
||||
=item has_exception ( [ TIMEOUT ] )
|
||||
|
||||
Same as C<can_read> except check for handles that have an exception
|
||||
condition, for example pending out-of-band data.
|
||||
|
||||
=item count ()
|
||||
|
||||
Returns the number of handles that the object will check for when
|
||||
one of the C<can_> methods is called or the object is passed to
|
||||
the C<select> static method.
|
||||
|
||||
=item bits()
|
||||
|
||||
Return the bit string suitable as argument to the core select() call.
|
||||
|
||||
=item select ( READ, WRITE, EXCEPTION [, TIMEOUT ] )
|
||||
|
||||
C<select> is a static method, that is you call it with the package name
|
||||
like C<new>. C<READ>, C<WRITE> and C<EXCEPTION> are either C<undef> or
|
||||
C<IO::Select> objects. C<TIMEOUT> is optional and has the same effect as
|
||||
for the core select call.
|
||||
|
||||
If at least one handle is ready for the specified kind of operation,
|
||||
the result will be an array of 3 elements, each a reference to an array
|
||||
which will hold the handles that are ready for reading, writing and
|
||||
have exceptions respectively. Upon timeout, an empty list is returned,
|
||||
with C<$!> unchanged. Upon error, an empty list is returned, with C<$!>
|
||||
set to indicate the error. To distinguish between timeout and error,
|
||||
set C<$!> to zero before calling this method, and check it after an
|
||||
empty list is returned.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLE
|
||||
|
||||
Here is a short example which shows how C<IO::Select> could be used
|
||||
to write a server which communicates with several sockets while also
|
||||
listening for more connections on a listen socket
|
||||
|
||||
use IO::Select;
|
||||
use IO::Socket;
|
||||
|
||||
$lsn = IO::Socket::INET->new(Listen => 1, LocalPort => 8080);
|
||||
$sel = IO::Select->new( $lsn );
|
||||
|
||||
while(@ready = $sel->can_read) {
|
||||
foreach $fh (@ready) {
|
||||
if($fh == $lsn) {
|
||||
# Create a new socket
|
||||
$new = $lsn->accept;
|
||||
$sel->add($new);
|
||||
}
|
||||
else {
|
||||
# Process socket
|
||||
|
||||
# Maybe we have finished with the socket
|
||||
$sel->remove($fh);
|
||||
$fh->close;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Graham Barr. Currently maintained by the Perl Porters. Please report all
|
||||
bugs to <perlbug@perl.org>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
|
||||
933
database/perl/lib/IO/Socket.pm
Normal file
933
database/perl/lib/IO/Socket.pm
Normal file
@@ -0,0 +1,933 @@
|
||||
|
||||
# IO::Socket.pm
|
||||
#
|
||||
# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Socket;
|
||||
|
||||
use 5.008_001;
|
||||
|
||||
use IO::Handle;
|
||||
use Socket 1.3;
|
||||
use Carp;
|
||||
use strict;
|
||||
use Exporter;
|
||||
use Errno;
|
||||
|
||||
# legacy
|
||||
|
||||
require IO::Socket::INET;
|
||||
require IO::Socket::UNIX if ($^O ne 'epoc' && $^O ne 'symbian');
|
||||
|
||||
our @ISA = qw(IO::Handle);
|
||||
|
||||
our $VERSION = "1.45";
|
||||
|
||||
our @EXPORT_OK = qw(sockatmark);
|
||||
|
||||
our $errstr;
|
||||
|
||||
sub import {
|
||||
my $pkg = shift;
|
||||
if (@_ && $_[0] eq 'sockatmark') { # not very extensible but for now, fast
|
||||
Exporter::export_to_level('IO::Socket', 1, $pkg, 'sockatmark');
|
||||
} else {
|
||||
my $callpkg = caller;
|
||||
Exporter::export 'Socket', $callpkg, @_;
|
||||
}
|
||||
}
|
||||
|
||||
sub new {
|
||||
my($class,%arg) = @_;
|
||||
my $sock = $class->SUPER::new();
|
||||
|
||||
$sock->autoflush(1);
|
||||
|
||||
${*$sock}{'io_socket_timeout'} = delete $arg{Timeout};
|
||||
|
||||
return scalar(%arg) ? $sock->configure(\%arg)
|
||||
: $sock;
|
||||
}
|
||||
|
||||
my @domain2pkg;
|
||||
|
||||
sub register_domain {
|
||||
my($p,$d) = @_;
|
||||
$domain2pkg[$d] = $p;
|
||||
}
|
||||
|
||||
sub configure {
|
||||
my($sock,$arg) = @_;
|
||||
my $domain = delete $arg->{Domain};
|
||||
|
||||
croak 'IO::Socket: Cannot configure a generic socket'
|
||||
unless defined $domain;
|
||||
|
||||
croak "IO::Socket: Unsupported socket domain"
|
||||
unless defined $domain2pkg[$domain];
|
||||
|
||||
croak "IO::Socket: Cannot configure socket in domain '$domain'"
|
||||
unless ref($sock) eq "IO::Socket";
|
||||
|
||||
bless($sock, $domain2pkg[$domain]);
|
||||
$sock->configure($arg);
|
||||
}
|
||||
|
||||
sub socket {
|
||||
@_ == 4 or croak 'usage: $sock->socket(DOMAIN, TYPE, PROTOCOL)';
|
||||
my($sock,$domain,$type,$protocol) = @_;
|
||||
|
||||
socket($sock,$domain,$type,$protocol) or
|
||||
return undef;
|
||||
|
||||
${*$sock}{'io_socket_domain'} = $domain;
|
||||
${*$sock}{'io_socket_type'} = $type;
|
||||
|
||||
# "A value of 0 for protocol will let the system select an
|
||||
# appropriate protocol"
|
||||
# so we need to look up what the system selected,
|
||||
# not cache PF_UNSPEC.
|
||||
${*$sock}{'io_socket_proto'} = $protocol if $protocol;
|
||||
|
||||
$sock;
|
||||
}
|
||||
|
||||
sub socketpair {
|
||||
@_ == 4 || croak 'usage: IO::Socket->socketpair(DOMAIN, TYPE, PROTOCOL)';
|
||||
my($class,$domain,$type,$protocol) = @_;
|
||||
my $sock1 = $class->new();
|
||||
my $sock2 = $class->new();
|
||||
|
||||
socketpair($sock1,$sock2,$domain,$type,$protocol) or
|
||||
return ();
|
||||
|
||||
${*$sock1}{'io_socket_type'} = ${*$sock2}{'io_socket_type'} = $type;
|
||||
${*$sock1}{'io_socket_proto'} = ${*$sock2}{'io_socket_proto'} = $protocol;
|
||||
|
||||
($sock1,$sock2);
|
||||
}
|
||||
|
||||
sub connect {
|
||||
@_ == 2 or croak 'usage: $sock->connect(NAME)';
|
||||
my $sock = shift;
|
||||
my $addr = shift;
|
||||
my $timeout = ${*$sock}{'io_socket_timeout'};
|
||||
my $err;
|
||||
my $blocking;
|
||||
|
||||
$blocking = $sock->blocking(0) if $timeout;
|
||||
if (!connect($sock, $addr)) {
|
||||
if (defined $timeout && ($!{EINPROGRESS} || $!{EWOULDBLOCK})) {
|
||||
require IO::Select;
|
||||
|
||||
my $sel = IO::Select->new( $sock );
|
||||
|
||||
undef $!;
|
||||
my($r,$w,$e) = IO::Select::select(undef,$sel,$sel,$timeout);
|
||||
if(@$e[0]) {
|
||||
# Windows return from select after the timeout in case of
|
||||
# WSAECONNREFUSED(10061) if exception set is not used.
|
||||
# This behavior is different from Linux.
|
||||
# Using the exception
|
||||
# set we now emulate the behavior in Linux
|
||||
# - Karthik Rajagopalan
|
||||
$err = $sock->getsockopt(SOL_SOCKET,SO_ERROR);
|
||||
$errstr = $@ = "connect: $err";
|
||||
}
|
||||
elsif(!@$w[0]) {
|
||||
$err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
|
||||
$errstr = $@ = "connect: timeout";
|
||||
}
|
||||
elsif (!connect($sock,$addr) &&
|
||||
not ($!{EISCONN} || ($^O eq 'MSWin32' &&
|
||||
($! == (($] < 5.019004) ? 10022 : Errno::EINVAL))))
|
||||
) {
|
||||
# Some systems refuse to re-connect() to
|
||||
# an already open socket and set errno to EISCONN.
|
||||
# Windows sets errno to WSAEINVAL (10022) (pre-5.19.4) or
|
||||
# EINVAL (22) (5.19.4 onwards).
|
||||
$err = $!;
|
||||
$errstr = $@ = "connect: $!";
|
||||
}
|
||||
}
|
||||
elsif ($blocking || !($!{EINPROGRESS} || $!{EWOULDBLOCK})) {
|
||||
$err = $!;
|
||||
$errstr = $@ = "connect: $!";
|
||||
}
|
||||
}
|
||||
|
||||
$sock->blocking(1) if $blocking;
|
||||
|
||||
$! = $err if $err;
|
||||
|
||||
$err ? undef : $sock;
|
||||
}
|
||||
|
||||
# Enable/disable blocking IO on sockets.
|
||||
# Without args return the current status of blocking,
|
||||
# with args change the mode as appropriate, returning the
|
||||
# old setting, or in case of error during the mode change
|
||||
# undef.
|
||||
|
||||
sub blocking {
|
||||
my $sock = shift;
|
||||
|
||||
return $sock->SUPER::blocking(@_)
|
||||
if $^O ne 'MSWin32' && $^O ne 'VMS';
|
||||
|
||||
# Windows handles blocking differently
|
||||
#
|
||||
# http://groups.google.co.uk/group/perl.perl5.porters/browse_thread/thread/b4e2b1d88280ddff/630b667a66e3509f?#630b667a66e3509f
|
||||
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/ioctlsocket_2.asp
|
||||
#
|
||||
# 0x8004667e is FIONBIO
|
||||
#
|
||||
# which is used to set blocking behaviour.
|
||||
|
||||
# NOTE:
|
||||
# This is a little confusing, the perl keyword for this is
|
||||
# 'blocking' but the OS level behaviour is 'non-blocking', probably
|
||||
# because sockets are blocking by default.
|
||||
# Therefore internally we have to reverse the semantics.
|
||||
|
||||
my $orig= !${*$sock}{io_sock_nonblocking};
|
||||
|
||||
return $orig unless @_;
|
||||
|
||||
my $block = shift;
|
||||
|
||||
if ( !$block != !$orig ) {
|
||||
${*$sock}{io_sock_nonblocking} = $block ? 0 : 1;
|
||||
ioctl($sock, 0x8004667e, pack("L!",${*$sock}{io_sock_nonblocking}))
|
||||
or return undef;
|
||||
}
|
||||
|
||||
return $orig;
|
||||
}
|
||||
|
||||
|
||||
sub close {
|
||||
@_ == 1 or croak 'usage: $sock->close()';
|
||||
my $sock = shift;
|
||||
${*$sock}{'io_socket_peername'} = undef;
|
||||
$sock->SUPER::close();
|
||||
}
|
||||
|
||||
sub bind {
|
||||
@_ == 2 or croak 'usage: $sock->bind(NAME)';
|
||||
my $sock = shift;
|
||||
my $addr = shift;
|
||||
|
||||
return bind($sock, $addr) ? $sock
|
||||
: undef;
|
||||
}
|
||||
|
||||
sub listen {
|
||||
@_ >= 1 && @_ <= 2 or croak 'usage: $sock->listen([QUEUE])';
|
||||
my($sock,$queue) = @_;
|
||||
$queue = 5
|
||||
unless $queue && $queue > 0;
|
||||
|
||||
return listen($sock, $queue) ? $sock
|
||||
: undef;
|
||||
}
|
||||
|
||||
sub accept {
|
||||
@_ == 1 || @_ == 2 or croak 'usage $sock->accept([PKG])';
|
||||
my $sock = shift;
|
||||
my $pkg = shift || $sock;
|
||||
my $timeout = ${*$sock}{'io_socket_timeout'};
|
||||
my $new = $pkg->new(Timeout => $timeout);
|
||||
my $peer = undef;
|
||||
|
||||
if(defined $timeout) {
|
||||
require IO::Select;
|
||||
|
||||
my $sel = IO::Select->new( $sock );
|
||||
|
||||
unless ($sel->can_read($timeout)) {
|
||||
$errstr = $@ = 'accept: timeout';
|
||||
$! = (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$peer = accept($new,$sock)
|
||||
or return;
|
||||
|
||||
${*$new}{$_} = ${*$sock}{$_} for qw( io_socket_domain io_socket_type io_socket_proto );
|
||||
|
||||
return wantarray ? ($new, $peer)
|
||||
: $new;
|
||||
}
|
||||
|
||||
sub sockname {
|
||||
@_ == 1 or croak 'usage: $sock->sockname()';
|
||||
getsockname($_[0]);
|
||||
}
|
||||
|
||||
sub peername {
|
||||
@_ == 1 or croak 'usage: $sock->peername()';
|
||||
my($sock) = @_;
|
||||
${*$sock}{'io_socket_peername'} ||= getpeername($sock);
|
||||
}
|
||||
|
||||
sub connected {
|
||||
@_ == 1 or croak 'usage: $sock->connected()';
|
||||
my($sock) = @_;
|
||||
getpeername($sock);
|
||||
}
|
||||
|
||||
sub send {
|
||||
@_ >= 2 && @_ <= 4 or croak 'usage: $sock->send(BUF, [FLAGS, [TO]])';
|
||||
my $sock = $_[0];
|
||||
my $flags = $_[2] || 0;
|
||||
my $peer;
|
||||
|
||||
if ($_[3]) {
|
||||
# the caller explicitly requested a TO, so use it
|
||||
# this is non-portable for "connected" UDP sockets
|
||||
$peer = $_[3];
|
||||
}
|
||||
elsif (!defined getpeername($sock)) {
|
||||
# we're not connected, so we require a peer from somewhere
|
||||
$peer = $sock->peername;
|
||||
|
||||
croak 'send: Cannot determine peer address'
|
||||
unless(defined $peer);
|
||||
}
|
||||
|
||||
my $r = $peer
|
||||
? send($sock, $_[1], $flags, $peer)
|
||||
: send($sock, $_[1], $flags);
|
||||
|
||||
# remember who we send to, if it was successful
|
||||
${*$sock}{'io_socket_peername'} = $peer
|
||||
if(@_ == 4 && defined $r);
|
||||
|
||||
$r;
|
||||
}
|
||||
|
||||
sub recv {
|
||||
@_ == 3 || @_ == 4 or croak 'usage: $sock->recv(BUF, LEN [, FLAGS])';
|
||||
my $sock = $_[0];
|
||||
my $len = $_[2];
|
||||
my $flags = $_[3] || 0;
|
||||
|
||||
# remember who we recv'd from
|
||||
${*$sock}{'io_socket_peername'} = recv($sock, $_[1]='', $len, $flags);
|
||||
}
|
||||
|
||||
sub shutdown {
|
||||
@_ == 2 or croak 'usage: $sock->shutdown(HOW)';
|
||||
my($sock, $how) = @_;
|
||||
${*$sock}{'io_socket_peername'} = undef;
|
||||
shutdown($sock, $how);
|
||||
}
|
||||
|
||||
sub setsockopt {
|
||||
@_ == 4 or croak '$sock->setsockopt(LEVEL, OPTNAME, OPTVAL)';
|
||||
setsockopt($_[0],$_[1],$_[2],$_[3]);
|
||||
}
|
||||
|
||||
my $intsize = length(pack("i",0));
|
||||
|
||||
sub getsockopt {
|
||||
@_ == 3 or croak '$sock->getsockopt(LEVEL, OPTNAME)';
|
||||
my $r = getsockopt($_[0],$_[1],$_[2]);
|
||||
# Just a guess
|
||||
$r = unpack("i", $r)
|
||||
if(defined $r && length($r) == $intsize);
|
||||
$r;
|
||||
}
|
||||
|
||||
sub sockopt {
|
||||
my $sock = shift;
|
||||
@_ == 1 ? $sock->getsockopt(SOL_SOCKET,@_)
|
||||
: $sock->setsockopt(SOL_SOCKET,@_);
|
||||
}
|
||||
|
||||
sub atmark {
|
||||
@_ == 1 or croak 'usage: $sock->atmark()';
|
||||
my($sock) = @_;
|
||||
sockatmark($sock);
|
||||
}
|
||||
|
||||
sub timeout {
|
||||
@_ == 1 || @_ == 2 or croak 'usage: $sock->timeout([VALUE])';
|
||||
my($sock,$val) = @_;
|
||||
my $r = ${*$sock}{'io_socket_timeout'};
|
||||
|
||||
${*$sock}{'io_socket_timeout'} = defined $val ? 0 + $val : $val
|
||||
if(@_ == 2);
|
||||
|
||||
$r;
|
||||
}
|
||||
|
||||
sub sockdomain {
|
||||
@_ == 1 or croak 'usage: $sock->sockdomain()';
|
||||
my $sock = shift;
|
||||
if (!defined(${*$sock}{'io_socket_domain'})) {
|
||||
my $addr = $sock->sockname();
|
||||
${*$sock}{'io_socket_domain'} = sockaddr_family($addr)
|
||||
if (defined($addr));
|
||||
}
|
||||
${*$sock}{'io_socket_domain'};
|
||||
}
|
||||
|
||||
sub socktype {
|
||||
@_ == 1 or croak 'usage: $sock->socktype()';
|
||||
my $sock = shift;
|
||||
${*$sock}{'io_socket_type'} = $sock->sockopt(Socket::SO_TYPE)
|
||||
if (!defined(${*$sock}{'io_socket_type'}) && defined(eval{Socket::SO_TYPE}));
|
||||
${*$sock}{'io_socket_type'}
|
||||
}
|
||||
|
||||
sub protocol {
|
||||
@_ == 1 or croak 'usage: $sock->protocol()';
|
||||
my($sock) = @_;
|
||||
${*$sock}{'io_socket_proto'} = $sock->sockopt(Socket::SO_PROTOCOL)
|
||||
if (!defined(${*$sock}{'io_socket_proto'}) && defined(eval{Socket::SO_PROTOCOL}));
|
||||
${*$sock}{'io_socket_proto'};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Socket - Object interface to socket communications
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use IO::Socket qw(AF_INET AF_UNIX);
|
||||
|
||||
# create a new AF_INET socket
|
||||
my $sock = IO::Socket->new(Domain => AF_INET);
|
||||
# which is the same as
|
||||
$sock = IO::Socket::INET->new();
|
||||
|
||||
# create a new AF_UNIX socket
|
||||
$sock = IO::Socket->new(Domain => AF_UNIX);
|
||||
# which is the same as
|
||||
$sock = IO::Socket::UNIX->new();
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Socket> provides an object-oriented, L<IO::Handle>-based interface to
|
||||
creating and using sockets via L<Socket>, which provides a near one-to-one
|
||||
interface to the C socket library.
|
||||
|
||||
C<IO::Socket> is a base class that really only defines methods for those
|
||||
operations which are common to all types of sockets. Operations which are
|
||||
specific to a particular socket domain have methods defined in subclasses of
|
||||
C<IO::Socket>. See L<IO::Socket::INET>, L<IO::Socket::UNIX>, and
|
||||
L<IO::Socket::IP> for examples of such a subclass.
|
||||
|
||||
C<IO::Socket> will export all functions (and constants) defined by L<Socket>.
|
||||
|
||||
=head1 CONSTRUCTOR ARGUMENTS
|
||||
|
||||
Given that C<IO::Socket> doesn't have attributes in the traditional sense, the
|
||||
following arguments, rather than attributes, can be passed into the
|
||||
constructor.
|
||||
|
||||
Constructor arguments should be passed in C<< Key => 'Value' >> pairs.
|
||||
|
||||
The only required argument is L<IO::Socket/"Domain">.
|
||||
|
||||
=head2 Blocking
|
||||
|
||||
my $sock = IO::Socket->new(..., Blocking => 1);
|
||||
$sock = IO::Socket->new(..., Blocking => 0);
|
||||
|
||||
If defined but false, the socket will be set to non-blocking mode. If not
|
||||
specified it defaults to C<1> (blocking mode).
|
||||
|
||||
=head2 Domain
|
||||
|
||||
my $sock = IO::Socket->new(Domain => IO::Socket::AF_INET);
|
||||
$sock = IO::Socket->new(Domain => IO::Socket::AF_UNIX);
|
||||
|
||||
The socket domain will define which subclass of C<IO::Socket> to use. The two
|
||||
options available along with this distribution are C<AF_INET> and C<AF_UNIX>.
|
||||
|
||||
C<AF_INET> is for the internet address family of sockets and is handled via
|
||||
L<IO::Socket::INET>. C<AF_INET> sockets are bound to an internet address and
|
||||
port.
|
||||
|
||||
C<AF_UNIX> is for the unix domain socket and is handled via
|
||||
L<IO::Socket::UNIX>. C<AF_UNIX> sockets are bound to the file system as their
|
||||
address name space.
|
||||
|
||||
This argument is B<required>. All other arguments are optional.
|
||||
|
||||
=head2 Listen
|
||||
|
||||
my $sock = IO::Socket->new(..., Listen => 5);
|
||||
|
||||
Listen should be an integer value or left unset.
|
||||
|
||||
If provided, this argument will place the socket into listening mode. New
|
||||
connections can then be accepted using the L<IO::Socket/"accept"> method. The
|
||||
value given is used as the C<listen(2)> queue size.
|
||||
|
||||
If the C<Listen> argument is given, but false, the queue size will be set to
|
||||
5.
|
||||
|
||||
=head2 Timeout
|
||||
|
||||
my $sock = IO::Socket->new(..., Timeout => 5);
|
||||
|
||||
The timeout value, in seconds, for this socket connection. How exactly this
|
||||
value is utilized is defined in the socket domain subclasses that make use of
|
||||
the value.
|
||||
|
||||
=head2 Type
|
||||
|
||||
my $sock = IO::Socket->new(..., Type => IO::Socket::SOCK_STREAM);
|
||||
|
||||
The socket type that will be used. These are usually C<SOCK_STREAM>,
|
||||
C<SOCK_DGRAM>, or C<SOCK_RAW>. If this argument is left undefined an attempt
|
||||
will be made to infer the type from the service name.
|
||||
|
||||
For example, you'll usually use C<SOCK_STREAM> with a C<tcp> connection and
|
||||
C<SOCK_DGRAM> with a C<udp> connection.
|
||||
|
||||
=head1 CONSTRUCTORS
|
||||
|
||||
C<IO::Socket> extends the L<IO::Handle> constructor.
|
||||
|
||||
=head2 new
|
||||
|
||||
my $sock = IO::Socket->new();
|
||||
|
||||
# get a new IO::Socket::INET instance
|
||||
$sock = IO::Socket->new(Domain => IO::Socket::AF_INET);
|
||||
# get a new IO::Socket::UNIX instance
|
||||
$sock = IO::Socket->new(Domain => IO::Socket::AF_UNIX);
|
||||
|
||||
# Domain is the only required argument
|
||||
$sock = IO::Socket->new(
|
||||
Domain => IO::Socket::AF_INET, # AF_INET, AF_UNIX
|
||||
Type => IO::Socket::SOCK_STREAM, # SOCK_STREAM, SOCK_DGRAM, ...
|
||||
Proto => 'tcp', # 'tcp', 'udp', IPPROTO_TCP, IPPROTO_UDP
|
||||
# and so on...
|
||||
);
|
||||
|
||||
Creates an C<IO::Socket>, which is a reference to a newly created symbol (see
|
||||
the L<Symbol> package). C<new> optionally takes arguments, these arguments
|
||||
are defined in L<IO::Socket/"CONSTRUCTOR ARGUMENTS">.
|
||||
|
||||
Any of the L<IO::Socket/"CONSTRUCTOR ARGUMENTS"> may be passed to the
|
||||
constructor, but if any arguments are provided, then one of them must be
|
||||
the L<IO::Socket/"Domain"> argument. The L<IO::Socket/"Domain"> argument can,
|
||||
by default, be either C<AF_INET> or C<AF_UNIX>. Other domains can be used if a
|
||||
proper subclass for the domain family is registered. All other arguments will
|
||||
be passed to the C<configuration> method of the package for that domain.
|
||||
|
||||
If the constructor fails it will return C<undef> and set the C<$errstr> package
|
||||
variable to contain an error message.
|
||||
|
||||
$sock = IO::Socket->new(...)
|
||||
or die "Cannot create socket - $IO::Socket::errstr\n";
|
||||
|
||||
For legacy reasons the error message is also set into the global C<$@>
|
||||
variable, and you may still find older code which looks here instead.
|
||||
|
||||
$sock = IO::Socket->new(...)
|
||||
or die "Cannot create socket - $@\n";
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
C<IO::Socket> inherits all methods from L<IO::Handle> and implements the
|
||||
following new ones.
|
||||
|
||||
=head2 accept
|
||||
|
||||
my $client_sock = $sock->accept();
|
||||
my $inet_sock = $sock->accept('IO::Socket::INET');
|
||||
|
||||
The accept method will perform the system call C<accept> on the socket and
|
||||
return a new object. The new object will be created in the same class as the
|
||||
listen socket, unless a specific package name is specified. This object can be
|
||||
used to communicate with the client that was trying to connect.
|
||||
|
||||
This differs slightly from the C<accept> function in L<perlfunc>.
|
||||
|
||||
In a scalar context the new socket is returned, or C<undef> upon
|
||||
failure. In a list context a two-element array is returned containing
|
||||
the new socket and the peer address; the list will be empty upon failure.
|
||||
|
||||
=head2 atmark
|
||||
|
||||
my $integer = $sock->atmark();
|
||||
# read in some data on a given socket
|
||||
my $data;
|
||||
$sock->read($data, 1024) until $sock->atmark;
|
||||
|
||||
# or, export the function to use:
|
||||
use IO::Socket 'sockatmark';
|
||||
$sock->read($data, 1024) until sockatmark($sock);
|
||||
|
||||
True if the socket is currently positioned at the urgent data mark, false
|
||||
otherwise. If your system doesn't yet implement C<sockatmark> this will throw
|
||||
an exception.
|
||||
|
||||
If your system does not support C<sockatmark>, the C<use> declaration will
|
||||
fail at compile time.
|
||||
|
||||
=head2 autoflush
|
||||
|
||||
# by default, autoflush will be turned on when referenced
|
||||
$sock->autoflush(); # turns on autoflush
|
||||
# turn off autoflush
|
||||
$sock->autoflush(0);
|
||||
# turn on autoflush
|
||||
$sock->autoflush(1);
|
||||
|
||||
This attribute isn't overridden from L<IO::Handle>'s implementation. However,
|
||||
since we turn it on by default, it's worth mentioning here.
|
||||
|
||||
=head2 bind
|
||||
|
||||
use Socket qw(pack_sockaddr_in);
|
||||
my $port = 3000;
|
||||
my $ip_address = '0.0.0.0';
|
||||
my $packed_addr = pack_sockaddr_in($port, $ip_address);
|
||||
$sock->bind($packed_addr);
|
||||
|
||||
Binds a network address to a socket, just as C<bind(2)> does. Returns true if
|
||||
it succeeded, false otherwise. You should provide a packed address of the
|
||||
appropriate type for the socket.
|
||||
|
||||
=head2 connected
|
||||
|
||||
my $peer_addr = $sock->connected();
|
||||
if ($peer_addr) {
|
||||
say "We're connected to $peer_addr";
|
||||
}
|
||||
|
||||
If the socket is in a connected state, the peer address is returned. If the
|
||||
socket is not in a connected state, C<undef> is returned.
|
||||
|
||||
Note that this method considers a half-open TCP socket to be "in a connected
|
||||
state". Specifically, it does not distinguish between the
|
||||
B<ESTABLISHED> and B<CLOSE-WAIT> TCP states; it returns the peer address,
|
||||
rather than C<undef>, in either case. Thus, in general, it cannot
|
||||
be used to reliably learn whether the peer has initiated a graceful shutdown
|
||||
because in most cases (see below) the local TCP state machine remains in
|
||||
B<CLOSE-WAIT> until the local application calls L<IO::Socket/"shutdown"> or
|
||||
C<close>. Only at that point does this function return C<undef>.
|
||||
|
||||
The "in most cases" hedge is because local TCP state machine behavior may
|
||||
depend on the peer's socket options. In particular, if the peer socket has
|
||||
C<SO_LINGER> enabled with a zero timeout, then the peer's C<close> will
|
||||
generate a C<RST> segment. Upon receipt of that segment, the local TCP
|
||||
transitions immediately to B<CLOSED>, and in that state, this method I<will>
|
||||
return C<undef>.
|
||||
|
||||
=head2 getsockopt
|
||||
|
||||
my $value = $sock->getsockopt(SOL_SOCKET, SO_REUSEADDR);
|
||||
my $buf = $socket->getsockopt(SOL_SOCKET, SO_RCVBUF);
|
||||
say "Receive buffer is $buf bytes";
|
||||
|
||||
Get an option associated with the socket. Levels other than C<SOL_SOCKET>
|
||||
may be specified here. As a convenience, this method will unpack a byte buffer
|
||||
of the correct size back into a number.
|
||||
|
||||
=head2 listen
|
||||
|
||||
$sock->listen(5);
|
||||
|
||||
Does the same thing that the C<listen(2)> system call does. Returns true if it
|
||||
succeeded, false otherwise. Listens to a socket with a given queue size.
|
||||
|
||||
=head2 peername
|
||||
|
||||
my $sockaddr_in = $sock->peername();
|
||||
|
||||
Returns the packed C<sockaddr> address of the other end of the socket
|
||||
connection. It calls C<getpeername>.
|
||||
|
||||
|
||||
=head2 protocol
|
||||
|
||||
my $proto = $sock->protocol();
|
||||
|
||||
Returns the number for the protocol being used on the socket, if
|
||||
known. If the protocol is unknown, as with an C<AF_UNIX> socket, zero
|
||||
is returned.
|
||||
|
||||
=head2 recv
|
||||
|
||||
my $buffer = "";
|
||||
my $length = 1024;
|
||||
my $flags = 0; # default. optional
|
||||
$sock->recv($buffer, $length);
|
||||
$sock->recv($buffer, $length, $flags);
|
||||
|
||||
Similar in functionality to L<perlfunc/recv>.
|
||||
|
||||
Receives a message on a socket. Attempts to receive C<$length> characters of
|
||||
data into C<$buffer> from the specified socket. C<$buffer> will be grown or
|
||||
shrunk to the length actually read. Takes the same flags as the system call of
|
||||
the same name. Returns the address of the sender if socket's protocol supports
|
||||
this; returns an empty string otherwise. If there's an error, returns
|
||||
C<undef>. This call is actually implemented in terms of the C<recvfrom(2)>
|
||||
system call.
|
||||
|
||||
Flags are ORed together values, such as C<MSG_BCAST>, C<MSG_OOB>,
|
||||
C<MSG_TRUNC>. The default value for the flags is C<0>.
|
||||
|
||||
The cached value of L<IO::Socket/"peername"> is updated with the result of
|
||||
C<recv>.
|
||||
|
||||
B<Note:> In Perl v5.30 and newer, if the socket has been marked as C<:utf8>,
|
||||
C<recv> will throw an exception. The C<:encoding(...)> layer implicitly
|
||||
introduces the C<:utf8> layer. See L<perlfunc/binmode>.
|
||||
|
||||
B<Note:> In Perl versions older than v5.30, depending on the status of the
|
||||
socket, either (8-bit) bytes or characters are received. By default all
|
||||
sockets operate on bytes, but for example if the socket has been changed
|
||||
using L<perlfunc/binmode> to operate with the C<:encoding(UTF-8)> I/O layer
|
||||
(see the L<perlfunc/open> pragma), the I/O will operate on UTF8-encoded
|
||||
Unicode characters, not bytes. Similarly for the C<:encoding> layer: in
|
||||
that case pretty much any characters can be read.
|
||||
|
||||
=head2 send
|
||||
|
||||
my $message = "Hello, world!";
|
||||
my $flags = 0; # defaults to zero
|
||||
my $to = '0.0.0.0'; # optional destination
|
||||
my $sent = $sock->send($message);
|
||||
$sent = $sock->send($message, $flags);
|
||||
$sent = $sock->send($message, $flags, $to);
|
||||
|
||||
Similar in functionality to L<perlfunc/send>.
|
||||
|
||||
Sends a message on a socket. Attempts to send the scalar message to the
|
||||
socket. Takes the same flags as the system call of the same name. On
|
||||
unconnected sockets, you must specify a destination to send to, in which case
|
||||
it does a C<sendto(2)> syscall. Returns the number of characters sent, or
|
||||
C<undef> on error. The C<sendmsg(2)> syscall is currently unimplemented.
|
||||
|
||||
The C<flags> option is optional and defaults to C<0>.
|
||||
|
||||
After a successful send with C<$to>, further calls to C<send> on an
|
||||
unconnected socket without C<$to> will send to the same address, and C<$to>
|
||||
will be used as the result of L<IO::Socket/"peername">.
|
||||
|
||||
B<Note:> In Perl v5.30 and newer, if the socket has been marked as C<:utf8>,
|
||||
C<send> will throw an exception. The C<:encoding(...)> layer implicitly
|
||||
introduces the C<:utf8> layer. See L<perlfunc/binmode>.
|
||||
|
||||
B<Note:> In Perl versions older than v5.30, depending on the status of the
|
||||
socket, either (8-bit) bytes or characters are sent. By default all
|
||||
sockets operate on bytes, but for example if the socket has been changed
|
||||
using L<perlfunc/binmode> to operate with the C<:encoding(UTF-8)> I/O layer
|
||||
(see the L<perlfunc/open> pragma), the I/O will operate on UTF8-encoded
|
||||
Unicode characters, not bytes. Similarly for the C<:encoding> layer: in
|
||||
that case pretty much any characters can be sent.
|
||||
|
||||
=head2 setsockopt
|
||||
|
||||
$sock->setsockopt(SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
$sock->setsockopt(SOL_SOCKET, SO_RCVBUF, 64*1024);
|
||||
|
||||
Set option associated with the socket. Levels other than C<SOL_SOCKET>
|
||||
may be specified here. As a convenience, this method will convert a number
|
||||
into a packed byte buffer.
|
||||
|
||||
=head2 shutdown
|
||||
|
||||
$sock->shutdown(SHUT_RD); # we stopped reading data
|
||||
$sock->shutdown(SHUT_WR); # we stopped writing data
|
||||
$sock->shutdown(SHUT_RDWR); # we stopped using this socket
|
||||
|
||||
Shuts down a socket connection in the manner indicated by the value passed in,
|
||||
which has the same interpretation as in the syscall of the same name.
|
||||
|
||||
This is useful with sockets when you want to tell the other side you're done
|
||||
writing but not done reading, or vice versa. It's also a more insistent form
|
||||
of C<close> because it also disables the file descriptor in any
|
||||
forked copies in other processes.
|
||||
|
||||
Returns C<1> for success; on error, returns C<undef> if the socket is
|
||||
not a valid filehandle, or returns C<0> and sets C<$!> for any other failure.
|
||||
|
||||
=head2 sockdomain
|
||||
|
||||
my $domain = $sock->sockdomain();
|
||||
|
||||
Returns the number for the socket domain type. For example, for
|
||||
an C<AF_INET> socket the value of C<&AF_INET> will be returned.
|
||||
|
||||
=head2 socket
|
||||
|
||||
my $sock = IO::Socket->new(); # no values given
|
||||
# now let's actually get a socket with the socket method
|
||||
# domain, type, and protocol are required
|
||||
$sock = $sock->socket(AF_INET, SOCK_STREAM, 'tcp');
|
||||
|
||||
Opens a socket of the specified kind and returns it. Domain, type, and
|
||||
protocol are specified the same as for the syscall of the same name.
|
||||
|
||||
=head2 socketpair
|
||||
|
||||
my ($r, $w) = $sock->socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
|
||||
($r, $w) = IO::Socket::UNIX
|
||||
->socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC);
|
||||
|
||||
Will return a list of two sockets created (read and write), or an empty list
|
||||
on failure.
|
||||
|
||||
Differs slightly from C<socketpair> in L<perlfunc> in that the argument list
|
||||
is a bit simpler.
|
||||
|
||||
=head2 sockname
|
||||
|
||||
my $packed_addr = $sock->sockname();
|
||||
|
||||
Returns the packed C<sockaddr> address of this end of the connection. It's the
|
||||
same as C<getsockname(2)>.
|
||||
|
||||
=head2 sockopt
|
||||
|
||||
my $value = $sock->sockopt(SO_REUSEADDR);
|
||||
$sock->sockopt(SO_REUSEADDR, 1);
|
||||
|
||||
Unified method to both set and get options in the C<SOL_SOCKET> level. If
|
||||
called with one argument then L<IO::Socket/"getsockopt"> is called, otherwise
|
||||
L<IO::Socket/"setsockopt"> is called.
|
||||
|
||||
=head2 socktype
|
||||
|
||||
my $type = $sock->socktype();
|
||||
|
||||
Returns the number for the socket type. For example, for
|
||||
a C<SOCK_STREAM> socket the value of C<&SOCK_STREAM> will be returned.
|
||||
|
||||
=head2 timeout
|
||||
|
||||
my $seconds = $sock->timeout();
|
||||
my $old_val = $sock->timeout(5); # set new and return old value
|
||||
|
||||
Set or get the timeout value (in seconds) associated with this socket.
|
||||
If called without any arguments then the current setting is returned. If
|
||||
called with an argument the current setting is changed and the previous
|
||||
value returned.
|
||||
|
||||
This method is available to all C<IO::Socket> implementations but may or may
|
||||
not be used by the individual domain subclasses.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Let's create a TCP server on C<localhost:3333>.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
|
||||
use IO::Socket qw(AF_INET AF_UNIX SOCK_STREAM SHUT_WR);
|
||||
|
||||
my $server = IO::Socket->new(
|
||||
Domain => AF_INET,
|
||||
Type => SOCK_STREAM,
|
||||
Proto => 'tcp',
|
||||
LocalHost => '0.0.0.0',
|
||||
LocalPort => 3333,
|
||||
ReusePort => 1,
|
||||
Listen => 5,
|
||||
) || die "Can't open socket: $IO::Socket::errstr";
|
||||
say "Waiting on 3333";
|
||||
|
||||
while (1) {
|
||||
# waiting for a new client connection
|
||||
my $client = $server->accept();
|
||||
|
||||
# get information about a newly connected client
|
||||
my $client_address = $client->peerhost();
|
||||
my $client_port = $client->peerport();
|
||||
say "Connection from $client_address:$client_port";
|
||||
|
||||
# read up to 1024 characters from the connected client
|
||||
my $data = "";
|
||||
$client->recv($data, 1024);
|
||||
say "received data: $data";
|
||||
|
||||
# write response data to the connected client
|
||||
$data = "ok";
|
||||
$client->send($data);
|
||||
|
||||
# notify client that response has been sent
|
||||
$client->shutdown(SHUT_WR);
|
||||
}
|
||||
|
||||
$server->close();
|
||||
|
||||
A client for such a server could be
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use feature 'say';
|
||||
|
||||
use IO::Socket qw(AF_INET AF_UNIX SOCK_STREAM SHUT_WR);
|
||||
|
||||
my $client = IO::Socket->new(
|
||||
Domain => AF_INET,
|
||||
Type => SOCK_STREAM,
|
||||
proto => 'tcp',
|
||||
PeerPort => 3333,
|
||||
PeerHost => '0.0.0.0',
|
||||
) || die "Can't open socket: $IO::Socket::errstr";
|
||||
|
||||
say "Sending Hello World!";
|
||||
my $size = $client->send("Hello World!");
|
||||
say "Sent data of length: $size";
|
||||
|
||||
$client->shutdown(SHUT_WR);
|
||||
|
||||
my $buffer;
|
||||
$client->recv($buffer, 1024);
|
||||
say "Got back $buffer";
|
||||
|
||||
$client->close();
|
||||
|
||||
|
||||
=head1 LIMITATIONS
|
||||
|
||||
On some systems, for an IO::Socket object created with C<new_from_fd>,
|
||||
or created with L<IO::Socket/"accept"> from such an object, the
|
||||
L<IO::Socket/"protocol">, L<IO::Socket/"sockdomain"> and
|
||||
L<IO::Socket/"socktype"> methods may return C<undef>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Socket>, L<IO::Handle>, L<IO::Socket::INET>, L<IO::Socket::UNIX>,
|
||||
L<IO::Socket::IP>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Graham Barr. atmark() by Lincoln Stein. Currently maintained by the
|
||||
Perl Porters. Please report all bugs to <perlbug@perl.org>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
The atmark() implementation: Copyright 2001, Lincoln Stein <lstein@cshl.org>.
|
||||
This module is distributed under the same terms as Perl itself.
|
||||
Feel free to use, modify and redistribute it as long as you retain
|
||||
the correct attribution.
|
||||
|
||||
=cut
|
||||
471
database/perl/lib/IO/Socket/INET.pm
Normal file
471
database/perl/lib/IO/Socket/INET.pm
Normal file
@@ -0,0 +1,471 @@
|
||||
# IO::Socket::INET.pm
|
||||
#
|
||||
# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Socket::INET;
|
||||
|
||||
use strict;
|
||||
use IO::Socket;
|
||||
use Socket;
|
||||
use Carp;
|
||||
use Exporter;
|
||||
use Errno;
|
||||
|
||||
our @ISA = qw(IO::Socket);
|
||||
our $VERSION = "1.45";
|
||||
|
||||
my $EINVAL = exists(&Errno::EINVAL) ? Errno::EINVAL() : 1;
|
||||
|
||||
IO::Socket::INET->register_domain( AF_INET );
|
||||
|
||||
my %socket_type = ( tcp => SOCK_STREAM,
|
||||
udp => SOCK_DGRAM,
|
||||
icmp => SOCK_RAW
|
||||
);
|
||||
my %proto_number;
|
||||
$proto_number{tcp} = Socket::IPPROTO_TCP() if defined &Socket::IPPROTO_TCP;
|
||||
$proto_number{udp} = Socket::IPPROTO_UDP() if defined &Socket::IPPROTO_UDP;
|
||||
$proto_number{icmp} = Socket::IPPROTO_ICMP() if defined &Socket::IPPROTO_ICMP;
|
||||
my %proto_name = reverse %proto_number;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
unshift(@_, "PeerAddr") if @_ == 1;
|
||||
return $class->SUPER::new(@_);
|
||||
}
|
||||
|
||||
sub _cache_proto {
|
||||
my @proto = @_;
|
||||
for (map lc($_), $proto[0], split(' ', $proto[1])) {
|
||||
$proto_number{$_} = $proto[2];
|
||||
}
|
||||
$proto_name{$proto[2]} = $proto[0];
|
||||
}
|
||||
|
||||
sub _get_proto_number {
|
||||
my $name = lc(shift);
|
||||
return undef unless defined $name;
|
||||
return $proto_number{$name} if exists $proto_number{$name};
|
||||
|
||||
my @proto = eval { getprotobyname($name) };
|
||||
return undef unless @proto;
|
||||
_cache_proto(@proto);
|
||||
|
||||
return $proto[2];
|
||||
}
|
||||
|
||||
sub _get_proto_name {
|
||||
my $num = shift;
|
||||
return undef unless defined $num;
|
||||
return $proto_name{$num} if exists $proto_name{$num};
|
||||
|
||||
my @proto = eval { getprotobynumber($num) };
|
||||
return undef unless @proto;
|
||||
_cache_proto(@proto);
|
||||
|
||||
return $proto[0];
|
||||
}
|
||||
|
||||
sub _sock_info {
|
||||
my($addr,$port,$proto) = @_;
|
||||
my $origport = $port;
|
||||
my @serv = ();
|
||||
|
||||
$port = $1
|
||||
if(defined $addr && $addr =~ s,:([\w\(\)/]+)$,,);
|
||||
|
||||
if(defined $proto && $proto =~ /\D/) {
|
||||
my $num = _get_proto_number($proto);
|
||||
unless (defined $num) {
|
||||
$IO::Socket::errstr = $@ = "Bad protocol '$proto'";
|
||||
return;
|
||||
}
|
||||
$proto = $num;
|
||||
}
|
||||
|
||||
if(defined $port) {
|
||||
my $defport = ($port =~ s,\((\d+)\)$,,) ? $1 : undef;
|
||||
my $pnum = ($port =~ m,^(\d+)$,)[0];
|
||||
|
||||
@serv = getservbyname($port, _get_proto_name($proto) || "")
|
||||
if ($port =~ m,\D,);
|
||||
|
||||
$port = $serv[2] || $defport || $pnum;
|
||||
unless (defined $port) {
|
||||
$IO::Socket::errstr = $@ = "Bad service '$origport'";
|
||||
return;
|
||||
}
|
||||
|
||||
$proto = _get_proto_number($serv[3]) if @serv && !$proto;
|
||||
}
|
||||
|
||||
return ($addr || undef,
|
||||
$port || undef,
|
||||
$proto || undef
|
||||
);
|
||||
}
|
||||
|
||||
sub _error {
|
||||
my $sock = shift;
|
||||
my $err = shift;
|
||||
{
|
||||
local($!);
|
||||
my $title = ref($sock).": ";
|
||||
$IO::Socket::errstr = $@ = join("", $_[0] =~ /^$title/ ? "" : $title, @_);
|
||||
$sock->close()
|
||||
if(defined fileno($sock));
|
||||
}
|
||||
$! = $err;
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub _get_addr {
|
||||
my($sock,$addr_str, $multi) = @_;
|
||||
my @addr;
|
||||
if ($multi && $addr_str !~ /^\d+(?:\.\d+){3}$/) {
|
||||
(undef, undef, undef, undef, @addr) = gethostbyname($addr_str);
|
||||
} else {
|
||||
my $h = inet_aton($addr_str);
|
||||
push(@addr, $h) if defined $h;
|
||||
}
|
||||
@addr;
|
||||
}
|
||||
|
||||
sub configure {
|
||||
my($sock,$arg) = @_;
|
||||
my($lport,$rport,$laddr,$raddr,$proto,$type);
|
||||
|
||||
|
||||
$arg->{LocalAddr} = $arg->{LocalHost}
|
||||
if exists $arg->{LocalHost} && !exists $arg->{LocalAddr};
|
||||
|
||||
($laddr,$lport,$proto) = _sock_info($arg->{LocalAddr},
|
||||
$arg->{LocalPort},
|
||||
$arg->{Proto})
|
||||
or return _error($sock, $!, $@);
|
||||
|
||||
$laddr = defined $laddr ? inet_aton($laddr)
|
||||
: INADDR_ANY;
|
||||
|
||||
return _error($sock, $EINVAL, "Bad hostname '",$arg->{LocalAddr},"'")
|
||||
unless(defined $laddr);
|
||||
|
||||
$arg->{PeerAddr} = $arg->{PeerHost}
|
||||
if exists $arg->{PeerHost} && !exists $arg->{PeerAddr};
|
||||
|
||||
unless(exists $arg->{Listen}) {
|
||||
($raddr,$rport,$proto) = _sock_info($arg->{PeerAddr},
|
||||
$arg->{PeerPort},
|
||||
$proto)
|
||||
or return _error($sock, $!, $@);
|
||||
}
|
||||
|
||||
$proto ||= _get_proto_number('tcp');
|
||||
|
||||
$type = $arg->{Type} || $socket_type{lc _get_proto_name($proto)};
|
||||
|
||||
my @raddr = ();
|
||||
|
||||
if(defined $raddr) {
|
||||
@raddr = $sock->_get_addr($raddr, $arg->{MultiHomed});
|
||||
return _error($sock, $EINVAL, "Bad hostname '",$arg->{PeerAddr},"'")
|
||||
unless @raddr;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
|
||||
$sock->socket(AF_INET, $type, $proto) or
|
||||
return _error($sock, $!, "$!");
|
||||
|
||||
if (defined $arg->{Blocking}) {
|
||||
defined $sock->blocking($arg->{Blocking})
|
||||
or return _error($sock, $!, "$!");
|
||||
}
|
||||
|
||||
if ($arg->{Reuse} || $arg->{ReuseAddr}) {
|
||||
$sock->sockopt(SO_REUSEADDR,1) or
|
||||
return _error($sock, $!, "$!");
|
||||
}
|
||||
|
||||
if ($arg->{ReusePort}) {
|
||||
$sock->sockopt(SO_REUSEPORT,1) or
|
||||
return _error($sock, $!, "$!");
|
||||
}
|
||||
|
||||
if ($arg->{Broadcast}) {
|
||||
$sock->sockopt(SO_BROADCAST,1) or
|
||||
return _error($sock, $!, "$!");
|
||||
}
|
||||
|
||||
if($lport || ($laddr ne INADDR_ANY) || exists $arg->{Listen}) {
|
||||
$sock->bind($lport || 0, $laddr) or
|
||||
return _error($sock, $!, "$!");
|
||||
}
|
||||
|
||||
if(exists $arg->{Listen}) {
|
||||
$sock->listen($arg->{Listen} || 5) or
|
||||
return _error($sock, $!, "$!");
|
||||
last;
|
||||
}
|
||||
|
||||
# don't try to connect unless we're given a PeerAddr
|
||||
last unless exists($arg->{PeerAddr});
|
||||
|
||||
$raddr = shift @raddr;
|
||||
|
||||
return _error($sock, $EINVAL, 'Cannot determine remote port')
|
||||
unless($rport || $type == SOCK_DGRAM || $type == SOCK_RAW);
|
||||
|
||||
last
|
||||
unless($type == SOCK_STREAM || defined $raddr);
|
||||
|
||||
return _error($sock, $EINVAL, "Bad hostname '",$arg->{PeerAddr},"'")
|
||||
unless defined $raddr;
|
||||
|
||||
# my $timeout = ${*$sock}{'io_socket_timeout'};
|
||||
# my $before = time() if $timeout;
|
||||
|
||||
undef $@;
|
||||
if ($sock->connect(pack_sockaddr_in($rport, $raddr))) {
|
||||
# ${*$sock}{'io_socket_timeout'} = $timeout;
|
||||
return $sock;
|
||||
}
|
||||
|
||||
return _error($sock, $!, $@ || "Timeout")
|
||||
unless @raddr;
|
||||
|
||||
# if ($timeout) {
|
||||
# my $new_timeout = $timeout - (time() - $before);
|
||||
# return _error($sock,
|
||||
# (exists(&Errno::ETIMEDOUT) ? Errno::ETIMEDOUT() : $EINVAL),
|
||||
# "Timeout") if $new_timeout <= 0;
|
||||
# ${*$sock}{'io_socket_timeout'} = $new_timeout;
|
||||
# }
|
||||
|
||||
}
|
||||
|
||||
$sock;
|
||||
}
|
||||
|
||||
sub connect {
|
||||
@_ == 2 || @_ == 3 or
|
||||
croak 'usage: $sock->connect(NAME) or $sock->connect(PORT, ADDR)';
|
||||
my $sock = shift;
|
||||
return $sock->SUPER::connect(@_ == 1 ? shift : pack_sockaddr_in(@_));
|
||||
}
|
||||
|
||||
sub bind {
|
||||
@_ == 2 || @_ == 3 or
|
||||
croak 'usage: $sock->bind(NAME) or $sock->bind(PORT, ADDR)';
|
||||
my $sock = shift;
|
||||
return $sock->SUPER::bind(@_ == 1 ? shift : pack_sockaddr_in(@_))
|
||||
}
|
||||
|
||||
sub sockaddr {
|
||||
@_ == 1 or croak 'usage: $sock->sockaddr()';
|
||||
my($sock) = @_;
|
||||
my $name = $sock->sockname;
|
||||
$name ? (sockaddr_in($name))[1] : undef;
|
||||
}
|
||||
|
||||
sub sockport {
|
||||
@_ == 1 or croak 'usage: $sock->sockport()';
|
||||
my($sock) = @_;
|
||||
my $name = $sock->sockname;
|
||||
$name ? (sockaddr_in($name))[0] : undef;
|
||||
}
|
||||
|
||||
sub sockhost {
|
||||
@_ == 1 or croak 'usage: $sock->sockhost()';
|
||||
my($sock) = @_;
|
||||
my $addr = $sock->sockaddr;
|
||||
$addr ? inet_ntoa($addr) : undef;
|
||||
}
|
||||
|
||||
sub peeraddr {
|
||||
@_ == 1 or croak 'usage: $sock->peeraddr()';
|
||||
my($sock) = @_;
|
||||
my $name = $sock->peername;
|
||||
$name ? (sockaddr_in($name))[1] : undef;
|
||||
}
|
||||
|
||||
sub peerport {
|
||||
@_ == 1 or croak 'usage: $sock->peerport()';
|
||||
my($sock) = @_;
|
||||
my $name = $sock->peername;
|
||||
$name ? (sockaddr_in($name))[0] : undef;
|
||||
}
|
||||
|
||||
sub peerhost {
|
||||
@_ == 1 or croak 'usage: $sock->peerhost()';
|
||||
my($sock) = @_;
|
||||
my $addr = $sock->peeraddr;
|
||||
$addr ? inet_ntoa($addr) : undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Socket::INET - Object interface for AF_INET domain sockets
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Socket::INET;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Socket::INET> provides an object interface to creating and using sockets
|
||||
in the AF_INET domain. It is built upon the L<IO::Socket> interface and
|
||||
inherits all the methods defined by L<IO::Socket>.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ( [ARGS] )
|
||||
|
||||
Creates an C<IO::Socket::INET> object, which is a reference to a
|
||||
newly created symbol (see the C<Symbol> package). C<new>
|
||||
optionally takes arguments, these arguments are in key-value pairs.
|
||||
|
||||
In addition to the key-value pairs accepted by L<IO::Socket>,
|
||||
C<IO::Socket::INET> provides.
|
||||
|
||||
|
||||
PeerAddr Remote host address <hostname>[:<port>]
|
||||
PeerHost Synonym for PeerAddr
|
||||
PeerPort Remote port or service <service>[(<no>)] | <no>
|
||||
LocalAddr Local host bind address hostname[:port]
|
||||
LocalHost Synonym for LocalAddr
|
||||
LocalPort Local host bind port <service>[(<no>)] | <no>
|
||||
Proto Protocol name (or number) "tcp" | "udp" | ...
|
||||
Type Socket type SOCK_STREAM | SOCK_DGRAM | ...
|
||||
Listen Queue size for listen
|
||||
ReuseAddr Set SO_REUSEADDR before binding
|
||||
Reuse Set SO_REUSEADDR before binding (deprecated,
|
||||
prefer ReuseAddr)
|
||||
ReusePort Set SO_REUSEPORT before binding
|
||||
Broadcast Set SO_BROADCAST before binding
|
||||
Timeout Timeout value for various operations
|
||||
MultiHomed Try all addresses for multi-homed hosts
|
||||
Blocking Determine if connection will be blocking mode
|
||||
|
||||
If C<Listen> is defined then a listen socket is created, else if the
|
||||
socket type, which is derived from the protocol, is SOCK_STREAM then
|
||||
connect() is called. If the C<Listen> argument is given, but false,
|
||||
the queue size will be set to 5.
|
||||
|
||||
Although it is not illegal, the use of C<MultiHomed> on a socket
|
||||
which is in non-blocking mode is of little use. This is because the
|
||||
first connect will never fail with a timeout as the connect call
|
||||
will not block.
|
||||
|
||||
The C<PeerAddr> can be a hostname or the IP-address on the
|
||||
"xx.xx.xx.xx" form. The C<PeerPort> can be a number or a symbolic
|
||||
service name. The service name might be followed by a number in
|
||||
parenthesis which is used if the service is not known by the system.
|
||||
The C<PeerPort> specification can also be embedded in the C<PeerAddr>
|
||||
by preceding it with a ":".
|
||||
|
||||
If C<Proto> is not given and you specify a symbolic C<PeerPort> port,
|
||||
then the constructor will try to derive C<Proto> from the service
|
||||
name. As a last resort C<Proto> "tcp" is assumed. The C<Type>
|
||||
parameter will be deduced from C<Proto> if not specified.
|
||||
|
||||
If the constructor is only passed a single argument, it is assumed to
|
||||
be a C<PeerAddr> specification.
|
||||
|
||||
If C<Blocking> is set to 0, the connection will be in nonblocking mode.
|
||||
If not specified it defaults to 1 (blocking mode).
|
||||
|
||||
Examples:
|
||||
|
||||
$sock = IO::Socket::INET->new(PeerAddr => 'www.perl.org',
|
||||
PeerPort => 'http(80)',
|
||||
Proto => 'tcp');
|
||||
|
||||
$sock = IO::Socket::INET->new(PeerAddr => 'localhost:smtp(25)');
|
||||
|
||||
$sock = IO::Socket::INET->new(Listen => 5,
|
||||
LocalAddr => 'localhost',
|
||||
LocalPort => 9000,
|
||||
Proto => 'tcp');
|
||||
|
||||
$sock = IO::Socket::INET->new('127.0.0.1:25');
|
||||
|
||||
$sock = IO::Socket::INET->new(
|
||||
PeerPort => 9999,
|
||||
PeerAddr => inet_ntoa(INADDR_BROADCAST),
|
||||
Proto => udp,
|
||||
LocalAddr => 'localhost',
|
||||
Broadcast => 1 )
|
||||
or die "Can't bind : $IO::Socket::errstr\n";
|
||||
|
||||
If the constructor fails it will return C<undef> and set the
|
||||
C<$IO::Socket::errstr> package variable to contain an error message.
|
||||
|
||||
$sock = IO::Socket::INET->new(...)
|
||||
or die "Cannot create socket - $IO::Socket::errstr\n";
|
||||
|
||||
For legacy reasons the error message is also set into the global C<$@>
|
||||
variable, and you may still find older code which looks here instead.
|
||||
|
||||
$sock = IO::Socket::INET->new(...)
|
||||
or die "Cannot create socket - $@\n";
|
||||
|
||||
=back
|
||||
|
||||
=head2 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item sockaddr ()
|
||||
|
||||
Return the address part of the sockaddr structure for the socket
|
||||
|
||||
=item sockport ()
|
||||
|
||||
Return the port number that the socket is using on the local host
|
||||
|
||||
=item sockhost ()
|
||||
|
||||
Return the address part of the sockaddr structure for the socket in a
|
||||
text form xx.xx.xx.xx
|
||||
|
||||
=item peeraddr ()
|
||||
|
||||
Return the address part of the sockaddr structure for the socket on
|
||||
the peer host
|
||||
|
||||
=item peerport ()
|
||||
|
||||
Return the port number for the socket on the peer host.
|
||||
|
||||
=item peerhost ()
|
||||
|
||||
Return the address part of the sockaddr structure for the socket on the
|
||||
peer host in a text form xx.xx.xx.xx
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Socket>, L<IO::Socket>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Graham Barr. Currently maintained by the Perl Porters. Please report all
|
||||
bugs to <perlbug@perl.org>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
1285
database/perl/lib/IO/Socket/IP.pm
Normal file
1285
database/perl/lib/IO/Socket/IP.pm
Normal file
File diff suppressed because it is too large
Load Diff
173
database/perl/lib/IO/Socket/UNIX.pm
Normal file
173
database/perl/lib/IO/Socket/UNIX.pm
Normal file
@@ -0,0 +1,173 @@
|
||||
# IO::Socket::UNIX.pm
|
||||
#
|
||||
# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Socket::UNIX;
|
||||
|
||||
use strict;
|
||||
use IO::Socket;
|
||||
use Carp;
|
||||
|
||||
our @ISA = qw(IO::Socket);
|
||||
our $VERSION = "1.45";
|
||||
|
||||
IO::Socket::UNIX->register_domain( AF_UNIX );
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
unshift(@_, "Peer") if @_ == 1;
|
||||
return $class->SUPER::new(@_);
|
||||
}
|
||||
|
||||
sub configure {
|
||||
my($sock,$arg) = @_;
|
||||
my($bport,$cport);
|
||||
|
||||
my $type = $arg->{Type} || SOCK_STREAM;
|
||||
|
||||
$sock->socket(AF_UNIX, $type, 0) or
|
||||
return undef;
|
||||
|
||||
if(exists $arg->{Blocking}) {
|
||||
$sock->blocking($arg->{Blocking}) or
|
||||
return undef;
|
||||
}
|
||||
if(exists $arg->{Local}) {
|
||||
my $addr = sockaddr_un($arg->{Local});
|
||||
$sock->bind($addr) or
|
||||
return undef;
|
||||
}
|
||||
if(exists $arg->{Listen} && $type != SOCK_DGRAM) {
|
||||
$sock->listen($arg->{Listen} || 5) or
|
||||
return undef;
|
||||
}
|
||||
elsif(exists $arg->{Peer}) {
|
||||
my $addr = sockaddr_un($arg->{Peer});
|
||||
$sock->connect($addr) or
|
||||
return undef;
|
||||
}
|
||||
|
||||
$sock;
|
||||
}
|
||||
|
||||
sub hostpath {
|
||||
@_ == 1 or croak 'usage: $sock->hostpath()';
|
||||
my $n = $_[0]->sockname || return undef;
|
||||
(sockaddr_un($n))[0];
|
||||
}
|
||||
|
||||
sub peerpath {
|
||||
@_ == 1 or croak 'usage: $sock->peerpath()';
|
||||
my $n = $_[0]->peername || return undef;
|
||||
(sockaddr_un($n))[0];
|
||||
}
|
||||
|
||||
1; # Keep require happy
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Socket::UNIX - Object interface for AF_UNIX domain sockets
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Socket::UNIX;
|
||||
|
||||
my $SOCK_PATH = "$ENV{HOME}/unix-domain-socket-test.sock";
|
||||
|
||||
# Server:
|
||||
my $server = IO::Socket::UNIX->new(
|
||||
Type => SOCK_STREAM(),
|
||||
Local => $SOCK_PATH,
|
||||
Listen => 1,
|
||||
);
|
||||
|
||||
my $count = 1;
|
||||
while (my $conn = $server->accept()) {
|
||||
$conn->print("Hello " . ($count++) . "\n");
|
||||
}
|
||||
|
||||
# Client:
|
||||
my $client = IO::Socket::UNIX->new(
|
||||
Type => SOCK_STREAM(),
|
||||
Peer => $SOCK_PATH,
|
||||
);
|
||||
|
||||
# Now read and write from $client
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Socket::UNIX> provides an object interface to creating and using sockets
|
||||
in the AF_UNIX domain. It is built upon the L<IO::Socket> interface and
|
||||
inherits all the methods defined by L<IO::Socket>.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ( [ARGS] )
|
||||
|
||||
Creates an C<IO::Socket::UNIX> object, which is a reference to a
|
||||
newly created symbol (see the C<Symbol> package). C<new>
|
||||
optionally takes arguments, these arguments are in key-value pairs.
|
||||
|
||||
In addition to the key-value pairs accepted by L<IO::Socket>,
|
||||
C<IO::Socket::UNIX> provides.
|
||||
|
||||
Type Type of socket (eg SOCK_STREAM or SOCK_DGRAM)
|
||||
Local Path to local fifo
|
||||
Peer Path to peer fifo
|
||||
Listen Queue size for listen
|
||||
|
||||
If the constructor is only passed a single argument, it is assumed to
|
||||
be a C<Peer> specification.
|
||||
|
||||
If the C<Listen> argument is given, but false, the queue size will be set to 5.
|
||||
|
||||
If the constructor fails it will return C<undef> and set the
|
||||
C<$IO::Socket::errstr> package variable to contain an error message.
|
||||
|
||||
$sock = IO::Socket::UNIX->new(...)
|
||||
or die "Cannot create socket - $IO::Socket::errstr\n";
|
||||
|
||||
For legacy reasons the error message is also set into the global C<$@>
|
||||
variable, and you may still find older code which looks here instead.
|
||||
|
||||
$sock = IO::Socket::UNIX->new(...)
|
||||
or die "Cannot create socket - $@\n";
|
||||
|
||||
=back
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item hostpath()
|
||||
|
||||
Returns the pathname to the fifo at the local end
|
||||
|
||||
=item peerpath()
|
||||
|
||||
Returns the pathanme to the fifo at the peer end
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Socket>, L<IO::Socket>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Graham Barr. Currently maintained by the Perl Porters. Please report all
|
||||
bugs to <perlbug@perl.org>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
111
database/perl/lib/IO/Uncompress/Adapter/Bunzip2.pm
Normal file
111
database/perl/lib/IO/Uncompress/Adapter/Bunzip2.pm
Normal file
@@ -0,0 +1,111 @@
|
||||
package IO::Uncompress::Adapter::Bunzip2;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Status);
|
||||
|
||||
use Compress::Raw::Bzip2 2.100 ;
|
||||
|
||||
our ($VERSION, @ISA);
|
||||
$VERSION = '2.100';
|
||||
|
||||
sub mkUncompObject
|
||||
{
|
||||
my $small = shift || 0;
|
||||
my $verbosity = shift || 0;
|
||||
|
||||
my ($inflate, $status) = Compress::Raw::Bunzip2->new(1, 1, $small, $verbosity, 1);
|
||||
|
||||
return (undef, "Could not create Inflation object: $status", $status)
|
||||
if $status != BZ_OK ;
|
||||
|
||||
return bless {'Inf' => $inflate,
|
||||
'CompSize' => 0,
|
||||
'UnCompSize' => 0,
|
||||
'Error' => '',
|
||||
'ConsumesInput' => 1,
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
sub uncompr
|
||||
{
|
||||
my $self = shift ;
|
||||
my $from = shift ;
|
||||
my $to = shift ;
|
||||
my $eof = shift ;
|
||||
|
||||
my $inf = $self->{Inf};
|
||||
|
||||
my $status = $inf->bzinflate($from, $to);
|
||||
$self->{ErrorNo} = $status;
|
||||
|
||||
if ($status != BZ_OK && $status != BZ_STREAM_END )
|
||||
{
|
||||
$self->{Error} = "Inflation Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
return STATUS_OK if $status == BZ_OK ;
|
||||
return STATUS_ENDSTREAM if $status == BZ_STREAM_END ;
|
||||
return STATUS_ERROR ;
|
||||
}
|
||||
|
||||
|
||||
sub reset
|
||||
{
|
||||
my $self = shift ;
|
||||
|
||||
my ($inf, $status) = Compress::Raw::Bunzip2->new();
|
||||
$self->{ErrorNo} = ($status == BZ_OK) ? 0 : $status ;
|
||||
|
||||
if ($status != BZ_OK)
|
||||
{
|
||||
$self->{Error} = "Cannot create Inflate object: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
$self->{Inf} = $inf;
|
||||
|
||||
return STATUS_OK ;
|
||||
}
|
||||
|
||||
sub compressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->compressedBytes();
|
||||
}
|
||||
|
||||
sub uncompressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->uncompressedBytes();
|
||||
}
|
||||
|
||||
sub crc32
|
||||
{
|
||||
my $self = shift ;
|
||||
#$self->{Inf}->crc32();
|
||||
}
|
||||
|
||||
sub adler32
|
||||
{
|
||||
my $self = shift ;
|
||||
#$self->{Inf}->adler32();
|
||||
}
|
||||
|
||||
sub sync
|
||||
{
|
||||
my $self = shift ;
|
||||
#( $self->{Inf}->inflateSync(@_) == BZ_OK)
|
||||
# ? STATUS_OK
|
||||
# : STATUS_ERROR ;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
188
database/perl/lib/IO/Uncompress/Adapter/Identity.pm
Normal file
188
database/perl/lib/IO/Uncompress/Adapter/Identity.pm
Normal file
@@ -0,0 +1,188 @@
|
||||
package IO::Uncompress::Adapter::Identity;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use bytes;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Status);
|
||||
use IO::Compress::Zip::Constants ;
|
||||
|
||||
our ($VERSION);
|
||||
|
||||
$VERSION = '2.100';
|
||||
|
||||
use Compress::Raw::Zlib 2.100 ();
|
||||
|
||||
sub mkUncompObject
|
||||
{
|
||||
my $streaming = shift;
|
||||
my $zip64 = shift;
|
||||
|
||||
my $crc32 = 1; #shift ;
|
||||
my $adler32 = shift;
|
||||
|
||||
bless { 'CompSize' => U64->new(), # 0,
|
||||
'UnCompSize' => 0,
|
||||
'wantCRC32' => $crc32,
|
||||
'CRC32' => Compress::Raw::Zlib::crc32(''),
|
||||
'wantADLER32'=> $adler32,
|
||||
'ADLER32' => Compress::Raw::Zlib::adler32(''),
|
||||
'ConsumesInput' => 1,
|
||||
'Streaming' => $streaming,
|
||||
'Zip64' => $zip64,
|
||||
'DataHdrSize' => $zip64 ? 24 : 16,
|
||||
'Pending' => '',
|
||||
|
||||
} ;
|
||||
}
|
||||
|
||||
|
||||
sub uncompr
|
||||
{
|
||||
my $self = shift;
|
||||
my $in = $_[0];
|
||||
my $eof = $_[2];
|
||||
|
||||
my $len = length $$in;
|
||||
my $remainder = '';
|
||||
|
||||
if (defined $$in && $len) {
|
||||
|
||||
if ($self->{Streaming}) {
|
||||
|
||||
if (length $self->{Pending}) {
|
||||
$$in = $self->{Pending} . $$in ;
|
||||
$len = length $$in;
|
||||
$self->{Pending} = '';
|
||||
}
|
||||
|
||||
my $ind = index($$in, "\x50\x4b\x07\x08");
|
||||
|
||||
if ($ind < 0) {
|
||||
$len = length $$in;
|
||||
if ($len >= 3 && substr($$in, -3) eq "\x50\x4b\x07") {
|
||||
$ind = $len - 3 ;
|
||||
}
|
||||
elsif ($len >= 2 && substr($$in, -2) eq "\x50\x4b") {
|
||||
$ind = $len - 2 ;
|
||||
}
|
||||
elsif ($len >= 1 && substr($$in, -1) eq "\x50") {
|
||||
$ind = $len - 1 ;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ind >= 0) {
|
||||
$remainder = substr($$in, $ind) ;
|
||||
substr($$in, $ind) = '' ;
|
||||
}
|
||||
}
|
||||
|
||||
if (length $remainder && length $remainder < $self->{DataHdrSize}) {
|
||||
$self->{Pending} = $remainder ;
|
||||
$remainder = '';
|
||||
}
|
||||
elsif (length $remainder >= $self->{DataHdrSize}) {
|
||||
my $crc = unpack "V", substr($remainder, 4);
|
||||
if ($crc == Compress::Raw::Zlib::crc32($$in, $self->{CRC32})) {
|
||||
my ($l1, $l2) ;
|
||||
|
||||
if ($self->{Zip64}) {
|
||||
$l1 = U64::newUnpack_V64(substr($remainder, 8));
|
||||
$l2 = U64::newUnpack_V64(substr($remainder, 16));
|
||||
}
|
||||
else {
|
||||
$l1 = U64::newUnpack_V32(substr($remainder, 8));
|
||||
$l2 = U64::newUnpack_V32(substr($remainder, 12));
|
||||
}
|
||||
|
||||
my $newLen = $self->{CompSize}->clone();
|
||||
$newLen->add(length $$in);
|
||||
if ($l1->equal($l2) && $l1->equal($newLen) ) {
|
||||
$eof = 1;
|
||||
}
|
||||
else {
|
||||
$$in .= substr($remainder, 0, 4) ;
|
||||
$remainder = substr($remainder, 4);
|
||||
#$self->{Pending} = substr($remainder, 4);
|
||||
#$remainder = '';
|
||||
$eof = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$$in .= substr($remainder, 0, 4) ;
|
||||
$remainder = substr($remainder, 4);
|
||||
#$self->{Pending} = substr($remainder, 4);
|
||||
#$remainder = '';
|
||||
$eof = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (length $$in) {
|
||||
$self->{CompSize}->add(length $$in) ;
|
||||
|
||||
$self->{CRC32} = Compress::Raw::Zlib::crc32($$in, $self->{CRC32})
|
||||
if $self->{wantCRC32};
|
||||
|
||||
$self->{ADLER32} = Compress::Zlib::adler32($$in, $self->{ADLER32})
|
||||
if $self->{wantADLER32};
|
||||
}
|
||||
|
||||
${ $_[1] } .= $$in;
|
||||
$$in = $remainder;
|
||||
}
|
||||
|
||||
return STATUS_ENDSTREAM if $eof;
|
||||
return STATUS_OK ;
|
||||
}
|
||||
|
||||
sub reset
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
$self->{CompSize}->reset();
|
||||
$self->{UnCompSize} = 0;
|
||||
$self->{CRC32} = Compress::Raw::Zlib::crc32('');
|
||||
$self->{ADLER32} = Compress::Raw::Zlib::adler32('');
|
||||
|
||||
return STATUS_OK ;
|
||||
}
|
||||
|
||||
#sub count
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# return $self->{UnCompSize} ;
|
||||
#}
|
||||
|
||||
sub compressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
return $self->{CompSize} ;
|
||||
}
|
||||
|
||||
sub uncompressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
return $self->{CompSize} ;
|
||||
}
|
||||
|
||||
sub sync
|
||||
{
|
||||
return STATUS_OK ;
|
||||
}
|
||||
|
||||
sub crc32
|
||||
{
|
||||
my $self = shift ;
|
||||
return $self->{CRC32};
|
||||
}
|
||||
|
||||
sub adler32
|
||||
{
|
||||
my $self = shift ;
|
||||
return $self->{ADLER32};
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
156
database/perl/lib/IO/Uncompress/Adapter/Inflate.pm
Normal file
156
database/perl/lib/IO/Uncompress/Adapter/Inflate.pm
Normal file
@@ -0,0 +1,156 @@
|
||||
package IO::Uncompress::Adapter::Inflate;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Status);
|
||||
use Compress::Raw::Zlib 2.100 qw(Z_OK Z_BUF_ERROR Z_STREAM_END Z_FINISH MAX_WBITS);
|
||||
|
||||
our ($VERSION);
|
||||
$VERSION = '2.100';
|
||||
|
||||
|
||||
|
||||
sub mkUncompObject
|
||||
{
|
||||
my $crc32 = shift || 1;
|
||||
my $adler32 = shift || 1;
|
||||
my $scan = shift || 0;
|
||||
|
||||
my $inflate ;
|
||||
my $status ;
|
||||
|
||||
if ($scan)
|
||||
{
|
||||
($inflate, $status) = Compress::Raw::Zlib::InflateScan->new(
|
||||
#LimitOutput => 1,
|
||||
CRC32 => $crc32,
|
||||
ADLER32 => $adler32,
|
||||
WindowBits => - MAX_WBITS );
|
||||
}
|
||||
else
|
||||
{
|
||||
($inflate, $status) = Compress::Raw::Zlib::Inflate->new(
|
||||
AppendOutput => 1,
|
||||
LimitOutput => 1,
|
||||
CRC32 => $crc32,
|
||||
ADLER32 => $adler32,
|
||||
WindowBits => - MAX_WBITS );
|
||||
}
|
||||
|
||||
return (undef, "Could not create Inflation object: $status", $status)
|
||||
if $status != Z_OK ;
|
||||
|
||||
return bless {'Inf' => $inflate,
|
||||
'CompSize' => 0,
|
||||
'UnCompSize' => 0,
|
||||
'Error' => '',
|
||||
'ConsumesInput' => 1,
|
||||
} ;
|
||||
|
||||
}
|
||||
|
||||
sub uncompr
|
||||
{
|
||||
my $self = shift ;
|
||||
my $from = shift ;
|
||||
my $to = shift ;
|
||||
my $eof = shift ;
|
||||
|
||||
my $inf = $self->{Inf};
|
||||
|
||||
my $status = $inf->inflate($from, $to, $eof);
|
||||
$self->{ErrorNo} = $status;
|
||||
if ($status != Z_OK && $status != Z_STREAM_END && $status != Z_BUF_ERROR)
|
||||
{
|
||||
$self->{Error} = "Inflation Error: $status";
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
return STATUS_OK if $status == Z_BUF_ERROR ; # ???
|
||||
return STATUS_OK if $status == Z_OK ;
|
||||
return STATUS_ENDSTREAM if $status == Z_STREAM_END ;
|
||||
return STATUS_ERROR ;
|
||||
}
|
||||
|
||||
sub reset
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->inflateReset();
|
||||
|
||||
return STATUS_OK ;
|
||||
}
|
||||
|
||||
#sub count
|
||||
#{
|
||||
# my $self = shift ;
|
||||
# $self->{Inf}->inflateCount();
|
||||
#}
|
||||
|
||||
sub crc32
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->crc32();
|
||||
}
|
||||
|
||||
sub compressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->compressedBytes();
|
||||
}
|
||||
|
||||
sub uncompressedBytes
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->uncompressedBytes();
|
||||
}
|
||||
|
||||
sub adler32
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->adler32();
|
||||
}
|
||||
|
||||
sub sync
|
||||
{
|
||||
my $self = shift ;
|
||||
( $self->{Inf}->inflateSync(@_) == Z_OK)
|
||||
? STATUS_OK
|
||||
: STATUS_ERROR ;
|
||||
}
|
||||
|
||||
|
||||
sub getLastBlockOffset
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->getLastBlockOffset();
|
||||
}
|
||||
|
||||
sub getEndOffset
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->getEndOffset();
|
||||
}
|
||||
|
||||
sub resetLastBlockByte
|
||||
{
|
||||
my $self = shift ;
|
||||
$self->{Inf}->resetLastBlockByte(@_);
|
||||
}
|
||||
|
||||
sub createDeflateStream
|
||||
{
|
||||
my $self = shift ;
|
||||
my $deflate = $self->{Inf}->createDeflateStream(@_);
|
||||
return bless {'Def' => $deflate,
|
||||
'CompSize' => 0,
|
||||
'UnCompSize' => 0,
|
||||
'Error' => '',
|
||||
}, 'IO::Compress::Adapter::Deflate';
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
__END__
|
||||
1004
database/perl/lib/IO/Uncompress/AnyInflate.pm
Normal file
1004
database/perl/lib/IO/Uncompress/AnyInflate.pm
Normal file
File diff suppressed because it is too large
Load Diff
1083
database/perl/lib/IO/Uncompress/AnyUncompress.pm
Normal file
1083
database/perl/lib/IO/Uncompress/AnyUncompress.pm
Normal file
File diff suppressed because it is too large
Load Diff
1568
database/perl/lib/IO/Uncompress/Base.pm
Normal file
1568
database/perl/lib/IO/Uncompress/Base.pm
Normal file
File diff suppressed because it is too large
Load Diff
913
database/perl/lib/IO/Uncompress/Bunzip2.pm
Normal file
913
database/perl/lib/IO/Uncompress/Bunzip2.pm
Normal file
@@ -0,0 +1,913 @@
|
||||
package IO::Uncompress::Bunzip2 ;
|
||||
|
||||
use strict ;
|
||||
use warnings;
|
||||
use bytes;
|
||||
|
||||
use IO::Compress::Base::Common 2.100 qw(:Status );
|
||||
|
||||
use IO::Uncompress::Base 2.100 ;
|
||||
use IO::Uncompress::Adapter::Bunzip2 2.100 ;
|
||||
|
||||
require Exporter ;
|
||||
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $Bunzip2Error);
|
||||
|
||||
$VERSION = '2.100';
|
||||
$Bunzip2Error = '';
|
||||
|
||||
@ISA = qw(IO::Uncompress::Base Exporter);
|
||||
@EXPORT_OK = qw( $Bunzip2Error bunzip2 ) ;
|
||||
#%EXPORT_TAGS = %IO::Uncompress::Base::EXPORT_TAGS ;
|
||||
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
|
||||
#Exporter::export_ok_tags('all');
|
||||
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift ;
|
||||
my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$Bunzip2Error);
|
||||
|
||||
$obj->_create(undef, 0, @_);
|
||||
}
|
||||
|
||||
sub bunzip2
|
||||
{
|
||||
my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$Bunzip2Error);
|
||||
return $obj->_inf(@_);
|
||||
}
|
||||
|
||||
sub getExtraParams
|
||||
{
|
||||
return (
|
||||
'verbosity' => [IO::Compress::Base::Common::Parse_boolean, 0],
|
||||
'small' => [IO::Compress::Base::Common::Parse_boolean, 0],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
sub ckParams
|
||||
{
|
||||
my $self = shift ;
|
||||
my $got = shift ;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub mkUncomp
|
||||
{
|
||||
my $self = shift ;
|
||||
my $got = shift ;
|
||||
|
||||
my $magic = $self->ckMagic()
|
||||
or return 0;
|
||||
|
||||
*$self->{Info} = $self->readHeader($magic)
|
||||
or return undef ;
|
||||
|
||||
my $Small = $got->getValue('small');
|
||||
my $Verbosity = $got->getValue('verbosity');
|
||||
|
||||
my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::Bunzip2::mkUncompObject(
|
||||
$Small, $Verbosity);
|
||||
|
||||
return $self->saveErrorString(undef, $errstr, $errno)
|
||||
if ! defined $obj;
|
||||
|
||||
*$self->{Uncomp} = $obj;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub ckMagic
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
my $magic ;
|
||||
$self->smartReadExact(\$magic, 4);
|
||||
|
||||
*$self->{HeaderPending} = $magic ;
|
||||
|
||||
return $self->HeaderError("Header size is " .
|
||||
4 . " bytes")
|
||||
if length $magic != 4;
|
||||
|
||||
return $self->HeaderError("Bad Magic.")
|
||||
if ! isBzip2Magic($magic) ;
|
||||
|
||||
|
||||
*$self->{Type} = 'bzip2';
|
||||
return $magic;
|
||||
}
|
||||
|
||||
sub readHeader
|
||||
{
|
||||
my $self = shift;
|
||||
my $magic = shift ;
|
||||
|
||||
$self->pushBack($magic);
|
||||
*$self->{HeaderPending} = '';
|
||||
|
||||
|
||||
return {
|
||||
'Type' => 'bzip2',
|
||||
'FingerprintLength' => 4,
|
||||
'HeaderLength' => 4,
|
||||
'TrailerLength' => 0,
|
||||
'Header' => '$magic'
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
sub chkTrailer
|
||||
{
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sub isBzip2Magic
|
||||
{
|
||||
my $buffer = shift ;
|
||||
return $buffer =~ /^BZh\d$/;
|
||||
}
|
||||
|
||||
1 ;
|
||||
|
||||
__END__
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Uncompress::Bunzip2 - Read bzip2 files/buffers
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
|
||||
|
||||
my $status = bunzip2 $input => $output [,OPTS]
|
||||
or die "bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
my $z = IO::Uncompress::Bunzip2->new( $input [OPTS] )
|
||||
or die "bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
$status = $z->read($buffer)
|
||||
$status = $z->read($buffer, $length)
|
||||
$status = $z->read($buffer, $length, $offset)
|
||||
$line = $z->getline()
|
||||
$char = $z->getc()
|
||||
$char = $z->ungetc()
|
||||
$char = $z->opened()
|
||||
|
||||
$data = $z->trailingData()
|
||||
$status = $z->nextStream()
|
||||
$data = $z->getHeaderInfo()
|
||||
$z->tell()
|
||||
$z->seek($position, $whence)
|
||||
$z->binmode()
|
||||
$z->fileno()
|
||||
$z->eof()
|
||||
$z->close()
|
||||
|
||||
$Bunzip2Error ;
|
||||
|
||||
# IO::File mode
|
||||
|
||||
<$z>
|
||||
read($z, $buffer);
|
||||
read($z, $buffer, $length);
|
||||
read($z, $buffer, $length, $offset);
|
||||
tell($z)
|
||||
seek($z, $position, $whence)
|
||||
binmode($z)
|
||||
fileno($z)
|
||||
eof($z)
|
||||
close($z)
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module provides a Perl interface that allows the reading of
|
||||
bzip2 files/buffers.
|
||||
|
||||
For writing bzip2 files/buffers, see the companion module IO::Compress::Bzip2.
|
||||
|
||||
=head1 Functional Interface
|
||||
|
||||
A top-level function, C<bunzip2>, is provided to carry out
|
||||
"one-shot" uncompression between buffers and/or files. For finer
|
||||
control over the uncompression process, see the L</"OO Interface">
|
||||
section.
|
||||
|
||||
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
|
||||
|
||||
bunzip2 $input_filename_or_reference => $output_filename_or_reference [,OPTS]
|
||||
or die "bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
The functional interface needs Perl5.005 or better.
|
||||
|
||||
=head2 bunzip2 $input_filename_or_reference => $output_filename_or_reference [, OPTS]
|
||||
|
||||
C<bunzip2> expects at least two parameters,
|
||||
C<$input_filename_or_reference> and C<$output_filename_or_reference>
|
||||
and zero or more optional parameters (see L</Optional Parameters>)
|
||||
|
||||
=head3 The C<$input_filename_or_reference> parameter
|
||||
|
||||
The parameter, C<$input_filename_or_reference>, is used to define the
|
||||
source of the compressed data.
|
||||
|
||||
It can take one of the following forms:
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is a simple scalar, it is
|
||||
assumed to be a filename. This file will be opened for reading and the
|
||||
input data will be read from it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is a filehandle, the input
|
||||
data will be read from it. The string '-' can be used as an alias for
|
||||
standard input.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$input_filename_or_reference> is a scalar reference, the input data
|
||||
will be read from C<$$input_filename_or_reference>.
|
||||
|
||||
=item An array reference
|
||||
|
||||
If C<$input_filename_or_reference> is an array reference, each element in
|
||||
the array must be a filename.
|
||||
|
||||
The input data will be read from each file in turn.
|
||||
|
||||
The complete array will be walked to ensure that it only
|
||||
contains valid filenames before any data is uncompressed.
|
||||
|
||||
=item An Input FileGlob string
|
||||
|
||||
If C<$input_filename_or_reference> is a string that is delimited by the
|
||||
characters "<" and ">" C<bunzip2> will assume that it is an
|
||||
I<input fileglob string>. The input is the list of files that match the
|
||||
fileglob.
|
||||
|
||||
See L<File::GlobMapper|File::GlobMapper> for more details.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$input_filename_or_reference> parameter is any other type,
|
||||
C<undef> will be returned.
|
||||
|
||||
=head3 The C<$output_filename_or_reference> parameter
|
||||
|
||||
The parameter C<$output_filename_or_reference> is used to control the
|
||||
destination of the uncompressed data. This parameter can take one of
|
||||
these forms.
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is a simple scalar, it is
|
||||
assumed to be a filename. This file will be opened for writing and the
|
||||
uncompressed data will be written to it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is a filehandle, the
|
||||
uncompressed data will be written to it. The string '-' can be used as
|
||||
an alias for standard output.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$output_filename_or_reference> is a scalar reference, the
|
||||
uncompressed data will be stored in C<$$output_filename_or_reference>.
|
||||
|
||||
=item An Array Reference
|
||||
|
||||
If C<$output_filename_or_reference> is an array reference,
|
||||
the uncompressed data will be pushed onto the array.
|
||||
|
||||
=item An Output FileGlob
|
||||
|
||||
If C<$output_filename_or_reference> is a string that is delimited by the
|
||||
characters "<" and ">" C<bunzip2> will assume that it is an
|
||||
I<output fileglob string>. The output is the list of files that match the
|
||||
fileglob.
|
||||
|
||||
When C<$output_filename_or_reference> is an fileglob string,
|
||||
C<$input_filename_or_reference> must also be a fileglob string. Anything
|
||||
else is an error.
|
||||
|
||||
See L<File::GlobMapper|File::GlobMapper> for more details.
|
||||
|
||||
=back
|
||||
|
||||
If the C<$output_filename_or_reference> parameter is any other type,
|
||||
C<undef> will be returned.
|
||||
|
||||
=head2 Notes
|
||||
|
||||
When C<$input_filename_or_reference> maps to multiple compressed
|
||||
files/buffers and C<$output_filename_or_reference> is
|
||||
a single file/buffer, after uncompression C<$output_filename_or_reference> will contain a
|
||||
concatenation of all the uncompressed data from each of the input
|
||||
files/buffers.
|
||||
|
||||
=head2 Optional Parameters
|
||||
|
||||
The optional parameters for the one-shot function C<bunzip2>
|
||||
are (for the most part) identical to those used with the OO interface defined in the
|
||||
L</"Constructor Options"> section. The exceptions are listed below
|
||||
|
||||
=over 5
|
||||
|
||||
=item C<< AutoClose => 0|1 >>
|
||||
|
||||
This option applies to any input or output data streams to
|
||||
C<bunzip2> that are filehandles.
|
||||
|
||||
If C<AutoClose> is specified, and the value is true, it will result in all
|
||||
input and/or output filehandles being closed once C<bunzip2> has
|
||||
completed.
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< BinModeOut => 0|1 >>
|
||||
|
||||
This option is now a no-op. All files will be written in binmode.
|
||||
|
||||
=item C<< Append => 0|1 >>
|
||||
|
||||
The behaviour of this option is dependent on the type of output data
|
||||
stream.
|
||||
|
||||
=over 5
|
||||
|
||||
=item * A Buffer
|
||||
|
||||
If C<Append> is enabled, all uncompressed data will be append to the end of
|
||||
the output buffer. Otherwise the output buffer will be cleared before any
|
||||
uncompressed data is written to it.
|
||||
|
||||
=item * A Filename
|
||||
|
||||
If C<Append> is enabled, the file will be opened in append mode. Otherwise
|
||||
the contents of the file, if any, will be truncated before any uncompressed
|
||||
data is written to it.
|
||||
|
||||
=item * A Filehandle
|
||||
|
||||
If C<Append> is enabled, the filehandle will be positioned to the end of
|
||||
the file via a call to C<seek> before any uncompressed data is
|
||||
written to it. Otherwise the file pointer will not be moved.
|
||||
|
||||
=back
|
||||
|
||||
When C<Append> is specified, and set to true, it will I<append> all uncompressed
|
||||
data to the output data stream.
|
||||
|
||||
So when the output is a filehandle it will carry out a seek to the eof
|
||||
before writing any uncompressed data. If the output is a filename, it will be opened for
|
||||
appending. If the output is a buffer, all uncompressed data will be
|
||||
appended to the existing buffer.
|
||||
|
||||
Conversely when C<Append> is not specified, or it is present and is set to
|
||||
false, it will operate as follows.
|
||||
|
||||
When the output is a filename, it will truncate the contents of the file
|
||||
before writing any uncompressed data. If the output is a filehandle
|
||||
its position will not be changed. If the output is a buffer, it will be
|
||||
wiped before any uncompressed data is output.
|
||||
|
||||
Defaults to 0.
|
||||
|
||||
=item C<< MultiStream => 0|1 >>
|
||||
|
||||
If the input file/buffer contains multiple compressed data streams, this
|
||||
option will uncompress the whole lot as a single data stream.
|
||||
|
||||
Defaults to 0.
|
||||
|
||||
=item C<< TrailingData => $scalar >>
|
||||
|
||||
Returns the data, if any, that is present immediately after the compressed
|
||||
data stream once uncompression is complete.
|
||||
|
||||
This option can be used when there is useful information immediately
|
||||
following the compressed data stream, and you don't know the length of the
|
||||
compressed data stream.
|
||||
|
||||
If the input is a buffer, C<trailingData> will return everything from the
|
||||
end of the compressed data stream to the end of the buffer.
|
||||
|
||||
If the input is a filehandle, C<trailingData> will return the data that is
|
||||
left in the filehandle input buffer once the end of the compressed data
|
||||
stream has been reached. You can then use the filehandle to read the rest
|
||||
of the input file.
|
||||
|
||||
Don't bother using C<trailingData> if the input is a filename.
|
||||
|
||||
If you know the length of the compressed data stream before you start
|
||||
uncompressing, you can avoid having to use C<trailingData> by setting the
|
||||
C<InputLength> option.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Examples
|
||||
|
||||
To read the contents of the file C<file1.txt.bz2> and write the
|
||||
uncompressed data to the file C<file1.txt>.
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
|
||||
|
||||
my $input = "file1.txt.bz2";
|
||||
my $output = "file1.txt";
|
||||
bunzip2 $input => $output
|
||||
or die "bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
To read from an existing Perl filehandle, C<$input>, and write the
|
||||
uncompressed data to a buffer, C<$buffer>.
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
|
||||
use IO::File ;
|
||||
|
||||
my $input = IO::File->new( "<file1.txt.bz2" )
|
||||
or die "Cannot open 'file1.txt.bz2': $!\n" ;
|
||||
my $buffer ;
|
||||
bunzip2 $input => \$buffer
|
||||
or die "bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
To uncompress all files in the directory "/my/home" that match "*.txt.bz2" and store the compressed data in the same directory
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
|
||||
|
||||
bunzip2 '</my/home/*.txt.bz2>' => '</my/home/#1.txt>'
|
||||
or die "bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
and if you want to compress each file one at a time, this will do the trick
|
||||
|
||||
use strict ;
|
||||
use warnings ;
|
||||
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
|
||||
|
||||
for my $input ( glob "/my/home/*.txt.bz2" )
|
||||
{
|
||||
my $output = $input;
|
||||
$output =~ s/.bz2// ;
|
||||
bunzip2 $input => $output
|
||||
or die "Error compressing '$input': $Bunzip2Error\n";
|
||||
}
|
||||
|
||||
=head1 OO Interface
|
||||
|
||||
=head2 Constructor
|
||||
|
||||
The format of the constructor for IO::Uncompress::Bunzip2 is shown below
|
||||
|
||||
my $z = IO::Uncompress::Bunzip2->new( $input [OPTS] )
|
||||
or die "IO::Uncompress::Bunzip2 failed: $Bunzip2Error\n";
|
||||
|
||||
Returns an C<IO::Uncompress::Bunzip2> object on success and undef on failure.
|
||||
The variable C<$Bunzip2Error> will contain an error message on failure.
|
||||
|
||||
If you are running Perl 5.005 or better the object, C<$z>, returned from
|
||||
IO::Uncompress::Bunzip2 can be used exactly like an L<IO::File|IO::File> filehandle.
|
||||
This means that all normal input file operations can be carried out with
|
||||
C<$z>. For example, to read a line from a compressed file/buffer you can
|
||||
use either of these forms
|
||||
|
||||
$line = $z->getline();
|
||||
$line = <$z>;
|
||||
|
||||
The mandatory parameter C<$input> is used to determine the source of the
|
||||
compressed data. This parameter can take one of three forms.
|
||||
|
||||
=over 5
|
||||
|
||||
=item A filename
|
||||
|
||||
If the C<$input> parameter is a scalar, it is assumed to be a filename. This
|
||||
file will be opened for reading and the compressed data will be read from it.
|
||||
|
||||
=item A filehandle
|
||||
|
||||
If the C<$input> parameter is a filehandle, the compressed data will be
|
||||
read from it.
|
||||
The string '-' can be used as an alias for standard input.
|
||||
|
||||
=item A scalar reference
|
||||
|
||||
If C<$input> is a scalar reference, the compressed data will be read from
|
||||
C<$$input>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Constructor Options
|
||||
|
||||
The option names defined below are case insensitive and can be optionally
|
||||
prefixed by a '-'. So all of the following are valid
|
||||
|
||||
-AutoClose
|
||||
-autoclose
|
||||
AUTOCLOSE
|
||||
autoclose
|
||||
|
||||
OPTS is a combination of the following options:
|
||||
|
||||
=over 5
|
||||
|
||||
=item C<< AutoClose => 0|1 >>
|
||||
|
||||
This option is only valid when the C<$input> parameter is a filehandle. If
|
||||
specified, and the value is true, it will result in the file being closed once
|
||||
either the C<close> method is called or the IO::Uncompress::Bunzip2 object is
|
||||
destroyed.
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< MultiStream => 0|1 >>
|
||||
|
||||
Allows multiple concatenated compressed streams to be treated as a single
|
||||
compressed stream. Decompression will stop once either the end of the
|
||||
file/buffer is reached, an error is encountered (premature eof, corrupt
|
||||
compressed data) or the end of a stream is not immediately followed by the
|
||||
start of another stream.
|
||||
|
||||
This parameter defaults to 0.
|
||||
|
||||
=item C<< Prime => $string >>
|
||||
|
||||
This option will uncompress the contents of C<$string> before processing the
|
||||
input file/buffer.
|
||||
|
||||
This option can be useful when the compressed data is embedded in another
|
||||
file/data structure and it is not possible to work out where the compressed
|
||||
data begins without having to read the first few bytes. If this is the
|
||||
case, the uncompression can be I<primed> with these bytes using this
|
||||
option.
|
||||
|
||||
=item C<< Transparent => 0|1 >>
|
||||
|
||||
If this option is set and the input file/buffer is not compressed data,
|
||||
the module will allow reading of it anyway.
|
||||
|
||||
In addition, if the input file/buffer does contain compressed data and
|
||||
there is non-compressed data immediately following it, setting this option
|
||||
will make this module treat the whole file/buffer as a single data stream.
|
||||
|
||||
This option defaults to 1.
|
||||
|
||||
=item C<< BlockSize => $num >>
|
||||
|
||||
When reading the compressed input data, IO::Uncompress::Bunzip2 will read it in
|
||||
blocks of C<$num> bytes.
|
||||
|
||||
This option defaults to 4096.
|
||||
|
||||
=item C<< InputLength => $size >>
|
||||
|
||||
When present this option will limit the number of compressed bytes read
|
||||
from the input file/buffer to C<$size>. This option can be used in the
|
||||
situation where there is useful data directly after the compressed data
|
||||
stream and you know beforehand the exact length of the compressed data
|
||||
stream.
|
||||
|
||||
This option is mostly used when reading from a filehandle, in which case
|
||||
the file pointer will be left pointing to the first byte directly after the
|
||||
compressed data stream.
|
||||
|
||||
This option defaults to off.
|
||||
|
||||
=item C<< Append => 0|1 >>
|
||||
|
||||
This option controls what the C<read> method does with uncompressed data.
|
||||
|
||||
If set to 1, all uncompressed data will be appended to the output parameter
|
||||
of the C<read> method.
|
||||
|
||||
If set to 0, the contents of the output parameter of the C<read> method
|
||||
will be overwritten by the uncompressed data.
|
||||
|
||||
Defaults to 0.
|
||||
|
||||
=item C<< Strict => 0|1 >>
|
||||
|
||||
This option is a no-op.
|
||||
|
||||
=item C<< Small => 0|1 >>
|
||||
|
||||
When non-zero this options will make bzip2 use a decompression algorithm
|
||||
that uses less memory at the expense of increasing the amount of time
|
||||
taken for decompression.
|
||||
|
||||
Default is 0.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Examples
|
||||
|
||||
TODO
|
||||
|
||||
=head1 Methods
|
||||
|
||||
=head2 read
|
||||
|
||||
Usage is
|
||||
|
||||
$status = $z->read($buffer)
|
||||
|
||||
Reads a block of compressed data (the size of the compressed block is
|
||||
determined by the C<Buffer> option in the constructor), uncompresses it and
|
||||
writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
|
||||
set in the constructor, the uncompressed data will be appended to the
|
||||
C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
|
||||
|
||||
Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
|
||||
or a negative number on error.
|
||||
|
||||
=head2 read
|
||||
|
||||
Usage is
|
||||
|
||||
$status = $z->read($buffer, $length)
|
||||
$status = $z->read($buffer, $length, $offset)
|
||||
|
||||
$status = read($z, $buffer, $length)
|
||||
$status = read($z, $buffer, $length, $offset)
|
||||
|
||||
Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
|
||||
|
||||
The main difference between this form of the C<read> method and the
|
||||
previous one, is that this one will attempt to return I<exactly> C<$length>
|
||||
bytes. The only circumstances that this function will not is if end-of-file
|
||||
or an IO error is encountered.
|
||||
|
||||
Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
|
||||
or a negative number on error.
|
||||
|
||||
=head2 getline
|
||||
|
||||
Usage is
|
||||
|
||||
$line = $z->getline()
|
||||
$line = <$z>
|
||||
|
||||
Reads a single line.
|
||||
|
||||
This method fully supports the use of the variable C<$/> (or
|
||||
C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
|
||||
determine what constitutes an end of line. Paragraph mode, record mode and
|
||||
file slurp mode are all supported.
|
||||
|
||||
=head2 getc
|
||||
|
||||
Usage is
|
||||
|
||||
$char = $z->getc()
|
||||
|
||||
Read a single character.
|
||||
|
||||
=head2 ungetc
|
||||
|
||||
Usage is
|
||||
|
||||
$char = $z->ungetc($string)
|
||||
|
||||
=head2 getHeaderInfo
|
||||
|
||||
Usage is
|
||||
|
||||
$hdr = $z->getHeaderInfo();
|
||||
@hdrs = $z->getHeaderInfo();
|
||||
|
||||
This method returns either a hash reference (in scalar context) or a list
|
||||
or hash references (in array context) that contains information about each
|
||||
of the header fields in the compressed data stream(s).
|
||||
|
||||
=head2 tell
|
||||
|
||||
Usage is
|
||||
|
||||
$z->tell()
|
||||
tell $z
|
||||
|
||||
Returns the uncompressed file offset.
|
||||
|
||||
=head2 eof
|
||||
|
||||
Usage is
|
||||
|
||||
$z->eof();
|
||||
eof($z);
|
||||
|
||||
Returns true if the end of the compressed input stream has been reached.
|
||||
|
||||
=head2 seek
|
||||
|
||||
$z->seek($position, $whence);
|
||||
seek($z, $position, $whence);
|
||||
|
||||
Provides a sub-set of the C<seek> functionality, with the restriction
|
||||
that it is only legal to seek forward in the input file/buffer.
|
||||
It is a fatal error to attempt to seek backward.
|
||||
|
||||
Note that the implementation of C<seek> in this module does not provide
|
||||
true random access to a compressed file/buffer. It works by uncompressing
|
||||
data from the current offset in the file/buffer until it reaches the
|
||||
uncompressed offset specified in the parameters to C<seek>. For very small
|
||||
files this may be acceptable behaviour. For large files it may cause an
|
||||
unacceptable delay.
|
||||
|
||||
The C<$whence> parameter takes one the usual values, namely SEEK_SET,
|
||||
SEEK_CUR or SEEK_END.
|
||||
|
||||
Returns 1 on success, 0 on failure.
|
||||
|
||||
=head2 binmode
|
||||
|
||||
Usage is
|
||||
|
||||
$z->binmode
|
||||
binmode $z ;
|
||||
|
||||
This is a noop provided for completeness.
|
||||
|
||||
=head2 opened
|
||||
|
||||
$z->opened()
|
||||
|
||||
Returns true if the object currently refers to a opened file/buffer.
|
||||
|
||||
=head2 autoflush
|
||||
|
||||
my $prev = $z->autoflush()
|
||||
my $prev = $z->autoflush(EXPR)
|
||||
|
||||
If the C<$z> object is associated with a file or a filehandle, this method
|
||||
returns the current autoflush setting for the underlying filehandle. If
|
||||
C<EXPR> is present, and is non-zero, it will enable flushing after every
|
||||
write/print operation.
|
||||
|
||||
If C<$z> is associated with a buffer, this method has no effect and always
|
||||
returns C<undef>.
|
||||
|
||||
B<Note> that the special variable C<$|> B<cannot> be used to set or
|
||||
retrieve the autoflush setting.
|
||||
|
||||
=head2 input_line_number
|
||||
|
||||
$z->input_line_number()
|
||||
$z->input_line_number(EXPR)
|
||||
|
||||
Returns the current uncompressed line number. If C<EXPR> is present it has
|
||||
the effect of setting the line number. Note that setting the line number
|
||||
does not change the current position within the file/buffer being read.
|
||||
|
||||
The contents of C<$/> are used to determine what constitutes a line
|
||||
terminator.
|
||||
|
||||
=head2 fileno
|
||||
|
||||
$z->fileno()
|
||||
fileno($z)
|
||||
|
||||
If the C<$z> object is associated with a file or a filehandle, C<fileno>
|
||||
will return the underlying file descriptor. Once the C<close> method is
|
||||
called C<fileno> will return C<undef>.
|
||||
|
||||
If the C<$z> object is associated with a buffer, this method will return
|
||||
C<undef>.
|
||||
|
||||
=head2 close
|
||||
|
||||
$z->close() ;
|
||||
close $z ;
|
||||
|
||||
Closes the output file/buffer.
|
||||
|
||||
For most versions of Perl this method will be automatically invoked if
|
||||
the IO::Uncompress::Bunzip2 object is destroyed (either explicitly or by the
|
||||
variable with the reference to the object going out of scope). The
|
||||
exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
|
||||
these cases, the C<close> method will be called automatically, but
|
||||
not until global destruction of all live objects when the program is
|
||||
terminating.
|
||||
|
||||
Therefore, if you want your scripts to be able to run on all versions
|
||||
of Perl, you should call C<close> explicitly and not rely on automatic
|
||||
closing.
|
||||
|
||||
Returns true on success, otherwise 0.
|
||||
|
||||
If the C<AutoClose> option has been enabled when the IO::Uncompress::Bunzip2
|
||||
object was created, and the object is associated with a file, the
|
||||
underlying file will also be closed.
|
||||
|
||||
=head2 nextStream
|
||||
|
||||
Usage is
|
||||
|
||||
my $status = $z->nextStream();
|
||||
|
||||
Skips to the next compressed data stream in the input file/buffer. If a new
|
||||
compressed data stream is found, the eof marker will be cleared and C<$.>
|
||||
will be reset to 0.
|
||||
|
||||
Returns 1 if a new stream was found, 0 if none was found, and -1 if an
|
||||
error was encountered.
|
||||
|
||||
=head2 trailingData
|
||||
|
||||
Usage is
|
||||
|
||||
my $data = $z->trailingData();
|
||||
|
||||
Returns the data, if any, that is present immediately after the compressed
|
||||
data stream once uncompression is complete. It only makes sense to call
|
||||
this method once the end of the compressed data stream has been
|
||||
encountered.
|
||||
|
||||
This option can be used when there is useful information immediately
|
||||
following the compressed data stream, and you don't know the length of the
|
||||
compressed data stream.
|
||||
|
||||
If the input is a buffer, C<trailingData> will return everything from the
|
||||
end of the compressed data stream to the end of the buffer.
|
||||
|
||||
If the input is a filehandle, C<trailingData> will return the data that is
|
||||
left in the filehandle input buffer once the end of the compressed data
|
||||
stream has been reached. You can then use the filehandle to read the rest
|
||||
of the input file.
|
||||
|
||||
Don't bother using C<trailingData> if the input is a filename.
|
||||
|
||||
If you know the length of the compressed data stream before you start
|
||||
uncompressing, you can avoid having to use C<trailingData> by setting the
|
||||
C<InputLength> option in the constructor.
|
||||
|
||||
=head1 Importing
|
||||
|
||||
No symbolic constants are required by IO::Uncompress::Bunzip2 at present.
|
||||
|
||||
=over 5
|
||||
|
||||
=item :all
|
||||
|
||||
Imports C<bunzip2> and C<$Bunzip2Error>.
|
||||
Same as doing this
|
||||
|
||||
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
=head2 Working with Net::FTP
|
||||
|
||||
See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
|
||||
|
||||
=head1 SUPPORT
|
||||
|
||||
General feedback/questions/bug reports should be sent to
|
||||
L<https://github.com/pmqs/IO-Compress/issues> (preferred) or
|
||||
L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzip>, L<IO::Uncompress::UnLzip>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Compress::Zstd>, L<IO::Uncompress::UnZstd>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
|
||||
|
||||
L<IO::Compress::FAQ|IO::Compress::FAQ>
|
||||
|
||||
L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
|
||||
L<Archive::Tar|Archive::Tar>,
|
||||
L<IO::Zlib|IO::Zlib>
|
||||
|
||||
The primary site for the bzip2 program is L<https://sourceware.org/bzip2/>.
|
||||
|
||||
See the module L<Compress::Bzip2|Compress::Bzip2>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
This module was written by Paul Marquess, C<pmqs@cpan.org>.
|
||||
|
||||
=head1 MODIFICATION HISTORY
|
||||
|
||||
See the Changes file.
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (c) 2005-2021 Paul Marquess. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the same terms as Perl itself.
|
||||
1128
database/perl/lib/IO/Uncompress/Gunzip.pm
Normal file
1128
database/perl/lib/IO/Uncompress/Gunzip.pm
Normal file
File diff suppressed because it is too large
Load Diff
1000
database/perl/lib/IO/Uncompress/Inflate.pm
Normal file
1000
database/perl/lib/IO/Uncompress/Inflate.pm
Normal file
File diff suppressed because it is too large
Load Diff
1128
database/perl/lib/IO/Uncompress/RawInflate.pm
Normal file
1128
database/perl/lib/IO/Uncompress/RawInflate.pm
Normal file
File diff suppressed because it is too large
Load Diff
1971
database/perl/lib/IO/Uncompress/Unzip.pm
Normal file
1971
database/perl/lib/IO/Uncompress/Unzip.pm
Normal file
File diff suppressed because it is too large
Load Diff
740
database/perl/lib/IO/Zlib.pm
Normal file
740
database/perl/lib/IO/Zlib.pm
Normal file
@@ -0,0 +1,740 @@
|
||||
# IO::Zlib.pm
|
||||
#
|
||||
# Copyright (c) 1998-2004 Tom Hughes <tom@compton.nu>.
|
||||
# All rights reserved. This program is free software; you can redistribute
|
||||
# it and/or modify it under the same terms as Perl itself.
|
||||
|
||||
package IO::Zlib;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IO::Zlib - IO:: style interface to L<Compress::Zlib>
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
With any version of Perl 5 you can use the basic OO interface:
|
||||
|
||||
use IO::Zlib;
|
||||
|
||||
$fh = new IO::Zlib;
|
||||
if ($fh->open("file.gz", "rb")) {
|
||||
print <$fh>;
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
$fh = IO::Zlib->new("file.gz", "wb9");
|
||||
if (defined $fh) {
|
||||
print $fh "bar\n";
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
$fh = IO::Zlib->new("file.gz", "rb");
|
||||
if (defined $fh) {
|
||||
print <$fh>;
|
||||
undef $fh; # automatically closes the file
|
||||
}
|
||||
|
||||
With Perl 5.004 you can also use the TIEHANDLE interface to access
|
||||
compressed files just like ordinary files:
|
||||
|
||||
use IO::Zlib;
|
||||
|
||||
tie *FILE, 'IO::Zlib', "file.gz", "wb";
|
||||
print FILE "line 1\nline2\n";
|
||||
|
||||
tie *FILE, 'IO::Zlib', "file.gz", "rb";
|
||||
while (<FILE>) { print "LINE: ", $_ };
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<IO::Zlib> provides an IO:: style interface to L<Compress::Zlib> and
|
||||
hence to gzip/zlib compressed files. It provides many of the same methods
|
||||
as the L<IO::Handle> interface.
|
||||
|
||||
Starting from IO::Zlib version 1.02, IO::Zlib can also use an
|
||||
external F<gzip> command. The default behaviour is to try to use
|
||||
an external F<gzip> if no C<Compress::Zlib> can be loaded, unless
|
||||
explicitly disabled by
|
||||
|
||||
use IO::Zlib qw(:gzip_external 0);
|
||||
|
||||
If explicitly enabled by
|
||||
|
||||
use IO::Zlib qw(:gzip_external 1);
|
||||
|
||||
then the external F<gzip> is used B<instead> of C<Compress::Zlib>.
|
||||
|
||||
=head1 CONSTRUCTOR
|
||||
|
||||
=over 4
|
||||
|
||||
=item new ( [ARGS] )
|
||||
|
||||
Creates an C<IO::Zlib> object. If it receives any parameters, they are
|
||||
passed to the method C<open>; if the open fails, the object is destroyed.
|
||||
Otherwise, it is returned to the caller.
|
||||
|
||||
=back
|
||||
|
||||
=head1 OBJECT METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item open ( FILENAME, MODE )
|
||||
|
||||
C<open> takes two arguments. The first is the name of the file to open
|
||||
and the second is the open mode. The mode can be anything acceptable to
|
||||
L<Compress::Zlib> and by extension anything acceptable to I<zlib> (that
|
||||
basically means POSIX fopen() style mode strings plus an optional number
|
||||
to indicate the compression level).
|
||||
|
||||
=item opened
|
||||
|
||||
Returns true if the object currently refers to a opened file.
|
||||
|
||||
=item close
|
||||
|
||||
Close the file associated with the object and disassociate
|
||||
the file from the handle.
|
||||
Done automatically on destroy.
|
||||
|
||||
=item getc
|
||||
|
||||
Return the next character from the file, or undef if none remain.
|
||||
|
||||
=item getline
|
||||
|
||||
Return the next line from the file, or undef on end of string.
|
||||
Can safely be called in an array context.
|
||||
Currently ignores $/ ($INPUT_RECORD_SEPARATOR or $RS when L<English>
|
||||
is in use) and treats lines as delimited by "\n".
|
||||
|
||||
=item getlines
|
||||
|
||||
Get all remaining lines from the file.
|
||||
It will croak() if accidentally called in a scalar context.
|
||||
|
||||
=item print ( ARGS... )
|
||||
|
||||
Print ARGS to the file.
|
||||
|
||||
=item read ( BUF, NBYTES, [OFFSET] )
|
||||
|
||||
Read some bytes from the file.
|
||||
Returns the number of bytes actually read, 0 on end-of-file, undef on error.
|
||||
|
||||
=item eof
|
||||
|
||||
Returns true if the handle is currently positioned at end of file?
|
||||
|
||||
=item seek ( OFFSET, WHENCE )
|
||||
|
||||
Seek to a given position in the stream.
|
||||
Not yet supported.
|
||||
|
||||
=item tell
|
||||
|
||||
Return the current position in the stream, as a numeric offset.
|
||||
Not yet supported.
|
||||
|
||||
=item setpos ( POS )
|
||||
|
||||
Set the current position, using the opaque value returned by C<getpos()>.
|
||||
Not yet supported.
|
||||
|
||||
=item getpos ( POS )
|
||||
|
||||
Return the current position in the string, as an opaque object.
|
||||
Not yet supported.
|
||||
|
||||
=back
|
||||
|
||||
=head1 USING THE EXTERNAL GZIP
|
||||
|
||||
If the external F<gzip> is used, the following C<open>s are used:
|
||||
|
||||
open(FH, "gzip -dc $filename |") # for read opens
|
||||
open(FH, " | gzip > $filename") # for write opens
|
||||
|
||||
You can modify the 'commands' for example to hardwire
|
||||
an absolute path by e.g.
|
||||
|
||||
use IO::Zlib ':gzip_read_open' => '/some/where/gunzip -c %s |';
|
||||
use IO::Zlib ':gzip_write_open' => '| /some/where/gzip.exe > %s';
|
||||
|
||||
The C<%s> is expanded to be the filename (C<sprintf> is used, so be
|
||||
careful to escape any other C<%> signs). The 'commands' are checked
|
||||
for sanity - they must contain the C<%s>, and the read open must end
|
||||
with the pipe sign, and the write open must begin with the pipe sign.
|
||||
|
||||
=head1 CLASS METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item has_Compress_Zlib
|
||||
|
||||
Returns true if C<Compress::Zlib> is available. Note that this does
|
||||
not mean that C<Compress::Zlib> is being used: see L</gzip_external>
|
||||
and L<gzip_used>.
|
||||
|
||||
=item gzip_external
|
||||
|
||||
Undef if an external F<gzip> B<can> be used if C<Compress::Zlib> is
|
||||
not available (see L</has_Compress_Zlib>), true if an external F<gzip>
|
||||
is explicitly used, false if an external F<gzip> must not be used.
|
||||
See L</gzip_used>.
|
||||
|
||||
=item gzip_used
|
||||
|
||||
True if an external F<gzip> is being used, false if not.
|
||||
|
||||
=item gzip_read_open
|
||||
|
||||
Return the 'command' being used for opening a file for reading using an
|
||||
external F<gzip>.
|
||||
|
||||
=item gzip_write_open
|
||||
|
||||
Return the 'command' being used for opening a file for writing using an
|
||||
external F<gzip>.
|
||||
|
||||
=back
|
||||
|
||||
=head1 DIAGNOSTICS
|
||||
|
||||
=over 4
|
||||
|
||||
=item IO::Zlib::getlines: must be called in list context
|
||||
|
||||
If you want read lines, you must read in list context.
|
||||
|
||||
=item IO::Zlib::gzopen_external: mode '...' is illegal
|
||||
|
||||
Use only modes 'rb' or 'wb' or /wb[1-9]/.
|
||||
|
||||
=item IO::Zlib::import: '...' is illegal
|
||||
|
||||
The known import symbols are the C<:gzip_external>, C<:gzip_read_open>,
|
||||
and C<:gzip_write_open>. Anything else is not recognized.
|
||||
|
||||
=item IO::Zlib::import: ':gzip_external' requires an argument
|
||||
|
||||
The C<:gzip_external> requires one boolean argument.
|
||||
|
||||
=item IO::Zlib::import: 'gzip_read_open' requires an argument
|
||||
|
||||
The C<:gzip_external> requires one string argument.
|
||||
|
||||
=item IO::Zlib::import: 'gzip_read' '...' is illegal
|
||||
|
||||
The C<:gzip_read_open> argument must end with the pipe sign (|)
|
||||
and have the C<%s> for the filename. See L</"USING THE EXTERNAL GZIP">.
|
||||
|
||||
=item IO::Zlib::import: 'gzip_write_open' requires an argument
|
||||
|
||||
The C<:gzip_external> requires one string argument.
|
||||
|
||||
=item IO::Zlib::import: 'gzip_write_open' '...' is illegal
|
||||
|
||||
The C<:gzip_write_open> argument must begin with the pipe sign (|)
|
||||
and have the C<%s> for the filename. An output redirect (>) is also
|
||||
often a good idea, depending on your operating system shell syntax.
|
||||
See L</"USING THE EXTERNAL GZIP">.
|
||||
|
||||
=item IO::Zlib::import: no Compress::Zlib and no external gzip
|
||||
|
||||
Given that we failed to load C<Compress::Zlib> and that the use of
|
||||
an external F<gzip> was disabled, IO::Zlib has not much chance of working.
|
||||
|
||||
=item IO::Zlib::open: needs a filename
|
||||
|
||||
No filename, no open.
|
||||
|
||||
=item IO::Zlib::READ: NBYTES must be specified
|
||||
|
||||
We must know how much to read.
|
||||
|
||||
=item IO::Zlib::WRITE: too long LENGTH
|
||||
|
||||
The LENGTH must be less than or equal to the buffer size.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<perlfunc>,
|
||||
L<perlop/"I/O Operators">,
|
||||
L<IO::Handle>,
|
||||
L<Compress::Zlib>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
Created by Tom Hughes E<lt>F<tom@compton.nu>E<gt>.
|
||||
|
||||
Support for external gzip added by Jarkko Hietaniemi E<lt>F<jhi@iki.fi>E<gt>.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 1998-2004 Tom Hughes E<lt>F<tom@compton.nu>E<gt>.
|
||||
All rights reserved. This program is free software; you can redistribute
|
||||
it and/or modify it under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
|
||||
require 5.006;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp;
|
||||
use Fcntl qw(SEEK_SET);
|
||||
use Symbol;
|
||||
use Tie::Handle;
|
||||
|
||||
our $VERSION = "1.11";
|
||||
our $AUTOLOAD;
|
||||
our @ISA = qw(Tie::Handle);
|
||||
|
||||
my $has_Compress_Zlib;
|
||||
my $gzip_external;
|
||||
my $gzip_used;
|
||||
my $gzip_read_open = "gzip -dc %s |";
|
||||
my $gzip_write_open = "| gzip > %s";
|
||||
my $aliased;
|
||||
|
||||
BEGIN {
|
||||
eval { require Compress::Zlib };
|
||||
$has_Compress_Zlib = $@ || $Compress::Zlib::VERSION < 2.000 ? 0 : 1;
|
||||
}
|
||||
|
||||
sub has_Compress_Zlib
|
||||
{
|
||||
$has_Compress_Zlib;
|
||||
}
|
||||
|
||||
sub gzip_external
|
||||
{
|
||||
$gzip_external;
|
||||
}
|
||||
|
||||
sub gzip_used
|
||||
{
|
||||
$gzip_used;
|
||||
}
|
||||
|
||||
sub gzip_read_open
|
||||
{
|
||||
$gzip_read_open;
|
||||
}
|
||||
|
||||
sub gzip_write_open
|
||||
{
|
||||
$gzip_write_open;
|
||||
}
|
||||
|
||||
sub can_gunzip
|
||||
{
|
||||
$has_Compress_Zlib || $gzip_external;
|
||||
}
|
||||
|
||||
sub _import
|
||||
{
|
||||
my $import = shift;
|
||||
|
||||
while (@_)
|
||||
{
|
||||
if ($_[0] eq ':gzip_external')
|
||||
{
|
||||
shift;
|
||||
|
||||
if (@_)
|
||||
{
|
||||
$gzip_external = shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
croak "$import: ':gzip_external' requires an argument";
|
||||
}
|
||||
}
|
||||
elsif ($_[0] eq ':gzip_read_open')
|
||||
{
|
||||
shift;
|
||||
|
||||
if (@_)
|
||||
{
|
||||
$gzip_read_open = shift;
|
||||
|
||||
croak "$import: ':gzip_read_open' '$gzip_read_open' is illegal"
|
||||
unless $gzip_read_open =~ /^.+%s.+\|\s*$/;
|
||||
}
|
||||
else
|
||||
{
|
||||
croak "$import: ':gzip_read_open' requires an argument";
|
||||
}
|
||||
}
|
||||
elsif ($_[0] eq ':gzip_write_open')
|
||||
{
|
||||
shift;
|
||||
|
||||
if (@_)
|
||||
{
|
||||
$gzip_write_open = shift;
|
||||
|
||||
croak "$import: ':gzip_write_open' '$gzip_read_open' is illegal"
|
||||
unless $gzip_write_open =~ /^\s*\|.+%s.*$/;
|
||||
}
|
||||
else
|
||||
{
|
||||
croak "$import: ':gzip_write_open' requires an argument";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return @_;
|
||||
}
|
||||
|
||||
sub _alias
|
||||
{
|
||||
my $import = shift;
|
||||
|
||||
if ($gzip_external || (!$has_Compress_Zlib && !defined($gzip_external)))
|
||||
{
|
||||
require IO::Handle;
|
||||
|
||||
undef *gzopen;
|
||||
*gzopen = \&gzopen_external;
|
||||
|
||||
*IO::Handle::gzread = \&gzread_external;
|
||||
*IO::Handle::gzwrite = \&gzwrite_external;
|
||||
*IO::Handle::gzreadline = \&gzreadline_external;
|
||||
*IO::Handle::gzeof = \&gzeof_external;
|
||||
*IO::Handle::gzclose = \&gzclose_external;
|
||||
|
||||
$gzip_used = 1;
|
||||
}
|
||||
elsif ($has_Compress_Zlib)
|
||||
{
|
||||
*gzopen = \&Compress::Zlib::gzopen;
|
||||
*gzread = \&Compress::Zlib::gzread;
|
||||
*gzwrite = \&Compress::Zlib::gzwrite;
|
||||
*gzreadline = \&Compress::Zlib::gzreadline;
|
||||
*gzeof = \&Compress::Zlib::gzeof;
|
||||
}
|
||||
else
|
||||
{
|
||||
croak "$import: no Compress::Zlib and no external gzip";
|
||||
}
|
||||
|
||||
$aliased = 1;
|
||||
}
|
||||
|
||||
sub import
|
||||
{
|
||||
my $class = shift;
|
||||
my $import = "IO::Zlib::import";
|
||||
|
||||
if (@_)
|
||||
{
|
||||
if (_import($import, @_))
|
||||
{
|
||||
croak "$import: '@_' is illegal";
|
||||
}
|
||||
}
|
||||
|
||||
_alias($import);
|
||||
}
|
||||
|
||||
sub TIEHANDLE
|
||||
{
|
||||
my $class = shift;
|
||||
my @args = @_;
|
||||
|
||||
my $self = bless {}, $class;
|
||||
|
||||
return @args ? $self->OPEN(@args) : $self;
|
||||
}
|
||||
|
||||
sub DESTROY
|
||||
{
|
||||
}
|
||||
|
||||
sub OPEN
|
||||
{
|
||||
my $self = shift;
|
||||
my $filename = shift;
|
||||
my $mode = shift;
|
||||
|
||||
croak "IO::Zlib::open: needs a filename" unless defined($filename);
|
||||
|
||||
$self->{'file'} = gzopen($filename,$mode);
|
||||
|
||||
return defined($self->{'file'}) ? $self : undef;
|
||||
}
|
||||
|
||||
sub CLOSE
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return undef unless defined($self->{'file'});
|
||||
|
||||
my $status = $self->{'file'}->gzclose();
|
||||
|
||||
delete $self->{'file'};
|
||||
|
||||
return ($status == 0) ? 1 : undef;
|
||||
}
|
||||
|
||||
sub READ
|
||||
{
|
||||
my $self = shift;
|
||||
my $bufref = \$_[0];
|
||||
my $nbytes = $_[1];
|
||||
my $offset = $_[2] || 0;
|
||||
|
||||
croak "IO::Zlib::READ: NBYTES must be specified" unless defined($nbytes);
|
||||
|
||||
$$bufref = "" unless defined($$bufref);
|
||||
|
||||
my $bytesread = $self->{'file'}->gzread(substr($$bufref,$offset),$nbytes);
|
||||
|
||||
return undef if $bytesread < 0;
|
||||
|
||||
return $bytesread;
|
||||
}
|
||||
|
||||
sub READLINE
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
my $line;
|
||||
|
||||
return () if $self->{'file'}->gzreadline($line) <= 0;
|
||||
|
||||
return $line unless wantarray;
|
||||
|
||||
my @lines = $line;
|
||||
|
||||
while ($self->{'file'}->gzreadline($line) > 0)
|
||||
{
|
||||
push @lines, $line;
|
||||
}
|
||||
|
||||
return @lines;
|
||||
}
|
||||
|
||||
sub WRITE
|
||||
{
|
||||
my $self = shift;
|
||||
my $buf = shift;
|
||||
my $length = shift;
|
||||
my $offset = shift;
|
||||
|
||||
croak "IO::Zlib::WRITE: too long LENGTH" unless $offset + $length <= length($buf);
|
||||
|
||||
return $self->{'file'}->gzwrite(substr($buf,$offset,$length));
|
||||
}
|
||||
|
||||
sub EOF
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->{'file'}->gzeof();
|
||||
}
|
||||
|
||||
sub FILENO
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub new
|
||||
{
|
||||
my $class = shift;
|
||||
my @args = @_;
|
||||
|
||||
_alias("new", @_) unless $aliased; # Some call new IO::Zlib directly...
|
||||
|
||||
my $self = gensym();
|
||||
|
||||
tie *{$self}, $class, @args;
|
||||
|
||||
return tied(${$self}) ? bless $self, $class : undef;
|
||||
}
|
||||
|
||||
sub getline
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return scalar tied(*{$self})->READLINE();
|
||||
}
|
||||
|
||||
sub getlines
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
croak "IO::Zlib::getlines: must be called in list context"
|
||||
unless wantarray;
|
||||
|
||||
return tied(*{$self})->READLINE();
|
||||
}
|
||||
|
||||
sub opened
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return defined tied(*{$self})->{'file'};
|
||||
}
|
||||
|
||||
sub AUTOLOAD
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
$AUTOLOAD =~ s/.*:://;
|
||||
$AUTOLOAD =~ tr/a-z/A-Z/;
|
||||
|
||||
return tied(*{$self})->$AUTOLOAD(@_);
|
||||
}
|
||||
|
||||
sub gzopen_external
|
||||
{
|
||||
my $filename = shift;
|
||||
my $mode = shift;
|
||||
my $fh = IO::Handle->new();
|
||||
|
||||
if ($mode =~ /r/)
|
||||
{
|
||||
# Because someone will try to read ungzipped files
|
||||
# with this we peek and verify the signature. Yes,
|
||||
# this means that we open the file twice (if it is
|
||||
# gzipped).
|
||||
# Plenty of race conditions exist in this code, but
|
||||
# the alternative would be to capture the stderr of
|
||||
# gzip and parse it, which would be a portability nightmare.
|
||||
if (-e $filename && open($fh, $filename))
|
||||
{
|
||||
binmode $fh;
|
||||
|
||||
my $sig;
|
||||
my $rdb = read($fh, $sig, 2);
|
||||
|
||||
if ($rdb == 2 && $sig eq "\x1F\x8B")
|
||||
{
|
||||
my $ropen = sprintf($gzip_read_open, $filename);
|
||||
|
||||
if (open($fh, $ropen))
|
||||
{
|
||||
binmode $fh;
|
||||
|
||||
return $fh;
|
||||
}
|
||||
else
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
seek($fh, 0, SEEK_SET) or
|
||||
die "IO::Zlib: open('$filename', 'r'): seek: $!";
|
||||
|
||||
return $fh;
|
||||
}
|
||||
else
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
elsif ($mode =~ /w/)
|
||||
{
|
||||
my $level = $mode =~ /([1-9])/ ? "-$1" : "";
|
||||
|
||||
# To maximize portability we would need to open
|
||||
# two filehandles here, one for "| gzip $level"
|
||||
# and another for "> $filename", and then when
|
||||
# writing copy bytes from the first to the second.
|
||||
# We are using IO::Handle objects for now, however,
|
||||
# and they can only contain one stream at a time.
|
||||
my $wopen = sprintf($gzip_write_open, $filename);
|
||||
|
||||
if (open($fh, $wopen))
|
||||
{
|
||||
$fh->autoflush(1);
|
||||
binmode $fh;
|
||||
|
||||
return $fh;
|
||||
}
|
||||
else
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
croak "IO::Zlib::gzopen_external: mode '$mode' is illegal";
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub gzread_external
|
||||
{
|
||||
my $file = shift;
|
||||
my $bufref = \$_[0];
|
||||
my $nbytes = $_[1] || 4096;
|
||||
|
||||
# Use read() instead of sysread() because people may
|
||||
# mix reads and readlines, and we don't want to mess
|
||||
# the stdio buffering. See also gzreadline_external()
|
||||
# and gzwrite_external().
|
||||
my $nread = read($file, $$bufref, $nbytes);
|
||||
|
||||
return defined $nread ? $nread : -1;
|
||||
}
|
||||
|
||||
sub gzwrite_external
|
||||
{
|
||||
my $file = shift;
|
||||
my $buf = shift;
|
||||
|
||||
# Using syswrite() is okay (cf. gzread_external())
|
||||
# since the bytes leave this process and buffering
|
||||
# is therefore not an issue.
|
||||
my $nwrote = syswrite($file, $buf);
|
||||
|
||||
return defined $nwrote ? $nwrote : -1;
|
||||
}
|
||||
|
||||
sub gzreadline_external
|
||||
{
|
||||
my $file = shift;
|
||||
my $bufref = \$_[0];
|
||||
|
||||
# See the comment in gzread_external().
|
||||
$$bufref = readline($file);
|
||||
|
||||
return defined $$bufref ? length($$bufref) : -1;
|
||||
}
|
||||
|
||||
sub gzeof_external
|
||||
{
|
||||
my $file = shift;
|
||||
|
||||
return eof($file);
|
||||
}
|
||||
|
||||
sub gzclose_external
|
||||
{
|
||||
my $file = shift;
|
||||
|
||||
close($file);
|
||||
|
||||
# I am not entirely certain why this is needed but it seems
|
||||
# the above close() always fails (as if the stream would have
|
||||
# been already closed - something to do with using external
|
||||
# processes via pipes?)
|
||||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user