#!/bin/sh
# Copyright © 2016 Johannes Schauer
# Copyright © 2022 Jochen Sprickerhof
# Copyright © 2022 Simon McVittie
# SPDX-License-Identifier: GPL-2.0-or-later
# shellcheck shell=dash

# A shell script that prepares the environment for autopkgtest-virt-unshare
# by bind-mounting all the important things.

set -eu

rootdir="$1"
shift

bind_mount() {
    local old="$1"
    local new="$2"

    case "$new" in
        (/*)
            ;;
        (*)
            echo "internal error: not an absolute path: $new" >&2
            exit 125
            ;;
    esac
    if test -d "$old"; then
        mkdir -p "$rootdir$new"
        mount -o rbind "$old" "$rootdir$new"
    else
        mkdir -p "$rootdir${new%/*}"
        touch "$rootdir$new"
        chmod -rwx "$rootdir/$new"
        mount -o bind "$old" "$rootdir$new"
    fi
}

while [ "$#" -gt 0 ]; do
    case "$1" in
        (--bind)
            bind_mount "$2" "$3"
            shift 3
            ;;

        (--)
            shift
            break
            ;;

        (*)
            echo "internal error: argument not understood: $1" >&2
            exit 125
            ;;
    esac
done

test -f /etc/resolv.conf && cp /etc/resolv.conf "$rootdir/etc/resolv.conf"

mkdir -p "$rootdir/dev"
for f in null zero full random urandom tty console; do
    touch "$rootdir/dev/$f"
    # The chmod is done such that somebody accidentally using the chroot
    # without the right bind-mounts will not fill up their disk.
    chmod -rwx "$rootdir/dev/$f"
    # silently ignore device files missing outside.
    # we can't print a warning as that breaks the adt protocol
    mount -o bind "/dev/$f" "$rootdir/dev/$f" > /dev/null 2>&1 || true
done
ln -sfT /proc/self/fd "$rootdir/dev/fd"
ln -sfT /proc/self/fd/0 "$rootdir/dev/stdin"
ln -sfT /proc/self/fd/1 "$rootdir/dev/stdout"
ln -sfT /proc/self/fd/2 "$rootdir/dev/stderr"
mkdir -p "$rootdir/dev/pts"
mount -o noexec,nosuid,newinstance,gid=5,mode=620,ptmxmode=666 -t devpts none "$rootdir/dev/pts"
ln -sfT /dev/pts/ptmx "$rootdir/dev/ptmx"
mkdir -p "$rootdir/dev/shm"
mount -t tmpfs tmpfs "$rootdir/dev/shm"
mkdir -p "$rootdir/sys"
mount -o rbind /sys "$rootdir/sys"

exec env -i PATH=/usr/sbin:/usr/bin:/sbin:/bin SHELL=/bin/sh \
unshare --root "$rootdir" --ipc --mount --pid --uts --cgroup --fork --mount-proc \
"$@"
