#! /bin/bash -eu

# dvdspan version 20050806 - NOT FINISHED YET
# by Sam Morris <sam@robots.org.uk>
#
# backs up some files to one or more DVDs. uses a multi-volume tar archive.

# capacity of the media in MB
#
capacity=4702

# burn speed
#
speed=8

# drive to burn to
#
drive=/dev/hdc

# directory containing files to back up
#
directory=/media/newhope

# filenames to add to the archive
#
#files=Music/incoming/SimCity
files=Music/

# the manifest file is added to every disc burned
#
manifest=$directory/Music/Manifest.bz2

#
# end of configuration

if test -z "${dvdspan_archive:-}"
then
	export dvdspan_name="${1:?Usage: $0 archive_name}"
	export dvdspan_archive="$dvdspan_name.tar"
fi

# burn all archives to dvd
#
function burn {
	cd $dvdspan_dir

	disc=1
	test -f disc && disc=$(( $(< disc) + 1 ))

	while test "${burn:-}" != 'burn'
	do
		read -p "Enter 'burn' to burn disc '$dvdspan_name.$disc': " burn
	done

	growisofs -dry-run -speed=$speed -Z $drive \
		-r -V "$dvdspan_name.$disc" \
		-input-charset utf-8 \
		$manifest $dvdspan_archive.*

	rm $dvdspan_archive.*
	echo $disc > disc
}

# if we are being run by tar, burn the current archive
#
if test $(awk '{print $2}' /proc/$PPID/stat) = '(tar)'
then
	# Tar manual §9.6: "Only when the first [--file option] in the sequence
	# needs to be used  again will `tar' prompt for a tape change (or run the
	# info script)." Unfortunatly it seems that, once the initial sequence of
	# --file options has been run through, tar prompts/runs the script for
	# every --file option.
	#
	# Therefore only call burn if the ${count}th archive exists.
	if test -f $dvdspan_dir/$dvdspan_archive.$dvdspan_count
	then
		burn
	fi
	exit 0
fi

dvd+rw-mediainfo /dev/hdc > /dev/null || { echo 'No disc in drive?'; exit 1; }

# make room for the manifest
#
manifest_size=$(( $(stat --format=%s $manifest) / 1024 / 1024 ))
test $manifest_size -lt 1 && manifest_size=1
capacity=$(( $capacity - $manifest_size ))

# if capacity is odd then we get an annoyingly large amount of small archives
#
test $(expr $capacity % 2 > /dev/null) || capacity=$((capacity - 1))

# iso9660 can't cope with files larger than 4 GB, and files larger than 2 GB
# are not very portable; therefore set the span size as the smallest factor of
# $capacity under 2 GB
#
span=$capacity
count=1
read -a factors <<< $(factor $capacity)
while test $span -gt $(( 2**32/1024/1024 / 2 ))
do
	factors=(${factors[@]:1})

	span=$(( $span / ${factors[0]} ))
	count=$(( $count * ${factors[0]} ))
done
export dvdspan_count=$count

echo "Will create $count archives of $span million bytes per disc."
echo "Press enter to proceed."
read

export dvdspan_dir=$(mktemp -t -d dvdspan.XXXXXX)

# construct the --file arguments for tar
for x in $(seq 1 $count)
do
	fileargs="${fileargs:-} --file=$dvdspan_dir/$dvdspan_archive.$x"
done

tar --create \
	$fileargs \
	--label="$dvdspan_name.$(date --iso-8601)" \
	--multi-volume --tape-length=$(( $span * 1000*1000/1024 )) \
	--new-volume-script=$0 \
	--totals \
	--directory=$directory $files

# burn the final archive file
burn last

rm disc
rmdir --ignore-fail-on-non-empty $dvdspan_dir

# create sparse file: dd if=/dev/zero of=image bs=1M seek=4700 count=0
