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