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:
David James 2012-10-24 19:46:29 -07:00 committed by Gerrit
parent 12a9a84de9
commit 76764885b9
5 changed files with 231 additions and 445 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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[@]}"

View File

@ -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