Linux ip-172-26-7-228 5.4.0-1103-aws #111~18.04.1-Ubuntu SMP Tue May 23 20:04:10 UTC 2023 x86_64
Your IP : 3.146.178.241
# -*- shell-script -*- vim:ft=sh:
#---------------------------------------------------------------------
# Description: Mount appropriate Ubuntu Core root filesystem read-only
# and writable partition writable.
# Entry point: mountroot().
#---------------------------------------------------------------------
# shellcheck disable=SC2034
. ${scriptsroot:-/scripts}/ubuntu-core-functions
sync_dirs()
{
base="$1"
source="$2"
target="$3"
OLD_PWD="$PWD"
cd "$base"
for file in "$source"/*
do
# Skip empty directories
[ ! -e "$base/$file" -a ! -L "$base/$file" ] && continue
# If the target already exists as a file or link, there's nothing we can do
[ -e "$target/$file" -o -L "$target/$file" ] && [ ! -d "$target/$file" ] && continue
# If the target doesn't exist, just copy it over
if [ ! -e "$target/$file" -a ! -L "$target/$file" ]; then
cp -Ra "$base/$file" "$target/$file"
continue
fi
# That leaves us with directories and a recursive call
[ -d "$file" ] && sync_dirs "$base" "$file" "$target"
done
cd "$OLD_PWD"
}
# Process the list of bind-mounts (but don't mount them - systemd will handle that)
# File format is documented in writable-paths(5).
handle_writable_paths()
{
writable_paths="$1"
fstab="$2"
[ -n "$writable_paths" ] || panic "need writeable paths"
[ -e "$writable_paths" ] || panic "writeable paths does not exist"
[ -n "$fstab" ] || panic "need fstab"
cat "$writable_paths" | while read line; do
# tokenise
set -- $line
# skip invalid/commented entries
([ -z "$1" ] || \
[ -z "$2" ] || \
[ -z "$3" ] || \
[ -z "$4" ] || \
[ -z "$5" ]) && continue
# ignore anything that isn't an absolute path (including comments)
case "$1" in
/*) ;;
*) continue ;;
esac
# skip invalid mount points
dstpath="${rootmnt}$1"
[ ! -e "$dstpath" ] && continue
if [ "$3" = "temporary" ]; then
# Temporary entries are simple, just mount a tmpfs
echo "tmpfs $1 tmpfs $5 0 0" >> "$fstab"
elif [ "$3" = "persistent" ] || \
[ "$3" = "synced" ]; then
# Figure out the source path
if [ "$2" = "auto" ]; then
srcpath="${rootmnt}/writable/system-data${1}"
path="/writable/system-data${1}"
else
srcpath="${rootmnt}/writable/$2"
path="/writable/$2"
fi
if [ ! -e "$srcpath" ]; then
# Process new persistent or synced paths
dstown=$(stat -c "%u:%g" "$dstpath")
dstmode=$(stat -c "%a" "$dstpath")
mkdir -p ${srcpath%/*}
if [ ! -d "$dstpath" ]; then
# Deal with redirected files
if [ "$4" = "transition" ]; then
cp -a "$dstpath" "$srcpath"
else
touch "$srcpath"
chown "$dstown" "$srcpath"
chmod "$dstmode" "$srcpath"
fi
else
# Deal with redirected directories
if [ "$4" = "transition" ] || [ "$3" = "synced" ]; then
cp -aR "$dstpath" "$srcpath"
else
mkdir "$srcpath"
chown "$dstown" "$srcpath"
chmod "$dstmode" "$srcpath"
fi
fi
elif [ "$3" = "synced" ]; then
# Process existing synced paths
sync_dirs "$dstpath" . "$srcpath"
fi
# mount all /etc dirs right now, not later when fstab is
# processed, as it will cause races.
case $1 in
/etc*)
[ -e "${rootmnt}/writable/system-data/$1" ] || mkdir -p "${rootmnt}/writable/system-data/$1"
mount -o bind "${rootmnt}/writable/system-data/$1" "${rootmnt}/$1"
;;
*)
# Write the fstab entry
if [ "$5" = "none" ]; then
echo "$path $1 none bind 0 0" >> "$fstab"
else
echo "$path $1 none bind,$5 0 0" >> "$fstab"
fi
;;
esac
else
continue
fi
done
# now apply the defaults on top
handle_writable_defaults
}
# handle_writable_default will apply system defaults *once* after
# the handle_writable_path got populated
handle_writable_defaults()
{
srcpath="${rootmnt}/writable/system-data/_writable_defaults"
if [ ! -d "$srcpath" ] || [ -e "${srcpath}/.done" ]; then
return
fi
dstpath="${rootmnt}/writable/system-data"
for fileordir in "$srcpath"/* ; do
# skip empty $srcpath/
[ ! -e "$fileordir" ] && [ ! -L "$fileordir" ] && continue
# copy
cp -a "$fileordir" "$dstpath"
done
touch "$srcpath/.done"
}
fsck_writable()
{
local writable_label="$1"
local writable_mnt="$2"
path=$(get_partition_from_label "$writable_label")
[ -n "$path" ] || panic "cannot find '$writable_label' partition"
# Mount the writable partition to a temporary mount point
# (to allow it to be move-mounted on top of the read-only root).
logfile="/run/initramfs/fsck-${writable_label}"
echo "initrd: checking filesystem for ${writable_label} partition" >/dev/kmsg || true
echo "$(date '+%s'): start" >> "$logfile" || true
# XXX: The following commands must not fail (to ensure the system boots!)
# Mount and umount first to let the kernel handle
# the journal and orphaned inodes (much faster than e2fsck).
mount -o errors=remount-ro "$path" "$writable_mnt" || true
umount "$writable_mnt" || true
# Automatically fix errors
/sbin/e2fsck -va "$path" >> "$logfile" 2>&1 || true
echo "$(date '+%s'): end" >> "$logfile" || true
}
# Mount core and kernel snaps
mount_snaps()
{
# mount OS snap
mount -o ro "${writable_mnt}/system-data/var/lib/snapd/snaps/${snap_core}" "$rootmnt"
# now add a kernel bind mounts to it
local kernel_mnt="/tmpmnt_kernel"
mkdir -p "$kernel_mnt"
mount -o ro "${writable_mnt}/system-data/var/lib/snapd/snaps/${snap_kernel}" "$kernel_mnt"
for d in modules firmware; do
if [ -d "${kernel_mnt}/$d" ]; then
mount -o bind "${kernel_mnt}/$d" "$rootmnt/lib/$d"
fi
done
# now we can umount the kernel and the bind mounts are still intact
# (magic!)
umount "$kernel_mnt"
}
#---------------------------------------------------------------------
# XXX: Entry point - called by the initramfs "/init" script.
#---------------------------------------------------------------------
mountroot()
{
pre_mountroot
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-premount"
run_scripts /scripts/local-premount
[ "$quiet" != "y" ] && log_end_msg
# find what snappy-os version to use
for x in $(cat /proc/cmdline); do
case "${x}" in
# new kernel/os snap vars
snap_core=*)
snap_core="${x#*=}"
;;
snap_kernel=*)
snap_kernel="${x#*=}"
;;
esac
done
# basic validation
if [ -z "$snap_core" ]; then
panic "the requried kernel commandline snap_core is not set"
fi
if [ -z "$snap_kernel" ]; then
panic "the requried kernel commandline snap_kernel is not set"
fi
# always ensure writable is in a good state
writable_label="writable"
writable_mnt="/tmpmnt_${writable_label}"
mkdir -p "$writable_mnt"
fsck_writable "$writable_label" "$writable_mnt"
# mount the root fs
do_root_mounting
# mount core and kernel snaps
mount_snaps
# mount /run
echo "initrd: mounting /run" >/dev/kmsg || true
mount -o rw,nosuid,noexec,relatime,mode=755 -t tmpfs tmpfs "${rootmnt}/run"
# move /writable to its final destination
mount --move "$writable_mnt" "${rootmnt}/writable"
# Prepare the fstab
fstab="${rootmnt}/etc/fstab"
writable_paths="${rootmnt}/etc/system-image/writable-paths"
# Add writable overlays
if [ -e "$writable_paths" ]; then
touch "${rootmnt}/run/image.fstab"
mount -o bind "${rootmnt}/run/image.fstab" "$fstab" || panic "Cannot bind mount fstab"
echo "# Auto-generated by $0" >> "$fstab"
echo "# DO NOT EDIT THIS FILE BY HAND - YOUR CHANGES WILL BE OVERWRITTEN" >> "$fstab"
echo "# (See writable-paths(5) for details)" >> "$fstab"
echo "/dev/root / rootfs defaults,ro 0 0" >> "$fstab"
# FIXME: ideally we would mount /writable RO here and
# let systemd do a "remount,rw" for us. unfortunately
# this is not supported by systemd so we need to do
# the RW mount and fsck dance etc here :/
echo "LABEL=writable /writable auto defaults 0 0" >> "$fstab"
handle_writable_paths "$writable_paths" "$fstab"
fi
# IMPORTANT: ensure we synced everything back to disk
sync
# Request bootloader partition be mounted
boot_partition=$(findfs LABEL="system-boot" 2>/dev/null || :)
if [ -n "$boot_partition" ]; then
# determine bootloader type, we need to inspect the boot
# partition for this
grubdir="/boot/grub"
ubootdir="/boot/uboot"
tmpboot_mnt="/tmpmnt_system-boot"
mkdir -p $tmpboot_mnt
mount -o ro "$boot_partition" "$tmpboot_mnt"
# Since the boot partition is not required to actually boot
# the image, request the init system handle it (fsck+mount).
if [ -f "${tmpboot_mnt}/EFI/ubuntu/grub/grub.cfg" ]; then
# OLD style (ubuntu-device-flash) base dir
efidir="/boot/efi"
efibinddir="${efidir}/EFI/ubuntu/grub"
if [ -d "${rootmnt}/${efidir}" ]; then
echo "$boot_partition $efidir auto defaults 0 2" >> "$fstab"
echo "$efibinddir $grubdir none bind 0 0" >> "$fstab"
fi
elif [ -f "${tmpboot_mnt}/EFI/ubuntu/grub.cfg" ]; then
# NEW style (u-i base dir)
efidir="/boot/efi"
efibinddir="${efidir}/EFI/ubuntu/"
if [ -d "${rootmnt}/${efidir}" ]; then
echo "$boot_partition $efidir auto defaults 0 2" >> "$fstab"
echo "$efibinddir $grubdir none bind 0 0" >> "$fstab"
fi
else
echo "$boot_partition $ubootdir auto defaults 0 2" >> "$fstab"
fi
# let systemd do the actual mounting
umount "$tmpboot_mnt"
elif abootimg -i "$(findfs PARTLABEL=recovery)" >/dev/null 2>&1; then
echo "android style bootloader detected" >/dev/kmsg || true
androiddir="writable/androidboot"
mkdir -p "${rootmnt}/${androiddir}"
if [ ! -e "${rootmnt}/${androiddir}/androidboot.env" ]; then
echo -e "snap_mode=\nsnap_core=$snap_core\nsnap_kernel=$snap_kernel\nsnap_try_core=\nsnap_try_kernel=" > \
"${rootmnt}/${androiddir}/androidboot.env"
fi
mount -o bind "${rootmnt}/${androiddir}" "${rootmnt}/boot/androidboot"
fi
# Mount the systemd overlay so that we have a complete root partition during boot
mkdir -p "${rootmnt}/writable/system-data/etc/systemd/system"
mount -o bind "${rootmnt}/writable/system-data/etc/systemd/system" "${rootmnt}/etc/systemd/system"
# create "machine-id" if it does not exist and bind mount it (LP: #1619721)
if [ ! -e ${rootmnt}/writable/system-data/etc/machine-id ]; then
cat /proc/sys/kernel/random/uuid|tr -d - >${rootmnt}/writable/system-data/etc/machine-id
fi
mount -o bind "${rootmnt}/writable/system-data/etc/machine-id" "${rootmnt}/etc/machine-id"
# Apply customized content
for user in "${rootmnt}"/writable/user-data/*
do
if [ -d "${rootmnt}/custom/home" ] && [ ! -e "$user/.customized" ]; then
echo "initrd: copying custom content tp " >/dev/kmsg || true
cp -Rap "${rootmnt}"/custom/home/* "$user/"
cp -Rap "${rootmnt}"/custom/home/.[a-zA-Z0-9]* "$user/"
touch "$user/.customized"
dstown=$(stat -c "%u:%g" "$user")
chown -R "$dstown" "$user/"
fi
done
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
run_scripts /scripts/local-bottom
[ "$quiet" != "y" ] && log_end_msg
}
|