Package: backupninja
Version: 1.2.2-1
Severity: normal
Package: backupninja
Version: 1.2.2-1
Severity: important
Tags: patch
--- Problem description
The rsync handler's rotate_long (and rotate_long_remote) functions contain
three bugs that together cause long-format backup rotation to stall silently
after a few cycles.
--- Bug 1 -- cuttoff_time calculation wrong for weekly/monthly
rotate_long currently reads:
cutoff_time=$(( now - (seconds*(i-1)) ))
For daily rotations this is correct (base_age = 0), but for weekly and monthly
it does not account for the time needed to fill all preceding tiers.
Example with keepdaily=5, keepweekly=3:
weekly.1: cutoff = now - 0 (immediately eligible for promotion)
monthly.1: cutoff = now - 0 (immediately eligible)
Instead they should take, respectively, 5 days and 26 days before being
rotated.
Fix: add base_age so that weekly/monthly only rotate after lower
tiers have been filled:
if [ "$rottype" == "daily" ]; then
base_age=0
elif [ "$rottype" == "weekly" ]; then
base_age=$((keepdaily * 86400))
elif [ "$rottype" == "monthly" ]; then
base_age=$(((keepdaily * 86400) + (keepweekly * 604800)))
fi
cutoff_time=$(( now - (base_age + (i * seconds)) ))
--- Bug 2 -- created file lost on daily/weekly promotion
When daily.MAX is promoted to weekly.1 (or weekly.MAX to monthly.1), the
original handler discards the "created" metadata file from the source directory
and writes only a new "rotated" file:
date +%c%n%s > metadata/rotated
#if [ -f metadata/daily.$max/created ]; then
# mv ... (commented out)
#fi
Over successive cycles every backup in a tier ends up with the same promotion
timestamp instead of the original backup creation time. The age calculation
sees all of them as equally new, which produces infinite "skipping rotation"
messages.
Fix: restore the mv of created into the promoted directory:
if [ -f $backuproot/metadata/daily.$max/created ]; then
$nice mv $backuproot/metadata/daily.$max/created \
$backuproot/metadata/weekly.1/
fi
(Same change needed on the weekly->monthly promotion and in
rotate_long_remote.)
--- Bug 3 -- no fallback when only "rotated" exists
rotate_long currently reads:
if [ -f $metadata.$i/created ]; then
$nice mv $metadata.$i/created $metadata.$next
fi
If a backup directory only has a "rotated" file (common after Bug 2 has
corrupted the metadata), the timestamp is silently lost during the shift. The
next iteration reads "created=0", triggers "Invalid metadata", and aborts the
rotation loop.
Fix:
if [ -f $metadata.$i/created ]; then
$nice mv $metadata.$i/created $metadata.$next
elif [ -f $metadata.$i/rotated ]; then
$nice mv $metadata.$i/rotated $metadata.$next/created
fi
--- Repairing existing corrupted timestamps
Backup sets already affected (all monthly.* metadata showing the
same date) can be repaired with:
for d in /path/to/backup/section/weekly.*
/path/to/backup/section/monthly.*; do
mtime=$(stat -c '%Y' "$d")
printf '%(%c)T\n%s\n' "$mtime" "$mtime" > "$(dirname
$d)/metadata/$(basename $d)/created"
done
--- Affected versions
The bugs affect both local (rotate_long) and remote (rotate_long_remote) code
paths.
-- System Information:
Debian Release: forky/sid
APT prefers testing
APT policy: (501, 'testing'), (500, 'stable-updates'), (500,
'stable-security'), (500, 'stable'), (50, 'unstable')
Architecture: amd64 (x86_64)
Kernel: Linux 7.0.10+deb14-amd64 (SMP w/12 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE,
TAINT_UNSIGNED_MODULE
Locale: LANG=it_IT.UTF-8, LC_CTYPE=it_IT.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages backupninja depends on:
ii bash 5.3-3
ii dialog 1.3-20260107-2
ii gawk 1:5.3.2-1
ii mawk 1.3.4.20260302-1
Versions of packages backupninja recommends:
ii bsd-mailx [mailx] 8.1.2-0.20220412cvs-1.1
Versions of packages backupninja suggests:
pn borgbackup <none>
ii bzip2 1.0.8-6+b2
pn debconf-utils <none>
pn duplicity <none>
ii fdisk 2.42.1-2
pn genisoimage <none>
pn hwinfo <none>
pn mdadm <none>
pn rdiff-backup <none>
pn restic <none>
ii rsync 3.4.3+ds1-2
pn subversion <none>
pn trickle <none>
ii util-linux 2.42.1-2
pn wodim <none>
-- Configuration Files:
/etc/backupninja.conf changed [not included]
-- no debconf information