From b38f7bc532b038cfc0aac13ba8a7ff15c6c6b923 Mon Sep 17 00:00:00 2001 From: jbj Date: Wed, 20 Oct 1999 16:46:54 +0000 Subject: Dependency code from Ken Estes. CVS patchset: 3384 CVS date: 1999/10/20 16:46:54 --- scripts/rpmdiff | 873 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/vpkg-provides.sh | 275 +++++++++++---- 2 files changed, 1085 insertions(+), 63 deletions(-) create mode 100644 scripts/rpmdiff (limited to 'scripts') diff --git a/scripts/rpmdiff b/scripts/rpmdiff new file mode 100644 index 000000000..65efd433a --- /dev/null +++ b/scripts/rpmdiff @@ -0,0 +1,873 @@ + +#!/usr/local/bin/perl + +# rpmdiff - a program for comparing two rpm files for differences. +# Written by Ken Estes, Mail.com. + +use Getopt::Long; + +# much of this code comes from reading the book +# "Maximum RPM" by Edward C. Bailey + + +sub usage { + + my $args = "[--".join("] [--", @ARGS)."]"; + my @default_args = map $RPMTAG->{$_}->{'arg'}, @DEFAULT_CMP; + my $default_args = "--".join(" --", @default_args).""; + + my $usage =< { + 'tag_name' => 'NAME', + }, + 1001 => { + 'tag_name' => 'VERSION', + }, + 1002 => { + 'tag_name' => 'RELEASE', + }, + 1006 => { + 'tag_name' => 'BUILDTIME', + }, + 1027 => { + 'tag_name' => 'FILENAMES', + }, + 1028 => { + 'tag_name' => 'FILESIZES', + 'diff_order' => 0, + 'diff_char' => 'S', + 'arg' => 'size', + 'script_cmp' => sub { return (length($_[0]) ne + length($_[1])); }, + }, + 1029 => { + 'tag_name' => 'FILESTATES', + }, + 1030 => { + 'tag_name' => 'FILEMODES', + 'diff_order' => 1, + 'diff_char' => 'M', + 'arg' => 'mode', + }, + 1031 => { + # /* internal */ + 'tag_name' => 'FILEUIDS', + 'diff_order' => 5, + 'diff_char' => 'U', + 'arg' => 'user', + }, + 1032 => { + # /* internal */ + 'tag_name' => 'FILEGIDS', + 'diff_order' => 6, + 'diff_char' => 'G', + 'arg' => 'group', + }, + 1033 => { + 'tag_name' => 'FILERDEVS', + 'diff_order' => 3, + 'diff_char' => 'D', + 'arg' => 'dev', + }, + 1034 => { + 'tag_name' => 'FILEMTIMES', + 'diff_order' => 7, + 'diff_char' => 'T', + 'arg' => 'mtime', + }, + 1035 => { + 'tag_name' => 'FILEMD5S', + 'diff_order' => 2, + 'diff_char' => '5', + 'arg' => 'md5', + 'script_cmp' => sub{ return ($_[0] ne + $_[1]); }, + }, + 1036 => { + 'tag_name' => 'FILELINKTOS', + 'diff_order' => 4, + 'diff_char' => 'L', + 'arg' => 'link', + }, + 1037 => { + 'tag_name' => 'FILEFLAGS', + }, + + # support for differences of scripts + + 1023 => { + 'tag_name' => 'PREIN', + 'is_script' => 1, + }, + 1024 => { + 'tag_name' => 'POSTIN', + 'is_script' => 1, + }, + 1025 => { + 'tag_name' => 'PREUN', + 'is_script' => 1, + }, + 1026 => { + 'tag_name' => 'POSTUN', + 'is_script' => 1, + }, + 1079 => { + 'tag_name' => 'VERIFYSCRIPT', + 'is_script' => 1, + }, + 1065 => { + 'tag_name' => 'TRIGGERSCRIPTS', + 'is_script' => 1, + }, + 1091 => { + 'tag_name' => 'VERIFYSCRIPTPROG', + 'is_script' => 1, + }, + 1092 => { + 'tag_name' => 'TRIGGERSCRIPTPROG', + 'is_script' => 1, + }, + + }; + + # by default check these options, which are the "contents" of the + # files. + + @DEFAULT_CMP = ( 1028, 1035, 1036, ); + + + $RPM_FILE_MAGIC = chr(0xed).chr(0xab).chr(0xee).chr(0xdb); + $RPM_HEADER_MAGIC = chr(0x8e).chr(0xad).chr(0xe8); + + # we want the second header block, as the first header is the + # signature block. + + $HEADER_BLOCK_NUM = 2; + + # number of bytes in the file to skip when looking for the first + # header. Actually I think the lead is bigger then this like 96, but + # I am sure this minimum value is correct. + + $LEAD_LENGTH = 66; + + $HEADER_RECORD_SIZE = 16; + + # largest exit code we allow. + + $MAX_EXIT = 250; + + $NUM_DIFFERENCES = 0; + + $RCS_REVISION = ' $Revision: 1.1 $ '; + + # set a known path. + + $ENV{'PATH'}= ( + '/opt/gnu/bin'. + ':/usr/local/bin'. + ':/usr/bin'. + ':/bin'. + ''); + + # taint perl requires we clean up these bad environmental variables. + + delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; + + + $VERSION = 'NONE'; + if ( $RCS_REVISION =~ m/([.0-9]+)/ ) { + $VERSION = $1; + } + + return ; +} + + +sub parse_args{ + + my $arg_include = ''; + my $arg_exclude = ''; + my %arg_tags= (); + + my @args_with_bang = (); + my %arg2tag = (); + + # find out what arguments are availible and build some + # data structures to work with them. + + foreach $tag (keys %$RPMTAG ) { + my $arg = $RPMTAG->{$tag}->{'arg'}; + ($arg) || next; + push @ARGS, $arg; + push @ALL_CMP_TAGS, $tag; + push @args_with_bang, "$arg!"; + $arg2tag{$arg}=$tag; + } + + # sort the tags to determine the proper comparison order. + # use the order stored in the RPMTAG table. + # If this code is too confusing, look up + # 'Schwartzian Transform' in perlfaq4 or an advanced perl book. + + @ALL_CMP_TAGS = map { $_->[0] } + sort{ $a->[1] <=> $b->[1] } + map { [ $_, $RPMTAG->{$_}->{'diff_order'} ] } + @ALL_CMP_TAGS; + + $FILES_EQ_STRING = '.' x scalar(@ALL_CMP_TAGS); + + if( !GetOptions("version", "help", "all", "cmpmode!", @args_with_bang) ) { + print("Illegal options in \@ARGV: '@ARGV'\n"); + usage() ; + exit 1 ; + } + + if($opt_version) { + print "Version: $VERSION\n"; + exit 0; + } + + if ($opt_help) { + usage(); + } + + if ($opt_all) { + # all is just an exclude with nothing to exclude + $arg_exclude = 1; + } + + # process each of the arguments derived from the $RPMTAG hash + + foreach $arg (@ARGS) { + my $arg_var = "opt_$arg"; + if (defined($$arg_var)) { + $arg_tags{$arg2tag{$arg}} = 1; + if ($$arg_var) { + $arg_include = 1; + } else { + $arg_exclude = 1; + } + } + } + + ($arg_include) && ($arg_exclude) && + die("$0: Can not mix both include and exclude arguements ". + "on the command line.\n"); + + if ($arg_include) { + # check only the options listed + foreach $tag (keys %arg_tags) { + $CMP_TAGS{$tag} = 1; + } + } elsif ($arg_exclude) { + # check everything but the options listed + foreach $tag (@ALL_CMP_TAGS) { + $CMP_TAGS{$tag} = 1; + } + foreach $tag (keys %arg_tags) { + delete $CMP_TAGS{$tag}; + } + } else { + # check the default options + foreach $tag (@DEFAULT_CMP) { + $CMP_TAGS{$tag} = 1; + } + } + + ($#ARGV == 1) || + die("$0: Argument list must include two file names\n"); + + $RPMFILE0 = $ARGV[0]; + $RPMFILE1 = $ARGV[1]; + + ( !(-f $RPMFILE0) || !(-r $RPMFILE0) ) && + die("$0: '$RPMFILE0' is not a readable file\n"); + + ( !(-f $RPMFILE1) || !(-r $RPMFILE1) ) && + die("$0: '$RPMFILE1' is not a readable file\n"); + + $CMP_MODE = ($opt_cmpmode == 1); + + return ; +} + +# read the rpmfile and extract the header information. + +sub parse_rpm_headers { + my ($filename) = @_; + + my $file = ''; + my $out = {}; + + # read whole file into memory + { + open (RPMFILE, "<$filename")|| + die("$0: Could not open: $filename for reading. $!\n"); + + # not needed on unix but lets be very clear + binmode (RPMFILE); + + # slurp whole file + my $old_irs = $/; + undef $/; + + $file = ; + + $/ = $old_irs; + + close(RPMFILE)|| + die("$0: Could not close: $filename. $!\n"); + + $file =~ m/^$RPM_FILE_MAGIC/ || + die("$0: file: $filename is not an RPM file. ". + "No magic number found.\n"); + } + + # we want the second header block, as the first header is the + # signature block. + + my ($header_start, $store_start) = ($LEAD_LENGTH,0); + my ($_version, $_reserved, $num_header_entries, $num_store_bytes) = (); + + foreach $i (1 .. $HEADER_BLOCK_NUM) { + + # find beginning of header, + $header_start = index($file, $RPM_HEADER_MAGIC, $header_start); + ($header_start < 0) && + die("$0: file: $filename is not an RPM file. ". + "No: $i, header found.\n"); + + $header_start += length($RPM_HEADER_MAGIC); + + ($_version, $_reserved, $num_header_entries, $num_store_bytes) = + unpack("CNNN", substr($file, $header_start, 1+(4*3))); + $header_start += 1+(4*3); + + # find beginning of store + $store_start = $header_start + + ($num_header_entries * $HEADER_RECORD_SIZE); + + ( ($store_start + $num_store_bytes) < length($file) ) || + die("$0: File Parse Error, file: $filename, ". + "is not long enough to hold store.\n"); + } + + # the header is just a list of information about data. + # the data is stored in the store futher down the file. + my $header_position = $header_start; + foreach $i (0 .. $num_header_entries-1) { + + my ($tag, $data_type, $offset, $data_count) = + unpack("N4", substr($file, $header_position, $HEADER_RECORD_SIZE)); + $header_position += $HEADER_RECORD_SIZE; + + ( + ( ($tag < 100) || ($tag > 1200) ) || + ( ($data_type < 0) || ($data_type > 10) ) || + ($offset < 0) + ) && die("$0: Error parsing header in rpm file: $filename, ". + "record number: $i.\n"); + + # we are only interested in the tags which are defined + $RPMTAG->{$tag} || next; + + foreach $j (0 .. $data_count-1) { + my $value =''; + if (0) { + # dummy for aliging the code like a case statement + } elsif ($data_type == 0) { + # null + $value = ''; + } elsif ($data_type == 1) { + # char + $value = substr($file, $store_start+$offset, 1); + $offset += 1; + } elsif ($data_type == 2) { + # int8 + $value = ord(substr($file, $store_start+$offset, 1)); + $offset += 1; + } elsif ($data_type == 3) { + # int16 + $value = unpack("n", substr($file, $store_start+$offset, 2)); + $offset += 2; + } elsif ($data_type == 4) { + # int32 + $value = unpack("N", substr($file, $store_start+$offset, 4)); + $offset += 4; + } elsif ($data_type == 5) { + # int64 + # ---- These aren't supported by RPM (yet) */ + die("$0: int64 type found in rpm file: $filename, ". + "record number: $i.\n"); + } elsif ($data_type == 6) { + # string + my $null_position = index ($file, "\0", $store_start+$offset); + my $length = $null_position - ($store_start+$offset); + $value = substr($file, $store_start+$offset, $length); + $offset += $length; + } elsif ($data_type == 7) { + # bin + # to properly support this I need to move it outside the $j + # loop. However I do not need it. + die("$0: Bin type found in rpm file: $filename, ". + "record number: $i.\n"); + } elsif ($data_type == 8) { + # string_array + my $null_position = index ($file, "\0", $store_start+$offset); + my $length = $null_position - ($store_start+$offset); + $value = substr($file, $store_start+$offset, $length); + $offset += $length+1 + } elsif ($data_type == 9) { + # this is listed as both RPM_I18NSTRING_TYPE and RPM_MAX_TYPE + # in file ~rpm/lib/header.h but I ignore it + die("$0: I18NSTRING type found in rpm file: $filename, ". + "record number: $i.\n"); + } + + push @{$out->{$tag}}, $value; + if ($RPMTAG->{$tag}->{"tag_name"} eq 'FILENAMES') { + $out->{'name2index'}->{$value} = $j; + } + } # foreach $j + + } # foreach $i + + return $out; +} + + +# traverse the datastructures to create a text representation of the +# critical differences between rpmscripts. If we are running in +# cmpmode and a difference is found exit early. + + +sub format_script_differences { + my ($rpm0, $rpm1) = @_; + + my $out = '';; + my %seen = (); + + foreach $script ( sort (keys %$RPMTAG) ) { + + ($RPMTAG->{$script}->{'is_script'}) || next; + + ($rpm0->{$script} || $rpm1->{$script}) || next; + + my $prefix=''; + + if ( ($rpm0->{$script}) && (!($rpm1->{$script})) ) { + $prefix = 'missing '; + } elsif ( (!($rpm0->{$script})) && ($rpm1->{$script}) ) { + $prefix = 'added '; + } else { + my $diff_str = ''; + foreach $cmp_tag (@ALL_CMP_TAGS) { + if ( !($CMP_TAGS{$cmp_tag}) || + !($RPMTAG->{$cmp_tag}->{'script_cmp'}) ){ + $diff_str .= '.'; + next; + } + + # In the rare case where an tag is defined in one RPM and not + # in another we charitably assume that the RPMs match on this + # tag. There is a warning in the stderr anyway. + + if ( + ($rpm0->{$cmp_tag}) && + ($rpm1->{$cmp_tag}) && + + # use the anonymous comparison function (stored in the + # table) to compare the two scripts + + (&{$RPMTAG->{$cmp_tag}->{'script_cmp'}} + ($rpm0->{$script}->[0], $rpm1->{$script}->[0])) + ) { + $diff_str .= $RPMTAG->{$cmp_tag}->{'diff_char'}; + } else { + $diff_str .= '.'; + } + + } # foreach $tag + if ($diff_str ne $FILES_EQ_STRING) { + $prefix = $diff_str; + } + } + + ($prefix) || next; + + if ($CMP_MODE) { + exit 1; + } + + ($NUM_DIFFERENCES < $MAX_EXIT) && + $NUM_DIFFERENCES++; + + $out .= "$prefix $RPMTAG->{$script}->{'tag_name'}\n"; + + } # foreach $filename + + return $out; +} + + + +# traverse the datastructures to create a text representation of the +# critical differences between file stored in the pacakge. If we are +# running in cmpmode and a difference is found exit early. + + + +sub format_file_differences { + my ($rpm0, $rpm1) = @_; + + my $out = '';; + my %seen = (); + + foreach $filename ( sort ( + (keys %{$rpm0->{'name2index'}}), + (keys %{$rpm1->{'name2index'}}) + ) ) { + + $seen{$filename} && next; + $seen{$filename} = 1; + $index0 = $rpm0->{'name2index'}->{$filename}; + $index1 = $rpm1->{'name2index'}->{$filename}; + + my $prefix=''; + + if ( ($index0) && (!($index1)) ) { + $prefix = 'missing '; + } elsif ( (!($index0)) && ($index1) ) { + $prefix = 'added '; + } else { + my $diff_str = ''; + foreach $cmp_tag (@ALL_CMP_TAGS) { + if (!($CMP_TAGS{$cmp_tag})){ + $diff_str .= '.'; + next; + } + + # In the rare case where an tag is defined in one RPM and not + # in another we charitably assume that the RPMs match on this + # tag. There is a warning in the stderr anyway. + + if ( + ($rpm0->{$cmp_tag}->[$index0]) && + ($rpm1->{$cmp_tag}->[$index1]) && + ($rpm0->{$cmp_tag}->[$index0] ne + $rpm1->{$cmp_tag}->[$index1]) + ) { + $diff_str .= $RPMTAG->{$cmp_tag}->{'diff_char'}; + } else { + $diff_str .= '.'; + } + + } # foreach $tag + if ($diff_str ne $FILES_EQ_STRING) { + $prefix = $diff_str; + } + } + + ($prefix) || next; + + if ($CMP_MODE) { + die 1; + } + + ($NUM_DIFFERENCES < $MAX_EXIT) && + $NUM_DIFFERENCES++; + + # this set of blanks would contain information from the flags, if + # only I was not so lazy + + $out .= "$prefix $filename\n"; + + } # foreach $filename + + return $out; +} + +# warn user of a cmp that was requested can not be carried out due to +# lack of data in the header of atleast one file. + +sub data_missing_warnings { + my ($rpm0, $rpm1) = @_; + + my $out = '';; + + foreach $cmp_tag (@ALL_CMP_TAGS) { + if (!($CMP_TAGS{$cmp_tag})) { + next; + } + + if ( ($CMP_TAGS{$cmp_tag}) && + (!$rpm0->{$cmp_tag}) + ){ + $out .= ("Comparison: '$RPMTAG->{$cmp_tag}->{'arg'}' ". + "specified, but data is not availible in ". + "rpm: $RPMFILE0.\n"); + } + if ( ($CMP_TAGS{$cmp_tag}) && + (!$rpm1->{$cmp_tag}) + ){ + $out .= ("Comparison: '$RPMTAG->{$cmp_tag}->{'arg'}' ". + "specified, but data is not availible in ". + "rpm: $RPMFILE1.\n"); + } + } + return $out; +} + + + + +# -------------- main -------------- +{ + set_static_vars(); + parse_args(); + $RPM0 = parse_rpm_headers($RPMFILE0); + $RPM1 = parse_rpm_headers($RPMFILE1); + + my $warnings = data_missing_warnings($RPM0, $RPM1); + + # we must print warnings before running diff as we may exit early. + + ($warnings) && + warn($warnings); + + my $header = "oldpkg $RPMFILE0\n"."newpkg $RPMFILE1\n"."\n\n"; + my $script_diffs = format_script_differences($RPM0, $RPM1); + my $file_diffs = format_file_differences($RPM0, $RPM1); + + ($script_diffs || $file_diffs) && + print $header, $script_diffs, $file_diffs; + + exit $NUM_DIFFERENCES; +} diff --git a/scripts/vpkg-provides.sh b/scripts/vpkg-provides.sh index df4746791..88130420c 100755 --- a/scripts/vpkg-provides.sh +++ b/scripts/vpkg-provides.sh @@ -1,12 +1,15 @@ + + #!/bin/sh # # Original Author: Tim Mooney (mooney@plains.NoDak.edu) +# Improvements by: Ken Estes # # This file is distributed under the terms of the GNU General Public License # -# non-linux-provides is part of RPM, the Red Hat Package Manager. -# non-linux-provides searches a list of directories (based on what OS it's +# vpkg-provides.sh is part of RPM, the Red Hat Package Manager. +# vpkg-provides.sh searches a list of directories (based on what OS it's # being executed on) for shared libraries and interpreters that have been # installed by some packaging system other than RPM. It then generates a # spec file that can be used to build a "virtual package" that provides all @@ -20,15 +23,55 @@ # first effort was great, so I didn't want to wait until the better solution # was done. +# you will need to create a spec_header for the virtual package. This +# header will provide such specfile information as: +# +# Summary: +# Name: +# Version: +# Release: +# Copyright: +# Group: +# Source: + + +usage= "usage: $0 [--spec_header '/path/to/os-base-header.spec'] \n" +usage= "$usage\t[--find_provides '/path/to/find-provides']\n" +usage= "$usage\t[--shlib_dirs 'dirs:which:contain:shared:libs']\n" +usage= "$usage\t[--ignore_dirs 'egrep|pattern|of|paths|to|ignore']\n" + +# these two should be unnessary as the regular dependency analysis +# should take care of interpreters as well as shared libraries. + +usage= "$usage\t[--interp_dirs 'dirs:which:contain:interpreters']\n" +usage= "$usage\t[--interps 'files:to:assume:are:installed']\n" + + +# this command may not be portable to all OS's, does something else +# work? can this be set in the case $osname statement? + +sum_cmd="xargs cksum" + +date=`date` +hostname=`uname -n` + +# if some subdirectories of the system directories needs to be ignored +# (eg /usr/local is a subdirectory of /usr but should not be part of +# the virtual package) then call this script with IGNORE_DIRS set to a +# vaild egrep pattern which discribes the directories to ignored. + PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb:/usr/bsd export PATH + # -# The default directories to use if they're not specified as -# arguments 1 and 2, respectively. +# The (OS independent) default values. # -default_spec_header='/usr/local/lib/rpm/os-base-header.spec'; -default_find_provides='/usr/local/lib/rpm/find-provides'; +spec_header='/usr/local/lib/rpm/os-base-header.spec'; +interps="sh:csh:ksh:dtksh:wish:tclsh:perl:awk:gawk:nawk:oawk" +find_provides='/usr/local/lib/rpm/find-provides'; +ignore_dirs="." + osname=`uname -s` if test $? -ne 0 || test X$osname = X ; then @@ -36,73 +79,29 @@ if test $? -ne 0 || test X$osname = X ; then exit 1 fi -if test X$1 = X ; then - if test -f $default_spec_header ; then - spec_header=$default_spec_header - else - echo "You must pass me the full path to the partial spec file" - echo "as my first argument, since this file does not appear in the" - echo "default location of $default_spec_header" - echo - echo "usage: $0 [ /path/to/spec-header ] [ /path/to/find-provides ]" - echo - exit 9 - fi -else - spec_header=$1 - if test ! -f $spec_header ; then - echo "$spec_header does not exist or is not what I was expecting." - exit 10 - fi -fi - -if test X$2 = X ; then - if test -f $default_find_provides ; then - find_provides=$default_find_provides - else - echo "You must pass me the full path to the find-provides script as my" - echo "second argument, since find-provides does not appear in the" - echo "default location of $default_find_provides" - echo - echo "usage: $0 [ /path/to/spec-header ] [ /path/to/find-provides ]" - echo - exit 9 - fi -else - find_provides=$2 - if test ! -f $find_provides ; then - echo "$find_provides does not exist or is not what I was expecting." - exit 10 - fi -fi # -# Set what directories we search for shared libraries and what interpreters -# we look for, based on what OS we're on. +# Set OS dependent defaults # case $osname in OSF1) shlib_dirs='/shlib:/usr/shlib:/usr/dt/lib:/usr/opt' interp_dirs='/bin:/usr/bin:/sbin:/usr/dt/bin:/usr/bin/posix' - interps="sh:csh:ksh:dtksh:wish:tclsh:perl:awk:gawk:nawk:oawk" ;; HP-UX) shlib_dirs='/usr/shlib:/usr/dt/lib:/opt' shlib_dirs="$shlib_dirs:/usr/bms:/usr/obam:/usr/sam" interp_dirs='/bin:/usr/bin:/sbin:/usr/dt/bin:/usr/bin/posix' - interps="sh:csh:ksh:dtksh:wish:tclsh:perl:awk:gawk:nawk:oawk" ;; AIX) shlib_dirs='/usr/lib:/usr/ccs/lib:/usr/dt/lib:/usr/lpp:/usr/opt' interp_dirs='/bin:/usr/bin:/sbin:/usr/dt/bin' - interps="bsh:sh:csh:ksh:dtksh:wish:tclsh:perl:awk:gawk:nawk:oawk" ;; SunOS) shlib_dirs='/etc/lib:/etc/vx:/opt:/usr/lib:/usr/ccs/lib:/usr/dt/lib' shlib_dirs="$shlib_dirs:/usr/4lib:/usr/openwin/lib:/usr/snadm/lib" shlib_dirs="$shlib_dirs:/usr/ucblib:/usr/xpg4/lib" interp_dirs='/bin:/usr/bin:/sbin:/usr/dt/bin:/usr/xpg4/bin' - interps="bsh:sh:csh:ksh:dtksh:wish:tclsh:perl:awk:gawk:nawk:oawk" ;; IRIX|IRIX64) shlib_dirs='/lib:/usr/lib:/usr/lib32:/usr/lib64' @@ -111,7 +110,6 @@ case $osname in shlib_dirs="$shlib_dirs:/usr/sgitcl:/usr/SGImeeting:/usr/pcp/lib" shlib_dirs="$shlib_dirs:/usr/Motif-2.1" interp_dirs='/bin:/usr/bin:/sbin:/usr/sbin:/usr/dt/bin' - interps="sh:csh:tcsh:ksh:dtksh:wish:tclsh:perl:perl5:awk:gawk:nawk:oawk" ;; *) echo "I'm sorry. I haven't been configured yet to work on $osname." @@ -126,9 +124,96 @@ case $osname in ;; esac -tmp_file=/tmp/shlibs.$$ -if test -f $tmp_file ; then - echo "$tmp_file already exists. Exiting." + +# allow the user to change defaults with the command line arguments. + +# Loop over all args + +while : +do + +# Break out if there are no more args + case $# in + 0) + break + ;; + esac + +# Get the first arg, and shuffle + option=$1 + shift + +# Make all options have two hyphens + orig_option=$option # Save original for error messages + case $option in + --*) ;; + -*) option=-$option ;; + esac + + + case $option in + --spec_header) + spec_header=$1 + shift + ;; + --ignore_dirs) + ignore_dirs=$1 + shift + ;; + --find_provides) + find_provides=$1 + shift + ;; + --shlib_dirs) + shlib_dirs=$1 + shift + ;; + --interp_dirs) + interp_dirs=$1 + shift + ;; + --interps) + interps=$1 + shift + ;; + --help) + echo $usage + exit 0 + ;; + *) + echo "$0: Unrecognized option: \"$orig_option\"; use --help for usage." >&2 + exit 1 + ;; + + +# consistancy checks on the arguments + +if [ ! -f $spec_header ]; then + echo "You must pass me the full path to the partial spec file" + echo "as my first argument, since this file does not appear in the" + echo "default location of $default_spec_header" + echo + echo $usage + echo + exit 9 +fi + + +if [ ! -f $find_provides ]; then + echo "You must pass me the full path to the find-provides script as my" + echo "second argument, since find-provides does not appear in the" + echo "default location of $default_find_provides" + echo + echo $usage + echo + exit 9 +fi + + + +provides_tmp=/tmp/provides.$$ +if test -f $provides_tmp ; then + echo "$provides_tmp already exists. Exiting." exit 11 fi @@ -138,15 +223,24 @@ fi # for d in `echo $shlib_dirs | sed -e 's/:/ /g'` do - find $d -type f -print 2>/dev/null | $find_provides >> $tmp_file + find $d -type f -print 2>/dev/null | egrep -v \'$IGNORE_DIRS\' | $find_provides >> $provides_tmp done -provides=/tmp/provides.$$ -if test -f $provides ; then - echo "$provides already exists. Exiting." +sum_tmp=/tmp/sum.$$ +if test -f $sum_tmp ; then + echo "$sum_tmp already exists. Exiting." exit 11 fi +# +# iterate through all the directories in shlib_dirs, record the sum +# +for d in `echo $shlib_dirs | sed -e 's/:/ /g'` +do + find $d -type f -print 2>/dev/null | egrep -v \'$IGNORE_DIRS\' | $sum_cmd >> $sum_tmp +done + + # # output the initial part of the spec file # @@ -155,7 +249,7 @@ cat $spec_header # # Output the shared libraries # -for f in `cat $tmp_file | sort -u` +for f in `cat $provides_tmp | sort -u` do echo "Provides: $f" done @@ -174,10 +268,8 @@ do done # -# Finish off the spec file we're spitting out. +# Output the discription of the spec file # -date=`date` -hostname=`uname -n` cat <<_EIEIO_ @@ -194,6 +286,9 @@ $date. _EIEIO_ +# +# Output the build sections of the spec file +# echo '%prep' echo '# nothing to do' echo '%build' @@ -202,4 +297,58 @@ echo '%install' echo '# nothing to do' echo '%clean' echo '# nothing to do' + +# +# Output the verify section of the spec file +# + +cat <<_EIEIO_ + +%verifyscript + +PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/ucb:/usr/bsd +export PATH + +sum_current_tmp=/tmp/rpm.sum.current.\$\$ +if test -f \$sum_current_tmp ; then + echo "\$sum_current_tmp already exists. Exiting." + exit 11 +fi + +sum_package_tmp=/tmp/rpm.sum.package.\$\$ +if test -f \$sum_package_tmp ; then + echo "\$sum_package_tmp already exists. Exiting." + exit 11 +fi + +for d in `echo $shlib_dirs | sed -e 's/:/ /g'` +do + find \$d -type f -print 2>/dev/null | egrep -v \'$IGNORE_DIRS\' | $sum_cmd >> \$sum_current_tmp +done + +cat >\$sum_package_tmp <<_EOF_ +_EIEIO_ + +# the contents of the temporary file are hardcoded into the verify +# script so that the file can be reproduced at verification time. + +cat $sum_tmp + +cat <<_EIEIO_ +_EOF_ + + +cmp \$sum_package_tmp \$sum_current_tmp + +if [ $? -ne 0 ]; then + echo"Differences found by: cmp \$sum_package_tmp \$sum_current_tmp" + exit \$? +fi + +_EIEIO_ + +# +# Output the files section of the spec file +# + echo '%files' -- cgit v1.2.3