
. disk_int.sh

readonly HELP_DISK="disk.hlp"
readonly HELP_PART="part.hlp"

readonly RSTR_TAB_PREFIX="RSTR"		# prefix for partition table variables


disk_setup()
{
	local disks="$INV_DISKS"
	local old_PS3="$PS3"
	local item=""
	local -i done=0

	PS3="[Enter number] "
	while test $done -eq 0; do
		mhdr "DISK LAYOUT SETUP"

		disks="$INV_DISKS"	# refresh available disks

		select item in "Shell" "Help" "Back" "Define Device" \
				"List All" $disks; do
			case "$item" in
			"Shell")         invoke_shell ;;
			"Help")          show_help "$HELP_DISK" ;;
			"Back")          done=1 ;;
			"Define Device") disk_define ;;
			"List All")      disk_list "$disks" ;;
			/dev/*)          part_disk "$item" ;;
			esac
			break
		done
	done

	PS3=$old_PS3
}

disk_define()
{
	local devpath=""
	local dev=""
	local path=""
	local size=""
	local model=""

	devpath=`input_field "Enter device path" validate_pathname` || return
	size=`input_field "Enter capacity" validate_disk_size` || return
	model=`input_field "Enter model"` || return

	clear_partition_table "$devpath"

	dev=${devpath##*/}
	path=${devpath%/*}
	eval ${PART_TAB_PREFIX}_${dev}_path=\"$path\"
	eval ${PART_TAB_PREFIX}_${dev}_size=\"$size\"
	eval ${PART_TAB_PREFIX}_${dev}_free=\"$size\"
	eval ${PART_TAB_PREFIX}_${dev}_model=\"$model\"

	INV_DISKS=`sort_list "$INV_DISKS $devpath"`
}

disk_list()
{
	local disks="$1"
	local disk=""

	ihdr "PARTITION TABLE OVERVIEW"

	for disk in $disks; do
		part_list "$disk"
	done
}

part_disk()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local path=${devpath%/*}
	local old_PS3="$PS3"
	local item=""
	local -i done=0

	part_restore "$devpath"
	disk_inquiry "$devpath"

	PS3="[Enter number] "
	while test $done -eq 0; do
		ihdr "PARTITION DISK"
		msg  "Device: $devpath\n"

		select item in "Shell" "Help" "Back" "Save" "List" "Probe" \
				"Add" "Set Type" "Set Mountpoint" "Delete" \
				"Delete All"; do
			case "$item" in
			"Shell")          invoke_shell ;;
			"Help")           show_help "$HELP_PART" ;;
			"Back")           part_back "$devpath"; done=1 ;;
			"Save")           part_save "$devpath"; done=1 ;;
			"List")           part_list "$devpath" ;;
			"Probe")          part_probe "$devpath" ;;
			"Add")            part_add "$devpath" ;;
			"Set Type")       part_type "$devpath" ;;
			"Set Mountpoint") part_mountpoint "$devpath" ;;
			"Delete")         part_delete "$devpath" ;;
			"Delete All")     part_delete_all "$devpath" ;;
			esac
			break
		done
	done

	PS3=$old_PS3
}

part_restore()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local part=""
	local parts=""
	local tmp=""		# copy variable

	clear_restore_table "$dev"

	eval tmp=\${${PART_TAB_PREFIX}_${dev}_path}
	eval ${RSTR_TAB_PREFIX}_${dev}_path=\"$tmp\"
	eval tmp=\${${PART_TAB_PREFIX}_${dev}_size}
	eval ${RSTR_TAB_PREFIX}_${dev}_size=\"$tmp\"
	eval tmp=\${${PART_TAB_PREFIX}_${dev}_free}
	eval ${RSTR_TAB_PREFIX}_${dev}_free=\"$tmp\"
	eval tmp=\${${PART_TAB_PREFIX}_${dev}_model}
	eval ${RSTR_TAB_PREFIX}_${dev}_model=\"$tmp\"

	eval parts=\${${PART_TAB_PREFIX}_${dev}}
	if test "${parts:+set}" = "set"; then
		eval ${RSTR_TAB_PREFIX}_${dev}=\"$parts\"
		for part in $parts; do
			eval tmp=\${${PART_TAB_PREFIX}_${dev}_${part}_size}
			eval ${RSTR_TAB_PREFIX}_${dev}_${part}_size=\"$tmp\"

			eval tmp=\${${PART_TAB_PREFIX}_${dev}_${part}_type}
			eval ${RSTR_TAB_PREFIX}_${dev}_${part}_type=\"$tmp\"

			eval tmp=\${${PART_TAB_PREFIX}_${dev}_${part}_mnt}
			eval ${RSTR_TAB_PREFIX}_${dev}_${part}_mnt=\"$tmp\"
		done
	fi
}

part_back()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local parts=""
	local part=""
	local tmp=""

	eval tmp=\${${RSTR_TAB_PREFIX}_${dev}_path}
	eval ${PART_TAB_PREFIX}_${dev}_path=\"$tmp\"
	eval tmp=\${${RSTR_TAB_PREFIX}_${dev}_size}
	eval ${PART_TAB_PREFIX}_${dev}_size=\"$tmp\"
	eval tmp=\${${RSTR_TAB_PREFIX}_${dev}_free}
	eval ${PART_TAB_PREFIX}_${dev}_free=\"$tmp\"
	eval tmp=\${${RSTR_TAB_PREFIX}_${dev}_model}
	eval ${PART_TAB_PREFIX}_${dev}_model=\"$tmp\"

	eval parts=\${${RSTR_TAB_PREFIX}_${dev}}
	if test "${parts:+set}" = "set"; then
		eval ${PART_TAB_PREFIX}_${dev}=\"$parts\"
		for part in $parts; do
			eval tmp=\${${RSTR_TAB_PREFIX}_${dev}_${part}_size}
			eval ${PART_TAB_PREFIX}_${dev}_${part}_size=\"$tmp\"

			eval tmp=\${${RSTR_TAB_PREFIX}_${dev}_${part}_type}
			eval ${PART_TAB_PREFIX}_${dev}_${part}_type=\"$tmp\"

			eval tmp=\${${RSTR_TAB_PREFIX}_${dev}_${part}_mnt}
			eval ${PART_TAB_PREFIX}_${dev}_${part}_mnt=\"$tmp\"
		done
	else
		clear_partition_table "$devpath"
	fi
}

part_save()
{
	local devpath=`trim "$1"`

}

part_list()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local parts=""
	local part=""
	local size=""
	local type=""
	local mnt=""
	local free=""
	local -i idx=0

	free=`get_free_disk_space "$devpath"`
	eval ${PART_TAB_PREFIX}_${dev}_free=\"$free\"

	msg "Partition table of device: $devpath\n"
	msg "Free: ${free:-<unknown>}\n"
	
	eval parts=\${${PART_TAB_PREFIX}_${dev}}
	if test -n "$parts"; then
		msg "PART        CAPACITY  TYPE  MOUNTPOINT"
		msg "====  ==============  ====  =========="
		for part in $parts; do
			eval size=\${${PART_TAB_PREFIX}_${dev}_${part}_size}
			eval type=\${${PART_TAB_PREFIX}_${dev}_${part}_type}
			eval  mnt=\${${PART_TAB_PREFIX}_${dev}_${part}_mnt}

			printf "%3s   %14s  0x%-2x  %s\n" "$part" "$size" "$type" "$mnt"
		done
		msg "====  ==============  ====  ==========\n"
	else
		msg "There are no partitions defined for this device.\n"
	fi
}

part_probe()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local -i ret=1

	msg "WARNING: Probing the device will erase the current partition configuration."
	confirm || return

	clear_partition_table "$dev"

	msg "Checking for existing partition table..."

	load_partition_config "$devpath"
	ret=$?
	if test $ret -eq 0; then
		msg "Found usable partition table on $devpath"
	elif test $ret -eq 1; then
		msg "Found partition table on $devpath"
		msg "WARNING: partition table may be incomplete or contain errors"
	else
		msg "No usable partition table on $devpath"
	fi

	disk_inquiry "$devpath"
}

part_add()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local model=`get_disk_id "$devpath"`
	local total=""
	local free=""
	local parts=""
	local part=""
	local size=""
	local type=""
	local mnt=""
	local -i idx=0

	total=`get_disk_space "$devpath"`
	free=`get_free_disk_space "$devpath"`

	ihdr "ADD PARTITION"
	msg  "Device   : $devpath"
	msg  "Model    : ${model:-<unknown>}"
	msg  "Capacity : ${total:-<unknown>}"
	msg  "Free     : ${free:-<unknown>}\n"

	part=`input_field "Enter partition" validate_partition` || return
	size=`input_field "Enter capacity" validate_disk_size`  || return
	type=`input_field "Enter type" validate_partition_type` || return
	 mnt=`input_field "Enter mountpoint"`                   || return

	if test "$part" != "$PART_WHOLEDISK"; then
		update_free_space "$devpath" "$size" "1"
	else
		true
	fi
	if test $? -eq 0; then
		eval parts=\${${PART_TAB_PREFIX}_${dev}}
		parts=`sort_list "$parts $part"`

		eval ${PART_TAB_PREFIX}_${dev}=\"$parts\"
		eval ${PART_TAB_PREFIX}_${dev}_${part}_size=\"$size\"
		eval ${PART_TAB_PREFIX}_${dev}_${part}_type=\"$type\"
		eval ${PART_TAB_PREFIX}_${dev}_${part}_mnt=\"$mnt\"
	else
		msg "Invalid partition size: $size"
	fi
}

part_type()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local model=`get_disk_id "$devpath"`
	local part=""
	local type=""

	ihdr "SET PARTITION TYPE"
	msg  "Device : $devpath"
	msg  "Model  : ${model:-<unknown>}"
	msg  ""

	part=`input_field "Enter partition" validate_partition` || return

	is_partition_defined "$devpath" "$part"
	if test $? -eq 0; then
		type=`input_field "Enter type" validate_partition_type`
		if test $? -eq 0; then
			eval ${PART_TAB_PREFIX}_${dev}_${part}_type=\"$type\"
		fi
	else
		msg "Cannot set partition type; partition does not exist."
	fi
}

part_mountpoint()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local model=`get_disk_id "$devpath"`
	local part=""
	local mnt=""

	ihdr "SET MOUNTPOINT"
	msg  "Device : $devpath"
	msg  "Model  : ${model:-<unknown>}"
	msg  ""

	part=`input_field "Enter partition" validate_partition` || return

	is_partition_defined "$devpath" "$part"
	if test $? -eq 0; then
		mnt=`input_field "Enter mountpoint"`
		if test $? -eq 0; then
			eval ${PART_TAB_PREFIX}_${dev}_${part}_mnt=\"$mnt\"
		fi
	else
		msg "Cannot set mountpoint; partition does not exist."
	fi
}

part_delete()
{
	local devpath=`trim "$1"`
	local model=""
	local part=""

	eval model=\${${PART_TAB_PREFIX}_${dev}_model}

	ihdr "DELETE PARTITION"
	msg  "Device : $devpath"
	msg  "Model  : ${model:-<unknown>}"
	msg  ""

	part=`input_field "Enter partition" validate_partition`
	if test $? -eq 0; then
		clear_part_defs "$devpath" "$part"
	fi
}

part_delete_all()
{
	clear_partition_table "$1"
}

clear_part_defs()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local part=`trim "$2"`
	local parts=""
	local size=""
	local vars=""
	local var=""

	[ -n "$devpath" ] || return 1
	validate_partition "$part" || return 1

	if test "$part" != "$PART_WHOLEDISK"; then
		eval size=\${${PART_TAB_PREFIX}_${dev}_${part}_size}
		update_free_space "$devpath" "$size" "0"
	fi

	eval vars=\${\!${PART_TAB_PREFIX}_${dev}_${part}\*}
	for var in $vars; do
		eval unset "$var"
	done

	eval parts=\${${PART_TAB_PREFIX}_${dev}}
	parts=${parts/$part/}
	eval ${PART_TAB_PREFIX}_${dev}=\"$parts\"

	return 0
}

clear_partition_table()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local parts=""
	local part=""

	[ -n "$dev" ] || return 2

	parts=`eval echo {$PART_FIRST..$PART_LAST}`
	for part in $parts; do
		eval unset -v \${\!${PART_TAB_PREFIX}_${dev}_${part}_*}
	done
	eval unset -v ${PART_TAB_PREFIX}_${dev}
}

clear_restore_table()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local parts=""
	local part=""

	[ -n "$dev" ] || return 2

	parts=`eval echo {$PART_FIRST..$PART_LAST}`
	for part in $parts; do
		eval unset -v \${\!${RSTR_TAB_PREFIX}_${dev}_${part}_*}
	done
	eval unset -v ${RSTR_TAB_PREFIX}_${dev}
}

update_free_space()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local size=`trim "$2"`
	local rel=`trim "$3"`
	local -i total=0	# in MB
	local -i free=0		# in MB
	local -i ret=1

	[ -n "$devpath" ] || return 2
	[ -n "$dev"     ] || return 2
	[ $rel -eq 0 -o $rel -eq 1 ] || return 2

	total=`get_disk_space "$devpath" | cut -d' ' -f1`
	free=`get_free_disk_space "$devpath" | cut -d' ' -f1`

	size=`convert_disk_size "$size" "M"`
	size=`echo $size | cut -d' ' -f1 2>/dev/null`	# remove unit
	if test $rel -eq 0; then
		if test $(($free + $size)) -le $total; then
			free=$(($free + $size))
			ret=0
		fi
	else
		if test $free -ge $size; then
			free=$(($free - $size))
			ret=0
		fi
	fi
	eval ${PART_TAB_PREFIX}_${dev}_free=\"$free M\"   # store in MB

	return $ret
}

disk_inquiry()
{
	local devpath=`trim "$1"`
	local dev=${devpath##*/}
	local size=""
	local model=""

	[ -n "$devpath" ] || return
	[ -n "$dev"     ] || return

	size=`get_disk_space "$devpath"`
	model=`get_disk_id "$devpath"`
	eval ${PART_TAB_PREFIX}_${dev}_path=\"$path\"
	eval ${PART_TAB_PREFIX}_${dev}_size=\"$size\"
	eval ${PART_TAB_PREFIX}_${dev}_model=\"$model\"
}
