summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2023-05-28 19:25:16 -0400
committerAndrew Cady <d@jerkface.net>2023-05-28 19:25:16 -0400
commit76f0e0e68939d64ac5ed2ccb3d21bf98337168af (patch)
treeb705dad1e56a02c8cb9da9163b0ecb7a2e681c25
parentb1ca342c72ad58a48b822fc9fa9374506c590d44 (diff)
btrfs-scan from other repo
-rwxr-xr-xsrc/btrfs-scan157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/btrfs-scan b/src/btrfs-scan
new file mode 100755
index 0000000..ab9f771
--- /dev/null
+++ b/src/btrfs-scan
@@ -0,0 +1,157 @@
1#!/bin/bash
2set -e -o pipefail
3
4confdir=/etc/btrfs
5blacklist=$confdir/blacklist.txt
6
7with_subvolumes()
8{
9 btrfs subvolume list / -a |
10 while read _ id _ gen _ _ toplevel _ path
11 do
12 "$@"
13 done
14}
15
16fixup_path()
17{
18 if ! [ "$root" ]
19 then
20 case "$path" in
21 '<FS_TREE>'/* ) root=${path#*/} ;;
22 * ) exit 1 ;;
23 esac
24 fi
25 case "$path" in
26 '<FS_TREE>'/"$root"/* ) path_fixed=${path#*/$root} ;;
27 "$root"/* ) path_fixed=${path#$root} ;;
28 * ) return ;;
29 esac
30 compute_paths
31 "$@"
32}
33
34is_our_snapshot()
35{
36 case "$1" in
37 */.snapshot~* ) true ;;
38 *) false ;;
39 esac
40}
41
42filter_blacklist()
43{
44 if is_our_snapshot "$path_fixed"
45 then
46 if [ -e "$conf_name" ]
47 then
48 printf '%20s %s\n' delete "$conf_name" >&2
49 printf '%20s %s\n' '(snapshot) lose' "$path_fixed" >&2
50 fi
51 return
52
53 # Re-reading the blacklist file once per snapshot is not ideal,
54 # but is fine.
55 elif [ "$blacklist" -a -f "$blacklist" ]
56 then
57 while read pattern
58 do
59 if [[ $path_fixed == $pattern ]]
60 then
61 if [ -e "$conf_name" ]
62 then
63 printf '%20s %s\n' delete "$conf_name" >&2
64 fi
65 printf '%20s %s\n' '(blacklist) lose' "$path_fixed" >&2
66 return
67 fi
68 done < "$blacklist"
69 fi
70 "$@"
71}
72
73compute_paths()
74{
75 source=$path_fixed
76 source_escaped=$(systemd-escape "$source")
77 conf_dir=/etc/btrfs/remotes
78 conf_name="$conf_dir"/$destination_host$source_escaped.json
79}
80
81mirror()
82{
83 if [ -e "$conf_name" ]
84 then
85 return
86 fi
87 set -- \
88 jq -c -n '{source: $source, destination: $destination}' \
89 --arg destination "$destination$source_escaped" \
90 --arg source "$source"
91
92 if [ ! "$NO_ACT" ]
93 then
94 conf_temp=$conf_name~$(date -Ins)
95 {
96 "$@" > "$conf_temp"
97 mv -T -- "$conf_temp" "$conf_name"
98 printf '%20s %s\n' 'add' "$path_fixed" >&2
99 } || {
100 rm -- "$conf_temp"
101 false
102 }
103 fi
104
105 if [ "$ONLY_ONCE" ]
106 then
107 exit 0
108 fi
109}
110
111usage()
112{
113cat <<END
114usage: $0 [-n] [-r]
115END
116}
117
118case "$0" in
119 ./* ) PATH=${0%/*}:$PATH ;;
120esac
121
122case "$(id -u)" in
123 0 ) ;;
124 * ) exec sudo --preserve-env=VERBOSE "$0" "$@" || exit ;;
125esac
126
127while [ $# -gt 0 ]
128do
129 case "$1" in
130 -- ) shift
131 break ;;
132 -n ) NO_ACT=y ;;
133 -r ) export RESUME=y ;;
134 -v ) VERBOSE=y ;;
135 --once ) ONLY_ONCE=y ;;
136 --destination ) DESTINATION=$2
137 shift ;;
138 -* ) usage
139 exit 1 ;;
140 * ) break ;;
141 esac
142 shift
143done
144
145[ "$DESTINATION" ]
146
147destination_host=${DESTINATION%%:*}
148destination_basename=$(hostname) && [ "$destination_basename" ] || destination_basename=btrfs
149case "$DESTINATION" in
150 */ ) destination=$DESTINATION$destination_basename ;;
151 [a-zA-Z]* ) destination=$DESTINATION ;;
152 * ) exit 1 ;;
153esac
154
155ssh root@"$destination_host" true || read -p 'Could not log in. Continue? '
156
157with_subvolumes fixup_path filter_blacklist mirror