Added lots more modules from lintian. Maemian appears to work.
[maemian] / checks / deb-format
diff --git a/checks/deb-format b/checks/deb-format
new file mode 100644 (file)
index 0000000..bb337de
--- /dev/null
@@ -0,0 +1,134 @@
+# deb-format -- lintian check script -*- perl -*-
+
+# Copyright (C) 2009 Russ Allbery
+#
+# 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, see <http://www.gnu.org/licenses/>.
+
+package Maemian::deb_format;
+use strict;
+use Tags;
+
+use Maemian::Command qw(spawn);
+
+# The files that contain error messages from tar, which we'll check and issue
+# tags for if they contain something unexpected, and their corresponding tags.
+our %ERRORS = ('control-errors'       => 'tar-errors-from-control',
+               'control-index-errors' => 'tar-errors-from-control',
+               'index-errors'         => 'tar-errors-from-data',
+               'unpacked-errors'      => 'tar-errors-from-data');
+
+# Used to match Ubuntu distribution names in target distributions.
+our $UBUNTU_REGEX;
+{
+    my $dists = Maemian::Data->new('changelog-file/ubuntu-dists');
+    my $string = join ('|', 'ubuntu', $dists->all);
+    $UBUNTU_REGEX = qr/$string/o;
+}
+
+sub run {
+
+my $pkg = shift;
+my $type = shift;
+my $info = shift;
+
+# Run ar t on the *.deb file.  deb will be a symlink to it.
+my $okay = 0;
+my $opts = {};
+my $success = spawn($opts, ['ar', 't', 'deb']);
+if ($success) {
+    my @members = split("\n", ${ $opts->{out} });
+    if (@members != 3) {
+        my $count = scalar(@members);
+        tag 'malformed-deb-archive',
+            "found $count members instead of 3";
+    } elsif ($members[0] ne 'debian-binary') {
+        tag 'malformed-deb-archive',
+            "first member $members[0] not debian-binary";
+    } elsif ($members[1] ne 'control.tar.gz') {
+        tag 'malformed-deb-archive',
+            "second member $members[1] not control.tar.gz";
+    } elsif ($members[2] eq 'data.tar.lzma') {
+        # Ubuntu's archive allows lzma packages.
+        my ($entry) = $info->changelog->data;
+        my $distribution = $entry->Distribution;
+        if ($distribution =~ /$UBUNTU_REGEX/) {
+            $okay = 1;
+        } else {
+            tag 'lzma-deb-archive';
+        }
+    } elsif ($members[2] !~ /^data\.tar\.(gz|bz2)\z/) {
+        tag 'malformed-deb-archive',
+            "third member $members[2] not data.tar.(gz|bz2)";
+    } else {
+        $okay = 1;
+    }
+} else {
+    # unpack will probably fail so we'll never get here, but may as well be
+    # complete just in case.
+    my $error = ${ $opts->{err} };
+    $error =~ s/\n.*//s;
+    $error =~ s/^ar:\s*//;
+    $error =~ s/^deb:\s*//;
+    tag 'malformed-deb-archive', "ar error: $error";
+}
+
+# Check the debian-binary version number.  We probably won't get here because
+# dpkg-deb will decline to unpack the deb, but be thorough just in case.  We
+# may eventually have a case where dpkg supports a newer format but it's not
+# permitted in the archive yet.
+if ($okay) {
+    my $opts = {};
+    my $success = spawn($opts, ['ar', 'p', 'deb', 'debian-binary']);
+    if (not $success) {
+        tag 'malformed-deb-archive', "can't read debian-binary member";
+    } elsif (${ $opts->{out} } !~ /^2\.\d+\n/) {
+        my ($version) = split("\n", ${ $opts->{out} });
+        tag 'malformed-deb-archive', "version $version not 2.0";
+    }
+}
+
+# If either control-errors or index-errors exist, tar produced error output
+# when processing the package.  We want to report those as tags unless they're
+# just tar noise that doesn't represent an actual problem.
+for my $file (keys %ERRORS) {
+    my $tag = $ERRORS{$file};
+    if (-s $file) {
+        open(ERRORS, '<', $file) or fail("cannot open $file: $!");
+        local $_;
+        while (<ERRORS>) {
+            chomp;
+            s,^(?:[/\w]+/)?tar: ,,;
+
+            # Record size errors are harmless.  Ignore implausibly old
+            # timestamps in the data section since we already check for that
+            # elsewhere, but still warn for control.
+            next if /^Record size =/;
+            if ($tag eq 'tar-errors-from-data') {
+                next if /implausibly old time stamp/;
+            }
+            tag $tag, $_;
+        }
+        close ERRORS;
+    }
+}
+
+}
+
+1;
+
+# Local Variables:
+# indent-tabs-mode: nil
+# cperl-indent-level: 4
+# End:
+# vim: syntax=perl sw=4 sts=4 ts=4 et shiftround