version 1.12, 2008/09/16 23:38:04 |
version 1.14, 2011/08/09 01:13:54 |
|
|
#!/usr/bin/perl |
#!/bin/sh |
# $RedRiver: find_depends,v 1.11 2008/09/16 22:28:53 andrew Exp $ |
# $AFresh1$ |
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; |
|
} |
|