#!/bin/bash
# tmverifyrpms.sh
# Check a set of rpms against a reference.
# Ideas from David Cox's perl script ported to bash
# creates tmverifyrpms.log in repository where it is run in the form of:
# rpmname-cmp OK|OK-PERFECT|FAIL ref:refsize +/-:sizediffabs %:sizediff%
# Where
# - refsize is the rpm -q --qf %{SIZE} of the ref rpm
# - sizediff% is the % difference between cmp and ref
# - sizediffabs is the difference in bytes
# If there are library, or file name/perm differences, create
# reports/rpm.out
#
# Version 4.1.5-CentOS
# 2007-02-27 Johnny Hughes <johnny@centos.org>
# - Modified so that it will match some of the standard file
#   extensions we use (.centos, .c4. .el4.centos) with their
#   reference counterparts w/o those extensions
# 2005-07-13 Johnny Hughes <johnny@centos.org>
# - Modified David's great script to run standalone
#   for using in CentOS compares.
# - Removed many of the features (run in background,
#   srpms maps, etc.) which are not needed in this
#   implementation of the script
#
#   You can get all of David's tmtools as a group
#   from the /tmtools directory of any taolinux
#   mirror.  See http://www.taolinux.com for details 
#
#   Thanks to David for a great script :)
#
# Version 4.1.4
# 2004-12-23 David L. Parsley <parsley@linuxjedi.org>
# - Sort rpm --requires output
# 2004-12-21 parsley@linuxjedi.org
# - Findrepo & cd there first (to run in subdirs)
# - Put error checking before the fork-to-background
# 2004-12-03 parsley@linuxjedi.org
# - Discard rpm errors
# - Fix sign error in SZDIFF
# 2004-11-30 parsley@linuxjedi.org
# - Strip (xxx) from end (ld-linux.so mainly)
# - Add checking of rpm --requires
# 2004-09-30 David L. Parsley <parsley@linuxjedi.org>
# - use mktemp -u, or files will be mode 600
# 2004-05-16 David L. Parsley <parsley@linuxjedi.org>
# - Add user & group to fingerprinting
# - Strip right-hand-side of library linkages (after =>)
# - dump stderr by default (can override locally)
# 2004-05-01 David L. Parsley <parsley@linuxjedi.org>j
# - use rpm --dump for files, can run unpriv
#set -x
#
# This has been modified to become a standalone compare tool
# by Johnny Hughes for CentOS compares on 7/13/2005
# 


#This is where the reference files are
REFDIR=RHEL

#This is the files to be compared
CMPDIR=CentOS

STARTDIR=`pwd`
RPTDIR=reports
WORKDIR=work

> tmverifyrpms.log 
if [ -e $WORKDIR ]
then
	rm -rf $WORKDIR
fi

mkdir -p $RPTDIR $WORKDIR

rpmarch(){
	STRIPPED=${1%.rpm}
	echo ${STRIPPED##*.}
}

genfilelist(){
    rpm -qp --dump $1 2>/dev/null | LC_ALL=C sort | while read DUMPLINE
    do
	DUMPLINE=${DUMPLINE/ [01] [01] /TMLINESEP}
	FSYMLINK=${DUMPLINE#*TMLINESEP* }
	DUMPLINE=${DUMPLINE%TMLINESEP*}
	FILENAME="${DUMPLINE% * * * * * *}"
	REST=${DUMPLINE#$FILENAME }
	set $REST
	echo "$FILENAME mode:$4 owner:$5 group:$6 linkto:$FSYMLINK"
    done
}

comprpms(){
	PKGOK="OK"
	CMPRPMDIR=`mktemp -d /var/tmp/cmprpm.XXXXXX`
	REFRPMDIR=`mktemp -d /var/tmp/refrpm.XXXXXX`
	rm -f $RPTDIR/$1.out
	cd $STARTDIR
	rpm2cpio $CMPDIR/$1 | ( cd $CMPRPMDIR; cpio -id --no-absolute-filenames --quiet )
	rpm2cpio $REFDIR/$2 | ( cd $REFRPMDIR; cpio -id --no-absolute-filenames --quiet )
	cd $CMPRPMDIR
	find . ! -type d | while read FILENAME
	do
		if [ -x "$FILENAME" -a -f "$FILENAME" ]
		then
			echo $FILENAME >> $STARTDIR/$WORKDIR/$CMPDIR-libs
			ldd $FILENAME | sort >> $STARTDIR/$WORKDIR/$CMPDIR-libs
		fi
	done
	cd $REFRPMDIR
	find . ! -type d | while read FILENAME
	do
		if [ -x "$FILENAME" -a -f "$FILENAME" ]
		then
			echo $FILENAME >> $STARTDIR/$WORKDIR/$REFDIR-libs
			ldd $FILENAME | sort >> $STARTDIR/$WORKDIR/$REFDIR-libs
		fi
	done
	cd $STARTDIR
	genfilelist $CMPDIR/$1 > $STARTDIR/$WORKDIR/$CMPDIR-list
	genfilelist $REFDIR/$2 > $STARTDIR/$WORKDIR/$REFDIR-list
	diff -u $WORKDIR/*list > $WORKDIR/rpmdiff
	if [ $? -eq 1 ]
	then
		PKGOK="FAIL"
		echo "Differing file fingerprints:">> $RPTDIR/$1.out
		cat $WORKDIR/rpmdiff >> $RPTDIR/$1.out
	fi	
	rpm -qp --requires $CMPDIR/$1 2>/dev/null | LC_ALL=C sort >$STARTDIR/$WORKDIR/$CMPDIR-req
	rpm -qp --requires $REFDIR/$2 2>/dev/null | LC_ALL=C sort >$STARTDIR/$WORKDIR/$REFDIR-req
	diff -u $WORKDIR/*req > $WORKDIR/reqdiff
	if [ $? -eq 1 ]
	then
		PKGOK="FAIL"
		echo "Differing package requirements:">> $RPTDIR/$1.out
		cat $WORKDIR/reqdiff >> $RPTDIR/$1.out
	fi	
	if [ -e $WORKDIR/$REFDIR-libs ]
	then
		# Only want what it's looking for, not what it actually gets
		perl -pi -e 's/ =>.*//' $WORKDIR/$CMPDIR-libs
		perl -pi -e 's/ =>.*//' $WORKDIR/$REFDIR-libs
		perl -pi -e 's/ \(.*//' $WORKDIR/$CMPDIR-libs
		perl -pi -e 's/ \(.*//' $WORKDIR/$REFDIR-libs
		diff -u $WORKDIR/*libs > $WORKDIR/libdiff
		if [ $? -eq 1 ]
		then
			PKGOK="FAIL"
			echo "Differing libraries:">> $RPTDIR/$1.out
			cat $WORKDIR/libdiff >> $RPTDIR/$1.out
			echo "ldd for $CMPDIR-rpm:">> $RPTDIR/$1.out
			cat $WORKDIR/$CMPDIR-libs >> $RPTDIR/$1.out
			echo "ldd for $REFDIR-rpm:">> $RPTDIR/$1.out
			cat $WORKDIR/$REFDIR-libs >> $RPTDIR/$1.out
		fi
	fi
	if [ -e $WORKDIR/$CMPDIR-libs ]
	then
		grep -q 'not found' $WORKDIR/$CMPDIR-libs
		if [ $? -eq 0 ]
		then
			PKGOK="FAIL"
			echo "Missing libraries:" \
			  >> $RPTDIR/$1.out
			cat $WORKDIR/$CMPDIR-libs >> $RPTDIR/$1.out
		fi
	fi
	cd $WORKDIR
	rm -f libdiff rpmdiff $CMPDIR-libs $REFDIR-libs
	cd $STARTDIR
	# MORE TESTS HERE
	CMPSIZE=`rpm -qp --qf %{SIZE} $CMPDIR/$1 2>/dev/null`
	REFSIZE=`rpm -qp --qf %{SIZE} $REFDIR/$2 2>/dev/null`
	SZDIFF=$(($CMPSIZE - $REFSIZE))
	ABSDIFF=$((SZDIFF<0?-$SZDIFF:$SZDIFF))
	if [ $REFSIZE -ne 0 ]
	then
		PCTDIFF=$(($ABSDIFF * 100 / $REFSIZE))
	else
		PCTDIFF=-0-
	fi
	if [ $PKGOK = "OK" -a $SZDIFF -eq 0 ]
	then
		PKGOK="OK-PERFECT"
	fi
	rm -rf $CMPRPMDIR $REFRPMDIR
	RESULTS="$1 $PKGOK ref:$REFSIZE +/-:$SZDIFF %:$PCTDIFF"
}

# Get list of rpms to compare
cd $CMPDIR
RPMLIST=`echo *.rpm`

cd $STARTDIR
for CMPRPM in $RPMLIST
do
	no_centos=`echo $CMPRPM | sed -e 's/\.centos//g'`
	no_el4_centos=`echo $CMPRPM | sed -e 's/\.el4\.centos//g'`
        no_centos4=`echo $CMPRPM | sed -e 's/\.centos4//g'`
	no_c4=`echo $CMPRPM | sed -e 's/\.c4//g'`
	no_el5_centos=`echo $CMPRPM | sed -e 's/\.el5\.centos//g'`
	if [ -e $REFDIR/$CMPRPM ]; then
		echo -n "Verifying $CMPRPM ... "
		comprpms $CMPRPM $CMPRPM
                echo ""
                echo $RESULTS
		echo "-------------------------"
	elif [ -e $REFDIR/$no_centos ]; then
		REFRPM=$no_centos
                echo -n "Verifying $CMPRPM ... "
                comprpms $CMPRPM $REFRPM
                echo ""
                echo $RESULTS
                echo "-------------------------"
	elif [ -e $REFDIR/$no_el4_centos ]; then
                REFRPM=$no_el4_centos
                echo -n "Verifying $CMPRPM ... "
                comprpms $CMPRPM $REFRPM
                echo ""
                echo $RESULTS
                echo "-------------------------"
	elif [ -e $REFDIR/$no_centos4 ]; then
                REFRPM=$no_centos4
                echo -n "Verifying $CMPRPM ... "
                comprpms $CMPRPM $REFRPM
                echo ""
                echo $RESULTS
                echo "-------------------------"
	elif [ -e $REFDIR/$no_c4 ]; then
                REFRPM=$no_c4
                echo -n "Verifying $CMPRPM ... "
                comprpms $CMPRPM $REFRPM
                echo ""
                echo $RESULTS
                echo "-------------------------"
	elif [ -e $REFDIR/$no_el5_centos ]; then
                REFRPM=$no_el5_centos
                echo -n "Verifying $CMPRPM ... "
                comprpms $CMPRPM $REFRPM
                echo ""
                echo $RESULTS
                echo "-------------------------"
	fi
done >> tmverifyrpms.log 
echo "Finished." >> tmverifyrpms.log 
