diff options
Diffstat (limited to 'destination')
-rw-r--r-- | destination | 169 |
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 |