summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorDieter Plaetinck <dieter@plaetinck.be>2008-12-07 21:23:38 +0100
committerDieter Plaetinck <dieter@plaetinck.be>2008-12-07 21:23:38 +0100
commitc416b909783915cf148123e8bcee217184dccb4a (patch)
treee76ae0be6e20133cea18cea9703b22e6c75116ad /src/core
parentbf86da5e959d0c0d1895ad1bbb527c676f43a042 (diff)
parent3a01621b8382964d348c35084840c8404f8257a9 (diff)
merging blockdevicerefactor into master
Diffstat (limited to 'src/core')
-rw-r--r--src/core/libs/lib-blockdevices-filesystems.sh552
-rw-r--r--src/core/libs/lib-ui-interactive.sh630
-rw-r--r--src/core/libs/lib-ui.sh389
-rw-r--r--src/core/procedures/base13
-rw-r--r--src/core/procedures/interactive16
5 files changed, 1066 insertions, 534 deletions
diff --git a/src/core/libs/lib-blockdevices-filesystems.sh b/src/core/libs/lib-blockdevices-filesystems.sh
index 9f88db2..df055de 100644
--- a/src/core/libs/lib-blockdevices-filesystems.sh
+++ b/src/core/libs/lib-blockdevices-filesystems.sh
@@ -1,7 +1,31 @@
#!/bin/sh
+
+# FORMAT DEFINITIONS:
+
+# MAIN FORMAT FOR $BLOCK_DATA (format used to interface with this library): one line per blockdevice, multiple fs'es in 1 'fs-string'
+# $BLOCK_DATA entry.
+# <blockdevice> type label/no_label <FS-string>/no_fs
+# FS-string:
+# type;recreate(yes/no);mountpoint;mount?(target,runtime,no);opts;label;params[|FS-string|...] where opts have _'s instead of whitespace
+# NOTE: the 'mount?' for now just matters for the location (if 'target', the target path gets prepended and mounted in the runtime system)
+
+
+# ADDITIONAL INTERNAL FORMAT FOR $TMP_FILESYSTEMS: each filesystem on a separate line, so block devices can appear multiple times be on multiple lines (eg LVM volumegroups with more lvm LV's)
+# part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
+
+
+
+#TODO: this should be fixed on the installcd.
+modprobe dm-crypt || show_warning modprobe 'Could not modprobe dm-crypt. no support for disk encryption'
+modprobe aes-i586 || show_warning modprobe 'Could not modprobe aes-i586. no support for disk encryption'
+
+
+
TMP_DEV_MAP=/home/arch/aif/runtime/dev.map
TMP_FSTAB=/home/arch/aif/runtime/.fstab
+TMP_PARTITIONS=/home/arch/aif/runtime/.partitions
+TMP_FILESYSTEMS=/home/arch/aif/runtime/.filesystems # Only used internally by this library. Do not even think about using this as interface to this library. it won't work
# procedural code from quickinst functionized and fixed.
# there were functions like this in the setup script too, with some subtle differences. see below
@@ -30,7 +54,7 @@ target_special_fs ()
# taken from setup
# Disable swap and all mounted partitions for the destination system. Unmount
-# the destination root partition last!
+# the destination root partition last! TODO: only taking care of / is not enough, we can have the same problem on another level (eg /a/b/c and /a/b)
target_umountall()
{
infofy "Disabling swapspace, unmounting already mounted disk devices..."
@@ -40,39 +64,46 @@ target_umountall()
}
-# literally taken from setup script
+# taken from setup script, modified for separator control
+# $1 set to 1 to echo a newline after device instead of a space (optional)
+# $2 extra things to echo for each device (optional)
+# $3 something to append directly after the device (optional)
finddisks() {
workdir="$PWD"
cd /sys/block
# ide devices
for dev in $(ls | egrep '^hd'); do
if [ "$(cat $dev/device/media)" = "disk" ]; then
- echo "/dev/$dev"
- [ "$1" ] && echo $1
+ echo -n "/dev/$dev$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
fi
done
#scsi/sata devices
for dev in $(ls | egrep '^sd'); do
# TODO: what is the significance of 5? ASKDEV
if ! [ "$(cat $dev/device/type)" = "5" ]; then
- echo "/dev/$dev"
- [ "$1" ] && echo $1
+ echo -n "/dev/$dev$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
fi
done
# cciss controllers
if [ -d /dev/cciss ] ; then
cd /dev/cciss
for dev in $(ls | egrep -v 'p'); do
- echo "/dev/cciss/$dev"
- [ "$1" ] && echo $1
+ echo -n "/dev/cciss/$dev$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
done
fi
# Smart 2 controllers
if [ -d /dev/ida ] ; then
cd /dev/ida
for dev in $(ls | egrep -v 'p'); do
- echo "/dev/ida/$dev"
- [ "$1" ] && echo $1
+ echo -n"/dev/ida/$dev$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
done
fi
cd "$workdir"
@@ -93,7 +124,10 @@ getuuid()
}
-# taken from setup. slightly optimized.
+# taken from setup script, slightly optimized and modified for separator control
+# $1 set to 1 to echo a newline after partition instead of a space (optional)
+# $2 extra things to echo for each partition (optional)
+# $3 something to append directly after the partition (optional) TODO: refactor code so there's a space in between, merge $2 and $3. use echo -e to print whatever user wants
findpartitions() {
workdir="$PWD"
for devpath in $(finddisks)
@@ -107,8 +141,9 @@ findpartitions() {
then
if [ -d $part ]
then
- echo "/dev/$part"
- [ "$1" ] && echo $1
+ echo -n "/dev/$part$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
fi
fi
done
@@ -116,16 +151,18 @@ findpartitions() {
# include any mapped devices
for devpath in $(ls /dev/mapper 2>/dev/null | grep -v control)
do
- echo "/dev/mapper/$devpath"
- [ "$1" ] && echo $1
+ echo -n "/dev/mapper/$devpath$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
done
# include any raid md devices
for devpath in $(ls -d /dev/md* | grep '[0-9]' 2>/dev/null)
do
if grep -qw $(echo $devpath /proc/mdstat | sed -e 's|/dev/||g')
then
- echo "$devpath"
- [ "$1" ] && echo $1
+ echo -n "$devpath$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
fi
done
# inlcude cciss controllers
@@ -134,8 +171,9 @@ findpartitions() {
cd /dev/cciss
for dev in $(ls | egrep 'p')
do
- echo "/dev/cciss/$dev"
- [ "$1" ] && echo $1
+ echo -n "/dev/cciss/$dev$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
done
fi
# inlcude Smart 2 controllers
@@ -144,8 +182,9 @@ findpartitions() {
cd /dev/ida
for dev in $(ls | egrep 'p')
do
- echo "/dev/ida/$dev"
- [ "$1" ] && echo $1
+ echo -n "/dev/ida/$dev$3"
+ [ "$1" = 1 ] && echo || echo -n ' '
+ [ "$2" ] && echo $2
done
fi
@@ -203,76 +242,6 @@ mapdev() {
}
-# _mkfs() taken from setup code and slightly improved.
-# Create and mount filesystems in our destination system directory.
-#
-# args:
-# $1 domk: Whether to make the filesystem or use what is already there (yes/no)
-# $2 device: Device filesystem is on
-# $3 fstype: type of filesystem located at the device (or what to create)
-# $4 dest: Mounting location for the destination system
-# $5 mountpoint: Mount point inside the destination system, e.g. '/boot'
-
-# returns: 1 on failure
-_mkfs() {
- local _domk=$1
- local _device=$2
- local _fstype=$3
- local _dest=$4
- local _mountpoint=$5
-
- debug "_mkfs: domk: $1, _device: $2, fstype: $3, dest: $4, mountpoint: $5"
- # we have two main cases: "swap" and everything else.
- if [ "${_fstype}" = "swap" ]; then
- swapoff ${_device} >/dev/null 2>&1
- if [ "${_domk}" = "yes" ]; then
- mkswap ${_device} >$LOG 2>&1 || ( show_warning "Error creating swap: mkswap ${_device}" ; return 1 )
- fi
- swapon ${_device} >$LOG 2>&1 || ( show_warning "Error activating swap: swapon ${_device}" ; return 1 )
- else
- # make sure the fstype is one we can handle
- local knownfs=0
- for fs in xfs jfs reiserfs ext2 ext3 vfat; do
- [ "${_fstype}" = "${fs}" ] && knownfs=1 && break
- done
-
- [ $knownfs -eq 0 ] && ( show_warning "unknown fstype ${_fstype} for ${_device}" ; return 1 )
- # if we were tasked to create the filesystem, do so
- if [ "${_domk}" = "yes" ]; then
- local ret
- case ${_fstype} in
- xfs) mkfs.xfs -f ${_device} >$LOG 2>&1; ret=$? ;;
- jfs) yes | mkfs.jfs ${_device} >$LOG 2>&1; ret=$? ;;
- reiserfs) yes | mkreiserfs ${_device} >$LOG 2>&1; ret=$? ;;
- ext2) mke2fs "${_device}" >$LOG 2>&1; ret=$? ;;
- ext3) mke2fs -j ${_device} >$LOG 2>&1; ret=$? ;;
- vfat) mkfs.vfat ${_device} >$LOG 2>&1; ret=$? ;;
- # don't handle anything else here, we will error later
- esac
- [ $ret != 0 ] && ( show_warning "Error creating filesystem ${_fstype} on ${_device}" ; return 1 )
- sleep 2
- fi
- # create our mount directory
- mkdir -p ${_dest}${_mountpoint}
- # mount the bad boy
- mount -t ${_fstype} ${_device} ${_dest}${_mountpoint} >$LOG 2>&1
- [ $? != 0 ] && ( show_warning "Error mounting ${_dest}${_mountpoint}" ; return 1 )
- fi
-
- # add to temp fstab
- local _uuid="$(getuuid ${_device})"
- if [ -n "${_uuid}" ]; then
- _device="UUID=${_uuid}"
- fi
- echo -n "${_device} ${_mountpoint} ${_fstype} defaults 0 " >>$TMP_FSTAB
-
- if [ "${_fstype}" = "swap" ]; then
- echo "0" >>$TMP_FSTAB
- else
- echo "1" >>$TMP_FSTAB
- fi
-}
-
# auto_fstab(). taken from setup
# preprocess fstab file
@@ -291,10 +260,10 @@ target_configure_fstab()
}
-# partitions a disk , creates filesystems and mounts them
+# partitions a disk. heavily altered
# $1 device to partition
-# $2 a string of the form: <mountpoint>:<partsize>:<fstype>[:+] (the + is bootable flag)
-partition ()
+# $2 a string of the form: <partsize>:<fstype>[:+] (the + is bootable flag)
+partition()
{
debug "Partition called like: partition '$1' '$2'"
[ -z "$1" ] && die_error "partition() requires a device file and a partition string"
@@ -303,56 +272,38 @@ partition ()
DEVICE=$1
STRING=$2
- # validate DEVICE
- if [ ! -b "$DEVICE" ]; then
- notify "Device '$DEVICE' is not valid"
- return 1
- fi
+ # validate DEVICE
+ if [ ! -b "$DEVICE" ]; then
+ notify "Device '$DEVICE' is not valid"
+ return 1
+ fi
- # validate DEST
- if [ ! -d "$var_TARGET_DIR" ]; then
- notify "Destination directory '$var_TARGET_DIR' is not valid"
- return 1
- fi
+ target_umountall
- # / required
- if [ $(grep -c '/:' <<< $STRING) -ne 1 ]; then
- notify "Need exactly one root partition"
- return 1
- fi
+ # setup input var for sfdisk
+ for fsspec in $STRING; do
+ fssize=$(echo $fsspec | tr -d ' ' | cut -f1 -d:)
+ fssize_spec=",$fssize"
+ [ "$fssize" = "*" ] && fssize_spec=';'
- rm -f $TMP_FSTAB
+ fstype=$(echo $fsspec | tr -d ' ' | cut -f2 -d:)
+ fstype_spec=","
+ [ "$fstype" = "swap" ] && fstype_spec=",S"
- target_umountall
- # setup input var for sfdisk #TODO: even though $STRING Contains a '/home' part it doesn't go through in the loops.. is this only in vbox?
- for fsspec in $STRING; do
- fssize=$(echo $fsspec | tr -d ' ' | cut -f2 -d:)
- if [ "$fssize" = "*" ]; then
- fssize_spec=';'
- else
- fssize_spec=",$fssize"
- fi
- fstype=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
- if [ "$fstype" = "swap" ]; then
- fstype_spec=",S"
- else
- fstype_spec=","
- fi
- bootflag=$(echo $fsspec | tr -d ' ' | cut -f4 -d:)
- if [ "$bootflag" = "+" ]; then
- bootflag_spec=",*"
- else
- bootflag_spec=""
- fi
- sfdisk_input="${sfdisk_input}${fssize_spec}${fstype_spec}${bootflag_spec}\n"
- done
- sfdisk_input=$(printf "$sfdisk_input")
+ bootflag=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
+ bootflag_spec=""
+ [ "$bootflag" = "+" ] && bootflag_spec=",*"
+
+ sfdisk_input="${sfdisk_input}${fssize_spec}${fstype_spec}${bootflag_spec}\n"
+ done
+
+ sfdisk_input=$(printf "$sfdisk_input")
- # invoke sfdisk
- debug "Partition calls: sfdisk $DEVICE -uM >$LOG 2>&1 <<< $sfdisk_input"
- printk off
- infofy "Partitioning $DEVICE"
- sfdisk $DEVICE -uM >$LOG 2>&1 <<EOF
+ # invoke sfdisk
+ debug "Partition calls: sfdisk $DEVICE -uM >$LOG 2>&1 <<< $sfdisk_input"
+ printk off
+ infofy "Partitioning $DEVICE"
+ sfdisk $DEVICE -uM >$LOG 2>&1 <<EOF
$sfdisk_input
EOF
if [ $? -gt 0 ]; then
@@ -362,67 +313,284 @@ EOF
fi
printk on
- # need to mount root first, then do it again for the others
- part=1
- for fsspec in $STRING; do
- mountpoint=$(echo $fsspec | tr -d ' ' | cut -f1 -d:)
- fstype=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
- if echo $mountpoint | tr -d ' ' | grep '^/$' 2>&1 > /dev/null; then
- _mkfs yes ${DEVICE}${part} "$fstype" "$var_TARGET_DIR" "$mountpoint" || return 1
- fi
- part=$(($part + 1))
- done
+ return 0
+}
- # make other filesystems
- part=1
- for fsspec in $STRING; do
- mountpoint=$(echo $fsspec | tr -d ' ' | cut -f1 -d:)
- fstype=$(echo $fsspec | tr -d ' ' | cut -f3 -d:)
- if [ $(echo $mountpoint | tr -d ' ' | grep -c '^/$') -eq 0 ]; then
- _mkfs yes ${DEVICE}${part} "$fstype" "$var_TARGET_DIR" "$mountpoint" || return 1
- fi
- part=$(($part + 1))
- done
- return 0
+# file layout:
+#TMP_PARTITIONS
+# disk partition-scheme
+
+# go over each disk in $TMP_PARTITIONS and partition it
+process_disks ()
+{
+ while read disk scheme
+ do
+ process_disk $disk "$scheme"
+ done < $TMP_PARTITIONS
}
-# makes and mounts filesystems #TODO: don't use files but pass variables, integrate this with other functions
-# $1 file with setup
-fix_filesystems ()
+process_disk ()
{
- [ -z "$1" -o ! -f "$1" ] && die_error "Fix_filesystems needs a file with the setup structure in it"
+ partition $1 $2
+}
- # Umount all things first, umount / last. After that create/mount stuff again, with / first
- # TODO: we now rely on the fact that the manual mountpoint selecter uses this order 'swap,/, /<*>'. It works for now but it's not the most solid
- for line in $(tac $1); do
- MP=$(echo $line | cut -d: -f 3)
- umount ${var_TARGET_DIR}${MP}
- done
- for line in $(cat $1); do
- PART=$(echo $line | cut -d: -f 1)
- FSTYPE=$(echo $line | cut -d: -f 2)
- MP=$(echo $line | cut -d: -f 3)
- DOMKFS=$(echo $line | cut -d: -f 4)
- if [ "$DOMKFS" = "yes" ]; then
- if [ "$FSTYPE" = "swap" ]; then
- infofy "Creating and activating swapspace on $PART"
- else
- infofy "Creating $FSTYPE on $PART, mounting to ${var_TARGET_DIR}${MP}"
- fi
- _mkfs yes $PART $FSTYPE $var_TARGET_DIR $MP || return 1
- else
- if [ "$FSTYPE" = "swap" ]; then
- infofy "Activating swapspace on $PART"
- else
- infofy "Mounting $PART to ${var_TARGET_DIR}${MP}"
- fi
- _mkfs no $PART $FSTYPE $var_TARGET_DIR $MP || return 1
- fi
- sleep 1
- done
+generate_filesystem_list ()
+{
+ echo -n > $TMP_FILESYSTEMS
+ while read part type label fs_string
+ do
+ if [ "$fs_string" != no_fs ]
+ then
+ for fs in `sed 's/|/ /g' <<< $fs_string` # this splits multiple fs'es up, or just takes the one if there is only one (lvm vg's can have more then one lv)
+ do
+ fs_type=` cut -d ';' -f 1 <<< $fs`
+ fs_create=` cut -d ';' -f 2 <<< $fs`
+ fs_mountpoint=` cut -d ';' -f 3 <<< $fs`
+ fs_mount=` cut -d ';' -f 4 <<< $fs`
+ fs_opts=` cut -d ';' -f 5 <<< $fs`
+ fs_label=` cut -d ';' -f 6 <<< $fs`
+ fs_params=` cut -d ';' -f 7 <<< $fs`
+ echo "$part $part_type $part_label $fs_type $fs_create $fs_mountpoint $fs_mount $fs_opts $fs_label $fs_params" >> $TMP_FILESYSTEMS
+ done
+ fi
+ done < $BLOCK_DATA
+
+}
+
+
+# process all entries in $BLOCK_DATA, create all blockdevices and filesystems and mount them correctly, destroying what's necessary first.
+process_filesystems ()
+{
+ debug "process_filesystems Called. checking all entries in $BLOCK_DATA"
+ rm -f $TMP_FSTAB
+ generate_filesystem_list
+
+ # phase 1: destruct all mounts in the vfs that are about to be reconstructed. (and also swapoff where appropriate)
+ # re-order list so that we umount in the correct order. eg first umount /a/b/c, then /a/b. we sort alphabetically, which has the side-effect of sorting by stringlength, hence by vfs dependencies.
+ # TODO: this is not entirely correct: what if something is mounted in a previous run that is now not anymore in $BLOCK_DATA ? that needs to be cleaned up too.
+
+ sort -t \ -k 2 $TMP_FILESYSTEMS | tac | while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
+ do
+ debug "umounting/swapoffing $part"
+ if [ "$fs_type" = swap ]
+ then
+ swapoff $part # could be that it was not swappedon yet. that's not a problem at all.
+ elif [ "$fs_mountpoint" != no_mount ]
+ then
+ [ "$fs_mount" = target ] && fs_mountpoint=$var_TARGET_DIR$fs_mountpoint
+ umount $fs_mountpoint # could be that this was not mounted yet. no problem.
+ fi
+ done
+
+# devs_avail=1
+# while [ $devs_avail = 1 ]
+# do
+# devs_avail=0
+# for part in `findpartitions`
+# do
+# if entry=`grep ^$part $BLOCK_DATA`
+# then
+# process_filesystem "$entry" && sed -i "/^$part/d" $BLOCK_DATA && debug "$part processed and removed from $BLOCK_DATA"
+# devs_avail=1
+# fi
+# done
+# done
+# entries=`wc -l $BLOCK_DATA`
+# if [ $entries -gt 0 ]
+# then
+# die_error "Could not process all entries because not all available blockdevices became available. Unprocessed:`awk '{print \$1}' $BLOCK_DATA`"
+# else
+# debug "All entries processed..."
+# fi
+
+
+ # phase 2: destruct blockdevices if they would exist already (destroy any lvm things, dm_crypt devices etc in the correct order)
+ # in theory devices with same names could be stacked on each other with different dependencies. I hope that's not the case for now. In the future maybe we should destruct things we need and who are in /etc/mtab or something.
+ # targets for destruction: /dev/mapper devices and lvm PV's who contain no fs, or a non-lvm/dm_crypt fs. TODO: improve regexes
+ # after destructing. the parent must be updated to reflect the vanished child.
+
+ # NOTE: an alternative approach could be to just go over all /dev/mapper devices or normal devices that are lvm PV's (by using finddisks etc instead of $BLOCK_DATA, or even better by using finddisks and only doing it if they are in $BLOCK_DATA ) and attempt to destruct.
+ # do that a few times and the ones that blocked because something else on it will probable have become freed and possible to destruct
+
+ # TODO: do this as long as devices in this list remains and exist physically
+ # TODO: abort when there still are physical devices listed, but we tried to destruct them already, give error
+
+ egrep '\+|mapper' $BLOCK_DATA | egrep -v ' lvm-pv;| lvm-vg;| lvm-lv;| dm_crypt;' | while read part part_type part_label fs
+ do
+ real_part=${part/+/}
+ if [ -b "$real_part" ]
+ then
+ debug "Attempting destruction of device $part (type $part_type)"
+ [ "$part_type" = lvm-pv ] && ( pvremove $part || show_warning "process_filesystems blockdevice destruction" "Could not pvremove $part")
+ [ "$part_type" = lvm-vg ] && ( vgremove -f $part || show_warning "process_filesystems blockdevice destruction" "Could not vgremove -f $part")
+ [ "$part_type" = lvm-lv ] && ( lvremove -f $part || show_warning "process_filesystems blockdevice destruction" "Could not lvremove -f $part")
+ [ "$part_type" = dm_crypt ] && ( cryptsetup luksClose $part || show_warning "process_filesystems blockdevice destruction" "Could not cryptsetup luksClose $part")
+ else
+ debug "Skipping destruction of device $part (type $part_type) because it doesn't exist"
+ fi
+ done
+
+
+ # TODO: phase 3: create all blockdevices and filesystems in the correct order (for each fs, the underlying block/lvm/devicemapper device must be available so dependencies must be resolved. for lvm:first pv's, then vg's, then lv's etc)
+
+ while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
+ do
+ if [ -b "$part" -a "$fs_create" = yes ]
+ then
+ # don't ask to mount. we take care of all that ourselves in the next phase
+ process_filesystem $part $fs_type $fs_create $fs_mountpoint no_mount $fs_opts $fs_label $fs_params
+ fi
+ done < $TMP_FILESYSTEMS
+
+
+ # phase 4: mount all filesystems in the vfs in the correct order. (also swapon where appropriate)
+ sort -t \ -k 2 $TMP_FILESYSTEMS | while read part part_type part_label fs_type fs_create fs_mountpoint fs_mount fs_opts fs_label fs_params
+ do
+ if [ "$part_type" = raw ]
+ then
+ debug "mounting/swaponning $part"
+ process_filesystem $part $fs_type no $fs_mountpoint $fs_mount $fs_opts $fs_label $fs_params
+ fi
+ done
+
+
+}
+
+
+# make a filesystem on a blockdevice and mount if needed.
+# $1 partition
+# $2 fs_type
+# $3 fs_create (optional. defaults to yes)
+# $4 fs_mountpoint (optional. defaults to no_mountpoint)
+# $5 fs_mount (optional. defaults to no_mount)
+# $6 fs_opts (optional. defaults to no_opts)
+# $7 fs_label (optional. defaults to no_label or for lvm volumes who need a label (VG's and LV's) vg1,vg2,lv1 etc). Note that if there's no label for a VG you probably did something wrong, because you probably want LV's on it so you need a label for the VG.
+# $8 fs_params (optional. defaults to no_params)
+
+process_filesystem ()
+{
+ [ -z "$1" -o ! -b "$1" ] && die_error "process_filesystem needs a partition as \$1"
+ [ -z "$2" ] && die_error "process_filesystem needs a filesystem type as \$2"
+ debug "process_filesystem $@"
+ part=$1
+ fs_type=$2
+ fs_create=${3:-yes}
+ fs_mountpoint=${4:-no_mountpoint}
+ fs_mount=${5:-no_mount}
+ fs_opts=${6:-no_opts}
+ fs_label=${7:-no_label}
+ fs_params=${8:-no_params}
+
+ # Create the FS
+ if [ "$fs_create" = yes ]
+ then
+ if ! program=`get_filesystem_program $fs_type`
+ then
+ show_warning "process_filesystem error" "Cannot determine filesystem program for $fs_type on $part. Not creating this FS"
+ return 1
+ fi
+ [ "$fs_label" = no_label ] && [ "$fs_type" = lvm-vg -o "$fs_type" = lvm-pv ] && fs_label=default #TODO. implement the incrementing numbers label for lvm vg's and lv's
+
+ ret=0
+ #TODO: health checks on $fs_params etc
+ case ${_fstype} in #TODO: implement label, opts etc decently
+ xfs) mkfs.xfs -f $part $opts >$LOG 2>&1; ret=$? ;;
+ jfs) yes | mkfs.jfs $part $opts >$LOG 2>&1; ret=$? ;;
+ reiserfs) yes | mkreiserfs $part $opts >$LOG 2>&1; ret=$? ;;
+ ext2) mke2fs "$part" $opts >$LOG 2>&1; ret=$? ;;
+ ext3) mke2fs -j $part $opts >$LOG 2>&1; ret=$? ;;
+ vfat) mkfs.vfat $part $opts >$LOG 2>&1; ret=$? ;;
+ swap) mkswap $part $opts >$LOG 2>&1; ret=$? ;;
+ dm_crypt) [ -z "$fs_params" ] && fs_params='-c aes-xts-plain -y -s 512';
+ fs_params=${fs_params//_/ }
+ cryptsetup $fs_params $opts luksFormat $part >$LOG 2>&1; ret=$?
+ cryptsetup luksOpen $part /dev/mapper/$fs_label >$LOG 2>&1; ret=$? || ( show_warning 'cryptsetup' "Error luksOpening $part on /dev/mapper/$fs_label" ) ;;
+ lvm-pv) pvcreate $opts $part >$LOG 2>&1; ret=$? ;;
+ lvm-vg) # $fs_params: ':'-separated list of PV's
+ vgcreate $opts $_label ${fs_params//:/ } >$LOG 2>&1; ret=$? ;;
+ lvm-lv) # $fs_params = size string (eg '5G')
+ lvcreate -L $fs_params $fs_opts -n $_label $part >$LOG 2>&1; ret=$? ;; #$opts is usually something like -L 10G
+ # don't handle anything else here, we will error later
+ esac
+ [ "$ret" -gt 0 ] && ( show_warning "process_filesystem error" "Error creating filesystem $fs_type on $part." ; return 1 )
+ sleep 2
+ fi
+
+ # Mount it, if requested. Note that it's your responsability to figure out if you want this or not before calling me. This will only work for 'raw' filesystems (ext,reiser,xfs, swap etc. not lvm stuff,dm_crypt etc)
+ if [ "$fs_mount" = runtime -o "$fs_mount" = target ]
+ then
+ if [ "$fs_type" = swap ]
+ then
+ debug "swaponning $part"
+ swapon $part >$LOG 2>&1 || ( show_warning 'Swapon' "Error activating swap: swapon $part" ; return 1 )
+ else
+ [ "$fs_mount" = runtime ] && dst=$fs_mountpoint
+ [ "$fs_mount" = target ] && dst=$var_TARGET_DIR$fs_mountpoint
+ debug "mounting $part on $dst"
+ mount -t $fs_type $part $dst >$LOG 2>&1 || ( show_warning 'Mount' "Error mounting $part on $dst" ; return 1 )
+ fi
+ fi
+
+
+ # Add to temp fstab, if not already there.
+ if [ $fs_mountpoint != no_mountpoint -a $fs_mount = target ]
+ then
+ local _uuid="$(getuuid $part)"
+ if [ -n "${_uuid}" ]; then
+ _device="UUID=${_uuid}"
+ fi
+ if ! grep -q "$part $fs_mountpoint $fs_type defaults 0 " $TMP_FSTAB
+ then
+ echo -n "$part $fs_mountpoint $fs_type defaults 0 " >> $TMP_FSTAB
+ if [ "$FSTYPE" = "swap" ]; then
+ echo "0" >>$TMP_FSTAB
+ else
+ echo "1" >>$TMP_FSTAB
+ fi
+ fi
+ fi
return 0
}
+
+
+# $1 filesystem type
+get_filesystem_program ()
+{
+ [ -z "$1" ] && die_error "get_filesystem_program needs a filesystem id as \$1"
+ [ $1 = swap ] && echo mkswap && return 0
+ [ $1 = ext2 ] && echo mkfs.ext2 && return 0
+ [ $1 = ext3 ] && echo mkfs.ext3 && return 0
+ [ $1 = reiserfs ] && echo mkreiserfs && return 0
+ [ $1 = xfs ] && echo mkfs.xfs && return 0
+ [ $1 = jfs ] && echo mkfs.jfs && return 0
+ [ $1 = vfat ] && echo mkfs.vfat && return 0
+ [ $1 = lvm-pv ] && echo pvcreate && return 0
+ [ $1 = lvm-vg ] && echo vgcreate && return 0
+ [ $1 = lvg-lv ] && echo lvcreate && return 0
+ [ $1 = dm_crypt ] && echo cryptsetup && return 0
+ return 1
+}
+
+
+# $1 blockdevice
+# $2 standard SI for 1000*n, IEC for 1024*n (optional. defaults to SI)
+# output will be in $BLOCKDEVICE_SIZE in MB/MiB
+get_blockdevice_size ()
+{
+ [ -b "$1" ] || die_error "get_blockdevice_size needs a blockdevice as \$1 ($1 given)"
+ standard=${2:-SI}
+
+ if [ "$2" = SI ]
+ then
+ BLOCKDEVICE_SIZE=$(hdparm -I $1 | grep -F '1000*1000' | sed "s/^.*:[ \t]*\([0-9]*\) MBytes.*$/\1/")
+ elif [ "$2" = IEC ]
+ then
+ blocks=`fdisk -s $1` || show_warning "Fdisk problem" "Something failed when trying to do fdisk -s $1"
+ #NOTE: on some interwebs they say 1 block = 512B, on other internets they say 1 block = 1kiB. 1kiB seems to work for me. don't sue me if it doesn't for you
+ BLOCKDEVICE_SIZE=$(($blocks/1024))
+ fi
+}
diff --git a/src/core/libs/lib-ui-interactive.sh b/src/core/libs/lib-ui-interactive.sh
index e0c536c..3652610 100644
--- a/src/core/libs/lib-ui-interactive.sh
+++ b/src/core/libs/lib-ui-interactive.sh
@@ -17,33 +17,6 @@ check_depend ()
}
-interactive_partition() {
- target_umountall
-
- # Select disk to partition
- DISCS=$(finddisks _)
- DISCS="$DISCS OTHER - DONE +"
- notify "Available Disks:\n\n$(_getavaildisks)\n"
- DISC=""
- while true; do
- # Prompt the user with a list of known disks
- ask_option no "Select the disk you want to partition (select DONE when finished)" $DISCS || return 1
- DISC=$ANSWER_OPTION
- if [ "$DISC" = "OTHER" ]; then
- _dia_DIALOG --inputbox "Enter the full path to the device you wish to partition" 8 65 "/dev/sda" 2>$ANSWER || return 1
- DISC=$(cat $ANSWER)
- fi
- # Leave our loop if the user is done partitioning
- [ "$DISC" = "DONE" ] && break
- # Partition disc
- notify "Now you'll be put into the cfdisk program where you can partition your hard drive. You should make a swap partition and as many data partitions as you will need.\
- NOTE: cfdisk may tell you to reboot after creating partitions. If you need to reboot, just re-enter this install program, skip this step and go on to step 2."
- cfdisk $DISC
- done
- return 0
-}
-
-
interactive_configure_system()
{
[ "$EDITOR" ] || interactive_get_editor
@@ -89,212 +62,445 @@ interactive_configure_system()
# returns: 1 on failure
interactive_set_clock()
{
- # utc or local?
- ask_option no "Is your hardware clock in UTC or local time?" \
- "UTC" " " \
- "local" " " \
- || return 1
- HARDWARECLOCK=$ANSWER_OPTION
-
- # timezone?
- TIMEZONE=`tzselect` || return 1
+ # utc or local?
+ ask_option no "Is your hardware clock in UTC or local time?" "UTC" " " "local" " " || return 1
+ HARDWARECLOCK=$ANSWER_OPTION
+
+ # timezone?
+ ask_timezone || return 1
+ TIMEZONE=$ANSWER_TIMEZONE
+
+ # set system clock from hwclock - stolen from rc.sysinit
+ local HWCLOCK_PARAMS=""
+ if [ "$HARDWARECLOCK" = "UTC" ]
+ then
+ HWCLOCK_PARAMS="$HWCLOCK_PARAMS --utc"
+ else
+ HWCLOCK_PARAMS="$HWCLOCK_PARAMS --localtime"
+ fi
+
+ if [ "$TIMEZONE" != "" -a -e "/usr/share/zoneinfo/$TIMEZONE" ]
+ then
+ /bin/rm -f /etc/localtime
+ /bin/cp "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
+ fi
+ /sbin/hwclock --hctosys $HWCLOCK_PARAMS --noadjfile
+
+ # display and ask to set date/time
+ ask_datetime
+
+ # save the time
+ date -s "$ANSWER_DATETIME" || show_warning "Date/time setting failed" "Something went wrong when doing date -s $ANSWER_DATETIME"
+ /sbin/hwclock --systohc $HWCLOCK_PARAMS --noadjfile
-
- # set system clock from hwclock - stolen from rc.sysinit
- local HWCLOCK_PARAMS=""
- if [ "$HARDWARECLOCK" = "UTC" ]; then
- HWCLOCK_PARAMS="$HWCLOCK_PARAMS --utc"
- else
- HWCLOCK_PARAMS="$HWCLOCK_PARAMS --localtime"
- fi
- if [ "$TIMEZONE" != "" -a -e "/usr/share/zoneinfo/$TIMEZONE" ]; then
- /bin/rm -f /etc/localtime
- /bin/cp "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
- fi
- /sbin/hwclock --hctosys $HWCLOCK_PARAMS --noadjfile
-
- # display and ask to set date/time
- dialog --calendar "Set the date.\nUse <TAB> to navigate and arrow keys to change values." 0 0 0 0 0 2> $ANSWER || return 1
- local _date="$(cat $ANSWER)"
- dialog --timebox "Set the time.\nUse <TAB> to navigate and up/down to change values." 0 0 2> $ANSWER || return 1
- local _time="$(cat $ANSWER)"
- echo "date: $_date time: $_time" >$LOG
-
- # save the time
- # DD/MM/YYYY hh:mm:ss -> YYYY-MM-DD hh:mm:ss
- local _datetime="$(echo "$_date" "$_time" | sed 's#\(..\)/\(..\)/\(....\) \(..\):\(..\):\(..\)#\3-\2-\1 \4:\5:\6#g')"
- echo "setting date to: $_datetime" >$LOG
- date -s "$_datetime" 2>&1 >$LOG
- /sbin/hwclock --systohc $HWCLOCK_PARAMS --noadjfile
-
- return 0
+ return 0
}
interactive_autoprepare()
{
- DISCS=$(finddisks)
- if [ $(echo $DISCS | wc -w) -gt 1 ]; then
- notify "Available Disks:\n\n$(_getavaildisks)\n"
- ask_option no "Select the hard drive to use" $(finddisks _) || return 1
- DISC=$ANSWER_OPTION
- else
- DISC=$DISCS
- fi
- SET_DEFAULTFS=""
- BOOT_PART_SET=""
- SWAP_PART_SET=""
- ROOT_PART_SET=""
- CHOSEN_FS=""
- # get just the disk size in 1000*1000 MB
- DISC_SIZE=$(hdparm -I /dev/sda | grep -F '1000*1000' | sed "s/^.*:[ \t]*\([0-9]*\) MBytes.*$/\1/")
- while [ "$SET_DEFAULTFS" = "" ]; do
- FSOPTS="ext2 ext2 ext3 ext3"
- [ "$(which mkreiserfs 2>/dev/null)" ] && FSOPTS="$FSOPTS reiserfs Reiser3"
- [ "$(which mkfs.xfs 2>/dev/null)" ] && FSOPTS="$FSOPTS xfs XFS"
- [ "$(which mkfs.jfs 2>/dev/null)" ] && FSOPTS="$FSOPTS jfs JFS"
- while [ "$BOOT_PART_SET" = "" ]; do
- _dia_DIALOG --inputbox "Enter the size (MB) of your /boot partition. Minimum value is 16.\n\nDisk space left: $DISC_SIZE MB" 8 65 "32" 2>$ANSWER || return 1
- BOOT_PART_SIZE="$(cat $ANSWER)"
- if [ "$BOOT_PART_SIZE" = "" ]; then
- notify "ERROR: You have entered an invalid size, please enter again."
- else
- if [ "$BOOT_PART_SIZE" -ge "$DISC_SIZE" -o "$SBOOT_PART_SIZE" = "$DISC_SIZE" ]; then
- notify "ERROR: You have entered a too large size, please enter again."
- elif [ "$BOOT_PART_SIZE" -lt "16" ];
- then
- notify "ERROR: You have entered a too small size, please enter again."
- else
- BOOT_PART_SET=1
- fi
- fi
- done
- DISC_SIZE=$(($DISC_SIZE-$BOOT_PART_SIZE))
- while [ "$SWAP_PART_SET" = "" ]; do
- _dia_DIALOG --inputbox "Enter the size (MB) of your swap partition. Minimum value is > 0.\n\nDisk space left: $DISC_SIZE MB" 8 65 "256" 2>$ANSWER || return 1
- SWAP_PART_SIZE=$(cat $ANSWER)
- if [ "$SWAP_PART_SIZE" = "" -o "$SWAP_PART_SIZE" -le "0" ]; then
- notify "ERROR: You have entered an invalid size, please enter again."
- else
- if [ "$SWAP_PART_SIZE" -ge "$DISC_SIZE" ]; then
- notify "ERROR: You have entered a too large size, please enter again."
- else
- SWAP_PART_SET=1
- fi
- fi
- done
- DISC_SIZE=$(($DISC_SIZE-$SWAP_PART_SIZE))
- while [ "$ROOT_PART_SET" = "" ]; do
- _dia_DIALOG --inputbox "Enter the size (MB) of your / partition. The /home partition will use the remaining space.\n\nDisk space left: $DISC_SIZE MB" 8 65 "7500" 2>$ANSWER || return 1
- ROOT_PART_SIZE=$(cat $ANSWER)
- if [ "$ROOT_PART_SIZE" = "" -o "$ROOT_PART_SIZE" -le "0" ]; then
- notify "ERROR: You have entered an invalid size, please enter again."
- else
- if [ "$ROOT_PART_SIZE" -ge "$DISC_SIZE" ]; then
- notify "ERROR: You have entered a too large size, please enter again."
- else
- ask_yesno "$(($DISC_SIZE-$ROOT_PART_SIZE)) MB will be used for your /home partition. Is this OK?" && ROOT_PART_SET=1
- fi
- fi
+ DISCS=$(finddisks)
+ if [ $(echo $DISCS | wc -w) -gt 1 ]
+ then
+ notify "Available Disks:\n\n$(_getavaildisks)\n"
+ ask_option no "Select the hard drive to use" $(finddisks 1 _) || return 1
+ DISC=$ANSWER_OPTION
+ else
+ DISC=$DISCS
+ fi
+
+ get_blockdevice_size $DISC SI
+ FSOPTS=
+ which `get_filesystem_program ext2` &>/dev/null && FSOPTS="$FSOPTS ext2 Ext2"
+ which `get_filesystem_program ext3` &>/dev/null && FSOPTS="$FSOPTS ext3 Ext3"
+ which `get_filesystem_program reiserfs` &>/dev/null && FSOPTS="$FSOPTS reiserfs Reiser3"
+ which `get_filesystem_program xfs` &>/dev/null && FSOPTS="$FSOPTS xfs XFS"
+ which `get_filesystem_program jfs` &>/dev/null && FSOPTS="$FSOPTS jfs JFS"
+ which `get_filesystem_program vfat` &>/dev/null && FSOPTS="$FSOPTS vfat VFAT"
+
+ ask_number "Enter the size (MB) of your /boot partition. Recommended size: 100MB\n\nDisk space left: $BLOCKDEVICE_SIZE MB" 16 $BLOCKDEVICE_SIZE || return 1
+ BOOT_PART_SIZE=$ANSWER_NUMBER
+
+ BLOCKDEVICE_SIZE=$(($BLOCKDEVICE_SIZE-$BOOT_PART_SIZE))
+
+ ask_number "Enter the size (MB) of your swap partition. Recommended size: 256MB\n\nDisk space left: $BLOCKDEVICE_SIZE MB" 1 $BLOCKDEVICE_SIZE || return 1
+ SWAP_PART_SIZE=$ANSWER_NUMBER
+
+ BLOCKDEVICE_SIZE=$(($BLOCKDEVICE_SIZE-$SWAP_PART_SIZE))
+
+ ROOT_PART_SET=""
+ while [ "$ROOT_PART_SET" = "" ]
+ do
+ ask_number "Enter the size (MB) of your / partition. Recommended size:7500. The /home partition will use the remaining space.\n\nDisk space left: $BLOCKDEVICE_SIZE MB" 1 $BLOCKDEVICE_SIZE || return 1
+ ROOT_PART_SIZE=$ANSWER_NUMBER
+ ask_yesno "$(($BLOCKDEVICE_SIZE-$ROOT_PART_SIZE)) MB will be used for your /home partition. Is this OK?" yes && ROOT_PART_SET=1 #TODO: when doing yes, cli mode prints option JFS all the time, dia mode goes back to disks menu
done
- while [ "$CHOSEN_FS" = "" ]; do
- _dia_DIALOG --menu "Select a filesystem for / and /home:" 13 45 6 $FSOPTS 2>$ANSWER || return 1
- FSTYPE=$(cat $ANSWER)
- ask_yesno "$FSTYPE will be used for / and /home. Is this OK?" && CHOSEN_FS=1
+
+ CHOSEN_FS=""
+ while [ "$CHOSEN_FS" = "" ]
+ do
+ ask_option "Select a filesystem for / and /home:" $FSOPTS || return 1
+ FSTYPE=$ANSWER_OPTION
+ ask_yesno "$FSTYPE will be used for / and /home. Is this OK?" yes && CHOSEN_FS=1
done
- SET_DEFAULTFS=1
- done
- _dia_DIALOG --defaultno --yesno "$DISC will be COMPLETELY ERASED! Are you absolutely sure?" 0 0 \
- || return 1
+ ask_yesno "$DISC will be COMPLETELY ERASED! Are you absolutely sure?" || return 1
- DEVICE=$DISC
- # TODO: why do we define a $DEFAULTFS variable someplace else if we hardcode it's attributes here to be able to replace them with custom values? Can't we just construct the custom thing?
- # For some reason the thing belows replaces everything well, but 'looses' the /home part, I don't know why, cannot reproduce it, but it happens in vbox
- # FSSPECS=$(echo $DEFAULTFS | sed -e "s|/:7500:ext3|/:$ROOT_PART_SIZE:$FSTYPE|g" -e "s|/home:\*:ext3|/home:\*:$FSTYPE|g" -e "s|swap:256|swap:$SWAP_PART_SIZE|g" -e "s|/boot:32|/boot:$BOOT_PART_SIZE|g")
- FSSPECS="/boot:$BOOT_PART_SIZE:ext2:+ swap:$SWAP_PART_SIZE:swap /:$ROOT_PART_SIZE:$FSTYPE /home:*:$FSTYPE"
- debug "\$DEFAULTFS: $DEFAULTFS"
- debug "\$FSSPECS : $FSSPECS"
- # we assume a /dev/hdX format (or /dev/sdX)
- PART_ROOT="${DEVICE}3"
+ # we assume a /dev/hdX format (or /dev/sdX)
+ PART_ROOT="${DISC}3"
+
+ echo "$DISC $BOOT_PART_SIZE:ext2:+ $SWAP_PART_SIZE:swap $ROOT_PART_SIZE:$FSTYPE *:$FSTYPE" > $TMP_PARTITIONS
+
+ echo "${DISC}1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params" >$BLOCK_DATA
+ echo "${DISC}2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params" >$BLOCK_DATA
+ echo "${DISC}3 raw no_label $FSTYPE;yes;/;target;no_opts;no_label;no_params" >$BLOCK_DATA
+ echo "${DISC}4 raw no_label $FSTYPE;yes;/home;target;no_opts;no_label;no_params" >$BLOCK_DATA
+
+
+ process_disks || die_error "Something went wrong while partitioning"
+ process_filesystems || die_error "Something went wrong while processing the filesystems"
+ notify "Auto-prepare was successful"
+ return 0
- partition $DEVICE "$FSSPECS" && notify "Auto-prepare was successful" && return 0
- return 1
}
-interactive_mountpoints() {
- while [ "$PARTFINISH" != "DONE" ]; do
- : >$TMP_FSTAB
- : >/home/arch/aif/runtime/.parts #TODO: use a variable instead of a file, we don't need to use a file for this
-
- # Determine which filesystems are available
- FSOPTS="ext2 ext2 ext3 ext3"
- [ "$(which mkreiserfs 2>/dev/null)" ] && FSOPTS="$FSOPTS reiserfs Reiser3"
- [ "$(which mkfs.xfs 2>/dev/null)" ] && FSOPTS="$FSOPTS xfs XFS"
- [ "$(which mkfs.jfs 2>/dev/null)" ] && FSOPTS="$FSOPTS jfs JFS"
- [ "$(which mkfs.vfat 2>/dev/null)" ] && FSOPTS="$FSOPTS vfat VFAT"
-
- # Select mountpoints
- notify "Available Disks:\n\n$(_getavaildisks)\n"
- PARTS=$(findpartitions _)
- _dia_DIALOG --menu "Select the partition to use as swap" 21 50 13 NONE - $PARTS 2>$ANSWER || return 1
- PART=$(cat $ANSWER)
- PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g")"
- if [ "$PART" != "NONE" ]; then
- DOMKFS="no"
- ask_yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" && DOMKFS="yes"
- echo "$PART:swap:swap:$DOMKFS" >>/home/arch/aif/runtime/.parts
- fi
+interactive_partition() {
+ target_umountall
- _dia_DIALOG --menu "Select the partition to mount as /" 21 50 13 $PARTS 2>$ANSWER || return 1
- PART=$(cat $ANSWER)
- PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g")"
- PART_ROOT=$PART
- # Select root filesystem type
- _dia_DIALOG --menu "Select a filesystem for $PART" 13 45 6 $FSOPTS 2>$ANSWER || return 1
- FSTYPE=$(cat $ANSWER)
- DOMKFS="no"
- ask_yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" && DOMKFS="yes"
- echo "$PART:$FSTYPE:/:$DOMKFS" >>/home/arch/aif/runtime/.parts
-
- #
- # Additional partitions
- #
- _dia_DIALOG --menu "Select any additional partitions to mount under your new root (select DONE when finished)" 21 50 13 $PARTS DONE _ 2>$ANSWER || return 1
- PART=$(cat $ANSWER)
- while [ "$PART" != "DONE" ]; do
- PARTS="$(echo $PARTS | sed -e "s#${PART}\ _##g")"
- # Select a filesystem type
- _dia_DIALOG --menu "Select a filesystem for $PART" 13 45 6 $FSOPTS 2>$ANSWER || return 1
- FSTYPE=$(cat $ANSWER)
- MP=""
- while [ "${MP}" = "" ]; do
- _dia_DIALOG --inputbox "Enter the mountpoint for $PART" 8 65 "/boot" 2>$ANSWER || return 1
- MP=$(cat $ANSWER)
- if grep ":$MP:" /home/arch/aif/runtime/.parts; then
- notify "ERROR: You have defined 2 identical mountpoints! Please select another mountpoint."
- MP=""
- fi
- done
- DOMKFS="no"
- ask_yesno "Would you like to create a filesystem on $PART?\n\n(This will overwrite existing data!)" && DOMKFS="yes"
- echo "$PART:$FSTYPE:$MP:$DOMKFS" >>/home/arch/aif/runtime/.parts
- _dia_DIALOG --menu "Select any additional partitions to mount under your new root" 21 50 13 $PARTS DONE _ 2>$ANSWER || return 1
- PART=$(cat $ANSWER)
- done
- ask_yesno "Would you like to create and mount the filesytems like this?\n\nSyntax\n------\nDEVICE:TYPE:MOUNTPOINT:FORMAT\n\n$(for i in $(cat /home/arch/aif/runtime/.parts); do echo "$i\n";done)" && PARTFINISH="DONE"
+ # Select disk to partition
+ DISCS=$(finddisks 1 _)
+ DISCS="$DISCS OTHER - DONE +"
+ notify "Available Disks:\n\n$(_getavaildisks)\n"
+ DISC=""
+ while true; do
+ # Prompt the user with a list of known disks
+ ask_option no "Select the disk you want to partition (select DONE when finished)" $DISCS || return 1
+ DISC=$ANSWER_OPTION
+ if [ "$DISC" = "OTHER" ]; then
+ ask_string "Enter the full path to the device you wish to partition" "/dev/sda" || return 1
+ DISC=$ANSWER_STRING
+ fi
+ # Leave our loop if the user is done partitioning
+ [ "$DISC" = "DONE" ] && break
+ # Partition disc
+ notify "Now you'll be put into the cfdisk program where you can partition your hard drive. You should make a swap partition and as many data partitions as you will need.\
+ NOTE: cfdisk may tell you to reboot after creating partitions. If you need to reboot, just re-enter this install program, skip this step and go on to the mountpoints selection step."
+ cfdisk $DISC
done
+ return 0
+}
- target_umountall
- fix_filesystems /home/arch/aif/runtime/.parts && notify "Partitions were successfully mounted." && return 0
+# create new, delete, or edit a filesystem
+# At first I had the idea of a menu where all properties of a filesystem and you could pick one to update only that one (eg mountpoint, type etc)\
+# but I think it's better to go through them all and by default always show the previous choice.
+interactive_filesystem ()
+{
+ part=$1 # must be given and (scheduled to become) a valid device -> don't do [ -b "$1" ] because the device might not exist *yet*
+ part_type=$2 # a part should always have a type
+ part_label=$3 # can be empty
+ fs=$4 # can be empty
+ NEW_FILESYSTEM=
+ if [ -z "$fs" ]
+ then
+ fs_type=
+ fs_mountpoint=
+ fs_opts=
+ fs_label=
+ fs_params=
+ else
+ ask_option edit "Alter $part (type:$part_type,label:$part_label) ?" edit EDIT delete 'DELETE (revert to raw partition)'
+ [ $? -gt 0 ] && NEW_FILESYSTEM=$fs && return 0
+ if [ "$ANSWER_OPTION" = delete ]
+ then
+ NEW_FILESYSTEM=empty
+ return 0
+ else
+ fs_type=` cut -d ';' -f 1 <<< $fs`
+ fs_create=` cut -d ';' -f 2 <<< $fs` #not asked for to the user. this is always 'yes' for now
+ fs_mountpoint=` cut -d ';' -f 3 <<< $fs`
+ fs_mount=` cut -d ';' -f 4 <<< $fs` #we dont need to ask this to the user. this is always 'target' for 99.99% of the users
+ fs_opts=` cut -d ';' -f 5 <<< $fs`
+ fs_label=` cut -d ';' -f 6 <<< $fs`
+ fs_params=` cut -d ';' -f 7 <<< $fs`
+ [ "$fs_type" = no_type ] && fs_type=
+ [ "$fs_mountpoint" = no_mountpoint ] && fs_mountpoint=
+ [ "$fs_opts" = no_opts ] && fs_opts=
+ [ "$fs_label" = no_label ] && fs_label=
+ [ "$fs_params" = no_params ] && fs_params=
+ old_fs_type=$fs_type
+ old_fs_mountpoint=$fs_mountpoint
+ old_fs_opts=$fs_opts
+ old_fs_label=$fs_label
+ old_fs_params=$fs_params
+ fi
+ fi
+
+ # Possible filesystems/software layers on partitions/block devices
+
+ # name on top of mountpoint? label? DM device? theoretical device? opts? special params?
+
+ # swap raw/lvm-lv/dm_crypt no no no no no no
+ # ext 2 raw/lvm-lv/dm_crypt optional optional no no optional no
+ # ext 3 raw/lvm-lv/dm_crypt optional optional no no optional no
+ # reiserFS raw/lvm-lv/dm_crypt optional optional no no optional no
+ # xfs raw/lvm-lv/dm_crypt optional optional no no optional no
+ # jfs raw/lvm-lv/dm_crypt optional optional no no optional no
+ # vfat raw/lvm-lv/dm_crypt optional opt i guess no no optional no
+ # lvm-pv raw/dm_crypt no no no. $pv = $part $part+ (+ is to differentiate from $part) optional no
+ # lvm-vg lvm-pv no yes /dev/mapper/$label =dm device optional PV's to use
+ # lvm-lv lvm-vg no yes /dev/mapper/$part_label-$label =dm device optional LV size
+ # dm_crypt raw/rvm-lv no yes /dev/mapper/$label =dm device optional no
+
+
+ # Determine which filesystems/blockdevices are possible for this blockdevice
+ FSOPTS=
+ [ $part_type = raw -o $part_type = lvm-lv -o $part_type = dm_crypt ] && which `get_filesystem_program swap` &>/dev/null && FSOPTS="$FSOPTS swap Swap"
+ [ $part_type = raw -o $part_type = lvm-lv -o $part_type = dm_crypt ] && which `get_filesystem_program ext2` &>/dev/null && FSOPTS="$FSOPTS ext2 Ext2"
+ [ $part_type = raw -o $part_type = lvm-lv -o $part_type = dm_crypt ] && which `get_filesystem_program ext3` &>/dev/null && FSOPTS="$FSOPTS ext3 Ext3"
+ [ $part_type = raw -o $part_type = lvm-lv -o $part_type = dm_crypt ] && which `get_filesystem_program reiserfs` &>/dev/null && FSOPTS="$FSOPTS reiserfs Reiser3"
+ [ $part_type = raw -o $part_type = lvm-lv -o $part_type = dm_crypt ] && which `get_filesystem_program xfs` &>/dev/null && FSOPTS="$FSOPTS xfs XFS"
+ [ $part_type = raw -o $part_type = lvm-lv -o $part_type = dm_crypt ] && which `get_filesystem_program jfs` &>/dev/null && FSOPTS="$FSOPTS jfs JFS"
+ [ $part_type = raw -o $part_type = lvm-lv -o $part_type = dm_crypt ] && which `get_filesystem_program vfat` &>/dev/null && FSOPTS="$FSOPTS vfat VFAT"
+ [ $part_type = raw -o $part_type = dm_crypt ] && which `get_filesystem_program lvm-pv` &>/dev/null && FSOPTS="$FSOPTS lvm-pv LVM_Physical_Volume"
+ [ $part_type = lvm-pv ] && which `get_filesystem_program lvm-vg` &>/dev/null && FSOPTS="$FSOPTS lvm-vg LVM_Volumegroup"
+ [ $part_type = lvm-vg ] && which `get_filesystem_program lvm-lv` &>/dev/null && FSOPTS="$FSOPTS lvm-lv LVM_Logical_Volume"
+ [ $part_type = raw -o $part_type = lvm-lv ] && which `get_filesystem_program dm_crypt` &>/dev/null && FSOPTS="$FSOPTS dm_crypt DM_crypt_Volume"
+
+ # determine FS
+ fsopts=($FSOPTS);
+ if [ ${#fsopts[*]} -lt 4 ] # less then 4 words in the $FSOPTS string. eg only one option
+ then
+ notify "Automatically picked the ${fsopts[1]} filesystem. It's the only option for $part_type blockdevices" #TODO: ${fsopts[1]} is empty when making an LV on a VG
+ fs_type=${fsopts[0]}
+ else
+ default=
+ [ -n "$fs_type" ] && default="--default-item $fs_type"
+ ask_option no "Select a filesystem for $part:" $FSOPTS || return 1
+ fs_type=$ANSWER_OPTION
+ fi
+
+ # ask mountpoint, if relevant
+ if [[ $fs_type != lvm-* && "$fs_type" != dm_crypt && $fs_type != swap ]]
+ then
+ default=
+ [ -n "$fs_mountpoint" ] && default="$fs_mountpoint"
+ ask_string "Enter the mountpoint for $part" "$default" || return 1
+ fs_mountpoint=$ANSWER_STRING
+ fi
+
+ # ask label, if relevant
+ if [ "$fs_type" = lvm-vg -o "$fs_type" = lvm-lv -o "$fs_type" = dm_crypt ]
+ then
+ default=
+ [ -n "$fs_label" ] && default="$fs_label"
+ ask_string "Enter the label/name for this $fs_type on $part" "$default" 0 #TODO: check that you can't give LV's labels that have been given already or the installer will break
+ fs_label=$ANSWER_STRING
+ fi
+
+ # ask special params, if relevant
+ if [ "$fs_type" = lvm-vg ]
+ then
+ # add $part to $fs_params if it's not in there because the user wants this enabled by default
+ pv=${part/+/}
+ grep -q ":$pv:" <<< $fs_params || grep -q ":$pv\$" <<< $fs_params || fs_params="$fs_params:$pv"
+
+ for pv in `sed 's/:/ /' <<< $fs_params`
+ do
+ list="$list $pv ON"
+ done
+ for pv in `grep '+ lvm-pv' $BLOCK_DATA | awk '{print $1}' | sed 's/\+$//'` # find PV's to be added: their blockdevice ends on + and has lvm-pv as type #TODO: i'm not sure we check which pv's are taken already
+ do
+ grep -q "$pv ON" <<< "$list" || list="$list $pv OFF"
+ done
+ list2=($list)
+ if [ ${#list2[*]} -lt 4 ] # less then 4 words in the list. eg only one option
+ then
+ notify "Automatically picked PV ${list2[0]} to use for this VG. It's the only available lvm PV"
+ fs_params=${list2[0]}
+ else
+ ask_checklist "Which lvm PV's must this volume group span?" $list || return 1
+ fs_params="$(sed 's/ /:/' <<< "$ANSWER_CHECKLIST")" #replace spaces by colon's, we cannot have spaces anywhere in any string
+ fi
+ fi
+ if [ "$fs_type" = lvm-lv ]
+ then
+ [ -z "$fs_params" ] && default='5G'
+ [ -n "$fs_params" ] && default="$fs_params"
+ ask_string "Enter the size for this $fs_type on $part (suffix K,M,G,T,P,E. default is M)" "$default" || return 1
+ fs_params=$ANSWER_STRING
+ fi
+ if [ "$fs_type" = dm_crypt ]
+ then
+ [ -z "$fs_params" ] && default='-c aes-xts-plain -y -s 512'
+ [ -n "$fs_params" ] && default="${fs_params//_/ }"
+ ask_string "Enter the options for this $fs_type on $part" "$default" || return 1
+ fs_params="${ANSWER_STRING// /_}"
+ fi
+
+ # ask opts
+ default=
+ [ -n "$fs_opts" ] && default="$fs_opts"
+ program=`get_filesystem_program $fs_type`
+ ask_string "Enter any additional opts for $program" "$default" 0
+ fs_opts=$(sed 's/ /_/g' <<< "$ANSWER_STRING") #TODO: clean up all whitespace (tabs and shit)
+
+ [ -z "$fs_type" ] && fs_type=no_type
+ [ -z "$fs_mountpoint" ] && fs_mountpoint=no_mountpoint
+ [ -z "$fs_opts" ] && fs_opts=no_opts
+ [ -z "$fs_label" ] && fs_label=no_label
+ [ -z "$fs_params" ] && fs_params=no_params
+ NEW_FILESYSTEM="$fs_type;yes;$fs_mountpoint;target;$fs_opts;$fs_label;$fs_params" #TODO: make re-creation yes/no asking available in this UI.
+
+ # add new theoretical blockdevice, if relevant
+ if [ "$fs_type" = lvm-vg ]
+ then
+ echo "/dev/mapper/$fs_label $fs_type $fs_label no_fs" >> $BLOCK_DATA
+ elif [ "$fs_type" = lvm-pv ]
+ then
+ echo "$part+ $fs_type no_label no_fs" >> $BLOCK_DATA
+ elif [ "$fs_type" = lvm-lv ]
+ then
+ echo "/dev/mapper/$part_label-$fs_label $fs_type no_label no_fs" >> $BLOCK_DATA
+ elif [ "$fs_type" = dm_crypt ]
+ then
+ echo "/dev/mapper/$fs_label $fs_type no_label no_fs" >> $BLOCK_DATA
+ fi
+
+ # TODO: cascading remove theoretical blockdevice(s), if relevant ( eg if we just changed from vg->ext3, dm_crypt -> fat, or if we changed the label of something, etc)
+ if [[ $old_fs = lvm-* || $old_fs = dm_crypt ]] && [[ $fs != lvm-* && "$fs" != dm_crypt ]]
+ then
+ [ "$fs" = lvm-vg -o "$fs" = dm_cryp ] && target="/dev/mapper/$label"
+ [ "$fs" = lvm-lv ] && target="/dev/mapper/$vg-$label" #TODO: $vg not set
+ sed -i "#$target#d" $BLOCK_DATA #TODO: check affected items, delete those, etc etc.
+ fi
+}
+
+interactive_filesystems() {
+
+ notify "Available Disks:\n\n$(_getavaildisks)\n"
+
+ BLOCK_DATA=/home/arch/aif/runtime/.blockdata
+
+ # $BLOCK_DATA entry. easily parsable.:
+ # <blockdevice> type label/no_label <FS-string>/no_fs
+ # FS-string:
+ # type;recreate;mountpoint;mount?(target,runtime,no);opts;label;params[|FS-string|...] where opts/params have _'s instead of whitespace if needed
+
+ findpartitions 0 'no_fs' ' raw no_label' > $BLOCK_DATA
+
+ ALLOK=0
+ while [ "$ALLOK" = 0 ]
+ do
+ # Let the user make filesystems and mountpoints
+ USERHAPPY=0
+
+ while [ "$USERHAPPY" = 0 ]
+ do
+ # generate a menu based on the information in the datafile
+ menu_list=
+ while read part type label fs
+ do
+ infostring="type:$type,label:$label,fs:$fs"
+ [ -b "$part" ] && get_blockdevice_size ${part/+/} && infostring="size:${BLOCKDEVICE_SIZE}MB,$infostring" # add size in MB for existing blockdevices (eg not for mapper devices that are not yet created yet)
+ menu_list="$menu_list $part $infostring" #don't add extra spaces, dialog doesn't like that.
+ done < $BLOCK_DATA
+
+ ask_option no "Manage filesystems, block devices and virtual devices. Note that you don't *need* to specify opts, labels or extra params if you're not using lvm, dm_crypt, etc." $menu_list DONE _
+ [ $? -gt 0 ] && USERHAPPY=1 && break
+ [ "$ANSWER_OPTION" == DONE ] && USERHAPPY=1 && break
+
+ part=$ANSWER_OPTION
+
+ declare part_escaped=${part//\//\\/} # escape all slashes otherwise awk complains
+ declare part_escaped=${part_escaped/+/\\+} # escape the + sign too
+ part_type=$( awk "/^$part_escaped/ {print \$2}" $BLOCK_DATA)
+ part_label=$(awk "/^$part_escaped/ {print \$3}" $BLOCK_DATA)
+ fs=$( awk "/^$part_escaped/ {print \$4}" $BLOCK_DATA)
+ [ "$part_label" == no_label ] && part_label=
+ [ "$fs" == no_fs ] && fs=
+
+ if [ $part_type = lvm-vg ] # one lvm VG can host multiple LV's so that's a bit a special blockdevice...
+ then
+ list=
+ if [ -n "$fs" ]
+ then
+ for lv in `sed 's/|/ /g' <<< $fs`
+ do
+ label=$(cut -d ';' -f 4 <<< $lv)
+ mountpoint=$(cut -d ';' -f 2 <<< $lv)
+ list="$list $label $mountpoint"
+ done
+ else
+ list="XXX no-LV's-defined-yet-make-a-new-one"
+ fi
+ list="$list empty NEW"
+ ask_option empty "Edit/create new LV's on this VG:" $list
+ if [ "$ANSWER_OPTION" = XXX -o "$ANSWER_OPTION" = empty ]
+ then
+ # a new LV must be created on this VG
+ if interactive_filesystem $part $part_type $part_label ''
+ then
+ [ -z "$fs" ] && fs=$NEW_FILESYSTEM
+ [ -n "$fs" ] && fs="$fs|$NEW_FILESYSTEM"
+ fi
+ else
+ # an existing LV will be edited and it's settings updated
+ for lv in `sed '/|/ /' <<< $fs`
+ do
+ label=$(cut -d ';' -f 4 <<< $lv)
+ [ "$label" = "$ANSWER_OPTION" ] && found_lv="$lv"
+ done
+ interactive_filesystem $part $part_type $part_label "$found_lv"
+ fs=
+ for lv in `sed '/|/ /' <<< $fs`
+ do
+ label=$(cut -d ';' -f 4 <<< $lv)
+ add=$lv
+ [ "$label" = "$ANSWER_OPTION" ] && add=$NEW_FILESYSTEM
+ [ -z "$fs" ] && fs=$add
+ [ -n "$fs" ] && fs="$fs|$add"
+ done
+ fi
+ else
+ interactive_filesystem $part $part_type $part_label $fs
+ [ $? -eq 0 ] && fs=$NEW_FILESYSTEM
+ fi
+
+ # update the menu # NOTE that part_type remains raw for basic filesystems!
+ [ -z "$part_label" ] && part_label=no_label
+ [ -z "$fs" ] && fs=no_fs
+ sed -i "s#^$part $part_type $part_label.*#$part $part_type $part_label $fs#" $BLOCK_DATA # '#' is a forbidden character !
+
+ done
+
+ # Check all conditions that need to be fixed and ask the user if he wants to go back and correct them
+ errors=
+ warnings=
+
+ grep -q ';/boot;' || warnings="$warnings\n-No separate /boot filesystem"
+ grep -q ';/;' || errors="$errors\n-No filesystem with mountpoint /"
+ grep -q ' swap;' || grep -q '|swap;' || warnings="$warnings\n-No swap partition defined"
+
+ if [ -n "$errors$warnings" ]
+ then
+ str="The following issues have been detected:\n"
+ [ -n "$errors" ] && str="$str\n - Errors: $errors"
+ [ -n "$warnings" ] && str="$str\n - Warnings: $warnings"
+ ask_yesno "$str\n Do you want to back to fix (one of) these issues?" || ALLOK=1
+ fi
+
+ done
+
- show_warning "Failure while doing filesystems" "Something went wrong. Check your logs"
+ process_filesystems && notify "Partitions were successfully created." && return 0
+ show_warning "Filesystem processing" "Something went wrong while processing the filesystems"
return 1
}
+
# select_packages()
# prompts the user to select packages to install
#
@@ -481,8 +687,8 @@ EOF
[ "$EDITOR" ] || interactive_get_editor
$EDITOR $grubmenu
- DEVS=$(finddisks _)
- DEVS="$DEVS $(findpartitions _)"
+ DEVS=$(finddisks 1 _)
+ DEVS="$DEVS $(findpartitions 1 _)"
if [ "$DEVS" = "" ]; then
notify "No hard drives were found"
return 1
diff --git a/src/core/libs/lib-ui.sh b/src/core/libs/lib-ui.sh
index d54ea0d..bddb739 100644
--- a/src/core/libs/lib-ui.sh
+++ b/src/core/libs/lib-ui.sh
@@ -1,5 +1,6 @@
#!/bin/sh
# TODO: lot's of implementation work still open in this library. especially the dialog & $var_UI_TYPE stuff
+# TODO: get rid of the echoing of the variables at the end. passing output as $ANSWER_<foo> is more useful
# Taken from setup. we store dialog output in a file. TODO: can't we do this with variables? ASKDEV
@@ -9,6 +10,7 @@ DIA_MENU_TEXT="Use the UP and DOWN arrows to navigate menus. Use TAB to switch
### Functions that your code can use. Cli/dialog mode is fully transparant. This library takes care of it ###
+
# display error message and die
die_error ()
{
@@ -100,44 +102,70 @@ debug ()
}
-# ask the user a password. return is stored in $PASSWORD or $<TYPE>_PASSWORD
-# $1 type (optional. eg 'svn', 'ssh').
-ask_password ()
+# taken from setup
+printk()
{
- [ "$var_UI_TYPE" = dia ] && { _dia_ask_password "$@" ; return $? ; }
- [ "$var_UI_TYPE" = cli ] && { _cli_ask_password "$@" ; return $? ; }
+ case $1 in
+ "on") echo 4 >/proc/sys/kernel/printk ;;
+ "off") echo 0 >/proc/sys/kernel/printk ;;
+ esac
}
-# ask a yes/no question.
-# $1 question
-# returns 0 if response is yes/y (case insensitive). 1 otherwise
-# TODO: support for default answer
-ask_yesno ()
+# TODO: pass disks as argument to decouple backend logic
+# Get a list of available disks for use in the "Available disks" dialogs. This
+# will print the disks as follows, getting size info from hdparm:
+# /dev/sda: 640133 MBytes (640 GB)
+# /dev/sdb: 640135 MBytes (640 GB)
+_getavaildisks()
{
- [ -z "$1" ] && die_error "ask_yesno needs a question!"
- [ "$var_UI_TYPE" = dia ] && { _dia_ask_yesno "$@" ; return $? ; }
- [ "$var_UI_TYPE" = cli ] && { _cli_ask_yesno "$@" ; return $? ; }
+ # NOTE: to test as non-root, stick in a 'sudo' before the hdparm call
+ for i in $(finddisks); do echo -n "$i: "; hdparm -I $i | grep -F '1000*1000' | sed "s/.*1000:[ \t]*\(.*\)/\1/"; echo "\n"; done
}
-# ask for a string.
+# ask the user to make a selection from a certain group of things
# $1 question
-# echo's the string the user gave.
-# returns 1 if the user cancelled, 0 otherwise
-ask_string ()
+# shift;shift; $@ list of options. first tag. then ON/OFF
+ask_checklist ()
{
- [ -z "$1" ] && die_error "ask_string needs a question!"
- [ "$var_UI_TYPE" = dia ] && { _dia_ask_string "$@" ; return $? ; }
- [ "$var_UI_TYPE" = cli ] && { _cli_ask_string "$@" ; return $? ; }
+ [ -z "$1" ] && die_error "ask_checklist needs a question!"
+ [ -z "$3" ] && debug "ask_checklist args: $@" && die_error "ask_checklist makes only sense if you specify at least 1 thing (incl ON/OFF switch)"
+ [ "$var_UI_TYPE" = dia ] && { _dia_ask_option "$@" ; return $? ; }
+ [ "$var_UI_TYPE" = cli ] && { _cli_ask_option "$@" ; return $? ; }
+}
+
+
+
+ask_datetime ()
+{
+ if [ "$var_UI_TYPE" = dia ]
+ then
+ # display and ask to set date/time
+ dialog --calendar "Set the date.\nUse <TAB> to navigate and arrow keys to change values." 0 0 0 0 0 2> $ANSWER || return 1
+ local _date="$(cat $ANSWER)" # form like: 07/12/2008
+ dialog --timebox "Set the time.\nUse <TAB> to navigate and up/down to change values." 0 0 2> $ANSWER || return 1
+ local _time="$(cat $ANSWER)" # form like: 15:26:46
+ echo "date: $_date time: $_time" >$LOG
+
+ # DD/MM/YYYY hh:mm:ss -> MMDDhhmmYYYY.ss (date default format, set like date $ANSWER_DATETIME) Not enabled because there is no use for it i think.
+ # ANSWER_DATETIME=$(echo "$_date" "$_time" | sed 's#\(..\)/\(..\)/\(....\) \(..\):\(..\):\(..\)#\2\1\4\5\3\6#g')
+ # DD/MM/YYYY hh:mm:ss -> YYYY-MM-DD hh:mm:ss ( date string format, set like date -s "$ANSWER_DATETIME")
+ ANSWER_DATETIME="$(echo "$_date" "$_time" | sed 's#\(..\)/\(..\)/\(....\) \(..\):\(..\):\(..\)#\3-\2-\1 \4:\5:\6#g')"
+ elif [ "$var_UI_TYPE" = cli ]
+ then
+ ask_string "Enter date [YYYY-MM-DD hh:mm:ss]"
+ ANSWER_DATETIME=$ANSWER_STRING
+ fi
}
-# TODO: we should have a wrapper around this function that keeps trying until the user entered a valid numeric?
+# TODO: we should have a wrapper around this function that keeps trying until the user entered a valid numeric?, maybe a wrapper that wraps all functions
# ask for a number.
# $1 question
# $2 lower limit (optional)
# $3 upper limit (optional)
+# TODO: implement a default number
# echo's the number the user said
# returns 1 if the user cancelled or did not enter a numeric, 0 otherwise
ask_number ()
@@ -148,13 +176,14 @@ ask_number ()
[ "$var_UI_TYPE" = dia ] && { _dia_ask_number "$1" "$2" "$3" ; return $? ; }
[ "$var_UI_TYPE" = cli ] && { _cli_ask_number "$1" "$2" "$3" ; return $? ; }
}
-
+
# ask the user to choose something
# $1 default item (set to 'no' for none)
# $2 title
# shift;shift; $@ list of options. first tag. then name. (eg tagA itemA "tag B" 'item B' )
# the response will be echoed to stdout. but also $ANSWER_OPTION will be set. take that because the former method seems to not work.
+# $? if user cancelled. 0 otherwise
ask_option ()
{
[ "$var_UI_TYPE" = dia ] && { _dia_ask_option "$@" ; return $? ; }
@@ -162,6 +191,50 @@ ask_option ()
}
+# ask the user a password. return is stored in $PASSWORD or $<TYPE>_PASSWORD
+# $1 type (optional. eg 'svn', 'ssh').
+ask_password ()
+{
+ [ "$var_UI_TYPE" = dia ] && { _dia_ask_password "$@" ; return $? ; }
+ [ "$var_UI_TYPE" = cli ] && { _cli_ask_password "$@" ; return $? ; }
+}
+
+
+# ask for a string.
+# $1 question
+# $2 default (optional)
+# $3 exitcode to use when string is empty and there was no default, or default was ignored (1 default)
+# echo's the string the user gave.
+# returns 1 if the user cancelled, 0 otherwise
+ask_string ()
+{
+ [ -z "$1" ] && die_error "ask_string needs a question!"
+ [ "$var_UI_TYPE" = dia ] && { _dia_ask_string "$1" "$2" "$3"; return $? ; }
+ [ "$var_UI_TYPE" = cli ] && { _cli_ask_string "$1" "$2" "$3"; return $? ; }
+}
+
+
+ask_timezone () # TODO: how to do this in dia?
+{
+ ANSWER_TIMEZONE=`tzselect`
+}
+
+
+# ask a yes/no question.
+# $1 question
+# $2 default answer yes/no (optional)
+# returns 0 if response is yes/y (case insensitive). 1 otherwise
+ask_yesno ()
+{
+ [ -z "$1" ] && die_error "ask_yesno needs a question!"
+ [ "$var_UI_TYPE" = dia ] && { _dia_ask_yesno "$@" ; return $? ; }
+ [ "$var_UI_TYPE" = cli ] && { _cli_ask_yesno "$@" ; return $? ; }
+}
+
+
+
+
+
# follow the progress of something by showing it's log, updating real-time
# $1 title
# $2 logfile
@@ -174,15 +247,6 @@ follow_progress ()
}
-# taken from setup
-printk()
-{
- case $1 in
- "on") echo 4 >/proc/sys/kernel/printk ;;
- "off") echo 0 >/proc/sys/kernel/printk ;;
- esac
-}
-
@@ -202,16 +266,70 @@ _dia_DIALOG()
}
+_dia_ask_checklist ()
+{
+ str=$1
+ shift
+ list=
+ while [ -n "$1" ]
+ do
+ [ -z "$2" ] && die_error "no ON/OFF switch given for element $1"
+ [ "$2" = ON ] && newlist="$1 ^ ON"
+ [ "$2" = OFF ] && newlist="$1 - OFF"
+ shift 2
+ done
+ _dia_DIALOG --checklist "$str" $list 2>$ANSWER
+ ret=$?
+ ANSWER_CHECKLIST=`cat $ANSWER`
+ debug "_dia_ask_checklist: user checked ON: $ANSWER_CHECKLIST"
+ return $ret
+}
+
+
+_dia_ask_number ()
+{
+ #TODO: i'm not entirely sure this works perfectly. what if user doesnt give anything or wants to abort?
+ while true
+ do
+ str="$1"
+ [ -n "$2" ] && str2="min $2"
+ [ -n "$3" ] && str2="$str2 max $3"
+ [ -n "$str2" ] && str="$str ( $str2 )"
+ _dia_DIALOG --inputbox "$str" 8 65 "$4" 2>$ANSWER
+ ret=$?
+ ANSWER_NUMBER=`cat $ANSWER`
+ if [[ $ANSWER_NUMBER = *[^0-9]* ]] #TODO: handle exit state
+ then
+ show_warning "$ANSWER_NUMBER is not a number! try again."
+ else
+ if [ -n "$3" -a $ANSWER_NUMBER -gt $3 ]
+ then
+ show_warning "$ANSWER_NUMBER is bigger then the maximum,$3! try again."
+ elif [ -n "$2" -a $ANSWER_NUMBER -lt $2 ]
+ then
+ show_warning "$ANSWER_NUMBER is smaller then the minimum,$2! try again."
+ else
+ break
+ fi
+ fi
+ done
+ echo "$ANSWER_NUMBER"
+ debug "_dia_ask_number: user entered: $ANSWER_NUMBER"
+ [ -z "$ANSWER_NUMBER" ] && return 1
+ return $?
+}
+
+
_dia_ask_option ()
{
DEFAULT=""
[ "$1" != 'no' ] && DEFAULT="--default-item $1"
[ -z "$2" ] && die_error "ask_option \$2 must be the title"
- [ -z "$6" ] && die_error "ask_option makes only sense if you specify at least 2 things (with tag and name)"
+ [ -z "$6" ] && debug "_dia_ask_option args: $@" && die_error "ask_option makes only sense if you specify at least 2 things (with tag and name)"
DIA_MENU_TITLE=$2
shift 2
- _dia_DIALOG $DEFAULT --colors --title " $DIA_MENU_TITLE " --menu "$DIA_MENU_TEXT" 16 55 8 "$@" 2>$ANSWER
+ _dia_DIALOG $DEFAULT --colors --title " $DIA_MENU_TITLE " --menu "$DIA_MENU_TEXT" 16 55 8 "$@" 2>$ANSWER #TODO: size not good! dynamically adapt?
ret=$?
ANSWER_OPTION=`cat $ANSWER`
echo $ANSWER_OPTION
@@ -220,13 +338,113 @@ _dia_ask_option ()
}
+_dia_ask_password ()
+{
+ if [ -n "$1" ]
+ then
+ type_l=`tr '[:upper:]' '[:lower:]' <<< $1`
+ type_u=`tr '[:lower:]' '[:upper:]' <<< $1`
+ else
+ type_l=
+ type_u=
+ fi
+
+ _dia_DIALOG --passwordbox "Enter your $type_l password" 8 65 "$2" 2>$ANSWER
+ ret=$?
+ [ -n "$type_u" ] && read ${type_u}_PASSWORD < $ANSWER
+ [ -z "$type_u" ] && read PASSWORD < $ANSWER
+ cat $ANSWER
+ debug "_dia_ask_password: user entered <<hidden>>"
+ return $ret
+}
+
+
+_dia_ask_string ()
+{
+ exitcode=${3:-1}
+ _dia_DIALOG --inputbox "$1" 8 65 "$2" 2>$ANSWER
+ ret=$?
+ ANSWER_STRING=`cat $ANSWER`
+ echo $ANSWER_STRING
+ debug "_dia_ask_string: user entered $ANSWER_STRING"
+ [ -z "$ANSWER_STRING" ] && return $exitcode
+ return $ret
+}
+
+
+_dia_ask_yesno ()
+{
+ height=$((`echo -e "$1" | wc -l` +7))
+ str=$1
+ #TODO: i think dialog doesnt support a default value for yes/no, so we need this workaround:
+ [ -n "$2" ] && str="$str (default: $2)"
+ dialog --yesno "$str" $height 55 # returns 0 for yes, 1 for no
+ ret=$?
+ [ $ret -eq 0 ] && debug "dia_ask_yesno: User picked YES"
+ [ $ret -gt 0 ] && debug "dia_ask_yesno: User picked NO"
+ return $ret
+}
+
+
+_dia_follow_progress ()
+{
+ title=$1
+ logfile=$2
+ _dia_DIALOG --title "$1" --no-kill --tailboxbg "$2" 18 70 2>$ANSWER
+}
+
+
+
+
+_cli_ask_checklist ()
+{
+ str=$1
+ shift
+ output=
+ while [ -n "$1" ]
+ do
+ [ -z "$2" ] && die_error "no ON/OFF switch given for element $1"
+ [ "$2" = ON ] && ask_yesno "Enable $1 ?" yes && output="$output $1"
+ [ "$2" = OFF ] && ask_yesno "Enable $1 ?" no && output="$output $1"
+ done
+ ANSWER_CHECKLIST=$output
+ return 0
+}
+
+
+_cli_ask_number ()
+{
+ #TODO: i'm not entirely sure this works perfectly. what if user doesnt give anything or wants to abort?
+ while true
+ do
+ str="$1"
+ [ -n "$2" ] && str2="min $2"
+ [ -n "$3" ] && str2="$str2 max $3"
+ [ -n "$str2" ] && str="$str ( $str2 )"
+ echo "$str"
+ read ANSWER_NUMBER
+ if [[ $ANSWER_NUMBER = *[^0-9]* ]]
+ then
+ show_warning "$ANSWER_NUMBER is not a number! try again."
+ else
+ break
+ fi
+ done
+ echo "$ANSWER_NUMBER"
+ debug "cli_ask_number: user entered: $ANSWER_NUMBER"
+ [ -z "$ANSWER_NUMBER" ] && return 1
+ return 0
+}
+
+
_cli_ask_option ()
{
#TODO: strip out color codes
+ #TODO: if user entered incorrect choice, ask him again
DEFAULT=""
[ "$1" != 'no' ] && DEFAULT=$1
[ -z "$2" ] && die_error "ask_option \$2 must be the title"
- [ -z "$6" ] && die_error "ask_option makes only sense if you specify at least 2 things (with tag and name)"
+ [ -z "$6" ] && debug "_cli_ask_option args: $@" && die_error "ask_option makes only sense if you specify at least 2 things (with tag and name)"
CLI_MENU_TITLE=$2
shift 2
@@ -237,44 +455,15 @@ _cli_ask_option ()
echo "$1 ] $2"
shift 2
done
+ echo "CANCEL ] CANCEL"
[ -n "$DEFAULT" ] && echo -n " > [ $DEFAULT ] "
[ -z "$DEFAULT" ] && echo -n " > "
read ANSWER_OPTION
[ -z "$ANSWER_OPTION" -a -n "$DEFAULT" ] && ANSWER_OPTION="$DEFAULT"
debug "cli_ask_option: User choose $ANSWER_OPTION"
echo "$ANSWER_OPTION"
-}
-
-
-
-# TODO: pass disks as argument to decouple backend logic
-# Get a list of available disks for use in the "Available disks" dialogs. This
-# will print the disks as follows, getting size info from hdparm:
-# /dev/sda: 640133 MBytes (640 GB)
-# /dev/sdb: 640135 MBytes (640 GB)
-_getavaildisks()
-{
- # NOTE: to test as non-root, stick in a 'sudo' before the hdparm call
- for i in $(finddisks); do echo -n "$i: "; hdparm -I $i | grep -F '1000*1000' | sed "s/.*1000:[ \t]*\(.*\)/\1/"; echo "\n"; done
-}
-
-
-_dia_follow_progress ()
-{
- title=$1
- logfile=$2
- _dia_DIALOG --title "$1" --no-kill --tailboxbg "$2" 18 70 2>$ANSWER
-}
-
-
-_dia_ask_yesno ()
-{
- height=$((`echo -e "$1" | wc -l` +7))
- dialog --yesno "$1" $height 55 # returns 0 for yes, 1 for no
- ret=$?
- [ $ret -eq 0 ] && debug "dia_ask_yesno: User picked YES"
- [ $ret -gt 0 ] && debug "dia_ask_yesno: User picked NO"
- return $ret
+ [ "$ANSWER_OPTION" = CANCEL ] && return 1
+ return 0
}
@@ -297,12 +486,39 @@ _cli_ask_password ()
echo
}
+
+# $3 -z string behavior: always take default if applicable, but if no default then $3 is the returncode (1 is default)
+_cli_ask_string ()
+{
+ exitcode=${3:-1}
+ echo "$1: "
+ [ -n "$2" ] && echo "(Press enter for default. Default: $2)"
+ echo -n ">"
+ read ANSWER_STRING
+ echo "$ANSWER_STRING"
+ debug "cli_ask_string: User entered: $ANSWER_STRING"
+ if [ -z "$ANSWER_STRING" ]
+ then
+ if [ -n "$2" ]
+ then
+ ANSWER_STRING=$2
+ else
+ return $exitcode
+ fi
+ fi
+ return 0
+}
+
+
_cli_ask_yesno ()
{
- echo -n "$1 (y/n): "
+ [ -z "$2" ] && echo -n "$1 (y/n): "
+ [ "$2" = yes ] && echo -n "$1 (Y/n): "
+ [ "$2" = no ] && echo -n "$1 (y/N): "
+
read answer
answer=`tr '[:upper:]' '[:lower:]' <<< $answer`
- if [ "$answer" = y -o "$answer" = yes ]
+ if [ "$answer" = y -o "$answer" = yes ] || [ -z "$answer" -a "$2" = yes ]
then
debug "cli_ask_yesno: User picked YES"
return 0
@@ -313,42 +529,6 @@ _cli_ask_yesno ()
}
-_cli_ask_string ()
-{
- echo -n "$@: "
- read answ
- echo "$answ"
- debug "cli_ask_string: User entered: $answ"
- [ -z "$answ" ] && return 1
- return 0
-}
-
-
-_cli_ask_number ()
-{
- #TODO: i'm not entirely sure this works perfectly. what if user doesnt give anything or wants to abort?
- while true
- do
- str="$1"
- [ -n "$2" ] && str2="min $2"
- [ -n "$3" ] && str2="$str2 max $3"
- [ -n "$str2" ] && str="$str ( $str2 )"
- echo "$str"
- read answ
- if [[ $answ = *[^0-9]* ]]
- then
- show_warning "$answ is not a number! try again."
- else
- break
- fi
- done
- echo "$answ"
- debug "cli_ask_number: user entered: $answ"
- [ -z "$answ" ] && return 1
- return 0
-}
-
-
_cli_follow_progress ()
{
title=$1
@@ -357,4 +537,3 @@ _cli_follow_progress ()
tail -f $2
#TODO: don't block anymore when it's done
}
-
diff --git a/src/core/procedures/base b/src/core/procedures/base
index e18298d..24131dd 100644
--- a/src/core/procedures/base
+++ b/src/core/procedures/base
@@ -72,18 +72,7 @@ worker_runtime_packages ()
worker_set_clock ()
{
- HARDWARECLOCK=utc
- TIMEZONE=`tzselect`
- HWCLOCK_PARAMS=" --utc"
- if [ "$TIMEZONE" != "" -a -e "/usr/share/zoneinfo/$TIMEZONE" ]
- then
- cp "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
- fi
-
- ask_string "Enter date [MMDDhhmmYYYY.ss]" # Thanks Ryan Sims for this one
- date $answ || show_warning "Date/time setting failed" "Something went wrong when doing date $answ"
-
- /sbin/hwclock --hctosys $HWCLOCK_PARAMS --noadjfile
+ interactive_set_clock
}
diff --git a/src/core/procedures/interactive b/src/core/procedures/interactive
index 1b23a45..9739cd3 100644
--- a/src/core/procedures/interactive
+++ b/src/core/procedures/interactive
@@ -1,5 +1,5 @@
#!/bin/sh
-depend_procedure core base # esp for auto_{network,locale,fstab} and intro workers
+depend_procedure core base # esp for auto_{network,locale,fstab}, intro and set_clock workers
# This is a port of the original /arch/setup script. It doesn't use aif phases but uses it's own menu-based flow (phase) control
@@ -142,7 +142,7 @@ worker_prepare_disks()
ask_option $default "Prepare Hard Drive" \
"1" "Auto-Prepare (erases the ENTIRE hard drive and sets up partitions and filesystems)" \
"2" "Partition Hard Drives" \
- "3" "Set Filesystem Mountpoints" \
+ "3" "Configure block devices, filesystems and mountpoints" \
"4" "Return to Main Menu"
case $ANSWER_OPTION in
@@ -160,7 +160,7 @@ worker_prepare_disks()
if [ "$DISK_CONFIG_TYPE" = "auto" ]; then
notify "You have already prepared your filesystems with Auto-prepare" #TODO: allow user to do this anyway. he can change his mind.
else
- interactive_mountpoints && ret=0 && NEXTITEM=4 && DISK_CONFIG_TYPE=manual
+ interactive_filesystems && ret=0 && NEXTITEM=4 && DISK_CONFIG_TYPE=manual
fi
;;
*)
@@ -171,16 +171,6 @@ worker_prepare_disks()
}
-# set_clock()
-# prompts user to set hardware clock and timezone
-#
-# params: none
-worker_set_clock()
-{
- interactive_set_clock
-}
-
-
worker_select_source ()
{
#TODO: how to handle user going here again? discard previous settings, warn him that he already done it?