summaryrefslogtreecommitdiff
path: root/list-all-subvolumes
blob: 7d4a1440370f6d2bf5c5f02d7cc6e0e202e3d2b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/bin/bash
set -e -o pipefail
btrfs_subvolume_list_args=('-o' "$@")

list_mounted_btrfs_devices()
{
    mount -t btrfs | while read
    do
        printf '%s\n' "${REPLY%% *}"
    done | sort -u
}

list_all_subvolumes()
{
    for dev in $(list_mounted_btrfs_devices)
    do
        [ -b "$dev" ] || return
        d=btrfs/pid-$$/$(systemd-escape "$dev")
        (
            cd /run
            mkdir -p "$d" || exit
            trap 'umount "$d"; rmdir -p "$d" 2>/dev/null' EXIT
            root=
            (
                set -x
                mountpoint -q "$d" || mount -o ro,subvol=/ "$dev" "$d" || return
                btrfs subvolume list "$@" "$d"
            ) | extract_subvolume_path "/run/$d" || return
        )
    done
}

extract_subvolume_path()
{
    while read
    do
        path=${REPLY#* path }
        [ "$path" != "$REPLY" ]
        path=${path#<FS_TREE>/}

        tryroot=$1/$path
        [ -d "$tryroot" ] || exit

        while ! [ "$root" ]
        do
            if [ / -ef "$tryroot" ]
            then
                root=${tryroot#$1/}
                break
            elif [ ! "$tryroot" -o "$tryroot" = / ]
            then
                break
            else
                tryroot=${tryroot%/*}
            fi
        done
        if [ "$root" ]
        then
            case "$path" in
                "$root" | "$root"/*) path=$root/.${path#$root} ;;
            esac
        fi
        printf '%s//%s\n' "${1##*/}" "$path"
    done
}

datetime_glob_a=.snapshot~[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]:[0-9][0-9]

datetime_glob_b=*_mirror.[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]:[0-9][0-9]

squash_snapshots()
{
    while read line
    do
        if [[ $line == */$datetime_glob_a ]] || [[ $line == $datetime_glob_b ]]
        then
            echo "${line%.*}.*"
        else
            echo "$line"
        fi
    done | sort -u
}

#SQUASH_SNAPSHOTS=y
if [ "$SQUASH_SNAPSHOTS" ]
then
    list_all_subvolumes "${btrfs_subvolume_list_args[@]}" | sort -u | squash_snapshots
else
    list_all_subvolumes "${btrfs_subvolume_list_args[@]}" | sort -u
fi