File Coverage

blib/lib/MDV/Packdrakeng/zlib.pm
Criterion Covered Total %
statement 85 111 76.5
branch 32 48 66.6
condition 10 17 58.8
subroutine 8 8 100.0
pod 0 5 0.0
total 135 189 71.4


line stmt bran cond sub pod time code
1             ##- Nanar
2             ##-
3             ##- This program is free software; you can redistribute it and/or modify
4             ##- it under the terms of the GNU General Public License as published by
5             ##- the Free Software Foundation; either version 2, or (at your option)
6             ##- any later version.
7             ##-
8             ##- This program is distributed in the hope that it will be useful,
9             ##- but WITHOUT ANY WARRANTY; without even the implied warranty of
10             ##- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             ##- GNU General Public License for more details.
12             ##-
13             ##- You should have received a copy of the GNU General Public License
14             ##- along with this program; if not, write to the Free Software
15             ##- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16              
17             #- This package provides functions to use Compress::Zlib instead of gzip.
18              
19             package MDV::Packdrakeng::zlib;
20              
21 2     2   87619 use strict;
  2         5  
  2         89  
22 2     2   13 use Compress::Zlib;
  2         4  
  2         765  
23 2     2   14 use base qw(MDV::Packdrakeng);
  2         40  
  2         9567  
24              
25             (our $VERSION) = q($Id: zlib.pm 225628 2007-08-09 11:00:15Z nanardon $) =~ /(\d+)/;
26              
27             my $gzip_header = pack("C" . 10,
28             31, 139,
29             8, 0,0,0,0,0,0, 3);
30              
31             # true if wrapper writes directly in archive and not into temp file
32 36     36 0 158 sub direct_write { 1; }
33              
34 10     10 0 73 sub method_info { "internal zlib $VERSION" }
35              
36             sub compress_handle {
37 30     30 0 67 my ($pack, $sourcefh) = @_;
38 30         49 my ($insize, $outsize) = (0, 0); # aka uncompressed / compressed data length
39              
40             # If $sourcefh is not set, this means we want a flush(), for end_block()
41             # EOF, flush compress stream, adding crc
42 30 100       72 if (!defined($sourcefh)) {
43 13         30 return(undef, $pack->compress_data());
44             }
45              
46 17         57 binmode $sourcefh;
47 17         701 while (my $lenght = sysread($sourcefh, my $buf, $pack->{bufsize})) {
48 134         463 my $wres = $pack->compress_data($buf);
49 134         191 $outsize += $wres;
50 134         4758 $insize += $lenght;
51             }
52              
53 17         101 ($insize, $outsize)
54             }
55              
56             sub compress_data {
57 149     149 0 294 my ($pack, $data) = ($_[0], \$_[1]);
58 149         204 my $outsize = 0;
59 149 100       420 if (! defined($$data)) {
60 13 100       45 if (defined($pack->{cstream_data}{object})) {
61 11         65 my ($cbuf, $status) = $pack->{cstream_data}{object}->flush();
62 11         2714 $outsize += syswrite($pack->{handle}, $cbuf);
63 11         213 $outsize += syswrite($pack->{handle}, pack("V V", $pack->{cstream_data}{crc}, $pack->{cstream_data}{object}->total_in()));
64             }
65 13         22 $pack->{cstream_data} = undef;
66 13         538 return($outsize);
67             }
68            
69 136 100       426 if (!defined $pack->{cstream_data}{object}) {
70             # Writing gzip header file
71 11         207 $outsize += syswrite($pack->{handle}, $gzip_header);
72 11         103 $pack->{cstream_data}{object} = deflateInit(
73             -Level => $pack->{level},
74             # Zlib does not create a gzip header, except with this flag
75             -WindowBits => - MAX_WBITS(),
76             );
77             }
78            
79 136         36821 $pack->{cstream_data}{crc} = crc32($$data, $pack->{cstream_data}{crc});
80 136         682 my ($cbuf, $status) = $pack->{cstream_data}{object}->deflate($$data);
81 136   100     461110 my $wres = syswrite($pack->{handle}, $cbuf) || 0;
82 136 50       419 $wres == length($cbuf) or do {
83 0         0 $pack->{destroyed} = 1;
84 0         0 die "Can't push all data to compressor\n";
85             };
86 136         223 $outsize += $wres;
87 136         343 return($outsize);
88             }
89              
90             sub uncompress_handle {
91 27     27 0 92 my ($pack, $destfh, $fileinfo) = @_;
92              
93 27 100       85 if (!defined $fileinfo) {
94 8         17 $pack->{ustream_data} = undef;
95 8         59 return 0;
96             }
97              
98 19 100 66     172 if (defined($pack->{ustream_data}) && ($fileinfo->{coff} != $pack->{ustream_data}{coff} || $fileinfo->{off} < ($pack->{ustream_data}{off} || 0))) {
      66        
99 8         26 $pack->{ustream_data} = undef;
100             }
101              
102 19 100       116 if (!defined($pack->{ustream_data})) {
103 11         40 $pack->{ustream_data}{coff} = $fileinfo->{coff};
104 11         47 $pack->{ustream_data}{read} = 0; # uncompressed data read
105 11         79 $pack->{ustream_data}{x} = inflateInit(
106             -WindowBits => - MAX_WBITS(),
107             );
108 11         2308 $pack->{ustream_data}{cread} = 0; # Compressed data read
109             {
110 11         19 my $buf;
  11         18  
111             # get magic
112 11 50       113 if (sysread($pack->{handle}, $buf, 2) == 2) {
113 11         67 my @magic = unpack("C*", $buf);
114 11 50 33     84 $magic[0] == 31 && $magic[1] == 139 or do {
115 0         0 warn("Wrong magic header found\n");
116 0         0 return -1;
117             };
118             } else {
119 0         0 warn("Unexpected end of file while reading magic\n");
120 0         0 return -1;
121             }
122 11         140 my ($method, $flags);
123 11 50       83 if (sysread($pack->{handle}, $buf, 2) == 2) {
124 11         30 ($method, $flags) = unpack("C2", $buf);
125             } else {
126 0         0 warn("Unexpected end of file while reading flags\n");
127 0         0 return -1;
128             }
129              
130 11 50       74 if (sysread($pack->{handle}, $buf, 6) != 6) {
131 0         0 warn("Unexpected end of file while reading gzip header\n");
132 0         0 return -1;
133             }
134              
135 11         26 $pack->{ustream_data}{cread} += 12; #Gzip header fixed size is already read
136 11 50       34 if ($flags & 0x04) {
137 0 0       0 if (sysread($pack->{handle}, $buf, 2) == 2) {
138 0         0 my $len = unpack("I", $buf);
139 0         0 $pack->{ustream_data}{cread} += $len;
140 0 0       0 if (sysread($pack->{handle}, $buf, $len) != $len) {
141 0         0 warn("Unexpected end of file while reading gzip header\n");
142 0         0 return -1;
143             }
144             } else {
145 0         0 warn("Unexpected end of file while reading gzip header\n");
146 0         0 return -1;
147             }
148             }
149             }
150             } else {
151 8         36 sysseek($pack->{handle}, $pack->{ustream_data}{cread} - 2, 1);
152             }
153 19         45 $pack->{ustream_data}{off} = $fileinfo->{off};
154 19         24 my $byteswritten = 0;
155 19         56 while ($byteswritten < $fileinfo->{size}) {
156 137         298 my ($l, $out, $status) = (0, $pack->{ustream_data}{buf});
157 137         207 $pack->{ustream_data}{buf} = undef;
158 137 100       271 if (!defined($out)) {
159             my $cl=sysread($pack->{handle}, my $buf,
160             $pack->{ustream_data}{cread} + $pack->{bufsize} > $fileinfo->{csize} ?
161             $fileinfo->{csize} - $pack->{ustream_data}{cread} :
162 129 100       5600 $pack->{bufsize}) or do {
    50          
163 0         0 warn("Unexpected end of file\n");
164 0         0 return -1;
165             };
166 129         216 $pack->{ustream_data}{cread} += $cl;
167 129         475 ($out, $status) = $pack->{ustream_data}{x}->inflate(\$buf);
168 129 50 66     18714 $status == Z_OK || $status == Z_STREAM_END or do {
169 0         0 warn("Unable to uncompress data\n");
170 0         0 return -1;
171             };
172             }
173 137 50       824 $l = length($out) or next;
174 137 50 33     467 if ($pack->{ustream_data}{read} < $fileinfo->{off} && $pack->{ustream_data}{read} + $l > $fileinfo->{off}) {
175 0         0 $out = substr($out, $fileinfo->{off} - $pack->{ustream_data}{read});
176             }
177 137         183 $pack->{ustream_data}{read} += $l;
178 137 50       2148 if ($pack->{ustream_data}{read} <= $fileinfo->{off}) { next }
  0         0  
179              
180 137         122 my $bw;
181 137 100       269 if ($byteswritten + length($out) > $fileinfo->{size}) {
182 8         11 $bw = $fileinfo->{size} - $byteswritten;
183 8         80 $pack->{ustream_data}{buf} = substr($out, $bw); # keeping track of unwritten uncompressed data
184 8         22 $pack->{ustream_data}{read} -= length($pack->{ustream_data}{buf});
185             } else {
186 129         153 $bw = length($out);
187             }
188 137 50       40617 syswrite($destfh, $out, $bw) == $bw or do {
189 0         0 warn "Can't write data into dest\n";
190 0         0 return -1;
191             };
192 137         492 $byteswritten += $bw;
193              
194             }
195             $byteswritten
196 19         109 }
197              
198             1;
199              
200             __END__