#!/bin/bash
#
# simplebackup - a simple backup script
#
# Copyright (C) 2004,2005,2006,2007,2008,2009,2011  Christian Garbs <mitch@cgarbs.de>
# licensed under GNU GPL v2 or later
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# initial setup
set -e
export PATH=/usr/sbin:/usr/bin:/sbin:/bin
RCFILE=~/.simplebackup.conf

# helper functions
echo_info() {
    if [ "$SILENT" != "1" -a \
         "$SILENT" != "true" ]; then
        echo "$@"
    fi
}

echo_warn() {
    echo "$@"
}

echo_err() {
    echo "$@" > /dev/stderr
}

# help wanted?
if [ "$1" = "-h" ]; then
    echo "usage:"
    echo -e "\t$0 [-h] [configuration_file]"
    exit 0
fi

# other configuration file given?
if [ "$1" ]; then
    RCFILE="$1"
fi

# check permissions on configuration file
if [ $(( 0$(stat -c %a "$RCFILE") & 0022 )) -gt 0 ] ; then
    echo_err Configuration file is writeable by group or others.
    echo_err As this file is executed under your userid, this is a
    echo_err security risk.  A malicious user could add a command to
    echo_err remove the contents of your home directory, for example.
    echo_err Change the permissions to something like 600 or 644.
    exit 2
fi

# set default values
unset SILENT
unset TARGETDIR
unset WORKDIR
unset BACKUPDIRS
unset BACKUPDIRS_ONEFS
unset NAME
unset LOCKFILE
unset NICELEVEL
unset CHROOT

extracommands() { :; }
postcopy() { :; }
postbackup() { :; }

# more initialization
source "$RCFILE"
TARGET="$NAME"-$(LANG=C date +%Y%m%d)

# check configuration
if [ -z "$TARGETDIR" ] ; then
    echo_err TARGETDIR is not set
    exit 3
else
    if [ ! -d "$TARGETDIR" ] ; then
	echo_err TARGETDIR is no directory
	exit 3
    fi
fi

if [ -z "$WORKDIR" ] ; then
    echo_err WORKDIR is not set
    exit 4
fi

if [ -z "${BACKUPDIRS}${BACKUPDIRS_ONEFS}" ] ; then
    echo_err neither BACKUPDIRS nor BACKUPDIRS_ONEFS is set
    exit 5
fi

if [ -z "$NAME" ] ; then
    echo_err NAME is not set
    exit 6
fi

if [ -z "$LOCKFILE" ] ; then
    echo_warn warning: no LOCKFILE is given, multiple instances may run
fi

if [ -z "$NICELEVEL" ] ; then
    NICELEVEL=0
fi

# init
if [ "$LOCKFILE" ] ; then
    [ -e "$LOCKFILE" ] && echo_err "another backup is already running" && exit 1
    echo $$ > "$LOCKFILE"
    trap 'STATUS=$?; echo_err "Received ERR $STATUS"; rm -f "$LOCKFILE"; exit $STATUS' ERR
    trap 'echo_err "Received SIGTERM"; rm -f "$LOCKFILE"; exit 98' SIGTERM
    trap 'echo_err "Received SIGINT"; rm -f "$LOCKFILE"; exit 99' SIGINT
fi
renice $NICELEVEL $$ > /dev/null

# prepare temporary directory
echo_info "setting up"
rm -rf "$WORKDIR"
mkdir -m 700 -p "$WORKDIR"
chown $UID "$WORKDIR"

# execute extra commands
(
    extracommands
)

# display chroot
if [ "$CHROOT" ]; then
    echo_info "chroot to $CHROOT"
    if [ ! -d "$CHROOT" ]; then
	echo_err "chroot path not found!"
	exit 3
    fi
fi

# backup files
OLDIFS="$IFS"
IFS=":"
for DIR in $BACKUPDIRS; do
    if [ -d "$CHROOT$DIR" ]; then
	echo_info "backing up $DIR"
	mkdir -p "$WORKDIR$DIR"
	(cd "$CHROOT$DIR" ; tar -c .) | (cd "$WORKDIR$DIR" ; tar -x)
    else
	echo_err "$DIR is no directory!"
    fi
done
for DIR in $BACKUPDIRS_ONEFS; do
    if [ -d "$CHROOT$DIR" ]; then
	echo_info "backing up $DIR (one fs)"
	mkdir -p "$WORKDIR$DIR"
	(cd "$CHROOT$DIR" ; tar -c --one-file-system .) | (cd "$WORKDIR$DIR" ; tar -x)
    else
	echo_err "$DIR is no directory!"
    fi
done
IFS="$OLDIFS"

# execute extra commands after copying
(
    postcopy
)

# build big archive
echo_info "renaming working directory"
cd "$TARGETDIR"
rm -rf "$TARGETDIR/$TARGET"
mv "$WORKDIR" "$TARGET"

echo_info "building archive"
BACKUPFILE="$TARGET.tar.bz2"
(
    umask 0377
    tar -cjf "$BACKUPFILE" "$TARGET"
)
rm -rf "$TARGET"

# execute postbackup commands
export BACKUPFILE
(
    postbackup
)

echo_info "finished"
[ "$LOCKFILE" ] && rm "$LOCKFILE"
exit 0
