#!/bin/bash
##
## Samba: Backup config and database files
## Copyright (c) 2019 SATOH Fumiyasu  @ OSS Technology Corp.
## 
## Lisence: GNU General Public License version 3
##

set -u
set -e
set -o pipefail
umask 0027

backup_config_file="${SAMBA_BACKUP_CONFIG_FILE:-/opt/osstech/etc/samba/backup.conf}"

sysconf_dir="/opt/osstech/etc/samba"
testparm="/opt/osstech/bin/testparm"
samba_tool="/opt/osstech/bin/samba-tool"
tdbbackup="/opt/osstech/bin/tdbbackup"
data_dir="/opt/osstech/var/lib/samba"
backup_dir="/opt/osstech/var/backup/samba"
backup_max_age="90"

[ -f "$backup_config_file" ] && . "$backup_config_file"

## Old samba_backup compatibility: Override options via environment variables
[ -n "${CONFDIR:+set}" ] && sysconf_dir="$CONFDIR"
[ -n "${DATADIR:+set}" ] && data_dir="$DATADIR"
[ -n "${WHERE:+set}" ] && backup_dir="$WHERE"
[ -n "${DAYS:+set}" ] && backup_max_age="$DAYS"

## ======================================================================

timestamp="$(date +%Y-%m-%d)"
backup_tmp_dir="$backup_dir/backup.$$.tmp"
backup_tmp_suffix=".$$.bak"

server_role="$("$testparm" --suppress-prompt 2>&1|sed -n 's/^Server role: //p')"

if [[ $server_role == ROLE_ACTIVE_DIRECTORY_DC ]]; then
  ## AD DC Backup Scheme
  ## ======================================================================

  "$samba_tool" domain backup offline --targetdir="$backup_dir"

elif [[ $server_role == ROLE_* ]]; then
  ## Legacy Backup Scheme
  ## ======================================================================

  atexit() {
    rc=$?
    rm -rf "$backup_tmp_dir" || true
    find "$data_dir" -name "*.[tl]db$backup_tmp_suffix" -exec rm {} + || true
    exit $rc
  }

  trap atexit EXIT INT TERM

  mkdir "$backup_tmp_dir"

  ## Backup config files
  ## ----------------------------------------------------------------------

  rm -rf "$backup_tmp_dir/conf"
  cp -rp "$sysconf_dir" "$backup_tmp_dir/conf"

  cd "$backup_tmp_dir"
  tar -cf - conf |gzip >"$backup_dir/conf.$timestamp.tar.gz"

  ## Backup database files
  ## ----------------------------------------------------------------------

  cd "$data_dir"

  ## AIX find(1) causes the error 'find: cannot execute :: No such file or directory'
  ## if '-exec ... +' action with no files, thus create a dummy file.
  [[ $(uname) == AIX ]] && touch "${0##*/}.dummy.tdb$backup_tmp_suffix"
  find . \
    -name "*.[tl]db$backup_tmp_suffix" \
    -exec rm {} + \
  ;

  ## Skip netlogon_creds_cli.tdb: https://bugzilla.samba.org/show_bug.cgi?id=13088
  find . \
    ! -name netlogon_creds_cli.tdb \
    -name "*.[tl]db" \
    -exec "$tdbbackup" -r -s "$backup_tmp_suffix" {} + \
  ;

  rm -rf "$backup_tmp_dir/data"
  mkdir "$backup_tmp_dir/data"
  tar -cf - -X <(echo '*.[lt]db'; echo msg.sock; echo ldapi; echo pipe; echo socket) . \
  |tar -xf - -C "$backup_tmp_dir/data" \
  ;

  cd "$backup_tmp_dir/data"
  find . \
    -name "*.[lt]db$backup_tmp_suffix" \
    -exec /bin/sh -c '
      for bak in "$@"; do
	db="${bak%.*.bak}"
	mv "$bak" "$db" || exit $?
      done
    ' sh {} + \
  ;

  cd "$backup_tmp_dir"
  tar -cf - data |gzip >"$backup_dir/data.$timestamp.tar.gz"
fi

## Expire old backup files
## ======================================================================

find "$backup_dir" \
  -name "*.tar.*" \
  -mtime "+$backup_max_age" \
  -exec rm {} \; \
;

## ======================================================================

exit 0
