ulthar.xyz > Repos

dotfiles

Seven years worth of accumulated configuration cruft
About Files Commits git clone https://ulthar.xyz/repos/dotfiles/dotfiles.git

dotfiles/scripts/.local/bin/bak

Download raw file: scripts/.local/bin/bak

#!/bin/sh
# Create archives of portions of my home directory and back up the
# whole thing to external drives.  Depends on restic and rsync.

# source `which bak` && bakmnt
# https://wiki.archlinux.org/title/Persistent_block_device_naming#by-label
# FIXME: How portable is /dev/disk/by-label?  Maybe I should use fstab
# for this instead.
bakmnt() {
	fat_opts="rw,uid=$(id -u),gid=$(id -g),fmask=137,dmask=027"
	sudo zpool import backup3
	sudo mount /dev/disk/by-label/Backup2     /backup/backup2
	sudo mount /dev/disk/by-label/KOBOeReader /backup/ereader -o "$fat_opts" -t vfat
	sudo mount /dev/disk/by-label/PhoneSDcard /backup/sdcard  -o "$fat_opts" -t exfat-fuse
}

say() { printf "\033[1m==========> %s\033[m\n" "$1"; }

directory_is_accessible() {
	if test "${1#*sftp:}" = "$1"; then
		[ -w "$1" ] || {
			echo "Directory $1 doesn't exist or isn't writable, skipping"
			return 1
		}
		mount | grep "$1" >/dev/null || {
			echo "Disk not mounted on $1, skipping"
			return 1
		}
	fi
	return 0
}

backup_important_dir() {
	src="$1"
	dst="$HOME/archive/backups/$(basename "$src")"
	say "Backing up directory $1"
	# shellcheck disable=SC2015
	[ -w "$dst" ] && [ -f "$dst/config" ] || {
		mkdir -p "$dst"
		restic -r "$dst" --insecure-no-password init
	}
	restic -r "$dst" --insecure-no-password backup "$src"
}

backup_home_to() {
	say "Backing up home directory to $1:"
	if directory_is_accessible "$1"; then
		restic -r "$1" \
		       --password-command "pass machines/backup_disks" \
		       backup "$HOME" \
		       --exclude-caches \
		       --exclude "$HOME/temporary/torrents/" \
		       --exclude "$HOME/.local/go" \
		       --exclude "$HOME/.local/quicklisp" \
		       --exclude "$HOME/.local/share/Trash" \
		       --exclude "$HOME/.local/share/julia/" \
		       --exclude "$HOME/.local/share/recoll/xapiandb/" \
		       --exclude "$HOME/.cache"
	else
		return 0
	fi
}

# DOS filesystems are awfully picky about what characters they allow.
# Add as they come up
dos_strip() { echo "$1" | sed 's/://g'; }

# I had thought that passing `-rlt` to rysnc should get archive-ish
# functionality to the exfat partition without spitting errors about
# nonexistent file permission support, however somewhere along the way
# the file mod times get clobbered so we end up draining the card's
# limited write lifetime with slow, redundant transfers.  This
# function is a workaround for that.
diff_copy_when_archaic_fs() {
	src="$1"
	dst="$2"
	say "Copying $src to $dst"
	if [ -d "$src" ] && [ -w "$dst" ]; then
		find "$src" -type f | while read -r srcpath; do
			relpath="${srcpath##"$src"/}"
			dstpath="$dst/$(dos_strip "$relpath")"
			# Copy the file over iff it doesn't exist at
			# the destination.
			if [ ! -f "$dstpath" ]; then
				mkdir -p -v "$(dirname "$dstpath")"
				cp -v "$srcpath" "$dstpath"
				# When the source is on the archaic
				# file system, fix the new file's
				# permissions to -rw-r--r--
				if mount | grep "$src" >/dev/null 2>&1; then
					chmod -v 644 "$dstpath"
				fi
			fi
			# If the destination already exists, skip it.
			# FIXME could be good to do primitve change
			# checking by comparing file size
		done
	elif [ ! -d "$src" ]; then
		echo "Directory $src doesn't exist, skipping"
	elif [ ! -w "$dst" ]; then
		echo "Directory $dst doesn't exist or isn't writable, skipping"
	fi
}

# If-guard allows this script to be sourced as a library by an
# interactive shell or another shell script
if [ "$(basename "$0")" = "bak" ] && ! (return >/dev/null 2>&1); then
	set -e
	diff_copy_when_archaic_fs "/backup/sdcard/Backups/Signal" "$HOME/archive/backups/signal"
	diff_copy_when_archaic_fs "/backup/sdcard/Backups/AntennaPod" "$HOME/archive/backups/antennapod"
	diff_copy_when_archaic_fs "$HOME/media/music" "/backup/sdcard/Music"
	diff_copy_when_archaic_fs "$HOME/media/audiobooks" "/backup/sdcard/Audiobooks"
	diff_copy_when_archaic_fs "$HOME/media/books" "/backup/ereader/personal/Books"
	diff_copy_when_archaic_fs "$HOME/media/papers" "/backup/ereader/personal/Papers"
	diff_copy_when_archaic_fs "$HOME/media/webpages" "/backup/ereader/personal/Webpages"
	backup_important_dir "$HOME/org"
	backup_important_dir "$HOME/wiki"
	backup_important_dir "$HOME/secrets"
	backup_home_to "/backup/backup1"
	backup_home_to "/backup/backup2"
	backup_home_to "/backup/backup3"
fi
Generated 2025-03-07 15:24:27 -0700 by RepoRat