#!/bin/bash
# --- SDE-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
#
# Filename: scripts/Create-ISO
# Copyright (C) 2006 - 2008 The OpenSDE Project
# Copyright (C) 2004 - 2006 The T2 SDE Project
#
# More information can be found in the files COPYING and README.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License. A copy of the
# GNU General Public License can be found in the file COPYING.
# --- SDE-COPYRIGHT-NOTE-END ---

#
# 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. The first attached argument is the CD
# number and the second the image file.
#

eval `grep sdever lib/parse-config`
. lib/functions.in

usage()
{
	echo
	echo "Usage: $0 [ -size MB ] [ -source ] [ -mkdebug ] [ -nomd5 ] ISO-Prefix \\"
	echo "       ${0//?/ } Config [ Config [ .. ] ]"
	echo
	echo "E.g.: $0 mycdset install generic"
	echo
	exit 1
}

# default disk-size
dsize=$(( 700 * 1024 ))
file_overhead=1
src=0; mkdebug=0; implantisomd5=1

while [ "$1" ] ; do
	case "$1" in
		-size)
			dsize=$(( $2 * 1024 )) ; shift ; shift ;;
		-source)
			src=1 ; shift ;;
		-mkdebug)
			mkdebug=1 ; shift ;;
		-nomd5)
			implantisomd5=0 ; shift ;;
		-* | '')
			$0 ; exit 1 ;;
		*)
			isoprefix=$1 ; shift ; break ;;
	esac
done

[ $# -eq 0 ] && usage

spacer="    "

errno=0; for cfg ; do
	if [ ! -f config/$cfg/config ]; then
		echo "Not a valid config: $cfg"
		errno=1
	fi
done
[ $errno -ne 0 ] && exit 1

if [ "$implantisomd5" = 1 -a ! -x tmp/isomd5sum/implantisomd5 ] ; then
	echo ; date "+  [%X] Creating ISO-MD5 tools ..."
	rm -rf tmp/isomd5sum; mkdir -p tmp/isomd5sum
	cp src/isomd5sum/* tmp/isomd5sum/
	make -C tmp/isomd5sum all
fi

echo ; date "+  [%X] Removing old files with same prefix ..."
[ "${isoprefix//\//}" = "${isoprefix}" ] && isoprefix="iso/$isoprefix"
mkdir -vp ${isoprefix%/*}
rm -rvf ${isoprefix}_* ${isoprefix}.md5

date "+  [%X] Reading configs ..."
index=`mktemp` ; dat=`mktemp` ; pathspec=`mktemp`
rm -f ${pathspec}*

for cfg ; do
	id="$( grep '^export SDECFG_ID=' config/$cfg/config | cut -f2 -d"'" 2> /dev/null)"
	if ! cat build/$id/TOOLCHAIN/isofs.txt >> $dat 2> /dev/null
	then
		echo "Not a valid build: $cfg"
		echo "build/$id/TOOLCHAIN/isofs.txt might be created."
		rm -f $dat $index ${pathspec}_* ; exit 1
	fi

	if test -f config/$cfg/license-issue.ask; then
		if ! grep LICENSE-WARNING $dat &> /dev/null; then
			echo "EVERY doc/files/LICENSE-WARNING LICENSE-WARNING" >> $dat
		fi

		cp -vf doc/files/LICENSE-WARNING build/$id/TOOLCHAIN/
		echo "" >> build/$id/TOOLCHAIN/LICENSE-WARNING
		echo "The following packages may have license restrictions:" >> build/$id/TOOLCHAIN/LICENSE-WARNING
		cat config/$cfg/license-issue.ask >> build/$id/TOOLCHAIN/LICENSE-WARNING

		if [ "$( grep '^export SDECFG_LICENSE_ISSUE=' config/$cfg/config | cut -f2 -d"'")" = "0" ]; then
			cat <<EOF
You have chosen to compile packages that are restricted
in their redistribution. Unless you accept this limitation
you cannot burn these packages.

Please rerun ./scripts/Config -cfg $cfg and check
'I have read and understood the licensing issues.'
EOF

#FIXME remove packages that have an issue instead of exiting
			exit 1
		fi
	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 ${pathspec}_* ; exit 1
	fi

	files="`find $from ! -type d | wc -l`"
	size="`du -s -b $from | cut -f1`"
	size=$(( size / 1024 + files * file_overhead ))

	if [ $size -gt $(( $dsize - $disk_0_size )) ] ; then
		echo "Chunk $from is too big!"
		rm -f $dat $index ${pathspec}_* ; 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 ))"
			echo "$to=$from" >> ${pathspec}_${disk_nr}
			done=1 ; break
		fi
	done

	if [ $done = 0 ] ; then
		disk_nr=$(( $disk_nr + 1 ))
		ds=disk_${disk_nr}_size ; eval "$ds=$size"

		# FIXME: if in a path-list files, mkisofs complains about
		#        missing isolinux. Should be a mkisofs bug!
		if [ "$to" = "isolinux/" -o "$from" = "isolinux/" ] ; then
			echo "$to=$from" >> ${pathspec}_iso
		else
			echo "$to=$from" >> ${pathspec}_${disk_nr}
		fi
		disks="$disks $disk_nr"
	fi
}

bootoptions=
scripts=
while read tag data ; do
	# empty lines
	[ "$tag" ] || continue
	if [ $tag = BOOT ]; then
		if [ "$bootoptions" ]; then
			echo "Multiple boot options found!"
			rm -f $dat $index ${pathspec}_* ; exit 1
		else
			bootoptions="$data"
			[[ $data == *-hfs* ]] && file_overhead=12
		fi
	elif [ $tag = SCRIPT ]; then
		scripts="$scripts $data"
	fi
done < $dat
while read tag data ; do
	if [ "$tag" = BOOTx ]; then
		bootoptions="$bootoptions $data"
		[[ $data == *-hfs* ]] && file_overhead=12
	fi
done < $dat

echo "$spacer parsing for EVERY disk."

disks="0" ; disk_nr=0 ; disk_0_size=0
echo "index.txt=${isoprefix}_index.txt" >> ${pathspec}_0
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 ${pathspec}_* ; 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 ${pathspec}_* ; 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

if [ $src = 1 ] ; then
	date "+  [%X] Embedding source ..."

	./scripts/Create-SrcTar

	for x in doc/* opensde-src-$sdever.tar.bz2 ; do
		[ ! -d $x ] && add $x ${x/doc\/}
	done

	while read from ; do
		from="`bz2filename $from`"
		if [ -e $from ] ; then
			add $from $from
		else
			echo "WARNING: File $from is missing!"
		fi
	done < <( ./bin/sde-download -list | sort -u )
fi

date "+  [%X] Creating ISO index ..."
echo -n > $index
for x in 0 $disks ; do
	dd=disk_${x}_data
	for y in ${!dd} `cat ${pathspec}_${x} 2> /dev/null` ; do
		to=${y%=*} ; from=${y#*=}
		if [ -e $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

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 | tee ${isoprefix}_index.txt | md5sum |
	sed "s/ -/ ${isoprefix##*/}_index.txt/" >> ${isoprefix}.md5

for x in $disks ; do
	ds=disk_${x}_size
	date "+  [%X] Creating ${isoprefix}_cd$x.iso ..."
	echo "This is disk #$x." > $dat
	# FIXME: current mkisofs does only accept one -path-list
	sort -u ${pathspec}_${x} ${pathspec}_0 > ${pathspec}_current 2> /dev/null
	mkisofs -quiet -r -T -J -l -A "OpenSDE - Disk $x" \
	    -publisher 'OpenSDE System Develop Environment - http://www.opensde.org' \
	    -path-list ${pathspec}_current \
	    $bootoptions -graft-points disk$x.txt=$dat \
	    `cat ${pathspec}_iso 2>/dev/null` | tee ${isoprefix}_cd$x.iso |
	md5sum | sed "s/ -/ ${isoprefix##*/}_cd$x.iso/" \
	             >> ${isoprefix}.md5
	rm -f ${pathspec}_iso
	rm -f ${pathspec}_current

	bootoptions=

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

	if [ "$implantisomd5" = 1 -a -x ./src/isomd5sum/implantisomd5 ] ; then
		echo "$spacer Calculating and implanting MD5 checksum ..."
		./tmp/isomd5sum/implantisomd5 ${isoprefix}_cd$x.iso >/dev/null
	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

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

rm -f $index $dat ${pathspec}_*