#!/bin/sh
set -eu

marker=/var/lib/octava-firstboot/expand-rootfs
state=/var/lib/octava-firstboot-expand
expected_start=729088
expected_number=6
expected_label=BPI-ROOT

log() { printf '%s\n' "octava-router-firstboot-expand: $*"; }
fail() { log "ERROR: $*" >&2; exit 1; }

if test "${OCTAVA_FIRSTBOOT_EXPAND_TEST:-0}" = 1; then
    disk=${OCTAVA_FIRSTBOOT_EXPAND_DISK:?}
    partition=${OCTAVA_FIRSTBOOT_EXPAND_PARTITION:?}
    state=${OCTAVA_FIRSTBOOT_EXPAND_STATE:?}
    marker=${OCTAVA_FIRSTBOOT_EXPAND_MARKER:?}
    case "$disk:$partition:$state:$marker" in
        /dev/loop*:/dev/loop*p6:/tmp/*:/tmp/*) ;;
        *) fail "unsafe test paths" ;;
    esac
else
    partition=$(readlink -f "$(findmnt -n -o SOURCE /)")
    case "$partition" in /dev/mmcblk*p6) ;; *) fail "root is not SD partition p6: $partition" ;; esac
    disk=${partition%p6}
fi

test -e "$marker" || exit 0

test -b "$disk" || fail "disk is unavailable: $disk"
test -b "$partition" || fail "partition is unavailable: $partition"
test "$(blockdev --getss "$disk")" = 512 || fail "unsupported sector size"
test "$(lsblk -dn -o PTTYPE "$disk")" = gpt || fail "disk does not use GPT"
test "$(blkid -s PARTLABEL -o value "$partition")" = "$expected_label" || fail "unexpected partition label"
test "$(blkid -s TYPE -o value "$partition")" = ext4 || fail "root filesystem is not ext4"

name=$(basename "$partition")
sys=/sys/class/block/$name
test "$(cat "$sys/partition")" = "$expected_number" || fail "unexpected partition number"
start=$(cat "$sys/start")
test "$start" = "$expected_start" || fail "unexpected partition start"

install -d -m 0700 "$state"
exec 9>"$state/lock"
flock -n 9 || fail "another expansion is running"
sfdisk --dump "$disk" >"$state/partition-table.before.tmp"
mv "$state/partition-table.before.tmp" "$state/partition-table.before"

disk_sectors=$(blockdev --getsz "$disk")
target_end=$((disk_sectors - 34))
current_sectors=$(cat "$sys/size")
current_end=$((start + current_sectors - 1))
test "$target_end" -ge "$current_end" || fail "target media is smaller than the image"

if test "$target_end" -gt "$current_end"; then
    target_sectors=$((target_end - start + 1))
    sfdisk --relocate gpt-bak-std "$disk"
    printf 'start=%s, size=%s\n' "$start" "$target_sectors" \
        | sfdisk --no-reread --force -N "$expected_number" "$disk"
    partx --update --nr "$expected_number" "$disk"
    udevadm settle
    retries=20
    while test "$retries" -gt 0; do
        current_sectors=$(cat "$sys/size")
        current_end=$((start + current_sectors - 1))
        test "$current_end" = "$target_end" && break
        retries=$((retries - 1))
        sleep 1
    done
    test "$current_end" = "$target_end" || fail "kernel did not accept the new partition size"
fi

resize2fs "$partition"
sync "$partition"
rm -f "$marker"
printf 'schema=1\nstart_sector=%s\nend_sector=%s\n' "$start" "$target_end" >"$state/completed.tmp"
mv "$state/completed.tmp" "$state/completed"
chmod 0600 "$state/completed"
sync -f "$state"
log "root filesystem expansion completed"
