#!/bin/bash
# comparerpms.sh
# Check a set of rpms against originals
# Ideas from David Cox's perl script ported to bash
# Create rpmcomp-sourcename.out of the form:
# rpmname-cmp rpmname-ref OK|OK-PERFECT|FAIL refsize sizediff% sizediffabs \
#  sourcename
# 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-sourcename.out

if [ $# -lt 3 ]
then
	echo "Usage: comparerpms.sh sourcedir refdir sourcename"
	echo " where sourcedir contains the rpms being examined"
	echo " refdir contains the originals"
	echo " and sourcename is a tag identifying sourcedir (rh9, rhel, tao)"
	exit 1
fi

# Run in the background
#if [ -z "$CHILDPROC" ]
#then
#        export CHILDPROC="true"
#        $0 $* &
#        exit 0
#fi

CMPDIR=$1
REFDIR=$2
SRCNAME=$3
STARTDIR=`pwd`
RPTDIR=reports-$SRCNAME
WORKDIR=work-$SRCNAME

if [ -e $WORKDIR ]
then
	rm -rf $WORKDIR
fi

if [ -e $RPTDIR ]
then
	rm -rf $RPTDIR
fi

mkdir $RPTDIR $WORKDIR

fingerprint(){
        echo -n "$1 "
        ls -la $1 | cut -c 1-10
}

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

comprpms(){
	FILESOK="OK"
	CMPRPMDIR=`mktemp -d /var/tmp/cmprpm.XXXXXX`
	REFRPMDIR=`mktemp -d /var/tmp/refrpm.XXXXXX`
	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
		fingerprint $FILENAME
		if [ -x "$FILENAME" -a -f "$FILENAME" ]
		then
			echo $FILENAME >> $STARTDIR/$WORKDIR/cmplibs
			ldd $FILENAME 2>>$STARTDIR/$WORKDIR/cmpliberr | sort >> $STARTDIR/$WORKDIR/cmplibs
		fi
	done > $STARTDIR/$WORKDIR/cmplist
	cd $REFRPMDIR
	find . ! -type d | while read FILENAME
	do
		fingerprint $FILENAME
		if [ -x "$FILENAME" -a -f "$FILENAME" ]
		then
			echo $FILENAME >> $STARTDIR/$WORKDIR/reflibs
			ldd $FILENAME | sort >> $STARTDIR/$WORKDIR/reflibs
		fi
	done > $STARTDIR/$WORKDIR/reflist
	cd $STARTDIR
	diff -u $WORKDIR/*list > $WORKDIR/rpmdiff
	if [ $? -eq 1 ]
	then
		FILESOK="FAIL"
		echo "Differing file fingerprints:">> $RPTDIR/$1-$SRCNAME.out
		cat $WORKDIR/rpmdiff >> $RPTDIR/$1-$SRCNAME.out
	fi	
	if [ -e $WORKDIR/reflibs ]
	then
		# locations wander a bit..., maybe PIC stuff?
		perl -pi -e 's/\(0x.*\)$//' $WORKDIR/cmplibs
		perl -pi -e 's/\(0x.*\)$//' $WORKDIR/reflibs
		diff -u $WORKDIR/*libs > $WORKDIR/libdiff
		if [ $? -eq 1 ]
		then
			FILESOK="FAIL"
			echo "Differing libraries:">> $RPTDIR/$1-$SRCNAME.out
			cat $WORKDIR/libdiff >> $RPTDIR/$1-$SRCNAME.out
			echo "ldd for cmprpm:">> $RPTDIR/$1-$SRCNAME.out
			cat $WORKDIR/cmplibs >> $RPTDIR/$1-$SRCNAME.out
			echo "ldd for refrpm:">> $RPTDIR/$1-$SRCNAME.out
			cat $WORKDIR/reflibs >> $RPTDIR/$1-$SRCNAME.out
		fi
	fi
	if [ -e $WORKDIR/cmplibs ]
	then
		grep -q 'not found' $WORKDIR/cmplibs
		if [ $? -eq 0 ]
		then
			FILESOK="FAIL"
			echo "Missing libraries:" \
			  >> $RPTDIR/$1-$SRCNAME.out
			cat $WORKDIR/cmplibs >> $RPTDIR/$1-$SRCNAME.out
		fi
	fi
	if [ -s $WORKDIR/cmpliberr ]
	then
		FILESOK="FAIL"
		echo "ldd errors:" \
		  >> $RPTDIR/$1-$SRCNAME.out
		cat $WORKDIR/cmpliberr >> $RPTDIR/$1-$SRCNAME.out
	fi
	cd $WORKDIR
	rm -f libdiff rpmdiff cmplibs cmpliberr reflibs
	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`
	ABSDIFF=$(($REFSIZE - $CMPSIZE))
	if [ $REFSIZE -ne 0 ]
	then
		PCTDIFF=$((100 - $CMPSIZE * 100 / $REFSIZE))
	else
		PCTDIFF=-0-
	fi
	if [ $FILESOK = "OK" -a $ABSDIFF -eq 0 ]
	then
		FILESOK="OK-PERFECT"
	fi
	rm -rf $CMPRPMDIR $REFRPMDIR
	echo "$1 $FILESOK $REFSIZE $PCTDIFF $ABSDIFF $SRCNAME"
}

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

cd $STARTDIR
for CMPRPM in $RPMLIST
do
	if [ -e $REFDIR/$CMPRPM ]
	then
		comprpms $CMPRPM $CMPRPM
	else
		# Don't worry about debuginfo
		echo $CMPRPM | grep -q 'debuginfo'
		if [ $? -ne 0 ]
		then
			echo "$CMPRPM FAIL (not found in $REFDIR)"
		fi
	fi
done > rpmcomp-$SRCNAME.out
