forked from dnschneid/crouton
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.sh
executable file
·774 lines (698 loc) · 27.9 KB
/
main.sh
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
#!/bin/sh -e
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
APPLICATION="${0##*/}"
SCRIPTDIR="${SCRIPTDIR:-"`dirname "$0"`/.."}"
CHROOTBINDIR="$SCRIPTDIR/chroot-bin"
CHROOTETCDIR="$SCRIPTDIR/chroot-etc"
DISTRODIR=''
INSTALLERDIR="$SCRIPTDIR/installer"
HOSTBINDIR="$SCRIPTDIR/host-bin"
TARGETSDIR="$SCRIPTDIR/targets"
SRCDIR="$SCRIPTDIR/src"
ARCH=''
BOOTSTRAP_RELEASE=''
DISTRO=''
DOWNLOADONLY=''
ENCRYPT=''
KEYFILE=''
MIRROR=''
MIRRORSET=''
MIRROR2=''
NAME=''
PREFIX='/usr/local'
PREFIXSET=''
CHROOTSLINK='/mnt/stateful_partition/crouton/chroots'
PROXY='unspecified'
RELEASE=''
RESTORE=''
RESTOREBIN=''
DEFAULTRELEASE='xenial'
PREVIOUS_DEFAULT_RELEASES='precise'
TARBALL=''
TARGETS=''
TARGETFILE=''
UPDATE=''
UPDATEIGNOREEXISTING=''
USAGE="$APPLICATION [options] -t targets
$APPLICATION [options] -f backup_tarball
$APPLICATION [options] -d -f bootstrap_tarball
Constructs a chroot for running a more standard userspace alongside Chromium OS.
If run with -f, where the tarball is a backup previously made using edit-chroot,
the chroot is restored and relevant scripts installed.
If run with -d, a bootstrap tarball is created to speed up chroot creation in
the future. You can use bootstrap tarballs generated this way by passing them
to -f the next time you create a chroot with the same architecture and release.
$APPLICATION must be run as root unless -d is specified AND fakeroot is
installed AND /tmp is mounted exec and dev.
It is highly recommended to run this from a crosh shell (Ctrl+Alt+T), not VT2.
Options:
-a ARCH The architecture to prepare a new chroot or bootstrap for.
Default: autodetected for the current chroot or system.
-b Restore crouton scripts in PREFIX/bin, as required by the
chroots currently installed in PREFIX/chroots.
-d Downloads the bootstrap tarball but does not prepare the chroot.
-e Encrypt the chroot with ecryptfs using a passphrase.
If specified twice, prompt to change the encryption passphrase.
-f TARBALL The bootstrap or backup tarball to use, or to download to (-d).
When using an existing tarball, -a and -r are ignored.
-k KEYFILE File or directory to store the (encrypted) encryption keys in.
If unspecified, the keys will be stored in the chroot if doing a
first encryption, or auto-detected on existing chroots.
-m MIRROR Mirror to use for bootstrapping and package installation.
Default depends on the release chosen.
Can only be specified during chroot creation and forced updates
(-u -u). After installation, the mirror can be modified using
the distribution's recommended way.
-M MIRROR2 A secondary mirror, often used for security updates.
Can only be specified alongside -m.
-n NAME Name of the chroot. Default is the release name.
Cannot contain any slash (/).
-p PREFIX The root directory in which to install the bin and chroot
subdirectories and data.
Default: $PREFIX, with $PREFIX/chroots linked to
$CHROOTSLINK.
-P PROXY Set an HTTP proxy for the chroot; effectively sets http_proxy.
Specify an empty string to remove a proxy when updating.
-r RELEASE Name of the distribution release. Default: $DEFAULTRELEASE,
or auto-detected if upgrading a chroot and -n is specified.
Specify 'help' or 'list' to print out recognized releases.
-t TARGETS Comma-separated list of environment targets to install.
Specify 'help' or 'list' to print out potential targets.
-T TARGETFILE Path to a custom target definition file that gets applied to
the chroot as if it were a target in the $APPLICATION bundle.
-u If the chroot exists, runs the preparation step again.
You can use this to install new targets or update old ones.
Passing this parameter twice will force an update even if the
specified release does not match the one already installed.
-V Prints the version of the installer to stdout.
Be aware that dev mode is inherently insecure, even if you have a strong
password in your chroot! Anyone can simply switch VTs and gain root access
unless you've permanently assigned a Chromium OS root password. Encrypted
chroots require you to set a Chromium OS root password, but are still only as
secure as the passphrases you assign to them."
# "Undocumented" flags:
# -U Same as -u, but does not reinstall existing targets.
# Targets specified with -t will be installed, but not recorded
# for future updates.
# Common functions
. "$SCRIPTDIR/installer/functions"
# Process arguments
while getopts 'a:bdef:k:m:M:n:p:P:r:s:t:T:uUV' f; do
case "$f" in
a) ARCH="$OPTARG";;
b) RESTOREBIN='y';;
d) DOWNLOADONLY='y';;
e) ENCRYPT="${ENCRYPT:-"-"}e";;
f) TARBALL="$OPTARG";;
k) KEYFILE="$OPTARG";;
m) MIRROR="$OPTARG"; MIRRORSET='y';;
M) MIRROR2="$OPTARG";;
n) NAME="$OPTARG";;
p) PREFIX="`readlink -m -- "$OPTARG"`"; PREFIXSET='y';;
P) PROXY="$OPTARG";;
r) RELEASE="$OPTARG";;
t) TARGETS="$TARGETS${TARGETS:+","}$OPTARG";;
T) TARGETFILE="$OPTARG";;
u) UPDATE="$((UPDATE+1))";;
U) UPDATE="$((UPDATE+1))"; UPDATEIGNOREEXISTING='y';;
V) echo "$APPLICATION: version ${VERSION:-"git"}"; exit 0;;
\?) error 2 "$USAGE";;
esac
done
shift "$((OPTIND-1))"
# Check against the minimum version of Chromium OS
if [ -n "$DOWNLOADONLY" ]; then
:
elif ! awk -F= '/_RELEASE_BUILD_NUMBER=/ { exit int($2) < '"${CROS_MIN_VERS:-0}"' }' \
'/etc/lsb-release' 2>/dev/null; then
error 2 "Your version of Chromium OS is extraordinarily old.
If there are updates pending, please reboot and try again.
Otherwise, you may not be getting automatic updates, in which case you should
post your update_engine.log from chrome://system to http://crbug.com/new and
restore your device using a recovery USB: https://goo.gl/AZ74hj"
fi
# If the release is "list" or "help", print out all the valid releases.
if [ "$RELEASE" = 'list' -o "$RELEASE" = 'help' ]; then
for DISTRODIR in "$INSTALLERDIR"/*/; do
DISTRODIR="${DISTRODIR%/}"
DISTRO="${DISTRODIR##*/}"
echo "Recognized $DISTRO releases:" 1>&2
accum=''
while IFS="|" read -r RELEASE _; do
newaccum="${accum:-" "} $RELEASE"
if [ "${#newaccum}" -gt 80 ]; then
echo "$accum" 1>&2
newaccum=" $RELEASE"
fi
accum="$newaccum"
done < "$DISTRODIR/releases"
if [ -n "$accum" ]; then
echo "$accum" 1>&2
fi
done
echo 'Releases marked with ! are upstream end-of-life, and should be avoided.' 1>&2
echo 'Releases marked with * are unsupported, but may work with some effort.' 1>&2
exit 2
fi
# Either a tarball, update, target, or restore binaries must be specified.
if [ -z "$TARBALL$UPDATE$TARGETS$TARGETFILE$RESTOREBIN" ]; then
error 2 "$USAGE"
fi
# Only one of 'download only', update and restore binaries can be specified
test="$DOWNLOADONLY${UPDATE:+y}$RESTOREBIN"
if [ "${#test}" -gt 1 ]; then
error 2 "$USAGE"
fi
# ARCH cannot be specified upon update
if [ -n "$UPDATE$RESTOREBIN" -a -n "$ARCH" ]; then
error 2 'Architecture cannot be specified with -b or -u.'
fi
# Release or name cannot be specified when restoring binaries
if [ -n "$RESTOREBIN" -a -n "$NAME$RELEASE$ENCRYPT" ]; then
error 2 "Name, release and encrypt cannot be specified with -b."
fi
# MIRROR and MIRROR2 must not be specified on update
if [ "$UPDATE" = 1 -o -n "$RESTOREBIN" ]; then
if [ -z "$MIRROR$MIRROR2" ]; then
# Makes sure MIRROR does not get overriden by distribution default
MIRROR='unspecified'
else
error 2 "$USAGE"
fi
fi
# Prefix must exist
if [ ! -d "$PREFIX" ]; then
error 2 "$PREFIX is not a valid prefix"
fi
# There should never be any extra parameters.
if [ $# != 0 ]; then
error 2 "$USAGE"
fi
# If this script was called with '-x' or '-v', pass that to prepare.sh
SETOPTIONS=""
if set -o | grep -q '^xtrace.*on$'; then
SETOPTIONS="-x"
fi
if set -o | grep -q '^verbose.*on$'; then
SETOPTIONS="$SETOPTIONS -v"
fi
sh() {
/bin/sh $SETOPTIONS -e "$@"
}
if [ "$USER" = root -o "$UID" = 0 ]; then
# Avoid kernel panics due to slow I/O when restoring or bootstrapping
disablehungtask
fi
# If we specified a tarball, we need to detect the tarball type
if [ -z "$DOWNLOADONLY" -a -n "$TARBALL" ]; then
if [ ! -f "$TARBALL" ]; then
error 2 "$TARBALL not found."
fi
label="`tar --test-label -f "$TARBALL" 2>/dev/null`"
if [ -n "$label" ]; then
if [ "${label#crouton:backup}" != "$label" ]; then
releasearch=''
if [ -z "$NAME" ]; then
NAME="${label#*-}"
fi
elif [ "${label#crouton:bootstrap}" != "$label" ]; then
releasearch="${label#*.}"
else
error 2 "$TARBALL doesn't appear to be a valid crouton bootstrap."
fi
else
# Old bootstraps just use the first folder name
echo "WARNING: $TARBALL is an old-style bootstrap or backup." 1>&2
releasearch="`tar -tf "$TARBALL" 2>/dev/null | head -n 1`"
releasearch="${releasearch%%/*}"
fi
if [ "${releasearch#*-}" != "$releasearch" ]; then
ARCH="${releasearch##*-}"
RELEASE="${releasearch%-*}"
else
RESTORE='y'
if [ -z "$NAME" ]; then
NAME="$releasearch"
fi
fi
elif [ -n "$DOWNLOADONLY" -a -s "$TARBALL" ]; then
error 2 "$TARBALL already exists; refusing to overwrite it!"
fi
# If we're not restoring, updating, or bootstrapping, targets must be specified
if [ -z "$RESTORE$RESTOREBIN$UPDATE$DOWNLOADONLY$TARGETS$TARGETFILE" ]; then
error 2 "$USAGE"
fi
if [ -n "$RESTORE" -a -n "$TARGETS$TARGETFILE" -a -z "$UPDATE" ]; then
error 2 "Specify -u if you want to add targets when you restore a chroot."
fi
# Detect which distro the release belongs to.
if [ -n "$RELEASE" -o -z "$UPDATE" ]; then
if [ -z "$RELEASE" ]; then
RELEASE="$DEFAULTRELEASE"
fi
for DISTRODIR in "$INSTALLERDIR"/*/; do
DISTRODIR="${DISTRODIR%/}"
if grep -q "^$RELEASE\([^a-z].*\)*$" "$DISTRODIR/releases"; then
DISTRO="${DISTRODIR##*/}"
. "$DISTRODIR/defaults"
break
fi
done
if [ -z "$DISTRO" ]; then
error 2 "$RELEASE does not belong to any supported distribution."
fi
fi
# Confirm or list targets if requested (and download only isn't chosen)
if [ -z "$DOWNLOADONLY" ]; then
t="${TARGETS%,},"
while [ -n "$t" ]; do
TARGET="${t%%,*}"
t="${t#*,}"
if [ -z "$TARGET" ]; then
continue
elif [ "$TARGET" = 'help' -o "$TARGET" = 'list' ]; then
TARGETS='help'
echo "Available targets:" 1>&2
for t in "$TARGETSDIR/"*; do
TARGET="${t##*/}"
if [ "${TARGET%common}" = "$TARGET" ]; then
(TARGETNOINSTALL='y'; . "$t") 1>&2
fi
done
exit 2
elif [ "${TARGET%common}" != "$TARGET" ] || \
[ ! -r "$TARGETSDIR/$TARGET" ] || \
! (TARGETNOINSTALL="${UPDATE:-c}"; . "$TARGETSDIR/$TARGET"); then
error 2 "Invalid target \"$TARGET\"."
fi
done
if [ -n "$TARGETFILE" ]; then
if [ ! -r "$TARGETFILE" ]; then
error 2 "Could not find \"$TARGETFILE\"."
elif [ ! -f "$TARGETFILE" ]; then
error 2 "\"$TARGETFILE\" is not a target definition file."
fi
fi
fi
# If we're not running as root, we must be downloading and have fakeroot and
# have an exec and dev /tmp
if grep -q '.* /tmp .*\(nodev\|noexec\|nosymfollow\)' /proc/mounts; then
NOEXECTMP=y
else
NOEXECTMP=n
fi
FAKEROOT=''
if [ "$USER" != root -a "$UID" != 0 ]; then
FAKEROOT=fakeroot
if [ "$NOEXECTMP" = y -o -z "$DOWNLOADONLY" ] \
|| ! hash "$FAKEROOT" 2>/dev/null; then
error 2 "$APPLICATION must be run as root."
fi
fi
# If we are only downloading, we need a destination tarball
if [ -n "$DOWNLOADONLY" -a -z "$TARBALL" ]; then
error 2 "$USAGE"
fi
# Check if we're running from a tty, which does not interact well with X11
if [ -z "$DOWNLOADONLY" ] && \
readlink -f -- "/proc/$$/fd/0" | grep -q '^/dev/tty'; then
echo \
"WARNING: It is highly recommended that you run $APPLICATION from a crosh shell
(Ctrl+Alt+T in Chromium OS), not from a VT. If you continue to run this from a
VT, you're gonna have a bad time. Press Ctrl-C at any point to abort." 1>&2
sleep 5
fi
# Set http_proxy if a proxy is specified.
if [ "$PROXY" != 'unspecified' ]; then
export http_proxy="$PROXY" https_proxy="$PROXY" ftp_proxy="$PROXY"
fi
# Done with parameter processing!
# Make sure we always have echo when this script exits
addtrap "stty echo 2>/dev/null"
# Determine directories
BIN="$PREFIX/bin"
CHROOTS="$PREFIX/chroots"
if [ -z "$RESTOREBIN" ]; then
# Fix NAME if it was not specified.
# If updating and name/release weren't specified, check previous defaults
if [ -n "$UPDATE" -a -z "$NAME$RELEASE" ]; then
for rel in "$DEFAULTRELEASE" $PREVIOUS_DEFAULT_RELEASES; do
if [ -d "$CHROOTS/$rel" ]; then
DEFAULTRELEASE="$rel"
break
fi
done
fi
CHROOT="$CHROOTS/${NAME:="${RELEASE:-"$DEFAULTRELEASE"}"}"
CHROOTSRC="$CHROOT"
fi
TARGETDEDUPFILE="`mktemp --tmpdir=/tmp "$APPLICATION-dedup.XXX"`"
addtrap "rm -f '$TARGETDEDUPFILE'"
# Confirm we have write access to the directory before starting.
if [ -z "$RESTOREBIN$DOWNLOADONLY" ]; then
# Validate chroot name
if ! validate_name "$NAME"; then
error 2 "Invalid chroot name '$NAME'."
fi
# If no prefix is set, check that /usr/local/chroots ($CHROOTS) is a
# symbolic link to /mnt/stateful_partition/crouton/chroots ($CHROOTSLINK)
# /mnt/stateful_partition/dev_image is bind-mounted to /usr/local, so mv
# does not understand that they are on the same filesystem
# Instead, use the direct path, and confirm that they're actually the same
# to catch situations where things are bind-mounted over /usr/local
truechroots="/mnt/stateful_partition/dev_image/chroots"
if [ -z "$PREFIXSET" -a ! -h "$CHROOTS" ] \
&& ([ ! -e "$CHROOTS" ] || [ "$CHROOTS" -ef "$truechroots" ]); then
# Detect if chroots are left in the old chroots directory, and move them
# to the new directory.
if [ -e "$CHROOTS" ] && ! rmdir "$CHROOTS" 2>/dev/null; then
echo \
"Migrating data from legacy chroots directory $CHROOTS to $CHROOTSLINK..." 1>&2
# Check that CHROOTSLINK is empty
if [ -e "$CHROOTSLINK" ] && ! rmdir "$CHROOTSLINK" 2>/dev/null; then
error 1 \
"There is data in both $CHROOTS and $CHROOTSLINK.
Make sure all chroots are unmounted, then manually move the contents of
$truechroots to $CHROOTSLINK."
fi
# Wait for currently-mounted chroots to be unmounted
if grep -q "$CHROOTS" /proc/mounts && \
! sh "$HOSTBINDIR/unmount-chroot" -a -y -c "$CHROOTS"; then
echo -n \
"The above chroots appear to be running from the legacy chroots directory.
Log out of all running chroots and the install will automatically continue.
Press Ctrl-C at any time to abort the installation." 1>&2
while grep -q "$CHROOTS" /proc/mounts; do
sleep 1
done
echo 1>&2
fi
mkdir -p "$CHROOTSLINK"
mv -T "$truechroots" "$CHROOTSLINK"
fi
ln -sT "$CHROOTSLINK" "$CHROOTS"
fi
create='-n'
if [ -d "$CHROOT" ] && ! rmdir "$CHROOT" 2>/dev/null; then
if [ -n "$RESTORE" ]; then
error 1 "$CHROOTSRC already has stuff in it!
Either delete it, specify a different name (-n), or use edit-chroot to restore."
elif [ -z "$UPDATE" ]; then
error 1 "$CHROOTSRC already has stuff in it!
Either delete it, specify a different name (-n), or specify -u to update it."
fi
create=''
echo "$CHROOTSRC already exists; updating it..." 1>&2
elif [ -n "$UPDATE" -a -z "$RESTORE" ]; then
error 1 "$CHROOTSRC does not exist; cannot update.
Valid chroots:
`sh "$HOSTBINDIR/edit-chroot" -c "$CHROOTS" -a`"
fi
# Chroot must be located on an ext filesystem
if df -T "`getmountpoint "$CHROOT"`" | awk '$2~"^ext"{exit 1}'; then
error 1 "$CHROOTSRC is not an ext filesystem."
fi
# Restore the chroot now
if [ -n "$RESTORE" ]; then
sh "$HOSTBINDIR/edit-chroot" -r -f "$TARBALL" -c "$CHROOTS" -- "$NAME"
fi
# Mount the chroot and update CHROOT path
CHROOT="`sh "$HOSTBINDIR/mount-chroot" -k "$KEYFILE" \
$create $ENCRYPT -p -c "$CHROOTS" -- "$NAME"`"
# Remove the directory if bootstrapping fails. Also delete if the only file
# there is .ecryptfs (valid chroots have far more than 1 file)
addtrap "[ \"\`ls -a '$CHROOTS/$NAME' 2>/dev/null | wc -l\`\" -le 3 ] \
&& rm -rf '$CHROOTS/$NAME'"
# Auto-unmount the chroot when the script exits
addtrap "sh '$HOSTBINDIR/unmount-chroot' -y -c '$CHROOTS' -- '$NAME' 2>/dev/null"
# Sanity-check the release if we're updating
if [ -n "$UPDATE" -a -n "$RELEASE" ] &&
[ "`sh "$DISTRODIR/getrelease.sh" -r "$CHROOT"`" != "$RELEASE" ]; then
if [ "$UPDATE" != 2 ]; then
error 1 \
"Release doesn't match! Please correct the -r option, or specify a second -u to
change the release, upgrading the chroot (dangerous)."
else
echo "WARNING: Changing the chroot release to $RELEASE." 1>&2
echo "Press Control-C to abort; upgrade will continue in 5 seconds." 1>&2
sleep 5
fi
elif [ -n "$UPDATE" -a -z "$RELEASE" ]; then
# Detect the release
for DISTRODIR in "$INSTALLERDIR"/*/; do
DISTRODIR="${DISTRODIR%/}"
if RELEASE="`sh "$DISTRODIR/getrelease.sh" -r "$CHROOT"`"; then
DISTRO="${DISTRODIR##*/}"
. "$DISTRODIR/defaults"
break
fi
done
if [ -z "$DISTRO" ]; then
error 2 "Unable to determine the release in $CHROOTSRC. Please specify it with -r."
fi
fi
# Enforce the correct architecture
if [ -n "$UPDATE" ]; then
ARCH="`sh "$DISTRODIR/getrelease.sh" -a "$CHROOT"`"
fi
mkdir -p "$BIN"
fi
# Check if RELEASE is supported
releaseline="`sed -n "s/^\($RELEASE[^a-z|]*\)\(|.*\)*$/\1/p" \
"$DISTRODIR/releases"`"
if [ "${releaseline%"!"}" != "$releaseline" ]; then
echo_color tr "WARNING: $RELEASE has reached upstream end-of-life."
if [ -z "$UPDATE" ]; then
if [ -z "$MIRRORSET" ]; then
error 2 "\
That means there will be no package updates available.
You also have to specify a mirror to crouton (-m) for installation to proceed."
fi
echo "\
You have specified a mirror, so installation will proceed anyway.
You will almost certainly run into issues, but some features may still work.
Press Ctrl-C to abort; installation will continue in 30 seconds." 1>&2
else
echo "\
That means you may have issues updating now or in the future.
You should upgrade your chroot to a supported version as soon as possible.
Refer to https://goo.gl/Z5LGVD for upgrade instructions.
Press Ctrl-C to abort; normal update will continue in 30 seconds." 1>&2
fi
sleep 30
elif [ "${releaseline%"*"}" != "$releaseline" ]; then
echo_color r "WARNING: $RELEASE is an unsupported release." "
You will likely run into issues, but things may work with some effort." 1>&2
if [ -z "$UPDATE" ]; then
echo "Press Ctrl-C to abort; installation will continue in 5 seconds." 1>&2
else
echo "Press Ctrl-C to abort; update will continue in 5 seconds." 1>&2
fi
sleep 5
fi
# Checks if it's safe to enable boot signing verification.
# We check by attempting to mount / read-write. We do so in a bind mount to a
# temporary directory to avoid changing its state permanently if it is
# successful.
vboot_is_safe() {
local tmp="`mktemp -d --tmpdir=/tmp 'crouton-rwtest.XXX'`"
local unmount="umount -l '$tmp' 2>/dev/null; rmdir '$tmp'"
addtrap "$unmount"
mount --bind / "$tmp" >/dev/null
local ret=1
mount -o remount,rw "$tmp" 2>/dev/null || ret=0
undotrap
eval "$unmount"
return "$ret"
}
# Check and update dev boot settings. This may fail on old systems; ignore it.
altfw=dev_boot_altfw
if crossystem "$altfw" 2>&1 >&- | grep -q Invalid; then
altfw=dev_boot_legacy
fi
if [ -z "$DOWNLOADONLY" ] && ! vboot_is_safe; then
echo "WARNING: Your rootfs is writable. Signed boot verification cannot be enabled." 1>&2
echo "If this is a surprise to you, you should do a full system recovery via USB." 1>&2
sleep 5
elif [ -z "$DOWNLOADONLY" ] && \
boot="`crossystem dev_boot_usb $altfw dev_boot_signed_only`"; then
# db_usb and db_legacy be off, db_signed_only should be on.
echo "$boot" | {
read -r usb legacy signed
suggest=''
if [ "$usb" != 0 ]; then
echo "WARNING: USB booting is enabled; consider disabling it." 1>&2
suggest="$suggest dev_boot_usb=0"
fi
if [ "$legacy" != 0 ]; then
echo "WARNING: Legacy booting is enabled; consider disabling it." 1>&2
suggest="$suggest ${altfw}=0"
fi
if [ -n "$suggest" ]; then
if [ "$signed" != 1 ]; then
echo "WARNING: Signed boot verification is disabled; consider enabling it." 1>&2
suggest="$suggest dev_boot_signed_only=1"
fi
echo "You can use the following command: sudo crossystem$suggest" 1>&2
sleep 5
elif [ "$signed" != 1 ]; then
# Only enable signed booting if the user hasn't enabled alternate
# boot options, since those are opt-in.
echo "WARNING: Signed boot verification is disabled; enabling it for security." 1>&2
echo "You can disable it again using: sudo crossystem dev_boot_signed_only=0" 1>&2
crossystem dev_boot_signed_only=1 || true
sleep 2
fi
}
fi
# Unpack the tarball if appropriate
if [ -z "$RESTOREBIN$RESTORE$UPDATE$DOWNLOADONLY" ]; then
echo "Installing $RELEASE-$ARCH chroot to $CHROOTSRC" 1>&2
if [ -n "$TARBALL" ]; then
# Unpack the chroot
echo 'Unpacking chroot environment...' 1>&2
tar -C "$CHROOT" --strip-components=1 -xf "$TARBALL"
fi
elif [ -z "$RESTOREBIN$RESTORE$UPDATE" ]; then
echo "Downloading $RELEASE-$ARCH bootstrap to $TARBALL" 1>&2
fi
# Download the bootstrap data if appropriate
if [ -z "$UPDATE$RESTOREBIN" ] && [ -n "$DOWNLOADONLY" -o -z "$TARBALL" ]; then
# Create the temporary directory and delete it upon exit
tmp="`mktemp -d --tmpdir=/tmp "$APPLICATION.XXX"`"
subdir="$RELEASE-$ARCH"
addtrap "rm -rf --one-file-system '$tmp'"
# Ensure that the temporary directory has exec+dev, or mount a new ramfs
if [ "$NOEXECTMP" = 'y' ]; then
mount -i -t ramfs -o 'rw,dev,exec' ramfs "$tmp"
# Ensure symfollow is set on platforms that feature it, but don't fail
# on ones that do not.
mount -o 'remount,symfollow' "$tmp" 2>/dev/null || true
addtrap "umount -l '$tmp'"
fi
. "$DISTRODIR/bootstrap"
# Tar it up if we're only downloading
if [ -n "$DOWNLOADONLY" ]; then
echo 'Compressing bootstrap files...' 1>&2
$FAKEROOT tar -C "$tmp" -V "crouton:bootstrap.$subdir" \
-cajf "$TARBALL" "$subdir"
echo 'Done!' 1>&2
exit 0
fi
# Move it to the right place
echo 'Moving bootstrap files into the chroot...' 1>&2
# Make sure we do not leave an incomplete chroot in case of interrupt or
# error during the move
addtrap "rm -rf --one-file-system '$CHROOT'"
mv -f "$tmp/$subdir/"* "$CHROOT"
undotrap
fi
# Add the list of targets in file $1 to $TARGETS
deduptargets() {
if [ -r "$1" ]; then
t="`tr '\n' , < "$1"`"
t="${t%,},"
while [ -n "$t" ]; do
TARGET="${t%%,*}"
t="${t#*,}"
if [ -z "$TARGET" ]; then
continue
fi
# Don't put duplicate entries in the targets list
tlist=",$TARGETS,"
if [ "${tlist%",$TARGET,"*}" != "$tlist" ]; then
continue
fi
if [ ! -r "$TARGETSDIR/$TARGET" ]; then
echo "Previously installed target '$TARGET' no longer exists." 1>&2
continue
fi
# Add the target
TARGETS="${TARGETS%,},$TARGET"
done
fi
}
if [ -z "$RESTOREBIN" ] && [ -z "$RESTORE" -o -n "$UPDATE" ]; then
PREPARE="$CHROOT/prepare.sh"
# Create the setup script inside the chroot
echo 'Preparing chroot environment...' 1>&2
VAREXPAND="s/releases=.*\$/releases=\"\
`sed 's/$/\\\\/' "$DISTRODIR/releases"`
\"/;"
VAREXPAND="${VAREXPAND}s #ARCH# $ARCH ;s #DISTRO# $DISTRO ;"
VAREXPAND="${VAREXPAND}s #MIRROR# $MIRROR ;s #MIRROR2# $MIRROR2 ;"
VAREXPAND="${VAREXPAND}s #RELEASE# $RELEASE ;s #PROXY# $PROXY ;"
VAREXPAND="${VAREXPAND}s #VERSION# ${VERSION:-"git"} ;"
VAREXPAND="${VAREXPAND}s #USERNAME# $CROUTON_USERNAME ;"
VAREXPAND="${VAREXPAND}s/#SETOPTIONS#/$SETOPTIONS/;"
installscript "$INSTALLERDIR/prepare.sh" "$PREPARE" "$VAREXPAND"
# Append the distro-specific prepare.sh
cat "$DISTRODIR/prepare" >> "$PREPARE"
else # Restore host-bin only
PREPARE="/dev/null"
# Make sure targets are aware that we only want to restore host-bin
RESTOREHOSTBIN='y'
fi
if [ -z "$RESTOREBIN" ]; then
# Ensure that /usr/local/bin and /etc/crouton exist
mkdir -p "$CHROOT/usr/local/bin" "$CHROOT/etc/crouton"
# If -U was not specified, update existing targets.
if [ -z "$UPDATEIGNOREEXISTING" ]; then
TARGETSFILE="$CHROOT/etc/crouton/targets"
# Read the explicit targets file in the chroot
deduptargets "$TARGETSFILE"
if [ -z "$TARGETS" ]; then
error 1 "\
No target list found (your chroot may be very old).
Please specify targets with -t."
fi
# Reset the installed target list files
echo "$TARGETS" > "$TARGETSFILE"
fi
else
# Collect targets over all chroots (ignore the ones that cannot be mounted)
for chroot in "$CHROOTS"/*; do
deduptargets "$chroot/.crouton-targets"
done
fi
echo -n '' > "$TARGETDEDUPFILE"
# Check if a target has defined PROVIDES, if we are not restoring host-bin.
if [ ! -n "$RESTOREHOSTBIN" ]; then
# Create temporary file to list PROVIDES=TARGET.
PROVIDESFILE="`mktemp --tmpdir=/tmp "$APPLICATION-provides.XXX"`"
addtrap "rm -f '$PROVIDESFILE'"
t="${TARGETS%,},"
while [ -n "$t" ]; do
TARGET="${t%%,*}"
t="${t#*,}"
if [ -n "$TARGET" ]; then
(TARGETNOINSTALL="p"; . "$TARGETSDIR/$TARGET")
fi
done
fi
# Run each target, appending stdout to the prepare script.
unset SIMULATE
TARGETNOINSTALL="$RESTOREHOSTBIN"
if [ -n "$TARGETFILE" ]; then
TARGET="`readlink -f -- "$TARGETFILE"`"
(. "$TARGET") >> "$PREPARE"
fi
t="${TARGETS%,},post-common,"
while [ -n "$t" ]; do
TARGET="${t%%,*}"
t="${t#*,}"
if [ -n "$TARGET" ]; then
(. "$TARGETSDIR/$TARGET") >> "$PREPARE"
fi
done
if [ -f "$PREPARE" ]; then
# Update .crouton-targets in the unencrypted part of the chroot
cp -fT "$TARGETDEDUPFILE" "$CHROOTSRC/.crouton-targets"
chmod 500 "$PREPARE"
# Run the setup script inside the chroot
sh -e "$HOSTBINDIR/enter-chroot" -c "$CHROOTS" -n "$NAME" -xx
fi
echo "Done! You can enter the chroot using enter-chroot." 1>&2