#!/bin/bash

#
# Commands in isofs.txt files:
#
# EVERY		from	to		Put this on every disk
# DISK1		from	to		Put this on the 1st disk
# SINGLE	from	to		Put it on any disk
# SPLIT		from	to		You may split it up over many disks
#
# BOOT		boot-options		Add this mkisofs options for 1st disk
#
# If you want to add multiple 'BOOT' lines, use the tag-name 'BOOTx' for
# the 2nd and all further lines.
#
# SCRIPT	script-name	args	Run given script for each image
#
# Intended for image post-processing - like needed for IBM RS/6k boot
# blessing. The first attached argument is the CD number and the second
# the image file.
#

if [ $# -eq 0 ] ; then
	echo
	echo "Usage: $0 [ -size MB ] [ -mkdebug] ISO-Prefix \\"
	echo "       ${0//?/ } Config [ Config [ .. ] ]"
	echo
	echo "E.g.: $0 mycdset install generic"
	echo
	exit 1
fi

# default disk-size is 600 MB
dsize=$(( 600 * 1024 ))

mkdebug=0

while true ; do
	case "$1" in
		-size)
			dsize=$(( $2 * 1024 )) ; shift ; shift ;;
		-mkdebug)
			mkdebug=1 ; shift ;;
		-* | '')
			$0 ; exit 1 ;;
		*)
			isoprefix=$1 ; shift ; break ;;
	esac
done

spacer="    "

echo ; date "+  [%X] Removing old files with same prefix ..."
rm -rf ${isoprefix}_*

date "+  [%X] Reading configs and creating ISO index ..."
index=`mktemp` ; dat=`mktemp`

for cfg ; do
	id="`grep '^export ROCKCFG_ID=' config/$cfg/config | cut -f2 -d\'`"
	if ! cat build/$id/isofs.txt >> $dat
	then rm -f $dat $index ; exit 1 ; fi
done

# function to add a given file $1 to the place $2 on the resulting ISO
#
add() {
	local from="$1" to="$2" done=0
	if [ ! -f "$from" -a ! -d "$from" ] ; then
		echo "No such file or directory: $from"
		rm -f $dat $index ; exit 1
	fi

	size="`du -sk $from | cut -f1`"
	if [ $size -gt $(( $dsize - $disk_0_size )) ] ; then
		echo "Junk $from is too big!"
		rm -f $dat $index ; exit 1
	fi

	for x in $disks ; do
		ds=disk_${x}_size ; dd=disk_${x}_data
		if [ $(( ${!ds} + $size )) -le \
		     $(( $dsize - $disk_0_size )) ] ; then
			eval "$ds=$(( ${!ds} + $size ))"
			eval "$dd='${!dd} $to=$from'"
			done=1 ; break
		fi
	done

	if [ $done = 0 ] ; then
		disk_nr=$(( $disk_nr + 1 ))
		ds=disk_${disk_nr}_size ; eval "$ds=$size"
		dd=disk_${disk_nr}_data ; eval "$dd='$to=$from'"
		disks="$disks $disk_nr"
	fi
}

bootoptions=""
scripts=""
while read tag data ; do
	if [ $tag = BOOT ] ; then
		if [ "$bootoptions" ] ; then
			echo "Multiple boot options found!"
			rm -f $dat $index ; exit 1
		else
			bootoptions="$data"
		fi
	elif [ $tag = SCRIPT ] ; then
		scripts="$scripts $data"
	fi
done < $dat
while read tag data ; do
	[ $tag = BOOTx ] && bootoptions="$bootoptions $data"
done < $dat

echo "$spacer parsing for EVERY disk."

disks="0" ; disk_nr=0 ; disk_0_size=0
disk_0_data="index.txt=${isoprefix}_index.txt"
while read type from to ; do
	if [ $type = EVERY ] ; then
		add $from $to
		if [ $disk_nr -gt 0 ] ; then
			echo "Every-disk data is too big!"
			rm -f $dat $index ; exit 1
		fi
	fi
done < $dat

echo "$spacer parsing for DISK1 disk."

disk_nr=0 ; disks=""
while read type from to ; do
	if [ $type = DISK1 ] ; then
		add $from $to
		if [ $disk_nr -gt 1 ] ; then
			echo "Disk 1 is too big!"
			rm -f $dat $index ; exit 1
		fi
	fi
done < $dat

echo "$spacer parsing for SINGLE disk."

while read type from to ; do
	if [ $type = SINGLE ] ; then
		add $from $to
	fi
done < $dat

echo "$spacer parsing for SPLIT disk."

while read type from to ; do
	if [ $type = SPLIT ] ; then
		find $from -type f -printf '%P\n' | sort > $index
		while read p ; do
			add $from$p $to$p
		done < $index
	fi
done < $dat

echo -n > $index
for x in 0 $disks ; do
	dd=disk_${x}_data
	for y in ${!dd} ; do
		to=${y%=*} ; from=${y#*=}
		if [ -d $from ] ; then
			find $from -printf "disk$x	$to%P\\n" >> $index
		else
			echo "disk$x	$to" >> $index
		fi
	done
done
disk_0_size=$(( $disk_0_size + $( du -sk $index | cut -f1 ) ))

if [ -z "$bootoptions" ] ; then
	echo "WARNING: Disk1 is not bootable - no boot options defined."
fi

xxx() {
	if ! mkisofs "$@" &> $dat ; then
		echo ; echo "mkisofs $*" ; echo
		cat $dat ; rm -f $index $dat ; exit 1
	fi
}

echo
total=0
for x in 0 $disks ; do
	ds=disk_${x}_size
	total=$(( $total + ${!ds} ))

	if [ $x = 0 ] ; then y="Shared"
	else y="`printf 'Disk%2d' $x`" ; fi

	z="$( grep "^disk$x	" $index | wc -l )"

	if [ -z "$bootoptions" -o $x != 1 ] ; then
		printf "%15s $y: %7s kB in %5d files\n" "" ${!ds} $z
	else
		printf "%15s $y: %7s kB in %5d files  (boot)\n" "" ${!ds} $z
	fi
done
printf "%15s Total: %8s kB in %5d files\n" "" $total $( wc -l < $index )
echo

date "+  [%X] Creating ${isoprefix}_index.txt ..."
sort -tk -n -k2 < $index > ${isoprefix}_index.txt

for x in $disks ; do
	dd=disk_${x}_data ; ds=disk_${x}_size
	date "+  [%X] Creating ${isoprefix}_cd$x.iso ..."
	echo "This is disk #$x." > $dat
	xxx -q -r -T -J -l -o ${isoprefix}_cd$x.iso -A "ROCK Linux - Disk $x" \
	    -P 'The ROCK Linux Project - http://www.rocklinux.org' \
	    $bootoptions -graft-points disk$x.txt=$dat $disk_0_data ${!dd}

	bootoptions=""

	if [ "$scripts" ] ; then
		echo "Running post-processing scripts on image ..."
		eval $scripts $x ${isoprefix}_cd$x.iso
	fi

	if [ "$mkdebug" = 1 ] ; then
		cat > ${isoprefix}_loop$x.sh << EOT
#!/bin/sh

if [ "\$1" -a -z "\${1//[0-9]/}" ] ; then
	[ "\$2" ] && umount \$2 > /dev/null 2>&1
	losetup -d /dev/loop/\$1 > /dev/null 2>&1
	losetup /dev/loop/\$1 ${isoprefix}_cd$x.iso
	[ "\$2" ] && mount /dev/loop/\$1 \$2
else
	echo "Usage: \$0 loopback-dev-nr [ mount-point ]"
	exit 1
fi
EOT
		chmod +x ${isoprefix}_loop$x.sh
	fi
done

if [ "$mkdebug" = 1 ] ; then
	vmwarebin="`type -p vmware`"
	if [ "$vmwarebin" ] ; then
		date "+  [%X] Creating ${isoprefix}_vmware.cfg ..."
		cat > ${isoprefix}_vmware.cfg << EOT
#!$vmwarebin
config.version = 6
virtualHW.version = 2
displayName = "${isoprefix}"

# CD-ROM
ide1:0.present = TRUE
ide1:0.fileName = "${isoprefix}_cd1.iso"
ide1:0.deviceType = "cdrom-image"
ide1:0.startConnected = "TRUE"

# Disk
ide0:0.present = "TRUE"
ide0:0.fileName = "${isoprefix}_vmware.vmdk"

# Floppy
floppy0.present = "TRUE"
floppy0.fileType = "device"
floppy0.startConnected = "FALSE"

# Networked through shared IP address
ethernet0.present = TRUE
ethernet0.connectionType = "bridged"

# Virtual Memory
memsize = 128
nvram = ${isoprefix}_vmware.nvram

# Various
log.fileName = ${isoprefix}_vmware.log
tools.remindInstall = "FALSE"
guestOS = linux
EOT
		chmod +x ${isoprefix}_vmware.cfg
		cat << 'EOT' > $index
begin 644 vmware_empty_disk.tar.bz2
M0EIH.3%!62936<Q_V!4``/E_[OX`0$C``WN1S`"2@&8KGX5``"````%``(0`
M!%PP`/@#`````#0:`-`-`8`````:#0!H!H`JA*-!!HU#)@:`A^J,GJ/)@GC[
MI_;>_#.I9(V),D]J8B*R99?]WJCD9V-9S.<YUD94PB%GT5$1$7)#-TT4RG6I
M:(CH3<E$&:3CEX+D5!H2:V-[K(^_=.!QXT-"1247(S/7ULT85/&CBQ5.19@>
M4J),'U7,*U,0W-RFY>_2R]+T?#^M+2ZFTO6;#)A-9J+-+8P&Q\-;;MS.#+&\
4EP<%+R]J60*?(NY(IPH2&8_[`J``
`
end
EOT
		uudecode -o - $index | bunzip2 > $dat
		date "+  [%X] Creating ${isoprefix}_vmware(-02).vmdk ..."
		tar xf $dat -O vmware.vmdk    > ${isoprefix}_vmware.vmdk
		tar xf $dat -O vmware-02.vmdk > ${isoprefix}_vmware-02.vmdk
	fi
fi

date "+  [%X] Done. Have fun!"
echo

rm -f $index $dat