File Coverage

File:Dpkg/Shlibs.pm
Coverage:70.6%

linestmtbrancondsubpodtimecode
1# Copyright © 2007, 2016 Raphaël Hertzog <hertzog@debian.org>
2# Copyright © 2007-2008, 2012-2015 Guillem Jover <guillem@debian.org>
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17=encoding utf8
18
19 - 29
=head1 NAME

Dpkg::Shlibs - shared library location handling

=head1 DESCRIPTION

This module provides functions to locate shared libraries.

B<Note>: This is a private module, its API can change at any time.

=cut
30
31package Dpkg::Shlibs 0.03;
32
33
6
6
6
38
4
260
use strict;
34
6
6
6
16
6
324
use warnings;
35
6
6
6
20
28
582
use feature qw(state);
36
37our @EXPORT_OK = qw(
38    blank_library_paths
39    setup_library_paths
40    get_library_paths
41    add_library_dir
42    find_library
43);
44
45
6
6
6
22
4
146
use Exporter qw(import);
46
6
6
6
18
6
328
use List::Util qw(none);
47
6
6
6
26
4
232
use File::Spec;
48
49
6
6
6
5708
12
204
use Dpkg::Gettext;
50
6
6
6
5122
8
346
use Dpkg::ErrorHandling;
51
6
6
6
5910
14
192
use Dpkg::Shlibs::Objdump;
52
6
6
6
6332
10
252
use Dpkg::BuildAPI qw(get_build_api);
53
6
6
6
26
8
204
use Dpkg::Path qw(resolve_symlink canonpath);
54
6
6
6
18
8
654
use Dpkg::Arch qw(get_build_arch get_host_arch :mappers);
55
56
6
220
use constant DEFAULT_LIBRARY_PATH =>
57
6
6
16
6
    qw(/lib /usr/lib);
58# XXX: Deprecated multilib paths.
59
6
5390
use constant DEFAULT_MULTILIB_PATH =>
60
6
6
14
4
    qw(/lib32 /usr/lib32 /lib64 /usr/lib64);
61
62# Library paths set by the user.
63my @custom_librarypaths;
64# Library paths from the system.
65my @system_librarypaths;
66my $librarypaths_init;
67
68sub parse_ldso_conf {
69
60
0
58
    my $file = shift;
70
60
24
    state %visited;
71
60
46
    local $_;
72
73
60
570
    open my $fh, '<', $file or syserr(g_('cannot open %s'), $file);
74
60
90
    $visited{$file}++;
75
60
296
    while (<$fh>) {
76
174
258
        next if /^\s*$/;
77
150
94
        chomp;
78
150
178
        s{/+$}{};
79
150
258
        if (/^include\s+(\S.*\S)\s*$/) {
80
30
580
            foreach my $include (glob($1)) {
81                parse_ldso_conf($include) if -e $include
82
54
292
                    && !$visited{$include};
83            }
84        } elsif (m{^\s*/}) {
85
90
70
            s/^\s+//;
86
90
60
            my $libdir = $_;
87
90
564
180
340
            if (none { $_ eq $libdir } (@custom_librarypaths, @system_librarypaths)) {
88
90
214
                push @system_librarypaths, $libdir;
89            }
90        }
91    }
92
60
212
    close $fh;
93}
94
95sub blank_library_paths {
96
6
0
10
    @custom_librarypaths = ();
97
6
4
    @system_librarypaths = ();
98
6
10
    $librarypaths_init = 1;
99}
100
101sub setup_library_paths {
102
6
0
6
    @custom_librarypaths = ();
103
6
6
    @system_librarypaths = ();
104
105    # XXX: Deprecated. Update library paths with LD_LIBRARY_PATH.
106
6
10
    if ($ENV{LD_LIBRARY_PATH}) {
107
6
22
        require Cwd;
108
6
42
        my $cwd = Cwd::getcwd;
109
110
6
14
        foreach my $path (split /:/, $ENV{LD_LIBRARY_PATH}) {
111
6
16
            $path =~ s{/+$}{};
112
113
6
62
            my $realpath = Cwd::realpath($path);
114
6
10
            next unless defined $realpath;
115
6
72
            if ($realpath =~ m/^\Q$cwd\E/) {
116
0
0
                if (get_build_api() >= 1) {
117
0
0
                    error(g_('use -l option instead of LD_LIBRARY_PATH'));
118                } else {
119
0
0
                    warning(g_('deprecated use of LD_LIBRARY_PATH with private ' .
120                               'library directory which interferes with ' .
121                               'cross-building, please use -l option instead'));
122                }
123            }
124
125
6
14
            next if get_build_api() >= 1;
126
127            # XXX: This should be added to @custom_librarypaths, but as this
128            # is deprecated we do not care as the code will go away.
129
6
40
            push @system_librarypaths, $path;
130        }
131    }
132
133    # Adjust set of directories to consider when we're in a situation of a
134    # cross-build or a build of a cross-compiler.
135
6
6
    my $multiarch;
136
137    # Detect cross compiler builds.
138
6
10
    if ($ENV{DEB_TARGET_GNU_TYPE} and
139        ($ENV{DEB_TARGET_GNU_TYPE} ne $ENV{DEB_BUILD_GNU_TYPE}))
140    {
141
0
0
        $multiarch = gnutriplet_to_multiarch($ENV{DEB_TARGET_GNU_TYPE});
142    }
143    # Host for normal cross builds.
144
6
28
    if (get_build_arch() ne get_host_arch()) {
145
0
0
        $multiarch = debarch_to_multiarch(get_host_arch());
146    }
147    # Define list of directories containing crossbuilt libraries.
148
6
8
    if ($multiarch) {
149
0
0
        push @system_librarypaths, "/lib/$multiarch", "/usr/lib/$multiarch";
150    }
151
152
6
10
    push @system_librarypaths, DEFAULT_LIBRARY_PATH;
153
154    # Update library paths with ld.so config.
155
6
40
    parse_ldso_conf('/etc/ld.so.conf') if -e '/etc/ld.so.conf';
156
157
6
14
    push @system_librarypaths, DEFAULT_MULTILIB_PATH;
158
159
6
6
    $librarypaths_init = 1;
160}
161
162sub add_library_dir {
163
12
0
18
    my $dir = shift;
164
165
12
50
    setup_library_paths() if not $librarypaths_init;
166
167
12
20
    push @custom_librarypaths, $dir;
168}
169
170sub get_library_paths {
171
18
0
20
    setup_library_paths() if not $librarypaths_init;
172
173
18
54
    return (@custom_librarypaths, @system_librarypaths);
174}
175
176# find_library ($soname, \@rpath, $format, $root)
177sub find_library {
178
0
0
    my ($lib, $rpath, $format, $root) = @_;
179
180
0
    setup_library_paths() if not $librarypaths_init;
181
182
0
0
    my @librarypaths = (@{$rpath}, @custom_librarypaths, @system_librarypaths);
183
0
    my @libs;
184
185
0
    $root //= '';
186
0
    $root =~ s{/+$}{};
187
0
    foreach my $dir (@librarypaths) {
188
0
        my $checkdir = "$root$dir";
189
0
        if (-e "$checkdir/$lib") {
190
0
            my $libformat = Dpkg::Shlibs::Objdump::get_format("$checkdir/$lib");
191
0
            if (not defined $libformat) {
192
0
                warning(g_("unknown executable format in file '%s'"), "$checkdir/$lib");
193            } elsif ($format eq $libformat) {
194
0
                push @libs, canonpath("$checkdir/$lib");
195            } else {
196
0
                debug(1, "Skipping lib $checkdir/$lib, libabi=<%s> != objabi=<%s>",
197                      $libformat, $format);
198            }
199        }
200    }
201
0
    return @libs;
202}
203
204 - 210
=head1 CHANGES

=head2 Version 0.xx

This is a private module.

=cut
211
2121;