#!/bin/sh

ListDrivePartitions() {
    local i
    for i in `cat $1 | sort -g | tr -s '\t' ' ' | grep "$2 " | cut -d' ' -f1` ; do
	basename $i
    done
}
# sort -n bugge => sort -g !!!


ProcessDrive() {
    local currentdrive mountlist stub partitions partno i j errors stub \
partname prevpart drive_size total_size this_size this_type diff dsK res
    currentdrive=$1
    mountlist=$2

    stub=`basename "$currentdrive"`
    res=`dmesg | grep "$stub: "`
    if [ "$res" = "" ] ; then
        LogIt "Drive $currentdrive not found; ignoring." 1
        LogIt "I'll also remove $currentdrive from mountlist." 1
        cat $mountlist | grep -v "$currentdrive[0-9]* " > /tmp/ml.txt
        cp /tmp/ml.txt $mountlist -f
        return 0
    fi
    drive_size=`calc-disk-size $currentdrive`
    LogIt "Drive=$currentdrive (stub=$stub); mountlist=$mountlist; drive_size=$drive_size"
    if [ "$drive_size" -le "0" ] ; then
        LogIt "Are you sure $currentdrive exists?" 1
        return 1
    fi

    errors=0
    total_size=0
    stub=`basename $currentdrive`
    partitions=`ListDrivePartitions $mountlist $currentdrive`
    for partname in $partitions ; do
	i=`echo "$partname" | sed s/[a-z]*//`
        j=`echo "$partname" | sed s/[0-9]// | sed s/[0-9]//`
        prevpart="$j"$(($i-1))
	LogIt "partname=$partname; i=$i; j=$j; prevpart=$prevpart"
        if [ "`cat $mountlist | grep "/dev/$prevpart "`" = "" ] \
&& [ "$i" != "1" ] && [ "$i" != "5" ] ; then
            LogIt "$prevpart is missing! " 1
            errors=$(($errors+1))
        else
            echo -e -n "."
            this_size=`cat $mountlist | grep "/dev/$partname " | cut -d' ' -f4`
	    this_type=`cat $mountlist | grep "/dev/$partname " | cut -d' ' -f3`
	    LogIt "this_size=$this_size; this_type=$this_type"
	    if [ "$this_type" = "vfat" ] && [ "$this_size" -ge "$((8000*1024))" ] && [ "$this_size" -le "$((8200*1024))" ] ; then
		echo "I'm not sure if a VFAT partition of $this_size MB should be 'b' or 'c' type, so I'll add 300MB to it and make sure it has to be 'c'."
		this_size=$(($this_size+300999))
            fi
	    total_size=$(($total_size+$this_size))
        fi
    done
    difference_in_size=$(($total_size-$(($drive_size*1024))))
#    if [ "$total_size" -ne "$(($drive_size*1024))" ] ; then
    if [ "$difference_in_size" -le "-2048" ] || [ "$difference_in_size" -ge "2048" ] ; then
	OfferToResizePartitions $currentdrive $mountlist $(($drive_size*1024)) $total_size
	errors=$(($errors+$?))
    fi
    return $errors
}



OfferToResizePartitions() {
    local currentdrive mountlist drive_size total_size diff \
percentage res message
    currentdrive=$1
    mountlist=$2
    drive_size=$3
    total_size=$4

    LogIt "$currentdrive might be resized. We'll see."
    diff=$(($total_size-$drive_size))
    if [ "$drive_size" -gt "$total_size" ] ; then
	LogIt "$message\nMountlist would leave $((((0-$diff))/1024+1))M unallocated on $currentdrive" 1
	ChooseAndAdjustPartition $mountlist $currentdrive $diff
	res=$?
	if [ "$res" -eq "99" ] ; then
	    LogIt "Warning - space left unallocated. User's choice." 1
	    return 0
	else
	    return $res
	fi
    elif [ "$(($drive_size/1024))" -lt "$(($total_size/1024))" ] ; then
	LogIt "Mountlist would occupy $(($diff/1024))M over $currentdrive's physical size." 1
	ChooseAndAdjustPartition $mountlist $currentdrive $diff
	res=$?
	if [ "$res" -eq "99" ] ; then
	    LogIt "Warning - partition(s) too big!" 1
	fi
	return $res
    else
	LogIt "Wow. Your mountlist is perfect. Way to go!"
	return 0
    fi

}


ChooseAndAdjustPartition() {
    local mountlist currentdrive diff drive_list choice i mountpt curr_size done retval
    mountlist=$1
    currentdrive=$2
    diff=$3
    retval=0

# NB: 'drive_list' means 'list of partitions on a given drive'
    drive_list=`ListDrivePartitions $mountlist $currentdrive`
    done="no"
    echo " "
    while [ "$done" != "yes" ] ; do
	choice="blahblah"
	while [ "`echo " $drive_list " | grep " $choice "`" = "" ] && [ "$choice" != "" ] ; do
	    for i in $drive_list ; do
		mountpt=`cat $mountlist | grep "/dev/$i " | gawk '{ print $2; }'`
		curr_size=$((`cat $mountlist | grep "/dev/$i " | gawk '{ print $4; }'`/1024))
		printf "      %-13s %7s   %s\n" "/dev/$i" "$curr_size"M "mounted at $mountpt"
	    done
	    echo -e -n "\nWhich one will you resize (e.g. 'hda1') or just <enter> to quit -->"
	    if [ "$NUKING" = "yes" ] ; then
		choice=`NukeSaysExpandTheLastOne $currentdrive "$drive_list"`
                done=yes
                break
	    else
		read choice
	    fi
	done
	if [ "$choice" = "" ] ; then
	    if [ "$diff" -gt "0" ] ; then
		echo "I can't let you do that. Your mountlist would still be too big."
	    else
                done=yes
                echo "OK. Some space will be left unallocated, however."
		retval=99
	    fi
	else
	    curr_size=`cat $mountlist | grep "/dev/$choice " | gawk '{print $4;}'`
	    res_size=$(($curr_size-$diff))
	    echo "/dev/$choice is $((curr_size/1024))M; would become $((res_size/1024))M"
	    if [ "$NUKING" != "yes" ] ; then
		echo -n "Is this what you want (y/n) ?"
		read i
	    else
		i="Y"
	    fi
	    if [ "$i" = "y" ] || [ "$i" = "Y" ] ; then
		ChangePartitionSize $mountlist $choice $res_size
		retval=$?
		done="yes"
                if [ "$res_size" -lt "0" ] ; then
                    echo "That's pretty fouled up, yo."
                    echo "Are you restoring to a really small hard drive?"
                    retval=$(($retval+1))
                fi
	    fi
	fi
    done

#    echo "returning $retval"
    return $retval
}


ChangePartitionSize() {
    local mountlist choice res_size currline
    mountlist=$1
    choice=$2
    res_size=$3

    LogIt "$choice is being resized (new size=$3)"
    currline=`cat $mountlist | grep "/dev/$choice "`
    cat $mountlist | grep -v "$currline" > $mountlist.mid
    res=`echo $currline | gawk '{ print $1,$2,$3 }'`
    res="$res $res_size"
    echo $res >> $mountlist.mid
    cp $mountlist $mountlist.pre-CPS -f
    mv $mountlist.mid $mountlist -f
}


NukeSaysExpandTheLastOne() {
    local currentdrive partitionlist numbers last_one
    currentdrive=$1
    partitionlist=$2
    numbers=`echo "$partitionlist" \
| tr '[:alpha:]' ' ' --squeeze-repeats`
    last_one=`echo "$numbers" \
| tr ' ' '\n' --squeeze-repeats \
| sort -g \
| tail -n 1`
    basename "$currentdrive$last_one"
}
# sort -n bugge => sort -g !!!




# ----------- main ---------

PATH=.:$PATH

LogIt "check-mountlist-sanity --- starting"

if [ "$#" -ne "1" ] ; then
    LogIt "check-mountlist-sanity mountlist" 1
    exit 1
fi

if [ ! -f "$1" ] ; then
    LogIt "mountlist '$1' not found" 1
    exit 1
fi

mountlist=$1
drivelist=`cat $mountlist | cut -d' ' -f1 | sed s/[0-9]// | sed s/[0-9]// | sort | uniq`
total_errors=0
if [ "`cat /proc/cmdline | grep "nuke"`" != "" ] ; then
    NUKING=yes
else
    NUKING=no
fi
echo -e -n "Checking mountlist.txt's sanity.."
for currentdrive in $drivelist ; do
    ProcessDrive $currentdrive $mountlist
    res=$?
    total_errors=$(($total_errors+$res))
done
if [ "$total_errors" -ne "0" ] ; then
    LogIt "$total_errors reasons why mountlist isn't sane." 1
    exit 2
else
    LogIt "Mountlist is sane." 1
fi

LogIt "check-mountlist-sanity --- leaving"
exit $total_errors
