mirror of
https://github.com/flatcar/scripts.git
synced 2025-11-28 14:01:43 +01:00
Convert make_chroot.sh and enter_chroot.sh to run as root.
sudo takes 150ms per invocation on Goobuntu, and with 10 invocations in
enter_chroot.sh, this means that we're wasting a lot of time, every time
cros_sdk is invoked. Cutting these unnecessary invocations reduces the time
required to run enter_chroot.sh from 2.3s to 0.8s.
CL:36618 is the companion change that updates cros_sdk to invoke
sudo unshare -m prior to calling enter_chroot.sh.
Summary of changes:
1. Remove all calls to sudo and just run the commands directly.
- Remove the mount queue and any sudo_multi optimizations.
- Rename sudo_chroot -> bare_chroot because we don't run sudo anymore there.
- Remove code for validating sudo timestamp.
2. Allow the scripts to work as root:
- Ensure that files created by cros_sdk that previously were owned by the
user still are owned by the user (either using chown or cp -p).
- Use $SUDO_USER to find the user's account.
- Use $SUDO_HOME instead of $HOME to find the user's home dir.
- Remove outdated code for disabling automount on Lucid, which doesn't work
when run as root.
- Update code for calculating the user's git username to use sudo to switch
to the user. Also move it to make_chroot.sh so that this change doesn't
impact performance.
3. Cleanup
- Remove environment syncer process in favor of just syncing once when chroot
is entered.
- Remove teardown and instead rely on unshare to unmount the mounts. To make
sure that outside processes never notice the mounts, we use mount -n. This
also ensures that /etc/mtab never contains stale mounts.
- Remove path-overrides, since it is no longer needed.
BUG=chromium-os:35714, chromium-os:35679
TEST=Trybot runs.
CQ-DEPEND=CL:36618
Change-Id: I919a8aadb08fafde97348e8511573c28fdd47186
Reviewed-on: https://gerrit.chromium.org/gerrit/36619
Tested-by: David James <davidjames@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Commit-Ready: David James <davidjames@chromium.org>
This commit is contained in:
parent
12a9a84de9
commit
76764885b9
@ -5,11 +5,12 @@
|
||||
# Note that this script is invoked by make_chroot in addition
|
||||
# to normal upgrade pathways.
|
||||
|
||||
if [ "$(id -u)" != 0 ]; then
|
||||
if [ "${UID:-$(id -u)}" != 0 ]; then
|
||||
# Note that since we're screwing w/ sudo variables, this script
|
||||
# explicitly bounces up to root for everything it does- that way
|
||||
# if anyone introduces a temp depriving in the sudo setup, it can't break
|
||||
# mid upgrade.
|
||||
load_environment_whitelist
|
||||
exec sudo bash -e "${VERSION_HOOKS_DIR}/45_rewrite_sudoers.d" \
|
||||
/ "${USER}" "${ENVIRONMENT_WHITELIST[@]}"
|
||||
exit 1
|
||||
|
||||
@ -2,12 +2,4 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# Ensure that crosutils path overrides are in use; note that chroot
|
||||
# creation also invokes this, thus why we check for CROS_CHROOT; for
|
||||
# the normal upgrade pathway, it's non existant. For chroot creation,
|
||||
# It points to the chroot base.
|
||||
sudo mkdir -p "${CROS_CHROOT}/etc/profile.d/"
|
||||
echo 'export PATH="/usr/local/path-overrides${PATH:+:${PATH}}"' | \
|
||||
sudo tee "${CROS_CHROOT}"/etc/profile.d/crosutils-path-overrides.sh \
|
||||
> /dev/null
|
||||
sudo chmod 644 "${CROS_CHROOT}"/etc/profile.d/crosutils-path-overrides.sh
|
||||
# Path overrides are no longer in use, so this script is just a placeholder.
|
||||
|
||||
95
common.sh
95
common.sh
@ -209,6 +209,15 @@ get_gclient_root() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Populate the ENVIRONMENT_WHITELIST array.
|
||||
load_environment_whitelist() {
|
||||
set -f
|
||||
ENVIRONMENT_WHITELIST=(
|
||||
$("${GCLIENT_ROOT}/chromite/scripts/cros_env_whitelist")
|
||||
)
|
||||
set +f
|
||||
}
|
||||
|
||||
# Find root of source tree
|
||||
get_gclient_root
|
||||
|
||||
@ -300,20 +309,6 @@ DEFAULT_FAST=${FLAGS_TRUE}
|
||||
# Directory to store built images. Should be set by sourcing script when used.
|
||||
BUILD_DIR=
|
||||
|
||||
# List of variables to proxy into the chroot from the host, and to
|
||||
# have sudo export if existent.
|
||||
# Anytime this list is modified, to make that change active a new
|
||||
# chroot_version_hooks.d upgrade script that symlinks to 45_rewrite_sudoers.d
|
||||
# is required.
|
||||
ENVIRONMENT_WHITELIST=(
|
||||
CHROMEOS_OFFICIAL
|
||||
{http{,s},ftp,all,no}_proxy
|
||||
RSYNC_PROXY
|
||||
GIT_{PROXY_COMMAND,SSH}
|
||||
SSH_AGENT_PID
|
||||
SSH_AUTH_SOCK
|
||||
)
|
||||
|
||||
# Standard filenames
|
||||
CHROMEOS_BASE_IMAGE_NAME="chromiumos_base_image.bin"
|
||||
CHROMEOS_IMAGE_NAME="chromiumos_image.bin"
|
||||
@ -324,7 +319,11 @@ CHROMEOS_FACTORY_TEST_IMAGE_NAME="chromiumos_factory_image.bin"
|
||||
CHROMEOS_FACTORY_INSTALL_SHIM_NAME="factory_install_shim.bin"
|
||||
|
||||
# Directory locations inside the dev chroot
|
||||
CHROOT_TRUNK_DIR="/home/$USER/trunk"
|
||||
if [ "${USER}" = "root" ]; then
|
||||
CHROOT_TRUNK_DIR="/home/${SUDO_USER}/trunk"
|
||||
else
|
||||
CHROOT_TRUNK_DIR="/home/${USER}/trunk"
|
||||
fi
|
||||
|
||||
# Install make for portage ebuilds. Used by build_image and gmergefs.
|
||||
# TODO: Is /usr/local/autotest-chrome still used by anyone?
|
||||
@ -452,12 +451,18 @@ assert_outside_chroot() {
|
||||
}
|
||||
|
||||
assert_not_root_user() {
|
||||
if [ $(id -u) = 0 ]; then
|
||||
if [ ${UID:-$(id -u)} = 0 ]; then
|
||||
echo "This script must be run as a non-root user."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_root_user() {
|
||||
if [ ${UID:-$(id -u)} != 0 ] || [ "${SUDO_USER:-root}" = "root" ]; then
|
||||
die_notrace "This script must be run using sudo from a non-root user."
|
||||
fi
|
||||
}
|
||||
|
||||
# Check that all arguments are flags; that is, there are no remaining arguments
|
||||
# after parsing from shflags. Allow (with a warning) a single empty-string
|
||||
# argument.
|
||||
@ -534,6 +539,37 @@ sudo_multi() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Writes stdin to the given file name as the sudo user in overwrite mode.
|
||||
#
|
||||
# $@ - The output file names.
|
||||
user_clobber() {
|
||||
install -m644 -o ${SUDO_UID} -g ${SUDO_GID} /dev/stdin "$@"
|
||||
}
|
||||
|
||||
# Appends stdin to the given file name as the sudo user.
|
||||
#
|
||||
# $1 - The output file name.
|
||||
user_append() {
|
||||
cat >> "$1"
|
||||
chown ${SUDO_UID}:${SUDO_GID} "$1"
|
||||
}
|
||||
|
||||
# Create the specified directory, along with parents, as the sudo user.
|
||||
#
|
||||
# $@ - The directories to create.
|
||||
user_mkdir() {
|
||||
install -o ${SUDO_UID} -g ${SUDO_GID} -d "$@"
|
||||
}
|
||||
|
||||
# Create the specified symlink as the sudo user.
|
||||
#
|
||||
# $1 - Link target
|
||||
# $2 - Link name
|
||||
user_symlink() {
|
||||
ln -sfT "$1" "$2"
|
||||
chown -h ${SUDO_UID}:${SUDO_GID} "$2"
|
||||
}
|
||||
|
||||
# Locate all mounts below a specified directory.
|
||||
#
|
||||
# $1 - The root tree.
|
||||
@ -585,15 +621,11 @@ safe_umount_tree() {
|
||||
}
|
||||
|
||||
|
||||
# Helper; all scripts should use this since it ensures our
|
||||
# override of umount is used (inside the chroot, it's enforced
|
||||
# via configuration; outside is the concern).
|
||||
# Args are passed directly to umount; no sudo args are allowed.
|
||||
# Run umount as root.
|
||||
safe_umount() {
|
||||
sudo "${SCRIPT_ROOT}/path-overrides/umount" "$@"
|
||||
$([ ${UID:-$(id -u)} != 0 ] && echo sudo) umount "$@"
|
||||
}
|
||||
|
||||
|
||||
get_git_id() {
|
||||
git var GIT_COMMITTER_IDENT | sed -e 's/^.*<\(\S\+\)>.*$/\1/'
|
||||
}
|
||||
@ -1080,23 +1112,6 @@ switch_to_strict_mode() {
|
||||
# TODO: Re-enable this once shflags is set -e safe.
|
||||
#switch_to_strict_mode
|
||||
|
||||
# The following code is used to ensure our umount wrapper is in use.
|
||||
# Shouldn't be invoked by anything other than common.sh
|
||||
_enable_path_overrides(){
|
||||
# Ensure that our PATH overrides are in use.
|
||||
local override_dir=$(readlink -f "${SCRIPT_ROOT}/path-overrides")
|
||||
local IFS=:
|
||||
local x
|
||||
for x in ${PATH}; do
|
||||
x=$(readlink -f "${x}")
|
||||
if [ "${x}" = "${override_dir}" ]; then
|
||||
# Already is in path; nothing more to do.
|
||||
return
|
||||
fi
|
||||
done
|
||||
export PATH="${override_dir}${PATH:+:${PATH}}"
|
||||
}
|
||||
|
||||
okboat() {
|
||||
# http://www.chris.com/ascii/index.php?art=transportation/nautical
|
||||
echo -e "${V_BOLD_GREEN}"
|
||||
@ -1127,5 +1142,3 @@ BOAT
|
||||
echo -e "${V_VIDOFF}"
|
||||
die "$* failed"
|
||||
}
|
||||
|
||||
_enable_path_overrides
|
||||
|
||||
@ -9,11 +9,9 @@
|
||||
SCRIPT_ROOT=$(readlink -f $(dirname "$0")/..)
|
||||
. "${SCRIPT_ROOT}/common.sh" || exit 1
|
||||
|
||||
enable_strict_sudo
|
||||
|
||||
# Script must be run outside the chroot and as a regular user.
|
||||
# Script must be run outside the chroot and as root.
|
||||
assert_outside_chroot
|
||||
assert_not_root_user
|
||||
assert_root_user
|
||||
|
||||
# Define command line flags
|
||||
# See http://code.google.com/p/shflags/wiki/Documentation10x
|
||||
@ -25,14 +23,12 @@ DEFINE_string build_number "" \
|
||||
"The build-bot build number (when called by buildbot only)." "b"
|
||||
DEFINE_string chrome_root "" \
|
||||
"The root of your chrome browser source. Should contain a 'src' subdir."
|
||||
DEFINE_string chrome_root_mount "/home/$USER/chrome_root" \
|
||||
DEFINE_string chrome_root_mount "/home/${SUDO_USER}/chrome_root" \
|
||||
"The mount point of the chrome broswer source in the chroot."
|
||||
DEFINE_string cache_dir "" "Directory to use for caching."
|
||||
|
||||
DEFINE_boolean official_build $FLAGS_FALSE \
|
||||
"Set CHROMEOS_OFFICIAL=1 for release builds."
|
||||
DEFINE_boolean mount $FLAGS_FALSE "Only set up mounts."
|
||||
DEFINE_boolean unmount $FLAGS_FALSE "Only tear down mounts."
|
||||
DEFINE_boolean ssh_agent $FLAGS_TRUE "Import ssh agent."
|
||||
DEFINE_boolean early_make_chroot $FLAGS_FALSE \
|
||||
"Internal flag. If set, the command is run as root without sudo."
|
||||
@ -47,7 +43,7 @@ the chroot environment. For example:
|
||||
$0 FOO=bar BAZ=bel
|
||||
|
||||
If [-- command] is present, runs the command inside the chroot,
|
||||
after changing directory to /$USER/trunk/src/scripts. Note that neither
|
||||
after changing directory to /${SUDO_USER}/trunk/src/scripts. Note that neither
|
||||
the command nor args should include single quotes. For example:
|
||||
|
||||
$0 -- ./build_platform_packages.sh
|
||||
@ -56,6 +52,7 @@ Otherwise, provides an interactive shell.
|
||||
"
|
||||
|
||||
CROS_LOG_PREFIX=cros_sdk:enter_chroot
|
||||
SUDO_HOME=$(eval echo ~${SUDO_USER})
|
||||
|
||||
# Version of info from common.sh that only echos if --verbose is set.
|
||||
debug() {
|
||||
@ -89,30 +86,21 @@ FILES_TO_COPY_TO_CHROOT=(
|
||||
|
||||
INNER_CHROME_ROOT=$FLAGS_chrome_root_mount # inside chroot
|
||||
CHROME_ROOT_CONFIG="/var/cache/chrome_root" # inside chroot
|
||||
INNER_DEPOT_TOOLS_ROOT="/home/$USER/depot_tools" # inside chroot
|
||||
INNER_DEPOT_TOOLS_ROOT="/home/${SUDO_USER}/depot_tools" # inside chroot
|
||||
FUSE_DEVICE="/dev/fuse"
|
||||
AUTOMOUNT_PREF="/apps/nautilus/preferences/media_automount"
|
||||
SAVED_AUTOMOUNT_PREF_FILE="/tmp/.automount_pref"
|
||||
|
||||
# Avoid the sudo call if possible since it is a little slow.
|
||||
if [ $(stat -c %a "$FLAGS_chroot/var/lock") != 777 ]; then
|
||||
sudo chmod 0777 "$FLAGS_chroot/var/lock"
|
||||
fi
|
||||
chmod 0777 "$FLAGS_chroot/var/lock"
|
||||
|
||||
LOCKFILE="$FLAGS_chroot/var/lock/enter_chroot"
|
||||
SYNCERPIDFILE="${FLAGS_chroot}/var/tmp/enter_chroot_sync.pid"
|
||||
|
||||
|
||||
MOUNTED_PATH=$(readlink -f "$FLAGS_chroot")
|
||||
mount_queue_init() {
|
||||
MOUNT_QUEUE=()
|
||||
}
|
||||
|
||||
queue_mount() {
|
||||
setup_mount() {
|
||||
# If necessary, mount $source in the host FS at $target inside the
|
||||
# chroot directory with $mount_args.
|
||||
# chroot directory with $mount_args. We don't write to /etc/mtab because
|
||||
# these mounts are all contained within an unshare and are therefore
|
||||
# inaccessible to other namespaces (e.g. the host desktop system).
|
||||
local source="$1"
|
||||
local mount_args="$2"
|
||||
local mount_args="-n $2"
|
||||
local target="$3"
|
||||
|
||||
local mounted_path="${MOUNTED_PATH}$target"
|
||||
@ -122,59 +110,17 @@ queue_mount() {
|
||||
# Already mounted!
|
||||
;;
|
||||
*)
|
||||
MOUNT_QUEUE+=( "mkdir -p '${mounted_path}'" )
|
||||
mkdir -p "${mounted_path}"
|
||||
# The args are left unquoted on purpose.
|
||||
if [[ -n ${source} ]]; then
|
||||
MOUNT_QUEUE+=( "mount ${mount_args} '${source}' '${mounted_path}'" )
|
||||
mount ${mount_args} "${source}" "${mounted_path}"
|
||||
else
|
||||
MOUNT_QUEUE+=( "mount ${mount_args} '${mounted_path}'" )
|
||||
mount ${mount_args} "${mounted_path}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
process_mounts() {
|
||||
if [[ ${#MOUNT_QUEUE[@]} -eq 0 ]]; then
|
||||
return 0
|
||||
fi
|
||||
sudo_multi "${MOUNT_QUEUE[@]}"
|
||||
mount_queue_init
|
||||
}
|
||||
|
||||
env_sync_proc() {
|
||||
# This function runs and performs periodic updates to the chroot env, if
|
||||
# necessary.
|
||||
|
||||
local poll_interval=10
|
||||
local sync_files=( etc/resolv.conf etc/hosts )
|
||||
|
||||
# Make sure the files exist before the find -- they might not in a
|
||||
# fresh chroot which results in warnings in the build output.
|
||||
local chown_cmd=(
|
||||
# Make sure the files exists first -- they might not in a fresh chroot.
|
||||
"touch ${sync_files[*]/#/${FLAGS_chroot}/}"
|
||||
# Make sure the files are writable by normal user so that we don't have
|
||||
# to execute sudo in the main loop below.
|
||||
"chown ${USER} ${sync_files[*]/#/${FLAGS_chroot}/}"
|
||||
)
|
||||
sudo_multi "${chown_cmd[@]}"
|
||||
|
||||
# Drop stdin, stderr, stdout, and chroot lock.
|
||||
# This is needed for properly daemonizing the process.
|
||||
exec 0>&- 1>&- 2>&- 200>&-
|
||||
|
||||
while true; do
|
||||
# Sync files
|
||||
for file in "${sync_files[@]}"; do
|
||||
if ! cmp /${file} ${FLAGS_chroot}/${file} &> /dev/null; then
|
||||
cp -f /${file} ${FLAGS_chroot}/${file}
|
||||
fi
|
||||
done
|
||||
|
||||
sleep ${poll_interval}
|
||||
done
|
||||
}
|
||||
|
||||
copy_ssh_config() {
|
||||
# Copy user .ssh/config into the chroot filtering out strings not supported
|
||||
# by the chroot ssh. The chroot .ssh directory is passed in as the first
|
||||
@ -188,7 +134,7 @@ copy_ssh_config() {
|
||||
'GSSAPIKeyExchange'
|
||||
'ProxyUseFdpass'
|
||||
)
|
||||
local sshc="${HOME}/.ssh/config"
|
||||
local sshc="${SUDO_HOME}/.ssh/config"
|
||||
local chroot_ssh_dir="${1}"
|
||||
local filter
|
||||
local option
|
||||
@ -206,13 +152,13 @@ copy_ssh_config() {
|
||||
fi
|
||||
done
|
||||
|
||||
sed "/^.*\(${filter}\).*$/d" "${sshc}" > "${chroot_ssh_dir}/config"
|
||||
sed "/^.*\(${filter}\).*$/d" "${sshc}" | \
|
||||
user_clobber "${chroot_ssh_dir}/config"
|
||||
}
|
||||
|
||||
copy_into_chroot_if_exists() {
|
||||
# $1 is file path outside of chroot to copy to path $2 inside chroot.
|
||||
[ -e "$1" ] || return
|
||||
cp "$1" "${FLAGS_chroot}/$2"
|
||||
[ -e "$1" ] && cp -p "$1" "${FLAGS_chroot}/$2"
|
||||
}
|
||||
|
||||
# Usage: promote_api_keys
|
||||
@ -222,22 +168,22 @@ copy_into_chroot_if_exists() {
|
||||
# have been used since the concept of keys got added, as well as before
|
||||
# and after the developer decding to grab his own keys.
|
||||
promote_api_keys() {
|
||||
local destination="${FLAGS_chroot}/home/${USER}/.googleapikeys"
|
||||
local destination="${FLAGS_chroot}/home/${SUDO_USER}/.googleapikeys"
|
||||
# Don't disturb existing keys. They could be set differently
|
||||
if [[ -s "${destination}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ -r "${HOME}/.googleapikeys" ]]; then
|
||||
cp "${HOME}/.googleapikeys" "${destination}"
|
||||
if [[ -r "${SUDO_HOME}/.googleapikeys" ]]; then
|
||||
cp -p "${SUDO_HOME}/.googleapikeys" "${destination}"
|
||||
if [[ -s "${destination}" ]] ; then
|
||||
info "Copied Google API keys into chroot."
|
||||
fi
|
||||
elif [[ -r "${HOME}/.gyp/include.gypi" ]]; then
|
||||
elif [[ -r "${SUDO_HOME}/.gyp/include.gypi" ]]; then
|
||||
local NAME="('google_(api_key|default_client_(id|secret))')"
|
||||
local WS="[[:space:]]*"
|
||||
local CONTENTS="('[^\\\\']*')"
|
||||
sed -nr -e "/^${WS}${NAME}${WS}[:=]${WS}${CONTENTS}.*/{s//\1: \4,/;p;}" \
|
||||
"${HOME}/.gyp/include.gypi" >"${destination}"
|
||||
"${SUDO_HOME}/.gyp/include.gypi" | user_clobber "${destination}"
|
||||
if [[ -s "${destination}" ]]; then
|
||||
info "Put discovered Google API keys into chroot."
|
||||
fi
|
||||
@ -245,73 +191,29 @@ promote_api_keys() {
|
||||
}
|
||||
|
||||
setup_env() {
|
||||
# Validate sudo timestamp before entering the critical section so that we
|
||||
# don't stall for a password while we have the lockfile.
|
||||
# Don't use sudo -v since that has issues on machines w/ no password.
|
||||
sudo echo "" > /dev/null
|
||||
|
||||
(
|
||||
flock 200
|
||||
echo $$ >> "$LOCKFILE"
|
||||
|
||||
# If there isn't a syncer daemon started already, start one. The
|
||||
# daemon is considered to not be started under the following
|
||||
# conditions:
|
||||
#
|
||||
# o There is no PID file
|
||||
#
|
||||
# o The PID file is 0 bytes in size, which might be a partial
|
||||
# manifestation of chromium-os:17680. This situation will not
|
||||
# occur anymore, but you might have a chroot which was already
|
||||
# affected.
|
||||
#
|
||||
# o The /proc node for the process named by the PID file does
|
||||
# not exist.
|
||||
#
|
||||
# Note: This does not address PID recycling. While
|
||||
# increasingly unlikely, it is possible for the PID in
|
||||
# the PID file to refer to a running process that is not
|
||||
# the syncer process. Since the PID file is now
|
||||
# removed, I think it is only possible for this to occur
|
||||
# if your system crashes and the PID file exists after
|
||||
# restart.
|
||||
#
|
||||
# The daemon is killed by the enter_chroot that exits last.
|
||||
if [ -f "${SYNCERPIDFILE}" ] && [ ! -s "${SYNCERPIDFILE}" ] ; then
|
||||
info "You may have suffered from chromium-os:17680 and";
|
||||
info "could have stray 'enter_chroot.sh' processes running.";
|
||||
info "You must manually kill any such stray processes.";
|
||||
info "Exit all chroot shells; remaining 'enter_chroot.sh'";
|
||||
info "processes are probably stray.";
|
||||
sudo rm -f "${SYNCERPIDFILE}";
|
||||
fi;
|
||||
if ! [ -f "${SYNCERPIDFILE}" ] || \
|
||||
! [ -d /proc/$(<"${SYNCERPIDFILE}") ]; then
|
||||
debug "Starting sync process"
|
||||
env_sync_proc &
|
||||
echo $! > "${SYNCERPIDFILE}"
|
||||
disown $!
|
||||
fi
|
||||
# Make the lockfile writable for backwards compatibility.
|
||||
chown ${SUDO_UID}:${SUDO_GID} "${LOCKFILE}"
|
||||
|
||||
# Refresh /etc/resolv.conf and /etc/hosts in the chroot.
|
||||
install -C -m644 /etc/resolv.conf ${FLAGS_chroot}/etc/resolv.conf
|
||||
install -C -m644 /etc/hosts ${FLAGS_chroot}/etc/hosts
|
||||
|
||||
debug "Mounting chroot environment."
|
||||
MOUNT_CACHE=$(echo $(awk '{print $2}' /proc/mounts))
|
||||
mount_queue_init
|
||||
queue_mount none "-t proc" /proc
|
||||
queue_mount none "-t sysfs" /sys
|
||||
queue_mount /dev "--bind" /dev
|
||||
queue_mount none "-t devpts" /dev/pts
|
||||
setup_mount none "-t proc" /proc
|
||||
setup_mount none "-t sysfs" /sys
|
||||
setup_mount /dev "--bind" /dev
|
||||
setup_mount none "-t devpts" /dev/pts
|
||||
if [ -d /run ]; then
|
||||
queue_mount /run "--bind" /run
|
||||
setup_mount /run "--bind" /run
|
||||
if [ -d /run/shm ]; then
|
||||
queue_mount /run/shm "--bind" /run/shm
|
||||
setup_mount /run/shm "--bind" /run/shm
|
||||
fi
|
||||
fi
|
||||
# Get path overrides for the chroot in place now- it's possible
|
||||
# that they may be needed for early teardown.
|
||||
queue_mount "${FLAGS_trunk}/src/scripts/path-overrides" "--bind" \
|
||||
"/usr/local/path-overrides"
|
||||
|
||||
queue_mount "${FLAGS_trunk}" "--bind" "${CHROOT_TRUNK_DIR}"
|
||||
setup_mount "${FLAGS_trunk}" "--bind" "${CHROOT_TRUNK_DIR}"
|
||||
|
||||
debug "Setting up referenced repositories if required."
|
||||
REFERENCE_DIR=$(git config --file \
|
||||
@ -322,17 +224,17 @@ setup_env() {
|
||||
ALTERNATES="${FLAGS_trunk}/.repo/alternates"
|
||||
|
||||
# Ensure this directory exists ourselves, and has the correct ownership.
|
||||
[ -d "${ALTERNATES}" ] || mkdir "${ALTERNATES}"
|
||||
[ -w "${ALTERNATES}" ] || sudo chown -R "${USER}" "${ALTERNATES}"
|
||||
user_mkdir "${ALTERNATES}"
|
||||
|
||||
unset ALTERNATES
|
||||
|
||||
IFS=$'\n';
|
||||
required=( $( "${FLAGS_trunk}/chromite/lib/rewrite_git_alternates.py" \
|
||||
required=( $( sudo -u "${SUDO_USER}" -- \
|
||||
"${FLAGS_trunk}/chromite/lib/rewrite_git_alternates.py" \
|
||||
"${FLAGS_trunk}" "${REFERENCE_DIR}" "${CHROOT_TRUNK_DIR}" ) )
|
||||
unset IFS
|
||||
|
||||
queue_mount "${FLAGS_trunk}/.repo/chroot/alternates" --bind \
|
||||
setup_mount "${FLAGS_trunk}/.repo/chroot/alternates" --bind \
|
||||
"${CHROOT_TRUNK_DIR}/.repo/alternates"
|
||||
|
||||
# Note that as we're bringing up each referened repo, we also
|
||||
@ -343,13 +245,13 @@ setup_env() {
|
||||
#
|
||||
# Finally note that if you're unfamiliar w/ chroot/vfs semantics,
|
||||
# the bind is visible only w/in the chroot.
|
||||
mkdir -p ${FLAGS_trunk}/.repo/chroot/empty
|
||||
user_mkdir ${FLAGS_trunk}/.repo/chroot/empty
|
||||
position=1
|
||||
for x in "${required[@]}"; do
|
||||
base="${CHROOT_TRUNK_DIR}/.repo/chroot/external${position}"
|
||||
queue_mount "${x}" "--bind" "${base}"
|
||||
setup_mount "${x}" "--bind" "${base}"
|
||||
if [ -e "${x}/.repo/alternates" ]; then
|
||||
queue_mount "${FLAGS_trunk}/.repo/chroot/empty" "--bind" \
|
||||
setup_mount "${FLAGS_trunk}/.repo/chroot/empty" "--bind" \
|
||||
"${base}/.repo/alternates"
|
||||
fi
|
||||
position=$(( ${position} + 1 ))
|
||||
@ -360,9 +262,9 @@ setup_env() {
|
||||
|
||||
chroot_cache='/var/cache/chromeos-cache'
|
||||
debug "Setting up shared cache dir directory."
|
||||
mkdir -p "${FLAGS_cache_dir}"/distfiles/{target,host}
|
||||
sudo mkdir -p "${FLAGS_chroot}/${chroot_cache}"
|
||||
queue_mount "${FLAGS_cache_dir}" "--bind" "${chroot_cache}"
|
||||
user_mkdir "${FLAGS_cache_dir}"/distfiles/{target,host}
|
||||
user_mkdir "${FLAGS_chroot}/${chroot_cache}"
|
||||
setup_mount "${FLAGS_cache_dir}" "--bind" "${chroot_cache}"
|
||||
# TODO(build): remove this as of 12/01/12.
|
||||
# Because of how distfiles -> cache_dir was deployed, if this isn't
|
||||
# a symlink, we *know* the ondisk pathways aren't compatible- thus
|
||||
@ -372,55 +274,51 @@ setup_env() {
|
||||
# While we're at it, ensure the var is exported w/in the chroot; it
|
||||
# won't exist if distfiles isn't a symlink.
|
||||
p="${FLAGS_chroot}/etc/profile.d/chromeos-cachedir.sh"
|
||||
sudo_multi "rm -rf '${distfiles_path}'" \
|
||||
"ln -s chromeos-cache/distfiles '${distfiles_path}'" \
|
||||
"mkdir -p -m 775 '${p%/*}'" \
|
||||
"echo 'export CHROMEOS_CACHEDIR=${chroot_cache}' > '${p}'" \
|
||||
"chmod 0644 '${p}'"
|
||||
rm -rf "${distfiles_path}"
|
||||
ln -s chromeos-cache/distfiles "${distfiles_path}"
|
||||
mkdir -p -m 775 "${p%/*}"
|
||||
echo 'export CHROMEOS_CACHEDIR=${chroot_cache}' > "${p}"
|
||||
chmod 0644 "${p}"
|
||||
fi
|
||||
|
||||
if [ $FLAGS_ssh_agent -eq $FLAGS_TRUE ]; then
|
||||
if [ -n "${SSH_AUTH_SOCK}" -a -d "${HOME}/.ssh" ]; then
|
||||
TARGET_DIR="${FLAGS_chroot}/home/${USER}/.ssh"
|
||||
mkdir -p "${TARGET_DIR}"
|
||||
if [ -n "${SSH_AUTH_SOCK}" -a -d "${SUDO_HOME}/.ssh" ]; then
|
||||
TARGET_DIR="${FLAGS_chroot}/home/${SUDO_USER}/.ssh"
|
||||
user_mkdir "${TARGET_DIR}"
|
||||
# Ignore errors as some people won't have these files to copy.
|
||||
cp "${HOME}"/.ssh/{known_hosts,*.pub} "${TARGET_DIR}/" 2>/dev/null || :
|
||||
cp -p "${SUDO_HOME}"/.ssh/{known_hosts,*.pub} "${TARGET_DIR}/" \
|
||||
2>/dev/null || :
|
||||
copy_ssh_config "${TARGET_DIR}"
|
||||
chown -R ${SUDO_UID}:${SUDO_GID} "${TARGET_DIR}"
|
||||
|
||||
# Don't try to bind mount the ssh agent dir if it has gone stale.
|
||||
ASOCK=${SSH_AUTH_SOCK%/*}
|
||||
if [ -d "${ASOCK}" ]; then
|
||||
queue_mount "${ASOCK}" "--bind" "${ASOCK}"
|
||||
setup_mount "${ASOCK}" "--bind" "${ASOCK}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d "$HOME/.subversion" ]; then
|
||||
TARGET="/home/${USER}/.subversion"
|
||||
mkdir -p "${FLAGS_chroot}${TARGET}"
|
||||
queue_mount "${HOME}/.subversion" "--bind" "${TARGET}"
|
||||
if [ -d "$SUDO_HOME/.subversion" ]; then
|
||||
TARGET="/home/${SUDO_USER}/.subversion"
|
||||
user_mkdir "${FLAGS_chroot}${TARGET}"
|
||||
setup_mount "${SUDO_HOME}/.subversion" "--bind" "${TARGET}"
|
||||
# Symbolic-link the .subversion directory so sandboxed subversion.class
|
||||
# clients can use it.
|
||||
local cmds=()
|
||||
for d in \
|
||||
"${FLAGS_cache_dir}"/distfiles/{host,target}/svn-src/"${USER}"; do
|
||||
"${FLAGS_cache_dir}"/distfiles/{host,target}/svn-src/"${SUDO_USER}"; do
|
||||
if [[ ! -L "${d}/.subversion" ]]; then
|
||||
cmds+=(
|
||||
"mkdir -p '${d}'"
|
||||
"ln -sf /home/${USER}/.subversion '${d}/.subversion'"
|
||||
"chown -R ${USER}:250 '${d%/*}'"
|
||||
)
|
||||
rm -rf "${d}/.subversion"
|
||||
user_mkdir "${d}"
|
||||
user_symlink /home/${SUDO_USER}/.subversion "${d}/.subversion"
|
||||
fi
|
||||
done
|
||||
if [[ ${#cmds[@]} -gt 0 ]]; then
|
||||
sudo_multi "${cmds[@]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if DEPOT_TOOLS=$(type -P gclient) ; then
|
||||
DEPOT_TOOLS=${DEPOT_TOOLS%/*} # dirname
|
||||
# A reference to the DEPOT_TOOLS path may be passed in by cros_sdk.
|
||||
if [ -n "${DEPOT_TOOLS}" ]; then
|
||||
debug "Mounting depot_tools"
|
||||
queue_mount "$DEPOT_TOOLS" --bind "$INNER_DEPOT_TOOLS_ROOT"
|
||||
setup_mount "${DEPOT_TOOLS}" --bind "${INNER_DEPOT_TOOLS_ROOT}"
|
||||
fi
|
||||
|
||||
# Mount additional directories as specified in .local_mounts file.
|
||||
@ -438,14 +336,12 @@ setup_env() {
|
||||
# if only source is assigned, use source as mount point.
|
||||
: ${mount_point:=${mount_source}}
|
||||
debug " mounting ${mount_source} on ${mount_point}"
|
||||
queue_mount "${mount_source}" "--bind" "${mount_point}"
|
||||
setup_mount "${mount_source}" "--bind" "${mount_point}"
|
||||
# --bind can't initially be read-only so we have to do it via remount.
|
||||
queue_mount "" "-o remount,ro" "${mount_point}"
|
||||
setup_mount "" "-o remount,ro" "${mount_point}"
|
||||
done < <(sed -e 's:#.*::' "${local_mounts}")
|
||||
fi
|
||||
|
||||
process_mounts
|
||||
|
||||
CHROME_ROOT="$(readlink -f "$FLAGS_chrome_root" || :)"
|
||||
if [ -z "$CHROME_ROOT" ]; then
|
||||
CHROME_ROOT="$(cat "${FLAGS_chroot}${CHROME_ROOT_CONFIG}" \
|
||||
@ -455,68 +351,38 @@ setup_env() {
|
||||
if [[ -n "$CHROME_ROOT" ]]; then
|
||||
if [[ ! -d "${CHROME_ROOT}/src" ]]; then
|
||||
error "Not mounting chrome source"
|
||||
sudo rm -f "${FLAGS_chroot}${CHROME_ROOT_CONFIG}"
|
||||
rm -f "${FLAGS_chroot}${CHROME_ROOT_CONFIG}"
|
||||
if [[ ! "$CHROME_ROOT_AUTO" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
debug "Mounting chrome source at: $INNER_CHROME_ROOT"
|
||||
sudo bash -c "echo '$CHROME_ROOT' > \
|
||||
'${FLAGS_chroot}${CHROME_ROOT_CONFIG}'"
|
||||
queue_mount "$CHROME_ROOT" --bind "$INNER_CHROME_ROOT"
|
||||
echo $CHROME_ROOT > "${FLAGS_chroot}${CHROME_ROOT_CONFIG}"
|
||||
setup_mount "$CHROME_ROOT" --bind "$INNER_CHROME_ROOT"
|
||||
fi
|
||||
fi
|
||||
|
||||
process_mounts
|
||||
|
||||
# Install fuse module. Skip modprobe when possible for slight
|
||||
# speed increase when initializing the env.
|
||||
if [ -c "${FUSE_DEVICE}" ] && ! grep -q fuse /proc/filesystems; then
|
||||
sudo modprobe fuse 2> /dev/null ||\
|
||||
modprobe fuse 2> /dev/null ||\
|
||||
warn "-- Note: modprobe fuse failed. gmergefs will not work"
|
||||
fi
|
||||
|
||||
# Turn off automounting of external media when we enter the
|
||||
# chroot; thus we don't have to worry about being able to unmount
|
||||
# from inside.
|
||||
if SAVED_PREF=$(gconftool-2 -g ${AUTOMOUNT_PREF} 2>/dev/null); then
|
||||
if [ "${SAVED_PREF}" != "false" ]; then
|
||||
if [ $(gconftool-2 -s --type=boolean ${AUTOMOUNT_PREF} false) ]; then
|
||||
warn "-- Note: USB sticks may be automounted by your host OS."
|
||||
warn "-- Note: If you plan to burn bootable media, you may need to"
|
||||
warn "-- Note: unmount these devices manually, or run image_to_usb.sh"
|
||||
warn "-- Note: outside the chroot."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# Always write the temp file so we can read it when exiting
|
||||
echo "${SAVED_PREF:-false}" > "${FLAGS_chroot}${SAVED_AUTOMOUNT_PREF_FILE}"
|
||||
|
||||
# Fix permissions on ccache tree. If this is a fresh chroot, then they
|
||||
# might not be set up yet. Or if the user manually `rm -rf`-ed things,
|
||||
# we need to reset it. Otherwise, gcc itself takes care of fixing things
|
||||
# on demand, but only when it updates.
|
||||
ccache_dir="${FLAGS_chroot}/var/cache/distfiles/ccache"
|
||||
if [[ ! -d ${ccache_dir} ]]; then
|
||||
sudo mkdir -p -m 2775 "${ccache_dir}"
|
||||
mkdir -p -m 2775 "${ccache_dir}"
|
||||
fi
|
||||
sudo find -H "${ccache_dir}" -type d -exec chmod 2775 {} + &
|
||||
sudo find -H "${ccache_dir}" -gid 0 -exec chgrp 250 {} + &
|
||||
|
||||
# Configure committer username and email in chroot .gitconfig. Change
|
||||
# to the root directory first so that random $PWD/.git/config settings
|
||||
# do not get picked up. We want to stick to ~/.gitconfig only.
|
||||
ident=$(cd /; git var GIT_COMMITTER_IDENT || :)
|
||||
ident_name=${ident%% <*}
|
||||
ident_email=${ident%%>*}; ident_email=${ident_email##*<}
|
||||
git config -f ${FLAGS_chroot}/home/${USER}/.gitconfig --replace-all \
|
||||
user.name "${ident_name}" || true
|
||||
git config -f ${FLAGS_chroot}/home/${USER}/.gitconfig --replace-all \
|
||||
user.email "${ident_email}" || true
|
||||
find -H "${ccache_dir}" -type d -exec chmod 2775 {} + &
|
||||
find -H "${ccache_dir}" -gid 0 -exec chgrp 250 {} + &
|
||||
|
||||
# Certain files get copied into the chroot when entering.
|
||||
for fn in "${FILES_TO_COPY_TO_CHROOT[@]}"; do
|
||||
copy_into_chroot_if_exists "${HOME}/${fn}" "/home/${USER}/${fn}"
|
||||
copy_into_chroot_if_exists "${SUDO_HOME}/${fn}" "/home/${SUDO_USER}/${fn}"
|
||||
done
|
||||
promote_api_keys
|
||||
|
||||
@ -545,25 +411,23 @@ setup_env() {
|
||||
# with long multibyte strings. Newer setups have this fixed,
|
||||
# but locale-gen doesn't need to be run in any locale in the
|
||||
# first place, so just go with C to keep it fast.
|
||||
sudo -- chroot "$FLAGS_chroot" env LC_ALL=C locale-gen -q -u \
|
||||
chroot "$FLAGS_chroot" env LC_ALL=C locale-gen -q -u \
|
||||
-G "$(printf '%s\n' "${gen_locales[@]}")"
|
||||
fi
|
||||
|
||||
# Fix permissions on shared memory to allow non-root users access to POSIX
|
||||
# semaphores. Avoid the sudo call if possible (sudo is slow).
|
||||
if [ -n "$(find "${FLAGS_chroot}/dev/shm" ! -perm 777)" ] ; then
|
||||
sudo chmod -R 777 "${FLAGS_chroot}/dev/shm"
|
||||
fi
|
||||
# semaphores.
|
||||
chmod -R 777 "${FLAGS_chroot}/dev/shm"
|
||||
|
||||
# If the private overlays are installed, gsutil can use those credentials.
|
||||
# We're also installing credentials for use by sudoed invocations.
|
||||
boto='src/private-overlays/chromeos-overlay/googlestorage_account.boto'
|
||||
if [ -s "${FLAGS_trunk}/${boto}" ]; then
|
||||
if [ ! -e "${FLAGS_chroot}/home/${USER}/.boto" ]; then
|
||||
ln -s "trunk/${boto}" "${FLAGS_chroot}/home/${USER}/.boto"
|
||||
if [ ! -e "${FLAGS_chroot}/home/${SUDO_USER}/.boto" ]; then
|
||||
user_symlink "trunk/${boto}" "${FLAGS_chroot}/home/${SUDO_USER}/.boto"
|
||||
fi
|
||||
if [ ! -e "${FLAGS_chroot}/root/.boto" ]; then
|
||||
sudo ln -s "../home/${USER}/trunk/${boto}" "${FLAGS_chroot}/root/.boto"
|
||||
ln -s "../home/${SUDO_USER}/trunk/${boto}" "${FLAGS_chroot}/root/.boto"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -571,95 +435,13 @@ setup_env() {
|
||||
# as a result of old gsutil or tools. This causes permission errors when
|
||||
# gsutil cp tries to create its cache files, so ensure the user can
|
||||
# actually write to their directory.
|
||||
gsutil_dir="${FLAGS_chroot}/home/${USER}/.gsutil"
|
||||
if [ -d "${gsutil_dir}" ] && [ ! -w "${gsutil_dir}" ]; then
|
||||
sudo chown -R "${USER}:$(id -gn)" "${gsutil_dir}"
|
||||
gsutil_dir="${FLAGS_chroot}/home/${SUDO_USER}/.gsutil"
|
||||
if [ -d "${gsutil_dir}" ]; then
|
||||
chown -R ${SUDO_UID}:${SUDO_GID} "${gsutil_dir}"
|
||||
fi
|
||||
) 200>>"$LOCKFILE" || die "setup_env failed"
|
||||
}
|
||||
|
||||
teardown_env() {
|
||||
# Validate sudo timestamp before entering the critical section so that we
|
||||
# don't stall for a password while we have the lockfile.
|
||||
# Don't use sudo -v since that has issues on machines w/ no password.
|
||||
sudo echo "" > /dev/null
|
||||
|
||||
# Only teardown if we're the last enter_chroot to die
|
||||
(
|
||||
flock 200
|
||||
|
||||
# check each pid in $LOCKFILE to see if it's died unexpectedly
|
||||
TMP_LOCKFILE="$LOCKFILE.tmp"
|
||||
|
||||
echo -n > "$TMP_LOCKFILE" # Erase/reset temp file
|
||||
cat "$LOCKFILE" | while read PID; do
|
||||
if [ "$PID" = "$$" ]; then
|
||||
# ourself, leave PROC_NAME empty
|
||||
PROC_NAME=""
|
||||
else
|
||||
PROC_NAME=$(ps --pid $PID -o comm=)
|
||||
fi
|
||||
|
||||
if [ ! -z "$PROC_NAME" ]; then
|
||||
# All good, keep going
|
||||
echo "$PID" >> "$TMP_LOCKFILE"
|
||||
fi
|
||||
done
|
||||
# Remove any dups from lock file while installing new one
|
||||
sort -u -n "$TMP_LOCKFILE" > "$LOCKFILE"
|
||||
|
||||
SAVED_PREF=$(<"${FLAGS_chroot}${SAVED_AUTOMOUNT_PREF_FILE}")
|
||||
if [ "${SAVED_PREF}" != "false" ]; then
|
||||
gconftool-2 -s --type=boolean ${AUTOMOUNT_PREF} ${SAVED_PREF} || \
|
||||
warn "could not re-set your automount preference."
|
||||
fi
|
||||
|
||||
if [ -s "$LOCKFILE" ]; then
|
||||
debug "At least one other pid is running in the chroot, so not"
|
||||
debug "tearing down env."
|
||||
else
|
||||
debug "Stopping syncer process"
|
||||
# If another process entering the chroot is blocked on this
|
||||
# flock in setup_env(), it can be a race condition.
|
||||
#
|
||||
# When this locked region is exited, the setup_env() flock can
|
||||
# be entered before the script can exit and the /proc entry for
|
||||
# the PID is removed. The newly-created chroot will not end up
|
||||
# with a syncer process. To avoid that situation, remove the
|
||||
# syncer PID file.
|
||||
#
|
||||
# The syncer PID file should also be removed because the kernel
|
||||
# will reuse PIDs. It's possible that the PID in the syncer PID
|
||||
# has been reused by another process; make sure we don't skip
|
||||
# starting the syncer process when this occurs by deleting the
|
||||
# PID file.
|
||||
kill $(<"${SYNCERPIDFILE}") && \
|
||||
{ rm -f "${SYNCERPIDFILE}" 2>/dev/null || \
|
||||
sudo rm -f "${SYNCERPIDFILE}" ; } ||
|
||||
debug "Unable to clean up syncer process.";
|
||||
|
||||
debug "Unmounting chroot environment."
|
||||
safe_umount_tree "${MOUNTED_PATH}/"
|
||||
fi
|
||||
) 200>>"$LOCKFILE" || die "teardown_env failed"
|
||||
}
|
||||
|
||||
if [ $FLAGS_mount -eq $FLAGS_TRUE ]; then
|
||||
setup_env
|
||||
info "Make sure you run"
|
||||
info " $0 --unmount"
|
||||
info "before deleting $FLAGS_chroot"
|
||||
info "or you'll end up deleting $FLAGS_trunk too!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $FLAGS_unmount -eq $FLAGS_TRUE ]; then
|
||||
teardown_env
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Make sure we unmount before exiting
|
||||
trap teardown_env EXIT
|
||||
setup_env
|
||||
|
||||
CHROOT_PASSTHRU=(
|
||||
@ -668,15 +450,9 @@ CHROOT_PASSTHRU=(
|
||||
"EXTERNAL_TRUNK_PATH=${FLAGS_trunk}"
|
||||
)
|
||||
|
||||
# Add the standard proxied variables, and a few we specifically
|
||||
# export for script usage; USE/GCC_GITHASH are for ebuilds/portage,
|
||||
# CHROMEOS_VERSION_* is for cros_set_lsb_release and local AU server
|
||||
# (builders export this for marking reasons).
|
||||
KEEP_VARS=(
|
||||
CHROMEOS_VERSION_{TRACK,AUSERVER,DEVSERVER}
|
||||
USE GCC_GITHASH
|
||||
)
|
||||
for var in "${ENVIRONMENT_WHITELIST[@]}" "${KEEP_VARS[@]}"; do
|
||||
# Add the whitelisted environment variables to CHROOT_PASSTHRU.
|
||||
load_environment_whitelist
|
||||
for var in "${ENVIRONMENT_WHITELIST[@]}" ; do
|
||||
[ "${!var+set}" = "set" ] && CHROOT_PASSTHRU+=( "${var}=${!var}" )
|
||||
done
|
||||
|
||||
@ -692,11 +468,8 @@ elif [ ! -x "${FLAGS_chroot}/usr/bin/sudo" ]; then
|
||||
error "Requested enter_chroot command was: $@"
|
||||
exit 127
|
||||
else
|
||||
cmd=( sudo -i -u "$USER" )
|
||||
cmd=( sudo -i -u "${SUDO_USER}" )
|
||||
fi
|
||||
|
||||
sudo -- chroot "${FLAGS_chroot}" "${cmd[@]}" "${CHROOT_PASSTHRU[@]}" "$@"
|
||||
|
||||
# Remove trap and explicitly unmount
|
||||
trap - EXIT
|
||||
teardown_env
|
||||
cmd+=( "${CHROOT_PASSTHRU[@]}" "$@" )
|
||||
exec chroot "${FLAGS_chroot}" "${cmd[@]}"
|
||||
|
||||
@ -14,8 +14,6 @@ SCRIPT_ROOT=$(readlink -f $(dirname "$0")/..)
|
||||
|
||||
ENTER_CHROOT=$(readlink -f $(dirname "$0")/enter_chroot.sh)
|
||||
|
||||
enable_strict_sudo
|
||||
|
||||
if [ -n "${USE}" ]; then
|
||||
echo "$SCRIPT_NAME: Building with a non-empty USE: ${USE}"
|
||||
echo "This modifies the expected behaviour and can fail."
|
||||
@ -28,8 +26,9 @@ if [[ "$ARCHITECTURE" != "x86_64" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Script must be run outside the chroot.
|
||||
# Script must be run outside the chroot and as root.
|
||||
assert_outside_chroot
|
||||
assert_root_user
|
||||
|
||||
# Define command line flags.
|
||||
# See http://code.google.com/p/shflags/wiki/Documentation10x
|
||||
@ -54,8 +53,8 @@ eval set -- "${FLAGS_ARGV}"
|
||||
check_flags_only_and_allow_null_arg "$@" && set --
|
||||
|
||||
CROS_LOG_PREFIX=cros_sdk:make_chroot
|
||||
SUDO_HOME=$(eval echo ~${SUDO_USER})
|
||||
|
||||
assert_not_root_user
|
||||
# Set the right umask for chroot creation.
|
||||
umask 022
|
||||
|
||||
@ -86,13 +85,13 @@ fi
|
||||
# Support faster build if necessary.
|
||||
EMERGE_CMD="emerge"
|
||||
if [ "$FLAGS_fast" -eq "${FLAGS_TRUE}" ]; then
|
||||
CHROOT_CHROMITE_DIR="/home/${USER}/trunk/chromite"
|
||||
CHROOT_CHROMITE_DIR="/home/${SUDO_USER}/trunk/chromite"
|
||||
EMERGE_CMD="${CHROOT_CHROMITE_DIR}/bin/parallel_emerge"
|
||||
fi
|
||||
|
||||
ENTER_CHROOT_ARGS=(
|
||||
CROS_WORKON_SRCROOT="$CHROOT_TRUNK"
|
||||
PORTAGE_USERNAME="$USER"
|
||||
PORTAGE_USERNAME="${SUDO_USER}"
|
||||
IGNORE_PREFLIGHT_BINHOST="$IGNORE_PREFLIGHT_BINHOST"
|
||||
)
|
||||
|
||||
@ -114,8 +113,8 @@ early_enter_chroot() {
|
||||
# Run a command within the chroot. The main usage of this is to avoid
|
||||
# the overhead of enter_chroot, and do not need access to the source tree,
|
||||
# don't need the actual chroot profile env, and can run the command as root.
|
||||
sudo_chroot() {
|
||||
sudo chroot "${FLAGS_chroot}" "$@"
|
||||
bare_chroot() {
|
||||
chroot "${FLAGS_chroot}" "$@"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
@ -131,120 +130,115 @@ delete_existing() {
|
||||
info "Cleaning up old mount points..."
|
||||
cleanup
|
||||
info "Deleting $FLAGS_chroot..."
|
||||
sudo rm -rf "$FLAGS_chroot"
|
||||
rm -rf "$FLAGS_chroot"
|
||||
info "Done."
|
||||
}
|
||||
|
||||
init_users () {
|
||||
info "Set timezone..."
|
||||
# date +%Z has trouble with daylight time, so use host's info.
|
||||
sudo rm -f "${FLAGS_chroot}/etc/localtime"
|
||||
rm -f "${FLAGS_chroot}/etc/localtime"
|
||||
if [ -f /etc/localtime ] ; then
|
||||
sudo cp /etc/localtime "${FLAGS_chroot}/etc"
|
||||
cp /etc/localtime "${FLAGS_chroot}/etc"
|
||||
else
|
||||
sudo ln -sf /usr/share/zoneinfo/PST8PDT "${FLAGS_chroot}/etc/localtime"
|
||||
ln -sf /usr/share/zoneinfo/PST8PDT "${FLAGS_chroot}/etc/localtime"
|
||||
fi
|
||||
info "Adding user/group..."
|
||||
# Add ourselves as a user inside the chroot.
|
||||
sudo_chroot groupadd -g 5000 eng
|
||||
bare_chroot groupadd -g 5000 eng
|
||||
# We need the UID to match the host user's. This can conflict with
|
||||
# a particular chroot UID. At the same time, the added user has to
|
||||
# be a primary user for the given UID for sudo to work, which is
|
||||
# determined by the order in /etc/passwd. Let's put ourselves on top
|
||||
# of the file.
|
||||
sudo_chroot useradd -o -G ${DEFGROUPS} -g eng -u `id -u` -s \
|
||||
/bin/bash -m -c "${FULLNAME}" -p ${CRYPTED_PASSWD} ${USER}
|
||||
bare_chroot useradd -o -G ${DEFGROUPS} -g eng -u ${SUDO_UID} -s \
|
||||
/bin/bash -m -c "${FULLNAME}" -p ${CRYPTED_PASSWD} ${SUDO_USER}
|
||||
# Because passwd generally isn't sorted and the entry ended up at the
|
||||
# bottom, it is safe to just take it and move it to top instead.
|
||||
sudo sed -e '1{h;d};$!{H;d};$G' -i "${FLAGS_chroot}/etc/passwd"
|
||||
sed -e '1{h;d};$!{H;d};$G' -i "${FLAGS_chroot}/etc/passwd"
|
||||
}
|
||||
|
||||
init_setup () {
|
||||
info "Running init_setup()..."
|
||||
sudo mkdir -p -m 755 "${FLAGS_chroot}/usr" \
|
||||
mkdir -p -m 755 "${FLAGS_chroot}/usr" \
|
||||
"${FLAGS_chroot}/usr/local/portage" \
|
||||
"${FLAGS_chroot}"/"${CROSSDEV_OVERLAY}"
|
||||
sudo ln -sf "${CHROOT_TRUNK}/src/third_party/portage" \
|
||||
ln -sf "${CHROOT_TRUNK}/src/third_party/portage" \
|
||||
"${FLAGS_chroot}/usr/portage"
|
||||
sudo ln -sf "${CHROOT_TRUNK}/src/third_party/chromiumos-overlay" \
|
||||
ln -sf "${CHROOT_TRUNK}/src/third_party/chromiumos-overlay" \
|
||||
"${FLAGS_chroot}"/"${CHROOT_OVERLAY}"
|
||||
sudo ln -sf "${CHROOT_TRUNK}/src/third_party/portage-stable" \
|
||||
ln -sf "${CHROOT_TRUNK}/src/third_party/portage-stable" \
|
||||
"${FLAGS_chroot}"/"${PORTAGE_STABLE_OVERLAY}"
|
||||
|
||||
# Some operations need an mtab.
|
||||
sudo ln -s /proc/mounts "${FLAGS_chroot}/etc/mtab"
|
||||
ln -s /proc/mounts "${FLAGS_chroot}/etc/mtab"
|
||||
|
||||
# Set up sudoers. Inside the chroot, the user can sudo without a password.
|
||||
# (Safe enough, since the only way into the chroot is to 'sudo chroot', so
|
||||
# the user's already typed in one sudo password...)
|
||||
# Make sure the sudoers.d subdir exists as older stage3 base images lack it.
|
||||
sudo mkdir -p "${FLAGS_chroot}/etc/sudoers.d"
|
||||
mkdir -p "${FLAGS_chroot}/etc/sudoers.d"
|
||||
|
||||
# Use the standardized upgrade script to setup proxied vars.
|
||||
sudo bash -e "${SCRIPT_ROOT}/chroot_version_hooks.d/45_rewrite_sudoers.d" \
|
||||
"${FLAGS_chroot}" "${USER}" "${ENVIRONMENT_WHITELIST[@]}"
|
||||
load_environment_whitelist
|
||||
bash -e "${SCRIPT_ROOT}/chroot_version_hooks.d/45_rewrite_sudoers.d" \
|
||||
"${FLAGS_chroot}" "${SUDO_USER}" "${ENVIRONMENT_WHITELIST[@]}"
|
||||
|
||||
# Turn on the path overrides; subshelled to protect our env from whatever
|
||||
# vars the scriptlet may bleed.
|
||||
( CROS_CHROOT="${FLAGS_chroot}"
|
||||
. "${SCRIPT_ROOT}/chroot_version_hooks.d/47_path_overrides" )
|
||||
|
||||
sudo find "${FLAGS_chroot}/etc/"sudoers* -type f -exec chmod 0440 {} +
|
||||
find "${FLAGS_chroot}/etc/"sudoers* -type f -exec chmod 0440 {} +
|
||||
# Fix bad group for some.
|
||||
sudo chown -R root:root "${FLAGS_chroot}/etc/"sudoers*
|
||||
chown -R root:root "${FLAGS_chroot}/etc/"sudoers*
|
||||
|
||||
info "Setting up hosts/resolv..."
|
||||
# Copy config from outside chroot into chroot.
|
||||
sudo cp /etc/{hosts,resolv.conf} "$FLAGS_chroot/etc/"
|
||||
sudo chmod 0644 "$FLAGS_chroot"/etc/{hosts,resolv.conf}
|
||||
cp /etc/{hosts,resolv.conf} "$FLAGS_chroot/etc/"
|
||||
chmod 0644 "$FLAGS_chroot"/etc/{hosts,resolv.conf}
|
||||
|
||||
# Setup host make.conf. This includes any overlay that we may be using
|
||||
# and a pointer to pre-built packages.
|
||||
# TODO: This should really be part of a profile in the portage.
|
||||
info "Setting up /etc/make.*..."
|
||||
sudo mv "${FLAGS_chroot}"/etc/make.conf{,.orig}
|
||||
sudo ln -sf "${CHROOT_CONFIG}/make.conf.amd64-host" \
|
||||
mv "${FLAGS_chroot}"/etc/make.conf{,.orig}
|
||||
ln -sf "${CHROOT_CONFIG}/make.conf.amd64-host" \
|
||||
"${FLAGS_chroot}/etc/make.conf"
|
||||
sudo mv "${FLAGS_chroot}"/etc/make.profile{,.orig}
|
||||
sudo ln -sf "${CHROOT_OVERLAY}/profiles/default/linux/amd64/10.0" \
|
||||
mv "${FLAGS_chroot}"/etc/make.profile{,.orig}
|
||||
ln -sf "${CHROOT_OVERLAY}/profiles/default/linux/amd64/10.0" \
|
||||
"${FLAGS_chroot}/etc/make.profile"
|
||||
|
||||
# Create make.conf.user .
|
||||
sudo touch "${FLAGS_chroot}"/etc/make.conf.user
|
||||
sudo chmod 0644 "${FLAGS_chroot}"/etc/make.conf.user
|
||||
touch "${FLAGS_chroot}"/etc/make.conf.user
|
||||
chmod 0644 "${FLAGS_chroot}"/etc/make.conf.user
|
||||
|
||||
# Create directories referred to by our conf files.
|
||||
sudo mkdir -p -m 775 "${FLAGS_chroot}/var/lib/portage/pkgs" \
|
||||
mkdir -p -m 775 "${FLAGS_chroot}/var/lib/portage/pkgs" \
|
||||
"${FLAGS_chroot}/var/cache/"chromeos-{cache,chrome} \
|
||||
"${FLAGS_chroot}/etc/profile.d"
|
||||
|
||||
echo "export CHROMEOS_CACHEDIR=/var/cache/chromeos-cache" | \
|
||||
sudo_clobber "${FLAGS_chroot}/etc/profile.d/chromeos-cachedir.sh"
|
||||
sudo_multi \
|
||||
"chmod 0644 '${FLAGS_chroot}/etc/profile.d/chromeos-cachedir.sh'" \
|
||||
"rm -rf '${FLAGS_chroot}/var/cache/distfiles'" \
|
||||
"ln -s chromeos-cache/distfiles '${FLAGS_chroot}/var/cache/distfiles'"
|
||||
echo "export CHROMEOS_CACHEDIR=/var/cache/chromeos-cache" > \
|
||||
"${FLAGS_chroot}/etc/profile.d/chromeos-cachedir.sh"
|
||||
chmod 0644 "${FLAGS_chroot}/etc/profile.d/chromeos-cachedir.sh"
|
||||
rm -rf "${FLAGS_chroot}/var/cache/distfiles"
|
||||
ln -s chromeos-cache/distfiles "${FLAGS_chroot}/var/cache/distfiles"
|
||||
|
||||
# Run this from w/in the chroot so we use whatever uid/gid
|
||||
# these are defined as w/in the chroot.
|
||||
sudo_chroot chown "${USER}:portage" /var/cache/chromeos-chrome
|
||||
bare_chroot chown "${SUDO_USER}:portage" /var/cache/chromeos-chrome
|
||||
|
||||
# These are created for compatibility while transitioning
|
||||
# make.conf and friends over to the new location.
|
||||
# TODO(ferringb): remove this 01/13 or so.
|
||||
sudo ln -s ../../cache/chromeos-cache/distfiles/host \
|
||||
ln -s ../../cache/chromeos-cache/distfiles/host \
|
||||
"${FLAGS_chroot}/var/lib/portage/distfiles"
|
||||
sudo ln -s ../../cache/chromeos-cache/distfiles/target \
|
||||
ln -s ../../cache/chromeos-cache/distfiles/target \
|
||||
"${FLAGS_chroot}/var/lib/portage/distfiles-target"
|
||||
|
||||
# Add chromite/bin and depot_tools into the path globally; note that the
|
||||
# chromite wrapper itself might also be found in depot_tools.
|
||||
# We rely on 'env-update' getting called below.
|
||||
target="${FLAGS_chroot}/etc/env.d/99chromiumos"
|
||||
sudo_clobber "${target}" <<EOF
|
||||
PATH=/home/$USER/trunk/chromite/bin:/home/$USER/depot_tools
|
||||
cat <<EOF > "${target}"
|
||||
PATH=/home/${SUDO_USER}/trunk/chromite/bin:/home/${SUDO_USER}/depot_tools
|
||||
CROS_WORKON_SRCROOT="${CHROOT_TRUNK}"
|
||||
PORTAGE_USERNAME=$USER
|
||||
PORTAGE_USERNAME=${SUDO_USER}
|
||||
EOF
|
||||
|
||||
# TODO(zbehan): Configure stuff that is usually configured in postinst's,
|
||||
@ -260,8 +254,8 @@ EOF
|
||||
/usr/local/portage/chromiumos/profiles/default/linux/amd64/10.0
|
||||
|
||||
target="${FLAGS_chroot}/etc/profile.d"
|
||||
sudo mkdir -p "${target}"
|
||||
sudo_clobber "${target}/chromiumos-niceties.sh" << EOF
|
||||
mkdir -p "${target}"
|
||||
cat << EOF > "${target}/chromiumos-niceties.sh"
|
||||
# Niceties for interactive logins. (cr) denotes this is a chroot, the
|
||||
# __git_branch_ps1 prints current git branch in ./ . The $r behavior is to
|
||||
# make sure we don't reset the previous $? value which later formats in
|
||||
@ -278,40 +272,53 @@ EOF
|
||||
# http://crosbug.com/20378
|
||||
local localegen="$FLAGS_chroot/etc/locale.gen"
|
||||
if ! grep -q -v -e '^#' -e '^$' "${localegen}" ; then
|
||||
sudo_append "${localegen}" <<EOF
|
||||
cat <<EOF >> "${localegen}"
|
||||
en_US ISO-8859-1
|
||||
en_US.UTF-8 UTF-8
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Add chromite as a local site-package.
|
||||
mkdir -p "${FLAGS_chroot}/home/$USER/.local/lib/python2.6/site-packages"
|
||||
ln -s ../../../../trunk/chromite \
|
||||
"${FLAGS_chroot}/home/$USER/.local/lib/python2.6/site-packages/"
|
||||
local site_packages="/home/${SUDO_USER}/.local/lib/python2.6/site-packages"
|
||||
user_mkdir "${FLAGS_chroot}${site_packages}"
|
||||
user_symlink ../../../../trunk/chromite \
|
||||
"${FLAGS_chroot}${site_packages}/chromite"
|
||||
|
||||
chmod a+x "$FLAGS_chroot/home/$USER/.bashrc"
|
||||
# Automatically change to scripts directory.
|
||||
echo 'cd ${CHROOT_CWD:-~/trunk/src/scripts}' \
|
||||
>> "$FLAGS_chroot/home/$USER/.bash_profile"
|
||||
| user_append "$FLAGS_chroot/home/${SUDO_USER}/.bash_profile"
|
||||
|
||||
# Enable bash completion for build scripts.
|
||||
echo ". ~/trunk/src/scripts/bash_completion" \
|
||||
>> "$FLAGS_chroot/home/$USER/.bashrc"
|
||||
| user_append "$FLAGS_chroot/home/${SUDO_USER}/.bashrc"
|
||||
|
||||
if [[ "$USER" = "chrome-bot" ]]; then
|
||||
if [[ "${SUDO_USER}" = "chrome-bot" ]]; then
|
||||
# Copy ssh keys, so chroot'd chrome-bot can scp files from chrome-web.
|
||||
cp -r ~/.ssh "$FLAGS_chroot/home/$USER/"
|
||||
cp -rp ~/.ssh "$FLAGS_chroot/home/${SUDO_USER}/"
|
||||
fi
|
||||
|
||||
if [[ -f $HOME/.gitconfig ]]; then
|
||||
if [[ -f ${SUDO_HOME}/.gitconfig ]]; then
|
||||
# Copy .gitconfig into chroot so repo and git can be used from inside.
|
||||
# This is required for repo to work since it validates the email address.
|
||||
echo "Copying ~/.gitconfig into chroot"
|
||||
cp $HOME/.gitconfig "$FLAGS_chroot/home/$USER/"
|
||||
cp -p "${SUDO_HOME}/.gitconfig" "$FLAGS_chroot/home/${SUDO_USER}/"
|
||||
fi
|
||||
|
||||
if [[ -f $HOME/.cros_chroot_init ]]; then
|
||||
/bin/bash $HOME/.cros_chroot_init "${FLAGS_chroot}"
|
||||
# If the user didn't set up their username in their gitconfig, look
|
||||
# at the default git settings for the user.
|
||||
if ! git config -f "${SUDO_HOME}/.gitconfig" user.email >& /dev/null; then
|
||||
ident=$(cd /; sudo -u ${SUDO_USER} -- git var GIT_COMMITTER_IDENT || :)
|
||||
ident_name=${ident%% <*}
|
||||
ident_email=${ident%%>*}; ident_email=${ident_email##*<}
|
||||
gitconfig=${FLAGS_chroot}/home/${SUDO_USER}/.gitconfig
|
||||
git config -f ${gitconfig} --replace-all user.name "${ident_name}" || :
|
||||
git config -f ${gitconfig} --replace-all user.email "${ident_email}" || :
|
||||
chown ${SUDO_UID}:${SUDO_GID} ${FLAGS_chroot}/home/${SUDO_USER}/.gitconfig
|
||||
fi
|
||||
|
||||
if [[ -f ${SUDO_HOME}/.cros_chroot_init ]]; then
|
||||
sudo -u ${SUDO_USER} -- /bin/bash "${SUDO_HOME}/.cros_chroot_init" \
|
||||
"${FLAGS_chroot}"
|
||||
fi
|
||||
}
|
||||
|
||||
@ -343,7 +350,7 @@ done
|
||||
# Create the base Gentoo stage3 based on last version put in chroot.
|
||||
STAGE3="${OVERLAY}/chromeos/stage3/stage3-amd64-${FLAGS_stage3_date}.tar.bz2"
|
||||
if [ -f $CHROOT_STATE ] && \
|
||||
! sudo egrep -q "^STAGE3=$STAGE3" $CHROOT_STATE >/dev/null 2>&1
|
||||
! egrep -q "^STAGE3=$STAGE3" $CHROOT_STATE >/dev/null 2>&1
|
||||
then
|
||||
info "STAGE3 version has changed."
|
||||
delete_existing
|
||||
@ -372,8 +379,8 @@ else
|
||||
*) die "Unknown tarball compression: ${STAGE3}";;
|
||||
esac
|
||||
${DECOMPRESS} -dc "${STAGE3}" | \
|
||||
sudo tar -xp -C "${FLAGS_chroot}"
|
||||
sudo rm -f "$FLAGS_chroot/etc/"make.{globals,conf.user}
|
||||
tar -xp -C "${FLAGS_chroot}"
|
||||
rm -f "$FLAGS_chroot/etc/"make.{globals,conf.user}
|
||||
fi
|
||||
|
||||
# Set up users, if needed, before mkdir/mounts below.
|
||||
@ -382,7 +389,7 @@ fi
|
||||
echo
|
||||
info "Setting up mounts..."
|
||||
# Set up necessary mounts and make sure we clean them up on exit.
|
||||
sudo mkdir -p "${FLAGS_chroot}/${CHROOT_TRUNK}" "${FLAGS_chroot}/run"
|
||||
mkdir -p "${FLAGS_chroot}/${CHROOT_TRUNK}" "${FLAGS_chroot}/run"
|
||||
|
||||
# Create a special /etc/make.conf.host_setup that we use to bootstrap
|
||||
# the chroot. The regular content for the file will be generated the
|
||||
@ -411,7 +418,7 @@ fi
|
||||
|
||||
# Add file to indicate that it is a chroot.
|
||||
# Add version of $STAGE3 for update checks.
|
||||
sudo sh -c "echo STAGE3=$STAGE3 > $CHROOT_STATE"
|
||||
echo STAGE3=$STAGE3 > $CHROOT_STATE
|
||||
|
||||
info "Updating portage"
|
||||
early_enter_chroot emerge -uNv --quiet portage
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user