-
Notifications
You must be signed in to change notification settings - Fork 0
/
create_8_exabyte_container
executable file
·198 lines (175 loc) · 4.41 KB
/
create_8_exabyte_container
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#! /bin/sh
# Create a RAM-backed block device using the size specified in the script name
# (which can be a symlink) or the size specified by the -n option (which
# overrides the size from the script name).
#
# The block device consists of a count of virtual zero-bytes corresponding to
# the specified device size, followed by 512 bytes of actual (non-virtual)
# device data.
#
# The new block device will be owner by the user invoking the script.
#
# On successful device creation, the pathname of the block device and
# instructions for its removal will be displayed.
#
# The script (or symlink) file name should match the shell filename pattern
# *create_$SIZESPEC* or just $SIZESPEC*, where $SIZESPEC is something like
# "8_kilobyte", "4_kibibyte", "100_yobibyte", "8_exabyte" or "7_exbibyte".
#
# Only byte sizes which can be expressed by "expr" will be recognized, though.
#
# Instead of the underscore ("_") character as shown above, any other
# non-alphanumeric character can be used as separator character in the
# filename/$SIZESPEC patterns was well.
#
# Some examples of valid names for this script (or symlinks) to it:
#
# ./create_100_petabyte_container
# ./64-kibibytes
# ./create-99_gigabytes-as-a-container
# ./"create 96 terabyte block-device"
# ./"1024 bytes-device"
#
# The same names can be passed via the -n option to override the script's
# actual file (or symlink) name.
#
# It the -s option is passed to the script, it just displays the effective
# size extracted from the script name (or -n) option and exits without
# actually trying to create any block device.
#
# Version 2021.337
#
# Copyright (c) 2019-2021 Guenther Brunthaler. All rights reserved.
#
# This script is free software.
# Distribution is permitted under the terms of the GPLv3.
set -e
cleanup() {
rc=$?
test "$loop" && losetup -d "$loop"
test "$backing" && rm -- "$backing"
test $rc = 0 || echo "\"$0\" failed!" >& 2
}
trap cleanup 0
backing=
loop=
trap 'exit $?' INT TERM QUIT HUP
me=$0
case $me in
/* | ./*) ;;
*)
if test -e "$me"
then
me=./$me
else
me=`command -v -- "$me"`
test -e "$me"
fi
esac
me=`readlink -f -- "$me"`
test -f "$me"
uid=`id -u`
if test $uid != 0
then
df=
for o in x v
do
case $- in
*$o*) df=$df$o;;
esac
done
command -v sudo > /dev/null 2>& 1 \
&& exec sudo "$me" -n "$0" ${df:+-D $df} -u $uid ${1+"$@"}
echo "Please install 'sudo' or run this command as the superuser!" >& 2
false || exit
fi
chowner=
name=`basename -- "$0"`
just_show=false
just_remove=false
while getopts D:n:su:r opt
do
case $opt in
u) chowner=$OPTARG;;
s) just_show=true;;
r) just_remove=true;;
n) name=$OPTARG;;
D) set -$OPTARG;;
*) false || exit
esac
done
shift `expr $OPTIND - 1 || :`
test $# = 0
mapping=`printf '%s\n' "$name" | sed 's/[^[:alnum:]]/_/g; s/__*/_/g'`
mapping=${mapping#*create_}
unit=${mapping#*_}
quantity=${mapping%"_$unit"}
unit=${unit%byte*}
prefix_bytes=$quantity
case $unit in
*bi) multiplier=1024;;
*) multiplier=1000
esac
for u in "" kilo mega giga tera peta exa zetta yotta -fail
do
case $multiplier in
1024) rest=${u#??}; u=${u%"$rest"}bi
esac
case $u in
"$unit") break;;
-fail) false || exit;;
esac
nx=`expr $prefix_bytes \* $multiplier 2> /dev/null` || continue
test $nx -gt $prefix_bytes
prefix_bytes=$nx
done
prefix_sectors=`expr $prefix_bytes / 512`
test `expr $prefix_sectors \* 512` = $prefix_bytes || {
echo "The selected device prefix size of $prefix_bytes virtual" \
"zero-bytes is not a multiple of 512 bytes as required!" >& 2
false || exit
}
if $just_show
then
echo "Parsed virtual zero-byte prefix device size (in bytes):"
echo $prefix_bytes
exit
fi
if $just_remove
then
echo "Executing:"
(set -x; dmsetup remove "$mapping")
exit
fi
for m in zero linear
do
modprobe $m || :
done 2> /dev/null
backing=`mktemp -- "${TMPDIR:-/tmp}/${0##*/}.XXXXXXXXXX"`
dd if=/dev/zero bs=512 count=1 > "$backing" 2> /dev/null
loop0=`losetup -f`
test -b "$loop0"
losetup "$loop0" "$backing"
loop=$loop0; unset loop0
rm -- "$backing"; backing=
{
echo 0 $prefix_sectors zero
echo $prefix_sectors 1 linear $loop 0
} | dmsetup create $mapping
losetup -d "$loop"; loop=
dev=/dev/mapper/$mapping
wait=5
while test ! -b "$dev"
do
test $wait = 2 && dmsetup mknodes
sleep 1
wait=`expr $wait - 1`
done
test "$chowner" && chown "$chowner" "$dev"
(set -x; ls -lL "$dev")
echo
(set -x; blockdev --getsize64 "$dev")
echo
cat << EOF
Run script again with -r (or use dmsetup remove) to destroy the new device.
EOF