-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
handle-writable-paths: extract the writable-path handling
This PR moves the code that handle the writable-path for a core system from the initramfs to the core20 snap. This has the benefit that we don't have to change the initramfs if this code needs to change. The initramfs will just call it from the core20 snap.
- Loading branch information
Showing
1 changed file
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
#!/bin/sh | ||
# | ||
# Extracted code from: | ||
# https://github.com/snapcore/core-build/blob/master/initramfs/scripts/ubuntu-core-rootfs | ||
# to keep in the core20+ snap in sync with the writable-path file. | ||
# | ||
# Having it here means we don't need to rebuld all kernels if this file | ||
# changes. | ||
|
||
set -e | ||
|
||
panic() | ||
{ | ||
echo "PANIC: $*" | ||
exit 1 | ||
} | ||
|
||
# XXX: we really want the "synced" feature to go away | ||
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 | ||
} | ||
|
||
main() | ||
{ | ||
writable_paths="${1:-${rootmnt}/etc/system-image/writable-paths}" | ||
fstab="${2:-${rootmnt}/etc/fstab}" | ||
|
||
# Add writable overlays | ||
if [ -e "$writable_paths" ]; then | ||
mkdir -p "${rootmnt}/run" | ||
mkdir -p "$(dirname "$fstab")" | ||
|
||
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 | ||
} | ||
|
||
rootmnt="$1" | ||
if [ -z "$rootmnt" ]; then | ||
echo "need rootmnt as the first argument" | ||
exit 1 | ||
fi | ||
# "$2" is the (optional) writable-paths file | ||
# "$3" is the (optional) /etc/fstab file | ||
main "$2" "$3" | ||
|