#!/usr/bin/perl
#
# Guillaume Cottenceau
#
# Copyright 2001-2005 Mandriva
#
# This software may be freely redistributed under the terms of the GNU
# public license.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

use lib qw(/usr/lib/libDrakX);
use common;
use devices;
use fs;
use fs::dmcrypt;
use fs::proc_partitions;
use fs::type;
use lvm;
use run_program;

my @proc_mounts = fs::read_fstab('', '/proc/mounts');

my $target = '/mnt';

if (fs::get::mntpoint2part($target, \@proc_mounts)) {
    print STDERR "$target is already mounted (according to /proc/mounts)\n";
    exit 0;
}

system('drvinst', 'STORAGE');

print STDERR "\nPlease wait, trying to find your root device...\n";

mkdir_p($target);

{
    local $::isInstall = 1; # so that detect_during_install() got called by init:
    lvm::init();
}
fs::dmcrypt::init;

my @parts = map {
    $_->{device} = delete $_->{dev};
    put_in_hash($_, fs::type::type_subpart_from_magic($_));   
} fs::proc_partitions::read_raw();
my ($raid_parts, $normal_parts) = partition { isRawRAID($_) } @parts;

if (@$raid_parts) {
    require raid;
    raid::detect_during_install(@$raid_parts);
    my $raids = raid::get_existing(@$raid_parts);
    push @$normal_parts, @$raids;
}

my @roots;

my $arch = arch() =~ /i.86/ ? $MDK::Common::System::compat_arch{arch()} : arch();
foreach (@$normal_parts) {
    my $dev = devices::make($_->{device});

    my $fs = find {
	system("mount -t $_ $dev $target 2>/dev/null") == 0;
    } fs::type::true_local_fs_types() or next;

    if (my $release_file = common::release_file($target)) {
	my $release = chomp_(cat_("$target$release_file"));
	print STDERR "=> found a $release root partition on $dev\n=> type $fs, version `\n";
	my @fstab = fs::read_fstab($target, '/etc/fstab');
	my $h = common::parse_release_file($target, $release_file, $_);
	add2hash($h, { dev => $dev,  fs => $fs, fstab => \@fstab,
		       pretty_name => "$h->{release} $h->{version} $h->{arch} on $dev" });
	# Offer to rescue only same arch:
	$h->{pretty_name} .= " (cannot be rescued: $h->{arch} ne $arch;)" if $h->{arch} ne $arch;
	push @roots, $h;
    }
    system('umount', $target) == 0 or die "error unmounting $target\n";
}

my ($root, $fs, @fstab);

# Try Mageia first:
if (@roots) {
    # Order by release number:
    @roots = sort { $b->{version} cmp $a->{version} } @roots;
    # Then pick mga over mdv:
    @roots = map { @$_ } partition { $_->{release} =~ /Mageia/ } @roots;

    my $selected;
    if (@roots == 1) {
        $selected = first(@roots);
    } else {
	print "\n\nWhich system do you want to rescue?\n0: Abort\n";
	each_index { print $::i + 1, ": $_->{pretty_name}\n" } @roots;
	my $res;
	while ($res < 1 || $res > @roots) {
	    print "what is your choice (type the number of your selection or C^c to abort)?\n";
	    $res = <>;
	    chomp($res);
	    if ($res eq "0") {
		print "Aborting\n";
		exit(1);
	    }
	}
        $selected = $roots[$res-1];
    }

    $root = $selected->{dev};
    $fs = $selected->{fs};
    @fstab = @{$selected->{fstab}};
    print STDERR "=> Selecting $root as root fs\n";
}

if ($root) {
    system("mount -t $fs $root $target 2>/dev/null");

    print STDERR "\nMounting other partitions from fstab on $target...\n";
    foreach (@fstab) {
	my ($valued_options, $options) = fs::mount_options::unpack($_);

	next if 
	  !$_->{fs_type} || $_->{device} eq 'none'
	    || $valued_options->{noauto}
	    || $_->{mntpoint} eq '/'
	    || member($_->{fs_type}, 'swap', 'nfs', 'ntfs', 'ntfs-3g');

	delete $valued_options->{'iocharset='};
	delete $valued_options->{'codepage='};
	fs::mount_options::pack($_, $valued_options, $options); #- vfat opts, we don't have the modules in rescue

	my $where = "$target$_->{mntpoint}";
	my $dev = fs::wild_device::from_part('', $_);
	mkdir_p($where);
	print STDERR "\t$dev on $where type $_->{fs_type} options $_->{options}\n";
	system("mount -t $_->{fs_type} $dev $where -o $_->{options}");
    }
    system("mount -t proc proc $target/proc");
    print STDERR "\nYour system is ready on $target.\n\n";
} else {
    die "Could not find your root device :-(.\n";
}