#!/bin/bash
# By Thomas KUSCHEL <oe1tkt@gmail.com>
# MIT License 2015
VERSION="v6.15"
set -o errexit # to make script exit when a command fails / a.k.a. set -e
# then add "|| true" to commands that you allow to fail.
set -o nounset # to exit when script tries to use undeclared variables / set -u
# set -o xtrace  # to trace when gets executed for debugging / a.k.a. set -x
set -o pipefail
SCRIPTNAME=${0##*/}
SCRIPTPATH=$(dirname "$0")
# echo $SCRIPTNAME
# where the btrfs is found (use command: which btrfs)
WHICH="/usr/bin/which"
BTRFS_ALT="/sbin/btrfs"
BTRFS="/usr/local/bin/btrfs"
# Function to install this script:
installation() {
# you have to switch to administrator
#`${WHICH} ${PATHINSTALL}`
PATHINSTALL="/usr/local/bin"
SNAPSYSTEMDCFG="/etc/systemd/system/"
SCRIPTPATH=$(dirname "$0")
# echo "Installation of ${SCRIPTNAME} to ${PATHINSTALL} and create systemd timer/service examples in ${SNAPSYSTEMDCFG}"
read -n 1 -p "Install ${SCRIPTNAME} to ${PATHINSTALL}? [Y/n] " reply;
 if [ "$reply" != "" ]; then echo; fi
 if [ "$reply" = "${reply#[Nn]}" ]; then
  sudo cp $0 ${PATHINSTALL}/${SCRIPTNAME}
 fi
 read -n 1 -p "Do you want to create systemd timer/service examples in ${SNAPSYSTEMDCFG}? [Y/n] " reply;
 if [ "$reply" != "" ]; then echo; fi
 if [ "$reply" = "${reply#[Nn]}" ]; then
  sudo cp -a ${SCRIPTPATH}/system/. ${SNAPSYSTEMDCFG}.
  path=`$WHICH $SCRIPTNAME`
 fi
}

deinstallation() {
PATHINSTALL="/usr/local/bin"
read -n 1 -p "Do you want to remove (deinstallation) of ${SCRIPTNAME} in ${PATHINSTALL}? [Y/n] " reply;
 if [ "$reply" != "" ]; then echo; fi
 if [ "$reply" = "${reply#[Nn]}" ]; then
  sudo rm -f ${PATHINSTALL}/${SCRIPTNAME}
 fi
}

# Function to display usage:
usage() {
path=`${WHICH} ${SCRIPTNAME}` || installation
if [ -z "${path}" ] ; then
	path="/usr/local/bin/"
	echo "Please install $SCRIPTNAME to \"$path\""
	path="${path}${SCRIPTNAME}"
fi
cat <<EOF
$SCRIPTNAME: Take and rotate snapshots on a btrfs file system

usage: $SCRIPTNAME [--version] source target snap_name count [-q]
  source:    path to make snaphots of
  target:    snapshot directory
  snap_name: Base name for snapshots, to be appended to
             date "+%F-%H%M"
  count:     Number of snapshots in the timestamp-@snap_name format to
             keep at one time for a given snap_name.
  [-q]:      Be quiet.
  --install: Force a new installation of this script.
  --version: Print the version of this script,
             additionally the version of btrfs-progs.

Example for crontab:
15,30,45 * * * *  root $0 /home /snap quarterly 4 -q
0        * * * *  root $0 /home /snap hourly 8 -q

Example for anacrontab:
1        15 daily_snap   $0 /home /snap daily 8
7        17 weekly_snap  $0 /home /snap weekly 5
@monthly 19 monthly_snap $0 /home /snap monthly 3

NEW: If you are using systemd on your linux system, see http://f0x.at/btrfs
EOF
 exit
}
if [ ! -f "$BTRFS" ] ; then
	if [ -f "$BTRFS_ALT" ] ; then
		# fallback
		BTRFS="$BTRFS_ALT"
	else
		echo "$BTRFS system file not found,"
		echo "please install btrfs-progs:"
		echo "Arch Linux:    # sudo pacman -S btrfs-progs"
		echo "Debian/Ubuntu: # sudo apt-get install btrfs-tools"
		exit
	fi
fi
# Basic argument checks:
if [ $# -gt 0 ] && [ "x$1" == "x--version" ] ; then
	echo "$SCRIPTNAME $VERSION"
	echo `$BTRFS --version`
	exit
fi
if [ $# -gt 0 ] && [ "x$1" == "x--install" ] ; then
	installation
	exit
fi
if [ $# -gt 0 ] && [ "x$1" == "x--deinstall" ] ; then
	deinstallation
	exit
fi

# Check count of arguments
if [ "$#" -ge 4 ]; then
	SOURCE=$1
	TARGET=$2
	SNAP=$3
	COUNT=$4
	QUIET=""
	if [ "$#" -gt 4 ]; then
		QUIET=$5
	fi
else
	echo "You need some arguments."
	usage
fi
if [ $# -gt 5 ] ; then
    echo "Too many parameters."
    usage
fi
if [ -n "$QUIET" ] && [ "x$QUIET" != "x-q"  ] ; then
    echo "Parameter 4 is either -q or empty. Given: \"$QUIET\""
    usage
fi
# $max_snap is the highest number of snapshots that will be kept for $SNAP.
max_snap=$(($COUNT -1))

# Check if $TARGET already exists - if NOT then create subdir
[ -d $TARGET ] || mkdir $TARGET

# Clean up older snapshots:
for i in `ls $TARGET|sort |grep @${SNAP}|head -n -${max_snap}`; do
	cmd="$BTRFS subvolume delete $TARGET/$i"
	if [ -z $QUIET ]; then
		echo $cmd
	fi
	$cmd >/dev/null
done
# Create new snapshot:
cmd="$BTRFS subvolume snapshot -r $SOURCE $TARGET/`date "+%F-%H%M-@${SNAP}"`"
if [ -z $QUIET ]; then
	echo $cmd
fi
$cmd >/dev/null
