# infofiles -- lintian check script -*- perl -*- # Copyright (C) 1998 Christian Schwarz # Copyright (C) 2001 Josip Rodin # # 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. package Maemian::infofiles; use strict; use lib "$ENV{'MAEMIAN_ROOT'}/checks/"; use common_data; use Tags; use Util; use File::Basename; sub run { my $pkg = shift; my $type = shift; my $info = shift; my %preinst; my %postinst; my %prerm; my %postrm; my %missing_section; # check maintainer scripts (for install-info invocation) check_script("preinst", \%preinst) if (-f "control/preinst"); check_script("postinst", \%postinst) if (-f "control/postinst"); check_script("prerm", \%prerm) if (-f "control/prerm"); check_script("postrm", \%postrm) if (-f "control/postrm"); # Read package contents... foreach my $file (sort keys %{$info->index}) { my $index_info = $info->index->{$file}; my $file_info = $info->file_info->{$file}; my $link = $index_info->{link} || ''; my ($fname, $path, $suffix) = fileparse($file); next unless ($index_info->{type} =~ m,^[\-lh],o) and ($path =~ m,^usr/share/info/, or $path =~ m,^usr/info/,); # Analyze the file names making sure the documents are named properly. # Note that Emacs 22 added support for images in info files, so we have to # accept those and ignore them. Just ignore .png files for now. my @fname_pieces = split /\./, $fname; my $ext = pop @fname_pieces; if ($ext eq "gz") { # ok! if ($index_info->{type} =~ m,^[-h],o) { # compressed with maximum compression rate? if ($file_info !~ m/gzip compressed data/o) { tag "info-document-not-compressed-with-gzip", "$file"; } else { if ($file_info !~ m/max compression/o) { tag "info-document-not-compressed-with-max-compression", "$file"; } } } } elsif ($ext eq 'png') { next; } else { push (@fname_pieces, $ext); tag "info-document-not-compressed", "$file"; } my $infoext = pop @fname_pieces; unless ($infoext && $infoext =~ /info(-\d)?/) { # it's not foo.info unless (!@fname_pieces) { # it's not foo{,-{1,2,3,...}} tag "info-document-has-wrong-extension", "$file"; } } # If this is the main info file (no numeric extension). make sure it has # appropriate dir entry information. if ($fname !~ /-\d+\.gz/ && $file_info =~ /gzip compressed data/) { my $pid = open INFO, '-|'; if (not defined $pid) { fail("cannot fork: $!"); } elsif ($pid == 0) { my %newenv = (LANG => 'C', PATH => $ENV{PATH}); undef %ENV; %ENV = %newenv; exec "zcat \Qunpacked/$file\E 2>&1" or fail("cannot run zcat: $!"); } local $_; my ($section, $start, $end); while () { $section = 1 if /INFO-DIR-SECTION\s+\S/; } close INFO; $missing_section{$file} = 1 unless $section; } } # policy 13.2 says prerm and postinst if ($postrm{'calls-install-info'}) { tag "postrm-calls-install-info", ""; } if ($preinst{'calls-install-info'}) { tag "preinst-calls-install-info", ""; } if ($postinst{'calls-install-info'}) { tag "install-info-not-called-with-quiet-option", "" unless $postinst{'calls-install-info-quiet'}; } if ($prerm{'calls-install-info'}) { # it must use the --quiet option tag "install-info-not-called-with-quiet-option", "" unless $prerm{'calls-install-info-quiet'}; } # Currently we assume all the info pages are fine if any of them are installed # with an explicit --section option. It would be nice to be stricter. for my $file (keys %missing_section) { tag "info-document-missing-dir-section", "$file" unless ($postinst{'calls-install-info-section'}); } # Ideally we'd check whether all documents installed are removed, # but for now we assume that if any are removed then they all are if ($postinst{'calls-install-info'}) { tag "info-documents-not-removed", "" unless ($prerm{'calls-install-info-remove'}); } } # ----------------------------------- sub check_script { my ($script,$pres) = @_; my ($no_check_menu,$no_check_installdocs); my $interp; open(IN, '<', "control/$script") or fail("cannot open maintainer script control/$script for reading: $!"); $interp = ; $interp = '' unless defined $interp; if ($interp =~ m,^\#\!\s*/bin/$known_shells_regex,) { $interp = 'sh'; } elsif ($interp =~ m,^\#\!\s*/usr/bin/perl,) { $interp = 'perl'; } else { if ($interp =~ m,^\#\!\s*(.+),) { $interp = $1; } else { # hmm, doesn't seem to start with #! # is it a binary? look for ELF header if ($interp =~ m/^\177ELF/) { return; # nothing to do here } $interp = 'unknown'; } } my $hold; while () { s/\s+#.*$//; # this wraps a previous line continuation into the current line if (defined $hold) { $_ = "$hold $_"; $hold = undef; } # check if install-info is called and if so, is it called properly if (m/install-info/o) { if (m,\\$,) { $hold = substr($_, 0, -1); next; } $pres->{'calls-install-info'} = 1; my @pieces = split(/\s+/); for my $piece (@pieces) { if ($piece eq '--quiet') { $pres->{'calls-install-info-quiet'} = 1; } elsif ($piece eq '--section') { $pres->{'calls-install-info-section'} = 1; } elsif ($piece eq '--remove' or $piece eq '--remove-exactly') { $pres->{'calls-install-info-remove'} = 1; } } } } close IN; } 1; # vim: syntax=perl