#!/bin/bash

### backup-to-samba script
### Version 1.3
### Patrick Nagel / mail AT patrick-nagel DOT net
### 2006-02-05
###
### Known bugs:    * If the script is aborted there is no way to tidy up, so the
###                  samba share remains mounted and the (incomplete) archive
###                  file(s) aren't deleted.
###                * GPG encryption is done on the samba share which is quite
###                  inefficient, network-wise and needs 2 x the space of the
###                  backup on the samba share.
###                * Samba password will be shown on screen and is stored insecurely.
###                  Would be possible to ask the user to input the password,
###                  but I wanted to be able to call the backup script via cron
###                  or other scripts without user-interaction.
###                * Have to clean up the script (introduce functions and so on)
###
### Needed tools:  * dar (Disk ARchive, http://dar.linux.free.fr/)
###                [ * gpg (GnuPG, http://www.gnupg.org/)
###                    if you want to use GnuPG, don't forget to place your ~/.gnupg
###                    folder (containing the keys) in /root/.gnupg, otherwise
###                    gpg (run as root) won't find the key you specified ]
###
###                And of course smbmount and a samba share where you have enough
###                space and writing permissions.
###
### How to restore:
###
### * Boot with a Linux live-CD, for example Kanotix (includes dar, otherwise
###   get a static version of dar, it will run on nearly any Linux).
### * Create two mount points
###      mkdir /source /destination
### * Mount the samba share
###      mount -t smbfs -o username=$username //$host/$share /source
### [ * Make new file system on the destination drive if necessary (mkfs) ]
### * Mount destination partition
###      mount $destination /destination
### * Change to the destination directory (cd)
### * Restore
###      /wherever-your-dar-executable-is/dar -x /source/$basename.1.dar
###
### ChangeLog:
###
### V1.1 Added local_backup flag because I don't have access to my samba share
###      at that time, and I want to do backups to an external USB HDD.
###      It's not exactly beautiful now (perhaps I'll improve the code when
###      I have the time) - but it works with minimal changes.
###      Note that the backup destination is being mounted and needs an entry
###      in /etc/fstab
### V1.2 Don't remember
### V1.3 Added the automatic /mnt dir exclusion in system scenario


# Please change the following variables to your needs.

# Local backup (no samba share will be used) [ignores host, share, username and password]  = 1
# Samba backup  = 0
local_backup=1

# IP address / hostname of the samba server
host="sambaserver"

# Name of the share (begin with a slash!)
# If local backup the share is used as sub-directory
share="/backup"

# Mount point of the samba share on this system
# Mount point must be in /etc/fstab if doing local backups!
mountpoint="/mnt/backup"

# User for the samba share
username=patrick

# Get the password for the samba share (I know there are better places to store passwords)
password=$(cat /root/backup_pw)

# GPG ID (eMail address or GPG ID) with whose public key the backup files should be encrypted
gpgid="0x86E346D4"

# Base name of the backup (.dar) files - you can leave it like that, it will look like
# notebook-system-2005-06-11-161253
basename="`hostname`-$1-`date +%Y-%m-%d-%H%M%S`"

# Timeout in seconds for error and status messages (useful if you're running the script from an
# auto-closing terminal)
timeout=5

# Now to the cases, each case is one backup scenario, look at
# the examples and you'll see how to insert new scenarios.
# The variables 'gpg', 'sourcedir' and 'excludes' must be filled
# whereas
#	gpg		1 or 0 (1 = with encryption / 0 = without encryption)
#	sourcedir	/directory (source directory on this system all sub-
#			directories will be included in the backup, use
#			the 'excludes' variable to specify sub-directories
#			that you don't want to be included
#	excludes	-P directory (for every directory you want to exclude)

case "$1" in
	home)
		gpg=0
		sourcedir="/home/patrick"
		excludes="-P temp -P temp/aMule -P temp/aMule_noshare -P temp/aMule_temp -P .local/share/Trash"
	;;
	system)
		gpg=0
		sourcedir="/"
		# Automatically exclude all dirs under /mnt - they'll be re-generated as empty dirs.
		MNT_DIRS=$(ls -1 /mnt | sed -e 's/^/-P mnt\//' -e 's/$/ /' | tr -d '\n')
		excludes="-P home/patrick -P usr/portage/distfiles -P vm -P dev/pts -P proc -P sys -P tmp -P var/tmp -P usr/tmp ${MNT_DIRS}"
	;;
	vm)
		gpg=0
		sourcedir="/vm"
		excludes="-P isos"
	;;
	*)
		# Here comes the "help", change it to your needs.
		clear
		echo ""
		echo "Choose from the following backup scenarios"
		echo "and supply the name as parameter to this script:"
		echo ""
		echo "  home    (/home/patrick except temp)"
		echo "  system  (system except /home/patrick, /vm and distfiles)"
		echo "  vm      (/vm except /vm/isos)"
		echo ""
		echo "Press enter to quit."
		read
		exit
	;;
esac


# Here starts the part of the script that's actually doing something.
# No further changes are needed from here on.

###########################################################################
###########################################################################

# Summarize
clear
echo ""
echo "The following backup scenario has been chosen:"
echo ""
(($local_backup)) && echo "Local backup                      : yes"
(($local_backup)) || echo "Samba server                      : $host"
(($local_backup)) || echo "Samba share                       : $share"
echo "Mount point for the backup files  : $mountpoint"
(($local_backup)) && echo "Sub-directory                     : $share"
(($local_backup)) || echo "User for the samba share          : $username"
echo ""
echo "Base name of the backup archive   : $basename"
echo "Source directory                  : $sourcedir"
echo "Excluded sub-directory string     : $excludes"
echo ""
echo "The backup process will begin in $timeout seconds from now on..."
echo "Abort with CTRL-C."
echo ""
sleep $timeout

# Mount
if (($local_backup)); then
{
	echo ""
	echo "Mounting $mountpoint ..."
	echo ""
	{ mount $mountpoint && \
		{ echo ""; echo "... Mount successful."; sleep $timeout; }; } || \
		{ echo ""; echo "Error while mounting. Aborting."; \
			sleep $timeout; exit 1; }
	destination=$mountpoint$share
}
else
{	
	echo ""
	echo "Mounting $host$share"
	echo "as $username in $mountpoint ..."
	echo ""
	{ mount -t smbfs -o username=$username%$password //$host$share $mountpoint && \
		{ echo ""; echo "... Mount successful."; sleep $timeout; }; } || \
		{ echo ""; echo "Error while mounting samba share. Aborting."; \
			sleep $timeout; exit 1; }
	echo ""
	destination=$mountpoint
}
fi

# Backup
echo "Beginning backup process ..."
echo ""
{ dar -c "$destination/$basename" -s 2147482624 -N -v -b -w -z1 -D -R "$sourcedir" $excludes && \
	{ echo "" ; echo "... Backup successful."; }; } || \
	{ echo "" ; echo "Backup not successful, see error messages above." ; sleep $timeout ; \
		umount $mountpoint; exit 1; }
echo ""

# Encrypt
if ((gpg))
then
	echo "Encrypting backup archive(s) with gpg for $gpgid ..."
	{ { for i in `ls $mountpoint/$basename*`; do gpg -r $gpgid -e $i; done; } && \
		{ echo "" ; echo "... Encryption successful. Deleting unencrypted archive(s)." ; \
			rm -f $mountpoint/$basename*.dar; }; } || \
		{ echo "" ; echo "Encryption not successful, see error messages above." ; \
			sleep $timeout; umount $mountpoint; exit 1; }
fi

# Tidy up
sync
umount $mountpoint
sleep $timeout
exit 0
