aboutsummaryrefslogtreecommitdiff
path: root/destination
diff options
context:
space:
mode:
Diffstat (limited to 'destination')
-rw-r--r--destination169
1 files changed, 169 insertions, 0 deletions
diff --git a/destination b/destination
new file mode 100644
index 0000000..4829838
--- /dev/null
+++ b/destination
@@ -0,0 +1,169 @@
+#!/usr/bin/env bash
+#
+# destination - functions acting on the destination host.
+#
+# Copyright 2015 - 2019 Einhard Leichtfuß
+#
+# This file is part of rsync-backup.
+#
+# rsync-backup is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# rsync-backup 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with rsync-backup. If not, see <https://www.gnu.org/licenses/>.
+#
+
+
+# Setup working directory on the destination files system.
+#
+# requires: create_new_dir
+#
+function dest_prepare_initial
+{
+ create_new_dir "$dest_path" || return $?
+ create_new_dir "${dest_path}/work" || return $?
+
+ return $RET_SUCCESS
+}
+
+
+# Setup working directory on the destination file system, check for too new
+# (future) backups and refresh the 'latest' symlink.
+#
+# requires: assert_is_dir, dest_list_backup_dirs, create_new_dir
+# $dest_path
+#
+# $1: old date: date in $DATEFMT
+# $2: new date: date in $DATEFMT
+#
+function dest_prepare_incremental
+{
+ local work_dir="${dest_path}/work"
+ local old_date="$1"
+ local new_date="$2"
+ local latest
+
+ assert_is_dir "$dest_path" || return $?
+
+ latest="$(dest_list_backup_dirs | tail -1)"
+
+ if [[ "$old_date" != "$latest" ]]
+ then
+ error "Dates of last backup do not match on source and destination."
+ debug_error "source: ${old_date} | dest: ${latest}"
+ return $RET_FILE_ERR
+ fi
+
+ if ! [[ "$latest" < "$new_date" ]]
+ then
+ error "Latest backup on destination not older than source."
+ return $RET_FILE_ERR
+ fi
+
+ # Refresh 'latest' symlink in case it was obsoleted or corrupted.
+ ln -sfT "$latest" "${dest_path}/latest" || return $RET_ERROR
+
+ create_new_dir "$work_dir" || return $?
+
+ return $RET_SUCCESS
+}
+
+
+# Finalize the backup creation on the destination host.
+#
+# requires: dest_refresh_symlinks
+# `-> assert_is_dir, dest_list_backup_dirs,
+# replace_symlink_target, create_dir
+# $dest_path (self, <- dest_refresh_symlinks),
+#
+# $1: old date: date in $DATEFMT
+# $2: new date: date in $DATEFMT
+#
+function dest_finalize
+{
+ local old_date="$1"
+ local new_date="$2"
+
+ message "Finish installment of new backup..."
+ mv -T "${dest_path}/work/${new_date}" "${dest_path}/${new_date}" \
+ || return $RET_ERROR
+
+ message "Remove auxiliary directory tree..."
+ rm -rf "${dest_path}/work/${old_date}" || return $RET_ERROR
+ rmdir "${dest_path}/work" || return $RET_ERROR
+
+ dest_refresh_symlinks || return $?
+
+ message 'Successfully finished installment of new backup.'
+}
+
+
+# Print existing backup directories.
+# Must be run on destination host.
+#
+# requires: $dest_path
+#
+function dest_list_backup_dirs
+{
+ find "$dest_path" -mindepth 1 -maxdepth 1 -type d \
+ -regextype posix-extended -regex \
+ '.*/[0-9]{4}-[0-1][0-9]-[0-3][0-9]_[0-2][0-9]([0-5][0-9]){2}' \
+ -printf '%f\n' \
+ | LC_ALL=C sort
+
+ if [[ ${PIPESTATUS[0]} -eq 0 && ${PIPESTATUS[1]} -eq 0 ]]
+ then
+ return $RET_SUCCESS
+ else
+ return $RET_ERROR
+ fi
+}
+
+
+# Create symbolic links to backup directories.
+#
+# requires: assert_is_dir, dest_list_backup_dirs, replace_symlink_target,
+# create_dir
+# $dest_path
+#
+function dest_refresh_symlinks
+{
+ local -i i
+ local -i n
+ local -a backup_dirs
+ local link
+ local ret
+
+ assert_is_dir "$dest_path" || return $?
+
+ backup_dirs=( $(dest_list_backup_dirs || return $?) )
+ n=${#backup_dirs[@]}
+
+ replace_symlink_target "${dest_path}/latest" "${backup_dirs[n-1]}" \
+ || return $?
+
+ ## by_number
+ numdir="${dest_path}/by_number"
+ create_dir "$numdir" || return $?
+
+ # Remove old symlinks.
+ find "$numdir" -mindepth 1 -maxdepth 1 -type l -regextype posix-extended \
+ -regex '.*/[0-9]*' -delete || return $RET_ERROR
+
+ for (( i = 0; i < n; i++ ))
+ do
+ ln -s "../${backup_dirs[i]}" "$(printf "%s/%.${#n}u" "$numdir" $i)" \
+ || return $RET_FILE_ERR
+ done
+
+ return $RET_SUCCESS
+}
+
+# vi: ft=bash ts=2 sw=2 noet