#!/usr/bin/env bash
# Copyright 2023 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
#
# Author: Kuniyuki Iwashima <kuniyu@amazon.com>
#
# create-ec2-rootfs.sh creates a rootfs from AL2023 container image.
#
# Usage:
#
#   1) Create a rootfs
#
#     ./create-ec2-rootfs.sh -f xfs -n rootfs.xfs -s 2G
#
#   2) Extend a rootfs
#
#     ./create-ec2-rootfs.sh -f xfs -n rootfs.xfs -s 4G
#
# The image can be tested locally with e.g.:
#
#   qemu-system-x86_64 -boot c -m 2G -kernel ${PATH_TO_bzImage} -hda ${PATH_TO_ROOTFS} \
#                      -append "root=/dev/sda rw console=ttyS0,115200" \
#                      -serial stdio -display none -nic user,hostfwd=tcp::10022-:22 \
#                      -enable-kvm -cpu host
#
# once the kernel boots, you can ssh into it with:
#
#   ssh -o StrictHostKeyChecking=no -p 10022 root@localhost
#

set -eux

NAME="rootfs.ext4"
FORMAT="ext4"
RESIZER="resize2fs"
SIZE="1G"
IMAGE="amazonlinux:2023"
PLATFORM="linux/amd64"

# Display help function
display_help() {
    echo "Usage: $0 [option...] " >&2
    echo
    echo "   -f, --format               rootfs format (ext4 or xfs), default ext4"
    echo "   -h, --help                 Display help message"
    echo "   -n, --name                 rootfs name, default rootfs.ext4"
    echo "   -p, --platform             linux platform type, default linux/amd64"
    echo "   -s, --size                 rootfs size, default 1G"
    echo
}

while true; do
    if [ $# -eq 0 ]; then
        break
    fi
    case "$1" in
        -h | --help)
            display_help
            exit 0
            ;;
        -f | --format)
            FORMAT=$2
            shift 2

            case "${FORMAT}" in
                ext4)
                    RESIZER="resize2fs"
                    ;;
                xfs)
                    RESIZER="xfs_growfs"
                    ;;
                -*)
                    echo "Error Unknown format: ${FORMAT}" >&2
                    exit 1
                    ;;
            esac
            ;;
        -n | --name)
            NAME=$2
            shift 2
            ;;
        -p | --platform)
            PLATFORM=$2
            shift 2
            ;;
        -s | --size)
            SIZE=$2
            shift 2
            ;;
        -*)
            echo "Error: Unknown option: $1" >&2
            exit 1
            ;;
        *)
            break
            ;;
    esac
done

MOUNT_DIR=$(mktemp -d)

if [ -f "${NAME}" ]; then
    truncate -s ${SIZE} ${NAME}
    sudo mount -o loop ${NAME} ${MOUNT_DIR}
    sudo ${RESIZER} /dev/loop0
    sudo umount ${MOUNT_DIR}
    rm -r ${MOUNT_DIR}
    exit 0;
fi

truncate -s ${SIZE} ${NAME}
yes | mkfs.${FORMAT} ${NAME}
sudo mount -o loop ${NAME} ${MOUNT_DIR}

REMOVE_IMAGE=false
if [[ "$(sudo docker images --platform ${PLATFORM} -q ${IMAGE} 2>/dev/null)" == "" ]]; then
    REMOVE_IMAGE=true
fi

CONTAINER=$(sudo docker create --platform ${PLATFORM} ${IMAGE})
sudo docker export ${CONTAINER} | sudo tar -xC ${MOUNT_DIR}
sudo docker rm ${CONTAINER}

if "${REMOVE_IMAGE}" ; then
    sudo docker rmi -f ${IMAGE}
fi

sudo cp /etc/resolv.conf ${MOUNT_DIR}/etc/resolv.conf

sudo chroot ${MOUNT_DIR} sh -c "
dnf install -y \
    systemd systemd-networkd systemd-resolved systemd-udev \
    openssh-server passwd strace openssh-clients

systemctl enable systemd-networkd

cat << EOF > /etc/systemd/network/ether.network
[Match]
Name=*

[Network]
DHCP=yes
EOF

rm /etc/resolv.conf
chmod 644 /etc/systemd/network/ether.network

cat << EOF > /etc/ssh/sshd_config
PasswordAuthentication yes
PermitRootLogin yes
PermitEmptyPasswords yes
Subsystem    sftp    /usr/libexec/openssh/sftp-server
EOF

passwd -d root
"

sudo umount ${MOUNT_DIR}
rm -r ${MOUNT_DIR}
