From 622997696fb4a7bcedee2b81ddcf07598c3d2e52 Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Fri, 18 Jun 2004 05:20:25 +0000 Subject: in disk-iso install, automatically choose and change ISO images, according to their volume id and application id --- perl-install/c/stuff.xs.pl | 28 ++++++++++++++ perl-install/install_any.pm | 63 +++++++++++++++++++++++++++++-- perl-install/install_steps_gtk.pm | 25 ++++++------ perl-install/install_steps_interactive.pm | 21 ++++++----- perl-install/pkgs.pm | 4 +- 5 files changed, 116 insertions(+), 25 deletions(-) diff --git a/perl-install/c/stuff.xs.pl b/perl-install/c/stuff.xs.pl index 2097f0efc..c4049eb95 100644 --- a/perl-install/c/stuff.xs.pl +++ b/perl-install/c/stuff.xs.pl @@ -33,6 +33,7 @@ print ' #include #include #include +#include #include #include #include @@ -146,6 +147,12 @@ SV * iconv_(char* s, char* from_charset, char* to_charset) { return newSVpv(retval, 0); } +int length_of_space_padded(char *str, int len) { + while (len >= 0 && str[len-1] == \' \') + --len; + return len; +} + MODULE = c::stuff PACKAGE = c::stuff '; @@ -697,6 +704,27 @@ standard_charset() OUTPUT: RETVAL +void +get_loopback_name(int fd) + INIT: + struct loop_info loopinfo; + PPCODE: + if (!ioctl(fd, LOOP_GET_STATUS, &loopinfo)) + XPUSHs(sv_2mortal(newSVpv(loopinfo.lo_name, 0))); + +void +get_iso_volume_ids(int fd) + INIT: + struct iso_primary_descriptor voldesc; + PPCODE: + lseek(fd, 16 * ISOFS_BLOCK_SIZE, SEEK_SET); + if (read(fd, &voldesc, sizeof(struct iso_primary_descriptor)) == sizeof(struct iso_primary_descriptor)) { + if (voldesc.type[0] == ISO_VD_PRIMARY && !strncmp(voldesc.id, ISO_STANDARD_ID, sizeof(voldesc.id))) { + XPUSHs(sv_2mortal(newSVpv(voldesc.volume_id, length_of_space_padded(voldesc.volume_id, sizeof(voldesc.volume_id))))); + XPUSHs(sv_2mortal(newSVpv(voldesc.application_id, length_of_space_padded(voldesc.application_id, sizeof(voldesc.application_id))))); + } + } + '; $ENV{C_RPM} and print ' diff --git a/perl-install/install_any.pm b/perl-install/install_any.pm index ed20cf048..e37a26df9 100644 --- a/perl-install/install_any.pm +++ b/perl-install/install_any.pm @@ -38,10 +38,11 @@ $asked_medium = $boot_medium; #-###################################################################################### my $postinstall_rpms = ''; my $cdrom; +my %iso_images; sub useMedium($) { #- before ejecting the first CD, there are some files to copy! #- does nothing if the function has already been called. - $_[0] > 1 and $::o->{method} eq 'cdrom' and setup_postinstall_rpms($::prefix, $::o->{packages}); + $_[0] > 1 and $::o->{method} =~ /(^cdrom|-iso)$/ and setup_postinstall_rpms($::prefix, $::o->{packages}); $asked_medium eq $_[0] or log::l("selecting new medium '$_[0]'"); $asked_medium = $_[0]; @@ -68,6 +69,58 @@ sub askChangeMedium($$) { log::l($allow ? "accepting medium $medium" : "refusing medium $medium"); $allow; } + +sub look_for_ISOs() { + $iso_images{media} = []; + + ($iso_images{loopdev}, $iso_images{mountpoint}) = cat_("/proc/mounts") =~ m|(/dev/loop\d+)\s+(/tmp/image) iso9660| or return; + + my $get_iso_ids = sub { + my ($F) = @_; + my ($vol_id, $app_id) = c::get_iso_volume_ids(fileno $F); + my ($cd_set) = $vol_id =~ /^(.*)-[0-9]+$/; + $cd_set && { cd_set => $cd_set, app_id => $app_id }; + }; + + sysopen(my $F, $iso_images{loopdev}, 0) or return; + put_in_hash(\%iso_images, $get_iso_ids->($F)); + + #- may not work if it the orginal iso image path was longer than 64 chars + my ($loopfile) = c::get_loopback_name(fileno($F)) or return; + $loopfile =~ s!^/sysroot!!; + my $iso_dir = dirname($loopfile); + + foreach my $iso_file (glob("$iso_dir/*.iso")) { + my $iso_dev = devices::set_loop($iso_file) or return; + if (sysopen($F, $iso_dev, 0)) { + my $iso_ids = $get_iso_ids->($F); + push @{$iso_images{media}}, { file => $iso_file, %$iso_ids } if $iso_ids; + close($F); #- needed to delete loop device + } + devices::del_loop($iso_dev); + } + 1; +} + +sub changeIso($) { + my ($iso_label) = @_; + + %iso_images or look_for_ISOs() or return; + + my $iso_info = find { $_->{app_id} eq $iso_label && $_->{cd_set} eq $iso_images{cd_set} } @{$iso_images{media}} or return; + + eval { fs::umount($iso_images{mountpoint}) }; + $@ and warnAboutFilesStillOpen(); + devices::del_loop($iso_images{loopdev}); + + $iso_images{loopdev} = devices::set_loop($iso_info->{file}); + eval { + fs::mount($iso_images{loopdev}, $iso_images{mountpoint}, "iso9660", 'readonly'); + log::l("using ISO image '$iso_label'"); + 1; + } +} + sub errorOpeningFile($) { my ($file) = @_; $file eq 'XXX' and return; #- special case to force closing file after rpmlib transaction. @@ -471,7 +524,7 @@ sub ejectCdrom(;$) { #- umount BEFORE opening the cdrom device otherwise the umount will #- D state if the cdrom is already removed eval { fs::umount("/tmp/image") }; - if ($@) { log::l("files still open: ", readlink($_)) foreach map { glob_("$_/fd/*") } glob_("/proc/*") } + $@ and warnAboutFilesStillOpen(); eval { my $dev = detect_devices::tryOpen($cdrom); ioctl($dev, c::CDROMEJECT(), 1) if ioctl($dev, c::CDROM_DRIVE_STATUS(), 0) == c::CDS_DISC_OK(); @@ -479,6 +532,10 @@ sub ejectCdrom(;$) { } } +sub warnAboutFilesStillOpen() { + log::l("files still open: ", readlink($_)) foreach map { glob_("$_/fd/*") } glob_("/proc/*"); + } + sub setupFB { my ($o, $vga) = @_; @@ -709,7 +766,7 @@ sub getAndSaveInstallFloppies { } else { my $image = cat_("/proc/cmdline") =~ /pcmcia/ ? "pcmcia" : arch() =~ /ia64|ppc/ ? "all" : #- we only use all.img there - ${{ disk => 'hd_grub', cdrom => 'cdrom', ftp => 'network', nfs => 'network', http => 'network' }}{$o->{method}}; + ${{ disk => 'hd_grub', 'disk-iso' => 'hd_grub', cdrom => 'cdrom', ftp => 'network', nfs => 'network', http => 'network' }}{$o->{method}}; my $have_drivers = $image eq 'network'; $image .= arch() =~ /sparc64/ && "64"; #- for sparc64 there are a specific set of image. diff --git a/perl-install/install_steps_gtk.pm b/perl-install/install_steps_gtk.pm index 6c97db1f8..7ee2212c0 100644 --- a/perl-install/install_steps_gtk.pm +++ b/perl-install/install_steps_gtk.pm @@ -590,20 +590,23 @@ sub installPackages { *install_any::changeMedium = sub { my ($method, $medium) = @_; - #- if not using a cdrom medium, always abort. - if ($method eq 'cdrom' && !$::oem) { - my $name = pkgs::mediumDescr($o->{packages}, $medium); - local $| = 1; print "\a"; - my $time = time(); - my $r = $name !~ /commercial/i || ($o->{useless_thing_accepted2} ||= $o->ask_from_list_('', formatAlaTeX(install_messages::com_license()), [ N_("Accept"), N_("Refuse") ], "Accept") eq "Accept"); - $r &&= $o->ask_okcancel('', N("Change your Cd-Rom! - + #- if not using a cdrom medium or an iso image, always abort. + return unless $method =~ /(^cdrom|-iso)$/ && !$::oem; + + my $name = pkgs::mediumDescr($o->{packages}, $medium); + local $| = 1; print "\a"; + my $time = time(); + my $r = $name !~ /commercial/i || ($o->{useless_thing_accepted2} ||= $o->ask_from_list_('', formatAlaTeX(install_messages::com_license()), [ N_("Accept"), N_("Refuse") ], "Accept") eq "Accept"); + if ($method =~ /-iso$/) { + $r = install_any::changeIso($name); + } else { + $r &&= $o->ask_okcancel('', N("Change your Cd-Rom! Please insert the Cd-Rom labelled \"%s\" in your drive and press Ok when done. If you don't have it, press Cancel to avoid installation from this Cd-Rom.", $name), 1); - #- add the elapsed time (otherwise the predicted time will be rubbish) - $start_time += time() - $time; - return $r; } + #- add the elapsed time (otherwise the predicted time will be rubbish) + $start_time += time() - $time; + return $r; }; my $install_result; catch_cdie { $install_result = $o->install_steps::installPackages($packages) } diff --git a/perl-install/install_steps_interactive.pm b/perl-install/install_steps_interactive.pm index 39c3729b3..7d948ca1d 100644 --- a/perl-install/install_steps_interactive.pm +++ b/perl-install/install_steps_interactive.pm @@ -384,7 +384,7 @@ sub choosePackages { #- this is done at the very beginning to take into account #- selection of CD by user if using a cdrom. - $o->chooseCD($packages) if $o->{method} eq 'cdrom' && !$::oem; + $o->chooseCD($packages) if $o->{method} =~ /(^cdrom|-iso)$/ && !$::oem; my $w = $o->wait_message('', N("Looking for available packages...")); my $availableC = &install_steps::choosePackages; @@ -683,17 +683,20 @@ sub installPackages { *install_any::changeMedium = sub { my ($method, $medium) = @_; - #- if not using a cdrom medium, always abort. - $method eq 'cdrom' && !$::oem and do { - my $name = pkgs::mediumDescr($o->{packages}, $medium); - local $| = 1; print "\a"; - my $r = $name !~ /commercial/i || ($o->{useless_thing_accepted2} ||= $o->ask_from_list_('', formatAlaTeX(install_messages::com_license()), [ N_("Accept"), N_("Refuse") ], "Accept") eq "Accept"); - $r &&= $o->ask_okcancel('', N("Change your Cd-Rom! + #- if not using a cdrom medium or an iso image, always abort. + return unless $method =~ /(^cdrom|-iso)$/ && !$::oem; + my $name = pkgs::mediumDescr($o->{packages}, $medium); + local $| = 1; print "\a"; + my $r = $name !~ /commercial/i || ($o->{useless_thing_accepted2} ||= $o->ask_from_list_('', formatAlaTeX(install_messages::com_license()), [ N_("Accept"), N_("Refuse") ], "Accept") eq "Accept"); + if ($method =~ /-iso$/) { + $r = install_any::changeIso($name); + } else { + $r &&= $o->ask_okcancel('', N("Change your Cd-Rom! Please insert the Cd-Rom labelled \"%s\" in your drive and press Ok when done. If you don't have it, press Cancel to avoid installation from this Cd-Rom.", $name), 1); - return $r; - }; + } + return $r; }; my $install_result; catch_cdie { $install_result = $o->install_steps::installPackages($packages) } diff --git a/perl-install/pkgs.pm b/perl-install/pkgs.pm index 3934fa0fe..ed1f7eaa2 100644 --- a/perl-install/pkgs.pm +++ b/perl-install/pkgs.pm @@ -448,7 +448,7 @@ 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} ||= $method eq 'cdrom' && $medium > 1 && !common::usingRamdisk(); + $m->{ignored} ||= $method =~ /(^cdrom|-iso)$/ && $medium > 1 && !common::usingRamdisk(); #- parse synthesis (if available) of directly hdlist (with packing). if ($m->{ignored}) { @@ -922,7 +922,7 @@ sub installTransactionClosure { #- it is sure at least one package will be installed according to medium chosen. install_any::useMedium($medium->{medium}); - if ($medium->{method} eq 'cdrom') { + if ($medium->{method} =~ /(^cdrom|-iso)$/) { my $pkg = $packages->{depslist}[$l[0]]; #- force changeCD callback to be called from main process. -- cgit v1.2.1