[BACK]Return to find_depends CVS log [TXT][DIR] Up to [local] / openbsd / fill_chroot

File: [local] / openbsd / fill_chroot / find_depends (download)

Revision 1.7, Tue Apr 22 20:08:41 2008 UTC (16 years, 1 month ago) by andrew
Branch: MAIN
Changes since 1.6: +8 -13 lines

use ldd instead of what I was using now that it does what I need.

#!/usr/bin/perl
# $RedRiver: find_depends,v 1.6 2007/05/16 19:55:42 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 ($name, $maj, $min) = $_ =~ /lib([^\/]+)\.so\.(\d+)\.(\d+)$/;
    my $spec = 'l' . $name . '.' . $maj . '.' . $min;

    if (exists $ld->{$spec}) {
      next if exists $locs->{$spec};

      $locs->{$spec} = $ld->{$spec};

      $locs = find_libs($locs->{$spec}, $ld, $locs);
      
    } else {
      warn "Couldn't find location for lib '$_' (file '$file')";
    }
  }
    
  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 = substr $_, 56;
    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;
}