#!/bin/sh -e

# mkbootdisk
#
# Written by Erik Troan <ewt@redhat.com>
# Modified by Axalon <axalon@mandrakesoft.com>
# Rewritten by Dmitry V. Levin <ldf@altlinux.org>

PROG="${0##*/}"
VERSION=1.2.9.4-alt
CATCHED=

umask 077

Exit()
{
	local rc
	[ -n "$1" ] && rc="$1" || rc=$?
	CATCHED=1
	exit $rc
}

Fatal()
{
	echo -E "$*" >&2
	Exit 1
}

verbose=
Verbose()
{
	[ -z "$verbose" ] || echo -E "$*"
}

debug=
Debug()
{
	[ -z "$debug" ] || echo -E "$*"
}

WORKDIR=
MOUNTDIR=
exit_handler()
{
	local rc=$?
	trap '' EXIT
	[ -n "$CATCHED" -o $rc -eq 0 ] ||
		echo "$PROG: something odd happened, exiting..."
	[ -n "$MOUNTDIR" ] && /bin/umount "$MOUNTDIR" &>/dev/null ||:
	[ -n "$WORKDIR" ] && /bin/rm -rf "$WORKDIR"
	exit $rc
}

signal_handler()
{
	echo 'Interrupted!'
	Exit 1
}

trap exit_handler EXIT
trap signal_handler SIGHUP SIGPIPE SIGINT SIGTERM SIGQUIT

pause=yes
kernel=
verbose=
mkinitrdargs=
lba=lba32
compact=
appendargs=

device=/dev/floppy/0
[ -e "$device" ] || device=/dev/fd0
export loop=/dev/loop/7
[ -e "$device" ] || device=/dev/loop7

Usage()
{
	/bin/cat >&2 <<EOF
$PROG - create a standalone boot floppy disk for the running system.

Usage: $PROG [options] <kernel>

Valid options are:
--noprompt              do not prompt before writing data on floppy;
--nolba32               do not pass 'lba32' option to lilo;
--compact               pass 'compact' option to lilo;
--mkinitrdargs <args>   pass specified arguments to mkinitrd;
--appendargs <args>     pass specified arguments to lilo 'append=' option;
--device <devicefile>   use specified device as floppy device;
--debug, -d             print debug information;
--verbose, -v           give detailed information about we are doing;
--version               print program version and exit.

Example: $PROG `uname -r`
EOF
	Exit $1
}

TEMP=`/bin/getopt -n "$PROG" -o hdv -l help,version,debug,verbose,noprompt,compact,device:,mkinitrdargs:,appendargs: -- "$@"` || Usage 1
eval set -- "$TEMP"

while :; do
	case "$1" in
		--device)
			shift
			device=$1
			shift
			;;
		--mkinitrdargs)
			shift
			mkinitrdargs=$1
			shift
			;;
		--appendargs)
			shift
			appendargs=$1
			shift
			;;
		--noprompt)
			pause=
			shift
			;;
		--nolba32)
			lba=
			shift
			;;
		--compact)
			compact="compact"
			shift
			;;
		-v|--verbose)
			verbose=-v
			shift
			;;
		-d|--debug)
			debug=-d
			verbose=-v
			shift
			;;
		--version)
			echo "$PROG: version $VERSION"
			exit 0
			;;
		-h|--help)
			Usage 0
			;;
		--)
			shift
			break
			;;
		*)
			Fatal "$PROG: unrecognized option: $1"
			;;
	esac
done

kernel="$*"
[ -n "$kernel" ] || Usage 1

KERNEL_IMAGE="/boot/vmlinuz-$kernel"

MODULES_DIR="/lib/modules/$kernel"

[ -d "$MODULES_DIR" ] || Fatal "$MODULES_DIR is not a directory."

[ -f "$KERNEL_IMAGE" ] || Fatal "$KERNEL_IMAGE does not exist."

rootdev=`/bin/awk '$2 == "/" && $1 ~ /^[^#]/ {print $4 ~ /loop/ ? ENVIRON["loop"] : $1}' /etc/fstab`

if [ -z "${rootdev##LABEL=*}" ]; then
	rootlabel="${rootdev#LABEL=*}"
	rootdev=

	# whee, now we have to look through every partition looking for
	# the thing called $rootlabel, which could be raid. Ick.

	list=$(/bin/tail +3 /proc/partitions |/bin/awk '{print $4}')
	for dev in `echo "$list" |/bin/grep '^md'` `echo "$list" |/bin/grep -v '^md'`; do
		if label=$(/sbin/tune2fs -l "/dev/$dev" 2>/dev/null); then
			label=`echo "$label" |/bin/grep '^Filesystem volume name:' |
				/bin/awk '{print $4}'`
			if [ "$label" = "$rootlabel" ]; then
				rootdev="/dev/$dev"
				break
			fi
		fi
	done
fi

[ -n "$rootdev" ] || Fatal 'Cannot find root partition in /etc/fstab.'

WORKDIR="$(/bin/mktemp -td mkbootdisk.XXXXXXXXXX)" || Fatal "Failed to create working directory."

INITRD_IMAGE="$WORKDIR/initrd.img"
/sbin/mkinitrd $verbose $debug $mkinitrdargs --ifneeded --nobootsplash "$INITRD_IMAGE" "$kernel" && 
	Verbose 'Created initial ramdisk image.' ||
	Fatal 'Failed to create initial ramdisk image.'

if [ -n "$pause" ]; then
	echo "Insert a disk in $device. Any information on the disk will be lost."
	echo -n "Press <Enter> to continue or ^C to abort: "
	read aline
fi

Verbose -n "Formatting $device: "
/sbin/mke2fs -q -m0 -F "$device" ||
	Fatal "Failed to format $device device."
Verbose done.

MOUNTDIR="$WORKDIR/mnt"
/bin/mkdir "$MOUNTDIR" || Fatal "Failed to create mount point."
/bin/mount -t ext2 "$device" "$MOUNTDIR" ||
	Fatal "Failed to mount $device device."

Verbose -n "Installing $KERNEL_IMAGE kernel image: "
/bin/cp -a --parents "$KERNEL_IMAGE" "$MOUNTDIR" ||
	Fatal "Failed to copy $KERNEL_IMAGE kernel image."
Verbose done.

if [ -f "$INITRD_IMAGE" ]; then
	Verbose -n "Installing $INITRD_IMAGE initial ramdisk image: "
	/bin/cp -p "$INITRD_IMAGE" "$MOUNTDIR/boot/initrd.img" ||
		Fatal "Failed to copy $INITRD_IMAGE initial ramdisk image."
	Verbose done.
fi

Verbose -n "Setting up lilo config: "
{
	/bin/cp -a --parents "$device" "$rootdev" "$MOUNTDIR"
	/bin/mkdir -p "$MOUNTDIR/boot"
	/bin/cp -p /boot/boot-text.b "$MOUNTDIR/boot/boot.b"

	/bin/mkdir "$MOUNTDIR"/{etc,tmp}
	LILO="$MOUNTDIR/etc/lilo.conf"
	/bin/cat >"$LILO" <<EOF
$lba
$compact
boot=$device
timeout=100
message=/boot/message
prompt
image=$KERNEL_IMAGE
	label=linux
	root=$rootdev
EOF
	if [ -f "$INITRD_IMAGE" ]; then
		echo "	initrd=/boot/initrd.img" >>"$LILO"
	fi
	if [ -n "$appendargs" ]; then
		echo "	append=\"$appendargs\"" >>"$LILO"
	fi

	/bin/chmod a+r "$LILO"

	/bin/cat >> $MOUNTDIR/boot/message <<EOF

Press <return> (or wait 10 seconds) to boot your ALT Linux system from
$rootdev. You may override the default linux kernel parameters by typing
"linux <params>", followed by <return> if you like.

EOF
} || Fatal "Failed to setup lilo config."
Verbose done.

{
if [ -n "$verbose" ]; then
	echo "Creating boot sector on $device device: "
	/sbin/lilo $verbose -r "$MOUNTDIR"
else
	/sbin/lilo -r "$MOUNTDIR" >/dev/null
fi
} || Fatal "Failed to create boot sector on $device device."

Verbose -n "Unmounting $device device: "
/bin/umount "$MOUNTDIR" &&
	MOUNTDIR= ||
	Fatal "Failed to unmount $device device."
Verbose done.
