checklibs, version 1.0

Christopher Nehren apeiron at comcast.net
Thu Aug 5 12:18:33 PDT 2004


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 
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.

-- 
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.
-------------- next part --------------
#!/usr/bin/perl -w
use strict;

$ENV{'PATH'} = "/bin:/sbin:/usr/bin:/usr/sbin";
my $LDD_PATH = "/usr/bin/ldd";
my $MISSING_STRING = " => not found (0x0)";
my $WARN = 0;
my $current_file = "";
my %bad_programs = ();
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 = readlink $_ or warn "problem reading $_: $!\n" if $WARN;
	}
	else
	{
		$current_file = $_;
	}
	my @ldd_output = qx/$LDD_PATH $current_file/;
	chomp @ldd_output;
	unless(@ldd_output)
	{
		warn "'$LDD_PATH $current_file' failed!\n" if $WARN;
	}
	my @sorted = sort grep (/\Q$MISSING_STRING\E/, @ldd_output);
	if(@sorted)
	{
		s/^\s+// for @sorted;
		my $previous = "previous";
		my @bad_libraries  = grep($_ ne $previous && 
			($previous = $_, 1), @sorted);
		my @split = map {(split / => /)[0]} @bad_libraries;
		$bad_programs{$current_file} = [@split];
	}
}

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

__END__

=head1 NAME

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

=head1 SYNOPSIS

% checklibs file1 [file2 ... filen]

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

=head1 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 does 
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 tunables,
including the variable which determines the "not found" string.

=head1 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 
bytecode towards the top of the file, and this fools Perl into thinking that 
the file is binary.

=head1 AUTHOR

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

=head1 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.

=head1 SEE ALSO

C<ldd(1)>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 186 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-ports/attachments/20040805/a3ec2483/attachment.bin


More information about the freebsd-ports mailing list