#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License"). You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# ident "%Z%%M% %I% %E% SMI"
#
# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# This utility program reads the contents file to extract Solaris ELF
# libraries, and then runs pvs(1) on them to find the library versioning
# information (if any). This info is printed to stdout in an index file
# format.
#
require 5.005;
use strict;
use locale;
use vars qw(
);
# parameters for what types of libraries to list out:
my $must_be_versioned = 0;
my $must_be_public = 0;
# paths to skip outright.
my @skip_list = qw(
/etc
/usr/4lib
);
# find library names:
#
# We have to use pkgchk -l output (even though it is much slower than
# file will go away or change incompatibly at some point.
#
if (defined($old)) {
} else {
delete($ENV{'LC_ALL'});
}
my $pathname = '';
my $type = '';
my $link = '';
my $pkgs = '';
my $status = '';
my $inpkgs = 0;
while (<$contents_fh>) {
next if (/^Ex/);
chomp;
if (/^Pathname:\s*/i) {
$pathname = $';
$type = '';
$link = '';
$status = '';
$pkgs = '';
$inpkgs = 0;
next;
} elsif (/^Type:\s*/i) {
$type = $';
next;
$link = $';
next;
} elsif (/^Referenced by/i) {
$inpkgs = 1;
$status = $';
$inpkgs = 0;
next;
} elsif (/^\s*$/) {
next unless ($pathname =~ m,/lib,);
}
if ($inpkgs) {
$pkgs .= $_ . ' ';
}
}
close($contents_fh);
# run pvs(1) on the libraries found:
my @list = ();
for (my $i = 1; $i <= scalar(@liblist); $i++) {
if ($i % $batch == 0) {
@list = ();
}
}
exit 0;
#
# Take a pkgchk -l entry and decide if it corresponds to a Solaris
# library. If so, save it in the list @liblist, and record info in
# %symlink & %inode_hash associative arrays as appropriate.
#
sub filter
{
# consider only SUNW packages:
my $basename;
if ($link ne '') {
# include developer build-time symlinks:
} else {
}
return unless (-f $path);
# inode is used to identify what file a symlink point to:
my $inode;
return unless (defined($inode));
if ($link ne '') {
# record info about symlinks:
} else {
}
} else {
# ordinary file case:
}
}
#
# Run pvs(1) on a list of libraries. More than one is done at a time to
# speed things up.
#
# Extracts the version information and passes it to the output() routine
# for final processing.
#
sub do_pvs
{
my (@list) = @_;
#
# record info about the library paths and construct the list of
# files for the pvs command line.
#
$cnt = 0;
$paths = '';
#
# $path should never have single quote in it in
# all normal usage. Make sure this is so:
#
next if ($path =~ /'/);
#
# quote the filename in case it has meta-characters
# (which should never happen in all normal usage)
#
$paths .= "'$path'";
$cnt++;
}
return if ($cnt == 0);
# set locale to C for running command, since we interpret the output:
# get the file(1) output for each item:
while (<$file_fh>) {
}
}
close($file_fh);
#
# in the case of only 1 item, we place it on the command line
# twice to induce pvs(1) to indicate which file it is reporting
# on.
#
if ($cnt == 1) {
$paths .= " $paths";
}
#
# so should not contain spaces or meta characters:
#
# reset LC_ALL, if there was any:
if (defined($old)) {
} else {
delete($ENV{'LC_ALL'});
}
undef($path);
# initialize strings used below for appending info to:
$pub = '';
$pri = '';
$obs = '';
$evo = '';
while (<$pvs_fh>) {
$_ =~ s/\s*$//;
if (m,^([^:]+):$,) {
if ($list{$1}) {
$new_path = $1;
# output the previous one and reset accumulators:
if (defined($path)) {
$pub = '';
$pri = '';
$obs = '';
$evo = '';
}
next; # done with pvs header case
}
}
# extract SUNW version head end:
$vers =~ s/;//g;
# handle the various non-standard cases in Solaris libraries:
} elsif ($vers =~ /^SUNWobsolete/) {
} elsif ($vers =~ /^SUNWevolving/) {
} else {
next;
}
}
close($pvs_fh);
# output the last one (if any):
if (defined($path)) {
}
}
#
# Take the raw library versioning information and process it into index
# file format and then print it out.
#
sub output
{
# trim off any trailing separators:
$pub =~ s/:$//;
$pri =~ s/:$//;
$obs =~ s/:$//;
$evo =~ s/:$//;
# work out the type of library:
my $type;
my $defn;
my $n;
$type = 'INTERNAL';
$defn = 'NO_PUBLIC_SYMS';
} elsif ($obs) {
$type = 'OBSOLETE';
} elsif ($pub) {
$type = 'PUBLIC';
if ($defn =~ /:/) {
$defn =~ s/:/,/g;
$defn = "PUBLIC=$defn";
}
} elsif ($evo) {
$type = 'EVOLVING';
$type = 'UNVERSIONED';
$defn = '-';
} else {
return;
}
# return if instructed to skip either of these cases:
return;
}
return;
}
# prepare the output line, including any symlink information:
my $links;
$links = "${path}$symlink{$inode}";
} else {
$links = "$path";
}
# count the total number of references:
my (@n) = split(/:/, $links);
$n = scalar(@n);
# determine the abi to which the library file belongs:
$abi = 'unknown';
$abi = 'sparcv9';
$abi = 'sparc';
$abi = 'amd64';
$abi = 'i386';
}
print STDOUT "$abi|$path|$defn|$n|$links\n";
# record that we did this library so we do not process it a second time.
}
#
# Remove leading and trailing spaces.
#
sub trim
{
my ($x) = @_;
$x =~ s/^\s*//;
$x =~ s/\s*$//;
return $x;
}