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