#!/bin/bash

# disrpm / undeb
# bash script to extract/unzip/unpack/unarchive *.rpm or *.deb packages.
# requires: bash, cpio, sed, hexdump|od, gzip/bzip2, dd.
# released under the Gnu General Public License (GPL)
# (c) bjdouma@xs4all.nl
######################
VER="v1.6, september 2007"
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
}

err_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()
{
	(
	exec 9<&2 2<&-
	dd if=$FILE ibs=$O skip=1 \
	| $2 -dc - \
	| cpio "$1"
	)
}

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

XDUMP=`type -P hexdump` || XDUMP=`type -P od` || err_exit "oops, can't find hexdump nor od -- bailing out"

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 ] && usage
[ -e "$FILE" ] || err_exit "$FILE: No such file or directory"

for ZIP in gzip bzip2
do
	r=0

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

	for O in $ZIP_OFFSETS
	do
		echo "--> at offset $O:" >&2
		$PASS1 $ZIP && $PASS2 $ZIP && r=1 \
		|| echo "... hmm, probably false drop" >&2
	done

	[ $r -eq 1 ] && break
done

[ $r -eq 0 ] && err_exit "$ME: failed to find anything -- maybe HEADER_SIZE is too small? (currently $HEADER_SIZE, see line 14)"
exit 0

