#!/usr/bin/perl # Rebuild the Debian '/var/lib/dpkg/status' file from information in # '/var/lib/dpkg/available' and '/var/lib/dpkg/info/*.list'. This is # useful if your 'status' file got corrupted if the system crashed during # package maintenance, for example. # # Copyright 2002 by Patrick Reynolds # Distributed under the terms of the GNU General Public License (GPL). # # Usage: # dpkg-rebuild # It takes no arguments and generates output in /tmp/status. # Move /tmp/status to /var/lib/dpkg if it looks acceptable. # # Limitations: # 1) Packages that are no longer available will not show up in the # rebuilt 'status' file. This means installed-but-obsolete packages # can't be managed after a rebuild. # # 2) The 'Conffiles:' keys in the 'status' file are not rebuilt. # Configuration files may not be completely removed when you purge # packages, and package upgrades may clobber existing configuration # files without asking. # # 3) The 'Essential:' keys in the 'status' file now appear after, not # before, the 'Status:' keys. I believe this is harmless. # # 4) Packages in the 'deinstall' state will appear to be in the 'purge' # state. Their configuration files will remain, but dpkg won't know # about them. # # 5) Packages in transitional or error states will be misreported. $available = "/var/lib/dpkg/available"; $status = "/tmp/status"; $info_dir = "/var/lib/dpkg/info"; foreach (<$info_dir/*.list>) { s#.*/([^/]+)\.list$#$1#; $installed{$_} = 1; } $state = 0; # 0=between, 1=copying-installed, 2=copying-not-installed open(AVAILABLE, "<$available") || die "no $available"; open(STATUS, ">$status") || die "no $status"; while () { chomp; if ($state == 0) { if (/^Package: (\S+)$/) { print STATUS "$_\n"; if ($installed{$1}) { $state = 1; print STATUS "Status: install ok installed\n"; delete $installed{$1}; } else { $state = 2; print STATUS "Status: purge ok not-installed\n"; } } else { die "Expected 'Package:' at $."; } } elsif ($state == 1) { if ($_ eq "") { print STATUS "\n"; $state = 0; } elsif (!/^Architecture: / && !/^Filename: / && !/^Size: / && !/^MD5sum: /) { print STATUS "$_\n"; } } elsif ($state == 2) { if ($_ eq "") { print STATUS "\n"; $state = 0; } elsif (/^Priority: / || /^Section: /) { print STATUS "$_\n"; } } else { die "Invalid state $state"; } } printf "Installed packages not found in $available:\n"; foreach (sort keys %installed) { print " $_\n"; }