| version 1.12, 2008/09/16 23:38:04 |
version 1.13, 2008/09/30 21:54:01 |
|
|
| #!/usr/bin/perl |
#!/bin/sh |
| # $RedRiver: find_depends,v 1.11 2008/09/16 22:28:53 andrew Exp $ |
# $RedRiver$ |
| use strict; |
|
| use warnings; |
|
| |
|
| my %opts; |
find_depends() { |
| my @Files; |
local _file="$1" |
| |
local _line |
| |
|
| foreach (@ARGV) { |
test -z "$_file" && continue |
| if (/^-+(\w+)$/) { |
|
| $opts{$1} = 1; |
|
| } else { |
|
| push @Files, $_; |
|
| } |
|
| } |
|
| |
|
| Help() if $opts{h} || $opts{help}; |
/usr/bin/ldd "$_file" | awk '$7 ~ /^\// { print $7 }' | { |
| Usage() unless @Files; |
while read _line; do |
| |
test -z "$_line" && continue |
| |
echo $_line |
| |
|
| my %libs; |
test X"$_file" == X"$_line" && continue |
| |
find_depends "$_line" |
| foreach my $file (@Files) { |
done |
| my $l = find_libs($file); |
|
| |
|
| foreach (keys %{ $l }) { |
|
| $libs{$_} = $l->{$_}; |
|
| } |
|
| } |
|
| |
|
| foreach (keys %libs) { |
|
| print $libs{$_}, "\n"; |
|
| } |
|
| |
|
| exit; |
|
| |
|
| sub Usage |
|
| { |
|
| print "Usage: $0 [-v] file [file2 [file3 [...]]]\n"; |
|
| exit; |
|
| } |
|
| |
|
| sub Help |
|
| { |
|
| print <<EOL; |
|
| Hopefully finds all libraries that are required by an executable |
|
| or shared library. |
|
| |
|
| Usage: |
|
| $0 [-v] file [file2 [file3 [...]]] |
|
| |
|
| Example: |
|
| find /var/www/ -name *.so* | xargs find_depends | \\ |
|
| sort -u | xargs -I {} cp {} /var/www{} |
|
| EOL |
|
| |
|
| exit; |
|
| } |
|
| |
|
| sub find_libs |
|
| { |
|
| my $file = shift; |
|
| my $ld = shift || get_ldconfig(); |
|
| my $locs = shift || {}; |
|
| |
|
| print STDERR "Finding libs for '$file'\n" if $opts{v}; |
|
| |
|
| my @libs = search_file($file); |
|
| foreach (@libs) { |
|
| my $spec; |
|
| |
|
| if ($_ eq $file) { |
|
| # We don't want to include the file we are looking in |
|
| next; |
|
| } |
} |
| elsif ( my ($name, $maj, $min) = $_ =~ /lib([^\/]+)\.so\.(\d+)\.(\d+)$/ ) { |
|
| $spec = 'l' . $name . '.' . $maj . '.' . $min; |
|
| if ($ld->{$spec}) { |
|
| $locs->{$spec} = $ld->{$spec}; |
|
| } |
|
| } |
|
| elsif (-e $_) { |
|
| $spec = $_; |
|
| $locs->{$spec} = $spec; |
|
| } |
|
| else { |
|
| next; |
|
| } |
|
| |
|
| if (! $locs->{$spec}) { |
|
| print STDERR "Couldn't find location for '$_' (file '$file')\n"; |
|
| next; |
|
| } |
|
| |
|
| print " Found '$spec' => '$locs->{$spec}'\n" if $opts{v}; |
|
| |
|
| $locs = find_libs($locs->{$spec}, $ld, $locs); |
|
| |
|
| } |
|
| |
|
| return $locs; |
|
| } |
} |
| |
|
| sub search_file |
|
| { |
{ |
| my $file = shift; |
for f in "$@"; do |
| my @libs; |
find_depends "$f" |
| |
done |
| open my $libs, '-|', '/usr/bin/ldd', $file or die "Couldn't open ldd '$file': $!"; |
} | sort -u |
| while (<$libs>) { |
|
| chomp; |
|
| my ($spec) = (split(/\s+/, $_))[7]; |
|
| next if ! $spec; |
|
| next if $spec !~ m{^/}xms; |
|
| push @libs, $spec; |
|
| } |
|
| close $libs; |
|
| |
|
| return @libs; |
|
| } |
|
| |
|
| sub get_ldconfig |
|
| { |
|
| my $ldconfig = '/sbin/ldconfig'; |
|
| my (%paths, %libs); |
|
| |
|
| open my $ld, '-|', $ldconfig, '-r' |
|
| or die "Couldn't open pipe to ldconfig: $!"; |
|
| while (<$ld>) { |
|
| chomp; |
|
| if (/search directories:\s+(.*)/) { |
|
| #search directories: /usr/lib:/usr/local/lib |
|
| my @p = split /:/, $1; |
|
| @paths{@p} = 1; |
|
| } elsif (/\d+:-(\S+)\s+=>\s+(\S+)/) { |
|
| #0:-ldes.9.0 => /usr/lib/libdes.so.9.0 |
|
| my $lib = $1; |
|
| my $loc = $2; |
|
| #my ($name, $maj, $min) = $lib =~ /l([^\.]+)\.(\d+)\.(\d+)/; |
|
| #my $spec = 'lib' . $name . '.so.' . $maj . '.' . $min; |
|
| $libs{$lib} = $loc; |
|
| } else { |
|
| #print $_, "\n"; |
|
| } |
|
| } |
|
| close $ld; |
|
| |
|
| $libs{_paths} = [ keys %paths ]; |
|
| return \%libs; |
|
| } |
|