#!/bin/bash

verbose()
{
	[ -z "$verbose" ] || echo $@
}

show_help()
{
cat <<'EOF'
   fixmbr - try to restore grub or lilo MBR

   Usage: fixmbr [options] [<device>]

   The <device> option is meaningfull only in --grub case (see).
   If no <device> specified, then fixmbr tries to install grub
   on each non-lilo disk.

   Options:
       --grub                      try to restore grub [this is default];
       --lilo                      try to restore lilo;
       -v, --verbose               be more verbose;
       -h, --help                  show this text and exit.

   Report bugs to http://bugzilla.altlinux.ru/

EOF
exit
}

# List possible target devices
list_disks()
{
	tail -n +3 /proc/partitions |
	while read major minor blocks name; do
		[ -d "/sys/block/$name" ] && echo "$name"
	done
}

# List devices where grub should be placed
list_grub_disks()
{
	for disk in $(list_disks); do
		detectloader.sh "/dev/$disk" |
		grep -q -v lilo && echo "/dev/$disk"
	done
}

# Find root partition with latest (by modification date) grub.cfg
find_grub_system()
{
	ls -ct1 /mnt/system*/boot/grub/grub.cfg 2>/dev/null |
	head -n 1 | sed -s 's|/boot/grub/grub.cfg||'
}

# Find root partition with latest (by modification date) lilo.conf
find_lilo_system()
{
	ls -ct1 /mnt/system*/etc/lilo.conf 2> /dev/null |
	head -n 1 | sed -s 's|/etc/lilo.conf||'
}

# repair_grub <device> <system>
#
# @device: repair grub MBR on that device
# @system: system to chroot to
repair_grub()
{
	local device="$1" system="$2"

	if [ -z "$device" ]; then
		verbose "device is not given"
		return 1
	fi

	if [ -z "$system" ]; then
		verbose "system is not given"
		return 1
	fi

	verbose "installing grub from $system to $device"
	chroot "$system" grub-install --no-floppy "$device"
}

# repair_lilo <system>
#
# @system: system to chroot to
repair_lilo()
{
	local system="$1"

	if [ -z "$system" ]; then
		verbose "system is not given"
		return 1
	fi

	verbose "installing lilo from $system"
	chroot "$system" lilo
}


TEMP=`getopt -n fixmbr -o v,h -l verbose,help,grub,lilo -- "$@"` || show_help
eval set "--" $TEMP

loader=grub # try to repair grub by default

while :; do
	case "$1" in
		--lilo) loader=lilo
			;;
		--grub) loader=grub
			;;
		-v|--verbose) verbose=-v
			;;
		-h|--help) show_help
			;;
		--) shift; break;
			;;
	esac
	shift
done

verbose "Mounting partitions"
verbose `mount-system 2>&1`

ok=
case "$loader" in
lilo)
	# find ``good'' lilo.conf
	if system=$(find_lilo_system) && [ -n "$system" ]; then
		repair_lilo "$system" && ok=1 ||
			verbose "can't install lilo from $system"
	else
		verbose "can't find root partition with lilo.conf"
	fi
	;;
grub)
	# find ``good'' grub.cfg
	if system=$(find_grub_system) && [ -n "$system" ]; then
		# generate list of target grub devices, i.e., devices
		# that don't contain lilo bootloader
		[ -n "$1" ] &&
			target_devices="$1" ||
			target_devices="$(list_grub_disks)"

		# install grub on each such device
		for device in $target_devices; do
			repair_grub "$device" "$system" && ok=1 ||
				verbose "can't install grub on $device from $system"
		done
	else
		verbose "can't find root partition with grub.cfg"
		verbose "maybee you should try \`fixmbr --lilo' instead?"
	fi
	;;
*)
	verbose "unsupported loader $loader"
	;;
esac

if [ -z "$ok" ]; then
	echo "Automatic fixing failed see /mnt/* and try repire manually..."
fi
