5 # Sorry about this, but POSIX.pm isn't necessarily available
7 $version= '1.0.11'; # This line modified by Makefile
10 Debian GNU/Linux dpkg-divert $version. Copyright (C) 1995
11 Ian Jackson. This is free software; see the GNU General Public Licence
12 version 2 or later for copying conditions. There is NO warranty.
15 dpkg-divert [options] [--add] <file>
16 dpkg-divert [options] --remove <file>
17 dpkg-divert [options] --list [<glob-pattern>]
19 Options: --package <package> | --local --divert <divert-to> --rename
20 --quiet --test --help|--version --admindir <directory>
22 <package> is the name of a package whose copy of <file> will not be diverted.
23 <divert-to> is the name used by other packages' versions.
24 --local specifies that all packages' versions are diverted.
25 --rename causes dpkg-divert to actually move the file aside (or back).
27 When adding, default is --local and --divert <original>.distrib.
28 When removing, --package or --local and --divert must match if specified.
29 Package preinst/postrm scripts should always specify --package and --divert.
31 || &quit
("failed to write usage: $!");
34 $admindir= '/var/lib/dpkg';
43 &badusage
("two modes specified: $_ and --$mode");
50 unshift(@ARGV,$_); last;
51 } elsif (m/^--(help|version)$/) {
52 &usageversion
; exit(0);
53 } elsif (m/^--test$/) {
55 } elsif (m/^--rename$/) {
57 } elsif (m/^--quiet$/) {
59 } elsif (m/^--local$/) {
61 } elsif (m/^--add$/) {
64 } elsif (m/^--remove$/) {
67 } elsif (m/^--list$/) {
70 } elsif (m/^--divert$/) {
71 @ARGV || &badusage
("--divert needs a divert-to argument");
72 $divertto= shift(@ARGV);
73 $divertto =~ m/\n/ && &badusage
("divert-to may not contain newlines");
74 } elsif (m/^--package$/) {
75 @ARGV || &badusage
("--package needs a package argument");
76 $package= shift(@ARGV);
77 $divertto =~ m/\n/ && &badusage
("package may not contain newlines");
78 } elsif (m/^--admindir$/) {
79 @ARGV || &badusage
("--admindir needs a directory argument");
80 $admindir= shift(@ARGV);
82 &badusage
("unknown option \`$_'");
86 $mode='add' unless $mode;
88 open(O
,"$admindir/diversions") || &quit
("cannot open diversions: $!");
90 s/\n$//; push(@contest,$_);
91 $_=<O
>; s/\n$// || &badfmt
("missing altname");
93 $_=<O
>; s/\n$// || &badfmt
("missing package");
99 @ARGV == 1 || &badusage
("--add needs a single argument");
101 $file =~ m/\n/ && &badusage
("file may not contain newlines");
102 $divertto= "$file.distrib" unless defined($divertto);
103 $package= ':' unless defined($package);
104 for ($i=0; $i<=$#contest; $i++) {
105 if ($contest[$i] eq $file || $altname[$i] eq $file ||
106 $contest[$i] eq $divertto || $altname[$i] eq $divertto) {
107 if ($contest[$i] eq $file && $altname[$i] eq $divertto &&
108 $package[$i] eq $package) {
109 print "Leaving \`",&infon
($i),"'\n" if $verbose > 0;
112 &quit
("\`".&infoa
."' clashes with \`".&infon
($i)."'");
115 push(@contest,$file);
116 push(@altname,$divertto);
117 push(@package,$package);
118 print "Adding \`",&infon
($#contest),"'\n" if $verbose > 0;
119 &checkrename
($file,$divertto);
121 &dorename
($file,$divertto);
123 } elsif ($mode eq 'remove') {
124 @ARGV == 1 || &badusage
("--remove needs a single argument");
126 for ($i=0; $i<=$#contest; $i++) {
127 next unless $file eq $contest[$i];
128 &quit
("mismatch on divert-to\n when removing \`".&infoa
."'\n found \`".
129 &infon
($i)."'") if defined($divertto) && $altname[$i] ne $divertto;
130 &quit
("mismatch on package\n when removing \`".&infoa
."'\n found \`".
131 &infon
($i)."'") if defined($package) && $package[$i] ne $package;
132 print "Removing \`",&infon
($i),"'\n" if $verbose > 0;
133 $orgfile= $contest[$i];
134 $orgdivertto= $altname[$i];
135 @contest= (($i > 0 ?
@contest[0..$i-1] : ()),
136 ($i < $#contest ?
@contest[$i+1..$#contest] : ()));
137 @altname= (($i > 0 ?
@altname[0..$i-1] : ()),
138 ($i < $#altname ?
@altname[$i+1..$#altname] : ()));
139 @package= (($i > 0 ?
@package[0..$i-1] : ()),
140 ($i < $#package ?
@package[$i+1..$#package] : ()));
141 &checkrename
($orgdivertto,$orgfile);
142 &dorename
($orgdivertto,$orgfile);
146 print "No diversion \`",&infoa
,"', none removed\n" if $verbose > 0;
148 } elsif ($mode eq 'list') {
149 @ilist= @ARGV ?
@ARGV : ('*');
150 while (defined($_=shift(@ilist))) {
156 $pat= join('$|^',@list);
157 for ($i=0; $i<=$#contest; $i++) {
158 next unless ($contest[$i] =~ m/$pat/o ||
159 $altname[$i] =~ m/$pat/o ||
160 $package[$i] =~ m/$pat/o);
161 print &infon
($i),"\n";
165 &quit
("internal error - bad mode \`$mode'");
169 return (($_[2] eq ':' ?
"local " : length($_[2]) ?
"" : "any ").
170 "diversion of $_[0]".
171 (length($_[1]) ?
" to $_[1]" : "").
172 (length($_[2]) && $_[2] ne ':' ?
" by $_[2]" : ""));
176 return unless $dorename;
178 (@ssrc= lstat($rsrc)) || $! == &ENOENT
||
179 &quit
("cannot stat old name \`$rsrc': $!");
180 (@sdest= lstat($rdest)) || $! == &ENOENT
||
181 &quit
("cannot stat new name \`$rdest': $!");
182 if (@ssrc && @sdest &&
183 !($ssrc[0] == $sdest[0] && $ssrc[1] == $sdest[1])) {
184 &quit
("rename involves overwriting \`$rdest' with\n".
185 " different file \`$rsrc', not allowed");
190 return unless $dorename;
193 unlink($rsrc) || &quit
("rename: remove duplicate old link \`$rsrc': $!");
195 rename($rsrc,$rdest) || &quit
("rename: rename \`$rsrc' to \`$rdest': $!");
202 open(N
,"> $admindir/diversions-new") || &quit
("create diversions-new: $!");
203 for ($i=0; $i<=$#contest; $i++) {
204 print(N
"$contest[$i]\n$altname[$i]\n$package[$i]\n")
205 || &quit
("write diversions-new: $!");
207 close(N
) || &quit
("close diversions-new: $!");
208 unlink("$admindir/diversions-old") ||
209 $! == &ENOENT
|| &quit
("remove old diversions-old: $!");
210 link("$admindir/diversions","$admindir/diversions-old") ||
211 $! == &ENOENT
|| &quit
("create new diversions-old: $!");
212 rename("$admindir/diversions-new","$admindir/diversions")
213 || &quit
("install new diversions: $!");
216 sub infoa
{ &infol
($file,$divertto,$package); }
217 sub infon
{ &infol
($contest[$i],$altname[$i],$package[$i]); }
219 sub quit
{ print STDERR
"dpkg-divert: @_\n"; exit(2); }
220 sub badusage
{ print STDERR
"dpkg-divert: @_\n\n"; &usageversion
; exit(2); }
221 sub badfmt
{ &quit
("internal error: $admindir/diversions corrupt: $_[0]"); }