package install_any; # $Id: install_any.pm,v 1.510 2002/03/12 13:46:43 fpons Exp $ @ISA = qw(Exporter); %EXPORT_TAGS = ( all => [ qw(getNextStep spawnShell addToBeDone) ], ); @EXPORT_OK = map { @$_ } values %EXPORT_TAGS; use MDK::Common::System; use common; use run_program; use partition_table qw(:types); use partition_table_raw; use devices; use fsedit; use modules; use detect_devices; use lang; use any; use log; use fs; $boot_medium = 1; my $postinstall_rpms = ''; my $current_medium = $boot_medium; my $asked_medium = $boot_medium; my $cdrom = undef; sub useMedium($) { $_[0] > 1 and $::o->{method} eq 'cdrom' and setup_postinstall_rpms($::o->{prefix}, $::o->{packages}); $asked_medium eq $_[0] or log::l("selecting new medium '$_[0]'"); $asked_medium = $_[0]; } sub changeMedium($$) { my ($method, $medium) = @_; log::l("change to medium $medium for method $method (refused by default)"); 0; } sub relGetFile($) { local $_ = $_[0]; m|\.rpm$| ? "$::o->{packages}{mediums}{$asked_medium}{rpmsdir}/$_" : $_; } sub askChangeMedium($$) { my ($method, $medium) = @_; my $allow; do { eval { $allow = changeMedium($method, $medium) }; } while ($@); log::l($allow ? "accepting medium $medium" : "refusing medium $medium"); $allow; } sub errorOpeningFile($) { my ($file) = @_; $file eq 'XXX' and return; $current_medium eq $asked_medium and log::l("errorOpeningFile $file"), return; $::o->{packages}{mediums}{$asked_medium}{selected} or return; my $max = 32; if ($::o->{method} eq "cdrom") { cat_("/proc/mounts") =~ m,(/(?:dev|tmp)/\S+)\s+(?:/mnt/cdrom|/tmp/image), and $cdrom = $1; return unless $cdrom; ejectCdrom($cdrom); while ($max > 0 && askChangeMedium($::o->{method}, $asked_medium)) { $current_medium = $asked_medium; eval { fs::mount($cdrom, "/tmp/image", "iso9660", 'readonly') }; my $getFile = getFile($file); $getFile && @advertising_images and copy_advertising($::o); $getFile and return $getFile; $current_medium = 'unknown'; ejectCdrom($cdrom); --$max; } } else { while ($max > 0 && askChangeMedium($::o->{method}, $asked_medium)) { $current_medium = $asked_medium; my $getFile = getFile($file); $getFile and return $getFile; $current_medium = 'unknown'; --$max; } } $::o->{packages}{mediums}{$asked_medium}{selected} = undef; $current_medium = 'unknown'; return; } sub getFile { my ($f, $method) = @_; log::l("getFile $f:$method"); my $rel = relGetFile($f); do { if ($f =~ m|^http://|) { require http; http::getFile($f); } elsif ($method =~ /crypto|update/i) { require crypto; crypto::getFile($f); } elsif ($::o->{method} eq "ftp") { require ftp; ftp::getFile($rel); } elsif ($::o->{method} eq "http") { require http; http::getFile("$ENV{URLPREFIX}/$rel"); } else { my $f2 = "$postinstall_rpms/$f"; $f2 = "/tmp/image/$rel" unless $postinstall_rpms && -e $f2; open GETFILE, $f2 and *GETFILE; } } || errorOpeningFile($f); } sub getAndSaveFile { my ($file, $local) = @_ == 1 ? ("Mandrake/mdkinst$_[0]", $_[0]) : @_; local *F; open F, ">$local" or return; local $/ = \ (16 * 1024); my $f = ref($file) ? $file : getFile($file) or return; local $_; while (<$f>) { syswrite F, $_ } 1; } sub setup_postinstall_rpms($$) { my ($prefix, $packages) = @_; $postinstall_rpms and return; $postinstall_rpms = "$prefix/usr/postinstall-rpm"; require pkgs; log::l("postinstall rpms directory set to $postinstall_rpms"); clean_postinstall_rpms(); mkdir_p($postinstall_rpms); my %toCopy; foreach (@{$packages->{needToCopy} || []}) { my $p = pkgs::packageByName($packages, $_); pkgs::selectPackage($packages, $p, 0, \%toCopy); } my @toCopy = grep { $_ && pkgs::packageFlagSelected($_) == 0 } map { pkgs::packageByName($packages, $_) } keys %toCopy; eval { cp_af((grep { -r $_ } map { "/tmp/image/" . relGetFile(pkgs::packageFile($_)) } @toCopy), $postinstall_rpms) }; log::l("copying Auto Install Floppy"); getAndSaveInstallFloppy($::o, "$postinstall_rpms/auto_install.img"); } sub clean_postinstall_rpms() { $postinstall_rpms and -d $postinstall_rpms and rm_rf($postinstall_rpms); } sub allowNVIDIA_rpms { my ($packages) = @_; require pkgs; if (pkgs::packageByName($packages, "NVIDIA_GLX")) { my @rpms; foreach (keys %{$packages->{names}}) { my ($ext, $version, $release) = /kernel[^-]*(-smp|-enterprise|-secure)?(?:-(\d.*?)\.(\d+mdk))?$/ or next; my $p = pkgs::packageByName($packages, $_); pkgs::packageSelectedOrInstalled($p) or next; $version or ($version, $release) = (pkgs::packageVersion($p), pkgs::packageRelease($p)); my $name = "NVIDIA_kernel-$version-$release$ext"; pkgs::packageByName($packages, $name) or return; push @rpms, $name; } @rpms > 0 or return; return [ @rpms, "NVIDIA_GLX" ]; } } sub kernelVersion { my ($o) = @_; my $kernel = readlink "$o->{prefix}/boot/vmlinuz" || first(all("$o->{prefix}/boot")); first($kernel =~ /vmlinuz-(.*)/); } sub getNextStep { my ($s) = $::o->{steps}{first}; $s = $::o->{steps}{$s}{next} while $::o->{steps}{$s}{done} || !$::o->{steps}{$s}{reachable}; $s; } sub spawnShell { return if $::o->{localInstall} || $::testing; -x "/bin/sh" or die "cannot open shell - /bin/sh doesn't exist"; fork and return; $ENV{DISPLAY} ||= ":0"; local *F; sysopen F, "/dev/tty2", 2 or die "cannot open /dev/tty2 -- no shell will be provided"; open STDIN, "<&F" or die ''; open STDOUT, ">&F" or die ''; open STDERR, ">&F" or die ''; close F; print any::drakx_version(), "\n"; c::setsid(); ioctl(STDIN, c::TIOCSCTTY(), 0) or warn "could not set new controlling tty: $!"; my $busybox = "/usr/bin/busybox"; exec {-e $busybox ? $busybox : "/bin/sh"} "/bin/sh" or log::l("exec of /bin/sh failed: $!"); } sub getAvailableSpace { my ($o) = @_; my $minAvailableSize = 65 * sqr(1024); my $n = !$::testing && getAvailableSpace_mounted($o->{prefix}) || getAvailableSpace_raw($o->{fstab}) * 512 / 1.07; $n - max(0.1 * $n, $minAvailableSize); } sub getAvailableSpace_mounted { my ($prefix) = @_; my $dir = -d "$prefix/usr" ? "$prefix/usr" : "$prefix"; my (undef, $free) = MDK::Common::System::df($dir) or return; log::l("getAvailableSpace_mounted $free KB"); $free * 1024 || 1; } sub getAvailableSpace_raw { my ($fstab) = @_; do { $_->{mntpoint} eq '/usr' and return $_->{size} } foreach @$fstab; do { $_->{mntpoint} eq '/' and return $_->{size} } foreach @$fstab; if ($::testing) { my $nb = 450; log::l("taking ${nb}MB for testing"); return $nb << 11; } die "missing root partition"; } sub preConfigureTimezone { my ($o) = @_; require timezone; add2hash($o->{timezone}, { timezone::read($o->{prefix}) }) if $o->{isUpgrade}; $o->{timezone}{timezone} ||= timezone::bestTimezone(lang::lang2text($o->{lang})); my $utc = $::expert && !grep { isFat($_) || isNT($_) } @{$o->{fstab}}; my $ntp = timezone::ntp_server($o->{prefix}); add2hash_($o->{timezone}, { UTC => $utc, ntp => $ntp }); } sub setPackages { my ($o) = @_; require pkgs; if (!$o->{packages} || is_empty_hash_ref($o->{packages}{names})) { $o->{packages} = pkgs::psUsingHdlists($o->{prefix}, $o->{method}); pkgs::getDeps($o->{prefix}, $o->{packages}); pkgs::selectPackage($o->{packages}, pkgs::packageByName($o->{packages}, 'basesystem') || die("missing basesystem package"), 1); pkgs::getProvides($o->{packages}); pkgs::read_rpmsrate($o->{packages}, getFile("Mandrake/base/rpmsrate")); ($o->{compssUsers}, $o->{compssUsersSorted}) = pkgs::readCompssUsers($o->{meta_class}); setDefaultPackages($o); } else { pkgs::psUpdateHdlistsDeps($o->{prefix}, $o->{method}, $o->{packages}); } } sub setDefaultPackages { my ($o, $clean) = @_; if ($clean) { delete $o->{$_} foreach qw(default_packages compssUsersChoice); } push @{$o->{default_packages}}, "nfs-utils-clients" if $o->{method} eq "nfs"; push @{$o->{default_packages}}, "numlock" if $o->{miscellaneous}{numlock}; push @{$o->{default_packages}}, "kernel22" if !$::oem && c::kernel_version() =~ /^\Q2.2/; push @{$o->{default_packages}}, "raidtools" if !is_empty_array_ref($o->{all_hds}{raids}); push @{$o->{default_packages}}, "lvm" if !is_empty_array_ref($o->{all_hds}{lvms}); push @{$o->{default_packages}}, "reiserfsprogs" if grep { isThisFs("reiserfs", $_) } @{$o->{fstab}}; push @{$o->{default_packages}}, "xfsprogs" if grep { isThisFs("xfs", $_) } @{$o->{fstab}}; push @{$o->{default_packages}}, "jfsprogs" if grep { isThisFs("jfs", $_) } @{$o->{fstab}}; push @{$o->{default_packages}}, "alsa", "alsa-utils" if modules::get_alias("sound-slot-0") =~ /^snd-card-/; unless ($clean) { if ($::auto_install && ($o->{compssUsersChoice} || {})->{ALL}) { $o->{compssUsersChoice}{$_} = 1 foreach map { @{$o->{compssUsers}{$_}{flags}} } @{$o->{compssUsersSorted}}; } if (!$o->{compssUsersChoice} && !$o->{isUpgrade}) { if ($o->{meta_class} eq 'server') { $o->{compssUsersChoice}{$_} = 1 foreach 'X', 'MONITORING', 'NETWORKING_REMOTE_ACCESS_SERVER'; } else { $o->{compssUsersChoice}{$_} = 1 foreach 'GNOME', 'KDE', 'CONFIG', 'X'; $o->{lang} eq 'eu_ES' and $o->{compssUsersChoice}{KDE} = 0; $o->{compssUsersChoice}{$_} = 1 foreach map { @{$o->{compssUsers}{$_}{flags}} } 'Workstation|Office Workstation', 'Workstation|Internet station'; } } } $o->{compssUsersChoice}{uc($_)} = 1 foreach grep { modules::get_that_type($_) } ('tv', 'scanner', 'photo', 'sound'); $o->{compssUsersChoice}{uc($_)} = 1 foreach map { $_->{driver} =~ /Flag:(.*)/ } detect_devices::probeall(); $o->{compssUsersChoice}{SYSTEM} = 1; $o->{compssUsersChoice}{DOCS} = !$o->{excludedocs}; $o->{compssUsersChoice}{BURNER} = 1 if detect_devices::burners(); $o->{compssUsersChoice}{DVD} = 1 if detect_devices::dvdroms(); $o->{compssUsersChoice}{USB} = 1 if modules::get_alias("usb-interface"); $o->{compssUsersChoice}{PCMCIA} = 1 if detect_devices::hasPCMCIA(); $o->{compssUsersChoice}{HIGH_SECURITY} = 1 if $o->{security} > 3; $o->{compssUsersChoice}{BIGMEM} = 1 if !$::oem && (availableRamMB() > 800) && (arch() !~ /ia64/); $o->{compssUsersChoice}{SMP} = 1 if detect_devices::hasSMP(); $o->{compssUsersChoice}{'3D'} = 1 if detect_devices::matching_desc('Matrox.* G[245][05]0') || detect_devices::matching_desc('Rage X[CL]') || detect_devices::matching_desc('3D Rage (?:LT|Pro)') || detect_devices::matching_desc('Voodoo [35]') || detect_devices::matching_desc('Voodoo Banshee') || detect_devices::matching_desc('8281[05].* CGC') || detect_devices::matching_desc('Rage 128') || detect_devices::matching_desc('Radeon ') && !detect_devices::matching_desc('Radeon 8500') || detect_devices::matching_desc('[nN]Vidia.*T[nN]T2') || detect_devices::matching_desc('[nN]Vidia.*NV[56]') || detect_devices::matching_desc('[nN]Vidia.*Vanta') || detect_devices::matching_desc('[nN]Vidia.*GeForce') || detect_devices::matching_desc('[nN]Vidia.*NV1[15]') || detect_devices::matching_desc('[nN]Vidia.*Quadro'); foreach (map { substr($_, 0, 2) } lang::langs($o->{langs})) { pkgs::packageByName($o->{packages}, "locales-$_") or next; push @{$o->{default_packages}}, "locales-$_"; $o->{compssUsersChoice}{qq(LOCALES"$_")} = 1; } foreach (lang::langsLANGUAGE($o->{langs})) { $o->{compssUsersChoice}{qq(LOCALES"$_")} = 1; } $o->{compssUsersChoice}{'CHARSET"' . lang::lang2charset($o->{lang}) . '"'} = 1; } sub unselectMostPackages { my ($o) = @_; pkgs::unselectAllPackages($o->{packages}); pkgs::selectPackage($o->{packages}, pkgs::packageByName($o->{packages}, $_) || next) foreach @{$o->{default_packages}}; } sub warnAboutNaughtyServers { my ($o) = @_; my @naughtyServers = pkgs::naughtyServers($o->{packages}) or return 1; if (!$o->ask_yesorno('', formatAlaTeX(_("You have selected the following server(s): %s These servers are activated by default. They don't have any known security issues, but some new 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))), 1)) { pkgs::unselectPackage($o->{packages}, pkgs::packageByName($o->{packages}, $_)) foreach @naughtyServers; } } sub addToBeDone(&$) { my ($f, $step) = @_; return &$f() if $::o->{steps}{$step}{done}; push @{$::o->{steps}{$step}{toBeDone}}, $f; } sub setAuthentication { my ($o) = @_; my ($shadow, $md5, $ldap, $nis) = @{$o->{authentication} || {}}{qw(shadow md5 LDAP NIS)}; my $p = $o->{prefix}; any::enableShadow($p) if $shadow; if ($ldap) { $o->pkg_install(qw(chkauth openldap-clients nss_ldap pam_ldap)); run_program::rooted($o->{prefix}, "/usr/sbin/chkauth", "ldap", "-D", $o->{netc}{LDAPDOMAIN}, "-s", $ldap); } elsif ($nis) { #$o->pkg_install(qw(chkauth ypbind yp-tools net-tools)); #run_program::rooted($o->{prefix}, "/usr/sbin/chkauth", "yp", $domain, "-s", $nis); $o->pkg_install("ypbind"); my $domain = $o->{netc}{NISDOMAIN}; $domain || $nis ne "broadcast" or die _("Can't use broadcast with no NIS domain"); my $t = $domain ? "domain $domain" . ($nis ne "broadcast" && " server") : "ypserver"; substInFile { $_ = "#~$_" unless /^#/; $_ .= "$t $nis\n" if eof; } "$p/etc/yp.conf"; require network; network::write_conf("$p/etc/sysconfig/network", $o->{netc}); } } sub killCardServices { my $pid = chomp_(cat_("/tmp/cardmgr.pid")); $pid and kill(15, $pid); } sub unlockCdrom(;$) { my ($cdrom) = @_; $cdrom or cat_("/proc/mounts") =~ m,(/(?:dev|tmp)/\S+)\s+(?:/mnt/cdrom|/tmp/image), and $cdrom = $1; eval { $cdrom and ioctl detect_devices::tryOpen($1), c::CDROM_LOCKDOOR(), 0 }; } sub ejectCdrom(;$) { my ($cdrom) = @_; getFile("XXX"); $cdrom ||= $1 if cat_("/proc/mounts") =~ m,(/(?:dev|tmp)/\S+)\s+(?:/mnt/cdrom|/tmp/image),; if ($cdrom) { eval { fs::umount("/tmp/image") }; if ($@) { log::l("files still open: ", readlink($_)) foreach map { glob_("$_/fd/*") } glob_("/proc/*") } eval { ioctl detect_devices::tryOpen($cdrom), c::CDROMEJECT(), 1 }; } } sub setupFB { my ($o, $vga) = @_; $vga ||= 785; require bootloader; foreach (qw(vmlinuz vmlinuz-secure vmlinuz-smp vmlinuz-hack)) { if (my $e = bootloader::get("/boot/$_", $o->{bootloader})) { $e->{vga} = $vga; } } bootloader::install($o->{prefix}, $o->{bootloader}, $o->{fstab}, $o->{all_hds}{hds}); 1; } sub hdInstallPath() { my $tail = first(readlink("/tmp/image") =~ m|^/tmp/hdimage/(.*)|); my $head = first(readlink("/tmp/hdimage") =~ m|$::o->{prefix}(.*)|); $tail && ($head ? "$head/$tail" : "/mnt/hd/$tail"); } sub install_urpmi { my ($prefix, $method, $mediums) = @_; $method eq 'disk' && !hdInstallPath() and return; my @cfg = map { my $name = $_->{fakemedium}; local *LIST; my $mask = umask 077; open LIST, ">$prefix/var/lib/urpmi/list.$name" or log::l("failed to write list.$name"); umask $mask; my $dir = ($_->{prefix} || ${{ nfs => "file://mnt/nfs", disk => "file:/" . hdInstallPath(), ftp => $ENV{URLPREFIX}, http => $ENV{URLPREFIX}, cdrom => "removable://mnt/cdrom" }}{$method}) . "/$_->{rpmsdir}"; local *FILES; open FILES, "$ENV{LD_LOADER} parsehdlist /tmp/$_->{hdlist} |"; print LIST "$dir/$_\n" foreach chomp_(); close FILES or log::l("parsehdlist failed"), return; close LIST; if (-s "$prefix/var/lib/urpmi/synthesis.hdlist.$name.cz" <= 32) { unlink "$prefix/var/lib/urpmi/synthesis.hdlist.$name.cz"; run_program::rooted($prefix, "parsehdlist", ">", "/var/lib/urpmi/synthesis.hdlist.$name", "--synthesis", "/var/lib/urpmi/hdlist.$name.cz"); run_program::rooted($prefix, "gzip", "-S", ".cz", "/var/lib/urpmi/synthesis.hdlist.$name"); } my ($qname, $qdir) = ($name, $dir); $qname =~ s/(\s)/\\$1/g; $qdir =~ s/(\s)/\\$1/g; "$qname " . ($dir !~ /^(ftp|http)/ && $qdir) . " { hdlist: hdlist.$name.cz with_hdlist: ../base/" . ($_->{update} ? "hdlist.cz" : $_->{hdlist}) . " list: list.$name" . ($dir =~ /removable:/ && " removable: /dev/cdrom") . ($_->{update} && " update") . " } "; } sort { $a->{medium} <=> $b->{medium} } values %$mediums; eval { output "$prefix/etc/urpmi/urpmi.cfg", @cfg }; } sub kderc_largedisplay { my ($prefix) = @_; update_gnomekderc($_, 'KDE', Contrast => 7, kfmIconStyle => "Large", kpanelIconStyle => "Normal", KDEIconStyle => "Large") foreach list_skels($prefix, '.kderc'); substInFile { s/^(GridWidth)=85/$1=100/; s/^(GridHeight)=70/$1=75/; } $_ foreach list_skels($prefix, '.kde/share/config/kfmrc'); } sub kdeicons_postinstall { my ($prefix) = @_; my %l = ( 'cdrom' => [ 'cdrom', 'Cd-Rom' ], 'zip' => [ 'zip', 'Zip' ], 'floppy-ls' => [ 'floppy', 'LS-120' ], 'floppy' => [ 'floppy', 'Floppy' ], ); foreach (fs::read_fstab($prefix, "/etc/fstab")) { my ($name_, $nb) = $_->{mntpoint} =~ m|.*/(\S+?)(\d*)$/|; my ($name, $text) = @{$l{$name_} || []}; my $f = ${{ supermount => sub { $name .= '.fsdev' if $name }, vfat => sub { $name = 'Dos_'; $text = $name_ }, }}{$_->{type}}; &$f if $f; template2userfile($prefix, "$ENV{SHARE_PATH}/$name.kdelnk.in", "Desktop/$text" . ($nb && " $nb"). ".kdelnk", 1, %$_) if $name; } # rename the .kdelnk to the name found in the .kdelnk as kde doesn't use it # for displaying foreach my $dir (grep { -d $_ } list_skels($prefix, 'Desktop')) { foreach (grep { /\.kdelnk$/ } all($dir)) { cat_("$dir/$_") =~ /^Name\[\Q$ENV{LANG}\E\]=(.{2,14})$/m and rename "$dir/$_", "$dir/$1.kdelnk"; } } } sub kdemove_desktop_file { my ($prefix) = @_; my @toMove = qw(doc.kdelnk news.kdelnk updates.kdelnk home.kdelnk printer.kdelnk floppy.kdelnk cdrom.kdelnk FLOPPY.kdelnk CDROM.kdelnk); foreach my $dir (grep { -d $_ } list_skels($prefix, 'Desktop')) { renamef("$dir/$_", "$dir/Trash/$_") foreach grep { -e "$dir/$_" } @toMove, grep { /\.rpmorig$/ } all($dir) } } sub auto_inst_file() { ($::g_auto_install ? "/tmp" : "$::o->{prefix}/root/drakx") . "/auto_inst.cfg.pl" } sub report_bug { my ($prefix) = @_; any::report_bug($prefix, 'auto_inst' => g_auto_install('', 1)); } sub g_auto_install { my ($replay, $respect_privacy) = @_; my $o = {}; require pkgs; $o->{default_packages} = pkgs::selected_leaves($::o->{packages}); my @fields = qw(mntpoint type size); $o->{partitions} = [ map { my %l; @l{@fields} = @$_{@fields}; \%l } grep { $_->{mntpoint} } @{$::o->{fstab}} ]; exists $::o->{$_} and $o->{$_} = $::o->{$_} foreach qw(lang authentication mouse wacom netc timezone superuser intf keyboard users partitioning isUpgrade manualFstab nomouseprobe crypto security netcnx useSupermount autoExitInstall mkbootdisk); if (my $printer = $::o->{printer}) { $o->{printer}{$_} = $::o->{printer}{$_} foreach qw(SPOOLER DEFAULT BROWSEPOLLADDR BROWSEPOLLPORT MANUALCUPSCONFIG); $o->{printer}{configured} = {}; foreach my $queue (keys %{$::o->{printer}{configured}}) { my $val = $::o->{printer}{configured}{$queue}{queuedata}; exists $val->{$_} and $o->{printer}{configured}{$queue}{queuedata}{$_} = $val->{$_} foreach keys %{$val || {}}; } } if (my $card = $::o->{X}{card}) { $o->{X}{$_} = $::o->{X}{$_} foreach qw(default_depth resolution_wanted); if ($o->{X}{default_depth} and my $depth = $card->{depth}{$o->{X}{default_depth}}) { $depth ||= []; $o->{X}{resolution_wanted} ||= join "x", @{$depth->[0]} unless is_empty_array_ref($depth->[0]); $o->{X}{monitor} = $::o->{X}{monitor} if $::o->{X}{monitor}{manual}; } } local $o->{partitioning}{auto_allocate} = !$replay; $o->{autoExitInstall} = !$replay; $o->{interactiveSteps} = [ 'doPartitionDisks', 'formatPartitions'] if $replay; $o->{users} = [ @{$o->{users} || []} ]; my @user_info_to_remove = ( if_($respect_privacy, qw(name realname home pw)), qw(oldu oldg password password2), ); $_ = { %{$_ || {}} }, delete @$_{@user_info_to_remove} foreach $o->{superuser}, @{$o->{users} || []}; if ($respect_privacy && $o->{netcnx}) { if (my $type = $o->{netcnx}{type}) { my @netcnx_type_to_remove = qw(passwd passwd2 login phone_in phone_out); $_ = { %{$_ || {}} }, delete @$_{@netcnx_type_to_remove} foreach $o->{netcnx}{$type}; } } require Data::Dumper; my $str = join('', "#!/usr/bin/perl -cw # # You should check the syntax of this file before using it in an auto-install. # You can do this with 'perl -cw auto_inst.cfg.pl' or by executing this file # (note the '#!/usr/bin/perl -cw' on the first line). ", Data::Dumper->Dump([$o], ['$o']), "\0"); $str =~ s/ {8}/\t/g; $str; } sub getAndSaveInstallFloppy { my ($o, $where) = @_; if ($postinstall_rpms && -d $postinstall_rpms && -r "$postinstall_rpms/auto_install.img") { log::l("getAndSaveInstallFloppy: using file saved as $postinstall_rpms/auto_install.img"); cp_af("$postinstall_rpms/auto_install.img", $where); } else { my $image = cat_("/proc/cmdline") =~ /pcmcia/ ? "pcmcia" : ${{ disk => 'hd', cdrom => 'cdrom', ftp => 'network', nfs => 'network', http => 'network' }}{$o->{method}}; $image .= arch() =~ /sparc64/ && "64"; getAndSaveFile("images/$image.img", $where) or log::l("failed to write Install Floppy ($image.img) to $where"), return; } 1; } sub getAndSaveAutoInstallFloppy { my ($o, $replay, $where) = @_; eval { modules::load('loop') }; if (arch() =~ /sparc/) { my $imagefile = "$o->{prefix}/tmp/autoinst.img"; my $mountdir = "$o->{prefix}/tmp/mount"; -d $mountdir or mkdir $mountdir, 0755; my $workdir = "$o->{prefix}/tmp/work"; -d $workdir or rmdir $workdir; getAndSaveInstallFloppy($o, $imagefile) or return; devices::make($_) foreach qw(/dev/loop6 /dev/ram); run_program::run("losetup", "/dev/loop6", $imagefile); fs::mount("/dev/loop6", $mountdir, "romfs", 'readonly'); cp_af($mountdir, $workdir); fs::umount($mountdir); run_program::run("losetup", "-d", "/dev/loop6"); substInFile { s/timeout.*//; s/^(\s*append\s*=\s*\".*)\"/$1 kickstart=floppy\"/ } "$workdir/silo.conf"; #" for po output "$workdir/boot.msg", "\n7m", "!! If you press enter, an auto-install is going to start. ALL data on this computer is going to be lost, including any Windows partitions !! ", "7m\n"; local $o->{partitioning}{clearall} = 1; output("$workdir/auto_inst.cfg", g_auto_install()); run_program::run("genromfs", "-d", $workdir, "-f", "/dev/ram", "-A", "2048,/..", "-a", "512", "-V", "DrakX autoinst"); fs::mount("/dev/ram", $mountdir, 'romfs', 0); run_program::run("silo", "-r", $mountdir, "-F", "-i", "/fd.b", "-b", "/second.b", "-C", "/silo.conf"); fs::umount($mountdir); require commands; commands::dd("if=/dev/ram", "of=$where", "bs=1440", "count=1024"); rm_rf($workdir, $mountdir, $imagefile); } elsif (arch() =~ /ia64/) { } else { my $imagefile = "$o->{prefix}/tmp/autoinst.img"; my $mountdir = "$o->{prefix}/tmp/aif-mount"; -d $mountdir or mkdir $mountdir, 0755; my $param = 'kickstart=floppy ' . generate_automatic_stage1_params($o); getAndSaveInstallFloppy($o, $imagefile) or return; my $dev = devices::set_loop($imagefile) or log::l("couldn't set loopback device"), return; fs::mount($dev, $mountdir, 'vfat', 0); substInFile { s/timeout.*/$replay ? 'timeout 1' : ''/e; s/^(\s*append)/$1 $param/ } "$mountdir/syslinux.cfg"; unlink "$mountdir/help.msg"; output "$mountdir/boot.msg", "\n0c", "!! If you press enter, an auto-install is going to start. All data on this computer is going to be lost, including any Windows partitions !! ", "07\n" if !$replay; local $o->{partitioning}{clearall} = !$replay; eval { output("$mountdir/auto_inst.cfg", g_auto_install($replay)); }; $@ and log::l("Warning: <$@>"); fs::umount($mountdir); rmdir $mountdir; devices::del_loop($dev); require commands; commands::dd("if=$imagefile", "of=$where", "bs=1440", "count=1024"); unlink $imagefile; } 1; } sub g_default_packages { my ($o, $quiet) = @_; my $floppy = detect_devices::floppy(); while (1) { $o->ask_okcancel('', _("Insert a FAT formatted floppy in drive %s", $floppy), 1) or return; eval { fs::mount(devices::make($floppy), "/floppy", "vfat", 0) }; last if !$@; $o->ask_warn('', _("This floppy is not FAT formatted")); } require Data::Dumper; my $str = Data::Dumper->Dump([ { default_packages => pkgs::selected_leaves($o->{packages}) } ], ['$o']); $str =~ s/ {8}/\t/g; output('/floppy/auto_inst.cfg', "# 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, "\0"); fs::umount("/floppy"); $quiet or $o->ask_warn('', _("To use this saved packages selection, boot installation with ``linux defcfg=floppy''")); } sub loadO { my ($O, $f) = @_; $f ||= auto_inst_file; my $o; if ($f =~ /^(floppy|patch)$/) { my $f = $f eq "floppy" ? 'auto_inst.cfg' : "patch"; unless ($::testing) { fs::mount(devices::make(detect_devices::floppy()), "/mnt", (arch() =~ /sparc/ ? "romfs" : "vfat"), 'readonly'); $f = "/mnt/$f"; } -e $f or $f .= '.pl'; my $b = before_leaving { fs::umount("/mnt") unless $::testing; modules::unload($_) foreach qw(vfat fat); }; $o = loadO($O, $f); } else { -e "$f.pl" and $f .= ".pl" unless -e $f; my $fh = -e $f ? do { local *F; open F, $f; *F } : getFile($f) or die _("Error reading file %s", $f); { local $/ = "\0"; no strict; eval <$fh>; close $fh; $@ and die; } add2hash_($o ||= {}, $O); } bless $o, ref $O; } sub generate_automatic_stage1_params { my ($o) = @_; my @ks = "method:$o->{method}"; if ($o->{method} eq 'http') { "$ENV{URLPREFIX}" =~ m|http://([^/:]+)/(.*)| or die; push @ks, "server:$1", "directory:$2"; } elsif ($o->{method} eq 'ftp') { push @ks, "server:$ENV{HOST}", "directory:$ENV{PREFIX}", "user:$ENV{LOGIN}", "pass:$ENV{PASSWORD}"; } elsif ($o->{method} eq 'nfs') { cat_("/proc/mounts") =~ m|(\S+):(\S+)\s+/tmp/image nfs| or die; push @ks, "server:$1", "directory:$2"; } if (member($o->{method}, qw(http ftp nfs))) { my ($intf) = values %{$o->{intf}}; push @ks, "interface:$intf->{DEVICE}"; if ($intf->{BOOTPROTO} eq 'dhcp') { push @ks, "network:dhcp"; } else { require network; push @ks, "network:static", "ip:$intf->{IPADDR}", "netmask:$intf->{NETMASK}", "gateway:$o->{netc}{GATEWAY}"; my @dnss = network::dnsServers($o->{netc}); push @ks, "dns:$dnss[0]" if @dnss; } } "automatic=".join(',', @ks); } sub guess_mount_point { my ($part, $prefix, $user) = @_; my %l = ( '/' => 'etc/fstab', '/boot' => 'vmlinuz', '/tmp' => '.X11-unix', '/usr' => 'X11R6', '/var' => 'catman', ); my $handle = any::inspect($part, $prefix) or return; my $d = $handle->{dir}; my ($mnt) = grep { -e "$d/$l{$_}" } keys %l; $mnt ||= (stat("$d/.bashrc"))[4] ? '/root' : '/home/user' . ++$$user if -e "$d/.bashrc"; $mnt ||= (grep { -d $_ && (stat($_))[4] >= 500 && -e "$_/.bashrc" } glob_("$d")) ? '/home' : ''; ($mnt, $handle); } sub suggest_mount_points { my ($fstab, $prefix, $uniq) = @_; my $user; foreach my $part (grep { isTrueFS($_) } @$fstab) { $part->{mntpoint} && !$part->{unsafeMntpoint} and next; my ($mnt, $handle) = guess_mount_point($part, $prefix, \$user) or next; next if $uniq && fsedit::mntpoint2part($mnt, $fstab); $part->{mntpoint} = $mnt; delete $part->{unsafeMntpoint}; fs::merge_info_from_fstab($fstab, $handle->{dir}, $uniq) if $mnt eq '/'; } $_->{mntpoint} and log::l("suggest_mount_points: $_->{device} -> $_->{mntpoint}") foreach @$fstab; } sub find_root_parts { my ($fstab, $prefix) = @_; log::l("find_root_parts"); my $user; grep { my ($mnt) = guess_mount_point($_, $prefix, \$user); $mnt eq '/'; } @$fstab; } sub use_root_part { my ($all_hds, $part, $prefix) = @_; my $fstab = [ fsedit::get_really_all_fstab($all_hds) ]; { my $handle = any::inspect($part, $prefix) or die; fs::merge_info_from_fstab($fstab, $handle->{dir}, 'uniq'); } map { $_->{mntpoint} = 'swap' } grep { isSwap($_) } @$fstab; } sub getHds { my ($o, $f_err) = @_; my $ok = 1; my $try_scsi = !$::expert; my $flags = $o->{partitioning}; my @drives = detect_devices::hds(); # add2hash_($o->{partitioning}, { readonly => 1 }) if partition_table_raw::typeOfMBR($drives[0]{device}) eq 'system_commander'; getHds: my $all_hds = catch_cdie { fsedit::hds(\@drives, $flags) } sub { $ok = 0; my $err = formatError($@); log::l("error reading partition table: $err"); !$flags->{readonly} && $f_err and $f_err->($err); }; my $hds = $all_hds->{hds}; if (is_empty_array_ref($hds) && $try_scsi) { $try_scsi = 0; $o->setupSCSI; goto getHds; } if (!$::testing) { @$hds = grep { eval { partition_table_raw::test_for_bad_drives($_) }; !$@ } @$hds; } $ok = fsedit::verifyHds($hds, $flags->{readonly}, $ok) if !($flags->{clearall} || $flags->{clear}); $ok && $hds && @$hds > 0 && @{$o->{all_hds}{hds} || []} == @$hds and return $ok; fs::get_raw_hds('', $all_hds); fs::add2all_hds($all_hds, @{$o->{manualFstab}}); $o->{all_hds} = $all_hds; $o->{fstab} = [ fsedit::get_all_fstab($all_hds) ]; fs::merge_info_from_mtab($o->{fstab}); my @win = grep { isFat($_) && isFat({ type => fsedit::typeOfPart($_->{device}) }) } @{$o->{fstab}}; log::l("win parts: ", join ",", map { $_->{device} } @win) if @win; if (@win == 1) { $win[0]{mntpoint} = arch() =~ /ia64/ ? "/boot/efi" : "/mnt/windows"; } else { my %w; foreach (@win) { my $v = $w{$_->{device_windobe}}++; $_->{mntpoint} = $_->{unsafeMntpoint} = "/mnt/win_" . lc($_->{device_windobe}) . ($v ? $v+1 : ''); } } my @sunos = grep { isSunOS($_) && type2name($_->{type}) =~ /root/i } @{$o->{fstab}}; if (@sunos) { my $v = ''; map { $_->{mntpoint} = $_->{unsafeMntpoint} = "/mnt/sunos" . ($v && ++$v) } @sunos; } $ok; } sub log_sizes { my ($o) = @_; my @df = MDK::Common::System::df($o->{prefix}); log::l(sprintf "Installed: %s(df), %s(rpm)", formatXiB($df[0] - $df[1], 1024), formatXiB(sum(`$ENV{LD_LOADER} rpm --root $o->{prefix}/ -qa --queryformat "%{size}\n"`))) if -x "$o->{prefix}/bin/rpm"; } sub copy_advertising { my ($o) = @_; return if $::rootwidth < 800; my $f; my $source_dir = "Mandrake/share/advertising"; foreach ("." . $o->{lang}, "." . substr($o->{lang},0,2), '') { $f = getFile("$source_dir$_/list") or next; $source_dir = "$source_dir$_"; } if (my @files = <$f>) { my $dir = "$o->{prefix}/tmp/drakx-images"; mkdir $dir; unlink glob_("$dir/*"); foreach (@files) { chomp; getAndSaveFile("$source_dir/$_", "$dir/$_"); s/\.png/\.pl/; getAndSaveFile("$source_dir/$_", "$dir/$_"); s/\.pl/_icon\.png/; getAndSaveFile("$source_dir/$_", "$dir/$_"); s/_icon\.png/\.png/; } @advertising_images = map { "$dir/$_" } @files; } } sub remove_advertising { my ($o) = @_; eval { rm_rf("$o->{prefix}/tmp/drakx-images") }; @advertising_images = (); } sub disable_user_view { my ($prefix) = @_; substInFile { s/^UserView=.*/UserView=true/ } "$prefix/usr/share/config/kdm/kdmrc"; substInFile { s/^Browser=.*/Browser=0/ } "$prefix/etc/X11/gdm/gdm.conf"; } sub write_fstab { my ($o) = @_; fs::write_fstab($o->{all_hds}, $o->{prefix}) if !$::live; } my @bigseldom_used_groups = ( ); sub check_prog { my ($f) = @_; my @l = $f !~ m|^/| ? map { "$_/$f" } split(":", $ENV{PATH}) : $f; return if grep { -x $_ } @l; common::usingRamdisk() or log::l("ERROR: check_prog can't find the program $f and we're not using ramdisk"), return; my ($f_) = map { m|^/| ? $_ : "/usr/bin/$_" } $f; remove_bigseldom_used(); foreach (@bigseldom_used_groups) { my (@l) = map { m|^/| ? $_ : "/usr/bin/$_" } @$_; if (member($f_, @l)) { foreach (@l) { getAndSaveFile($_); chmod 0755, $_; } return; } } getAndSaveFile($f_); chmod 0755, $f_; } sub remove_unused { $::testing and return; if ($::o->isa('interactive_gtk')) { unlink glob_("/lib/lib$_*") foreach qw(slang newt); unlink "/usr/bin/perl-install/auto/Newt/Newt.so"; } else { unlink glob_("/usr/X11R6/bin/XF*"); } } sub remove_bigseldom_used { log::l("remove_bigseldom_used"); $::testing and return; remove_unused(); unlink "/usr/X11R6/lib/modules/xf86Wacom.so"; unlink glob_("/usr/share/gtk/themes/$_*") foreach qw(marble3d); unlink(m|^/| ? $_ : "/usr/bin/$_") foreach ((map { @$_ } @bigseldom_used_groups), qw(pvcreate pvdisplay vgchange vgcreate vgdisplay vgextend vgremove vgscan lvcreate lvdisplay lvremove /lib/liblvm.so), qw(mkreiserfs resize_reiserfs mkfs.xfs), ); } ################################################################################ package pkgs_interactive; use run_program; use common; use pkgs; sub install_steps::do_pkgs { my ($o) = @_; bless { o => $o }, 'pkgs_interactive'; } sub install { my ($do, @l) = @_; $do->{o}->pkg_install(@l); } sub is_installed { my ($do, @l) = @_; foreach (@l) { my $p = pkgs::packageByName($do->{o}->{packages}, $_); $p && pkgs::packageFlagSelected($p) or return; } 1; } sub remove { my ($do, @l) = @_; @l = grep { my $p = pkgs::packageByName($do->{o}->{packages}, $_); pkgs::unselectPackage($do->{o}->{packages}, $p) if $p; $p; } @l; run_program::rooted($do->{o}->{prefix}, 'rpm', '-e', @l); } sub remove_nodeps { my ($do, @l) = @_; @l = grep { my $p = pkgs::packageByName($do->{o}->{packages}, $_); pkgs::packageSetFlagSelected($p, 0) if $p; $p; } @l; run_program::rooted($do->{o}->{prefix}, 'rpm', '-e', '--nodeps', @l); } ################################################################################ package install_any; 1;