File: [local] / openbsd / fill_chroot / find_depends (download)
Revision 1.11, Tue Sep 16 22:28:53 2008 UTC (15 years, 9 months ago) by andrew
Branch: MAIN
Changes since 1.10: +27 -11 lines
Make find_depends understand that ld.so is a depend
|
#!/usr/bin/perl
# $RedRiver: find_depends,v 1.10 2008/09/16 22:15:03 andrew Exp $
use strict;
use warnings;
my %opts;
my @Files;
foreach (@ARGV) {
if (/^-+(\w+)$/) {
$opts{$1} = 1;
} else {
push @Files, $_;
}
}
Help() if $opts{h} || $opts{help};
Usage() unless @Files;
my %libs;
foreach my $file (@Files) {
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 (/\/ld\.so$/) {
$spec = $_;
}
else {
if ( my ($name, $maj, $min) = $_ =~ /lib([^\/]+)\.so\.(\d+)\.(\d+)$/ ) {
$spec = 'l' . $name . '.' . $maj . '.' . $min;
}
}
next if ! $spec;
next if exists $locs->{$spec};
print " Found spec '$spec'\n" if $opts{v};
if (-e $spec) {
$locs->{$spec} = $spec;
}
else {
$locs->{$spec} = $ld->{$spec};
}
if (! $locs->{$spec}) {
print STDERR "Couldn't find location for '$_' (file '$file')\n";
next;
}
$locs = find_libs($locs->{$spec}, $ld, $locs);
}
return $locs;
}
sub search_file
{
my $file = shift;
my @libs;
open my $libs, '-|', '/usr/bin/ldd', $file or die "Couldn't open ldd '$file': $!";
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;
}