rpm-build/scripts/magic.prov
2002-03-25 20:16:26 +00:00

168 lines
3.5 KiB
Perl
Executable File

#!/usr/bin/perl
use File::Basename;
use Getopt::Long;
# this dependency analysis program is the only one which need to know
# the RPM buildroot to do its work.
# Figuring out what files are really executables via magic numbers is
# hard. Not only is every '#!' an executable of some type (with a
# potentially infinite supply of interpreters) but there are thousands
# of valid binary magic numbers for old OS's and old CPU types.
# Permissions do not always help discriminate binaries from the rest
# of the files, on Solaris the shared libraries are marked as
# 'executable'.
# -rwxr-xr-x 1 bin bin 1013248 Jul 1 1998 /lib/libc.so.1
# I would like to let the 'file' command take care of the magic
# numbers for us. Alas! under linux file prints different kind of
# messages for each interpreter, there is no common word 'script' to
# look for.
# ' perl commands text'
# ' Bourne shell script text'
# ' a /usr/bin/wish -f script text'
# WORSE on solaris there are entries which say:
# ' current ar archive, not a dynamic executable or shared object'
# how do I grep for 'executable' when people put a 'not executable' in
# there? I trim off everything after the first comma (if there is
# one) and if the result has the string 'executable' in it then it may
# be one.
# so we must also do some magic number processing ourselves, and be
# satisfied with 'good enough'.
# I look for files which have atleast one of the executable bits set
# and are either labled 'executable' by the file command (see above
# restriction) OR have a '#!' as their first two characters.
$is_mode_executable=oct(111);
# set a known path
$ENV{'PATH'}= (
':/usr/bin'.
':/bin'.
'');
# taint perl requires we clean up these bad environmental variables.
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
$BUILDROOT = '';
%option_linkage = (
"buildroot" => \$BUILDROOT,
);
if( !GetOptions (\%option_linkage, "buildroot=s") ) {
die("Illegal options in \@ARGV: '@ARGV'\n");
}
if ($BUILDROOT == '/') {
$BUILDROOT = '';
}
if ("@ARGV") {
foreach (@ARGV) {
process_file($_);
}
} else {
# notice we are passed a list of filenames NOT as common in unix the
# contents of the file.
foreach (<>) {
process_file($_);
}
}
foreach $module (sort keys %provides) {
print "executable($module)\n";
}
exit 0;
sub is_file_script {
my ($file) = @_;
chomp $file;
my $out = 0;
open(FILE, "<$file")||
die("$0: Could not open file: '$file' : $!\n");
my $rc = sysread(FILE,$line,2);
if ( ($rc > 1) && ($line =~ m/^\#\!/) ) {
$out = 1;
}
close(FILE) ||
die("$0: Could not close file: '$file' : $!\n");
return $out;
}
sub is_file_binary_executable {
my ($file) = @_;
$file_out=`file $file`;
# trim off any extra descriptions.
$file_out =~ s/\,.*$//;
my $out = 0;
if ($file_out =~ m/executable/ ) {
$out = 1;
}
return $out;
}
sub process_file {
my ($file) = @_;
chomp $file;
my $prov_name = $file;
$prov_name =~ s!^$BUILDROOT!!;
# If its a link find the file it points to. Dead links do not
# provide anything.
while (-l $file) {
my $newfile = readlink($file);
if ($newfile !~ m!^/!) {
$newfile = dirname($file).'/'.$newfile;
} else {
$newfile = $BUILDROOT.$newfile;
}
$file = $newfile;
}
(-f $file) || return ;
( (stat($file))[2] & $is_mode_executable ) || return ;
is_file_script($file) ||
is_file_binary_executable($file) ||
return ;
$provides{$prov_name}=1;
$provides{basename($prov_name)}=1;
return ;
}