#!/bin/bash

set -euo pipefail

TARGET="${1:-}"

log()
{
    echo "Synex ZFS key: $*"
}

die()
{
    echo "Synex ZFS key ERROR: $*" >&2
    exit 1
}

#
# Validate target.
#

[ -n "$TARGET" ] \
    || die "missing target root"

[ -d "$TARGET" ] \
    || die "target root does not exist: $TARGET"

[ -d "$TARGET/etc" ] \
    || die "target does not contain /etc"

#
# Receive the ZFS passphrase from Calamares through stdin.
#
# Never echo it and never pass it as a command-line argument.
#

IFS= read -r ZFSKEY \
    || die "could not read ZFS passphrase from stdin"

[ -n "$ZFSKEY" ] \
    || die "received an empty ZFS passphrase"

#
# Determine the actual root dataset from the mounted Calamares target.
#

ROOT_DATASET="$(
    findmnt -n -o SOURCE --target "$TARGET" 2>/dev/null || true
)"

[ -n "$ROOT_DATASET" ] \
    || die "could not determine target root dataset"

log "root dataset: $ROOT_DATASET"

#
# Make sure this really is ZFS.
#

ROOT_FSTYPE="$(
    findmnt -n -o FSTYPE --target "$TARGET" 2>/dev/null || true
)"

[ "$ROOT_FSTYPE" = "zfs" ] \
    || die "target root filesystem is not ZFS: ${ROOT_FSTYPE:-unknown}"

#
# Determine the actual encryption root dynamically.
#
# For the new direct Calamares installation we already observed that
# this can be the pool root itself, so nothing is hardcoded here.
#

ENCRYPTION_ROOT="$(
    zfs get -H -o value encryptionroot "$ROOT_DATASET"
)"

[ -n "$ENCRYPTION_ROOT" ] \
    || die "could not determine encryption root"

[ "$ENCRYPTION_ROOT" != "-" ] \
    || die "target ZFS dataset is not encrypted"

log "encryption root: $ENCRYPTION_ROOT"

ENCRYPTION="$(
    zfs get -H -o value encryption "$ENCRYPTION_ROOT"
)"

KEYFORMAT="$(
    zfs get -H -o value keyformat "$ENCRYPTION_ROOT"
)"

KEYLOCATION="$(
    zfs get -H -o value keylocation "$ENCRYPTION_ROOT"
)"

log "encryption: $ENCRYPTION"
log "keyformat: $KEYFORMAT"
log "current keylocation: $KEYLOCATION"

[ "$ENCRYPTION" != "off" ] \
    || die "encryption root has encryption=off"

[ "$KEYFORMAT" = "passphrase" ] \
    || die "unexpected keyformat: $KEYFORMAT"

#
# Validate pool compatibility as another safety check.
#

POOL="${ROOT_DATASET%%/*}"

COMPATIBILITY="$(
    zpool get -H -o value compatibility "$POOL"
)"

log "pool: $POOL"
log "compatibility: $COMPATIBILITY"

[ "$COMPATIBILITY" = "openzfs-2.3-linux" ] \
    || die "unexpected ZFS compatibility profile: $COMPATIBILITY"

#
# Create the key directory inside the installed target.
#

install \
    -d \
    -o root \
    -g root \
    -m 0700 \
    "$TARGET/etc/zfs"

KEYFILE="$TARGET/etc/zfs/zpsynex.key"

#
# Create the keyfile without exposing the passphrase in argv.
#

umask 077

printf '%s\n' "$ZFSKEY" > "$KEYFILE"

chown root:root "$KEYFILE"
chmod 0600 "$KEYFILE"

#
# Verify that the generated file actually contains the correct key.
#
# IMPORTANT:
# During installation the file physically lives below the Calamares
# target, so use that host-visible path only for this validation.
#
# -n verifies the key without changing its loaded state.
# -L temporarily overrides keylocation for this command.
#

zfs load-key \
    -n \
    -L "file://$KEYFILE" \
    "$ENCRYPTION_ROOT" \
    || die "generated keyfile does not validate against the encryption root"

log "keyfile validation successful"

#
# Now store the FINAL keylocation property.
#
# This path is intentionally the path as seen by the installed system,
# not the temporary /tmp/calamares-root-* host path.
#

zfs set \
    keylocation=file:///etc/zfs/zpsynex.key \
    "$ENCRYPTION_ROOT"

NEW_KEYLOCATION="$(
    zfs get -H -o value keylocation "$ENCRYPTION_ROOT"
)"

[ "$NEW_KEYLOCATION" = "file:///etc/zfs/zpsynex.key" ] \
    || die "failed to set final keylocation"

log "final keylocation: $NEW_KEYLOCATION"

#
# Match the already validated Synex procedure.
#
# Root can still copy this file into initramfs, while ordinary users
# cannot read it.
#

chmod 000 "$KEYFILE"

#
# Restrictive initramfs permissions.
#

install \
    -d \
    -o root \
    -g root \
    -m 0755 \
    "$TARGET/etc/initramfs-tools/conf.d"

printf '%s\n' 'UMASK=0077' \
    > "$TARGET/etc/initramfs-tools/conf.d/umask.conf"

chown root:root \
    "$TARGET/etc/initramfs-tools/conf.d/umask.conf"

chmod 0644 \
    "$TARGET/etc/initramfs-tools/conf.d/umask.conf"

#
# Erase the shell variable as soon as it is no longer required.
#

unset ZFSKEY

sync

log "keyfile created successfully"
log "initramfs UMASK configured successfully"
log "configuration completed"
