gentoo-tools

Some Gentoo helper tools
git clone git://r-36.net/gentoo-tools
Log | Files | Refs | LICENSE

commit e84d5e93a8c939af2ad215f71cbcb058ebf4afb0
parent 5b592d35ecc16a01808adddb9b075010a6cea180
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(-)

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]}; + } +}