3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
7 # This script installs Debian-derived distributions in a chroot environment.
8 # It can for example be used to have an accurate 32bit build and test
9 # environment when otherwise working on a 64bit machine.
10 # N. B. it is unlikely that this script will ever work on anything other than a
11 # Debian-derived system.
13 # Older Debian based systems had both "admin" and "adm" groups, with "admin"
14 # apparently being used in more places. Newer distributions have standardized
15 # on just the "adm" group. Check /etc/group for the prefered name of the
16 # administrator group.
17 admin
=$
(grep '^admin:' /etc
/group
>&/dev
/null
&& echo admin ||
echo adm
)
20 echo "usage: ${0##*/} [-m mirror] [-g group,...] [-s] [-c]"
21 echo "-b dir additional directories that should be bind mounted,"
23 echo " Default: if local filesystems present, ask user for help"
24 echo "-g group,... groups that can use the chroot unauthenticated"
25 echo " Default: '${admin}' and current user's group ('$(id -gn)')"
26 echo "-l List all installed chroot environments"
27 echo "-m mirror an alternate repository mirror for package downloads"
28 echo "-s configure default deb-srcs"
29 echo "-c always copy 64bit helper binaries to 32bit chroot"
30 echo "-h this help message"
34 local OPTNAME OPTIND OPTERR OPTARG
35 while getopts ":b:g:lm:sch" OPTNAME
; do
38 if [ "${OPTARG}" = "NONE" -a -z "${bind_mounts}" ]; then
39 bind_mounts
="${OPTARG}"
41 if [ "${bind_mounts}" = "NONE" -o "${OPTARG}" = "${OPTARG#/}" -o \
42 ! -d "${OPTARG}" ]; then
43 echo "Invalid -b option(s)"
47 bind_mounts
="${bind_mounts}
48 ${OPTARG} ${OPTARG} none rw,bind 0 0"
53 chroot_groups
="${chroot_groups}${chroot_groups:+,}${OPTARG}"
60 if [ -n "${mirror}" ]; then
61 echo "You can only specify exactly one mirror location"
78 echo "'-$OPTARG' needs an argument."
83 echo "invalid command-line option: $OPTARG"
90 if [ $# -ge ${OPTIND} ]; then
91 eval echo "Unexpected command line argument: \${${OPTIND}}"
98 for i
in /var
/lib
/chroot
/*; do
100 [ "${i}" = "*" ] && continue
101 [ -x "/usr/local/bin/${i%bit}" ] ||
continue
102 grep -qs "^\[${i%bit}\]\$" /etc
/schroot
/schroot.conf ||
continue
103 [ -r "/etc/schroot/script-${i}" -a \
104 -r "/etc/schroot/mount-${i}" ] ||
continue
111 trap 'stty echo -iuclc icanon 2>/dev/null' EXIT INT TERM QUIT HUP
112 stty
-echo iuclc
-icanon 2>/dev
/null
113 dd count
=1 bs
=1 2>/dev
/null
118 printf "\\$(printf '%03o' "$1")"
122 printf '%d' $
(printf '%c' "$1" |
od -tu1 -An)
126 stat
-c %T
-f "$1/" 2>/dev
/null |
127 egrep -qs '^nfs|cifs|smbfs'
130 # Check that we are running as a regular user
131 [ "$(id -nu)" = root
] && {
132 echo "Run this script as a regular user and provide your \"sudo\"" \
133 "password if requested" >&2
139 echo "This script will help you through the process of installing a"
140 echo "Debian or Ubuntu distribution in a chroot environment. You will"
141 echo "have to provide your \"sudo\" password when requested."
145 trap 'exit 1' INT TERM QUIT HUP
146 trap 'sudo apt-get clean; tput bel; echo; echo Failed' EXIT
148 # Install any missing applications that this script relies on. If these packages
149 # are already installed, don't force another "apt-get install". That would
150 # prevent them from being auto-removed, if they ever become eligible for that.
151 # And as this script only needs the packages once, there is no good reason to
152 # introduce a hard dependency on things such as dchroot and debootstrap.
154 for i
in dchroot debootstrap libwww-perl
; do
155 [ -d /usr
/share
/doc
/"$i" ] || dep
="$dep $i"
157 [ -n "$dep" ] && sudo apt-get
-y install $dep
158 sudo apt-get
-y install schroot
160 # Create directory for chroot
161 sudo mkdir
-p /var
/lib
/chroot
163 # Find chroot environments that can be installed with debootstrap
164 targets
="$(cd /usr/share/debootstrap/scripts
165 ls | grep '^[a-z]*$')"
167 # Ask user to pick one of the available targets
168 echo "The following targets are available to be installed in a chroot:"
169 j
=1; for i
in $targets; do
170 printf '%4d: %s\n' "$j" "$i"
174 printf "Which target would you like to install: "
176 [ "$n" -gt 0 -a "$n" -lt "$j" ] >&/dev
/null
&& break
178 j
=1; for i
in $targets; do
179 [ "$j" -eq "$n" ] && { distname
="$i"; break; }
184 # On x86-64, ask whether the user wants to install x86-32 or x86-64
187 if [ "$(uname -m)" = x86_64
]; then
189 echo "You are running a 64bit kernel. This allows you to install either a"
190 printf "32bit or a 64bit chroot environment. %s" \
191 "Which one do you want (32, 64) "
193 [ "${arch}" == 32 -o "${arch}" == 64 ] && break
195 [ "${arch}" == 32 ] && archflag
="--arch i386" || archflag
="--arch amd64"
199 target
="${distname}${arch}"
201 # Don't accidentally overwrite an existing installation
202 [ -d /var
/lib
/chroot
/"${target}" ] && {
204 echo "This chroot already exists on your machine."
205 if schroot
-l --all-sessions 2>&1 |
206 sed 's/^session://' |
207 grep -qs "^${target%bit}-"; then
208 echo "And it appears to be in active use. Terminate all programs that"
209 echo "are currently using the chroot environment and then re-run this"
211 echo "If you still get an error message, you might have stale mounts"
212 echo "that you forgot to delete. You can always clean up mounts by"
213 echo "executing \"${target%bit} -c\"."
216 echo "I can abort installation, I can overwrite the existing chroot,"
217 echo "or I can delete the old one and then exit. What would you like to"
218 printf "do (a/o/d)? "
222 o|O
) sudo
rm -rf "/var/lib/chroot/${target}"; break;;
223 d|D
) sudo
rm -rf "/var/lib/chroot/${target}" \
224 "/usr/local/bin/${target%bit}" \
225 "/etc/schroot/mount-${target}" \
226 "/etc/schroot/script-${target}"
227 sudo
sed -ni '/^[[]'"${target%bit}"']$/,${
228 :1;n;/^[[]/b2;b1;:2;p;n;b2};p' \
229 "/etc/schroot/schroot.conf"
230 trap '' INT TERM QUIT HUP
238 sudo mkdir
-p /var
/lib
/chroot
/"${target}"
240 # Offer to include additional standard repositories for Ubuntu-based chroots.
242 grep -qs ubuntu.com
/usr
/share
/debootstrap
/scripts
/"${distname}" && {
244 echo "Would you like to add ${distname}-updates and ${distname}-security "
245 printf "to the chroot's sources.list (y/n)? "
247 case "${alt_repos}" in
260 # Check for non-standard file system mount points and ask the user whether
261 # they should be imported into the chroot environment
262 # We limit to the first 26 mount points that much some basic heuristics,
263 # because a) that allows us to enumerate choices with a single character,
264 # and b) if we find more than 26 mount points, then these are probably
265 # false-positives and something is very unusual about the system's
266 # configuration. No need to spam the user with even more information that
267 # is likely completely irrelevant.
268 if [ -z "${bind_mounts}" ]; then
269 mounts
="$(awk '$2 != "/" && $2 !~ "^
/boot
" && $2 !~ "^
/home
" &&
270 $2 !~ "^
/media
" && $2 !~ "^
/run
" &&
271 ($3 ~ "ext
[2-4]" || $3 == "reiserfs
" || $3 == "btrfs
" ||
272 $3 == "xfs
" || $3 == "jfs
" || $3 == "u?msdos
" ||
273 $3 == "v?fat
" || $3 == "hfs
" || $3 == "ntfs
" ||
274 $3 ~ "nfs
[4-9]?
" || $3 == "smbfs
" || $3 == "cifs
") {
278 if [ -n "${mounts}" ]; then
279 echo "You appear to have non-standard mount points that you"
280 echo "might want to import into the chroot environment:"
284 # Print a menu, listing all non-default mounts of local or network
286 j
=1; for m
in ${mounts}; do
287 c
="$(printf $(printf '\\%03o' $((64+$j))))"
288 echo "$sel" |
grep -qs $c &&
289 state
="mounted in chroot" || state
="$(tput el)"
290 printf " $c) %-40s${state}\n" "$m"
293 # Allow user to interactively (de-)select any of the entries
295 printf "Select mount points that you want to be included or press %s" \
297 c
="$(getkey | tr a-z A-Z)"
298 [ "$c" == " " ] && { echo; echo; break; }
300 [ "$c" '<' 'A' -o $
(ord
"$c") -gt $
((64 + $
(ord
"$j"))) ]; then
301 # Invalid input, ring the console bell
304 # Toggle the selection for the given entry
305 if echo "$sel" |
grep -qs $c; then
306 sel
="$(printf "$sel" | sed "s
/$c//")"
311 # Reposition cursor to the top of the list of entries
316 j
=1; for m
in ${mounts}; do
317 c
="$(chr $(($j + 64)))"
318 if echo "$sel" |
grep -qs $c; then
319 bind_mounts
="${bind_mounts}$m $m none rw,bind 0 0
326 # Remove stale entry from /etc/schroot/schroot.conf. Entries start
327 # with the target name in square brackets, followed by an arbitrary
328 # number of lines. The entry stops when either the end of file has
329 # been reached, or when the beginning of a new target is encountered.
330 # This means, we cannot easily match for a range of lines in
331 # "sed". Instead, we actually have to iterate over each line and check
332 # whether it is the beginning of a new entry.
333 sudo
sed -ni '/^[[]'"${target%bit}"']$/,${:1;n;/^[[]/b2;b1;:2;p;n;b2};p' \
334 /etc
/schroot
/schroot.conf
336 # Download base system. This takes some time
337 if [ -z "${mirror}" ]; then
338 grep -qs ubuntu.com
/usr
/share
/debootstrap
/scripts
/"${distname}" &&
339 mirror
="http://archive.ubuntu.com/ubuntu" ||
340 mirror
="http://ftp.us.debian.org/debian"
343 sudo
${http_proxy:+http_proxy="${http_proxy}"} debootstrap
${archflag} \
344 "${distname}" "/var/lib/chroot/${target}" "$mirror"
346 # Add new entry to /etc/schroot/schroot.conf
347 grep -qs ubuntu.com
/usr
/share
/debootstrap
/scripts
/"${distname}" &&
348 brand
="Ubuntu" || brand
="Debian"
349 if [ -z "${chroot_groups}" ]; then
350 chroot_groups
="${admin},$(id -gn)"
352 # Older versions of schroot wanted a "priority=" line, whereas recent
353 # versions deprecate "priority=" and warn if they see it. We don't have
354 # a good feature test, but scanning for the string "priority=" in the
355 # existing "schroot.conf" file is a good indication of what to do.
356 priority
=$
(grep -qs 'priority=' /etc
/schroot
/schroot.conf
&&
357 echo 'priority=3' ||
:)
358 sudo sh
-c 'cat >>/etc/schroot/schroot.conf' <<EOF
360 description=${brand} ${distname} ${arch}
362 directory=/var/lib/chroot/${target}
364 groups=${chroot_groups}
365 root-groups=${chroot_groups}
366 personality=linux$([ "${arch}" != 64bit ] && echo 32)
367 script-config=script-${target}
372 # Set up a list of mount points that is specific to this
373 # chroot environment.
374 sed '/^FSTAB=/s,"[^"]*","/etc/schroot/mount-'"${target}"'",' \
375 /etc
/schroot
/script-defaults |
376 sudo sh
-c 'cat >/etc/schroot/script-'"${target}"
377 sed '\,^/home[/[:space:]],s/\([,[:space:]]\)bind[[:space:]]/\1rbind /' \
378 /etc
/schroot
/mount-defaults |
379 sudo sh
-c 'cat > /etc/schroot/mount-'"${target}"
381 # Add the extra mount points that the user told us about
382 [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] &&
383 printf "${bind_mounts}" |
384 sudo sh
-c 'cat >>/etc/schroot/mount-'"${target}"
386 # If this system has a "/media" mountpoint, import it into the chroot
387 # environment. Most modern distributions use this mount point to
388 # automatically mount devices such as CDROMs, USB sticks, etc...
390 ! grep -qs '^/media' /etc
/schroot
/mount-
"${target}"; then
391 echo '/media /media none rw,rbind 0 0' |
392 sudo sh
-c 'cat >>/etc/schroot/mount-'"${target}"
395 # Share /dev/shm and possibly /run/shm
396 grep -qs '^/dev/shm' /etc
/schroot
/mount-
"${target}" ||
397 echo '/dev/shm /dev/shm none rw,bind 0 0' |
398 sudo sh
-c 'cat >>/etc/schroot/mount-'"${target}"
399 if [ -d "/var/lib/chroot/${target}/run" ] &&
400 ! grep -qs '^/run/shm' /etc
/schroot
/mount-
"${target}"; then
401 { [ -d /run
] && echo '/run/shm /run/shm none rw,bind 0 0' ||
402 echo '/dev/shm /run/shm none rw,bind 0 0'; } |
403 sudo sh
-c 'cat >>/etc/schroot/mount-'"${target}"
406 # Set up a special directory that changes contents depending on the target
408 d
="$(readlink -f "${HOME}/chroot
" 2>/dev/null || echo "${HOME}/chroot
")"
410 echo "${s} ${d} none rw,bind 0 0" |
411 sudo sh
-c 'cat >>/etc/schroot/mount-'"${target}"
414 # Install a helper script to launch commands in the chroot
415 sudo sh
-c 'cat >/usr/local/bin/'"${target%bit}" <<'EOF'
421 # Word-wrap the text passed-in on stdin. Optionally, on continuation lines
422 # insert the same number of spaces as the number of characters in the
423 # parameter(s) passed to this function.
424 # If the "fold" program cannot be found, or if the actual width of the
425 # terminal cannot be determined, this function doesn't attempt to do any
427 local f="$(type -P fold)"
428 [ -z "${f}" ] && { cat; return; }
429 local c="$(stty -a </dev/tty 2>/dev/null |
430 sed 's/.*columns[[:space:]]*\([0-9]*\).*/\1/;t;d')"
431 [ -z "${c}" ] && { cat; return; }
432 local i="$(echo "$*"|sed 's/./ /g')"
433 local j="$(printf %s "${i}"|wc -c)"
434 if [ "${c}" -gt "${j}" ]; then
435 dd bs=1 count="${j}" 2>/dev/null
436 "${f}" -sw "$((${c}-${j}))" | sed '2,$s/^/'"${i}"'/'
443 echo "Usage ${0##*/} [-h|--help] [-c|--clean] [-C|--clean-all] [-l|--list] [--] args" | wrap "Usage ${0##*/} "
444 echo " help: print this message" | wrap " "
445 echo " list: list all known chroot environments" | wrap " "
446 echo " clean: remove all old chroot sessions for \"${chroot}\"" | wrap " "
447 echo " clean-all: remove all old chroot sessions for all environments" | wrap " "
454 for s in $(schroot -l --all-sessions); do
457 [ "${t#${chroot}-}" == "${t}" ] && continue
459 if ls -l /proc/*/{cwd,fd} 2>/dev/null |
460 fgrep -qs "/var/lib/schroot/mount/${t}"; then
461 echo "Session \"${t}\" still has active users, not cleaning up" | wrap
465 sudo schroot -c "${s}" -e || rc=1
471 for e in $(schroot -l); do
473 [ -x "/usr/local/bin/${e}" ] || continue
474 if schroot -l --all-sessions 2>/dev/null |
475 sed 's/^session://' |
476 grep -qs "^${e}-"; then
477 echo "${e} is currently active"
485 while [ "$#" -ne 0 ]; do
488 -h|--help) shift; help;;
489 -l|--list) shift; list;;
490 -c|--clean) shift; clean "${chroot}";;
491 -C|--clean-all) shift; clean;;
496 session="$(schroot -c "${chroot}" -b)"
498 if [ $# -eq 0 ]; then
499 schroot -c "${session}" -r -p
502 schroot -c "${session}" -r -p "$p" -- "$@"
506 i=$(schroot -c "${session}" -r -p ls -- -id /proc/self/root/. |
507 awk '{ print $1 }') 2>/dev/null
508 while [ -n "$i" ]; do
509 pids=$(ls -id1 /proc/*/root/. 2>/dev/null |
510 sed -e 's,^[^0-9]*'$i'.*/\([1-9][0-9]*\)/.*$,\1,
513 [ -z "$pids" ] && break
516 schroot -c "${session}" -e
519 sudo chown root
:root
/usr
/local
/bin
/"${target%bit}"
520 sudo
chmod 755 /usr
/local
/bin
/"${target%bit}"
522 # Add the standard Ubuntu update repositories if requested.
523 [ "${alt_repos}" = "y" -a \
524 -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
525 sudo
sed -i '/^deb .* [^ -]\+ main$/p
526 s/^\(deb .* [^ -]\+\) main/\1-security main/
530 :1;s/-security main/-updates main/
532 d' "/var/lib/chroot/${target}/etc/apt/sources.list"
534 # Add a few more repositories to the chroot
535 [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
536 sudo
sed -i 's/ main$/ main restricted universe multiverse/' \
537 "/var/lib/chroot/${target}/etc/apt/sources.list"
539 # Add the Ubuntu "partner" repository, if available
540 if [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
541 HEAD
"http://archive.canonical.com/ubuntu/dists/${distname}/partner" \
544 echo "deb http://archive.canonical.com/ubuntu" \
545 "'"${distname}"' partner" \
546 >>"/var/lib/chroot/'"${target}"'/etc/apt/sources.list"'
549 # Add source repositories, if the user requested we do so
550 [ "${add_srcs}" = "y" -a \
551 -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] &&
552 sudo
sed -i '/^deb[^-]/p
553 s/^deb\([^-]\)/deb-src\1/' \
554 "/var/lib/chroot/${target}/etc/apt/sources.list"
556 # Set apt proxy if host has set http_proxy
557 if [ -n "${http_proxy}" ]; then
559 echo "Acquire::http::proxy \"'"${http_proxy}"'\";" \
560 >>"/var/lib/chroot/'"${target}"'/etc/apt/apt.conf"'
564 sudo
"/usr/local/bin/${target%bit}" /bin
/sh
-c '
565 apt-get update; apt-get -y dist-upgrade' ||
:
567 # Install a couple of missing packages
568 for i
in debian-keyring ubuntu-keyring locales sudo
; do
569 [ -d "/var/lib/chroot/${target}/usr/share/doc/$i" ] ||
570 sudo
"/usr/local/bin/${target%bit}" apt-get
-y install "$i" ||
:
574 sudo
"/usr/local/bin/${target%bit}" /bin
/sh
-c '
575 l='"${LANG:-en_US}"'; l="${l%%.*}"
576 [ -r /etc/locale.gen ] &&
577 sed -i "s/^# \($l\)/\1/" /etc/locale.gen
578 locale-gen $LANG en_US en_US.UTF-8' ||
:
580 # Enable multi-arch support, if available
581 sudo
"/usr/local/bin/${target%bit}" dpkg
--assert-multi-arch >&/dev
/null
&&
582 [ -r "/var/lib/chroot/${target}/etc/apt/sources.list" ] && {
583 sudo
sed -i 's/ / [arch=amd64,i386] /' \
584 "/var/lib/chroot/${target}/etc/apt/sources.list"
585 [ -d /var
/lib
/chroot
/${target}/etc
/dpkg
/dpkg.cfg.d
/ ] &&
586 echo foreign-architecture \
587 $
([ "${arch}" = "32bit" ] && echo amd64 ||
echo i386
) |
588 sudo sh
-c "cat >'/var/lib/chroot/${target}/etc/dpkg/dpkg.cfg.d/multiarch'"
591 # Configure "sudo" package
592 sudo
"/usr/local/bin/${target%bit}" /bin
/sh
-c '
593 egrep -qs '"'^$(id -nu) '"' /etc/sudoers ||
594 echo '"'$(id -nu) ALL=(ALL) ALL'"' >>/etc/sudoers'
596 # Install a few more commonly used packages
597 sudo
"/usr/local/bin/${target%bit}" apt-get
-y install \
598 autoconf automake1.9 dpkg-dev g
++-multilib gcc-multilib gdb
less libtool \
601 # If running a 32bit environment on a 64bit machine, install a few binaries
602 # as 64bit. This is only done automatically if the chroot distro is the same as
603 # the host, otherwise there might be incompatibilities in build settings or
604 # runtime dependencies. The user can force it with the '-c' flag.
605 host_distro
=$
(grep -s DISTRIB_CODENAME
/etc
/lsb-release | \
607 if [ "${copy_64}" = "y" -o \
608 "${host_distro}" = "${distname}" -a "${arch}" = 32bit
] && \
609 file /bin
/bash
2>/dev
/null |
grep -q x86-64
; then
610 readlinepkg
=$
(sudo
"/usr/local/bin/${target%bit}" sh
-c \
611 'apt-cache search "lib64readline.\$" | sort | tail -n 1 | cut -d " " -f 1')
612 sudo
"/usr/local/bin/${target%bit}" apt-get
-y install \
613 lib64expat1 lib64ncurses5
${readlinepkg} lib64z1
615 for i
in binutils gdb
; do
616 [ -d /usr
/share
/doc
/"$i" ] || dep
="$dep $i"
618 [ -n "$dep" ] && sudo apt-get
-y install $dep
619 sudo mkdir
-p "/var/lib/chroot/${target}/usr/local/lib/amd64"
620 for i
in libbfd libpython
; do
621 lib
="$({ ldd /usr/bin/ld; ldd /usr/bin/gdb; } |
622 grep -s "$i" | awk '{ print $3 }')"
623 if [ -n "$lib" -a -r "$lib" ]; then
624 sudo
cp "$lib" "/var/lib/chroot/${target}/usr/local/lib/amd64"
627 for lib
in libssl libcrypt
; do
628 for path
in /usr
/lib
/usr
/lib
/x86_64-linux-gnu
; do
629 sudo
cp $path/$lib* \
630 "/var/lib/chroot/${target}/usr/local/lib/amd64/" >&/dev
/null ||
:
634 sudo
cp /usr
/bin
/$i "/var/lib/chroot/${target}/usr/local/lib/amd64/"
635 sudo sh
-c "cat >'/var/lib/chroot/${target}/usr/local/bin/$i'" <<EOF
637 exec /lib64/ld-linux-x86-64.so.2 --library-path /usr/local/lib/amd64 \
638 /usr/local/lib/amd64/$i "\$@"
640 sudo
chmod 755 "/var/lib/chroot/${target}/usr/local/bin/$i"
645 # If the install-build-deps.sh script can be found, offer to run it now
646 script="$(dirname $(readlink -f "$0"))/install-build-deps.sh"
647 if [ -x "${script}" ]; then
650 echo "If you plan on building Chrome inside of the new chroot environment,"
651 echo "you now have to install the build dependencies. Do you want me to"
652 printf "start the script that does this for you (y/n)? "
654 case "${install_deps}" in
657 # We prefer running the script in-place, but this might not be
658 # possible, if it lives on a network filesystem that denies
661 if ! sudo
"${target%bit}" sh
-c "[ -x '${script}' ]" >&/dev
/null
; then
662 tmp_script
="/tmp/${script##*/}"
663 cp "${script}" "${tmp_script}"
665 # Some distributions automatically start an instance of the system-
666 # wide dbus daemon or of the logging daemon, when installing the Chrome
667 # build depencies. This prevents the chroot session from being closed.
668 # So, we always try to shut down any running instance of dbus and
670 sudo
"${target%bit}" sh
-c "${script} --no-lib32;
672 /etc/init.d/rsyslog stop >/dev/null 2>&1 || :;
673 /etc/init.d/dbus stop >/dev/null 2>&1 || :;
676 [ -n "${tmp_script}" ] && rm -f "${tmp_script}"
677 [ $rc -ne 0 ] && exit $rc
688 # Check whether ~/chroot is on a (slow) network file system and offer to
689 # relocate it. Also offer relocation, if the user appears to have multiple
690 # spindles (as indicated by "${bind_mount}" being non-empty).
691 # We only offer this option, if it doesn't look as if a chroot environment
692 # is currently active. Otherwise, relocation is unlikely to work and it
693 # can be difficult for the user to recover from the failed attempt to relocate
694 # the ~/chroot directory.
695 # We don't aim to solve this problem for every configuration,
696 # but try to help with the common cases. For more advanced configuration
697 # options, the user can always manually adjust things.
698 mkdir
-p "${HOME}/chroot/"
699 if [ ! -h "${HOME}/chroot" ] &&
700 ! egrep -qs '^[^[:space:]]*/chroot' /etc
/fstab
&&
701 { [ -n "${bind_mounts}" -a "${bind_mounts}" != "NONE" ] ||
702 is_network_drive
"${HOME}/chroot"; } &&
703 ! egrep -qs '/var/lib/[^/]*chroot/.*/chroot' /proc
/mounts
; then
704 echo "${HOME}/chroot is currently located on the same device as your"
705 echo "home directory."
706 echo "This might not be what you want. Do you want me to move it somewhere"
708 # If the computer has multiple spindles, many users configure all or part of
709 # the secondary hard disk to be writable by the primary user of this machine.
710 # Make some reasonable effort to detect this type of configuration and
711 # then offer a good location for where to put the ~/chroot directory.
713 for i
in $
(echo "${bind_mounts}"|cut
-d ' ' -f 1); do
714 if [ -d "$i" -a -w "$i" -a \
( ! -a "$i/chroot" -o -w "$i/chroot/." \
) ] &&
715 ! is_network_drive
"$i"; then
719 if [ -d "$j" -a -w "$j" -a \
720 \
( ! -a "$j/chroot" -o -w "$j/chroot/." \
) ] &&
721 ! is_network_drive
"$j"; then
725 if [ -d "$k" -a -w "$k" -a \
726 \
( ! -a "$k/chroot" -o -w "$k/chroot/." \
) ] &&
727 ! is_network_drive
"$k"; then
733 [ -n "${suggest}" ] && break
736 [ -n "${suggest}" ] && break
738 def_suggest
="${HOME}"
739 if [ -n "${suggest}" ]; then
740 # For home directories that reside on network drives, make our suggestion
741 # the default option. For home directories that reside on a local drive,
742 # require that the user manually enters the new location.
743 if is_network_drive
"${HOME}"; then
744 def_suggest
="${suggest}"
746 echo "A good location would probably be in \"${suggest}\""
750 printf "Physical location [${def_suggest}]: "
752 [ -z "${dir}" ] && dir
="${def_suggest}"
753 [ "${dir%%/}" == "${HOME%%/}" ] && break
754 if ! [ -d "${dir}" -a -w "${dir}" ] ||
755 [ -a "${dir}/chroot" -a ! -w "${dir}/chroot/." ]; then
756 echo "Cannot write to ${dir}/chroot. Please try again"
758 mv "${HOME}/chroot" "${dir}/chroot"
759 ln -s "${dir}/chroot" "${HOME}/chroot"
760 for i
in $
(list_all_chroots
); do
761 sudo
"$i" mkdir
-p "${dir}/chroot"
763 sudo
sed -i "s,${HOME}/chroot,${dir}/chroot,g" /etc
/schroot
/mount-
*
769 # Clean up package files
770 sudo schroot
-c "${target%bit}" -p -- apt-get clean
773 trap '' INT TERM QUIT HUP
776 # Let the user know what we did
780 Successfully installed ${distname} ${arch}
782 You can run programs inside of the chroot by invoking the "${target%bit}"
785 This command can be used with arguments, in order to just run a single
786 program inside of the chroot environment (e.g. "${target%bit} make chrome")
787 or without arguments, in order to run an interactive shell session inside
788 of the chroot environment.
790 If you need to run things as "root", you can use "sudo" (e.g. try
791 "sudo ${target%bit} apt-get update").
793 Your home directory is shared between the host and the chroot. But I
794 configured "${HOME}/chroot" to be private to the chroot environment.
795 You can use it for files that need to differ between environments. This
796 would be a good place to store binaries that you have built from your
799 For Chrome, this probably means you want to make your "out" directory a
800 symbolic link that points somewhere inside of "${HOME}/chroot".
802 You still need to run "gclient runhooks" whenever you switch from building
803 outside of the chroot to inside of the chroot. But you will find that you
804 don't have to repeatedly erase and then completely rebuild all your object