#!/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 /boot/efi: LVM:no Type:DOS /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: handle_mountpoint_demands # # 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 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] # # 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 local mountoptions="" while IFS=: read device mountpoint filesystem automount do [ -z "$mountpoint" ] && continue [ "$1" != "--nomount" ] && umount_all_affected $device mountoptions="" if [ "$filesystem" = "btrfs-lzo" ]; then filesystem="btrfs" mountoptions="-o compress=lzo" fi # format device with filesystem (if specified) if [ "$filesystem" ]; then wipefs -a $device # clean all old signatures 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. prepare_partitions_for_install was not called with "--nomount" # and 3. the mountpoint exists on the Live system # (or 4. the mountpoint is a special one that always should be mounted [/boot/efi]) if [ "$automount" = "auto" -a "$1" != "--nomount" ] && [ -d "/live/filesystem$mountpoint" -o "$mountpoint" = "/boot/efi" ]; then # mount device to mountpoint EC="$(LC_ALL=C mount $mountoptions $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 < <(sort -t: -k2,2 <<<"$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 disk="$(get_disk "$part")" if is_removeable "$part" && [ "$disk" != "$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 ) | sort -u -t: -k1,1)" }