#!/bin/sh

set -eu

puavo_link_to_state() {
  local current_linktarget dirpath wanted_linktarget

  dirpath=$1
  wanted_linktarget="/state${dirpath}"

  current_linktarget=$(readlink "$dirpath" 2>/dev/null || true)
  if [ -n "$current_linktarget" \
       -a "$current_linktarget" = "$wanted_linktarget" ]; then
    return 0
  fi

  # Before linking the directory, make sure that the /state partition has
  # the same directory structure as the image so that applications do
  # not freak out because something was be missing. The original directory
  # is renamed to ${dirpath}.rofs before replacing the directory with a
  # symbolic link to the /state partition.
  if [ -d "$dirpath" ]; then
    find "$dirpath" -type d -print0 | cpio -0dpm --quiet /state || true
    mv -T "$dirpath" "${dirpath}.rofs" 2>/dev/null || true
  else
    mkdir -p "/state${dirpath}"
  fi

  ln -fns "$wanted_linktarget" "$dirpath"
}

puavo_setup_admins() {
  local admins_status

  admins_status=0

  if puavo_link_to_state /adm-home; then
    rsync -au /adm-home.rofs/ /state/adm-home/ || admins_status=1
  else
    admins_status=1
  fi

  if puavo_link_to_state /root; then
    rsync -au /root.rofs/ /state/root/ || admins_status=1
  else
    admins_status=1
  fi

  return $admins_status
}

# CUPS always writes its configuration files as new files and then
# renames the new file to the old name.  This breaks the /state linking
# if we just link /etc/cups/printers.conf to /state.  To overcome
# this we always copy cups files from the image to the /state partition
# when booting.  Locally configured printers should stay configured
# this way and PPDs are placed under /state/etc/cups/ppd.
puavo_setup_cups_dir() {
  local cups_status

  cups_status=0

  if puavo_link_to_state /etc/cups; then
    cp -a -t /state/etc/cups/                 \
             /etc/cups.rofs/cups-browsed.conf \
             /etc/cups.rofs/cupsd.conf        \
             /etc/cups.rofs/cups-files.conf   \
             /etc/cups.rofs/raw.convs         \
             /etc/cups.rofs/raw.types         \
             /etc/cups.rofs/snmp.conf
  else
    cups_status=1
  fi

  for dir in zjs lava oak hp qpdl slx hiperc; do
    if [ ! -d "/usr/share/foo2${dir}/icm" ]; then
      {
        mkdir -p "/usr/share/foo2${dir}/icm" \
          && puavo_link_to_state "/usr/share/foo2${dir}/icm"
      } || cups_status=1
    fi
  done

  return $cups_status
}

mountpoint -q /state || exit 0

status=0

read puavo_hosttype < /etc/puavo/hosttype
case "$puavo_hosttype" in
  bootserver)
    statedirlist='
      /etc/ldap/slapd.d
      /etc/libvirt
      /etc/nbd-server/conf.d
      /etc/network/interfaces.d
      /etc/shorewall
      /var/lib/bind
      /var/lib/dhcp
      /var/lib/docker
      /var/lib/flatpak
      /var/lib/krb5kdc
      /var/lib/ldap
      /var/lib/logrotate
      /var/lib/munin
      /var/lib/nfs
      /var/lib/puavo
      /var/lib/samba
      /var/lib/shorewall
      /var/lib/tftpboot/ltsp
      /var/log
      /var/spool/anacron
    '
    ;;
  laptop)
    statedirlist='
      /etc/NetworkManager/system-connections
      /var/cache/ccreds
      /var/cache/cups
      /var/lib/AccountsService
      /var/lib/bluetooth
      /var/lib/docker
      /var/lib/extrausers
      /var/lib/flatpak
      /var/lib/logrotate
      /var/lib/munin
      /var/lib/puavo
      /var/lib/puavo-desktop
      /var/lib/systemd
      /var/log
      /var/spool/anacron
    '
    ;;
  *)
    # nothing to do
    exit $status
    ;;
esac

# must fix in case puavo gid has changed...
chgrp puavo /state/etc/puavo/ldap/password || status=1
rsync -a --exclude=certificates --exclude=certs /state/etc/puavo/ /etc/puavo/ \
  || status=1

for statedir in $statedirlist; do
  puavo_link_to_state "$statedir" || status=1
done

puavo_setup_cups_dir || status=1

for x in $(cat /proc/cmdline); do
  case "$x" in
    puavo.admin.persistent_homedirs=true)
      puavo_setup_admins || status=1
      ;;
  esac
done

exit $status
