merged grml-quickconfig nonblocking branch
[grml-scripts.git] / usr_sbin / dpkg-rebuild
1 #!/usr/bin/perl
2
3 # Rebuild the Debian '/var/lib/dpkg/status' file from information in
4 # '/var/lib/dpkg/available' and '/var/lib/dpkg/info/*.list'.  This is
5 # useful if your 'status' file got corrupted if the system crashed during
6 # package maintenance, for example.
7 #
8 # Copyright 2002 by Patrick Reynolds <reynolds@cs.duke.edu>
9 # Distributed under the terms of the GNU General Public License (GPL).
10 #
11 # Usage:
12 #   dpkg-rebuild
13 # It takes no arguments and generates output in /tmp/status.
14 # Move /tmp/status to /var/lib/dpkg if it looks acceptable.
15 #
16 # Limitations:
17 #   1) Packages that are no longer available will not show up in the
18 #   rebuilt 'status' file.  This means installed-but-obsolete packages
19 #   can't be managed after a rebuild.
20 #
21 #   2) The 'Conffiles:' keys in the 'status' file are not rebuilt.
22 #   Configuration files may not be completely removed when you purge
23 #   packages, and package upgrades may clobber existing configuration
24 #   files without asking.
25 #
26 #   3) The 'Essential:' keys in the 'status' file now appear after, not
27 #   before, the 'Status:' keys.  I believe this is harmless.
28 #
29 #   4) Packages in the 'deinstall' state will appear to be in the 'purge'
30 #   state.  Their configuration files will remain, but dpkg won't know
31 #   about them.
32 #
33 #   5) Packages in transitional or error states will be misreported.
34
35 $available = "/var/lib/dpkg/available";
36 $status = "/tmp/status";
37 $info_dir = "/var/lib/dpkg/info";
38
39 foreach (<$info_dir/*.list>) {
40         s#.*/([^/]+)\.list$#$1#;
41         $installed{$_} = 1;
42 }
43
44 $state = 0;   # 0=between, 1=copying-installed, 2=copying-not-installed
45 open(AVAILABLE, "<$available") || die "no $available";
46 open(STATUS, ">$status") || die "no $status";
47 while (<AVAILABLE>) {
48         chomp;
49         if ($state == 0) {
50                 if (/^Package: (\S+)$/) {
51                         print STATUS "$_\n";
52                         if ($installed{$1}) {
53                                 $state = 1;
54                                 print STATUS "Status: install ok installed\n";
55                                 delete $installed{$1};
56                         }
57                         else {
58                                 $state = 2;
59                                 print STATUS "Status: purge ok not-installed\n";
60                         }
61                 }
62                 else {
63                         die "Expected 'Package:' at $.";
64                 }
65         }
66         elsif ($state == 1) {
67                 if ($_ eq "") {
68                         print STATUS "\n";
69                         $state = 0;
70                 }
71                 elsif (!/^Architecture: / && !/^Filename: / && !/^Size: / && !/^MD5sum: /) {
72                         print STATUS "$_\n";
73                 }
74         }
75         elsif ($state == 2) {
76                 if ($_ eq "") {
77                         print STATUS "\n";
78                         $state = 0;
79                 }
80                 elsif (/^Priority: / || /^Section: /) {
81                         print STATUS "$_\n";
82                 }
83         }
84         else {
85                 die "Invalid state $state";
86         }
87 }
88
89 printf "Installed packages not found in $available:\n";
90 foreach (sort keys %installed) {
91         print "  $_\n";
92 }