File Coverage

blib/lib/Sys/GNU/ldconfig.pm
Criterion Covered Total %
statement 110 122 90.1
branch 25 46 54.3
condition 3 9 33.3
subroutine 23 23 100.0
pod 6 6 100.0
total 167 206 81.0


line stmt bran cond sub pod time code
1             package Sys::GNU::ldconfig;
2             # $Id: ldconfig.pm 1546 2016-08-29 17:27:27Z fil $
3             # Copyright 2013 Philip Gwyn - All rights reserved
4              
5 1     1   13852 use 5.00405;
  1         3  
6 1     1   4 use strict;
  1         1  
  1         15  
7 1     1   3 use warnings;
  1         1  
  1         23  
8              
9 1     1   2 use vars qw($VERSION @ISA @EXPORT);
  1         1  
  1         99  
10              
11             $VERSION = '0.02_01';
12              
13             require Exporter;
14             @ISA = qw( Exporter );
15             @EXPORT = qw( ld_lookup ld_root );
16              
17             sub DEBUG () { 0 }
18              
19 1     1   3 use Carp;
  1         1  
  1         66  
20 1     1   4 use Config;
  1         1  
  1         29  
21 1     1   5 use File::Basename qw( dirname );
  1         1  
  1         67  
22 1     1   4 use File::Glob qw( bsd_glob );
  1         0  
  1         66  
23 1     1   480 use File::Slurp qw( slurp );
  1         10147  
  1         47  
24 1     1   10 use File::Spec;
  1         1  
  1         859  
25              
26              
27             #############################################################################
28             our $LD;
29             sub ld_lookup
30             {
31 1     1 1 4 my( $name ) = @_;
32 1   33     2 $LD ||= Sys::GNU::ldconfig->new;
33 1         3 return $LD->lookup( $name );
34             }
35              
36             sub ld_root
37             {
38 1     1 1 40 my( $path ) = @_;
39 1   33     8 $LD ||= Sys::GNU::ldconfig->new;
40 1         3 $LD->root( $path );
41             }
42              
43             #############################################################################
44             sub new
45             {
46 2     2 1 1235 my( $package ) = @_;
47 2 50       4 $package = ref $package if ref $package;
48 2         18 my $self = bless { root => File::Spec->rootdir,
49             absroot => File::Spec->rootdir,
50             dirs => [],
51             have_dirs => 0
52             }, $package;
53 2         8 return $self;
54             }
55              
56             #################################################
57             sub root
58             {
59 2     2 1 355 my( $self, $path ) = @_;
60 2 50       36 confess "Root '$path' doesn't exist" unless -d $path;
61 2         3 $self->{root} = $path;
62 2         3 $self->{have_dirs} = 0;
63 2         3 $self->{dirs} = [];
64 2         4 return;
65             }
66              
67              
68             #################################################
69             # The heart of the module
70             sub lookup
71             {
72 7     7 1 3527 my( $self, $part ) = @_;
73              
74 7         14 my $file = $self->_lookup( $part );
75 7 50       18 return unless defined $file;
76 7         10 return $self->_derooted( $file );
77             }
78              
79             sub _lookup
80             {
81 7     7   7 my( $self, $part ) = @_;
82              
83 7 100       21 $part = "lib$part" unless $part =~ /^lib/;
84 7 100       78 $part = "$part.$Config{dlext}" unless $part =~ /\.\Q$Config{dlext}\E/; # allow .so.7 (for example)
85 7         15 DEBUG and warn "Looking for '$part'\n";
86              
87 7 50       106 return $self->_chase_lib( $part ) if -e $part;
88 7         12 foreach my $dir ( $self->dirs ) {
89 19         102 my $file = File::Spec->catfile( $dir, $part );
90 19 100       233 return $self->_chase_lib( $file ) if -e $file;
91             }
92 0         0 return;
93             }
94              
95              
96             # This logic is lifted from PAR::Packer
97             # _chase_lib - find the runtime link of a shared library
98             # Logic based on info found at the following sites:
99             # http://lists.debian.org/lsb-spec/1999/05/msg00011.html
100             # http://docs.sun.com/app/docs/doc/806-0641/6j9vuqujh?a=view#chapter5-97360
101             sub _chase_lib {
102 7     7   7 my ($self, $file) = @_;
103              
104 7   33     107 while ($Config{d_symlink} and -l $file) {
105 0 0       0 if ($file =~ /^(.*?\.\Q$Config{dlext}\E\.\d+)\..*/) {
106 0 0       0 return $1 if -e $1;
107             }
108              
109 0 0       0 return $file if $file =~ /\.\Q$Config{dlext}\E\.\d+$/;
110              
111 0         0 my $dir = File::Basename::dirname($file);
112 0         0 $file = readlink($file);
113              
114 0 0       0 unless (File::Spec->file_name_is_absolute($file)) {
115 0         0 $file = File::Spec->rel2abs($file, $dir);
116             }
117             }
118              
119 7 50       55 if ($file =~ /^(.*?\.\Q$Config{dlext}\E\.\d+)\..*/) {
120 0 0       0 return $1 if -e $1;
121             }
122            
123 7         18 return $file;
124             }
125              
126             #################################################
127             sub _rooted
128             {
129 14     14   13 my( $self, $dir ) = @_;
130 14         12 my $root = $self->{root};
131 14 50       19 return $dir if $root eq $self->{absroot};
132 14         63 return File::Spec->catdir( $root, $dir );
133             }
134              
135             #################################################
136             sub _derooted
137             {
138 7     7   8 my( $self, $file ) = @_;
139 7         6 my $root = $self->{root};
140 7 50       39 $file =~ s/^\Q$root// unless $root eq $self->{absroot};
141 7         18 return $file;
142             }
143              
144             #################################################
145             sub _list_dirs
146             {
147 2     2   6 my( $self ) = @_;
148 2         1 my @dirs;
149 2 50       11 if( $ENV{$Config{ldlibpthname}} ) {
150 0         0 DEBUG and warn "Using $Config{ldlibpthname}\n";
151 0         0 push @dirs, map { $self->_rooted( $_ ) }
152 0         0 split ':', $ENV{$Config{ldlibpthname}};
153             }
154 2         17 my $conf = File::Spec->catfile( $self->{root}, 'etc', 'ld.so.conf' );
155 2 50       32 push @dirs, $self->_read_conf( $conf ) if -f $conf;
156              
157 2         3 push @dirs, map { $self->_rooted( $_ ) } qw( /lib64 /lib /usr/lib64 /usr/lib );
  8         12  
158 2         3 foreach my $dir ( @dirs ) {
159 14 100       130 next unless -d $dir;
160 8         4 DEBUG and warn "Search in $dir\n";
161 8         9 push @{ $self->{dirs} }, $dir;
  8         10  
162             }
163 2         5 $self->{have_dirs} = 1;
164             }
165              
166              
167             #################################################
168             sub _read_conf
169             {
170 4     4   5 my( $self, $file ) = @_;
171 4         5 DEBUG and warn "Reading config '$file'\n";
172 4         10 my $c = slurp( $file );
173 4         222 my @dirs = split /[: \t\n,]+/, $c;
174 4         4 my @ret;
175 4         4 my $include_next = 0;
176 4         5 foreach my $dir ( @dirs ) {
177 10 100       17 if( $include_next ) {
    100          
178 2         2 $include_next = 0;
179 2         5 push @ret, $self->_read_glob( $file, $dir );
180             }
181             elsif( $dir eq 'include' ) {
182 2         1 $include_next = 1;
183             }
184             else {
185 6         11 push @ret, $self->_rooted( $dir );
186             }
187             }
188 4         8 return @ret;
189             }
190              
191              
192             sub _read_glob
193             {
194 2     2   2 my( $self, $file, $dir ) = @_;
195 2         28 my( $vol, $dirname, $glob ) = File::Spec->splitpath( $dir );
196 2         3 my $root = $self->{root};
197 2 50       83 $root = dirname( $file ) unless File::Spec->file_name_is_absolute( $dir );
198 2         9 my $confdir = File::Spec->catdir( $root, $dirname );
199 2         2 DEBUG and warn "Look in $confdir for $glob\n";
200 2         3 my @ret;
201 2         143 foreach my $conf ( bsd_glob( File::Spec->catfile( $confdir, $glob ) ) ) {
202 2 50       23 next unless -f $conf;
203 2         7 push @ret, $self->_read_conf( $conf );
204             }
205 2         5 return @ret;
206             }
207              
208              
209             #################################################
210             sub dirs
211             {
212 7     7 1 6 my( $self ) = @_;
213 7 100       17 $self->_list_dirs unless $self->{have_dirs};
214 7         5 return @{ $self->{dirs} };
  7         15  
215             }
216              
217             1;
218             __END__