You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
9.6 KiB
338 lines
9.6 KiB
#!/bin/sh
|
|
|
|
## live-build(7) - System Build Scripts
|
|
## Copyright (C) 2006-2012 Daniel Baumann <daniel@debian.org>
|
|
##
|
|
## This program comes with ABSOLUTELY NO WARRANTY; for details see COPYING.
|
|
## This is free software, and you are welcome to redistribute it
|
|
## under certain conditions; see COPYING for details.
|
|
|
|
## This is a fork of lb_chroot for layered live system.
|
|
## We don't want leaking host configuration in each layer, and so,
|
|
## we clean and setup the chroot each time.
|
|
## In addition, we create the squashfs for each layer, but top one (live)
|
|
## which still can be configured after lb chroot call.
|
|
|
|
set -e
|
|
|
|
# Including common functions
|
|
( . "${LIVE_BUILD}/scripts/build.sh" > /dev/null 2>&1 || true ) || . /usr/lib/live/build.sh
|
|
|
|
# Automatically populating config tree
|
|
if [ -x auto/config ] && [ ! -e .build/config ]
|
|
then
|
|
Echo_message "Automatically populating config tree."
|
|
lb config
|
|
fi
|
|
|
|
# Setting static variables
|
|
DESCRIPTION="$(Echo 'customize the Debian system')"
|
|
HELP=""
|
|
USAGE="${PROGRAM} [--force]"
|
|
|
|
Arguments "${@}"
|
|
|
|
# Reading configuration files
|
|
Read_conffiles config/all config/common config/bootstrap config/chroot config/binary config/source
|
|
Set_defaults
|
|
|
|
# Setup cleanup function
|
|
Setup_cleanup
|
|
|
|
. config/functions
|
|
|
|
lb_chroot_remove_packages () {
|
|
# Remove packages from the chroot specific to this layer
|
|
#
|
|
# $1: Name of the pass*
|
|
local pass=$1
|
|
|
|
Expand_packagelist "$(basename config/package-lists/*.removal-list.chroot_${pass})" "config/package-lists" \
|
|
>> chroot/root/packages.chroot.removal
|
|
Chroot chroot "xargs --arg-file=/root/packages.chroot.removal apt-get ${APT_OPTIONS} autoremove --purge"
|
|
rm -f chroot/root/packages.chroot.removal
|
|
}
|
|
|
|
# Create the snap list specific to this layer
|
|
lb_chroot_snap_lists () {
|
|
local pass=$1
|
|
|
|
# This assumes that the prefix is unique for a given project
|
|
local snap_for_pass=$(ls config/package-lists/*.snaplist.chroot_${pass}.full 2>/dev/null || true)
|
|
parent_pass=$(get_parent_pass $pass)
|
|
local snap_for_parent_pass=$(ls config/package-lists/*.snaplist.chroot_${parent_pass}.full 2>/dev/null || true)
|
|
|
|
if [ -z "${snap_for_pass}" ]; then
|
|
return
|
|
fi
|
|
|
|
if [ -z "${snap_for_parent_pass}" ]; then
|
|
cp ${snap_for_pass} ${snap_for_pass%.full}
|
|
return
|
|
fi
|
|
|
|
# Generate a list of snaps added to a layer.
|
|
diff -NU0 ${snap_for_parent_pass} ${snap_for_pass}|grep -Ev '^(---|\+\+\+|@@)'|cut -c2- > ${snap_for_pass%.full}
|
|
}
|
|
|
|
lb_chroot_install_snaps () {
|
|
# Prepare the snap environment and install snaps into a chroot
|
|
#
|
|
# $1: Name of the pass
|
|
|
|
local snaplist_file=$(ls config/package-lists/*.snaplist.chroot_${1} 2>/dev/null || true)
|
|
|
|
if [ -z "${snaplist_file}" ]; then
|
|
return
|
|
fi
|
|
|
|
snap_prepare chroot
|
|
|
|
while read snap; do
|
|
SNAP_NO_VALIDATE_SEED=1 snap_preseed chroot "${snap}"
|
|
done < $snaplist_file
|
|
snap_validate_seed chroot
|
|
}
|
|
|
|
lb_chroot_includes () {
|
|
# Copying includes from pass subdirectory
|
|
local pass="$1"
|
|
|
|
if [ ! -d config/includes.chroot.${pass} ]; then
|
|
return
|
|
fi
|
|
|
|
cd config/includes.chroot.${pass}
|
|
find . | cpio -dmpu --no-preserve-owner "${OLDPWD}"/chroot
|
|
cd "${OLDPWD}"
|
|
}
|
|
|
|
reduce_pass_size () {
|
|
# Remove duplicated files between parent and current pass
|
|
# Note the empty directories created in a child pass are not removed
|
|
local pass=$1
|
|
local parent="$(get_parent_pass $pass)"
|
|
|
|
$(is_root_layer $pass) && return
|
|
|
|
pass_dir="overlay.${pass}"
|
|
parent_pass_dir="overlay.${parent}"
|
|
|
|
local list_pass=$(mktemp)
|
|
local list_parent=$(mktemp)
|
|
|
|
(cd $pass_dir && find . ! -type d -printf "%h/%f|%s|%y|%U|%G|%m\n"|sort > $list_pass)
|
|
(cd $parent_pass_dir && find . ! -type d -printf "%h/%f|%s|%y|%U|%G|%m\n"|sort > $list_parent)
|
|
|
|
# Only iterate on common files with same type, owner, permission and size
|
|
comm -12 $list_pass $list_parent|cut -d'|' -f1|while read f; do
|
|
# If file contents are different, keep it
|
|
if ! diff --brief --no-dereference "$pass_dir/$f" "$parent_pass_dir/$f" >/dev/null; then
|
|
continue
|
|
fi
|
|
p=$(dirname $f)
|
|
while [ "$p" != . ]; do
|
|
# As explained in the overlayfs documentation
|
|
# https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#whiteouts-and-opaque-directories
|
|
# an xattr of trusted.overlay.opaque indicates an 'opaque' directory
|
|
# that was deleted from the overlay. Removing files from within the
|
|
# directory, even if identical with one in the lower layer, will result
|
|
# in it going missing from the combined filesystem.
|
|
#
|
|
# It would be possible to be more clever, e.g. if the two directories
|
|
# are still similar, we could the delete the attribute and convert any
|
|
# still-needed deletions to whiteouts but it doesn't seem worth it in
|
|
# the cases seen so far.
|
|
if [ -n "$(getfattr -n trusted.overlay.opaque -h --only-values -- "$pass_dir/$p" 2>/dev/null)" ]; then
|
|
Echo_message "reduce_pass_size: '%s' would be removed from overlay but for trusted.overlay.opaque on '%s'" "$f" "$p"
|
|
continue 2
|
|
fi
|
|
p=$(dirname $p)
|
|
done
|
|
# Files are strictly identical between the 2 passes (only mod or access times differs). No need for unused delta.
|
|
Echo_message "reduce_pass_size: '%s' is strictly identical between %s and %s. Removing." "$f" "$pass" "$parent"
|
|
rm "$pass_dir/$f"
|
|
done
|
|
|
|
rm $list_pass
|
|
rm $list_parent
|
|
}
|
|
|
|
create_chroot_pass () {
|
|
local pass=$1
|
|
shift 1 # restore ${*}
|
|
|
|
Echo_message "lb_chroot_layered: treating pass %s" "$pass"
|
|
|
|
# We have already treated that pass just return.
|
|
local overlay_dir="overlay.${pass}"
|
|
if [ -d "$overlay_dir/" ]; then
|
|
return
|
|
fi
|
|
|
|
# Only get some function executed on root passes
|
|
# Copy bootstrap on root layers
|
|
if $(is_root_layer $pass); then
|
|
rm -f .build/chroot_linux-image .build/chroot_preseed
|
|
cp -a chroot.bootstrap/ "$overlay_dir/"
|
|
fi
|
|
# Others have to be executed on every pass
|
|
rm -f .build/chroot_early_hooks .build/chroot_hooks .build/chroot_interactive
|
|
|
|
mkdir -p "$overlay_dir/"
|
|
lowerdirs=$(get_lowerdirs_for_pass $pass)
|
|
if [ -n "$lowerdirs" ]; then
|
|
mkdir -p chroot/
|
|
mount_overlay "$lowerdirs" "$overlay_dir" chroot/
|
|
else
|
|
ln -s "$overlay_dir/" chroot
|
|
fi
|
|
|
|
export PASS=${pass}
|
|
setenv_file PASS "${pass}" config/environment.chroot
|
|
|
|
# Configuring chroot
|
|
lb chroot_devpts install ${*}
|
|
lb chroot_proc install ${*}
|
|
lb chroot_sysfs install ${*}
|
|
|
|
# grub-probe should not be called as part of an image build so divert it
|
|
divert_grub chroot
|
|
|
|
# We run chroot_hacks only on root layers (update-initramfs diverted)
|
|
if $(is_root_layer $pass); then
|
|
divert_update_initramfs
|
|
fi
|
|
lb chroot_debianchroot install ${*}
|
|
lb chroot_dpkg install ${*}
|
|
lb chroot_tmpfs install ${*}
|
|
lb chroot_hosts install ${*}
|
|
lb chroot_resolv install ${*}
|
|
lb chroot_hostname install ${*}
|
|
lb chroot_apt install ${*}
|
|
# Note: this triggers an upgrade + dist-ugprade; which may impact sublayers with more
|
|
# diff content than desired. So only running this on root pass.
|
|
# Only configure universe on root passes
|
|
if $(is_root_layer $pass); then
|
|
lb chroot_archives chroot install ${*}
|
|
fi
|
|
|
|
# Customizing chroot
|
|
lb chroot_linux-image ${*}
|
|
lb chroot_preseed ${*}
|
|
lb chroot_early_hooks ${*}
|
|
|
|
lb chroot_package-lists ${pass} ${*}
|
|
lb chroot_install-packages ${pass} ${*}
|
|
lb_chroot_remove_packages ${pass} ${*}
|
|
|
|
lb chroot_sysfs remove ${*}
|
|
lb chroot_proc remove ${*}
|
|
lb chroot_devpts remove ${*}
|
|
|
|
setup_mountpoint chroot
|
|
|
|
# Snap management
|
|
lb_chroot_snap_lists ${pass} ${*}
|
|
lb_chroot_install_snaps ${pass} ${*}
|
|
|
|
teardown_mountpoint chroot
|
|
|
|
lb chroot_devpts install ${*}
|
|
lb chroot_proc install ${*}
|
|
lb chroot_sysfs install ${*}
|
|
|
|
configure_network_manager
|
|
|
|
# Mark kernel headers as autoremovable
|
|
Chroot chroot "dpkg -l linux-headers-3* linux-headers-4*" 2>/dev/null \
|
|
| awk '/^i/ {print $2}' > chroot.headers
|
|
for i in $(cat chroot.headers); do
|
|
Chroot chroot "apt-mark auto $i"
|
|
done
|
|
|
|
Chroot chroot "apt-get --purge -y autoremove"
|
|
|
|
# Add live packages to live layers
|
|
for livepass in $LIVE_PASSES; do
|
|
[ "$livepass" != "$pass" ] && continue
|
|
lb chroot_live-packages ${*}
|
|
break
|
|
done
|
|
|
|
# Run includes by pass
|
|
lb_chroot_includes ${pass} ${*}
|
|
|
|
lb chroot_hooks ${*}
|
|
|
|
# Run chroot_hacks only on live layers. chroot_hacks is what repacks
|
|
# the initrd in a full casperized mode. We don't want to do that for
|
|
# each and every layer, just for the live layers (which
|
|
# lb_binary_layered will call lb binary_linux-image on).
|
|
if $(is_live_layer $pass); then
|
|
rm -f .build/chroot_hacks
|
|
lb chroot_hacks ${*}
|
|
else
|
|
# chroot_hacks also removes some cruft, which is appropriate for
|
|
# any layer so we copy and paste that bit here.
|
|
rm -f chroot/boot/initrd*bak*
|
|
rm -f chroot/etc/apt/trusted.gpg~
|
|
rm -f chroot/etc/group- chroot/etc/passwd-
|
|
rm -f chroot/etc/gshadow- chroot/etc/shadow-
|
|
rm -f chroot/var/cache/debconf/*-old
|
|
rm -f chroot/var/lib/dpkg/*-old
|
|
rm -f chroot/var/log/apt/term.log
|
|
rm -f chroot/etc/adjtime
|
|
fi
|
|
|
|
lb chroot_interactive ${*}
|
|
|
|
# Misc ubuntu cleanup and post-layer configuration
|
|
/usr/share/livecd-rootfs/minimize-manual chroot
|
|
clean_debian_chroot
|
|
|
|
Chroot chroot "dpkg-query -W" > chroot.packages.${pass}
|
|
|
|
# Deconfiguring chroot
|
|
if $(is_root_layer $pass); then
|
|
lb chroot_archives chroot remove ${*}
|
|
configure_universe
|
|
fi
|
|
lb chroot_apt remove ${*}
|
|
lb chroot_hostname remove ${*}
|
|
lb chroot_resolv remove ${*}
|
|
lb chroot_hosts remove ${*}
|
|
lb chroot_tmpfs remove ${*}
|
|
lb chroot_dpkg remove ${*}
|
|
lb chroot_debianchroot remove ${*}
|
|
|
|
# Restore update-initramfs, if necessary
|
|
if $(is_root_layer $pass); then
|
|
undivert_update_initramfs
|
|
fi
|
|
|
|
# Restore grub
|
|
undivert_grub chroot
|
|
|
|
lb chroot_sysfs remove ${*}
|
|
lb chroot_proc remove ${*}
|
|
lb chroot_devpts remove ${*}
|
|
|
|
if [ -n "$lowerdirs" ]; then
|
|
umount chroot
|
|
rmdir chroot
|
|
else
|
|
rm chroot
|
|
fi
|
|
|
|
reduce_pass_size $pass
|
|
}
|
|
|
|
if [ ! -d chroot.bootstrap/ ]; then
|
|
mv chroot/ chroot.bootstrap/
|
|
fi
|
|
for _PASS in $PASSES
|
|
do
|
|
create_chroot_pass "$_PASS" ${*}
|
|
done
|