]> code.delx.au - monosys/blob - bsnap
Fix Debian packaging
[monosys] / bsnap
1 #!/bin/bash
2
3 set -eu
4
5 function snap {
6 unsnap
7
8 mkdir -p /a
9
10 dispatch snap < /etc/fstab
11 }
12
13 function unsnap {
14 tac /etc/fstab | dispatch unsnap
15
16 if [ -d "/a" ]; then
17 rmdir /a
18 fi
19 }
20
21 function dispatch {
22 local action="" snaptype=""
23 local dev="" mnt="" fstype="" opts="" dump=""
24
25 while read -r dev mnt fstype opts dump pass; do
26 snaptype="$(get_snaptype "$fstype" "$dump")"
27 if [ -z "$snaptype" ]; then
28 continue
29 fi
30 action="${1}_${snaptype}"
31 echo "$action $mnt"
32 "$action" "$dev" "$mnt" "$opts"
33 done
34 }
35
36 function get_snaptype {
37 local fstype="$1" dump="$2"
38 if [ "$dump" = "1" ]; then
39 echo bind
40 elif [ "$dump" = "2" ] && [ "$fstype" = "btrfs" ]; then
41 echo btrfs
42 elif [ "$dump" = "2" ]; then
43 echo lvm
44 fi
45 }
46
47 function snap_bind {
48 local mnt="$2"
49 mount --bind "${mnt}" "/a${mnt}"
50 }
51
52 function unsnap_bind {
53 local snapmnt="/a$2"
54 if mountpoint -q "$snapmnt"; then
55 umount "$snapmnt"
56 fi
57 }
58
59 function snap_lvm {
60 local dev="$1" mnt="$2"
61 local lvname="" vgname=""
62 read -r lvname vgname _ < <(lvdisplay --noheadings -C "$dev")
63 echo "snapshot ${vgname}/${lvname}"
64 lvcreate -L1G --snapshot --name "${lvname}snap" "${vgname}/${lvname}"
65 mount -o ro "${dev}snap" "/a${mnt}"
66 }
67
68 function unsnap_lvm {
69 local snapdev="${1}snap"
70 local snapmnt="/a$2"
71 if mountpoint -q "$snapmnt"; then
72 umount "$snapmnt"
73 fi
74 if [ -b "$(readlink -f "$snapdev")" ]; then
75 lvremove -f "${dev}snap"
76 fi
77 }
78
79 function snap_btrfs {
80 local mnt="$2" opts="$3" snapdir=""
81
82 snapdir="$(get_btrfs_snapshot_dir "$opts" "$mnt")"
83 btrfs subvolume snapshot "$mnt" "$snapdir"
84
85 mount --bind "$snapdir" "/a${mnt}"
86 }
87
88 function unsnap_btrfs {
89 local mnt="$2" opts="$3" snapdir=""
90
91 local snapmnt="/a$2"
92 if mountpoint -q "$snapmnt"; then
93 umount "$snapmnt"
94 fi
95
96 snapdir="$(get_btrfs_snapshot_dir "$opts" "$mnt")"
97 if [ -d "$snapdir" ]; then
98 btrfs subvolume delete "$snapdir"
99 fi
100 }
101
102 function get_btrfs_snapshot_dir {
103 local opts="$1" mnt="$2" subvol=""
104 subvol="$(echo "$opts" | sed -nE 's/^.*\bsubvol=([^,]+)\b.*$/\1/p')"
105 if [ -z "$subvol" ]; then
106 echo "Unknown subvol for mountpoint: $mnt"
107 exit 1
108 fi
109 echo "/$(hostname -s)/${subvol}-snap"
110 }
111
112 if [ "$(id -u)" -ne 0 ]; then
113 echo "Must be root"
114 exit 1
115 fi
116
117 if [ "${1:-}" = "off" ]; then
118 unsnap
119 elif [ "${1:-}" = "on" ]; then
120 snap
121 else
122 echo "Usage: $0 on|off"
123 exit 1
124 fi