perl-dpkg.pl 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  1. #!/usr/bin/perl --
  2. #
  3. # dpkg: Debian GNU/Linux package maintenance utility
  4. #
  5. # Copyright (C) 1994 Matt Welsh <mdw@sunsite.unc.edu>
  6. # Copyright (C) 1994 Carl Streeter <streeter@cae.wisc.edu>
  7. # Copyright (C) 1994 Ian Murdock <imurdock@debian.org>
  8. # Copyright (C) 1994 Ian Jackson <iwj10@cus.cam.ac.uk>
  9. #
  10. # dpkg is free software; you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License as
  12. # published by the Free Software Foundation; either version 2,
  13. # or (at your option) any later version.
  14. #
  15. # dpkg is distributed in the hope that it will be useful, but
  16. # WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public
  21. # License along with dpkg; if not, write to the Free Software
  22. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. #
  24. $version= '0.93.15'; # This line modified by Makefile
  25. sub version {
  26. print STDERR <<END;
  27. Debian GNU/Linux \`dpkg\' package handling tool version $version.
  28. Copyright (C)1994 Matt Welsh, Carl Streeter, Ian Murdock, Ian Jackson.
  29. This is free software; see the GNU General Public Licence version 2
  30. or later for copying conditions. There is NO warranty.
  31. END
  32. }
  33. sub usage {
  34. print STDERR <<END;
  35. Usage: dpkg -i|--install <opts> <.deb file name> ... | -a|--auto <dir> ...
  36. dpkg --unpack <opts> <.deb file name> ... | -a|--auto <dir> ...
  37. dpkg -A|--avail <opts> <.deb file name> ... | -a|--auto <dir> ...
  38. dpkg --configure <opts> <package name> ... | -a|--auto
  39. dpkg -r|--remove <opts> <package name> ... | -a|--auto
  40. dpkg -l|--list <status select> [<regexp> ...]
  41. dpkg -s|--status <status select> [<package-name> ...]
  42. dpkg -S|--search <glob pattern> ...
  43. dpkg -b|--build|-c|--contents|-e|--control|--info|-f|--field|
  44. -x|--extract|-X|--vextract ... (see dpkg-deb --help)
  45. Options: --purge --control-quiet --control-verbose --version --help
  46. -R|--root=<directory> --admindir=<directory> --instdir=<directory>
  47. --no-keep-old-conf --no-keep-new-conf -N|--no-also-select
  48. --ignore-depends=<package name>,...
  49. --conf-(same|diff|all)-(new|old|promptnew|promptold)
  50. --force-<thing>,<thing>,... --no-force-...|--refuse-...
  51. Status selections: --isok-[o][h] (OK, Hold; alternatives are y, n)
  52. --want-[u][i][d][p] (Unknown, Install, Deinstall, Purge)
  53. --stat-[nupircNO] (Not, Unpacked, Postinst-failed, Installed, Removal-failed,
  54. Config-files, Not/Config-files, Not/Config-files/Installed)
  55. Force things: conflicts, depends, downgrade, depends-version, prermfail,
  56. configure-any, hold, extractfail
  57. (default is --no-force everything, except --force-downgrade)
  58. Use \`$dselect\' for user-friendly package management.
  59. END
  60. }
  61. $instroot= '';
  62. $controlwarn = 1;
  63. $estatus = 0;
  64. $filename_pattern = "*.deb";
  65. %force= ( 'conflicts',0, 'depends',0, 'depends-version',0, 'downgrade',1,
  66. 'prermfail',0, 'postrmfail',0, 'hold',0, 'configure-any',0,
  67. 'extractfail',0 );
  68. %selectmap_h= ('o','ok', 'h','hold', 'y','ok', 'n','hold');
  69. %selectmap_w= ('u', 'unknown', 'i', 'install', 'd', 'deinstall', 'p', 'purge');
  70. %selectmap_s= ('n', 'not-installed',
  71. 'u', 'unpacked',
  72. 'p', 'postinst-failed',
  73. 'i', 'installed',
  74. 'r', 'removal-failed',
  75. 'c', 'config-files',
  76. 'n', 'not-installed,config-files',
  77. 'o', 'not-installed,config-files,installed');
  78. %selectthings= ('isok','h', 'want','w', 'stat','s');
  79. require 'lib.pl'; # This line modified by Makefile
  80. $0 =~ m|[^/]+$|; $name = $dpkg;
  81. $|=1;
  82. umask(022);
  83. $action= 'none';
  84. %myabbrevact= ('i','install', 'r','remove', 'A','avail',
  85. 'S','search', 'l','list', 's','status');
  86. # $conf...[0] corresponds to `same', 1 to diff
  87. $confusenew[0]= 0; $confprompt[0]= 0;
  88. $confusenew[1]= 1; $confprompt[1]= 1;
  89. # Ie, default is to prompt only when hashes differ,
  90. # and to use new when hashes differ
  91. while ($ARGV[0] =~ m/^-/) {
  92. $_= shift(@ARGV);
  93. $noptsdone++;
  94. if (m/^--$/) {
  95. $noptsdone--; last;
  96. } elsif (m/^--(install|remove|unpack|configure|avail|list|status)$/) {
  97. &setaction($1);
  98. } elsif (m/^--(build|contents|control|info|field|extract|vextract)$/) {
  99. $noptsdone--; &backend($1);
  100. } elsif (m/^--ignore-depends=($packagere(,$packagere)*)$/o) {
  101. grep($ignore_depends{$_}=1, split(/,/,$1));
  102. } elsif (m/^--(force|no-force|refuse)-/) {
  103. $fvalue= ($1 eq 'force');
  104. for $fv (split(/,/,$')) {
  105. defined($force{$fv}) || &badusage("unknown --force option \`$fv'");
  106. $force{$fv}= $fvalue;
  107. }
  108. } elsif (m/^--conf-(same|diff|all)-(new|old|promptnew|promptold)$/) {
  109. $new= $2 eq 'new' || $2 eq 'promptnew';
  110. $prompt= $2 eq 'promptnew' || $2 eq 'promptold';
  111. if ($1 ne 'same') { $confusenew[1]= $new; $confprompt[1]= $prompt; }
  112. if ($1 ne 'diff') { $confusenew[0]= $new; $confprompt[0]= $prompt; }
  113. } elsif (m/^--(\w+)-(\w+)$/ && defined($selectthings{$1})) {
  114. $thisname= $1;
  115. $thisthing= $selectthings{$thisname};
  116. $_=$2;
  117. eval '%thismap= %selectmap_'.$thisthing;
  118. while (s/^.//) {
  119. if (!defined($thismap{$&})) {
  120. &badusage("unknown status letter $& for status field $thisname");
  121. }
  122. $thiscodes= $thismap{$&};
  123. $selectdo.= "undef \$select_$thisthing;";
  124. for $v (split(m/,/, $thiscodes)) {
  125. $selectdo .= "\$select_$thisthing{'$v'}=1;";
  126. }
  127. }
  128. } elsif (m/^--root=/) {
  129. $instroot=$'; &setadmindir("$instroot/$orgadmindir");
  130. } elsif (m/^--admindir=/) {
  131. &setadmindir("$'");
  132. } elsif (m/^--instdir=/) {
  133. $instroot=$';
  134. } elsif (m/^--auto$/) {
  135. $auto= 1;
  136. } elsif (m/^--purge$/) {
  137. $purge= 1;
  138. } elsif (m/^--skip-same-version$/) {
  139. print STDERR
  140. "Warning: dpkg --skip-same-version not implemented, will process\n".
  141. " process even packages the same version of which is installed.\n";
  142. } elsif (m/^--no-also-select$/) {
  143. $noalsoselect= 1;
  144. } elsif (m/^--control-verbose$/) {
  145. $controlwarn= 1;
  146. } elsif (m/^--control-quiet$/) {
  147. $controlwarn= 0;
  148. } elsif (m/^--no-keep-old-conf$/) {
  149. $nokeepold= 1;
  150. } elsif (m/^--no-keep-new-conf$/) {
  151. $nokeepnew= 1;
  152. } elsif (m/^--succinct-prompts$/) {
  153. $succinct= 1;
  154. } elsif (m/^--debug$/) {
  155. $debug= 1;
  156. } elsif (m/^--help$/) {
  157. &usage; exit(0);
  158. } elsif (m/^--version$/) {
  159. &version; exit(0);
  160. } elsif (m/^--/) {
  161. &badusage("unknown option \`$_'");
  162. } else {
  163. s/^-//; $noptsdone--;
  164. while (s/^.//) {
  165. $noptsdone++;
  166. if (defined($myabbrevact{$&})) {
  167. &setaction($myabbrevact{$&});
  168. } elsif (defined($debabbrevact{$&})) {
  169. $noptsdone--; &backend($debabbrevact{$&});
  170. } elsif ($& eq 'a') {
  171. $auto= 1;
  172. } elsif ($& eq 'D') {
  173. $debug= 1;
  174. } elsif ($& eq 'N') {
  175. $noautoselect= 1;
  176. } elsif ($& eq 'R') {
  177. s/^=// || &badusage("missing value for -R=<dir> option");
  178. $instroot= $_; &setadmindir("$instroot/$orgadmindir"); $_='';
  179. } else {
  180. &badusage("unknown option \`-$&'");
  181. }
  182. }
  183. }
  184. }
  185. $action eq 'none' && &badusage("an action must be specified");
  186. &debug("arguments parsed");
  187. #*** list, status or search - the nonactive operations ***#
  188. if ($action eq 'list' || $action eq 'status') {
  189. &database_start;
  190. if ($action eq 'list' || !@ARGV) {
  191. &selectall(*selectmap_h,*select_h);
  192. &selectall(*selectmap_w,*select_w);
  193. &selectall(*selectmap_s,*select_s);
  194. if (@ARGV) { $select_s{'not-installed'}=0; }
  195. }
  196. $ecode= 0;
  197. if ($action eq 'status') {
  198. for ($i=0;$i<=$#keysortorder;$i++) {
  199. $keysortorder{$keysortorder[$i]}= sprintf("%6d ",$i);
  200. # &debug("set $i: $keysortorder[$i], sortorder ".
  201. # "\`$keysortorder{$keysortorder[$i]}'");
  202. }
  203. @ARGV= &applyselcrit(sort keys %st_p21) unless @ARGV;
  204. for $p (@ARGV) {
  205. if (!$st_p21{$p}) {
  206. print(STDERR "$name: no information available about package $p\n")
  207. || &bombout("writing to stderr: $!");
  208. $ecode= 1;
  209. }
  210. print("Package: $p\n",
  211. "Status: $st_p2w{$p} $st_p2h{$p} $st_p2s{$p}\n") || &outerr;
  212. for $k (sort { $keysortorder{$a}.$a cmp $keysortorder{$b}.$b; }
  213. keys %all_k21) {
  214. # &debug("field $k, sortorder \`$keysortorder{$k}'");
  215. next unless defined($st_pk2v{$p,$k});
  216. $v= $st_pk2v{$p,$k}; next unless length($v);
  217. if ($k eq 'conffiles' || $k eq 'list') {
  218. $v= sprintf("(%d files, not listed)",
  219. scalar(grep(m/\S/, split(/\n/,$v))));
  220. }
  221. print("$k: $v\n") || &outerr;
  222. }
  223. if (defined($av_p21{$p})) {
  224. print("\n\`Available' version of package $p, where different:\n")
  225. || &outerr;
  226. for $k (keys %all_k21) {
  227. next unless defined($av_pk2v{$p,$k});
  228. $v= $st_pk2v{$p,$k}; next unless length($v);
  229. $u= $st_pk2v{$p,$k}; next if $u eq $v;
  230. print("$k: $v\n") || &outerr;
  231. }
  232. print("\n") || &outerr;
  233. }
  234. }
  235. } else { # $action eq 'list'
  236. $listhead=0;
  237. if (@ARGV) {
  238. for $r (@ARGV) {
  239. &listinfo(&applyselcrit(sort grep(m/$r/,keys %st_p21)));
  240. }
  241. } else {
  242. undef $r;
  243. &listinfo(&applyselcrit(sort keys %st_p21));
  244. }
  245. }
  246. &database_finish;
  247. exit($ecode);
  248. }
  249. sub listinfo {
  250. if (!@_) {
  251. print(STDERR
  252. defined($r) ?
  253. "No selected packages found matching regexp \`$r'.\n" :
  254. "No packages matched selection criteria.\n") ||
  255. &bombout("writing to stderr: $!");
  256. return;
  257. }
  258. if (!$listhead) {
  259. print <<END
  260. Err? Name Version Rev Description
  261. | Status=Not/Unpacked/Postinst-failed/Installed/Removal-failed/Config-files
  262. |/ Desired=Unknown/Install/Deinstall/Purge
  263. ||/ | | | |
  264. +++-============-==========-===-===============================================
  265. END
  266. || &outerr;
  267. $listhead= 1;
  268. }
  269. for $p (@_) {
  270. $des= $st_pk2v{$p,'description'};
  271. $des= $` if $des =~ m/\n/;
  272. printf("%s%.1s%.1s %-12.12s %-10.10s %-3.3s %-47.47s\n",
  273. $st_p2h{$p} eq 'hold' ? 'x' : ' ', $st_p2s{$p}, $st_p2w{$p},
  274. $p, $st_pk2v{$p,'version'}, $st_pk2v{$p,'package_revision'},
  275. $des);
  276. }
  277. }
  278. sub applyselcrit {
  279. &debug("sel from @_");
  280. for $f (@_) { &debug("$f :$st_p2s{$f},$select_s{$st_p2s{$f}}:$st_p2w{$f},$select_w{$st_p2w{$f}}:$st_p2h{$f},$select_h{$st_p2h{$f}}:"); }
  281. @ascr= grep($select_s{$st_p2s{$_}} &&
  282. $select_w{$st_p2w{$_}} &&
  283. $select_h{$st_p2h{$_}},
  284. @_);
  285. &debug("sel gave @ascr");
  286. @ascr;
  287. }
  288. sub selectall {
  289. local (*map, *sel) = @_;
  290. local ($v);
  291. for $v (values %map) {
  292. next if m/,/;
  293. $sel{$v}=1;
  294. }
  295. }
  296. if ($action eq 'search') {
  297. @ARGV || &badusage("need at least one glob pattern for --$action");
  298. &database_start;
  299. while (@ARGV) {
  300. $orgpat= $_= shift(@ARGV);
  301. s/\W/\\$&/g;
  302. s|\\\*\\\*|.*|g;
  303. s|\\\*|[^/]*|g;
  304. s|\\\?|[^/]|g;
  305. $pat= $_; $f=0;
  306. for $p (sort keys %st_p21) {
  307. $s= $st_p2s{$p};
  308. next if $s eq 'not-installed' || $s eq 'config-files';
  309. &filesinpackage($arg, $package);
  310. @ilist= grep(m/^$pat$/,@ilist);
  311. next unless @ilist;
  312. $f=1;
  313. for $_ (@ilist) { print("$p: $_\n") || &outerr; }
  314. }
  315. if (!$f) {
  316. print(STDERR "No packages found containing \`$orgpat'.\n")
  317. || &bombout("writing to stderr: $!");
  318. $ecode= 1;
  319. }
  320. }
  321. &database_finish;
  322. exit($ecode);
  323. }
  324. #*** lock and read in databases ***#
  325. &database_start;
  326. &debug("databases read");
  327. #*** derive argument list for --auto ***#
  328. if ($auto) {
  329. if ($action eq 'install' || $action eq 'unpack' || $action eq 'avail') {
  330. @ARGV || &badusage("need at least one directory for --$action --auto");
  331. pipe(RP,WP) || &bombout("create pipe for \`find': $!");
  332. defined($c= fork) || &bombout("fork for \`find': $!");
  333. if (!$c) {
  334. close(RP); open(STDOUT,">& WP"); close(WP);
  335. exec('find',@ARGV,'-name',$filename_pattern,'-type','f','-print0');
  336. die "$name: could not exec \`find': $!";
  337. }
  338. close(WP);
  339. $/="\0"; @ARGV= <RP>; $/="\n";
  340. eof || &bombout("read filenames from \`find': $!");
  341. close(RP);
  342. $!=0; waitpid($c,0) eq $c || &bombout("wait for \`find' failed: $!");
  343. $? && &bombout("\`find' process returned error code ".&ecode);
  344. @ARGV || &bombout("no packages found to $action");
  345. } else {
  346. @ARGV && &badusage("no package names may be specified with --$action --auto");
  347. if ($action eq 'remove') {
  348. eval 'sub condition {
  349. $wants eq "deinstall" || $wants eq "purge" || return 0;
  350. $cstatus eq "not-installed" && return 0;
  351. $cstatus eq "config-files" && $wants eq "deinstall" && return 0;
  352. return 1;
  353. } 1;' || &internalerr("sub condition: $@");
  354. } elsif ($action eq 'configure') {
  355. eval 'sub condition {
  356. $wants eq "install" || return 0;
  357. $cstatus eq "unpacked" || $cstatus eq "postinst-failed" || return 0;
  358. return 1;
  359. } 1;' || &internalerr("sub condition: $@");
  360. } else {
  361. &internalerr("unknown auto nonames action $action");
  362. }
  363. for $p (keys %st_p21) {
  364. next if $st_p2h{$p} eq 'hold';
  365. $wants= $st_p2w{$p}; $cstatus= $st_p2s{$p};
  366. next unless &condition;
  367. push(@ARGV,$p);
  368. }
  369. }
  370. &debug("auto: arglist @ARGV");
  371. } else {
  372. @ARGV || &badusage("need a list of packages or filenames");
  373. }
  374. if ($action eq 'install' || $action eq 'unpack') {
  375. grep(s:^[^/.]:./$&:, @ARGV); # Sanitise filenames
  376. }
  377. &debug("action: $action; arglist @ARGV");
  378. #*** actually do things ***#
  379. for $arg (@ARGV) {
  380. $package= ''; @undo=();
  381. &debug("&do_$action($arg)");
  382. if (!eval "&do_$action(\$arg); 1;") { &handleerror || last; }
  383. &checkpointstatus;
  384. }
  385. &checkpointstatus;
  386. if (!$abort) {
  387. &debug("&middle_$action($arg)");
  388. if (!eval "&middle_$action; 1;") { print STDERR $@; $abort=1; }
  389. }
  390. &checkpointstatus;
  391. if (!$abort) {
  392. while (@deferred) {
  393. $arg= shift(@deferred); $package= ''; @undo=();
  394. &debug("&deferred_$action($arg) ($dependtry: $sincenothing)");
  395. if (!eval "&deferred_$action(\$arg); 1;") { &handleerror || last; }
  396. &checkpointstatus;
  397. }
  398. &checkpointstatus;
  399. }
  400. if ($errors) {
  401. print STDERR "$name: $errors errors occurred.\n";
  402. $estatus= 1;
  403. }
  404. &database_finish;
  405. &cleanup;
  406. exit($estatus);
  407. #*** useful subroutines for main control section ***#
  408. sub handleerror {
  409. print STDERR $@;
  410. if (length($package) && defined($st_p21{$package})) {
  411. $st_p2h{$package}='hold'; &amended_status($package);
  412. }
  413. $errors++;
  414. if ($errors >20) { print STDERR "$name: too many errors, halting\n"; return 0; }
  415. return !$abort;
  416. }
  417. sub checkpointstatus {
  418. return unless keys %statusupdated;
  419. &amended_status(keys %statusupdated);
  420. undef %statusupdated;
  421. }
  422. sub backend {
  423. &setaction('');
  424. ($noptsdone) && &badusage("action \`$_[0]' must be first argument");
  425. &debug("backend --$_[0]");
  426. exec($backend, "--$_[0]", @ARGV);
  427. &bombout("unable to run $backend: $!");
  428. }
  429. sub setaction {
  430. $action eq 'none' || &badusage("conflicting actions \`$action' and \`$1'");
  431. $action= $_[0];
  432. }
  433. #*** error handlers for use in actions ***#
  434. sub warn { warn "$name - warning: @_\n"; }
  435. sub subcriterr { warn "$name - subcritical error: @_\n"; $estatus=1; }
  436. sub error { &acleanup; die "$name - error: @_\n"; }
  437. sub internalerr { &acleanup; die "$name - internal error, please report: @_\n"; }
  438. sub fatalerr { &acleanup; die "$name - fatal error, halting: @_\n"; $abort=1; }
  439. sub corruptingerr {
  440. local ($corruptingerr)= @_;
  441. &acleanup;
  442. die "$name - horrible error: $corruptingerr;\n".
  443. "Package manager data is now out of step with installed system.\n".
  444. "Please re-install \`$package' to ensure system consistency!\n".
  445. "(Seek assistance from an expert if problems persist.)\n";
  446. $abort=1;
  447. }
  448. sub forcibleerr {
  449. local ($msg,@forces) = @_;
  450. if (@forces= grep($force{$_},@forces)) {
  451. &warn("$msg (proceeding due to --force-$forces[0])");
  452. } else {
  453. &error("$msg (skipping this package)");
  454. }
  455. }
  456. sub acleanup {
  457. while (@undo) {
  458. eval(pop(@undo));
  459. $@ && print STDERR "error while cleaning up: $@";
  460. }
  461. }
  462. #*** --install ***#
  463. sub do_install {
  464. &do_unpack($arg);
  465. $arg= $package;
  466. &do_configure($arg);
  467. }
  468. sub deferred_install { &deferred_configure; }
  469. sub middle_install { &middle_configure }
  470. #*** --avail ***#
  471. sub do_avail {
  472. unlink($controli);
  473. if ($! != &ENOENT) {
  474. system('rm','-rf',$controli);
  475. unlink($controli);
  476. $! == &ENOENT || &fatalerr("unable to get rid of $controli: $!");
  477. }
  478. &debug("extract control $backend --control $arg $controli");
  479. $!=0; system($backend,"--control",$arg,$controli);
  480. $? && &error("$arg: could not extract control information (".&ecode.")");
  481. open(CONTROL,"$controli/control") ||
  482. &error("$arg: corrupt - unable to read control file: $!");
  483. &parse_control("$arg");
  484. for $k (keys %cf_k2v) {
  485. $av_pk2v{$p,$k}= $cf_k2v{$k};
  486. }
  487. for $k (@nokeepfields) {
  488. delete $av_pk2v{$p,$k} unless defined($cf_k2v{$k});
  489. }
  490. &amended_available($p);
  491. $package=$p;
  492. }
  493. sub deferred_avail { }
  494. sub middle_avail { }
  495. #*** --unpack ***#
  496. sub middle_unpack { }
  497. sub do_unpack {
  498. &do_avail;
  499. $cstatus= $st_p2s{$package};
  500. if ($st_p2w{$package} ne 'install') {
  501. if (!$noalsoselect) {
  502. $st_p2w{$package}= 'install'; $statusupdated{$package}= 1;
  503. print STDOUT "Selecting previously deselected package $package.\n";
  504. } else {
  505. print STDOUT "Skipping deselected package $package.\n";
  506. return;
  507. }
  508. }
  509. for $tp (split(/,/, $av_pk2v{$package,'conflicts'})) {
  510. $tp =~ s/^\s*//; $tp =~ s/\s+$//;
  511. ($tps, $rightver, $inst, $want, $tpp)= &installationstatus($tp);
  512. unless ($tps eq 'not-installed' || $tps eq 'config-files' || !$rightver) {
  513. &forcibleerr("$arg: conflicts with package $tpp ($want),".
  514. " found $inst on system",
  515. 'conflicts');
  516. }
  517. }
  518. if ($cstatus eq 'installed') {
  519. if (&compare_verrevs($av_pk2v{$package,'version'},
  520. $av_pk2v{$package,'package_revision'},
  521. $st_k2v{'version'},$st_k2v{'package_revision'}) <0) {
  522. &forcibleerr("$arg: downgrading installed $package version ".
  523. "$st_k2v{'version'}, ".
  524. "package revision $st_k2v{'package_revision'} ".
  525. "to older version ".
  526. "$av_pk2v{$package,'version'}, ".
  527. "package revision $av_pk2v{$package,'package_revision'}",
  528. 'downgrade');
  529. }
  530. }
  531. if (open(CONF,"$controli/conffiles")) {
  532. @configf= <CONF>;
  533. eof || &error("$arg: unable to read $controli/conffiles: $!");
  534. close(CONF);
  535. grep((chop, m,^/, || s,^,/,), @configf);
  536. } elsif ($! != &ENOENT) {
  537. &error("$arg: cannot get config files list: $!");
  538. } else {
  539. @configf= ();
  540. }
  541. if ($cstatus eq 'installed' || $cstatus eq 'unpacked' ||
  542. $cstatus eq 'postinst-failed' || $cstatus eq 'removal-failed') {
  543. &filesinpackage($arg,$package);
  544. print STDOUT "Preparing to replace $package ...\n";
  545. }
  546. if ($cstatus eq 'installed') {
  547. if (!eval {
  548. &run_script_ne("$scriptsdir/$package.prerm", 'old pre-removal script',
  549. 'upgrade',
  550. $av_pk2v{$package,'version'}.'-'.
  551. $av_pk2v{$package,'package_revision'});
  552. 1;
  553. }) {
  554. &warn("$@... trying script from new package instead.");
  555. &run_script("$controli/prerm", 'new prerm script',
  556. 'failed-upgrade',
  557. $st_k2v{'version'}.'-'.$st_k2v{'package_revision'});
  558. }
  559. push(@undo,
  560. '$st_p2s{$package}= "postinst-failed"; $statusupdated{$package}=1;
  561. &run_script_ne("$scriptsdir/$package.postinst",
  562. "old post-installation script",
  563. "abort-upgrade",
  564. $av_pk2v{$package,"version"}."-".
  565. $av_pk2v{$package,"package_revision"});
  566. $st_p2s{$package}= "installed"; $statusupdated{$package}=1;');
  567. }
  568. @fbackups=();
  569. if ($cstatus eq 'installed' || $cstatus eq 'unpacked' ||
  570. $cstatus eq 'postinst-failed' || $cstatus eq 'removal-failed') {
  571. for ($i=0; $i<=$#ilist; $i++) {
  572. next if grep($_ eq $ilist[$i], @configf);
  573. $_= $ilist[$i];
  574. unless (lstat("$instroot/$_")) {
  575. $! == &ENOENT || &error("old file $_ unstattable: $!");
  576. next;
  577. }
  578. next if -d _;
  579. rename("$instroot/$_","$instroot/$_.dpkg-tmp") ||
  580. &error("couldn't rename old file $_ to $_.dpkg-tmp: $!");
  581. push(@undo,
  582. '$_=pop(@fbackups); rename("$instroot/$_.dpkg-tmp","$instroot/$_") ||
  583. die "unable to undo rename of $_ to $_.dpkg-tmp: $!"');
  584. push(@fbackups, $_);
  585. }
  586. if (!eval {
  587. &run_script_ne("$scriptsdir/$package.postrm", 'old post-removal script',
  588. 'upgrade',
  589. $av_pk2v{$package,'version'}.'-'.
  590. $av_pk2v{$package,'package_revision'});
  591. 1;
  592. }) {
  593. &warn("$@... trying script from new package instead.");
  594. &run_script("$controli/postrm", 'new post-removal script',
  595. 'failed-upgrade',
  596. $st_k2v{'version'}.'-'.$st_k2v{'package_revision'});
  597. }
  598. push(@undo,
  599. '&run_script_ne("$scriptsdir/$package.preinst",
  600. "old pre-installation script",
  601. "abort-upgrade",
  602. $av_pk2v{$package,"version"}.
  603. "-".$av_pk2v{$package,"package_revision"})');
  604. }
  605. $shortarg= $arg; $shortarg =~ s:.{15,}/:.../:;
  606. print STDOUT "Unpacking $arg, containing $package ...\n";
  607. &run_script("$controli/preinst", 'pre-installation script',
  608. 'upgrade', $st_k2v{'version'}.'-'.$st_k2v{'package_revision'});
  609. push(@undo,'&run_script_ne("$controli/postrm", "post-removal script",
  610. "abort-upgrade",
  611. $st_k2v{"version"}."-".$st_k2v{"package_revision"})');
  612. if ($cstatus ne 'not-installed') {
  613. for $_ (split(/\n/,$st_pk2v{$package,'conffiles'})) {
  614. s/^ //; next unless length($_);
  615. if (!m/^(\S+) (-|newconffile|nonexistent|[0-9a-f]{32})$/) {
  616. &warn("$arg: ignoring bad stuff in old conffiles field \`$_'");
  617. next;
  618. }
  619. $oldhash{$1}= $2;
  620. }
  621. }
  622. for $f (@configf) {
  623. $drf= &conffderef($f); if (!defined($drf)) { next; }
  624. if (lstat("$instroot/$drf.dpkg-tmp")) {
  625. $undo=1;
  626. } else {
  627. $! == &ENOENT || &error("unable to stat backup config file $_.dpkg-tmp: $!");
  628. if (lstat("$instroot/$drf")) {
  629. rename("$instroot/$drf","$instroot/$drf.dpkg-tmp") ||
  630. &error("couldn't back up config file $f (= $drf): $!");
  631. $undo=1;
  632. } elsif ($! == &ENOENT) {
  633. $undo=0;
  634. } else {
  635. &error("unable to stat config file $drf: $!");
  636. }
  637. }
  638. if ($undo) {
  639. push(@undo,
  640. '$_=pop(@undof); rename("$instroot/$_.dpkg-tmp","$instroot/$_") ||
  641. die "unable to undo backup of config file $_: $!"');
  642. push(@undof, $drf);
  643. }
  644. }
  645. open(NL,">$listsdir/$package.list.new") ||
  646. &error("$package: cannot create $listsdir/$package.list.new: $!");
  647. defined($c= fork) || &error("$package: cannot pipe/fork for $backend --vextract");
  648. if (!$c) {
  649. if (!open(STDOUT,">&NL")) {
  650. print STDERR "$name: cannot redirect stdout: $!\n"; exit(1);
  651. }
  652. $vexroot= length($instroot) ? $instroot : '/';
  653. exec($backend,"--vextract",$arg,$vexroot);
  654. print STDERR "$name: cannot exec $backend --vextract $arg $vexroot: $!\n";
  655. exit(1);
  656. }
  657. $!=0; waitpid($c,0) == $c || &error("could not wait for $backend: $!");
  658. $? && &forcibleerr("$package: failed to install (".&ecode.")", 'extractfail');
  659. rename("$listsdir/$package.list.new","$listsdir/$package.list") ||
  660. &error("$package: failed to install new $listsdir/$package.list: $!");
  661. $newconff='';
  662. for $f (@configf) {
  663. $h= $oldhash{$f};
  664. $h='newconffile' unless length($h);
  665. $newconff.= "\n $f $h";
  666. &debug("new hash, after unpack, of $f, is $h");
  667. }
  668. for $k (keys %all_k21) {
  669. next if $k eq 'binary' || $k eq 'source' || $k eq 'section';
  670. $st_pk2v{$package,$k}= $av_pk2v{$package,$k};
  671. }
  672. $st_pk2v{$package,'conffiles'}= $newconff; $all_k21{'conffiles'}= 1;
  673. $st_p2s{$package}= 'unpacked'; $st_p2h{$package}= 'ok'; $st_p21{$package}= 1;
  674. $statusupdated{$package}= 1;
  675. @undo=(); @undof=();
  676. for $f (@fbackups) {
  677. unlink("$instroot/$f.dpkg-tmp") || $! == &ENOENT ||
  678. &subcriterr("$package: unable to delete saved old file $f.dpkg-tmp: $!\n");
  679. }
  680. undef %fordeletion;
  681. opendir(PI,"$scriptsdir") ||
  682. &corruptingerr("$package: unable to read $scriptsdir directory ($!)");
  683. while(defined($_=readdir(PI))) {
  684. next unless substr($_,0,length($package)+1) eq $package.'.';
  685. $fordeletion{$_}= 1;
  686. }
  687. closedir(PI);
  688. opendir(PI,"$controli") ||
  689. &corruptingerr("$package: unable to read $controli".
  690. " new package control information directory ($!)");
  691. $fordeletion{"$package.list"}= 0;
  692. while(defined($_=readdir(PI))) {
  693. next if m/^\.\.?$/ || m/^conffiles$/ || m/^control$/;
  694. rename("$controli/$_","$scriptsdir/$package.$_") ||
  695. &corruptingerr("$package: unable to install new package control".
  696. " information file $scriptsdir/$package.$_ ($!)");
  697. $fordeletion{"$package.$_"}= 0;
  698. }
  699. closedir(PI);
  700. for $_ (keys %fordeletion) {
  701. next unless $fordeletion{$_};
  702. unlink("$scriptsdir/$_") ||
  703. &corruptingerr("$package: unable to remove old package script".
  704. " $scriptsdir/$_ ($!)");
  705. }
  706. }
  707. #*** --configure ***#
  708. sub do_configure {
  709. $package=$arg; $cstatus= $st_p2s{$package};
  710. if (!defined($st_p21{$package})) { $cstatus= 'not-installed'; }
  711. unless ($cstatus eq 'unpacked' || $cstatus eq 'postinst-failed') {
  712. if ($cstatus eq 'not-installed') {
  713. &error("no package named \`$package' is installed, cannot configure");
  714. } else {
  715. &error("$package: is currently in state \`$cstatus', cannot configure");
  716. }
  717. }
  718. push(@deferred,$package);
  719. }
  720. sub middle_configure {
  721. $sincenothing=0; $dependtry=1;
  722. }
  723. sub deferred_configure {
  724. # The algorithm for deciding what to configure first is as follows:
  725. # Loop through all packages doing a `try 1' until we've been round
  726. # and nothing has been done, then do `try 2' and `try 3' likewise.
  727. # Try 1:
  728. # Are all dependencies of this package done ? If so, do it.
  729. # Are any of the dependencies missing or the wrong version ?
  730. # If so, abort (unless --force-depends, in which case defer)
  731. # Will we need to configure a package we weren't given as an
  732. # argument ? If so, abort - except if --force-configure-any,
  733. # in which case we add the package to the argument list.
  734. # If none of the above, defer the package.
  735. # Try 2:
  736. # Find a cycle and break it (see above).
  737. # Do as for try 1.
  738. # Try 3 (only if --force-depends-version).
  739. # Same as for try 2, but don't mind version number in dependencies.
  740. # Try 4 (only if --force-depends).
  741. # Do anyway.
  742. $package= $arg;
  743. if ($sincenothing++ > $#deferred*2+2) {
  744. $dependtry++; $sincenothing=0;
  745. &internalerr("$package: nothing configured, but try was already 4 !")
  746. if $dependtry > 4;
  747. }
  748. if ($dependtry > 1) { &findbreakcycle($package); }
  749. ($ok, @aemsgs) = &dependencies_ok($package,'');
  750. if ($ok == 1) {
  751. push(@deferred,$package); return;
  752. } elsif ($ok == 0) {
  753. $sincenothing= 0;
  754. &error("$arg: dependency problems - not configuring this package:\n ".
  755. join("\n ",@aemsgs));
  756. } elsif (@aemsgs) {
  757. &warn("$arg: dependency problems, configuring anyway as you request:\n ".
  758. join("\n ",@aemsgs));
  759. }
  760. $sincenothing= 0;
  761. print STDOUT "Setting up $package ...\n";
  762. if ($st_p2s{$package} eq 'unpacked') {
  763. &debug("conffiles updating >$st_pk2v{$package,'conffiles'}<");
  764. undef %oldhash; @configf=();
  765. for $_ (split(/\n/,$st_pk2v{$package,'conffiles'})) {
  766. s/^ //; next unless length($_);
  767. if (!m/^(\S+) (-|newconffile|nonexistent|[0-9a-f]{32})$/) {
  768. &warn("$arg: ignoring bad stuff in old conffiles field \`$_'");
  769. next;
  770. }
  771. $oldhash{$1}= $2; push(@configf,$1);
  772. &debug("old hash of $1 is $2");
  773. }
  774. undef %newhash;
  775. for $file (@configf) {
  776. $drf= &conffderef($file);
  777. if (!defined($drf)) { $newhash{$file}= '-'; next; }
  778. $newhash{$file}= &hash("$instroot/$drf");
  779. &debug("new hash of $file is $newhash{$file} (old $oldhash{$file})");
  780. if ($oldhash{$file} eq 'newconffile') {
  781. $usenew= 1;
  782. } else {
  783. if (!&files_not_identical("$instroot/$drf",
  784. "$instroot/$drf.dpkg-tmp")) {
  785. rename("$instroot/$drf.dpkg-tmp",$drf) || $!==&ENOENT ||
  786. &error("$package: unable to reinstall ".
  787. "existing conffile $drf.dpkg-tmp: $!");
  788. &debug("files identical $file");
  789. } else {
  790. $diff= $newhash{$file} ne $oldhash{$file};
  791. $usenew= $confusenew[$diff];
  792. &debug("the decision - diff $diff;".
  793. " usenew $usenew prompt $confpromt[$diff]");
  794. if ($confprompt[$diff]) {
  795. $symlinked = $drf eq $file ? '' :
  796. $succinct ? " (-> $drf)" :
  797. " (which is a symlink to $drf)";
  798. for (;;) {
  799. print
  800. $succinct ? "
  801. Package $package, file $file$symlinked, ".($diff ? "CHANGED": "not changed")
  802. : $diff ? "
  803. In package $package, distributed version of configuration
  804. file $file$symlinked has changed
  805. since the last time it was installed. You may:
  806. * Install the new version and edit it later to reflect your wishes.
  807. ". ($nokeepold ?
  808. "(Your old version will not be saved.)" :
  809. "(Your old version will be saved in $drf.dpkg-old.)") . "
  810. * Leave your old version in place, and perhaps check later that
  811. you don't want to update it to take account of new features.
  812. ". ($nokeepnew ?
  813. "(The new version be discarded.)" :
  814. "(The new version will be placed in $drf.dpkg-new.)")
  815. : "
  816. Package $package contains the same distributed version of
  817. configuration file $file$symlinked
  818. as the last time it was installed. You may:
  819. * Install the distributed version, overwriting your changes.
  820. ". ($nokeepold ?
  821. "(Your changed version will not be saved.)" :
  822. "(Your changed version will be saved in $drf.dpkg-old.)") . "
  823. * Leave your own version in place.
  824. ". ($nokeepnew ?
  825. "(The distributed version be discarded.)" :
  826. "(The distributed version will be placed in $drf.dpkg-new.)");
  827. print "
  828. $file: install new version ? (y/n, default=". ($usenew?'y':'n'). ") ";
  829. $!=0; defined($iread= <STDIN>) ||
  830. &error("$package: prompting, EOF/error on stdin: $!");
  831. $_= $iread; s/^\s*//; s/\s+$//;
  832. ($usenew=0, last) if m/^n(o)?$/i;
  833. ($usenew=1, last) if m/^y(es)?$/i;
  834. last if m/^$/;
  835. print "\nPlease answer \`y' or \`n'.\n";
  836. }
  837. }
  838. &debug("decided, usenew $usenew");
  839. if ($usenew) {
  840. &copyperm("$drf.dpkg-tmp",$drf,$drf);
  841. if ($nokeepold) {
  842. unlink("$instroot/$drf.dpkg-tmp") || $!==&ENOENT ||
  843. &error("$package: unable to delete old conffile ".
  844. "$drf.dpkg-tmp: $!");
  845. unlink("$instroot/$drf.dpkg-old") || $!==&ENOENT ||
  846. &error("$package: unable to delete very old ".
  847. "conffile $drf.dpkg-old: $!");
  848. } else {
  849. rename("$instroot/$drf.dpkg-tmp","$instroot/$drf.dpkg-old")
  850. || $!==&ENOENT ||
  851. &error("$package: unable to back up old conffile ".
  852. "$drf.dpkg-tmp as $drf.dpkg-old: $!");
  853. }
  854. } else {
  855. unlink("$instroot/$drf.dpkg-new") || $!==&ENOENT ||
  856. &error("$package: unable to delete old new conffile ".
  857. "$drf.dpkg-new: $!");
  858. if (!$nokeepnew) {
  859. link("$instroot/$drf","$instroot/$drf.dpkg-new")
  860. || $!==&ENOENT ||
  861. &error("$package: unable save new conffile ".
  862. "$drf as $drf.dpkg-new: $!");
  863. }
  864. if (!rename("$instroot/$drf.dpkg-tmp","$instroot/$drf")) {
  865. $!==&ENOENT || &error("$package: unable reinstall old ".
  866. "conffile $drf.dpkg-tmp as $drf: $!");
  867. unlink("$instroot/$drf");
  868. }
  869. }
  870. }
  871. }
  872. }
  873. $newconff='';
  874. for $f (@configf) {
  875. $h= $newhash{$f}; $newconff.= "\n $f $h";
  876. }
  877. $st_pk2v{$package,'conffiles'}= $newconff; $all_k21{'conffiles'}= 1;
  878. }
  879. $st_p2s{$package}= 'postinst-failed'; $statusupdated{$package}= 1;
  880. &run_script("$scriptsdir/$package.postinst",
  881. 'post-installation script', 'configure');
  882. $st_p2s{$package}= 'installed';
  883. $st_p2h{$package}= 'ok'; $statusupdated{$package}= 1;
  884. }
  885. #*** --remove ***#
  886. sub do_remove {
  887. $package=$arg; $cstatus= $st_p2s{$package};
  888. if (!defined($st_p21{$package}) ||
  889. $cstatus eq 'not-installed' ||
  890. !$purge && $cstatus eq 'config-files') {
  891. &error("$package: is not installed, cannot remove");
  892. }
  893. push(@deferred,$package);
  894. if (!$auto) {
  895. $ns= $purge ? 'purge' : 'deinstall';
  896. if ($st_p2w{$package} ne $ns) {
  897. $st_p2w{$package}= $ns; $statusupdated{$package}= 1;
  898. }
  899. }
  900. }
  901. sub middle_remove {
  902. $sincenothing=0; $dependtry=1;
  903. for $p (keys %st_p2s) {
  904. $cstatus= $st_p2s{$p};
  905. next unless $cstatus eq 'installed';
  906. for $tp (split(/[\|,]/, $st_pk2v{$p,'depends'})) {
  907. $tp =~ s/\s*\(.+\)\s*$//; $tp =~ s/^\s*//; $tp =~ s/\s+$//;
  908. $tp =~ m/^$packagere$/o ||
  909. &internalerr("package $p dependency $tp didn't match re");
  910. $depended{$tp}.= "$p ";
  911. }
  912. }
  913. }
  914. sub deferred_remove {
  915. $package= $arg;
  916. if ($sincenothing++ > $#deferred*2+2) {
  917. $dependtry++; $sincenothing=0;
  918. &internalerr("$package: nothing configured, but try was already 4 !")
  919. if $dependtry > 4;
  920. }
  921. @raemsgs= (); $rok= 2;
  922. &debug("$package may be depended on by any of >$depended{$package}<");
  923. for $fp (split(/ /, $depended{$package})) {
  924. next if $fp eq '' || $ignore_depends{$tp};
  925. $is= $st_p2s{$fp};
  926. next if $is eq 'not-installed' || $is eq 'unpacked' ||
  927. $is eq 'removal-failed' || $is eq 'config-files';
  928. if ($dependtry > 1) { &findbreakcycle($fp); }
  929. ($ok, @aemsgs) = &dependencies_ok($fp,$package);
  930. if ($rok != 1) { push(@raemsgs,@aemsgs); }
  931. $rok= $ok if $ok < $rok;
  932. }
  933. if ($rok == 1) {
  934. push(@deferred,$package); return;
  935. } elsif ($rok == 0) {
  936. $sincenothing= 0;
  937. &error("$arg: dependency problems - not removing this package:\n ".
  938. join("\n ",@raemsgs));
  939. } elsif (@raemsgs) {
  940. &warn("$arg: dependency problems, removing anyway as you request:\n ".
  941. join("\n ",@raemsgs));
  942. }
  943. $sincenothing= 0;
  944. &filesinpackage($arg,$package);
  945. undef %hash; @configfr= @configf= ();
  946. for $_ (split(/\n/,$st_pk2v{$package,'conffiles'})) {
  947. s/^ //; next unless length($_);
  948. if (!m/^(\S+) (-|newconffile|nonexistent|[0-9a-f]{32})$/) {
  949. &warn("$arg: ignoring bad stuff in old conffiles field \`$_'");
  950. next;
  951. }
  952. unshift(@configfr,$1); push(@configf,$1);
  953. $hash{$1}= $2;
  954. }
  955. if ($st_p2s{$package} ne 'config-files') {
  956. print STDOUT "Removing $package ...\n";
  957. &run_script("$scriptsdir/$package.prerm", 'pre-removal script', 'remove');
  958. $st_p2s{$package}= 'removal-failed'; $statusupdated{$package}= 1;
  959. for $file (reverse @ilist) {
  960. next if grep($_ eq $file, @configf);
  961. unlink("$instroot/$file.dpkg-tmp") || $! == &ENOENT ||
  962. &error("$arg: cannot remove supposed old temp file $file: $!");
  963. next if unlink("$instroot/$file");
  964. next if $! == &ENOENT;
  965. &error("$arg: cannot remove file $file: $!") unless $! == &EISDIR;
  966. next if rmdir("$instroot/$file");
  967. &error("$arg: cannot remove directory $file: $!") unless $! == &ENOTEMPTY;
  968. }
  969. &run_script("$scriptsdir/$package.postrm", 'post-removal script', 'remove');
  970. opendir(DSD,"$scriptsdir") ||
  971. &error("$arg: cannot read directory $scriptsdir: $!");
  972. for $_ (readdir(DSD)) {
  973. next unless m/\.[^.]$/;
  974. next if $& eq '.postrm' || $& eq '.list';
  975. # need postrm for --purge, and list has to go last in case it
  976. # goes wrong
  977. next unless $` eq $package;
  978. unlink("$scriptsdir/$_") ||
  979. &error("$arg: unable to delete control information $scriptsdir/$_: $!");
  980. }
  981. closedir(DSD);
  982. $st_p2s{$package}= 'config-files';
  983. $statusupdated{$package}= 1;
  984. }
  985. if ($purge) {
  986. print STDOUT "Purging configuration files for $package ...\n";
  987. push(@undo,
  988. '$newconff="";
  989. for $f (@configf) { $newconff.= "\n $f $hash{$f}"; }
  990. $st_pk2v{$package,"conffiles"}= $newconff; $all_k21{"conffiles"}= 1;');
  991. for $file (@configfr) {
  992. $drf= &conffderef($file); if (!defined($drf)) { next; }
  993. unlink("$instroot/$drf") || $! == &ENOENT ||
  994. &error("$arg: cannot remove old config file $file (= $drf): $!");
  995. $hash{$file}= 'newconffile';
  996. unlink("$instroot/$file") || $! == &ENOENT ||
  997. &error("$arg: cannot remove old config file $file: $!")
  998. if $file ne $drf;
  999. for $ext ('.dpkg-tmp', '.dpkg-old', '.dpkg-new', '~', '.bak', '%') {
  1000. unlink("$instroot/$drf$ext") || $! == &ENOENT ||
  1001. &error("$arg: cannot remove old config file $drf$ext: $!");
  1002. }
  1003. unlink("#$instroot/$drf#") || $! == &ENOENT ||
  1004. &error("$arg: cannot remove old auto-save file #$drf#: $!");
  1005. $drf =~ m,^(.*)/, || next; $dir= $1; $base= $';
  1006. if (opendir(CFD,"$instroot/$dir")) {
  1007. for $_ (readdir(CFD)) {
  1008. next unless m/\.~\d+~$/;
  1009. next unless $` eq $base;
  1010. unlink("$instroot/$dir/$_") || $! == &ENOENT ||
  1011. &error("$arg: cannot remove old emacs backup file $dir/$_: $!");
  1012. }
  1013. closedir(CFD);
  1014. if (grep($_ eq $dir, @ilist)) {
  1015. rmdir("$instroot/$dir") || $! == &ENOTEMPTY ||
  1016. &error("$arg: cannot remove config file directory $dir: $!");
  1017. }
  1018. } elsif ($! != &ENOENT) {
  1019. &error("$arg: cannot read config file dir $dir: $!");
  1020. }
  1021. }
  1022. &run_script("$scriptsdir/$package.postrm", 'post-removal script for purge',
  1023. 'purge');
  1024. unlink("$scriptsdir/$package.postrm") || $! == &ENOENT ||
  1025. &error("$arg: cannot remove old postrm script: $!");
  1026. &setnotinstalled;
  1027. @undo= ();
  1028. } elsif (!@configf && !stat("$scripts/$package.postrm")) {
  1029. # If there are no config files and no postrm script then we
  1030. # go straight into `purge'. However, perhaps the stat didn't
  1031. # fail with ENOENT ...
  1032. $! == &ENOENT || &error("$package: stat failed on postrm script: $!");
  1033. $st_p2w{$package}= 'purge';
  1034. &setnotinstalled;
  1035. }
  1036. $st_p2h{$package}= 'ok'; $statusupdated{$package}= 1;
  1037. }
  1038. sub setnotinstalled {
  1039. unlink("$listsdir/$package.list") ||
  1040. &error("$arg: unable to delete old file list: $!");
  1041. $st_p2s{$package}= 'not-installed';
  1042. for $k (keys %all_k21) { delete $st_pk2v{$package,$k}; }
  1043. }
  1044. #*** dependency processing - common to --configure and --remove ***#
  1045. # The algorithm for deciding what to configure or remove first is as
  1046. # follows:
  1047. #
  1048. # Loop through all packages doing a `try 1' until we've been round and
  1049. # nothing has been done, then do `try 2' and `try 3' likewise.
  1050. #
  1051. # When configuring, in each try we check to see whether all
  1052. # dependencies of this package are done. If so we do it. If some of
  1053. # the dependencies aren't done yet but will be later we defer the
  1054. # package, otherwise it is an error.
  1055. #
  1056. # When removing, in each try we check to see whether there are any
  1057. # packages that would have dependencies missing if we removed this
  1058. # one. If not we remove it now. If some of these packages are
  1059. # themselves scheduled for removal we defer the package until they
  1060. # have been done.
  1061. #
  1062. # The criteria for satisfying a dependency vary with the various
  1063. # tries. In try 1 we treat the dependencies as absolute. In try 2 we
  1064. # check break any cycles in the dependency graph involving the package
  1065. # we are trying to process before trying to process the package
  1066. # normally. In try 3 (which should only be reached if
  1067. # --force-depends-version is set) we ignore version number clauses in
  1068. # Depends lines. In try 4 (only reached if --force-depends is set) we
  1069. # say "ok" regardless.
  1070. #
  1071. # If we are configuring and one of the packages we depend on is
  1072. # awaiting configuration but wasn't specified in the argument list we
  1073. # will add it to the argument list if --configure-any is specified.
  1074. # In this case we note this as having "done something" so that we
  1075. # don't needlessly escalate to higher levels of dependency checking
  1076. # and breaking.
  1077. sub dependencies_ok {
  1078. local ($dp, $removingp) = @_;
  1079. local ($tpo, $however_t, $ok, $found, @aemsgs, @oemsgs);
  1080. local ($tp, $rightver, $inst, $want, $thisf, $matched, $tpp);
  1081. $ok= 2; # 2=ok, 1=defer, 0=halt
  1082. &debug("checking dependencies of $dp (- $removingp)");
  1083. for $tpo (split(/,/, $st_pk2v{$dp,'depends'})) {
  1084. $tpo =~ s/^\s*//; $tpo =~ s/\s+$//;
  1085. &debug(" checking group $dp -> $tpo");
  1086. $matched= 0; @oemsgs=();
  1087. $found=0; # 0=none, 1=defer, 2=withwarning, 3=ok
  1088. for $tp (split(/\|/, $tpo)) {
  1089. $tp =~ s/^\s*//; $tp =~ s/\s+$//;
  1090. &debug(" checking possibility $dp -> $tp");
  1091. if ($ignore_depends{$tp}) { &debug("ignoring so ok"); $found=3; last; }
  1092. if (defined($cyclebreak{$dp,$tp})) { &debug("break cycle"); $found=3; last; }
  1093. if ($tp eq $removingp) {
  1094. ($tps, $rightver, $inst, $want, $tpp)= ('removing-now', 1, '','', $tp);
  1095. $matched= 1;
  1096. } else {
  1097. ($tps, $rightver, $inst, $want, $tpp)= &installationstatus($tp);
  1098. &debug("installationstatus($tp) -> !$tps!$rightver!$inst!$want!$tps|");
  1099. }
  1100. if (($tps eq 'installed' || $tps eq 'unpacked' || $tps eq 'postinst-failed')
  1101. && !$rightver) {
  1102. push(@oemsgs,"version of $tpp on system is $inst (wanted $want)");
  1103. if ($force{'depends'}) { $thisf= $dependtry >= 3 ? 2 : 1; }
  1104. } elsif ($tps eq 'unpacked' || $tps eq 'postinst-failed') {
  1105. if (grep($_ eq $tpp, @deferred)) {
  1106. $thisf=1;
  1107. } elsif (!length($removingp) && $force{'configure-any'}) {
  1108. &warn("will also configure $tpp");
  1109. push(@deferred,$tpp); $sincenothing=0; $thisf=1;
  1110. } else {
  1111. push(@oemsgs,"package $tpp is not configured yet");
  1112. if ($force{'depends'}) { $thisf= $dependtry >= 4 ? 2 : 1; }
  1113. }
  1114. } elsif ($tps eq 'installed') {
  1115. $found=3; last;
  1116. } elsif ($tps eq 'removing-now') {
  1117. push(@oemsgs,"$tpp is to be removed");
  1118. if ($force{'depends'}) { $thisf= $dependtry >= 4 ? 2 : 1; }
  1119. } else {
  1120. push(@oemsgs,"$tpp ($want) is not installed");
  1121. if ($force{'depends'}) { $thisf= $dependtry >= 4 ? 2 : 1; }
  1122. }
  1123. &debug(" found $found");
  1124. $found=$thisf if $thisf>$found;
  1125. }
  1126. &debug(" found $found matched $matched");
  1127. next if length($removingp) && !$matched;
  1128. if (length($removingp) && $tpo !~ m/\|/) {
  1129. $however_t= '';
  1130. } elsif (@oemsgs > 1) {
  1131. $however_t= "\n However, ". join(",\n ", @oemsgs[0..($#oemsgs-1)]).
  1132. " and\n ". $oemsgs[$#oemsgs]. ".";
  1133. } else {
  1134. $however_t= "\n However, @oemsgs.";
  1135. }
  1136. if ($found == 0) {
  1137. push(@aemsgs, "$dp depends on $tpo.$however_t");
  1138. $ok=0;
  1139. } elsif ($found == 1) {
  1140. $ok=1 if $ok>1;
  1141. } elsif ($found == 2) {
  1142. push(@aemsgs, "$dp depends on $tpo.$however_t");
  1143. } elsif ($found != 3) {
  1144. &internalerr("found value in deferred_configure $found not known");
  1145. }
  1146. }
  1147. &debug("ok $ok msgs >>@aemsgs<<");
  1148. return ($ok, @aemsgs);
  1149. }
  1150. sub findbreakcycle {
  1151. # Cycle breaking works recursively down the package dependency
  1152. # tree. @sofar is the list of packages we've descended down
  1153. # already - if we encounter any of its packages again in a
  1154. # dependency we have found a cycle.
  1155. #
  1156. # Cycles are preferentially broken by ignoring a dependency from
  1157. # a package which doesn't have a postinst script. If there isn't
  1158. # such a dependency in the cycle we break at the `start' of the
  1159. # cycle from the point of view of our package.
  1160. #
  1161. local ($package,@sofar) = @_;
  1162. local ($tp,$tpp,$tps,$rightver,$inst,$want,$i,$dr,$de,@sf);
  1163. &debug("findbreakcycle($package; @sofar)");
  1164. push(@sofar,$package);
  1165. for $tp (split(/[,|]/, $st_pk2v{$package,'depends'})) {
  1166. $tp =~ s/^\s*//; $tp =~ s/\s+$//;
  1167. ($tps, $rightver, $inst, $want, $tpp)= &installationstatus($tp);
  1168. next unless $tps eq 'config-files' || $tps eq 'unpacked';
  1169. next if $cyclebreak{$package,$tpp};
  1170. if (grep($_ eq $tpp, @sofar)) {
  1171. &debug("found cycle $package, $tpp (@sofar)");
  1172. @sf= (@sofar,$tpp);
  1173. for ($i=0;
  1174. $i<$#sf;
  1175. $i++) {
  1176. next if stat("$scriptsdir/$sf[$i].postinst");
  1177. last if $! == &ENOENT;
  1178. &error("$arg: unable to stat $scriptsdir/$sf[$i].postinst: $!");
  1179. }
  1180. $i=0 if $i>=$#sf;
  1181. ($dr,$de)= @sf[$i..$i+1];
  1182. if (!defined($cyclebreak{$dr,$de})) {
  1183. $sincenothing=0; $cyclebreak{$dr,$de}= 1;
  1184. &debug("broken cycle $i (@sf) at $dr -> $de");
  1185. return 1;
  1186. }
  1187. } else {
  1188. return if &findbreakcycle($tpp,@sofar);
  1189. }
  1190. }
  1191. return 0;
  1192. }
  1193. #*** useful subroutines for actions ***#
  1194. sub filesinpackage {
  1195. # Returns the list in @ilist.
  1196. # If error, calls &error("$epfx: ...");
  1197. local ($epfx, $package) = @_;
  1198. open(LIST,"$listsdir/$package.list") ||
  1199. &error("$epfx: database broken for $package - ".
  1200. "can't get installed files list: $!");
  1201. @ilist= <LIST>;
  1202. eof || &error("$epfx: cannot read $listsdir/$package.list: $!");
  1203. close(LIST);
  1204. @ilist= grep((chop,
  1205. s|/$||,
  1206. m|^/| || s|^|/|,
  1207. m/./),
  1208. @ilist);
  1209. }
  1210. sub installationstatus {
  1211. local ($controlstring) = @_;
  1212. local ($lversion,$lpackage,$lstatus,$lrevision,$cmp) = @_;
  1213. local ($cc);
  1214. $lversion= $controlstring;
  1215. $lversion =~ s/^($packagere)\s*// ||
  1216. &internalerr("needed installation status of bogus thing \`$lversion'");
  1217. $lpackage= $1;
  1218. $lstatus= defined($st_p2s{$lpackage}) ? $st_p2s{$lpackage} : 'not-installed';
  1219. if ($lstatus ne 'not-installed') {
  1220. if (length($lversion)) {
  1221. $lversion =~ s/^\s*\(\s*// && $lversion =~ s/\s*\)\s*$// ||
  1222. &internalerr("failed to strip version \`$lversion'");
  1223. if ($lversion =~ s/^[><=]//) { $cc= $&; } else { $cc= '='; }
  1224. $lrevision = ($lversion =~ s/-([^-]+)$//) ? $1 : '';
  1225. $wantedstring= "version $lversion";
  1226. $wantedstring .= ", package revision $lrevision" if length($lrevision);
  1227. $cmp= &compare_verrevs($st_pk2v{$lpackage,'version'},
  1228. $st_pk2v{$lpackage,'package_revision'},
  1229. $lversion,
  1230. $lrevision);
  1231. $installedstring= "version $st_pk2v{$lpackage,'version'}";
  1232. $installedstring .=
  1233. ", package revision $st_pk2v{$lpackage,'package_revision'}"
  1234. if length($st_pk2v{$lpackage,'package_revision'});
  1235. if ($cc eq '>') {
  1236. $rightver= $cmp>=0; $wantedstring.= ' or later';
  1237. } elsif ($cc eq '<') {
  1238. $rightver= $cmp<=0; $wantedstring.= ' or earlier';
  1239. } else {
  1240. s/^=//;
  1241. $rightver= !$cmp; $wantedstring= "exactly $wantedstring";
  1242. }
  1243. } else {
  1244. $rightver= 1;
  1245. $wantedstring= "any version";
  1246. $installedstring= $st_pk2v{$lpackage,'version'}.'-'.
  1247. $st_pk2v{$lpackage,'package_revision'};
  1248. }
  1249. } else {
  1250. $rightver= -1;
  1251. $installedstring= "not installed";
  1252. }
  1253. return ($lstatus,$rightver,$installedstring,$wantedstring,$lpackage);
  1254. }
  1255. sub parse_control {
  1256. # reads from fh CONTROL
  1257. local ($fn) = @_;
  1258. local ($cf,$ln,$l,$k,$v);
  1259. defined($cf= &readall('CONTROL')) || &error("read control file $fn: $!");
  1260. close(CONTROL);
  1261. $p= &parse_control_entry;
  1262. if (@cwarnings) {
  1263. &warn("$fn: control file contains oddities: ".join("; ",@cwarnings))
  1264. unless $controlwarn;
  1265. }
  1266. if (@cerrors) {
  1267. &error("$fn: control file contains errors: ".join("; ",@cerrors));
  1268. }
  1269. }
  1270. sub run_script_ne {
  1271. local ($script,$describe,@args) = @_;
  1272. local ($extranewlines) = $script =~ m/postinst/;
  1273. &debug("running $describe = $script @args");
  1274. if (!stat("$script")) {
  1275. return if $! == &ENOENT;
  1276. die "couldn't stat $script: $!\n";
  1277. }
  1278. if (! -x _) {
  1279. chmod(0755, "$script") || die "couldn't make $script executable: $!\n";
  1280. }
  1281. print "\n" if $extranewlines;
  1282. &debug("forking now");
  1283. defined($rsc= fork) || die "couldn't fork for running $script: $!\n";
  1284. if (!$rsc) {
  1285. if ($instroot !~ m|^/*$| && !chroot($instroot)) {
  1286. print STDERR "$name: failed to chroot to $instroot for $describe: $!\n";
  1287. exit(1);
  1288. }
  1289. exec($script,@args);
  1290. print STDERR "$name: failed to exec $script: $!\n";
  1291. exit(1);
  1292. }
  1293. $!=0; waitpid($rsc,0) == $rsc || die "couldn't wait for $describe: $!\n";
  1294. $? && die "$describe failed (".&ecode.")\n";
  1295. &debug("script done");
  1296. print "\n" if $extranewlines;
  1297. }
  1298. sub run_script {
  1299. return if eval { &run_script_ne; 1; };
  1300. $rse= $@; chop($rse); &error("$package: $rse");
  1301. }
  1302. sub hash {
  1303. local ($file) = @_; # NB: filename must already have $instroot here
  1304. local ($c);
  1305. if (open(HF,"<$file")) {
  1306. defined($c= open(MDP,"-|")) || &error("fork/pipe for hash: $!");
  1307. if (!$c) {
  1308. if (!open(STDIN,"<&HF")) {
  1309. print STDERR "$name: unable to redirect stdin for hash: $!\n"; exit(1);
  1310. }
  1311. exec($md5sum); print STDERR "$name: unable to exec $md5sum: $!\n"; exit(1);
  1312. }
  1313. defined($hash= &readall('MDP')) || &error("unable to read from $md5sum: $!\n");
  1314. $!=0; close(MDP); $? && &error("$md5sum returned error (".&ecode.")");
  1315. $hash =~ s/\n+$//;
  1316. $hash =~ m/^[0-9a-f]{32}$/i || &error("$md5sum returned bogus output \`$hash'");
  1317. return $hash;
  1318. } elsif ($! == &ENOENT) {
  1319. return 'nonexistent';
  1320. } else {
  1321. &warn("$arg: unable to open conffile $file for hash: $!");
  1322. return '-';
  1323. }
  1324. }
  1325. sub files_not_identical {
  1326. local ($file1,$file2) = @_; # NB: filenames must already have $instroot here
  1327. if (stat($file1)) {
  1328. if (stat($file2)) {
  1329. system("cmp","-s",$file1,$file2);
  1330. if (&WIFEXITED($?)) {
  1331. $es= &WEXITSTATUS($?);
  1332. return $es if $es == 0 || $es == 1;
  1333. }
  1334. &error("cmp $file1 $file2 returned error (".&ecode.")");
  1335. } elsif ($! == &ENOENT) {
  1336. return 1;
  1337. } else {
  1338. &error("failed to stat conffile $file2: $!");
  1339. }
  1340. } elsif ($! == &ENOENT) {
  1341. if (stat($file2)) {
  1342. return 1;
  1343. } elsif ($! == &ENOENT) {
  1344. return 0;
  1345. } else {
  1346. &error("failed to stat conffile $file2: $!");
  1347. }
  1348. } else {
  1349. &error("failed to stat conffile $file1: $!");
  1350. }
  1351. }
  1352. sub copyperm {
  1353. local ($from,$to,$name) = @_;
  1354. if (@statv= stat("$instroot/$from")) {
  1355. chown($statv[4],$statv[5],"$instroot/$to") ||
  1356. $!==&ENOENT ||
  1357. &warn("$package: unable to preserve ownership of $name");
  1358. chmod($statv[2],"$instroot/$to") ||
  1359. $!==&ENOENT ||
  1360. &warn("$package: unable to preserve permissions of $name");
  1361. } elsif ($! != &ENOENT) {
  1362. &warn("$package: unable to check permissions and ownership of".
  1363. " $name in order to preserve them");
  1364. }
  1365. }
  1366. sub conffderef {
  1367. local ($file) = @_;
  1368. local ($drf, $warning);
  1369. $drf= $file; $warning='';
  1370. for (;;) {
  1371. if (!lstat("$instroot/$drf")) {
  1372. last if $! == &ENOENT; $warning= "unable to lstat: $!"; last;
  1373. } elsif (-f _) {
  1374. last;
  1375. } elsif (-l _) {
  1376. if (!defined($lv= readlink("$instroot/$drf"))) {
  1377. $warning= "unable to readlink: $!"; last;
  1378. }
  1379. if ($lv =~ m|^/|) {
  1380. $drf= $lv;
  1381. } else {
  1382. $drf =~ s|/[^/]+$|/$lv|;
  1383. }
  1384. } else {
  1385. $warning= "not a plain file or symlink"; last;
  1386. }
  1387. }
  1388. &debug("conffile $file drf $drf warns \`$warning'");
  1389. if ($warning) {
  1390. &warn("$arg: possible problem with configuration file $file (= $drf):\n".
  1391. " $warning");
  1392. return undef;
  1393. } else {
  1394. return $drf;
  1395. }
  1396. }