-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathextents-expr
executable file
·162 lines (145 loc) · 4.33 KB
/
extents-expr
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/bash
# SPDX-FileCopyrightText: 2016-2020 Graham R. Cobb
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Copyright (C) 2016 Graham R. Cobb
# Released under GPL V3.0 -- see LICENSE
#
# extents-expr [-s] <directory>|@<file>... [<operator> <directory>|@<file>...]...
#
# Extents lists are generated from each <directory> and the operators are applied. The default
# operator used between adjacent directories is "union". Specifying @ causes the extents to be
# read from an existing file.
#
# Operators are:
# + union
# ^ intersection
# - difference
#
# There is no operator precedence, no parentheses and all evaluation is strictly left-to-right.
# This means that using wildcards or concatenation between directories in the righthand-side
# of an operator will almost certainly not achieve the desired effect (see example below).
#
# If the -s option is specified then the resulting list is automatically sent to extents-size.
#
# Example: to find out how much space is being wasted by keeping historical btrbk snapshots
# of a subvolume called 'cobb' you could use:
#
# extents-expr -s cobb.* - cobb.20160815T000602+0100
#
# Or, to find out how much data is shared between two specific snapshots use:
#
# extents-expr -s Media.20160801T030601+0100 ^ Media.20160815T000602+0100
#
# However, the following expression DOES NOT give the result that is probably intended:
#
# extents-expr -s cobb.20160815T000602+0100 - cobb.*
#
# The desired calculation was probably to determine how much of the data in the latest snapshot is
# unique to that snapshot (i.e. new). However the effect is to subtract the first of the cobb.*
# directories and then add in all the rest. The desired effect would be something like:
#
# extents-expr -s cobb.20160815T000602+0100 - ( cobb.* )
#
# but parentheses (and precedence) are not available.
#
# THIS MIGHT CHANGE at some time in the future.
#
# Make sure errors are passed back
set -o pipefail
if [ "$1" = "-s" ]
then
shift
$0 "$@" | extents-size
exit $?
fi
extents-file-or-list() {
# Either generate an extent list or use an existing file
if [ -z "${1##@*}" ]
then
# @file
cat "${1#@}"
else
extents-list "$1"
fi
}
outfile=""
while [ $# -gt 0 ]
do
if [ "$1" = "+" ]
then
: Skip, as + is the default operator
elif [ "$1" = "^" ]
then
# Intersection
shift
# If existing outfile is null then we do nothing as intersection with null is still null
if [ -n "$outfile" ]
then
tmpfile="$(mktemp)"
status=$?
if [ $status != 0 ] ; then rm $outfile ; exit $status ; fi
extents-file-or-list "$1" >$tmpfile
status=$?
if [ $status != 0 ] ; then rm $tmpfile ; rm $outfile ; exit $status ; fi
newoutfile="$(mktemp)"
extents-intersection $outfile $tmpfile >$newoutfile
status=$?
rm $outfile
rm $tmpfile
if [ $status != 0 ] ; then rm $newoutfile ; exit $status ; fi
outfile=$newoutfile
fi
elif [ "$1" = "-" ]
then
# Difference
shift
# If existing outfile is null then we do nothing as difference from null is still null
if [ -n "$outfile" ]
then
tmpfile="$(mktemp)"
status=$?
if [ $status != 0 ] ; then rm $outfile ; exit $status ; fi
extents-file-or-list "$1" >$tmpfile
status=$?
if [ $status != 0 ] ; then rm $tmpfile ; rm $outfile ; exit $status ; fi
newoutfile="$(mktemp)"
status=$?
if [ $status != 0 ] ; then rm $tmpfile ; rm $outfile ; exit $status ; fi
extents-difference $outfile $tmpfile >$newoutfile
status=$?
rm $outfile
rm $tmpfile
if [ $status != 0 ] ; then rm $newoutfile ; exit $status ; fi
outfile=$newoutfile
fi
else
# Default operation (union)
tmpfile="$(mktemp)"
status=$?
if [ $status != 0 ] ; then [ $outfile ] && rm $outfile ; exit $status ; fi
extents-file-or-list "$1" >$tmpfile
status=$?
if [ $status != 0 ] ; then rm $tmpfile ; [ $outfile ] && rm $outfile ; exit $status ; fi
if [ -n "$outfile" ]
then
newoutfile="$(mktemp)"
status=$?
if [ $status != 0 ] ; then rm $tmpfile ; rm $outfile ; exit $status ; fi
extents-union $outfile $tmpfile >$newoutfile
status=$?
rm $outfile
rm $tmpfile
if [ $status != 0 ] ; then rm $newoutfile ; exit $status ; fi
outfile=$newoutfile
else
outfile=$tmpfile
fi
fi
shift
done
if [ -n "$outfile" ]
then
cat $outfile
rm $outfile
fi