#!/bin/bash
# -*- mode: sh; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# vim: et sts=4 sw=4

#  SPDX-License-Identifier: LGPL-2.1+
#
#  Copyright © 2020-2021 Collabora Ltd.
#  Copyright © 2020-2021 Valve Corporation.
#
#  This file is part of steamos-customizations.
#
#  steamos-customizations is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public License as
#  published by the Free Software Foundation; either version 2.1 of the License,
#  or (at your option) any later version.

set -e
set -u
set -o pipefail

# default and future guess
fstype=btrfs

usage() {
    cat <<EOF
Usage: ${0##*/} enable|disable|status

Enable or disable read-only on the current running SteamOS.
EOF
}

# mark root partition writable
read_write_extfs() {
    tune2fs -O ^read-only "$1"
    mount -o remount,rw /
    sync /
}
read_write_btrfs() {
    btrfs property set / ro false
}
read_write() {
    read_write_$fstype "$@"
}

#
# mark root partition read-only
read_only_btrfs() {
    sync /
    btrfs property set / ro true
}
read_only_extfs() {
    if tune2fs -l "$1" | grep -q '^Filesystem features: .*read-only.*$'
    then
        echo "Warning: The rootfs is already read-only!" >&2
        echo "         Nothing is performed." >&2
        return
    fi

    sync /
    mount -o remount,ro /
    tune2fs -O read-only "$1"
}
read_only() {
    read_only_$fstype "$@"
}

status_extfs() {
    local filesystem_is_readonly
    local device_is_readonly
    local roothash

    if tune2fs -l "$1" | grep -q '^Filesystem features: .*read-only.*$'
    then
        echo "enabled"
        return
    else
        echo "disabled"
        return 1
    fi
}
status_btrfs() {
    prop_val=$(btrfs property get / ro)
    if [[ $prop_val = "ro=true" ]]
    then
        echo "enabled"
    else
        echo "disabled"
        return 1
    fi
}
status() {
    status_$fstype "$@"
}


toggle() {
    if status "$@" 2>/dev/null
    then
        read_write "$@"
    else
        read_only "$@"
    fi
}

shell() {
    local dev

    dev="$1"
    shift

    if status "$dev" >/dev/null 2>&1
    then
        read_write "$dev"
        trap "read_only \"$dev\"" 0
    fi

    "${SHELL:-/bin/sh}" "$@"
}

# determine file system type and set the fstype variable used above
get_fstype() {
    declare $(findmnt -fnP --output FSTYPE /)
    case "$FSTYPE" in
    \"ext4\")
        fstype=extfs
        ;;
    \"btrfs\")
        fstype=btrfs
        ;;
    *)
        echo "Unrecognized root filesystem type $FSTYPE"
        exit 1
    esac
}

get_fstype

case "${1:-}" in
    disable)
        read_write /dev/disk/by-partsets/self/rootfs
        ;;
    enable)
        read_only /dev/disk/by-partsets/self/rootfs
        ;;
    toggle)
        toggle /dev/disk/by-partsets/self/rootfs
        ;;
    status)
        status /dev/disk/by-partsets/self/rootfs
        ;;
    shell)
        shift
        shell /dev/disk/by-partsets/self/rootfs "$@"
        ;;
    *)
        usage
        exit 1
esac
