aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Packdrakeng/zlib.pm150
1 files changed, 150 insertions, 0 deletions
diff --git a/Packdrakeng/zlib.pm b/Packdrakeng/zlib.pm
new file mode 100644
index 0000000..d541a67
--- /dev/null
+++ b/Packdrakeng/zlib.pm
@@ -0,0 +1,150 @@
+##- Nanar <nanardon@mandrake.org>
+##-
+##- This program is free software; you can redistribute it and/or modify
+##- it under the terms of the GNU General Public License as published by
+##- the Free Software Foundation; either version 2, or (at your option)
+##- any later version.
+##-
+##- This program is distributed in the hope that it will be useful,
+##- but WITHOUT ANY WARRANTY; without even the implied warranty of
+##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+##- GNU General Public License for more details.
+##-
+##- You should have received a copy of the GNU General Public License
+##- along with this program; if not, write to the Free Software
+##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+##- $Id$
+
+##- This package provide functions to use Zlib::Compress instead gzip.
+
+package Packdrakeng::zlib;
+
+use strict;
+use warnings;
+use Compress::Zlib;
+
+my $gzip_header = pack("C" . Compress::Zlib::MIN_HDR_SIZE,
+ Compress::Zlib::MAGIC1, Compress::Zlib::MAGIC2,
+ Compress::Zlib::Z_DEFLATED(), 0,0,0,0,0,0, Compress::Zlib::OSCODE);
+
+sub gzip_compress {
+ my ($pack, $sourcefh) = @_;
+ my ($insize, $outsize) = (0, 0); # aka uncompressed / compressed data length
+
+ # If $sourcefh is not set, this mean we want a flush(), for end_block()
+ # EOF, flush compress stream, adding crc
+ if (!defined($sourcefh)) {
+ if (defined($pack->{cstream_data}{object})) {
+ my ($cbuf, $status) = $pack->{cstream_data}{object}->flush();
+ $outsize += syswrite($pack->{handle}, $cbuf);
+ $outsize += syswrite($pack->{handle}, pack("V V", $pack->{cstream_data}{crc}, $pack->{cstream_data}{object}->total_in()));
+ }
+ $pack->{cstream_data} = undef;
+ return(undef, $outsize);
+ }
+
+ if (!defined $pack->{cstream_data}{object}) {
+ # Writing gzip header file
+ $outsize += syswrite($pack->{handle}, $gzip_header);
+ $pack->{cstream_data}{object} = deflateInit(
+ -Level => $pack->{level},
+ # Zlib do not create gzip header, except with this flag
+ -WindowBits => - MAX_WBITS(),
+ );
+ }
+
+ binmode $sourcefh;
+
+ while (my $lenght = sysread($sourcefh, my $buf, $pack->{bufsize})) {
+ $pack->{cstream_data}{crc} = crc32($buf, $pack->{cstream_data}{crc});
+ my ($cbuf, $status) = $pack->{cstream_data}{object}->deflate($buf);
+ $outsize += syswrite($pack->{handle}, $cbuf);
+ $insize += $lenght;
+ }
+
+ ($insize, $outsize)
+}
+
+sub gzip_uncompress {
+ my ($pack, $destfh, $fileinfo) = @_;
+ my $x = inflateInit(
+ -WindowBits => - MAX_WBITS(),
+ );
+ my $cread = 0; # Compressed data read
+ {
+ my $buf;
+ # get magic
+ if (sysread($pack->{handle}, $buf, 2) == 2) {
+ my @magic = unpack("C*", $buf);
+ $magic[0] == Compress::Zlib::MAGIC1 && $magic[1] == Compress::Zlib::MAGIC2 or do {
+ warn("Wrong magic header found");
+ return -1;
+ };
+ } else {
+ warn("Unexpect end of file while reading magic");
+ return -1;
+ }
+ my ($method, $flags);
+ if (sysread($pack->{handle}, $buf, 2) == 2) {
+ ($method, $flags) = unpack("C2", $buf);
+ } else {
+ warn("Unexpect end of file while reading flags");
+ return -1;
+ }
+
+ if (sysread($pack->{handle}, $buf, 6) != 6) {
+ warn("Unexpect end of file while reading gzip header");
+ return -1;
+ }
+
+ $cread += 12; #Gzip header fixed size is already read
+ if ($flags & 0x04) {
+ if (sysread($pack->{handle}, $buf, 2) == 2) {
+ my $len = unpack("I", $buf);
+ $cread += $len;
+ if (sysread($pack->{handle}, $buf, $len) != $len) {
+ warn("Unexpect end of file while reading gzip header");
+ return -1;
+ }
+ } else {
+ warn("Unexpect end of file while reading gzip header");
+ return -1;
+ }
+ }
+ }
+ my $byteswritten = 0;
+ my $read = 0; # uncompressed data read
+ while ($byteswritten < $fileinfo->{size}) {
+ my $cl=sysread($pack->{handle}, my $buf,
+ $cread + $pack->{bufsize} > $fileinfo->{csize} ?
+ $fileinfo->{csize} - $cread :
+ $pack->{bufsize}) or do {
+ warn("Enexpected end of file");
+ return -1;
+ };
+ $cread += $cl;
+ my ($out, $status) = $x->inflate(\$buf);
+ $status == Z_OK || $status == Z_STREAM_END or do {
+ warn("Unable to uncompress data");
+ return -1;
+ };
+ my $l = length($out) or next;
+ if ($read < $fileinfo->{off} && $read + $l > $fileinfo->{off}) {
+ $out = substr($out, $fileinfo->{off} - $read);
+ }
+ $read += $l;
+ if ($read <= $fileinfo->{off}) { next }
+
+ my $bw = $byteswritten + length($out) > $fileinfo->{size} ? $fileinfo->{size} - $byteswritten : length($out);
+ syswrite($destfh, $out, $bw) == $bw or do {
+ warn "Can't write data into dest";
+ return -1;
+ };
+ $byteswritten += $bw;
+
+ }
+ $byteswritten
+}
+
+