Removed upstream dir
[maemian] / nokia-lintian / checks / shared-libs
diff --git a/nokia-lintian/checks/shared-libs b/nokia-lintian/checks/shared-libs
deleted file mode 100644 (file)
index 9ee576a..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-# shared-libs -- lintian check script -*- perl -*-
-
-# Copyright (C) 1998 Christian Schwarz
-#
-# 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 Lintian::shared_libs;
-use strict;
-
-use File::Basename;
-
-use Lintian::Data;
-use Dep;
-use Tags;
-use Util;
-
-sub run {
-
-# Libraries that should only be used in the presence of certain capabilities
-# may be located in subdirectories of the standard ldconfig search path with
-# one of the following names.
-my %hwcap_dir = map { $_ => 1 }
-    qw( i486 i586 i686 cmov tls );
-
-# The following architectures should always have a STACK setting in shared
-# libraries to disable executable stack.  Other architectures don't always add
-# this section and therefore can't be checked.
-my %stack_arches = map { $_ => 1 }
-    qw( alpha
-       amd64
-       i386
-       m68k
-       powerpc
-       s390
-       sparc
-      );
-
-my $ldconfig_dirs = Lintian::Data->new('shared-libs/ldconfig-dirs');
-my $file;
-my $must_call_ldconfig;
-my $postrm = "control/postrm";
-my $postinst = "control/postinst";
-my $preinst = "control/preinst";
-my $prerm = "control/prerm";
-my $shlibs_control_file = "control/shlibs";
-my $symbols_control_file = "control/symbols";
-my %SONAME;
-my %INTERP;
-my %STACK;
-my %TEXTREL;
-my %objsomething;
-my %sharedobject;
-my %index_info;
-my %link_info;
-my @shlibs;
-my @words;
-
-# ---end-of-configuration-part---
-
-my $pkg = shift;
-my $type = shift;
-
-# 1st step: get info about shared libraries installed by this package
-open(IN, '<', "objdump-info")
-    or fail("cannot find objdump-info for $type package $pkg");
-while (<IN>) {
-    chop;
-
-    #skip blank lines
-    next if m/^\s*$/o;
-
-    if (m/^-- (\S+)\s*$/o) {
-       $file = $1;
-       $file =~ s,^(\./)?,,;
-    } elsif (m/^\s*SONAME\s+(\S+)/o) {
-       $SONAME{$file} = $1;
-    } elsif (m/^\s*TEXTREL\s/o) {
-        $TEXTREL{$file} = 1;
-    } elsif (m/^\s*INTERP\s/) {
-       $INTERP{$file} = 1;
-    } elsif (m/^\s*STACK\s/) {
-       $STACK{$file} = 0;
-    } else {
-        if (defined $STACK{$file} and $STACK{$file} eq 0) {
-           m/\sflags\s+(\S+)/o;
-           $STACK{$file} = $1;
-       }
-       else {
-           $objsomething{$file} = 1;
-       }
-    }
-}
-close(IN);
-
-open (IN, '<', "file-info")
-    or fail("cannot find file-info for $type package $pkg");
-while (<IN>) {
-    chomp;
-    # with file names containing colons and spaces, we're fucked.
-    m/^(?:\.\/)?(.+?):\s+(.*)$/o or fail("unrecognized file(1) output: $_");
-    my ($file,$info) = ($1,$2);
-    if ($info =~ m/^[^,]*\bELF\b/ && $info =~ m/shared object/) {
-       $sharedobject{$file} = 1;
-    }
-}
-close(IN);
-
-# 2nd step: read package contents
-my %files;
-open(IN, '<', "index") or fail("cannot open index file index: $!");
-while (<IN>) {
-    chop;
-    @words = split(/\s+/o, $_, 6);
-    my $perm = $words[0];
-    my $cur_file = $words[5];
-    $cur_file =~ s,^(\./),,;
-    $cur_file =~ s/ link to .*//;
-
-    if ($perm =~ m/^l/) {
-       my $link;
-       ($cur_file, $link) = split(' -> ', $cur_file);
-       $link_info{$cur_file} = $link;
-    }
-    $index_info{$cur_file} = 1;
-    $files{$cur_file} = $perm;
-}
-
-for (keys %files) {
-    my ($cur_file, $perm) = ($_, $files{$_});
-
-    # shared library?
-    if (exists $SONAME{$cur_file} or 
-       ($link_info{$cur_file} and exists $SONAME{abs_path(dirname($cur_file)."/".$link_info{$cur_file})})) {
-       # yes!!
-
-       my ($real_file, $real_perm);
-       if ($SONAME{$cur_file}) {
-           $real_file = $cur_file;
-           $real_perm = $perm;
-       } else {
-           $real_file = abs_path(dirname($cur_file)."/".$link_info{$cur_file});
-           $real_perm = $files{$real_file} || $perm;
-       }
-
-       # Now that we're sure this is really a shared library, report on
-       # non-PIC problems.
-        if ($cur_file eq $real_file and $TEXTREL{$cur_file}) {
-            tag "shlib-with-non-pic-code", "$cur_file";
-        }
-
-        # don't apply the permission checks to links
-        # since this only results in doubled messages
-        if ($cur_file eq $real_file) { 
-            # executable?
-            if ($real_perm =~ m/x/) {
-                # yes.  But if the library has an INTERP section, it's designed
-                # to do something useful when executed, so don't report an error.
-                tag "shlib-with-executable-bit", $cur_file, sprintf("%04o",perm2oct($real_perm))
-                    unless $INTERP{$real_file};
-            } elsif ($real_perm ne '-rw-r--r--') {
-                # bad permissions
-                tag "shlib-with-bad-permissions", $cur_file, sprintf("%04o",perm2oct($real_perm));
-            }
-        }
-
-       # Installed in a directory controlled by the dynamic linker?  We have
-       # to strip off directories named for hardware capabilities.
-       my $dirname = dirname($cur_file);
-       my $last;
-       do {
-           $dirname =~ s%/([^/]+)$%%;
-           $last = $1;
-       } while ($last && $hwcap_dir{$last});
-       $dirname .= "/$last" if $last;
-       if ($ldconfig_dirs->known($dirname)) {
-           # yes! so postinst must call ldconfig
-           $must_call_ldconfig = $real_file;
-       }
-
-       # executable stack.  We can only warn about a missing section on some
-       # architectures.  Only warn if there's an Architecture field; if
-       # that's missing, we'll already be complaining elsewhere.
-       if (exists $objsomething{$cur_file}) {
-           if (not defined $STACK{$cur_file}) {
-               if (open(FH, '<', "fields/architecture")) {
-                   my $arch = <FH>;
-                   close FH;
-                   chomp $arch;
-                   tag "shlib-without-PT_GNU_STACK-section", $cur_file
-                       if $stack_arches{$arch};
-               }
-           } elsif ($STACK{$cur_file} ne "rw-") {
-               tag "shlib-with-executable-stack", $cur_file;
-           }
-       }
-    } elsif (exists $objsomething{$cur_file}
-            && $ldconfig_dirs->known(dirname($cur_file))
-            && exists $sharedobject{$cur_file}) {
-       tag "sharedobject-in-library-directory-missing-soname", "$cur_file";
-    }
-}
-
-close(IN);
-
-# 3rd step: check if shlib symlinks are present and in correct order
-for my $shlib_file (keys %SONAME) {
-    # file found?
-    if (not exists $index_info{$shlib_file}) {
-       fail("shlib $shlib_file not found in package (should not happen!)");
-    }
-
-    my ($dir, $shlib_name) = $shlib_file =~ m,(.*)/([^/]+)$,;
-
-    # not a public shared library, skip it
-    next unless $ldconfig_dirs->known($dir);
-
-    # symlink found?
-    my $link_file = "$dir/$SONAME{$shlib_file}";
-    if (not exists $index_info{$link_file}) {
-       tag "ldconfig-symlink-missing-for-shlib", "$link_file $shlib_file $SONAME{$shlib_file}";
-    } else {
-       # $link_file really another file?
-       if ($link_file eq $shlib_file) {
-           # the library file uses its SONAME, this is ok...
-       } else {
-           # $link_file really a symlink?
-           if (exists $link_info{$link_file}) {
-               # yes.
-
-               # $link_file pointing to correct file?
-               if ($link_info{$link_file} eq $shlib_name) {
-                   # ok.
-               } else {
-                   tag "ldconfig-symlink-referencing-wrong-file", "$link_file -> $link_info{$link_file} instead of $shlib_name";
-               }
-           } else {
-               tag "ldconfig-symlink-is-not-a-symlink", "$shlib_file $link_file";
-           }
-
-           # symlink after shlib?
-           if ($index_info{$link_file} < $index_info{$shlib_file}) {
-               tag "ldconfig-symlink-before-shlib-in-deb", "$link_file";
-           }
-       }
-    }
-
-    # determine shlib link name (w/o version)
-    $link_file =~ s/\.so.*$/.so/o;
-
-    # -dev package?
-    if ($pkg =~ m/\-dev$/o) {
-       # yes!!
-
-       # need shlib symlink
-       if (not exists $index_info{$link_file}) {
-           tag "dev-pkg-without-shlib-symlink", "$shlib_file $link_file";
-       }
-    } else {
-       # no.
-
-       # shlib symlink may not exist.
-       # if shlib doesn't _have_ a version, then $link_file and $shlib_file will
-       # be equal, and it's not a development link, so don't complain.
-       if (exists $index_info{$link_file} and $link_file ne $shlib_file) {
-           tag "non-dev-pkg-with-shlib-symlink", "$shlib_file $link_file";
-       }
-    }
-}
-
-# 4th step: check shlibs control file
-my $version;
-if (open (VERSION, '<', 'fields/version')) {
-    $version = <VERSION>;
-    close VERSION;
-    chomp $version;
-}
-my $provides = $pkg . "( = $version)";
-if (open (PROVIDES, '<', 'fields/provides')) {
-    my $line = <PROVIDES>;
-    close PROVIDES;
-    chomp $line;
-    $provides .= ", $line";
-}
-$provides = Dep::parse($provides);
-
-my %shlibs_control;
-my %symbols_control;
-
-@shlibs = grep { !m,^lib/libnss_[^.]+\.so(\.[0-9]+)$, } keys %SONAME;
-if ($#shlibs == -1) {
-    # no shared libraries included in package, thus shlibs control file should
-    # not be present
-    if (-f $shlibs_control_file) {
-       tag "pkg-has-shlibs-control-file-but-no-actual-shared-libs", "";
-    }
-} else {
-    # shared libraries included, thus shlibs control file has to exist
-    if (not -f $shlibs_control_file) {
-       if ($type ne 'udeb') {
-           for my $shlib (@shlibs) {
-               # skip it if it's not a public shared library
-               next unless $ldconfig_dirs->known(dirname($shlib));
-               tag "no-shlibs-control-file", "$shlib";
-           }
-       }
-    } else {
-       my %shlibs_control_used;
-       my @shlibs_depends;
-       open(SHLIBS, '<', $shlibs_control_file)
-           or fail("cannot open shlibs control file $shlibs_control_file for reading: $!");
-       while (<SHLIBS>) {
-           chop;
-           next if m/^\s*$/ or /^#/;
-
-           # We exclude udebs from the checks for correct shared library
-           # dependencies, since packages may contain dependencies on
-           # other udeb packages.
-           my $udeb="";
-           $udeb = "udeb: " if s/^udeb:\s+//o;
-           @words = split(/\s+/o,$_);
-           my $shlibs_string = $udeb.$words[0].' '.$words[1];
-           if ($shlibs_control{$shlibs_string}) {
-               tag "duplicate-entry-in-shlibs-control-file", $shlibs_string;
-           } else {
-               $shlibs_control{$shlibs_string} = 1;
-               push (@shlibs_depends, join (' ', @words[2 .. $#words]))
-                   unless $udeb;
-           }
-       }
-       close(SHLIBS);
-       my $shlib_name;
-       for my $shlib (@shlibs) {
-           $shlib_name = $SONAME{$shlib};
-           $shlib_name = format_soname($shlib_name);
-           $shlibs_control_used{$shlib_name} = 1;
-           $shlibs_control_used{"udeb: ".$shlib_name} = 1;
-           unless (exists $shlibs_control{$shlib_name}) {
-               # skip it if it's not a public shared library
-               next unless $ldconfig_dirs->known(dirname($shlib));
-               # no!!
-               tag "shlib-missing-in-control-file", $shlib_name, 'for', $shlib;
-           }
-       }
-       for $shlib_name (keys %shlibs_control) {
-           tag "unused-shlib-entry-in-control-file", $shlib_name
-               unless $shlibs_control_used{$shlib_name};
-       }
-
-       # Check that all of the packages listed as dependencies in the shlibs
-       # file are satisfied by the current package or its Provides.
-       # Normally, packages should only declare dependencies in their shlibs
-       # that they themselves can satisfy.
-       #
-       # Deduplicate the list of dependencies before warning so that we don't
-       # dupliate warnings.
-       my %seen;
-       @shlibs_depends = grep { !$seen{$_}++ } @shlibs_depends;
-       for my $depend (@shlibs_depends) {
-           unless (Dep::implies($provides, Dep::parse($depend))) {
-               tag "shlibs-declares-dependency-on-other-package", $depend;
-           }
-       }
-    }
-}
-
-# 5th step: check symbols control file
-if ($#shlibs == -1) {
-    # no shared libraries included in package, thus symbols control file should
-    # not be present
-    if (-f $symbols_control_file) {
-        tag "pkg-has-symbols-control-file-but-no-shared-libs", "";
-    }
-} elsif (not -f $symbols_control_file) {
-    if ($type ne 'udeb') {
-       for my $shlib (@shlibs) {
-           # skip it if it's not a public shared library
-           next unless $ldconfig_dirs->known(dirname($shlib));
-           tag "no-symbols-control-file", "$shlib";
-       }
-    }
-} elsif (open(IN, '<', $symbols_control_file)) {
-    my $version_wo_rev = $version;
-    $version_wo_rev =~ s/^(.+)-([^-]+)$/$1/;
-    my ($full_version_count, $full_version_sym) = (0, undef);
-    my ($debian_revision_count, $debian_revision_sym) = (0, undef);
-    my ($soname, $dep_package, $dep);
-    my %symbols_control_used;
-    my @symbols_depends;
-    my $dep_templates = 0;
-    my $meta_info_seen = 0;
-
-    while (<IN>) {
-       chomp;
-       next if m/^\s*$/ or /^#/;
-
-       if (m/^([^\s|*]\S+)\s(\S+)(?:\s(\S+))?/) {
-           # soname, main dependency template
-
-           ($soname, $dep_package, $dep) = ($1, $2, $3);
-           $dep ||= '';
-           $soname = format_soname($soname);
-
-           if ($symbols_control{$soname}) {
-               tag "duplicate-entry-in-symbols-control-file", $soname;
-           } else {
-               $symbols_control{$soname} = 1;
-               push @symbols_depends, $dep_package . ' ' . $dep;
-           }
-
-           $dep_templates = 0;
-           $meta_info_seen = 0;
-       } elsif (m/^\|\s+(\S+)\s(\S+(\s\S+)?)$/) {
-           # alternative dependency template
-
-           if ($meta_info_seen or not defined $soname) {
-               tag "syntax-error-in-symbols-file", $.;
-           }
-
-           ($dep_package, $dep) = ($1, $2);
-           push @symbols_depends, $dep_package . ' ' . $dep;
-           $dep_templates++;
-       } elsif (m/^\*\s(\S+):\s(\S+)/) {
-           # meta-information
-
-           # This should probably be in a hash, but there's
-           # only one supported value currently
-           tag "unknown-meta-field-in-symbols-file", "$1, line $."
-               unless $1 eq 'Build-Depends-Package';
-           tag "syntax-error-in-symbols-file", $.
-               if $dep_templates > 0;
-
-           $meta_info_seen = 1;
-       } elsif (m/^\s+(\S+)\s(\S+)(?:\s(\S+(\s\S+)?))?$/) {
-           # Symbol definition
-
-           tag "syntax-error-in-symbols-file", $.
-               unless defined $soname;
-
-           my ($sym, $v, $dep_order) = ($1, $2, $3);
-           $dep_order ||= '';
-
-           if (($v eq $version) and ($version =~ /-/)) {
-               $full_version_sym ||= $sym;
-               $full_version_count++;
-           }
-           if (($v =~ /-/) and (not $v =~ /~$/) and ($v ne $version_wo_rev)) {
-               $debian_revision_sym ||= $sym;
-               $debian_revision_count++;
-           }
-
-           if (length $dep_order) {
-               if ($dep_order !~ /^\d+$/ or $dep_order > $dep_templates) {
-                   tag "invalid-template-id-in-symbols-file", $.;
-               }
-           }
-       } else {
-           # Unparseable line
-
-           tag "syntax-error-in-symbols-file", $.;
-       }
-    }
-    close IN;
-    if ($full_version_count) {
-       $full_version_count--;
-       my $others = '';
-       if ($full_version_count > 0) {
-           $others = " and $full_version_count others";
-       }
-       tag "symbols-file-contains-current-version-with-debian-revision",
-           "on symbol $full_version_sym$others";
-    }
-    if ($debian_revision_count) {
-       $debian_revision_count--;
-       my $others = '';
-       if ($debian_revision_count > 0) {
-           $others = " and $debian_revision_count others";
-       }
-       tag "symbols-file-contains-debian-revision",
-           "on symbol $debian_revision_sym$others";
-    }
-    my $shlib_name;
-    for my $shlib (@shlibs) {
-       $shlib_name = $SONAME{$shlib};
-       $shlib_name = format_soname($shlib_name);
-       $symbols_control_used{$shlib_name} = 1;
-       $symbols_control_used{"udeb: ".$shlib_name} = 1;
-       unless (exists $symbols_control{$shlib_name}) {
-           # skip it if it's not a public shared library
-           next unless $ldconfig_dirs->known(dirname($shlib));
-           tag "shlib-missing-in-symbols-control-file", $shlib_name, 'for', $shlib;
-       }
-    }
-    for $shlib_name (keys %symbols_control) {
-       tag "unused-shlib-entry-in-symbols-control-file", $shlib_name
-           unless $symbols_control_used{$shlib_name};
-    }
-
-    # Check that all of the packages listed as dependencies in the symbols
-    # file are satisfied by the current package or its Provides.
-    # Normally, packages should only declare dependencies in their symbols
-    # files that they themselves can satisfy.
-    #
-    # Deduplicate the list of dependencies before warning so that we don't
-    # dupliate warnings.
-    my %seen;
-    @symbols_depends = grep { !$seen{$_}++ } @symbols_depends;
-    for my $depend (@symbols_depends) {
-       unless (Dep::implies($provides, Dep::parse($depend))) {
-           tag "symbols-declares-dependency-on-other-package", $depend;
-       }
-    } 
-}
-
-# Compare the contents of the shlibs and symbols control files
-if (keys %shlibs_control and keys %symbols_control) {
-    for my $key (keys %symbols_control) {
-       unless (exists $shlibs_control{$key}) {
-           tag "symbols-declared-but-not-shlib", $key;
-       }
-    }
-}
-
-# 6th step: check pre- and post- control files
-if (-f $preinst) {
-    local $_ = slurp_entire_file($preinst);
-    if (/^[^\#]*\bldconfig\b/m) {
-       tag "preinst-calls-ldconfig", ""
-    }
-}
-
-my $we_call_postinst=0;
-if (-f $postinst) {
-    local $_ = slurp_entire_file($postinst);
-
-    # Decide if we call ldconfig
-    if (/^[^\#]*\bldconfig\b/m) {
-       $we_call_postinst=1;
-    }
-}
-
-if ($type eq 'udeb') {
-    tag "udeb-postinst-must-not-call-ldconfig"
-       if $we_call_postinst;
-} else {
-    tag "postinst-has-useless-call-to-ldconfig", ""
-       if $we_call_postinst and not $must_call_ldconfig;
-    tag "postinst-must-call-ldconfig", "$must_call_ldconfig"
-       if not $we_call_postinst and $must_call_ldconfig;
-}
-
-if (-f $prerm) {
-    local $_ = slurp_entire_file($prerm);
-    if (/^[^\#]*\bldconfig\b/m) {
-       tag "prerm-calls-ldconfig", "";
-    }
-}
-
-if (-f $postrm) {
-    local $_ = slurp_entire_file($postrm);
-
-    # Decide if we call ldconfig
-    if (/^[^\#]*\bldconfig\b/m) {
-       tag "postrm-has-useless-call-to-ldconfig", ""
-           unless $must_call_ldconfig;
-    } else {
-       tag "postrm-should-call-ldconfig", "$must_call_ldconfig"
-           if $must_call_ldconfig;
-    }
-
-    # Decide if we do it safely
-    s/\bldconfig\b/BldconfigB/g;
-    s/[ \t]//g;
-    # this one matches code from debhelper
-    s/^if\["\$1"=.?remove.?\];?\n*then\n*BldconfigB//gm;
-    # variations...
-    s/^if\[.?remove.?="\$1"\];?\n*then\n*BldconfigB//gm;
-    s/^\["\$1"=.?remove.?\]\&&BldconfigB//gm;
-    s/^\[.?remove.?="\$1"\]&&BldconfigB//gm;
-    s/remove(?:\|[^)]+)*\).*?BldconfigB.*?(;;|esac)//s;
-
-    if (/^[^\#]*BldconfigB/m) {
-        tag "postrm-unsafe-ldconfig", "";
-    }
-}
-
-}
-
-# make /tmp/baz/baz.txt from /tmp/foo/../bar/../baz/baz.txt
-sub abs_path {
-    my $path = shift;
-    while($path =~ s!/[^/]*/\.\./!/!g){1};
-    return $path;
-}
-
-sub format_soname {
-    my $soname = shift;
-
-    # libfoo.so.X.X
-    if ($soname =~ m/(.+)\.so\.(.*)$/) {
-       $soname = "$1 $2";
-    # libfoo-X.X.so
-    } elsif ($soname =~ m/(.+)\-(\w[\w\.]*)\.so$/) {
-       $soname = "$1 $2";
-    }
-
-    return $soname
-}
-
-1;
-
-# Local Variables:
-# indent-tabs-mode: t
-# cperl-indent-level: 4
-# End:
-# vim: syntax=perl sw=4 ts=8