#!/bin/bash
#
# mnt_d			mountpoint pro backup disk .. nesmi byt obsazen, neni zde check, musi byt unikatni, nesmi obsahovat trailing "/"
# pwd_f			soubor s heslem, vytvori se pomoci: echo nejake_heslo > $cesta_na_zarizeni .. po kazdem (byt neuspesnem) pokusu je smazano
# exe_f			skript s backup instrukcema .. muze obsahovat cokoliv, neprovadi se jako root, jeho beh je zaznamenan v $debug_log a po provedeni nakopirovan z5 na backup zarizeni
# usr_b			jmeno uzivatelskeho uctu, pod kterym se backup provede. nesmi (nemel by) byt root
# key_f			trigger. Obnovuje se cronem denne v 16:00 .. je tedy mozne jen jedno provedeni $exe_f za 24 hodin
# disk_uuid		uuid disku, ktery je duveryhodny a na ktery backupujeme
# password		ocekavany md5sum souboru s heslem
# debug_log		vyse zmineny log behu zalohovaciho skriptu $exe_f
# mount_method		metoda, jakou se provede pripojeni .. nutno zmenit pro sve potreby, zde je predpoklad ntfs|vfat disku
# umount_method		metoda pro odpojeni .. -lf je pomerne nasilne .. mozna klidne jen cistej umount staci
# main_loop_rate	standardni delka hlavniho loopu co bezi 24/7 .. probehne polling blkid .. casy kolem 60-120 sekund jsou primerene
# success_rate		interval, v jakem se bude opakovat _make_warn v pripade uspechu .. default je pipani jednou za 10 sekund
# error_rate		interval, v jakem se bude pipat pri failu, default je 5 sekund .. v soucasne chcili znamena fail ze se nepodarilo disk odpojit, nemelo by nikdy nastat
# bad_config_rate	interval, v jakem se bude opakovat _make_warn v pripade spatne configurace: nepripojenej_disk, syntax error v $exe_f nebo nesedi/neexistuje heslo v $pwd_f
# _make_warn()		akce, co se provadi v danych intervalech

### TODO
## support for more disks - eg to can have more then one trusted disk_uuid
## support for trusted script repository, probably md5sum checks
## better resolution of final actions (eg current is only _make_warn() in several intervals)


#### debug saved to this semi-hardcoded path, uncomment if you want, beware, log file then constantly grows
#set -x;
#exec 2>/tmp/auto_backup.log

mnt_d=/mnt/backup;
pwd_f=$mnt_d/.password;
exe_f=$mnt_d/.orders;
usr_b=backup;
key_f=/tmp/.backup_enabled;
disk_uuid=902A-8B8A;
password=286755fad04869ca523320acce0dc6a4;
debug_log=/tmp/last_backup_log.txt;
mount_method="mount -vv -o rw,uid=$usr_b,gid=users";
umount_method="umount -lf";  ### probably not needed to *nuke mountpoint
main_loop_rate=120;
success_rate=10;
error_rate=5;
bad_config_rate=2;

_make_warn() {
	echo -e '\007';	
#	echo remove drive | wall;
};

while sleep $main_loop_rate; do
        _disk=`blkid | grep "$disk_uuid"`;
	_id=$RANDOM;
	_run=1;
	if ! test -z "$_disk" && test -f "$key_f"; then
		$mount_method `echo $_disk | sed 's/:.*//'` $mnt_d 2>&1 | logger;
		sleep 2;
		sync;

		#### Backup execution
		if grep $mnt_d /etc/mtab >/dev/null && test "$(md5sum $pwd_f | sed 's/\s.*//' 2>/dev/null)" == "$password" && bash -n $exe_f; then
			cp $exe_f /var/tmp/bckp_`date +%Y%m%d%H%M%S-$_id` 2>/dev/null;
			cat << EOF | logger;
#### $(date) id: $_id
#### starting with executing /mnt/backup.orders
EOF

			su $usr_b -c "set -x; exec 2>$debug_log; . $exe_f; set +x";

			cat << EOF | logger;
#### $(date) id: $_id
#### finished execution of /mnt/backup.orders
EOF
			cp $debug_log $mnt_d;
			rm -f $key_f 2>/dev/null;
			unset _run;
		fi
		#### End of execution, umount phase follows, from here comes error_rate in case of umounting fails
		
		rm -f $pwd_f 2>/dev/null;
		sync;
		while sleep $error_rate; do
			$umount_method $mnt_d 2>/dev/null;
			if ! grep $mnt_d /etc/mtab >/dev/null; then
				break;
			fi
			_make_warn;
		done

		#### Once umounted then 2 possible cases could happen
		#### success when $_run is unset or bad_config when not
		if test -z "$_run"; then
			echo "#### backup loop id: $_id successful finished" | logger;
			while sleep $success_rate; do
				if ! blkid | grep $disk_uuid >/dev/null; then
					break;
				fi
				_make_warn;
			done
		else
			while sleep $bad_config_rate; do
				if ! blkid | grep $disk_uuid >/dev/null; then
					break;
				fi
				_make_warn;
			done;
		fi
	fi
	unset _disk;
	unset _id;
done

