diff options
author | Andrew Cady <d@cryptonomic.net> | 2021-01-21 10:44:39 -0500 |
---|---|---|
committer | Andrew Cady <d@cryptonomic.net> | 2021-01-21 10:44:39 -0500 |
commit | 01f7c340c36290a85ed13ddbc76ec497c83e6f9b (patch) | |
tree | 33be3a30c5b18674af538933626b50da82f85e29 /src/selfstrap | |
parent | 7a5a13c17be7bf7a6e8315240ded71d90babd1f4 (diff) |
remove selfstrap from this archive, which should be installed from fsmgr
Diffstat (limited to 'src/selfstrap')
-rwxr-xr-x | src/selfstrap | 453 |
1 files changed, 0 insertions, 453 deletions
diff --git a/src/selfstrap b/src/selfstrap deleted file mode 100755 index 6766c0c..0000000 --- a/src/selfstrap +++ /dev/null | |||
@@ -1,453 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | debian_mirror=http://httpredir.debian.org/debian | ||
3 | debian_security_mirror=http://security.debian.org | ||
4 | EXTRA_PACKAGES='apt debian-archive-keyring locales' | ||
5 | |||
6 | die() { printf 'Error: %s\n' "$*"; exit 1; } | ||
7 | |||
8 | usage() | ||
9 | { | ||
10 | echo "Usage: $0 -t <target directory> [options] [packages]" >&2 | ||
11 | cat <<EOF | ||
12 | Options: | ||
13 | --target|-t (Mandatory) Target directory | ||
14 | --help|-h | ||
15 | --verbose|-v | ||
16 | --unpack Only unpack; do not configure | ||
17 | --chroot=<prog> Use prog for chroot command | ||
18 | --packages=<file> Text file contains names of packages to install | ||
19 | --real-apt Use 'apt-get install' to install packages | ||
20 | --skip-update Do not run 'apt-get update' at startup | ||
21 | EOF | ||
22 | exit ${1:-1} | ||
23 | } | ||
24 | |||
25 | GETOPT=$(getopt -n "${0##*/}" -o t:hv --long help,target:,verbose,unpack,chroot:,packages:,real-apt,skip-update -- "$@") || exit | ||
26 | eval set -- "$GETOPT" | ||
27 | while [ $# -gt 0 ]; do | ||
28 | case "$1" in | ||
29 | -t|--target) TARGET=$2; shift ;; | ||
30 | -h|--help) usage 0 ;; | ||
31 | -v|--verbose) VERBOSE=y ;; | ||
32 | --skip-update) SKIP_UPDATE=y ;; | ||
33 | --unpack) UNPACK_ONLY=y ;; | ||
34 | --packages) x=$(cat < "$2") || die "could not read file '$2'" | ||
35 | EXTRA_PACKAGES="$EXTRA_PACKAGES $x" | ||
36 | shift ;; | ||
37 | --chroot) CHROOT_PROG=$2; shift ;; | ||
38 | --real-apt) REAL_APT_INSTALL=y ;; | ||
39 | --) shift; break ;; | ||
40 | *) usage 1 ;; | ||
41 | esac | ||
42 | shift | ||
43 | done | ||
44 | |||
45 | [ "$TARGET" ] || usage | ||
46 | |||
47 | ! [ "$REAL_APT_INSTALL" -a "$UNPACK_ONLY" ] || die "option --real-apt is incompatible with option --unpack" | ||
48 | |||
49 | EXTRA_PACKAGES="$EXTRA_PACKAGES $*" | ||
50 | |||
51 | am_root() { [ "$(id -u)" = 0 ]; } | ||
52 | |||
53 | current_debian_codename() | ||
54 | { | ||
55 | # lsb_release -cs | ||
56 | sed -ne 's/^VERSION=.* (\(.*\)).*/\1/p' /etc/os-release | ||
57 | } | ||
58 | |||
59 | sanity_checks() | ||
60 | { | ||
61 | am_root || die 'you are not root' | ||
62 | TARGET=$(realpath "$TARGET") || die 'realpath failed' | ||
63 | [ "$TARGET" ] || die 'no $TARGET' | ||
64 | [ -d "$TARGET" ] || mkdir "$TARGET" || die 'could not mkdir($TARGET)' | ||
65 | } | ||
66 | |||
67 | generate_apt_config() | ||
68 | { | ||
69 | APT_CONFIG=$(mktemp) || exit | ||
70 | chmod 644 "$APT_CONFIG" | ||
71 | cat > "$APT_CONFIG" <<EOF | ||
72 | Dir "${TARGET}"; | ||
73 | EOF | ||
74 | export APT_CONFIG | ||
75 | } | ||
76 | |||
77 | apt_() | ||
78 | { | ||
79 | local apt_cmd="$1" | ||
80 | shift | ||
81 | |||
82 | [ "$TARGET" ] || die 'no $TARGET' | ||
83 | [ "$APT_CONFIG" ] || die 'no $APT_CONFIG' | ||
84 | |||
85 | if [ "$VERBOSE" ]; then | ||
86 | printf "+ apt-${apt_cmd} %s\n" "$*" >&2 | ||
87 | fi | ||
88 | |||
89 | set -- "$@" -o Apt::Install-Recommends=false | ||
90 | set -- "$@" -o Apt::Architecture="$target_arch" | ||
91 | set -- "$@" -o Apt::Default-Release="$target_release" | ||
92 | |||
93 | # Set default paths to within the created system. | ||
94 | set -- "$@" -o Dir="$TARGET" | ||
95 | set -- "$@" -o Dir::State::Status="$TARGET"/var/lib/dpkg/status | ||
96 | |||
97 | # We must also set dpkg to use the created system. | ||
98 | # Dpkg::options requires undocumented apt CLI magic. | ||
99 | if [ "$DEBUG_DPKG" ]; then | ||
100 | [ "$DEBUG_DPKG" -gt 0 ] 2>/dev/null || DEBUG_DPKG=10013 | ||
101 | set -- "$@" -o DPkg::options::arg0=--debug="${DEBUG_DPKG}" | ||
102 | fi | ||
103 | # This is the important one: | ||
104 | set -- "$@" -o DPkg::options::arg1=--root="$TARGET" | ||
105 | set -- "$@" -o DPkg::options::arg2=--force-unsafe-io | ||
106 | |||
107 | # Use the calling system for these. This is an optimization. | ||
108 | #set -- "$@" -o Dir::Etc::sourcelist=/etc/apt/sources.list | ||
109 | #set -- "$@" -o Dir::Etc::sourceparts=/etc/apt/sources.list.d | ||
110 | set -- "$@" -o Dir::Etc::Trusted=/etc/apt/trusted.gpg | ||
111 | set -- "$@" -o Dir::Etc::TrustedParts=/etc/apt/trusted.gpg.d | ||
112 | set -- "$@" -o Dir::State::lists=/var/lib/apt/lists | ||
113 | set -- "$@" -o Dir::Cache::archives=/var/cache/apt/archives | ||
114 | |||
115 | # Avoid deleting lists on the calling system. | ||
116 | set -- "$@" -o APT::Get::List-Cleanup=false | ||
117 | |||
118 | apt-"${apt_cmd}" "$@" | ||
119 | } | ||
120 | apt_get() { apt_ get "$@"; } | ||
121 | apt_cache() { apt_ cache "$@"; } | ||
122 | |||
123 | idem() { if [ ! -e "${!#}" ]; then "$@"; fi; } | ||
124 | idem_mknod() { if [ ! -e "$3" ]; then mknod "$@"; fi; } | ||
125 | |||
126 | # This function is copied (with modifications) from debootstrap. | ||
127 | install_devices() | ||
128 | { | ||
129 | [ "$TARGET" -a -d "$TARGET" ] || die 'no $TARGET' | ||
130 | idem mkdir "$TARGET"/dev | ||
131 | # The list of devices that can be created in a container comes from | ||
132 | # src/core/cgroup.c in the systemd source tree. | ||
133 | idem_mknod -m 666 "$TARGET"/dev/null c 1 3 | ||
134 | idem_mknod -m 666 "$TARGET"/dev/zero c 1 5 | ||
135 | idem_mknod -m 666 "$TARGET"/dev/full c 1 7 | ||
136 | idem_mknod -m 666 "$TARGET"/dev/random c 1 8 | ||
137 | idem_mknod -m 666 "$TARGET"/dev/urandom c 1 9 | ||
138 | idem_mknod -m 666 "$TARGET"/dev/tty c 5 0 | ||
139 | idem mkdir "$TARGET"/dev/pts/ | ||
140 | idem mkdir "$TARGET"/dev/shm/ | ||
141 | # Inside a container, we might not be allowed to create /dev/ptmx. | ||
142 | # If not, do the next best thing. | ||
143 | if ! idem_mknod -m 666 "$TARGET"/dev/ptmx c 5 2; then | ||
144 | idem ln -s pts/ptmx "$TARGET"/dev/ptmx | ||
145 | fi | ||
146 | idem ln -s /proc/self/fd "$TARGET"/dev/fd | ||
147 | idem ln -s /proc/self/fd/0 "$TARGET"/dev/stdin | ||
148 | idem ln -s /proc/self/fd/1 "$TARGET"/dev/stdout | ||
149 | idem ln -s /proc/self/fd/2 "$TARGET"/dev/stderr | ||
150 | } | ||
151 | |||
152 | mount_virtfs() | ||
153 | { | ||
154 | [ "$TARGET" ] || die 'no $TARGET' | ||
155 | [ -d "$TARGET"/proc ] || mkdir "$TARGET"/proc | ||
156 | [ -d "$TARGET"/sys ] || mkdir "$TARGET"/sys | ||
157 | mount -t proc proc "$TARGET"/proc | ||
158 | mount -t sysfs sysfs "$TARGET"/sys | ||
159 | } | ||
160 | |||
161 | umount_virtfs() | ||
162 | { | ||
163 | [ "$TARGET" ] || die 'no $TARGET' | ||
164 | umount "$TARGET"/proc || fail=y | ||
165 | umount "$TARGET"/sys || fail=y | ||
166 | [ ! "$fail" ] | ||
167 | } | ||
168 | |||
169 | write_lines_once() | ||
170 | { | ||
171 | local output="$1" | ||
172 | shift | ||
173 | [ -e "$output" ] || printf '%s\n' "$@" > "$output" | ||
174 | } | ||
175 | |||
176 | populate_rootfs() | ||
177 | { | ||
178 | [ "$TARGET" ] || die 'no $TARGET' | ||
179 | set -B | ||
180 | mkdir -p \ | ||
181 | "$TARGET"/etc/apt/{preferences.d,apt.conf.d,trusted.gpg.d,sources.list.d} \ | ||
182 | "$TARGET"/var/{lib/{apt/lists/partial,dpkg/{info,parts,triggers,alternatives,updates}},cache/apt} \ | ||
183 | "$TARGET"/var/log/apt | ||
184 | |||
185 | touch "$TARGET"/var/lib/dpkg/status | ||
186 | |||
187 | [ -d "$TARGET"/usr/bin ] || mkdir -p "$TARGET"/usr/bin | ||
188 | [ -e "$TARGET/usr/bin/awk" -o -L "$TARGET/usr/bin/awk" ] || ln -s mawk "$TARGET/usr/bin/awk" | ||
189 | |||
190 | write_lines_once "$TARGET"/var/lib/dpkg/arch "$target_arch" | ||
191 | write_sources_list | ||
192 | install_devices | ||
193 | } | ||
194 | |||
195 | write_sources_list() | ||
196 | { | ||
197 | local dest="$TARGET"/etc/apt/sources.list | ||
198 | [ -e "$dest" ] && return | ||
199 | printf '%s\n' \ | ||
200 | "deb ${debian_mirror} ${target_release} main contrib non-free" \ | ||
201 | "deb ${debian_mirror} ${target_release}-backports main contrib non-free" \ | ||
202 | "deb ${debian_security_mirror} ${target_release}/updates main contrib non-free" | | ||
203 | column -t > "$dest" | ||
204 | } | ||
205 | |||
206 | parse_apt_simul_line() | ||
207 | { | ||
208 | set -- $* | ||
209 | action=$1 | ||
210 | package=$2 | ||
211 | # Third word might either be "(version" or "[version]" depending on which | ||
212 | # apt is producing the output. Newer apt versions apparently add an extra | ||
213 | # "[version]" parameter, making "(version" the fourth argument. | ||
214 | version=${3#\(} | ||
215 | version=${version#\[} | ||
216 | version=${version%]} | ||
217 | shift 3 | ||
218 | |||
219 | # Find the last word, which is inside (a group of words that are inside | ||
220 | # parentheses). | ||
221 | while [ "$1" ]; do | ||
222 | case "$1" in | ||
223 | *\)) | ||
224 | arch=${1%\)} | ||
225 | arch=${arch#\[} | ||
226 | arch=${arch%\]} | ||
227 | return | ||
228 | ;; | ||
229 | *) shift ;; | ||
230 | esac | ||
231 | done | ||
232 | return 1 | ||
233 | } | ||
234 | |||
235 | dpkg_unpack() | ||
236 | { | ||
237 | [ "$TARGET" -a -d "$TARGET" ] || die 'no $TARGET' | ||
238 | local deb="$1" multiarch="$2" SET_STATUS="$3" command PKG | ||
239 | PKG=${deb##*/} | ||
240 | PKG=${PKG%%_*} | ||
241 | PKG=$PKG$multiarch | ||
242 | |||
243 | extract_tmp_ci "$deb" | ||
244 | install_metadata_from_tmp_ci # uses TARGET PKG SET_STATUS | ||
245 | remove_tmp_ci | ||
246 | |||
247 | dpkg --fsys-tarfile "$deb" | | ||
248 | (cd "$TARGET" && tar -xv) | | ||
249 | sed 's?^\.??; s?^/$?/.?; s?/$??' > "$TARGET/var/lib/dpkg/info/$PKG.list" | ||
250 | } | ||
251 | |||
252 | install_metadata_from_tmp_ci() # uses TARGET PKG SET_STATUS | ||
253 | { | ||
254 | (cd "$TARGET"/var/lib/dpkg/tmp.ci || die "cannot cd to /var/lib/dpkg/tmp.ci" | ||
255 | # PKG=$(sed -n 's/^Package: *//p' control) | ||
256 | for f in *; do | ||
257 | [ "$f" = postinst ] && SET_STATUS=${SET_STATUS:+installed} || true | ||
258 | [ "$f" = control ] || mv "$f" "$TARGET"/var/lib/dpkg/info/"$PKG"."$f" | ||
259 | done | ||
260 | if [ "$SET_STATUS" -a -e control ]; then | ||
261 | (sed "/^Package:/a Status: install ok $SET_STATUS"; echo) < control >> "$TARGET"/var/lib/dpkg/status | ||
262 | fi) | ||
263 | } | ||
264 | |||
265 | verbosely() | ||
266 | { | ||
267 | if [ "$VERBOSE" ]; then | ||
268 | (set -x; "$@") | ||
269 | else | ||
270 | "$@" | ||
271 | fi | ||
272 | } | ||
273 | |||
274 | remove_tmp_ci() | ||
275 | { | ||
276 | [ ! -e "$TARGET"/var/lib/dpkg/tmp.ci ] || rm -r "$TARGET"/var/lib/dpkg/tmp.ci | ||
277 | } | ||
278 | |||
279 | # /var/lib/dpkg/tmp.ci/control is read by debconf to determine the owner package | ||
280 | # See `grep -A3 control /usr/share/debconf/frontend` | ||
281 | extract_tmp_ci() | ||
282 | { | ||
283 | local deb="$1" | ||
284 | remove_tmp_ci | ||
285 | mkdir "$TARGET"/var/lib/dpkg/tmp.ci | ||
286 | dpkg --ctrl-tarfile "$deb" | tar -C "$TARGET"/var/lib/dpkg/tmp.ci -x | ||
287 | } | ||
288 | |||
289 | dpkg_configure_from_apt_actions() | ||
290 | { | ||
291 | while read line; do | ||
292 | parse_apt_simul_line "$line" || die "parse_apt_simul_line: unexpected output from apt-get: $line" | ||
293 | export LC_ALL=C | ||
294 | export DEBIAN_FRONTEND=noninteractive | ||
295 | export DPKG_MAINTSCRIPT_PACKAGE="$package" DPKG_MAINTSCRIPT_ARCH="$arch" | ||
296 | is_multiarch_same "$package" && multiarch=":$arch" || multiarch= | ||
297 | case "$action" in | ||
298 | Inst) | ||
299 | export DPKG_MAINTSCRIPT_NAME=preinst | ||
300 | preinst=/var/lib/dpkg/info/${package}${multiarch}.preinst | ||
301 | if [ -x "$TARGET"/"$preinst" ]; then | ||
302 | extract_tmp_ci "$deb" | ||
303 | verbosely ${CHROOT_PROG:-chroot} "$TARGET" "$preinst" install | ||
304 | remove_tmp_ci | ||
305 | fi | ||
306 | ;; | ||
307 | Conf) | ||
308 | export DPKG_MAINTSCRIPT_NAME=postinst | ||
309 | postinst=/var/lib/dpkg/info/${package}${multiarch}.postinst | ||
310 | if [ -x "$TARGET"/"$postinst" ]; then | ||
311 | extract_tmp_ci "$deb" | ||
312 | verbosely ${CHROOT_PROG:-chroot} "$TARGET" "$postinst" configure | ||
313 | remove_tmp_ci | ||
314 | fi | ||
315 | ;; | ||
316 | Remv) ;; | ||
317 | *) die "dpkg_configure_from_apt_actions: unknown apt simul action: $action" ;; | ||
318 | esac | ||
319 | done | ||
320 | } | ||
321 | |||
322 | apt_extract() | ||
323 | { | ||
324 | apt_get -d -yqq install "$@" | ||
325 | actions=$(mktemp) || die 'mktemp failed' | ||
326 | apt_get -s -yqq install "$@" > "$actions" || die 'apt-get failed' | ||
327 | |||
328 | dpkg_unpack_from_apt_actions < "$actions" || die 'dpkg unpack (using internal dpkg) failed' | ||
329 | |||
330 | if [ ! "$UNPACK_ONLY" ]; then | ||
331 | install_etc_passwd | ||
332 | dpkg_configure_from_apt_actions < "$actions" || die 'dpkg configure (using internal dpkg) failed' | ||
333 | fi | ||
334 | |||
335 | rm "$actions" | ||
336 | } | ||
337 | |||
338 | dpkg_unpack_from_apt_actions() | ||
339 | { | ||
340 | while read line; do | ||
341 | |||
342 | parse_apt_simul_line "$line" || die "parse_apt_simul_line: unexpected output from apt-get: $line" | ||
343 | |||
344 | deb=/var/cache/apt/archives/${package}_${version//:/%3a}_${arch}.deb | ||
345 | [ -f "$deb" ] || { | ||
346 | echo "line=$line" >&2 | ||
347 | printf '%s\n' "$action" "$package" "$version" "$arch" >&2 | ||
348 | die "deb not found: $deb" | ||
349 | } | ||
350 | case "$action" in | ||
351 | Inst) | ||
352 | printf 'Unpacking %s\n' "${deb##*/}" >&2 | ||
353 | if [ "$REAL_APT_INSTALL" ]; then | ||
354 | dpkg --extract "$deb" "$TARGET" || die 'dpkg' | ||
355 | else | ||
356 | is_multiarch_same "$package" && multiarch=":$arch" || multiarch= | ||
357 | [ "$UNPACK_ONLY" ] && set_status=unpacked || set_status=installed | ||
358 | dpkg_unpack "$deb" "$multiarch" "$set_status" || die "dpkg_unpack" | ||
359 | fi | ||
360 | ;; | ||
361 | Conf) ;; | ||
362 | Remv) ;; | ||
363 | *) die "dpkg_unpack_from_apt_actions: unknown apt simul action: $action" ;; | ||
364 | esac | ||
365 | done | ||
366 | } | ||
367 | |||
368 | install_etc_passwd() | ||
369 | { | ||
370 | [ -e "$TARGET"/etc/passwd ] || cp "$TARGET"/usr/share/base-passwd/passwd.master "$TARGET"/etc/passwd | ||
371 | [ -e "$TARGET"/etc/group ] || cp "$TARGET"/usr/share/base-passwd/group.master "$TARGET"/etc/group | ||
372 | } | ||
373 | |||
374 | required_packages() | ||
375 | { | ||
376 | apt_cache dumpavail | | ||
377 | perl -00 -ne '/^Priority: required/m || next; /^Package: (.*)$/m && print "$1\n"' | | ||
378 | sort -u | ||
379 | } | ||
380 | |||
381 | declare -A is_multiarch_same | ||
382 | multicheck() | ||
383 | { | ||
384 | local m | ||
385 | if [ ! "$multichecked" ]; then | ||
386 | for m in $(multiarch_same_packages); do | ||
387 | is_multiarch_same[$m]=y | ||
388 | done | ||
389 | fi | ||
390 | multichecked=y | ||
391 | } | ||
392 | |||
393 | multiarch_same_packages() | ||
394 | { | ||
395 | apt_cache dumpavail | | ||
396 | perl -00 -ne '/^Multi-Arch: same/mi || next; /^Package: (.*)$/m && print "$1\n"' | | ||
397 | sort -u | ||
398 | } | ||
399 | |||
400 | is_multiarch_same() | ||
401 | { | ||
402 | multicheck | ||
403 | [ "${is_multiarch_same[$1]}" ] | ||
404 | } | ||
405 | |||
406 | apt_update_stamp=~/.selfstrap/apt-update-stamp | ||
407 | |||
408 | apt_get_update() | ||
409 | { | ||
410 | if [ ! -e "$apt_update_stamp" ] || [ $(( $(date +%s) - $(stat -c %Y "$apt_update_stamp") )) -gt $(( 60 * 60 * 24 )) ] | ||
411 | then | ||
412 | apt_get update | ||
413 | mkdir -p ~/.selfstrap | ||
414 | touch "$apt_update_stamp" | ||
415 | fi | ||
416 | } | ||
417 | |||
418 | set -e | ||
419 | |||
420 | target_arch=$(dpkg-architecture -q DEB_HOST_ARCH) || die 'dpkg-architecture failed' | ||
421 | target_release=$(current_debian_codename) && [ "$target_release" ] || die 'could not determine Debian release name' | ||
422 | |||
423 | # Set things up so apt-get update works. | ||
424 | sanity_checks | ||
425 | generate_apt_config | ||
426 | populate_rootfs | ||
427 | [ "$SKIP_UPDATE" ] || apt_get_update | ||
428 | |||
429 | required_packages=$(required_packages) && [ "$required_packages" ] || die 'failed to determine list of required packages' | ||
430 | |||
431 | export LC_ALL=C | ||
432 | export DEBIAN_FRONTEND=noninteractive | ||
433 | |||
434 | if [ "$REAL_APT_INSTALL" ]; then | ||
435 | # Some files need to be present before 'apt-get install' can install anything. | ||
436 | # In particular: | ||
437 | # | ||
438 | # 1. binaries used by dpkg 'inst' scripts. | ||
439 | # 2. /etc/passwd and /etc/group so that 'chown' works | ||
440 | |||
441 | # Unpack required packages. Handles (1) | ||
442 | # Note: populate_rootfs() already created a necessary symlink /usr/bin/awk -> /usr/bin/mawk | ||
443 | apt_extract $required_packages | ||
444 | |||
445 | # This handles (2). | ||
446 | # An alternative (used by debootstrap) is to configure base-passwd | ||
447 | install_etc_passwd | ||
448 | |||
449 | apt_get install -y $required_packages $EXTRA_PACKAGES | ||
450 | else | ||
451 | apt_extract $required_packages | ||
452 | apt_extract $EXTRA_PACKAGES | ||
453 | fi | ||