Advertisement
arthurwayne

update-alternatives

Nov 29th, 2020 (edited)
1,502
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 20.19 KB | None | 0 0
  1. #! /usr/bin/perl --
  2.  
  3. #use POSIX; &ENOENT;
  4. sub ENOENT { 2; }
  5.  
  6. # Global variables:
  7. #  $alink            Alternative we are managing (ie the symlink we're making/removing) (install only)
  8. #  $name             Name of the alternative (the symlink) we are processing
  9. #  $apath            Path of alternative we are offering
  10. #  $apriority        Priority of link (only when we are installing an alternative)
  11. #  $mode             action to perform (display / install / remove / display / auto / config)
  12. #  $manual           update-mode for alternative (manual / auto)
  13. #  $state            State of alternative:
  14. #                       expected: alternative with highest priority is the active alternative
  15. #                       expected-inprogress: busy selecting alternative with highest priority
  16. #                       unexpected: alternative another alternative is active / error during readlink
  17. #                       nonexistent: alternative-symlink does not exist
  18. #  $link             Link we are working with
  19. #  @slavenames       List with names of slavelinks
  20. #  %slavenum         Map from name of slavelink to slave-index (into @slavelinks)
  21. #  @slavelinks       List of slavelinks (indexed by slave-index)
  22. #  %versionnum       Map from currently available versions into @versions and @priorities
  23. #  @versions         List of available versions for alternative
  24. #  %priorities       Map from @version-index to priority
  25. #  %slavepath        Map from (@version-index,slavename) to slave-path
  26.  
  27. $version="1.8.4"; # This line modified by Makefile
  28. sub usageversion {
  29.     print(STDERR <<END)
  30. The update-alternatives $version.  Copyright (C) 1995 Ian Jackson.
  31. This is free software; see the GNU General Public Licence
  32. version 2 or later for copying conditions.  There is NO warranty.
  33.  
  34. Usage: update-alternatives --install <link> <name> <path> <priority>
  35.                           [--slave <link> <name> <path>] ...
  36.        update-alternatives --remove <name> <path>
  37.        update-alternatives --auto <name>
  38.        update-alternatives --display <name>
  39.        update-alternatives --config <name> [<path>]
  40. <name> is the name in /etc/alternatives.
  41. <path> is the name referred to.
  42. <link> is the link pointing to /etc/alternatives/<name>.
  43. <priority> is an integer; options with higher numbers are chosen.
  44.  
  45. Options:  --verbose|--quiet  --test  --help  --version
  46.           --altdir <directory>  --admindir <directory>
  47. END
  48.         || &quit("failed to write usage: $!");
  49. }
  50. sub quit { print STDERR "update-alternatives: @_\n"; exit(2); }
  51. sub badusage { print STDERR "update-alternatives: @_\n\n"; &usageversion; exit(2); }
  52.  
  53. $altdir= '/etc/alternatives';
  54. $admindir= '/var/lib/alternatives';
  55. $testmode= 0;
  56. $verbosemode= 0;
  57. $mode='';
  58. $manual= 'auto';
  59. $|=1;
  60.  
  61. sub checkmanymodes {
  62.     return unless $mode;
  63.     &badusage("two modes specified: $_ and --$mode");
  64. }
  65.  
  66. while (@ARGV) {
  67.     $_= shift(@ARGV);
  68.     last if m/^--$/;
  69.     if (!m/^--/) {
  70.         &quit("unknown argument \`$_'");
  71.     } elsif (m/^--(help|version)$/) {
  72.         &usageversion; exit(0);
  73.     } elsif (m/^--test$/) {
  74.         $testmode= 1;
  75.     } elsif (m/^--verbose$/) {
  76.         $verbosemode= +1;
  77.     } elsif (m/^--quiet$/) {
  78.         $verbosemode= -1;
  79.     } elsif (m/^--install$/) {
  80.         &checkmanymodes;
  81.         @ARGV >= 4 || &badusage("--install needs <link> <name> <path> <priority>");
  82.         ($alink,$name,$apath,$apriority,@ARGV) = @ARGV;
  83.         $apriority =~ m/^[-+]?\d+/ || &badusage("priority must be an integer");
  84.         $mode= 'install';
  85.     } elsif (m/^--remove$/) {
  86.         &checkmanymodes;
  87.         @ARGV >= 2 || &badusage("--remove needs <name> <path>");
  88.         ($name,$apath,@ARGV) = @ARGV;
  89.         $mode= 'remove';
  90.     } elsif (m/^--(display|auto)$/) {
  91.         &checkmanymodes;
  92.         @ARGV || &badusage("--$1 needs <name>");
  93.         $mode= $1;
  94.         $name= shift(@ARGV);
  95.     } elsif (m/^--config$/) {
  96.         &checkmanymodes;
  97.         @ARGV || &badusage("--config needs <name> [<path>]");
  98.         ($name,$apath,@ARGV) = @ARGV;
  99.         $mode= 'config';
  100.     } elsif (m/^--slave$/) {
  101.         @ARGV >= 3 || &badusage("--slave needs <link> <name> <path>");
  102.         ($slink,$sname,$spath,@ARGV) = @ARGV;
  103.         defined($aslavelink{$sname}) && &badusage("slave name $sname duplicated");
  104.         $aslavelinkcount{$slink}++ && &badusage("slave link $slink duplicated");
  105.         $aslavelink{$sname}= $slink;
  106.         $aslavepath{$sname}= $spath;
  107.     } elsif (m/^--altdir$/) {
  108.         @ARGV || &badusage("--altdir needs a <directory> argument");
  109.         $altdir= shift(@ARGV);
  110.     } elsif (m/^--admindir$/) {
  111.         @ARGV || &badusage("--admindir needs a <directory> argument");
  112.         $admindir= shift(@ARGV);
  113.     } else {
  114.         &badusage("unknown option \`$_'");
  115.     }
  116. }
  117.  
  118. defined($aslavelink{$name}) && &badusage("name $name is both primary and slave");
  119. $aslavelinkcount{$alink} && &badusage("link $link is both primary and slave");
  120.  
  121. $mode || &badusage("need --display, --config, --install, --remove or --auto");
  122. $mode eq 'install' || !%aslavelink || &badusage("--slave only allowed with --install");
  123.  
  124. if (open(AF,"$admindir/$name")) {
  125.     $manual= &gl("manflag");
  126.     $manual eq 'auto' || $manual eq 'manual' || &badfmt("manflag");
  127.     $link= &gl("link");
  128.     while (($sname= &gl("sname")) ne '') {
  129.         push(@slavenames,$sname);
  130.         defined($slavenum{$sname}) && &badfmt("duplicate slave $sname");
  131.         $slavenum{$sname}= $#slavenames;
  132.         $slink= &gl("slink");
  133.         $slink eq $link && &badfmt("slave link same as main link $link");
  134.         $slavelinkcount{$slink}++ && &badfmt("duplicate slave link $slink");
  135.         push(@slavelinks,$slink);
  136.     }
  137.     while (($version= &gl("version")) ne '') {
  138.         defined($versionnum{$version}) && &badfmt("duplicate path $version");
  139.        if ( -e $version ) {
  140.            push(@versions,$version);
  141.            $versionnum{$version}= $i= $#versions;
  142.            $priority= &gl("priority");
  143.            $priority =~ m/^[-+]?\d+$/ || &badfmt("priority $version $priority");
  144.            $priorities[$i]= $priority;
  145.            for ($j=0; $j<=$#slavenames; $j++) {
  146.                $slavepath{$i,$j}= &gl("spath");
  147.            }
  148.        } else {
  149.            # File not found - remove
  150.            &pr("Alternative for $name points to $version - which wasn't found.  Removing from list of alternatives.")
  151.              if $verbosemode > 0;
  152.            &gl("priority");
  153.            for ($j=0; $j<=$#slavenames; $j++) {
  154.                &gl("spath");
  155.            }
  156.        }
  157.     }
  158.     close(AF);
  159.     $dataread=1;
  160. } elsif ($! != &ENOENT) {
  161.     &quit("failed to open $admindir/$name: $!");
  162. }
  163.  
  164. $best= '';
  165. for ($i=0; $i<=$#versions; $i++) {
  166.     if ($best eq '' || $priorities[$i] > $bestpri) {
  167.         $best= $versions[$i]; $bestpri= $priorities[$i];
  168.     }
  169. }
  170.  
  171. if ($mode eq 'display') {
  172.     if (!$dataread) {
  173.         &quit("No alternatives found for $name.");
  174.     } else {
  175.         &pr("$name - status is $manual.");
  176.         if (defined($linkname= readlink("$altdir/$name"))) {
  177.             &pr(" link currently points to $linkname");
  178.         } elsif ($! == &ENOENT) {
  179.             &pr(" link currently absent");
  180.         } else {
  181.             &pr(" link unreadable - $!");
  182.         }
  183.         for ($i=0; $i<=$#versions; $i++) {
  184.             &pr("$versions[$i] - priority $priorities[$i]");
  185.             for ($j=0; $j<=$#slavenames; $j++) {
  186.                 next unless length($tspath= $slavepath{$i,$j});
  187.                 &pr(" slave $slavenames[$j]: $tspath");
  188.             }
  189.         }
  190.         if ($best eq '') {
  191.             &pr("No versions available.");
  192.         } else {
  193.             &pr("Current \`best' version is $best.");
  194.         }
  195.     }
  196.     exit 0;
  197. }
  198.  
  199. if ($mode eq 'config') {
  200.     if (!$dataread) {
  201.     &quit("No alternatives found for $name.");
  202.     } else {
  203.     &config_alternatives($name);
  204.     }
  205. }
  206.  
  207. if (defined($linkname= readlink("$altdir/$name"))) {
  208.     if ($linkname eq $best) {
  209.         $state= 'expected';
  210.     } elsif (defined(readlink("$altdir/$name.tmp"))) {
  211.         $state= 'expected-inprogress';
  212.     } else {
  213.         $state= 'unexpected';
  214.     }
  215. } elsif ($! == &ENOENT) {
  216.     $state= 'nonexistent';
  217. } else {
  218.     $state= 'unexpected';
  219. }
  220.  
  221. # Possible values for:
  222. #   $manual      manual, auto
  223. #   $state       expected, expected-inprogress, unexpected, nonexistent
  224. #   $mode        auto, install, remove
  225. # all independent
  226.  
  227. if ($mode eq 'auto') {
  228.     &pr("Setting up automatic selection of $name.")
  229.       if $verbosemode > 0;
  230.     unlink("$altdir/$name.tmp") || $! == &ENOENT ||
  231.         &quit("unable to remove $altdir/$name.tmp: $!");
  232.     unlink("$altdir/$name") || $! == &ENOENT ||
  233.         &quit("unable to remove $altdir/$name.tmp: $!");
  234.     $state= 'nonexistent';
  235.     $manual= 'auto';
  236. } elsif ($state eq 'nonexistent') {
  237.     if ($manual eq 'manual') {
  238.         &pr("$altdir/$name has been deleted, returning to automatic selection.")
  239.           if $verbosemode > 0;
  240.         $manual= 'auto';
  241.     }
  242. }
  243.  
  244. #   $manual      manual, auto
  245. #   $state       expected, expected-inprogress, unexpected, nonexistent
  246. #   $mode        auto, install, remove
  247. # mode=auto <=> state=nonexistent
  248.  
  249. if ($state eq 'unexpected' && $manual eq 'auto') {
  250.     &pr("$altdir/$name has been changed (manually or by a script).\n".
  251.         "Switching to manual updates only.")
  252.       if $verbosemode > 0;
  253.     $manual= 'manual';
  254. }
  255.  
  256. #   $manual      manual, auto
  257. #   $state       expected, expected-inprogress, unexpected, nonexistent
  258. #   $mode        auto, install, remove
  259. # mode=auto <=> state=nonexistent
  260. # state=unexpected => manual=manual
  261.  
  262. &pr("Checking available versions of $name, updating links in $altdir ...\n".
  263.     "(You may modify the symlinks there yourself if desired - see \`man ln'.)")
  264.   if $verbosemode > 0;
  265.  
  266. if ($mode eq 'install') {
  267.     if ($link ne $alink && $link ne '') {
  268.         &pr("Renaming $name link from $link to $alink.")
  269.           if $verbosemode > 0;
  270.         &rename_mv($link,$alink) || $! == &ENOENT ||
  271.             &quit("unable to rename $link to $alink: $!");
  272.     }
  273.     $link= $alink;
  274.     if (!defined($i= $versionnum{$apath})) {
  275.         push(@versions,$apath);
  276.         $versionnum{$apath}= $i= $#versions;
  277.     }
  278.     $priorities[$i]= $apriority;
  279.     for $sname (keys %aslavelink) {
  280.         if (!defined($j= $slavenum{$sname})) {
  281.             push(@slavenames,$sname);
  282.             $slavenum{$sname}= $j= $#slavenames;
  283.         }
  284.         $oldslavelink= $slavelinks[$j];
  285.         $newslavelink= $aslavelink{$sname};
  286.         $slavelinkcount{$oldslavelink}-- if $oldslavelink ne '';
  287.         $slavelinkcount{$newslavelink}++ &&
  288.             &quit("slave link name $newslavelink duplicated");
  289.         if ($newslavelink ne $oldslavelink && $oldslavelink ne '') {
  290.             &pr("Renaming $sname slave link from $oldslavelink to $newslavelink.")
  291.               if $verbosemode > 0;
  292.             &rename_mv($oldslavelink,$newslavelink) || $! == &ENOENT ||
  293.                 &quit("unable to rename $oldslavelink to $newslavelink: $!");
  294.         }
  295.         $slavelinks[$j]= $newslavelink;
  296.     }
  297.     for ($j=0; $j<=$#slavenames; $j++) {
  298.         $slavepath{$i,$j}= $aslavepath{$slavenames[$j]};
  299.     }
  300. }
  301.  
  302. if ($mode eq 'remove') {
  303.     if ($manual eq "manual" and $state eq "expected") {
  304.         &pr("Removing manually selected alternative - switching to auto mode");
  305.     $manual= "auto";
  306.     }
  307.     if (defined($i= $versionnum{$apath})) {
  308.         $k= $#versions;
  309.         $versionnum{$versions[$k]}= $i;
  310.         delete $versionnum{$versions[$i]};
  311.         $versions[$i]= $versions[$k]; $#versions--;
  312.         $priorities[$i]= $priorities[$k]; $#priorities--;
  313.         for ($j=0; $j<=$#slavenames; $j++) {
  314.             $slavepath{$i,$j}= $slavepath{$k,$j};
  315.             delete $slavepath{$k,$j};
  316.         }
  317.     } else {
  318.         &pr("Alternative $apath for $name not registered, not removing.")
  319.           if $verbosemode > 0;
  320.     }
  321. }
  322.  
  323. for ($j=0; $j<=$#slavenames; $j++) {
  324.     for ($i=0; $i<=$#versions; $i++) {
  325.         last if $slavepath{$i,$j} ne '';
  326.     }
  327.     if ($i > $#versions) {
  328.         &pr("Discarding obsolete slave link $slavenames[$j] ($slavelinks[$j]).")
  329.           if $verbosemode > 0;
  330.         unlink("$altdir/$slavenames[$j]") || $! == &ENOENT ||
  331.             &quit("unable to remove $slavenames[$j]: $!");
  332.         unlink($slavelinks[$j]) || $! == &ENOENT ||
  333.             &quit("unable to remove $slavelinks[$j]: $!");
  334.         $k= $#slavenames;
  335.         $slavenum{$slavenames[$k]}= $j;
  336.         delete $slavenum{$slavenames[$j]};
  337.         $slavelinkcount{$slavelinks[$j]}--;
  338.         $slavenames[$j]= $slavenames[$k]; $#slavenames--;
  339.         $slavelinks[$j]= $slavelinks[$k]; $#slavelinks--;
  340.         for ($i=0; $i<=$#versions; $i++) {
  341.             $slavepath{$i,$j}= $slavepath{$i,$k};
  342.             delete $slavepath{$i,$k};
  343.         }
  344.         $j--;
  345.     }
  346. }
  347.  
  348. if ($manual eq 'manual') {
  349.     &pr("Automatic updates of $altdir/$name are disabled, leaving it alone.")
  350.       if $verbosemode > 0;
  351.     &pr("To return to automatic updates use \`update-alternatives --auto $name'.")
  352.       if $verbosemode > 0;
  353. } else {
  354.     if ($state eq 'expected-inprogress') {
  355.         &pr("Recovering from previous failed update of $name ...");
  356.         rename("$altdir/$name.tmp","$altdir/$name") ||
  357.             &quit("unable to rename $altdir/$name.tmp to $altdir/$name: $!");
  358.         $state= 'expected';
  359.     }
  360. }
  361.  
  362. #   $manual      manual, auto
  363. #   $state       expected, expected-inprogress, unexpected, nonexistent
  364. #   $mode        auto, install, remove
  365. # mode=auto <=> state=nonexistent
  366. # state=unexpected => manual=manual
  367. # manual=auto => state!=expected-inprogress && state!=unexpected
  368.  
  369. open(AF,">$admindir/$name.new") ||
  370.     &quit("unable to open $admindir/$name.new for write: $!");
  371. &paf($manual);
  372. &paf($link);
  373. for ($j=0; $j<=$#slavenames; $j++) {
  374.     &paf($slavenames[$j]);
  375.     &paf($slavelinks[$j]);
  376. }
  377. &paf('');
  378. $best= '';
  379. for ($i=0; $i<=$#versions; $i++) {
  380.     if ($best eq '' || $priorities[$i] > $bestpri) {
  381.         $best= $versions[$i]; $bestpri= $priorities[$i]; $bestnum= $i;
  382.     }
  383.     &paf($versions[$i]);
  384.     &paf($priorities[$i]);
  385.     for ($j=0; $j<=$#slavenames; $j++) {
  386.         &paf($slavepath{$i,$j});
  387.     }
  388. }
  389. &paf('');
  390. close(AF) || &quit("unable to close $admindir/$name.new: $!");
  391.  
  392. if ($manual eq 'auto') {
  393.     if ($best eq '') {
  394.         &pr("Last package providing $name ($link) removed, deleting it.")
  395.           if $verbosemode > 0;
  396.         unlink("$altdir/$name") || $! == &ENOENT ||
  397.             &quit("unable to remove $altdir/$name: $!");
  398.         unlink("$link") || $! == &ENOENT ||
  399.             &quit("unable to remove $altdir/$name: $!");
  400.         unlink("$admindir/$name.new") ||
  401.             &quit("unable to remove $admindir/$name.new: $!");
  402.         unlink("$admindir/$name") || $! == &ENOENT ||
  403.             &quit("unable to remove $admindir/$name: $!");
  404.         exit(0);
  405.     } else {
  406.         if (!defined($linkname= readlink($link)) && $! != &ENOENT) {
  407.             &pr("warning: $link is supposed to be a symlink to $altdir/$name\n".
  408.                 " (or nonexistent); however, readlink failed: $!")
  409.               if $verbosemode > 0;
  410.         } elsif ($linkname ne "$altdir/$name") {
  411.             &tmped_symlink("$altdir/$name",$link);
  412.         }
  413.         if (defined($linkname= readlink("$altdir/$name")) && $linkname eq $best) {
  414.             &pr("Leaving $name ($link) pointing to $best.")
  415.               if $verbosemode > 0;
  416.         } else {
  417.             &pr("Updating $name ($link) to point to $best.")
  418.               if $verbosemode > 0;
  419.         }
  420.         &checked_symlink($best,"$altdir/$name.tmp");
  421.     }
  422. }
  423.  
  424. rename("$admindir/$name.new","$admindir/$name") ||
  425.     &quit("unable to rename $admindir/$name.new to $admindir/$name: $!");
  426.  
  427. if ($manual eq 'auto') {
  428.     &checked_mv("$altdir/$name.tmp","$altdir/$name");
  429.     for ($j=0; $j<=$#slavenames; $j++) {
  430.         $sname= $slavenames[$j];
  431.         $slink= $slavelinks[$j];
  432.         if (!defined($linkname= readlink($slink)) && $! != &ENOENT) {
  433.             &pr("warning: $slink is supposed to be a slave symlink to\n".
  434.                 " $altdir/$sname, or nonexistent; however, readlink failed: $!")
  435.               if $verbosemode > 0;
  436.         } elsif ($linkname ne "$altdir/$sname") {
  437.             &tmped_symlink("$altdir/$sname",$slink);
  438.         }
  439.         $spath= $slavepath{$bestnum,$j};
  440.         unlink("$altdir/$sname.tmp") || $! == &ENOENT ||
  441.             &quit("unable to ensure $altdir/$sname.tmp nonexistent: $!");
  442.         if ($spath eq '') {
  443.             &pr("Removing $sname ($slink), not appropriate with $best.")
  444.               if $verbosemode > 0;
  445.             unlink("$altdir/$sname") || $! == &ENOENT ||
  446.                 &quit("unable to remove $altdir/$sname: $!");
  447.         unlink("$slink") || $! == &ENOENT ||
  448.             &quit("unable to remove $slink: $!");
  449.         } else {
  450.             if (defined($linkname= readlink("$altdir/$sname")) && $linkname eq $spath) {
  451.                 &pr("Leaving $sname ($slink) pointing to $spath.")
  452.                   if $verbosemode > 0;
  453.             } else {
  454.                 &pr("Updating $sname ($slink) to point to $spath.")
  455.                   if $verbosemode > 0;
  456.             }
  457.             &tmped_symlink("$spath","$altdir/$sname");
  458.         }
  459.     }
  460. }
  461.  
  462. sub config_message {
  463.     if ($#versions == 0) {
  464.     &pr("\nThere is only 1 program which provides $name");
  465.     &pr("($versions[0]). Nothing to configure.");
  466.     exit(0);
  467.     }
  468.     printf(STDOUT "\nThere are %s programs which provide \`$name'.\n\n", $#versions+1);
  469.     printf(STDOUT "  Selection    Command\n");
  470.     printf(STDOUT "-----------------------------------------------\n");
  471.     for ($i=0; $i<=$#versions; $i++) {
  472.     printf(STDOUT "%s%s    %s        %s\n",
  473.         (readlink("$altdir/$name") eq $versions[$i]) ? '*' : ' ',
  474.         ($best eq $versions[$i]) ? '+' : ' ',
  475.         $i+1, $versions[$i]);
  476.     }
  477.     printf(STDOUT "\nEnter to keep the default[*], or type selection number: ");
  478. }
  479.  
  480. sub config_alternative {
  481.     my ($preferred) = @_;
  482.     $manual = "manual";
  483.     &pr("Using \`$versions[$preferred]' to provide \`$name'.");
  484.     my $spath = $versions[$preferred];
  485.     &tmped_symlink("$spath","$altdir/$name");
  486.     #Link slaves...
  487.     for( my $slnum = 0; $slnum < @slavenames; $slnum++ ) {
  488.     my $slave = $slavenames[$slnum];
  489.     if ($slavepath{$preferred,$slnum} ne '') {
  490.         &tmped_symlink($slavepath{$preferred,$slnum}, "$altdir/$slave");
  491.     } else {
  492.         &pr("Removing $slave ($slavelinks[$slnum]), not appropriate with $versions[$preferred].")
  493.         if $verbosemode > 0;
  494.         unlink("$altdir/$slave") || $! == &ENOENT ||
  495.         &quit("unable to remove $altdir/$slave: $!");
  496.     }
  497.     }
  498.     exit(0);
  499. }
  500.  
  501. sub config_alternatives {
  502.     if (defined($apath)) {
  503.     if (defined($i= $versionnum{$apath})) {
  504.         &config_alternative($i);
  505.     } else {
  506.         &quit("Alternative $apath for $name not registered.");
  507.     }
  508.     }
  509.     do {
  510.     &config_message;
  511.     $preferred=<STDIN>;
  512.     chop($preferred);
  513.     } until $preferred eq '' || $preferred>=1 && $preferred<=$#versions+1 &&
  514.     ($preferred =~ m/[0-9]*/);
  515.     if ($preferred ne '') {
  516.     $preferred--;
  517.         &config_alternative($preferred);
  518.     } else {
  519.     &quit("Nothing selected.");
  520.     }
  521. }
  522.  
  523. sub pr { print(STDOUT "@_\n") || &quit("error writing stdout: $!"); }
  524. sub paf {
  525.     $_[0] =~ m/\n/ && &quit("newlines prohibited in update-alternatives files ($_[0])");
  526.     print(AF "$_[0]\n") || &quit("error writing stdout: $!");
  527. }
  528. sub gl {
  529.     $!=0; $_= <AF>;
  530.     length($_) || &quit("error or eof reading $admindir/$name for $_[0] ($!)");
  531.     s/\n$// || &badfmt("missing newline after $_[0]");
  532.     $_;
  533. }
  534. sub badfmt {
  535.     &quit("internal error: $admindir/$name corrupt: $_[0]");
  536. }
  537. sub rename_mv {
  538.     return (rename($_[0], $_[1]) || (system(("mv", $_[0], $_[1])) == 0));
  539. }
  540. sub checked_symlink {
  541.     my ($filename, $linkname) = @_;
  542.     unlink($linkname) || $! == &ENOENT ||
  543.     &quit("unable to ensure $linkname nonexistent: $!");
  544.     symlink($filename,$linkname) ||
  545.     &quit("unable to symlink $linkname to $filename: $!");
  546. }
  547. sub checked_mv {
  548.     my ($source, $dest) = @_;
  549.     &rename_mv($source, $dest) ||
  550.     &quit("unable to install $source as $dest: $!");
  551. }
  552. sub tmped_symlink {
  553.     my ($filename, $linkname) = @_;
  554.     my $tmplink = "$linkname.tmp";
  555.  
  556.     &checked_symlink($filename,$tmplink);
  557.     &checked_mv($tmplink,$linkname);
  558. }
  559.  
  560. exit(0);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement