#!/usr/bin/perl # # A Perl script for evaluating and summarising which executables in # the given directories depend on the old 32-bit stat() family APIs. # # Usage: summariese-stat64.pl directory [...] # # Copyright (c) 2007 Silicon Graphics, Inc. All Rights Reserved. # By Greg Banks # # 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 @results; # array of { path, used32, used64, not_exe, no_perm } hashes my $verbose = 0; sub usage { print STDERR "Usage: summarise-stat64 [--verbose] file_or_directory...\n"; exit 1; } # Parse arguments foreach my $a (@ARGV) { if ($a eq '--verbose' || $a eq '-v') { $verbose++; } elsif ($a =~ m/^-/) { usage; } else { push(@pathnames,$a); } } usage unless scalar(@pathnames); # Function to scan a file sub scan_file { my ($path) = @_; my $fh; my %res = ( path => $path, used32 => 0, used64 => 0, not_exe => 0, no_perm => 0, ); open $fh,'-|', "nm -uD \"$path\" 2>&1" or return; while (<$fh>) { chomp; if (m/File format not recognized/) { $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; push(@results, \%res); } # 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 $verbose > 2; 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 $verbose > 2; 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); } my @status_strings = ( "cannot be read (permission denied)", "are scripts (shell, perl, whatever)", "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", ); sub STATUS_UNCLEAN { return 3 }; sub STATUS_MIXED { return 5 }; sub STATUS_MAX { return 5 }; sub status { my ($r) = @_; return 0 if ($r->{no_perm}); return 1 if ($r->{not_exe}); return 2 + ($r->{used64} ? 2 : 0) + ($r->{used32} ? 1 : 0); } # Function to generate a summary sub emit_summary { my @summ; my $total = 0; foreach my $r (@results) { my $s = status($r); $summ[$s] = 0 unless defined $summ[$s]; $summ[$s]++; $total++; printf "%s %s\n", $r->{path}, $status_strings[$s] if ($verbose && ($s == STATUS_UNCLEAN || $s == STATUS_MIXED)); } foreach my $s (0..STATUS_MAX) { next unless defined $summ[$s]; printf "%7d %4.1f%% %s\n", $summ[$s], (100.0 * $summ[$s] / $total), $status_strings[$s]; } } # Function to dump raw data sub emit_raw { foreach my $r (@results) { print "$r->{used32} $r->{used64} $r->{not_exe} $r->{no_perm} $r->{path}\n"; } } emit_raw if $verbose > 1; emit_summary;