#!/usr/bin/sh

. /lib/dracut-lib.sh

can_decrypt=0
if [ -f /lib/dracut-crypt-lib.sh ] ; then
    . /lib/dracut-crypt-lib.sh
    can_decrypt=1
fi

[ -f /tmp/root.info ] && . /tmp/root.info

PATH=/usr/sbin:/usr/bin:/sbin:/bin

[ -z "$1" ] && exit 1
livedev="$1"

# Create live tree
mkdir -m 0755 -p /live/distrib
mkdir -m 0755 -p /live/media
mkdir -m 0755 -p /live/overlay
mkdir -m 0755 -p /live/union
mkdir -m 0755 -p /run/mgalive/ovlsize

# Get the base device name
basedev=$(echo $livedev | sed -e 's,\(/dev/sd[a-z]\)1,\1,g' -e 's,\(/dev/mmcblk[0-9]\)p1,\1,g')
# Make it available to draklive-install and mgalive-shutdown
echo $basedev > /run/mgalive/basedev

# Unlock any encrypted partitions on the base device
if [ $can_decrypt -eq 1 ] ; then
    for dev in $(blkid -t TYPE=crypto_LUKS -o device | grep $basedev) ; do
        ask_for_password \
            --ply-cmd "cryptsetup open -T1 $dev crypt_${dev##/dev/}" \
            --ply-prompt "Password ($dev)" \
            --ply-tries 3 \
            --tty-cmd "cryptsetup open -T3 $dev crypt_${dev##/dev/}" \
            --tty-tries 1
    done
fi


# Get the base directory for locating the loopback file. In normal use this is
# the root directory, but a multi-boot USB stick may want to override this.
basedir=$(getarg mgalive.basedir)

# Get the device or path used for persistent storage (if it exists). In normal
# use this is another partition on the same base device, but a multi-boot USB
# stick may want to override this.
overlay=$(getarg mgalive.overlay)
if [ -z "$overlay" ] ; then
    overlay=$(blkid -t LABEL=mgalive-persist -o device | grep $basedev'\|'/dev/mapper)
elif [ "$overlay" = "ram" ] ; then
    overlay=
else
    overlay=$livedev$overlay
fi

# If the base device is partitioned (i.e. it's a USB stick, not a DVD), get the
# device name and start offset of the first partition. This is the protective
# partition covering the iso9660 filesystem.
if [ $livedev = $basedev ] ; then
    ps=0
    case $basedev in
      /dev/sd*)
        test -b ${basedev}1  && livedev=${basedev}1  && ps=$(partx -go START $livedev)
        ;;
      /dev/mmblk*)
        test -b ${basedev}p1 && livedev=${basedev}p1 && ps=$(partx -go START $livedev)
        ;;
    esac
else
    ps=$(partx -go START $livedev)
fi

info "mgalive basedev is $basedev"
info "mgalive livedev is $livedev"
info "mgalive basedir is $basedir/"
info "mgalive overlay is $overlay"

media=$livedev

if [ $ps -ne 0 ] ; then
    if strstr "$(blkid $basedev)" "iso9660" ; then
        # This happens when we boot from a USB stick with a isohybrid partition
        # scheme where the first sector is unclaimed, so the first partition starts
        # at sector 1. The iso9660 filesystem starts at sector 0, so blkid doesn't
        # detect a valid filesystem in the first partition. In the past, udev linked        
        # the entry in /dev/disk/by-label to the first partition, not to the raw
        # device, and that is what we got passed in $1 (mga#3334). More recently,
	# udev links it to the base device (mga#27629). The preceding tests ensure
	# we handle both cases.
        if [ -n "$overlay" ] ; then
            # If we mount the raw device, we can't then also mount a partition
            # on that device. So to enable persistence, we need to extend the
            # first partition to claim the full range  of the iso9660 filesystem.
	    # The loops waiting for udev are to ensure we don't try to mount the
	    # partition in the small window when udev has removed it but not yet
	    # re-added it (mga#27638).
            pe=$(partx -go END   $livedev)
            if [ $ps -eq 1 ] ; then
                info "Extending $livedev to cover sector 0"
                delpart $basedev 1
		while [ -e $livedev ] ; do
		    info "Wait for udev to remove $livedev"
		done
                addpart $basedev 1 0 $pe
		while [ ! -e $livedev ] ; do
		    info "Wait for udev to re-add $livedev"
		done
            else
                info "$livedev is not a valid protective partition"
            fi
        else
            # If we don't have a persistent partition, take the easy option.
            info "Using $basedev to mount the iso9660 filesystem"
            media=$basedev
        fi
    else
	info "$basedev does not contain a valid filesystem"
    fi
fi

# Mount the live media
mount -n -o ro $media /live/media

# Mount the loopback filesystem
LOOPDEV=$( losetup -f )
if [ -e /live/media$basedir/loopbacks/distrib-lzma.sqfs ] ; then
    # Retain support for the original draklive. Note that despite the file
    # name, it uses xz compression.
    losetup -r $LOOPDEV /live/media$basedir/loopbacks/distrib-lzma.sqfs
else
    losetup -r $LOOPDEV /live/media$basedir/loopbacks/distrib.sqfs
fi
mount -n -t squashfs -o ro $LOOPDEV /live/distrib
mount -n -t squashfs -o ro $LOOPDEV /run/mgalive/ovlsize

# Mount the overlay filesystem
if [ -z "$overlay" ] ; then
    mount -n -t tmpfs -o mode=755 none /live/overlay
else
    mount -n -o noatime $overlay /live/overlay
    echo 1 > /run/mgalive/persistent
fi
# work and memory must be on same root
mkdir -m 0755 -p /live/overlay/work
mkdir -m 0755 -p /live/overlay/memory
mount -n -t overlay overlay -o lowerdir=/live/distrib,upperdir=/live/overlay/memory,workdir=/live/overlay/work,noatime /live/union

ln -s /live/union /dev/root

printf '/bin/mount --rbind /live/union %s\n' "$NEWROOT" > $hookdir/mount/01-$$-live.sh
printf '/bin/umount /live/union\n'                     >> $hookdir/mount/01-$$-live.sh

# /live will not be visible once we pivot, so schedule its cleanup now.
# This is needed to allow a persistent overlay to be shutdown cleanly.
umount -l /live/distrib
umount -l /live/overlay
umount -l /live/media

need_shutdown

exit 0
