#!/bin/bash
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.installer
# SPDX-Security-Contact: security@coresecret.eu

guard_sourcing

#######################################
# Wrapper to write '/etc/fstab' entries.
# Globals:
#   TARGET
# Arguments:
#   1: UUID or /dev/mapper
#   2: Mount Path
#   3: Filesystem
#   4: Mount Options
#   5: Pass value, while Dump value is hardcoded always "0".
# Returns:
#   0: on success
#######################################
write_fstab() {
  declare write_maps="$1" write_path="$2" write_type="$3" write_opts="$4" write_pass="$5"

  if [[ "${write_maps}" =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}$ ]] || [[ "${write_maps}" =~ ^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$ ]]; then

    printf "%-43s%-28s%-18s%-100s0 %s\n" "UUID=${write_maps}" "${write_path}" "${write_type}" "${write_opts}" "${write_pass}" >> "${TARGET}/etc/fstab"
    do_log "info" "file_only" "4200() fstab entry generated: [UUID=${write_maps}    ${write_path}    ${write_type}    ${write_opts}    0 ${write_pass}]."

  elif [[ "${write_maps}" == /dev/mapper/* ]]; then

    printf "%-43s%-28s%-18s%-100s0 %s\n" "${write_maps}" "${write_path}" "${write_type}" "${write_opts}" "${write_pass}" >> "${TARGET}/etc/fstab"
    do_log "info" "file_only" "4200() fstab entry generated: [${write_maps}    ${write_path}    ${write_type}    ${write_opts}    0 ${write_pass}]."

  fi

  return 0
}

#######################################
# Generate target '/etc/fstab' entries.
# Globals:
#   ARY_PATHS_SORTED
#   HMP_EPHEMERAL_ENCLABEL
#   HMP_FSTAB_MOUNT_FTYPE
#   HMP_FSTAB_MOUNT_OPTS
#   HMP_PATH_FSUUID
#   TARGET
#   VAR_VERSION
# Arguments:
#   None
# Returns:
#   0: on success
#######################################
generate_fstab() {
  ### Declare Arrays, HashMaps, and Variables.
  declare    var_path="" var_dmapper="" var_fs_uuid="" var_fs_path="" var_fs_type="" var_fs_opts="" var_fs_pass=""

  ### Generate '${TARGET}/etc/fstab' header.
  : >| "${TARGET}/etc/fstab"
  chmod 0600 "${TARGET}/etc/fstab"

  cat << EOF >> "${TARGET}/etc/fstab"
# SPDX-Version: 3.0
# SPDX-CreationInfo: 2025-06-17; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-ExternalRef: GIT https://git.coresecret.dev/msw/CISS.debian.installer.git
# SPDX-FileContributor: WEIDNER, Marc S.; Centurion Intelligence Consulting Agency
# SPDX-FileCopyrightText: 2024-2025; WEIDNER, Marc S.; <msw@coresecret.dev>
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: EUPL-1.2 OR LicenseRef-CCLA-1.0
# SPDX-LicenseComment: This file is part of the CISS.debian.installer.secure framework.
# SPDX-PackageName: CISS.debian.installer
# SPDX-Security-Contact: security@coresecret.eu

# /etc/fstab                   : Generated by CISS.debian.installer ${VAR_VERSION}
# Architecture                 : ${VAR_ARCHITECTURE}
# Distribution                 : ${VAR_CODENAME}

# Static file system information '/etc/fstab'.
#
# Use 'blkid' to print the universally unique identifier for a device; this may be used with [UUID=] as a more robust way to
# name devices that work even if disks are added and removed. See fstab(5).
#
# 'systemd' generates mount units based on this file. See systemd.mount(5). Please run 'systemctl daemon-reload' after making
# changes here.
#
# <file system UUID>                       <mount point>               <type>            <options>                                                                                           <dump> <pass>

EOF

  ### Generate dynamic '${TARGET}/etc/fstab' entries.
  for var_path in "${ARY_PATHS_SORTED[@]}"; do

    case "${var_path,,}" in

      swap|SWAP) continue;;

      /tmp)

        var_dmapper="${HMP_EPHEMERAL_ENCLABEL["${var_path}"]}"
        var_fs_uuid="/dev/mapper/${var_dmapper}"
        var_fs_path="${var_path}"
        var_fs_type="${HMP_FSTAB_MOUNT_FTYPE["${var_path}"]}"
        var_fs_opts="${HMP_FSTAB_MOUNT_OPTS["${var_path}"]}"
        var_fs_pass="0"
        ;;

      *)

        var_fs_uuid="${HMP_PATH_FSUUID["${var_path}"]}"
        var_fs_path="${var_path}"
        var_fs_type="${HMP_FSTAB_MOUNT_FTYPE["${var_path}"]}"
        var_fs_opts="${HMP_FSTAB_MOUNT_OPTS["${var_path}"]}"
        case "${var_path,,}" in
           /)         var_fs_pass="1" ;;
           /boot/efi) var_fs_pass="0" ;;
           *)         var_fs_pass="2" ;;
        esac
        ;;

    esac

    case "${var_fs_type,,}" in

      btrfs)

        write_fstab "${var_fs_uuid}" "${var_fs_path}" "${var_fs_type}" "${var_fs_opts}" "${var_fs_pass}"

        if [[ -v HMP_FSTAB_MOUNT_OPTS["${var_path}/.snapshots"] ]]; then

          var_fs_opts="${HMP_FSTAB_MOUNT_OPTS["${var_path}/.snapshots"]}"

          if [[ "${var_fs_path}" == "/" ]]; then

            write_fstab "${var_fs_uuid}" "/.snapshots" "${var_fs_type}" "${var_fs_opts}" "${var_fs_pass}"

          else

            write_fstab "${var_fs_uuid}" "${var_fs_path}/.snapshots" "${var_fs_type}" "${var_fs_opts}" "${var_fs_pass}"

          fi

        fi

        continue
        ;;

      ext4)

        write_fstab "${var_fs_uuid}" "${var_fs_path}" "${var_fs_type}" "${var_fs_opts}" "${var_fs_pass}"
        continue
        ;;

      fat32)

        write_fstab "${var_fs_uuid}" "${var_fs_path}" "vfat" "${var_fs_opts}" "${var_fs_pass}"
        continue
        ;;

    esac

  done

  ### Generate separate SWAP entry.
  var_dmapper="${HMP_EPHEMERAL_ENCLABEL["SWAP"]}"
  var_fs_uuid="/dev/mapper/${var_dmapper}"
  var_fs_path="none"
  var_fs_type="swap"
  var_fs_opts="defaults"
  var_fs_pass="0"
  write_fstab "${var_fs_uuid}" "${var_fs_path}" "${var_fs_type}" "${var_fs_opts}" "${var_fs_pass}"

  cat << 'EOF' >> "${TARGET}/etc/fstab"

/dev/sr0                                   /media/cdrom0               udf,iso9660       user,noauto                                                                                         0 0

EOF
  do_log "info" "file_only" "4200() fstab entry generated: '/dev/sr0  /media/cdrom0  udf,iso9660  user,noauto  0 0'."

  cat << 'EOF' >> "${TARGET}/etc/fstab"
### Secure tmpfs mounts for a hardened system
# Mount the 'proc' filesystem to provide process and kernel information.
# Mount 'sysfs' to expose kernel device information to user space.
# Mount the 'devpts' filesystem to enable pseudo-terminal support for user sessions.
# Restrict '/dev/shm' to shared memory, limit size, prevent code execution.
# System runtime directory in RAM. Do not set 'noexec' here for compatibility.
proc                                       /proc                       proc              nodev,nosuid,noexec,hidepid=2                                                                       0 0
sysfs                                      /sys                        sysfs             defaults                                                                                            0 0
devpts                                     /dev/pts                    devpts            gid=5,mode=620                                                                                      0 0
tmpfs                                      /dev/shm                    tmpfs             rw,nodev,noexec,nosuid,relatime,size=1G                                                             0 0
tmpfs                                      /run                        tmpfs             mode=0755,nodev,nosuid                                                                              0 0

# vim: number et ts=2 sw=2 sts=2 ai tw=200 ft=sh
EOF

  guard_dir && return 0
}
# vim: number et ts=2 sw=2 sts=2 ai tw=128 ft=sh
