summaryrefslogtreecommitdiffstats
path: root/modules.d/90dmsquash-live/dmsquash-live-root.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xmodules.d/90dmsquash-live/dmsquash-live-root.sh432
1 files changed, 432 insertions, 0 deletions
diff --git a/modules.d/90dmsquash-live/dmsquash-live-root.sh b/modules.d/90dmsquash-live/dmsquash-live-root.sh
new file mode 100755
index 0000000..e808339
--- /dev/null
+++ b/modules.d/90dmsquash-live/dmsquash-live-root.sh
@@ -0,0 +1,432 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type det_fs > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+command -v unpack_archive > /dev/null || . /lib/img-lib.sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+if getargbool 0 rd.live.debug -n -y rdlivedebug; then
+ exec > /tmp/liveroot.$$.out
+ exec 2>> /tmp/liveroot.$$.out
+ set -x
+fi
+
+[ -z "$1" ] && exit 1
+livedev="$1"
+
+# parse various live image specific options that make sense to be
+# specified as their own things
+live_dir=$(getarg rd.live.dir -d live_dir)
+[ -z "$live_dir" ] && live_dir="LiveOS"
+squash_image=$(getarg rd.live.squashimg)
+[ -z "$squash_image" ] && squash_image="squashfs.img"
+
+getargbool 0 rd.live.ram -d -y live_ram && live_ram="yes"
+getargbool 0 rd.live.overlay.reset -d -y reset_overlay && reset_overlay="yes"
+getargbool 0 rd.live.overlay.readonly -d -y readonly_overlay && readonly_overlay="--readonly" || readonly_overlay=""
+overlay=$(getarg rd.live.overlay -d overlay)
+getargbool 0 rd.writable.fsimg -d -y writable_fsimg && writable_fsimg="yes"
+overlay_size=$(getarg rd.live.overlay.size=)
+[ -z "$overlay_size" ] && overlay_size=32768
+
+getargbool 0 rd.live.overlay.thin && thin_snapshot="yes"
+getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes"
+
+# Take a path to a disk label and return the parent disk if it is a partition
+# Otherwise returns the original path
+get_check_dev() {
+ local _udevinfo
+ dev_path="$(udevadm info -q path --name "$1")"
+ _udevinfo="$(udevadm info -q property --path "${dev_path}")"
+ strstr "$_udevinfo" "DEVTYPE=partition" || {
+ echo "$1"
+ return
+ }
+ parent="${dev_path%/*}"
+ _udevinfo="$(udevadm info -q property --path "${parent}")"
+ strstr "$_udevinfo" "DEVTYPE=disk" || {
+ echo "$1"
+ return
+ }
+ strstr "$_udevinfo" "ID_FS_TYPE=iso9660" || {
+ echo "$1"
+ return
+ }
+
+ # Return the name of the parent disk device
+ echo "$_udevinfo" | grep "DEVNAME=" | sed 's/DEVNAME=//'
+}
+
+# Find the right device to run check on
+check_dev=$(get_check_dev "$livedev")
+# CD/DVD media check
+[ -b "$check_dev" ] && fs=$(det_fs "$check_dev")
+if [ "$fs" = "iso9660" -o "$fs" = "udf" ]; then
+ check="yes"
+fi
+getarg rd.live.check -d check || check=""
+if [ -n "$check" ]; then
+ type plymouth > /dev/null 2>&1 && plymouth --hide-splash
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ p=$(dev_unit_name "$check_dev")
+ systemctl start checkisomd5@"${p}".service
+ else
+ checkisomd5 --verbose "$check_dev"
+ fi
+ if [ $? -eq 1 ]; then
+ die "CD check failed!"
+ exit 1
+ fi
+ type plymouth > /dev/null 2>&1 && plymouth --show-splash
+fi
+
+ln -s "$livedev" /run/initramfs/livedev
+
+# determine filesystem type for a filesystem image
+det_img_fs() {
+ udevadm settle >&2
+ blkid -s TYPE -u noraid -o value "$1"
+}
+
+load_fstype squashfs
+CMDLINE=$(getcmdline)
+for arg in $CMDLINE; do
+ case $arg in
+ ro | rw) liverw=$arg ;;
+ esac
+done
+
+# mount the backing of the live image first
+mkdir -m 0755 -p /run/initramfs/live
+if [ -f "$livedev" ]; then
+ # no mount needed - we've already got the LiveOS image in initramfs
+ # check filesystem type and handle accordingly
+ fstype=$(det_img_fs "$livedev")
+ case $fstype in
+ squashfs) SQUASHED=$livedev ;;
+ auto) die "cannot mount live image (unknown filesystem type)" ;;
+ *) FSIMG=$livedev ;;
+ esac
+ [ -e /sys/fs/"$fstype" ] || modprobe "$fstype"
+else
+ livedev_fstype=$(det_fs "$livedev")
+ if [ "$livedev_fstype" = "squashfs" ]; then
+ # no mount needed - we've already got the LiveOS image in $livedev
+ SQUASHED=$livedev
+ elif [ "$livedev_fstype" != "ntfs" ]; then
+ if ! mount -n -t "$livedev_fstype" -o "${liverw:-ro}" "$livedev" /run/initramfs/live; then
+ die "Failed to mount block device of live image"
+ exit 1
+ fi
+ else
+ [ -x "/sbin/mount-ntfs-3g" ] && /sbin/mount-ntfs-3g -o "${liverw:-ro}" "$livedev" /run/initramfs/live
+ fi
+fi
+
+# overlay setup helper function
+do_live_overlay() {
+ # create a sparse file for the overlay
+ # overlay: if non-ram overlay searching is desired, do it,
+ # otherwise, create traditional overlay in ram
+
+ l=$(blkid -s LABEL -o value "$livedev") || l=""
+ u=$(blkid -s UUID -o value "$livedev") || u=""
+
+ if [ -z "$overlay" ]; then
+ pathspec="/${live_dir}/overlay-$l-$u"
+ elif strstr "$overlay" ":"; then
+ # pathspec specified, extract
+ pathspec=${overlay##*:}
+ fi
+
+ if [ -z "$pathspec" -o "$pathspec" = "auto" ]; then
+ pathspec="/${live_dir}/overlay-$l-$u"
+ fi
+ devspec=${overlay%%:*}
+
+ # need to know where to look for the overlay
+ if [ -z "$setup" -a -n "$devspec" -a -n "$pathspec" -a -n "$overlay" ]; then
+ mkdir -m 0755 -p /run/initramfs/overlayfs
+ if ismounted "$devspec"; then
+ devmnt=$(findmnt -e -v -n -o 'TARGET' --source "$devspec")
+ # We need $devspec writable for overlay storage
+ mount -o remount,rw "$devspec"
+ mount --bind "$devmnt" /run/initramfs/overlayfs
+ else
+ mount -n -t auto "$devspec" /run/initramfs/overlayfs || :
+ fi
+ if [ -f /run/initramfs/overlayfs$pathspec -a -w /run/initramfs/overlayfs$pathspec ]; then
+ OVERLAY_LOOPDEV=$(losetup -f --show ${readonly_overlay:+-r} /run/initramfs/overlayfs$pathspec)
+ over=$OVERLAY_LOOPDEV
+ umount -l /run/initramfs/overlayfs || :
+ oltype=$(det_img_fs "$OVERLAY_LOOPDEV")
+ if [ -z "$oltype" ] || [ "$oltype" = DM_snapshot_cow ]; then
+ if [ -n "$reset_overlay" ]; then
+ info "Resetting the Device-mapper overlay."
+ dd if=/dev/zero of="$OVERLAY_LOOPDEV" bs=64k count=1 conv=fsync 2> /dev/null
+ fi
+ if [ -n "$overlayfs" ]; then
+ unset -v overlayfs
+ [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ setup="yes"
+ else
+ mount -n -t "$oltype" ${readonly_overlay:+-r} "$OVERLAY_LOOPDEV" /run/initramfs/overlayfs
+ if [ -d /run/initramfs/overlayfs/overlayfs ] \
+ && [ -d /run/initramfs/overlayfs/ovlwork ]; then
+ ln -s /run/initramfs/overlayfs/overlayfs /run/overlayfs${readonly_overlay:+-r}
+ ln -s /run/initramfs/overlayfs/ovlwork /run/ovlwork${readonly_overlay:+-r}
+ if [ -z "$overlayfs" ] && [ -n "$DRACUT_SYSTEMD" ]; then
+ reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ overlayfs="required"
+ setup="yes"
+ fi
+ fi
+ elif [ -d /run/initramfs/overlayfs$pathspec ] \
+ && [ -d /run/initramfs/overlayfs$pathspec/../ovlwork ]; then
+ ln -s /run/initramfs/overlayfs$pathspec /run/overlayfs${readonly_overlay:+-r}
+ ln -s /run/initramfs/overlayfs$pathspec/../ovlwork /run/ovlwork${readonly_overlay:+-r}
+ if [ -z "$overlayfs" ] && [ -n "$DRACUT_SYSTEMD" ]; then
+ reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ overlayfs="required"
+ setup="yes"
+ fi
+ fi
+ if [ -n "$overlayfs" ]; then
+ if ! load_fstype overlay; then
+ if [ "$overlayfs" = required ]; then
+ die "OverlayFS is required but not available."
+ exit 1
+ fi
+ [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit=":>/xor_overlayfs;"
+ m='OverlayFS is not available; using temporary Device-mapper overlay.'
+ info "$m"
+ unset -v overlayfs setup
+ fi
+ fi
+
+ if [ -z "$setup" -o -n "$readonly_overlay" ]; then
+ if [ -n "$setup" ]; then
+ warn "Using temporary overlay."
+ elif [ -n "$devspec" -a -n "$pathspec" ]; then
+ [ -z "$m" ] \
+ && m=' Unable to find a persistent overlay; using a temporary one.'
+ m="$m"'
+ All root filesystem changes will be lost on shutdown.
+ Press [Enter] to continue.'
+ printf "\n\n\n\n%s\n\n\n" "${m}" > /dev/kmsg
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ if type plymouth > /dev/null 2>&1 && plymouth --ping; then
+ if getargbool 0 rhgb || getargbool 0 splash; then
+ m='>>>
+>>>
+>>>
+
+
+'"$m"
+ m="${m%n.*}"'n.
+
+
+<<<
+<<<
+<<<'
+ plymouth display-message --text="${m}"
+ else
+ plymouth ask-question --prompt="${m}" --command=true
+ fi
+ else
+ m=">>>$(printf '%s' "$m" | tr -d '\n') <<<"
+ systemd-ask-password --timeout=0 "${m}"
+ fi
+ else
+ type plymouth > /dev/null 2>&1 && plymouth --ping && plymouth --quit
+ printf '\n\n%s' "$m"
+ read -r _
+ fi
+ fi
+ if [ -n "$overlayfs" ]; then
+ if [ -n "$readonly_overlay" ] && ! [ -h /run/overlayfs-r ]; then
+ info "No persistent overlay found."
+ unset -v readonly_overlay
+ [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="${reloadsysrootmountunit}:>/xor_readonly;"
+ fi
+ else
+ dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((overlay_size * 1024)) 2> /dev/null
+ if [ -n "$setup" -a -n "$readonly_overlay" ]; then
+ RO_OVERLAY_LOOPDEV=$(losetup -f --show /overlay)
+ over=$RO_OVERLAY_LOOPDEV
+ else
+ OVERLAY_LOOPDEV=$(losetup -f --show /overlay)
+ over=$OVERLAY_LOOPDEV
+ fi
+ fi
+ fi
+
+ # set up the snapshot
+ if [ -z "$overlayfs" ]; then
+ if [ -n "$readonly_overlay" ] && [ -n "$OVERLAY_LOOPDEV" ]; then
+ echo 0 "$sz" snapshot "$BASE_LOOPDEV" "$OVERLAY_LOOPDEV" P 8 | dmsetup create --readonly live-ro
+ base="/dev/mapper/live-ro"
+ else
+ base=$BASE_LOOPDEV
+ fi
+ fi
+
+ if [ -n "$thin_snapshot" ]; then
+ modprobe dm_thin_pool
+ mkdir -m 0755 -p /run/initramfs/thin-overlay
+
+ # In block units (512b)
+ thin_data_sz=$((overlay_size * 1024 * 1024 / 512))
+ thin_meta_sz=$((thin_data_sz / 10))
+
+ # It is important to have the backing file on a tmpfs
+ # this is needed to let the loopdevice support TRIM
+ dd if=/dev/null of=/run/initramfs/thin-overlay/meta bs=1b count=1 seek=$((thin_meta_sz)) 2> /dev/null
+ dd if=/dev/null of=/run/initramfs/thin-overlay/data bs=1b count=1 seek=$((thin_data_sz)) 2> /dev/null
+
+ THIN_META_LOOPDEV=$(losetup --show -f /run/initramfs/thin-overlay/meta)
+ THIN_DATA_LOOPDEV=$(losetup --show -f /run/initramfs/thin-overlay/data)
+
+ echo 0 $thin_data_sz thin-pool "$THIN_META_LOOPDEV" "$THIN_DATA_LOOPDEV" 1024 1024 | dmsetup create live-overlay-pool
+ dmsetup message /dev/mapper/live-overlay-pool 0 "create_thin 0"
+
+ # Create a snapshot of the base image
+ echo 0 "$sz" thin /dev/mapper/live-overlay-pool 0 "$base" | dmsetup create live-rw
+ elif [ -z "$overlayfs" ]; then
+ echo 0 "$sz" snapshot "$base" "$over" PO 8 | dmsetup create live-rw
+ fi
+
+ # Create a device for the ro base of overlaid file systems.
+ if [ -z "$overlayfs" ]; then
+ echo 0 "$sz" linear "$BASE_LOOPDEV" 0 | dmsetup create --readonly live-base
+ fi
+ ln -s "$BASE_LOOPDEV" /dev/live-base
+}
+# end do_live_overlay()
+
+# we might have an embedded fs image on squashfs (compressed live)
+if [ -e /run/initramfs/live/${live_dir}/${squash_image} ]; then
+ SQUASHED="/run/initramfs/live/${live_dir}/${squash_image}"
+fi
+if [ -e "$SQUASHED" ]; then
+ if [ -n "$live_ram" ]; then
+ imgsize=$(($(stat -c %s -- $SQUASHED) / (1024 * 1024)))
+ check_live_ram $imgsize
+ echo 'Copying live image to RAM...' > /dev/kmsg
+ echo ' (this may take a minute)' > /dev/kmsg
+ dd if=$SQUASHED of=/run/initramfs/squashed.img bs=512 2> /dev/null
+ echo 'Done copying live image to RAM.' > /dev/kmsg
+ SQUASHED="/run/initramfs/squashed.img"
+ fi
+
+ SQUASHED_LOOPDEV=$(losetup -f)
+ losetup -r "$SQUASHED_LOOPDEV" $SQUASHED
+ mkdir -m 0755 -p /run/initramfs/squashfs
+ mount -n -t squashfs -o ro "$SQUASHED_LOOPDEV" /run/initramfs/squashfs
+
+ if [ -d /run/initramfs/squashfs/LiveOS ]; then
+ if [ -f /run/initramfs/squashfs/LiveOS/rootfs.img ]; then
+ FSIMG="/run/initramfs/squashfs/LiveOS/rootfs.img"
+ elif [ -f /run/initramfs/squashfs/LiveOS/ext3fs.img ]; then
+ FSIMG="/run/initramfs/squashfs/LiveOS/ext3fs.img"
+ fi
+ elif [ -d /run/initramfs/squashfs/proc ]; then
+ FSIMG=$SQUASHED
+ if [ -z "$overlayfs" ] && [ -n "$DRACUT_SYSTEMD" ]; then
+ reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ overlayfs="required"
+ else
+ die "Failed to find a root filesystem in $SQUASHED."
+ exit 1
+ fi
+else
+ # we might have an embedded fs image to use as rootfs (uncompressed live)
+ if [ -e /run/initramfs/live/${live_dir}/rootfs.img ]; then
+ FSIMG="/run/initramfs/live/${live_dir}/rootfs.img"
+ elif [ -e /run/initramfs/live/${live_dir}/ext3fs.img ]; then
+ FSIMG="/run/initramfs/live/${live_dir}/ext3fs.img"
+ fi
+ if [ -n "$live_ram" ]; then
+ echo 'Copying live image to RAM...' > /dev/kmsg
+ echo ' (this may take a minute or so)' > /dev/kmsg
+ dd if=$FSIMG of=/run/initramfs/rootfs.img bs=512 2> /dev/null
+ echo 'Done copying live image to RAM.' > /dev/kmsg
+ FSIMG='/run/initramfs/rootfs.img'
+ fi
+fi
+
+if [ -n "$FSIMG" ]; then
+ if [ -n "$writable_fsimg" ]; then
+ # mount the provided filesystem read/write
+ echo "Unpacking live filesystem (may take some time)" > /dev/kmsg
+ mkdir -m 0755 -p /run/initramfs/fsimg/
+ if [ -n "$SQUASHED" ]; then
+ cp -v $FSIMG /run/initramfs/fsimg/rootfs.img
+ else
+ unpack_archive $FSIMG /run/initramfs/fsimg/
+ fi
+ FSIMG=/run/initramfs/fsimg/rootfs.img
+ fi
+ # For writable DM images...
+ readonly_base=1
+ if [ -z "$SQUASHED" -a -n "$live_ram" -a -z "$overlayfs" ] \
+ || [ -n "$writable_fsimg" ] \
+ || [ "$overlay" = none -o "$overlay" = None -o "$overlay" = NONE ]; then
+ if [ -z "$readonly_overlay" ]; then
+ unset readonly_base
+ setup=rw
+ else
+ setup=yes
+ fi
+ fi
+ if [ "$FSIMG" = "$SQUASHED" ]; then
+ BASE_LOOPDEV=$SQUASHED_LOOPDEV
+ else
+ BASE_LOOPDEV=$(losetup -f --show ${readonly_base:+-r} $FSIMG)
+ sz=$(blockdev --getsz "$BASE_LOOPDEV")
+ fi
+ if [ "$setup" = rw ]; then
+ echo 0 "$sz" linear "$BASE_LOOPDEV" 0 | dmsetup create live-rw
+ else
+ # Add a DM snapshot or OverlayFS for writes.
+ do_live_overlay
+ fi
+fi
+
+if [ -n "$reloadsysrootmountunit" ]; then
+ eval "$reloadsysrootmountunit"
+ systemctl daemon-reload
+fi
+
+ROOTFLAGS="$(getarg rootflags)"
+
+if [ "$overlayfs" = required ]; then
+ echo "rd.live.overlay.overlayfs=1" > /etc/cmdline.d/dmsquash-need-overlay.conf
+fi
+
+if [ -n "$overlayfs" ]; then
+ if [ -n "$FSIMG" ]; then
+ mkdir -m 0755 -p /run/rootfsbase
+ mount -r $FSIMG /run/rootfsbase
+ else
+ ln -sf /run/initramfs/live /run/rootfsbase
+ fi
+else
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
+ printf 'mount %s /dev/mapper/live-rw %s\n' "$ROOTFLAGS" "$NEWROOT" > "$hookdir"/mount/01-$$-live.sh
+ fi
+fi
+[ -e "$SQUASHED" ] && umount -l /run/initramfs/squashfs
+
+ln -s null /dev/root
+
+need_shutdown
+
+exit 0