diff options
Diffstat (limited to 'perl-install/any.pm')
-rw-r--r-- | perl-install/any.pm | 1089 |
1 files changed, 828 insertions, 261 deletions
diff --git a/perl-install/any.pm b/perl-install/any.pm index 89dc0e310..ab93036dc 100644 --- a/perl-install/any.pm +++ b/perl-install/any.pm @@ -9,6 +9,7 @@ use strict; use common; use detect_devices; use partition_table; +use fs::proc_partitions; use fs::type; use lang; use run_program; @@ -19,7 +20,7 @@ use fs; use c; sub facesdir() { - "$::prefix/usr/share/mdk/faces/"; + "$::prefix/usr/share/mga/faces/"; } sub face2png { my ($face) = @_; @@ -81,6 +82,7 @@ sub create_user { ? ('-l', $u->{name}, $u->{rename_from}) : $u->{name})); symlink($u->{home}, $symlink_home_from) if $symlink_home_from; + eval { run_program::rooted($::prefix, 'systemctl', 'try-restart', 'accounts-daemon.service') }; } my (undef, undef, $uid, $gid, undef, undef, undef, $home) = getpwnam($u->{name}); @@ -116,11 +118,10 @@ sub install_acpi_pkgs { my $acpi = bootloader::get_append_with_key($b, 'acpi'); my $use_acpi = !member($acpi, 'off', 'ht'); if ($use_acpi) { - $do_pkgs->ensure_is_installed('acpi', '/usr/bin/acpi', $::isInstall); - $do_pkgs->ensure_is_installed('acpid', '/usr/sbin/acpid', $::isInstall); + $do_pkgs->ensure_files_are_installed([ [ qw(acpi acpi) ], [ qw(acpid acpid) ] ], $::isInstall); } require services; - services::set_status($_, $use_acpi, $::isInstall) foreach qw(acpi acpid); + services::set_status($_, $use_acpi, $::isInstall) foreach qw(acpid); } sub setupBootloaderBeforeStandalone { @@ -130,12 +131,13 @@ sub setupBootloaderBeforeStandalone { my $allow_fb = listlength(cat_("/proc/fb")); my $cmdline = cat_('/proc/cmdline'); my $vga_fb = first($cmdline =~ /\bvga=(\S+)/); - my $quiet = $cmdline =~ /\bsplash=silent\b/; - setupBootloaderBefore($do_pkgs, $b, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $quiet); + my $splash = $cmdline =~ /\bsplash\b/; + my $quiet = $cmdline =~ /\bquiet\b/; + setupBootloaderBefore($do_pkgs, $b, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $splash, $quiet); } sub setupBootloaderBefore { - my ($do_pkgs, $bootloader, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $quiet) = @_; + my ($do_pkgs, $bootloader, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $splash, $quiet) = @_; require bootloader; #- auto_install backward compatibility @@ -144,12 +146,6 @@ sub setupBootloaderBefore { $bootloader->{message_text} = delete $bootloader->{message}; } - #- remove previous ide-scsi lines - bootloader::modify_append($bootloader, sub { - my ($_simple, $dict) = @_; - @$dict = grep { $_->[1] ne 'ide-scsi' } @$dict; - }); - if (cat_("/proc/cmdline") =~ /mem=nopentium/) { bootloader::set_append_with_key($bootloader, mem => 'nopentium'); } @@ -174,15 +170,19 @@ sub setupBootloaderBefore { bootloader::set_append_simple($bootloader, 'noresume'); } elsif (bootloader::get_append_simple($bootloader, 'noresume')) { } else { - my ($MemTotal) = cat_("/proc/meminfo") =~ /^MemTotal:\s*(\d+)/m; if (my ($biggest_swap) = sort { $b->{size} <=> $a->{size} } grep { isSwap($_) } @$fstab) { - log::l("MemTotal: $MemTotal < ", $biggest_swap->{size} / 2); - if ($MemTotal < $biggest_swap->{size} / 2) { - bootloader::set_append_with_key($bootloader, resume => fs::wild_device::from_part('', $biggest_swap)); - } + my $biggest_swap_dev = fs::wild_device::from_part('', $biggest_swap); + bootloader::set_append_with_key($bootloader, resume => $biggest_swap_dev); + mkdir_p("$::prefix/etc/dracut.conf.d"); + output("$::prefix/etc/dracut.conf.d/51-mageia-resume.conf", qq(add_device+=" $biggest_swap_dev "\n)); } } + #- set nokmsboot if a conflicting driver is configured. + if (-x "$::prefix/sbin/display_driver_helper" && !run_program::rooted($::prefix, "/sbin/display_driver_helper", "--is-kms-allowed")) { + bootloader::set_append_simple($bootloader, 'nokmsboot'); + } + #- check for valid fb mode to enable a default boot with frame buffer. my $vga = $allow_fb && (!detect_devices::matching_desc__regexp('3D Rage LT') && !detect_devices::matching_desc__regexp('Rage Mobility [PL]') && @@ -202,13 +202,26 @@ sub setupBootloaderBefore { detect_devices::matching_desc__regexp('GeForce.*Integrated') #- needed for fbdev driver (hack). ); - #- propose the default fb mode for kernel fb, if aurora or bootsplash is installed. - my $need_fb = $do_pkgs->are_installed('bootsplash'); + #- propose the default fb mode for kernel fb, if bootsplash is installed. + my $need_fb = -e "$::prefix/usr/share/bootsplash/scripts/make-boot-splash"; bootloader::suggest($bootloader, $all_hds, vga_fb => ($force_vga || $vga && $need_fb) && $vga_fb, + splash => $splash, quiet => $quiet); + if (is_uefi()) { + if (my @esp = grep { $_->{mntpoint} eq '/boot/EFI' } @$fstab) { + $bootloader->{removable} = $esp[0]{is_removable}; + } + } else { + if (my $root_part = fs::get::root($fstab)) { + $bootloader->{removable} = $root_part->{is_removable}; + } + } + $bootloader->{default_to_no_probe} = 1 if $bootloader->{removable}; + $bootloader->{keytable} ||= keyboard::keyboard2kmap($keyboard); + log::l("setupBootloaderBefore end"); } sub setupBootloader { @@ -223,7 +236,11 @@ sub setupBootloader { setupBootloader__boot_bios_drive($in, $b, $all_hds->{hds}) or goto general; { local $::Wizard_finished = 1 if $::isStandalone; - setupBootloader__entries($in, $b, $all_hds, $fstab) or goto general; + if (bootloader::main_method($b->{method}) eq 'grub2') { + setupBootloader__grub2($in, $b, $all_hds, $fstab) or goto general; + } else { + setupBootloader__entries($in, $b, $all_hds, $fstab) or goto general; + } } 1; } @@ -234,7 +251,9 @@ sub setupBootloaderUntilInstalled { my $before = fs::fstab_to_string($all_hds); setupBootloader($in, $b, $all_hds, $fstab, $security) or $in->exit; if ($before ne fs::fstab_to_string($all_hds)) { - #- for /tmp using tmpfs when "clean /tmp" is chosen + #- ovitters: This fstab comparison was needed for optionally + #- setting up /tmp using tmpfs. That code was removed. Not removing + #- this code as I'm not sure if something still relies on this fs::write_fstab($all_hds); } } while !installBootloader($in, $b, $all_hds); @@ -243,9 +262,10 @@ sub setupBootloaderUntilInstalled { sub installBootloader { my ($in, $b, $all_hds) = @_; return if detect_devices::is_xbox(); - install_bootloader_pkgs($in->do_pkgs, $b); - eval { run_program::rooted($::prefix, 'echo | lilo -u') } if $::isInstall && !$::o->{isUpgrade} && -e "$::prefix/etc/lilo.conf" && glob("$::prefix/boot/boot.*"); + return 1 if arch() =~ /arm/; + + install_bootloader_pkgs($in->do_pkgs, $b); retry: eval { @@ -274,11 +294,6 @@ Assign a new Volume ID?", $dev)))) { $in->ask_warn('', [ N("Installation of bootloader failed. The following error occurred:"), $err ]); return; } - } elsif (arch() =~ /ppc/) { - if (detect_devices::get_mac_model() !~ /IBM/) { - my $of_boot = bootloader::dev2yaboot($b->{boot}); - $in->ask_warn('', N("You may need to change your Open Firmware boot-device to\n enable the bootloader. If you do not see the bootloader prompt at\n reboot, hold down Command-Option-O-F at reboot and enter:\n setenv boot-device %s,\\\\:tbxi\n Then type: shut-down\nAt your next boot you should see the bootloader prompt.", $of_boot)); - } } 1; } @@ -290,7 +305,7 @@ sub setupBootloader_simple { require bootloader; bootloader::ensafe_first_bios_drive($hds) - || $b->{bootUnsafe} || arch() =~ /ppc/ or return 1; #- default is good enough + || $b->{bootUnsafe} or return 1; #- default is good enough if (arch() !~ /ia64/) { setupBootloader__mbr_or_not($in, $b, $hds, $fstab) or return 0; @@ -306,8 +321,7 @@ sub setupBootloader_simple { sub setupBootloader__boot_bios_drive { my ($in, $b, $hds) = @_; - if (arch() =~ /ppc/ || - !is_empty_hash_ref($b->{bios})) { + if (!is_empty_hash_ref($b->{bios})) { #- some bios mapping already there return 1; } elsif (bootloader::mixed_kind_of_disks($hds) && $b->{boot} =~ /\d$/) { #- on a partition @@ -318,7 +332,7 @@ sub setupBootloader__boot_bios_drive { log::l("_ask_boot_bios_drive"); my $hd = $in->ask_from_listf('', N("You decided to install the bootloader on a partition. -This implies you already have a bootloader on the hard drive you boot (eg: System Commander). +This implies you already have a bootloader on the hard disk drive you boot (eg: System Commander). On which drive are you booting?"), \&partition_table::description, $hds) or return 0; log::l("mixed_kind_of_disks chosen $hd->{device}"); @@ -326,19 +340,24 @@ On which drive are you booting?"), \&partition_table::description, $hds) or retu 1; } +sub _ask_mbr_or_not { + my ($in, $default, @l) = @_; + $in->ask_from_({ title => N("Bootloader Installation"), + interactive_help_id => 'setupBootloaderBeginner', + }, + [ + { label => N("Where do you want to install the bootloader?"), title => 1 }, + { val => \$default, list => \@l, format => sub { $_[0][0] }, type => 'list' }, + ] + ); + $default; +} + sub setupBootloader__mbr_or_not { my ($in, $b, $hds, $fstab) = @_; log::l("setupBootloader__mbr_or_not"); - if (arch() =~ /ppc/) { - if (defined $partition_table::mac::bootstrap_part) { - $b->{boot} = $partition_table::mac::bootstrap_part; - log::l("set bootstrap to $b->{boot}"); - } else { - die "no bootstrap partition - yaboot.conf creation failed"; - } - } else { my $floppy = detect_devices::floppy(); my @l = ( @@ -355,89 +374,77 @@ sub setupBootloader__mbr_or_not { ); my $default = find { $_->[1] eq $b->{boot} } @l; - $in->ask_from_({ title => N("Bootloader Installation"), - interactive_help_id => 'setupBootloaderBeginner', - }, - [ - { label => N("Where do you want to install the bootloader?"), title => 1 }, - { val => \$default, list => \@l, format => sub { $_[0][0] }, type => 'list' }, - ] - ); + if (!$::isInstall) { + $default = _ask_mbr_or_not($in, $default, @l); + } my $new_boot = $default->[1]; #- remove bios mapping if the user changed the boot device delete $b->{bios} if $new_boot && $new_boot ne $b->{boot}; $b->{boot} = $new_boot or return; - } 1; } sub setupBootloader__general { - my ($in, $b, $all_hds, $fstab, $security) = @_; + my ($in, $b, $all_hds, $fstab, $_security) = @_; return if detect_devices::is_xbox(); my @method_choices = bootloader::method_choices($all_hds); my $prev_force_acpi = my $force_acpi = bootloader::get_append_with_key($b, 'acpi') !~ /off|ht/; my $prev_enable_apic = my $enable_apic = !bootloader::get_append_simple($b, 'noapic'); my $prev_enable_lapic = my $enable_lapic = !bootloader::get_append_simple($b, 'nolapic'); - my $prev_clean_tmp = my $clean_tmp = any { $_->{mntpoint} eq '/tmp' } @{$all_hds->{special} ||= []}; + my $prev_enable_smp = my $enable_smp = !bootloader::get_append_simple($b, 'nosmp'); my $prev_boot = $b->{boot}; my $prev_method = $b->{method}; $b->{password2} ||= $b->{password} ||= ''; $::Wizard_title = N("Boot Style Configuration"); - if (arch() !~ /ppc/) { - my (@boot_devices, %boot_devices); + my (@boot_devices, %boot_devices); + if (is_uefi()) { + @boot_devices = 'ESP'; + %boot_devices = (ESP => N("EFI System Partition")); + } else { foreach (bootloader::allowed_boot_parts($b, $all_hds)) { my $dev = "/dev/$_->{device}"; push @boot_devices, $dev; - $boot_devices{$dev} = $_->{info} ? "$dev ($_->{info})" : $dev; + my $name = $_->{mntpoint} || $_->{info} || $_->{device_LABEL}; + unless ($name) { + $name = formatXiB($_->{size}*512) . " " if $_->{size}; + $name .= $_->{fs_type}; + } + $boot_devices{$dev} = $name ? "$dev ($name)" : $dev; } + } - $in->ask_from_({ #messages => N("Bootloader main options"), - title => N("Bootloader main options"), - interactive_help_id => 'setupBootloader', - }, [ + $in->ask_from_({ #messages => N("Bootloader main options"), + title => N("Bootloader main options"), + interactive_help_id => 'setupBootloader', + }, [ #title => N("Bootloader main options"), { label => N("Bootloader"), title => 1 }, - { label => N("Bootloader to use"), val => \$b->{method}, list => \@method_choices, format => \&bootloader::method2text }, - if_(arch() !~ /ia64/, - { label => N("Boot device"), val => \$b->{boot}, list => \@boot_devices, format => sub { $boot_devices{$_[0]} } }, - ), + { label => N("Bootloader to use"), val => \$b->{method}, + list => \@method_choices, format => \&bootloader::method2text }, + { label => N("Boot device"), val => \$b->{boot}, list => \@boot_devices, allow_empty_list => 1, + format => sub { $boot_devices{$_[0]} } }, { label => N("Main options"), title => 1 }, { label => N("Delay before booting default image"), val => \$b->{timeout} }, - { text => N("Enable ACPI"), val => \$force_acpi, type => 'bool' }, - { text => N("Enable APIC"), val => \$enable_apic, type => 'bool', advanced => 1, disabled => sub { !$enable_lapic } }, + { text => N("Enable ACPI"), val => \$force_acpi, type => 'bool', advanced => 1 }, + { text => N("Enable SMP"), val => \$enable_smp, type => 'bool', advanced => 1 }, + { text => N("Enable APIC"), val => \$enable_apic, type => 'bool', advanced => 1, + disabled => sub { !$enable_lapic } }, { text => N("Enable Local APIC"), val => \$enable_lapic, type => 'bool', advanced => 1 }, - if_($security >= 4 || $b->{password} || $b->{restricted}, + { label => N("Security"), title => 1 }, { label => N("Password"), val => \$b->{password}, hidden => 1, validate => sub { - my $ok = $b->{password} eq $b->{password2} or $in->ask_warn('', [ N("The passwords do not match"), N("Please try again") ]); - my $ok2 = !($b->{password} && $b->{method} eq 'grub-graphic') or $in->ask_warn('', N("You can not use a password with %s", bootloader::method2text($b->{method}))); + my $ok = $b->{password} eq $b->{password2} + or $in->ask_warn('', [ N("The passwords do not match"), N("Please try again") ]); + my $ok2 = !($b->{password} && $b->{method} eq 'grub-graphic') + or $in->ask_warn('', N("You cannot use a password with %s", + bootloader::method2text($b->{method}))); $ok && $ok2; } }, { label => N("Password (again)"), val => \$b->{password2}, hidden => 1 }, - { text => N("Restrict command line options"), val => \$b->{restricted}, type => "bool", text => N("restrict"), - validate => sub { my $ok = !$b->{restricted} || $b->{password} or $in->ask_warn('', N("Option ``Restrict command line options'' is of no use without a password")); $ok } }, - ), - { text => N("Clean /tmp at each boot"), val => \$clean_tmp, type => 'bool', advanced => 1 }, ]) or return 0; - } else { - $b->{boot} = $partition_table::mac::bootstrap_part; - $in->ask_from_({ messages => N("Bootloader main options"), - title => N("Bootloader main options"), - interactive_help_id => 'setupYabootGeneral', - }, [ - { label => N("Bootloader to use"), val => \$b->{method}, list => \@method_choices, format => \&bootloader::method2text }, - { label => N("Init Message"), val => \$b->{'init-message'} }, - { label => N("Boot device"), val => \$b->{boot}, list => [ map { "/dev/$_" } (map { $_->{device} } (grep { isAppleBootstrap($_) } @$fstab)) ] }, - { label => N("Open Firmware Delay"), val => \$b->{delay} }, - { label => N("Kernel Boot Timeout"), val => \$b->{timeout} }, - { label => N("Enable CD Boot?"), val => \$b->{enablecdboot}, type => "bool" }, - { label => N("Enable OF Boot?"), val => \$b->{enableofboot}, type => "bool" }, - { label => N("Default OS?"), val => \$b->{defaultos}, list => [ 'linux', 'macos', 'macosx', 'darwin' ] }, - ]) or return 0; - } #- remove bios mapping if the user changed the boot device delete $b->{bios} if $b->{boot} ne $prev_boot; @@ -455,6 +462,11 @@ sub setupBootloader__general { if ($prev_force_acpi != $force_acpi) { bootloader::set_append_with_key($b, acpi => ($force_acpi ? '' : 'ht')); } + + if ($prev_enable_smp != $enable_smp) { + ($enable_smp ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'nosmp'); + } + if ($prev_enable_apic != $enable_apic) { ($enable_apic ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'noapic'); ($enable_apic ? \&bootloader::set_append_simple : \&bootloader::remove_append_simple)->($b, 'apic'); @@ -464,19 +476,110 @@ sub setupBootloader__general { ($enable_lapic ? \&bootloader::set_append_simple : \&bootloader::remove_append_simple)->($b, 'lapic'); } - if ($prev_clean_tmp != $clean_tmp) { - if ($clean_tmp && !fs::get::has_mntpoint('/tmp', $all_hds)) { - push @{$all_hds->{special}}, { device => 'none', mntpoint => '/tmp', fs_type => 'tmpfs' }; - } else { - @{$all_hds->{special}} = grep { $_->{mntpoint} ne '/tmp' } @{$all_hds->{special}}; - } - } - if (bootloader::main_method($prev_method) eq 'lilo' && bootloader::main_method($b->{method}) eq 'grub') { log::l("switching for lilo to grub, ensure we don't read lilo.conf anymore"); renamef("$::prefix/etc/lilo.conf", "$::prefix/etc/lilo.conf.unused"); } + if ($prev_method eq 'refind' && $b->{method} ne 'refind') { + log::l("switching from rEFInd, ensure we don't detect refind as the active boot method"); + renamef("$::prefix/boot/refind_linux.conf", "$::prefix/boot/refind_linux.conf.unused"); + } + if ($b->{method} eq 'refind') { + if (bootloader::main_method($prev_method) eq 'grub2') { + #- grub2 doesn't provide any entries we can use, so revert to the defaults + %$b = (); + setupBootloaderBeforeStandalone($in->do_pkgs, $b, $all_hds, $fstab); + $b->{method} = 'refind'; + $b->{boot} = 'ESP'; + undef $b->{default}; + } + setupBootloader__refind($in, $b, $fstab); + } else { + 1; + } +} + +sub setupBootloader__refind { + my ($in, $b, $fstab) = @_; + + my $already_in_refind = -e "$::prefix/boot/EFI/EFI/refind/refind.conf"; + my $already_in_default = -e "$::prefix/boot/EFI/EFI/BOOT/refind.conf"; + my $already_installed = $already_in_refind || $already_in_default; + + my $update_esp = !$already_installed; + my $as_default = $already_in_default || $b->{removable}; + + if (!defined $b->{banner_path}) { + #- We haven't yet read any existing configuration, either because we are doing a clean + #- install or because we are switching from a different bootloader. Try to read it now. + #- Even if we are doing a clean install, rEFInd may already be installed in the ESP. + bootloader::read_refind_config($b); + } + + my $use_nvram = $b->{use_nvram}; + my $banner_path = $b->{banner_path}; + my $banner_scale = $b->{banner_scale}; + my $banner_type = $banner_path eq 'refind_banner.png' ? 'banner' + : $banner_path eq 'mageia_theme.png' ? 'theme' + : 'custom'; + $in->ask_from_( + { + title => N("Bootloader Configuration"), + interactive_help_id => 'setupBootloader', + }, + [ + { label => N("Install Options"), title => 1, }, + { text => N("Install or update rEFInd in the EFI system partition"), + val => \$update_esp, type => 'bool', disabled => sub { !$already_installed } }, + { text => N("Install in /EFI/BOOT (removable device or workaround for some BIOSs)"), + val => \$as_default, type => 'bool', disabled => sub { !$update_esp } }, + { text => N("Configure rEFInd to store its variables in the EFI NVRAM"), + val => \$use_nvram, type => 'bool' }, + { label => N("Background"), title => 1, }, + { val => \$banner_type, type => 'combo', list => [ 'banner', 'theme', 'custom' ], + format => sub { + my ($choice) = @_; + +{ + 'banner' => N("rEFInd banner"), + 'theme' => N("Mageia theme"), + 'custom' => N("Custom"), + }->{$choice}; + }, + changed => sub { + if ($banner_type eq 'banner') { + $banner_path = 'refind_banner.png'; + $banner_scale = 'noscale'; + } elsif ($banner_type eq 'theme') { + $banner_path = 'mageia_theme.png'; + $banner_scale = 'fillscreen'; + } + } + }, + { val => \$banner_path, type => 'entry', disabled => sub { $banner_type ne 'custom' } }, + { val => \$banner_scale, type => 'combo', list => [ 'noscale', 'fillscreen' ], + format => sub { + my ($choice) = @_; + +{ + 'noscale' => N("No scaling"), + 'fillscreen' => N("Scale to fit"), + }->{$choice}; + } + }, + ] + ) or return 0; + + if ($update_esp) { + $b->{install_mode} = $as_default ? 'as_default' : 'as_refind'; + } else { + $b->{install_mode} = $as_default ? 'no_install' : 'nvram_only'; + } + $b->{use_nvram} = $use_nvram; + $b->{banner_path} = $banner_path; + $b->{banner_scale} = $banner_scale; + if (my @esp = grep { $_->{mntpoint} eq '/boot/EFI' } @$fstab) { + $b->{esp_device} = $esp[0]{real_device} || fs::wild_device::from_part('', $esp[0]); + } 1; } @@ -496,22 +599,29 @@ sub setupBootloader__entries { my %root_descr = map { my $info = delete $hd_infos{$_->{rootDevice}}; my $dev = "/dev/$_->{device}"; - my $info_ = $info ? "$dev ($info)" : $dev; + my $hint = $info || $_->{info} || $_->{device_LABEL}; + my $info_ = $hint ? "$dev ($hint)" : $dev; ($dev => $info_, fs::wild_device::from_part('', $_) => $info_); } @$fstab; my @l; - if ($e->{type} eq "image") { + if ($b->{method} eq 'refind') { + @l = ( + { label => N("Label"), val => \$e->{label} }, + { label => N("Append"), val => \$append }, + { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ], + format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 }, + ); + } elsif ($e->{type} eq "image") { @l = ( { label => N("Image"), val => \$e->{kernel_or_dev}, list => [ map { "/boot/$_" } bootloader::installed_vmlinuz() ], not_edit => 0 }, -{ label => N("Root"), val => \$e->{root}, list => [ map { fs::wild_device::from_part('', $_) } @$fstab ], format => sub { $root_descr{$_[0]} } }, +{ label => N("Root"), val => \$e->{root}, list => [ map { fs::wild_device::from_part('', $_) } grep { !isSwap($_) } @$fstab ], format => sub { $root_descr{$_[0]} } }, { label => N("Append"), val => \$append }, if_($e->{xen}, { label => N("Xen append"), val => \$e->{xen_append} } ), - if_(arch() !~ /ppc|ia64/, + if_($b->{password}, { label => N("Requires password to boot"), val => \$e->{lock}, type => "bool" }), { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ], format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 }, -), { label => N("Initrd"), val => \$e->{initrd}, list => [ map { if_(/^initrd/, "/boot/$_") } all("$::prefix/boot") ], not_edit => 0, advanced => 1 }, { label => N("Network profile"), val => \$netprofile, list => [ sort(uniq('', $netprofile, network::network::netprofile_list())) ], advanced => 1 }, ); @@ -520,26 +630,16 @@ sub setupBootloader__entries { { label => N("Root"), val => \$e->{kernel_or_dev}, list => [ map { "/dev/$_->{device}" } @$fstab, detect_devices::floppies() ] }, ); } - if (arch() !~ /ppc/) { + if ($b->{method} ne 'refind') { @l = ( { label => N("Label"), val => \$e->{label} }, @l, { text => N("Default"), val => \$default, type => 'bool' }, ); - } else { - unshift @l, { label => N("Label"), val => \$e->{label}, list => ['macos', 'macosx', 'darwin'] }; - if ($e->{type} eq "image") { - @l = ({ label => N("Label"), val => \$e->{label} }, - (@l[1..2], { label => N("Append"), val => \$append }), - { label => N("NoVideo"), val => \$e->{novideo}, type => 'bool' }, - { text => N("Default"), val => \$default, type => 'bool' } - ); - } } - $in->ask_from_( { - interactive_help_id => arch() =~ /ppc/ ? 'setupYabootAddEntry' : 'setupBootloaderAddEntry', + interactive_help_id => 'setupBootloaderAddEntry', callbacks => { complete => sub { $e->{label} or $in->ask_warn('', N("Empty label not allowed")), return 1; @@ -562,17 +662,22 @@ sub setupBootloader__entries { my $Add = sub { my @labels = map { $_->{label} } @{$b->{entries}}; my ($e, $prefix); - if ($in->ask_from_list_('', N("Which type of entry do you want to add?"), - [ N_("Linux"), arch() =~ /sparc/ ? N_("Other OS (SunOS...)") : arch() =~ /ppc/ ? - N_("Other OS (MacOS...)") : N_("Other OS (Windows...)") ] - ) eq "Linux") { + if ($b->{method} eq 'refind') { + $e = { type => 'image', + kernel_or_dev => '/boot/vmlinuz', + root => '/dev/' . fs::get::root($fstab)->{device}, #- assume a good default. + }; + $prefix = "linux"; + } elsif ($in->ask_from_list_('', N("Which type of entry do you want to add?"), + [ N_("Linux"), N_("Other OS (Windows...)") ] + ) eq "Linux") { $e = { type => 'image', root => '/dev/' . fs::get::root($fstab)->{device}, #- assume a good default. }; $prefix = "linux"; } else { $e = { type => 'other' }; - $prefix = arch() =~ /sparc/ ? "sunos" : arch() =~ /ppc/ ? "macos" : "windows"; + $prefix = "windows"; } $e->{label} = $prefix; for (my $nb = 0; member($e->{label}, @labels); $nb++) { @@ -590,17 +695,49 @@ sub setupBootloader__entries { 1; }; + my $Up = sub { + my ($e) = @_; + my @entries = @{$b->{entries}}; + my ($index) = grep { $entries[$_]{label} eq $e->{label} } 0..$#entries; + if ($index > 0) { + ($b->{entries}[$index - 1], $b->{entries}[$index]) = ($b->{entries}[$index], $b->{entries}[$index - 1]); + } + 1; + }; + + my $Down = sub { + my ($e) = @_; + my @entries = @{$b->{entries}}; + my ($index) = grep { $entries[$_]{label} eq $e->{label} } 0..$#entries; + if ($index < $#entries) { + ($b->{entries}[$index + 1], $b->{entries}[$index]) = ($b->{entries}[$index], $b->{entries}[$index + 1]); + } + 1; + }; + my @prev_entries = @{$b->{entries}}; + + #- the rEFInd configuration file just provides alternative kernel command lines + #- so we only want to display entries that relate to the default kernel. + if ($b->{method} eq 'refind') { + @{$b->{entries}} = + grep { + my $pb = $_->{type} ne 'image' || $_->{kernel_or_dev} ne '/boot/vmlinuz'; + log::l("dropping bootloader entry $_->{label} because it is not needed by rEFInd") if $pb; + !$pb; + } @{$b->{entries}}; + } + if ($in->ask_from__add_modify_remove(N("Bootloader Configuration"), N("Here are the entries on your boot menu so far. You can create additional entries or change the existing ones."), [ { format => sub { my ($e) = @_; ref($e) ? - ($b->{default} eq $e->{label} ? " * " : " ") . "$e->{label} ($e->{kernel_or_dev})" : + ($b->{default} eq $e->{label} ? " * " : " ") . "$e->{label} ($e->{kernel_or_dev})" : translate($e); }, list => $b->{entries}, - } ], Add => $Add, Modify => $Modify, Remove => $Remove)) { + } ], Add => $Add, Modify => $Modify, Remove => $Remove, Up => $Up, Down => $Down)) { 1; } else { @{$b->{entries}} = @prev_entries; @@ -608,52 +745,214 @@ You can create additional entries or change the existing ones."), [ { } } +sub setupBootloader__grub2 { + my ($in, $b, $_all_hds, $_fstab) = @_; + + # update entries (so that we can display their list below): + my $error; + # grub2-update can take many minutes on some systems (mga#18538) + # FIXME: change the message to be more informative + my $_w = $in->wait_message(N("Please wait"), N("Please wait")); + run_program::rooted($::prefix, 'update-grub2', '2>', \$error) or die "update-grub2 failed: $error"; + undef $_w; + + # read grub2 auto-generated entries (instead of keeping eg: grub/lilo ones): + my $b2 = bootloader::read_grub2(); + + # get default parameters: + my $append = $b->{perImageAppend} || bootloader::get_grub2_append($b2); + my $default = $b2->{default}; + + require Xconfig::resolution_and_depth; + + require network::network; #- to list network profiles + my $vga = Xconfig::resolution_and_depth::from_bios($b->{default_vga}); + my $os_prober = $in->do_pkgs->is_installed('os-prober', '/usr/bin/os-prober') && !$b->{default_to_no_probe}; + + my $res = $in->ask_from_( + { + title => N("Bootloader Configuration"), + interactive_help_id => 'setupBootloaderAddEntry', + }, + [ + { label => N("Default"), val => \$default, + list => [ map { $_->{label} } @{$b2->{entries}} ] }, + { label => N("Append"), val => \$append }, + { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ], + format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 }, + { text => N("Do not touch ESP or MBR"), val => \$b->{no_esp_or_mbr}, type => 'bool', advanced => 1, + validate => sub { + $b->{no_esp_or_mbr} and $in->ask_warn(N("Warning"), + N("Not installing on ESP or MBR means that the installation is not bootable unless chain loaded from another OS!")); + 1; + }, + }, + { text => N("Probe Foreign OS"), val => \$os_prober, type => 'bool', + help => N("Unselect this option to stop grub2 scanning for other operating systems, which will prevent them from being included in the grub2 boot menu. The option may also be unselected after installation, removing the other operating systems from the grub2 boot menu, but reducing the time needed for installing kernel updates"), + }, + if_(is_uefi(), + { text => N("Install in /EFI/BOOT (removable device or workaround for some BIOSs)"), + val => \$b->{removable}, type => 'bool' }, + ), + ]); + if ($res) { + $b->{entries} = $b2->{entries}; + $b->{default} = $default; + $b->{default_vga} = ref($vga) ? $vga->{bios} : $vga; + $b->{perImageAppend} = $append; + if ($os_prober) { + $in->do_pkgs->ensure_is_installed('os-prober', '/usr/bin/os-prober'); + } else { + $in->do_pkgs->remove('os-prober'); + } + 1; + } else { + ''; + } +} + +sub get_session_file { + my ($desktop) = @_; + my @dir_wm = qw(xsessions wayland-sessions); + my $xsession_file; + foreach my $dwm (@dir_wm) { + my $xs_file = find { + my %xsession = read_gnomekderc($_, 'Desktop Entry'); + $xsession{Name} =~ s/\s+//g; + $xsession{Name} eq ${desktop}; + } glob("$::prefix/usr/share/$dwm/*.desktop"); + $xsession_file = $xs_file unless $xsession_file; + } + $xsession_file =~ s!\.[^.]+$!!; + $xsession_file =~ s!.*/!!; + $xsession_file ||= $desktop; + return $xsession_file; +} + +sub get_session_file_with_extension { + return get_session_file(@_) . '.desktop'; +} + +sub available_dms() { + my @l; + foreach (glob("$::prefix/usr/share/X11/dm.d/*.conf")) { + my %dm = getVarsFromSh($_); + push @l, $dm{EXEC} if $dm{EXEC} && -x "$::prefix/$dm{EXEC}"; + } + @l; +} + sub get_autologin() { my %desktop = getVarsFromSh("$::prefix/etc/sysconfig/desktop"); my $gdm_file = "$::prefix/etc/X11/gdm/custom.conf"; - my $kdm_file = common::read_alternative('kdm4-config'); - my $desktop = $desktop{DESKTOP} || (! -e $kdm_file && -e $gdm_file ? 'GNOME' : 'KDE4'); - my $autologin = do { - if (($desktop{DISPLAYMANAGER} || $desktop) eq 'GNOME') { - my %conf = read_gnomekderc($gdm_file, 'daemon'); - text2bool($conf{AutomaticLoginEnable}) && $conf{AutomaticLogin}; - } else { # KDM / MdkKDM - my %conf = read_gnomekderc($kdm_file, 'X-:0-Core'); - text2bool($conf{AutoLoginEnable}) && $conf{AutoLoginUser}; - } - }; - { autologin => $autologin, desktop => $desktop }; + my $sddm_file = "$::prefix/etc/sddm.conf"; + my $lightdm_conffile = "$::prefix/etc/lightdm/lightdm.conf.d/50-mageia-autologin.conf"; + my $lxdm_conffile = "$::prefix/etc/lxdm/lxdm.conf"; + my $autologin_file = "$::prefix/etc/sysconfig/autologin"; + my $desktop = $desktop{DESKTOP} || first(sessions()); + my %desktop_to_dm = ( + GNOME => 'gdm', + Plasma => 'sddm', + Xfce => 'lightdm', + LXDE => 'lxdm', + ); + my $dm = + basename(readlink("$::prefix/etc/systemd/system/display-manager.service")) =~ s/(.*)\.service/$1/r || + $desktop_to_dm{$desktop} || + basename(first(available_dms())); + + my $autologin_user; + if ($dm eq "gdm") { + my %conf = read_gnomekderc($gdm_file, 'daemon'); + $autologin_user = text2bool($conf{AutomaticLoginEnable}) && $conf{AutomaticLogin}; + } elsif ($dm eq "sddm") { + my %conf = read_gnomekderc($sddm_file, 'Autologin'); + $autologin_user = $conf{User}; + } elsif ($dm eq "lightdm") { + my %conf = read_gnomekderc($lightdm_conffile, 'Seat:*'); + $autologin_user = text2bool($conf{'#dummy-autologin'}) && $conf{"autologin-user"}; + } elsif ($dm eq "lxdm") { + my %conf = read_gnomekderc($lxdm_conffile, 'base'); + $autologin_user = $conf{autologin}; + $autologin_user =~ s/^.//; + } else { + my %conf = getVarsFromSh($autologin_file); + $autologin_user = text2bool($conf{AUTOLOGIN}) && $conf{USER}; + } + + { user => $autologin_user, desktop => $desktop, dm => $dm }; +} + +sub is_standalone_autologin_needed { + my ($dm) = @_; + return member($dm, qw(slim xdm)); } sub set_autologin { - my ($do_pkgs, $o_user, $o_wm) = @_; - log::l("set_autologin $o_user $o_wm"); - my $autologin = bool2text($o_user); + my ($do_pkgs, $autologin, $o_auto) = @_; + log::l("set_autologin $autologin->{user} $autologin->{desktop}"); + my $do_autologin = bool2text($autologin->{user}); + + $autologin->{dm} ||= 'xdm'; + $do_pkgs->ensure_is_installed($autologin->{dm}, undef, $o_auto) + or return; + if ($autologin->{user} && is_standalone_autologin_needed($autologin->{dm})) { + $do_pkgs->ensure_is_installed('autologin', '/usr/bin/startx.autologin', $o_auto) + or return; + } - #- Configure KDM / MDKKDM - eval { common::update_gnomekderc_no_create(common::read_alternative('kdm4-config'), 'X-:0-Core' => ( - AutoLoginEnable => $autologin, - AutoLoginUser => $o_user, - )) }; + #- Configure SDDM + my $sddm_conffile = "$::prefix/etc/sddm.conf"; + eval { common::update_gnomekderc_no_create($sddm_conffile, 'Autologin' => ( + Session => get_session_file_with_extension($autologin->{desktop}), + User => $autologin->{user}, + )) } if -e $sddm_conffile; #- Configure GDM - eval { update_gnomekderc("$::prefix/etc/X11/gdm/custom.conf", daemon => ( - AutomaticLoginEnable => $autologin, - AutomaticLogin => $o_user, - )) }; - + my $gdm_conffile = "$::prefix/etc/X11/gdm/custom.conf"; + eval { update_gnomekderc($gdm_conffile, daemon => ( + AutomaticLoginEnable => $do_autologin, + AutomaticLogin => $autologin->{user}, + )) } if -e $gdm_conffile; + + #- Configure LIGHTDM + my $lightdm_conffile = "$::prefix/etc/lightdm/lightdm.conf.d/50-mageia-autologin.conf"; + eval { update_gnomekderc($lightdm_conffile, 'Seat:*' => ( + '#dummy-autologin' => $do_autologin, + 'autologin-user' => $autologin->{user}, + 'autologin-session' => get_session_file($autologin->{desktop}), + )) } if -e $lightdm_conffile; + + #- Configure LXDM + my $lxdm_conffile = "$::prefix/etc/lxdm/lxdm.conf"; + eval { update_gnomekderc($lxdm_conffile, 'base' => ( + 'autologin' => $autologin->{user} ? '@' . $autologin->{user} : '' + )); + if ($autologin->{user} && $autologin->{desktop} && !member($autologin->{desktop}, qw(default failsafe))) { + update_gnomekderc($lxdm_conffile, $autologin->{user} => ( + 'user' => $autologin->{user}, + 'session' => get_session_file($autologin->{desktop}), + )) } } if -e $lxdm_conffile; + + #- Configure XDM my $xdm_autologin_cfg = "$::prefix/etc/sysconfig/autologin"; - if (member($o_wm, 'KDE', 'KDE4', 'GNOME')) { - unlink $xdm_autologin_cfg; - } else { - $do_pkgs->ensure_is_installed('autologin', '/usr/bin/startx.autologin') if $o_user; + if (is_standalone_autologin_needed($autologin->{dm})) { setVarsInShMode($xdm_autologin_cfg, 0644, - { USER => $o_user, AUTOLOGIN => bool2yesno($o_user), EXEC => '/usr/bin/startx.autologin' }); + { USER => $autologin->{user}, AUTOLOGIN => bool2yesno($autologin->{user}), EXEC => '/usr/bin/startx.autologin' }); + } else { + unlink $xdm_autologin_cfg; } - if ($o_user) { - my $home = (getpwnam($o_user))[7]; - set_window_manager($home, $o_wm); + my $sys_conffile = "$::prefix/etc/sysconfig/desktop"; + my %desktop = getVarsFromSh($sys_conffile); + $desktop{DESKTOP} = $autologin->{desktop}; + $desktop{DISPLAYMANAGER} = $autologin->{dm}; + setVarsInSh($sys_conffile, \%desktop); + symlinkf("/usr/lib/systemd/system/$autologin->{dm}.service", "$::prefix/etc/systemd/system/display-manager.service"); + + if ($autologin->{user}) { + my $home = (getpwnam($autologin->{user}))[7]; + set_window_manager($home, $autologin->{desktop}); } } sub set_window_manager { @@ -674,10 +973,6 @@ sub set_window_manager { $l{DESKTOP} = $wm; setVarsInSh("$p_home/.desktop", \%l); } - my $sys_conffile = "$::prefix/etc/sysconfig/desktop"; - my %desktop = getVarsFromSh($sys_conffile); - $desktop{DESKTOP} = $wm; - setVarsInSh($sys_conffile, \%desktop); } sub rotate_log { @@ -690,7 +985,7 @@ sub rotate_log { } sub rotate_logs { my ($prefix) = @_; - rotate_log("$prefix/root/drakx/$_") foreach qw(ddebug.log install.log); + rotate_log("$prefix/root/drakx/$_") foreach qw(stage1.log ddebug.log install.log updates.log); } sub writeandclean_ldsoconf { @@ -699,7 +994,7 @@ sub writeandclean_ldsoconf { my @l = chomp_(cat_($file)); my @default = ('/lib', '/usr/lib'); #- no need to have /lib and /usr/lib in ld.so.conf - my @suggest = ('/usr/X11R6/lib', '/usr/lib/qt3/lib'); #- needed for upgrade where package renaming can cause this to disappear + my @suggest = ('/usr/lib/qt3/lib'); #- needed for upgrade where package renaming can cause this to disappear if (arch() =~ /x86_64/) { @default = map { $_, $_ . '64' } @default; @@ -748,9 +1043,15 @@ sub ask_user { ask_user_and_root($in, undef, $users, $security, %options); } +sub is_xguest_installed() { + -e "$::prefix/etc/security/namespace.d/xguest.conf"; +} + sub ask_user_and_root { my ($in, $superuser, $users, $security, %options) = @_; + my $xguest = is_xguest_installed(); + $options{needauser} ||= $security >= 3; my @icons = facesnames(); @@ -778,7 +1079,7 @@ sub ask_user_and_root { require authentication; my $validate_name = sub { $u->{name} or $in->ask_warn('', N("Please give a user name")), return; - $u->{name} =~ /^[a-z]+?[a-z0-9_-]*?$/ or $in->ask_warn('', N("The user name must contain only lower cased letters, numbers, `-' and `_'")), return; + $u->{name} =~ /^[a-z]+[a-z0-9_-]*$/ or $in->ask_warn('', N("The user name must start with a lower case letter followed by only lower cased letters, numbers, `-' and `_'")), return; length($u->{name}) <= 32 or $in->ask_warn('', N("The user name is too long")), return; defined getpwnam($u->{name}) || member($u->{name}, map { $_->{name} } @$users) and $in->ask_warn('', N("This user name has already been added")), return; 'ok'; @@ -788,18 +1089,21 @@ sub ask_user_and_root { my $id = $u->{$field} or return 'ok'; my $name = $field eq 'uid' ? N("User ID") : N("Group ID"); $id =~ /^\d+$/ or $in->ask_warn('', N("%s must be a number", $name)), return; - $id >= 500 or $in->ask_yesorno('', N("%s should be above 500. Accept anyway?", $name)) or return; + $id >= 1000 or $in->ask_yesorno('', N("%s should be above 1000. Accept anyway?", $name)) or return; 'ok'; }; my $ret = $in->ask_from_( { title => N("User management"), interactive_help_id => 'addUser', if_($::isInstall && $superuser, cancel => ''), - focus_first => 1, }, [ $superuser ? ( + if_(0, + { text => N("Enable guest account"), val => \$xguest, type => 'bool', advanced => 1 }, + ), { label => N("Set administrator (root) password"), title => 1 }, - { label => N("Password"), val => \$superuser->{password}, hidden => 1, alignment => 'right', + { label => N("Password"), val => \$superuser->{password}, hidden => 1, alignment => 'right', weakness_check => 1, + focus => sub { 1 }, validate => sub { authentication::check_given_password($in, $superuser, 2 * $security) } }, { label => N("Password (again)"), val => \$superuser->{password2}, hidden => 1, alignment => 'right' }, ) : (), @@ -809,24 +1113,35 @@ sub ask_user_and_root { alignment => 'right', format => \&translate }, ), { label => N("Real name"), val => \$u->{realname}, alignment => 'right', focus_out => sub { - $u->{name} ||= lc first($u->{realname} =~ /([a-zA-Z0-9_-]+)/); - } }, + $u->{name} ||= lc(Locale::gettext::iconv($u->{realname}, "utf-8", "ascii//TRANSLIT")); + $u->{name} =~ s/[^a-zA-Z0-9_-]//g; # drop any character that would break login program + }, + focus => sub { !$superuser }, + }, { label => N("Login name"), val => \$u->{name}, list => \@suggested_names, alignment => 'right', not_edit => 0, validate => $validate_name }, - { label => N("Password"),val => \$u->{password}, hidden => 1, alignment => 'right', + { label => N("Password"),val => \$u->{password}, hidden => 1, alignment => 'right', weakness_check => 1, validate => sub { authentication::check_given_password($in, $u, $security > 3 ? 6 : 0) } }, { label => N("Password (again)"), val => \$u->{password2}, hidden => 1, alignment => 'right' }, { label => N("Shell"), val => \$u->{shell}, list => [ shells() ], advanced => 1 }, { label => N("User ID"), val => \$u->{uid}, advanced => 1, validate => sub { $validate_uid_gid->('uid') } }, { label => N("Group ID"), val => \$u->{gid}, advanced => 1, validate => sub { $validate_uid_gid->('gid') } }, - if_($security > 3, + if_($security >= 1, + { label => N("Extra Groups:"), advanced => 1, title => 1 }, map { - { label => $_, val => \$groups{$_}, text => $high_security_groups{$_}, type => 'bool' }; + { label => $_, val => \$groups{$_}, text => $high_security_groups{$_}, type => 'bool', advanced => 1 }; } keys %high_security_groups, ), ], ); + + if ($xguest && !is_xguest_installed()) { + $in->do_pkgs->ensure_is_installed('xguest', '/etc/security/namespace.d/xguest.conf'); + } elsif (!$xguest && is_xguest_installed()) { + $in->do_pkgs->remove('xguest') or return; + } + $u->{groups} = [ grep { $groups{$_} } keys %groups ]; push @$users, $u if $u->{name}; @@ -835,7 +1150,12 @@ sub ask_user_and_root { } sub sessions() { - split(' ', run_program::rooted_get_stdout($::prefix, '/usr/sbin/chksession', '-l')); + my @l; + my @dir_wm = qw(xsessions wayland-sessions); + foreach my $dwm (@dir_wm) { + push @l, map { s/.desktop$//; basename($_) } glob("$::prefix/usr/share/$dwm/*.desktop"); + } + @l; } sub sessions_with_order() { my %h = map { /(.*)=(.*)/ } split(' ', run_program::rooted_get_stdout($::prefix, '/usr/sbin/chksession', '-L')); @@ -843,18 +1163,32 @@ sub sessions_with_order() { } sub urpmi_add_all_media { - my ($in, $o_previous_release) = @_; + my ($in, $o_previous_release, $o_mirror_url) = @_; - my $binary = find { whereis_binary($_, $::prefix) } 'gurpmi.addmedia', 'urpmi.addmedia' or return; + $o_mirror_url = undef if $o_mirror_url eq '$MIRRORLIST'; + + my $binary = find { whereis_binary($_, $::prefix) } if_(check_for_xserver(), 'gurpmi.addmedia'), 'urpmi.addmedia'; + if (!$binary) { + log::l("urpmi.addmedia not found!"); + return; + } #- configure urpmi media if network is up require network::tools; - return if !network::tools::has_network_connection(); + if (!network::tools::has_network_connection()) { + log::l("no network connexion!"); + return; + } + # First remove all media: + run_program::rooted($::prefix, 'urpmi.removemedia', '-a'); + # Then add online media: my $wait; + my @options = $o_mirror_url ? ( '--distrib', $o_mirror_url) : ('--distrib', '--mirrorlist', '$MIRRORLIST'); if ($binary eq 'urpmi.addmedia') { $wait = $in->wait_message(N("Please wait"), N("Please wait, adding media...")); } elsif ($in->isa('interactive::gtk')) { - mygtk2::flush(); + push @options, '--silent-success'; + mygtk3::flush(); } my $reason = join(',', $o_previous_release ? @@ -863,7 +1197,46 @@ sub urpmi_add_all_media { log::l("URPMI_ADDMEDIA_REASON $reason"); local $ENV{URPMI_ADDMEDIA_REASON} = $reason; - run_program::rooted($::prefix, $binary, '--distrib', '--mirrorlist', '$MIRRORLIST'); + my $log_file = '/root/drakx/updates.log'; + my $val = run_program::rooted($::prefix, $binary, '>>', $log_file, '2>>', $log_file, @options); + + undef $wait; + $val; +} + +sub urpmi_set_downloader { + my ($in, $urpm, $downloader) = @_; + + if ($urpm->{global_config}{downloader} ne $downloader) { + my $binary = $downloader eq 'aria2' ? 'aria2c' : $downloader; + if ($in->do_pkgs->ensure_binary_is_installed($downloader, $binary, 1)) { + log::l("Setting urpmi downloader to '$downloader'"); + $urpm->{global_config}{downloader} = $downloader; + urpm::media::write_config($urpm); + } else { + return; + } + } + 1; +} + +sub format_wm { + my ($wm) = @_; + return { + cinnamon => 'Cinnamon', + enlightenment => 'Enlightenment', + 'gnome-classic' => 'GNOME Classic', + gnome => 'GNOME', + i3 => 'I3', + 'i3-with-shmlog' => 'I3 with shmlog', + lxqt => 'LxQt', + mate => 'Mate', + openbox => 'OpenBox', + 'plasma-mediacenter' => 'Plasma Mediacenter', + '01plasma' => 'Plasma', + sugar => 'Sugar', + xfce => 'Xfce', + }->{$wm}; } sub autologin { @@ -884,7 +1257,7 @@ sub autologin { messages => N("I can set up your computer to automatically log on one user.") }, [ { text => N("Use this feature"), val => \$use_autologin, type => 'bool' }, { label => N("Choose the default user:"), val => \$o->{autologin}, list => \@users, disabled => sub { !$use_autologin } }, - { label => N("Choose the window manager to run:"), val => \$o->{desktop}, list => \@wm, disabled => sub { !$use_autologin } } ] + { label => N("Choose the window manager to run:"), val => \$o->{desktop}, list => \@wm, disabled => sub { !$use_autologin }, format => \&format_wm } ] ); delete $o->{autologin} if !$use_autologin; } else { @@ -893,74 +1266,82 @@ sub autologin { } sub display_release_notes { - my ($o) = @_; - if (!$o->isa('interactive::gtk')) { - $o->ask_from_({ title => N("Release Notes"), - messages => $o->{release_notes}, #formatAlaTeX(messages::main_license()), + my ($in, $release_notes) = @_; + if (!$in->isa('interactive::gtk')) { + $in->ask_from_({ title => N("Release Notes"), + messages => $release_notes, }, [ {} ]); return; } - require Gtk2::Html2; - require ugtk2; - ugtk2->import(':all'); - require mygtk2; - mygtk2->import('gtknew'); - my $view = Gtk2::Html2::View->new; - my $document = Gtk2::Html2::Document->new; - $view->set_document($document); - - $document->clear; - $document->open_stream("text/html"); - $document->write_stream($o->{release_notes}); + + require Gtk3::WebKit2; + Gtk3::WebKit2->import; + require ugtk3; + ugtk3->import(':all'); + require mygtk3; + mygtk3->import('gtknew'); + my $view = gtknew('WebKit2_WebView', no_popup_menu => 1); + $view->load_html($release_notes, '/'); - my $w = ugtk2->new(N("Release Notes"), transient => $::main_window, modal => 1, pop_it => 1); + my $w = ugtk3->new(N("Release Notes"), transient => $::main_window, modal => 1, pop_it => 1); gtkadd($w->{rwindow}, - gtkpack_(Gtk2::VBox->new, - 1, create_scrolled_window(ugtk2::gtkset_border_width($view, 5), + gtkpack_(Gtk3::VBox->new, + 1, create_scrolled_window(ugtk3::gtkset_border_width($view, 5), [ 'never', 'automatic' ], ), - 0, gtkpack(create_hbox('edge'), + 0, gtkpack(create_hbox('end'), gtknew('Button', text => N("Close"), - clicked => sub { Gtk2->main_quit }) + clicked => sub { Gtk3->main_quit }) ), ), ); - mygtk2::set_main_window_size($w->{rwindow}); + mygtk3::set_main_window_size($w->{rwindow}); $w->{real_window}->grab_focus; $w->{real_window}->show_all; $w->main; return; } -sub acceptLicense { - my ($o) = @_; - require messages; - - my $ext = $o->isa('interactive::gtk') ? '.html' : '.txt'; - my $separator = $o->isa('interactive::gtk') ? "\n\n" : ''; +sub get_release_notes { + my ($in) = @_; + my $ext = $in->isa('interactive::gtk') ? '.html' : '.txt'; + my $separator = $in->isa('interactive::gtk') ? "\n\n" : ''; - $o->{release_notes} = join($separator, grep { $_ } map { + my $release_notes = join($separator, grep { $_ } map { if ($::isInstall) { - my $f = install::any::getFile_($o->{stage2_phys_medium}, $_); + my $f = install::any::getFile_($::o->{stage2_phys_medium}, $_); $f && cat__($f); } else { my $file = $_; my $d = find { -e "$_/$file" } glob_("/usr/share/doc/*-release-*"); $d && cat_("$d/$file"); } - } "release-notes$ext", 'release-notes.' . arch() . $ext); + } "release-notes$ext", 'release-notes.' . $ext); # we do not handle links: - $o->{release_notes} =~ s!<a href=".*?">(.*?)</a>!$1!g; + $release_notes =~ s!<a href=".*?">(.*?)</a>!$1!g; + $release_notes; +} + +sub run_display_release_notes { + my ($release_notes) = @_; + output('/tmp/release_notes.html', $release_notes); + local $ENV{LC_ALL} = $::o->{locale}{lang} || 'C'; + run_program::raw({ detach => 1 }, '/usr/bin/display_release_notes.pl'); +} - return if $o->{useless_thing_accepted}; +sub acceptLicense { + my ($in) = @_; + require messages; + + my $release_notes = get_release_notes($in); my $r = $::testing ? 'Accept' : 'Refuse'; - $o->ask_from_({ title => N("License agreement"), + $in->ask_from_({ title => N("License agreement"), focus_first => 1, cancel => N("Quit"), - messages => formatAlaTeX(messages::main_license() . "\n\n\n" . messages::warning_about_patents()), + messages => formatAlaTeX(messages::main_license()), interactive_help_id => 'acceptLicense', callbacks => { ok_disabled => sub { $r eq 'Refuse' } }, }, @@ -969,24 +1350,23 @@ sub acceptLicense { { label => N("Do you accept this license ?"), title => 1, alignment => 'right' }, { list => [ N_("Accept"), N_("Refuse") ], val => \$r, type => 'list', alignment => 'right', format => sub { translate($_[0]) } }, - if_($o->{release_notes}, - { clicked => sub { display_release_notes($o) }, do_not_expand => 1, + if_($release_notes, + { clicked => sub { run_display_release_notes($release_notes) }, do_not_expand => 1, val => \ (my $_t1 = N("Release Notes")), install_button => 1, no_indent => 1 } ), ]) - or reboot($o); + or reboot(); } -sub reboot { - my ($o) = @_; - +sub reboot() { if ($::isInstall) { + my $o = $::o; install::media::umount_phys_medium($o->{stage2_phys_medium}); install::media::openCdromTray($o->{stage2_phys_medium}{device}) if !detect_devices::is_xbox() && $o->{method} eq 'cdrom'; $o->exit; } else { # when refusing license in finish-install: - exec("/sbin/reboot"); + exec("/bin/reboot"); } } @@ -1020,25 +1400,22 @@ sub selectLanguage_install { } my $non_utf8 = 0; - my $utf8_forced; add2hash($common, { cancel => '', focus_first => 1, - advanced_messages => formatAlaTeX(N("Mandriva Linux can support multiple languages. Select + advanced_messages => formatAlaTeX(N("%s can support multiple languages. Select the languages you would like to install. They will be available -when your installation is complete and you restart your system.")), - advanced_label => N("Multi languages"), +when your installation is complete and you restart your system.", N("Mageia"))), + advanced_label => N("Multiple languages"), + advanced_title => N("Select Additional Languages"), }); $in->ask_from_($common, [ { val => \$lang, separator => '|', if_($using_images, image2f => sub { $name2l{$_[0]} =~ /^[a-z]/ && "langs/lang-$name2l{$_[0]}" }), format => sub { $_[0] =~ /(.*\|)(.*)/ ? $1 . lang::l2name($2) : lang::l2name($_[0]) }, - list => \@langs, sort => !$in->isa('interactive::gtk'), changed => sub { - #- very special cases for langs which do not like UTF-8 - $non_utf8 = $lang =~ /\bzh_TW/i if !$utf8_forced; - }, focus_out => sub { $langs->{$listval2val->($lang)} = 1 } }, - { val => \$non_utf8, type => 'bool', text => N("Old compatibility (non UTF-8) encoding"), - advanced => 1, changed => sub { $utf8_forced = 1 } }, + list => \@langs, sort => !$in->isa('interactive::gtk'), + focus_out => sub { $langs->{$listval2val->($lang)} = 1 } }, + { val => \$non_utf8, type => 'bool', text => N("Old compatibility (non UTF-8) encoding"), advanced => 1 }, { val => \$langs->{all}, type => 'bool', text => N("All languages"), advanced => 1 }, map { { val => \$langs->{$_->[0]}, type => 'bool', disabled => sub { $langs->{all} }, @@ -1073,7 +1450,7 @@ sub selectLanguage_standalone { ]); $locale->{utf8} = !$non_utf8; lang::set($locale); - Gtk2->set_locale if $in->isa('interactive::gtk'); + c::init_setlocale() if $in->isa('interactive::gtk'); lang::lang_changed($locale) if $old_lang ne $locale->{lang}; } @@ -1116,8 +1493,8 @@ sub selectCountry { $in->ask_from_( { title => N("Country / Region"), - messages => N("Please choose your country."), - interactive_help_id => 'selectCountry', + messages => N("Please choose your country"), + interactive_help_id => 'selectCountry.html', if_(@best, advanced_messages => N("Here is the full list of available countries")), advanced_label => @best ? N("Other Countries") : N("Advanced"), }, @@ -1143,44 +1520,64 @@ sub set_login_serial_console { substInFile { s/^s$port:.*//; $_ = $line if eof } "$::prefix/etc/inittab"; } -sub report_bug { - my (@other) = @_; - - sub header { " +sub header { " ******************************************************************************** * $_[0] ********************************************************************************"; - } +} + +sub fdisk() { + my @devs = grep { !m!^/dev/(loop|ram)\d+! && !/\d$/ } map { "/dev/$_->{dev}" } fs::proc_partitions::read_raw(); + `fdisk -l @devs`; + +} + +sub report_bug { + my (@other) = @_; join '', map { chomp; "$_\n" } header("lspci"), detect_devices::stringlist(), + header("hid_devices"), (map { sprintf("%-16s: %s", $_->{driver} || "unknown", $_->{description}) } c::hid_probe()), + header("input devices"), cat_("/proc/bus/input/devices"), + header("libinput devices"), `libinput list-devices`, header("pci_devices"), cat_("/proc/bus/pci/devices"), - header("dmidecode"), `dmidecode`, - header("fdisk"), arch() =~ /ppc/ ? `pdisk -l` : `fdisk -l`, + header("dmidecode"), arch() =~ /86/ ? `dmidecode` : (), + header("fdisk"), fdisk(), header("scsi"), cat_("/proc/scsi/scsi"), header("/sys/bus/scsi/devices"), -d '/sys/bus/scsi/devices' ? `ls -l /sys/bus/scsi/devices` : (), header("lsmod"), cat_("/proc/modules"), header("cmdline"), cat_("/proc/cmdline"), header("pcmcia: stab"), cat_("$::prefix/var/lib/pcmcia/stab") || cat_("$::prefix/var/run/stab"), - header("usb"), cat_("/proc/bus/usb/devices"), + header("usb"), cat_("/sys/kernel/debug/usb/devices"), header("partitions"), cat_("/proc/partitions"), + header("PVs"), `pvs`, + header("VGs"), `vgs`, + header("LVs"), `lvs`, + header("dmsetup info"), `dmsetup info`, + header("dmsetup table"), `dmsetup table`, + header("dmsetup ls"), `dmsetup ls`, header("cpuinfo"), cat_("/proc/cpuinfo"), - header("syslog"), cat_("/tmp/syslog") || cat_("$::prefix/var/log/syslog"), + header("syslog"), cat_("/tmp/syslog") || cat_("$::prefix/var/log/syslog") || `journalctl -q -D $::prefix/var/log/journal -b`, header("Xorg.log"), cat_("/var/log/Xorg.0.log"), header("monitor_full_edid"), monitor_full_edid(), header("stage1.log"), cat_("/tmp/stage1.log") || cat_("$::prefix/root/drakx/stage1.log"), header("ddebug.log"), cat_("/tmp/ddebug.log") || cat_("$::prefix/root/drakx/ddebug.log"), header("install.log"), cat_("$::prefix/root/drakx/install.log"), + header("draklive-install.log"), cat_("/tmp/draklive-install.log") || cat_("$::prefix/root/drakx/draklive-install.log"), header("fstab"), cat_("$::prefix/etc/fstab"), header("modprobe.conf"), cat_("$::prefix/etc/modprobe.conf"), header("lilo.conf"), cat_("$::prefix/etc/lilo.conf"), header("grub: menu.lst"), join('', map { s/^(\s*password)\s+(.*)/$1 xxx/; $_ } cat_("$::prefix/boot/grub/menu.lst")), header("grub: install.sh"), cat_("$::prefix/boot/grub/install.sh"), header("grub: device.map"), cat_("$::prefix/boot/grub/device.map"), + header("grub2: grub"), cat_("$::prefix/etc/default/grub"), + header("grub2: grub.cfg"), join('', map { s/^(\s*password_pbkdf2)\s+grub.pbkdf2.*/$1 xxx/; $_ } cat_("$::prefix/boot/grub2/grub.cfg")), + header("grub2: install.sh"), cat_("$::prefix/boot/grub2/install.sh"), header("xorg.conf"), cat_("$::prefix/etc/X11/xorg.conf"), header("urpmi.cfg"), cat_("$::prefix/etc/urpmi/urpmi.cfg"), header("modprobe.preload"), cat_("$::prefix/etc/modprobe.preload"), header("sysconfig/i18n"), cat_("$::prefix/etc/sysconfig/i18n"), + header("locale.conf"), cat_("$::prefix/etc/locale.conf"), header("/proc/iomem"), cat_("/proc/iomem"), header("/proc/ioport"), cat_("/proc/ioports"), map_index { even($::i) ? header($_) : $_ } @other; @@ -1227,7 +1624,7 @@ Allowing this will permit users to simply click on \"Share\" in konqueror and na nfs => [ 'nfs-utils', 'nfs-server', N("NFS: the traditional Unix file sharing system, with less support on Mac and Windows.") ], - smb => [ 'samba-server', 'smb', + smb => [ 'samba', 'smb', N("SMB: a file sharing system used by Windows, Mac OS X and many modern Linux systems.") ], ); @@ -1243,7 +1640,7 @@ Allowing this will permit users to simply click on \"Share\" in konqueror and na } foreach (keys %types) { my ($pkg, $service, $_descr) = @{$types{$_}}; - my $file = "/etc/init.d/$service"; + my $file = "/usr/lib/systemd/system/${service}.service"; if ($l{$_}) { $in->do_pkgs->ensure_is_installed($pkg, $file) or return; services::start($service); @@ -1275,13 +1672,18 @@ You can use userdrake to add a user to this group.") } sub monitor_full_edid() { - return if $::noauto; + return if $::noauto || $::local_install; - devices::make('zero'); my ($vbe, $edid); - run_program::raw({ timeout => 20 }, - 'monitor-edid', '>', \$edid, '2>', \$vbe, - '-v', '--perl', if_($::isStandalone, '--try-in-console')); + { + # prevent warnings in install's logs: + local $ENV{LC_ALL} = 'C'; + # don't use --try-in-console as it can cause a GNOME session to die (mga#28124) + # with most DMs the DE is running in vt1, so it does nothing anyway + run_program::raw({ timeout => 20 }, + 'monitor-edid', '>', \$edid, '2>', \$vbe, + '-v', '--perl'); + } if ($::isInstall) { foreach (['edid', \$edid], ['vbe', \$vbe]) { my ($name, $val) = @$_; @@ -1300,8 +1702,9 @@ sub monitor_full_edid() { ($edid, $vbe); } +# FIXME: is buggy regarding multiple sessions sub running_window_manager() { - my @window_managers = qw(ksmserver kwin gnome-session icewm wmaker afterstep fvwm fvwm2 fvwm95 mwm twm enlightenment xfce blackbox sawfish olvwm fluxbox compiz); + my @window_managers = qw(drakx-matchbox-window-manager ksmserver kwin kwin_x11 kwin_wayland gnome-session icewm wmaker afterstep fvwm fvwm2 fvwm95 mwm twm enlightenment xfce4-session blackbox sawfish olvwm fluxbox compiz lxsession); foreach (@window_managers) { my @pids = fuzzy_pidofs(qr/\b$_\b/) or next; @@ -1310,6 +1713,13 @@ sub running_window_manager() { undef; } +sub set_wm_hints_if_needed { + my ($o_in) = @_; + my $wm = any::running_window_manager(); + $o_in->{no_Window_Manager} = !$wm if $o_in; + $::set_dialog_hint = $wm eq 'drakx-matchbox-window-manager'; +} + sub ask_window_manager_to_logout { my ($wm) = @_; @@ -1318,15 +1728,17 @@ sub ask_window_manager_to_logout { 'kwin' => "dcop kdesktop default logout", 'gnome-session' => "gnome-session-save --kill", 'icewm' => "killall -QUIT icewm", + 'xfce4-session' => "xfce4-session-logout --logout", + 'lxsession' => "lxde-logout", ); my $cmd = $h{$wm} or return; - if ($wm eq 'gnome-session') { - #- NB: consolehelper does not destroy $HOME whereas kdesu does - #- for gnome, we use consolehelper, so below works - $ENV{ICEAUTHORITY} ||= "$ENV{HOME}/.ICEauthority"; - } elsif (member($wm, 'ksmserver', 'kwin') && $> == 0) { - #- we can not use dcop when we are root - $cmd = "su $ENV{USER} -c '$cmd'"; + if (member($wm, 'ksmserver', 'kwin', 'gnome-session') && $> == 0) { + #- we cannot use dcop when we are root + if (my $user = $ENV{USERHELPER_UID} && getpwuid($ENV{USERHELPER_UID})) { + $cmd = "su $user -c '$cmd'"; + } else { + log::l('missing or unknown $USERHELPER_UID'); + } } system($cmd); 1; @@ -1359,13 +1771,14 @@ sub ask_for_X_restart { my ($wm, $pid) = running_window_manager(); if (!$wm) { - $in->ask_warn('', N("Please log out and then use Ctrl-Alt-BackSpace")); - return; + # no window manager, ctrl-alt-del may not be supported, but we still have to restart X.. + $in->ask_okcancel('', N("You need to logout and back in again for changes to take effect. Press OK to logout now."), 1) or return; + system('killall', 'Xorg'); + } + else { + $in->ask_okcancel('', N("You need to log out and back in again for changes to take effect"), 1) or return; + ask_window_manager_to_logout_then_do($wm, $pid, 'killall Xorg'); } - - $in->ask_okcancel('', N("You need to log out and back in again for changes to take effect"), 1) or return; - - ask_window_manager_to_logout_then_do($wm, $pid, 'killall X'); } sub alloc_raw_device { @@ -1420,7 +1833,7 @@ sub configure_time_more { my $tz_prefix = timezone::get_timezone_prefix(); local $ENV{TZ} = ':' . $tz_prefix . '/' . $timezone->{timezone}; - $in->ask_from_({ interactive_help_id => 'configureTimezoneGMT', + $in->ask_from_({ interactive_help_id => 'configureTimezoneUTC', title => N("Date, Clock & Time Zone Settings"), }, [ { label => N("Date, Clock & Time Zone Settings"), title => 1 }, @@ -1455,4 +1868,158 @@ sub enable_x_screensaver() { run_program::run("xset", "s", "reset"); } +=item ask_url($in, $o_url) + +Asks URL of the mirror + +=cut + +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!^(https?|ftp)://!) { + 1; + } else { + $in->ask_warn('', N("URL must start with ftp:// or http:// or https://")); + 0; + } + } } ]) && $url; +} + +=item ask_mirror($in, $type, $o_url) + +Retrieves list of mirrors and offers to pick one + +=cut + +sub ask_mirror { + my ($in, $type, $o_url) = @_; + + require mirror; + + my $mirrors = eval { + my $_w = $in->wait_message('', N("Contacting %s web site to get the list of available mirrors...", N("Mageia"))); + mirror::list($in->{product_id}, $type); + }; + my $err = $@; + if (!$mirrors) { + $in->ask_warn('', N("Failed contacting %s web site to get the list of available mirrors", N("Mageia")) . "\n$err"); + return ask_url($in, $o_url); + } + + my $give_url = { country => '-', host => 'URL' }; + + my $mirror; + if ($o_url) { + $mirror = (find { $_->{url} eq $o_url } @$mirrors) || $give_url; + } else { + #- use current time zone to select best mirror + require urpm::mirrors; + my $urpm = $in->{packages} || { log => \&log::l }; + urpm::mirrors::add_proximity_and_sort($urpm, $mirrors); + $mirror = @$mirrors[0] || $give_url; + } + $in->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($in, $o_url) or goto &ask_mirror; + } else { + $url = $mirror->{url}; + } + $url =~ s!/main/?$!!; + log::l("chosen mirror: $url"); + $url; +} + +=item ask_mirror_and_downloader($in, $options, $o_downloader_only) + +Asks whether to automatically select the mirror (using $MIRRORLIST) or use +one specified by the user. Also asks whether to use the default downloader +or to use one specified by the user. + +Default values are supplied and user-entered values are returned in $options +which should be a reference to a hash containing the following fields: + +=over 4 + +=item * B<mirror_url>: the currently selected mirror URL ('$MIRRORLIST' for automatic selection) + +=item * B<downloader>: the currently selected downloader (undefined when using the default downloader) + +=back + +If $o_downloader_only is true, the mirror selection choice is not displayed. + +=cut + +sub ask_mirror_and_downloader { + my ($in, $options, $o_downloader_only) = @_; + + my $mirror_url = $options->{mirror_url} || ''; + my $downloader = $options->{downloader} || 'default'; + + my $mirror_choice = $mirror_url eq '$MIRRORLIST' ? 'automatic' : 'specific'; + + my $enable_aria2 = $::isInstall || $in->do_pkgs->is_installed('aria2', '/usr/bin/aria2c'); + my $enable_curl = $::isInstall || $in->do_pkgs->is_installed('curl', '/usr/bin/curl'); + my $enable_wget = $::isInstall || $in->do_pkgs->is_installed('wget', '/usr/bin/wget'); + + $in->ask_from_( + { + }, + [ + if_(!$o_downloader_only, + { label => N("Mirror choice"), val => \$mirror_choice, + type => 'combo', list => [ 'automatic', 'specific' ], + format => sub { + my ($choice) = @_; + +{ + 'automatic' => N("Automatic"), + 'specific' => N("Specific"), + }->{$choice}; + }, + }, + ), + { label => N("Downloader"), val => \$downloader, + type => 'combo', list => [ 'default', 'aria2', 'curl', 'wget' ], + format => sub { + my ($choice) = @_; + +{ + 'default' => N("Default"), + if_($enable_aria2, 'aria2' => 'aria2'), + if_($enable_curl, 'curl' => 'curl'), + if_($enable_wget, 'wget' => 'wget'), + }->{$choice}; + }, + }, + ] + ) or return; + + if ($mirror_choice eq 'automatic') { + $mirror_url = '$MIRRORLIST'; + } elsif ($mirror_url eq '$MIRRORLIST') { + $mirror_url = undef; + } + if ($downloader eq 'default') { + $downloader = undef; + } + + $options->{mirror_url} = $mirror_url; + $options->{downloader} = $downloader; + + 1; +} + 1; |