Add checking script for the stat bug. - gentoo-tools - Some Gentoo helper tools
       
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit e84d5e93a8c939af2ad215f71cbcb058ebf4afb0
 (DIR) parent 5b592d35ecc16a01808adddb9b075010a6cea180
 (HTM) Author: Christoph Lohmann <20h@r-36.net>
       Date:   Wed,  9 Sep 2015 17:37:01 +0200
       
       Add checking script for the stat bug.
       
       Diffstat:
         bin/echeck-stat-brokeness           |     221 +++++++++++++++++++++++++++++++
       
       1 file changed, 221 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/bin/echeck-stat-brokeness b/bin/echeck-stat-brokeness
       @@ -0,0 +1,221 @@
       +#!/usr/bin/perl
       +#
       +# This script was taken from the source below and is licenses under different
       +# terms. It is renamed to fit the naming convention of all other tools.
       +# -- Christoph Lohmann <20h@r-36.net>, 2015-09-09
       +#
       +# A Perl script for evaluating and summarising which executables in
       +# the given directories depend on the old 32-bit stat() family APIs.
       +#
       +# Usage: summarise_stat.pl directory [...]
       +#
       +# Copyright (c) 2007,2013 Silicon Graphics, Inc.  All Rights Reserved.
       +# By Greg Banks <gnb@melbourne.sgi.com>
       +#
       +# Updated 20130511 to correctly diagnose 64b executables
       +#
       +# 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, write to the Free Software
       +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       +#
       +
       +use strict;
       +use warnings;
       +
       +my @pathnames;                # file and directories to read, from the commandline
       +my @summ;
       +my $nbroken = 0;
       +my $total = 0;
       +my $debug = 0;
       +my @broken_by_status;
       +
       +# Parse arguments
       +@pathnames = @ARGV;
       +if ( scalar @pathnames == 0 )
       +{
       +        my $baseargv0 = (split /\//, $0)[-1];
       +        die "usage: $baseargv0 path0 [path1 ...]\n"
       +}
       +
       +my @status_strings =
       +(
       +        "cannot be read (permission denied)",
       +        "are scripts (shell, perl, whatever)",
       +        "are 64-bit executables",
       +        "don't use any stat() family calls at all",
       +        "use 32-bit stat() family interfaces only",
       +        "use 64-bit stat64() family interfaces only",
       +        "use both 32-bit and 64-bit stat() family interfaces",
       +);
       +my @status_broken = (
       +        0,
       +        0,
       +        0,
       +        0,
       +        1,
       +        0,
       +        1
       +);
       +
       +sub MAX_STATUS { return 6 };
       +sub status
       +{
       +        my ($r) = @_;
       +        return 0 if ($r->{no_perm});
       +        return 1 if ($r->{not_exe});
       +        return 2 if ($r->{elf64b});
       +        return 3 + ($r->{used64} ? 2 : 0) + ($r->{used32} ? 1 : 0);
       +}
       +
       +map { $summ[$_] = 0 } (0..MAX_STATUS);
       +map { $broken_by_status[$_] = [] } (0..MAX_STATUS);
       +
       +# Function to scan a file
       +sub scan_file
       +{
       +        my ($path) = @_;
       +        my $fh;
       +
       +        my %res =
       +        (
       +                elf64b => 0,
       +                used32 => 0,
       +                used64 => 0,
       +                not_exe => 0,
       +                no_perm => 0,
       +        );
       +
       +        open $fh,'-|', "file -L \"$path\" 2>&1"
       +                or return;
       +        $_ = readline $fh;
       +        chomp;
       +        if (m/ELF 64-bit/)
       +        {
       +                $res{elf64b} = 1;
       +        }
       +        close $fh;
       +        $fh = undef;
       +
       +        open $fh,'-|', "nm -uD \"$path\" 2>&1"
       +                or return;
       +        while (<$fh>)
       +        {
       +                chomp;
       +
       +                if (m/File format not recogni[sz]ed/)
       +                {
       +                        $res{not_exe} = 1;
       +                }
       +                elsif (m/Permission denied/)
       +                {
       +                        $res{no_perm} = 1;
       +                }
       +                elsif (m/^\s+U __(|l|f)xstat$/)
       +                {
       +                        $res{used32}++;
       +                }
       +                elsif (m/^\s+U __(|l|f)xstat64$/)
       +                {
       +                        $res{used64}++;
       +                }
       +        }
       +        close $fh;
       +
       +        print "$res{used32} $res{used64} $res{not_exe} $res{no_perm} $res{elf64b} $path\n" if $debug;
       +
       +        my $s = status(\%res);
       +        if ($status_broken[$s])
       +        {
       +            push(@{$broken_by_status[$s]}, $path);
       +            $nbroken++;
       +        }
       +        $summ[$s]++;
       +        $total++;
       +}
       +
       +# Function to scan a directory
       +sub scan_directory
       +{
       +        my ($path) = @_;
       +        my $dh;
       +        return unless opendir($dh,$path);
       +        while (my $d = readdir $dh)
       +        {
       +                next if ($d =~ m/^\./);
       +                print "$path/$d\n" if $debug;
       +                scan_path("$path/$d");
       +        }
       +        closedir $dh;
       +}
       +
       +# Function to scan something that might be a file or a directory
       +sub scan_path
       +{
       +        my ($path) = @_;
       +        print "scan_path($path)\n" if $debug;
       +        if ( -l $path )
       +        {
       +            # Ignore symlinks to files
       +            return if ( -f $path );
       +            # Follow symlinks to directories, but avoid deep recursion
       +            # on silly compatibility symlinks like /usr/bin/X11 -> .
       +            return if ( readlink($path) eq "." );
       +        }
       +        if ( -d $path )
       +        {
       +                scan_directory($path);
       +        }
       +        elsif ( -e $path )
       +        {
       +                scan_file($path);
       +        }
       +}
       +
       +# Scan files and directories specified in the commandline
       +foreach my $path (@pathnames)
       +{
       +        scan_path($path);
       +}
       +
       +if ( !$total )
       +{
       +    printf "No files found.\n";
       +    exit;
       +}
       +
       +# generate a summary
       +print "Summary by status\n";
       +print "-----------------\n";
       +foreach my $s (0..MAX_STATUS)
       +{
       +        next if $summ[$s] == 0;
       +        printf "%7d %4.1f%% %s%s\n",
       +                $summ[$s], (100.0 * $summ[$s] / $total), $status_strings[$s],
       +                ($status_broken[$s] ? " [BROKEN]" : "");
       +}
       +printf "%7d %4.1f%% BROKEN\n",
       +        $nbroken, (100.0 * $nbroken / $total);
       +
       +# list all broken files
       +if ($nbroken)
       +{
       +        print "List of broken files\n";
       +        print "--------------------\n";
       +        foreach my $s (0..MAX_STATUS)
       +        {
       +                next if !$status_broken[$s];
       +                next if !scalar(@{$broken_by_status[$s]});
       +                printf "These %s\n", $status_strings[$s];
       +                map { printf "    %s\n", $_; } @{$broken_by_status[$s]};
       +        }
       +}