Added Cyg-Win

This commit is contained in:
Frank Harris 2026-06-06 18:46:40 -04:00
parent 82cbc206eb
commit 413c315806
10586 changed files with 3806249 additions and 0 deletions

View file

@ -0,0 +1,153 @@
package IO::Compress::Adapter::Bzip2 ;
use strict;
use warnings;
use bytes;
use IO::Compress::Base::Common 2.212 qw(:Status);
use Compress::Raw::Bzip2 2.212 ;
our ($VERSION);
$VERSION = '2.212';
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__

View file

@ -0,0 +1,192 @@
package IO::Compress::Adapter::Deflate ;
use strict;
use warnings;
use bytes;
use IO::Compress::Base::Common 2.212 qw(:Status);
use Compress::Raw::Zlib 2.212 qw( !crc32 !adler32 ) ;
require Exporter;
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, @EXPORT, %DEFLATE_CONSTANTS);
$VERSION = '2.212';
@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 mkCompObject1
{
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__

View file

@ -0,0 +1,100 @@
package IO::Compress::Adapter::Identity ;
use strict;
use warnings;
use bytes;
use IO::Compress::Base::Common 2.212 qw(:Status);
our ($VERSION);
$VERSION = '2.212';
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__

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,884 @@
package IO::Compress::Bzip2 ;
use strict ;
use warnings;
use bytes;
require Exporter ;
use IO::Compress::Base 2.212 ;
use IO::Compress::Base::Common 2.212 qw();
use IO::Compress::Adapter::Bzip2 2.212 ;
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $Bzip2Error);
$VERSION = '2.212';
$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.212 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 Oneshot 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";
The constructor takes one mandatory parameter, C<$output>, defined below and
zero or more C<OPTS>, defined in L<Constructor Options>.
It returns an C<IO::Compress::Bzip2> object on success and C<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";
Below is a simple exaple of using the OO interface to create an output file
C<myfile.bz2> and write some data to it.
my $filename = "myfile.bz2";
my $z = IO::Compress::Bzip2->new($filename)
or die "IO::Compress::Bzip2 failed: $Bzip2Error\n";
$z->print("abcde");
$z->close();
See the L</Examples> for more.
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
=head3 Streaming
This very simple command line example demonstrates the streaming capabilities
of the module. The code reads data from STDIN or all the files given on the
commandline, compresses it, and writes the compressed data to STDOUT.
use strict ;
use warnings ;
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
my $z = IO::Compress::Bzip2->new("-", Stream => 1)
or die "IO::Compress::Bzip2 failed: $Bzip2Error\n";
while (<>) {
$z->print("abcde");
}
$z->close();
Note the use of C<"-"> to means C<STDOUT>. Alternatively you can use C<\*STDOUT>.
=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> there are a few options
Start by creating the compression object and opening the input file
use strict ;
use warnings ;
use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
my $input = "file1.txt";
my $z = IO::Compress::Bzip2->new("file1.txt.bz2")
or die "IO::Compress::Bzip2 failed: $Bzip2Error\n";
# open the input file
open my $fh, "<", "file1.txt"
or die "Cannot open file1.txt: $!\n";
# loop through the input file & write to the compressed file
while (<$fh>) {
$z->print($_);
}
# not forgetting to close the compressed file
$z->close();
=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-2024 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.

View 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.212 ();
use IO::Compress::Adapter::Deflate 2.212 ;
use IO::Compress::Zlib::Constants 2.212 ;
use IO::Compress::Base::Common 2.212 qw();
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $DeflateError);
$VERSION = '2.212';
$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 mkComp
{
my $self = shift ;
my $got = shift ;
my ($obj, $errstr, $errno) = IO::Compress::Adapter::Deflate::mkCompObject1(
$got->getValue('crc32'),
$got->getValue('adler32'),
$got->getValue('level'),
$got->getValue('strategy')
);
return $self->saveErrorString(undef, $errstr, $errno)
if ! defined $obj;
return $obj;
}
sub mkHeader
{
my $self = shift ;
return '';
}
sub mkTrailer
{
my $self = shift ;
return '';
}
sub mkFinalTrailer
{
return '';
}
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 Oneshot 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";
The constructor takes one mandatory parameter, C<$output>, defined below and
zero or more C<OPTS>, defined in L<Constructor Options>.
It returns an C<IO::Compress::Deflate> object on success and C<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";
Below is a simple exaple of using the OO interface to create an output file
C<myfile.1950> and write some data to it.
my $filename = "myfile.1950";
my $z = IO::Compress::Deflate->new($filename)
or die "IO::Compress::Deflate failed: $DeflateError\n";
$z->print("abcde");
$z->close();
See the L</Examples> for more.
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
=head3 Streaming
This very simple command line example demonstrates the streaming capabilities
of the module. The code reads data from STDIN or all the files given on the
commandline, compresses it, and writes the compressed data to STDOUT.
use strict ;
use warnings ;
use IO::Compress::Deflate qw(deflate $DeflateError) ;
my $z = IO::Compress::Deflate->new("-", Stream => 1)
or die "IO::Compress::Deflate failed: $DeflateError\n";
while (<>) {
$z->print("abcde");
}
$z->close();
Note the use of C<"-"> to means C<STDOUT>. Alternatively you can use C<\*STDOUT>.
=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> there are a few options
Start by creating the compression object and opening the input file
use strict ;
use warnings ;
use IO::Compress::Deflate qw(deflate $DeflateError) ;
my $input = "file1.txt";
my $z = IO::Compress::Deflate->new("file1.txt.1950")
or die "IO::Compress::Deflate failed: $DeflateError\n";
# open the input file
open my $fh, "<", "file1.txt"
or die "Cannot open file1.txt: $!\n";
# loop through the input file & write to the compressed file
while (<$fh>) {
$z->print($_);
}
# not forgetting to close the compressed file
$z->close();
=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<https://datatracker.ietf.org/doc/html/rfc1950>,
L<https://datatracker.ietf.org/doc/html/rfc1951> and
L<https://datatracker.ietf.org/doc/html/rfc1952>
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 the I<zlib-ng> compression library is
L<https://github.com/zlib-ng/zlib-ng>.
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-2024 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.

View 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<https://datatracker.ietf.org/doc/html/rfc1952>
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-2024 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.

File diff suppressed because it is too large Load diff

View 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.212';
@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;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,132 @@
package IO::Compress::Zip::Constants;
use strict ;
use warnings;
require Exporter;
our ($VERSION, @ISA, @EXPORT, %ZIP_CM_MIN_VERSIONS);
$VERSION = '2.212';
@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_CM_AES
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
use constant ZIP_CM_AES => 99 ;
# 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__

View file

@ -0,0 +1,77 @@
package IO::Compress::Zlib::Constants ;
use strict ;
use warnings;
use bytes;
require Exporter;
our ($VERSION, @ISA, @EXPORT);
$VERSION = '2.212';
@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;

View 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.212';
use IO::Compress::Gzip::Constants 2.212 ;
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__

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,111 @@
package IO::Uncompress::Adapter::Bunzip2;
use strict;
use warnings;
use bytes;
use IO::Compress::Base::Common 2.212 qw(:Status);
use Compress::Raw::Bzip2 2.212 ;
our ($VERSION, @ISA);
$VERSION = '2.212';
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__

View file

@ -0,0 +1,188 @@
package IO::Uncompress::Adapter::Identity;
use warnings;
use strict;
use bytes;
use IO::Compress::Base::Common 2.212 qw(:Status);
use IO::Compress::Zip::Constants ;
our ($VERSION);
$VERSION = '2.212';
use Compress::Raw::Zlib 2.212 ();
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__

View file

@ -0,0 +1,156 @@
package IO::Uncompress::Adapter::Inflate;
use strict;
use warnings;
use bytes;
use IO::Compress::Base::Common 2.212 qw(:Status);
use Compress::Raw::Zlib 2.212 qw(Z_OK Z_BUF_ERROR Z_STREAM_END Z_FINISH MAX_WBITS);
our ($VERSION);
$VERSION = '2.212';
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__

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,928 @@
package IO::Uncompress::Bunzip2 ;
use strict ;
use warnings;
use bytes;
use IO::Compress::Base::Common 2.212 qw(:Status );
use IO::Uncompress::Base 2.212 ;
use IO::Uncompress::Adapter::Bunzip2 2.212 ;
require Exporter ;
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $Bunzip2Error);
$VERSION = '2.212';
$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 ;
# ASCII: B Z h 0 9
return $buffer =~ qr/^\x42\x5A\x68[\x30-\x39]$/;
}
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 OneShot 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";
The constructor takes one mandatory parameter, C<$input>, defined below, and
zero or more C<OPTS>, defined in L<Constructor Options>.
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>;
Below is a simple exaple of using the OO interface to read the compressed file
C<myfile.bz2> and write its contents to stdout.
my $filename = "myfile.bz2";
my $z = IO::Uncompress::Bunzip2->new($filename)
or die "IO::Uncompress::Bunzip2 failed: $Bunzip2Error\n";
while (<$z>) {
print $_;
}
$z->close();
See L</EXAMPLES> for further examples
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
=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-2024 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.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View 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.15";
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;