blob: 13d0de22266fb881829aa90d8e7c6b8190fd28fc (
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
|
PACKAGE=drakxtools
PKGVERSION:=$(shell rpm -q --qf '%{VERSION}\n' --specfile $(PACKAGE).spec|head -1)
RELEASE:=$(shell rpm -q --qf '%{RELEASE}\n' --specfile $(PACKAGE).spec|head -1)
TAG := $(shell echo "V$(PKGVERSION)_$(RELEASE)" | tr -- '-.' '__')
include Makefile.config
POFILES = $(shell ls share/po/*.po)
MOFILES = $(POFILES:%.po=%.mo)
DISTFILES = *.pm $(PMS_DIRS) Makefile Makefile.config apps.net_monitor ddcprobe drakxtools.spec pam.net_monitor serial_probe share/po share/diskdrake.rc $(STANDALONEPMS) standalone/icons pixmaps pixmaps/langs standalone/interactive_http rpcinfo-flushed.c standalone/service_harddrake.sh
OTHERS = $(OTHERDIRS) $(OTHERFILES)
OTHERDIRS = tools/ddcprobe tools/serial_probe
OTHERFILES = tools/rpcinfo-flushed.c
.PHONY: all $(DIRS) install clean stage2 full_stage2
all: list_modules.pm TAGS $(DIRS)
list_modules.pm:
ln -sf ../kernel/list_modules.pm
TAGS: $(ALLPMS)
@etags -o - $^ /usr/lib/perl5/*/*/MDK/Common/*.pm | ./perl2etags > $@
clean:
for i in $(DIRS) share/po; do $(MAKE) -C $$i clean; done;:
rm -rf auto ../drakxtools.tar.bz2 *.bak
find . -name "*~" -o -name ".#*" -o -name "TAGS" -o -name "*.old" | xargs rm -f
check:
$(MAKE) -C share/po check
perl -I. -Mlang -e 'lang::check'
perl -I. -Mkeyboard -e 'keyboard::check'
localcopy: clean
rm -rf standalone/pixmaps
$(MAKE) -C ../tools clean || :
cd .. ; rm -rf $(PACKAGE)-$(PKGVERSION) ; cp -af perl-install $(PACKAGE)-$(PKGVERSION) ; cp -af $(OTHERS) $(PACKAGE)-$(PKGVERSION)
cd
@make nuke_perl
$(DIRS):
install -d auto
$(MAKE) -C $@
test_pms:
perl_checker install2.pm install_steps_gtk.pm install_steps_stdio.pm partition_table/*.pm standalone/{harddrake2,diskdrake,draksec}
test_pms_all:
perl_checker --check-unused $(wildcard $(ALLPMS))
%.mo: %.po
msgfmt -o $@ $<
install_pms: $(DIRS)
for i in `perl -ne 's/sub (\w+?)_? {.*/$$1/ and print' commands.pm` sync; do ln -sf commands $(DEST)/usr/bin/$$i; done
install -d $(DESTREP4PMS)
find $(DESTREP4PMS) -name "*.pm.gz" | xargs rm -f
for i in $(PMS); do \
dest=$(DESTREP4PMS)/`dirname $$i`; \
install -d $$dest; \
perl -ne 'print' $$i > $(DESTREP4PMS)/$$i; \
perl -pe 's/#[-+].*//; $$_ = "\n" if (/^=(head|begin)/ .. /^=cut/) || /use (diagnostics|vars|strict)/' $$i > $(DESTREP4PMS)/$$i; \
done
if [ "x$(PERL_INSTALL_DEBUG)" == "x" ]; then \
perl -pi -e 's|#!/usr/bin/perl -d.*\n|#!/usr/bin/perl\n|' $(DESTREP4PMS)/install2; \
else \
perl -pe 's|#!/usr/bin/perl.*\n|#!/usr/bin/perl -d \n|' install2 > $(DESTREP4PMS)/install2; \
fi \
rm -f $(DESTREP4PMS)/{bootlook,tinyfirewall}.pm
cp share/*.rc $(DESTREP4PMS)
chmod a+x $(DESTREP4PMS)/install2
chmod a+x $(DESTREP4PMS)/commands
chmod a+x $(DESTREP4PMS)/g_auto_install
chmod a+x $(DESTREP4PMS)/live_install*
get_needed_files: $(DIRS) $(MOFILES)
$(MAKE) -C share
# export PERL_INSTALL_TEST=1 ; strace -f -e trace=file -o '| grep -v "(No such file or directory)" | sed -e "s/[^\"]*\"//" -e "s/\".*//" | grep "^/" | grep -v -e "^/tmp" -e "^/home" -e "^/proc" -e "^/var" -e "^/dev" -e "^/etc" -e "^/usr/lib/rpm" > /tmp/list ' $(PERL) -d install2 < /dev/null
eval `perl -V:version`; \
cat share/list `../tools/specific_arch share/list` | \
perl -pe "s/ARCH/$(ARCH)/g ; s/PERL_VERSION/$$version/g ; s|/LIB/|/$(LIB)/|g " | \
perl -lpe '@l = glob; !m|\*.*/| || @l == 1 and $$_ = join("\n", @l)' > /tmp/list
rpm -ql perl-GTK2 | grep '^/usr/lib/perl5' >> /tmp/list
@missing=`perl -lne 'print if !-e $$_' /tmp/list`; [ -z "$$missing" ] || { echo "missing or multiple files vvvvvvvvvvvvvvvvvvvvvvvvvv" ; echo "$$missing" ; echo "missing or multiple files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" ; exit 1; }
find auto -follow -name "*.so" >> /tmp/list
for i in $(LOCALFILES) `cat /tmp/list` ; do \
ldd $$i 2>/dev/null | grep "=>" | perl -pe 's/.*=> //; s/ .*//; s,^/lib/.*?/,/lib/,' | sort | uniq >> /tmp/list; \
done
perl -Mlang -I. -e 'print "$$_\n" foreach lang::console_font_files()' >> /tmp/list
install -d $(DEST)/etc
install -d $(DEST)/etc/sysconfig/network-scripts
install -d $(DEST)/lib
install -d $(DEST)/$(LIB)
install -d $(DEST)/bin
install -d $(DEST)/usr/bin
install -d $(DEST)/usr/lib
install -d $(DEST)/usr/$(LIB)
install -d $(DEST)/usr/share
install -d $(DEST)/usr/share/gtk
install -d $(DEST)/usr/share/xmodmap
install -d $(DEST)/usr/X11R6/lib/X11
install -d $(ROOTDEST)/Mandrake/base
install -s $(LOCALFILES) $(DEST)/usr/bin
# cp -f $(LOCALFILES2) $(DEST)/usr/bin
ln -s ../X11R6/lib/X11 $(DEST)/usr/lib/X11
ifeq (sparc,$(ARCH))
cp -a /usr/X11R6/lib/X11/xkb $(DEST)/usr/X11R6/lib/X11
rm -f $(DEST)/usr/X11R6/lib/X11/xkb/compiled
ln -s /tmp $(DEST)/usr/X11R6/lib/X11/xkb/compiled
ln -s /usr/X11R6/lib/X11/xkb/xkbcomp $(DEST)/usr/bin/xkbcomp
endif
ifeq (i386,$(ARCH))
install -s /sbin/cardmgr $(DEST)/usr/bin
endif
for i in `cat /tmp/list`; do \
if (echo $$i | grep -q "lib/[^/]*\.so"); then \
install -s $$i $(DEST)/lib; \
elif (echo $$i | grep -q "lib64/[^/]*\.so"); then \
install -s $$i $(DEST)/lib64; \
else \
d=$$i; \
(echo $$d | grep -q "^[^/]") && d="$(REP4PMS)/$$d"; \
d=`echo $(DEST)/$$d | sed 's/\/usr\/local\//\/usr\//'`; \
install -d `dirname $$d` && \
if (echo $$i | grep -q "\.pm"); then \
perl -pe '$$_ =~ /^__END__/ and exit(0);' $$i > $$d; \
elif (echo $$i | grep -q "\.so"); then \
install -s $$i $$d; \
else \
cp -f $$i $$d; \
fi; \
fi; \
done
perl -pi -e 's/\s*use\s+(warnings|diagnostics|vars|strict).*//g' $(DEST)/usr/*/*/*/utf8_heavy.pl
mv -f $(DEST)/bin/* $(DEST)/sbin/* $(DEST)/usr/bin
cd $(DEST)/usr/bin ; mv insmod insmod_
rmdir $(DEST)/bin $(DEST)/sbin
perl -ane 'symlink "$$F[1]", "$(DEST)/usr/bin/$$F[0]"' share/aliases
ifeq (i386,$(ARCH))
cp ../tools/i386/busybox $(DEST)/usr/bin
endif
ln -sf ash $(DEST)/usr/bin/sh
for i in fonts keyboards locales keymaps; do tar xfj `../tools/specific_arch share/$$i.tar.bz2` -C $(DEST); done
grep ChangeLog CVS/Entries > $(DEST)/usr/share/VERSION
gzip -9f $(DEST)/usr/share/ldetect-lst/*
cd share ; cp -a consolefonts $(DEST)/usr/share
-cd share ; cp -f *.png $(DEST)/usr/share
-cd pixmaps ; cp -af *.png *.xpm langs $(DEST)/usr/share ; rm -f $(DEST)/usr/share/wiz_*
cd share ; cp compssUsers compssUsers.* rpmsrate $(ROOTDEST)/Mandrake/base
clean-rpmsrate $(ROOTDEST)/Mandrake/base/rpmsrate $(ROOTDEST)/Mandrake/RPMS*
for i in ../kernel/modules.description ../kernel/all.modules/modules.cz*; do cp -f $$i $(DEST)/lib/; done
$(MAKE) -C share/po install NAME=libDrakX LOCALEDIR=$(DEST)/usr/share/locale_special
# echo -e '#!/bin/sh\n\nexec "/usr/bin/sh"' > $(DEST)/usr/bin/runinstall2
# chmod a+x $(DEST)/usr/bin/runinstall2
ifeq (i386,$(ARCH))
cp -a /etc/pcmcia $(DEST)/etc
../tools/patch_pcmcia_config.pl $(DEST)/etc/pcmcia/config ../kernel/all.modules/`cat ../kernel/all.kernels/.main`/modules.dep
endif
find $(DEST) -name CVS | xargs rm -rf
full_stage2:
if [ `id -u` = 0 ]; then rm -rf $(DEST); else $(SUDO) rm -rf $(DEST); fi
mkdir -p $(DEST)
$(MAKE) get_needed_files
$(MAKE) stage2
stage2:
$(MAKE) install_pms
find $(DEST)/usr -name "*.pm" | xargs gzip -9f
cd $(DEST)/usr/lib/perl5 ; gunzip 5.*/{PerlIO,Exporter}.pm.gz 5.*/*-linux-thread-multi/{XSLoader,lib}.pm.gz vendor_perl/*/*-linux-thread-multi/PerlIO/gzip.pm.gz
$(ROOTDEST)/misc/make_mdkinst_stage2 $(DEST) $(ROOTDEST)/Mandrake/base/mdkinst_stage2
# rules to build a test rpm
localrpm: localdist buildrpm
localsrpm: spec_test localdist buildsrpm
srpm: spec_test cvstag localsrpm
localdist: cleandist localcopy tar
cleandist:
rm -rf ../$(PACKAGE)-$(PKGVERSION) ../$(PACKAGE)-$(PKGVERSION).tar.bz2
spec_test:
@if [[ -z "$(PKGVERSION)" ]]; then echo "unable to get spec version"; exit 3;fi
@if [[ -z "$(RELEASE)" ]]; then echo "unable to get spec release"; exit 2;fi
tar:
cd ../$(PACKAGE)-$(PKGVERSION) && perl -pi -e 's/^C_RPM.*/C_RPM=0/; s/^C_DRAKX.*/C_DRAKX=0/' c/Makefile
cd ../$(PACKAGE)-$(PKGVERSION) && perl -pi -e 's/^all: help/all:/' share/po/Makefile
cd ../$(PACKAGE)-$(PKGVERSION) && rm -rf install* pkgs.pm help.pm ftp.pm http.pm crypto.pm ugtk2.pm t.pm debug.log `find -name CVS`
cd ../$(PACKAGE)-$(PKGVERSION) && mv -f Makefile.drakxtools Makefile
cd ../$(PACKAGE)-$(PKGVERSION) && rm -f list_modules.pm && cp -f ../kernel/list_modules.pm .
cd ..; tar cfj $(PACKAGE)-$(PKGVERSION).tar.bz2 $(patsubst %,$(PACKAGE)-$(PKGVERSION)/%,$(DISTFILES))
cd ..; rm -rf $(PACKAGE)-$(PKGVERSION)
buildrpm:
rpm -ta ../$(PACKAGE)-$(PKGVERSION).tar.bz2
buildsrpm:
rpm -ts --nodeps ../$(PACKAGE)-$(PKGVERSION).tar.bz2
# rules to build a distributable rpm
rpm: cvstag dist buildrpm
slowsrpm: spec_test cvstag dist buildsrpm
dist: cleandist export tar
export:
cd ..; cvs export -d $(PACKAGE)-$(PKGVERSION) -r $(TAG) $(PACKAGE)
cd ../$(PACKAGE)-$(PKGVERSION) && rm -rf $(OTHERDIRS) && set -x && for f in $(OTHERDIRS); do cvs -d `cat ../CVS/Root` export -r $(TAG) -d `basename $$f` gi/$$f; done
cd ..; set -x && for f in $(OTHERFILES); do cvs -d `cat ../CVS/Root` export -r $(TAG) -d $(PACKAGE)-$(PKGVERSION) gi/$$f; done
@make nuke_perl
cvstag:
cvs tag $(CVSTAGOPT) $(TAG)
cd ..; cvs tag $(CVSTAGOPT) $(TAG) $(OTHERS)
nuke_perl:
find ../$(PACKAGE)-$(PKGVERSION) -name '*.pm' | xargs perl -pi -e 's/\s*use\s+(diagnostics|vars|strict).*//g'
find ../$(PACKAGE)-$(PKGVERSION)/standalone -type f | xargs perl -pi -e 's/\s*use\s+(diagnostics|vars|strict).*//g'
|
'n1316' href='#n1316'>1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
package diskdrake::interactive; # $Id$
use diagnostics;
use strict;
use utf8;
use common;
use fs::type;
use fs::loopback;
use fs::format;
use fs::mount_options;
use fs;
use partition_table;
use partition_table::raw;
use detect_devices;
use run_program;
use devices;
use fsedit;
use raid;
use any;
use log;
=begin
=head1 SYNOPSYS
struct part {
int active # one of { 0 | 0x80 } x86 only, primary only
int start # in sectors
int size # in sectors
int pt_type # 0x82, 0x83, 0x6 ...
string fs_type # 'ext2', 'nfs', ...
string type_name # 'Linux RAID', 'Linux Logical Volume Manager', ...
int part_number # 1 for hda1...
string device # 'hda5', 'sdc1' ...
string device_LABEL # volume label. LABEL=xxx or /dev/disk/by-label/xxx can be used in fstab instead of the device
string device_UUID # volume UUID. UUID=xxx or /dev/disk/by-uuid/xxx can be used in fstab instead of the device
bool prefer_device_LABEL # should the {device_LABEL} or the {device} be used in fstab
bool prefer_device_UUID # should the {device_UUID} or the {device} be used in fstab
bool prefer_device # should the {device} be used in fstab
bool faked_device # false if {device} is a real device, true for nfs/smb/dav/none devices. If the field does not exist, we do not know
bool device_LABEL_changed # true if device_LABEL is different from the one on the disk
string rootDevice # 'sda', 'hdc' ... (can also be a VG_name)
string real_mntpoint # directly on real /, '/tmp/hdimage' ...
string mntpoint # '/', '/usr' ...
string options # 'defaults', 'noauto'
string device_windobe # 'C', 'D' ...
string encrypt_key # [0-9A-Za-z./]{20,}
string comment # comment to have in fstab
string volume_label #
bool is_removable # is the partition on a removable drive
bool isMounted
bool isFormatted
bool notFormatted
# isFormatted means the device is formatted
# !isFormatted && notFormatted means the device is not formatted
# !isFormatted && !notFormatted means we do not know which state we're in
string raid # for partitions of type isRawRAID and which isPartOfRAID, the raid device
string lvm # partition used as a PV for the VG with {lvm} as VG_name #-#
loopback loopback[] # loopback living on this partition
string dmcrypt_key
string dm_name
bool dm_active
# internal
string real_device # '/dev/loop0', '/dev/loop1' ... (used for encrypted loopback)
# internal CHS (Cylinder/Head/Sector)
int start_cyl, start_head, start_sec, end_cyl, end_head, end_sec,
}
struct part_allocate inherits part {
int maxsize # in sectors (alike "size")
int min_hd_size # in sectors (do not allocate if the drive is smaller than the given size)
int ratio #
string hd # 'hda', 'hdc'
string parts # for creating raid partitions. eg: 'foo bar' where 'foo' and 'bar' are mntpoint
}
struct part_raid inherits part {
string chunk-size # in KiB, usually '64'
string level # one of { 0, 1, 4, 5, 'linear' }
string UUID
part disks[]
# invalid: active, start, rootDevice, device_windobe?, CHS
}
struct part_dmcrypt inherits part {
string dmcrypt_name
# rootDevice is special here: it is the device hosting the dm
}
struct part_loopback inherits part {
string loopback_file # absolute file name which is relative to the partition
part loopback_device # where the loopback file live
# device is special here: it is the absolute filename of the loopback file.
# invalid: active, start, rootDevice, device_windobe, CHS
}
struct part_lvm inherits part {
# invalid: active, start, device_windobe, CHS
string lv_name
}
struct partition_table_elem {
part normal[] #
part extended # the main/next extended
part raw[4] # primary partitions
}
struct geom {
int heads
int sectors
int cylinders
int totalcylinders # for SUN, forget it
int start # always 0, forget it
}
struct hd {
int totalsectors # size in sectors
string device # 'hda', 'sdc' ...
string device_alias # 'cdrom', 'floppy' ...
string media_type # one of { 'hd', 'cdrom', 'fd', 'tape' }
string capacity # contain of the strings of { 'burner', 'DVD' }
string info # name of the hd, eg: 'QUANTUM ATLAS IV 9 WLS'
bool readonly # is it allowed to modify the partition table
bool getting_rid_of_readonly_allowed # is it forbidden to write because the partition table is badly handled, or is it because we MUST not change the partition table
bool isDirty # does it need to be written to the disk
list will_tell_kernel # list of actions to tell to the kernel so that it knows the new partition table
bool rebootNeeded # happens when a kernel reread failed
list partitionsRenumbered # happens when you
# - remove an extended partition which is not the last one
# - add an extended partition which is the first extended partition
list allPartitionsRenumbered # used to update bootloader configuration
int bus, id
bool is_removable # is it a removable drive
partition_table_elem primary
partition_table_elem extended[]
geom geom
# internal
string prefix # for some RAID arrays device=>c0d0 and prefix=>c0d0p
string file # '/dev/hda' ...
}
struct hd_lvm inherits hd {
int PE_size # block size (granularity, similar to cylinder size on x86)
string VG_name # VG name
part_lvm disks[]
# invalid: bus, id, extended, geom
}
struct raw_hd inherits hd {
string fs_type # 'ext2', 'nfs', ...
string mntpoint # '/', '/usr' ...
string options # 'defaults', 'noauto'
# invalid: isDirty, will_tell_kernel, rebootNeeded, primary, extended
}
struct all_hds {
hd hds[]
hd_lvm lvms[]
part_raid raids[]
part_dmcrypt dmcrypts[]
part_loopback loopbacks[]
raw_hd raw_hds[]
raw_hd nfss[]
raw_hd smbs[]
raw_hd davs[]
raw_hd special[]
# internal: if fstab_to_string($all_hds) eq current_fstab then no need to save
string current_fstab
}
=cut
sub main {
my ($in, $all_hds, $do_force_reload) = @_;
if ($in->isa('interactive::gtk')) {
require diskdrake::hd_gtk;
goto &diskdrake::hd_gtk::main;
}
my ($current_part, $current_hd);
while (1) {
my $choose_txt = $current_part ? N_("Choose another partition") : N_("Choose a partition");
my $parts_and_holes = [ fs::get::fstab_and_holes($all_hds) ];
my $choose_part = sub {
$current_part = $in->ask_from_listf('diskdrake', translate($choose_txt),
sub {
my $hd = fs::get::part2hd($_[0] || return, $all_hds);
format_part_info_short($hd, $_[0]);
}, $parts_and_holes, $current_part) || return;
$current_hd = fs::get::part2hd($current_part, $all_hds);
};
$choose_part->() if !$current_part;
return if !$current_part;
my %actions = my @actions = (
if_($current_part,
(map { my $s = $_; $_ => sub { $diskdrake::interactive::{$s}($in, $current_hd, $current_part, $all_hds) } } part_possible_actions($in, $current_hd, $current_part, $all_hds)),
'____________________________' => sub {},
),
if_(@$parts_and_holes > 1, $choose_txt => $choose_part),
if_($current_hd,
(map { my $s = $_; $_ => sub { $diskdrake::interactive::{$s}($in, $current_hd, $all_hds) } } hd_possible_actions_interactive($in, $current_hd, $all_hds)),
),
(map { my $s = $_; $_ => sub { $diskdrake::interactive::{$s}($in, $all_hds) } } general_possible_actions($in, $all_hds)),
);
my ($actions) = list2kv(@actions);
my $a;
if ($current_part) {
$in->ask_from_({
cancel => N("Exit"),
title => 'diskdrake',
messages => format_part_info($current_hd, $current_part),
},
[ { val => \$a, list => $actions, format => \&translate, type => 'list', sort => 0, gtk => { use_boxradio => 0 } } ]) or last;
my $v = eval { $actions{$a}() };
if (my $err = $@) {
$in->ask_warn(N("Error"), formatError($err));
}
if ($v eq 'force_reload') {
$all_hds = $do_force_reload->();
}
$current_hd = $current_part = '' if !is_part_existing($current_part, $all_hds);
} else {
$choose_part->();
}
partition_table::assign_device_numbers($_) foreach fs::get::hds($all_hds);
}
return if eval { Done($in, $all_hds) };
if (my $err = $@) {
$in->ask_warn(N("Error"), formatError($err));
}
goto &main;
}
################################################################################
# general actions
################################################################################
sub general_possible_actions {
my ($_in, $_all_hds) = @_;
if_($::isInstall, N_("More"));
}
sub Done {
my ($in, $all_hds) = @_;
eval { raid::verify($all_hds->{raids}) };
if (my $err = $@) {
$::expert or die;
$in->ask_okcancel(N("Confirmation"), [ formatError($err), N("Continue anyway?") ]) or return;
}
foreach (@{$all_hds->{hds}}) {
if (!write_partitions($in, $_, 'skip_check_rebootNeeded')) {
return if !$::isStandalone;
$in->ask_yesorno(N("Quit without saving"), N("Quit without writing the partition table?"), 1) or return;
}
}
if (!$::isInstall) {
my $new = fs::fstab_to_string($all_hds);
if ($new ne $all_hds->{current_fstab} && $in->ask_yesorno(N("Confirmation"), N("Do you want to save /etc/fstab modifications"), 1)) {
$all_hds->{current_fstab} = $new;
fs::write_fstab($all_hds);
}
update_bootloader_for_renumbered_partitions($in, $all_hds);
if (any { $_->{rebootNeeded} } @{$all_hds->{hds}}) {
$in->ask_warn(N("Partitioning"), N("You need to reboot for the partition table modifications to take place"));
tell_wm_and_reboot();
}
}
if (my $part = find { $_->{mntpoint} && !maybeFormatted($_) } fs::get::fstab($all_hds)) {
$in->ask_okcancel(N("Warning"), N("You should format partition %s.
Otherwise no entry for mount point %s will be written in fstab.
Quit anyway?", $part->{device}, $part->{mntpoint})) or return if $::isStandalone;
}
1;
}
################################################################################
# per-hd actions
################################################################################
sub hd_possible_actions_base {
my ($hd) = @_;
(
if_(!$hd->{readonly} || $hd->{getting_rid_of_readonly_allowed}, N_("Clear all")),
if_(!$hd->{readonly} && $::isInstall, N_("Auto allocate")),
);
}
sub hd_possible_actions_extra {
my ($_hd) = @_;
$::expert ? N_("Toggle to normal mode") : N_("Toggle to expert mode");
}
sub hd_possible_actions {
my ($_in, $hd, $_all_hds) = @_;
hd_possible_actions_base($hd);
hd_possible_actions_extra($hd);
}
sub hd_possible_actions_interactive {
my ($_in, $_hd, $_all_hds) = @_;
&hd_possible_actions, N_("Hard drive information");
}
sub Clear_all {
my ($in, $hd, $all_hds) = @_;
return if detect_devices::is_xbox(); #- do not let them wipe the OS
my @parts = partition_table::get_normal_parts($hd);
foreach (@parts) {
RemoveFromLVM($in, $hd, $_, $all_hds) if isPartOfLVM($_);
RemoveFromRAID($in, $hd, $_, $all_hds) if isPartOfRAID($_);
RemoveFromDm($in, $hd, $_, $all_hds) if $_->{dm_active};
}
if (isLVM($hd)) {
lvm::lv_delete($hd, $_) foreach @parts;
} else {
$hd->{readonly} = 0; #- give a way out of readonly-ness. only allowed when getting_rid_of_readonly_allowed
$hd->{getting_rid_of_readonly_allowed} = 0; #- we don't need this flag anymore
fsedit::partition_table_clear_and_initialize($all_hds->{lvms}, $hd, $in);
}
}
sub Auto_allocate {
my ($in, $hd, $all_hds) = @_;
my $suggestions = partitions_suggestions($in) or return;
my %all_hds_ = %$all_hds;
$all_hds_{hds} = [ sort { $a == $hd ? -1 : 1 } fs::get::hds($all_hds) ];
eval { fsedit::auto_allocate(\%all_hds_, $suggestions) };
if ($@) {
$@ =~ /partition table already full/ or die;
$in->ask_warn("", [
N("All primary partitions are used"),
N("I can not add any more partitions"),
N("To have more partitions, please delete one to be able to create an extended partition"),
]);
}
}
sub More {
my ($in, $_hd) = @_;
my $r;
$in->ask_from(N("More"), '',
[
{ val => N("Reload partition table"), clicked_may_quit => sub { $r = 'force_reload'; 1 } },
],
) && $r;
}
sub Hd_info {
my ($in, $hd) = @_;
$in->ask_warn(N("Warning"), [ N("Detailed information"), format_hd_info($hd) ]);
}
################################################################################
# per-part actions
################################################################################
sub part_possible_actions {
my ($_in, $hd, $part, $all_hds) = @_;
$part or return;
my %actions = my @l = (
N_("View") => '!isSwap && !isNonMountable && maybeFormatted',
N_("Mount point") => '$part->{real_mntpoint} || (!isBusy && !isSwap && !isNonMountable)',
N_("Type") => '!isBusy && $::expert && (!readonly || $part->{pt_type} == 0x83)',
N_("Options") => '!isSwap($part) && !isNonMountable && $::expert',
N_("Label") => '!isNonMountable && $::expert && fs::format::canEditLabel($part)',
N_("Resize") => '!isBusy && !readonly && !isSpecial || isLVM($hd) && LVM_resizable',
N_("Format") => '!isBusy && !isRawLVM && !isPartOfLVM && (!readonly && ($::expert || $::isStandalone) || fs::type::isRawLUKS($part))',
N_("Mount") => '!isBusy && (hasMntpoint || isSwap) && maybeFormatted && ($::expert || $::isStandalone)',
N_("Add to RAID") => '!isBusy && isRawRAID && (!isSpecial || isRAID)',
N_("Add to LVM") => '!isBusy && isRawLVM',
N_("Use") => '!isBusy && fs::type::isRawLUKS($part) && !$part->{notFormatted}',
N_("Unmount") => '!$part->{real_mntpoint} && isMounted',
N_("Delete") => '!isBusy && !readonly',
N_("Remove from RAID") => 'isPartOfRAID',
N_("Remove from LVM") => 'isPartOfLVM',
N_("Remove from dm") => '$part->{dm_active}',
N_("Modify RAID") => 'canModifyRAID',
N_("Use for loopback") => '!$part->{real_mntpoint} && isMountableRW && !isSpecial && hasMntpoint && maybeFormatted && $::expert',
);
my ($actions_names) = list2kv(@l);
my $_all_hds = $all_hds; #- help perl_checker know the $all_hds *is* used in the macro below
my %macros = (
readonly => '$hd->{readonly}',
hasMntpoint => '$part->{mntpoint}',
LVM_resizable => 'member($part->{fs_type}, qw(reiserfs xfs ext3 ext4))',
canModifyRAID => 'isPartOfRAID($part) && !isMounted(fs::get::device2part($part->{raid}, $all_hds->{raids}))',
);
if (isEmpty($part)) {
if_(!$hd->{readonly}, N_("Create"));
} elsif ($part->{pt_type} == 0xbf && detect_devices::is_xbox()) {
#- XBox OS partitions, do not allow anything
return;
} else {
grep {
my $cond = $actions{$_};
while (my ($k, $v) = each %macros) {
$cond =~ s/$k/qq(($v))/e;
}
$cond =~ s/(^|[^:\$]) \b ([a-z]\w{3,}) \b ($|[\s&\)])/$1 . $2 . '($part)' . $3/exg;
eval $cond;
} @$actions_names;
}
}
sub View {
my ($in, $hd, $part, $all_hds) = @_;
my $handle = any::inspect($part, $::prefix);
if ($handle) {
$in->ask_directory({'directory'=>$handle->{dir}});
} else {
$in->ask_warn(N("Error"), N("Failed to mount partition"));
}
}
#- in case someone use diskdrake only to create partitions,
#- ie without assigning a mount point,
#- do not suggest mount points anymore
my $do_suggest_mount_point = $::isInstall;
sub Create {
my ($in, $hd, $part, $all_hds) = @_;
my ($def_start, $def_size, $max) = ($part->{start}, $part->{size}, $part->{start} + $part->{size});
$part->{maxsize} = $part->{size}; $part->{size} = 0;
if (fsedit::suggest_part($part, $all_hds)) {
$part->{mntpoint} = '' if !$do_suggest_mount_point;
} else {
$part->{size} = $part->{maxsize};
fs::type::suggest_fs_type($part, 'ext3');
}
if (isLVM($hd)) {
lvm::suggest_lv_name($hd, $part);
}
#- update adjustment for start and size, take into account the minimum partition size
#- including one less sector for start due to a capacity to increase the adjustement by
#- one.
my ($primaryOrExtended, $migrate_files);
my $type_name = fs::type::part2type_name($part);
my $mb_size = to_Mb($part->{size});
my $has_startsector = ($::expert || arch() !~ /i.86/) && !isLVM($hd);
$in->ask_from(N("Create a new partition"), '',
[
{ label => N("Create a new partition"), title => 1 },
if_($has_startsector,
{ label => N("Start sector: "), val => \$part->{start}, min => $def_start, max => ($max - min_partition_size($hd)),
type => 'range', SpinButton => $::expert, changed => sub { $mb_size = min($mb_size, to_Mb($max - $part->{start})) } },
),
{ label => N("Size in MB: "), val => \$mb_size, min => to_Mb(min_partition_size($hd)), max => to_Mb($def_size),
type => 'range', SpinButton => $::expert, changed => sub { $part->{start} = min($part->{start}, $max - $mb_size * 2048) } },
{ label => N("Filesystem type: "), val => \$type_name, list => [ fs::type::type_names($::expert, $hd) ],
sort => 0, if_($::expert, gtk => { wrap_width => 2 }, do_not_ellipsize => 1) },
{ label => N("Mount point: "), val => \$part->{mntpoint}, list => [ fsedit::suggestions_mntpoint($all_hds), '' ],
disabled => sub { my $p = fs::type::type_name2subpart($type_name); isSwap($p) || isNonMountable($p) }, type => 'combo', not_edit => 0,
},
if_($::expert && $hd->hasExtended,
{ label => N("Preference: "), val => \$primaryOrExtended, list => [ '', "Extended", "Primary", if_($::expert, "Extended_0x85") ] },
),
if_($::expert && isLVM($hd),
{ label => N("Logical volume name "), val => \$part->{lv_name}, list => [ qw(root swap usr home var), '' ], sort => 0, not_edit => 0 },
),
], complete => sub {
$part->{size} = from_Mb($mb_size, min_partition_size($hd), $max - $part->{start}); #- need this to be able to get back the approximation of using MB
put_in_hash($part, fs::type::type_name2subpart($type_name));
$do_suggest_mount_point = 0 if !$part->{mntpoint};
$part->{mntpoint} = '' if isNonMountable($part);
$part->{mntpoint} = 'swap' if isSwap($part);
fs::mount_options::set_default($part, ignore_is_removable => 1);
check($in, $hd, $part, $all_hds) or return 1;
$migrate_files = need_migration($in, $part->{mntpoint}) or return 1;
my $seen;
eval {
catch_cdie { fsedit::add($hd, $part, $all_hds, { force => 1, primaryOrExtended => $primaryOrExtended }) }
sub { $seen = 1; $in->ask_okcancel('', formatError($@)) };
};
if (my $err = $@) {
if ($err =~ /raw_add/ && $hd->hasExtended && !$hd->{primary}{extended}) {
$in->ask_warn(N("Error"), N("You can not create a new partition
(since you reached the maximal number of primary partitions).
First remove a primary partition and create an extended partition."));
return 0;
} else {
$in->ask_warn(N("Error"), formatError($err)) if !$seen;
return 1;
}
}
0;
},
) or return;
warn_if_renumbered($in, $hd);
if ($migrate_files eq 'migrate') {
format_($in, $hd, $part, $all_hds) or return;
migrate_files($in, $hd, $part);
fs::mount::part($part);
}
}
sub Delete {
my ($in, $hd, $part, $all_hds) = @_;
if (isRAID($part)) {
raid::delete($all_hds->{raids}, $part);
} elsif (isLVM($hd)) {
lvm::lv_delete($hd, $part);
} elsif (isLoopback($part)) {
my $f = "$part->{loopback_device}{mntpoint}$part->{loopback_file}";
if (-e $f && $in->ask_yesorno(N("Warning"), N("Remove the loopback file?"))) {
unlink $f;
}
my $l = $part->{loopback_device}{loopback};
@$l = grep { $_ != $part } @$l;
delete $part->{loopback_device}{loopback} if @$l == 0;
fsedit::recompute_loopbacks($all_hds);
} else {
if (arch() =~ /ppc/) {
undef $partition_table::mac::bootstrap_part if isAppleBootstrap($part) && ($part->{device} = $partition_table::mac::bootstrap_part);
}
partition_table::remove($hd, $part);
warn_if_renumbered($in, $hd);
}
}
sub Type {
my ($in, $hd, $part) = @_;
my $warned;
my $warn = sub {
$warned = 1;
ask_alldatawillbelost($in, $part, N_("After changing type of partition %s, all data on this partition will be lost"));
};
#- for ext2, warn after choosing as ext2->ext3 can be achieved without loosing any data :)
$part->{fs_type} eq 'ext2' || $part->{fs_type} =~ /ntfs/ or $warn->() or return;
my @types = fs::type::type_names($::expert, $hd);
#- when readonly, Type() is allowed only when changing {fs_type} but not {pt_type}
#- eg: switching between ext2, ext3, ext4, reiserfs...
@types = grep { fs::type::type_name2pt_type($_) == $part->{pt_type} } @types if $hd->{readonly};
my $type_name = fs::type::part2type_name($part);
$in->ask_from_({ title => N("Change partition type") },
[
{ label => N("Which filesystem do you want?"), title => 1 },
{ label => N("Type"), val => \$type_name, type => 'list', list => \@types, sort => 1, do_not_ellipsize => 1,
focus => sub { 1 }, not_edit => 1, gtk => { wrap_width => 2 } } ]) or return;
my $type = $type_name && fs::type::type_name2subpart($type_name);
if (member($type->{fs_type}, qw(ext2 ext3 ext4))) {
my $_w = $in->wait_message(N("Please wait"), N("Switching from %s to %s", 'ext2', $type->{fs_type}));
if (run_program::run("tune2fs", "-j", devices::make($part->{device}))) {
put_in_hash($part, $type);
set_isFormatted($part, 1); #- assume that if tune2fs works, partition is formatted
#- disable the fsck (do not do it together with -j in case -j fails?)
fs::format::disable_forced_fsck($part->{device});
return;
}
} elsif ($type->{fs_type} =~ /ntfs/ && $part->{fs_type} =~ /ntfs/) {
if ($type->{fs_type} eq 'ntfs-3g') {
$in->do_pkgs->ensure_binary_is_installed('ntfs-3g', 'mount.ntfs-3g') or return;
}
put_in_hash($part, $type);
return;
}
#- either we switch to non-ext3 or switching losslessly to ext3 failed
$warned or $warn->() or return;
if (defined $type) {
check_type($in, $type, $hd, $part) and fsedit::change_type($type, $hd, $part);
}
}
sub Label {
my ($in, $_hd, $part) = @_;
my $new_label = $part->{device_LABEL} || "";
write_partitions($in, $_hd) or return;
$in->ask_from(N("Set volume label"),
maybeFormatted($part) ?
N("Beware, this will be written to disk as soon as you validate!")
: N("Beware, this will be written to disk only after formatting!"),
[
{ label => N("Which volume label?"), title => 1 },
{ label => N("Label:"), val => \$new_label } ]) or return;
fs::format::check_package_is_installed_label($in->do_pkgs, $part->{fs_type}) or return;
return if $new_label eq $part->{device_LABEL};
$part->{device_LABEL} = $new_label;
$part->{device_LABEL_changed} = 1;
$part->{prefer_device_LABEL} = to_bool($part->{device_LABEL}) && !isLVM($part);
fs::format::clean_label($part);
fs::format::write_label($part);
}
sub Mount_point {
my ($in, $hd, $part, $all_hds) = @_;
my $migrate_files;
my $mntpoint = $part->{mntpoint} || do {
my $part_ = { %$part };
if (fsedit::suggest_part($part_, $all_hds)) {
fs::get::has_mntpoint('/', $all_hds) || $part_->{mntpoint} eq '/boot' ? $part_->{mntpoint} : '/';
} else { '' }
};
my $msg = isLoopback($part) ? N("Where do you want to mount the loopback file %s?", $part->{loopback_file}) :
N("Where do you want to mount device %s?", $part->{device});
$in->ask_from_({
callbacks => {
complete => sub {
!isPartOfLoopback($part) || $mntpoint or $in->ask_warn(N("Error"),
N("Can not unset mount point as this partition is used for loop back.
Remove the loopback first")), return 1;
$part->{mntpoint} eq $mntpoint || check_mntpoint($in, $mntpoint, $part, $all_hds) or return 1;
$migrate_files = need_migration($in, $mntpoint) or return 1;
0;
} },
},
[
{ label => $msg, title => 1 },
{ label => N("Mount point"), val => \$mntpoint,
list => [ uniq(if_($mntpoint, $mntpoint), fsedit::suggestions_mntpoint($all_hds), '') ],
focus => sub { 1 },
not_edit => 0 } ],
) or return;
$part->{mntpoint} = $mntpoint;
if ($migrate_files eq 'migrate') {
format_($in, $hd, $part, $all_hds) or return;
migrate_files($in, $hd, $part);
fs::mount::part($part);
}
}
sub Mount_point_raw_hd {
my ($in, $part, $all_hds, @propositions) = @_;
my $mntpoint = $part->{mntpoint} || shift @propositions;
$in->ask_from(
N("Mount point"),
'',
[
{ label => N("Where do you want to mount %s?", $part->{device}), title => 1 },
{ label => N("Mount point"), val => \$mntpoint,
list => [ if_($mntpoint, $mntpoint), '', @propositions ],
not_edit => 0 } ],
complete => sub {
$part->{mntpoint} eq $mntpoint || check_mntpoint($in, $mntpoint, $part, $all_hds) or return 1;
0;
}
) or return;
$part->{mntpoint} = $mntpoint;
}
sub Resize {
my ($in, $hd, $part) = @_;
my (%nice_resize);
my ($min, $max) = (min_partition_size($hd), max_partition_resize($hd, $part));
if (maybeFormatted($part)) {
# here we may have a non-formatted or a formatted partition
# -> doing as if it was formatted
if ($part->{fs_type} eq 'vfat') {
write_partitions($in, $hd) or return;
#- try to resize without losing data
my $_w = $in->wait_message(N("Resizing"), N("Computing FAT filesystem bounds"));
require resize_fat::main;
$nice_resize{fat} = resize_fat::main->new($part->{device}, devices::make($part->{device}));
$min = max($min, $nice_resize{fat}->min_size);
$max = min($max, $nice_resize{fat}->max_size);
} elsif (member($part->{fs_type}, qw(ext2 ext3))) { # resize2fs is known to be broken regarding extents with ext4
write_partitions($in, $hd) or return;
require diskdrake::resize_ext2;
if ($nice_resize{ext2} = diskdrake::resize_ext2->new($part->{device}, devices::make($part->{device}))) {
$min = max($min, $nice_resize{ext2}->min_size);
} else {
delete $nice_resize{ext2};
}
} elsif ($part->{fs_type} =~ /ntfs/) {
write_partitions($in, $hd) or return;
require diskdrake::resize_ntfs;
diskdrake::resize_ntfs::check_prog($in) or return;
$nice_resize{ntfs} = diskdrake::resize_ntfs->new($part->{device}, devices::make($part->{device}));
$min = $nice_resize{ntfs}->min_size or delete $nice_resize{ntfs};
} elsif ($part->{fs_type} eq 'reiserfs') {
write_partitions($in, $hd) or return;
if ($part->{isMounted}) {
$nice_resize{reiserfs} = 1;
$min = $part->{size}; #- ensure the user can only increase
} elsif (defined(my $free = fs::df($part))) {
$nice_resize{reiserfs} = 1;
$min = max($min, $part->{size} - $free);
}
} elsif ($part->{fs_type} eq 'xfs' && isLVM($hd) && $::isStandalone && $part->{isMounted}) {
$min = $part->{size}; #- ensure the user can only increase
$nice_resize{xfs} = 1;
}
#- make sure that even after normalizing the size to cylinder boundaries, the minimun will be saved,
#- this save at least a cylinder (less than 8Mb).
$min += partition_table::raw::cylinder_size($hd);
$min >= $max and return $in->ask_warn(N("Warning"), N("This partition is not resizeable"));
#- for these, we have tools to resize partition table
#- without losing data (or at least we hope so :-)
if (%nice_resize) {
ask_alldatamaybelost($in, $part, N_("All data on this partition should be backed-up")) or return;
} else {
ask_alldatawillbelost($in, $part, N_("After resizing partition %s, all data on this partition will be lost")) or return;
}
}
my $mb_size = to_Mb($part->{size});
my ($gmin, $gmax) = (to_Mb($min), to_Mb($max));
$in->ask_from(N("Resize"), '', [
{ label => N("Choose the new size"), title => 1 },
{ label => N("New size in MB: "), val => \$mb_size, min => $gmin, max => $gmax, type => 'range', SpinButton => $::expert },
{ label => N("Minimum size: %s MB", $gmin) },
{ label => N("Maximum size: %s MB", $gmax) },
]) or return;
my $size = from_Mb($mb_size, $min, $max);
$part->{size} == $size and return;
my $oldsize = $part->{size};
$part->{size} = $size;
$hd->adjustEnd($part);
undef $@;
my $_b = before_leaving { $@ and $part->{size} = $oldsize };
my $adjust = sub {
my ($write_partitions) = @_;
if (isLVM($hd)) {
lvm::lv_resize($part, $oldsize);
} else {
partition_table::will_tell_kernel($hd, resize => $part);
partition_table::adjust_local_extended($hd, $part);
partition_table::adjust_main_extended($hd);
write_partitions($in, $hd) or return if $write_partitions && %nice_resize;
}
1;
};
$adjust->(1) or return if $size > $oldsize;
my $wait = $in->wait_message(N("Please wait"), N("Resizing"));
if ($nice_resize{fat}) {
local *log::l = sub { $wait->set(join(' ', @_)) };
$nice_resize{fat}->resize($part->{size});
} elsif ($nice_resize{ext2}) {
$nice_resize{ext2}->resize($part->{size});
} elsif ($nice_resize{ntfs}) {
log::l("ntfs resize to $part->{size} sectors");
$nice_resize{ntfs}->resize($part->{size});
$wait = undef;
$in->ask_warn(N("Warning"), N("To ensure data integrity after resizing the partition(s),
filesystem checks will be run on your next boot into Microsoft Windows®"));
} elsif ($nice_resize{reiserfs}) {
log::l("reiser resize to $part->{size} sectors");
run_program::run_or_die('resize_reiserfs', '-f', '-q', '-s' . int($part->{size}/2) . 'K', devices::make($part->{device}));
} elsif ($nice_resize{xfs}) {
#- happens only with mounted LVM, see above
run_program::run_or_die("xfs_growfs", $part->{mntpoint});
}
if (%nice_resize) {
set_isFormatted($part, 1);
} else {
set_isFormatted($part, 0);
partition_table::verifyParts($hd) if !isLVM($hd);
$part->{mntpoint} = '' if isNonMountable($part); #- mainly for ntfs, which we can not format
}
$adjust->(0) if $size < $oldsize;
}
sub Format {
my ($in, $hd, $part, $all_hds) = @_;
format_($in, $hd, $part, $all_hds);
}
sub Mount {
my ($in, $hd, $part) = @_;
ensure_we_have_encrypt_key_if_needed($in, $part) or return;
write_partitions($in, $hd) or return;
my $w;
fs::mount::part($part, 0, sub {
my ($msg) = @_;
$w ||= $in->wait_message(N("Please wait"), $msg);
$w->set($msg);
});
}
sub dmcrypt_open {
my ($in, $_hd, $part, $all_hds) = @_;
$part->{dm_name} ||= do {
my $s = $part->{device};
$s =~ s/[^\w]/_/g;
"crypt_$s";
};
if (!$part->{dmcrypt_key}) {
$in->ask_from_({
title => N("Filesystem encryption key"),
messages => N("Enter your filesystem encryption key"),
}, [ { label => N("Encryption key"), val => \$part->{dmcrypt_key},
hidden => 1, focus => sub { 1 } } ]) or return;
}
eval { fs::dmcrypt::open_part($all_hds->{dmcrypts}, $part) };
if ($@) {
delete $part->{dmcrypt_key};
die(($? >> 8) == 255 ? N("Invalid key") : $@);
}
}
sub Add2RAID {
my ($in, $_hd, $part, $all_hds) = @_;
my $raids = $all_hds->{raids};
my $md_part = $in->ask_from_listf(N("Add to RAID"), N("Choose an existing RAID to add to"),
sub { ref($_[0]) ? $_[0]{device} : $_[0] },
[ @$raids, N_("new") ]) or return;
if (ref($md_part)) {
raid::add($md_part, $part);
raid::write_conf($raids) if $::isStandalone;
} else {
raid::check_prog($in) or return;
my $md_part = raid::new($raids, disks => [ $part ]);
modifyRAID($in, $raids, $md_part) or return raid::delete($raids, $md_part);
}
}
sub Add2LVM {
my ($in, $hd, $part, $all_hds) = @_;
my $lvms = $all_hds->{lvms};
write_partitions($in, $_) or return foreach isRAID($part) ? @{$all_hds->{hds}} : $hd;
my $lvm = $in->ask_from_listf_(N("Add to LVM"), N("Choose an existing LVM to add to"),
sub { ref($_[0]) ? $_[0]{VG_name} : $_[0] },
[ @$lvms, N_("new") ]) or return;
require lvm;
if (!ref $lvm) {
# create new lvm
# FIXME: when mdv2006 is out: remove the question mark from the dialog title
my $name = $in->ask_from_entry(N("LVM name?"), N("LVM name?")) or return;
$lvm = new lvm($name);
push @$lvms, $lvm;
}
raid::make($all_hds->{raids}, $part) if isRAID($part);
lvm::check($in->do_pkgs) if $::isStandalone;
lvm::add_to_VG($part, $lvm);
}
sub Unmount {
my ($_in, $_hd, $part) = @_;
fs::mount::umount_part($part);
}
sub RemoveFromRAID {
my ($_in, $_hd, $part, $all_hds) = @_;
raid::removeDisk($all_hds->{raids}, $part);
}
sub RemoveFromDm {
my ($_in, $_hd, $part, $all_hds) = @_;
fs::dmcrypt::close_part($all_hds->{dmcrypts}, $part);
}
sub RemoveFromLVM {
my ($in, $_hd, $part, $all_hds) = @_;
isPartOfLVM($part) or die;
my ($lvm, $other_lvms) = partition { $_->{VG_name} eq $part->{lvm} } @{$all_hds->{lvms}};
if (@{$lvm->[0]{disks}} > 1) {
my ($used, $_total) = lvm::pv_physical_extents($part);
if ($used) {
$in->ask_yesorno(N("Warning"), N("Physical volume %s is still in use.
Do you want to move used physical extents on this volume to other volumes?", $part->{device})) or return;
my $_w = $in->wait_message(N("Please wait"), N("Moving physical extents"));
lvm::pv_move($part);
}
lvm::vg_reduce($lvm->[0], $part);
} else {
lvm::vg_destroy($lvm->[0]);
$all_hds->{lvms} = $other_lvms;
}
}
sub ModifyRAID {
my ($in, $_hd, $part, $all_hds) = @_;
modifyRAID($in, $all_hds->{raids}, fs::get::device2part($part->{raid}, $all_hds->{raids}));
}
sub Loopback {
my ($in, $hd, $real_part, $all_hds) = @_;
write_partitions($in, $hd) or return;
my $handle = any::inspect($real_part) or $in->ask_warn(N("Error"), N("This partition can not be used for loopback")), return;
my ($min, $max) = (1, fs::loopback::getFree($handle->{dir}, $real_part));
$max = min($max, 1 << (31 - 9)) if $real_part->{fs_type} eq 'vfat'; #- FAT does not handle file size bigger than 2GB
my $part = { maxsize => $max, size => 0, loopback_device => $real_part, notFormatted => 1 };
if (!fsedit::suggest_part($part, $all_hds)) {
$part->{size} = $part->{maxsize};
fs::type::suggest_fs_type($part, 'ext3');
}
delete $part->{mntpoint}; # we do not want the suggested mntpoint
my $type_name = fs::type::part2type_name($part);
my $mb_size = to_Mb($part->{size});
$in->ask_from(N("Loopback"), '', [
{ label => N("Loopback file name: "), val => \$part->{loopback_file} },
{ label => N("Size in MB: "), val => \$mb_size, min => to_Mb($min), max => to_Mb($max), type => 'range', SpinButton => $::expert },
{ label => N("Filesystem type: "), val => \$type_name, list => [ fs::type::type_names($::expert, $hd) ], not_edit => !$::expert, sort => 0 },
],
complete => sub {
$part->{loopback_file} or $in->ask_warn(N("Give a file name"), N("Give a file name")), return 1, 0;
$part->{loopback_file} =~ s|^([^/])|/$1|;
if (my $size = fs::loopback::verifFile($handle->{dir}, $part->{loopback_file}, $real_part)) {
$size == -1 and $in->ask_warn(N("Warning"), N("File is already used by another loopback, choose another one")), return 1, 0;
$in->ask_yesorno(N("Warning"), N("File already exists. Use it?")) or return 1, 0;
delete $part->{notFormatted};
$part->{size} = divide($size, 512);
} else {
$part->{size} = from_Mb($mb_size, $min, $max);
}
0;
}) or return;
put_in_hash($part, fs::type::type_name2subpart($type_name));
push @{$real_part->{loopback}}, $part;
fsedit::recompute_loopbacks($all_hds);
}
sub Options {
my ($in, $hd, $part, $all_hds) = @_;
my @simple_options = qw(users noauto username= password=);
my (undef, $user_implies) = fs::mount_options::list();
my ($options, $unknown) = fs::mount_options::unpack($part);
my %help = fs::mount_options::help();
my %callbacks = (
# we don't want both user and users
user => sub { $options->{users} = 0; $options->{$_} = $options->{user} foreach @$user_implies },
users => sub { $options->{user} = 0; $options->{$_} = $options->{users} foreach @$user_implies },
# we don't want both relatime and noatime
relatime => sub { $options->{noatime} = 0 },
noatime => sub { $options->{relatime} = 0 },
);
$in->ask_from(N("Mount options"),
'',
[
{ label => N("Mount options"), title => 1 },
(map {
{ label => $_, text => scalar warp_text(formatAlaTeX($help{$_}), 60), val => \$options->{$_}, hidden => scalar(/password/),
advanced => !$part->{rootDevice} && !member($_, @simple_options), if_(!/=$/, type => 'bool'),
if_($callbacks{$_}, changed => $callbacks{$_}),
};
} keys %$options),
{ label => N("Various"), val => \$unknown, advanced => 1 },
],
complete => sub {
if (($options->{usrquota} || $options->{grpquota}) && !$::isInstall) {
$in->do_pkgs->ensure_binary_is_installed('quota', 'quotacheck');
}
if ($options->{encrypted}) {
# modify $part->{options} for the check
local $part->{options};
fs::mount_options::pack($part, $options, $unknown);
if (!check($in, $hd, $part, $all_hds)) {
$options->{encrypted} = 0;
} elsif (!$part->{encrypt_key} && !isSwap($part)) {
if (my ($encrypt_key, $encrypt_algo) = choose_encrypt_key($in, $options, '')) {
$options->{'encryption='} = $encrypt_algo;
$part->{encrypt_key} = $encrypt_key;
} else {
$options->{encrypted} = 0;
}
}
#- don't be sure of anything
set_isFormatted($part, 0);
$part->{notFormatted} = 0;
} else {
delete $options->{'encryption='};
delete $part->{encrypt_key};
}
}) or return;