#!/bin/sh

# disrpm / undeb
# small (bourne) shell script to extract/unzip/unpack/unarchive *.rpm or *.deb packages.
# uses sh, sed, hexdump|od, gzip|bzip2, dd, cpio.
# released under the Gnu General Public License (GPL)
# (c) bjdouma@xs4all.nl
######################
VER="v1.5, october 2004"
ME="${0##*/}"

# change HEADER_SIZE here or issue e.g.
# $> HEADER_SIZE=512000 disrpm -v foo.rpm
[ -z $HEADER_SIZE ] && HEADER_SIZE=256000
######################

usage()
{
	echo -e "disrpm $VER (bjdouma@xs4all.nl)

usage:	 $ME -v|-x foo.rpm
	 $ME -v|-x foo.deb

options: -v|-l  view (list) contents of foo.
	 -x     extract foo.
"
	exit 1
}

error_exit()
{
	echo $1 >&2
	exit 1
}

gzip_sieve()
{
	# gzip-magic: 0x1F,0x8B
	sed -ne '/1[fF]/{;N;/8[bB]$/{;s/1[fF]//g;s/^0*//g;P;};}'
}

bzip2_sieve()
{
	# bzip2-magic: 0x42,0x5A,0x68
	sed -ne '/42/{;N;/5[aA]$/{;N;/68$/{s/42//g;s/5[aA]//g;s/^0*//g;P;};};}'
}

probe()
{
	dd if=$FILE ibs=$O skip=1 2>/dev/null \
	| $2 -dc - 2>/dev/null \
	| cpio "$1" 2>/dev/null
}

######################

XDUMP=`type -P hexdump` || XDUMP=`type -P od` || error_exit "oops, can't find hexdump or od -- bailing out"
XDUMP="${XDUMP##*/}"

OPT=$1
[ -z $OPT ] && usage

PASS1="probe -tv"
{ [ "$OPT" = "-l" -o "$OPT" = "-v" ] && PASS2=":" ; } || { [ "$OPT" = "-x" ] && PASS2="probe -mid" ; } || usage

FILE=$2
[ x"$FILE"x == xx ] && usage
[ -e "$FILE" ] || error_exit "$FILE: No such file or directory"
 
for AR in gzip bzip2
do
	e=1

	[ "$XDUMP" = "od" ] && AR_OFFSETS=`$XDUMP -A d -N $HEADER_SIZE -v -t x1 -w1 $FILE | ${AR}_sieve`
	[ "$XDUMP" = "hexdump" ] && AR_OFFSETS=`$XDUMP -n $HEADER_SIZE -v -e '"%_ad " 1/1 "%02x" "\n"' $FILE | ${AR}_sieve`

	for O in $AR_OFFSETS
	do
		echo "--> at offset $O:" >&2
		$PASS1 $AR 2>/dev/null && $PASS2 $AR && e=0 \
		|| echo "... hmm, probably false drop" >&2
	done

	[ $e -eq 0 ] && break
done

[ $e -eq 1 ] && echo "$ME: failed to find anything -- maybe HEADER_SIZE is too small (currently $HEADER_SIZE, see line 14)" >&2

exit $e
