summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perl-install/c/stuff.xs.pl28
-rw-r--r--perl-install/install_any.pm63
-rw-r--r--perl-install/install_steps_gtk.pm25
-rw-r--r--perl-install/install_steps_interactive.pm21
-rw-r--r--perl-install/pkgs.pm4
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 <linux/cdrom.h>
#include <linux/loop.h>
#include <linux/blkpg.h>
+#include <linux/iso_fs.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -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.