aboutsummaryrefslogtreecommitdiffstats
BranchCommit messageAuthorAge
topic/AUI1.92Papoteur2 weeks
master1.63daviddavid4 weeks
topic/newguiImprove messages after success or warning.Papoteur5 years
topic/mga8Update Serbian translation from TxYuri Chornoivan5 years
topic/mga5Finalize the preparation of 0.48Papoteur10 years
topic/yuiCorrection of writing tiny images (mga#18411)Papoteur10 years
user/animtim/designWorknew icon and header for isodumperTimothée Giet10 years
 
TagDownloadAuthorAge
1.91isodumper-1.91.tar  isodumper-1.91.tar.gz  isodumper-1.91.tar.bz2  isodumper-1.91.tar.xz  isodumper-1.91.zip  Papoteur2 weeks
1.90isodumper-1.90.tar  isodumper-1.90.tar.gz  isodumper-1.90.tar.bz2  isodumper-1.90.tar.xz  isodumper-1.90.zip  Papoteur3 weeks
1.63isodumper-1.63.tar  isodumper-1.63.tar.gz  isodumper-1.63.tar.bz2  isodumper-1.63.tar.xz  isodumper-1.63.zip  daviddavid4 weeks
1.62isodumper-1.62.tar  isodumper-1.62.tar.gz  isodumper-1.62.tar.bz2  isodumper-1.62.tar.xz  isodumper-1.62.zip  Papoteur8 weeks
1.61isodumper-1.61.tar  isodumper-1.61.tar.gz  isodumper-1.61.tar.bz2  isodumper-1.61.tar.xz  isodumper-1.61.zip  Papoteur4 months
1.60isodumper-1.60.tar  isodumper-1.60.tar.gz  isodumper-1.60.tar.bz2  isodumper-1.60.tar.xz  isodumper-1.60.zip  Papoteur4 months
1.59isodumper-1.59.tar  isodumper-1.59.tar.gz  isodumper-1.59.tar.bz2  isodumper-1.59.tar.xz  isodumper-1.59.zip  Papoteur4 months
1.58isodumper-1.58.tar  isodumper-1.58.tar.gz  isodumper-1.58.tar.bz2  isodumper-1.58.tar.xz  isodumper-1.58.zip  Papoteur4 months
1.57isodumper-1.57.tar  isodumper-1.57.tar.gz  isodumper-1.57.tar.bz2  isodumper-1.57.tar.xz  isodumper-1.57.zip  Papoteur5 months
1.56isodumper-1.56.tar  isodumper-1.56.tar.gz  isodumper-1.56.tar.bz2  isodumper-1.56.tar.xz  isodumper-1.56.zip  Papoteur19 months
1.55isodumper-1.55.tar  isodumper-1.55.tar.gz  isodumper-1.55.tar.bz2  isodumper-1.55.tar.xz  isodumper-1.55.zip  daviddavid3 years
1.54isodumper-1.54.tar  isodumper-1.54.tar.gz  isodumper-1.54.tar.bz2  isodumper-1.54.tar.xz  isodumper-1.54.zip  Papoteur3 years
1.53isodumper-1.53.tar  isodumper-1.53.tar.gz  isodumper-1.53.tar.bz2  isodumper-1.53.tar.xz  isodumper-1.53.zip  Papoteur3 years
1.52isodumper-1.52.tar  isodumper-1.52.tar.gz  isodumper-1.52.tar.bz2  isodumper-1.52.tar.xz  isodumper-1.52.zip  Papoteur3 years
1.51isodumper-1.51.tar  isodumper-1.51.tar.gz  isodumper-1.51.tar.bz2  isodumper-1.51.tar.xz  isodumper-1.51.zip  Papoteur3 years
1.50isodumper-1.50.tar  isodumper-1.50.tar.gz  isodumper-1.50.tar.bz2  isodumper-1.50.tar.xz  isodumper-1.50.zip  Papoteur3 years
1.49isodumper-1.49.tar  isodumper-1.49.tar.gz  isodumper-1.49.tar.bz2  isodumper-1.49.tar.xz  isodumper-1.49.zip  Papoteur3 years
1.48isodumper-1.48.tar  isodumper-1.48.tar.gz  isodumper-1.48.tar.bz2  isodumper-1.48.tar.xz  isodumper-1.48.zip  Papoteur3 years
1.47isodumper-1.47.tar  isodumper-1.47.tar.gz  isodumper-1.47.tar.bz2  isodumper-1.47.tar.xz  isodumper-1.47.zip  Papoteur3 years
1.46isodumper-1.46.tar  isodumper-1.46.tar.gz  isodumper-1.46.tar.bz2  isodumper-1.46.tar.xz  isodumper-1.46.zip  Papoteur3 years
1.45isodumper-1.45.tar  isodumper-1.45.tar.gz  isodumper-1.45.tar.bz2  isodumper-1.45.tar.xz  isodumper-1.45.zip  Papoteur3 years
1.44isodumper-1.44.tar  isodumper-1.44.tar.gz  isodumper-1.44.tar.bz2  isodumper-1.44.tar.xz  isodumper-1.44.zip  Papoteur3 years
1.43isodumper-1.43.tar  isodumper-1.43.tar.gz  isodumper-1.43.tar.bz2  isodumper-1.43.tar.xz  isodumper-1.43.zip  Papoteur3 years
1.42isodumper-1.42.tar  isodumper-1.42.tar.gz  isodumper-1.42.tar.bz2  isodumper-1.42.tar.xz  isodumper-1.42.zip  Papoteur3 years
1.41isodumper-1.41.tar  isodumper-1.41.tar.gz  isodumper-1.41.tar.bz2  isodumper-1.41.tar.xz  isodumper-1.41.zip  Papoteur5 years
1.40isodumper-1.40.tar  isodumper-1.40.tar.gz  isodumper-1.40.tar.bz2  isodumper-1.40.tar.xz  isodumper-1.40.zip  Papoteur5 years
1.35isodumper-1.35.tar  isodumper-1.35.tar.gz  isodumper-1.35.tar.bz2  isodumper-1.35.tar.xz  isodumper-1.35.zip  Papoteur5 years
1.34isodumper-1.34.tar  isodumper-1.34.tar.gz  isodumper-1.34.tar.bz2  isodumper-1.34.tar.xz  isodumper-1.34.zip  Papoteur5 years
1.33isodumper-1.33.tar  isodumper-1.33.tar.gz  isodumper-1.33.tar.bz2  isodumper-1.33.tar.xz  isodumper-1.33.zip  Papoteur5 years
1.32isodumper-1.32.tar  isodumper-1.32.tar.gz  isodumper-1.32.tar.bz2  isodumper-1.32.tar.xz  isodumper-1.32.zip  Papoteur5 years
1.31isodumper-1.31.tar  isodumper-1.31.tar.gz  isodumper-1.31.tar.bz2  isodumper-1.31.tar.xz  isodumper-1.31.zip  Yuri Chornoivan5 years
1.30isodumper-1.30.tar  isodumper-1.30.tar.gz  isodumper-1.30.tar.bz2  isodumper-1.30.tar.xz  isodumper-1.30.zip  Papoteur5 years
1.29isodumper-1.29.tar  isodumper-1.29.tar.gz  isodumper-1.29.tar.bz2  isodumper-1.29.tar.xz  isodumper-1.29.zip  Papoteur5 years
1.28isodumper-1.28.tar  isodumper-1.28.tar.gz  isodumper-1.28.tar.bz2  isodumper-1.28.tar.xz  isodumper-1.28.zip  Papoteur5 years
1.27isodumper-1.27.tar  isodumper-1.27.tar.gz  isodumper-1.27.tar.bz2  isodumper-1.27.tar.xz  isodumper-1.27.zip  Papoteur5 years
1.26isodumper-1.26.tar  isodumper-1.26.tar.gz  isodumper-1.26.tar.bz2  isodumper-1.26.tar.xz  isodumper-1.26.zip  Papoteur5 years
1.25isodumper-1.25.tar  isodumper-1.25.tar.gz  isodumper-1.25.tar.bz2  isodumper-1.25.tar.xz  isodumper-1.25.zip  Papoteur6 years
1.24isodumper-1.24.tar  isodumper-1.24.tar.gz  isodumper-1.24.tar.bz2  isodumper-1.24.tar.xz  isodumper-1.24.zip  Papoteur6 years
1.23isodumper-1.23.tar  isodumper-1.23.tar.gz  isodumper-1.23.tar.bz2  isodumper-1.23.tar.xz  isodumper-1.23.zip  Papoteur6 years
1.22isodumper-1.22.tar  isodumper-1.22.tar.gz  isodumper-1.22.tar.bz2  isodumper-1.22.tar.xz  isodumper-1.22.zip  Papoteur6 years
1.21isodumper-1.21.tar  isodumper-1.21.tar.gz  isodumper-1.21.tar.bz2  isodumper-1.21.tar.xz  isodumper-1.21.zip  Papoteur6 years
1.20isodumper-1.20.tar  isodumper-1.20.tar.gz  isodumper-1.20.tar.bz2  isodumper-1.20.tar.xz  isodumper-1.20.zip  Papoteur6 years
1.19isodumper-1.19.tar  isodumper-1.19.tar.gz  isodumper-1.19.tar.bz2  isodumper-1.19.tar.xz  isodumper-1.19.zip  Papoteur6 years
1.18isodumper-1.18.tar  isodumper-1.18.tar.gz  isodumper-1.18.tar.bz2  isodumper-1.18.tar.xz  isodumper-1.18.zip  Papoteur6 years
1.17isodumper-1.17.tar  isodumper-1.17.tar.gz  isodumper-1.17.tar.bz2  isodumper-1.17.tar.xz  isodumper-1.17.zip  Papoteur6 years
1.16isodumper-1.16.tar  isodumper-1.16.tar.gz  isodumper-1.16.tar.bz2  isodumper-1.16.tar.xz  isodumper-1.16.zip  Papoteur6 years
1.15isodumper-1.15.tar  isodumper-1.15.tar.gz  isodumper-1.15.tar.bz2  isodumper-1.15.tar.xz  isodumper-1.15.zip  Papoteur7 years
1.14isodumper-1.14.tar  isodumper-1.14.tar.gz  isodumper-1.14.tar.bz2  isodumper-1.14.tar.xz  isodumper-1.14.zip  Papoteur7 years
1.13isodumper-1.13.tar  isodumper-1.13.tar.gz  isodumper-1.13.tar.bz2  isodumper-1.13.tar.xz  isodumper-1.13.zip  Papoteur7 years
1.12isodumper-1.12.tar  isodumper-1.12.tar.gz  isodumper-1.12.tar.bz2  isodumper-1.12.tar.xz  isodumper-1.12.zip  Papoteur7 years
1.11isodumper-1.11.tar  isodumper-1.11.tar.gz  isodumper-1.11.tar.bz2  isodumper-1.11.tar.xz  isodumper-1.11.zip  Papoteur7 years
1.10isodumper-1.10.tar  isodumper-1.10.tar.gz  isodumper-1.10.tar.bz2  isodumper-1.10.tar.xz  isodumper-1.10.zip  Papoteur7 years
1.09isodumper-1.09.tar  isodumper-1.09.tar.gz  isodumper-1.09.tar.bz2  isodumper-1.09.tar.xz  isodumper-1.09.zip  Papoteur7 years
1.08isodumper-1.08.tar  isodumper-1.08.tar.gz  isodumper-1.08.tar.bz2  isodumper-1.08.tar.xz  isodumper-1.08.zip  Papoteur7 years
1.07isodumper-1.07.tar  isodumper-1.07.tar.gz  isodumper-1.07.tar.bz2  isodumper-1.07.tar.xz  isodumper-1.07.zip  Papoteur7 years
1.06isodumper-1.06.tar  isodumper-1.06.tar.gz  isodumper-1.06.tar.bz2  isodumper-1.06.tar.xz  isodumper-1.06.zip  Papoteur7 years
1.05isodumper-1.05.tar  isodumper-1.05.tar.gz  isodumper-1.05.tar.bz2  isodumper-1.05.tar.xz  isodumper-1.05.zip  Papoteur7 years
1.04isodumper-1.04.tar  isodumper-1.04.tar.gz  isodumper-1.04.tar.bz2  isodumper-1.04.tar.xz  isodumper-1.04.zip  Papoteur8 years
1.03isodumper-1.03.tar  isodumper-1.03.tar.gz  isodumper-1.03.tar.bz2  isodumper-1.03.tar.xz  isodumper-1.03.zip  Papoteur8 years
1.02isodumper-1.02.tar  isodumper-1.02.tar.gz  isodumper-1.02.tar.bz2  isodumper-1.02.tar.xz  isodumper-1.02.zip  Papoteur8 years
1.01isodumper-1.01.tar  isodumper-1.01.tar.gz  isodumper-1.01.tar.bz2  isodumper-1.01.tar.xz  isodumper-1.01.zip  Papoteur8 years
1.00isodumper-1.00.tar  isodumper-1.00.tar.gz  isodumper-1.00.tar.bz2  isodumper-1.00.tar.xz  isodumper-1.00.zip  Papoteur8 years
0.59isodumper-0.59.tar  isodumper-0.59.tar.gz  isodumper-0.59.tar.bz2  isodumper-0.59.tar.xz  isodumper-0.59.zip  Yuri Chornoivan9 years
0.49isodumper-0.49.tar  isodumper-0.49.tar.gz  isodumper-0.49.tar.bz2  isodumper-0.49.tar.xz  isodumper-0.49.zip  Papoteur9 years
0.58isodumper-0.58.tar  isodumper-0.58.tar.gz  isodumper-0.58.tar.bz2  isodumper-0.58.tar.xz  isodumper-0.58.zip  Papoteur9 years
0.57isodumper-0.57.tar  isodumper-0.57.tar.gz  isodumper-0.57.tar.bz2  isodumper-0.57.tar.xz  isodumper-0.57.zip  Papoteur9 years
0.56isodumper-0.56.tar  isodumper-0.56.tar.gz  isodumper-0.56.tar.bz2  isodumper-0.56.tar.xz  isodumper-0.56.zip  Papoteur9 years
0.55isodumper-0.55.tar  isodumper-0.55.tar.gz  isodumper-0.55.tar.bz2  isodumper-0.55.tar.xz  isodumper-0.55.zip  Papoteur9 years
0.54isodumper-0.54.tar  isodumper-0.54.tar.gz  isodumper-0.54.tar.bz2  isodumper-0.54.tar.xz  isodumper-0.54.zip  Papoteur10 years
0.53isodumper-0.53.tar  isodumper-0.53.tar.gz  isodumper-0.53.tar.bz2  isodumper-0.53.tar.xz  isodumper-0.53.zip  Papoteur10 years
0.48isodumper-0.48.tar  isodumper-0.48.tar.gz  isodumper-0.48.tar.bz2  isodumper-0.48.tar.xz  isodumper-0.48.zip  Papoteur10 years
0.52isodumper-0.52.tar  isodumper-0.52.tar.gz  isodumper-0.52.tar.bz2  isodumper-0.52.tar.xz  isodumper-0.52.zip  Papoteur10 years
0.47isodumper-0.47.tar  isodumper-0.47.tar.gz  isodumper-0.47.tar.bz2  isodumper-0.47.tar.xz  isodumper-0.47.zip  Papoteur10 years
0.51isodumper-0.51.tar  isodumper-0.51.tar.gz  isodumper-0.51.tar.bz2  isodumper-0.51.tar.xz  isodumper-0.51.zip  Papoteur10 years
0.50isodumper-0.50.tar  isodumper-0.50.tar.gz  isodumper-0.50.tar.bz2  isodumper-0.50.tar.xz  isodumper-0.50.zip  Papoteur10 years
0.45isodumper-0.45.tar  isodumper-0.45.tar.gz  isodumper-0.45.tar.bz2  isodumper-0.45.tar.xz  isodumper-0.45.zip  Papoteur10 years
0.44isodumper-0.44.tar  isodumper-0.44.tar.gz  isodumper-0.44.tar.bz2  isodumper-0.44.tar.xz  isodumper-0.44.zip  SARL ENR 6810 years
0.43isodumper-0.43.tar  isodumper-0.43.tar.gz  isodumper-0.43.tar.bz2  isodumper-0.43.tar.xz  isodumper-0.43.zip  SARL ENR 6811 years
0.42isodumper-0.42.tar  isodumper-0.42.tar.gz  isodumper-0.42.tar.bz2  isodumper-0.42.tar.xz  isodumper-0.42.zip  daviddavid11 years
0.41isodumper-0.41.tar  isodumper-0.41.tar.gz  isodumper-0.41.tar.bz2  isodumper-0.41.tar.xz  isodumper-0.41.zip  daviddavid11 years
0.40isodumper-0.40.tar  isodumper-0.40.tar.gz  isodumper-0.40.tar.bz2  isodumper-0.40.tar.xz  isodumper-0.40.zip  daviddavid11 years
0.32isodumper-0.32.tar  isodumper-0.32.tar.gz  isodumper-0.32.tar.bz2  isodumper-0.32.tar.xz  isodumper-0.32.zip  SARL ENR-6812 years
0.25isodumper-0.25.tar  isodumper-0.25.tar.gz  isodumper-0.25.tar.bz2  isodumper-0.25.tar.xz  isodumper-0.25.zip  SARL ENR-6812 years
0.31isodumper-0.31.tar  isodumper-0.31.tar.gz  isodumper-0.31.tar.bz2  isodumper-0.31.tar.xz  isodumper-0.31.zip  SARL ENR-6812 years
0.30isodumper-0.30.tar  isodumper-0.30.tar.gz  isodumper-0.30.tar.bz2  isodumper-0.30.tar.xz  isodumper-0.30.zip  SARL ENR-6812 years
0.23isodumper-0.23.tar  isodumper-0.23.tar.gz  isodumper-0.23.tar.bz2  isodumper-0.23.tar.xz  isodumper-0.23.zip  SARL ENR-6812 years
0.22isodumper-0.22.tar  isodumper-0.22.tar.gz  isodumper-0.22.tar.bz2  isodumper-0.22.tar.xz  isodumper-0.22.zip  SARL ENR-6812 years
0.21isodumper-0.21.tar  isodumper-0.21.tar.gz  isodumper-0.21.tar.bz2  isodumper-0.21.tar.xz  isodumper-0.21.zip  SARL ENR-6812 years
0.20isodumper-0.20.tar  isodumper-0.20.tar.gz  isodumper-0.20.tar.bz2  isodumper-0.20.tar.xz  isodumper-0.20.zip  SARL ENR-6812 years
0.13isodumper-0.13.tar  isodumper-0.13.tar.gz  isodumper-0.13.tar.bz2  isodumper-0.13.tar.xz  isodumper-0.13.zip  SARL ENR-6812 years
0.12isodumper-0.12.tar  isodumper-0.12.tar.gz  isodumper-0.12.tar.bz2  isodumper-0.12.tar.xz  isodumper-0.12.zip  SARL ENR-6812 years
0.11isodumper-0.11.tar  isodumper-0.11.tar.gz  isodumper-0.11.tar.bz2  isodumper-0.11.tar.xz  isodumper-0.11.zip  SARL ENR-6812 years
0.11_beta1isodumper-0.11_beta1.tar  isodumper-0.11_beta1.tar.gz  isodumper-0.11_beta1.tar.bz2  isodumper-0.11_beta1.tar.xz  isodumper-0.11_beta1.zip  SARL ENR-6813 years
0.10isodumper-0.10.tar  isodumper-0.10.tar.gz  isodumper-0.10.tar.bz2  isodumper-0.10.tar.xz  isodumper-0.10.zip  SARL ENR-6813 years
0.1isodumper-0.1.tar  isodumper-0.1.tar.gz  isodumper-0.1.tar.bz2  isodumper-0.1.tar.xz  isodumper-0.1.zip  SARL ENR-6813 years
'#n1766'>1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
package install_any; # $Id$

use strict;

use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK $boot_medium $current_medium $asked_medium @advertising_images);

@ISA = qw(Exporter);
%EXPORT_TAGS = (
    all => [ qw(getNextStep spawnShell addToBeDone) ],
);
@EXPORT_OK = map { @$_ } values %EXPORT_TAGS;

#-######################################################################################
#- misc imports
#-######################################################################################
use MDK::Common::System;
use common;
use run_program;
use fs::type;
use fs::format;
use partition_table;
use devices;
use fsedit;
use modules;
use detect_devices;
use lang;
use any;
use log;

#- boot medium (the first medium to take into account).
$boot_medium = 1;
$current_medium = $boot_medium;
$asked_medium = $boot_medium;

our $global_ftp_prefix;

sub drakx_version() { 
    $::move ? sprintf "DrakX-move v%s", cat_('/usr/bin/stage2/move.pm') =~ /move\.pm,v (\S+ \S+ \S+)/
	    : sprintf "DrakX v%s built %s", $::testing ? ('TEST', scalar gmtime()) : (split('/', cat__(getFile("install/stage2/VERSION"))))[2,3];
}

#-######################################################################################
#- Media change variables&functions
#-######################################################################################
my $postinstall_rpms = '';
my $cdrom;
my %iso_images;

sub mountCdrom {
    my ($mountpoint, $o_cdrom) = @_;
    $o_cdrom = $cdrom if !defined $o_cdrom;
    eval { fs::mount($o_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.
    $_[0] > 1 and method_allows_medium_change($::o->{method}) and setup_postinstall_rpms($::prefix, $::o->{packages});

    $asked_medium eq $_[0] or log::l("selecting new medium '$_[0]'");
    $asked_medium = $_[0];
}
sub changeMedium($$) {
    my ($method, $medium_name) = @_;
    log::l("change to medium $medium_name for method $method (refused by default)");
    0;
}
sub relGetFile($) {
    local $_ = $_[0];
    if (my ($arch) = m|\.([^\.]*)\.rpm$|) {
	$_ = "$::o->{packages}{mediums}{$asked_medium}{rpmsdir}/$_";
	s/%{ARCH}/$arch/g;
	s,^/+,,g;
    }
    $_;
}
sub askChangeMedium($$) {
    my ($method, $medium_name) = @_;
    my $allow;
    do {
	local $::o->{method} = $method = 'cdrom' if $medium_name =~ /^\d+s$/; #- Suppl CD
	eval { $allow = changeMedium($method, $medium_name) };
    } while $@; #- really it is not allowed to die in changeMedium!!! or install will core with rpmlib!!!
    log::l($allow ? "accepting medium $medium_name" : "refusing medium $medium_name");
    $allow;
}

sub method_is_from_ISO_images($) {
    my ($method) = @_;
    $method eq "disk-iso" || $method eq "nfs-iso";
}
sub method_allows_medium_change($) {
    my ($method) = @_;
    $method eq "cdrom" || method_is_from_ISO_images($method);
}

sub look_for_ISO_images() {
    $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);
	#- the ISO volume names must end in -Disc\d+
	my ($cd_set) = $vol_id =~ /^(.*)-(?:disc\d*|extra)$/i;
	$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));

    my $iso_dir = $ENV{ISOPATH};
    #- strip old root and remove iso file from path if present
    $iso_dir =~ s!^/sysroot!!; $iso_dir =~ s![^/]*\.iso$!!;

    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 find_ISO_image_labelled($) {
    %iso_images or look_for_ISO_images() or return;
    my ($iso_label) = @_;
    find { $_->{app_id} eq $iso_label && $_->{cd_set} eq $iso_images{cd_set} } @{$iso_images{media}};
}

sub changeIso($) {
    my ($iso_label) = @_;
    my $iso_info = find_ISO_image_labelled($iso_label) 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.
    $current_medium eq $asked_medium and log::l("errorOpeningFile $file"), return; #- nothing to do in such case.
    $::o->{packages}{mediums}{$asked_medium}{selected} or return; #- not selected means no need to worry about.
    my $current_method = $::o->{packages}{mediums}{$asked_medium}{method} || $::o->{method};

    my $max = 32; #- always refuse after $max tries.
    if ($current_method eq "cdrom") {
	cat_("/proc/mounts") =~ m,(/dev/\S+)\s+(/mnt/cdrom|/tmp/image),
	    and ($cdrom, my $mountpoint) = ($1, $2);
	return unless $cdrom;
	ejectCdrom($cdrom, $mountpoint);
	while ($max > 0 && askChangeMedium($current_method, $asked_medium)) {
	    $current_medium = $asked_medium;
	    mountCdrom("/tmp/image");
	    my $getFile = getFile($file); 
	    $getFile && @advertising_images and copy_advertising($::o);
	    $getFile and return $getFile;
	    $current_medium = 'unknown'; #- do not know what CD is inserted now.
	    ejectCdrom($cdrom, $mountpoint);
	    --$max;
	}
    } else {
	while ($max > 0 && askChangeMedium($current_method, $asked_medium)) {
	    $current_medium = $asked_medium;
	    my $getFile = getFile($file); $getFile and return $getFile;
	    $current_medium = 'unknown'; #- do not know what CD image has been copied.
	    --$max;
	}
    }

    #- Do not 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;

    #- on cancel, we can expect the current medium to be undefined too,
    #- this enables remounting if selecting a package back.
    $current_medium = 'unknown';

    return;
}
sub getFile {
    my ($f, $o_method, $o_altroot) = @_;
    my $current_method = ($asked_medium ? $::o->{packages}{mediums}{$asked_medium}{method} : '') || $::o->{method};
    log::l("getFile $f:$o_method ($asked_medium:$current_method)");
    my $rel = relGetFile($f);
    do {
	if ($f =~ m|^http://|) {
	    require http;
	    http::getFile($f);
	} elsif ($o_method =~ /crypto|update/i) {
	    require crypto;
	    crypto::getFile($f);
	} elsif ($current_method eq "ftp") {
	    require ftp;
	    ftp::getFile($rel, @{ $::o->{packages}{mediums}{$asked_medium}{ftp_prefix} || $global_ftp_prefix || [] });
	} elsif ($current_method eq "http") {
	    require http;
	    http::getFile(($ENV{URLPREFIX} || $o_altroot) . "/$rel");
	} else {
	    #- 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";
	    $o_altroot ||= '/tmp/image';
	    $f2 = "$o_altroot/$rel" if $rel !~ m,^/, && (!$postinstall_rpms || !-e $f2);
	    #- $f2 = "/$rel" if !$::o->{packages}{mediums}{$asked_medium}{rpmsdir} && !-e $f2; #- not a relative path, should not be necessary with new media layout
	    my $F; open($F, $f2) ? $F : do { $f2 !~ /XXX/ and log::l("Can not open $f2: $!"); undef };
	}
    } || errorOpeningFile($f);
}
sub getAndSaveFile {
    my ($file, $local) = @_ == 1 ? ("install/stage2/live$_[0]", $_[0]) : @_;
    local $/ = \ (16 * 1024);
    my $f = ref($file) ? $file : getFile($file) or return;
    open(my $F, ">$local") or log::l("getAndSaveFile(opening $local): $!"), return;
    local $_;
    while (<$f>) { syswrite($F, $_) or die("getAndSaveFile($local): $!") }
    1;
}


#-######################################################################################
#- Post installation RPMS from cdrom only, functions
#-######################################################################################
sub setup_postinstall_rpms($$) {
    my ($prefix, $packages) = @_;

    $postinstall_rpms and return;
    $postinstall_rpms = "$prefix/usr/postinstall-rpm";

    require pkgs;

    log::l("postinstall rpms directory set to $postinstall_rpms");
    clean_postinstall_rpms(); #- make sure in case of previous upgrade problem.
    mkdir_p($postinstall_rpms);

    my %toCopy;
    #- compute closure of package that may be copied, use INSTALL category
    #- in rpmsrate.
    $packages->{rpmdb} ||= pkgs::rpmDbOpen();
    foreach (@{$packages->{needToCopy} || []}) {
	my $p = pkgs::packageByName($packages, $_) or next;
	pkgs::selectPackage($packages, $p, 0, \%toCopy);
    }
    delete $packages->{rpmdb};

    my @toCopy = grep { $_ && !$_->flag_selected } map { $packages->{depslist}[$_] } keys %toCopy;

    #- extract headers of package, this is necessary for getting
    #- the complete filename of each package.
    #- copy the package files in the postinstall RPMS directory.
    #- last arg is default medium '' known as the CD#1.
    #- cp_af does not handle correctly a missing file.
    eval { cp_af((grep { -r $_ } map { "/tmp/image/" . relGetFile($_->filename) } @toCopy), $postinstall_rpms) };

    log::l("copying Auto Install Floppy");
    getAndSaveInstallFloppies($::o, $postinstall_rpms, 'auto_install');
}

sub clean_postinstall_rpms() {
    $postinstall_rpms and -d $postinstall_rpms and rm_rf($postinstall_rpms);
}


#-######################################################################################
#- Functions
#-######################################################################################
sub getNextStep {
    my ($o) = @_;
    find { !$o->{steps}{$_}{done} && $o->{steps}{$_}{reachable} } @{$o->{orderedSteps}};
}

sub dont_run_directly_stage2() {
    readlink("/usr/bin/runinstall2") eq "runinstall2.sh";
}

sub spawnShell() {
    return if $::o->{localInstall} || $::testing || dont_run_directly_stage2();

    if (my $shellpid = fork()) {
        output('/var/run/drakx_shell.pid', $shellpid);
        return;
    }

    $ENV{DISPLAY} ||= ":0"; #- why not :pp

    local *F;
    sysopen F, "/dev/tty2", 2 or log::l("cannot open /dev/tty2 -- no shell will be provided: $!"), goto cant_spawn;

    open STDIN, "<&F" or goto cant_spawn;
    open STDOUT, ">&F" or goto cant_spawn;
    open STDERR, ">&F" or goto cant_spawn;
    close F;

    print drakx_version(), "\n";

    c::setsid();

    ioctl(STDIN, c::TIOCSCTTY(), 0) or warn "could not set new controlling tty: $!";

    my @args; -e '/etc/bashrc' and @args = qw(--rcfile /etc/bashrc);
    foreach (qw(/bin/bash /usr/bin/busybox /bin/sh)) {
        -x $_ or next;
        my $program_name = /busybox/ ? "/bin/sh" : $_;  #- since perl_checker is too dumb
        exec { $_ } $program_name, @args or log::l("exec of $_ failed: $!");
    }

    log::l("cannot open any shell");
cant_spawn:
    c::_exit(1);
}

sub getAvailableSpace {
    my ($o) = @_;

    #- make sure of this place to be available for installation, this could help a lot.
    #- currently doing a very small install use 36Mb of postinstall-rpm, but installing
    #- these packages may eat up to 90Mb (of course not all the server may be installed!).
    #- 65mb may be a good choice to avoid almost all problem of insuficient space left...
    my $minAvailableSize = 65 * sqr(1024);

    my $n = !$::testing && getAvailableSpace_mounted($o->{prefix}) || 
            getAvailableSpace_raw($o->{fstab}) * 512 / 1.07;
    $n - max(0.1 * $n, $minAvailableSize);
}

sub getAvailableSpace_mounted {
    my ($prefix) = @_;
    my $dir = -d "$prefix/usr" ? "$prefix/usr" : $prefix;
    my (undef, $free) = MDK::Common::System::df($dir) or return;
    log::l("getAvailableSpace_mounted $free KB");
    $free * 1024 || 1;
}
sub getAvailableSpace_raw {
    my ($fstab) = @_;

    do { $_->{mntpoint} eq '/usr' and return $_->{size} } foreach @$fstab;
    do { $_->{mntpoint} eq '/'    and return $_->{size} } foreach @$fstab;

    if ($::testing) {
	my $nb = 450;
	log::l("taking ${nb}MB for testing");
	return $nb << 11;
    }
    die "missing root partition";
}

sub preConfigureTimezone {
    my ($o) = @_;
    require timezone;
   
    #- can not be done in install cuz' timeconfig %post creates funny things
    add2hash($o->{timezone}, timezone::read()) if $o->{isUpgrade};

    $o->{timezone}{timezone} ||= timezone::bestTimezone($o->{locale}{country});

    my $utc = every { !isFat_or_NTFS($_) } @{$o->{fstab}};
    my $ntp = timezone::ntp_server();
    add2hash_($o->{timezone}, { UTC => $utc, ntp => $ntp });
}

sub ask_if_suppl_media {
    my ($o) = @_;
    our $suppl_already_asked;
    my $msg = $suppl_already_asked
      ? N("Do you have further supplementary media?")
      : formatAlaTeX(
#-PO: keep the double empty lines between sections, this is formatted a la LaTeX
	    N("The following media have been found and will be used during install: %s.


Do you have a supplementary installation media to configure?",
	    join ", ", sort uniq(map { $_->{descr} } values %{$o->{packages}{mediums}})));
    $o->ask_from(
	'', $msg,
	[ {
	    val => \my $suppl,
	    list => [ N_("None"), N_("CD-ROM"), N_("Network (http)"), N_("Network (ftp)") ],
	    type => 'list',
	    format => \&translate,
	} ],
    );
    $suppl_already_asked = 1;
    return $suppl;
}

#- if the supplementary media is networked, but not the main one, network
#- support must be installed and network started.
sub prep_net_suppl_media {
    return if our $net_suppl_media_configured;
    $net_suppl_media_configured = 1;
    my ($o) = @_;
    #- install basesystem now
    $::o->do_pkgs->ensure_is_installed('basesystem', undef, 1);
    #- from install_steps_interactive:
    local $::expert = $::expert;
    require network::netconnect;
    network::netconnect::main($o->{netcnx} ||= {}, $o, $o->{modules_conf}, $o->{netc}, $o->{mouse}, $o->{intf}, 0, 1);
    require install_interactive;
    install_interactive::upNetwork($o);
    sleep(3);
}

sub selectSupplMedia {
    my ($o, $suppl_method) = @_;
    #- ask whether there are supplementary media
    my $prev_asked_medium = $asked_medium;
    if ($suppl_method && (my $suppl = ask_if_suppl_media($o)) ne 'None') {
	#- translate to method name
	$suppl_method = {
	    'CD-ROM' => 'cdrom',
	    'Network (http)' => 'http',
	    'Network (ftp)' => 'ftp',
	}->{$suppl};
	#- by convention, the media names for suppl. CDs match /^\d+s$/
	my $medium_name = $suppl_method eq 'cdrom'
	    ? (max(map { $_->{medium} =~ /^(\d+)s$/ ? $1 : 0 } values %{$o->{packages}{mediums}}) + 1) . "s"
	    : int(keys %{$o->{packages}{mediums}}) + 1;
	#- configure network if needed
	prep_net_suppl_media($o) if !scalar keys %{$o->{intf}} && $suppl_method !~ /^(?:cdrom|disk)/;
	local $::isWizard = 0;
	my $main_method = $o->{method};
	local $o->{method} = $suppl_method;
	if ($suppl_method eq 'cdrom') {
	    (my $cdromdev) = detect_devices::cdroms();
	    $o->ask_warn('', N("No device found")), return 'error' if !$cdromdev;
	    $cdrom = $cdromdev->{device};
	    $cdrom =~ m,^/, or $cdrom = "/dev/$cdrom";
	    devices::make($cdrom);
	    ejectCdrom($cdrom);
	    if ($o->ask_okcancel('', N("Insert the CD"), 1)) {
		#- mount suppl CD in /mnt/cdrom to avoid umounting /tmp/image
		mountCdrom("/mnt/cdrom", $cdrom);
		if ($@) {
		    log::l($@);
		    $o->ask_warn('', N("Unable to mount CD-ROM"));
		    return 'error';
		}
		useMedium($medium_name);

		#- probe for an hdlists file and then look for all hdlists listed herein
		eval { pkgs::psUsingHdlists($o, $suppl_method, "/mnt/cdrom", $o->{packages}, $medium_name) };
		log::l("psUsingHdlists failed: $@") if $@;

		#- copy latest compssUsers.pl and rpmsrate somewhere locally
		getAndSaveFile("/mnt/cdrom/media/media_info/compssUsers.pl", "/tmp/compssUsers.pl");
		getAndSaveFile("/mnt/cdrom/media/media_info/rpmsrate", "/tmp/rpmsrate");

		#- umount supplementary CD. Will re-ask for it later
		getFile("XXX"); #- close still opened filehandles
		log::l("Umounting suppl. CD, back to medium 1");
		eval { fs::umount("/mnt/cdrom") };
		#- re-mount CD 1 if this was a cdrom install
		if ($main_method eq 'cdrom') {
		    openCdromTray($cdrom);
		    $o->ask_warn('', N("Insert the CD 1 again"));
		    mountCdrom("/tmp/image", $cdrom);
		    log::l($@) if $@;
		    $asked_medium = 1;
		}
	    }
	} else {
	    my $url;
	    local $global_ftp_prefix;
	    if ($suppl_method eq 'ftp') { #- mirrors are ftp only (currently)
		$url = $o->askSupplMirror(N("URL of the mirror?")) or return 'error';
		$url =~ m!^ftp://(?:(.*?)(?::(.*?))?\@)?([^/]+)/(.*)!
		    and $global_ftp_prefix = [ $3, $4, $1, $2 ]; #- for getFile
	    } else {
		$url = $o->ask_from_entry('', N("URL of the mirror?")) or return 'error';
		$url =~ s!/+\z!!;
	    }
	    useMedium($medium_name);
	    require http if $suppl_method eq 'http';
	    require ftp if $suppl_method eq 'ftp';
	    #- first, try to find an hdlists file
	    eval { pkgs::psUsingHdlists($o, $suppl_method, $url, $o->{packages}, $medium_name, \&setup_suppl_medium) };
	    if ($@) {
		log::l("psUsingHdlists failed: $@");
	    } else {
		#- copy latest compssUsers.pl and rpmsrate somewhere locally
		if ($suppl_method eq 'ftp') {
		    getAndSaveFile("media/media_info/compssUsers.pl", "/tmp/compssUsers.pl");
		    getAndSaveFile("media/media_info/rpmsrate", "/tmp/rpmsrate");
		} else {
		    getAndSaveFile("$url/media/media_info/compssUsers.pl", "/tmp/compssUsers.pl");
		    getAndSaveFile("$url/media/media_info/rpmsrate", "/tmp/rpmsrate");
		}
		useMedium($prev_asked_medium); #- back to main medium
		return $suppl_method;
	    }
	    #- then probe for an hdlist.cz
	    my $f = eval {
		if ($suppl_method eq 'http') {
		    http::getFile("$url/media_info/hdlist.cz");
		} elsif ($suppl_method eq 'ftp') {
		    getFile("media_info/hdlist.cz");
		} else { undef }
	    };
	    if (!defined $f) {
		log::l($@) if $@;
		#- no hdlist found
		$o->ask_warn('', N("Can't find a package list file on this mirror. Make sure the location is correct."));
		useMedium($prev_asked_medium);
		return 'error';
	    }
	    my $supplmedium = pkgs::psUsingHdlist(
		$suppl_method,
		$o->{packages},
		"hdlist$medium_name.cz", #- hdlist
		$medium_name,
		'', #- rpmsdir
		"Supplementary media $medium_name", #- description
		1, # selected
		$f,
	    );
	    close $f;
	    if ($supplmedium) {
		log::l("read suppl hdlist (via $suppl_method)");
		setup_suppl_medium($supplmedium, $url, $suppl_method);
	    } else {
		log::l("no suppl hdlist");
		$suppl_method = 'error';
	    }
	}
    } else {
	$suppl_method = '';
    }
    useMedium($prev_asked_medium); #- back to main medium
    return $suppl_method;
}

sub setup_suppl_medium {
    my ($supplmedium, $url, $suppl_method) = @_;
    $supplmedium->{prefix} = $url; #- for install_urpmi
    if ($suppl_method eq 'ftp') {
	$url =~ m!^ftp://(?:(.*?)(?::(.*?))?\@)?([^/]+)/(.*)!
	    and $supplmedium->{ftp_prefix} = [ $3, $4, $1, $2 ]; #- for getFile
    }
    $supplmedium->{selected} = 1;
    $supplmedium->{method} = $suppl_method;
    $supplmedium->{with_hdlist} = 'media_info/hdlist.cz'; #- for install_urpmi
    $supplmedium->{issuppl} = 1; #- remember it's a suppl medium
}

sub _media_rank {
    my ($x) = @_;
    my ($y, $s) = $x =~ /(\d+)(s?)\)\.cz/;
    $s and $y += 100;
    $y;
}

sub load_rate_files {
    my ($o) = @_;
    #- must be done after getProvides
    #- if there is a supplementary media, the rpmsrate/compssUsers are overridable
    pkgs::read_rpmsrate(
	$o->{packages},
	$o->{rpmsrate_flags_chosen},
	getFile(-e "/tmp/rpmsrate" ? "/tmp/rpmsrate" : "media/media_info/rpmsrate")
    );
    ($o->{compssUsers}, $o->{gtk_display_compssUsers}) = pkgs::readCompssUsers(
	-e '/tmp/compssUsers.pl' ? '/tmp/compssUsers.pl' : 'media/media_info/compssUsers.pl'
    );
    defined $o->{compssUsers} or die "Can't read compssUsers.pl file, aborting installation\n";
}

sub setPackages {
    my ($o, $rebuild_needed) = @_;

    require pkgs;
    if (!$o->{packages} || is_empty_array_ref($o->{packages}{depslist})) {
	($o->{packages}, my $suppl_method, my $copy_rpms_on_disk) = pkgs::psUsingHdlists($o, $o->{method});

	1 while $suppl_method = $o->selectSupplMedia($suppl_method);

	#- open rpm db according to right mode needed.
	$o->{packages}{rpmdb} ||= pkgs::rpmDbOpen($rebuild_needed);

	#- always try to select basic kernel (else on upgrade, kernel will never be updated provided a kernel is already
	#- installed and provides what is necessary).
	pkgs::selectPackage($o->{packages},
			    pkgs::bestKernelPackage($o->{packages}) || die("missing kernel package"), 1);

	pkgs::selectPackage($o->{packages},
			    pkgs::packageByName($o->{packages}, 'basesystem') || die("missing basesystem package"), 1);

	my $rpmsrate_flags_was_chosen = $o->{rpmsrate_flags_chosen};

	put_in_hash($o->{rpmsrate_flags_chosen} ||= {}, rpmsrate_always_flags($o)); #- must be done before pkgs::read_rpmsrate()
	load_rate_files($o);

	copy_rpms_on_disk($o) if $copy_rpms_on_disk;

	set_rpmsrate_default_category_flags($o, $rpmsrate_flags_was_chosen);

	push @{$o->{default_packages}}, default_packages($o);
	select_default_packages($o);
    } else {
	#- this has to be done to make sure necessary files for urpmi are
	#- present.
	pkgs::psUpdateHdlistsDeps($o->{packages});

	#- open rpm db (always without rebuilding db, it should be false at this point).
	$o->{packages}{rpmdb} ||= pkgs::rpmDbOpen();
    }
}

sub count_files {
    my ($dir) = @_;
    -d $dir or return 0;
    opendir my $dh, $dir or return 0;
    my @list = grep { !/^\.\.?$/ } readdir $dh;
    closedir $dh;
    my $c = 0;
    foreach my $n (@list) {
	my $p = "$dir/$n";
	if (-d $p) { $c += count_files($p) } else { ++$c }
    }
    $c;
}

sub cp_with_progress {
    my $wait_message = shift;
    my $current = shift;
    my $total = shift;
    my $dest = pop @_;
    @_ or return;
    @_ == 1 || -d $dest or die "cp: copying multiple files, but last argument ($dest) is not a directory\n";

    foreach my $src (@_) {
	my $dest = $dest;
	-d $dest and $dest .= '/' . basename($src);

	unlink $dest;

	if (-l $src) {
	    unless (symlink(readlink($src) || die("readlink failed: $!"), $dest)) {
		warn "symlink: can't create symlink $dest: $!\n";
	    }
	} elsif (-d $src) {
	    -d $dest or mkdir $dest, (stat($src))[2] or die "mkdir: can't create directory $dest: $!\n";
	    cp_with_progress($wait_message, $current, $total, glob_($src), $dest);
	} else {
	    open(my $F, $src) or die "can't open $src for reading: $!\n";
	    open(my $G, ">", $dest) or die "can't cp to file $dest: $!\n";
	    local $/ = \4096;
	    local $_; while (<$F>) { print $G $_ }
	    chmod((stat($src))[2], $dest);
	    $wait_message->('', ++$current, $total);
	}
    }
    1;
}

sub copy_rpms_on_disk {
    my ($o) = @_;
    mkdir "$o->{prefix}/$_", 0755 foreach qw(var var/ftp var/ftp/pub var/ftp/pub/Mandrakelinux var/ftp/pub/Mandrakelinux/media);
    local *changeMedium = sub {
	my ($method, $medium) = @_;
	my $name = pkgs::mediumDescr($o->{packages}, $medium);
	if (method_allows_medium_change($method)) {
	    my $r;
	    if ($method =~ /-iso$/) {
		$r = install_any::changeIso($name);
	    } else {
		cat_("/proc/mounts") =~ m,(/dev/\S+)\s+(/mnt/cdrom|/tmp/image),
		    and ($cdrom, my $mountpoint) = ($1, $2);
		ejectCdrom($cdrom, $mountpoint);
		$r = $o->ask_okcancel('', N("Change your Cd-Rom!
Please insert the Cd-Rom labelled \"%s\" in your drive and press Ok when done.", $name), 1);
	    }
	    return $r;
	} else {
	    return 1;
	}
    };
    foreach my $k (pkgs::allMediums($o->{packages})) {