package partition_table; # $Id$ use diagnostics; use strict; use common; use fs::type; use partition_table::raw; use detect_devices; use log; sub hd2minimal_part { my ($hd) = @_; { rootDevice => $hd->{device}, if_($hd->{usb_media_type}, is_removable => 1), }; } #- works for both hard drives and partitions ;p sub description { my ($hd) = @_; my $win = $hd->{device_windobe}; sprintf "%s%s (%s)", $hd->{device}, $win && " [$win:]", join(', ', grep { $_ } formatXiB($hd->{totalsectors} || $hd->{size}, 512), $hd->{info}, $hd->{mntpoint}, $hd->{fs_type}); } sub adjustStartAndEnd { my ($hd, $part) = @_; $hd->adjustStart($part); $hd->adjustEnd($part); } sub verifyNotOverlap { my ($a, $b) = @_; $a->{start} + $a->{size} <= $b->{start} || $b->{start} + $b->{size} <= $a->{start}; } sub verifyInside { my ($a, $b) = @_; $b->{start} <= $a->{start} && $a->{start} + $a->{size} <= $b->{start} + $b->{size}; } sub verifyParts_ { foreach my $i (@_) { foreach (@_) { next if !$i || !$_ || $i == $_ || isWholedisk($i) || isExtended($i); #- avoid testing twice for simplicity :-) if (isWholedisk($_)) { verifyInside($i, $_) or cdie sprintf("partition sector #$i->{start} (%s) is not inside whole disk (%s)!", formatXiB($i->{size}, 512), formatXiB($_->{size}, 512)); } elsif (isExtended($_)) { verifyNotOverlap($i, $_) or log::l(sprintf("warning partition sector #$i->{start} (%s) is overlapping with extended partition!", formatXiB($i->{size}, 512))); #- only warning for this one is acceptable } else { verifyNotOverlap($i, $_) or cdie sprintf("partitions sector #$i->{start} (%s) and sector #$_->{start} (%s) are overlapping!", formatXiB($i->{size}, 512), formatXiB($_->{size}, 512)); } } } } sub verifyParts { my ($hd) = @_; verifyParts_(get_normal_parts($hd)); } sub verifyPrimary { my ($pt) = @_; $_->{start} > 0 || arch() =~ /^sparc/ || die "partition must NOT start at sector 0" foreach @{$pt->{normal}}; verifyParts_(@{$pt->{normal}}, $pt->{extended}); } sub compute_device_name { my ($part, $hd) = @_; $part->{device} = _compute_device_name($hd, $part->{part_number}); } sub _compute_device_name { my ($hd, $nb) = @_; my $prefix = $hd->{prefix} || $hd->{device} . ($hd->{device} =~ /\d$/ ? 'p' : ''); $prefix . $nb; } sub assign_device_numbers { my ($hd) = @_; my $i = 1; my $start = 1; #- on PPC we need to assign device numbers to the holes too - big FUN! #- not if it's an IBM machine using a DOS partition table though if (arch() =~ /ppc/ && detect_devices::get_mac_model() !~ /^IBM/) { #- first sort the normal parts $hd->{primary}{normal} = [ sort { $a->{start} <=> $b->{start} } @{$hd->{primary}{normal}} ]; #- now loop through them, assigning partition numbers - reserve one for the holes foreach (@{$hd->{primary}{normal}}) { if ($_->{start} > $start) { log::l("PPC: found a hole on $hd->{device} before $_->{start}, skipping device..."); $i++; } $_->{part_number} = $i; compute_device_name($_, $hd); $start = $_->{start} + $_->{size}; $i++; } } else { foreach (@{$hd->{primary}{raw}}) { $_->{part_number} = $i; compute_device_name($_, $hd); $i++; } foreach (map { $_->{normal} } @{$hd->{extended} || []}) { my $dev = _compute_device_name($hd, $i); my $renumbered = $_->{device} && $dev ne $_->{device}; if ($renumbered) { require fs::mount; eval { fs::mount::umount_part($_) }; #- at least try to umount it will_tell_kernel($hd, del => $_, 'delay_del'); push @{$hd->{partitionsRenumbered}}, [ $_->{device}, $dev ]; } $_->{part_number} = $i; compute_device_name($_, $hd); if ($renumbered) { will_tell_kernel($hd, add => $_, 'delay_add'); } $i++; } } #- try to figure what the windobe drive letter could be! # #- first verify there's at least one primary dos partition, otherwise it #- means it is a secondary disk and all will be false :( #- my ($c, @others) = grep { isFat_or_NTFS($_) } @{$hd->{primary}{normal}}; $i = ord 'C'; $c->{device_windobe} = chr($i++) if $c; $_->{device_windobe} = chr($i++) foreach grep { isFat_or_NTFS($_) } map { $_->{normal} } @{$hd->{extended}}; $_->{device_windobe} = chr($i++) foreach @others; } sub remove_empty_extended { my ($hd) = @_; my $last = $hd->{primary}{extended} or return; @{$hd->{extended}} = grep { if ($_->{normal}) { $last = $_; } else { %{$last->{extended}} = $_->{extended} ? %{$_->{extended}} : (); } $_->{normal}; } @{$hd->{extended}}; adjust_main_extended($hd); } sub adjust_main_extended { my ($hd) = @_; if (!is_empty_array_ref $hd->{extended}) { my ($l, @l) = @{$hd->{extended}}; # the first is a special case, must recompute its real size my $start = round_down($l->{normal}{start} - 1, $hd->{geom}{sectors}); my $end = $l->{normal}{start} + $l->{normal}{size}; my $only_linux = 1; my $has_win_lba = 0; foreach (map { $_->{normal} } $l, @l) { $start = min($start, $_->{start}); $end = max($end, $_->{start} + $_->{size}); $only_linux &&= isTrueLocalFS($_) || isSwap($_); $has_win_lba ||= $_->{pt_type} == 0xc || $_->{pt_type} == 0xe; } $l->{start} = $hd->{primary}{extended}{start} = $start; $l->{size} = $hd->{primary}{extended}{size} = $end - $start; } if (!@{$hd->{extended} || []} && $hd->{primary}{extended}) { will_tell_kernel($hd, del => $hd->{primary}{extended}); %{$hd->{primary}{extended}} = (); #- modify the raw entry delete $hd->{primary}{extended}; } verifyParts($hd); #- verify everything is all right } sub adjust_local_extended { my ($hd, $part) = @_; my $extended = find { $_->{normal} == $part } @{$hd->{extended} || []} or return; $extended->{size} = $part->{size} + $part->{start} - $extended->{start}; #- must write it there too because values are not shared my $prev = find { $_->{extended}{start} == $extended->{start} } @{$hd->{extended} || []} or return; $prev->{extended}{size} = $part->{size} + $part->{start} - $prev->{extended}{start}; } sub get_normal_parts { my ($hd) = @_; @{$hd->{primary}{normal} || []}, map { $_->{normal} } @{$hd->{extended} || []}; } sub get_normal_parts_and_holes { my ($hd) = @_; my ($start, $last) = ($hd->first_usable_sector, $hd->last_usable_sector); ref($hd) or print("get_normal_parts_and_holes: bad hd" . backtrace(), "\n"); my $minimal_hole = put_in_hash({ pt_type => 0 }, hd2minimal_part($hd)); my @l = map { my $current = $start; $start = $_->{start} + $_->{size}; my $hole = { start => $current, size => $_->{start} - $current, %$minimal_hole }; put_in_hash($hole, hd2minimal_part($hd)); $hole, $_; } sort { $a->{start} <=> $b->{start} } grep { !isWholedisk($_) } get_normal_parts($hd); push @l, { start => $start, size => min($last - $start, $hd->max_partition_size), %$minimal_hole } if $start < $hd->max_partition_start; grep { !isEmpty($_) || $_->{size} >= $hd->cylinder_size } @l; } sub _default_type { my ($hd) = @_; arch() =~ /ia64/ ? 'gpt' : arch() eq "alpha" ? "bsd" : arch() =~ /^sparc/ ? "sun" : arch() eq "ppc" && detect_devices::get_mac_model() !~ /^IBM/ ? "mac" : $hd->{totalsectors} > 4 * 1024 * 1024 * 2048 ? 'lvm' : "dos"; #- default to LVM on full disk when >4TB } sub initialize { my ($hd, $o_type) = @_; my $type = $o_type || _default_type($hd); require "partition_table/$type.pm"; "partition_table::$type"->initialize($hd); delete $hd->{extended}; if (detect_devices::is_xbox()) { my $part = { start => 1, size => 15632048, pt_type => 0x0bf, isFormatted => 1 }; partition_table::dos::compute_CHS($hd, $part); $hd->{primary}{raw}[0] = $part; } } sub read_primary { my ($hd) = @_; #- it can be safely considered that the first sector is used to probe the partition table #- but other sectors (typically for extended partition ones) have to match this type! my @parttype = ( if_(arch() =~ /^ia64/, 'gpt'), arch() =~ /^sparc/ ? ('sun', 'bsd') : ('lvm', 'dos', 'bsd', 'sun', 'mac'), ); foreach ('empty', @parttype, 'unknown') { /unknown/ and die "unknown partition table format on disk " . $hd->{file}; # perl_checker: require partition_table::bsd # perl_checker: require partition_table::dos # perl_checker: require partition_table::empty # perl_checker: require partition_table::lvm # perl_checker: require partition_table::gpt # perl_checker: require partition_table::mac # perl_checker: require partition_table::sun require "partition_table/$_.pm"; bless $hd, "partition_table::$_"; if ($hd->read_primary) { log::l("found a $_ partition table on $hd->{file} at sector 0"); return 1; } } 0; } sub read { my ($hd) = @_; read_primary($hd) or return 0; eval { my $need_removing_empty_extended; if ($hd->{primary}{extended}) { read_extended($hd, $hd->{primary}{extended}, \$need_removing_empty_extended) or return 0; } if ($need_removing_empty_extended) { #- special case when hda5 is empty, it must be skipped #- (windows XP generates such partition tables) remove_empty_extended($hd); #- includes adjust_main_extended } }; die "extended partition: $@" if $@; assign_device_numbers($hd); remove_empty_extended($hd); $hd->set_best_geometry_for_the_partition_table; 1; } sub read_extended { my ($hd, $extended, $need_removing_empty_extended) = @_; my $pt = do { my ($pt, $info) = $hd->read_one($extended->{start}) or return 0; partition_table::raw::pt_info_to_primary($hd, $pt, $info); }; $pt = { %$extended, %$pt }; push @{$hd->{extended}}, $pt; @{$hd->{extended}} > 100 and die "oops, seems like we're looping here :( (or you have more than 100 extended partitions!)"; if (@{$pt->{normal}} == 0) { $$need_removing_empty_extended = 1; delete $pt->{normal}; print "need_removing_empty_extended\n"; } elsif (@{$pt->{normal}} > 1) { die "more than one normal partition in extended partition"; } else { $pt->{normal} = $pt->{normal}[0]; #- in case of extended partitions, the start sector is local to the partition or to the first extended_part! $pt->{normal}{start} += $pt->{start}; #- the following verification can broke an existing partition table that is #- correctly read by fdisk or cfdisk. maybe the extended partition can be #- recomputed to get correct size. if (!verifyInside($pt->{normal}, $extended)) { $extended->{size} = $pt->{normal}{start} + $pt->{normal}{size}; verifyInside($pt->{normal}, $extended) or die "partition $pt->{normal}{device} is not inside its extended partition"; } } if ($pt->{extended}) { $pt->{extended}{start} += $hd->{primary}{extended}{start}; return read_extended($hd, $pt->{extended}, $need_removing_empty_extended); } else { 1; } } sub will_tell_kernel { my ($hd, $action, $o_part, $o_delay) = @_; if ($action eq 'resize') { will_tell_kernel($hd, del => $o_part); will_tell_kernel($hd, add => $o_part); } else { my $part_number; if ($o_part) { ($part_number) = $o_part->{device} =~ /(\d+)$/ or #- do not die, it occurs when we zero_MBR_and_dirty a raw_lvm_PV log::l("ERROR: will_tell_kernel bad device " . description($o_part)), return; } my @para = $action eq 'force_reboot' ? () : $action eq 'add' ? ($part_number, $o_part->{start}, $o_part->{size}) : $action eq 'del' ? $part_number : internal_error("unknown action $action"); push @{$hd->{'will_tell_kernel' . ($o_delay || '')} ||= []}, [ $action, @para ]; } if (!$o_delay) { foreach my $delay ('delay_del', 'delay_add') { my $l = delete $hd->{"will_tell_kernel$delay"} or next; push @{$hd->{will_tell_kernel} ||= []}, @$l; } } $hd->{isDirty} = 1; } sub tell_kernel { my ($hd, $tell_kernel) = @_; my $F = partition_table::raw::openit($hd); my $force_reboot = any { $_->[0] eq 'force_reboot' } @$tell_kernel; if (!$force_reboot) { # only keep the last action on the partition number # that way we do not del/add the same partition, and this helps udev :) foreach (reverse(uniq_ { $_->[1] } reverse @$tell_kernel)) { my ($action, $part_number, $o_start, $o_size) = @$_; if ($action eq 'add') { $force_reboot ||= !c::add_partition(fileno $F, $part_number, $o_start, $o_size); } elsif ($action eq 'del') { $force_reboot ||= !c::del_partition(fileno $F, $part_number); } log::l("tell kernel $action ($hd->{device} $part_number $o_start $o_size) force_reboot=$force_reboot rebootNeeded=$hd->{rebootNeeded}"); } } if ($force_reboot) { my @magic_parts = grep { $_->{isMounted} && $_->{real_mntpoint} } get_normal_parts($hd); foreach (@magic_parts) { syscall_('umount', $_->{real_mntpoint}) or log::l(N("error unmounting %s: %s", $_->{real_mntpoint}, $!)); } $hd->{rebootNeeded} = !ioctl($F, c::BLKRRPART(), 0); log::l("tell kernel force_reboot ($hd->{device}), rebootNeeded=$hd->{rebootNeeded}"); foreach (@magic_parts) { syscall_('mount', $_->{real_mntpoint}, $_->{fs_type}, c::MS_MGC_VAL()) or log::l(N("mount failed: ") . $!); } } } # write the partition table sub write { my ($hd) = @_; $hd->{isDirty} or return; $hd->{readonly} and internal_error("a read-only partition table should not be dirty ($hd->{device})!"); #- set first primary partition active if no primary partitions are marked as active. if (my @l = @{$hd->{primary}{raw}}) { foreach (@l) { $_->{local_start} = $_->{start}; $_->{active} ||= 0; } $l[0]{active} = 0x80 if !any { $_->{active} } @l; } #- last chance for verification, this make sure if an error is detected, #- it will never be writed back on partition table. verifyParts($hd); $hd->write(0, $hd->{primary}{raw}, $hd->{primary}{info}) or die "writing of partition table failed"; #- should be fixed but a extended exist with no real extended partition, that blanks mbr! if (arch() !~ /^sparc/) { foreach (@{$hd->{extended}}) { # in case of extended partitions, the start sector must be local to the partition $_->{normal}{local_start} = $_->{normal}{start} - $_->{start}; $_->{extended} and $_->{extended}{local_start} = $_->{extended}{start} - $hd->{primary}{extended}{start}; $hd->write($_->{start}, $_->{raw}) or die "writing of partition table failed"; } } $hd->{isDirty} = 0; if (my $tell_kernel = delete $hd->{will_tell_kernel}) { if (fs::type::is_dmraid($hd)) { fs::dmraid::call_dmraid('-an'); fs::dmraid::call_dmraid('-ay'); } else { tell_kernel($hd, $tell_kernel); } } } sub active { my ($hd, $part) = @_; $_->{active} = 0 foreach @{$hd->{primary}{normal}}; $part->{active} = 0x80; $hd->{isDirty} = 1; } # remove a normal partition from hard drive hd sub remove { my ($hd, $part) = @_; my $i; #- first search it in the primary partitions $i = 0; foreach (@{$hd->{primary}{normal}}) { if ($_ eq $part) { will_tell_kernel($hd, del => $_); splice(@{$hd->{primary}{normal}}, $i, 1); %$_ = (); #- blank it $hd->raw_removed($hd->{primary}{raw}); return 1; } $i++; } my ($first, $second, $third) = map { $_->{normal} } @{$hd->{extended} || []}; if ($third && $first eq $part) { die "Can not handle removing hda5 when hda6 is not the second partition" if $second->{start} > $third->{start}; } #- otherwise search it in extended partitions foreach (@{$hd->{extended} || []}) { $_->{normal} eq $part or next; delete $_->{normal}; #- remove it remove_empty_extended($hd); assign_device_numbers($hd); will_tell_kernel($hd, del => $part); return 1; } 0; } # create of partition at starting at `start', of size `size' and of type `pt_type' (nice comment, uh?) sub add_primary { my ($hd, $part) = @_; { local $hd->{primary}{normal}; #- save it to fake an addition of $part, that way add_primary do not modify $hd if it fails push @{$hd->{primary}{normal}}, $part; adjust_main_extended($hd); #- verify $hd->raw_add($hd->{primary}{raw}, $part); } push @{$hd->{primary}{normal}}, $part; #- really do it } sub add_extended { arch() =~ /^sparc|ppc/ and die N("Extended partition not supported on this platform"); my ($hd, $part, $extended_type) = @_; $extended_type =~ s/Extended_?//; my $e = $hd->{primary}{extended}; if ($e && !verifyInside($part, $e)) { #-die "sorry, can not add outside the main extended partition" unless $::unsafe; my $end = $e->{start} + $e->{size}; my $start = min($e->{start}, $part->{start}); $end = max($end, $part->{start} + $part->{size}) - $start; { #- faking a resizing of the main extended partition to test for problems local $e->{start} = $start; local $e->{size} = $end - $start; eval { verifyPrimary($hd->{primary}) }; $@ and die N("You have a hole in your partition table but I can not use it. The only solution is to move your primary partitions to have the hole next to the extended partitions."); } } if ($e && $part->{start} < $e->{start}) { my $l = first(@{$hd->{extended}}); #- the first is a special case, must recompute its real size $l->{start} = round_down($l->{normal}{start} - 1, $hd->cylinder_size); $l->{size} = $l->{normal}{start} + $l->{normal}{size} - $l->{start}; my $ext = { %$l }; unshift @{$hd->{extended}}, { pt_type => 5, raw => [ $part, $ext, {}, {} ], normal => $part, extended => $ext }; #- size will be autocalculated :) } else { my ($ext, $ext_size) = is_empty_array_ref($hd->{extended}) ? ($hd->{primary}, -1) : #- -1 size will be computed by adjust_main_extended (top(@{$hd->{extended}}), $part->{size}); my %ext = (pt_type => $extended_type || 5, start => $part->{start}, size => $ext_size); $hd->raw_add($ext->{raw}, \%ext); $ext->{extended} = \%ext; push @{$hd->{extended}}, { %ext, raw => [ $part, {}, {}, {} ], normal => $part }; } $part->{start}++; $part->{size}--; #- let it start after the extended partition sector adjustStartAndEnd($hd, $part); adjust_main_extended($hd); } sub add { my ($hd, $part, $b_primaryOrExtended, $b_forceNoAdjust) = @_; get_normal_parts($hd) >= ($hd->{device} =~ /^rd/ ? 7 : $hd->{device} =~ /^(sd|ida|cciss|ataraid)/ ? 15 : 63) and cdie "maximum number of partitions handled by linux reached"; set_isFormatted($part, 0); put_in_hash($part, hd2minimal_part($hd)); $part->{start} ||= 1 if arch() !~ /^sparc/; #- starting at sector 0 is not allowed adjustStartAndEnd($hd, $part) unless $b_forceNoAdjust; my $nb_primaries = $hd->{device} =~ /^rd/ ? 3 : 1; if (arch() =~ /^sparc|ppc/ || $b_primaryOrExtended eq 'Primary' || $b_primaryOrExtended !~ /Extended/ && @{$hd->{primary}{normal} || []} < $nb_primaries) { eval { add_primary($hd, $part) }; goto success if !$@; } if ($hd->hasExtended) { eval { add_extended($hd, $part, $b_primaryOrExtended) }; goto success if !$@; } { add_primary($hd, $part); } success: assign_device_numbers($hd); will_tell_kernel($hd, add => $part); } # search for the next partition sub next { my ($hd, $part) = @_; first( sort { $a->{start} <=> $b->{start} } grep { $_->{start} >= $part->{start} + $part->{size} } get_normal_parts($hd) ); } sub next_start { my ($hd, $part) = @_; my $next = &next($hd, $part); $next ? $next->{start} : $hd->last_usable_sector; } 1; n408'>408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
package help; # $Id$

use common qw(:common);

%steps = (
empty => '',

selectLanguage =>
 __("Please choose your preferred language for installation and system usage."),

license =>
 __("You need to accept the terms of the above license to continue installation.

Please click on \"Accept\" if you are agree with its terms.

Please click on \"Refuse\" if you disagree with its terms. Installation will end without modifying your current
configuration."),

selectKeyboard =>
 __("Choose the layout corresponding to your keyboard from the list above"),

selectLangs => 
 __("If you wish other languages (than the one you choose at
beginning of installation) will be available after installation, please chose
them in list above. If you want select all, you just need to select \"All\"."),

selectInstallClass =>
 __("Please choose \"Install\" if there are no previous version of Linux-Mandrake
installed or if you wish to use several operating systems.

Please choose \"Rescue\" if you wish to rescue an already installed version of Linux-Mandrake.

Depend of your knowledge in GNU/Linux, you can choose one of the following levels to install or rescue your
Linux-Mandrake operating system:

	* Recommanded: if you have never installed a GNU/Linux operating system choose this. Installation will be
	  be very easy and you will be asked only on few questions.

	* Customized: if you are familiar enough with GNU/Linux, you may choose the primary usge (workstation, server,
	  development) of your sytem. You will need to answer to more questions than in \"Recommanded\" installation
	  class, so you need to know how works GNU/Linux to choose this installation class.

	* Expert: if you have a good knowledge in GNU/Linux, you can choose this installation class. As in \"Customized\"
	  installation class, you will be able to choose the primary usage (workstation, server, development). Be very
	  careful before choose this installation class. You will be able to perform a higly customized installation.
	  Answer to some questions can be very difficult if you haven't a good knowledge in GNU/Linux. So, don't choose
	  this installation class unless you know what you are doing."),

selectInstallClassCorpo =>
 __("Select:

  - Customized: If you are familiar enough with GNU/Linux, you may then choose
    the primary usage for your machine. See below for details.

  - Expert: This supposes that you are fluent with GNU/Linux and want to
    perform a highly customized installation. As for a \"Customized\"
    installation class, you will be able to select the usage for your system.
    But please, please, DO NOT CHOOSE THIS UNLESS YOU KNOW WHAT YOU ARE DOING!"),

selectInstallClass2 =>
 __("You must now define your machine usage. Choices are:

	* Workstation: this the ideal choice if you intend to use your machine primarily for everyday use, at office or
	  at home.

	* Development: if you intend to use your machine primarily for software development, it is the good choice. You
	  will then have a complete collection of software installed in order to compile, debug and format source code,
	  or create software packages.

	* Server: if you intend to use this machine as a server, it is the good choice. Either a file server (NFS or
	  SMB), a print server (Unix style or Microsoft Windows style), an authentication server (NIS), a database
	  server and so on. As such, do not expect any gimmicks (KDE, GNOME, etc.) to be installed."),

setupSCSI => 
 __("DrakX will attempt to look for PCI SCSI adapter(s). If DrakX
finds an SCSI adapter and knows which driver to use, it will be automatically
installed.

If you have no SCSI adapter, an ISA SCSI adapter or a PCI SCSI adapter that
DrakX doesn't recognize, you will be asked if a SCSI adapter is present in your
system. If there is no adapter present, you can click on \"No\". If you click on
\"Yes\", a list of drivers will be presented from which you can select your
specific adapter.

If you have to manually specify your adapter, DrakX will ask if you want to
specify options for it. You should allow DrakX to probe the hardware for the
options. This usually works well.

If not, you will need to provide options to the driver. Please review the User
Guide (chapter 3, section \"Collective informations on your hardware) for hints
on retrieving this information from hardware documentation, from the
manufacturer's Web site (if you have Internet access) or from Microsoft Windows
(if you have it on your system)."),

doPartitionDisks => 
 __("At this point, you need to choose where to install your
Linux-Mandrake operating system on your hard drive. If it is empty or if an
existing operating system uses all the space available on it, you need to
partition it. Basically, partitioning a hard drive consists of logically
dividing it to create space to install your new Linux-Mandrake system.

Because the effects of the partitioning process are usually irreversible,
partitioning can be intimidating and stressful if you are an inexperienced user.
This wizard simplifies this process. Before begining, please consult the manual
and take your time.

You need at least two partitions. One is for the operating system itself and the
other is for the virtual memory (also called Swap).

If partitions have been already defined (from a previous installation or from
another partitioning tool), you just need choose those to use to install your
Linux system.

If partitions haven't been already defined, you need to create them. 
To do that, use the wizard available above. Depending of your hard drive
configuration, several solutions can be available:

	* Use existing partition: the wizard has detected one or more existing Linux partitions on your hard drive. If
	  you want to keep them, choose this option. 

	* Erase entire disk: if you want delete all data and
all partitions present on your hard drive and replace them by
	  your new Linux-Mandrake system, you can choose this option. Be careful with this solution, you will not be
	  able to revert your choice after confirmation.

	* Use the free space on the Windows partition: if Microsoft Windows is installed on your hard drive and takes
	  all space available on it, you have to create free space for Linux data. To do that you can delete your
	  Microsoft Windows partition and data (see \"Erase entire disk\" or \"Expert mode\" solutions) or resize your
	  Microsoft Windows partition. Resizing can be performed
without loss of any data. This solution is
	  recommended if you want use both Linux-Mandrake and Microsoft Windows on same computer.

	  Before choosing this solution, please understand
that the size of your Microsoft
	  Windows partition will be smaller than at present time. It means that you will have less free space under
	  Microsoft Windows to store your data or install new software.

	* Expert mode: if you want to partition manually your hard drive, you can choose this option. Be careful before
	  choosing this solution. It is powerful but it is very dangerous. You can lose all your data very easily. So,
	  don't choose this solution unless you know what you are doing."),

partition_with_diskdrake => 
 __("At this point, you need to choose what
partition(s) to use to install your new Linux-Mandrake system. If partitions
have been already defined (from a previous installation of GNU/Linux or from
another partitioning tool), you can use existing partitions. In other cases,
hard drive partitions must be defined.

To create partitions, you must first select a hard drive. You can select the
disk for partitioning by clicking on \"hda\" for the firs IDE drive, \"hdb\" for
the second or \"sda\" for the first SCSI drive and so on.

To partition the selected hard drive, you can use these options:

   * Clear all: this option deletes all partitions available on the selected hard drive.

   * Auto allocate:: this option allows you to automatically create Ext2 and swap partitions in free space of your
     hard drive.

   * Rescue partition table: if your partition table is damaged, you can try to recover it using this option. Please
     be careful and remember that it can fail.

   * Undo: you can use this option to cancel your changes.

   * Reload: you can use this option if you wish to undo all changes and load your initial partitions table

   * Wizard: If you wish to use a wizard to partition your hard drive, you can use this option. It is recommended if
     you do not have a good knowledge in partitioning.

   * Restore from floppy: if you have saved your partition table on a floppy during a previous installation, you can
     recover it using this option.

   * Save on floppy: if you wish to save your partition table on a floppy to be able to recover it, you can use this
     option. It is strongly recommended to use this option

   * Done: when you have finished partitioning your hard drive, use this option to save your changes.

For information, you can reach any option using the keyboard: navigate trough the partitions using Tab and Up/Down
        arrows. When a partition is selected, you can use:

           * Ctrl-c to create a new partition (when a empty partition is selected)

           * Ctrl-d to delete a partition

           * Ctrl-m to set the mount point"),

ask_mntpoint_s => 
 __("Above are listed the existing Linux partitions detected on
your hard drive. You can keep choices make by the wizard, they are good for a
common usage. If you change these choices, you must at least define a root
partition (\"/\"). Don't choose a too little partition or you will not be able
to install enough software. If you want store your data on a separate partition,
you need also to choose a \"/home\" (only possible if you have more than one
Linux partition available).

For information, each partition is listed as follows: \"Name\", \"Capacity\".

\"Name\" is coded as follow: \"hard drive type\", \"hard drive number\",
\"partition number\" (for example, \"hda1\").

\"Hard drive type\" is \"hd\" if your hard drive is an IDE hard drive and \"sd\"
if it is an SCSI hard drive.

\"Hard drive number\" is always a letter after \"hd\" or \"sd\". With IDE hard drives:

   * \"a\" means \"master hard drive on the primary IDE controller\",

   * \"b\" means \"slave hard drive on the primary IDE controller\",

   * \"c\" means \"master hard drive on the secondary IDE controller\",

   * \"d\" means \"slave hard drive on the secondary IDE controller\".

With SCSI hard drives, a \"a\" means \"primary hard drive\", a \"b\" means \"secondary hard drive\", etc..."),

takeOverHdChoose => 
 __("Choose the hard drive you want to erase to install your
new Linux-Mandrake partition. Be careful, all data present on it will be lost
and will not be recoverable."),

takeOverHdConfirm => 
 __("Click on \"OK\" if you want to delete all data and
partitions present on this hard drive. Be careful, after clicking on \"OK\", you
will not be able to recover any data and partitions present on this hard drive,
including any Windows data.

Click on \"Cancel\" to cancel this operation without losing any data and
partitions present on this hard drive."),

resizeFATChoose => 
 __("More than one Microsoft Windows partition have been
detected on your hard drive. Please choose the one you want resize to install
your new Linux-Mandrake operating system.

For information, each partition is listed as follow; \"Linux name\", \"Windows
name\" \"Capacity\".

\"Linux name\" is coded as follow: \"hard drive type\", \"hard drive number\",
\"partition number\" (for example, \"hda1\").

\"Hard drive type\" is \"hd\" if your hard dive is an IDE hard drive and \"sd\"
if it is an SCSI hard drive.

\"Hard drive number\" is always a letter putted after \"hd\" or \"sd\". With IDE hard drives:

   * \"a\" means \"master hard drive on the primary IDE controller\",

   * \"b\" means \"slave hard drive on the primary IDE controller\",

   * \"c\" means \"master hard drive on the secondary IDE controller\",

   * \"d\" means \"slave hard drive on the secondary IDE controller\".

With SCSI hard drives, a \"a\" means \"primary hard drive\", a \"b\" means \"secondary hard drive\", etc.

\"Windows name\" is the letter of your hard drive under Windows (the first disk
or partition is called \"C:\")."),

resizeFATWait => 
 __("Please be patient. This operation can take several minutes."),

formatPartitions => 
 __("Any partitions that have been newly defined must be
formatted for use (formatting meaning creating a filesystem).

At this time, you may wish to reformat some already existing partitions to erase
the data they contain. If you wish do that, please also select the partitions
you want to format.

Please note that it is not necessary to reformat all pre-existing partitions.
You must reformat the partitions containing the operating system (such as \"/\",
\"/usr\" or \"/var\") but do you no have to reformat partitions containing data
that you wish to keep (typically /home).

Please be careful selecting partitions, after formatting, all data will be
deleted and you will not be able to recover any of them.

Click on \"OK\" when you are ready to format partitions.