#!/bin/bash

## Copyright (C) 2012 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See file COPYING for copying conditions.

set -o errexit
set -o nounset
set -o errtrace
set -o pipefail
shopt -s inherit_errexit
shopt -s shift_verbose

source /usr/libexec/helper-scripts/as_root.sh

shared_folder_users=( 'user' 'sysmaint' )

main() {
  local virt_type shared_folder_group account_name target_group_id
  local virtiofs_error ninep_error

  virt_type="${1:-}"
  case "${virt_type}" in
    kvm)
      shared_folder_group='kvmsf'
      ;;
    vbox)
      shared_folder_group='vboxsf'
      ;;
    *)
      printf '%s\n' "ERROR: Unknown virtualization type '${virt_type}'!"
      exit 1
      ;;
  esac

  ## Create group for shared folder permissions and add appropriate users to
  ## it if needed
  if ! accountctl "${shared_folder_group}" is-group 2>/dev/null; then
    /usr/sbin/addgroup "${shared_folder_group}"
  fi
  for account_name in "${shared_folder_users[@]}"; do
    if accountctl "${account_name}" is-user 2>/dev/null; then
      /usr/sbin/adduser "${account_name}" "${shared_folder_group}" 2>/dev/null || true
    fi
  done

  ## Create shared folder.
  # shellcheck disable=SC2174
  mkdir --parents /mnt/shared --mode 770 || exit 1
  chown "root:${shared_folder_group}" /mnt/shared || exit 1

  mount_failed_msg="INFO: could not mount /mnt/shared; leaving it unmounted. Probably no share named 'shared' is configured on the host."

  ## Copy the appropriate README file, and mount the shared folder if possible.
  case "${virt_type}" in
    kvm)
      cp --no-clobber -- /usr/share/doc/vm-config-dist/shared-folder-kvm-README.md /mnt/shared/README.md || true
      ## Try virtiofs first, it works much better and is now recommended.
      if ! virtiofs_error="$(mount -t virtiofs shared /mnt/shared 2>&1)" \
        && ! ninep_error="$(mount -t 9p -o trans=virtio shared /mnt/shared -oversion=9p2000.L 2>&1)"; then
        printf '%s\n' "${mount_failed_msg}"
        printf '%s\n' "INFO: virtiofs: ${virtiofs_error}"
        printf '%s\n' "INFO: 9p: ${ninep_error}"
      fi
      ;;
    vbox)
      cp --no-clobber -- /usr/share/doc/vm-config-dist/shared-folder-vbox-README.md /mnt/shared/README.md || true
      target_group_id="$(accountctl vboxsf get-entry group gid)"
      if ! vboxsf_error="$(mount -t vboxsf -o uid=0,gid="${target_group_id}",umask=0007 shared /mnt/shared 2>&1)"; then
        printf '%s\n' "${mount_failed_msg}"
        printf '%s\n' "INFO: vboxsf: ${vboxsf_error}"
      fi
      ;;
  esac
}

as_root
main "$@"
