#!/bin/bash
############################################################################
#    Copyright (C) 2008 by Adam Jimerson                                   #
#    vendion@gmail.com                                                     #
#                                                                          #
#    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.                                   #
#                                                                          #
#    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.                          #
#                                                                          #
#    You should have received a copy of the GNU General Public License     #
#    along with this program; if not, write to the                         #
#    Free Software Foundation, Inc.,                                       #
#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
############################################################################


# Backup - create either a full or incremental backup of a set of
#     defined directories on the system. By default, the output
#     file is saved in /tmp with a timestamped filename, compressed.
#     Otherwise, specify an output device (another disk, a removable).

#check to see if backup-light is already ready running by testing for a PID
#proccessid=`pgrep backup-light` #get any possible PID of backup-light
#if [ "$proccessid" != " " ] ; then
#	echo "Error: Backup-light is already running, running it again would be pointless"
#	exit 1
#fi

if [ ! -d ~/.backup-light ] ; then #This will make the ~/.backup-light directory to hold the timestamp and log files needed for backup-light to work
	if [ -f ~/.backup-light ] ; then #If an older version of backup-light was used, I.E. 0.3, then the log file is renamed so a directory can be made with the same name.
		backuppath="/tmp"
		compression="bzip2"
		mv ~/.backup-light log 2> /dev/null #rename the file .backup-light to log
		mkdir ~/.backup-light 2> /dev/null
		mv ~/log ~/.backup-light/log 2> /dev/null
		mv ~/.backup.timestamp ~/.backup-light/backup.timestamp 2> /dev/null
		echo "Please enter the default location for storing backups, the default is \"/tmp\"?"
		read backuppath
		if [ "$backuppath" == '' ] ; then
			backuppath="/tmp"
		fi
		echo $backuppath > ~/.backup-light/backuppath
		echo "Please enter which compression app you prefer to use (bzip2/gzip), the default is \"bzip2\"?"
		read compression
		if [ "$compression" == '' ] ; then
			compression="bzip2"
		fi
		echo $compression > ~/.backup-light/compression
	else
		mkdir ~/.backup-light #If an older version of backup-light was not used then just the directory will be made Backup-light will make the other two files as needed and within this directory.
		echo "Please enter the default location for storing backups, the default is \"/tmp\"?"
		read backuppath
		if [ "$backuppath" == '' ] ; then
			backuppath="/tmp"
		fi
		echo $backuppath > ~/.backup-light/backuppath
		echo "Please enter which compression app you prefer to use (bzip2/gzip), the default is \"bzip2\"?"
		read compression
		if [ "$compression" == '' ] ; then
			compression="bzip2"
		fi
		echo $compression > ~/.backup-light/compression
	fi
fi


usageQuit () {
	echo
	echo "Usage: `basename $0` [-o output] [-i|-f] [-n]"
	echo " -o lets you specify an alternative backup file/device"
	echo " -i is an incremental or -f is a full backup"
	echo " -e specifies a directory to be excluded from the backup"
	echo " -r restores from a backup"
	echo " -R recovers from a full backup then restores all the incremental backups up to the user specified point"
	echo " -d creates a backup and burns it to a CD/DVD"
	echo " -m restores from a multi disk (split) backup"
	echo " -n prevents updating the timestamp if an incremental backup is done"
	echo " -l Shows the log file containing dates and types of backups preformed"
	echo " -v shows program version"
	echo " -h Shows you this help message"
	exit 0
}

version() {
	echo
	echo "`basename $0` version 0.4"
	exit 0
}

createBackup() {
	grep -v ^"$excludedir" | \
	pax -w 2> /dev/null | $compress > $output 2> /dev/null
	cp -r ~/.backup-light $backupdir/.backup-light #copy .backup-light directory recursively to the backup device
	echo "Your $btype backup is done and is in $output"
}

restore() {
	echo "Backup archives are available for the following dates:"
	ls $backupdir | grep backup-$USER.*.tar* | sed 's_/.*/\(.*\)_\1_' | egrep -o [0-9]{6}
	echo "Please type the date to restore from:"
	read rdate
	until [ -f $backupdir/backup-$USER.$rdate.tar.* ]; do
		echo "Sorry, there is no backup from that date. Please try again."
		read rdate
	done
	if [ ! -f $backupdir/backup-$USER.$rdate.MD5SUM ]; then
		echo "Warning! No md5 sum found, archive integrity could not be checked."
		echo "Proceed anyway? (y/n)"
		read ans
		if [ $ans != "y" ]; then
		exit 1
		fi
	fi
	md5=`md5sum $backupdir/backup-$USER.$rdate.tar.*`
	md5file=`cat $backupdir/backup-$USER.$rdate.MD5SUM`
	if [ $md5 != $md5file ]; then
		echo "Warning! md5 checksum doesn't match, archive may be corrupted."
		exit 1
	fi
	mkdir /tmp/backup-light
	$compress -d backup-$USER.$rdate.tar.* | pax -rp p /tmp/backup-light
	sudo mv /tmp/backup-light/home / #Sudo should not interrupt the process of the script, if it does then, we can fix this with the following: mv /tmp/backup-light/home/$USER /home.  That will overwrite the existing $HOME for the user, and because of that they will have write access to allow it to happen.
	echo "backup-$USER.$rdate.tar.bz2 has been restored."
	rm -rf /tmp/backup-light
}

disk () { #break this into separate sub-routines, this one to set everything up and the second to restore
	echo "What device should be used:"
	cdrecord --scanbus
	echo "Remember to use the proper type, ie sr0"
	read device
	echo "Doing $btype backup, saving output to /dev/$device"

	if [ "$btype" = "incremental" ] ; then
		find $HOME -depth -type f -newer $tsfile -user ${USER:-LOGNAME} | \
		pax -w 2> /dev/null | $compress > /tmp/backup-$USER.$date.tar.bz2 2> /dev/null  #Backups on DVD/CD will be saved to /tmp until it can be burned to disk, then it will be removed.
	else
		find $HOME -depth -type f -user ${USER:-LOGNAME} | \
		pax -w 2> /dev/null | $compress > /tmp/backup-$USER.$date.tar.bz2 2> /dev/null
	fi
	cd /tmp
	md5sum backup-$USER.$date.tar.* > backup-$USER.$date.MD5SUM  #The MD5SUM will also be created in /tmp and burned to the disk.


	if [ /tmp/backup-$USER.$date.tar.bz2 -ge 670 ]; then
		echo "The backup is to large to fit on a CD, please use a DVD medium." #CD spiting will be added later
	elif [ /tmp/backup-$USER.$date.tar.bz2 -ge 4403 ]; then
		echo "The backup is to large to fit on a DVD"
		echo "Splitting file, please wait..."
		#echo $date > /tmp/date This file will be used to restore the creation date of the backup upon recreation.
		#echo $USER > /tmp/user This file will be used to restore the creation user of the backup upon recreation.
		#Only uncomment the above two lines if $USER and $date can not be restored from the split files (kind of seeing a problem with this, so best to be prepared)
		split -bd 4403m /tmp/backup-$USER.$date.tar.bz2
		rm /tmp/backup-$USER.$date.tar.bz2
		splitfile = 001
		loopcount = 0
		until [ ! -f /tmp/$splitfile ] ; do
			if [ $loopcount -ge 0 ] ; then
				echo "Please insert a blank disk"
				sleep 30 #This is to give the user time to switch disks
			fi
			mkisofs -R -J -iso-level 2 -0 /tmp/backup-$USER.$date-part$splitfile.iso /tmp/$splitfile
			rm /tmp/$splitfile
			cdrecord -v speed=4 -data -eject -silent dev=/dev/$device -dao /tmp/backup-$USER.$date-part$splitfile.iso
			rm /tmp/backup-$USER.$date-part$splitfile.iso
			$splitfile += 1
			$loopcount += 1
		done
		exit
	fi
	#the syntax needed to split the files is "split -bd (size in MB)m backup-$USER.$date.tar.bz2.
	#"-d" as been added so the output of split will be numbers 001-999 instead of letters, this way a loop process can be created to handle all the parts.

	mkisofs -R -J -iso-level 2 -o /tmp/backup-$USER.$date.iso /tmp/backup-$USER.$date.tar.bz2 /tmp/backup-$USER.$date.MD5SUM
	rm /tmp/backup-$USER.$date.tar.bz2 /tmp/backup-$USER.$date.MD5SUM
	cdrecord -v speed=4 -data -eject -silent dev=/dev/$device -dao /tmp/backup-$USER.$date.iso #if -silent does not stop cdrecord from printing out drive information then add "2> /dev/null at the end of this line, drive info does not need to be printed.
	rm /tmp/backup-$USER.$date.iso
	echo "Your $btype backup is done and is burnt to /dev/$device"
	touch -t $timestamp $tsfile
	echo "The timestamp has been updated to:"
	ls -l ~/.backup.timestamp | awk '{ print $6, $7;}'
	exit 0
}

multi () {
	#This is used to restore from multiple CDs and DVDs if the backup had to be split.
	echo "How many disks are you restoring from?"
	read maxrestore
	echo "Which device is the backup disk in?"
	cdrecord --scanbus #It would be nice to avoid this step
	read device
	mkdir /tmp/backup-light
	loopcount = 0
	until [ $loopcount == $maxrestore ] ; do
		cp /dev/$device/* /tmp/backup-light
		if [ $loopcount == $maxrestore -1 ] ; then
			echo "Please insert the last disk"
			sleep 30
		else
			echo "Please insert the next disk"
			sleep 30
		fi
		$loopcount += 1
	done
	cd /tmp/backup-light
	cat 0* >backup-$USER.tar.bz2
	rm -r 0*
	#checking of MD5SUMS will be integrated later on
	$compress -d backup-$USER.$rdate.tar.* | pax -rp p /tmp/backup-light
	sudo mv /tmp/backup-light/home / #Sudo should not interrupt the process of the script, if it does then, we can fix this with the following: mv /tmp/backup-light/home/$USER /home.  That will overwrite the existing $HOME for the user, and because of that they will have write access to allow it to happen.
	echo "backup-$USER.$rdate.tar.bz2 has been restored."
	rm -rf /tmp/backup-light
}

log () {
	#This option servers two purposes, the first being a test for the planned "recovery" feature.  The second is to show the user when they last did a full backup, and how many incremental backups after that.
	echo "The last full backup was preformed on:"
	cat ~/.backup-light/log | grep Full
	echo "There are incremental backups, that contain changes from the full backup, for the following dates:"
	cat ~/.backup-light/log | grep Incremental
	exit 0
}

recover () {
	#Recover code
	#some code will be placed here and it will work like magic, don't ask me how
	echo "Error:  This feature is incomplete and is disabled, please check back in future versions for the working version."
	exit 0
# 	if [ ! -d ~/.backup-light ] ; then
# 		#in case the `~/.backup-light` directory does not exist then copy if from the $backupdir and continue
# 		cp -r $backupdir/.backup-light ~/.backup-light
# 	fi
# 	rdate = cat ~/.backup-light/log | grep Full | sed 's_/.*/\(.*\)_\1_' | egrep -o [0-9]{6} #need to get this just down to the date, I am hoping that `sed 's_/.*/\(.*\)_\1_' | egrep -o [0-9]{6}` will do the trick.
# 	if [ ! -f $backupdir/backup-$USER.$rdate.tar.* ] ; then
# 		echo "Error:  There is no full backup for $rdate, can not continue with a corrupt log file!"
# 		echo "Try rerunning the program with \"-r\" instead of \"-R\""
# 		exit 1
# 	else
# 		echo "Restoring full backup..."
# 		echo "Please wait this could take some time..."
# 	fi
# 	if [ ! -f $backupdir/backup-$USER.$rdate.MD5SUM ]; then
# 		echo "Warning! No md5 sum found, archive integrity could not be checked." >&2
# 		echo "Proceed anyway? (y/n)"
# 		read ans
# 		if [ $ans != "y" ]; then
# 		exit 1
# 		fi
# 	fi
# 	md5=`md5sum $backupdir/backup-$USER.$rdate.tar.*`
# 	md5file=`cat $backupdir/backup-$USER.$rdate.MD5SUM`
# 	if [ $md5 != $md5file ]; then
# 		echo "Warning! md5 checksum doesn't match, archive may be corrupted." >&2
# 		exit 1
# 	fi
# 	mkdir /tmp/backup-light
# 	$compress -d backup-$USER.$rdate.tar.* | pax -rp p /tmp/backup-light
# 	sudo mv /tmp/backup-light/home / #Sudo should not interrupt the process of the script, if it does then, we can fix this with the following: mv /tmp/backup-light/home/$USER /home.  That will overwrite the existing $HOME for the user, and because of that they will have write access to allow it to happen.
# 	echo "backup-$USER.$rdate.tar.bz2 has been restored."
# 	rm -rf /tmp/backup-light
	#a loop to restore from incremental backups goes here
}

compress=`cat ~/.backup-light/compression`	#to cut down on the issue with user settings gets changed after patching this has been moved to a config file
backupdir=`cat ~/.backup-light/backuppath` #to cut down on the issue with user settings gets changed after patching this has been moved to a config file
tsfile="$HOME/.backup-light/backup.timestamp" #moving the timestamp and the log into a single directory in the users $HOME
btype="incremental"	# default to an incremental backup
noinc=0			#   and an update of the timestamp
date=$(date +%d%m%y)
excludedir="none"	# default to excluding nothing, instead of everything

while getopts "o:ife:rRdmnlvh" opt; do
  case "$opt" in
    o ) backupdir="$OPTARG";  	;;
    i ) btype="incremental";	;;
    f ) btype="full";		;;
    e ) excludedir="$OPTARG";	;;
    r ) restore;		;;
    R ) recover;		;;
    d ) disk;			;;
    m ) multi;			;;
    n ) noinc=1;		;;
    l ) log;			;;
    v ) version			;;
    h ) usageQuit		;;
  esac
done

if [ $compress == "bzip2" ] ; then
	comptype="bz2"
else
	comptype="gz"
fi

output="$backupdir/backup-$USER.$date.tar.$comptype"

shift $(( $OPTIND - 1 ))

echo "Doing $btype backup, saving output to $output..."
echo "Please wait for larger backups this could take some time"

if [ ! -d $backupdir ] ; then
	clear
	echo "Error: The device or directory is not mounted or is not present, can not backup"
	exit 1
fi

timestamp="$(date +%m%d%I%M)"

if [ "$btype" = "incremental" ] ; then
	if [ ! -f "$tsfile" ] ; then
		echo "Error: No backup.timestamp file found, can not perform Incremental backup" >&2
		echo "Do you want me to make one for you? (y/n) Note: This will run a full backup"
		read ans
		if [ $ans = "y" ] ; then
			find $HOME -depth -type f -user ${USER:-LOGNAME} | createBackup
			touch -t $timestamp $tsfile
			echo "Timestamp file has been made, and .backup.timestamp has been created"
			exit 0
		else
			echo "Exiting"
			exit 1
		fi
	fi
	echo "$date (Incremental)" >> ~/.backup-light/log
	find $HOME -depth -type f -newer $tsfile -user ${USER:-LOGNAME} | createBackup
else
	echo "$date (Full)" > ~/.backup-light/log
	find $HOME -depth -type f -user ${USER:-LOGNAME} | createBackup
fi

if [ "$noinc" = "0" ] ; then
	touch -t $timestamp $tsfile
	echo "The timestamp has been updated to:"
	ls -l ~/.backup-light/backup.timestamp | awk '{ print $6, $7;}'
fi

cd $backupdir
md5sum backup-$USER.$date.tar.* > backup-$USER.$date.MD5SUM  #If possable we need to remove the path to the file from the md5sum.

exit 0
