From 153d299a41b9be4e15dab1ca29bb93a74bd2445d Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 29 Apr 2016 14:36:26 -0400 Subject: fix paths (in progress) --- src/btrfs-functions.sh | 161 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/btrfs-functions.sh (limited to 'src/btrfs-functions.sh') diff --git a/src/btrfs-functions.sh b/src/btrfs-functions.sh new file mode 100644 index 0000000..b83b94d --- /dev/null +++ b/src/btrfs-functions.sh @@ -0,0 +1,161 @@ +push() +{ + $(ARGS_NE mnt src dst_dir) + + now=$(date +%F.%H%M%S) || die + snap_dir=$mnt/snapshot.$now + prev_dir=$mnt/snapshot.prev + + local BTRFS_RECEIVE_DESTINATION_PATH="$dst_dir" + push_helper true "$snap_dir" "$prev_dir" "$src" local_btrfs_receiver +} + +push_simple() +{ + $(ARGS_NE mnt src dst_dir) + local BTRFS_RECEIVE_DESTINATION_PATH="$dst_dir" + push_helper false "$mnt" "$src" local_btrfs_receiver +} + +sex() +{ + (set -x; "$@") +} + +local_btrfs_receiver() +{ + btrfs receive "$BTRFS_RECEIVE_DESTINATION_PATH" +} + +shellescape() +{ + if [ "$BASH_VERSION" ]; then + printf %q "$1" + else + bash -c 'printf %q "$1"' bash "$1" + fi +} + +remote_btrfs_receiver() +{ + ssh "$BTRFS_RECEIVE_DESTINATION_HOST" -- "btrfs receive $(shellescape "$BTRFS_RECEIVE_DESTINATION_PATH")" +} + +push_helper() +{ + $(ARGS keep_as_prev snap_dir prev_dir src dst_pipe) + $(NONEMPTY keep_as_prev snap_dir src dst_pipe) + + local full_dest rw_dest + + btrfs subvolume snapshot -r "$src" "$snap_dir" || die + + if [ "$prev_dir" -a -d "$prev_dir" ]; then + btrfs send -p "$prev_dir" "$snap_dir" + else + btrfs send "$snap_dir" + fi | "$dst_pipe" || die + + if [ "$dst_pipe" = local_btrfs_receiver ]; then + local dst="$BTRFS_RECEIVE_DESTINATION_PATH" + full_dest=$dst/$(basename "$snap_dir") + rw_dest=$full_dest.rw + btrfs subvolume snapshot "$full_dest" "$rw_dest" || die + btrfs_replace_default_subvolume_with "$rw_dest" + fi + + if $keep_as_prev && [ "$prev_dir" ] + then + # keep the pushed snapshot in order to reuse it on subsequent pushes. + with_dir "$prev_dir" btrfs subvolume delete || die + sex mv "$snap_dir" "$prev_dir" || die + else + btrfs subvolume delete "$snap_dir" + fi +} + +btrfs_mountpoint() +{ + $(ARGS_NE dir) + btrfs filesystem show -m "$dir" >/dev/null 2>&1 +} + +btrfs_get_mountpoint() +{ + $(ARGS_NE dir) + while [ "$dir" -a "$dir" != '.' ]; do + if btrfs_mountpoint "$dir" + then printf '%s\n' "$dir" + return + fi + dir=$(dirname "$dir") + done + false +} + +btrfs_show_default_path() +{ + $(ARGS_NE mp) + local path + mp=$(btrfs_get_mountpoint "$mp") || die # TODO: fix caller? + btrfs_mountpoint "$mp" || die "not a mountpoint: $mp" + path=$(btrfs subvolume get-default "$mp"/|sed -n -e 's/.* path //p') + if [ "$path" ]; then + printf '%s\n' "$mp/$path" + else + printf '%s\n' "$mp" + fi +} + +btrfs_show_default_id() +{ + $(ARGS_NE mp) + local id + mp=$(btrfs_get_mountpoint "$mp") || die # TODO: fix caller? + btrfs_mountpoint "$mp" || die "not a mountpoint: $mp" + id=$(btrfs subvolume get-default "$mp"/|sed -n -e 's/^ID \([^ ]*\) .*/\1/p') + [ "$id" ] || return + echo $id +} + +btrfs_replace_default_subvolume_with() +{ + $(ARGS_NE new_default) + local old_default old_default_id new_default_id + old_default_id=$(btrfs_show_default_id "$new_default") || die + new_default_id=$(btrfs_show_subvolume_id "$new_default") || die + + [ "$new_default_id" = "$old_default_id" ] && return + + if [ "$old_default_id" != 5 ]; then + old_default=$(btrfs_show_default_path "$new_default") || die + else + old_default= + fi + + btrfs subvolume set-default "$new_default_id" "$new_default" || die + + if [ "$old_default" ]; then + btrfs subvolume delete "$old_default" + sex mv "$new_default" "$old_default" + fi +} + +btrfs_show_subvolume_id() +{ + $(ARGS_NE path) + local result + result=$(btrfs subvolume show "$path" | sed -n -e 's/^[ \t]*Subvolume ID:[ \t]*//p; s/.*is toplevel subvolume/5/p') + if [ "$result" ] + then printf '%s\n' "$result" + else false + fi +} + +with_dir() +{ + $(ARGS_NE d) + shift + [ -d "$d" ] || return 0 + "$@" "$d" +} -- cgit v1.2.3