1# Copyright © 2008-2010 Raphaël Hertzog <hertzog@debian.org> 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 of the License, or 6# (at your option) 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, see <https://www.gnu.org/licenses/>. 15 16package Dpkg::Compression::Process; 17 18use strict; 19use warnings; 20 21our $VERSION = '1.00'; 22 23use Carp; 24 25use Dpkg::Compression; 26use Dpkg::ErrorHandling; 27use Dpkg::Gettext; 28use Dpkg::IPC; 29 30=encoding utf8 31 32=head1 NAME 33 34Dpkg::Compression::Process - run compression/decompression processes 35 36=head1 DESCRIPTION 37 38This module provides an object oriented interface to run and manage 39compression/decompression processes. 40 41=head1 METHODS 42 43=over 4 44 45=item $proc = Dpkg::Compression::Process->new(%opts) 46 47Create a new instance of the object. Supported options are "compression" 48and "compression_level" (see corresponding set_* functions). 49 50=cut 51 52sub new { 53 my ($this, %args) = @_; 54 my $class = ref($this) || $this; 55 my $self = {}; 56 bless $self, $class; 57 $self->set_compression($args{compression} || compression_get_default()); 58 $self->set_compression_level($args{compression_level} || 59 compression_get_default_level()); 60 return $self; 61} 62 63=item $proc->set_compression($comp) 64 65Select the compression method to use. It errors out if the method is not 66supported according to C<compression_is_supported> (of 67B<Dpkg::Compression>). 68 69=cut 70 71sub set_compression { 72 my ($self, $method) = @_; 73 error(g_('%s is not a supported compression method'), $method) 74 unless compression_is_supported($method); 75 $self->{compression} = $method; 76} 77 78=item $proc->set_compression_level($level) 79 80Select the compression level to use. It errors out if the level is not 81valid according to C<compression_is_valid_level> (of 82B<Dpkg::Compression>). 83 84=cut 85 86sub set_compression_level { 87 my ($self, $level) = @_; 88 error(g_('%s is not a compression level'), $level) 89 unless compression_is_valid_level($level); 90 $self->{compression_level} = $level; 91} 92 93=item @exec = $proc->get_compress_cmdline() 94 95=item @exec = $proc->get_uncompress_cmdline() 96 97Returns a list ready to be passed to C<exec>, its first element is the 98program name (either for compression or decompression) and the following 99elements are parameters for the program. 100 101When executed the program acts as a filter between its standard input 102and its standard output. 103 104=cut 105 106sub get_compress_cmdline { 107 my $self = shift; 108 my @prog = (@{compression_get_property($self->{compression}, 'comp_prog')}); 109 my $level = '-' . $self->{compression_level}; 110 $level = '--' . $self->{compression_level} 111 if $self->{compression_level} !~ m/^[1-9]$/; 112 push @prog, $level; 113 return @prog; 114} 115 116sub get_uncompress_cmdline { 117 my $self = shift; 118 return (@{compression_get_property($self->{compression}, 'decomp_prog')}); 119} 120 121sub _sanity_check { 122 my ($self, %opts) = @_; 123 # Check for proper cleaning before new start 124 error(g_('Dpkg::Compression::Process can only start one subprocess at a time')) 125 if $self->{pid}; 126 # Check options 127 my $to = my $from = 0; 128 foreach my $thing (qw(file handle string pipe)) { 129 $to++ if $opts{"to_$thing"}; 130 $from++ if $opts{"from_$thing"}; 131 } 132 croak 'exactly one to_* parameter is needed' if $to != 1; 133 croak 'exactly one from_* parameter is needed' if $from != 1; 134 return %opts; 135} 136 137=item $proc->compress(%opts) 138 139Starts a compressor program. You must indicate where it will read its 140uncompressed data from and where it will write its compressed data to. 141This is accomplished by passing one parameter C<to_*> and one parameter 142C<from_*> as accepted by B<Dpkg::IPC::spawn>. 143 144You must call C<wait_end_process> after having called this method to 145properly close the sub-process (and verify that it exited without error). 146 147=cut 148 149sub compress { 150 my ($self, %opts) = @_; 151 152 $self->_sanity_check(%opts); 153 my @prog = $self->get_compress_cmdline(); 154 $opts{exec} = \@prog; 155 $self->{cmdline} = "@prog"; 156 $self->{pid} = spawn(%opts); 157 delete $self->{pid} if $opts{to_string}; # wait_child already done 158} 159 160=item $proc->uncompress(%opts) 161 162Starts a decompressor program. You must indicate where it will read its 163compressed data from and where it will write its uncompressed data to. 164This is accomplished by passing one parameter C<to_*> and one parameter 165C<from_*> as accepted by B<Dpkg::IPC::spawn>. 166 167You must call C<wait_end_process> after having called this method to 168properly close the sub-process (and verify that it exited without error). 169 170=cut 171 172sub uncompress { 173 my ($self, %opts) = @_; 174 175 $self->_sanity_check(%opts); 176 my @prog = $self->get_uncompress_cmdline(); 177 $opts{exec} = \@prog; 178 $self->{cmdline} = "@prog"; 179 $self->{pid} = spawn(%opts); 180 delete $self->{pid} if $opts{to_string}; # wait_child already done 181} 182 183=item $proc->wait_end_process(%opts) 184 185Call B<Dpkg::IPC::wait_child> to wait until the sub-process has exited 186and verify its return code. Any given option will be forwarded to 187the C<wait_child> function. Most notably you can use the "nocheck" option 188to verify the return code yourself instead of letting C<wait_child> do 189it for you. 190 191=cut 192 193sub wait_end_process { 194 my ($self, %opts) = @_; 195 $opts{cmdline} //= $self->{cmdline}; 196 wait_child($self->{pid}, %opts) if $self->{pid}; 197 delete $self->{pid}; 198 delete $self->{cmdline}; 199} 200 201=back 202 203=head1 CHANGES 204 205=head2 Version 1.00 (dpkg 1.15.6) 206 207Mark the module as public. 208 209=cut 210 2111; 212