|
| 1 | +#!/bin/sh |
| 2 | + |
| 3 | +type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh |
| 4 | + |
| 5 | +if getargbool 0 rd.live.debug -n -y rdlivedebug; then |
| 6 | + exec > /tmp/create-overlay.$$.out |
| 7 | + exec 2>> /tmp/create-overlay.$$.out |
| 8 | + set -x |
| 9 | +fi |
| 10 | + |
| 11 | +gatherData() { |
| 12 | + overlay=$(getarg rd.live.overlay) |
| 13 | + if [ -z "$overlay" ]; then |
| 14 | + info "Skipping overlay creation: kernel command line parameter 'rd.live.overlay' is not set" |
| 15 | + exit 0 |
| 16 | + fi |
| 17 | + # shellcheck disable=SC2086 |
| 18 | + if ! str_starts ${overlay} LABEL=; then |
| 19 | + die "Overlay creation failed: the partition must be set by LABEL in the 'rd.live.overlay' kernel parameter" |
| 20 | + fi |
| 21 | + |
| 22 | + overlayLabel=${overlay#LABEL=} |
| 23 | + # shellcheck disable=SC2086 |
| 24 | + if [ -b /dev/disk/by-label/${overlayLabel} ]; then |
| 25 | + info "Skipping overlay creation: overlay already exists" |
| 26 | + exit 0 |
| 27 | + fi |
| 28 | + |
| 29 | + filesystem=$(getarg rd.live.overlay.cowfs) |
| 30 | + [ -z "$filesystem" ] && filesystem="ext4" |
| 31 | + if [ "$filesystem" != "ext4" ] && [ "$filesystem" != "xfs" ] && [ "$filesystem" != "btrfs" ]; then |
| 32 | + die "Overlay creation failed: only ext4, xfs, and btrfs are supported in the 'rd.live.overlay.cowfs' kernel parameter" |
| 33 | + fi |
| 34 | + |
| 35 | + live_dir=$(getarg rd.live.dir) |
| 36 | + [ -z "$live_dir" ] && live_dir="LiveOS" |
| 37 | + |
| 38 | + [ -z "$1" ] && exit 1 |
| 39 | + rootDevice=$1 |
| 40 | + |
| 41 | + # The kernel command line's 'root=' parameter was parsed into the $root variable by the dmsquash-live module. |
| 42 | + # $root contains the path to a symlink within /dev/disk/by-label, which points to a partition. |
| 43 | + # This script needs that partition's parent block device. |
| 44 | + # shellcheck disable=SC2046 |
| 45 | + # shellcheck disable=SC2086 |
| 46 | + rootDeviceAbsolutePath=$(readlink -f ${rootDevice}) |
| 47 | + rootDeviceSysfsPath=/sys/class/block/${rootDeviceAbsolutePath##*/} |
| 48 | + if [ -f "${rootDeviceSysfsPath}/partition" ]; then |
| 49 | + # shellcheck disable=SC2086 |
| 50 | + partition=$(cat ${rootDeviceSysfsPath}/partition) |
| 51 | + else |
| 52 | + partition=0 |
| 53 | + fi |
| 54 | + # shellcheck disable=SC2086 |
| 55 | + readonly=$(cat ${rootDeviceSysfsPath}/ro) |
| 56 | + # shellcheck disable=SC2086 |
| 57 | + if [ "$partition" != "1" ] || [ "$readonly" != "0" ]; then |
| 58 | + info "Skipping overlay creation: unpartitioned or read-only media detected" |
| 59 | + exit 0 |
| 60 | + fi |
| 61 | + # shellcheck disable=SC2046 |
| 62 | + # shellcheck disable=SC2086 |
| 63 | + fullDriveSysfsPath=$(readlink -f ${rootDeviceSysfsPath}/..) |
| 64 | + blockDevice=/dev/${fullDriveSysfsPath##*/} |
| 65 | + currentPartitionCount=$(grep --count -E "${blockDevice#/dev/}[0-9]+" /proc/partitions) |
| 66 | + |
| 67 | + # shellcheck disable=SC2086 |
| 68 | + freeSpaceStart=$(parted --script ${blockDevice} unit % print free \ |
| 69 | + | awk -v x=${currentPartitionCount} '$1 == x {getline; print $1}') |
| 70 | + if [ -z "$freeSpaceStart" ]; then |
| 71 | + info "Skipping overlay creation: there is no free space after the last partition" |
| 72 | + exit 0 |
| 73 | + fi |
| 74 | + partitionStart=$((${freeSpaceStart%.*} + 1)) |
| 75 | + if [ $partitionStart -eq 100 ]; then |
| 76 | + info "Skipping overlay creation: there is not enough free space after the last partition" |
| 77 | + exit 0 |
| 78 | + fi |
| 79 | + |
| 80 | + overlayPartition=${blockDevice}$((currentPartitionCount + 1)) |
| 81 | + |
| 82 | + label=$(blkid --match-tag LABEL --output value "$rootDevice") |
| 83 | + uuid=$(blkid --match-tag UUID --output value "$rootDevice") |
| 84 | + if [ -z "$label" ] || [ -z "$uuid" ]; then |
| 85 | + die "Overlay creation failed: failed to look up root device label and UUID" |
| 86 | + fi |
| 87 | +} |
| 88 | + |
| 89 | +createPartition() { |
| 90 | + # shellcheck disable=SC2086 |
| 91 | + parted --script --align optimal ${blockDevice} mkpart primary ${partitionStart}% 100% |
| 92 | +} |
| 93 | + |
| 94 | +createFilesystem() { |
| 95 | + # shellcheck disable=SC2086 |
| 96 | + mkfs.${filesystem} -L ${overlayLabel} ${overlayPartition} |
| 97 | + |
| 98 | + baseDir=/run/initramfs/create-overlayfs |
| 99 | + mkdir -p ${baseDir} |
| 100 | + # shellcheck disable=SC2086 |
| 101 | + mount -t auto ${overlayPartition} ${baseDir} |
| 102 | + |
| 103 | + mkdir -p ${baseDir}/${live_dir}/ovlwork |
| 104 | + # shellcheck disable=SC2086 |
| 105 | + mkdir ${baseDir}/${live_dir}/overlay-${label}-${uuid} |
| 106 | + |
| 107 | + umount ${baseDir} |
| 108 | + rm -r ${baseDir} |
| 109 | +} |
| 110 | + |
| 111 | +main() { |
| 112 | + gatherData "$1" |
| 113 | + createPartition |
| 114 | + udevsettle |
| 115 | + createFilesystem |
| 116 | + udevsettle |
| 117 | +} |
| 118 | + |
| 119 | +main "$1" |
0 commit comments