blob: 0558a9787dd5833a19e195934808db488a7df2e5 (
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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
|
#!/bin/bash
# Synopsis: mointpoint_demands
#
# This function dumps the demands of various mountpoints
function mointpoint_demands()
{
cat <<"EOT"
/: Type:Linux
/boot: LVM:no Type:Linux
/bin: Type:Linux
/etc: Type:Linux
/home: Type:Linux
/lib: Type:Linux
/opt: Type:Linux
/root: Type:Linux
/sbin: Type:Linux
/tmp: Type:Linux
/usr: Type:Linux
/var: Type:Linux
EOT
}
# Synopsis: is_disk /dev/xyz
#
# This function returns 0 if the supplied argument is a disk.
function is_disk()
{
stat --format "%t %G" "$1" | grep -qe "^3 " -e " disk$" && return 0
return 1
}
# Synopsis: calculate_min_space
#
# This function estimates the minimum space needed for a hdinstall
function calculate_min_space()
{
ESTIMATED_ROOT_MIN=$(df -m "/live/filesystem" | tail -1 | gawk '{print $3}')
grep -q squashfs /proc/mounts && ESTIMATED_ROOT_MIN=$(($ESTIMATED_ROOT_MIN*270/100))
export ESTIMATED_ROOT_MIN
}
# Synopsis: handle_mountpoint_demands <device>
#
# This function handles the demands of the mountpoints (data from function mountpoint_demands)
# * check if filesystem matches (Filesystem:reiserfs / Filesystem:ext3 / see get_filesystem() )
# * check if filesystem-type matches (Type:Linux / Type:Windows / see get_filesystem_type() )
# * check if <device> is a LVM-device (LVM:yes / LVM:no)
# TODO: from old installer, not adapted yet.
function handle_mountpoint_demands()
{
PART="$1";
FORMAT_FS="$2";
POINT=$(echo $3 | cut -d":" -f1); shift 3
while [ "$1" ];
do
VAR=$(echo $1 | cut -d":" -f1)
VAL=$(echo $1 | cut -d":" -f2)
case "$VAR" in
Filesystem)
if [ -n "$FORMAT_FS" -a "$FORMAT_FS" != "$VAL" ]; then
echo "ERROR: Filesystem on $PART ($POINT) has to be formatted with $VAL!" \
| send_error 1
return 1
elif [ -z "$FORMAT_FS" -a "$(get_filesystem "$PART")" != "$VAL" ]; then
echo "ERROR: Filesystem on $PART ($POINT) is not $VAL!" \
| send_error 1
return 1
fi
;;
Type)
if [ -n "$FORMAT_FS" -a "$(get_filesystem_type -fs "$FORMAT_FS")" != "$VAL" ]; then
echo "ERROR: Filesystem on $PART ($POINT) has to be formatted with a $VAL-Filesystem!" \
| send_error 1
return 1
elif [ -z "$FORMAT_FS" -a "$(get_filesystem_type "$PART")" != "$VAL" ]; then
echo "ERROR: Filesystem on $PART ($POINT) is not a $VAL-Filesystem!" \
| send_error 1
return 1
fi
;;
LVM)
not=not
lvdisplay $PART &>/dev/null; A=$?
[ "$VAL" = "yes" ] && unset not; B=$?
((A*B)) || ! ((A-B)) || ( echo ERROR: $PART "($POINT)" must $not be on a LVM-device! | send_error 1; return 1 ) || return 1
;;
esac
shift
done
}
# Synopsis: check_partitions_for_install
#
# This function processes the hd_map-config:
# * make sure that the device exists
# * take care of the mountpoint demands
# * check if partition has the "automount"-flag
# * check if all partitions are big enough to install the system on it
# TODO: from old installer, not adapted yet.
function check_partitions_for_install()
{
unset found_root
local progress_steps=$(( $(wc -l <<<"$cfg_hdmap") * 2 + 1))
local progress=0
# compute partition_min_table
local partition_min_table_=$ESTIMATED_ROOT_MIN
while IFS=: read device mountpoint filesystem automount
do
progress=$[progress+1]; emit_progress $[100*progress/progress_steps]
case "$mountpoint" in
"") continue;;
/) continue;;
/usr) MP_MIN=$(( $ESTIMATED_ROOT_MIN - $(du -sm --exclude /live/filesystem/usr /live/filesystem | cut -f1) ));;
*) MP_MIN=$(du -sm "/live/filesystem$mountpoint" 2>/dev/null | cut -f1);;
esac
[ -z "$MP_MIN" ] && MP_MIN=0
mp="$mountpoint"
while mp="$(dirname "$mp")"
do
var_mp="$(echo "$mp" | sed 's/[^a-zA-Z0-9]/_/g')"
parent_min="$(eval echo \$partition_min_table$var_mp)"
if [ -n "$parent_min" ]; then
eval local partition_min_table$var_mp=$(( $parent_min-$MP_MIN ))
break
fi
[ "${#mp}" -gt 1 ] || break;
done
var_mp="$(echo "$mountpoint" | sed 's/[^a-zA-Z0-9]/_/g')"
eval local partition_min_table$var_mp=$MP_MIN
done <<<"$cfg_hdmap"
progress=$[progress+1]; emit_progress $[100*progress/progress_steps]
isosrc_dev="$(awk '{if($2 == "/isosrc"){print $1}}' /proc/mounts)"
while IFS=: read device mountpoint filesystem automount
do
if [ -z "$mountpoint" ]; then
# update progress
progress=$[progress+1]; emit_progress $[100*progress/progress_steps]
continue
fi
# set flag if there is a root-partition in the hd_map
[ "$mountpoint" = / ] && found_root=1
if [ "$device" = "$isosrc_dev" ]; then
if [ "$filesystem" ]; then
send_error 1 "Partition $device ($mountpoint) is mounted to /isosrc... This partition cannot be formatted!"
return 1
fi
fi
# take care of the mountpoint demands
if part_demands="$(mointpoint_demands | egrep "^$mountpoint:" 2>/dev/null)"; then
[ "$automount" = "auto" ] || send_error 1 "Partition $device ($mountpoint) doesn't have the automount-flag set!" || return 1
eval handle_mountpoint_demands \"$device\" \"$filesystem\" $part_demands
fi
# Check if the partition is big enough to contain the installation
var_mp="$(echo "$mountpoint" | sed 's/[^a-zA-Z0-9]/_/g')"
mp_min="$(eval echo \$partition_min_table$var_mp)"
partition_size_min=$[mp_min*1024*1024*115/100] # + 15% Filesystem overhead
partition_size="$(blockdev --getsize64 $device)" # actual size of device (in bytes)
if [ "$partition_size" -lt "$partition_size_min" ]; then
send_error 1 "Partition $device ($mountpoint) is too small! it is $[partition_size/1024/1024] MB big, but it should be at least $[partition_size_min/1024/1024+10] MB big"
return 1
fi
progress=$[progress+1]; emit_progress $[100*progress/progress_steps]
done <<<"$cfg_hdmap"
if [ -z "$found_root" ]; then
send_error 1 "No root-partition selected!"
fi
}
# Synopsis: umount_all_affected [-fdisk] <device>
#
# This function unlocks a device and all affected devices:
# * it umounts mounted partitions with "umount" and disables swap-partitions with "swapoff"
# * if "-fdisk" is set:
# - it unlocks all partitions that are on the same device as the one given
# (e.g. "umount_all_affected -fdisk /dev/hda3" is called, so /dev/hda* is unlocked)
# - it takes care of LVM-Volumes and unlocks them if they are affected
# - it takes care of dm_crypt-Disks and unlocks them if they are affected
# TODO: from old installer, not fully adapted yet.
function umount_all_affected()
{
unset DEV NR EXHAUSITIVE
if [ "$1" = "-fdisk" ]; then
# partition itself and its "sister" partitions (just to be sure, for fdisk):
shift
#DEV="${1%%[0-9]*}"
DEV="$(get_disk "$1")"
NR="${1:${#disk}}"
EXHAUSITIVE=1
fi
[ -z "$DEV" ] && DEV="$(echo "$1" | dereferce_links_in_list)"
# Mounts
while IFS=" " read mnt_dev mnt_point mnt_dummy
do
[ "$mnt_point" = "/live/filesystem" -o -z "$mnt_point" ] && continue
case "$mnt_point" in
/|/cdrom|/dev|/dev/*|/isosrc|/proc|/proc/*|/ramdisk|/sys|/tmp) ;;
*)
echo $mnt_dev | dereferce_links_in_list | grep -q ^$DEV$ || continue
for umount_point in $(gawk '{print $2}' /proc/mounts | grep -e "^$mnt_point$" -e "^$mnt_point/" | sort -r)
do
fuser -km "$umount_point"
umount "$umount_point" &>/dev/null || \
umount -l "$umount_point"
done
;;
esac
done < /proc/mounts
# Swap
for i in $(grep -e "^$DEV" /proc/swaps | cut -d\ -f1)
do
swapoff "$i";
done
# # LVM
# for i in $(pvdisplay -c 2>/dev/null | grep "$DEV" | cut -d: -f2 | sort | uniq)
# do
# lv_name="$(lvdisplay $i | gawk '/LV Name/{print $3}')"
# lv_dev="$(echo $lv_name | dereferce_links_in_list)"
# for dev in $( ( echo $lv_name; echo $lv_dev ) | sort | uniq)
# do
# # recursive function call
# umount_all_affected $dev
# done
# ((EXHAUSITIVE)) && vgchange -a n $i &>/dev/null
# done
# # Crypttab
# for cmapname in $(grep $DEV /etc/crypttab | cut -d\ -f1)
# do
# umount_all_affected "/dev/mapper/$cmapname"
# ((EXHAUSITIVE)) && cryptsetup remove $cmapname
# done
}
# Synopsis: prepare_partitions_for_install [--nomount]
#
# This function processes the hd_map-config:
# * create mountpoints
# * format the partitions if a filesystem is given
# * take care of LVM-Volumes and dm_crypt-Disks
# * create the specified mountpoints in $TARGET
# * mount the partitions to the target
# * mount (bind) /dev, /proc and /sys to the target
#
# --nomount simply doesn't mount or umount partitions
# TODO: from old installer, not adapted yet.
function prepare_partitions_for_install()
{
send install_step prepare_partitions_for_install
emit_progress 0
local progress_steps=$(( $(wc -l <<<"$cfg_hdmap") ))
local progress=0
while IFS=: read device mountpoint filesystem automount
do
[ -z "$mountpoint" ] && continue
[ "$1" != "--nomount" ] && umount_all_affected $device
# format device with filesystem (if specified)
if [ "$filesystem" ]; then
dd if=/dev/zero of=$device bs=1k count=16 >/dev/null 2>/dev/null # shutup! :-)
TMP=/tmp/mkfs.$$
case "$filesystem" in
xfs)
mkfs.$filesystem -f $device 2> $TMP 1>&2
;;
reiser*)
echo y | mkfs.$filesystem $device 2> $TMP 1>&2
;;
jfs)
echo y | mkfs.$filesystem $device 2> $TMP 1>&2
;;
*)
mkfs.$filesystem $device 2> $TMP 1>&2
;;
esac
RC="$?"
if [ $RC -ne 0 ]; then
ERROR_MESSAGES=$(tail -8 $TMP)
echo "$ERROR_MESSAGES"
send_error 1 "mkfs failed" || return 1
fi
# Deactivate dir_index-feature of ext2/ext3/ext4-partitions
case $filesystem in
*ext*)
tune2fs -O ^dir_index $device &>/dev/null
;;
esac
fi
mkdir -p ${TARGET}${mountpoint} # make sure mountpoint exists
# only mount the partition if: 1. it has the automount flag
# 2. the mountpoint exists on the Live system
# and 3. prepare_partitions_for_install was not called with "--nomount"
if [ "$automount" = "auto" -a "$1" != "--nomount" -a -d "/live/filesystem$mountpoint" ]; then
# mount device to mountpoint
EC="$(LC_ALL=C mount $device ${TARGET}${mountpoint} 2>&1)"
if (($?)); then
case "$EC" in
"*already mounted*") # then let's try "mount --bind"
already_mp="$(grep ^$device /proc/mounts | cut -d\ -f2)"
if [ -d "$already_mp" ]; then
awk '/^\/dev/{if($4 ~ /^rw/){print $1}}' /proc/mounts | grep -qw $device || mount -o remount,rw "$already_mp"
mount --bind "$already_mp" ${TARGET}${mountpoint} 2>&1
fi
;;
*)
send_error 1 "mount failed: $EC" || return 1
;;
esac
fi
if ! awk '/^\/dev/{if($4 ~ /^rw/){print $1}}' /proc/mounts | grep -qw $device; then
send_error 1 "mount failed: $EC" || return 1
fi
fi
# update progress
progress=$[progress+1]; emit_progress $[100*progress/progress_steps]
done <<<"$cfg_hdmap"
}
function fill_hdmap()
{
hdmap_set "$(
(
echo "$cfg_hdmap"
root_disk="$(get_disk "$(hdmap_get device of mountpoint /)")"
for part in $(list_partitions -usage filesystem)
do
if is_removeable "$part" && [ "$(get_disk "$part")" != "$root_disk" ]; then
echo "$part:::"
else
echo "$part:/media/$(basename "$part")::auto"
fi
done
for part in $(list_linux_partitions)
do
if is_removeable "$part" && [ "$(get_disk "$part")" != "$root_disk" ]; then
echo "$part:::"
else
echo "$part:/media/$(basename "$part")::auto"
fi
done
for part in $(list_dm_partitions)
do
echo "$part:::"
done
) | sort -u -t: -k1,1)"
}
|