livecd-rootfs/live-build/lb_binary_layered
Dan Bungert eec13dad68 lb_binary_layered: fix mtimes in layered squashfses
layer construction involves rsync, and that process ignores times to
avoid some of the layers being larger than they would otherwise where
the only difference is times.  This saves a small amount of space,
around 14MiB, but results in files in the layers having non-intended
time values.  Ensure mtime and atime in the source chroot match what is
found in the destination chroot.
2025-06-02 12:23:02 -06:00

227 lines
7.0 KiB
Bash
Executable File

#!/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.
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 'build binary images')"
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_binary_includes () {
# Copying includes from pass subdirectory
local pass="$1"
if [ ! -d config/includes.binary.${pass} ]; then
return
fi
cd config/includes.binary.${pass}
find . | cpio -dmpu --no-preserve-owner "${OLDPWD}"/chroot
cd "${OLDPWD}"
}
build_layered_squashfs () {
local pass=$1
shift 1 # restore ${*}
Echo_message "lb_binary_layered: treating pass $pass"
# Per convention, we include the subarch name next to the project
PROJECT_FULL=$PROJECT${SUBARCH:+-$SUBARCH}
# Building squashfs filesystem & manifest
local overlay_dir="overlay.${pass}"
base="${PWD}/livecd.${PROJECT_FULL}.${pass}"
squashfs_f="${base}.squashfs"
# We have already treated that pass
if [ -f "${squashfs_f}" ]; then
return
fi
rm -f .build/binary_chroot .build/binary_hooks
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
# Cleanup root filesystem
lb binary_chroot ${*}
lb_binary_includes $pass ${*}
lb binary_hooks ${*}
# Copy initrd and vmlinuz outside of chroot and remove them from the layer squashfs
if $(is_live_layer "$pass"); then
lb binary_linux-image ${*}
rm -f chroot/boot/initrd.img-* chroot/boot/vmlinu{x,z}-*
fi
make_squashfs=yes
ppass="${pass}"
while :; do
for nsp in ${NO_SQUASHFS_PASSES}; do
if [ "${ppass}" = "${nsp}" ]; then
make_squashfs=no
break 2
fi
done
ppass="$(get_parent_pass "${ppass}")"
if [ -z "${ppass}" ]; then
break
fi
done
if [ $make_squashfs = yes ]; then
# Full manifest until that PASS
squashfs_f_manifest="${base}.manifest"
create_manifest "chroot" "${squashfs_f_manifest}.full"
# Delta manifest
diff -NU0 ${PWD}/livecd.${PROJECT_FULL}.$(get_parent_pass $pass).manifest.full ${squashfs_f_manifest}.full|grep -v ^@ > $squashfs_f_manifest || true
echo "Delta manifest:"
cat $squashfs_f_manifest
squashfs_f_size="${base}.size"
du -B 1 -s "overlay.${pass}/" | cut -f1 > "${squashfs_f_size}"
# We take first live pass for "global" ISO properties (used by installers and checkers):
# Prepare initrd + kernel
# Main manifest and size files
prefix="livecd.$PROJECT_FULL"
if [ ! -e "${prefix}.manifest" ] && $(is_live_layer "$pass"); then
totalsize=$(cat ${squashfs_f_size})
curpass="$pass"
while :; do
curpass=$(get_parent_pass $curpass)
# We climbed up the tree to the root layer, we are done
[ -z "$curpass" ] && break
totalsize=$(expr $totalsize + $(cat "${PWD}/livecd.${PROJECT_FULL}.${curpass}.size"))
done
echo ${totalsize} > "${prefix}.size"
cp "${squashfs_f_manifest}.full" "${prefix}.manifest"
fi
if [ -n "$lowerdirs" ]; then
# Although the current chroot was created as an overlay over
# the previous layer, many operations can result in redundant
# files in the upperdir. Rather than trying to minimize the
# overlay by hand, we rsync the chroot into a fresh overlay,
# rely on rsyncs ability to avoid redundant file operations,
# and take _that_ overlay's upperdir as the content of the
# layer.
mkdir -p chroot-2 "$overlay_dir-2"
mount_overlay "$lowerdirs" "$overlay_dir-2" chroot-2
# rsync takes many, many options. The subset
# we pass here is quite important:
# -a is standard to operate in the basic way required here.
# -X to preserve xattrs
# -H to preserve hardlinks
# -A to preserve ACLs
# -S to preserve sparseness
# --checksum to skip copies based on the content of the file
# (rather than the default which is to skip copies based
# on size + mtime)
# --no-times to not copy mtimes from source to dest (we
# don't care about mtime in the image and want to
# deduplicate files that have indentical contents but
# different mtimes)
# --del because we want to remove files that have been
# deleted in this layer.
rsync -aXHAS --checksum --no-times --del chroot/ chroot-2/
# but since we used --no-times, mtime was not actually
# replicated to chroot-2, instead using the mtime of
# the moment of rsync. This will break anything that
# requires an accurate mtime, so go fix that up.
# LP: #2107332
/usr/share/livecd-rootfs/sync-mtime chroot chroot-2
umount chroot-2
rmdir chroot-2
overlay_dir="$overlay_dir-2"
fi
create_squashfs "${overlay_dir}" ${squashfs_f}
if [ -f config/$pass.catalog-in.yaml ]; then
echo "Expanding catalog entry template for $pass"
usc_opts="--output livecd.${PROJECT_FULL}.install-sources.yaml \
--template config/$pass.catalog-in.yaml \
--size $(du -B 1 -s chroot/ | cut -f1) --squashfs ${pass}.squashfs \
--translations config/catalog-translations"
if [ -f config/seeded-languages ]; then
usc_opts="$usc_opts --langs $(cat config/seeded-languages)"
fi
/usr/share/livecd-rootfs/update-source-catalog source $usc_opts
else
echo "No catalog entry template for $pass"
fi
fi
if [ -n "$lowerdirs" ]; then
umount chroot
rmdir chroot
else
rm chroot
fi
}
for _PASS in $PASSES
do
build_layered_squashfs "${_PASS}" ${*}
done
if [ -n "$DEFAULT_KERNEL" -a -f livecd.${PROJECT_FULL}.install-sources.yaml ]; then
write_kernel_yaml "$DEFAULT_KERNEL" "$BRIDGE_KERNEL_REASONS"
/usr/share/livecd-rootfs/update-source-catalog merge \
--output livecd.${PROJECT_FULL}.install-sources.yaml \
--template config/kernel.yaml
fi
# Ubiquity-compatible removal manifest for ISO not using a layered-aware installer
if [ -n "$(ls livecd.${PROJECT_FULL}.*install.live.manifest.full 2>/dev/null)" ] && \
[ -n "$(ls livecd.${PROJECT_FULL}.*install.manifest.full 2>/dev/null)" ]; then
echo "$(diff livecd.${PROJECT_FULL}.*install.live.manifest.full livecd.${PROJECT_FULL}.*install.manifest.full | awk '/^< / { print $2 }')" > livecd.${PROJECT_FULL}-manifest-remove
fi
chmod 644 *.squashfs *.manifest* *.size