#!/bin/sh
#
#	incbru    bru incremental backup script  
#
#  DESCRIPTION
#
# 	This script will perform different levels of incremental
#	backups using bru.
#
#	It will backup all files that have changed since doing a
#	backup with a lower level.
#
#	If no argument is specified, it will do a level 1 backup
#	and will backup all files since the last full (level 0)
#	backup.  If the level 0 backup does not exist, it will
#	do that instead.
#
#  NOTES
#
#	Feel free to customize this script to handle your
#	specific backup requirements.  This script is designed
#	to do basic backups of the entire system from the root
#	directory. 
#	
#

# die on uninitialized variables
set -u

# name of backup device, use default if none is specified
# BRUDEV defined below

#BRUOPTS="-vvvvV -R -s 4200M -B -b 294912 -PEPf -X"
BRUOPTS="-vvvvV -s 4200M -B -X -Z -R -PEPf -QX"

export BRUXPAT=/etc/bruxpat
export OVERWRITEPROTECT=NO

DIRS="/"

# mount point of backup directory
# We will test to see that it is mounted and abort the backup
# if it isn't.  This is to prevent fill-up of the root FS
MOUNTPOINT='/Volumes/Laptop Backup' 

# no spaces for BRU, which can't handle them
MOUNTPOINT_LINK=/backup-link-static

#MOUNT_CMD='mount -t nfs -o async 192.168.0.2:/backup/mercury /backup 2>/dev/null'
MOUNT_CMD='mount -t hfs /dev/disk2s1 /backup'

LOGFILE="${MOUNTPOINT}/brubackup-`date +%Y%m%d`.log"

# where to mail the results
MAILTO=reds

case "$#" in
    0)
	LVL=1		# no argument, so do a level 1 backup
	;;
    1)
	LVL=$1
	;;
    *)
	echo "usage: incbru [level]"
	echo "   valid level is integer from [0-9]"
	echo "   level 0 = full backup"			
	exit 1
	;;
esac

#
# check to see backup media is mounted
#
MOUNTED=0
ATTEMPTS=1
while [ $MOUNTED -eq 0 ]; do

        # first see whether it's already mounted
	if [ `mount | grep "$MOUNTPOINT" | wc -l` -eq 0 ]; then
		exec $MOUNT_CMD
		if [ $? -ne 0 ]; then
                        echo mount attempt \#$ATTEMPTS of $MOUNTPOINT failed.
                else
                        MOUNTED=1
			echo `mount | grep "$MOUNTPOINT"`
                fi
        else
                MOUNTED=1
        fi

	# don't sit here forever...
	if [ $ATTEMPTS -eq 5 ]; then
		echo Failed to mount $MOUNTPOINT.  Backup aborted.
		exit 1
	fi

        # if we didn't successfully mount, then retry in a sec
        if [ $MOUNTED -eq 0 ]; then
 		echo Retrying in 4 seconds...
		let ATTEMPTS+=1
		sleep 4
        fi
done

BACKUPMOUNTED=`mount | grep "$MOUNTPOINT" | wc -l`
if [ $BACKUPMOUNTED -gt 1 ]
then
	echo "Backup filesystem $MOUNTPOINT mounted more than once. Backup aborted"
	exit 1
fi

ln -s "$MOUNTPOINT" "$MOUNTPOINT_LINK"

#
# check for legal backup level
#
case $LVL in
	0|1|2|3|4|5|6|7|8|9)
	;;
	*)
		echo "incbru: $LVL is an illegal backup level"
		exit 1
	;;
esac

#
# if level 0, do a full backup
#
DATEFILE=""
if [ "$LVL" -eq 0 ]
then
	# full backup

	ls "$MOUNTPOINT/old" >/dev/null 2>&1
	if [ $? -ne 0 ]
	then
		mkdir "${MOUNTPOINT}/old"
	else
		rm "${MOUNTPOINT}/old/full-"*.? 2>/dev/null
		rm "${MOUNTPOINT}/old/full-"*.?? 2>/dev/null
		rm "${MOUNTPOINT}/old/increment-"*.? 2>/dev/null
		rm "${MOUNTPOINT}/old/increment-"*.?? 2>/dev/null
		rm "${MOUNTPOINT}/old/brubackup-"* 2>/dev/null
	fi
	mv "$MOUNTPOINT/full"* "$MOUNTPOINT/increment"* "$MOUNTPOINT"/*.log.gz "$MOUNTPOINT"/old/ 2>/dev/null

	export BRUDEV="-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.1 \
	        -f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.2 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.3 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.4 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.5 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.6 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.7 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.8 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.9 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.10 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.11 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.12 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.13 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.14 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.15 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.16 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.17 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.18 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.19 \
		-f $MOUNTPOINT_LINK/full-`date +%Y%m%d`.20"
	DATEFILE=""
else
	# incremental backup
	export BRUDEV="-f "$MOUNTPOINT_LINK"/increment-`date +%Y%m%d`.1 \
	        -f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.2 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.3 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.4 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.5 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.6 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.7 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.8 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.9 \
		-f $MOUNTPOINT_LINK/increment-`date +%Y%m%d`.10"

	PREVLVL=`expr $LVL - 1`		# previous backup level	
	echo "PREVLVL = $PREVLVL"
	#
	#  find date marker file for previous level backup
	#
	i=0
	while [ "$i" -le "$PREVLVL" ]	
	do
		FILE=/etc/BRULEVEL$i
		if [ -f "$FILE" ]
		then
			DATEFILE=$FILE
			if [ "/etc/BRULEVEL${PREVLVL}" = "$FILE" ]
			then
				break	# found previous date marker file
			fi
		fi

		i=`expr $i + 1`
	done 
fi

if [ "$DATEFILE" = "" ]
then
	if [ "$LVL" -ne 0 ]
	then
		echo "incbru: No previous backup less than Level $LVL"
		LVL=0
	fi
	echo "Performing Full Backup (Level 0)"
else
	echo "Performing Level $LVL Backup"
	BRUOPTS="$BRUOPTS -n $DATEFILE"
fi

#
#  set up bru command that will do the backup, use default device
#  from brutab if none is specified
#
if [ "$BRUDEV" != "" ]
then
	BRUCMD="bru -c $BRUOPTS $BRUDEV $DIRS"
else
	BRUCMD="bru -c $BRUOPTS $DIRS"		# use default device 
fi

#
#  create a temporary date marker file.  if the backup is
#  successful, this will be renamed
#
MARKER=/etc/BRULEVEL${LVL}
TMP=$MARKER.err
TS=`date`
echo "$TS - Started BRU Level $LVL Backup" > $TMP
echo "command = '$BRUCMD'" >> $TMP 

#
#  change to the root directory and execute the bru backup.  write
#  output to log file if one is specified
#
BRUEXIT=2
cd /	
if [ "$LOGFILE" != "" ]
then
	#$BRUCMD | gzip > "$LOGFILE"
	echo command used: $BRUCMD
	$BRUCMD > "$LOGFILE"
	BRUEXIT=$?
else
	$BRUCMD 2>&1
	BRUEXIT=$?
fi

if [ -e "$LOGFILE" ]
then
	gzip -f "$LOGFILE"
	#umount "$MOUNTPOINT" 2>/dev/null
	if [ $? -ne 0 ]; then
		echo umount of $MOUNTPOINT failed.
		BRUEXIT=1
	else
		#echo successfully umounted $MOUNTPOINT
		echo successfully gzipped logfile
	fi

else
	echo "end of backup"
fi

# clean up some
rm $MOUNTPOINT_LINK

#
#  check the exit code.  if greater than or equal to 2, we've
#  got a problem
#
TS=`date`
if [ "$BRUEXIT" -ge 2 ]
then
	echo "incbru: ERROR in BRU Backup"
	echo "$TS - ERROR IN BRU BACKUP, check log file: '$LOGFILE'" >> $TMP 
	mail $MAILTO < $TMP 
	exit 2
else
	if [ "$BRUEXIT" -eq 0 ]
	then
		echo "BRU Level $LVL Backup successful"
	else
		# exit code = 1
		echo "BRU Level $LVL Backup completed (with warnings)"
	fi
	mv $TMP $MARKER 
	echo "$TS - BRU Level $LVL Backup completed, results in log file: '$LOGFILE'" | mail $MAILTO
	exit 0
fi
