aboutsummaryrefslogtreecommitdiff
path: root/destination
blob: 4829838b5bd28165f56d4212509bc67f466dbc73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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