diff options
-rwxr-xr-x | rpm2targz | 250 |
1 files changed, 150 insertions, 100 deletions
@@ -21,107 +21,157 @@ # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# debug switch to allow to bypass use of rpm2cpio provided by the rpm package -USERPM2CPIO=true -[ "$TMPDIR" = "" ] && TMPDIR=/tmp -if [ ! -d "$TMPDIR" ]; then - echo "TMPDIR=$TMPDIR is not a dir" > /dev/stderr - exit 1 -fi -WORKDIR=`mktemp -d $TMPDIR/$$XXXXXX` -if [ $? != 0 ]; then - echo "Failed to make tmp workdir for file i/o conversion" > /dev/stderr - exit 1 +argv0=${0##*/} + +usage=false +stdout=false +verbose=false +files=false +msg="" +for opt; do + case ${opt} in + -h|--help) usage=true;; + -O|--stdout) stdout=true;; + -v|--verbose) verbose=true;; + --) break;; + -*) usage=true msg="unknown option '${opt}'";; + *) files=true;; + esac +done + +if ! ${files} || ${usage} ; then + cat <<-EOF + ${argv0}: Converts RPM archives to tar archives + + Usage: ${argv0} [options] <rpms> + + Options: + -h, --help This help screen (imagine that) + -O, --stdout Write tarball to stdout + -v, --verbose Verbose output + EOF + + if [ -n "${msg}" ] ; then + echo "Error: ${msg}" 1>&2 + exit 1 + else + exit 0 + fi fi -if [ "$1" = "" ]; then - echo "$0: Converts RPM format to standard GNU tar + GNU zip format." - if [ -e /etc/slackware-version ]; then - echo " (view converted packages with \"less\", install and remove" - echo " with \"installpkg\", \"removepkg\", \"pkgtool\", or manually" - echo " with \"tar\")" - fi - echo - echo "Usage: $0 <file.rpm>" - if [ "`basename $0`" = "rpm2tgz" ]; then - echo " (Outputs \"file.tgz\")" - else - echo " (Outputs \"file.tar.gz\")" - fi - exit 1; +compress="cat" +case ${argv0} in + rpm2tar) suffix=".tar";; + rpm2tarbz2) compress="bzip2" suffix=".tar.bz2";; + rpm2tbz2) compress="bzip2" suffix=".tbz2";; + rpm2tarlzma) compress="lzma" suffix=".tarlzma";; + rpm2tgz) compress="gzip" suffix=".tgz";; + rpm2targz|*) compress="gzip" suffix=".tar.gz";; +esac + +# try to get a temp dir using progressively older/crappier methods +WORKDIR="" +trap 'rm -rf "${WORKDIR}"' 0 + +WORKDIR=$(mktemp -d --tmpdir ${argv0}.XXXXXX 2>/dev/null) +if [ -z "${WORKDIR}" ] ; then + WORKDIR=$(mktemp -d -t ${argv0}.XXXXXX 2>/dev/null) + if [ -z "${WORKDIR}" ] ; then + [ -z "${TMPDIR}" ] && TMPDIR="/tmp" + WORKDIR=$(mcookie 2>/dev/null) + if [ -n "${WORKDIR}" ] ; then + WORKDIR="${TMPDIR}/${WORKDIR}" + else + WORKDIR="${TMPDIR}/$$" + fi + + worked=false + if rm -rf "${WORKDIR}" ; then + if mkdir -m 700 -p "${WORKDIR}" ; then + worked=true + elif mkdir -p "${WORKDIR}" ; then + if chmod 700 "${WORKDIR}" ; then + worked=true + fi + fi + fi + if ! ${worked} ; then + echo "${argv0}: ${WORKDIR}: unable to create a temp directory" + exit 1 + fi + fi fi -for i in $* ; do - if [ ! "$1" = "$*" ]; then - echo "Processing file: $i" - fi - rm -rf ${WORKDIR}/* || exit 1 ; # clear the way, just in case of mischief - - # Determine if this is a source or binary RPM. - # If we have getrpmtype, use that. Otherwise, try "file". - if command -v getrpmtype 1> /dev/null 2> /dev/null; then - if getrpmtype -n $i | grep source 1> /dev/null 2> /dev/null ; then - isSource=1 - else - isSource=0 - fi - else # use file. This works fine on Slackware, and is the default. - if file $i | grep RPM | grep " src " 1> /dev/null 2> /dev/null ; then - isSource=1 - else - isSource=0 - fi - fi - - ofn=${WORKDIR}/`basename $i .rpm`.cpio - if $USERPM2CPIO && command -v rpm2cpio 1> /dev/null 2> /dev/null ; then - rpm2cpio $i > $ofn 2> /dev/null - if [ ! $? = 0 ]; then - echo "... rpm2cpio failed. (maybe $i is not an RPM?)" - ( rm -rf "${WORKDIR}/*" ) - continue - fi - else # less reliable than rpm2cpio... - # get offset of start of payload - PAYLOADOFFSET=`rpmoffset < $i` - #identify compression - PAYLOADHEAD=`dd ibs=${PAYLOADOFFSET} skip=1 if=$i 2> /dev/null | dd bs=10 count=1 2> /dev/null` - if echo ${PAYLOADHEAD} | od -c | grep '037.213' > /dev/null ; then - echo "found gzip magic bytes" - decomp="gzip" - elif echo ${PAYLOADHEAD} | grep -e "^BZh" > /dev/null ; then - echo "found bzip magic bytes" - decomp="bzip2" - else - echo " $i - no magic compression identifier found - skipping file" - ( rm -rf "${WORKDIR}/*" ) - continue - fi - echo -n " trying to decompress with ${decomp}..." - dd ibs=`rpmoffset < $i` skip=1 if=$i 2> /dev/null | ${decomp} -dc > $ofn 2> /dev/null - if [ $? = 0 ]; then - echo " OK" - else - echo " FAILED" - echo " $i failed to decompress - skipping file" - ( rm -rf "${WORKDIR}/*" ) - continue - fi - fi - DEST=${WORKDIR} - if [ "$isSource" = "1" ]; then - DEST=$DEST/$(basename $(basename $i .rpm) .src) - fi - mkdir -p $DEST - ( cd $DEST - cpio -i -m -d < $ofn 1> /dev/null 2> /dev/null - rm -f $ofn - find . -type d -perm 700 -exec chmod 755 {} \; ) - ( cd ${WORKDIR} ; tar cf - . ) > `basename $i .rpm`.tar - gzip -9 `basename $i .rpm`.tar - if [ "`basename $0`" = "rpm2tgz" ]; then - mv `basename $i .rpm`.tar.gz `basename $i .rpm`.tgz - fi - ( rm -rf "${WORKDIR}/*" ) - echo + +ret=0 +dashdash=false +for file; do + if ! ${dashdash} ; then + case ${file} in + -v|--verbose) continue;; + -O|--stdout) continue;; + --) dashdash=true; continue;; + esac + fi + + ${verbose} && printf "Processing file: ${file} ... " + + outfile=${file##*/} + outfile=${outfile%.rpm} + base=${outfile%.src} + DEST="${WORKDIR}/${base}" + rm -rf "${DEST}" + if ! mkdir "${DEST}" ; then + echo "${argv0}: ${file}: ${DEST}: unable to create working directory" + rm -rf "${WORKDIR}" + exit 1 + fi + + # extract the CPIO from the RPM and unpack it + ( + decompressor="" + if command -v rpm2cpio 2>/dev/null 1>&2 ; then + decompressor="rpm2cpio" + rpm2cpio "${file}" + else + # do it by hand :/ + offset=$(rpmoffset < "${file}") + magic=`(dd ibs=${offset} skip=1 if="${file}" count=1 | dd bs=10 count=1 | od -b) 2>/dev/null` + case ${magic} in + "0000000 102 132 150 "*) decompressor="bzip2";; + "0000000 037 213 010 "*|*) decompressor="gzip";; + esac + dd ibs=${offset} skip=1 if="${file}" 2>/dev/null | ${decompressor} -dc + fi + [ $? -ne 0 ] && echo "${argv0}: ${file}: failed to extract cpio via ${decompressor} (not actually an RPM?)" 1>&2 + ) | ( + cd "${DEST}" + # filter stupid blocks info from cpio + cpio -i -m -d 2>/dev/null + ) + + if [ $? -ne 0 ] ; then + ret=1 + + ${verbose} && echo "FAIL" + else + # repack the files into the appropriate tar file + ( + cd "${WORKDIR}" + tar cf - "./${base}" + ) | ${compress} | ( + if ${stdout} ; then + cat + else + cat > "${outfile}${suffix}" + fi + ) + + ${verbose} && echo "OK" + fi + + rm -rf "${DEST}" done -rm -rf ${WORKDIR} + +rm -rf "${WORKDIR}" + +exit ${ret} |