From ca1fb73b4ccf0ff0fe0f8c54e2d5db923f8bba6a Mon Sep 17 00:00:00 2001 From: Rafael Garcia-Suarez Date: Wed, 23 Jun 2004 07:52:31 +0000 Subject: Support for supplementary CDs during installation (from the 10.0 update branch.) --- perl-install/install_any.pm | 109 ++++++++++++++++++++++++++++++++++++++------ perl-install/pkgs.pm | 49 ++++++++++++++++---- 2 files changed, 137 insertions(+), 21 deletions(-) diff --git a/perl-install/install_any.pm b/perl-install/install_any.pm index f64da8589..aaf820648 100644 --- a/perl-install/install_any.pm +++ b/perl-install/install_any.pm @@ -1,6 +1,5 @@ package install_any; # $Id$ -use diagnostics; use strict; use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK $boot_medium $current_medium $asked_medium @advertising_images); @@ -39,6 +38,13 @@ $asked_medium = $boot_medium; my $postinstall_rpms = ''; my $cdrom; my %iso_images; + +sub mountCdrom($;$) { + my ($mountpoint, $cdrom_) = @_; + $cdrom_ = $cdrom if !defined $cdrom_; + eval { fs::mount($cdrom_, $mountpoint, "iso9660", 'readonly') }; +} + sub useMedium($) { #- before ejecting the first CD, there are some files to copy! #- does nothing if the function has already been called. @@ -64,6 +70,7 @@ sub askChangeMedium($$) { my ($method, $medium) = @_; my $allow; do { + local $::o->{method} = $method = 'cdrom' if $medium =~ /^\d+s$/; #- Suppl CD eval { $allow = changeMedium($method, $medium) }; } while $@; #- really it is not allowed to die in changeMedium!!! or install will cores with rpmlib!!! log::l($allow ? "accepting medium $medium" : "refusing medium $medium"); @@ -137,7 +144,7 @@ sub errorOpeningFile($) { ejectCdrom($cdrom); while ($max > 0 && askChangeMedium($::o->{method}, $asked_medium)) { $current_medium = $asked_medium; - eval { fs::mount($cdrom, "/tmp/image", "iso9660", 'readonly') }; + mountCdrom("/tmp/image"); my $getFile = getFile($file); $getFile && @advertising_images and copy_advertising($::o); $getFile and return $getFile; @@ -154,6 +161,9 @@ sub errorOpeningFile($) { } } + #- Don't unselect supplementary CDs. + return if $asked_medium =~ /^\d+s$/; + #- keep in mind the asked medium has been refused on this way. #- this means it is no more selected. $::o->{packages}{mediums}{$asked_medium}{selected} = undef; @@ -165,7 +175,7 @@ sub errorOpeningFile($) { return; } sub getFile { - my ($f, $o_method) = @_; + my ($f, $o_method, $altroot) = @_; log::l("getFile $f:$o_method"); my $rel = relGetFile($f); do { @@ -182,11 +192,13 @@ sub getFile { require http; http::getFile("$ENV{URLPREFIX}/$rel"); } else { - #- try to open the file, but examine if it is present in the repository, this allow - #- handling changing a media when some of the file on the first CD has been copied - #- to other to avoid media change... + #- try to open the file, but examine if it is present in the repository, + #- this allows handling changing a media when some of the files on the + #- first CD have been copied to other to avoid media change... my $f2 = "$postinstall_rpms/$f"; - $f2 = "/tmp/image/$rel" if !$postinstall_rpms || !-e $f2; + $altroot = '/tmp/image' unless $altroot; + $f2 = "$altroot/$rel" if !$postinstall_rpms || !-e $f2; + $f2 = $rel if $rel =~ m!^/! && !-e $f2; #- not a relative path my $F; open($F, $f2) && $F; } } || errorOpeningFile($f); @@ -343,7 +355,53 @@ sub setPackages { require pkgs; if (!$o->{packages} || is_empty_array_ref($o->{packages}{depslist})) { - $o->{packages} = pkgs::psUsingHdlists($o->{prefix}, $o->{method}); + my $cdrom; + ($o->{packages}, my $suppl_CDs) = pkgs::psUsingHdlists($o->{prefix}, $o->{method}); + + #- ask whether there are supplementary CDs + SUPPL: { + if ($suppl_CDs && !$o->{isUpgrade} + && $o->ask_yesorno('', N("Do you have a supplementary CD to install?"), 0)) + { + #- by convention, the media names for suppl. CDs match /^\d+s$/ + my $medium = '1s'; #- supplement 1 + local $::isWizard = 0; + local $o->{method} = 'cdrom'; + (my $cdromdev) = detect_devices::cdroms(); + last SUPPL if !$cdromdev; + $cdrom = $cdromdev->{device}; + my $dev = devices::make($cdrom); + ejectCdrom($cdrom); + if ($o->ask_okcancel('', N("Insert the CD"), 1)) { + mountCdrom("/mnt/cdrom", $cdrom); + log::l($@) if $@; + useMedium($medium); + my $supplmedium = pkgs::psUsingHdlist( + $o->{prefix}, # /mnt + 'cdrom', + $o->{packages}, + "hdlist$medium.cz", + $medium, + 'Mandrake/RPMS', + "Supplementary CD $medium", + 1, # selected + "/mnt/cdrom/Mandrake/base/hdlist$medium.cz", + ); + if ($supplmedium) { + log::l("read suppl hdlist"); + $supplmedium->{prefix} = "removable://mnt/cdrom"; #- pour install_urpmi + $supplmedium->{selected} = 1; + $supplmedium->{method} = 'cdrom'; + } else { + log::l("no suppl hdlist"); + } + #- TODO loop if there are several supplementary CDs + # ++$medium; $medium .= "s"; + } + } else { + $suppl_CDs = 0; + } + } #- open rpm db according to right mode needed. $o->{packages}{rpmdb} ||= pkgs::rpmDbOpen($o->{prefix}, $rebuild_needed); @@ -357,12 +415,36 @@ sub setPackages { pkgs::packageByName($o->{packages}, 'basesystem') || die("missing basesystem package"), 1); #- must be done after getProvides - pkgs::read_rpmsrate($o->{packages}, getFile("Mandrake/base/rpmsrate")); - ($o->{compssUsers}, $o->{compssUsersSorted}) = pkgs::readCompssUsers($o->{meta_class}); + #- if there is a supplementary CD, override the rpmsrate/compssUsers + pkgs::read_rpmsrate( + $o->{packages}, + getFile($suppl_CDs ? "/mnt/cdrom/Mandrake/base/rpmsrate" : "Mandrake/base/rpmsrate") + ); + ($o->{compssUsers}, $o->{compssUsersSorted}) = pkgs::readCompssUsers( + $o->{meta_class}, + $suppl_CDs ? "/mnt/cdrom/Mandrake/base/compssUsers" : "", + ); #- preselect default_packages and compssUsersChoices. setDefaultPackages($o); pkgs::selectPackage($o->{packages}, pkgs::packageByName($o->{packages}, $_) || next) foreach @{$o->{default_packages}}; + + #- umount supplementary CD. Will re-ask for it later + if ($suppl_CDs) { + getFile("XXX"); #- close still opened filehandles + log::l("Umounting suppl. CD"); + eval { fs::umount("/mnt/cdrom") }; + #- re-mount CD 1 if this was a cdrom install + if ($o->{method} eq 'cdrom') { + eval { + my $dev = detect_devices::tryOpen($cdrom); + ioctl($dev, c::CDROMEJECT(), 1); + }; + $o->ask_warn('', N("Insert the CD 1 again")); + mountCdrom("/tmp/image", $cdrom); + $asked_medium = 1; + } + } } else { #- this has to be done to make sure necessary files for urpmi are #- present. @@ -588,7 +670,8 @@ sub install_urpmi { cdrom => "removable://mnt/cdrom" }}{$method} || #- for live_update or live_install script. readlink("/tmp/image/Mandrake") =~ m,^(/.*)/Mandrake/*$, && "removable:/$1") . "/$_->{rpmsdir}"; - my $need_list = $dir =~ m,^(?:[^:]*://[^/:\@]*:[^/:\@]+\@|.*%{),; #- use list file only if visible password or macro. + #- use list file only if visible password or macro. + my $need_list = $dir =~ m,^(?:[^:]*://[^/:\@]*:[^/:\@]+\@|.*%{),; #- } #- build a list file if needed. if ($need_list) { @@ -596,7 +679,7 @@ sub install_urpmi { open(my $LIST, ">$prefix/var/lib/urpmi/list.$name") or log::l("failed to write list.$name"); umask $mask; - #- build list file using internal data, synthesis file should exists. + #- build list file using internal data, synthesis file should exist. if ($_->{end} > $_->{start}) { #- WARNING this method of build only works because synthesis (or hdlist) #- has been read. @@ -640,7 +723,7 @@ sub install_urpmi { } else { $with = $_->{rpmsdir}; $with =~ s|/[^/]*%{ARCH}.*||; - $with =~ s|/+|/|g; $with =~ s|/$||; $with =~ s|[^/]||g; $with =~ s|/|../|g; + $with =~ s|/+|/|g; $with =~ s|/$||; $with =~ s|[^/]||g; $with =~ s!/!../!g; $with .= "../Mandrake/base/$_->{hdlist}"; } diff --git a/perl-install/pkgs.pm b/perl-install/pkgs.pm index 618ef63b9..815ce25bc 100644 --- a/perl-install/pkgs.pm +++ b/perl-install/pkgs.pm @@ -1,6 +1,5 @@ package pkgs; # $Id$ -use diagnostics; use strict; use MDK::Common::System; @@ -85,6 +84,11 @@ sub extractHeaders { } } +sub isSupplCDMedium($) { + my ($medium) = @_; + $medium->{method} eq 'cdrom' && $medium->{medium} =~ /^\d+s$/; +} + #- TODO BEFORE TODO #- size and correction size functions for packages. my $B = 1.20873; @@ -371,6 +375,7 @@ sub psUsingHdlists { my ($prefix, $method) = @_; my $listf = install_any::getFile('Mandrake/base/hdlists') or die "no hdlists found"; my $packages = new URPM; + my $suppl_CDs = 0; #- add additional fields used by DrakX. @$packages{qw(count mediums)} = (0, {}); @@ -381,6 +386,9 @@ sub psUsingHdlists { chomp; s/\s*#.*$//; /^\s*$/ and next; + #- we'll ask afterwards for supplementary CDs, if the hdlists file contains + #- a line that begins with "suppl" + if (/^suppl/) { $suppl_CDs = 1; next } m/^\s*(noauto:)?(hdlist\S*\.cz2?)\s+(\S+)\s*(.*)$/ or die qq(invalid hdlist description "$_" in hdlists file); #- make sure the first medium is always selected! @@ -393,7 +401,7 @@ sub psUsingHdlists { log::l("psUsingHdlists read " . int(@{$packages->{depslist}}) . " headers on " . int(keys %{$packages->{mediums}}) . " hdlists"); - $packages; + return ($packages, $suppl_CDs); } sub psUsingHdlist { @@ -448,7 +456,10 @@ sub psUsingHdlist { #- avoid using more than one medium if Cd is not ejectable. #- but keep all medium here so that urpmi has the whole set. - $m->{ignored} ||= install_any::method_allows_medium_change($method) && $medium > 1 && !common::usingRamdisk(); + $m->{ignored} ||= ( + install_any::method_allows_medium_change($method) && $medium > 1 #- first cdrom + && $medium !~ /^\d+s/ #- not a suppl. CD + && !common::usingRamdisk()); #- parse synthesis (if available) of directly hdlist (with packing). if ($m->{ignored}) { @@ -560,9 +571,9 @@ sub read_rpmsrate { } sub readCompssUsers { - my ($meta_class) = @_; + my ($meta_class, $file) = @_; - my $file = 'Mandrake/base/compssUsers'; + $file = 'Mandrake/base/compssUsers' if !$file; my $f = $meta_class && install_any::getFile("$file.$meta_class") || install_any::getFile($file) or die "can't find $file"; readCompssUsers_raw($f); } @@ -920,13 +931,28 @@ sub installTransactionClosure { $medium or return (); #- no more medium usable -> end of installation by returning empty list. ($min_id, $max_id) = ($medium->{start}, $medium->{end}); + #- Supplementary CD : switch temporarily to "cdrom" method + my $suppl_CD = isSupplCDMedium($medium); + local $::o->{method} = do { + my $cdrom; + cat_("/proc/mounts") =~ m,(/(?:dev|tmp)/\S+)\s+(?:/mnt/cdrom|/tmp/image), and $cdrom = $1; + if (!defined $cdrom) { + (my $cdromdev) = detect_devices::cdroms(); + $cdrom = $cdromdev->{device}; + log::l("cdrom redetected at $cdrom"); + my $dev = devices::make($cdrom); + install_any::ejectCdrom($cdrom) if $::o->{method} eq 'cdrom'; # will umount /tmp/image + install_any::mountCdrom("/mnt/cdrom", $cdrom); + } else { log::l("cdrom already found at $cdrom") } + 'cdrom'; + } if $suppl_CD; #- it is sure at least one package will be installed according to medium chosen. install_any::useMedium($medium->{medium}); if (install_any::method_allows_medium_change($medium->{method})) { my $pkg = $packages->{depslist}[$l[0]]; #- force changeCD callback to be called from main process. - install_any::getFile($pkg->filename, $medium->{descr}); + install_any::getFile($pkg->filename, $medium->{descr}, $suppl_CD ? '/mnt/cdrom' : undef); #- close opened handle above. install_any::getFile('XXX'); } @@ -1062,7 +1088,8 @@ sub install($$$;$$) { my $trans = $db->create_transaction($prefix); if ($retry_pkg) { log::l("opened rpm database for retry transaction of 1 package only"); - $trans->add($retry_pkg, $isUpgrade && allowedToUpgrade($retry_pkg->name)); + $trans->add($retry_pkg, $isUpgrade && allowedToUpgrade($retry_pkg->name)) + or log::l("add failed for ".$retry_pkg->fullname); } else { log::l("opened rpm database for transaction of " . int(@transToInstall) . " new packages, still $nb after that to do"); @@ -1082,7 +1109,12 @@ sub install($$$;$$) { my $medium = packageMedium($packages, $pkg); my $f = $pkg && $pkg->filename; print $LOG "$f\n"; - $fd = install_any::getFile($f, $medium->{descr}); + if (isSupplCDMedium($medium)) { + #- supplementary CD already mounted in /mnt/cdrom + $fd = install_any::getFile($f, $medium->{descr}, '/mnt/cdrom'); + } else { + $fd = install_any::getFile($f, $medium->{descr}); + } $fd ? fileno $fd : -1; }, callback_close => sub { my ($data, $_type, $id) = @_; @@ -1176,6 +1208,7 @@ sub install($$$;$$) { log::l("closing install.log file"); close $LOG; + eval { fs::umount("/mnt/cdrom") }; cleanHeaders($prefix); -- cgit v1.2.1