Monday, January 4, 2016

Arch Linux: fixing deleted /var/lib/pacman/

So a couple days ago when installing a new SSD in my laptop and moving /var to its own partition my old hard drive decided to  quit on me and I ended up losing my var partition. Arch still booted up ok once I updated my fstab, but any time I tried to run pacman I would get this error:


error: failed to initialize alpm library
(could not find or read directory: /var/lib/pacman/)


The answers on the Arch forums all seemed to say the only way to get pacman working again would be an Arch reinstall, because pacman keeps all its history in /var. So without that there's no way to know what packages are installed, hence no way to update or manage any of it.

I came up with a very hackish way to fix pacman, trust it at your own risk, I make no guarantees that it'll work for you.

The first step is getting a list of installed without pacman somehow. The program pkgfile is what I used. It can test if a file exists in a package and also list all files in a package, and it uses it own database, not pacman's. If you don't have it installed you can download it from the archwiki, untar it and create /var/cache/pkgfile/ .

Now you can use pkgfile to check the files in /usr to see what packages they possibly match up to with:


sudo find /usr/ -name "*" | xargs -n 1 basename | xargs -n 1 /home/user/Downloads/usr/bin/pkgfile -s | tee ~/packages

replacing the path to pkgfile with whatever it is for you. This list will be really huge because it has tons of duplicate packages and a lot of packages that share files. But we can prune the list down a bit further with


cat ~/packages | sort | uniq > sorted_packages

Then you can sort even further by checking if all of the files listed in the package exist on your system. Create a script called varfix.sh


#!/bin/bash

/home/user/Downloads/usr/bin/pkgfile -l $1 | awk '{print $2}' | grep -v var > /tmp/files
test -s /tmp/files || exit 1

while IFS= read -r f; do
    if [[ ! -e $f ]]; then
        exit 1
    fi
done < /tmp/files
echo $1


then run it like this:

cat sorted_packages | ./varfix.sh | tee installed_packages

That list should be a lot smaller. Now boot into an Arch install CD so you can use pacstrap to reinitialize pacman's database. Because the files all already exist on your system, by default pacman won't overwrite them. You can change that behaviour by editing /usr/bin/pacstrap and adding

pacman_args+=(--force)

right before the "#create obligatory directories" line. Because pacstrap will now be overwriting all the files on your system, be sure to back up /etc and any other configuration data, you'll want to copy that back over when you're done installing packages.

You can now run pacstrap like you normally would when installing Arch. Then chroot into your root partition and run:

cat installed_packages | xargs pacman --noconfirm --force -S

There's a good chance it will error out with conflicting packages a couple times, for example my list contained both xarchiver and xarchiver-gtk2. Just manually edit installed_packages and delete one of the packages.

Now copy back over your saved /etc folder and any other saved configuration files and you should have a working pacman again.