#!/bin/sh

# Copyright © 2020, Trond Endrestøl <Trond.Endrestol@ximalas.info>

# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:

# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# PROVIDE: bemigrate
# REQUIRE: hostname adjkerntz
# BEFORE: random
# KEYWORD: firstboot

# Important!
# cp -p bemigrate.sh /etc/rc.d/bemigrate
# This file must not have the .sh suffix when saved in /etc/rc.d.

# Note, this script is ONLY useful if you create the new BE as a clone
# of the running BE.

# Do NOT use this script if you follow the usual convention of creating
# a snapshot and a clone for rescue purposes, and then upgrade your
# default BE.

# Don't forget to add bemigrate_enable="YES" to /etc/rc.conf, and to
# create the /firstboot marker in the new BE.

# Place this script in /etc/rc.d under the name bemigrate, so that it
# will be run in a timely manner, i.e. ahead of /etc/rc.d/random.
# Do NOT let mergemaster(8) remove this "orphaned" script.

. /etc/rc.subr

name="bemigrate"
desc="Migrate files from the previous BE where the new BE is a clone of the former BE"
start_cmd="bemigrate_start"
stop_cmd=":"
rcvar="bemigrate_enable"

bemigrate_start ()
{
  # Ensure / is of type ZFS.
  if [ -z "$(/bin/df -Tt zfs /)" ]; then
    echo "${name}: root filesystem must be of type ZFS" >/dev/stderr
    exit 69
  fi

  # Get the name of the parent BE.
  # Ideally this should be the name of the previously multiuser booted
  # BE, which will require a new (user) pool property to be maintained.
  BEORIGIN=$(zfs get -Ho value origin / | cut -d @ -f 1)
  if [ -z "${BEORIGIN}" ]; then
    echo "${name}: empty value for BEORIGIN" >/dev/stderr
    exit 69
  fi

  echo "${name}: mounting old root BE ${BEORIGIN} on /mnt"
  mount -t zfs "${BEORIGIN}" /mnt || exit

  # This part must be changed if /boot doesn't come from a separate bootpool mounted as /bootpool.
  # We assume the root BEs are named rootpool/ROOT/yyyymmdd-rNNNNNN and that the bootpool BEs
  # follow suit, i.e. bootpool/BOOT/yyyymmdd-rNNNNNN.
  # See below for the counterpart doing the unmounting.
  if [ -d /mnt/bootpool ]; then
    BOOTBEORIGIN=$(echo "${BEORIGIN}" | sed 's/root/boot/g;s/ROOT/BOOT/g')
    if [ -z "${BOOTBEORIGIN}" ]; then
      echo "${name}: empty value for BOOTBEORIGIN" >/dev/stderr
      exit 69
    fi

    echo "${name}: mounting old boot BE ${BOOTBEORIGIN} on /mnt/bootpool"
    mount -t zfs "${BOOTBEORIGIN}" /mnt/bootpool || exit
  fi

  echo "${name}: copying boot entropy file from old BE"
  cat /mnt/boot/entropy > /boot/entropy || exit

  echo "${name}: copying early entropy file from old BE"
  cat /mnt/entropy > /entropy || exit

  echo "${name}: copying csh history file from old BE"
  cat /mnt/root/.history > /root/.history || exit

  if [ -r /mnt/root/.bash_history ]; then
    if [ ! -f /root/.bash_history ]; then
      echo "${name}: creating, chmodding, and linking new bash history file"
      touch /root/.bash_history
      chmod 0600 /root/.bash_history
      ln /root/.bash_history /.bash_history
    fi

    echo "${name}: copying bash history file from old BE"
    cat /mnt/root/.bash_history > /root/.bash_history || exit
  fi

  old_cc_version=$(/mnt/usr/bin/cc --version | sed 1q)
  new_cc_version=$(/usr/bin/cc --version | sed 1q)

  if [ "${new_cc_version}" = "${old_cc_version}" ]; then
    echo "${name}: new and old system compiler match, transferring the mtime from the old system compiler executable to the new one"
    touch -mr /mnt/usr/bin/cc /usr/bin/cc
  fi

  # This part must be changed if /boot doesn't come from a separate bootpool mounted as /bootpool.
  # See above for the counterpart doing the mounting.
  if [ -d /mnt/bootpool ]; then
    echo "${name}: unmounting old boot BE on /mnt/bootpool"
    umount /mnt/bootpool || exit
  fi

  echo "${name}: unmounting old root BE on /mnt"
  umount /mnt || exit

  echo "${name}: updating files in /etc/mail"
  cd /etc/mail || exit
  make all install || exit

  if [ -x /usr/local/bin/rkhunter ]; then
    echo "${name}: updating rkhunter files"
    /usr/local/bin/rkhunter --no-mail-on-warning --propupd --quiet
  fi

  echo "${name}: done"
}

load_rc_config ${name}
run_rc_command "$1"

# EOF
