Sunday, December 27, 2009

Restoring RPM and YUM on Fedora after an accidental yum remove rpm

By default there is nothing that prevents an user from accidentally removing both yum and rpm from a Fedora system and once removed it is very painful to try to put them back. If only yum was removed it would be a little easier to restore. Yum can be reinstalled through rpm using the yum-*.rpm package downloaded from Fedora or the install disc. Without RPM, it's like a chicken-and-the-egg problem. The packages from Fedora and install discs (including the rpm package itself) are .rpm files and needs rpm to install.

Today I found myself in the situation where both YUM and RPM got removed by accident. I was following Fedora's instructions on finding and removing orphaned packages after upgrading and had yum remove some Fedora 11 packages that was left over. Being distracted by other things at the time, I noticed too late that removing those F11 orphaned packages also led yum to remove a bunch of F12 packages including rpm and yum.

So, what does one do in this situation besides "backup and reinstall? which I wanted to avoid if at all possible. It took me awhile to figure out but I was get rpm back on my system and restore it to its earlier state. Here are the steps I took.

My first inclination was to try to compile RPM. However, this was a FAIL since it required additional packages that I didn't have installed and I didn't have a package management system... Instead, I downloaded the rpm-*.rpm package from Fedora and was hoping to extract the files so I can use them to reinstall rpm and yum. To extract files out of an RPM package requires... rpm! Oh, the irony. There is a rpm2cpio program that will do that but that is available in . . . the rpm-build-*.rpm package! Fortunately, there are a lot of scripts available that will do it including some shell scripts. The Fedora RPM docs included some scripts and I downloaded the bash script version but it didn't work. After a little more digging, I found out that Fedora changed the compression scheme it uses in F12 from gzip to xz, so I modified the shell script as follows:


#!/bin/sh

pkg=$1
if [ "$pkg" = "" -o ! -e "$pkg" ]; then
echo "no package supplied" 1>&2
exit 1
fi
leadsize=96
o=`expr $leadsize + 8`
set `od -j $o -N 8 -t u1 $pkg`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "sig il: $il dl: $dl"
sigsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $sigsize + \( 8 - \( $sigsize \% 8 \) \) \% 8 + 8`
set `od -j $o -N 8 -t u1 $pkg`
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
# echo "hdr il: $il dl: $dl"
hdrsize=`expr 8 + 16 \* $il + $dl`
o=`expr $o + $hdrsize`
dd if=$pkg ibs=$o skip=1 2>/dev/null | xz -d


With this script, I extracted the rpm (rpm, rpm-build, rpm-libs, rpm-devel, rpm-python) files to a temp directory and install the files manually:


rpm2cpio.sh rpm-*.rpm | cpio -d -i
tar cf - ./usr ./etc ./bin ./var | (cd /; tar xvf -)


This installs the files onto the system but doesn't update the rpm databases, so I did a 'rpm -ivh rpm*.rpm' in addition to the dependent packages they needed.

With RPM installed, I was able to install YUM . I had kept a list of all the files that got removed earlier so I had yum reinstall all those packages and my system is now restored.

2 comments:

  1. Mmm.. I tried to run your script, but I had to compile and install xz first. I downloaded it from here http://tukaani.org/xz/.

    The problem now is that xz is saying it does not recognize the file format of the rpm file, giving me this output:

    xz: (stdin): File format not recognized

    What can I do?
    Thanks

    ReplyDelete
  2. This is what worked for me. If you have a machine which has rpm installed find out which files rpm uses. On the working machiner just run "rpm -qil rpm". You will see a long list but the ones you want are:
    /usr/bin/gendiff
    /usr/bin/rpm2cpio
    /usr/bin/rpmdb
    /usr/bin/rpmquery
    /usr/bin/rpmsign
    /usr/bin/rpmverify
    /usr/lib/rpm

    Copy these to the machine with the missing rpm package. This will allow you to pick yourself up by your botstraps. To complete you can "yum -y install rpm" or "rpm -ivh

    ReplyDelete