diff options
Diffstat (limited to 'perl-install/install/any.pm')
| -rw-r--r-- | perl-install/install/any.pm | 791 | 
1 files changed, 535 insertions, 256 deletions
| diff --git a/perl-install/install/any.pm b/perl-install/install/any.pm index 956f1adff..4ea2ce45d 100644 --- a/perl-install/install/any.pm +++ b/perl-install/install/any.pm @@ -1,4 +1,4 @@ -package install::any; # $Id$ +package install::any;  use strict; @@ -8,6 +8,7 @@ our @EXPORT_OK = qw(addToBeDone);  #-######################################################################################  #- misc imports  #-###################################################################################### +use feature 'state';  use common;  use run_program;  use fs::type; @@ -22,17 +23,29 @@ use lang;  use any;  use log; +=head1 SYNOPSYS + +Misc installer specific functions + +=head1 Functions + +=over + +=cut +  our @advertising_images; +=item drakx_version($o) + +Returns DrakX version as stored in C<install/stage2/VERSION> file + +=cut +  sub drakx_version {       my ($o) = @_; -    if ($::move) { -	sprintf "DrakX-move v%s", cat_('/usr/bin/stage2/move.pm') =~ /move\.pm,v (\S+ \S+ \S+)/; -    } else {  	my $version = cat__(getFile_($o->{stage2_phys_medium}, "install/stage2/VERSION"));  	sprintf "DrakX v%s", chomp_($version); -    }  }  #-###################################################################################### @@ -42,29 +55,25 @@ sub dont_run_directly_stage2() {      readlink("/usr/bin/runinstall2") eq "runinstall2.sh";  } +=item is_network_install($o) + +Is it a network install? + +=cut +  sub is_network_install {      my ($o) = @_;      member($o->{method}, qw(ftp http nfs));  } +=item spawnShell() -sub start_i810fb() { -    my ($vga) = cat_('/proc/cmdline') =~ /vga=(\S+)/; -    return if !$vga || listlength(cat_('/proc/fb')); +Starts a shell on tty2 -    my %vga_to_xres = (0x311 => '640', 0x314 => '800', 0x317 => '1024'); -    my $xres = $vga_to_xres{$vga} || '800'; - -    log::l("trying to load i810fb module with xres <$xres> (vga was <$vga>)"); -    eval { modules::load('intel-agp') }; -    eval { -	my $opt = "xres=$xres hsync1=32 hsync2=48 vsync1=50 vsync2=70 vram=2 bpp=16 accel=1 mtrr=1"; #- this sucking i810fb does not accept floating point numbers in hsync! -	modules::load_with_options([ 'i810fb' ], { i810fb => $opt });  -    }; -} +=cut  sub spawnShell() { -    return if $::local_install || $::testing || dont_run_directly_stage2(); +    return if $::local_install || $::testing;      my $shellpid_file = '/var/run/drakx_shell.pid';      return if -e $shellpid_file && -d '/proc/' . chomp_(cat_($shellpid_file)); @@ -74,7 +83,8 @@ sub spawnShell() {          return;      } -    $ENV{DISPLAY} ||= ":0"; #- why not :pp +    #- why not :pp +    $ENV{DISPLAY} ||= ":0" if $::o->{interactive} eq "gtk";      local *F;      sysopen F, "/dev/tty2", 2 or log::l("cannot open /dev/tty2 -- no shell will be provided: $!"), goto cant_spawn; @@ -102,46 +112,22 @@ 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); +=item getAvailableSpace($o) -    my $n = !$::testing && getAvailableSpace_mounted($::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) = @_; +Returns available space -    do { $_->{mntpoint} eq '/usr' and return $_->{size} } foreach @$fstab; -    do { $_->{mntpoint} eq '/'    and return $_->{size} } foreach @$fstab; +=cut -    if ($::testing) { -	my $nb = 450; -	log::l("taking ${nb}MB for testing"); -	return $nb << 11; -    } -    die "missing root partition"; +sub getAvailableSpace { +    my ($o) = @_; +    fs::any::getAvailableSpace($o->{fstab});  }  sub preConfigureTimezone {      my ($o) = @_;      require timezone; -    #- can not be done in install cuz' timeconfig %post creates funny things +    #- cannot 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}); @@ -149,8 +135,29 @@ sub preConfigureTimezone {      my $utc = every { !isFat_or_NTFS($_) } @{$o->{fstab}};      my $ntp = timezone::ntp_server();      add2hash_($o->{timezone}, { UTC => $utc, ntp => $ntp }); + +    #- Make the timezone available to urpm::mirrors. +    write_installer_timezone($o->{timezone}); +} + +=item write_installer_timezone($timezone) + +Writes a minimal version of $timezone to /etc/sysconfig/clock for use by urpm::mirrors + +=cut + +sub write_installer_timezone { +    my ($timezone) = @_; +    mkdir_p('/etc/sysconfig/'); +    setVarsInSh('/etc/sysconfig/clock', { ZONE => $timezone->{timezone} });  } +=item ask_suppl_media_method($o) + +Enables to add supplementary media + +=cut +  sub ask_suppl_media_method {      my ($o) = @_;      our $suppl_already_asked; @@ -163,18 +170,18 @@ sub ask_suppl_media_method {  Do you have a supplementary installation medium to configure?", -	    join(", ", map { $_->{name} } install::media::allMediums($o->{packages})))); +	    "\n\n\n" . join(",\n\n", map { "- $_->{name}" . ($_->{ignore} ? " (disabled)" : '') } install::media::allMediums($o->{packages}))));      my %l = my @l = (  	''      => N("None"), -	'cdrom' => N("CD-ROM"),  	'http'  => N("Network (HTTP)"),  	'ftp'   => N("Network (FTP)"),  	'nfs'   => N("Network (NFS)"),      ); -    $o->ask_from( -	'', $msg, +    $o->ask_from_({ messages => $msg, +		    interactive_help_id => 'add_supplemental_media', +		  },  	[ {  	    val => \my $suppl,  	    list => [ map { $_->[0] } group_by2(@l) ], @@ -187,20 +194,30 @@ Do you have a supplementary installation medium to configure?",      $suppl;  } -#- if the supplementary media is networked, but not the main one, network -#- support must be installed and network started. +=item prep_net_suppl_media($o) + +If the supplementary media is networked, but not the main one, network +support must be installed and network started. + +=cut +  sub prep_net_suppl_media {      my ($o) = @_;      require network::tools; -    my (undef, $is_up, undef) = network::tools::get_internet_connection($o->{net}); - -    return if our $net_suppl_media_configured && $is_up; +    return if our $net_suppl_media_configured && network::tools::has_network_connection();      $net_suppl_media_configured = 1; -    #- install basesystem now -    $o->do_pkgs->ensure_is_installed('basesystem', undef, 1); +    # needed so that one can install basesystem-minimal before adding suppl network media: +    install::media::update_media($o->{packages}); +    require urpm::media; +    urpm::media::configure($o->{packages}); +    #- install basesystem-minimal now +    $o->do_pkgs->ensure_is_installed('basesystem-minimal', undef, 1); + +    # in case of no network install: +    $o->{net} ||= {};      require network::netconnect;      network::netconnect::real_main($o->{net}, $o, $o->{modules_conf});      require install::interactive; @@ -208,69 +225,14 @@ sub prep_net_suppl_media {      sleep(3);  } -sub ask_url { -    my ($in, $o_url) = @_; - -    my $url = $o_url; -    $in->ask_from_({ messages => N("URL of the mirror?"), focus_first => 1 }, [  -	{ val => \$url, -	  validate => sub {  -	      if ($url =~ m!^(http|ftp)://!) { -		  1; -	      } else { -		  $in->ask_warn('', N("URL must start with ftp:// or http://")); -		  0; -	      } -	  } } ]) && $url; -} -sub ask_mirror { -    my ($o, $type, $o_url) = @_; -     -    require mirror; - -    my $mirrors = eval { -	my $_w = $o->wait_message('', N("Contacting Mandriva Linux web site to get the list of available mirrors...")); -	mirror::list($o->{product_id}, $type); -    }; -    my $err = $@; -    if (!$mirrors) { -	$o->ask_warn('', N("Failed contacting Mandriva Linux web site to get the list of available mirrors") . "\n$err"); -	return ask_url($o, $o_url); -    } - -    my $give_url = { country => '-', host => 'URL' }; - -    my $mirror = $o_url ? (find { $_->{url} eq $o_url } @$mirrors) || $give_url  -        #- use current time zone to select best mirror -      : mirror::nearest($o->{timezone}{timezone}, $mirrors); - -    $o->ask_from_({ messages => N("Choose a mirror from which to get the packages"), -		    cancel => N("Cancel"), -		}, [ { separator => '|', -		       format => \&mirror::mirror2text, -		       list => [ @$mirrors, $give_url ], -		       val => \$mirror, -		   }, -		 ]) or return; - -    my $url; -    if ($mirror eq $give_url) { -	$url = ask_url($o, $o_url) or goto &ask_mirror; -    } else { -	$url = $mirror->{url}; -    } -    $url =~ s!/main/?$!!; -    log::l("chosen mirror: $url"); -    $url; -} -  sub ask_suppl_media_url {      my ($o, $method, $o_url) = @_; -    if ($method eq 'ftp' || $method eq 'http') { -	install::any::ask_mirror($o, 'distrib', $o_url); -    } elsif ($method eq 'cdrom') { -	'cdrom://'; +    if (member($method, qw(ftp http))) { +        preConfigureTimezone($o); +        any::ask_mirror_and_downloader($o, $o->{options}, 'downloader_only'); +        $o->{packages}{options}{downloader} = $o->{options}{downloader}; +	any::ask_mirror($o, 'distrib', $o_url);      } elsif ($method eq 'nfs') {  	my ($host, $dir) = $o_url ? $o_url =~ m!nfs://(.*?)(/.*)! : ();  	$o->ask_from_( @@ -292,6 +254,14 @@ sub ask_suppl_media_url {  	"nfs://$host$dir";      } else { internal_error("bad method $method") }  } + + +=item selectSupplMedia($o) + +Offers to add a supplementary media. If yes, ask which mirror to use, ... + +=cut +  sub selectSupplMedia {      my ($o) = @_;      my $url; @@ -300,7 +270,7 @@ sub selectSupplMedia {      my $method = ask_suppl_media_method($o) or return;      #- configure network if needed -    if (!scalar keys %{$o->{net}{ifcfg}} && $method !~ /^(?:cdrom|disk)/ && !$::local_install) { +    if (!scalar keys %{$o->{net}{ifcfg}} && $method !~ /^(?:disk)/ && !$::local_install) {  	prep_net_suppl_media($o);      } @@ -332,7 +302,7 @@ sub selectSupplMedia {      $phys_medium->{$field} = $val;      #- try using media_info/hdlist.cz -    my $medium_id = int(@{$o->{packages}{mediums}}); +    my $medium_id = int(@{$o->{packages}{media}});      eval { install::media::get_standalone_medium($o, $phys_medium, $o->{packages}, { name => "Supplementary media $medium_id" }) };      if (!$@) {  	log::l("read suppl hdlist (via $method)"); @@ -346,73 +316,284 @@ sub selectSupplMedia {      goto ask_url;  } +=item load_rate_files($o) + +Loads the package rates file (C<rpmsrate>) as well as the C<compssUsers.pl> +file which contains the package groups GUI. + +Both files came from the C<meta-task> package. + +=cut +  sub load_rate_files {      my ($o) = @_;      #- must be done after getProvides -    install::pkgs::read_rpmsrate($o->{packages}, $o->{rpmsrate_flags_chosen}, '/tmp/rpmsrate', $o->{match_all_hardware}); +    require pkgs; +    pkgs::read_rpmsrate($o->{packages}, $o->{rpmsrate_flags_chosen}, '/tmp/rpmsrate', $o->{match_all_hardware});      ($o->{compssUsers}, $o->{gtk_display_compssUsers}) = install::pkgs::readCompssUsers('/tmp/compssUsers.pl');      defined $o->{compssUsers} or die "Can't read compssUsers.pl file, aborting installation\n";  } +sub _core_medium() { N("Core Release") } + +sub _tainted_medium() { N("Tainted Release") } + +sub _nonfree_medium() { N("Nonfree Release") } + +# FIXME: move me in ../any.pm or in harddrake::*, might be needed by rpmdrake/harddrake: +sub is_firmware_needed_ { +    my ($o) = @_; +    require list_firmwares; +    my @l = map { $_->{driver} } detect_devices::probeall(); +    my @need = intersection(\@l, \@list_firmwares::modules_with_nonfree_firmware); +    log::l("the following driver(s) need nonfree firmware(s): " . join(', ', @need)) if @need; + +    require pkgs; +    my @xpkgs = pkgs::detect_graphical_drivers($o->do_pkgs, undef, 'firmware-only'); +    log::l("the following nonfree firmware(s) are needed for X.org: " . join(', ', @xpkgs)) if @xpkgs; + +    my $need_microcode = detect_devices::hasCPUMicrocode(); +    log::l("nonfree firmware is needed for the CPU (microcode)") if $need_microcode; + +    if_(@need, 'kernel-firmware-nonfree'), @xpkgs, if_($need_microcode, 'microcode'); +} + +=item is_firmware_needed($o) + +Is a firmware needed by some HW? + +=cut + +sub is_firmware_needed { +    my ($o) = @_; +    state $res; +    $res = is_firmware_needed_($o) if !defined $res; +    $res; +} + +sub msg_if_firmware_needed { +    my ($o) = @_; +    return if !is_firmware_needed($o); +    join("\n", +	 # FIXME: actually can be proprietary drivers (same medium eventually): +         N("Some hardware on your machine needs some non free firmwares in order for the free software drivers to work."), +         N("You should enable \"%s\"", _nonfree_medium()), +     ); +} + +=item enable_nonfree_media($medium) + +Enable a disabled Nonfree medium. + +=cut + +sub enable_nonfree_media { +    my ($medium) = @_; +    return if $medium->{name} !~ /Nonfree/ || $medium->{name} =~ /32bit/ || !$medium->{ignore}; +    log::l("preselecting $medium->{name}"); +    $medium->{temp_enabled} = 1; +} + +=item enable_core_32bit_media($medium) + +Enable a disabled Core 32bit medium. + +=cut + +sub enable_core_32bit_media { +    my ($medium) = @_; +    return if $medium->{name} !~ /Core/ || $medium->{name} !~ /32bit/ || !$medium->{ignore}; +    log::l("preselecting $medium->{name}"); +    $medium->{temp_enabled} = 1; +} + +=item media_screen($o) + +Lists available media with their status (enabled/disabled). +Suggests to enable Nonfree media if needed. + +=cut + +sub media_screen { +    my ($o) = @_; + +    my $urpm = $o->{packages}; +    # FIXME: +    # - nice info +    # - ignore already failed media (such as 32bit media on NFS) +    # - detect if non-free/tainted were selected previously / are now needed +    #   rpm -qa |grep tainted/non-free +    # - use red color in that case (gtk+ version? interactive::gtk version?) +    # - present media as trees (eg 3 main branches (core/nonfree/tainted and sub medium below (release/updates/...) +    # - enable to add media from the media screen +    # - introduce 'mandatory' keyword for guessing media that can *not* be disabled +    my %descriptions = ( +        'Core Release' => N("\"%s\" contains the various pieces of the systems and its applications", _core_medium()), +        'Nonfree Release' => N("\"%s\" contains non free software.\n", _nonfree_medium()) . " " . +          N("It also contains firmwares needed for certain devices to operate (eg: some ATI/AMD graphic cards, some network cards, some RAID cards, ...)"), +        'Tainted Release' => N("\"%s\" contains software that can not be distributed in every country due to software patents.", _tainted_medium()) . " " . +          N("It also contains software from \"%s\" rebuild with additional capabilities.", _core_medium()), +    ); + +    my $nonfree_is_needed = is_firmware_needed($o); + +    $o->ask_from_({ messages => join("\n", +                                      N("Here you can enable more media if you want."), +                                      msg_if_firmware_needed($o) +                                  ), +		    interactive_help_id => 'media_selection', +                     focus_first => sub { 1 } }, [  +        map { +            my $medium = $_; +	    $medium->{temp_enabled} = !$medium->{ignore}; +	    my $name = $medium->{name}; +	    my ($distribconf, $medium_path) = @{$_->{mediacfg}}; +	    my @media_types = split(':', $distribconf->getvalue($medium_path, 'media_type')); +	    my $parent = $distribconf->getvalue($distribconf->getvalue($medium_path, 'updates_for'), 'name'); +	    my $non_regular_medium = intersection(\@media_types, [ qw(backports debug source testing) ]); +	    enable_nonfree_media($medium) if $nonfree_is_needed && !$non_regular_medium; +	    enable_core_32bit_media($medium) if arch() eq 'x86_64' && uefi_type() eq 'ia32' && !$non_regular_medium; +	    $non_regular_medium ? () : +	    +{ +                val => \$medium->{temp_enabled}, type => 'bool', text => $name, +		help => $medium->{update} ? N("This medium provides package updates for medium \"%s\"", $parent) : $descriptions{$name}, +                # 'Core Release' cannot be unselected: +                disabled => sub { +		    state $parent_media = $parent && urpm::media::name2medium($urpm, $parent); +		    $name =~ /^(?:Core|Main) Release$/ || $parent_media ? !$parent_media->{temp_enabled} : 0; +		}, +            }; +	} @{$urpm->{media}}, +    ]); +} + +sub enable_choosen_media { +    my ($o) = @_; +    my $urpm = $o->{packages}; + +    # is there some media to enable? +    my $todo; +    foreach my $medium (@{$urpm->{media}}) { +        if ($medium->{temp_enabled} == $medium->{ignore}) { +            $medium->{ignore} = !$medium->{temp_enabled}; +            if (!$medium->{ignore}) { +		delete $medium->{ignore}; +		log::l("Medium '$medium->{name}' needs to be updated to be usable"); +		urpm::media::select_media($urpm, $medium->{name}); +		$todo = 1; +	    } +	} +	delete $medium->{temp_enabled}; +    } +    return if !$todo; +    urpm::media::update_media($urpm, allow_failures => 1, nolock => 1, noclean => 1, +			      callback => \&urpm::download::sync_logger +			     ); +} + +=item setPackages($o) + +=over 4 + +=item * Initialize urpmi + +=item * Retrieves media.cfg + +=item * Offers to add supplementary media (according to the install method) + +=item * Offers to enable some disabled media + +=item * Ensure we have a kernel and basesystem + +=item * Flags package rates + +=item * Select default packages according to the computer + +=back + +=cut +  sub setPackages {      my ($o) = @_; +    my $urpm;      require install::pkgs;      { -	$o->{packages} = install::pkgs::empty_packages(); +	#- clean shared regions very early +	#  (update_media will open rpmdb for listing existing pubkeys, +	#   which may fail when rpm version mistmatches between drakx & chrooted env) +	install::pkgs::clean_rpmdb_shared_regions(); +	$urpm = $o->{packages} = install::pkgs::empty_packages($o->{keep_unrequested_dependencies});  	my $media = $o->{media} || [ { type => 'media_cfg', url => 'drakx://media' } ]; +	my ($suppl_method, $copy_rpms_on_disk); -	my ($suppl_method, $copy_rpms_on_disk) = install::media::get_media($o, $media, $o->{packages}); +	{ +	    install::pkgs::start_pushing_error(); +	    ($suppl_method, $copy_rpms_on_disk) = install::media::get_media($o, $media, $urpm); -	if ($suppl_method) { -	    1 while $o->selectSupplMedia; +	    if ($suppl_method) { +	        1 while $o->selectSupplMedia; +	    } +	    install::media::update_media($urpm); +	    install::pkgs::popup_errors();  	} -	#- open rpm db according to right mode needed (ie rebuilding database if upgrading) -	$o->{packages}{rpmdb} ||= install::pkgs::rpmDbOpen($o->{isUpgrade}, $o->{rpm_dbapi}); +        install::pkgs::start_pushing_error(); + +	# in auto-install mode, we enforce selected media, else we respect media.cfg's default: +        if ($::auto_install && !is_empty_array_ref($o->{enabled_media})) { +	    # respect enabled/disabled media selection: +	    foreach my $medium (@{$urpm->{media}}) { +	        $medium->{temp_enabled} = member($medium->{name}, @{$o->{enabled_media}}); +	    } +        } +        media_screen($o) if !$::auto_install || member('chooseMedia', @{$::o->{interactiveSteps}}); +        enable_choosen_media($o); +        my @choosen_media = map { $_->{name} } grep { !$_->{ignore} } @{$urpm->{media}}; +        log::l("choosen media: ", join(', ', @choosen_media)); +        die "no choosen media" if !@choosen_media; + +        # actually read synthesis now we have all the ones we want: +        require urpm::media; +        urpm::media::configure($urpm); + +        install::pkgs::popup_errors(); + +        install::media::adjust_paths_in_urpmi_cfg($urpm); +        log::l('urpmi completely set up'); + +	#- open rpm db according to right mode needed +	$urpm->{rpmdb} ||= install::pkgs::rpmDbOpen('rebuild_if_needed');  	{  	    my $_wait = $o->wait_message('', N("Looking at packages already installed...")); -	    install::pkgs::selectPackagesAlreadyInstalled($o->{packages}); +	    install::pkgs::selectPackagesAlreadyInstalled($urpm);  	} -	if (my $extension = $o->{upgrade_by_removing_pkgs_matching}) { -	    my $time = time(); -	    my ($_w, $wait_message) = $o->wait_message_with_progress_bar; -	    $wait_message->(N("Removing packages prior to upgrade...")); -	    my ($current, $total); -	    my $callback = sub { -		my (undef, $type, $_id, $subtype, $amount) = @_; -		if ($type eq 'user') { -		    ($current, $total) = (0, $amount); -		} elsif ($type eq 'uninst' && $subtype eq 'stop') { -		    $wait_message->('', $current++, $total); -		} -	    }; -	    push @{$o->{default_packages}}, install::pkgs::upgrade_by_removing_pkgs($o->{packages}, $callback, $extension, $o->{isUpgrade}); -	    log::l("Removing packages took: ", formatTimeRaw(time() - $time)); -	} +        remove_package_for_upgrade($o);  	mark_skipped_packages($o);  	#- 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). -	my $kernel_pkg = install::pkgs::bestKernelPackage($o->{packages}); -	install::pkgs::selectPackage($o->{packages}, $kernel_pkg, 1); -	if ($o->{isUpgrade} && $o->{packages}{sizes}{dkms}) { -	    log::l("selecting kernel-source-stripped-latest (since dkms was installed)"); -	    install::pkgs::select_by_package_names($o->{packages}, ['kernel-source-stripped-latest'], 1); +	my $kernel_pkg = install::pkgs::bestKernelPackage($urpm, $o->{match_all_hardware}); +	install::pkgs::selectPackage($urpm, $kernel_pkg, 1); +	if ($o->{isUpgrade} && $urpm->{sizes}{dkms} && $kernel_pkg =~ /(.*)-latest/) { +	    my $devel_kernel_pkg = "$1-devel-latest"; +	    log::l("selecting $devel_kernel_pkg (since dkms was installed)"); +	    install::pkgs::select_by_package_names($urpm, [ $devel_kernel_pkg ], 1);  	} -	install::pkgs::select_by_package_names_or_die($o->{packages}, ['basesystem'], 1); +	install::pkgs::select_by_package_names_or_die($urpm, default_bootloader(), 1) if !$o->{isUpgrade} && !$o->{match_all_hardware}; +	install::pkgs::select_by_package_names_or_die($urpm, ['basesystem'], 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 install::pkgs::read_rpmsrate() +	put_in_hash($o->{rpmsrate_flags_chosen} ||= {}, rpmsrate_always_flags($o)); #- must be done before pkgs::read_rpmsrate()  	load_rate_files($o);  	install::media::copy_rpms_on_disk($o) if $copy_rpms_on_disk; @@ -424,29 +605,45 @@ sub setPackages {      }      if ($o->{isUpgrade}) { -	{ -	    my $_w = $o->wait_message('', N("Finding packages to upgrade...")); -	    install::pkgs::selectPackagesToUpgrade($o->{packages}); -	} -	if ($o->{packages}{sizes}{'kdebase-progs'}) { -	    log::l("selecting task-kde (since kdebase-progs was installed)"); -	    install::pkgs::select_by_package_names($o->{packages}, ['task-kde']); -	} +        my $_w = $o->wait_message('', N("Finding packages to upgrade...")); +        install::pkgs::selectPackagesToUpgrade($urpm);      }  } -sub create_minimal_files() { -    mkdir "$::prefix/$_", 0755 foreach  -      qw(dev etc etc/profile.d etc/rpm etc/sysconfig etc/sysconfig/console  -	etc/sysconfig/network-scripts etc/sysconfig/console/consolefonts  -	etc/sysconfig/console/consoletrans -	home mnt tmp var var/tmp var/lib var/lib/rpm var/lib/urpmi); -    mkdir "$::prefix/$_", 0700 foreach qw(root root/tmp root/drakx); +=item remove_package_for_upgrade($o) + +Removes packages that must be uninstalled prior to upgrade + +=cut -    devices::make("$::prefix/dev/null"); -    chmod 0666, "$::prefix/dev/null"; +sub remove_package_for_upgrade { +    my ($o) = @_; +    my $extension = $o->{upgrade_by_removing_pkgs_matching}; + +    return if !$extension; + +    my $time = time(); +    my ($_w, $wait_message) = $o->wait_message_with_progress_bar; +    $wait_message->(N("Removing packages prior to upgrade...")); +    my ($current, $total); +    my $callback = sub { +        my (undef, $type, $_id, $subtype, $amount) = @_; +        if ($type eq 'user') { +            ($current, $total) = (0, $amount); +        } elsif ($type eq 'uninst' && $subtype eq 'stop') { +            $wait_message->('', $current++, $total); +        } +    }; +    push @{$o->{default_packages}}, install::pkgs::upgrade_by_removing_pkgs($o->{packages}, $callback, $extension, $o->{isUpgrade}); +    log::l("Removing packages took: ", formatTimeRaw(time() - $time));  } +=item count_files($dir) + +Returns the number of files in $dir + +=cut +  sub count_files {      my ($dir) = @_;      -d $dir or return 0; @@ -463,25 +660,35 @@ sub count_files {  sub cp_with_progress {      my $wait_message = shift; -    my $current = 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"; +    cp_with_progress_({ keep_special => 1 }, $wait_message, $total, \@_, $dest); +} +sub cp_with_progress_ { +    my ($options, $wait_message, $total, $list, $dest) = @_; +    @$list or return; +    @$list == 1 || -d $dest or die "cp: copying multiple files, but last argument ($dest) is not a directory\n"; + +    -d $dest or $dest = dirname($dest); +    _cp_with_progress($options, $wait_message, 0, $total, $list, $dest); +} +sub _cp_with_progress { +    my ($options, $wait_message, $current, $total, $list, $dest) = @_; -    foreach my $src (@_) { +    foreach my $src (@$list) {  	my $dest = $dest;  	-d $dest and $dest .= '/' . basename($src);  	unlink $dest; -	if (-l $src) { +	if (-l $src && $options->{keep_special}) {  	    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); +	    _cp_with_progress($options, $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"; @@ -530,10 +737,14 @@ sub rpmsrate_always_flags {      $rpmsrate_flags_chosen->{DVD} = 1 if $o->{match_all_hardware} || detect_devices::dvdroms();      $rpmsrate_flags_chosen->{USB} = 1 if $o->{match_all_hardware} || $o->{modules_conf}->get_probeall("usb-interface");      $rpmsrate_flags_chosen->{PCMCIA} = 1 if $o->{match_all_hardware} || detect_devices::hasPCMCIA(); -    $rpmsrate_flags_chosen->{HIGH_SECURITY} = 1 if $o->{security} > 3; +    $rpmsrate_flags_chosen->{HIGH_SECURITY} = 1 if $o->{security} > 1;      $rpmsrate_flags_chosen->{BIGMEM} = 1 if detect_devices::BIGMEM(); -    $rpmsrate_flags_chosen->{SMP} = 1 if detect_devices::hasSMP(); -    $rpmsrate_flags_chosen->{CDCOM} = 1 if any { $_->{name} =~ /commercial/i } install::media::allMediums($o->{packages}); +    $rpmsrate_flags_chosen->{SMP} = 1 if $o->{match_all_hardware} || detect_devices::hasSMP(); +    if (!$o->{match_all_hardware} && !defined $o->{compssListLevel} && detect_devices::need_light_desktop()) { +        log::l("activation light desktop mode (for low resources systems or netbook/nettops)"); +        $rpmsrate_flags_chosen->{LIGHT} = 1; +    } +    # FIXME: to be updated!!!      $rpmsrate_flags_chosen->{'3D'} = 1 if        $o->{match_all_hardware} ||        detect_devices::matching_desc__regexp('Matrox.* G[245][05]0') || @@ -559,18 +770,54 @@ sub rpmsrate_always_flags {      $rpmsrate_flags_chosen;  } +sub default_bootloader() { +    require bootloader; +    my (undef, $p) = bootloader::get_grub2_pkg(); +    if (is_uefi()) { +	log::l("defaulting to grub2-efi"); +    } else { +	log::l("defaulting to grub2"); +    } +    [ $p ]; +} + +=item default_packages($o) + +Selects default packages to install according to configuration (FS, HW, ...) + +=cut +  sub default_packages {      my ($o) = @_;      my @l; -    push @l, "brltty" if cat_("/proc/cmdline") =~ /brltty=/; -    push @l, "nfs-utils-clients" if $o->{method} eq "nfs"; -    push @l, "mdadm" if !is_empty_array_ref($o->{all_hds}{raids}); -    push @l, "lvm2" if !is_empty_array_ref($o->{all_hds}{lvms}); -    push @l, "dmraid" if any { fs::type::is_dmraid($_) } @{$o->{all_hds}{hds}}; -    push @l, 'powernowd' if cat_('/proc/cpuinfo') =~ /AuthenticAMD/ && arch() =~ /x86_64/ -      || cat_('/proc/cpuinfo') =~ /model name.*Intel\(R\) Core\(TM\)2 CPU/; -    push @l, detect_devices::probe_name('Pkg'); +    sub add_n_log { +       my ($reason, @packages) = @_; +       if (@packages) { +          log::l("selecting " . join(',', @packages) . " because of $reason"); +          push @l, @packages; +       } +    } + +    add_n_log("/proc/cmdline=~/brltty=/", "brltty") if cat_("/proc/cmdline") =~ /brltty=/; +    add_n_log("method==nfs", "nfs-utils") if $o->{method} eq "nfs"; +    add_n_log("have RAID", "mdadm") if !is_empty_array_ref($o->{all_hds}{raids}); +    add_n_log("have LVM", "lvm2") if !is_empty_array_ref($o->{all_hds}{lvms}); +    add_n_log("have crypted DM", qw(cryptsetup dmsetup)) if !is_empty_array_ref($o->{all_hds}{dmcrypts}); +    add_n_log("some disks are fake RAID", qw(mdadm dmraid)) if any { fs::type::is_dmraid($_) } @{$o->{all_hds}{hds}}; +    add_n_log("CPU needs microcode", "microcode_ctl") if detect_devices::hasCPUMicrocode(); +    add_n_log("either CPU or GFX needs firmware", is_firmware_needed($o)) if is_firmware_needed($o); +    add_n_log("CPU needs cpupower", 'cpupower') if detect_devices::hasCPUFreq(); +    add_n_log("APM support needed", 'apmd') if -e "/proc/apm"; +    add_n_log("needed by hardware", detect_devices::probe_name('Pkg')); +    my @ltmp = map { $_->{BOOTPROTO} eq 'dhcp' ? $_->{DHCP_CLIENT} || 'dhcp-client' : () } values %{$o->{net}{ifcfg}}; +    add_n_log("needed by networking", @ltmp) if @ltmp; +    # will get auto selected at summary stage for bootloader: +    add_n_log("needed later at summary stage", qw(acpi acpid)); +    # will get auto selected at summary stage for firewall: +    add_n_log("needed for firewall/security", qw(shorewall shorewall-ipv6 mandi-ifw)); +    # only needed for CDs/DVDs installations: +    add_n_log("method='cdrom'", 'perl-Hal-Cdroms') if $o->{method} eq 'cdrom';      my $dmi_BIOS = detect_devices::dmidecode_category('BIOS');      my $dmi_Base_Board = detect_devices::dmidecode_category('Base Board'); @@ -580,13 +827,16 @@ sub default_packages {  	modules::append_to_modules_loaded_at_startup_for_all_kernels('acerhk');      } -    push @l, 'quota' if any { $_->{options} =~ /usrquota|grpquota/ } @{$o->{fstab}}; -    push @l, uniq(grep { $_ } map { fs::format::package_needed_for_partition_type($_) } @{$o->{fstab}}); +    add_n_log("some fs is mounted with quota options", 'quota') if any { $_->{options} =~ /usrquota|grpquota/ } @{$o->{fstab}}; +    @ltmp = uniq(grep { $_ } map { fs::format::package_needed_for_partition_type($_) } @{$o->{fstab}}); +    add_n_log("needed by some fs", @ltmp) if @ltmp; -    my @locale_pkgs = map { install::pkgs::packagesProviding($o->{packages}, 'locales-' . $_) } lang::langsLANGUAGE($o->{locale}{langs}); +    # handle locales with specified scripting: +    my @languages = map { s/\@.*//; $_ } lang::langsLANGUAGE($o->{locale}{langs}); +    my @locale_pkgs = map { URPM::packages_providing($o->{packages}, 'locales-' . $_) } @languages;      unshift @l, uniq(map { $_->name } @locale_pkgs); -    @l; +    uniq(@l);  }  sub mark_skipped_packages { @@ -605,29 +855,6 @@ sub unselectMostPackages {      select_default_packages($o);  } -sub warnAboutNaughtyServers { -    my ($o) = @_; -    my @naughtyServers = install::pkgs::naughtyServers($o->{packages}) or return 1; -    my $r = $o->ask_from_list_('',  -formatAlaTeX( -             #-PO: keep the double empty lines between sections, this is formatted a la LaTeX -             N("You have selected the following server(s): %s - - -These servers are activated by default. They do not have any known security -issues, but some new ones could be found. In that case, you must make sure -to upgrade as soon as possible. - - -Do you really want to install these servers? -", join(", ", @naughtyServers))), [ N_("Yes"), N_("No") ], 'Yes') or return; -    if ($r ne 'Yes') { -	log::l("unselecting naughty servers: " . join(' ', @naughtyServers)); -	install::pkgs::unselectPackage($o->{packages}, install::pkgs::packageByName($o->{packages}, $_)) foreach @naughtyServers; -    } -    1; -} -  sub warnAboutRemovedPackages {      my ($o, $packages) = @_;      my @removedPackages = keys %{$packages->{state}{ask_remove} || {}} or return; @@ -682,6 +909,13 @@ sub kdemove_desktop_file {      }  } +sub log_system_info { +    my ($o) = @_; +    log::l("second stage install running (", drakx_version($o), ")"); +    log::l(sprintf("Virtualization=%s", detect_devices::virt_technology() || "none")); +    log::l(sprintf("Is UEFI=%s", bool2yesno(is_uefi()))); +} +  #-###############################################################################  #- auto_install stuff @@ -697,16 +931,16 @@ sub g_auto_install {      my $o = {};      require install::pkgs; -    $o->{default_packages} = install::pkgs::selected_leaves($::o->{packages}); +    $o->{default_packages} = [ sort @{ install::pkgs::selected_leaves($::o->{packages}) } ]; -    my @fields = qw(mntpoint fs_type size); +    my @fields = qw(fs_type hd level mntpoint options parts size VG_name);      $o->{partitions} = [ map {   	my %l; @l{@fields} = @$_{@fields}; \%l;      } grep {   	$_->{mntpoint} && fs::format::known_type($_);      } @{$::o->{fstab}} ]; -    exists $::o->{$_} and $o->{$_} = $::o->{$_} foreach qw(locale authentication mouse net timezone superuser keyboard users partitioning isUpgrade manualFstab nomouseprobe crypto security security_user libsafe autoExitInstall X services postInstall postInstallNonRooted); #- TODO modules bootloader  +    exists $::o->{$_} and $o->{$_} = $::o->{$_} foreach qw(locale authentication mouse net timezone superuser keyboard users partitioning isUpgrade manualFstab nomouseprobe crypto security security_user autoExitInstall X services postInstall postInstallNonRooted); #- TODO modules bootloader       local $o->{partitioning}{auto_allocate} = !$b_replay;      $o->{autoExitInstall} = !$b_replay; @@ -715,6 +949,9 @@ sub g_auto_install {      #- deep copy because we're modifying it below      $o->{users} = $b_respect_privacy ? [] : [ @{$o->{users} || []} ]; +    # remember selected media: +    local $o->{enabled_media} = [ map { $_->{name} } grep { !$_->{ignore} } @{$::o->{packages}{media}} ]; +      my @user_info_to_remove = (  	if_($b_respect_privacy, qw(realname pw)),   	qw(oldu oldg password password2), @@ -749,9 +986,6 @@ sub getAndSaveAutoInstallFloppies {      eval { modules::load('loop') }; -    if (arch() =~ /ia64/) { -	#- nothing yet -    } else {  	my $mountdir = "$::prefix/root/aif-mount"; -d $mountdir or mkdir $mountdir, 0755;  	my $param = 'kickstart=floppy ' . generate_automatic_stage1_params($o); @@ -759,7 +993,7 @@ sub getAndSaveAutoInstallFloppies {  	{  	    my $dev = devices::set_loop($img) or log::l("couldn't set loopback device"), return; -	    find { eval { fs::mount::mount($dev, $mountdir, $_, 0); 1 } } qw(ext2 vfat) or return; +	    find { eval { fs::mount::mount($dev, $mountdir, $_, 0); 1 } } qw(ext2 vfat ntfs-3g) or return;  	    if (-e "$mountdir/menu.lst") {  		# hd_grub boot disk is different than others @@ -794,7 +1028,6 @@ sub getAndSaveAutoInstallFloppies {  	}  	rmdir $mountdir;  	$img; -    }  } @@ -802,14 +1035,19 @@ sub g_default_packages {      my ($o) = @_;      my ($_h, $file) = media_browser($o, 'save', 'package_list.pl') or return; +    output($file, selected_leaves_pl($o)); +} + +sub selected_leaves_pl { +    my ($o) = @_;      require Data::Dumper;      my $str = Data::Dumper->Dump([ { default_packages => install::pkgs::selected_leaves($o->{packages}) } ], ['$o']);      $str =~ s/ {8}/\t/g; -    output($file, -	   "# You should always check the syntax with 'perl -cw auto_inst.cfg.pl'\n" . -	   "# before testing.  To use it, boot with ``linux defcfg=floppy''\n" . -	   $str); + +    "# You should always check the syntax with 'perl -cw auto_inst.cfg.pl'\n" . +      "# before testing.  To use it, boot with ``linux defcfg=floppy''\n" . +      $str;  }  sub loadO { @@ -819,7 +1057,7 @@ sub loadO {  	my $o;  	foreach (removable_media__early_in_install()) {              my $dev = devices::make($_->{device}); -            foreach my $fs (arch() =~ /sparc/ ? 'romfs' : ('ext2', 'vfat')) { +            foreach my $fs (qw(ext4 vfat ntfs-3g)) {                  eval { fs::mount::mount($dev, '/mnt', $fs, 'readonly'); 1 } or next;  		if (my $abs_f = find { -e $_ } "/mnt/$f", "/mnt/$f.pl") {  		    $o = loadO_($O, $abs_f); @@ -925,10 +1163,11 @@ sub generate_automatic_stage1_params {  	$method = $1; #- in stage1, FTP via HTTP proxy is available through FTP config, not HTTP  	@ks = (server => $2, directory => $3);      } elsif ($o->{method} eq 'ftp') { +	require install::ftp;  	my @l = install::ftp::parse_ftp_url($ENV{URLPREFIX});  	@ks = (server => $l[0], directory => $l[1], user => $l[2], pass => $l[3]);      } elsif ($o->{method} eq 'nfs') { -	cat_("/proc/mounts") =~ m|(\S+):(\S+)\s+/tmp/media| or internal_error("can not find nfsimage"); +	cat_("/proc/mounts") =~ m|(\S+):(\S+)\s+/tmp/media| or internal_error("cannot find nfsimage");  	@ks = (server => $1, directory => $2);      }      @ks = (method => $method, @ks); @@ -961,23 +1200,22 @@ sub generate_automatic_stage1_params {  sub find_root_parts {      my ($fstab, $prefix) = @_; -    my $extract = sub { -	my ($prefix, $f, $part) = @_; -	chomp(my $s = cat_("$prefix$f")); -	$s =~ s/\s+for\s+\S+//; -	log::l("find_root_parts found $part->{device}: $s" . ($f !~ m!/etc/! ? " in special release file $f" : '')); -	{ release => $s, release_file => $f, part => $part }; -    }; +    grep { $_->{release} =~ /\b(mandrake|mandrakelinux|mandriva|conectiva|mageia)\b/i }  +      _find_root_parts($fstab, $prefix); +} + +sub _find_root_parts { +    my ($fstab, $prefix) = @_;      if ($::local_install) {  	my $f = common::release_file('/mnt') or return; -	return $extract->('/mnt', $f, {}); +	return common::parse_release_file('/mnt', $f, {});      }      map {   	my $handle = any::inspect($_, $prefix);  	if (my $f = $handle && common::release_file($handle->{dir})) { -	    $extract->($handle->{dir}, $f, $_); +	    common::parse_release_file($handle->{dir}, $f, $_);  	} else { () }      } grep { isTrueLocalFS($_) } @$fstab;  } @@ -1037,7 +1275,7 @@ sub migrate_device_names {  	goto found_one;      } -    #- we can not find one and only one matching hd +    #- we cannot find one and only one matching hd      my @from_fstab_not_handled = map { @$_ } @from_fstab_per_hds;      log::l("we still do not know what to do with: " . join(' ', map { $_->{device} } @from_fstab_not_handled)); @@ -1097,7 +1335,7 @@ sub getHds {  }  sub removable_media__early_in_install() { -    eval { modules::load('usb-storage', 'sd_mod') } if detect_devices::usbStorage(); +    eval { modules::load('usb_storage', 'sd_mod') } if detect_devices::usbStorage();      my $all_hds = fsedit::get_hds({});      fs::get_raw_hds('', $all_hds); @@ -1252,11 +1490,12 @@ sub X_options_from_o {  sub screenshot_dir__and_move() {      my ($dir0, $dir1, $dir2) = ('/root', "$::prefix/root", '/tmp');      if (-e $dir0 && ! -e '/root/non-chrooted-marker.DrakX') { -	$dir0; #- it occurs during pkgs install when we are chrooted +	($dir0, 'nowarn'); #- it occurs during pkgs install when we are chrooted      } elsif (-e $dir1) { -	if (-e "$dir2/DrakX-screenshots") { -	    cp_af("$dir2/DrakX-screenshots", $dir1); -	    rm_rf("$dir2/DrakX-screenshots"); +        my $path = "$dir2/DrakX-screenshots"; +	if (-e $path) { +	    cp_af($path, $dir1); +	    rm_rf($path);  	}  	$dir1;      } else { @@ -1264,19 +1503,25 @@ sub screenshot_dir__and_move() {      }  } +my $warned;  sub take_screenshot {      my ($in) = @_; -    my $dir = screenshot_dir__and_move() . '/DrakX-screenshots'; -    my $warn; +    my ($base_dir, $nowarn) = screenshot_dir__and_move(); +    my $dir = "$base_dir/DrakX-screenshots";      if (!-e $dir) { -	mkdir $dir or $in->ask_warn('', N("Can not make screenshots before partitioning")), return; -	$warn = 1; +	mkdir $dir or $in->ask_warn('', N("Cannot make screenshots before partitioning")), return;      }      my $nb = 1;      $nb++ while -e "$dir/$nb.png"; -    system("fb2png /dev/fb0 $dir/$nb.png 0"); +    run_program::run('scrot', "$dir/$nb.png"); + +    # help doesn't remember warning has been shown (one shot processes): +    $warned ||= -e "$dir/2.png"; -    $in->ask_warn('', N("Screenshots will be available after install in %s", "/root/DrakX-screenshots")) if $warn; +    if (!$warned && !$nowarn) { +	$warned = 1; +	$in->ask_warn('', N("Screenshots will be available after install in %s", "/root/DrakX-screenshots")); +    }  }  sub copy_advertising { @@ -1310,24 +1555,54 @@ sub remove_advertising() {  }  sub disable_user_view() { -    substInFile { s/^UserView=.*/UserView=true/ } "$::prefix/etc/kde/kdm/kdmrc";      substInFile { s/^Browser=.*/Browser=0/ } "$::prefix/etc/X11/gdm/custom.conf"; +    #TODO: Needed for sddm ?  }  sub set_security {      my ($o) = @_;      require security::various; +    return if !-x "$::prefix/usr/sbin/msec";      security::level::set($o->{security}); -    security::various::config_libsafe($::prefix, $o->{libsafe});      security::various::config_security_user($::prefix, $o->{security_user});  }  sub write_fstab {      my ($o) = @_; -    fs::write_fstab($o->{all_hds}, $::prefix)  -	if !$o->{isUpgrade} || $o->{isUpgrade} =~ /redhat|conectiva/ || $o->{migrate_device_names}; +    return if $::local_install || $o->{isUpgrade} && $o->{isUpgrade} !~ /redhat|conectiva/ && !$o->{migrate_device_names}; +    fs::write_fstab($o->{all_hds}, $::prefix); +} + +=item adjust_files_mtime_to_timezone() { + +Fixes mtime of a couple important files according to timezone in order to: + +=over 4 + +=item * to ensure linuxconf does not cry against those files being in the future + +=item * to ensure fc-cache works correctly on fonts installed after reboot + +=back + +=cut + +sub adjust_files_mtime_to_timezone() { +    my $timezone_shift = run_program::rooted_get_stdout($::prefix, 'date', '+%z'); +    my ($h, $m) = $timezone_shift =~ /\+(..)(..)/ or return; +    my $now = time() - ($h * 60 + $m * 60) * 60; + +    my @files = ( +	(map { "$::prefix/$_" } '/etc/modules.conf', '/etc/crontab', '/etc/sysconfig/mouse', '/etc/sysconfig/network', '/etc/X11/fs/config'), +	glob_("$::prefix/var/cache/fontconfig/*"), +    ); +    log::l("adjust_files_mtime_to_timezone: setting time back $h:$m for files " . join(' ', @files)); +    foreach (@files) { +	utime $now, $now, $_; +    }  } +  sub move_compressed_image_to_disk {      my ($o) = @_; @@ -1405,7 +1680,11 @@ sub configure_pcmcia {      log::l("configuring PCMCIA controller ($o->{pcmcia})");      symlink "/tmp/stage2/$_", $_ foreach "/etc/pcmcia";      eval { modules::load($o->{pcmcia}, 'pcmcia') }; -    run_program::run("pcmcia-socket-startup"); +    run_program::run("/lib/udev/pcmcia-socket-startup");  } +=back + +=cut +  1; | 
