#!/bin/sh

#
# Tarsnap helper tool to sync new backups and clean old ones
#
# Version:  0.14 (2013-05-13)
#
# "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/
#

# 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.bz2 2>/dev/null`
  do
    DATE=`echo ${file} | cut -d "-" -f 3 | cut -d "." -f 1`
    ARCHIVENAME=`basename ${file} .tar.bz2`
    ARCHIVEDIR="${TMP}/${ARCHIVENAME}"

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

    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 | grep "^${ARCHIVENAME}" >/dev/null ; then
      echo "Tarsnap archive for ${ARCHIVENAME} already exists"
      continue
    fi

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

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

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

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

    if ! tarsnap -c -f ${ARCHIVENAME} "${ARCHIVEDIR}" ; then
      rm -Rf "${ARCHIVEDIR}"
      echo "Tarsnap error while uploading ${file}"
      continue
    fi

    rm -Rf "${ARCHIVEDIR}"
    rm ${file}

    echo "Successfully uploaded ${file}"

  done

  return 0
}

tarsnap_clean()
{
  for machine in `tarsnap --list-archives | sort | cut -d'-' -f-2 | uniq`
  do
    tarsnap_cleanone $machine || return $?
  done

  return 0
}


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

  MACHINE=$1

  if [ -z "${MACHINE}" ]; then
    echo "Machine is not set"
    return 1
  fi

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

  for backup in `tarsnap --list-archives | grep "^${MACHINE}" | sort -r | tail -n +${KDB}`
  do
    backupdate=`echo ${backup} | cut -d'-' -f3`
    limit=`expr 2 "*" ${KWB}`
    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}" = "${backupdate}" ]; then
        echo "Keep weekly backup ${backup}"
        continue 2
      fi
    done

    limit=`expr 2 "*" ${KMB}`
    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}" = "${backupdate}" ]; then
        echo "Keep monthly backup ${backup}"
        continue 2
      fi
    done

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

  done

  return 0
}

tarsnap_check()
{
  if [ `uname` = "FreeBSD" ]; then
    HOSTNAME=`hostname -s`
  else
    HOSTNAME=`uname -n`
  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

