Added lots more modules from lintian. Maemian appears to work.
[maemian] / checks / deb-format
1 # deb-format -- lintian check script -*- perl -*-
2
3 # Copyright (C) 2009 Russ Allbery
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; either version 2 of the License, or (at your option)
8 # any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13 # more details.
14 #
15 # You should have received a copy of the GNU General Public License along with
16 # this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 package Maemian::deb_format;
19 use strict;
20 use Tags;
21
22 use Maemian::Command qw(spawn);
23
24 # The files that contain error messages from tar, which we'll check and issue
25 # tags for if they contain something unexpected, and their corresponding tags.
26 our %ERRORS = ('control-errors'       => 'tar-errors-from-control',
27                'control-index-errors' => 'tar-errors-from-control',
28                'index-errors'         => 'tar-errors-from-data',
29                'unpacked-errors'      => 'tar-errors-from-data');
30
31 # Used to match Ubuntu distribution names in target distributions.
32 our $UBUNTU_REGEX;
33 {
34     my $dists = Maemian::Data->new('changelog-file/ubuntu-dists');
35     my $string = join ('|', 'ubuntu', $dists->all);
36     $UBUNTU_REGEX = qr/$string/o;
37 }
38
39 sub run {
40
41 my $pkg = shift;
42 my $type = shift;
43 my $info = shift;
44
45 # Run ar t on the *.deb file.  deb will be a symlink to it.
46 my $okay = 0;
47 my $opts = {};
48 my $success = spawn($opts, ['ar', 't', 'deb']);
49 if ($success) {
50     my @members = split("\n", ${ $opts->{out} });
51     if (@members != 3) {
52         my $count = scalar(@members);
53         tag 'malformed-deb-archive',
54             "found $count members instead of 3";
55     } elsif ($members[0] ne 'debian-binary') {
56         tag 'malformed-deb-archive',
57             "first member $members[0] not debian-binary";
58     } elsif ($members[1] ne 'control.tar.gz') {
59         tag 'malformed-deb-archive',
60             "second member $members[1] not control.tar.gz";
61     } elsif ($members[2] eq 'data.tar.lzma') {
62         # Ubuntu's archive allows lzma packages.
63         my ($entry) = $info->changelog->data;
64         my $distribution = $entry->Distribution;
65         if ($distribution =~ /$UBUNTU_REGEX/) {
66             $okay = 1;
67         } else {
68             tag 'lzma-deb-archive';
69         }
70     } elsif ($members[2] !~ /^data\.tar\.(gz|bz2)\z/) {
71         tag 'malformed-deb-archive',
72             "third member $members[2] not data.tar.(gz|bz2)";
73     } else {
74         $okay = 1;
75     }
76 } else {
77     # unpack will probably fail so we'll never get here, but may as well be
78     # complete just in case.
79     my $error = ${ $opts->{err} };
80     $error =~ s/\n.*//s;
81     $error =~ s/^ar:\s*//;
82     $error =~ s/^deb:\s*//;
83     tag 'malformed-deb-archive', "ar error: $error";
84 }
85
86 # Check the debian-binary version number.  We probably won't get here because
87 # dpkg-deb will decline to unpack the deb, but be thorough just in case.  We
88 # may eventually have a case where dpkg supports a newer format but it's not
89 # permitted in the archive yet.
90 if ($okay) {
91     my $opts = {};
92     my $success = spawn($opts, ['ar', 'p', 'deb', 'debian-binary']);
93     if (not $success) {
94         tag 'malformed-deb-archive', "can't read debian-binary member";
95     } elsif (${ $opts->{out} } !~ /^2\.\d+\n/) {
96         my ($version) = split("\n", ${ $opts->{out} });
97         tag 'malformed-deb-archive', "version $version not 2.0";
98     }
99 }
100
101 # If either control-errors or index-errors exist, tar produced error output
102 # when processing the package.  We want to report those as tags unless they're
103 # just tar noise that doesn't represent an actual problem.
104 for my $file (keys %ERRORS) {
105     my $tag = $ERRORS{$file};
106     if (-s $file) {
107         open(ERRORS, '<', $file) or fail("cannot open $file: $!");
108         local $_;
109         while (<ERRORS>) {
110             chomp;
111             s,^(?:[/\w]+/)?tar: ,,;
112
113             # Record size errors are harmless.  Ignore implausibly old
114             # timestamps in the data section since we already check for that
115             # elsewhere, but still warn for control.
116             next if /^Record size =/;
117             if ($tag eq 'tar-errors-from-data') {
118                 next if /implausibly old time stamp/;
119             }
120             tag $tag, $_;
121         }
122         close ERRORS;
123     }
124 }
125
126 }
127
128 1;
129
130 # Local Variables:
131 # indent-tabs-mode: nil
132 # cperl-indent-level: 4
133 # End:
134 # vim: syntax=perl sw=4 sts=4 ts=4 et shiftround