#! /bin/sh

# 'saveset.sh'
#
# - writes data to CD or CD-RW
# - allows to specify directories & exclude patterns
# - allows external config file
# - ... but supports only 1 CD
#
# TO DO: - check that mkisofs is 1.13 or later
#        - check integrity of CD image after burning
# -----------------------------------------------------------------
# Note 1: adjust parameters, CD-RW device etc. below!
# Note 2: This must be run this as root.
# -----------------------------------------------------------------
# Creation:  2001-10-03, JHa (first "draft").
# Revisions:
# 2001-10-05, JHa: added check for free space, preserve existing
#             file permissions (Thanks to Hendric Stattmann !)
# 2001-10-28, JHa: excluded wwwoffle completely
# 2001-11-03, JHa: adjusted for mkisofs-1.14 syntax
# 2002-04-18, JHa: fixed IMGDIR stuff (Thanks to Jochen Gruse !)
# 2002-12-28, JHa: added error check in mkisofs "dry run".
# 2003-01-27, JHa: added comments
# 2003-09-05, JHa: archive name is derived from $HOST + $DATE.
# 2003-09-28, JHa: allows external config file. MAXSIZE is now
#             variable to allow non-standard CD sizes.
# 2003-10-30  HST: simplified exit status handling.
# 2003-10-30  HST: added max. ISO sizes for CD-R media w more than 650MB.
# 2006-12-25, JHa: added more info and $WRITE_OPTS 
# -----------------------------------------------------------------
# Copyright (c) 2001-2006 Joerg Hau <joerg.hau(at)dplanet.ch>.
#
# 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; either version 2 of
# the License, or (at your option) any later version, provided that
# the copyright notice remains intact even in future versions.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# -----------------------------------------------------------------

# disable filename expansion
#
set -f

# --- user-specific setup ---
#
# All parameters below can also be specified (or changed ;-)
# via a config file that is given on the command line.
# As an example, the config to save my digital photos looks
# like this (without the '#' of course ;-):
#
# DIRLIST="/home/jha/graf"
# EXCLUDE="*~ *.tgz"
# NAME=`cat /etc/HOSTNAME`.jha-graf.`date +%Y%m%dT%H%M`
#

# list of directories to archive. Do not use slashes at the end!
#
DIRLIST="home root etc var"

# ... and list of exclude pattern (see mkisofs manpage)
#
EXCLUDE="*cache* *~ *thumbnails* */mp3/* *.wav \
/home/jha/graf/* /var/spool/wwwoffle*"

# the CD-RW device 'cdrecord' syntax (dev=BUS,ID,LUN)
# SCSI (all): "dev=0,6,0" or similar
# Kernel 2.4 with ide-scsi: "dev=0,0,0" or similar
# Kernel 2.6: "dev=/dev/hdc" or similar
#
WRITE_DEV="dev=/dev/hdc"

# default speed and other options
#
WRITE_SPEED="speed=8"
WRITE_OPTS="driveropts=burnfree -overburn -eject"

# Blanking option:
# for CD-RW media, specify "blank=fast". For CD-R, set it to "".
#
BLANK="blank=fast"

# name for the Volume
#
NAME=`cat /etc/HOSTNAME`.`date +%Y%m%dT%H%M`

# Recommanded maximum image sizes (in 2048-byte blocks):
# CD-R(W) 650: 332500 = 680'960'000 bytes
# CD-R(W) 700: 359849 = 736'970'752 bytes
# Some CD-writing programs and/or media don't allow bigger images.
# See an extended list of CD-R(W) capacities at:
# http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/cd-cap.html
#
MAXSIZE=332500

#
# --- end of user-specific setup ---
#
# "No user adjustable parts below this line" :-)
#

if [ `whoami` != 'root' ]; then
    echo "You must be root to run this script."
    exit 2
fi

# if any external config file was specified, source it
#
if [ $# -eq 1 ]; then
    echo -n "Reading configuration from $1 ..."
    if [ -e "$1" ]; then
        source $1
        echo "done."
    else
        echo "Configuration file $1 not found."
        exit 1
    fi
fi


# concatenate list of directories & excludes
#
DIRS=`for X in $DIRLIST; do echo -n "$X/=/$X "; done`
EXCL=`for X in $EXCLUDE; do echo -n "-m "$X" "; done`

echo -n "Preparing to archive ("
for X in $DIRLIST; do echo -n " $X"; done
echo " )"

echo "Excluding ( "$EXCLUDE" )"

# the temporary file
#
IMG="/tmp/img-${NAME}.iso"

# get size from a "dry run", same parameters as for the final run below
#
# for mkisofs 1.13:
#
# SIZE=`/usr/bin/mkisofs -J -L -R -V $NAME -quiet -o $IMG $EXCL \
# -print-size -graft-points $DIRS 2>&1 \
# | grep "scheduled to be written" | cut -d ' ' -f 8`
#
# for mkisofs 1.14:
#
SIZE=`/usr/bin/mkisofs -J -L -R -V $NAME -quiet -o $IMG $EXCL \
-print-size -graft-points $DIRS`

# check status of last cmd, abort if not OK
# (command may fail e.g. with too-long filenames)
#
if [ $? != 0 ]; then
	echo " *** Error occurred during 'mkisofs' dry run! Exiting."
	exit 1
fi

# Check if image size fits media.
#
echo "Size of ISO image will be $SIZE blocks."
if (($SIZE > $MAXSIZE)); then
	echo "Sorry, this is too big - should be less than $MAXSIZE blocks."
 	exit 1
fi

# verify that we have enough disk space in $IMG
#
IMGDIR=`dirname $IMG`
FREE=`df --block-size 2048 $IMGDIR | grep dev | awk '{print $4}'`
if (($FREE < $SIZE)); then
	echo "Problem: not enough disk space to store image file."
	exit 1
fi

# arrive here if OK: Create a "real" image file,
# burn to disk and erase image file afterwards.
# Option '-R' preserves file permissions.
#
/usr/bin/mkisofs -L -J -R -V $NAME -quiet \
                 -o $IMG $EXCL -graft-points $DIRS \
&& cdrecord -v $WRITE_DEV $WRITE_SPEED $BLANK $WRITE_OPTS $IMG \
&& rm $IMG || exit 1

# FIXME: check for integrity of data
# mount -t iso9660 -o ro /cdrom
# for X in $DIRLIST; do diff -r /$X /cdrom/$X"; done
# ... all we need to implement here is an error check for diff
# and ... well, the consideration of the exclude list ;-)
#

# If we get through here in the script, everything went well.
exit 0

