home *** CD-ROM | disk | FTP | other *** search
/ PC User 2003 January / Disc 3 / Amethyst.iso / live / usr / bin / phi-upgrade < prev    next >
Encoding:
Text File  |  2001-04-27  |  8.8 KB  |  381 lines

  1. #!/usr/bin/perl
  2.  
  3. # @ARGV contains list of RPMs to upgrade
  4. $|=1;
  5. $dryrun = 1;
  6. $verbose = 0;
  7. $philine = 'phi-gen-upgrade ';
  8. $RPM = 'rpm';
  9. $logfile = '/var/log/update';
  10.  
  11. $usrpath = '/usr/lib/PHI';
  12.  
  13. $outofspace = 0;
  14.  
  15. sub usage {
  16. print STDERR "This program upgrades your OpenLinux system from one version to the\n";
  17. print STDERR "RPMs as given on the commandline and as specified by additional options below.\n";
  18. print STDERR "\n";
  19. print STDERR "Usage: phi-upgrade [<options>] <path to RPMS>\n";
  20. print STDERR "\n";
  21. print STDERR "    --help            Print this helptext and exit.\n";
  22. print STDERR "    --root /root/dir/    Use this as root directory for all RPM \n";
  23. print STDERR "                operations (db and install) and scripts.\n";
  24. print STDERR "    --suggest /path/to/list    Points to a list of suggested additional RPMS of\n";
  25. print STDERR "                the form:\n";
  26. print STDERR "\n";
  27. print STDERR "                <pkg>:<suggestpkg1>,<suggestpkg2>,...\n";
  28. print STDERR "    --list /path/to/list    Points to a list of unconditional additional\n";
  29. print STDERR "                RPMs to be installed.\n";
  30. print STDERR "    --verbose / -v        Increase verbosity.\n";
  31. print STDERR "\n";
  32. print STDERR "    --indeed        Do the real update (instead of just printing\n";
  33. print STDERR "                the number of RPMs to update).\n";
  34. print STDERR "\n\n";
  35. print STDERR "Make sure you are in single user mode before running this on a live system!\n";
  36.     exit 1;
  37. }
  38.  
  39. open(LOGFILE,">>$logfile");
  40.  
  41. $numberofrpms = 0;
  42.  
  43. @NARGV=();
  44. while (@ARGV) {
  45.     $_ = shift @ARGV;
  46.     if (/--help/) { &usage(); }
  47.     if (/--root/) {
  48.         $rootdir = shift @ARGV;
  49.         $RPM .= " --root $rootdir";
  50.         $philine .= " --root $rootdir";
  51.         next;
  52.     }
  53.     if (/--indeed/) {
  54.         $dryrun = 0;
  55.         next;
  56.     }
  57.     if (/--suggest/) {
  58.         $suggest = shift @ARGV;
  59.         $philine .= " --suggest $suggest";
  60.         next;
  61.     }
  62.     if (/--list/) {
  63.         $suggest = shift @ARGV;
  64.         $philine .= " --list $suggest";
  65.         next;
  66.     }
  67.     if (/--verbose/ || /-v/) {
  68.         $verbose = 1;
  69.         next;
  70.     }
  71.     push @NARGV,$_;
  72. }
  73. @ARGV=@NARGV;
  74.  
  75. if ($dryrun) {
  76.     $philine .= " --pretty";
  77. }
  78.  
  79. $debug = 0;
  80. sub xdeb { print STDERR @_ if ($debug); }
  81.  
  82. if (@ARGV==0) { &usage(); }
  83.  
  84. #############################################################################
  85.  
  86. system("mount -t proc none $rootdir/proc/");
  87. system("mkdir -p $rootdir/var/lib/PHI/");
  88.  
  89. check_for_rebuild_rpmdb();
  90.  
  91. if (@ARGV==1) {
  92.     $d1 = shift @ARGV;
  93.     $philine.=" --to $d1";
  94.     open(TOUPGRADE,"$philine 2>&1|")||die "could not start $philine:$!";
  95.     @toupgrade = <TOUPGRADE>;
  96.     close(TOUPGRADE);
  97.     print LOGFILE @toupgrade;
  98.     slurp_installed_rpms();
  99.     slurp_new_rpms($d1);
  100. } else {
  101.     $d1 = shift @ARGV;
  102.     $d2 = shift @ARGV;
  103.     $philine.=" --from $d1 --to $d2 ";
  104.     open(TOUPGRADE,"$philine 2>&1|")||die "could not start $philine:$!";
  105.     @toupgrade = <TOUPGRADE>;
  106.     close(TOUPGRADE);
  107.     print LOGFILE @toupgrade;
  108.     slurp_old_rpms($d1);
  109.     slurp_new_rpms($d2);
  110. }
  111.  
  112. foreach (@toupgrade) { 
  113.     xdeb($_);
  114.     chomp;
  115.     if (/^install: (\S*)/) {
  116.         $rpm = $1;
  117.         $toupgrade{$rpm}=1;
  118.         $numberofrpms++;
  119.         next;
  120.     }
  121.     if (/^interlocked: (\S*)/) {
  122.         %{$interlocked{$rpm}} = map { $_ => 1 } split(/,/,$1);
  123.         # the following is for catching 'broken' dependency RPMs.
  124.         foreach (keys %{$interlocked{$rpm}}) {
  125.             next if (/^!/);
  126.             if (!$toupgrade{$_}) {
  127.                 $toupgrade{$_}=1;
  128.                 %{$interlocked{$_}} = %{$interlocked{$rpm}};
  129.             }
  130.         }
  131.         next;
  132.     }
  133.     if (/^remove: (\S*)/) {
  134.         $toremove{$1}=1;
  135.         $numberofrpms++;
  136.         next;
  137.     }
  138. }
  139.  
  140. sub do_exec_fixupscript {
  141.     my($cmd) = @_;
  142.  
  143.     return 0 if (! -x "$usrpath/$cmd");
  144.     return system("$usrpath/$cmd") if (!$rootdir);
  145.     system("mkdir -p $rootdir/$usrpath");
  146.     system("cp -a $usrpath/$cmd $rootdir/$usrpath");
  147.     chdir($rootdir) || print LOGFILE "chdir $rootdir did not work:$!\n";
  148.     open(EXECOUT,"chroot . /$usrpath/$cmd 2>&1|");
  149.     while (<EXECOUT>) { print LOGFILE; }
  150.     close(EXECOUT);
  151.     return 1;
  152. }
  153.  
  154. sub do_execute {
  155.     my($cmd) = @_;
  156.     my($res);
  157.  
  158.     open(CMD,"$cmd 2>&1|")||return 0;
  159.     while (<CMD>) {
  160.         if (/installing.*needs.*on the.*filesystem/) {
  161.             $outofspace = 1;
  162.         }
  163.         print LOGFILE;
  164.     }
  165.     if (!close(CMD)) {
  166.         return 0;
  167.     }
  168.     if ($outofspace) {
  169.         return 0;
  170.     }
  171.     return 1;
  172. }
  173.  
  174. sub do_rpm {
  175.     my($rpmline,@rpms) = @_;
  176.     my($res,$rpm);
  177.  
  178.     if ($dryrun) {
  179.         $verbose && print "$rpmline\n";
  180.     } else {
  181.         foreach $rpm (@rpms) {
  182.             &do_exec_fixupscript("$rpm.prefixup");
  183.         }
  184.         if (!do_execute("$rpmline")) {
  185.             if ($outofspace) {
  186.                 print STDERR "Failure: Out of memory.\n";
  187.                 return 0;
  188.             }
  189.             print STDERR "Failure: trying with --force\n";
  190.             if (!do_execute("$rpmline --force")) {
  191.                 print STDERR "Failure: trying with --force --nodeps\n";
  192.                 if ($outofspace) {
  193.                     print STDERR "Failure: Out of memory.\n";
  194.                     return 0;
  195.                 }
  196.                 if (!do_execute("$rpmline --force --nodeps")){
  197.                     if ($outofspace) {
  198.                         print STDERR "Failure: Out of memory.\n";
  199.                         return 0;
  200.                     }
  201.                     print STDERR "--force --nodeps failed too ... Umm.\n";
  202.                 }
  203.             }
  204.         }
  205.         foreach $rpm (@rpms) {
  206.             &do_exec_fixupscript("$rpm.postfixup");
  207.         }
  208.         print join("\n",@rpms) . "\n";
  209.     }
  210.     if ($outofspace) {
  211.         exit(42);
  212.     }
  213.     return 1;
  214. }
  215.  
  216. sub delete_all_ilockrefs {
  217.     my($rpm) = @_;
  218.  
  219.     foreach $blub (keys %interlocked) {
  220.         %ilocks = %{$interlocked{$blub}};
  221.         foreach $xrpm (keys %ilocks) {
  222.             next if (defined($toupgrade{$xrpm}) || defined($topremove{$xrpm}));
  223.             delete $ilocks{$xrpm};
  224.         }
  225.         %{$interlocked{$blub}} = %ilocks;
  226.     }
  227. }
  228.  
  229. sub output_rpmline {
  230.     my($rpm) = @_;
  231.     if ($newrealname{$rpm} ne $oldrealname{$rpm}) {
  232.         do_rpm("$RPM -Uvh $newrpmfn{$rpm}");
  233.     } else {
  234.         do_rpm("$RPM -Uvh --force $newrpmfn{$rpm}");
  235.     }
  236. }
  237.  
  238. sub slurp_new_rpms($) {
  239.     my($path) = @_;
  240.     my(@rpms,$rpm,$rpmname,$rpmversion);
  241.  
  242.     # regular glob doesn't work in Live FS.
  243.     $foo = `echo $path/*.rpm`;chomp($foo);@rpms=split(/ /,$foo);
  244.     foreach $rpm (@rpms) {
  245.         $rpm =~ s/.*\///;
  246.         $rpmname = $rpm;
  247.         $rpmversion = $rpmname;
  248.         $rpmversion =~ s/\.[^.]*\.rpm$//; # strip .i386/src.rpm;
  249.         $rpmname =~ s/-[^-]*-[^-]*\.[^.]*\.rpm$//; # strip version-release-i386/src.rpm;
  250.         $newrealname{$rpmname} = $rpm;
  251.         $newrpmfn{$rpmname} = "$path/$rpm";
  252.  
  253.     }
  254. }
  255.  
  256. sub slurp_old_rpms($) {
  257.     my($path) = @_;
  258.     my(@rpms,$rpm,$rpmname,$rpmversion);
  259.  
  260.     # regular glob doesn't work in Live FS.
  261.     $foo = `echo $path/*.rpm`;chomp($foo);@rpms=split(/ /,$foo);
  262.     foreach $rpm (@rpms) {
  263.         $rpm =~ s/.*\///;
  264.         $rpmname = $rpm;
  265.         $rpmversion = $rpmname;
  266.         $rpmversion =~ s/\.[^.]*\.rpm$//; # strip .i386/src.rpm;
  267.         $rpmname =~ s/-[^-]*-[^-]*\.[^.]*\.rpm$//; # strip version-release-i386/src.rpm;
  268.         $oldrealname{$rpmname} = $rpm;
  269.         $oldrpmfn{$rpmname} = "$path/$rpm";
  270.  
  271.     }
  272. }
  273.  
  274. sub slurp_installed_rpms() {
  275.     my(@rpms,$rpm,$rpmname,$rpmversion);
  276.     open(RPMQA,"$RPM -qa|");
  277.     @rpms=<RPMQA>;chomp(@rpms);
  278.     close(RPMQA);
  279.  
  280.     foreach $rpm (@rpms) {
  281.         $rpmname = $rpm;
  282.         $rpmversion = $rpmname; # no .i386.rpm here
  283.         $rpmname =~ s/-[^-]*-[^-]*$//; # strip version-release
  284.         $oldrealname{$rpmname} = "$rpm.i386.rpm";
  285.     }
  286. }
  287.  
  288. sub check_for_rebuild_rpmdb {
  289.     my (@rpms);
  290.     open(RPMQA,"$RPM -qi bash 2>&1|");
  291.     @rpms=<RPMQA>;chomp(@rpms);
  292.     if (!close(RPMQA)) {
  293.         do_rpm("$RPM --rebuilddb",'rpmupdatedb');
  294.     }
  295. }
  296.  
  297. ##############################################################################
  298. # main() :)
  299.  
  300. if (!$dryrun) {
  301.     &do_exec_fixupscript("phi-upgrade-start.fixup");
  302. }
  303.  
  304. # check versions of RPM. 
  305. $orpmver = $oldrealname{'rpm'};
  306. $nrpmver = $newrealname{'rpm'};
  307. # If they are not the same release, upgrade by all means necessary.
  308. if (defined($newrealname{'rpm'})) {
  309.     $xorpmver = $ormpver;
  310.     $xnrpmver = $nrmpver;
  311.  
  312.     $xorpmver =~ s/-[^-]*$//g; # strip release
  313.     $xnrpmver =~ s/-[^-]*$//g; # strip release
  314.  
  315.     if ($orpmver ne $nrpmver) {
  316.         do_rpm("$RPM -Uvh --nodeps --force " . $newrpmfn{'rpm'},'rpm');
  317.     }
  318.     $orpmver =~ s/-[^-]*$//g; # strip release
  319.     $nrpmver =~ s/-[^-]*$//g; # strip release
  320. }
  321.  
  322. while (scalar %toupgrade) {
  323.     # 1. Find smallest interlocked set.
  324.  
  325.     $smallestsetsize = 10000;
  326.     $smallestrpm = '';
  327.     foreach $rpm (keys %toupgrade) {
  328.         @xkeys = keys %{$interlocked{$rpm}};
  329.         $xkeys = @xkeys;
  330.         if ($xkeys<$smallestsetsize) {
  331.             next if (!$xkeys);
  332.             $smallestrpm = $rpm;
  333.             $smallestsetsize = $xkeys;
  334.         }
  335.     }
  336.     last if ($smallestsetsize == 10000);
  337.  
  338.     # 2. First remove the RPMS from this interlocked set.
  339.  
  340.     %ilocks = %{$interlocked{$smallestrpm}};
  341.     foreach $rpm (keys %ilocks) {
  342.         if ($rpm =~ /^!(.*)/) {
  343.             next if (!defined($toremove{$1}));
  344.             do_rpm("$RPM -e $1",$1);
  345.             delete $toremove{$1};
  346.             # &delete_all_ilockrefs($1);
  347.         }
  348.     }
  349.     $rpmline="";$useforce=0;$usedrpms=0;@rpms = ();
  350.     foreach $rpm (keys %ilocks) {
  351.         next if (!defined($toupgrade{$rpm}));
  352.         if ($newrealname{$rpm} eq $oldrealname{$rpm}) {
  353.             $useforce=1;
  354.         }
  355.         $rpmline .= " $newrpmfn{$rpm}";
  356.         push @rpms,$rpm;
  357.         # &delete_all_ilockrefs($rpm);
  358.         delete $toupgrade{$rpm};
  359.         $usedrpms++;
  360.     }
  361.     if ($useforce) {
  362.         # needs --force --nodeps. RPM does not get it otherwise.
  363.         if ($usedrpms > 1) {
  364.             do_rpm("$RPM -Uvh --force --nodeps $rpmline",@rpms);
  365.         } else {
  366.             do_rpm("$RPM -Uvh --force $rpmline",@rpms);
  367.         }
  368.     } else {
  369.         do_rpm("$RPM -Uvh $rpmline",@rpms);
  370.     }
  371.     delete $interlocked{$smallestrpm};
  372. }
  373. if (!$dryrun) {
  374.     &do_exec_fixupscript("phi-upgrade-end.fixup");
  375. }
  376.  
  377. $dryrun && print "Number of RPMS to upgrade: $numberofrpms\n";
  378.  
  379. close(LOGFILE);
  380. system("umount $rootdir/proc/");
  381.