#!/bin/sh

#
# Tarsnap helper tool to sync new backups and clean old ones
#
# Version:  0.11 (24-01-2013)
#
# "THE BEER-WARE LICENSE" (Revision 42):
# <decke@bluelife.at> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return.
#
# Author:   Bernhard Froehlich <decke@bluelife.at>
# Homepage: http://www.bluelife.at/
#

# tarsnap key (default: ${HOME}/.tarsnap.subdomain.key)
KEY=

# backup directories
SOURCE=/backup
TMP=/backup

# number of recent daily/weekly/monthly backups to keep
KEEPDAILYBACKUPS=3
KEEPWEEKLYBACKUPS=1
KEEPMONTHLYBACKUPS=1


tarsnap_sync()
{
  for file in `ls ${SOURCE}/*.tar.* 2>/dev/null`
  do
    DATE=`echo ${file} | cut -d "-" -f 3 | cut -d "." -f 1`

    echo "Preparing to upload Backup from ${DATE}" 

    if [ `echo ${DATE} | cut -b 1-2` != "20" ] ; then
      echo "Date ${DATE} does not look like a valid date"
      continue
    fi

    if [ `echo ${DATE} | wc -c` != 9 ] ; then
      echo "Date ${DATE} has invalid length"
      continue
    fi

    if tarsnap --list-archives --key "${KEY}" | grep ${DATE} >/dev/null ; then
      echo "Tarsnap archive for ${DATE} already exists"
      continue
    fi

    if [ -d "${TMP}/${DATE}" ]; then
      echo "Directory ${TMP}/${DATE} already exists!"
      continue
    fi

    if ! mkdir "${TMP}/${DATE}" ; then
      echo "Could not create ${TMP}/${DATE} directory!"
      continue
    fi

    if ! cd "${TMP}/${DATE}" ; then
      rm -Rf "${TMP}/${DATE}"
      echo "Could not change to ${TMP}/${DATE}"
      continue
    fi

    if ! tar xvf "${file}" 2>/dev/null ; then
      rm -Rf "${TMP}/${DATE}"
      echo "Error while extracting backup ${file}"
      continue
    fi

    if ! tarsnap -c --keyfile "${KEY}" -f ${DATE} "${TMP}/${DATE}" ; then
      rm -Rf "${TMP}/${DATE}"
      echo "Tarsnap error while uploading ${file}"
      continue
    fi

    rm -Rf "${TMP}/${DATE}"
    rm ${file}

    echo "Successfully uploaded ${file}"

  done

  return 0
}

tarsnap_clean()
{
  LOOPS="0 1 2 3 4 5 6 7 8 9"
  KEEPDAILYBACKUPSINC=`expr ${KEEPDAILYBACKUPS} + 1`
  KEEPWEEKLYBACKUPS=`expr ${KEEPWEEKLYBACKUPS} + 1`
  KEEPMONTHLYBACKUPS=`expr ${KEEPMONTHLYBACKUPS} + 1`

  for backup in `tarsnap --list-archives --key ${KEY} | sort -r | head -n +${KEEPDAILYBACKUPS}`
  do
    echo "Keep daily backup ${backup}"
  done

  for backup in `tarsnap --list-archives --key ${KEY} | sort -r | tail -n +${KEEPDAILYBACKUPSINC}`
  do
    limit=`expr 2 "*" ${KEEPWEEKLYBACKUPS}`
    for week in `echo "${LOOPS}" | head -c ${limit}`
    do
      if [ `uname` = "FreeBSD" ]; then
        weeklybackup=`date -v-${week}w -v-sun -v0H -v0M -v0S "+%Y%m%d"`
      else
        weeklybackup=`date --date="${week} week ago" "+%Y%m%d"`
      fi

      if [ "${weeklybackup}" = "${backup}" ]; then
        echo "Keep weekly backup ${backup}"
        continue 2
      fi
    done

    limit=`expr 2 "*" ${KEEPMONTHLYBACKUPS}`
    for month in `echo "${LOOPS}" | head -c ${limit}`
    do
      if [ `uname` = "FreeBSD" ]; then
        monthlybackup=`date -v-${month}m -v1d -v0H -v0M -v0S "+%Y%m%d"`
      else
        monthlybackup=`date --date="${month} month ago" "+%Y%m%d"`
      fi

      if [ "${monthlybackup}" = "${backup}" ]; then
        echo "Keep monthly backup ${backup}"
        continue 2
      fi
    done

    echo "Removing backup ${backup}"
    tarsnap -d --key ${KEY} -f ${backup}

  done

  return 0
}

tarsnap_check()
{
  if [ `uname` = "FreeBSD" ]; then
    HOSTNAME=`hostname -s`
  else
    HOSTNAME=`uname -n`
  fi

  if [ "${KEY}" = "" ]; then
    if [ -f "${HOME}/.tarsnap.${HOSTNAME}.key" ]; then
      KEY=${HOME}/.tarsnap.${HOSTNAME}.key
    fi
  fi

  if [ ! -f "${KEY}" ]; then
    echo "Tarsnap keyfile ${KEY} does not exist"
    return 1
  fi

  if [ ! -d "${SOURCE}" ]; then
    echo "SOURCE ${SOURCE} does not exist"
    return 1
  fi

  if [ ! -d "${TMP}" ]; then
    echo "TMP ${TMP} does not exist"
    return 1
  fi

  return 0
}

case "$1" in
'sync')
  tarsnap_check && \
  tarsnap_sync
  exit $?
;;
'clean')
  tarsnap_check && \
  tarsnap_clean
  exit $?
;;
*)
  echo "Usage: $0 [sync|clean]"
  exit 1
;;
esac

exit 0

