3 # dpkg library: Debian GNU/Linux package maintenance utility,
4 # useful library functions.
6 # Copyright (C) 1994 Matt Welsh <mdw@sunsite.unc.edu>
7 # Copyright (C) 1994 Carl Streeter <streeter@cae.wisc.edu>
8 # Copyright (C) 1994 Ian Murdock <imurdock@debian.org>
9 # Copyright (C) 1994 Ian Jackson <iwj10@cus.cam.ac.uk>
11 # dpkg is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as
13 # published by the Free Software Foundation; either version 2,
14 # or (at your option) any later version.
16 # dpkg is distributed in the hope that it will be useful, but
17 # WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public
22 # License along with dpkg; if not, write to the Free Software
23 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 # /var/lib/dpkg/ +---- status
26 # |---- updates/ +---- <id>
31 # |---- info/ |---- <package>.{post,pre}{inst,rm}
33 # \---- tmp.ci/ +---- control
35 # |---- {post,pre}{inst,rm}
39 $backend = "dpkg-deb";
40 $fpextract = "dpkg-deb";
45 $status_mergeevery = 20;
47 $visiblecontroldir = "DEBIAN";
51 $statusdb = "$dd/status";
52 $updatesdir = "$dd/updates";
53 $availabledb = "$dd/available";
54 $scriptsdir = "$dd/info";
55 $listsdir = "$dd/info";
56 $lockfile = "$dd/lock";
57 $lockmine = "$dd/tmp.$$";
58 $controli = "$dd/tmp.ci";
59 $importantspace = "$updatesdir/tmp.i";
61 $orgadmindir= "/var/lib/dpkg";
62 &setadmindir
($orgadmindir);
64 @nokeepfields= ('package','version','package_revision',
65 'depends','recommended','optional','conflicts','part');
66 # Don't keep these fields in the Available database if a new record is
67 # merged which is missing values for any of them.
69 $packagere = '\w[-_a-zA-Z0-9+.@:=%]+';
70 $packageversionre= $packagere.'(\s*\([^()]+\))?';
71 $singledependencyre= "$packageversionre(\\s*\\|\\s*$packageversionre)*";
73 # Abbreviations for dpkg-deb options common to dpkg & dpkg-deb.
74 %debabbrevact= ('b','build', 'c','contents', 'e','control', 'i','info',
75 'f','field', 'x','extract', 'X','vextract');
77 @keysortorder= ('package', 'status', 'version', 'package_revision',
78 'maintainer', 'description',
79 'depends', 'recommended', 'optional', 'conflicts',
82 #*** replacements for things in headers ***#
84 #require 'sys/errno.ph';
85 sub ENOENT
{ 2; } # No such file or directory
86 sub EEXIST
{ 17; } # File exists
87 sub EISDIR
{ 21; } # Is a directory
88 sub ENOTEMPTY
{ 39; } # Directory not empty
90 #require 'sys/stat.ph';
91 sub S_IFMT
{ 00170000; }
92 sub S_IFREG
{ 0100000; }
93 sub S_IFLNK
{ 0120000; }
94 sub S_ISREG
{ ($_[0] & &S_IFMT
) == &S_IFREG
; }
95 sub S_ISLNK
{ ($_[0] & &S_IFMT
) == &S_IFLNK
; }
97 #require 'sys/wait.ph';
98 sub WIFEXITED
{ ($_[0] & 0x0ff) == 0; }
99 sub WIFSTOPPED
{ ($_[0] & 0x0ff) == 0x07f; }
100 sub WIFSIGNALED
{ !&WIFEXITED
&& !&WIFSTOPPED
; }
101 sub WCOREDUMP
{ ($_[0] & 0x080) != 0; }
102 sub WEXITSTATUS
{ ($_[0] & 0x0ff00) >> 8; }
103 sub WSTOPSIG
{ ($_[0] & 0x0ff00) >> 8; }
104 sub WTERMSIG
{ $_[0] & 0x07f; }
106 #require 'sys/signal.ph';
109 #require 'sys/syscall.ph';
110 sub SYS_lseek
{ 19; }
113 #*** /var/lib/dpkg database management - `exported' routines ***#
116 # Lock the package management databases, amalgamate any
117 # changes files, and leave the results in:
118 # From /var/lib/dpkg/status:
119 # %st_pk2v{ package_name, field_name } = field_value
120 # %st_p21{ package_name } = 1
121 # From /var/lib/dpkg/available:
122 # %av_pk2v{ package_name, field_name } = field_value
123 # %av_p21{ package_name } = 1
125 # %all_k21{ field_name } = 1
127 &read_status_mainfile
;
128 &read_status_extrafiles
;
129 &write_status_mainfile
;
130 &delete_status_extrafiles
;
131 &read_available_file
;
132 &prepare_important_database
;
133 &invent_status_availableonly_packages
;
136 sub database_finish
{
137 # Tidy up and unlock the package management databases.
138 &release_important_database
;
139 &write_available_file
;
140 &write_status_mainfile
;
141 &delete_status_extrafiles
;
146 # Record amended status of package (in an `extra' file).
147 local (@packages) = @_;
149 &debug
("amended @packages");
151 $st_pk2v{$p,'status'}= "$st_p2w{$p} $st_p2h{$p} $st_p2s{$p}";
154 $all_k21{'status'}= 1;
155 local ($ef) = sprintf("%03d",$next_extrafile++);
156 &write_database_file
("$updatesdir/$ef",*st_pk2v
,*st_p21
,1,@packages);
157 push(@status_extrafiles_done,$ef); &sync
;
158 if ($next_extrafile >= $status_mergeevery) {
159 &write_status_mainfile
;
160 &delete_status_extrafiles
;
163 for $p (@packages) { delete $st_pk2v{$p,'status'}; }
164 &prepare_important_database
;
167 sub note_amended_status
{
168 # Note the fact that the status has been modified, but don't
173 sub amended_available
{
174 # Record amended available information (in core for the moment -
175 # noncritical, so we defer writing it out).
176 $available_modified++;
177 &invent_status_availableonly_packages
(@_);
180 #*** internal routines ***#
182 sub invent_status_availableonly_packages
{
184 for $p (@_ ?
@_ : keys %av_p21) {
185 next if defined($st_p2w{$p});
186 $st_p2w{$p}= 'unknown';
188 $st_p2s{$p}= 'not-installed';
192 sub read_status_mainfile
{
194 &read_status_database_file
($statusdb);
197 sub read_status_extrafiles
{
199 opendir(UPD
,$updatesdir) || &bombout
("cannot opendir updates $updatesdir: $!");
200 for $_ (sort readdir(UPD
)) {
201 next if $_ eq '.' || $_ eq '..';
202 if (m/\.new$/ || m/\.old$/ || $_ eq 'tmp.i') {
203 unlink("$updatesdir/$_") ||
204 &bombout
("cannot unlink old update temp file $updatesdir/$_: $!");
207 &read_status_database_file
("$updatesdir/$fn");
208 $status_modified= 1; push(@status_extrafiles_done, $fn);
210 warn("$name: ignoring unexpected file in $updatesdir named \`$_'\n");
216 sub read_status_database_file
{
217 local ($filename) = @_;
218 @p= &read_database_file
($filename,*st_pk2v
,*st_p21
);
220 if (defined($st_pk2v{$p,'status'})) {
221 $v= $st_pk2v{$p,'status'};
224 m/^(unknown|install|deinstall|purge)\s+(ok|hold)\s+(not-installed|unpacked|postinst-failed|installed|removal-failed|config-files)$/
225 || &bombout
("package \`$p' has bad status in $statusdb (\`$v')");
230 delete($st_pk2v{$p,'status'});
232 $status_modified= 0; @status_extrafiles_done= ();
235 sub write_status_mainfile
{
236 return unless $status_modified;
238 for $p (keys %st_p21) {
239 $st_pk2v{$p,'status'}= "$st_p2w{$p} $st_p2h{$p} $st_p2s{$p}";
241 $all_k21{'status'}= 1;
242 unlink("$statusdb.old") || $!==&ENOENT
||
243 &bombout
("unable to remove $statusdb.old: $!");
244 link("$statusdb","$statusdb.old") ||
245 &bombout
("unable to back up $statusdb: $!");
246 &write_database_file
($statusdb,*st_pk2v
,*st_p21
,0);
249 for $p (keys %st_p21) { delete $st_pk2v{$p,'status'}; }
252 sub delete_status_extrafiles
{
253 #print STDERR "delete @status_extrafiles_done> "; <STDIN>;
254 for $_ (@status_extrafiles_done) {
255 unlink("$updatesdir/$_") ||
256 &bombout
("cannot remove already-done update file $updatesdir/$_: $!");
259 @status_extrafiles_done= ();
262 sub read_available_file
{
263 &read_database_file
($availabledb,*av_pk2v
,*av_p21
);
264 $available_modified= 0;
267 sub write_available_file
{
268 return unless $available_modified;
269 &write_database_file
($availabledb,*av_pk2v
,*av_p21
,0);
270 $available_modified= 0;
273 #*** bottom level of read routines ***#
275 sub read_database_file
{
276 local ($filename, *xx_pk2v
, *xx_p21
) = @_;
277 local ($quick,$cf,@cf,%cf_k2v,@cwarnings,@cerrors,$p,@p)= 1;
278 &debug
("reading database file $filename");
279 open(DB
,"<$filename") || &bombout
("unable to open $filename for reading: $!");
282 while (defined($cf=<DB
>)) {
285 $p= &parse_control_entry
;
287 # warn("$name: warning, packaging database file $filename\n".
288 # " contains oddities in entry for package \`$p':\n ".
289 # join(";\n ",@cwarnings).
290 # ".\n This is probably a symptom of a bug.\n");
293 &bombout
("packaging database corruption - please report:\n".
294 " file $filename has error(s) in entry for \`$p':\n ".
295 join(";\n ",@cerrors). ".");
298 for $k (keys %all_k21) { $xx_pk2v{$p,$k}= $cf_k2v{$k}; }
301 &debug
("database file $filename read");
306 sub parse_control_entry
{
307 # Expects $cf to be a sequence of lines,
308 # representing exactly one package's information.
309 # Results are put in cf_k2v.
310 # @warnings and @errors are made to contain warning and error
311 # messages, respectively.
312 local ($ln,$k,$v,$p,$l);
313 @cwarnings= @cerrors= ();
316 # &debug(">>>$cf<<<#\n");
318 if ($cf =~ s/\n\n+/\n/g) { push(@cwarnings, "blank line(s) found and ignored"); }
319 if ($cf =~ s/^\n+//) { push(@cwarnings, "blank line(s) at start ignored"); }
321 $cf.= "\n"; push(@cwarnings, "missing newline after last line assumed");
323 if ($cf =~ s/\0//g) {
324 push(@cwarnings, "nul characters discarded");
327 $cf =~ s/\n([ \t])/\0$1/g; # join lines
328 # &debug(">>>$cf<<<*\n");
330 for $_ (split(/\n/,$cf)) {
333 m/^(\S+):[ \t]*/ || (push(@cerrors, "garbage at line $ln, \`$_'"), next);
334 $k= $1; $v= $'; $k =~ y/A-Z/a-z/; $k='package_revision
' if $k eq 'revision
';
335 # &debug("key=\`$k' value
=\
`$v' line=\`$_'\n");
336 $ln += ($v =~ s/\0/\n/g);
339 # while ($cf =~ s/^(\S+):[ \t]*(.*)\n//) {
341 return unless keys %cf_k2v;
342 $p= $cf_k2v{'package'}; delete $cf_k2v{'package'}; delete $all_k21{'package'};
343 $cf_k2v{'class'} =~ y/A-Z/a-z/ if defined($cf_k2v{'class'});
344 $cf_k2v{'section
'} =~ y/A-Z/a-z/ if defined($cf_k2v{'section
'});
346 # push(@cerrors, "garbage at line $ln, \`".($cf =~ m/\n/ ? $` : $cf)."'");
348 defined($p) || push(@cerrors, "no \
`package' line");
349 $p =~ m/^$packagere$/o || &bad_control_field('package');
350 defined($cf_k2v{'version'}) || push(@cerrors, "no Version field");
351 for $f ('depends','recommended','optional','conflicts') {
352 next unless defined($cf_k2v{$f}) && length($cf_k2v{$f});
353 $cf_k2v{$f} =~ m/^$singledependencyre(\s*,\s*$singledependencyre)*$/o
354 || &bad_control_field("$f");
360 sub bad_control_field {
361 push(@cerrors, "bad \`$_[0]' line, contains \`$cf_k2v{$_[0]}'");
364 #*** bottom level of database writing code ***#
366 sub write_database_file {
367 local ($filename, *xx_pk2v, *xx_p21, $important, @packages) = @_;
368 local ($p,$tl,$k,$v);
369 if (!@packages) { @packages= keys(%xx_p21); }
371 &debug("called write_database_file
$filename, important
=$important, for @packages");
373 open(DB,">$filename.new
") || &bombout("unable to create
$filename.new
: $!");
377 &write_database_string("\n") if $tl;
378 &write_database_string("Package
: $p\n");
379 for $k (keys %all_k21) {
380 next unless defined($xx_pk2v{$p,$k});
382 $v =~ s/\n(\S)/\n $1/g;
383 &write_database_string("$k: $v\n");
387 if (!truncate(IMP,$tl)) {
388 if (print(IMP "#")) {
389 warn("$name: warning - unable to truncate $importantspace: $!;".
390 "\n commenting the rest out instead seems to have worked.\n");
392 &database_corrupted
("unable to truncate $importantspace: $!");
395 close(IMP
) || &database_corrupted
("unable to close $importantspace: $!");
396 rename($importantspace,$filename) ||
397 &database_corrupted
("unable to install $importantspace as $filename: $!");
399 close(DB
) || &bombout
("unable to close $filename.new: $!");
400 rename("$filename.new",$filename) ||
401 &bombout
("unable to install $filename.new as $filename: $!");
405 sub write_database_string
{
406 $tl += length($_[0]);
409 &database_corrupted
("failed write to update file $importantspace: $!");
412 &bombout
("failed to write to $filename.new: $!");
416 sub database_corrupted
{
417 &debug
("corruptingstatus @_");
418 print STDERR
"$name - really horrible error:\n @_\n".
419 "Package manager status data is now out of step with installed system.\n".
420 "(Last action has not been recorded. Please try re-installing \`@packages'\n".
421 "to ensure system consistency, or seek assistance from an expert if\n".
422 "problems persist.)\n";
426 sub prepare_important_database
{
427 open(IMP
,"+>$importantspace") || &bombout
("unable to create $importantspace: $!");
428 select((select(IMP
),$|=1)[0]);
429 print(IMP
"#padding\n"x512
) || &bombout
("unable to pad $importantspace: $!");
430 seek(IMP
,0,0) || &bombout
("unable to seek (rewind) $importantspace: $!");
431 &debug
("important database prepared");
434 sub release_important_database
{
436 unlink($importantspace) || &bombout
("unable to delete $importantspace: $!");
437 &debug
("important database released");
440 #*** database lock management ***#
443 # Lock the package management databases. Stale locks will
444 # be broken, but there is no concurrency checking on the lock-
446 push(@cleanups,'unlink($lockmine)');
447 open(PID
,">$lockmine") || &bombout
("failed to create new pid file $lockmine: $!");
448 printf(PID
"%010d\n",$$) || &bombout
("failed to add pid to $lockmine: $!");
449 close(PID
) || &bombout
("failed to close new pid file $lockmine: $!");
450 unless (link($lockmine,$lockfile)) {
451 $! == &EEXIST
|| &bombout
("failed to create lock on packages database: $!");
452 if (open(PID
,"<$lockfile")) {
453 undef $/; $opid= <PID>; $/="\n";
454 $opid =~ m/^\d{10}\n$/ || &lockfailed
(" (pid missing)");
457 &bombout
("/proc/self not found ($!) - /proc not mounted ?");
458 -d
sprintf("/proc/%d",$opid) && &lockfailed
(" (in use by pid $opid)");
459 if (open(PID
,"<$lockfile")) {
460 $opid eq <PID
> || &lockfailed
(' (pid changed)');
463 &bombout
("failed to break stale lock on database: $!");
465 "$name: stale lock found on packages database, lock forced\n";
468 &bombout
("failed to confirm who owns lock on database: $!");
471 $!==&ENOENT
|| &bombout
("failed to determine who owns lock on database: $!");
473 link($lockmine,$lockfile) ||
474 &bombout
("failed to create lock on packages database: $!");
476 push(@cleanups, 'unlink($lockfile) ||
477 warn("$name: failed to unlock packages database: $!\n")');
481 sub unlock_database
{
482 unlink($lockfile) || &bombout
("failed to unlock packages database: $!");
486 #*** error handling ***#
488 sub lockfailed
{ &bombout
("unable to lock packages database@_"); }
489 sub bombout
{ print STDERR
"$name - critical error: @_\n"; &cleanup
; exit(2); }
490 sub badusage
{ print STDERR
"$name: @_\n\n"; &usage
; &cleanup
; exit(3); }
493 &bombout
("failed write to stdout: $!");
498 eval(pop(@cleanups));
499 $@
&& print STDERR
"error while cleaning up: $@";
504 return unless $debug;
509 local ($w,$s) = ($?
,$!);
510 &debug
("ecode $w syserr $s");
512 # (($w & 0x0ffff) == 0x0ff00 ? "problems running program - exit code -1" :
513 # ($w & 0x0ff) == 0 ? "exit status ".(($w & 0x0ff00) >> 8) :
514 # ($w & 0x0ff) == 0x07f ? "stopped by signal ".(($w & 0x0ff00) >> 8) :
515 # "killed by signal ".($w & 0x07f).($w & 0x080 ? " (core dumped)" : '')).
516 (&WIFEXITED
($w) ?
"exit status ".&WEXITSTATUS
($w) :
517 &WIFSIGNALED
($w) ?
"killed by signal ".&WTERMSIG
($w).
518 (&WCOREDUMP
($w) ?
" (core dumped)" : ""):
519 &WIFSTOPPED
($w) ?
"stopped due to signal ".&WSTOPSIG
($w) :
520 "unknown status $w").
521 ($s ?
", system error $s" : '');
524 #*** miscellaneous helpful routines ***#
528 local ($r,$n,$this) = '';
530 defined($n=read($fh,$this,4096)) || return undef;
537 #sub debug_compare_verrevs {
539 # local ($i)= &x_compare_verrevs(@i);
540 # &debug("compare_verrevs >@i< = >$i<");
544 sub compare_verrevs
{
545 local ($av,$ar,$bv,$br,$c) = @_;
546 $c = &compare_vnumbers
($av,$bv); return $c if $c;
547 return &compare_vnumbers
($ar,$br);
550 sub compare_vnumbers
{
553 $a =~ s/^\D*//; $ad= $&; $ad =~ s/\W/ /g;
554 $b =~ s/^\D*//; $bd= $&; $bd =~ s/\W/ /g;
555 $cm = $ad cmp $bd; return $cm if $cm;
556 $a =~ s/^\d*//; $ad= $&;
557 $b =~ s/^\d*//; $bd= $&;
558 $cm = $ad <=> $bd; return $cm if $cm;
559 } while (length ($a) && length ($b));
560 return length ($a) cmp length ($b);