Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Aug 2004 15:18:27 -0400
From:      Christopher Nehren <apeiron@comcast.net>
To:        FreeBSD Ports List <ports@freebsd.org>
Subject:   checklibs, version 1.0
Message-ID:  <20040805191827.GA81915@prophecy.dyndns.org>

next in thread | raw e-mail | index | archive | help
--/WwmFnJnmDyWGHa4
Content-Type: multipart/mixed; boundary="J2SCkAp4GZ/dPZZf"
Content-Disposition: inline

--J2SCkAp4GZ/dPZZf
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

As I've been playing with the development version of the GNOME desktop,
sometimes portupgrade's magic doesn't always work. Sometimes (read:
often), my own stupidity causes problems. These issues combined lead to
programs and libraries that aren't updated properly, and that thus have
dependencies on library files that no longer exist. You can't run these
programs, and you need to rebuild the program / library in question (and
sometimes, dependent libraries as well). Wouldn't it be nice if there
was a program that would check your files and tell you which ones have
dependencies on missing libraries, and which libraries they are? Enter
checklibs. checklibs takes a list of files as input, checks that each
one is a real binary executable (not a shell script or something else
not directly executable), and then runs ldd on each file. It looks
through the output of ldd for a configurable string which indicates that
a dependent library was not found. For each missing library of each file
given on the command line, checklibs makes an entry in a global hash. At
the end of its run, checklibs outputs each file with a missing
dependency and all of the missing dependencies of each file, sorted
lexicographically.

Note that in order to do its job, checklibs uses Perl's file tests,
including the -B test. Some naughty shell scripts (like sawfish-ui)
include binary data like bytecode towards the top of the file, and this
fools Perl into thinking that the file is binary.

checklibs is covered by the Egoware License, version 1.0 (c) Christopher=20
Nehren. The Egoware License is identical to placing something in the public=
=20
domain, except that a user of the materials in question who appreciates said
materials is asked to write an email to the author stating such.

--=20
I abhor a system designed for the "user", if that word is a coded
pejorative meaning "stupid and unsophisticated".  -- Ken Thompson
-
Unix is user friendly. However, it isn't idiot friendly.
--J2SCkAp4GZ/dPZZf
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=checklibs
Content-Transfer-Encoding: quoted-printable

#!/usr/bin/perl -w
use strict;

$ENV{'PATH'} =3D "/bin:/sbin:/usr/bin:/usr/sbin";
my $LDD_PATH =3D "/usr/bin/ldd";
my $MISSING_STRING =3D " =3D> not found (0x0)";
my $WARN =3D 0;
my $current_file =3D "";
my %bad_programs =3D ();
for(@ARGV)
{
	unless(-e)
	{
		warn "$_ doesn't exist, skipping...\n" if $WARN;
		next;
	}
	unless(-f _)
	{
		warn "$_ isn't a regular file, skipping...\n" if $WARN;
		next;
	}
	unless(-x _ or -X _)
	{
		warn "$_ isn't an executable, skipping...\n" if $WARN;
		next;
	}
	unless(-B _)
	{
		warn "$_ doesn't appear to be a binary file, skipping...\n" if $WARN;
		next;
	}
	if(-l $_) # need $_ because the previous stat may not have been an lstat
	{
		$current_file =3D readlink $_ or warn "problem reading $_: $!\n" if $WARN;
	}
	else
	{
		$current_file =3D $_;
	}
	my @ldd_output =3D qx/$LDD_PATH $current_file/;
	chomp @ldd_output;
	unless(@ldd_output)
	{
		warn "'$LDD_PATH $current_file' failed!\n" if $WARN;
	}
	my @sorted =3D sort grep (/\Q$MISSING_STRING\E/, @ldd_output);
	if(@sorted)
	{
		s/^\s+// for @sorted;
		my $previous =3D "previous";
		my @bad_libraries  =3D grep($_ ne $previous &&=20
			($previous =3D $_, 1), @sorted);
		my @split =3D map {(split / =3D> /)[0]} @bad_libraries;
		$bad_programs{$current_file} =3D [@split];
	}
}

for(keys %bad_programs)
{
	print "$_:\n";
	for my $badlib (@{$bad_programs{$_}})
	{
		print "\t$badlib not found\n";
	}
}

__END__

=3Dhead1 NAME

B<checklibs> -- analyse programs and libraries for missing libraries

=3Dhead1 SYNOPSIS

% checklibs file1 [file2 ... filen]

% checklibs /usr/X11R6/bin/* /usr/local/bin/*

=3Dhead1 DESCRIPTION

B<checklibs> is a simple program which takes a list of files as command line
arguments and checks each one to see if any of them depends upon a library =
file
which the linker cannot find. If B<checklibs> finds any files with missing
dependencies, it lists them in a style similar to that of C<ldd(1)>. It doe=
s=20
this by processing the output of C<ldd(1)> and using a configurable string =
to
indicate that a library was not found. Read the top of the file for tunable=
s,
including the variable which determines the "not found" string.

=3Dhead1 CAVEATS

Note that in order to do its job, checklibs uses Perl's file tests,
including the -B test. Some naughty shell scripts include binary data like=
=20
bytecode towards the top of the file, and this fools Perl into thinking tha=
t=20
the file is binary.

=3Dhead1 AUTHOR

B<checklibs> was written by Christopher Nehren <apeiron@comcast.net>.

=3Dhead1 LICENSE

B<checklibs> is covered by the Egoware License, version 1.0 (c) Christopher
Nehren. The Egoware License is identical to placing something in the public
domain, except that a user of the materials in question who appreciates said
materials is asked to write an email to the author stating such.

=3Dhead1 SEE ALSO

C<ldd(1)>
--J2SCkAp4GZ/dPZZf--
--/WwmFnJnmDyWGHa4
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (FreeBSD)

iD8DBQFBEogBk/lo7zvzJioRAiwoAJ9S2EVLexPL78wTPPG3AlabLsf6JQCeK85D
alKo5S8T2xwpsQS1AipAO1U=
=WGzB
-----END PGP SIGNATURE-----
--/WwmFnJnmDyWGHa4--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040805191827.GA81915>