#!/bin/bash
#
# syncs the given directory (or file) to the configured backup space

. /usr/lib/bsclient/load_environment

DIR=$1
if [ -z "$DIR" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): ERROR: No directory (or file) to backup given."
  exit 2
fi

if [ ! -e "$DIR" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): ERROR: No such file or directory: $DIR"
  exit 3
fi

if [ ! -d "$DIR" ] ; then
  if [ ! -f "$DIR" ] ; then
    echo "$(date +%Y-%m-%d\ %H:%M:%S): ERROR: $DIR is neither a file nor a directory:"
    ls -ld $DIR
    exit 4
  fi
fi

export FILE="$DIR"
if [ ! -d "$DIR" ] ; then
  DIR=$(dirname $FILE)
fi

ABSDIR=$(echo "$DIR" |egrep '^/')
if [ -z "$ABSDIR" ]
then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): ERROR: Path not absolute: ${DIR}"
  exit 11
fi

EVILDIR=$(echo "$DIR" |egrep '^/($|dev|proc|sys)')
if [ ! -z "$EVILDIR" ]
then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): ERROR: Path not allowed: ${DIR}"
  exit 12
fi

if [ -d "${FILE}" ] ; then
  FILE="${FILE}/"
fi

#echo "DIR=${DIR}"
#echo "FILE=${FILE}"

# OK, go to work

# sooner or later we might have multiple backup generations on most hosts
# this also makes sure we have access

if [ "$BAKMKDIRMODE" = "sftp" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): INFO: Creating remote target dir for $DIR via sftp"
  export SDPATH="${BAKDESTBASE}"
  ( echo $DIR |sed -e 's/^\///' |sed -e 's/\//\/\n/g' |while read SDPART ; do
      SDPATH="${SDPATH}/${SDPART}"
      echo "mkdir $SDPATH"
    done ) | SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" sftp -i ${BAKSSHIDFILE} ${BAKUSER}@${BAKHOST}
  #exit 99
else
  echo "$(date +%Y-%m-%d\ %H:%M:%S): INFO: Creating remote target dir for $DIR via ssh mkdir"
  ( SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" ssh -i ${BAKSSHIDFILE} ${BAKUSER}@${BAKHOST} mkdir -pv ${BAKDESTBASE}/$DIR ) || \
    ( SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" ssh -i ${BAKSSHIDFILE} ${BAKUSER}@${BAKHOST} mkdir -pv ${BAKDESTBASE}/$DIR ) || \
    exit 12
fi

shift
export SYNCOPTIONS=""
if [ -n "$*" ] ; then
  export SYNCOPTIONS="$*"
fi
DIRLISTFILES=$(ls -1d ${BSCLIENT_ETC_DIR}/dirs2backup ${BSCLIENT_ETC_DIR}/bsclient-etc-dirs.d/*/dirs2backup 2>/dev/null |sort)
SYNCOPTIONS="$SYNCOPTIONS "$(egrep "^$DIR " ${DIRLISTFILES} |cut -f2- -d ' ')
if [ ! "${SYNCOPTIONS}" = " " ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): INFO: Using special rsync options:"
  echo "  ${SYNCOPTIONS}"
fi

export RSYNCOPTIONS="-r --compress --partial --progress --delete --delete-after --force -g -l -o -p -v -S -t -x --timeout=30"
if [ -z "${BAKSSHIDFILE}" ] ; then
  RSYNCOPTIONS="${RSYNCOPTIONS} --rsh "'"'"ssh -i ${BAKSSHIDFILE}"'"'
else
  RSYNCOPTIONS="${RSYNCOPTIONS} --rsh ssh"
fi

echo "$(date +%Y-%m-%d\ %H:%M:%S): INFO: Synching ${FILE}"
#XSOK="no"
RC=-1
echo 'Calling   SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY=""'" rsync ${RSYNCOPTIONS} ${SYNCOPTIONS} ${FILE} ${BAKUSER}@${BAKHOST}:${BAKDESTBASE}/${FILE}"
SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" rsync ${RSYNCOPTIONS} ${SYNCOPTIONS} ${FILE} ${BAKUSER}@${BAKHOST}:${BAKDESTBASE}/${FILE} ${SSHIDFILEOPTION} ; RC=$?
if [ "$RC" = "24" ] ; then echo "WARNING: Initial rsync exited with code 24 about vanished source files, treating this as successful sync." ; RC=0 ; fi
if [ "$RC" != "0" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): WARNING: Initial rsync failed with exit code ${RC}, retry 1 ..."
  SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" rsync ${RSYNCOPTIONS} ${SYNCOPTIONS} ${FILE} ${BAKUSER}@${BAKHOST}:${BAKDESTBASE}/${FILE} ${SSHIDFILEOPTION} ; RC=$?
  if [ "$RC" = "24" ] ; then echo "Retry 1 rsync exited with code 24 about vanished source files, treating this as successful sync." ; RC=0 ; fi
fi
if [ "$RC" != "0" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): WARNING: Retry 1 rsync failed with exit code ${RC}, retry 2 ..."
  SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" rsync ${RSYNCOPTIONS} ${SYNCOPTIONS} ${FILE} ${BAKUSER}@${BAKHOST}:${BAKDESTBASE}/${FILE} ${SSHIDFILEOPTION} ; RC=$?
  if [ "$RC" = "24" ] ; then echo "WARNING: Retry 2 rsync exited with code 24 about vanished source files, treating this as successful sync." ; RC=0 ; fi
fi
if [ "$RC" != "0" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): WARNING: Retry 2 rsync failed with exit code ${RC}, retry 3 ..."
  SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" rsync ${RSYNCOPTIONS} ${SYNCOPTIONS} ${FILE} ${BAKUSER}@${BAKHOST}:${BAKDESTBASE}/${FILE} ${SSHIDFILEOPTION} ; RC=$?
  if [ "$RC" = "24" ] ; then echo "WARNING: Retry 3 rsync exited with code 24 about vanished source files, treating this as successful sync." ; RC=0 ; fi
fi
if [ "$RC" != "0" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): WARNING: Retry 3 rsync failed with exit code ${RC}, retry 4 ..."
  SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" rsync ${RSYNCOPTIONS} ${SYNCOPTIONS} ${FILE} ${BAKUSER}@${BAKHOST}:${BAKDESTBASE}/${FILE} ${SSHIDFILEOPTION} ; RC=$?
  if [ "$RC" = "24" ] ; then echo "WARNING: Retry 4 rsync exited with code 24 about vanished source files, treating this as successful sync." ; RC=0 ; fi
fi
if [ "$RC" != "0" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): WARNING: Retry 4 rsync failed with exit code ${RC}, retry 5 ..."
  SSH_AUTH_SOCK="" SSH_CLIENT="" SSH_CONNECTION="" SSH_TTY="" rsync ${RSYNCOPTIONS} ${SYNCOPTIONS} ${FILE} ${BAKUSER}@${BAKHOST}:${BAKDESTBASE}/${FILE} ${SSHIDFILEOPTION} ; RC=$?
  if [ "$RC" = "24" ] ; then echo "WARNING: Retry 5 rsync exited with code 24 about vanished source files, treating this as successful sync." ; RC=0 ; fi
fi
if [ "$RC" != "0" ] ; then
  echo "$(date +%Y-%m-%d\ %H:%M:%S): ERROR: Final retry 5 rsync failed with exit code ${RC}. FAILED to backup ${FILE} 5 times, giving up"
  exit 10
fi

echo "$(date +%Y-%m-%d\ %H:%M:%S): GOOD: Finished syncing ${FILE} to ${BAKHOST}"

