summaryrefslogtreecommitdiffstats
path: root/perl-install/fsedit.pm
blob: 55efecdddaf065f0fdb0882c77654cb928e41f17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
-rw-r--r--
perl-install/share/po/uz.po642
1 files changed, 311 insertions, 331 deletions
diff --git a/perl-install/share/po/uz.po b/perl-install/share/po/uz.po
index c4f909f00..61ec5456c 100644
--- a/perl-install/share/po/uz.po
+++ b/perl-install/share/po/uz.po
@@ -28,7 +28,7 @@ msgstr "Iltimos kutib turing"
#: any.pm:245
#, c-format
msgid "Bootloader installation in progress"
-msgstr "Operatsion tizim yuklagichini o'rnatish davom etmoqda"
+msgstr "Operatsion tizim yuklagichini oʻrnatish davom etmoqda"
#: any.pm:256
#, c-format
@@ -45,8 +45,8 @@ msgstr ""
#, c-format
msgid "Installation of bootloader failed. The following error occurred:"
msgstr ""
-"Operatsion tizim yuklagichini o'rnatish muvaffaqiyatsiz tugadi. Quyidagi "
-"xato ro'y berdi:"
+"Operatsion tizim yuklagichini oʻrnatish muvaffaqiyatsiz tugadi. Quyidagi xato roʻy "
+"berdi:"
#: any.pm:273
#, c-format
@@ -87,17 +87,17 @@ msgstr "Disketga"
#: any.pm:339
#, c-format
msgid "Skip"
-msgstr "O'tkazib yuborish"
+msgstr "Oʻtkazib yuborish"
#: any.pm:343
#, c-format
msgid "LILO/grub Installation"
-msgstr "LILO/GRUB dasturini o'rnatish"
+msgstr "LILO/GRUB dasturini oʻrnatish"
#: any.pm:345
#, c-format
msgid "Where do you want to install the bootloader?"
-msgstr "Operatsion tizim yuklagichini qaerga o'rnatmoqchisiz?"
+msgstr "Operatsion tizim yuklagichini qaerga oʻrnatmoqchisiz?"
#: any.pm:372
#, c-format
@@ -153,17 +153,17 @@ msgstr "Lokal APIC'ni yoqish"
#: diskdrake/smbnfs_gtk.pm:181
#, c-format
msgid "Password"
-msgstr "Maxfiy so'z"
+msgstr "Maxfiy soʻz"
#: any.pm:400 authentication.pm:208
#, c-format
msgid "The passwords do not match"
-msgstr "Maxfiy so'zlar mos kelmaydi"
+msgstr "Maxfiy soʻzlar mos kelmaydi"
#: any.pm:400 authentication.pm:208 diskdrake/interactive.pm:1299
#, c-format
msgid "Please try again"
-msgstr "Iltimos yana urinib ko'ring"
+msgstr "Iltimos yana urinib koʻring"
#: any.pm:401
#, c-format
@@ -173,7 +173,7 @@ msgstr ""
#: any.pm:404 any.pm:787 any.pm:796 authentication.pm:198
#, c-format
msgid "Password (again)"
-msgstr "Maxfiy so'z (yana)"
+msgstr "Maxfiy soʻz (yana)"
#: any.pm:405
#, c-format
@@ -194,12 +194,12 @@ msgstr ""
#: any.pm:408
#, c-format
msgid "Clean /tmp at each boot"
-msgstr "Tizimni yuklashda /tmp direktoriyasini bo'shatish"
+msgstr "Tizimni yuklashda /tmp direktoriyasini boʻshatish"
#: any.pm:409
#, c-format
msgid "Precise RAM size if needed (found %d MB)"
-msgstr "Kerak bo'lsa, RAM'ning aniq hajmi (%d Mb topildi)"
+msgstr "Kerak boʻlsa, RAM'ning aniq hajmi (%d Mb topildi)"
#: any.pm:410
#, c-format
@@ -289,12 +289,12 @@ msgstr "Videosiz"
#: any.pm:532
#, c-format
msgid "Empty label not allowed"
-msgstr "Bo'sh yorliqni ishlatish mumkin emas"
+msgstr "Boʻsh yorliqni ishlatish mumkin emas"
#: any.pm:533
#, c-format
msgid "You must specify a kernel image"
-msgstr "Kernelning tasvirini ko'rsatishingiz kerak."
+msgstr "Kernelning tasvirini koʻrsatishingiz kerak."
#: any.pm:533
#, c-format
@@ -309,7 +309,7 @@ msgstr "Yorliq allaqachon ishlatilgan"
#: any.pm:552
#, c-format
msgid "Which type of entry do you want to add?"
-msgstr "Bandning qaysi turini qo'shmoqchisiz?"
+msgstr "Bandning qaysi turini qoʻshmoqchisiz?"
#: any.pm:553
#, c-format
@@ -338,8 +338,8 @@ msgid ""
"You can create additional entries or change the existing ones."
msgstr ""
"Tizimni yuklash menyusining bandlari.\n"
-"Qo'shimcha bandlar yaratishingiz yoki mavjud bo'lgan bandlarni "
-"o'zgartirishingiz mumkin."
+"Qoʻshimcha bandlar yaratishingiz yoki mavjud boʻlgan bandlarni oʻzgartirishingiz "
+"mumkin."
#: any.pm:745
#, c-format
@@ -354,7 +354,7 @@ msgstr "RPM vositalaridan foydalanishga ruxsat etish"
#: any.pm:747
#, c-format
msgid "allow \"su\""
-msgstr "\"su\" buyrug'idan foydalanishga ruxsat etish"
+msgstr "\"su\" buyrugʻidan foydalanishga ruxsat etish"
#: any.pm:748
#, c-format
@@ -374,7 +374,7 @@ msgstr ""
#: any.pm:756
#, c-format
msgid "(already added %s)"
-msgstr "(%s allaqachon qo'shilgan)"
+msgstr "(%s allaqachon qoʻshilgan)"
#: any.pm:762
#, c-format
@@ -387,7 +387,7 @@ msgid ""
"The user name must contain only lower cased letters, numbers, `-' and `_'"
msgstr ""
"Foydalanuvchining ismi faqat kichkina harf, son, \"-\" va \"_\" belgilaridan "
-"iborat bo'lishi shart"
+"iborat boʻlishi shart"
#: any.pm:764
#, c-format
@@ -397,7 +397,7 @@ msgstr "Foydalanuvchining ismi juda uzun"
#: any.pm:765
#, c-format
msgid "This user name has already been added"
-msgstr "Foydalanuvchining ismi allaqachon qo'shilgan"
+msgstr "Foydalanuvchining ismi allaqachon qoʻshilgan"
#: any.pm:771 any.pm:798
#, c-format
@@ -412,7 +412,7 @@ msgstr "Guruh ID"
#: any.pm:772
#, c-format
msgid "%s must be a number"
-msgstr "%s son bo'lishi kerak"
+msgstr "%s son boʻlishi kerak"
#: any.pm:773
#, c-format
@@ -556,7 +556,7 @@ msgstr "Davlatingizni tanlang."
#: any.pm:1056
#, c-format
msgid "Here is the full list of available countries"
-msgstr "Mavjud bo'lgan davlatlarning to'liq ro'yxati"
+msgstr "Mavjud boʻlgan davlatlarning toʻliq roʻyxati"
#: any.pm:1057
#, c-format
@@ -566,7 +566,7 @@ msgstr "Boshqa davlatlar"
#: any.pm:1057 interactive.pm:481
#, c-format
msgid "Advanced"
-msgstr "Qo'shimcha"
+msgstr "Qoʻshimcha"
#: any.pm:1063
#, c-format
@@ -576,7 +576,7 @@ msgstr "Kiritish usuli:"
#: any.pm:1066
#, c-format
msgid "None"
-msgstr "Yo'q"
+msgstr "Yoʻq"
#: any.pm:1146
#, c-format
@@ -645,8 +645,7 @@ msgstr "Iltimos tizimdan chiqing va Ctrl+Alt+BackSpace tugmalarni bosing"
#: any.pm:1299
#, c-format
msgid "You need to log out and back in again for changes to take effect"
-msgstr ""
-"O'zgarishlar to'liq qo'llanilishi uchun tizimga boshqadan kirishingiz kerak"
+msgstr "Oʻzgarishlar toʻliq qoʻllanilishi uchun tizimga boshqadan kirishingiz kerak"
#: any.pm:1334
#, c-format
@@ -844,7 +843,7 @@ msgstr "Server"
#: authentication.pm:126
#, c-format
msgid "LDAP users database"
-msgstr "LDAP ma'lumot bazasi"
+msgstr "LDAP maʼlumot bazasi"
#: authentication.pm:127
#, c-format
@@ -859,7 +858,7 @@ msgstr ""
#: authentication.pm:129
#, c-format
msgid "Password for user"
-msgstr "Foydalanuvchi uchun maxfiy so'z"
+msgstr "Foydalanuvchi uchun maxfiy soʻz"
#: authentication.pm:141
#, c-format
@@ -927,13 +926,12 @@ msgstr "Tasdiqlash usuli"
#: authentication.pm:190
#, c-format
msgid "No password"
-msgstr "Maxfiy so'zsiz"
+msgstr "Maxfiy soʻzsiz"
#: authentication.pm:211
#, c-format
msgid "This password is too short (it must be at least %d characters long)"
-msgstr ""
-"Bu maxfiy so'z juda qisqa (u eng kami %d belgidan iborat bo'lishi shart)"
+msgstr "Bu maxfiy soʻz juda qisqa (u eng kami %d belgidan iborat boʻlishi shart)"
#: authentication.pm:352
#, c-format
@@ -984,12 +982,12 @@ msgstr "SILO"
#: bootloader.pm:1135
#, c-format
msgid "not enough room in /boot"
-msgstr "/boot direktoriyasida yetarli joy yo'q"
+msgstr "/boot direktoriyasida yetarli joy yoʻq"
#: bootloader.pm:1760
#, c-format
msgid "You can not install the bootloader on a %s partition\n"
-msgstr "Operatsion tizim yuklagichini diskning %s qismiga o'rnatib bo'lmaydi\n"
+msgstr "Operatsion tizim yuklagichini diskning %s qismiga oʻrnatib boʻlmaydi\n"
#: bootloader.pm:1813
#, c-format
@@ -1008,7 +1006,7 @@ msgstr ""
#: bootloader.pm:1827
#, c-format
msgid "Re-install Boot Loader"
-msgstr "OT yuklagichini qaytadan o'rnatish"
+msgstr "OT yuklagichini qaytadan oʻrnatish"
#: common.pm:142
#, c-format
@@ -1053,7 +1051,7 @@ msgstr "%d soniya"
#: common.pm:335
#, c-format
msgid "command %s missing"
-msgstr "%s buyrug'i yetishmayapti"
+msgstr "%s buyrugʻi yetishmayapti"
#: diskdrake/dav.pm:17
#, c-format
@@ -1147,18 +1145,18 @@ msgstr "Parametrlar: %s"
#: fs/partitioning_wizard.pm:270 fs/partitioning_wizard.pm:275
#, c-format
msgid "Partitioning"
-msgstr "Diskni bo'lish"
+msgstr "Diskni boʻlish"
#: diskdrake/hd_gtk.pm:93 diskdrake/interactive.pm:1008
#: diskdrake/interactive.pm:1018 diskdrake/interactive.pm:1071
#, c-format
msgid "Read carefully!"
-msgstr "Diqqat bilan o'qing!"
+msgstr "Diqqat bilan oʻqing!"
#: diskdrake/hd_gtk.pm:93
#, c-format
msgid "Please make a backup of your data first"
-msgstr "Iltimos avvalo ma'lumotlaringizdan zahira nusxa oling"
+msgstr "Iltimos avvalo maʼlumotlaringizdan zahira nusxa oling"
#: diskdrake/hd_gtk.pm:94 diskdrake/interactive.pm:224
#, c-format
@@ -1177,8 +1175,8 @@ msgid ""
"enough)\n"
"at the beginning of the disk"
msgstr ""
-"Agar rejangizda aboot dasturini ishlatish bo'lsa, diskning boshida bo'sh joy "
-"(2048 sektor yetadi)\n"
+"Agar rejangizda aboot dasturini ishlatish boʻlsa, diskning boshida boʻsh joy (2048 "
+"sektor yetadi)\n"
"qoldirish esingizdan chiqmasin"
#: diskdrake/hd_gtk.pm:160 interactive.pm:644 interactive/gtk.pm:744
@@ -1200,8 +1198,8 @@ msgid ""
"(click on it, then click on \"Resize\")"
msgstr ""
"Diskingiz bitta katta Microsoft Windows qismidan iborat.\n"
-"Avvalo, uning hajmini o'zgartirishni taklif qilaman\n"
-"(uni bosing keyin \"Hajmini o'gartirish\" tugmasini bosing)."
+"Avvalo, uning hajmini oʻzgartirishni taklif qilaman\n"
+"(uni bosing keyin \"Hajmini oʻgartirish\" tugmasini bosing)."
#: diskdrake/hd_gtk.pm:201
#, c-format
@@ -1221,7 +1219,7 @@ msgstr "Qattiq disklar topilmadi"
#: diskdrake/hd_gtk.pm:290
#, c-format
msgid "Unknown"
-msgstr "Noma'lum"
+msgstr "Nomaʼlum"
#: diskdrake/hd_gtk.pm:352
#, c-format
@@ -1261,7 +1259,7 @@ msgstr "Boshqa"
#: diskdrake/hd_gtk.pm:353 diskdrake/interactive.pm:1194
#, c-format
msgid "Empty"
-msgstr "Bo'sh"
+msgstr "Boʻsh"
#: diskdrake/hd_gtk.pm:357
#, c-format
@@ -1282,7 +1280,7 @@ msgstr "Diqqat"
#: diskdrake/hd_gtk.pm:381
#, c-format
msgid "This partition is already empty"
-msgstr "Diskning bu qismi allaqachon use vars qw(%suggestions); #-###################################################################################### #- misc imports #-###################################################################################### use common; use partition_table; use partition_table::raw; use fs::get; use fs::type; use fs::loopback; use fs::proc_partitions; use detect_devices; use devices; use log; use fs; # min_hd_size: only suggest this partition if the hd size is bigger than that %suggestions = ( N_("simple") => [ { mntpoint => "/", size => MB(300), fs_type => defaultFS(), ratio => 10, maxsize => MB(12300) }, { mntpoint => "swap", size => MB(128), fs_type => 'swap', ratio => 1, maxsize => MB(4000) }, { mntpoint => "/home", size => MB(300), fs_type => defaultFS(), ratio => 8, min_hd_size => MB(8000) }, ], N_("with /usr") => [ { mntpoint => "/", size => MB(250), fs_type => defaultFS(), ratio => 1, maxsize => MB(8000) }, { mntpoint => "swap", size => MB(64), fs_type => 'swap', ratio => 1, maxsize => MB(4000) }, { mntpoint => "/usr", size => MB(300), fs_type => defaultFS(), ratio => 4, maxsize => MB(8000) }, { mntpoint => "/home", size => MB(100), fs_type => defaultFS(), ratio => 3, min_hd_size => MB(7000) }, ], N_("server") => [ { mntpoint => "/", size => MB(150), fs_type => defaultFS(), ratio => 1, maxsize => MB(8000) }, { mntpoint => "swap", size => MB(64), fs_type => 'swap', ratio => 2, maxsize => MB(4000) }, { mntpoint => "/usr", size => MB(300), fs_type => defaultFS(), ratio => 4, maxsize => MB(8000) }, { mntpoint => "/var", size => MB(200), fs_type => defaultFS(), ratio => 3 }, { mntpoint => "/home", size => MB(150), fs_type => defaultFS(), ratio => 3, min_hd_size => MB(7000) }, { mntpoint => "/tmp", size => MB(150), fs_type => defaultFS(), ratio => 2, maxsize => MB(4000) }, ], ); foreach (values %suggestions) { if (arch() =~ /ia64/) { @$_ = ({ mntpoint => "/boot/efi", size => MB(50), pt_type => 0xef, ratio => 1, maxsize => MB(150) }, @$_); } } my @suggestions_mntpoints = ( "/var/ftp", "/var/www", "/boot", '/usr/local', '/opt', arch() =~ /sparc/ ? "/mnt/sunos" : arch() =~ /ppc/ ? "/mnt/macos" : "/mnt/windows", ); #-###################################################################################### #- Functions #-###################################################################################### sub recompute_loopbacks { my ($all_hds) = @_; my @fstab = fs::get::fstab($all_hds); @{$all_hds->{loopbacks}} = map { isPartOfLoopback($_) ? @{$_->{loopback}} : () } @fstab; } sub raids { my ($hds) = @_; my @parts = fs::get::hds_fstab(@$hds); my @l = grep { isRawRAID($_) } @parts or return []; log::l("looking for raids in " . join(' ', map { $_->{device} } @l)); require raid; raid::detect_during_install(@l) if $::isInstall; raid::get_existing(@l); } sub dmcrypts { my ($all_hds) = @_; my @parts = fs::get::fstab($all_hds); my @l = grep { fs::type::isRawLUKS($_) } @parts or return; log::l("using dm-crypt from " . join(' ', map { $_->{device} } @l)); require fs::dmcrypt; fs::dmcrypt::read_crypttab($all_hds); fs::dmcrypt::get_existing(@l); } sub lvms { my ($all_hds) = @_; my @pvs = grep { isRawLVM($_) } fs::get::fstab($all_hds) or return; scan_pvs(@pvs); } sub scan_pvs { my (@pvs) = @_; log::l("looking for vgs in " . join(' ', map { $_->{device} } @pvs)); #- otherwise vgscan will not find them devices::make($_->{device}) foreach @pvs; require lvm; my @lvms; foreach (@pvs) { my $name = lvm::pv_to_vg($_) or next; my $lvm = find { $_->{VG_name} eq $name } @lvms; if (!$lvm) { $lvm = new lvm($name); lvm::update_size($lvm); lvm::get_lvs($lvm); push @lvms, $lvm; } $_->{lvm} = $name; push @{$lvm->{disks}}, $_; } @lvms; } sub handle_dmraid { my ($drives, $o_in) = @_; @$drives > 1 or return; devices::make($_->{device}) foreach @$drives; require fs::dmraid; eval { fs::dmraid::init() } or log::l("dmraid::init failed"), return; my @vgs = fs::dmraid::vgs(); log::l(sprintf('dmraid: ' . join(' ', map { "$_->{device} [" . join(' ', @{$_->{disks}}) . "]" } @vgs))); if ($o_in && @vgs && $::isInstall) { @vgs = grep { $o_in->ask_yesorno('', N("BIOS software RAID detected on disks %s. Activate it?", join(' ', @{$_->{disks}})), 1); } @vgs or do { fs::dmraid::call_dmraid('-an'); return; }; } if (!$::isInstall) { fs::dmraid::migrate_device_names($_) foreach @vgs; } log::l("using dmraid on " . join(' ', map { $_->{device} } @vgs)); my @used_hds = map { my $part = fs::get::device2part($_, $drives) or log::l("handle_dmraid: can't find $_ in known drives"); if_($part, $part); } map { @{$_->{disks}} } @vgs; @$drives = difference2($drives, \@used_hds); push @$drives, @vgs; } sub get_hds { my ($o_flags, $o_in) = @_; my $flags = $o_flags || {}; $flags->{readonly} && ($flags->{clearall} || $flags->{clear}) and die "conflicting flags readonly and clear/clearall"; my @drives = detect_devices::hds(); #- replace drives used in dmraid by the merged name handle_dmraid(\@drives, $o_in) if !$flags->{nodmraid}; foreach my $hd (@drives) { $hd->{file} = devices::make($hd->{device}); } @drives = partition_table::raw::get_geometries(@drives); my (@hds, @raw_hds); foreach my $hd (@drives) { $hd->{readonly} = $flags->{readonly}; eval { partition_table::raw::test_for_bad_drives($hd) if !$flags->{no_bad_drives} }; if (my $err = $@) { log::l("test_for_bad_drives returned $err"); if ($err =~ /write error:/) { log::l("setting $hd->{device} readonly"); $hd->{readonly} = 1; } elsif ($err =~ /read error:/) { next; } else { $o_in and $o_in->ask_warn('', $err); next; } } if ($flags->{clearall} || member($hd->{device}, @{$flags->{clear} || []})) { my $lvms = []; #- temporary one, will be re-created later in get_hds() partition_table_initialize($lvms, $hd, $o_in); } else { my $handle_die_and_cdie = sub { if (my $type = fs::type::type_subpart_from_magic($hd)) { #- non partitioned drive? if (exists $hd->{usb_description} && $type->{fs_type}) { #- USB keys put_in_hash($hd, $type); push @raw_hds, $hd; $hd = ''; 1; } else { 0; } } elsif ($hd->{readonly}) { log::l("using /proc/partitions since diskdrake failed :("); fs::proc_partitions::use_($hd); 1; } else { 0; } }; my $handled; eval { catch_cdie { partition_table::read($hd); if (listlength(partition_table::get_normal_parts($hd)) == 0) { $handled = 1 if $handle_die_and_cdie->(); } elsif ($::isInstall) { if (fs::type::is_dmraid($hd)) { if (my $p = find { ! -e "/dev/$_->{device}" } partition_table::get_normal_parts($hd)) { #- dmraid should have created the device, so it means we don't agree die sprintf(q(bad dmraid (missing partition %s), you may try rebooting install with option "nodmraid"), $p->{device}); } } else { fs::proc_partitions::compare($hd) if !detect_devices::is_xbox() && arch() ne 'ppc'; } } } sub { my $err = $@; if ($handle_die_and_cdie->()) { $handled = 1; 0; #- do not continue, transform cdie into die } else { !$o_in || $o_in->ask_okcancel('', formatError($err)); } }; }; if (my $err = $@) { if ($handled) { #- already handled in cdie handler above } elsif ($handle_die_and_cdie->()) { } elsif ($o_in && $o_in->ask_yesorno(N("Error"), N("I cannot read the partition table of device %s, it's too corrupted for me :( I can try to go on, erasing over bad partitions (ALL DATA will be lost!). The other solution is to not allow DrakX to modify the partition table. (the error is %s) Do you agree to lose all the partitions? ", $hd->{device}, formatError($err)))) { partition_table::raw::zero_MBR($hd); } else { #- using it readonly log::l("using /proc/partitions since diskdrake failed :("); fs::proc_partitions::use_($hd); } } $hd or next; member($_->{device}, @{$flags->{clear} || []}) and partition_table::remove($hd, $_) foreach partition_table::get_normal_parts($hd); } my @parts = partition_table::get_normal_parts($hd); # checking the magic of the filesystem, do not rely on pt_type foreach (@parts) { if (my $type = fs::type::type_subpart_from_magic($_)) { $type->{pt_type} = $_->{pt_type}; #- keep {pt_type} put_in_hash($_, $type); } else { $_->{bad_fs_type_magic} = 1; } } if ($hd->{usb_media_type}) { $hd->{is_removable} = 1; $_->{is_removable} = 1 foreach @parts; } push @hds, $hd; } #- detect raids before LVM allowing LVM on raid my $raids = raids(\@hds); my $all_hds = { %{ fs::get::empty_all_hds() }, hds => \@hds, raw_hds => \@raw_hds, lvms => [], raids => $raids }; $all_hds->{lvms} = [ lvms($all_hds) ]; fs::get_major_minor([ fs::get::fstab($all_hds) ]); # must be done after getting major/minor $all_hds->{dmcrypts} = [ dmcrypts($all_hds) ]; # allow lvm on dmcrypt $all_hds->{lvms} = [ lvms($all_hds) ]; $_->{faked_device} = 0 foreach fs::get::fstab($all_hds); $all_hds; } #- are_same_partitions() do not look at the device name since things may have changed sub are_same_partitions { my ($part1, $part2) = @_; foreach ('start', 'size', 'pt_type', 'fs_type', 'rootDevice') { $part1->{$_} eq $part2->{$_} or return 0; } 1; } sub is_one_big_fat_or_NT { my ($hds) = @_; @$hds == 1 or return 0; my @l = fs::get::hds_fstab(@$hds); @l == 1 && isFat_or_NTFS($l[0]) && fs::get::hds_free_space(@$hds) < MB(10); } sub computeSize { my ($part, $best, $all_hds, $suggestions) = @_; my $max = $part->{maxsize} || $part->{size}; return min($max, $best->{size}) unless $best->{ratio}; my %free_space; $free_space{$_->{rootDevice}} += $_->{size} foreach fs::get::holes($all_hds); my @l = my @L = grep { my @possible = $_->{hd} ? $_->{hd} : keys %free_space; my $size = $_->{size}; if (my $dev = find { $free_space{$_} >= $size } @possible) { $free_space{$dev} -= $size; 1; } else { 0 } } @$suggestions; my $free_space = $best->{hd} && $free_space{$best->{hd}} || sum(values %free_space); my $cylinder_size_maxsize_adjusted; my $tot_ratios = 0; while (1) { my $old_free_space = $free_space; my $old_tot_ratios = $tot_ratios; $tot_ratios = sum(map { $_->{ratio} } @l); last if $tot_ratios == $old_tot_ratios; @l = grep { if ($_->{ratio} && $_->{maxsize} && $tot_ratios && $_->{size} + $_->{ratio} / $tot_ratios * $old_free_space >= $_->{maxsize}) { return min($max, $best->{maxsize}) if $best->{mntpoint} eq $_->{mntpoint}; $free_space -= $_->{maxsize} - $_->{size}; if (!$cylinder_size_maxsize_adjusted++) { eval { $free_space += fs::get::part2hd($part, $all_hds)->cylinder_size - 1 }; } 0; } else { $_->{ratio}; } } @l; } my $size = int min($max, $best->{size} + $free_space * ($tot_ratios && $best->{ratio} / $tot_ratios)); #- verify other entry can fill the hole (any { $_->{size} <= $max - $size } @L) ? $size : $max; } sub suggest_part { my ($part, $all_hds, $o_suggestions) = @_; my $suggestions = $o_suggestions || $suggestions{server} || $suggestions{simple}; #- suggestions now use {fs_type}, but still keep compatibility foreach (@$suggestions) { fs::type::set_pt_type($_, $_->{pt_type}) if !exists $_->{fs_type}; } my $hd = fs::get::part2hd($part, $all_hds); my $hd_size = $hd && $hd->{totalsectors}; # nb: no $hd if $part is /dev/mdX my $has_swap = any { isSwap($_) } fs::get::fstab($all_hds); my @local_suggestions = grep { !$_->{mntpoint} && !$_->{VG_name} || !fs::get::has_mntpoint($_->{mntpoint}, $all_hds) || isSwap($_) && !$has_swap } grep { !$_->{min_hd_size} || !$hd_size || $_->{min_hd_size} <= $hd_size } grep { !$_->{hd} || $_->{hd} eq $part->{rootDevice} } @$suggestions; #- this allows specifying the size using a relative size. #- one should rather use {ratio} instead foreach (@local_suggestions) { if ($_->{percent_size} && $_->{percent_size} =~ /(.+?)%?$/) { $_->{size} = $1 / 100 * $hd_size; log::l("in suggestion, setting size=$_->{size} for percent_size=$_->{percent_size}"); } } my ($best) = grep { !$_->{maxsize} || $part->{size} <= $_->{maxsize} } grep { $_->{size} <= ($part->{maxsize} || $part->{size}) } grep { !$part->{fs_type} || $part->{fs_type} eq $_->{fs_type} || isTrueFS($part) && isTrueFS($_) } @local_suggestions; defined $best or return 0; #- sorry no suggestion :( $part->{mntpoint} = $best->{mntpoint}; fs::type::set_type_subpart($part, $best) if !isTrueFS($best) || !isTrueFS($part); $part->{size} = computeSize($part, $best, $all_hds, \@local_suggestions); foreach ('options', 'lv_name', 'encrypt_key', 'primaryOrExtended', 'device_LABEL', 'prefer_device_LABEL', 'device_UUID', 'prefer_device_UUID', 'prefer_device') { $part->{$_} = $best->{$_} if $best->{$_}; } $best; } sub suggestions_mntpoint { my ($all_hds) = @_; sort grep { !/swap/ && !fs::get::has_mntpoint($_, $all_hds) } (@suggestions_mntpoints, map { $_->{mntpoint} } @{$suggestions{server} || $suggestions{simple}}); } #- you can do this before modifying $part->{mntpoint} #- so $part->{mntpoint} should not be used here, use $mntpoint instead sub check_mntpoint { my ($mntpoint, $part, $all_hds) = @_; $mntpoint eq '' || isSwap($part) || isNonMountable($part) and return 0; $mntpoint =~ m|^/| or die N("Mount points must begin with a leading /"); $mntpoint =~ m|[\x7f-\xff]| and cdie N("Mount points should contain only alphanumerical characters"); fs::get::mntpoint2part($mntpoint, [ grep { $_ ne $part } fs::get::really_all_fstab($all_hds) ]) and die N("There is already a partition with mount point %s\n", $mntpoint); if ($mntpoint eq "/" && isRAID($part) && !fs::get::has_mntpoint("/boot", $all_hds)) { # lilo handles / on RAID1 if ($part->{level} ne '1') { cdie N("You've selected a software RAID partition as root (/). No bootloader is able to handle this without a /boot partition. Please be sure to add a separate /boot partition"); } else { # LILO only handles 0.90 metadata if ($part->{isFormatted} && $part->{metadata} && $part->{metadata} ne '0.90') { cdie N("Metadata version unsupported for a boot partition. Please be sure to add a separate /boot partition."); } else { $part->{metadata} = '0.90'; } } } if ($mntpoint eq "/boot" && isRAID($part)) { die N("You've selected a software RAID partition as /boot. No bootloader is able to handle this.") if $part->{level} ne '1'; # lilo handles /boot on RAID1 # LILO only handles 0.90 metadata if ($part->{isFormatted} && $part->{metadata} && $part->{metadata} ne '0.90') { die N("Metadata version unsupported for a boot partition."); } else { $part->{metadata} = '0.90'; } } if ($mntpoint eq "/" && (isLUKS($part) || isRawLUKS($part)) && !fs::get::has_mntpoint("/boot", $all_hds)) { cdie N("You've selected an encrypted partition as root (/). No bootloader is able to handle this without a /boot partition. Please be sure to add a separate /boot partition"); } if ($mntpoint eq "/boot" && (isLUKS($part) || isRawLUKS($part))) { die N("You cannot use an encrypted filesystem for mount point %s", "/boot"); } #- NB: if the LV doesn't exist, lv_nb_pvs returns 0 die N("You cannot use the LVM Logical Volume for mount point %s since it spans physical volumes", $mntpoint) if $mntpoint eq '/boot' && isLVM($part) && lvm::lv_nb_pvs($part) > 1; cdie N("You've selected the LVM Logical Volume as root (/). The bootloader is not able to handle this when the volume spans physical volumes. You should create a separate /boot partition first") if $mntpoint eq "/" && isLVM($part) && lvm::lv_nb_pvs($part) != 1 && !fs::get::has_mntpoint("/boot", $all_hds); cdie N("This directory should remain within the root filesystem") if member($mntpoint, qw(/root)); die N("This directory should remain within the root filesystem") if member($mntpoint, qw(/bin /dev /etc /lib /sbin /mnt /media)); die N("You need a true filesystem (ext2/3/4, reiserfs, xfs, or jfs) for this mount point\n") if !isTrueLocalFS($part) && $mntpoint eq '/'; die N("You need a true filesystem (ext2/3/4, reiserfs, xfs, or jfs) for this mount point\n") if !isTrueFS($part) && member($mntpoint, '/home', fs::type::directories_needed_to_boot()); die N("You cannot use an encrypted filesystem for mount point %s", $mntpoint) if $part->{options} =~ /encrypted/ && member($mntpoint, qw(/ /usr /var /boot)); local $part->{mntpoint} = $mntpoint; fs::loopback::check_circular_mounts($part, $all_hds); } sub add { my ($hd, $part, $all_hds, $options) = @_; isSwap($part) ? ($part->{mntpoint} = 'swap') : $options->{force} || check_mntpoint($part->{mntpoint}, $part, $all_hds); delete $part->{maxsize}; if (isLVM($hd)) { lvm::lv_create($hd, $part); } else { partition_table::add($hd, $part, $options->{primaryOrExtended}); } fs::get_major_minor([ $part ]); } sub allocatePartitions { my ($all_hds, $to_add) = @_; my @to_add = @$to_add; foreach my $part_ (fs::get::holes($all_hds, 'non_readonly')) { my ($start, $size, $dev) = @$part_{"start", "size", "rootDevice"}; my ($part, $suggested); while ($suggested = suggest_part($part = { start => $start, size => 0, maxsize => $size, rootDevice => $dev }, $all_hds, \@to_add)) { my $hd = fs::get::part2hd($part, $all_hds); add($hd, $part, $all_hds, { primaryOrExtended => $part->{primaryOrExtended} }); $size -= $part->{size} + $part->{start} - $start; $start = $part->{start} + $part->{size}; @to_add = grep { $_ != $suggested } @to_add; } } } sub auto_allocate { my ($all_hds, $o_suggestions) = @_; my $before = listlength(fs::get::fstab($all_hds)); my $suggestions = $o_suggestions || $suggestions{simple}; allocatePartitions($all_hds, $suggestions); if ($o_suggestions) { auto_allocate_raids($all_hds, $suggestions); if (auto_allocate_vgs($all_hds, $suggestions)) { #- allocatePartitions needs to be called twice, once for allocating PVs, once for allocating LVs my @vgs = map { $_->{VG_name} } @{$all_hds->{lvms}}; my @suggested_lvs = grep { member($_->{hd}, @vgs) } @$suggestions; allocatePartitions($all_hds, \@suggested_lvs); } } partition_table::assign_device_numbers($_) foreach @{$all_hds->{hds}}; if ($before == listlength(fs::get::fstab($all_hds))) { # find out why auto_allocate failed if (any { !fs::get::has_mntpoint($_->{mntpoint}, $all_hds) } @$suggestions) { die N("Not enough free space for auto-allocating"); } else { die N("Nothing to do"); } } } sub auto_allocate_raids { my ($all_hds, $suggestions) = @_; my @raids = grep { isRawRAID($_) } fs::get::fstab($all_hds) or return; require raid; my @mds = grep { $_->{hd} =~ /md/ } @$suggestions; foreach my $md (@mds) { my @raids_ = grep { !$md->{parts} || $md->{parts} =~ /\Q$_->{mntpoint}/ } @raids; @raids = difference2(\@raids, \@raids_); my %h = %$md; delete @h{'hd', 'parts'}; # keeping mntpoint, level, chunk-size, fs_type/pt_type $h{disks} = \@raids_; my $part = raid::new($all_hds->{raids}, %h); raid::updateSize($part); push @raids, $part; #- we can build raid over raid } } sub auto_allocate_vgs { my ($all_hds, $suggestions) = @_; my @pvs = grep { isRawLVM($_) } fs::get::fstab($all_hds) or return 0; my @vgs = grep { $_->{VG_name} } @$suggestions or return 0; partition_table::write($_) foreach @{$all_hds->{hds}}; require lvm; foreach my $vg (@vgs) { my $lvm = new lvm($vg->{VG_name}); push @{$all_hds->{lvms}}, $lvm; my @pvs_ = grep { !$vg->{parts} || $vg->{parts} =~ /\Q$_->{mntpoint}/ } @pvs; @pvs = difference2(\@pvs, \@pvs_); foreach my $part (@pvs_) { raid::make($all_hds->{raids}, $part) if isRAID($part); $part->{lvm} = $lvm->{VG_name}; delete $part->{mntpoint}; lvm::vg_add($part); push @{$lvm->{disks}}, $part; } lvm::update_size($lvm); } 1; } sub change_type { my ($type, $hd, $part) = @_; $type->{pt_type} != $part->{pt_type} || $type->{fs_type} ne $part->{fs_type} or return; fs::type::check($type->{fs_type}, $hd, $part); delete $part->{device_UUID}; $hd->{isDirty} = 1; $part->{mntpoint} = '' if isSwap($part) && $part->{mntpoint} eq "swap"; $part->{mntpoint} = '' if fs::type::cannotBeMountable($part); set_isFormatted($part, 0); fs::type::set_type_subpart($part, $type); fs::mount_options::rationalize($part); 1; } sub partition_table_clear_and_initialize { my ($lvms, $hd, $o_in, $o_type, $b_warn) = @_; $hd->clear_existing; partition_table_initialize($lvms, $hd, $o_in, $o_type, $b_warn); } sub partition_table_initialize { my ($lvms, $hd, $o_in, $o_type, $b_warn) = @_; partition_table::initialize($hd, $o_type); if ($hd->isa('partition_table::lvm')) { if ($b_warn && $o_in) { $o_in->ask_okcancel_('', N("ALL existing partitions and their data will be lost on drive %s", partition_table::description($hd))) or return; } require lvm; lvm::check($o_in ? $o_in->do_pkgs : do_pkgs_standalone->new) if $::isStandalone; lvm::create_singleton_vg($lvms, fs::get::hds_fstab($hd)); } } 1;