Always use our dpkg wrapper when mastering an image.

This changes install_packages to always have apt use our dpkg
wrapper when building an image. The dpkg_no_scripts.sh has been
modified to check if a package's maintainer scripts have been
whitelisted. If so, it will install without maintainer scripts.
If any relevant maintainer script has not been whitelisted it
will fall back to standard dpkg which will process the
maintainer scripts.

This will allow us to transition to installing packages without
maintainer scripts in batches rather than all at once. Once
everything is switched over we will have dpkg_no_scripts.sh
throw an error if it encounters a package with maintainer
scripts that have not been whitelisted.

Move postinst stuff from install_packages.sh to actual postinst
scripts.

Review URL: http://codereview.chromium.org/549017
This commit is contained in:
tedbo 2010-01-11 17:34:44 -08:00
parent 55d1c59a58
commit 3d9b18913c
2 changed files with 142 additions and 85 deletions

View File

@ -22,6 +22,8 @@
# Flags
DEFINE_string root "" \
"The target rootfs directory in which to install packages."
DEFINE_boolean dpkg_fallback $FLAGS_TRUE \
"Run normal dpkg if maintainer scripts are not whitelisted."
DEFINE_string status_fd "" \
"The file descriptor to report status on; ignored."
DEFINE_boolean unpack $FLAGS_FALSE "Is the action 'unpack'?"
@ -43,52 +45,144 @@ eval set -- "${FLAGS_ARGV}"
# Die on any errors.
set -e
if [ $FLAGS_configure -eq $FLAGS_TRUE ]; then
# We ignore configure requests.
exit 0
fi
if [ $FLAGS_remove -eq $FLAGS_TRUE ]; then
# We log but ignore remove requests.
echo "dpkg_no_scripts, remove: $@"
exit 0
fi
if [ $FLAGS_unpack -ne $FLAGS_TRUE ]; then
# Ignore unknown command line.
echo "Unexpected command line: $@"
exit 0
fi
if [ -z "$FLAGS_root" ]; then
echo "Missing root directory."
exit 0
fi
# Returns true if the input file is whitelisted.
#
# $1 - The file to check
is_whitelisted() {
local whitelist="${SRC_ROOT}/package_scripts/package.whitelist"
test -f "$whitelist" || return
DPKG_STATUS=""
if [ -d "$FLAGS_root/var/lib/dpkg" ]; then
DPKG_STATUS="$FLAGS_root/var/lib/dpkg/status"
DPKG_INFO="$FLAGS_root/var/lib/dpkg/info/"
fi
local checksum=$(md5sum "$1" | awk '{ print $1 }')
local count=$(grep -c "$checksum" "${whitelist}" || /bin/true)
test $count -ne 0
}
for p in "$@"; do
echo "Extracting $p"
dpkg-deb --extract "$p" "$FLAGS_root"
# Returns true if either of the two given files exist and are not whitelisted.
#
# $1 - The package name.
# $2 - The path to the preinst file if it were to exist.
# $3 - The path to the postinst file if it were to exist.
has_missing_whitelist() {
local package=$1
local preinst=$2
local postinst=$3
local missing_whitelist=0
if [ -n "$DPKG_STATUS" ]; then
TMPDIR=$(mktemp -d)
dpkg-deb --control "$p" "$TMPDIR"
if [ -f "$preinst" ]; then
if ! is_whitelisted "$preinst"; then
missing_whitelist=1
echo "Warning: Missing whitelist entry for ${package}.preinst"
fi
fi
if [ -f "$postinst" ]; then
if ! is_whitelisted "$postinst"; then
missing_whitelist=1
echo "Warning: Missing whitelist entry for ${package}.postinst"
fi
fi
test $missing_whitelist -ne 0
}
do_configure() {
local dpkg_info="$FLAGS_root/var/lib/dpkg/info/"
local fallback_packages=""
for p in "$@"; do
echo "Configuring: $p"
# Make sure that any .preinst or .postinst files are whitelisted.
local preinst="${dpkg_info}/${p}.preinst"
local postinst="${dpkg_info}/${p}.postinst"
if has_missing_whitelist "$p" "$preinst" "$postinst"; then
if [ $FLAGS_dpkg_fallback -eq $FLAGS_TRUE ]; then
echo "** Warning: Will run full maintainer scripts for ${p}."
fallback_packages="$fallback_packages $p"
continue
else
# TODO: Eventually should be upgraded to a full error.
echo "** Warning: Ignoring missing whitelist for ${p}."
fi
fi
# Run our maintainer script for this package if we have one.
local chromium_postinst="${SRC_ROOT}/package_scripts/${p}.postinst"
if [ -f "$chromium_postinst" ]; then
echo "Running: $chromium_postinst"
ROOT="$FLAGS_root" SRC_ROOT="$SRC_ROOT" sh -x $chromium_postinst
fi
done
if [ -n "$fallback_packages" ]; then
dpkg --root="$FLAGS_root" --configure $fallback_packages
fi
}
do_unpack() {
local dpkg_status="$FLAGS_root/var/lib/dpkg/status"
local dpkg_info="$FLAGS_root/var/lib/dpkg/info/"
for p in "$@"; do
local package=$(dpkg-deb --field "$p" Package)
local tmpdir=$(mktemp -d)
dpkg-deb --control "$p" "$tmpdir"
local preinst="${tmpdir}/preinst"
local postinst="${tmpdir}/postinst"
if has_missing_whitelist "$package" "$preinst" "$postinst"; then
if [ $FLAGS_dpkg_fallback -eq $FLAGS_TRUE ]; then
echo "** Warning: Running full maintainer scripts for ${package}."
dpkg --root="$FLAGS_root" --unpack --auto-deconfigure "$p"
rm -rf "$tmpdir"
continue
else
# TODO: Eventually should be upgraded to a full error.
echo "** Warning: Ignoring missing whitelist for ${p}."
fi
fi
# Copy the info files
PACKAGE=$(dpkg-deb --field "$p" Package)
FILES=$(ls "$TMPDIR" | grep -v control)
for f in $FILES; do
cp "${TMPDIR}/$f" "${DPKG_INFO}/$PACKAGE.$f"
local files=$(ls "$tmpdir" | grep -v control)
for f in $files; do
cp "${tmpdir}/${f}" "${dpkg_info}/${package}.${f}"
done
touch "${DPKG_INFO}/$PACKAGE.list"
touch "${dpkg_info}/${package}.list" # TODO: Proper .list files.
# Mark the package as installed successfully.
echo "Status: install ok installed" >> "$DPKG_STATUS"
cat "${TMPDIR}/control" >> "$DPKG_STATUS"
echo "" >> "$DPKG_STATUS"
echo "Status: install ok installed" >> "$dpkg_status"
cat "${tmpdir}/control" >> "$dpkg_status"
echo "" >> "$dpkg_status"
rm -rf "$TMPDIR"
fi
done
rm -rf "$tmpdir"
# Run our maintainer script for this package if we have one.
local chromium_postinst="${SRC_ROOT}/package_scripts/${package}.preinst"
if [ -f "$chromium_preinst" ]; then
echo "Running: ${chromium_preinst}"
ROOT="$FLAGS_root" SRC_ROOT="$SRC_ROOT" $chromium_preinst
fi
echo "Unpacking: $p"
dpkg-deb --extract "$p" "$FLAGS_root"
done
}
# This script requires at least "--root="
if [ -z "$FLAGS_root" ]; then
echo "dpkg_no_scripts: Missing root directory."
exit 1
fi
if [ $FLAGS_configure -eq $FLAGS_TRUE ]; then
do_configure $@
elif [ $FLAGS_unpack -eq $FLAGS_TRUE ]; then
do_unpack $@
elif [ $FLAGS_remove -eq $FLAGS_TRUE ]; then
# We log but ignore remove requests.
echo "Ignoring remove: $@"
else
echo "dpkg_no_scripts.sh: Unknown or missing command."
exit 1
fi
exit 0

View File

@ -101,10 +101,6 @@ APT_CACHE_DIR="${FLAGS_build_root}/apt_cache-${FLAGS_target}/"
mkdir -p "${APT_CACHE_DIR}/archives/partial"
# Create the apt configuration file. See "man apt.conf"
NO_MAINTAINER_SCRIPTS=""
if [ -n "$EXPERIMENTAL_NO_MAINTAINER_SCRIPTS" ]; then
NO_MAINTAINER_SCRIPTS="Bin { dpkg \"${SCRIPTS_DIR}/dpkg_no_scripts.sh\"; };"
fi
APT_PARTS="${OUTPUT_DIR}/apt.conf.d"
mkdir -p "$APT_PARTS" # An empty apt.conf.d to avoid other configs.
export APT_CONFIG="${OUTPUT_DIR}/apt.conf"
@ -121,7 +117,9 @@ APT
};
Dir
{
$NO_MAINTAINER_SCRIPTS
Bin {
dpkg "${SCRIPTS_DIR}/dpkg_no_scripts.sh";
};
Cache "$APT_CACHE_DIR";
Cache {
archives "${APT_CACHE_DIR}/archives";
@ -185,59 +183,24 @@ for p in $PACKAGES $EXTRA_PACKAGES; do
PKG=$(ls "${REPO}"/${p}_*_all.deb)
fi
sudo "${SCRIPTS_DIR}"/dpkg_no_scripts.sh \
--root="$ROOT_FS_DIR" --unpack "$PKG"
--root="$ROOT_FS_DIR" --nodpkg_fallback --unpack "$PKG"
sudo "${SCRIPTS_DIR}"/dpkg_no_scripts.sh \
--root="$ROOT_FS_DIR" --nodpkg_fallback --configure "$p"
done
# Make sure that apt is ready to work. We use --fix-broken to trigger apt
# to install additional critical packages. If there are any of these, we
# disable the maintainer scripts so they install ok.
TMP_FORCE_NO_SCRIPTS="-o=Dir::Bin::dpkg=${SCRIPTS_DIR}/dpkg_no_scripts.sh"
TMP_FORCE_NO_SCRIPTS="-o=DPkg::options::=--nodpkg_fallback"
sudo APT_CONFIG="$APT_CONFIG" DEBIAN_FRONTEND=noninteractive \
apt-get $TMP_FORCE_NO_SCRIPTS --force-yes --fix-broken install
# ----- MAINTAINER SCRIPT FIXUPS -----
# TODO: Remove when we stop having maintainer scripts altogether.
# TODO: Remove these hacks when we stop having maintainer scripts altogether.
sudo cp -a /dev/* "${ROOT_FS_DIR}/dev"
sudo cp -a /etc/resolv.conf "${ROOT_FS_DIR}/etc/resolv.conf"
sudo ln -sf /bin/true "${ROOT_FS_DIR}/usr/sbin/invoke-rc.d"
sudo ln -sf /bin/true "${ROOT_FS_DIR}/usr/sbin/update-rc.d"
# base-files
# TODO: Careful audit of the postinst; this isn't all that is there.
sudo cp -a "${ROOT_FS_DIR}/usr/share/base-files/networks" \
"${ROOT_FS_DIR}/usr/share/base-files/nsswitch.conf" \
"${ROOT_FS_DIR}/usr/share/base-files/profile" \
"${ROOT_FS_DIR}/etc/"
# base-passwd
sudo cp "${ROOT_FS_DIR}/usr/share/base-passwd/passwd.master" \
"${ROOT_FS_DIR}/etc/passwd"
sudo cp "${ROOT_FS_DIR}/usr/share/base-passwd/group.master" \
"${ROOT_FS_DIR}/etc/group"
# libpam-runtime
# The postinst script calls pam-auth-update, which is a perl script that
# expects to run within the targetfs. Until we fix this, we just copy
# from the build chroot.
sudo cp -a /etc/pam.d/common-* \
/etc/pam.d/login \
/etc/pam.d/newusers \
/etc/pam.d/su \
/etc/pam.d/sudo \
"${ROOT_FS_DIR}/etc/pam.d/"
# mawk
sudo ln -s mawk "${ROOT_FS_DIR}/usr/bin/awk"
# base-files?
sudo touch "${ROOT_FS_DIR}/etc/fstab"
# sysv-rc needs this
sudo mkdir -p "${ROOT_FS_DIR}/etc/init.d"
# ----- END MAINTAINER SCRIPT FIXUPS -----
# Set up mounts for working within the rootfs. We copy some basic
# network information from the host so that maintainer scripts can
# access the network as needed.