1
# $Id: Gunzip.pm,v 1.6 2004/01/03 14:52:53 epaepa Exp $
7
XMLTV::Gunzip - wrapper to Compress::Zlib or gzip(1)
12
my $decompressed = gunzip($gzdata);
13
my $fh = gunzip_open('file.gz') or die;
14
while (<$fh>) { print }
16
Compress::Zlib will be used if installed, otherwise an external gzip
17
will be spawned. gunzip() returns the decompressed data and throws an
18
exception if things go wrong; gunzip_open() returns a filehandle, or
23
Ed Avis, ed@membled.com. Distributed as part of the xmltv package.
27
L<Compress::Zlib>, L<gzip(1)>, L<XMLTV>.
34
package XMLTV::Gunzip;
36
our @EXPORT; @EXPORT = qw(gunzip gunzip_open);
39
# Implementations of gunzip().
41
sub zlib_gunzip( $ ) {
42
for (Compress::Zlib::memGunzip(shift)) {
43
die 'memGunzip() failed' if not defined;
47
sub external_gunzip( $ ) {
48
my ($fh, $fname) = File::Temp::tempfile();
49
print $fh shift or die "cannot write to $fname: $!";
50
close $fh or die "cannot close $fname: $!";
51
open(GZIP, "gzip -d <$fname |") or die "cannot run gzip: $!";
54
close GZIP or die "cannot close pipe from gzip: $!";
55
unlink $fname or die "cannot unlink $fname: $!";
59
sub gunzip( $ ) { return $gunzip_f->(shift) }
62
# Implementations of gunzip_open().
64
sub perlio_gunzip_open( $ ) {
68
open FH, '<:gzip', $fname
69
or die "cannot open $fname via PerlIO::gzip: $!";
72
sub zlib_gunzip_open( $ ) {
74
# Use the XMLTV::Zlib_handle package defined later in this file.
76
tie *FH, 'XMLTV::Zlib_handle', $fname, 'r'
77
or die "cannot open $fname using XMLTV::Zlib_handle: $!";
80
sub external_gunzip_open( $ ) {
83
if (not open(FH, "gzip -d <$fname |")) {
84
warn "cannot run gzip: $!";
90
sub gunzip_open( $ ) { return $gunzip_open_f->(shift) }
93
# Switch between implementations depending on whether Compress::Zlib
97
eval { require Compress::Zlib }; my $have_zlib = not $@;
98
eval { require PerlIO::gzip }; my $have_perlio = not $@;
100
if (not $have_zlib and not $have_perlio) {
101
$gunzip_f = \&external_gunzip;
102
$gunzip_open_f = \&external_gunzip_open;
104
elsif (not $have_zlib and $have_perlio) {
105
# Could gunzip by writing to a file and reading that with
106
# PerlIO, but won't bother yet.
108
$gunzip_f = \&external_gunzip;
109
$gunzip_open_f = \&perlio_gunzip_open;
111
elsif ($have_zlib and not $have_perlio) {
112
$gunzip_f = \&zlib_gunzip;
113
$gunzip_open_f = \&zlib_gunzip_open;
115
elsif ($have_zlib and $have_perlio) {
116
$gunzip_f = \&zlib_gunzip;
117
$gunzip_open_f = \&perlio_gunzip_open;
124
# This is a filehandle wrapper around Compress::Zlib, but supporting
125
# only read at the moment.
127
package XMLTV::Zlib_handle;
128
require Tie::Handle; use base 'Tie::Handle';
132
croak 'usage: package->TIEHANDLE(file, mode)' if @_ != 3;
133
my ($pkg, $file, $mode) = @_;
135
croak "only mode 'r' is supported" if $mode ne 'r';
137
# This object is a reference to a Compress::Zlib handle. I did
138
# try to inherit directly from Compress::Zlib, but got weird
139
# errors of '(in cleanup) gzclose is not a valid Zlib macro'.
141
my $fh = Compress::Zlib::gzopen($file, $mode);
143
warn "could not gzopen $file";
146
return bless(\$fh, $pkg);
149
# Assuming that WRITE() is like print(), not like syswrite().
151
my ($self, $scalar, $length, $offset) = @_;
152
return 1 if not $length;
153
my $r = $$self->gzwrite(substr($scalar, $offset, $length));
155
warn "gzwrite() failed";
158
elsif (0 < $r and $r < $length) {
159
warn "gzwrite() wrote only $r of $length bytes";
162
elsif ($r == $length) {
168
# PRINT(), PRINTF() inherited from Tie::Handle
171
my ($self, $scalar, $length, $offset) = @_;
173
my $n = $$self->gzread($_, $length);
175
warn 'gzread() failed';
182
elsif (0 < $n and $n <= $length) {
184
substr($scalar, $offset, $n) = $_;
193
# When gzreadline() uses $/, this can be removed.
194
die '$/ not supported' if $/ ne "\n";
197
my $r = $$self->gzreadline($_);
199
warn 'gzreadline() failed';
208
# Number of bytes read.
214
# GETC inherited from Tie::Handle
216
# This seems to segfault in my perl installation.
219
gzclose $$self; # no meaningful return value?
224
# Compress::Zlib doesn't support reopening.
226
die 'not yet implemented';
233
return $$self->gzeof();
237
# Could track position manually. But Compress::Zlib should do it.
238
die 'not implemented';
242
# Argh, fairly impossible. Could simulate, but probably better to
245
die 'not implemented';
248
sub DESTROY { &CLOSE }