This file is indexed.

/usr/share/perl5/Lintian/ProcessableGroup.pm is in lintian 2.5.50.4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# Copyright (C) 2011 Niels Thykier <niels@thykier.net>
#
# 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 of the License, 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, you can find it on the World Wide
# Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.

## Represents a group of 'Lintian::Processable's
package Lintian::ProcessableGroup;

use strict;
use warnings;

use Lintian::Collect::Group;
use Lintian::Processable;
use Lintian::Util qw(fail get_dsc_info strip);

=head1 NAME

Lintian::ProcessableGroup -- A group of objects that Lintian can process

=head1 SYNOPSIS

 use Lintian::ProcessableGroup;

 my $group = Lintian::ProcessableGroup->new('lintian_2.5.0_i386.changes');
 foreach my $proc ($group->get_processables){
     printf "%s %s (%s)\n", $proc->pkg_name,
            $proc->pkg_version, $proc->pkg_type;
 }
 # etc.

=head1 DESCRIPTION

Instances of this perl class are sets of
L<processables|Lintian::Processable>.  It allows at most one source
and one changes package per set, but multiple binary packages
(provided that the binary is not already in the set).

=head1 METHODS

=over 4

=item Lintian::ProcessableGroup->new ([LAB[, CHANGES]])

Creates a group and optionally add all processables from CHANGES.

If the LAB parameter is given, all processables added to this group
will be stored as a L<lab entry|Lintian::Lab::Entry> from LAB.

=cut

sub new {
    my ($class, $lab, $changes) = @_;
    my $self = {'lab' => $lab,};
    bless $self, $class;
    $self->_init_group_from_changes($changes)
      if defined $changes;
    return $self;
}

# Map a processable to L::Lab::Entry if needed.
sub _lab_proc {
    my ($self, $proc) = @_;
    return $proc unless $self->{'lab'};
    return $proc
      if $proc->isa('Lintian::Lab::Entry')
      and not $proc->from_lab($self->{'lab'});
    return $self->{'lab'}->get_package($proc);
}

# Internal initialization sub
#  populates $self from a changes file.
sub _init_group_from_changes {
    my ($self, $changes) = @_;
    my ($cinfo, $cdir);
    fail "$changes does not exist" unless -e $changes;
    $cinfo = get_dsc_info($changes)
      or fail "$changes is not a valid changes file";
    $self->add_new_processable($changes, 'changes');
    $cdir = $changes;
    if ($changes =~ m,^/+[^/]++$,o){
        # it is "/files.changes?"
        #  - In case you were wondering, we were told not to ask :)
        #   See #624149
        $cdir = '/';
    } else {
        # it is "<something>/files.changes"
        $cdir =~ s,(.+)/[^/]+$,$1,;
    }
    for my $line (split(/\n/o, $cinfo->{'files'}//'')) {
        my ($file);
        next unless defined $line;
        strip($line);
        next if $line eq '';
        # Ignore files that may lead to path traversal issues.

        # We do not need (in order) md5sum, size, section or priority
        # - just the file name please.
        (undef, undef, undef, undef, $file) = split(/\s+/o, $line);

        # If the field is malformed, $file may be undefined; we also
        # skip it, if it contains a "/" since that is most likely a
        # traversal attempt
        next if !$file || $file =~ m,/,o;

        if (not -f "$cdir/$file") {
            print STDERR "$cdir/$file does not exist, exiting\n";
            exit 2;
        }

        if ($file !~ /\.u?deb$/o and $file !~ m/\.dsc$/o) {
            # Some file we do not care about (at least not here).
            next;
        }

        $self->add_new_processable("$cdir/$file");

    }
    return 1;
}

=item $group->add_new_processable ($pkg_path[, $pkg_type])

Adds a new processable of type $pkg_type from $pkg_path.  If $pkg_type
is not given, it will be determined by the file extension.

This is short hand for:

 $group->add_processable(
    Lintian::Processable->new ($pkg_path, $pkg_type));

=cut

sub add_new_processable {
    my ($self, $pkg_path, $pkg_type) = @_;
    return $self->add_processable(
        Lintian::Processable::Package->new($pkg_path, $pkg_type));
}

=item $group->add_processable($proc)

Adds $proc to $group.  At most one source and one changes $proc can be
in a $group.  There can be multiple binary $proc's, as long as they
are all unique.

This will error out if an additional source or changes $proc is added
to the group. Otherwise it will return a truth value if $proc was
added.

=cut

sub add_processable{
    my ($self, $processable) = @_;
    my $pkg_type = $processable->pkg_type;

    if ($pkg_type eq 'changes'){
        fail 'Cannot add another changes file' if (exists $self->{changes});
        $self->{changes} = $self->_lab_proc($processable);
    } elsif ($pkg_type eq 'source'){
        fail 'Cannot add another source package' if (exists $self->{source});
        $self->{source} = $self->_lab_proc($processable);
    } else {
        my $phash;
        my $id = $processable->identifier;
        fail "Unknown type $pkg_type"
          unless ($pkg_type eq 'binary' or $pkg_type eq 'udeb');
        $phash = $self->{$pkg_type};
        if (!defined $phash){
            $phash = {};
            $self->{$pkg_type} = $phash;
        }
        # duplicate ?
        return 0 if (exists $phash->{$id});
        $phash->{$id} = $self->_lab_proc($processable);
    }
    $processable->group($self);
    return 1;
}

=item $group->get_processables([$type])

Returns an array of all processables in $group.  The processables are
returned in the following order: changes (if any), source (if any),
all binaries (if any) and all udebs (if any).

This order is based on the original order that Lintian processed
packages in and some parts of the code relies on this order.

Note if $type is given, then only processables of that type is
returned.

=cut

sub get_processables {
    my ($self, $type) = @_;
    my @result;
    if (defined $type){
        # We only want $type
        if ($type eq 'changes' or $type eq 'source'){
            return $self->{$type}  if defined $self->{$type};
        }
        return values %{$self->{$type}}
          if $type eq 'binary'
          or $type eq 'udeb';
        fail "Unknown type of processable: $type";
    }
    # We return changes, dsc, debs and udebs in that order,
    # because that is the order lintian used to process a changes
    # file (modulo debs<->udebs ordering).
    #
    # Also correctness of other parts rely on this order.
    foreach my $type (qw(changes source)){
        push @result, $self->{$type} if (exists $self->{$type});
    }
    foreach my $type (qw(binary udeb)){
        push @result, values %{$self->{$type}} if (exists $self->{$type});
    }
    return @result;
}

=item $group->remove_processable($proc)

Removes $proc from $group

=cut

sub remove_processable {
    my ($self, $proc) = @_;
    my $pkg_type = $proc->pkg_type;
    if ($pkg_type eq 'source' or $pkg_type eq 'changes'){
        delete $self->{$pkg_type};
    } elsif (defined $self->{$pkg_type}) {
        my $phash = $self->{$pkg_type};
        my $id = $proc->identifier;
        delete $phash->{$id};
    }
    return 1;
}

=item $group->get_source_processable

Returns the processable identified as the "source" package (e.g. the dsc).

If $group does not have a source processable, this method returns C<undef>.

=cut

sub get_source_processable {
    my ($self) = @_;
    return $self->{source};
}

=item $group->get_changes_processable

Returns the processable identified as the "changes" processable (e.g.
the changes file).

If $group does not have a changes processable, this method returns C<undef>.

=cut

sub get_changes_processable {
    my ($self) = @_;
    return $self->{changes};
}

=item $group->get_binary_processables

Returns all binary (and udeb) processables in $group.

If $group does not have any binary processables then an empty list is
returned.

=cut

sub get_binary_processables {
    my ($self) = @_;
    my @result;
    foreach my $type (qw(binary udeb)){
        push @result, values %{$self->{$type}} if (exists $self->{$type});
    }
    return @result;
}

=item $group->info

Returns L<$info|Lintian::Collect::Group> element for this group.

=cut

sub info {
    my ($self) = @_;
    my $info = $self->{info};
    if (!defined $info) {
        $info = Lintian::Collect::Group->new($self);
        $self->{info} = $info;
    }
    return $info;
}

=item $group->init_shared_cache

Prepare a shared memory cache for all current members of the group.
This is solely a memory saving optimization and is not required for
correct performance.

=cut

sub init_shared_cache {
    my ($self) = @_;
    $self->info; # Side-effect of creating the info object.
    return;
}

=item $group->clear_cache

Discard the info element of all members of this group, so the memory
used by it can be reclaimed.  Mostly useful when checking a lot of
packages (e.g. on lintian.d.o).

=cut

sub clear_cache {
    my ($self) = @_;
    for my $proc ($self->get_processables) {
        $proc->clear_cache;
    }
    delete $self->{info};
    return;
}

=back

=head1 AUTHOR

Originally written by Niels Thykier <niels@thykier.net> for Lintian.

=head1 SEE ALSO

lintian(1)

L<Lintian::Processable>

=cut

1;

# Local Variables:
# indent-tabs-mode: nil
# cperl-indent-level: 4
# End:
# vim: syntax=perl sw=4 sts=4 sr et