dpkg (1.18.25) stretch; urgency=medium
[dpkg] / scripts / Dpkg / Compression / Process.pm
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
16 package Dpkg::Compression::Process;
17
18 use strict;
19 use warnings;
20
21 our $VERSION = '1.00';
22
23 use Carp;
24
25 use Dpkg::Compression;
26 use Dpkg::ErrorHandling;
27 use Dpkg::Gettext;
28 use Dpkg::IPC;
29
30 =encoding utf8
31
32 =head1 NAME
33
34 Dpkg::Compression::Process - run compression/decompression processes
35
36 =head1 DESCRIPTION
37
38 This module provides an object oriented interface to run and manage
39 compression/decompression processes.
40
41 =head1 METHODS
42
43 =over 4
44
45 =item $proc = Dpkg::Compression::Process->new(%opts)
46
47 Create a new instance of the object. Supported options are "compression"
48 and "compression_level" (see corresponding set_* functions).
49
50 =cut
51
52 sub 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
65 Select the compression method to use. It errors out if the method is not
66 supported according to C<compression_is_supported> (of
67 B<Dpkg::Compression>).
68
69 =cut
70
71 sub 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
80 Select the compression level to use. It errors out if the level is not
81 valid according to C<compression_is_valid_level> (of
82 B<Dpkg::Compression>).
83
84 =cut
85
86 sub 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
97 Returns a list ready to be passed to C<exec>, its first element is the
98 program name (either for compression or decompression) and the following
99 elements are parameters for the program.
100
101 When executed the program acts as a filter between its standard input
102 and its standard output.
103
104 =cut
105
106 sub 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
116 sub get_uncompress_cmdline {
117 my $self = shift;
118 return (@{compression_get_property($self->{compression}, 'decomp_prog')});
119 }
120
121 sub _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
139 Starts a compressor program. You must indicate where it will read its
140 uncompressed data from and where it will write its compressed data to.
141 This is accomplished by passing one parameter C<to_*> and one parameter
142 C<from_*> as accepted by B<Dpkg::IPC::spawn>.
143
144 You must call C<wait_end_process> after having called this method to
145 properly close the sub-process (and verify that it exited without error).
146
147 =cut
148
149 sub 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
162 Starts a decompressor program. You must indicate where it will read its
163 compressed data from and where it will write its uncompressed data to.
164 This is accomplished by passing one parameter C<to_*> and one parameter
165 C<from_*> as accepted by B<Dpkg::IPC::spawn>.
166
167 You must call C<wait_end_process> after having called this method to
168 properly close the sub-process (and verify that it exited without error).
169
170 =cut
171
172 sub 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
185 Call B<Dpkg::IPC::wait_child> to wait until the sub-process has exited
186 and verify its return code. Any given option will be forwarded to
187 the C<wait_child> function. Most notably you can use the "nocheck" option
188 to verify the return code yourself instead of letting C<wait_child> do
189 it for you.
190
191 =cut
192
193 sub 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
207 Mark the module as public.
208
209 =cut
210
211 1;